KiCad PCB EDA Suite
Loading...
Searching...
No Matches
nl_schematic_plugin_impl.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2022 3Dconnexion
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
22
23// KiCAD includes
25#include <sch_base_frame.h>
26#include <bitmaps.h>
28#include <view/view.h>
30#include <tool/action_manager.h>
31#include <tool/tool_action.h>
32#include <tool/tool_manager.h>
33
34// stdlib
35#include <list>
36#include <map>
37#include <memory>
38#include <utility>
39#include <vector>
40#include <cfloat>
41
42#include <wx/log.h>
43#include <wx/mstream.h>
44
45
53const wxChar* NL_SCHEMATIC_PLUGIN_IMPL::m_logTrace = wxT( "KI_TRACE_NL_SCHEMATIC_PLUGIN" );
54
55
57 CNavigation3D( false, false ),
58 m_viewport2D( nullptr ),
59 m_view( nullptr ),
60 m_isMoving( false ),
61 m_viewportWidth( 0.0 )
62{
63 PutProfileHint( "KiCAD Eeschema" );
64}
65
66
68{
69 EnableNavigation( false );
70}
71
72
74{
75 bool init = m_viewport2D == nullptr;
76
77 m_viewport2D = aViewport;
78
79 if( m_viewport2D != nullptr )
80 {
81 m_view = static_cast<KIGFX::SCH_VIEW*>( m_viewport2D->GetView() );
83
84 if( init )
85 {
86 // Use the default settings for the connexion to the 3DMouse navigation
87 // They are use a single-threaded threading model and row vectors.
88 EnableNavigation( true );
89
90 // Use the SpaceMouse internal timing source for the frame rate.
91 PutFrameTimingSource( TimingSource::SpaceMouse );
92
94 }
95 }
96}
97
98
100{
101 wxLogTrace( m_logTrace, wxT( "NL_SCHEMATIC_PLUGIN_IMPL::SetFocus %d" ), aFocus );
102 NAV_3D::Write( navlib::focus_k, aFocus );
103}
104
105// temporary store for the command categories
106typedef std::map<std::string, TDx::CCommandTreeNode*> CATEGORY_STORE;
107
108
117static void add_category( const std::string& aCategoryPath, CATEGORY_STORE& aCategoryStore )
118{
119 using TDx::SpaceMouse::CCategory;
120
121 CATEGORY_STORE::iterator parent_iter = aCategoryStore.begin();
122 std::string::size_type pos = aCategoryPath.find_last_of( '.' );
123
124 if( pos != std::string::npos )
125 {
126 std::string parentPath = aCategoryPath.substr( 0, pos );
127 parent_iter = aCategoryStore.find( parentPath );
128
129 if( parent_iter == aCategoryStore.end() )
130 {
131 add_category( parentPath, aCategoryStore );
132 parent_iter = aCategoryStore.find( parentPath );
133 }
134 }
135
136 std::string name = aCategoryPath.substr( pos + 1 );
137 auto categoryNode = std::make_unique<CCategory>( aCategoryPath.c_str(), name.c_str() );
138
139 aCategoryStore.insert( aCategoryStore.end(), { aCategoryPath, categoryNode.get() } );
140
141 if( parent_iter != aCategoryStore.end() )
142 parent_iter->second->push_back( std::move( categoryNode ) );
143}
144
145
147{
148 wxLogTrace( m_logTrace, wxT( "NL_SCHEMATIC_PLUGIN_IMPL::exportCommandsAndImages" ) );
149
150 std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
151
152 if( actions.size() == 0 )
153 return;
154
155 using TDx::SpaceMouse::CCommand;
156 using TDx::SpaceMouse::CCommandSet;
157
158 // The root action set node
159 CCommandSet commandSet( "SCHEMATIC_EDITOR", "Schematic Editor" );
160
161 // Activate the command set
162 NAV_3D::PutActiveCommands( commandSet.GetId() );
163
164 // temporary store for the categories
165 CATEGORY_STORE categoryStore;
166
167 std::vector<TDx::CImage> vImages;
168
169 // add the action set to the category_store
170 categoryStore.insert( categoryStore.end(), CATEGORY_STORE::value_type( ".", &commandSet ) );
171
172 std::list<TOOL_ACTION*>::const_iterator it;
173
174 for( it = actions.begin(); it != actions.end(); ++it )
175 {
176 const TOOL_ACTION* action = *it;
177 std::string label = action->GetMenuLabel().ToStdString();
178
179 if( label.empty() )
180 continue;
181
182 std::string name = action->GetName();
183
184 // Do no export commands for the 3DViewer app.
185
186 if( name.rfind( "3DViewer.", 0 ) == 0 )
187 continue;
188
189 std::string strCategory = action->GetToolName();
190 CATEGORY_STORE::iterator iter = categoryStore.find( strCategory );
191
192 if( iter == categoryStore.end() )
193 {
194 add_category( strCategory, categoryStore );
195 iter = categoryStore.find( strCategory );
196 }
197
198 std::string description = action->GetDescription().ToStdString();
199
200 // Arbitrary 8-bit data stream
201 wxMemoryOutputStream imageStream;
202
203 if( action->GetIcon() != BITMAPS::INVALID_BITMAP )
204 {
205 wxImage image = KiBitmap( action->GetIcon() ).ConvertToImage();
206 image.SaveFile( imageStream, wxBitmapType::wxBITMAP_TYPE_PNG );
207 image.Destroy();
208
209 if( imageStream.GetSize() )
210 {
211 wxStreamBuffer* streamBuffer = imageStream.GetOutputStreamBuffer();
212 TDx::CImage tdxImage = TDx::CImage::FromData( "", 0, name.c_str() );
213 tdxImage.AssignImage( std::string( reinterpret_cast<const char*>(
214 streamBuffer->GetBufferStart() ),
215 streamBuffer->GetBufferSize() ),
216 0 );
217
218 wxLogTrace( m_logTrace, wxT( "Adding image for : %s" ), name );
219 vImages.push_back( std::move( tdxImage ) );
220 }
221 }
222
223 if( iter != categoryStore.end() )
224 {
225 wxLogTrace( m_logTrace, wxT( "Inserting command: %s, description: %s, in category: %s" ),
226 name, description, iter->first );
227
228 iter->second->push_back( CCommand( name, label, description ) );
229 }
230 }
231
232 NAV_3D::AddCommandSet( commandSet );
233 NAV_3D::AddImages( vImages );
234}
235
236
237long NL_SCHEMATIC_PLUGIN_IMPL::GetCameraMatrix( navlib::matrix_t& matrix ) const
238{
239 if( !m_view )
240 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
241
243
244 double x = m_view->IsMirroredX() ? -1 : 1;
245 double y = m_view->IsMirroredY() ? 1 : -1;
246
247 // x * y * z = 1 for a right-handed coordinate system.
248 double z = x * y;
249
250 // Note: the connexion has been configured as row vectors, the coordinate system is defined in
251 // NL_SCHEMATIC_PLUGIN_IMPL::GetCoordinateSystem and the front view in NL_SCHEMATIC_PLUGIN_IMPL::GetFrontView.
252 matrix = { { { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, m_viewPosition.x, m_viewPosition.y, 0, 1 } } };
253 return 0;
254}
255
256
257long NL_SCHEMATIC_PLUGIN_IMPL::GetPointerPosition( navlib::point_t& position ) const
258{
259 if( !m_view )
260 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
261
263
264 position.x = mouse_pointer.x;
265 position.y = mouse_pointer.y;
266 position.z = 0;
267
268 return 0;
269}
270
271
272long NL_SCHEMATIC_PLUGIN_IMPL::GetViewExtents( navlib::box_t& extents ) const
273{
274 if( !m_view )
275 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
276
277 double scale = m_viewport2D->GetGAL()->GetWorldScale();
278 BOX2D box = m_view->GetViewport();
279
281
282 extents.min_x = -box.GetWidth() / 2.0;
283 extents.min_y = -box.GetHeight() / 2.0;
284 extents.min_z = m_viewport2D->GetGAL()->GetMinDepth() / scale;
285 extents.max_x = box.GetWidth() / 2.0;
286 extents.max_y = box.GetHeight() / 2.0;
287 extents.max_z = m_viewport2D->GetGAL()->GetMaxDepth() / scale;
288 return 0;
289}
290
291
292long NL_SCHEMATIC_PLUGIN_IMPL::GetIsViewPerspective( navlib::bool_t& perspective ) const
293{
294 perspective = false;
295
296 return 0;
297}
298
299
300long NL_SCHEMATIC_PLUGIN_IMPL::SetCameraMatrix( const navlib::matrix_t& matrix )
301{
302 if( !m_view )
303 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
304
305 long result = 0;
306 VECTOR2D viewPos( matrix.m4x4[3][0], matrix.m4x4[3][1] );
307
308 if( !equals( m_view->GetCenter(), m_viewPosition, static_cast<VECTOR2D::coord_type>( FLT_EPSILON ) ) )
309 {
311 result = navlib::make_result_code( navlib::navlib_errc::error );
312 }
313 else
314 {
315 m_view->SetCenter( viewPos );
316 }
317
318 m_viewPosition = viewPos;
319
320 return result;
321}
322
323
324long NL_SCHEMATIC_PLUGIN_IMPL::SetViewExtents( const navlib::box_t& extents )
325{
326 if( !m_view )
327 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
328
329 long result = 0;
330
332 result = navlib::make_result_code( navlib::navlib_errc::error );
333
334 double width = m_viewportWidth;
335 m_viewportWidth = extents.max_x - extents.min_x;
336
337 double scale = width / m_viewportWidth * m_view->GetScale();
339
340 if( !equals( m_view->GetScale(), scale, static_cast<double>( FLT_EPSILON ) ) )
341 result = navlib::make_result_code( navlib::navlib_errc::error );
342
343 return result;
344}
345
346
348{
349 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
350}
351
352
353long NL_SCHEMATIC_PLUGIN_IMPL::SetViewFrustum( const navlib::frustum_t& frustum )
354{
355 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
356}
357
358
359long NL_SCHEMATIC_PLUGIN_IMPL::GetModelExtents( navlib::box_t& extents ) const
360{
361 if( !m_view )
362 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
363
364 BOX2I box = static_cast<SCH_BASE_FRAME*>( m_viewport2D->GetParent() )->GetDocumentExtents();
365 box.Normalize();
366
367 double half_depth = 0.1 / m_viewport2D->GetGAL()->GetWorldScale();
368
369 if( box.GetWidth() == 0 && box.GetHeight() == 0 )
370 half_depth = 0;
371
372 extents.min_x = static_cast<double>( box.GetOrigin().x );
373 extents.min_y = static_cast<double>( box.GetOrigin().y );
374 extents.min_z = -half_depth;
375 extents.max_x = static_cast<double>( box.GetEnd().x );
376 extents.max_y = static_cast<double>( box.GetEnd().y );
377 extents.max_z = half_depth;
378
379 return 0;
380}
381
382
383long NL_SCHEMATIC_PLUGIN_IMPL::GetCoordinateSystem( navlib::matrix_t& matrix ) const
384{
385 // The coordinate system is defined as x to the right, y down and z into the screen.
386 matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } };
387 return 0;
388}
389
390
391long NL_SCHEMATIC_PLUGIN_IMPL::GetFrontView( navlib::matrix_t& matrix ) const
392{
393 matrix = { { { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 } } };
394 return 0;
395}
396
397
399{
400 empty = true;
401 return 0;
402}
403
404
405long NL_SCHEMATIC_PLUGIN_IMPL::GetIsViewRotatable( navlib::bool_t& isRotatable ) const
406{
407 isRotatable = false;
408 return 0;
409}
410
411
413{
414 if( commandId.empty() )
415 return 0;
416
417 std::list<TOOL_ACTION*> actions = ACTION_MANAGER::GetActionList();
418 TOOL_ACTION* context = nullptr;
419
420 for( std::list<TOOL_ACTION*>::const_iterator it = actions.begin(); it != actions.end(); it++ )
421 {
422 TOOL_ACTION* action = *it;
423 std::string nm = action->GetName();
424
425 if( commandId == nm )
426 context = action;
427 }
428
429 if( context )
430 {
431 wxWindow* parent = m_viewport2D->GetParent();
432
433 // Only allow command execution if the window is enabled. i.e. there is not a modal dialog
434 // currently active.
435 if( parent && parent->IsEnabled() )
436 {
437 TOOLS_HOLDER* tools_holder = dynamic_cast<TOOLS_HOLDER*>( parent );
438 TOOL_MANAGER* tool_manager = tools_holder ? tools_holder->GetToolManager() : nullptr;
439
440 // Only allow for command execution if the tool manager is accessible.
441 if( !tool_manager )
442 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
443
444 // Get the selection to use to test if the action is enabled
445 SELECTION& sel = tool_manager->GetToolHolder()->GetCurrentSelection();
446
447 bool runAction = true;
448
449 if( const ACTION_CONDITIONS* aCond = tool_manager->GetActionManager()->GetCondition( *context ) )
450 runAction = aCond->enableCondition( sel );
451
452 if( runAction )
453 tool_manager->RunAction( *context );
454 }
455 else
456 {
457 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
458 }
459 }
460
461 return 0;
462}
463
464
466{
467 return 0;
468}
469
470
472{
473 m_isMoving = value;
474
475 return 0;
476}
477
478
480{
481 if( value == 0L )
483
484 return 0;
485}
486
487
489{
490 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
491}
492
493
494long NL_SCHEMATIC_PLUGIN_IMPL::GetViewFrustum( navlib::frustum_t& frustum ) const
495{
496 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
497}
498
499
500long NL_SCHEMATIC_PLUGIN_IMPL::GetSelectionExtents( navlib::box_t& extents ) const
501{
502 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
503}
504
505
506long NL_SCHEMATIC_PLUGIN_IMPL::GetSelectionTransform( navlib::matrix_t& transform ) const
507{
508 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
509}
510
511
512long NL_SCHEMATIC_PLUGIN_IMPL::SetSelectionTransform( const navlib::matrix_t& matrix )
513{
514 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
515}
516
517
518long NL_SCHEMATIC_PLUGIN_IMPL::GetPivotPosition( navlib::point_t& position ) const
519{
520 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
521}
522
523
524long NL_SCHEMATIC_PLUGIN_IMPL::IsUserPivot( navlib::bool_t& userPivot ) const
525{
526 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
527}
528
529
530long NL_SCHEMATIC_PLUGIN_IMPL::SetPivotPosition( const navlib::point_t& position )
531{
532 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
533}
534
535
536long NL_SCHEMATIC_PLUGIN_IMPL::GetPivotVisible( navlib::bool_t& visible ) const
537{
538 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
539}
540
541
543{
544 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
545}
546
547
548long NL_SCHEMATIC_PLUGIN_IMPL::GetHitLookAt( navlib::point_t& position ) const
549{
550 return navlib::make_result_code( navlib::navlib_errc::no_data_available );
551}
552
553
555{
556 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
557}
558
559
560long NL_SCHEMATIC_PLUGIN_IMPL::SetHitDirection( const navlib::vector_t& direction )
561{
562 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
563}
564
565
566long NL_SCHEMATIC_PLUGIN_IMPL::SetHitLookFrom( const navlib::point_t& eye )
567{
568 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
569}
570
571
573{
574 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
575}
576
577
578long NL_SCHEMATIC_PLUGIN_IMPL::SetCameraTarget( const navlib::point_t& position )
579{
580 return navlib::make_result_code( navlib::navlib_errc::invalid_operation );
581}
const char * name
Definition: DXF_plotter.cpp:62
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:104
const ACTION_CONDITIONS * GetCondition(const TOOL_ACTION &aAction) const
Get the conditions to use for a specific tool action.
static std::list< TOOL_ACTION * > & GetActionList()
Return list of TOOL_ACTIONs.
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:146
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr size_type GetHeight() const
Definition: box2.h:215
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
KIGFX::VIEW_CONTROLS * GetViewControls() const
Return a pointer to the #VIEW_CONTROLS instance used in the panel.
virtual KIGFX::VIEW * GetView() const
Return a pointer to the #VIEW instance used in the panel.
void ForceRefresh()
Force a redraw.
KIGFX::GAL * GetGAL() const
Return a pointer to the GAL instance used in the panel.
double GetMaxDepth() const
double GetMinDepth() const
double GetWorldScale() const
Get the world scale.
void SetScale(double aScale, VECTOR2D aAnchor={ 0, 0 }) override
Set the scaling factor, zooming around a given anchor point.
Definition: sch_view.cpp:102
virtual VECTOR2D GetMousePosition(bool aWorldCoordinates=true) const =0
Return the current mouse pointer position.
double GetScale() const
Definition: view.h:276
BOX2D GetViewport() const
Return the current viewport visible area rectangle.
Definition: view.cpp:530
const VECTOR2D & GetCenter() const
Return the center point of this VIEW (in world space coordinates).
Definition: view.h:346
bool IsMirroredX() const
Return true if view is flipped across the X axis.
Definition: view.h:250
bool IsMirroredY() const
Return true if view is flipped across the Y axis.
Definition: view.h:258
const BOX2D & GetBoundary() const
Definition: view.h:305
void SetCenter(const VECTOR2D &aCenter)
Set the center point of the VIEW (i.e.
Definition: view.cpp:596
long GetHitLookAt(navlib::point_t &aPosition) const override
long GetSelectionExtents(navlib::box_t &aExtents) const override
long GetCoordinateSystem(navlib::matrix_t &aMatrix) const override
long SetViewFOV(double aFov) override
long GetSelectionTransform(navlib::matrix_t &aTransform) const override
long GetPivotPosition(navlib::point_t &aPosition) const override
long SetPivotPosition(const navlib::point_t &aPosition) override
long SetViewFrustum(const navlib::frustum_t &aFrustum) override
long GetFrontView(navlib::matrix_t &aMatrix) const override
long GetViewFOV(double &aFov) const override
long SetHitAperture(double aAperture) override
long SetSelectionTransform(const navlib::matrix_t &aMatrix) override
void SetFocus(bool aFocus)
Set the connection to the 3Dconnexion driver to the focus state so that 3DMouse data is routed here.
long SetViewExtents(const navlib::box_t &aExtents) override
void SetCanvas(EDA_DRAW_PANEL_GAL *aViewport)
Sets the viewport controlled by the SpaceMouse.
long GetCameraMatrix(navlib::matrix_t &aMatrix) const override
long GetPointerPosition(navlib::point_t &aPosition) const override
long GetPivotVisible(navlib::bool_t &aVisible) const override
void exportCommandsAndImages()
Export the invocable actions and images to the 3Dconnexion UI.
long SetTransaction(long aValue) override
long GetIsViewPerspective(navlib::bool_t &aPerspective) const override
long SetHitSelectionOnly(bool aSelectionOnly) override
NL_SCHEMATIC_PLUGIN_IMPL()
Initializes a new instance of the NL_SCHEMATIC_PLUGIN_IMPL.
long SetHitLookFrom(const navlib::point_t &aPosition) override
long SetActiveCommand(std::string aCommandId) override
long GetViewExtents(navlib::box_t &aExtents) const override
long SetCameraTarget(const navlib::point_t &aPosition) override
long GetIsSelectionEmpty(navlib::bool_t &aEmpty) const override
long SetCameraMatrix(const navlib::matrix_t &aMatrix) override
long GetIsViewRotatable(navlib::bool_t &isRotatable) const override
long SetMotionFlag(bool aValue) override
long SetHitDirection(const navlib::vector_t &aDirection) override
long GetModelExtents(navlib::box_t &aExtents) const override
long IsUserPivot(navlib::bool_t &aUserPivot) const override
long SetSettingsChanged(long aChangeNumber) override
long GetViewFrustum(navlib::frustum_t &aFrustum) const override
long SetPivotVisible(bool aVisible) override
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
TOOL_MANAGER * GetToolManager() const
Return the MVC controller.
Definition: tools_holder.h:55
virtual SELECTION & GetCurrentSelection()
Get the current selection from the canvas area.
Definition: tools_holder.h:98
Represent a single user action.
Definition: tool_action.h:304
wxString GetMenuLabel() const
Return the translated label for the action.
BITMAPS GetIcon() const
Return an icon associated with the action.
Definition: tool_action.h:459
std::string GetToolName() const
Return name of the tool associated with the action.
const std::string & GetName() const
Return name of the action.
Definition: tool_action.h:337
wxString GetDescription() const
Master controller class:
Definition: tool_manager.h:62
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
TOOLS_HOLDER * GetToolHolder() const
Definition: tool_manager.h:406
ACTION_MANAGER * GetActionManager() const
Definition: tool_manager.h:306
double coord_type
Definition: vector2d.h:74
static bool empty(const wxTextEntryBase *aCtrl)
static const wxChar * m_logTrace
Trace mask used to enable or disable the trace output of this class.
bool equals(glm::mat< L, C, T, Q > const &aFirst, glm::mat< L, C, T, Q > const &aSecond, T aEpsilon=static_cast< T >(FLT_EPSILON *10))
Template to compare two glm::mat<T> values for equality within a required epsilon.
CATEGORY_STORE::iterator add_category(std::string aCategoryPath, CATEGORY_STORE &aCategoryStore)
Add a category to the store.
std::map< std::string, TDx::CCommandTreeNode * > CATEGORY_STORE
std::map< std::string, TDx::CCommandTreeNode * > CATEGORY_STORE
static void add_category(const std::string &aCategoryPath, CATEGORY_STORE &aCategoryStore)
Add a category to the store.
Declaration of the NL_SCHEMATIC_PLUGIN_IMPL class.
const int scale
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
WX_VIEW_CONTROLS class definition.