KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_toolbar_customization.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <bitmaps.h>
31
32#include <magic_enum.hpp>
33#include <wx/listctrl.h>
34#include <wx/menu.h>
35
36// Simple IDs for the split button menu
37enum
38{
39 ID_SEPARATOR_MENU = ( wxID_HIGHEST + 5 ),
42};
43
44
45static std::map<TOOLBAR_LOC, wxString> s_toolbarNameMap = {
46 { TOOLBAR_LOC::LEFT, _( "Left" ) },
47 { TOOLBAR_LOC::RIGHT, _( "Right" ) },
48 { TOOLBAR_LOC::TOP_MAIN, _( "Top main" ) },
49 { TOOLBAR_LOC::TOP_AUX, _( "Top auxillary" ) }
50};
51
52
53class TOOLBAR_TREE_ITEM_DATA : public wxTreeItemData
54{
55public:
57 { }
58
60 m_type( aType )
61 { }
62
64 m_type( aType ),
65 m_size( aSize )
66 {
67 wxASSERT( aType == TOOLBAR_ITEM_TYPE::SPACER );
68 }
69
70 TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE aType, wxString aName ) :
71 m_type( aType ),
72 m_name( aName )
73 {
74 wxASSERT( aType == TOOLBAR_ITEM_TYPE::CONTROL
75 || aType == TOOLBAR_ITEM_TYPE::TB_GROUP );
76 }
77
79 m_type( aType ),
80 m_action( aAction )
81 {
82 wxASSERT( aType == TOOLBAR_ITEM_TYPE::TOOL );
83 }
84
85 void SetAction( TOOL_ACTION* aAction ) { m_action = aAction; }
86 TOOL_ACTION* GetAction() const { return m_action; }
87
88 void SetName( const wxString& aName ) { m_name = aName; }
89 const wxString& GetName() const { return m_name; }
90
91 void SetSize( int aSize ) { m_size = aSize; }
92 int GetSize() const { return m_size; }
93
94 TOOLBAR_ITEM_TYPE GetType() const { return m_type; }
95
96private:
97 // Item type
99
100 // Tool properties
102
103 // Spacer properties
105
106 // Group/control properties
107 wxString m_name;
108};
109
110
112 TOOLBAR_SETTINGS* aTbSettings,
113 std::vector<TOOL_ACTION*> aTools,
114 std::vector<ACTION_TOOLBAR_CONTROL*> aControls ) :
116 m_actionImageList( nullptr ),
117 m_appSettings( aCfg ),
118 m_appTbSettings( aTbSettings )
119{
120 // Copy the tools and controls into the internal maps
121 for( auto& tool : aTools )
122 m_availableTools.emplace( tool->GetName(), tool );
123
124 for( auto& control : aControls )
125 m_availableControls.emplace( control->GetName(), control );
126
127 // Configure the Ui elements
128 m_btnToolDelete->SetBitmap( KiBitmapBundle( BITMAPS::small_trash ) );
129 m_btnToolMoveUp->SetBitmap( KiBitmapBundle( BITMAPS::small_up ) );
130 m_btnToolMoveDown->SetBitmap( KiBitmapBundle( BITMAPS::small_down ) );
131 m_btnAddTool->SetBitmap( KiBitmapBundle( BITMAPS::left ) );
132
133 m_insertButton->SetLabel( _( "Insert separator" ) );
134 //m_insertButton->SetWidthPadding( 4 );
135
136 // Populate the browse library options
137 wxMenu* insertMenu = m_insertButton->GetSplitButtonMenu();
138
139 insertMenu->Append( ID_SPACER_MENU, _( "Insert spacer" ) );
140 insertMenu->Append( ID_GROUP_MENU, _( "Insert group" ) );
141
142 insertMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_TOOLBAR_CUSTOMIZATION::onSpacerPress,
143 this, ID_SPACER_MENU );
144 insertMenu->Bind( wxEVT_COMMAND_MENU_SELECTED, &PANEL_TOOLBAR_CUSTOMIZATION::onGroupPress,
145 this, ID_GROUP_MENU );
146
147 // This is the button only press for the browse button instead of the menu
149
150 // TODO (ISM): Enable moving up/down and draging
151 m_btnToolMoveDown->Enable( false );
152 m_btnToolMoveUp->Enable( false );
153}
154
155
157{
158 delete m_actionImageList;
159}
160
161
163{
164 // Go over every toolbar and initialize things
165 for( auto& tb : magic_enum::enum_values<TOOLBAR_LOC>() )
166 {
167 // Create a shadow toolbar
168 auto tbConfig = m_appTbSettings->DefaultToolbarConfig( tb );
169
170 if( tbConfig.has_value() )
171 m_toolbars[tb] = tbConfig.value();
172 }
173
174 // Populate the toolbar view with the default toolbar
175 m_tbChoice->SetSelection( 0 );
176
177 auto firstTb = magic_enum::enum_cast<TOOLBAR_LOC>( 0 );
178
179 if( firstTb.has_value() )
180 m_currentToolbar = firstTb.value();
181
183
184}
185
186
188{
189 wxArrayString tbChoices;
190
191 // Go over every toolbar and initialize things
192 for( auto& tb : magic_enum::enum_values<TOOLBAR_LOC>() )
193 {
194 // Create a shadow toolbar
195 auto tbConfig = m_appTbSettings->GetToolbarConfig( tb );
196
197 if( tbConfig.has_value() )
198 m_toolbars.emplace( tb, tbConfig.value() );
199
200 // Setup the UI name
201 const auto& tbName = s_toolbarNameMap.find( tb );
202
203 wxASSERT_MSG( tbName != s_toolbarNameMap.end(),
204 wxString::Format( "Unknown toolbar: %s", magic_enum::enum_name( tb ) ) );
205
206 tbChoices.Add( tbName->second );
207 }
208
209 m_tbChoice->Set( tbChoices );
210
211 // Always populate the actions before the toolbars, that way the icons are available
213
214 // Populate the toolbar view
215 m_tbChoice->SetSelection( 0 );
216
217 auto firstTb = magic_enum::enum_cast<TOOLBAR_LOC>( 0 );
218
219 if( firstTb.has_value() )
220 m_currentToolbar = firstTb.value();
221
223
224 // Sync the enable/disable control
227
228 return true;
229}
230
231
233{
235
236 // Store the current toolbar
237 auto currentTb = parseToolbarTree();
238
239 if( currentTb.has_value() )
240 m_toolbars[m_currentToolbar] = currentTb.value();
241
242 // Write the shadow toolbars with changes back to the app toolbar settings
243 for( auto& tb : m_toolbars )
244 m_appTbSettings->SetStoredToolbarConfig( tb.first, tb.second );
245
246 return true;
247}
248
249
250std::optional<TOOLBAR_CONFIGURATION> PANEL_TOOLBAR_CUSTOMIZATION::parseToolbarTree()
251{
253
254 wxTreeItemId mainId;
255 wxTreeItemId rootId = m_toolbarTree->GetRootItem();
256 wxTreeItemIdValue mainCookie;
257
258 if( !rootId.IsOk() )
259 return std::nullopt;
260
261 mainId = m_toolbarTree->GetFirstChild( rootId, mainCookie );
262
263 while( mainId.IsOk() )
264 {
265 wxTreeItemData* treeData = m_toolbarTree->GetItemData( mainId );
266
267 TOOLBAR_TREE_ITEM_DATA* tbData = dynamic_cast<TOOLBAR_TREE_ITEM_DATA*>( treeData );
268
269 wxASSERT( tbData );
270
271 switch( tbData->GetType() )
272 {
273 case TOOLBAR_ITEM_TYPE::SPACER:
274 config.AppendSpacer( tbData->GetSize() );
275 break;
276
277 case TOOLBAR_ITEM_TYPE::SEPARATOR:
278 config.AppendSeparator();
279 break;
280
281 case TOOLBAR_ITEM_TYPE::CONTROL:
282 config.AppendControl( tbData->GetName().ToStdString() );
283 break;
284
285 case TOOLBAR_ITEM_TYPE::TOOL:
286 config.AppendAction( *( tbData->GetAction() ) );
287 break;
288
289 case TOOLBAR_ITEM_TYPE::TB_GROUP:
290 TOOLBAR_GROUP_CONFIG grpConfig( tbData->GetName() );
291
292 if( m_toolbarTree->ItemHasChildren( mainId ) )
293 {
294 wxTreeItemIdValue childCookie;
295 wxTreeItemId childId = m_toolbarTree->GetFirstChild( mainId, childCookie );
296
297 while( childId.IsOk() )
298 {
299 wxTreeItemData* childTreeData = m_toolbarTree->GetItemData( childId );
300
301 TOOLBAR_TREE_ITEM_DATA* childTbData = dynamic_cast<TOOLBAR_TREE_ITEM_DATA*>( childTreeData );
302
303 wxASSERT( childTbData );
304
305 switch( childTbData->GetType() )
306 {
307 case TOOLBAR_ITEM_TYPE::TB_GROUP:
308 case TOOLBAR_ITEM_TYPE::SPACER:
309 case TOOLBAR_ITEM_TYPE::SEPARATOR:
310 case TOOLBAR_ITEM_TYPE::CONTROL:
311 wxASSERT_MSG( false, "Invalid entry in a group" );
312 break;
313
314 case TOOLBAR_ITEM_TYPE::TOOL:
315 grpConfig.AddAction( *( childTbData->GetAction() ) );
316 break;
317 }
318
319 childId = m_toolbarTree->GetNextChild( mainId, childCookie );
320 }
321 }
322
323 config.AppendGroup( grpConfig );
324 }
325
326 mainId = m_toolbarTree->GetNextChild( rootId, mainCookie );
327 }
328
329 return config;
330}
331
332
334{
335 m_toolbarTree->DeleteAllItems();
336 m_toolbarTree->SetImageList( m_actionImageList );
337
338 const auto& it = m_toolbars.find( m_currentToolbar );
339
340 if( it == m_toolbars.end() )
341 {
342 // Disable the controls and bail out - no toolbar here
343 enableToolbarControls( false );
344 return;
345 }
346
347 // Ensure the controls are enabled
348 enableToolbarControls( true );
349
350 TOOLBAR_CONFIGURATION toolbar = it->second;
351
352 wxTreeItemId root = m_toolbarTree->AddRoot( "Toolbar" );
353
354 for( auto& item : toolbar.GetToolbarItems() )
355 {
356 switch( item.m_Type )
357 {
358 case TOOLBAR_ITEM_TYPE::SEPARATOR:
359 {
360 // Add a separator
361 TOOLBAR_TREE_ITEM_DATA* sepTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::SEPARATOR );
362 m_toolbarTree->AppendItem( root, "Separator", -1, -1, sepTreeItem );
363 break;
364 }
365
366 case TOOLBAR_ITEM_TYPE::SPACER:
367 {
368 // Add a spacer
369 TOOLBAR_TREE_ITEM_DATA* spacerTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::SPACER );
370 spacerTreeItem->SetSize( item.m_Size );
371 m_toolbarTree->AppendItem( root, wxString::Format( "Spacer: %i", item.m_Size ), -1, -1,
372 spacerTreeItem );
373 break;
374 }
375
376 case TOOLBAR_ITEM_TYPE::CONTROL:
377 {
378 // Add a control
379 TOOLBAR_TREE_ITEM_DATA* controlTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::CONTROL );
380 controlTreeItem->SetName( item.m_ControlName );
381 m_toolbarTree->AppendItem( root, item.m_ControlName, -1, -1,
382 controlTreeItem );
383 break;
384 }
385
386 case TOOLBAR_ITEM_TYPE::TOOL:
387 {
388 // Add a tool
389 auto toolMap = m_availableTools.find( item.m_ActionName );
390
391 if( toolMap == m_availableTools.end() )
392 {
393 wxASSERT_MSG( false, wxString::Format( "Unable to find tool %s", item.m_ActionName ) );
394 continue;
395 }
396
397 TOOLBAR_TREE_ITEM_DATA* toolTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::TOOL );
398 toolTreeItem->SetAction( toolMap->second );
399
400 int imgIdx = -1;
401 auto imgMap = m_actionImageListMap.find( item.m_ActionName );
402
403 if( imgMap != m_actionImageListMap.end() )
404 imgIdx = imgMap->second;
405
406 m_toolbarTree->AppendItem( root, toolMap->second->GetFriendlyName(),
407 imgIdx, -1, toolTreeItem );
408 break;
409 }
410
411 case TOOLBAR_ITEM_TYPE::TB_GROUP:
412 {
413 // Add a group of items to the toolbar
414 TOOLBAR_TREE_ITEM_DATA* groupTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::TB_GROUP );
415 groupTreeItem->SetName( item.m_GroupName );
416
417 wxTreeItemId groupId = m_toolbarTree->AppendItem( root, item.m_GroupName, -1, -1,
418 groupTreeItem );
419
420 // Add the elements below the group
421 for( auto& groupItem : item.m_GroupItems )
422 {
423 auto toolMap = m_availableTools.find( groupItem.m_ActionName );
424
425 if( toolMap == m_availableTools.end() )
426 {
427 wxASSERT_MSG( false, wxString::Format( "Unable to find group tool %s", groupItem.m_ActionName ) );
428 continue;
429 }
430
431 TOOLBAR_TREE_ITEM_DATA* toolTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::TOOL );
432 toolTreeItem->SetAction( toolMap->second );
433
434 int imgIdx = -1;
435 auto imgMap = m_actionImageListMap.find( groupItem.m_ActionName );
436
437 if( imgMap != m_actionImageListMap.end() )
438 imgIdx = imgMap->second;
439
440 m_toolbarTree->AppendItem( groupId, toolMap->second->GetFriendlyName(),
441 imgIdx, -1, toolTreeItem );
442 }
443 break;
444 }
445 }
446 }
447
448 m_toolbarTree->ExpandAll();
449
450 wxTreeItemIdValue temp;
451 wxTreeItemId firstItem = m_toolbarTree->GetFirstChild( root, temp );
452
453 if( firstItem.IsOk() )
454 {
455 m_toolbarTree->SelectItem( firstItem );
456 m_toolbarTree->EnsureVisible( firstItem );
457 }
458}
459
460
462{
463 // Clear all existing information for the actions
464 delete m_actionImageList;
465 m_actionImageListMap.clear();
467
468 // Prep the control
469 m_actionsList->DeleteAllItems();
470 m_actionsList->DeleteAllColumns();
471 m_actionsList->InsertColumn( 0, "", wxLIST_FORMAT_LEFT, wxLIST_AUTOSIZE );
472
473 // Prepare the image list (taken from project_tree.cpp)
474 int logicSize = 24 * GetDPIScaleFactor() / GetContentScaleFactor(); // Cross-platform way
475 int physSize = ToPhys( logicSize ); // aka *GetContentScaleFactor()
476
477 if( physSize >= 64 )
478 physSize = 64;
479 else if( physSize >= 48 )
480 physSize = 48;
481 else if( physSize >= 32 )
482 physSize = 32;
483 else
484 physSize = 24;
485
486 logicSize = std::min( logicSize, physSize );
487 int bmpsf = std::max( 1, physSize / logicSize );
488
489 logicSize = physSize / bmpsf;
490
491 auto toBitmap = [&]( BITMAPS aBmps )
492 {
493 wxBitmap bmp = KiBitmap( aBmps, physSize );
494 bmp.SetScaleFactor( bmpsf );
495 wxASSERT(bmp.IsOk());
496 return bmp;
497 };
498
499 m_actionImageList = new wxImageList( logicSize, logicSize, true,
500 static_cast<int>( m_availableTools.size() ) );
501
502 // Populate the various image lists for the action icons, and the actual control
503 int itemIdx = 0;
504
505 for( auto [k, tool] : m_availableTools )
506 {
507 if( tool->CheckToolbarState( TOOLBAR_STATE::HIDDEN ) )
508 continue;
509
510 wxListItem item;
511 item.SetText( tool->GetFriendlyName() );
512 item.SetData( static_cast<void*>( tool ) );
513 item.SetId( itemIdx++ );
514
515 if( tool->GetIcon() != BITMAPS::INVALID_BITMAP )
516 {
517 int idx = m_actionImageList->Add( toBitmap( tool->GetIcon() ) );
518
519 // If the image list throws away the image, then we shouldn't show the image anywhere.
520 // TODO: Make sure all images have all possible sizes so the image list doesn't get grumpy.
521 if( idx != -1 )
522 {
523 m_actionImageBundleVector.push_back( KiBitmapBundle( tool->GetIcon() ) );
524 m_actionImageListMap.emplace( tool->GetName(), idx );
525
526 item.SetImage( idx );
527 }
528 }
529
530 m_actionsList->InsertItem( item );
531 }
532
533 m_actionsList->SetSmallImages( m_actionImageBundleVector );
534
535 // This must be done after adding everything to the list to make the columns wide enough
536 m_actionsList->SetColumnWidth( 0, wxLIST_AUTOSIZE );
537}
538
539
540void PANEL_TOOLBAR_CUSTOMIZATION::onGroupPress( wxCommandEvent& aEvent )
541{
542 TOOLBAR_TREE_ITEM_DATA* treeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::TB_GROUP,
543 _( "Group" ) );
544
545 wxTreeItemId newItem;
546 wxTreeItemId selItem = m_toolbarTree->GetSelection();
547
548 if( selItem.IsOk() )
549 {
550 // Can't add a group onto a group
551 wxTreeItemId parent = m_toolbarTree->GetItemParent( selItem );
552
553 if( parent.IsOk() )
554 {
555 wxTreeItemId secondParent = m_toolbarTree->GetItemParent( parent );
556
557 if( secondParent.IsOk() )
558 {
559 delete treeItem;
560 return;
561 }
562 }
563
564 newItem = m_toolbarTree->InsertItem( m_toolbarTree->GetRootItem(), selItem, treeItem->GetName(),
565 -1, -1, treeItem );
566 }
567 else
568 {
569 newItem = m_toolbarTree->AppendItem( m_toolbarTree->GetRootItem(), treeItem->GetName(), -1, -1,
570 treeItem );
571 }
572
573 if( newItem.IsOk() )
574 {
575 m_toolbarTree->SelectItem( newItem );
576 m_toolbarTree->EnsureVisible( newItem );
577 }
578}
579
580
581void PANEL_TOOLBAR_CUSTOMIZATION::onSpacerPress( wxCommandEvent& aEvent )
582{
583 TOOLBAR_TREE_ITEM_DATA* treeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::SPACER, 5 );
584
585 wxString label = wxString::Format( "Spacer: %i", treeItem->GetSize() );
586
587 wxTreeItemId newItem;
588 wxTreeItemId selItem = m_toolbarTree->GetSelection();
589
590 if( selItem.IsOk() )
591 {
592 // Insert after the current selection at the same level
593 wxTreeItemId parent = m_toolbarTree->GetItemParent( selItem );
594
595 // Can't insert a spacer in a group yet
596 if( parent.IsOk() )
597 {
598 wxTreeItemId secondParent = m_toolbarTree->GetItemParent( parent );
599
600 if( secondParent.IsOk() )
601 {
602 delete treeItem;
603 return;
604 }
605 }
606
607 newItem = m_toolbarTree->InsertItem( parent, selItem, label, -1, -1, treeItem );
608 }
609 else
610 newItem = m_toolbarTree->AppendItem( m_toolbarTree->GetRootItem(), label, -1, -1, treeItem );
611
612 if( newItem.IsOk() )
613 {
614 m_toolbarTree->SelectItem( newItem );
615 m_toolbarTree->EnsureVisible( newItem );
616 }
617}
618
619
621{
622 TOOLBAR_TREE_ITEM_DATA* treeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::SEPARATOR );
623
624 wxTreeItemId newItem;
625 wxTreeItemId selItem = m_toolbarTree->GetSelection();
626
627 if( selItem.IsOk() )
628 {
629 // Insert after the current selection at the same level
630 wxTreeItemId parent = m_toolbarTree->GetItemParent( selItem );
631
632 // Can't insert a separator in a group yet
633 if( parent.IsOk() )
634 {
635 wxTreeItemId secondParent = m_toolbarTree->GetItemParent( parent );
636
637 if( secondParent.IsOk() )
638 {
639 delete treeItem;
640 return;
641 }
642 }
643
644 newItem = m_toolbarTree->InsertItem( parent, selItem, "Separator", -1, -1, treeItem );
645 }
646 else
647 {
648 newItem = m_toolbarTree->AppendItem( m_toolbarTree->GetRootItem(), "Separator", -1, -1,
649 treeItem );
650 }
651
652 if( newItem.IsOk() )
653 {
654 m_toolbarTree->SelectItem( newItem );
655 m_toolbarTree->EnsureVisible( newItem );
656 }
657}
658
659
661{
662 enableCustomControls( event.IsChecked() );
663}
664
665
667{
668 m_tbChoice->Enable( enable );
669 enableToolbarControls( enable );
670}
671
672
674{
675 m_toolbarTree->Enable( enable );
676 m_btnAddTool->Enable( enable );
677 m_btnToolDelete->Enable( enable );
678
679 // TODO (ISM): Enable moving up/down
680 //m_btnToolMoveDown->Enable( enable );
681 //m_btnToolMoveUp->Enable( enable );
682 m_actionsList->Enable( enable );
683 m_insertButton->Enable( enable );
684}
685
686
687void PANEL_TOOLBAR_CUSTOMIZATION::onToolDelete( wxCommandEvent& event )
688{
689 wxTreeItemId item = m_toolbarTree->GetSelection();
690
691 if( !item.IsOk() )
692 return;
693
694 // The tree control defaults to nothing selected if you delete the item
695 // at the last place, so we have to manually get the itme immediately before
696 // the one we will delete, and then select it if nothing is selected.
697 wxTreeItemId prev = m_toolbarTree->GetPrevSibling( item );
698
699 m_toolbarTree->Delete( item );
700
701 item = m_toolbarTree->GetSelection();
702
703 if( !item.IsOk() && prev.IsOk() )
704 {
705 m_toolbarTree->SelectItem( prev );
706 m_toolbarTree->EnsureVisible( prev );
707 }
708}
709
710
711void PANEL_TOOLBAR_CUSTOMIZATION::onToolMoveUp( wxCommandEvent& event )
712{
713
714}
715
716
718{
719
720}
721
722
724{
725 // Get the selected item
726 long actionIdx = m_actionsList->GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED );
727
728 // Nothing is selected, bail out
729 if( actionIdx < 0 )
730 return;
731
732 // This is needed because GetItemData returns a wxUIntPtr, which is actually size_t...
733 void* v = ( void* ) m_actionsList->GetItemData( actionIdx );
734 TOOL_ACTION* action = static_cast<TOOL_ACTION*>( v );
735
736 // Build the item to add
737 TOOLBAR_TREE_ITEM_DATA* toolTreeItem = new TOOLBAR_TREE_ITEM_DATA( TOOLBAR_ITEM_TYPE::TOOL );
738 toolTreeItem->SetAction( action );
739
740 int imgIdx = -1;
741 auto imgMap = m_actionImageListMap.find( action->GetName() );
742
743 if( imgMap != m_actionImageListMap.end() )
744 imgIdx = imgMap->second;
745
746 // Actually add the item
747 wxString label = action->GetFriendlyName();
748 wxTreeItemId selItem = m_toolbarTree->GetSelection();
749 wxTreeItemId newItem;
750
751 if( selItem.IsOk() )
752 {
753
755 dynamic_cast<TOOLBAR_TREE_ITEM_DATA*>( m_toolbarTree->GetItemData( selItem ) );
756
757 if( data && data->GetType() == TOOLBAR_ITEM_TYPE::TB_GROUP )
758 {
759 // Insert into the end of the group
760 newItem = m_toolbarTree->AppendItem( selItem, label, imgIdx, -1, toolTreeItem );
761 }
762 else
763 {
764 // Insert after the current selection at the same level
765 wxTreeItemId parent = m_toolbarTree->GetItemParent( selItem );
766 newItem = m_toolbarTree->InsertItem( parent, selItem, label, imgIdx, -1, toolTreeItem );
767 }
768 }
769 else
770 {
771 // Insert at the root level if there is no selection
772 newItem = m_toolbarTree->AppendItem( m_toolbarTree->GetRootItem(), label, imgIdx, -1,
773 toolTreeItem );
774 }
775
776 if( newItem.IsOk() )
777 {
778 m_toolbarTree->SelectItem( newItem );
779 m_toolbarTree->EnsureVisible( newItem );
780
781 // Move the action to the next available one, to be nice
782 if( ++actionIdx < m_actionsList->GetItemCount() )
783 m_actionsList->SetItemState( actionIdx, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED );
784 }
785}
786
787
789{
790 wxTreeItemId id = event.GetItem();
791
792 if( id.IsOk() )
793 {
794 wxTreeItemData* treeData = m_toolbarTree->GetItemData( id );
795 TOOLBAR_TREE_ITEM_DATA* tbData = dynamic_cast<TOOLBAR_TREE_ITEM_DATA*>( treeData );
796
797 switch( tbData->GetType() )
798 {
799 case TOOLBAR_ITEM_TYPE::TOOL:
800 case TOOLBAR_ITEM_TYPE::CONTROL:
801 case TOOLBAR_ITEM_TYPE::SEPARATOR:
802 // Don't let these be edited
803 event.Veto();
804 break;
805
806 case TOOLBAR_ITEM_TYPE::TB_GROUP:
807 case TOOLBAR_ITEM_TYPE::SPACER:
808 // Do nothing here
809 break;
810 }
811 }
812}
813
814
816{
817
818}
819
820
822{
823 // Store the current toolbar
824 auto currentTb = parseToolbarTree();
825
826 if( currentTb.has_value() )
827 m_toolbars[m_currentToolbar] = currentTb.value();
828
829 // Populate the new one
830 auto newTb = magic_enum::enum_cast<TOOLBAR_LOC>( event.GetInt() );
831
832 if( newTb.has_value() )
833 {
834 m_currentToolbar = newTb.value();
836 }
837}
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
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition: bitmap.cpp:110
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad application.
Definition: app_settings.h:92
bool m_CustomToolbars
Use custom toolbars.
Definition: app_settings.h:202
Class PANEL_TOOLBAR_CUSTOMIZATION_BASE.
void onSpacerPress(wxCommandEvent &aEvent)
wxVector< wxBitmapBundle > m_actionImageBundleVector
PANEL_TOOLBAR_CUSTOMIZATION(wxWindow *aParent, APP_SETTINGS_BASE *aCfg, TOOLBAR_SETTINGS *aTbSettings, std::vector< TOOL_ACTION * > aTools, std::vector< ACTION_TOOLBAR_CONTROL * > aControls)
void onTbChoiceSelect(wxCommandEvent &event) override
void onTreeEndLabelEdit(wxTreeEvent &event) override
void onTreeBeginLabelEdit(wxTreeEvent &event) override
void onToolDelete(wxCommandEvent &event) override
std::map< TOOLBAR_LOC, TOOLBAR_CONFIGURATION > m_toolbars
void onGroupPress(wxCommandEvent &aEvent)
void onSeparatorPress(wxCommandEvent &aEvent)
void ResetPanel() override
Reset the contents of this panel.
std::map< std::string, int > m_actionImageListMap
void onBtnAddAction(wxCommandEvent &event) override
std::map< std::string, TOOL_ACTION * > m_availableTools
std::map< std::string, ACTION_TOOLBAR_CONTROL * > m_availableControls
std::optional< TOOLBAR_CONFIGURATION > parseToolbarTree()
void onCustomizeTbCb(wxCommandEvent &event) override
void onToolMoveDown(wxCommandEvent &event) override
void onToolMoveUp(wxCommandEvent &event) override
void SetLabel(const wxString &aLabel) override
wxMenu * GetSplitButtonMenu()
bool Enable(bool aEnable=true) override
bool Enable(bool aEnable=true) override
void SetBitmap(const wxBitmapBundle &aBmp)
std::vector< TOOLBAR_ITEM > GetToolbarItems() const
TOOLBAR_GROUP_CONFIG & AddAction(std::string aActionName)
virtual std::optional< TOOLBAR_CONFIGURATION > DefaultToolbarConfig(TOOLBAR_LOC aToolbar)
Get the default tools to show on the specified canvas toolbar.
void SetStoredToolbarConfig(TOOLBAR_LOC aToolbar, TOOLBAR_CONFIGURATION &aConfig)
Set the stored configuration for the given toolbar.
std::optional< TOOLBAR_CONFIGURATION > GetToolbarConfig(TOOLBAR_LOC aToolbar, bool aAllowCustom=true)
Get the tools to show on the specified canvas toolbar.
void SetName(const wxString &aName)
void SetAction(TOOL_ACTION *aAction)
TOOLBAR_TREE_ITEM_DATA(TOOLBAR_ITEM_TYPE aType)
TOOLBAR_TREE_ITEM_DATA(TOOLBAR_ITEM_TYPE aType, int aSize)
TOOLBAR_TREE_ITEM_DATA(TOOLBAR_ITEM_TYPE aType, TOOL_ACTION *aAction)
const wxString & GetName() const
TOOLBAR_TREE_ITEM_DATA(TOOLBAR_ITEM_TYPE aType, wxString aName)
TOOLBAR_ITEM_TYPE GetType() const
Represent a single user action.
Definition: tool_action.h:304
const std::string & GetName() const
Return name of the action.
Definition: tool_action.h:337
wxString GetFriendlyName() const
Return the translated user-friendly name of the action.
#define _(s)
static std::map< TOOLBAR_LOC, wxString > s_toolbarNameMap
@ RIGHT
Toolbar on the right side of the canvas.
@ LEFT
Toolbar on the left side of the canvas.
@ TOP_AUX
Toolbar on the top of the canvas.
@ TOP_MAIN
Toolbar on the top of the canvas.
TOOLBAR_ITEM_TYPE