KiCad PCB EDA Suite
Loading...
Searching...
No Matches
action_toolbar.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) 2019 CERN
5 * Copyright The KiCad Developers, see CHANGELOG.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <algorithm>
22#include <advanced_config.h>
23#include <bitmaps.h>
24#include <bitmap_store.h>
25#include <eda_draw_frame.h>
26#include <functional>
27#include <kiplatform/ui.h>
28#include <math/util.h>
29#include <memory>
30#include <pgm_base.h>
32#include <trace_helpers.h>
33#include <tool/action_toolbar.h>
34#include <tool/tool_action.h>
35#include <tool/tool_event.h>
37#include <tool/tool_manager.h>
42
43#include <wx/log.h>
44#include <wx/popupwin.h>
45#include <wx/renderer.h>
46#include <wx/sizer.h>
47#include <wx/dcclient.h>
48#include <wx/settings.h>
49
50#ifdef __WXMSW__
51#include <windows.h>
52#endif
53
54// Needed to handle adding the plugins to the toolbar
55// TODO (ISM): This should be better abstracted away from the toolbars
57
58
59ACTION_GROUP::ACTION_GROUP( const std::string_view& aName )
60{
61 m_name = aName;
63 m_defaultAction = nullptr;
64}
65
66
67ACTION_GROUP::ACTION_GROUP( const std::string_view& aName,
68 const std::vector<const TOOL_ACTION*>& aActions )
69{
70 m_name = aName;
72
73 SetActions( aActions );
74}
75
76
77void ACTION_GROUP::SetActions( const std::vector<const TOOL_ACTION*>& aActions )
78{
79 wxASSERT_MSG( aActions.size() > 0, wxS( "Action groups must have at least one action" ) );
80
81 // The default action is just the first action in the vector
82 m_actions = aActions;
84}
85
87{
89}
90
91
93{
94 bool valid = std::any_of( m_actions.begin(), m_actions.end(),
95 [&]( const TOOL_ACTION* aAction ) -> bool
96 {
97 // For some reason, we can't compare the actions directly
98 return aAction->GetId() == aDefault.GetId();
99 } );
100
101 wxASSERT_MSG( valid, wxS( "Action must be present in a group to be the default" ) );
102
103 m_defaultAction = &aDefault;
104}
105
106
107#define PALETTE_BORDER FromDIP( 4 ) // The border around the palette buttons on all sides
108#define BUTTON_BORDER FromDIP( 1 ) // The border on the sides of the buttons that touch other buttons
109
110
111ACTION_TOOLBAR_PALETTE::ACTION_TOOLBAR_PALETTE( wxWindow* aParent, bool aVertical ) :
112 wxPopupTransientWindow( aParent, wxBORDER_NONE ),
113 m_group( nullptr ),
114 m_isVertical( aVertical ),
115 m_panel( nullptr ),
116 m_mainSizer( nullptr ),
117 m_buttonSizer( nullptr )
118{
119 m_panel = new wxPanel( this, wxID_ANY );
120 m_panel->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
121
122 // This sizer holds the buttons for the actions
123 m_buttonSizer = new wxBoxSizer( aVertical ? wxVERTICAL : wxHORIZONTAL );
124
125 // This sizer holds the other sizer, so that a consistent border is present on all sides
126 m_mainSizer = new wxBoxSizer( aVertical ? wxVERTICAL : wxHORIZONTAL );
127 m_mainSizer->Add( m_buttonSizer, wxSizerFlags().Border( wxALL, PALETTE_BORDER ) );
128
129 m_panel->SetSizer( m_mainSizer );
130
131 Connect( wxEVT_CHAR_HOOK, wxCharEventHandler( ACTION_TOOLBAR_PALETTE::onCharHook ), nullptr, this );
132}
133
134
136{
138 wxBitmapBundle normalBmp = KiBitmapBundleDef( aAction.GetIcon(), iconSize );
139 int paddingDip = ( ToDIP( m_buttonSize.GetWidth() ) - iconSize ) / 2;
140
141 BITMAP_BUTTON* button = new BITMAP_BUTTON( m_panel, aAction.GetUIId() );
142
143 button->SetIsToolbarButton();
144 button->SetBitmap( normalBmp );
145 button->SetDisabledBitmap( KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ) );
146 button->SetPadding( paddingDip );
147 button->SetToolTip( aAction.GetButtonTooltip() );
148 button->AcceptDragInAsClick();
149 button->SetBitmapCentered();
150
151 m_buttons[aAction.GetUIId()] = button;
152
153 if( m_isVertical )
154 m_buttonSizer->Add( button, wxSizerFlags().Border( wxTOP | wxBOTTOM, BUTTON_BORDER ) );
155 else
156 m_buttonSizer->Add( button, wxSizerFlags().Border( wxLEFT | wxRIGHT, BUTTON_BORDER ) );
157
158 m_buttonSizer->Layout();
159}
160
161
162void ACTION_TOOLBAR_PALETTE::EnableAction( const TOOL_ACTION& aAction, bool aEnable )
163{
164 auto it = m_buttons.find( aAction.GetUIId() );
165
166 if( it != m_buttons.end() )
167 it->second->Enable( aEnable );
168}
169
170
171void ACTION_TOOLBAR_PALETTE::CheckAction( const TOOL_ACTION& aAction, bool aCheck )
172{
173 auto it = m_buttons.find( aAction.GetUIId() );
174
175 if( it != m_buttons.end() )
176 it->second->Check( aCheck );
177}
178
179
181{
182 m_mainSizer->Fit( m_panel );
183 SetClientSize( m_panel->GetSize() );
184
185 return m_panel->GetSize();
186}
187
188
189void ACTION_TOOLBAR_PALETTE::Popup( wxWindow* aFocus )
190{
192
193 wxPopupTransientWindow::Popup( aFocus );
194}
195
196
197void ACTION_TOOLBAR_PALETTE::onCharHook( wxKeyEvent& aEvent )
198{
199 // Allow the escape key to dismiss this popup
200 if( aEvent.GetKeyCode() == WXK_ESCAPE )
201 Dismiss();
202 else
203 aEvent.Skip();
204}
205
206
207#ifdef __WXMSW__
208bool ACTION_TOOLBAR_PALETTE::MSWHandleMessage( WXLRESULT* aResult, WXUINT aMessage,
209 WXWPARAM aWParam, WXLPARAM aLParam )
210{
211 // The Windows "Activate on hover" option (active window tracking) activates whatever
212 // top-level window the pointer is over. As the pointer travels from the toolbar button
213 // toward this palette it crosses the owner frame, which then steals activation and would
214 // normally deactivate and dismiss this transient popup before the user can reach it.
215 // Ignore that specific deactivation so the palette survives the trip. Dismissal by Escape,
216 // by pressing a palette button, or by switching to any other window is unaffected because
217 // those do not hand activation back to the owner frame.
218 if( aMessage == WM_ACTIVATE && LOWORD( aWParam ) == WA_INACTIVE )
219 {
220 BOOL tracking = FALSE;
221
222 if( ::SystemParametersInfo( SPI_GETACTIVEWINDOWTRACKING, 0, &tracking, 0 ) && tracking )
223 {
224 HWND activated = reinterpret_cast<HWND>( aLParam );
225 wxWindow* owner = MSWGetOwner();
226
227 if( activated && owner && ::GetAncestor( activated, GA_ROOT ) == owner->GetHWND() )
228 return wxPopupTransientWindowBase::MSWHandleMessage( aResult, aMessage, aWParam,
229 aLParam );
230 }
231 }
232
233 return wxPopupTransientWindow::MSWHandleMessage( aResult, aMessage, aWParam, aLParam );
234}
235#endif
236
237
238ACTION_TOOLBAR::ACTION_TOOLBAR( EDA_BASE_FRAME* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
239 long style ) :
240 wxAuiToolBar( parent, id, pos, size, style ),
241 m_parent( parent ),
242 m_paletteTimer( nullptr ),
243 m_auiManager( nullptr ),
244 m_toolManager( parent->GetToolManager() ),
245 m_palette( nullptr )
246{
247 m_paletteTimer = new wxTimer( this );
248
249 SetArtProvider( new WX_AUI_TOOLBAR_ART );
250
251 Connect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ), nullptr, this );
252 Connect( wxEVT_AUITOOLBAR_RIGHT_CLICK, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onRightClick ), nullptr, this );
253 Connect( wxEVT_RIGHT_UP, wxMouseEventHandler( ACTION_TOOLBAR::onRightUp ), nullptr, this );
254 Connect( wxEVT_AUITOOLBAR_BEGIN_DRAG, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onItemDrag ), nullptr, this );
255 Connect( wxEVT_LEFT_DOWN, wxMouseEventHandler( ACTION_TOOLBAR::onMouseClick ), nullptr, this );
256 Connect( wxEVT_LEFT_UP, wxMouseEventHandler( ACTION_TOOLBAR::onMouseClick ), nullptr, this );
257 Connect( m_paletteTimer->GetId(), wxEVT_TIMER, wxTimerEventHandler( ACTION_TOOLBAR::onTimerDone ), nullptr, this );
258
259 Bind( wxEVT_SIZE,
260 [&]( wxSizeEvent& aEvent )
261 {
262 CallAfter(
263 [&]()
264 {
265 SetOverflowVisible( !GetToolBarFits() );
266 } );
267
268 aEvent.Skip();
269 } );
270
271 Bind( wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler( ACTION_TOOLBAR::onThemeChanged ), this );
272
273 Bind( wxEVT_DPI_CHANGED,
274 [&]( wxDPIChangedEvent& aEvent )
275 {
276#ifdef __WXMSW__
277 // Update values which are normally only initialized in wxAuiToolBar::Create.
278 // FromDIP is no-op on backends other than wxMSW.
279 SetToolPacking( FromDIP( 2 ) );
280 SetToolBorderPadding( FromDIP( 3 ) );
281
282 wxSize margin_lt = FromDIP( wxSize( 5, 5 ) );
283 wxSize margin_rb = FromDIP( wxSize( 2, 2 ) );
284 SetMargins( margin_lt.x, margin_lt.y, margin_rb.x, margin_rb.y );
285
286 // Re-realize the toolbar to recalculate all item sizes with the new DPI.
287 // This fixes excessive button padding when moving windows between displays
288 // with different DPI scaling factors.
289 if( GetToolCount() > 0 )
290 {
292 InvalidateBestSize();
293 KiRealize();
294 }
295#endif
296
297 aEvent.Skip();
298 } );
299}
300
301
303{
304 Disconnect( wxEVT_COMMAND_TOOL_CLICKED, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onToolEvent ), nullptr, this );
305 Disconnect( wxEVT_AUITOOLBAR_RIGHT_CLICK, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onRightClick ), nullptr, this );
306 Disconnect( wxEVT_RIGHT_UP, wxMouseEventHandler( ACTION_TOOLBAR::onRightUp ), nullptr, this );
307 Disconnect( wxEVT_AUITOOLBAR_BEGIN_DRAG, wxAuiToolBarEventHandler( ACTION_TOOLBAR::onItemDrag ), nullptr, this );
308 Disconnect( wxEVT_LEFT_DOWN, wxMouseEventHandler( ACTION_TOOLBAR::onMouseClick ), nullptr, this );
309 Disconnect( wxEVT_LEFT_UP, wxMouseEventHandler( ACTION_TOOLBAR::onMouseClick ), nullptr, this );
310 Disconnect( m_paletteTimer->GetId(), wxEVT_TIMER, wxTimerEventHandler( ACTION_TOOLBAR::onTimerDone ), nullptr,
311 this );
312
313 Unbind( wxEVT_SYS_COLOUR_CHANGED, wxSysColourChangedEventHandler( ACTION_TOOLBAR::onThemeChanged ), this );
314
315 delete m_paletteTimer;
316
317 // Clear all the maps keeping track of our items on the toolbar
318 m_toolMenus.clear();
319 m_actionGroups.clear();
320 m_toolCancellable.clear();
321 m_toolKinds.clear();
322 m_toolActions.clear();
323}
324
325
326std::list<ACTION_TOOLBAR_CONTROL*> ACTION_TOOLBAR::GetCustomControlList( FRAME_T aContext )
327{
328 std::list<ACTION_TOOLBAR_CONTROL*> controls;
329
331 {
332 if( control->SupportedFor( aContext ) )
333 controls.push_back( control );
334 }
335
336 return controls;
337}
338
339
341{
342 wxASSERT( GetParent() );
343
344 // Keep each group's selection across the rebuild.
345 std::map<std::string, std::string> currentGroupItems = m_groupSelections;
346
347 // Remove existing tools
348 ClearToolbar();
349
350 std::vector<TOOLBAR_ITEM> items = aConfig.GetToolbarItems();
351
352 // Add all the items to the toolbar
353 for( auto& item : items )
354 {
355 switch( item.m_Type )
356 {
358 AddScaledSeparator( GetParent() );
359 break;
360
362 AddSpacer( item.m_Size );
363 break;
364
366 {
367 // Add a group of items to the toolbar
368 std::string groupName = item.m_GroupName.ToStdString();
369 std::vector<const TOOL_ACTION*> tools;
370 const TOOL_ACTION* defaultTool = nullptr;
371
372 for( TOOLBAR_ITEM& groupItem : item.m_GroupItems )
373 {
374 switch( groupItem.m_Type )
375 {
380 wxFAIL_MSG( wxT( "Unsupported group item type" ) );
381 continue;
382
384 TOOL_ACTION* grpAction = m_toolManager->GetActionManager()->FindAction( groupItem.m_ActionName );
385
386 if( !grpAction )
387 {
388 wxFAIL_MSG( wxString::Format( wxT( "Unable to find group tool %s" ), groupItem.m_ActionName ) );
389 continue;
390 }
391
392 tools.push_back( grpAction );
393
394 if( currentGroupItems[groupName] == groupItem.m_ActionName )
395 defaultTool = grpAction;
396 }
397 }
398
399 // A group needs at least one action
400 if( tools.empty() )
401 continue;
402
403 std::unique_ptr<ACTION_GROUP> group = std::make_unique<ACTION_GROUP>( groupName, tools );
404
405 if( defaultTool )
406 group->SetDefaultAction( *defaultTool );
407
408 AddGroup( std::move( group ) );
409
410 // Look up and attach context menu if one is registered for this group
411 auto menuFactory = TOOLBAR_CONTEXT_MENU_REGISTRY::GetGroupMenuFactory( groupName );
412
413 if( menuFactory && m_toolManager )
414 {
415 // Register the menu for each action in the group
416 for( const TOOL_ACTION* grpAction : tools )
417 AddToolContextMenu( *grpAction, menuFactory( m_toolManager ) );
418 }
419
420 break;
421 }
422
424 {
425 // Add a custom control to the toolbar
426 EDA_BASE_FRAME* frame = static_cast<EDA_BASE_FRAME*>( GetParent() );
427 ACTION_TOOLBAR_CONTROL_FACTORY* factory = frame->GetCustomToolbarControlFactory( item.m_ControlName );
428
429 if( !factory )
430 {
431 wxFAIL_MSG( wxString::Format( wxT( "Unable to find control factory for %s" ), item.m_ControlName ) );
432 continue;
433 }
434
435 // The factory functions are responsible for adding the controls to the toolbar themselves
436 (*factory)( this );
437 break;
438 }
439
441 {
442 TOOL_ACTION* action = m_toolManager->GetActionManager()->FindAction( item.m_ActionName );
443
444 if( !action )
445 {
446 wxFAIL_MSG( wxString::Format( wxT( "Unable to find toolbar tool %s" ), item.m_ActionName ) );
447 continue;
448 }
449
450 Add( *action );
451
452 // Look up and attach context menu if one is registered for this action
453 auto factory = TOOLBAR_CONTEXT_MENU_REGISTRY::GetMenuFactory( item.m_ActionName );
454
455 if( factory && m_toolManager )
456 AddToolContextMenu( *action, factory( m_toolManager ) );
457
458 break;
459 }
460 }
461 }
462
463 // Apply the configuration
464 KiRealize();
465}
466
467
468void ACTION_TOOLBAR::DoSetToolTipText( const wxString& aTip )
469{
470 // We use \t in short description to align accelerators in wxMenuItem
471 // But they should be converted when displaying tooltips
472 wxString tip = aTip;
473 tip.Replace( "\t", " " );
474
475 wxAuiToolBar::DoSetToolTipText( tip );
476}
477
478
479void ACTION_TOOLBAR::Add( const TOOL_ACTION& aAction )
480{
481 wxASSERT_MSG( !aAction.CheckToolbarState( TOOLBAR_STATE::HIDDEN ),
482 wxString::Format( "Attempting to add hidden action %s to the toolbar", aAction.GetName() ) );
483
484 bool isToggleEntry = aAction.CheckToolbarState( TOOLBAR_STATE::TOGGLE );
485 bool isCancellable = aAction.CheckToolbarState( TOOLBAR_STATE::CANCEL );
486
487 Add( aAction, isToggleEntry, isCancellable );
488}
489
490
491void ACTION_TOOLBAR::Add( const TOOL_ACTION& aAction, bool aIsToggleEntry, bool aIsCancellable )
492{
493 wxASSERT( GetParent() );
494 wxASSERT_MSG( !( aIsCancellable && !aIsToggleEntry ),
495 wxS( "aIsCancellable requires aIsToggleEntry" ) );
496
497 int toolId = aAction.GetUIId();
499
500 AddTool( toolId, wxEmptyString,
501 KiBitmapBundleDef( aAction.GetIcon(), iconSize ),
502 KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ),
503 aIsToggleEntry ? wxITEM_CHECK : wxITEM_NORMAL,
504 aAction.GetButtonTooltip(), wxEmptyString, nullptr );
505
506 m_toolKinds[ toolId ] = aIsToggleEntry;
507 m_toolActions[ toolId ] = &aAction;
508 m_toolCancellable[ toolId ] = aIsCancellable;
509}
510
511
513{
514 int toolId = aAction.GetUIId();
516
517 AddTool( toolId, wxEmptyString,
518 KiBitmapBundleDef( aAction.GetIcon(), iconSize ),
519 KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ),
520 wxITEM_NORMAL, aAction.GetButtonTooltip(), wxEmptyString, nullptr );
521
522 m_toolKinds[ toolId ] = false;
523 m_toolActions[ toolId ] = &aAction;
524}
525
526
527void ACTION_TOOLBAR::AddScaledSeparator( wxWindow* aWindow )
528{
529 int scale = KiIconScale( aWindow );
530
531 if( scale > 4 )
532 AddSpacer( 16 * ( scale - 4 ) / 4 );
533
534 AddSeparator();
535
536 if( scale > 4 )
537 AddSpacer( 16 * ( scale - 4 ) / 4 );
538}
539
540
541void ACTION_TOOLBAR::Add( wxControl* aControl, const wxString& aLabel )
542{
543 wxASSERT( aControl );
544 m_controlIDs.push_back( aControl->GetId() );
545 AddControl( aControl, aLabel );
546}
547
548
549void ACTION_TOOLBAR::AddToolContextMenu( const TOOL_ACTION& aAction, std::unique_ptr<ACTION_MENU> aMenu )
550{
551 int toolId = aAction.GetUIId();
552
553 m_toolMenus[toolId] = std::move( aMenu );
554}
555
556
557void ACTION_TOOLBAR::AddGroup( std::unique_ptr<ACTION_GROUP> aGroup )
558{
559 int groupId = aGroup->GetUIId();
560 const TOOL_ACTION* defaultAction = aGroup->GetDefaultAction();
562
563 wxASSERT( GetParent() );
564 wxASSERT( defaultAction );
565
566 // Turn this into a toggle entry if any one of the actions is a toggle entry
567 bool isToggleEntry = false;
568
569 for( const auto& act : aGroup->GetActions() )
570 isToggleEntry |= act->CheckToolbarState( TOOLBAR_STATE::TOGGLE );
571
572 m_toolKinds[ groupId ] = isToggleEntry;
573 m_toolActions[ groupId ] = defaultAction;
574 m_actionGroups[ groupId ] = std::move( aGroup );
575
576 // Add the main toolbar item representing the group
577 AddTool( groupId, wxEmptyString,
578 KiBitmapBundleDef( defaultAction->GetIcon(), iconSize ),
579 KiDisabledBitmapBundleDef( defaultAction->GetIcon(), iconSize ),
580 isToggleEntry ? wxITEM_CHECK : wxITEM_NORMAL, wxEmptyString, wxEmptyString, nullptr );
581
582 // Select the default action
583 doSelectAction( m_actionGroups[ groupId ].get(), *defaultAction );
584}
585
586
588{
589 bool valid = std::any_of( aGroup->m_actions.begin(), aGroup->m_actions.end(),
590 [&]( const TOOL_ACTION* action2 ) -> bool
591 {
592 // For some reason, we can't compare the actions directly
593 return aAction.GetId() == action2->GetId();
594 } );
595
596 if( valid )
597 doSelectAction( aGroup, aAction );
598}
599
600
602{
603 // Find the group that contains this action and select it
604 for( auto& [id, groupPtr] : m_actionGroups )
605 {
606 ACTION_GROUP* group = groupPtr.get();
607
608 bool inGroup = std::any_of( group->m_actions.begin(), group->m_actions.end(),
609 [&]( const TOOL_ACTION* action2 )
610 {
611 return aAction.GetId() == action2->GetId();
612 } );
613
614 if( inGroup )
615 {
616 doSelectAction( group, aAction );
617 break;
618 }
619 }
620}
621
622
624{
625 wxASSERT( GetParent() );
626
627 int groupId = aGroup->GetUIId();
628
629 wxAuiToolBarItem* item = FindTool( groupId );
630
631 if( !item )
632 return;
633
635
636 // Update the item information
637 item->SetShortHelp( aAction.GetButtonTooltip() );
638 item->SetBitmap( KiBitmapBundleDef( aAction.GetIcon(), iconSize ) );
639 item->SetDisabledBitmap( KiDisabledBitmapBundleDef( aAction.GetIcon(), iconSize ) );
640
641 // Register a new handler with the new UI conditions
642 if( m_toolManager )
643 {
644 m_toolManager->GetToolHolder()->UnregisterUIUpdateHandler( groupId );
645
646 const ACTION_CONDITIONS* cond = m_toolManager->GetActionManager()->GetCondition( aAction );
647
648 // Register the new UI condition to control this entry
649 if( cond )
650 {
651 m_toolManager->GetToolHolder()->RegisterUIUpdateHandler( groupId, *cond );
652 }
653 else
654 {
655 wxLogTrace( kicadTraceToolStack, wxString::Format( "No UI condition for action %s",
656 aAction.GetName() ) );
657 }
658 }
659
660 // Update the currently selected action
661 m_toolActions[ groupId ] = &aAction;
662 m_groupSelections[aGroup->GetName()] = aAction.GetName();
663
664 Refresh();
665}
666
667
669{
670 for( int id : m_controlIDs )
671 UpdateControlWidth( id );
672}
673
674
676{
677 wxAuiToolBarItem* item = FindTool( aID );
678 wxASSERT_MSG( item, wxString::Format( "No toolbar item found for ID %d", aID ) );
679
680 // The control on the toolbar is stored inside the window field of the item
681 wxControl* control = dynamic_cast<wxControl*>( item->GetWindow() );
682 wxASSERT_MSG( control, wxString::Format( "No control located in toolbar item with ID %d", aID ) );
683
684 // Update the size the item has stored using the best size of the control
685 control->InvalidateBestSize();
686 wxSize bestSize = control->GetBestSize();
687 item->SetMinSize( bestSize );
688
689 // Update the sizer item sizes
690 // This is a bit convoluted because there are actually 2 sizers that need to be updated:
691 // 1. The main sizer that is used for the entire toolbar (this sizer item can be found in the
692 // toolbar item)
693 if( wxSizerItem* szrItem = item->GetSizerItem() )
694 szrItem->SetMinSize( bestSize );
695
696 // 2. The controls have a second sizer that allows for padding above/below the control with
697 // stretch space, so we also need to update the sizer item for the control in that sizer with
698 // the new size. We let wx do the search for us, since SetItemMinSize is recursive and will
699 // locate the control on that sizer.
700 if( m_sizer )
701 {
702 m_sizer->SetItemMinSize( control, bestSize );
703
704 // Now actually update the toolbar with the new sizes
705 m_sizer->Layout();
706 }
707}
708
709
711{
712 // A group made again gets a new id, so the frame would keep this one's handler for good
713 if( m_toolManager )
714 {
715 for( const auto& [groupId, group] : m_actionGroups )
716 m_toolManager->GetToolHolder()->UnregisterUIUpdateHandler( groupId );
717 }
718
719 // Clear all the maps keeping track of our items on the toolbar
720 m_toolMenus.clear();
721 m_actionGroups.clear();
722 m_toolCancellable.clear();
723 m_toolKinds.clear();
724 m_toolActions.clear();
725
726 for( int id : m_controlIDs )
727 {
728 m_parent->ClearToolbarControl( id );
729 DestroyTool( id );
730 }
731
732 m_controlIDs.clear();
733
734 // Remove the actual tools from the toolbar
735 Clear();
736}
737
738
739void ACTION_TOOLBAR::SetToolBitmap( const TOOL_ACTION& aAction, const wxBitmapBundle& aBitmap )
740{
741 int toolId = aAction.GetUIId();
742
743 // Set the disabled bitmap: we use the disabled bitmap version of aBitmap.
744 wxAuiToolBarItem* tb_item = wxAuiToolBar::FindTool( toolId );
745
746 if( !tb_item )
747 return;
748
749 wxBitmap bm = aBitmap.GetBitmapFor( this );
750
751 tb_item->SetBitmap( aBitmap );
752 tb_item->SetDisabledBitmap( bm.ConvertToDisabled( KIPLATFORM::UI::IsDarkTheme() ? 70 : 255 ) );
753}
754
755
756void ACTION_TOOLBAR::Toggle( const TOOL_ACTION& aAction, bool aState )
757{
758 int toolId = aAction.GetUIId();
759
760 if( m_toolKinds[ toolId ] )
761 ToggleTool( toolId, aState );
762 else
763 EnableTool( toolId, aState );
764}
765
766
767void ACTION_TOOLBAR::Toggle( const TOOL_ACTION& aAction, bool aEnabled, bool aChecked )
768{
769 int toolId = aAction.GetUIId();
770
771 EnableTool( toolId, aEnabled );
772 ToggleTool( toolId, aEnabled && aChecked );
773}
774
775
776void ACTION_TOOLBAR::onToolEvent( wxAuiToolBarEvent& aEvent )
777{
778 int id = aEvent.GetId();
779 wxEventType type = aEvent.GetEventType();
780 OPT_TOOL_EVENT evt;
781
782 bool handled = false;
783
784 if( m_toolManager && type == wxEVT_COMMAND_TOOL_CLICKED )
785 {
786 const auto actionIt = m_toolActions.find( id );
787 const auto cancelIt = m_toolCancellable.find( id );
788 const auto groupIt = m_actionGroups.find( id );
789
790 // Determine if the tool is actually cancellable
791 bool isCancellable = ( cancelIt != m_toolCancellable.end() ) ? cancelIt->second : false;
792
793 // The toolbar item is toggled before the event is sent, so we check for it not being
794 // toggled to see if it was toggled originally
795 if( isCancellable && !GetToolToggled( id ) )
796 {
797 // Send a cancel event
798 m_toolManager->CancelTool();
799 handled = true;
800 }
801 else if( groupIt != m_actionGroups.end()
802 && std::none_of( groupIt->second->GetActions().begin(),
803 groupIt->second->GetActions().end(),
804 []( const TOOL_ACTION* a )
805 {
806 return a->IsActivation();
807 } ) )
808 {
809 // For non-tool toggle groups (units, crosshair, line modes), cycle to the next
810 // action on click. Tool groups (route track, etc.) fall through and just dispatch
811 // the currently displayed action.
812 ACTION_GROUP* group = groupIt->second.get();
813 const std::vector<const TOOL_ACTION*>& actions = group->GetActions();
814 const TOOL_ACTION* current = actionIt->second;
815
816 const TOOL_ACTION* next = actions[0];
817
818 for( size_t i = 0; i < actions.size(); ++i )
819 {
820 if( actions[i]->GetId() == current->GetId() )
821 {
822 next = actions[( i + 1 ) % actions.size()];
823 break;
824 }
825 }
826
827 evt = next->MakeEvent();
828 evt->SetHasPosition( false );
829 m_toolManager->ProcessEvent( *evt );
830 m_toolManager->GetToolHolder()->RefreshCanvas();
831
833 handled = true;
834 }
835 else if( actionIt != m_toolActions.end() )
836 {
837 // Dispatch a tool event
838 evt = actionIt->second->MakeEvent();
839 evt->SetHasPosition( false );
840 m_toolManager->ProcessEvent( *evt );
841 m_toolManager->GetToolHolder()->RefreshCanvas();
842 handled = true;
843 }
844 }
845
846 // Skip the event if we don't handle it
847 if( !handled )
848 aEvent.Skip();
849}
850
851
852void ACTION_TOOLBAR::onRightClick( wxAuiToolBarEvent& aEvent )
853{
854 int toolId = aEvent.GetToolId();
855
856 // This means the event was not on a button
857 if( toolId == -1 )
858 return;
859
860 showContextMenu( toolId );
861}
862
863
864void ACTION_TOOLBAR::onRightUp( wxMouseEvent& aEvent )
865{
866 // wxAuiToolBar::OnRightDown() uses horizontal-only geometry to reserve its overflow
867 // dead-zone, which on a vertical toolbar kills right-clicks over part of every button.
868 // Hit-test the tool ourselves so the whole button works.
869 wxAuiToolBarItem* item = FindToolByPosition( aEvent.GetX(), aEvent.GetY() );
870
871 if( !item )
872 {
873 aEvent.Skip();
874 return;
875 }
876
877 // Don't Skip(): suppress wx's own OnRightUp() so the menu is shown exactly once.
878 showContextMenu( item->GetId() );
879}
880
881
883{
884 // Ensure that the ID maps to a proper tool ID. If right-clicked on a group item, this is needed
885 // to get the ID of the currently selected action, since the event's ID is that of the group.
886 const auto actionIt = m_toolActions.find( aToolId );
887
888 if( actionIt != m_toolActions.end() )
889 aToolId = actionIt->second->GetUIId();
890
891 // Find the menu for the action
892 const auto menuIt = m_toolMenus.find( aToolId );
893
894 if( menuIt == m_toolMenus.end() )
895 return;
896
897 // Update and show the menu
898 std::unique_ptr<ACTION_MENU>& owningMenu = menuIt->second;
899
900 // Get the actual menu pointer to show it
901 ACTION_MENU* menu = owningMenu.get();
902 SELECTION dummySel;
903
904 if( CONDITIONAL_MENU* condMenu = dynamic_cast<CONDITIONAL_MENU*>( menu ) )
905 condMenu->Evaluate( dummySel );
906
907 menu->UpdateAll();
908 PopupMenu( menu );
909
910 // Remove hovered item when the menu closes, otherwise it remains hovered even if the
911 // mouse is not on the toolbar
912 SetHoverItem( nullptr );
913}
914
915
916// The time (in milliseconds) between pressing the left mouse button and opening the palette
917#define PALETTE_OPEN_DELAY 500
918
919
920void ACTION_TOOLBAR::onMouseClick( wxMouseEvent& aEvent )
921{
922 wxAuiToolBarItem* item = FindToolByPosition( aEvent.GetX(), aEvent.GetY() );
923
924 if( item )
925 {
926 // Ensure there is no active palette
927 if( m_palette )
928 {
929 m_palette->Hide();
930 m_palette->Destroy();
931 m_palette = nullptr;
932 }
933
934 // Start the popup conditions if it is a left mouse click and the tool clicked is a group
935 if( aEvent.LeftDown() && ( m_actionGroups.find( item->GetId() ) != m_actionGroups.end() ) )
937
938 // Clear the popup conditions if it is a left up, because that implies a click happened
939 if( aEvent.LeftUp() )
940 m_paletteTimer->Stop();
941 }
942
943 // Skip the event so wx can continue processing the mouse event
944 aEvent.Skip();
945}
946
947
948void ACTION_TOOLBAR::onItemDrag( wxAuiToolBarEvent& aEvent )
949{
950 int toolId = aEvent.GetToolId();
951
952 if( m_actionGroups.find( toolId ) != m_actionGroups.end() )
953 {
954 wxAuiToolBarItem* item = FindTool( toolId );
955
956 // Use call after because opening the palette from a mouse handler
957 // creates a weird mouse state that causes problems on OSX.
958 CallAfter( &ACTION_TOOLBAR::popupPalette, item );
959
960 // Don't skip this event since we are handling it
961 return;
962 }
963
964 // Skip since we don't care about it
965 aEvent.Skip();
966}
967
968
969void ACTION_TOOLBAR::onTimerDone( wxTimerEvent& aEvent )
970{
971 // We need to search for the tool using the client coordinates
972 wxPoint mousePos = ScreenToClient( KIPLATFORM::UI::GetMousePosition() );
973
974 wxAuiToolBarItem* item = FindToolByPosition( mousePos.x, mousePos.y );
975
976 if( item )
977 popupPalette( item );
978}
979
980
981void ACTION_TOOLBAR::onPaletteEvent( wxCommandEvent& aEvent )
982{
983 if( !m_palette )
984 return;
985
986 // Clear m_palette up front so a re-entrant dispatch (modal dialog pumping events)
987 // hits the null guard above instead of double-destroying.
989 m_palette = nullptr;
990
991 OPT_TOOL_EVENT evt;
992 ACTION_GROUP* group = palette->GetGroup();
993
994 // Find the action corresponding to the button press
995 auto actionIt = std::find_if( group->GetActions().begin(), group->GetActions().end(),
996 [&]( const TOOL_ACTION* aAction )
997 {
998 return aAction->GetUIId() == aEvent.GetId();
999 } );
1000
1001 if( actionIt != group->GetActions().end() )
1002 {
1003 const TOOL_ACTION* action = *actionIt;
1004
1005 // Dispatch a tool event
1006 evt = action->MakeEvent();
1007 evt->SetHasPosition( false );
1008 m_toolManager->ProcessEvent( *evt );
1009 m_toolManager->GetToolHolder()->RefreshCanvas();
1010
1011 // Update the main toolbar item with the selected action
1012 doSelectAction( group, *action );
1013 }
1014
1015 // Hide the palette
1016 palette->Hide();
1017 palette->Destroy();
1018}
1019
1020
1021void ACTION_TOOLBAR::popupPalette( wxAuiToolBarItem* aItem )
1022{
1023 // Clear all popup conditions
1024 m_paletteTimer->Stop();
1025
1026 wxWindow* toolParent = dynamic_cast<wxWindow*>( m_toolManager->GetToolHolder() );
1027
1028 wxCHECK( GetParent() && m_auiManager && toolParent, /* void */ );
1029
1030 // Ensure the item we are using for the palette has a group associated with it.
1031 const auto it = m_actionGroups.find( aItem->GetId() );
1032
1033 if( it == m_actionGroups.end() )
1034 return;
1035
1036 ACTION_GROUP* group = it->second.get();
1037
1038 wxAuiPaneInfo& pane = m_auiManager->GetPane( this );
1039
1040 // We use the size of the toolbar items for our palette buttons
1041 wxRect toolRect = GetToolRect( aItem->GetId() );
1042
1043 // The position for the palette window must be in screen coordinates
1044 wxPoint pos( ClientToScreen( toolRect.GetPosition() ) );
1045
1046 // True for vertical buttons, false for horizontal
1047 bool dir = pane.dock_direction != wxAUI_DOCK_LEFT && pane.dock_direction != wxAUI_DOCK_RIGHT;
1048
1049 m_palette = new ACTION_TOOLBAR_PALETTE( GetParent(), dir );
1050
1051 m_palette->SetGroup( group );
1052 m_palette->SetButtonSize( toolRect );
1053 m_palette->Connect( wxEVT_BUTTON, wxCommandEventHandler( ACTION_TOOLBAR::onPaletteEvent ), nullptr, this );
1054
1055
1056 for( const TOOL_ACTION* action : group->m_actions )
1057 {
1058 wxUpdateUIEvent evt( action->GetUIId() );
1059
1060 toolParent->ProcessWindowEvent( evt );
1061
1062 m_palette->AddAction( *action );
1063
1064 if( evt.GetSetEnabled() )
1065 m_palette->EnableAction( *action, evt.GetEnabled() );
1066 }
1067
1068 wxSize paletteSize = m_palette->GetFittedSize();
1069
1070 // Determine the position of the top left corner of the palette window
1071 switch( pane.dock_direction )
1072 {
1073 case wxAUI_DOCK_TOP:
1074 // Top toolbars need to shift the palette window down by the toolbar padding
1075 pos = ClientToScreen( toolRect.GetBottomLeft() );
1076 pos += wxPoint( -PALETTE_BORDER, // Shift left to align the button edges
1077 m_bottomPadding ); // Shift down to move away from the toolbar
1078 break;
1079
1080 case wxAUI_DOCK_BOTTOM:
1081 // Bottom toolbars need to shift the palette window up by its height (all buttons +
1082 // border + toolbar padding)
1083 pos = ClientToScreen( toolRect.GetTopLeft() );
1084 pos += wxPoint( -PALETTE_BORDER, // Shift left to align the button
1085 // Shift up by the entire length of the palette.
1086 -( paletteSize.GetHeight() + m_topPadding ) );
1087 break;
1088
1089 case wxAUI_DOCK_LEFT:
1090 // Left toolbars open the palette to the right, with a small extra nudge so it does not
1091 // paint over the toolbar icon that opened it.
1092 pos = ClientToScreen( toolRect.GetTopRight() );
1093 pos += wxPoint( m_rightPadding + PALETTE_BORDER, 0 );
1094 break;
1095
1096 case wxAUI_DOCK_RIGHT:
1097 // Right toolbars need to shift the palette window left by its width (all buttons +
1098 // border + toolbar padding)
1099 pos = ClientToScreen( toolRect.GetTopLeft() );
1100
1101 // Shift left by the palette length, with a small extra nudge so it does not paint over
1102 // the toolbar icon that opened it.
1103 pos += wxPoint( -( paletteSize.GetWidth() + m_leftPadding + PALETTE_BORDER ), 0 );
1104 break;
1105 }
1106
1107 // Release the mouse to ensure the first click will be recognized in the palette
1108 if( HasCapture() )
1109 ReleaseMouse();
1110
1111 m_palette->SetPosition( pos );
1112 m_palette->Popup();
1113
1114 // Clear the mouse state on the toolbar because otherwise wxWidgets gets confused
1115 // and won't properly display any highlighted items after the palette is closed.
1116 // (This is the equivalent of calling the DoResetMouseState() private function)
1117 RefreshOverflowState();
1118 SetHoverItem( nullptr );
1119 SetPressedItem( nullptr );
1120
1121 m_dragging = false;
1122 m_tipItem = nullptr;
1123 m_actionPos = wxPoint( -1, -1 );
1124 m_actionItem = nullptr;
1125}
1126
1127
1128void ACTION_TOOLBAR::OnCustomRender(wxDC& aDc, const wxAuiToolBarItem& aItem, const wxRect& aRect )
1129{
1130 auto it = m_actionGroups.find( aItem.GetId() );
1131
1132 if( it == m_actionGroups.end() )
1133 return;
1134
1135 // Choose the color to draw the triangle
1136 wxColour clr;
1137
1138 if( aItem.GetState() & wxAUI_BUTTON_STATE_DISABLED )
1139 clr = wxSystemSettings::GetColour( wxSYS_COLOUR_GRAYTEXT );
1140 else
1141 clr = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNTEXT );
1142
1143 // Must set both the pen (for the outline) and the brush (for the polygon fill)
1144 aDc.SetPen( wxPen( clr ) );
1145 aDc.SetBrush( wxBrush( clr ) );
1146
1147 // Make the side length of the triangle approximately 1/5th of the bitmap
1148 int sideLength = KiROUND( aRect.height / 5.0 );
1149
1150 // This will create a triangle with its point at the bottom right corner,
1151 // and its other two corners along the right and bottom sides
1152 wxPoint btmRight = aRect.GetBottomRight();
1153 wxPoint topCorner( btmRight.x, btmRight.y - sideLength );
1154 wxPoint btmCorner( btmRight.x - sideLength, btmRight.y );
1155
1156 wxPointList points;
1157 points.Append( &btmRight );
1158 points.Append( &topCorner );
1159 points.Append( &btmCorner );
1160
1161 aDc.DrawPolygon( &points );
1162}
1163
1164
1166{
1167#if wxCHECK_VERSION( 3, 3, 0 )
1168 return Realize();
1169#else
1170 wxClientDC dc( this );
1171
1172 if( !dc.IsOk() )
1173 return false;
1174
1175 // calculate hint sizes for both horizontal and vertical
1176 // in the order that leaves toolbar in correct final state
1177
1178 // however, skip calculating alternate orientations if we don't need them due to window style
1179 bool retval = true;
1180
1181 if( m_orientation == wxHORIZONTAL )
1182 {
1183 if( !( GetWindowStyle() & wxAUI_TB_HORIZONTAL ) )
1184 {
1185 m_vertHintSize = GetSize();
1186 retval = RealizeHelper( dc, false );
1187 }
1188
1189 if( retval && RealizeHelper( dc, true ) )
1190 m_horzHintSize = GetSize();
1191 else
1192 retval = false;
1193 }
1194 else
1195 {
1196 if( !( GetWindowStyle() & wxAUI_TB_VERTICAL ) )
1197 {
1198 m_horzHintSize = GetSize();
1199 retval = RealizeHelper( dc, true );
1200 }
1201
1202 if( retval && RealizeHelper( dc, false ) )
1203 m_vertHintSize = GetSize();
1204 else
1205 retval = false;
1206 }
1207
1208 Refresh( false );
1209 return retval;
1210#endif
1211}
1212
1213
1214void ACTION_TOOLBAR::onThemeChanged( wxSysColourChangedEvent &aEvent )
1215{
1218
1219 aEvent.Skip();
1220}
1221
1222
1224{
1226
1227 for( const std::pair<int, const TOOL_ACTION*> pair : m_toolActions )
1228 {
1229 wxAuiToolBarItem* tool = FindTool( pair.first );
1230
1231 tool->SetBitmap( KiBitmapBundleDef( pair.second->GetIcon(), iconSize ) );
1232 tool->SetDisabledBitmap( KiDisabledBitmapBundleDef( pair.second->GetIcon(), iconSize ) );
1233 }
1234
1235 Refresh();
1236}
1237
1238/*
1239 * Common controls for the toolbar
1240 */
1242 _( "Grid selector" ),
1243 _( "Grid Selection box" ),
1244 { FRAME_SCH,
1251 FRAME_PL_EDITOR } );
1252
1253
1255 _( "Zoom selector" ),
1256 _( "Zoom Selection box" ),
1257 { FRAME_SCH,
1265 FRAME_PL_EDITOR } );
1266
1268 _( "IPC/Scripting plugins" ),
1269 _( "Region to hold the IPC/Scripting action buttons" ),
1270 { FRAME_SCH,
1274
1276 _( "Layer selector" ),
1277 _( "Control to select the layer" ),
1281 FRAME_GERBER } );
1282
1284 _( "Symbol unit selector" ),
1285 _( "Displays the current unit" ),
1287 FRAME_SCH_VIEWER } );
1288
1290 _( "Symbol body style selector" ),
1291 _( "Displays the current body style" ),
1293 FRAME_SCH_VIEWER } );
1294
1296 _( "Override locks" ),
1297 _( "Allow moving of locked items with the mouse" ),
#define PALETTE_BORDER
#define PALETTE_OPEN_DELAY
#define BUTTON_BORDER
std::function< void(ACTION_TOOLBAR *)> ACTION_TOOLBAR_CONTROL_FACTORY
Type for the function signature that is used to add custom controls to the toolbar.
wxBitmapBundle KiBitmapBundleDef(BITMAPS aBitmap, int aDefHeight)
Construct and return a bitmap bundle for the given icon ID, with the default bitmap size being aDefHe...
Definition bitmap.cpp:112
int KiIconScale(wxWindow *aWindow)
Return the automatic scale factor that would be used for a given window by KiScaledBitmap and KiScale...
Definition bitmap.cpp:130
BITMAP_STORE * GetBitmapStore()
Definition bitmap.cpp:88
KICOMMON_API wxBitmapBundle KiDisabledBitmapBundleDef(BITMAPS aBitmap, int aDefHeight)
Definition bitmap.cpp:124
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
A group of actions that will be displayed together on a toolbar palette.
void SetDefaultAction(const TOOL_ACTION &aDefault)
Set the default action to use when first creating the toolbar palette icon.
ACTION_GROUP(const std::string_view &aName)
std::vector< const TOOL_ACTION * > m_actions
The actions that compose the group. Non-owning.
void SetActions(const std::vector< const TOOL_ACTION * > &aActions)
Set the actions contained in this group.
int GetUIId() const
Get the ID used in the UI to reference this group.
int m_id
The action ID for this action group.
const TOOL_ACTION * m_defaultAction
The default action to display on the toolbar item.
std::string m_name
The name of this action group.
std::string GetName() const
Get the name of the group.
static int MakeActionId(const std::string &aActionName)
Generate an unique ID from for an action with given name.
Define the structure of a menu based on ACTIONs.
Definition action_menu.h:43
void UpdateAll()
Run update handlers for the menu and its submenus.
static ACTION_TOOLBAR_CONTROL gridSelect
static ACTION_TOOLBAR_CONTROL overrideLocks
static ACTION_TOOLBAR_CONTROL layerSelector
static ACTION_TOOLBAR_CONTROL zoomSelect
static ACTION_TOOLBAR_CONTROL unitSelector
static ACTION_TOOLBAR_CONTROL ipcScripting
static ACTION_TOOLBAR_CONTROL bodyStyleSelector
Class to hold basic information about controls that can be added to the toolbars.
A popup window that contains a row of toolbar-like buttons for the user to choose from.
void CheckAction(const TOOL_ACTION &aAction, bool aCheck=true)
Check/Toggle the button for an action on the palette.
void onCharHook(wxKeyEvent &aEvent)
void AddAction(const TOOL_ACTION &aAction)
Add an action to the palette.
ACTION_TOOLBAR_PALETTE(wxWindow *aParent, bool aVertical)
Create the palette.
wxRect m_buttonSize
The size each button on the toolbar should be.
void EnableAction(const TOOL_ACTION &aAction, bool aEnable=true)
Enable the button for an action on the palette.
ACTION_GROUP * m_group
The group that the buttons in the palette are part of.
std::map< int, BITMAP_BUTTON * > m_buttons
The buttons that act as the toolbar on the palette.
bool m_isVertical
True if the palette uses vertical buttons, false for horizontal buttons.
ACTION_GROUP * GetGroup()
void Popup(wxWindow *aFocus=nullptr) override
Popup this window.
void RefreshBitmaps()
Reload all the bitmaps for the tools (e.g.
void SetToolBitmap(const TOOL_ACTION &aAction, const wxBitmapBundle &aBitmap)
Updates the bitmap of a particular tool.
void OnCustomRender(wxDC &aDc, const wxAuiToolBarItem &aItem, const wxRect &aRect) override
Render the triangle in the lower-right corner that represents that an action palette is available for...
void onTimerDone(wxTimerEvent &aEvent)
Handle the palette timer triggering.
void doSelectAction(ACTION_GROUP *aGroup, const TOOL_ACTION &aAction)
Update a group toolbar item to look like a specific action.
void onMouseClick(wxMouseEvent &aEvent)
Handler for a mouse up/down event.
void AddButton(const TOOL_ACTION &aAction)
Add a large button such as used in the KiCad Manager Frame's launch bar.
wxAuiManager * m_auiManager
void UpdateControlWidth(int aID)
Update the toolbar item width of a control using its best size.
ACTION_TOOLBAR(EDA_BASE_FRAME *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxAUI_TB_DEFAULT_STYLE)
void Toggle(const TOOL_ACTION &aAction, bool aState)
Apply the default toggle action.
void SelectAction(ACTION_GROUP *aGroup, const TOOL_ACTION &aAction)
Select an action inside a group.
void Add(const TOOL_ACTION &aAction)
Add a TOOL_ACTION-based button to the toolbar.
static std::list< ACTION_TOOLBAR_CONTROL * > & GetAllCustomControls()
Get the list of custom controls that could be used on toolbars.
void onPaletteEvent(wxCommandEvent &aEvent)
Handle the button select inside the palette.
void onRightClick(wxAuiToolBarEvent &aEvent)
Handle a right-click on a menu item.
wxTimer * m_paletteTimer
std::map< int, std::unique_ptr< ACTION_MENU > > m_toolMenus
void onToolEvent(wxAuiToolBarEvent &aEvent)
The default tool event handler.
void onItemDrag(wxAuiToolBarEvent &aEvent)
Handler for when a drag event occurs on an item.
std::map< int, bool > m_toolKinds
static std::list< ACTION_TOOLBAR_CONTROL * > GetCustomControlList(FRAME_T aContext)
Get the list of custom controls that could be used on a particular frame type.
std::map< int, std::unique_ptr< ACTION_GROUP > > m_actionGroups
void AddGroup(std::unique_ptr< ACTION_GROUP > aGroup)
Add a set of actions to a toolbar as a group.
void AddToolContextMenu(const TOOL_ACTION &aAction, std::unique_ptr< ACTION_MENU > aMenu)
Add a context menu to a specific tool item on the toolbar.
void DoSetToolTipText(const wxString &aTip) override
std::map< int, bool > m_toolCancellable
void AddScaledSeparator(wxWindow *aWindow)
Add a separator that introduces space on either side to not squash the tools when scaled.
bool KiRealize()
Use this over Realize() to avoid a rendering glitch with fixed orientation toolbars.
void popupPalette(wxAuiToolBarItem *aItem)
Popup the ACTION_TOOLBAR_PALETTE associated with the ACTION_GROUP of the given toolbar item.
virtual ~ACTION_TOOLBAR()
ACTION_TOOLBAR_PALETTE * m_palette
std::vector< int > m_controlIDs
IDs for all the control items in this toolbar.
void onThemeChanged(wxSysColourChangedEvent &aEvent)
EDA_BASE_FRAME * m_parent
std::map< int, const TOOL_ACTION * > m_toolActions
std::map< std::string, std::string > m_groupSelections
Selected action per group name.
void ClearToolbar()
Clear the toolbar and remove all associated menus.
void onRightUp(wxMouseEvent &aEvent)
Handle a right mouse button release; resolves the tool ourselves to work around a wxAuiToolBar hit-te...
void showContextMenu(int aToolId)
Show the context menu registered for the given tool ID (handles group remapping).
void UpdateControlWidths()
Update the width of all wxControl tools on thsi toolbar.
void ApplyConfiguration(const TOOLBAR_CONFIGURATION &aConfig)
Replace the contents of this toolbar with the configuration given in aConfig.
TOOL_MANAGER * m_toolManager
A bitmap button widget that behaves like an AUI toolbar item's button when it is drawn.
void AcceptDragInAsClick(bool aAcceptDragIn=true)
Accept mouse-up as click even if mouse-down happened outside of the control.
void SetDisabledBitmap(const wxBitmapBundle &aBmp)
Set the bitmap shown when the button is disabled.
void SetBitmapCentered(bool aCentered=true)
void SetIsToolbarButton(bool aIsToolbar=true)
void SetPadding(int aPaddingDIP)
Set the amount of padding present on each side of the bitmap.
void SetBitmap(const wxBitmapBundle &aBmp)
Set the bitmap shown when the button is enabled.
void ThemeChanged()
Notifies the store that the icon theme has been changed by the user, so caches must be invalidated.
APPEARANCE m_Appearance
The base frame for deriving all KiCad main window classes.
ACTION_TOOLBAR_CONTROL_FACTORY * GetCustomToolbarControlFactory(const std::string &aName)
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:551
std::vector< TOOLBAR_ITEM > GetToolbarItems() const
static MENU_FACTORY GetMenuFactory(const std::string &aActionName)
Get the menu factory for an action, if one is registered.
static MENU_FACTORY GetGroupMenuFactory(const std::string &aGroupName)
Get the menu factory for a group, if one is registered.
std::vector< TOOLBAR_ITEM > m_GroupItems
std::string m_ActionName
TOOLBAR_ITEM_TYPE m_Type
Represent a single user action.
static int GetBaseUIId()
Get the base value used to offset the user interface IDs for the actions.
BITMAPS GetIcon() const
Return an icon associated with the action.
int GetId() const
Return the unique id of the TOOL_ACTION object.
const std::string & GetName() const
Return name of the action.
bool CheckToolbarState(TOOLBAR_STATE aState) const
Check if a specific toolbar state is required for this action.
TOOL_EVENT MakeEvent() const
Return the event associated with the action (i.e.
wxString GetButtonTooltip() const
int GetUIId() const
Get the unique ID for this action in the user interface system.
void SetHasPosition(bool aHasPosition)
Definition tool_event.h:257
#define _(s)
FRAME_T
The set of EDA_BASE_FRAME derivatives, typically stored in EDA_BASE_FRAME::m_Ident.
Definition frame_type.h:29
@ FRAME_PCB_EDITOR
Definition frame_type.h:38
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
@ FRAME_FOOTPRINT_VIEWER
Definition frame_type.h:41
@ FRAME_SCH_VIEWER
Definition frame_type.h:32
@ FRAME_SCH
Definition frame_type.h:30
@ FRAME_PL_EDITOR
Definition frame_type.h:55
@ FRAME_FOOTPRINT_EDITOR
Definition frame_type.h:39
@ FRAME_GERBER
Definition frame_type.h:53
@ FRAME_PCB_DISPLAY3D
Definition frame_type.h:43
const wxChar *const kicadTraceToolStack
Flag to enable tracing of the tool handling stack.
wxPoint GetMousePosition()
Returns the mouse position in screen coordinates.
Definition wxgtk/ui.cpp:930
bool IsDarkTheme()
Determine if the desktop interface is currently using a dark theme or a light theme.
Definition wxgtk/ui.cpp:52
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
CITER next(CITER it)
Definition ptree.cpp:120
const int scale
Functors that can be used to figure out how the action controls should be displayed in the UI and if ...
@ TOGGLE
Action is a toggle button on the toolbar.
Definition tool_action.h:60
@ CANCEL
Action can be cancelled by clicking the toolbar button again.
Definition tool_action.h:61
@ HIDDEN
Action is hidden from the toolbar.
Definition tool_action.h:59
std::optional< TOOL_EVENT > OPT_TOOL_EVENT
Definition tool_event.h:652
wxLogTrace helper definitions.