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