Merge ~qu1ck/kicad:plugin-icon-squashed into ~kicad-product-committers/kicad:master

Proposed by Andrew Lutsenko
Status: Superseded
Proposed branch: ~qu1ck/kicad:plugin-icon-squashed
Merge into: ~kicad-product-committers/kicad:master
Diff against target: 2260 lines (+1637/-186)
21 files modified
common/bitmap.cpp (+19/-0)
common/widgets/grid_icon_text_helpers.cpp (+40/-1)
include/bitmap_types.h (+8/-0)
include/widgets/grid_icon_text_helpers.h (+18/-1)
pcbnew/CMakeLists.txt (+7/-2)
pcbnew/action_plugin.cpp (+44/-2)
pcbnew/action_plugin.h (+49/-11)
pcbnew/dialogs/panel_pcbnew_action_plugins.cpp (+199/-0)
pcbnew/dialogs/panel_pcbnew_action_plugins.h (+70/-0)
pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp (+98/-0)
pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp (+578/-0)
pcbnew/dialogs/panel_pcbnew_action_plugins_base.h (+58/-0)
pcbnew/pcb_edit_frame.cpp (+2/-0)
pcbnew/pcb_edit_frame.h (+55/-4)
pcbnew/pcb_general_settings.cpp (+45/-0)
pcbnew/pcb_general_settings.h (+5/-0)
pcbnew/pcbnew_config.cpp (+4/-0)
pcbnew/swig/pcbnew_action_plugins.cpp (+308/-164)
pcbnew/swig/pcbnew_action_plugins.h (+3/-0)
pcbnew/tool_pcb_editor.cpp (+4/-0)
scripting/kicadplugins.i (+23/-1)
Reviewer Review Type Date Requested Status
Seth Hillbrand Pending
Jeff Young Pending
Review via email: mp+353692@code.launchpad.net

This proposal supersedes a proposal from 2018-08-24.

This proposal has been superseded by a proposal from 2018-08-25.

Commit message

Add toolbar buttons for action plugins

Description of the change

This adds toolbar buttons for pcbnew action plugins and a corresponding settings dialog in preferences which allows you to choose which buttons to show and their order.

To post a comment you must log in.
Revision history for this message
Seth Hillbrand (sethh) wrote : Posted in a previous version of this proposal

Overall looks good. I haven't checked MacOS compatibility, so I tagged Jeff Young to comment.

The code style issues are scattered around, I think I found most all.

You should remove the unsafe/unused functions.

I don't think we should be mixing IDs between buttons and menus.

You can simplify your map usage to just a vector (O(n) is fine for searching this)

Can you squash these into a single commit (this is to allow git bisect without errors)?

review: Needs Fixing
Revision history for this message
Jeff Young (jeyjey) wrote : Posted in a previous version of this proposal

I didn't try to compile it yet as my tree's in the middle of something.

Revision history for this message
Andrew Lutsenko (qu1ck) wrote : Posted in a previous version of this proposal

Thanks for comments, I replied to all of them inline.

> Can you squash these into a single commit (this is to allow git bisect without errors)?

Can launchpad not do it on merge? If so I think I'll have to open separate merge request in the end. Will LP review system tolerate rewritten commit history?

Revision history for this message
Andrew Lutsenko (qu1ck) wrote :

I found a way to squash commits and resubmit current proposal.

Revision history for this message
Jeff Young (jeyjey) wrote :

A few more comments for you, Andrew. Looking good!

Revision history for this message
Wayne Stambaugh (stambaughw) wrote : Posted in a previous version of this proposal
Download full text (17.6 KiB)

On 08/23/2018 05:01 PM, Seth Hillbrand wrote:
> Review: Needs Fixing
>
> Overall looks good. I haven't checked MacOS compatibility, so I tagged Jeff Young to comment.
>
> The code style issues are scattered around, I think I found most all.
>
> You should remove the unsafe/unused functions.
>
> I don't think we should be mixing IDs between buttons and menus.

@Seth, event IDs for menu and toolbar actions should be the same. In
fact wxMENU_EVENT is the same as wxTOOL_EVENT. It's merely a #define in
wxwidgets. Please use the same event ID for the toolbar and the menu
for running the same script or you will be creating a maintenance issue.

>
> You can simplify your map usage to just a vector (O(n) is fine for searching this)
>
> Can you squash these into a single commit (this is to allow git bisect without errors)?
>
> Diff comments:
>
>> diff --git a/common/widgets/grid_icon_text_helpers.cpp b/common/widgets/grid_icon_text_helpers.cpp
>> index 8d348c7..feb04bb 100644
>> --- a/common/widgets/grid_icon_text_helpers.cpp
>> +++ b/common/widgets/grid_icon_text_helpers.cpp
>> @@ -68,6 +68,45 @@ void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, w
>> aGrid.DrawTextRectangle( aDC, value, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
>> }
>>
>> +//---- Grid helpers: custom wxGridCellRenderer that renders just an icon ----------------
>> +//
>> +// Note: this renderer is supposed to be used with read only cells
>> +
>> +GRID_CELL_ICON_RENDERER::GRID_CELL_ICON_RENDERER(const wxBitmap& icon) : m_icon( icon )
>> +{
>> +}
>> +
>> +
>> +void GRID_CELL_ICON_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
>> + const wxRect& aRect, int aRow, int aCol, bool isSelected )
>> +{
>> + wxRect rect = aRect;
>> + rect.Inflate( -1 );
>> +
>> + // erase background
>> + wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
>> +
>> + // Draw icon
>> + if( m_icon.IsOk() )
>> + {
>> + aDC.DrawBitmap( m_icon,
>> + rect.GetLeft() + (rect.GetWidth() - m_icon.GetWidth()) / 2,
>
> Whitespace here around parentheses
>
>> + rect.GetTop() + (rect.GetHeight() - m_icon.GetHeight()) / 2,
>> + true );
>> + }
>> +}
>> +
>> +
>> +wxSize GRID_CELL_ICON_RENDERER::GetBestSize(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, int row, int col)
>
> Whitespace here around parentheses.
>
>> +{
>> + return wxSize( m_icon.GetWidth() + 6, m_icon.GetHeight() + 4 );
>> +}
>> +
>> +
>> +wxGridCellRenderer* GRID_CELL_ICON_RENDERER::Clone() const
>> +{
>> + return new GRID_CELL_ICON_RENDERER( m_icon );
>> +}
>>
>>
>> //---- Grid helpers: custom wxGridCellEditor ------------------------------------------
>> diff --git a/include/widgets/grid_icon_text_helpers.h b/include/widgets/grid_icon_text_helpers.h
>> index 9e14829..e859f11 100644
>> --- a/include/widgets/grid_icon_text_helpers.h
>> +++ b/include/widgets/grid_icon_text_helpers.h
>> @@ -49,6 +49,23 @@ private:
>> const wxArrayString& m_names;
>> };
>>
>> +//---- Grid helpers: custom wxGridCellRenderer that re...

Revision history for this message
Seth Hillbrand (sethh) wrote : Posted in a previous version of this proposal

@Wayne- My comment here was unclear. The IDs are generated by wx when the menu items are added and a different ID is generated when the toolbar button is added. However, they are linked in the same callback handler, checking first for the menu button ID in the event and then, failing that, for the toolbar button ID. My concern was that separating the event handling based on wx's autogenerated IDs makes an assumption about the IDs. I'd feel better about that line if the handler split based on an event type and then did the ID lookup in the related list.

Revision history for this message
Wayne Stambaugh (stambaughw) wrote : Posted in a previous version of this proposal

@Seth, got it. I don't have any further issues.

Revision history for this message
Andrew Lutsenko (qu1ck) wrote :

Some comments got lost after I force pushed an update. That's why I didn't want to squash commits early.

@Seth
I split event handler for buttons and menus. They call common function. Is that what you had in mind?

@Jeff
I addressed your comments. About pythons calls: they don't throw, they return errors and there is also PyErr_Occurred() which checks for python exception state. It's done in CallMethod()

Also if you are worried about backward compatibility with old plugins I made sure that they still work. New fields in ActionPlugin class are set by default so plugin writers don't have to change anything unless they want to add a custom icon.

Revision history for this message
Andrew Lutsenko (qu1ck) :

Unmerged commits

41192c0... by Andrew Lutsenko

Add toolbar buttons for action plugins

Add icons to action menu items as well

Fix backwards compatibility for plugins that don't define icon

Fix compilation errors for action plugin icon code

Fixes compilation with actio menu option off.
Fixes compilation error on non windows platforms.

Make showing toolbar button optional for action plugins

Add "Action Plugins" panel stub in pcbnew settings

Add action plugin grid form and stub

Load action plugin list in pcbnew prefs

Add category, description and path to action plugin grid

Store and read action plugin settings display buttons accordingly

Add action plugin ordering buttons in preferences

Don't show error on icon load failure

Fix build with actions menu disabled

Adjust action plugins grid properties

Fix bug with plugin order when one is removed and another added

Also fix formatting

Scale plugin icons on toolbar

Address review comments

Removed unused methods, switched to std::vector from map where possible,
fixed formatting and spelling.

Address another round of comments

Also append class name to plugin path to avoid issues with multiple classes in single plugin file

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/common/bitmap.cpp b/common/bitmap.cpp
index 031b2cc..bce8344 100644
--- a/common/bitmap.cpp
+++ b/common/bitmap.cpp
@@ -144,6 +144,25 @@ wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow )
144}144}
145145
146146
147wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, EDA_BASE_FRAME* aWindow )
148{
149 const int scale = get_scale_factor( aWindow );
150
151 if( scale == 4)
152 {
153 return wxBitmap( aBitmap );
154 }
155 else
156 {
157 wxImage image = aBitmap.ConvertToImage();
158 image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4,
159 wxIMAGE_QUALITY_BILINEAR );
160
161 return wxBitmap( image );
162 }
163}
164
165
147void KiScaledSeparator( wxAuiToolBar* aToolbar, EDA_BASE_FRAME* aWindow )166void KiScaledSeparator( wxAuiToolBar* aToolbar, EDA_BASE_FRAME* aWindow )
148{167{
149 const int scale = get_scale_factor( aWindow );168 const int scale = get_scale_factor( aWindow );
diff --git a/common/widgets/grid_icon_text_helpers.cpp b/common/widgets/grid_icon_text_helpers.cpp
index 8d348c7..b1f949e 100644
--- a/common/widgets/grid_icon_text_helpers.cpp
+++ b/common/widgets/grid_icon_text_helpers.cpp
@@ -27,7 +27,7 @@
27#include <wx/dc.h>27#include <wx/dc.h>
2828
2929
30//---- Grid helpers: custom wxGridCellRenderer ------------------------------------------30//---- Grid helpers: custom wxGridCellRenderer that renders icon and a label ------------
3131
3232
33GRID_CELL_ICON_TEXT_RENDERER::GRID_CELL_ICON_TEXT_RENDERER( const std::vector<BITMAP_DEF>& icons,33GRID_CELL_ICON_TEXT_RENDERER::GRID_CELL_ICON_TEXT_RENDERER( const std::vector<BITMAP_DEF>& icons,
@@ -68,6 +68,45 @@ void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, w
68 aGrid.DrawTextRectangle( aDC, value, rect, wxALIGN_LEFT, wxALIGN_CENTRE );68 aGrid.DrawTextRectangle( aDC, value, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
69}69}
7070
71//---- Grid helpers: custom wxGridCellRenderer that renders just an icon ----------------
72//
73// Note: this renderer is supposed to be used with read only cells
74
75GRID_CELL_ICON_RENDERER::GRID_CELL_ICON_RENDERER(const wxBitmap& icon) : m_icon( icon )
76{
77}
78
79
80void GRID_CELL_ICON_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
81 const wxRect& aRect, int aRow, int aCol, bool isSelected )
82{
83 wxRect rect = aRect;
84 rect.Inflate( -1 );
85
86 // erase background
87 wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
88
89 // Draw icon
90 if( m_icon.IsOk() )
91 {
92 aDC.DrawBitmap( m_icon,
93 rect.GetLeft() + ( rect.GetWidth() - m_icon.GetWidth() ) / 2,
94 rect.GetTop() + ( rect.GetHeight() - m_icon.GetHeight() ) / 2,
95 true );
96 }
97}
98
99
100wxSize GRID_CELL_ICON_RENDERER::GetBestSize( wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, int row, int col )
101{
102 return wxSize( m_icon.GetWidth() + 6, m_icon.GetHeight() + 4 );
103}
104
105
106wxGridCellRenderer* GRID_CELL_ICON_RENDERER::Clone() const
107{
108 return new GRID_CELL_ICON_RENDERER( m_icon );
109}
71110
72111
73//---- Grid helpers: custom wxGridCellEditor ------------------------------------------112//---- Grid helpers: custom wxGridCellEditor ------------------------------------------
diff --git a/include/bitmap_types.h b/include/bitmap_types.h
index 8657df4..f703ddb 100644
--- a/include/bitmap_types.h
+++ b/include/bitmap_types.h
@@ -73,6 +73,14 @@ wxBitmap KiBitmap( BITMAP_DEF aBitmap );
73 */73 */
74wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow );74wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow );
7575
76/**
77 * Function KiScaledBitmap
78 * Overload of the above function that takes another wxBitmap as a parameter
79 *
80 * @param aBitmap bitmap definition
81 * @param aWindow target window for scaling context
82 */
83wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, EDA_BASE_FRAME* aWindow );
7684
77/**85/**
78 * Function KiScaledSeparator86 * Function KiScaledSeparator
diff --git a/include/widgets/grid_icon_text_helpers.h b/include/widgets/grid_icon_text_helpers.h
index 9e14829..60ea612 100644
--- a/include/widgets/grid_icon_text_helpers.h
+++ b/include/widgets/grid_icon_text_helpers.h
@@ -34,7 +34,7 @@
34class wxGrid;34class wxGrid;
3535
3636
37//---- Grid helpers: custom wxGridCellRenderer ------------------------------------------37//---- Grid helpers: custom wxGridCellRenderer that renders icon and a label ------------
3838
39class GRID_CELL_ICON_TEXT_RENDERER : public wxGridCellStringRenderer39class GRID_CELL_ICON_TEXT_RENDERER : public wxGridCellStringRenderer
40{40{
@@ -49,6 +49,23 @@ private:
49 const wxArrayString& m_names;49 const wxArrayString& m_names;
50};50};
5151
52//---- Grid helpers: custom wxGridCellRenderer that renders just an icon ----------------
53//
54// Note: use with read only cells
55
56class GRID_CELL_ICON_RENDERER : public wxGridCellRenderer
57{
58public:
59 GRID_CELL_ICON_RENDERER( const wxBitmap& icon );
60
61 void Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
62 const wxRect& aRect, int aRow, int aCol, bool isSelected ) override;
63 wxSize GetBestSize( wxGrid & grid, wxGridCellAttr & attr, wxDC & dc, int row, int col ) override;
64 wxGridCellRenderer* Clone() const override;
65
66private:
67 const wxBitmap& m_icon;
68};
5269
53//---- Grid helpers: custom wxGridCellEditor ------------------------------------------70//---- Grid helpers: custom wxGridCellEditor ------------------------------------------
54//71//
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index a77f8eb..2202080 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -152,8 +152,6 @@ set( PCBNEW_DIALOGS
152 dialogs/panel_modedit_settings_base.cpp152 dialogs/panel_modedit_settings_base.cpp
153 dialogs/panel_pcbnew_display_options.cpp153 dialogs/panel_pcbnew_display_options.cpp
154 dialogs/panel_pcbnew_display_options_base.cpp154 dialogs/panel_pcbnew_display_options_base.cpp
155 dialogs/panel_pcbnew_display_options.cpp
156 dialogs/panel_pcbnew_display_options_base.cpp
157 dialogs/panel_pcbnew_settings.cpp155 dialogs/panel_pcbnew_settings.cpp
158 dialogs/panel_pcbnew_settings_base.cpp156 dialogs/panel_pcbnew_settings_base.cpp
159 dialogs/panel_setup_mask_and_paste.cpp157 dialogs/panel_setup_mask_and_paste.cpp
@@ -174,6 +172,13 @@ set( PCBNEW_DIALOGS
174 ${GITHUB_3DLIBRARIES_WIZARD}172 ${GITHUB_3DLIBRARIES_WIZARD}
175 )173 )
176174
175if( KICAD_SCRIPTING AND KICAD_SCRIPTING_ACTION_MENU )
176 set( PCBNEW_DIALOGS ${PCBNEW_DIALOGS}
177 dialogs/panel_pcbnew_action_plugins.cpp
178 dialogs/panel_pcbnew_action_plugins_base.cpp
179 )
180endif()
181
177set( PCBNEW_IMPORT_DXF182set( PCBNEW_IMPORT_DXF
178 import_dxf/dialog_dxf_import.cpp183 import_dxf/dialog_dxf_import.cpp
179 import_dxf/dialog_dxf_import_base.cpp184 import_dxf/dialog_dxf_import_base.cpp
diff --git a/pcbnew/action_plugin.cpp b/pcbnew/action_plugin.cpp
index c10d0fa..e79ea29 100644
--- a/pcbnew/action_plugin.cpp
+++ b/pcbnew/action_plugin.cpp
@@ -73,9 +73,37 @@ void ACTION_PLUGINS::SetActionMenu( int aIndex, int idMenu )
73}73}
7474
7575
76int ACTION_PLUGINS::GetActionMenu( int aIndex )76ACTION_PLUGIN* ACTION_PLUGINS::GetActionByButton( int aButton )
77{77{
78 return m_actionsList[aIndex]->m_actionMenuId;78 int max = GetActionsCount();
79
80 for( int i = 0; i < max; i++ )
81 {
82 if( m_actionsList[i]->m_actionButtonId == aButton )
83 return m_actionsList[i];
84 }
85
86 return NULL;
87}
88
89
90void ACTION_PLUGINS::SetActionButton( ACTION_PLUGIN* aAction, int idButton )
91{
92 aAction->m_actionButtonId = idButton;
93}
94
95
96ACTION_PLUGIN* ACTION_PLUGINS::GetActionByPath(const wxString& aPath)
97{
98 for( int i = 0; i < GetActionsCount() ; i++ )
99 {
100 if( m_actionsList[i]->GetPluginPath() == aPath)
101 {
102 return m_actionsList[i];
103 }
104 }
105
106 return NULL;
79}107}
80108
81109
@@ -127,6 +155,20 @@ void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction )
127 }155 }
128 }156 }
129157
158 // Load icon if supplied
159 if (!aAction->GetIconFileName().IsEmpty())
160 {
161 {
162 wxLogNull eat_errors;
163 aAction->iconBitmap.LoadFile( aAction->GetIconFileName() , wxBITMAP_TYPE_PNG );
164 }
165
166 if ( !aAction->iconBitmap.IsOk() )
167 {
168 wxLogVerbose( "Failed to load icon " + aAction->GetIconFileName() + " for action plugin " );
169 }
170 }
171
130 m_actionsList.push_back( aAction );172 m_actionsList.push_back( aAction );
131}173}
132174
diff --git a/pcbnew/action_plugin.h b/pcbnew/action_plugin.h
index ff3ed14..8bb6c9c 100644
--- a/pcbnew/action_plugin.h
+++ b/pcbnew/action_plugin.h
@@ -44,9 +44,16 @@ public:
44 // m_actionMenuId set to 0 means the corresponding menuitem to call this44 // m_actionMenuId set to 0 means the corresponding menuitem to call this
45 // action is not yet created45 // action is not yet created
46 int m_actionMenuId;46 int m_actionMenuId;
47 // Same for button id
48 int m_actionButtonId;
49 // Icon for the action button and menu entry
50 wxBitmap iconBitmap;
51 // If show_on_toolbar is true a button will be added to top toolbar
52 bool show_on_toolbar;
4753
48public:54public:
49 ACTION_PLUGIN() : m_actionMenuId( 0 ) {}55 ACTION_PLUGIN() : m_actionMenuId( 0 ), m_actionButtonId( 0 ),
56 show_on_toolbar( false ) {}
50 virtual ~ACTION_PLUGIN();57 virtual ~ACTION_PLUGIN();
5158
52 /**59 /**
@@ -69,6 +76,24 @@ public:
69 virtual wxString GetDescription() = 0;76 virtual wxString GetDescription() = 0;
7077
71 /**78 /**
79 * Function GetShowToolbarButton
80 * @return true if button should be shown on top toolbar
81 */
82 virtual bool GetShowToolbarButton() = 0;
83
84 /**
85 * Function GetIconFileName
86 * @return a path to icon for the action plugin button
87 */
88 virtual wxString GetIconFileName() = 0;
89
90 /**
91 * Function GetPluginPath
92 * @return a path this plugin was loaded from
93 */
94 virtual wxString GetPluginPath() = 0;
95
96 /**
72 * Function GetObject97 * Function GetObject
73 * This method gets the pointer to the object from where this action constructs98 * This method gets the pointer to the object from where this action constructs
74 * @return it's a void pointer, as it could be a PyObject or any other99 * @return it's a void pointer, as it could be a PyObject or any other
@@ -137,16 +162,6 @@ public:
137 */162 */
138 static void SetActionMenu( int aIndex, int idMenu );163 static void SetActionMenu( int aIndex, int idMenu );
139164
140
141 /**
142 * Function GetActionMenu
143 * Provide menu id for a plugin index
144 * @param aIndex is the action index
145 * @return associated menuitem id
146 */
147 static int GetActionMenu( int aIndex );
148
149
150 /**165 /**
151 * Function GetActionByMenu166 * Function GetActionByMenu
152 * find action plugin associated to a menu id167 * find action plugin associated to a menu id
@@ -155,6 +170,29 @@ public:
155 */170 */
156 static ACTION_PLUGIN* GetActionByMenu( int aMenu );171 static ACTION_PLUGIN* GetActionByMenu( int aMenu );
157172
173 /**
174 * Function SetActionButton
175 * Associate a button id to an action plugin
176 * @param aAction is the action
177 * @param idButton is the associated menuitem id
178 */
179 static void SetActionButton( ACTION_PLUGIN* aAction, int idButton );
180
181 /**
182 * Function GetActionByButton
183 * find action plugin associated to a button id
184 * @param aButton is the button id (defined with SetActionButton)
185 * @return the associated ACTION_PLUGIN (or null if not found)
186 */
187 static ACTION_PLUGIN* GetActionByButton( int aButton );
188
189 /**
190 * Function GetActionByPath
191 * find action plugin by module path
192 * @param aPath the path of plugin
193 * @return the corresponding ACTION_PLUGIN (or null if not found)
194 */
195 static ACTION_PLUGIN* GetActionByPath( const wxString& aPath );
158196
159 /**197 /**
160 * Function GetAction198 * Function GetAction
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
161new file mode 100644199new file mode 100644
index 0000000..3887fe9
--- /dev/null
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
@@ -0,0 +1,199 @@
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Andrew Lutsenko, anlutsenko at gmail dot com
5 * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <pcb_edit_frame.h>
22#include <panel_pcbnew_action_plugins.h>
23#include <widgets/paged_dialog.h>
24#include <widgets/grid_icon_text_helpers.h>
25#include <bitmaps.h>
26#include <action_plugin.h>
27#include <grid_tricks.h>
28#include <widgets/wx_grid.h>
29
30
31PANEL_PCBNEW_ACTION_PLUGINS::PANEL_PCBNEW_ACTION_PLUGINS( PCB_EDIT_FRAME* aFrame, PAGED_DIALOG* aWindow ) :
32 PANEL_PCBNEW_ACTION_PLUGINS_BASE( aWindow->GetTreebook() ),
33 m_frame( aFrame )
34{
35 m_genericIcon = KiBitmap( hammer_xpm );
36 m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
37
38 m_moveUpButton->SetBitmap( KiBitmap( up_xpm ) );
39 m_moveDownButton->SetBitmap( KiBitmap( down_xpm ) );
40 m_reloadButton->SetBitmap( KiBitmap( refresh_xpm ) );
41}
42
43
44PANEL_PCBNEW_ACTION_PLUGINS::~PANEL_PCBNEW_ACTION_PLUGINS()
45{
46 m_grid->PopEventHandler( true );
47}
48
49
50void PANEL_PCBNEW_ACTION_PLUGINS::OnGridCellClick( wxGridEvent& event )
51{
52 SelectRow( event.GetRow() );
53}
54
55
56void PANEL_PCBNEW_ACTION_PLUGINS::SelectRow( int aRow )
57{
58 m_grid->ClearSelection();
59 m_grid->SelectRow( aRow );
60}
61
62
63void PANEL_PCBNEW_ACTION_PLUGINS::OnMoveUpButtonClick( wxCommandEvent& event )
64{
65 auto selectedRows = m_grid->GetSelectedRows();
66
67 // If nothing is selected or multiple rows are selected don't do anything.
68 if( selectedRows.size() != 1 ) return;
69
70 int selectedRow = selectedRows[0];
71
72 // If first row is selected, then it can't go any further up.
73 if( selectedRow == 0 )
74 {
75 wxBell();
76 return;
77 }
78
79 SwapRows( selectedRow, selectedRow - 1 );
80
81 SelectRow( selectedRow - 1 );
82}
83
84
85void PANEL_PCBNEW_ACTION_PLUGINS::OnMoveDownButtonClick( wxCommandEvent& event )
86{
87 auto selectedRows = m_grid->GetSelectedRows();
88
89 // If nothing is selected or multiple rows are selected don't do anything.
90 if( selectedRows.size() != 1 ) return;
91
92 int selectedRow = selectedRows[0];
93
94 // If last row is selected, then it can't go any further down.
95 if( selectedRow + 1 == m_grid->GetNumberRows() )
96 {
97 wxBell();
98 return;
99 }
100
101 SwapRows( selectedRow, selectedRow + 1 );
102
103 SelectRow( selectedRow + 1 );
104}
105
106
107void PANEL_PCBNEW_ACTION_PLUGINS::SwapRows( int aRowA, int aRowB )
108{
109 m_grid->Freeze();
110
111 // Swap all columns except icon
112 wxString tempStr;
113
114 for( int column = 1; column < m_grid->GetNumberCols(); column++ )
115 {
116 tempStr = m_grid->GetCellValue( aRowA, column );
117 m_grid->SetCellValue( aRowA, column, m_grid->GetCellValue( aRowB, column ) );
118 m_grid->SetCellValue( aRowB, column, tempStr );
119 }
120
121 // Swap icon column renderers
122 auto cellRenderer = m_grid->GetCellRenderer( aRowA, COLUMN_ICON );
123 m_grid->SetCellRenderer( aRowA, COLUMN_ICON, m_grid->GetCellRenderer( aRowB, COLUMN_ICON ) );
124 m_grid->SetCellRenderer( aRowB, COLUMN_ICON, cellRenderer );
125
126 m_grid->Thaw();
127}
128
129
130void PANEL_PCBNEW_ACTION_PLUGINS::OnReloadButtonClick( wxCommandEvent& event )
131{
132 m_frame->PythonPluginsReload();
133 TransferDataToWindow();
134}
135
136
137bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataFromWindow()
138{
139 std::vector< std::pair<wxString, wxString> > pluginSettings;
140
141 for( int ii = 0; ii < m_grid->GetNumberRows(); ii++ )
142 {
143 pluginSettings.push_back( std::make_pair(
144 m_grid->GetCellValue( ii, COLUMN_PATH ),
145 m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT("1") ? wxT( "Visible" ) : wxT( "Hidden" )
146 ) );
147 }
148
149 m_frame->SetActionPluginSettings( pluginSettings );
150
151 return true;
152}
153
154
155bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataToWindow()
156{
157 m_grid->Freeze();
158 m_grid->DeleteRows( 0, m_grid->GetNumberRows() );
159
160 const auto& orderedPlugins = m_frame->GetOrderedActionPlugins();
161 m_grid->AppendRows( orderedPlugins.size() );
162
163 for( size_t row = 0; row < orderedPlugins.size(); row++ )
164 {
165 ACTION_PLUGIN* ap = orderedPlugins[row];
166
167 // Icon
168 m_grid->SetCellRenderer( row, COLUMN_ICON, new GRID_CELL_ICON_RENDERER(
169 ap->iconBitmap.IsOk() ? ap->iconBitmap : m_genericIcon ) );
170
171 // Toolbar button checkbox
172 m_grid->SetCellRenderer( row, COLUMN_VISIBLE, new wxGridCellBoolRenderer() );
173 m_grid->SetCellAlignment( row, COLUMN_VISIBLE, wxALIGN_CENTER, wxALIGN_CENTER );
174
175 bool showButton = m_frame->GetActionPluginButtonVisible(
176 ap->GetPluginPath(), ap->GetShowToolbarButton() );
177
178 m_grid->SetCellValue( row, COLUMN_VISIBLE, showButton ? wxT( "1" ) : wxEmptyString );
179
180 // Name
181 m_grid->SetCellValue( row, COLUMN_NAME, ap->GetName() );
182
183 // Category
184 m_grid->SetCellValue( row, COLUMN_CATEGORY, ap->GetCategoryName() );
185
186 // Description
187 m_grid->SetCellValue( row, COLUMN_DESCRIPTION, ap->GetDescription() );
188
189 // Path
190 m_grid->SetCellValue( row, COLUMN_PATH, ap->GetPluginPath() );
191 }
192
193 m_grid->AutoSizeColumns();
194 m_grid->AutoSizeRows();
195
196 m_grid->Thaw();
197
198 return true;
199}
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.h b/pcbnew/dialogs/panel_pcbnew_action_plugins.h
0new file mode 100644200new file mode 100644
index 0000000..48e8dc0
--- /dev/null
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.h
@@ -0,0 +1,70 @@
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 Andrew Lutsenko, anlutsenko at gmail dot com
5 * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "panel_pcbnew_action_plugins_base.h"
22
23class PANEL_PCBNEW_ACTION_PLUGINS : public PANEL_PCBNEW_ACTION_PLUGINS_BASE
24{
25public:
26 PANEL_PCBNEW_ACTION_PLUGINS ( PCB_EDIT_FRAME* aFrame, PAGED_DIALOG* aWindow );
27
28 bool TransferDataFromWindow() override;
29 bool TransferDataToWindow() override;
30 ~PANEL_PCBNEW_ACTION_PLUGINS() override;
31
32 /**
33 * Selects a whole row
34 */
35 void OnGridCellClick( wxGridEvent& event ) override;
36
37 /**
38 * Moves plugin up in the grid
39 */
40 void OnMoveUpButtonClick( wxCommandEvent& event ) override;
41
42 /**
43 * Moves plugin down in the grid
44 */
45 void OnMoveDownButtonClick( wxCommandEvent& event ) override;
46
47 /**
48 * Reloads plugins and updates grid
49 */
50 void OnReloadButtonClick( wxCommandEvent& event ) override;
51
52private:
53
54 enum GRID_COLUMNS
55 {
56 COLUMN_ICON,
57 COLUMN_VISIBLE,
58 COLUMN_NAME,
59 COLUMN_CATEGORY,
60 COLUMN_DESCRIPTION,
61 COLUMN_PATH
62 };
63
64 PCB_EDIT_FRAME* m_frame;
65 wxBitmap m_genericIcon;
66
67 void SwapRows( int aRowA, int aRowB );
68 void SelectRow( int aRow );
69};
70
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp
0new file mode 10064471new file mode 100644
index 0000000..d8f8909
--- /dev/null
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp
@@ -0,0 +1,98 @@
1///////////////////////////////////////////////////////////////////////////
2// C++ code generated with wxFormBuilder (version Jul 11 2018)
3// http://www.wxformbuilder.org/
4//
5// PLEASE DO *NOT* EDIT THIS FILE!
6///////////////////////////////////////////////////////////////////////////
7
8#include "widgets/wx_grid.h"
9
10#include "panel_pcbnew_action_plugins_base.h"
11
12///////////////////////////////////////////////////////////////////////////
13
14PANEL_PCBNEW_ACTION_PLUGINS_BASE::PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
15{
16 wxBoxSizer* bPanelSizer;
17 bPanelSizer = new wxBoxSizer( wxHORIZONTAL );
18
19 wxBoxSizer* bGridSizer;
20 bGridSizer = new wxBoxSizer( wxVERTICAL );
21
22 m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE );
23
24 // Grid
25 m_grid->CreateGrid( 3, 6 );
26 m_grid->EnableEditing( false );
27 m_grid->EnableGridLines( true );
28 m_grid->EnableDragGridSize( false );
29 m_grid->SetMargins( 0, 0 );
30
31 // Columns
32 m_grid->AutoSizeColumns();
33 m_grid->EnableDragColMove( false );
34 m_grid->EnableDragColSize( true );
35 m_grid->SetColLabelSize( 22 );
36 m_grid->SetColLabelValue( 0, wxT("Icon") );
37 m_grid->SetColLabelValue( 1, wxT("Show button") );
38 m_grid->SetColLabelValue( 2, wxT("Name") );
39 m_grid->SetColLabelValue( 3, wxT("Category") );
40 m_grid->SetColLabelValue( 4, wxT("Description") );
41 m_grid->SetColLabelValue( 5, wxT("Path") );
42 m_grid->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
43
44 // Rows
45 m_grid->EnableDragRowSize( true );
46 m_grid->SetRowLabelSize( 0 );
47 m_grid->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE );
48
49 // Label Appearance
50
51 // Cell Defaults
52 m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE );
53 bGridSizer->Add( m_grid, 1, wxALL|wxEXPAND, 5 );
54
55
56 bPanelSizer->Add( bGridSizer, 1, wxALIGN_LEFT|wxEXPAND|wxLEFT, 0 );
57
58 wxBoxSizer* bButtonsSizer;
59 bButtonsSizer = new wxBoxSizer( wxVERTICAL );
60
61 m_moveUpButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
62 m_moveUpButton->SetMinSize( wxSize( 32,32 ) );
63
64 bButtonsSizer->Add( m_moveUpButton, 0, wxALIGN_TOP|wxALL, 5 );
65
66 m_moveDownButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
67 m_moveDownButton->SetMinSize( wxSize( 32,32 ) );
68
69 bButtonsSizer->Add( m_moveDownButton, 0, wxALL, 5 );
70
71 m_reloadButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
72 m_reloadButton->SetMinSize( wxSize( 32,32 ) );
73
74 bButtonsSizer->Add( m_reloadButton, 0, wxALL, 5 );
75
76
77 bPanelSizer->Add( bButtonsSizer, 0, wxALIGN_RIGHT|wxALIGN_TOP, 0 );
78
79
80 this->SetSizer( bPanelSizer );
81 this->Layout();
82
83 // Connect Events
84 m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnGridCellClick ), NULL, this );
85 m_moveUpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveUpButtonClick ), NULL, this );
86 m_moveDownButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveDownButtonClick ), NULL, this );
87 m_reloadButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnReloadButtonClick ), NULL, this );
88}
89
90PANEL_PCBNEW_ACTION_PLUGINS_BASE::~PANEL_PCBNEW_ACTION_PLUGINS_BASE()
91{
92 // Disconnect Events
93 m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnGridCellClick ), NULL, this );
94 m_moveUpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveUpButtonClick ), NULL, this );
95 m_moveDownButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveDownButtonClick ), NULL, this );
96 m_reloadButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnReloadButtonClick ), NULL, this );
97
98}
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp
0new file mode 10064499new file mode 100644
index 0000000..6c91f1f
--- /dev/null
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp
@@ -0,0 +1,578 @@
1<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2<wxFormBuilder_Project>
3 <FileVersion major="1" minor="14" />
4 <object class="Project" expanded="1">
5 <property name="class_decoration"></property>
6 <property name="code_generation">C++</property>
7 <property name="disconnect_events">1</property>
8 <property name="disconnect_mode">source_name</property>
9 <property name="disconnect_php_events">0</property>
10 <property name="disconnect_python_events">0</property>
11 <property name="embedded_files_path">res</property>
12 <property name="encoding">UTF-8</property>
13 <property name="event_generation">connect</property>
14 <property name="file">panel_pcbnew_action_plugins_base</property>
15 <property name="first_id">1000</property>
16 <property name="help_provider">none</property>
17 <property name="indent_with_spaces">0</property>
18 <property name="internationalize">0</property>
19 <property name="name">PanelPcbnewActionPlugins</property>
20 <property name="namespace"></property>
21 <property name="path">.</property>
22 <property name="precompiled_header"></property>
23 <property name="relative_path">1</property>
24 <property name="skip_lua_events">1</property>
25 <property name="skip_php_events">1</property>
26 <property name="skip_python_events">1</property>
27 <property name="ui_table">UI</property>
28 <property name="use_enum">1</property>
29 <property name="use_microsoft_bom">0</property>
30 <object class="Panel" expanded="1">
31 <property name="aui_managed">0</property>
32 <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
33 <property name="bg"></property>
34 <property name="context_help"></property>
35 <property name="context_menu">1</property>
36 <property name="enabled">1</property>
37 <property name="event_handler">impl_virtual</property>
38 <property name="fg"></property>
39 <property name="font"></property>
40 <property name="hidden">0</property>
41 <property name="id">wxID_ANY</property>
42 <property name="maximum_size"></property>
43 <property name="minimum_size"></property>
44 <property name="name">PANEL_PCBNEW_ACTION_PLUGINS_BASE</property>
45 <property name="pos"></property>
46 <property name="size">485,200</property>
47 <property name="subclass">; forward_declare</property>
48 <property name="tooltip"></property>
49 <property name="window_extra_style"></property>
50 <property name="window_name"></property>
51 <property name="window_style">wxTAB_TRAVERSAL</property>
52 <event name="OnAuiPaneActivated"></event>
53 <event name="OnAuiPaneButton"></event>
54 <event name="OnAuiPaneClose"></event>
55 <event name="OnAuiPaneMaximize"></event>
56 <event name="OnAuiPaneRestore"></event>
57 <event name="OnAuiRender"></event>
58 <event name="OnAux1DClick"></event>
59 <event name="OnAux1Down"></event>
60 <event name="OnAux1Up"></event>
61 <event name="OnAux2DClick"></event>
62 <event name="OnAux2Down"></event>
63 <event name="OnAux2Up"></event>
64 <event name="OnChar"></event>
65 <event name="OnCharHook"></event>
66 <event name="OnEnterWindow"></event>
67 <event name="OnEraseBackground"></event>
68 <event name="OnInitDialog"></event>
69 <event name="OnKeyDown"></event>
70 <event name="OnKeyUp"></event>
71 <event name="OnKillFocus"></event>
72 <event name="OnLeaveWindow"></event>
73 <event name="OnLeftDClick"></event>
74 <event name="OnLeftDown"></event>
75 <event name="OnLeftUp"></event>
76 <event name="OnMiddleDClick"></event>
77 <event name="OnMiddleDown"></event>
78 <event name="OnMiddleUp"></event>
79 <event name="OnMotion"></event>
80 <event name="OnMouseEvents"></event>
81 <event name="OnMouseWheel"></event>
82 <event name="OnPaint"></event>
83 <event name="OnRightDClick"></event>
84 <event name="OnRightDown"></event>
85 <event name="OnRightUp"></event>
86 <event name="OnSetFocus"></event>
87 <event name="OnSize"></event>
88 <event name="OnUpdateUI"></event>
89 <object class="wxBoxSizer" expanded="1">
90 <property name="minimum_size"></property>
91 <property name="name">bPanelSizer</property>
92 <property name="orient">wxHORIZONTAL</property>
93 <property name="permission">none</property>
94 <object class="sizeritem" expanded="1">
95 <property name="border">0</property>
96 <property name="flag">wxALIGN_LEFT|wxEXPAND|wxLEFT</property>
97 <property name="proportion">1</property>
98 <object class="wxBoxSizer" expanded="1">
99 <property name="minimum_size"></property>
100 <property name="name">bGridSizer</property>
101 <property name="orient">wxVERTICAL</property>
102 <property name="permission">none</property>
103 <object class="sizeritem" expanded="1">
104 <property name="border">5</property>
105 <property name="flag">wxALL|wxEXPAND</property>
106 <property name="proportion">1</property>
107 <object class="wxGrid" expanded="1">
108 <property name="BottomDockable">1</property>
109 <property name="LeftDockable">1</property>
110 <property name="RightDockable">1</property>
111 <property name="TopDockable">1</property>
112 <property name="aui_layer"></property>
113 <property name="aui_name"></property>
114 <property name="aui_position"></property>
115 <property name="aui_row"></property>
116 <property name="autosize_cols">1</property>
117 <property name="autosize_rows">0</property>
118 <property name="best_size"></property>
119 <property name="bg"></property>
120 <property name="caption"></property>
121 <property name="caption_visible">1</property>
122 <property name="cell_bg"></property>
123 <property name="cell_font"></property>
124 <property name="cell_horiz_alignment">wxALIGN_LEFT</property>
125 <property name="cell_text"></property>
126 <property name="cell_vert_alignment">wxALIGN_CENTRE</property>
127 <property name="center_pane">0</property>
128 <property name="close_button">1</property>
129 <property name="col_label_horiz_alignment">wxALIGN_CENTRE</property>
130 <property name="col_label_size">22</property>
131 <property name="col_label_values">&quot;Icon&quot; &quot;Show button&quot; &quot;Name&quot; &quot;Category&quot; &quot;Description&quot; &quot;Path&quot;</property>
132 <property name="col_label_vert_alignment">wxALIGN_CENTRE</property>
133 <property name="cols">6</property>
134 <property name="column_sizes"></property>
135 <property name="context_help"></property>
136 <property name="context_menu">1</property>
137 <property name="default_pane">0</property>
138 <property name="dock">Dock</property>
139 <property name="dock_fixed">0</property>
140 <property name="docking">Left</property>
141 <property name="drag_col_move">0</property>
142 <property name="drag_col_size">1</property>
143 <property name="drag_grid_size">0</property>
144 <property name="drag_row_size">1</property>
145 <property name="editing">0</property>
146 <property name="enabled">1</property>
147 <property name="fg"></property>
148 <property name="floatable">1</property>
149 <property name="font"></property>
150 <property name="grid_line_color"></property>
151 <property name="grid_lines">1</property>
152 <property name="gripper">0</property>
153 <property name="hidden">0</property>
154 <property name="id">wxID_ANY</property>
155 <property name="label_bg"></property>
156 <property name="label_font"></property>
157 <property name="label_text"></property>
158 <property name="margin_height">0</property>
159 <property name="margin_width">0</property>
160 <property name="max_size"></property>
161 <property name="maximize_button">0</property>
162 <property name="maximum_size"></property>
163 <property name="min_size"></property>
164 <property name="minimize_button">0</property>
165 <property name="minimum_size"></property>
166 <property name="moveable">1</property>
167 <property name="name">m_grid</property>
168 <property name="pane_border">1</property>
169 <property name="pane_position"></property>
170 <property name="pane_size"></property>
171 <property name="permission">protected</property>
172 <property name="pin_button">1</property>
173 <property name="pos"></property>
174 <property name="resize">Resizable</property>
175 <property name="row_label_horiz_alignment">wxALIGN_CENTRE</property>
176 <property name="row_label_size">0</property>
177 <property name="row_label_values"></property>
178 <property name="row_label_vert_alignment">wxALIGN_CENTRE</property>
179 <property name="row_sizes"></property>
180 <property name="rows">3</property>
181 <property name="show">1</property>
182 <property name="size"></property>
183 <property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property>
184 <property name="toolbar_pane">0</property>
185 <property name="tooltip"></property>
186 <property name="window_extra_style"></property>
187 <property name="window_name"></property>
188 <property name="window_style">wxBORDER_SIMPLE</property>
189 <event name="OnAux1DClick"></event>
190 <event name="OnAux1Down"></event>
191 <event name="OnAux1Up"></event>
192 <event name="OnAux2DClick"></event>
193 <event name="OnAux2Down"></event>
194 <event name="OnAux2Up"></event>
195 <event name="OnChar"></event>
196 <event name="OnCharHook"></event>
197 <event name="OnEnterWindow"></event>
198 <event name="OnEraseBackground"></event>
199 <event name="OnGridCellChange"></event>
200 <event name="OnGridCellLeftClick">OnGridCellClick</event>
201 <event name="OnGridCellLeftDClick"></event>
202 <event name="OnGridCellRightClick"></event>
203 <event name="OnGridCellRightDClick"></event>
204 <event name="OnGridCmdCellChange"></event>
205 <event name="OnGridCmdCellLeftClick"></event>
206 <event name="OnGridCmdCellLeftDClick"></event>
207 <event name="OnGridCmdCellRightClick"></event>
208 <event name="OnGridCmdCellRightDClick"></event>
209 <event name="OnGridCmdColSize"></event>
210 <event name="OnGridCmdEditorCreated"></event>
211 <event name="OnGridCmdEditorHidden"></event>
212 <event name="OnGridCmdEditorShown"></event>
213 <event name="OnGridCmdLabelLeftClick"></event>
214 <event name="OnGridCmdLabelLeftDClick"></event>
215 <event name="OnGridCmdLabelRightClick"></event>
216 <event name="OnGridCmdLabelRightDClick"></event>
217 <event name="OnGridCmdRangeSelect"></event>
218 <event name="OnGridCmdRowSize"></event>
219 <event name="OnGridCmdSelectCell"></event>
220 <event name="OnGridColSize"></event>
221 <event name="OnGridEditorCreated"></event>
222 <event name="OnGridEditorHidden"></event>
223 <event name="OnGridEditorShown"></event>
224 <event name="OnGridLabelLeftClick"></event>
225 <event name="OnGridLabelLeftDClick"></event>
226 <event name="OnGridLabelRightClick"></event>
227 <event name="OnGridLabelRightDClick"></event>
228 <event name="OnGridRangeSelect"></event>
229 <event name="OnGridRowSize"></event>
230 <event name="OnGridSelectCell"></event>
231 <event name="OnKeyDown"></event>
232 <event name="OnKeyUp"></event>
233 <event name="OnKillFocus"></event>
234 <event name="OnLeaveWindow"></event>
235 <event name="OnLeftDClick"></event>
236 <event name="OnLeftDown"></event>
237 <event name="OnLeftUp"></event>
238 <event name="OnMiddleDClick"></event>
239 <event name="OnMiddleDown"></event>
240 <event name="OnMiddleUp"></event>
241 <event name="OnMotion"></event>
242 <event name="OnMouseEvents"></event>
243 <event name="OnMouseWheel"></event>
244 <event name="OnPaint"></event>
245 <event name="OnRightDClick"></event>
246 <event name="OnRightDown"></event>
247 <event name="OnRightUp"></event>
248 <event name="OnSetFocus"></event>
249 <event name="OnSize"></event>
250 <event name="OnUpdateUI"></event>
251 </object>
252 </object>
253 </object>
254 </object>
255 <object class="sizeritem" expanded="1">
256 <property name="border">0</property>
257 <property name="flag">wxALIGN_RIGHT|wxALIGN_TOP</property>
258 <property name="proportion">0</property>
259 <object class="wxBoxSizer" expanded="1">
260 <property name="minimum_size"></property>
261 <property name="name">bButtonsSizer</property>
262 <property name="orient">wxVERTICAL</property>
263 <property name="permission">none</property>
264 <object class="sizeritem" expanded="0">
265 <property name="border">5</property>
266 <property name="flag">wxALIGN_TOP|wxALL</property>
267 <property name="proportion">0</property>
268 <object class="wxBitmapButton" expanded="0">
269 <property name="BottomDockable">1</property>
270 <property name="LeftDockable">1</property>
271 <property name="RightDockable">1</property>
272 <property name="TopDockable">1</property>
273 <property name="aui_layer"></property>
274 <property name="aui_name"></property>
275 <property name="aui_position"></property>
276 <property name="aui_row"></property>
277 <property name="best_size"></property>
278 <property name="bg"></property>
279 <property name="bitmap"></property>
280 <property name="caption"></property>
281 <property name="caption_visible">1</property>
282 <property name="center_pane">0</property>
283 <property name="close_button">1</property>
284 <property name="context_help"></property>
285 <property name="context_menu">1</property>
286 <property name="current"></property>
287 <property name="default">0</property>
288 <property name="default_pane">0</property>
289 <property name="disabled"></property>
290 <property name="dock">Dock</property>
291 <property name="dock_fixed">0</property>
292 <property name="docking">Left</property>
293 <property name="enabled">1</property>
294 <property name="fg"></property>
295 <property name="floatable">1</property>
296 <property name="focus"></property>
297 <property name="font"></property>
298 <property name="gripper">0</property>
299 <property name="hidden">0</property>
300 <property name="id">wxID_ANY</property>
301 <property name="label">Move Up</property>
302 <property name="margins"></property>
303 <property name="markup">0</property>
304 <property name="max_size"></property>
305 <property name="maximize_button">0</property>
306 <property name="maximum_size"></property>
307 <property name="min_size"></property>
308 <property name="minimize_button">0</property>
309 <property name="minimum_size">32,32</property>
310 <property name="moveable">1</property>
311 <property name="name">m_moveUpButton</property>
312 <property name="pane_border">1</property>
313 <property name="pane_position"></property>
314 <property name="pane_size"></property>
315 <property name="permission">protected</property>
316 <property name="pin_button">1</property>
317 <property name="pos"></property>
318 <property name="position"></property>
319 <property name="pressed"></property>
320 <property name="resize">Resizable</property>
321 <property name="show">1</property>
322 <property name="size"></property>
323 <property name="style"></property>
324 <property name="subclass">; forward_declare</property>
325 <property name="toolbar_pane">0</property>
326 <property name="tooltip"></property>
327 <property name="validator_data_type"></property>
328 <property name="validator_style">wxFILTER_NONE</property>
329 <property name="validator_type">wxDefaultValidator</property>
330 <property name="validator_variable"></property>
331 <property name="window_extra_style"></property>
332 <property name="window_name"></property>
333 <property name="window_style"></property>
334 <event name="OnAux1DClick"></event>
335 <event name="OnAux1Down"></event>
336 <event name="OnAux1Up"></event>
337 <event name="OnAux2DClick"></event>
338 <event name="OnAux2Down"></event>
339 <event name="OnAux2Up"></event>
340 <event name="OnButtonClick">OnMoveUpButtonClick</event>
341 <event name="OnChar"></event>
342 <event name="OnCharHook"></event>
343 <event name="OnEnterWindow"></event>
344 <event name="OnEraseBackground"></event>
345 <event name="OnKeyDown"></event>
346 <event name="OnKeyUp"></event>
347 <event name="OnKillFocus"></event>
348 <event name="OnLeaveWindow"></event>
349 <event name="OnLeftDClick"></event>
350 <event name="OnLeftDown"></event>
351 <event name="OnLeftUp"></event>
352 <event name="OnMiddleDClick"></event>
353 <event name="OnMiddleDown"></event>
354 <event name="OnMiddleUp"></event>
355 <event name="OnMotion"></event>
356 <event name="OnMouseEvents"></event>
357 <event name="OnMouseWheel"></event>
358 <event name="OnPaint"></event>
359 <event name="OnRightDClick"></event>
360 <event name="OnRightDown"></event>
361 <event name="OnRightUp"></event>
362 <event name="OnSetFocus"></event>
363 <event name="OnSize"></event>
364 <event name="OnUpdateUI"></event>
365 </object>
366 </object>
367 <object class="sizeritem" expanded="1">
368 <property name="border">5</property>
369 <property name="flag">wxALL</property>
370 <property name="proportion">0</property>
371 <object class="wxBitmapButton" expanded="1">
372 <property name="BottomDockable">1</property>
373 <property name="LeftDockable">1</property>
374 <property name="RightDockable">1</property>
375 <property name="TopDockable">1</property>
376 <property name="aui_layer"></property>
377 <property name="aui_name"></property>
378 <property name="aui_position"></property>
379 <property name="aui_row"></property>
380 <property name="best_size"></property>
381 <property name="bg"></property>
382 <property name="bitmap"></property>
383 <property name="caption"></property>
384 <property name="caption_visible">1</property>
385 <property name="center_pane">0</property>
386 <property name="close_button">1</property>
387 <property name="context_help"></property>
388 <property name="context_menu">1</property>
389 <property name="current"></property>
390 <property name="default">0</property>
391 <property name="default_pane">0</property>
392 <property name="disabled"></property>
393 <property name="dock">Dock</property>
394 <property name="dock_fixed">0</property>
395 <property name="docking">Left</property>
396 <property name="enabled">1</property>
397 <property name="fg"></property>
398 <property name="floatable">1</property>
399 <property name="focus"></property>
400 <property name="font"></property>
401 <property name="gripper">0</property>
402 <property name="hidden">0</property>
403 <property name="id">wxID_ANY</property>
404 <property name="label">Move Down</property>
405 <property name="margins"></property>
406 <property name="markup">0</property>
407 <property name="max_size"></property>
408 <property name="maximize_button">0</property>
409 <property name="maximum_size"></property>
410 <property name="min_size"></property>
411 <property name="minimize_button">0</property>
412 <property name="minimum_size">32,32</property>
413 <property name="moveable">1</property>
414 <property name="name">m_moveDownButton</property>
415 <property name="pane_border">1</property>
416 <property name="pane_position"></property>
417 <property name="pane_size"></property>
418 <property name="permission">protected</property>
419 <property name="pin_button">1</property>
420 <property name="pos"></property>
421 <property name="position"></property>
422 <property name="pressed"></property>
423 <property name="resize">Resizable</property>
424 <property name="show">1</property>
425 <property name="size"></property>
426 <property name="style"></property>
427 <property name="subclass">; forward_declare</property>
428 <property name="toolbar_pane">0</property>
429 <property name="tooltip"></property>
430 <property name="validator_data_type"></property>
431 <property name="validator_style">wxFILTER_NONE</property>
432 <property name="validator_type">wxDefaultValidator</property>
433 <property name="validator_variable"></property>
434 <property name="window_extra_style"></property>
435 <property name="window_name"></property>
436 <property name="window_style"></property>
437 <event name="OnAux1DClick"></event>
438 <event name="OnAux1Down"></event>
439 <event name="OnAux1Up"></event>
440 <event name="OnAux2DClick"></event>
441 <event name="OnAux2Down"></event>
442 <event name="OnAux2Up"></event>
443 <event name="OnButtonClick">OnMoveDownButtonClick</event>
444 <event name="OnChar"></event>
445 <event name="OnCharHook"></event>
446 <event name="OnEnterWindow"></event>
447 <event name="OnEraseBackground"></event>
448 <event name="OnKeyDown"></event>
449 <event name="OnKeyUp"></event>
450 <event name="OnKillFocus"></event>
451 <event name="OnLeaveWindow"></event>
452 <event name="OnLeftDClick"></event>
453 <event name="OnLeftDown"></event>
454 <event name="OnLeftUp"></event>
455 <event name="OnMiddleDClick"></event>
456 <event name="OnMiddleDown"></event>
457 <event name="OnMiddleUp"></event>
458 <event name="OnMotion"></event>
459 <event name="OnMouseEvents"></event>
460 <event name="OnMouseWheel"></event>
461 <event name="OnPaint"></event>
462 <event name="OnRightDClick"></event>
463 <event name="OnRightDown"></event>
464 <event name="OnRightUp"></event>
465 <event name="OnSetFocus"></event>
466 <event name="OnSize"></event>
467 <event name="OnUpdateUI"></event>
468 </object>
469 </object>
470 <object class="sizeritem" expanded="1">
471 <property name="border">5</property>
472 <property name="flag">wxALL</property>
473 <property name="proportion">0</property>
474 <object class="wxBitmapButton" expanded="1">
475 <property name="BottomDockable">1</property>
476 <property name="LeftDockable">1</property>
477 <property name="RightDockable">1</property>
478 <property name="TopDockable">1</property>
479 <property name="aui_layer"></property>
480 <property name="aui_name"></property>
481 <property name="aui_position"></property>
482 <property name="aui_row"></property>
483 <property name="best_size"></property>
484 <property name="bg"></property>
485 <property name="bitmap"></property>
486 <property name="caption"></property>
487 <property name="caption_visible">1</property>
488 <property name="center_pane">0</property>
489 <property name="close_button">1</property>
490 <property name="context_help"></property>
491 <property name="context_menu">1</property>
492 <property name="current"></property>
493 <property name="default">0</property>
494 <property name="default_pane">0</property>
495 <property name="disabled"></property>
496 <property name="dock">Dock</property>
497 <property name="dock_fixed">0</property>
498 <property name="docking">Left</property>
499 <property name="enabled">1</property>
500 <property name="fg"></property>
501 <property name="floatable">1</property>
502 <property name="focus"></property>
503 <property name="font"></property>
504 <property name="gripper">0</property>
505 <property name="hidden">0</property>
506 <property name="id">wxID_ANY</property>
507 <property name="label">Reload Plugins</property>
508 <property name="margins"></property>
509 <property name="markup">0</property>
510 <property name="max_size"></property>
511 <property name="maximize_button">0</property>
512 <property name="maximum_size"></property>
513 <property name="min_size"></property>
514 <property name="minimize_button">0</property>
515 <property name="minimum_size">32,32</property>
516 <property name="moveable">1</property>
517 <property name="name">m_reloadButton</property>
518 <property name="pane_border">1</property>
519 <property name="pane_position"></property>
520 <property name="pane_size"></property>
521 <property name="permission">protected</property>
522 <property name="pin_button">1</property>
523 <property name="pos"></property>
524 <property name="position"></property>
525 <property name="pressed"></property>
526 <property name="resize">Resizable</property>
527 <property name="show">1</property>
528 <property name="size"></property>
529 <property name="style"></property>
530 <property name="subclass">; forward_declare</property>
531 <property name="toolbar_pane">0</property>
532 <property name="tooltip"></property>
533 <property name="validator_data_type"></property>
534 <property name="validator_style">wxFILTER_NONE</property>
535 <property name="validator_type">wxDefaultValidator</property>
536 <property name="validator_variable"></property>
537 <property name="window_extra_style"></property>
538 <property name="window_name"></property>
539 <property name="window_style"></property>
540 <event name="OnAux1DClick"></event>
541 <event name="OnAux1Down"></event>
542 <event name="OnAux1Up"></event>
543 <event name="OnAux2DClick"></event>
544 <event name="OnAux2Down"></event>
545 <event name="OnAux2Up"></event>
546 <event name="OnButtonClick">OnReloadButtonClick</event>
547 <event name="OnChar"></event>
548 <event name="OnCharHook"></event>
549 <event name="OnEnterWindow"></event>
550 <event name="OnEraseBackground"></event>
551 <event name="OnKeyDown"></event>
552 <event name="OnKeyUp"></event>
553 <event name="OnKillFocus"></event>
554 <event name="OnLeaveWindow"></event>
555 <event name="OnLeftDClick"></event>
556 <event name="OnLeftDown"></event>
557 <event name="OnLeftUp"></event>
558 <event name="OnMiddleDClick"></event>
559 <event name="OnMiddleDown"></event>
560 <event name="OnMiddleUp"></event>
561 <event name="OnMotion"></event>
562 <event name="OnMouseEvents"></event>
563 <event name="OnMouseWheel"></event>
564 <event name="OnPaint"></event>
565 <event name="OnRightDClick"></event>
566 <event name="OnRightDown"></event>
567 <event name="OnRightUp"></event>
568 <event name="OnSetFocus"></event>
569 <event name="OnSize"></event>
570 <event name="OnUpdateUI"></event>
571 </object>
572 </object>
573 </object>
574 </object>
575 </object>
576 </object>
577 </object>
578</wxFormBuilder_Project>
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h
0new file mode 100644579new file mode 100644
index 0000000..8766d0c
--- /dev/null
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h
@@ -0,0 +1,58 @@
1///////////////////////////////////////////////////////////////////////////
2// C++ code generated with wxFormBuilder (version Jul 11 2018)
3// http://www.wxformbuilder.org/
4//
5// PLEASE DO *NOT* EDIT THIS FILE!
6///////////////////////////////////////////////////////////////////////////
7
8#ifndef __PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__
9#define __PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__
10
11#include <wx/artprov.h>
12#include <wx/xrc/xmlres.h>
13class WX_GRID;
14
15#include <wx/colour.h>
16#include <wx/settings.h>
17#include <wx/string.h>
18#include <wx/font.h>
19#include <wx/grid.h>
20#include <wx/gdicmn.h>
21#include <wx/sizer.h>
22#include <wx/bmpbuttn.h>
23#include <wx/bitmap.h>
24#include <wx/image.h>
25#include <wx/icon.h>
26#include <wx/button.h>
27#include <wx/panel.h>
28
29///////////////////////////////////////////////////////////////////////////
30
31///////////////////////////////////////////////////////////////////////////////
32/// Class PANEL_PCBNEW_ACTION_PLUGINS_BASE
33///////////////////////////////////////////////////////////////////////////////
34class PANEL_PCBNEW_ACTION_PLUGINS_BASE : public wxPanel
35{
36 private:
37
38 protected:
39 WX_GRID* m_grid;
40 wxBitmapButton* m_moveUpButton;
41 wxBitmapButton* m_moveDownButton;
42 wxBitmapButton* m_reloadButton;
43
44 // Virtual event handlers, overide them in your derived class
45 virtual void OnGridCellClick( wxGridEvent& event ) { event.Skip(); }
46 virtual void OnMoveUpButtonClick( wxCommandEvent& event ) { event.Skip(); }
47 virtual void OnMoveDownButtonClick( wxCommandEvent& event ) { event.Skip(); }
48 virtual void OnReloadButtonClick( wxCommandEvent& event ) { event.Skip(); }
49
50
51 public:
52
53 PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 485,200 ), long style = wxTAB_TRAVERSAL );
54 ~PANEL_PCBNEW_ACTION_PLUGINS_BASE();
55
56};
57
58#endif //__PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index e8bbb88..5c4a8d5 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -1243,6 +1243,8 @@ void PCB_EDIT_FRAME::PythonPluginsReload()
1243 // Action plugins can be modified, therefore the plugins menu1243 // Action plugins can be modified, therefore the plugins menu
1244 // must be updated:1244 // must be updated:
1245 RebuildActionPluginMenus();1245 RebuildActionPluginMenus();
1246 // Recreate top toolbar to add action plugin buttons
1247 ReCreateHToolbar();
1246 #endif1248 #endif
1247#endif1249#endif
1248}1250}
diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h
index 4179353..4788841 100644
--- a/pcbnew/pcb_edit_frame.h
+++ b/pcbnew/pcb_edit_frame.h
@@ -25,13 +25,14 @@
25#define WXPCB_STRUCT_H_25#define WXPCB_STRUCT_H_
2626
27#include <unordered_map>27#include <unordered_map>
28#include <map>
28#include "pcb_base_edit_frame.h"29#include "pcb_base_edit_frame.h"
29#include "config_params.h"30#include "config_params.h"
30#include "undo_redo_container.h"31#include "undo_redo_container.h"
31#include "zones.h"32#include "zones.h"
3233
33
34/* Forward declarations of classes. */34/* Forward declarations of classes. */
35class ACTION_PLUGIN;
35class PCB_SCREEN;36class PCB_SCREEN;
36class BOARD;37class BOARD;
37class BOARD_COMMIT;38class BOARD_COMMIT;
@@ -117,16 +118,36 @@ protected:
117#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)118#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
118 /**119 /**
119 * Function RebuildActionPluginMenus120 * Function RebuildActionPluginMenus
120 * Fill action menu with all registred action plugins121 * Fill action menu with all registered action plugins
121 */122 */
122 void RebuildActionPluginMenus();123 void RebuildActionPluginMenus();
123124
124 /**125 /**
125 * Function OnActionPlugin126 * Function AddActionPluginTools
127 * Append action plugin buttons to main toolbar
128 */
129 void AddActionPluginTools();
130
131 /**
132 * Function RunActionPlugin
133 * Executes action plugin's Run() method and updates undo buffer
134 * @param aActionPlugin action plugin
135 */
136 void RunActionPlugin( ACTION_PLUGIN* aActionPlugin );
137
138 /**
139 * Function OnActionPluginMenu
126 * Launched by the menu when an action is called140 * Launched by the menu when an action is called
127 * @param aEvent sent by wx141 * @param aEvent sent by wx
128 */142 */
129 void OnActionPlugin( wxCommandEvent& aEvent);143 void OnActionPluginMenu( wxCommandEvent& aEvent);
144
145 /**
146 * Function OnActionPluginButton
147 * Launched by the button when an action is called
148 * @param aEvent sent by wx
149 */
150 void OnActionPluginButton( wxCommandEvent& aEvent );
130151
131 /**152 /**
132 * Function OnActionPluginRefresh153 * Function OnActionPluginRefresh
@@ -379,6 +400,36 @@ public:
379 // Configurations:400 // Configurations:
380 void Process_Config( wxCommandEvent& event );401 void Process_Config( wxCommandEvent& event );
381402
403#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
404
405 /**
406 * Function SetActionPluginSettings
407 * Set a set of plugins that have visible buttons on toolbar
408 * Plugins are identified by their module path
409 */
410 void SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginsWithButtons );
411
412 /**
413 * Function GetActionPluginSettings
414 * Get a set of plugins that have visible buttons on toolbar
415 */
416 std::vector< std::pair<wxString, wxString> > GetActionPluginSettings();
417
418 /**
419 * Function GetActionPluginButtonVisible
420 * Returns true if button visibility action plugin setting was set to true
421 * or it is unset and plugin defaults to true.
422 */
423 bool GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault );
424
425 /**
426 * Function GetOrderedActionPlugins
427 * Returns ordered list of plugins in sequence in which they should appear on toolbar or in settings
428 */
429 std::vector<ACTION_PLUGIN*> GetOrderedActionPlugins();
430
431#endif
432
382 /**433 /**
383 * Function GetProjectFileParameters434 * Function GetProjectFileParameters
384 * returns a project file parameter list for Pcbnew.435 * returns a project file parameter list for Pcbnew.
diff --git a/pcbnew/pcb_general_settings.cpp b/pcbnew/pcb_general_settings.cpp
index a8c70cd..96c525a 100644
--- a/pcbnew/pcb_general_settings.cpp
+++ b/pcbnew/pcb_general_settings.cpp
@@ -22,6 +22,7 @@
22 */22 */
2323
24#include <pcb_general_settings.h>24#include <pcb_general_settings.h>
25#include <wx/tokenzr.h>
2526
26PCB_GENERAL_SETTINGS::PCB_GENERAL_SETTINGS( FRAME_T aFrameType )27PCB_GENERAL_SETTINGS::PCB_GENERAL_SETTINGS( FRAME_T aFrameType )
27 : m_frameType( aFrameType ), m_colorsSettings( aFrameType )28 : m_frameType( aFrameType ), m_colorsSettings( aFrameType )
@@ -54,6 +55,32 @@ PCB_GENERAL_SETTINGS::PCB_GENERAL_SETTINGS( FRAME_T aFrameType )
54void PCB_GENERAL_SETTINGS::Load( wxConfigBase* aCfg )55void PCB_GENERAL_SETTINGS::Load( wxConfigBase* aCfg )
55{56{
56 m_colorsSettings.Load( aCfg );57 m_colorsSettings.Load( aCfg );
58
59#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
60
61 m_pluginSettings.clear();
62
63 wxString pluginSettings = aCfg->Read( "ActionPluginButtons" );
64
65 wxStringTokenizer pluginSettingsTokenizer = wxStringTokenizer( pluginSettings, ";" );
66
67 while( pluginSettingsTokenizer.HasMoreTokens() )
68 {
69 wxString plugin = pluginSettingsTokenizer.GetNextToken();
70 wxStringTokenizer pluginTokenizer = wxStringTokenizer( plugin, "=" );
71
72 if( pluginTokenizer.CountTokens() != 2 )
73 {
74 // Bad config
75 continue;
76 }
77
78 plugin = pluginTokenizer.GetNextToken();
79 m_pluginSettings.push_back( std::make_pair( plugin, pluginTokenizer.GetNextToken() ) );
80 }
81
82#endif
83
57 SETTINGS::Load( aCfg );84 SETTINGS::Load( aCfg );
58}85}
5986
@@ -61,6 +88,24 @@ void PCB_GENERAL_SETTINGS::Load( wxConfigBase* aCfg )
61void PCB_GENERAL_SETTINGS::Save( wxConfigBase* aCfg )88void PCB_GENERAL_SETTINGS::Save( wxConfigBase* aCfg )
62{89{
63 m_colorsSettings.Save( aCfg );90 m_colorsSettings.Save( aCfg );
91
92#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
93
94 wxString pluginSettings;
95
96 for( auto const& entry : m_pluginSettings )
97 {
98 if( !pluginSettings.IsEmpty() )
99 {
100 pluginSettings = pluginSettings + wxT( ";" );
101 }
102 pluginSettings = pluginSettings + entry.first + wxT( "=" ) + entry.second;
103 }
104
105 aCfg->Write( "ActionPluginButtons" , pluginSettings );
106
107#endif
108
64 SETTINGS::Save( aCfg );109 SETTINGS::Save( aCfg );
65}110}
66111
diff --git a/pcbnew/pcb_general_settings.h b/pcbnew/pcb_general_settings.h
index bc8f953..fbcbe90 100644
--- a/pcbnew/pcb_general_settings.h
+++ b/pcbnew/pcb_general_settings.h
@@ -25,6 +25,7 @@
25#define __PCBNEW_GENERAL_SETTINGS_H25#define __PCBNEW_GENERAL_SETTINGS_H
2626
27#include <colors_design_settings.h>27#include <colors_design_settings.h>
28#include <vector>
2829
29class wxConfigBase;30class wxConfigBase;
30class wxString;31class wxString;
@@ -65,6 +66,10 @@ public:
65 MAGNETIC_PAD_OPTION_VALUES m_magneticPads = CAPTURE_CURSOR_IN_TRACK_TOOL;66 MAGNETIC_PAD_OPTION_VALUES m_magneticPads = CAPTURE_CURSOR_IN_TRACK_TOOL;
66 MAGNETIC_PAD_OPTION_VALUES m_magneticTracks = CAPTURE_CURSOR_IN_TRACK_TOOL;67 MAGNETIC_PAD_OPTION_VALUES m_magneticTracks = CAPTURE_CURSOR_IN_TRACK_TOOL;
6768
69#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
70 std::vector< std::pair<wxString, wxString> > m_pluginSettings; // Settings for action plugins
71#endif
72
68protected:73protected:
69 const FRAME_T m_frameType;74 const FRAME_T m_frameType;
70 COLORS_DESIGN_SETTINGS m_colorsSettings;75 COLORS_DESIGN_SETTINGS m_colorsSettings;
diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp
index ae164fd..b6025a5 100644
--- a/pcbnew/pcbnew_config.cpp
+++ b/pcbnew/pcbnew_config.cpp
@@ -45,6 +45,7 @@
45#include <panel_hotkeys_editor.h>45#include <panel_hotkeys_editor.h>
46#include <panel_pcbnew_settings.h>46#include <panel_pcbnew_settings.h>
47#include <panel_pcbnew_display_options.h>47#include <panel_pcbnew_display_options.h>
48#include <panel_pcbnew_action_plugins.h>
48#include <fp_lib_table.h>49#include <fp_lib_table.h>
49#include <worksheet_shape_builder.h>50#include <worksheet_shape_builder.h>
50#include <class_board.h>51#include <class_board.h>
@@ -97,6 +98,9 @@ void PCB_EDIT_FRAME::InstallPreferences( PAGED_DIALOG* aParent )
9798
98 book->AddPage( new PANEL_PCBNEW_SETTINGS( this, aParent ), _( "Pcbnew" ) );99 book->AddPage( new PANEL_PCBNEW_SETTINGS( this, aParent ), _( "Pcbnew" ) );
99 book->AddSubPage( new PANEL_PCBNEW_DISPLAY_OPTIONS( this, aParent ), _( "Display Options" ) );100 book->AddSubPage( new PANEL_PCBNEW_DISPLAY_OPTIONS( this, aParent ), _( "Display Options" ) );
101#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
102 book->AddSubPage( new PANEL_PCBNEW_ACTION_PLUGINS( this, aParent ), _( "Action Plugins" ) );
103#endif
100}104}
101105
102106
diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp
index 4fb232e..0de6526 100644
--- a/pcbnew/swig/pcbnew_action_plugins.cpp
+++ b/pcbnew/swig/pcbnew_action_plugins.cpp
@@ -140,6 +140,32 @@ wxString PYTHON_ACTION_PLUGIN::GetDescription()
140}140}
141141
142142
143bool PYTHON_ACTION_PLUGIN::GetShowToolbarButton()
144{
145 PyLOCK lock;
146
147 PyObject* result = CallMethod( "GetShowToolbarButton");
148
149 return PyObject_IsTrue(result);
150}
151
152
153wxString PYTHON_ACTION_PLUGIN::GetIconFileName()
154{
155 PyLOCK lock;
156
157 return CallRetStrMethod( "GetIconFileName" );
158}
159
160
161wxString PYTHON_ACTION_PLUGIN::GetPluginPath()
162{
163 PyLOCK lock;
164
165 return CallRetStrMethod( "GetPluginPath" );
166}
167
168
143void PYTHON_ACTION_PLUGIN::Run()169void PYTHON_ACTION_PLUGIN::Run()
144{170{
145 PyLOCK lock;171 PyLOCK lock;
@@ -164,217 +190,226 @@ void PYTHON_ACTION_PLUGINS::register_action( PyObject* aPyAction )
164190
165void PYTHON_ACTION_PLUGINS::deregister_action( PyObject* aPyAction )191void PYTHON_ACTION_PLUGINS::deregister_action( PyObject* aPyAction )
166{192{
167 // deregister also destroyes the previously created "PYTHON_ACTION_PLUGIN object"193 // deregister also destroys the previously created "PYTHON_ACTION_PLUGIN object"
168 ACTION_PLUGINS::deregister_object( (void*) aPyAction );194 ACTION_PLUGINS::deregister_object( (void*) aPyAction );
169}195}
170196
171197
172#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)198#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
173199
174void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent )200void PCB_EDIT_FRAME::OnActionPluginMenu( wxCommandEvent& aEvent )
175{201{
176 int id = aEvent.GetId();202 ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByMenu( aEvent.GetId() );
177203
178 ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByMenu( id );204 if( actionPlugin )
205 RunActionPlugin( actionPlugin );
206}
179207
180 if( actionPlugin )208void PCB_EDIT_FRAME::OnActionPluginButton( wxCommandEvent& aEvent )
181 {209{
182 PICKED_ITEMS_LIST itemsList;210 ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByButton( aEvent.GetId() );
183 BOARD* currentPcb = GetBoard();
184 bool fromEmpty = false;
185211
186 itemsList.m_Status = UR_CHANGED;212 if( actionPlugin )
213 RunActionPlugin( actionPlugin );
214}
187215
188 OnModify();216void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin )
217{
218 PICKED_ITEMS_LIST itemsList;
219 BOARD* currentPcb = GetBoard();
220 bool fromEmpty = false;
189221
190 // Append tracks:222 itemsList.m_Status = UR_CHANGED;
191 for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
192 {
193 ITEM_PICKER picker( item, UR_CHANGED );
194 itemsList.PushItem( picker );
195 }
196223
197 // Append modules:224 OnModify();
198 for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
199 {
200 ITEM_PICKER picker( item, UR_CHANGED );
201 itemsList.PushItem( picker );
202 }
203225
204 // Append drawings226 // Append tracks:
205 for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )227 for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
206 {228 {
207 ITEM_PICKER picker( item, UR_CHANGED );229 ITEM_PICKER picker( item, UR_CHANGED );
208 itemsList.PushItem( picker );230 itemsList.PushItem( picker );
209 }231 }
210232
211 // Append zones outlines233 // Append modules:
212 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )234 for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
213 {235 {
214 ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(236 ITEM_PICKER picker( item, UR_CHANGED );
215 ii ), UR_CHANGED );237 itemsList.PushItem( picker );
216 itemsList.PushItem( picker );238 }
217 }
218239
219 // Append zones segm:240 // Append drawings
220 for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )241 for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
221 {242 {
222 ITEM_PICKER picker( item, UR_CHANGED );243 ITEM_PICKER picker( item, UR_CHANGED );
223 itemsList.PushItem( picker );244 itemsList.PushItem( picker );
224 }245 }
225246
226 if( itemsList.GetCount() > 0 )247 // Append zones outlines
227 SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) );248 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
228 else249 {
229 fromEmpty = true;250 ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
251 ii ), UR_CHANGED );
252 itemsList.PushItem( picker );
253 }
230254
231 itemsList.ClearItemsList();255 // Append zones segm:
256 for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )
257 {
258 ITEM_PICKER picker( item, UR_CHANGED );
259 itemsList.PushItem( picker );
260 }
232261
233 // Execute plugin himself...262 if( itemsList.GetCount() > 0 )
234 ACTION_PLUGINS::SetActionRunning( true );263 SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) );
235 actionPlugin->Run();264 else
236 ACTION_PLUGINS::SetActionRunning( false );265 fromEmpty = true;
237266
238 currentPcb->m_Status_Pcb = 0;267 itemsList.ClearItemsList();
239268
240 // Get back the undo buffer to fix some modifications269 // Execute plugin itself...
241 PICKED_ITEMS_LIST* oldBuffer = NULL;270 ACTION_PLUGINS::SetActionRunning( true );
271 aActionPlugin->Run();
272 ACTION_PLUGINS::SetActionRunning( false );
242273
243 if( fromEmpty )274 currentPcb->m_Status_Pcb = 0;
244 {
245 oldBuffer = new PICKED_ITEMS_LIST();
246 oldBuffer->m_Status = UR_NEW;
247 }
248 else
249 {
250 oldBuffer = GetScreen()->PopCommandFromUndoList();
251 wxASSERT( oldBuffer );
252 }
253275
254 // Try do discover what was modified276 // Get back the undo buffer to fix some modifications
277 PICKED_ITEMS_LIST* oldBuffer = NULL;
255278
256 PICKED_ITEMS_LIST deletedItemsList;279 if( fromEmpty )
280 {
281 oldBuffer = new PICKED_ITEMS_LIST();
282 oldBuffer->m_Status = UR_NEW;
283 }
284 else
285 {
286 oldBuffer = GetScreen()->PopCommandFromUndoList();
287 wxASSERT( oldBuffer );
288 }
257289
258 // Found deleted modules290 // Try do discover what was modified
259 for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ )
260 {
261 BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i );
262 ITEM_PICKER picker( item, UR_DELETED );
263291
264 wxASSERT( item );292 PICKED_ITEMS_LIST deletedItemsList;
265293
266 switch( item->Type() )294 // Found deleted modules
267 {295 for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ )
268 case PCB_NETINFO_T:296 {
269 case PCB_MARKER_T:297 BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i );
270 case PCB_MODULE_T:298 ITEM_PICKER picker( item, UR_DELETED );
271 case PCB_TRACE_T:299
272 case PCB_VIA_T:300 wxASSERT( item );
273 case PCB_LINE_T:301
274 case PCB_TEXT_T:302 switch( item->Type() )
275 case PCB_DIMENSION_T:303 {
276 case PCB_TARGET_T:304 case PCB_NETINFO_T:
277 case PCB_ZONE_T:305 case PCB_MARKER_T:
278306 case PCB_MODULE_T:
279 // If item has a list it's mean that the element is on the board307 case PCB_TRACE_T:
280 if( item->GetList() == NULL )308 case PCB_VIA_T:
281 {309 case PCB_LINE_T:
282 deletedItemsList.PushItem( picker );310 case PCB_TEXT_T:
283 }311 case PCB_DIMENSION_T:
284312 case PCB_TARGET_T:
285 break;313 case PCB_ZONE_T:
286314
287 case PCB_ZONE_AREA_T:315 // If item has a list it's mean that the element is on the board
316 if( item->GetList() == NULL )
288 {317 {
289 bool zoneFound = false;318 deletedItemsList.PushItem( picker );
319 }
290320
291 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )321 break;
292 zoneFound |= currentPcb->GetArea( ii ) == item;
293322
294 if( !zoneFound )323 case PCB_ZONE_AREA_T:
295 {324 {
296 deletedItemsList.PushItem( picker );325 bool zoneFound = false;
297 }
298326
299 break;327 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
300 }328 zoneFound |= currentPcb->GetArea( ii ) == item;
301329
302 default:330 if( !zoneFound )
303 wxString msg;331 {
304 msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: "332 deletedItemsList.PushItem( picker );
305 "BOARD_ITEM type (%d) not handled" ),
306 item->Type() );
307 wxFAIL_MSG( msg );
308 break;
309 }333 }
334
335 break;
310 }336 }
311337
312 // Mark deleted elements in undolist338 default:
313 for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ )339 wxString msg;
314 {340 msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: "
315 oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) );341 "BOARD_ITEM type (%d) not handled" ),
342 item->Type() );
343 wxFAIL_MSG( msg );
344 break;
316 }345 }
346 }
317347
318 // Find new modules348 // Mark deleted elements in undolist
319 for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )349 for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ )
350 {
351 oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) );
352 }
353
354 // Find new modules
355 for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() )
356 {
357 if( !oldBuffer->ContainsItem( item ) )
320 {358 {
321 if( !oldBuffer->ContainsItem( item ) )359 ITEM_PICKER picker( item, UR_NEW );
322 {360 oldBuffer->PushItem( picker );
323 ITEM_PICKER picker( item, UR_NEW );
324 oldBuffer->PushItem( picker );
325 }
326 }361 }
362 }
327363
328 for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )364 for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() )
365 {
366 if( !oldBuffer->ContainsItem( item ) )
329 {367 {
330 if( !oldBuffer->ContainsItem( item ) )368 ITEM_PICKER picker( item, UR_NEW );
331 {369 oldBuffer->PushItem( picker );
332 ITEM_PICKER picker( item, UR_NEW );
333 oldBuffer->PushItem( picker );
334 }
335 }370 }
371 }
336372
337 for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )373 for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() )
374 {
375 if( !oldBuffer->ContainsItem( item ) )
338 {376 {
339 if( !oldBuffer->ContainsItem( item ) )377 ITEM_PICKER picker( item, UR_NEW );
340 {378 oldBuffer->PushItem( picker );
341 ITEM_PICKER picker( item, UR_NEW );
342 oldBuffer->PushItem( picker );
343 }
344 }379 }
380 }
345381
346 for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )382 for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() )
383 {
384 if( !oldBuffer->ContainsItem( item ) )
347 {385 {
348 if( !oldBuffer->ContainsItem( item ) )386 ITEM_PICKER picker( item, UR_NEW );
349 {387 oldBuffer->PushItem( picker );
350 ITEM_PICKER picker( item, UR_NEW );
351 oldBuffer->PushItem( picker );
352 }
353 }388 }
389 }
354390
355 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )391 for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ )
392 {
393 if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) )
356 {394 {
357 if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) )395 ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(
358 {396 ii ), UR_NEW );
359 ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea(397 oldBuffer->PushItem( picker );
360 ii ), UR_NEW );
361 oldBuffer->PushItem( picker );
362 }
363 }398 }
399 }
364400
365401
366 GetScreen()->PushCommandToUndoList( oldBuffer );402 GetScreen()->PushCommandToUndoList( oldBuffer );
367403
368 if( IsGalCanvasActive() )404 if( IsGalCanvasActive() )
369 {405 {
370 UseGalCanvas( GetGalCanvas() );406 UseGalCanvas( GetGalCanvas() );
371 }407 }
372 else408 else
373 {409 {
374 UpdateUserInterface();410 UpdateUserInterface();
375 GetScreen()->SetModify();411 GetScreen()->SetModify();
376 Refresh();412 Refresh();
377 }
378 }413 }
379}414}
380415
@@ -409,30 +444,39 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
409 // Remove menus which are not usable for our current plugin list444 // Remove menus which are not usable for our current plugin list
410 Disconnect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,445 Disconnect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
411 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &446 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
412 PCB_EDIT_FRAME::OnActionPlugin );447 PCB_EDIT_FRAME::OnActionPluginMenu );
413 actionMenu->Delete( item );448 actionMenu->Delete( item );
414 }449 }
415450
416 for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ )451 for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ )
417 {452 {
418 wxMenuItem* item;453 wxMenuItem* item;
454 ACTION_PLUGIN* ap = ACTION_PLUGINS::GetAction( ii );
455 const wxBitmap& bitmap = ap->iconBitmap.IsOk() ? ap->iconBitmap : KiBitmap( hammer_xpm );
419456
420 if( ii < (int) available_menus.size() )457 if( ii < (int) available_menus.size() )
421 {458 {
422 item = available_menus[ii];459 item = available_menus[ii];
423 item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() );460 item->SetItemLabel( ap->GetName() );
424 item->SetHelp( ACTION_PLUGINS::GetAction( ii )->GetDescription() );461 item->SetHelp( ap->GetDescription() );
462
463 // On windows we need to set "unchecked" bitmap
464#if defined(__WXMSW__)
465 item->SetBitmap( bitmap, false );
466#else
467 item->SetBitmap( bitmap );
468#endif
425 }469 }
426 else470 else
427 {471 {
428 item = AddMenuItem( actionMenu, wxID_ANY,472 item = AddMenuItem( actionMenu, wxID_ANY,
429 ACTION_PLUGINS::GetAction( ii )->GetName(),473 ap->GetName(),
430 ACTION_PLUGINS::GetAction( ii )->GetDescription(),474 ap->GetDescription(),
431 KiBitmap( hammer_xpm ) );475 bitmap );
432476
433 Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,477 Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
434 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &478 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
435 PCB_EDIT_FRAME::OnActionPlugin );479 PCB_EDIT_FRAME::OnActionPluginMenu );
436 }480 }
437481
438 ACTION_PLUGINS::SetActionMenu( ii, item->GetId() );482 ACTION_PLUGINS::SetActionMenu( ii, item->GetId() );
@@ -440,4 +484,104 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus()
440}484}
441485
442486
487void PCB_EDIT_FRAME::AddActionPluginTools()
488{
489 bool need_separator = true;
490 const auto& orderedPlugins = GetOrderedActionPlugins();
491
492 for( const auto& ap : orderedPlugins )
493 {
494 if( GetActionPluginButtonVisible( ap->GetPluginPath(), ap->GetShowToolbarButton() ) )
495 {
496
497 if ( need_separator )
498 {
499 KiScaledSeparator( m_mainToolBar, this );
500 need_separator = false;
501 }
502
503 // Add button
504 wxBitmap bitmap;
505
506 if ( ap->iconBitmap.IsOk() )
507 bitmap = KiScaledBitmap( ap->iconBitmap, this );
508 else
509 bitmap = KiScaledBitmap( hammer_xpm, this );
510
511 wxAuiToolBarItem* button = m_mainToolBar->AddTool(
512 wxID_ANY, wxEmptyString, bitmap, ap->GetName() );
513
514 Connect( button->GetId(), wxEVT_COMMAND_MENU_SELECTED,
515 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
516 PCB_EDIT_FRAME::OnActionPluginButton );
517
518 // Link action plugin to button
519 ACTION_PLUGINS::SetActionButton( ap, button->GetId() );
520 }
521 }
522}
523
524
525void PCB_EDIT_FRAME::SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginSettings )
526{
527 m_configSettings.m_pluginSettings = aPluginSettings;
528 ReCreateHToolbar();
529}
530
531
532std::vector< std::pair<wxString, wxString> > PCB_EDIT_FRAME::GetActionPluginSettings()
533{
534 return m_configSettings.m_pluginSettings;
535}
536
537
538std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
539{
540 std::vector<ACTION_PLUGIN*> orderedPlugins;
541 const auto& pluginSettings = GetActionPluginSettings();
542
543 // First add plugins that have entries in settings
544 for( size_t ii = 0; ii < pluginSettings.size(); ii++ )
545 {
546 for( int jj = 0; jj < ACTION_PLUGINS::GetActionsCount(); jj++ )
547 {
548 if( ACTION_PLUGINS::GetAction( jj )->GetPluginPath() == pluginSettings[ii].first )
549 orderedPlugins.push_back( ACTION_PLUGINS::GetAction( jj ) );
550 }
551 }
552
553 // Now append new plugins that have not been configured yet
554 for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ )
555 {
556 bool found = false;
557
558 for( size_t jj = 0; jj < orderedPlugins.size(); jj++ )
559 {
560 if( ACTION_PLUGINS::GetAction( ii ) == orderedPlugins[jj] )
561 found = true;
562 }
563
564 if ( !found )
565 orderedPlugins.push_back( ACTION_PLUGINS::GetAction( ii ) );
566 }
567
568 return orderedPlugins;
569}
570
571
572bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault )
573{
574 auto& settings = m_configSettings.m_pluginSettings;
575
576 for(const auto& entry : settings )
577 {
578 if (entry.first == aPluginPath )
579 return entry.second == wxT( "Visible" );
580 }
581
582 // Plugin is not in settings, return default.
583 return aPluginDefault;
584}
585
586
443#endif587#endif
diff --git a/pcbnew/swig/pcbnew_action_plugins.h b/pcbnew/swig/pcbnew_action_plugins.h
index 08dfa14..a1d6d9f 100644
--- a/pcbnew/swig/pcbnew_action_plugins.h
+++ b/pcbnew/swig/pcbnew_action_plugins.h
@@ -47,6 +47,9 @@ public:
47 wxString GetCategoryName() override;47 wxString GetCategoryName() override;
48 wxString GetName() override;48 wxString GetName() override;
49 wxString GetDescription() override;49 wxString GetDescription() override;
50 bool GetShowToolbarButton() override;
51 wxString GetIconFileName() override;
52 wxString GetPluginPath() override;
50 void Run() override;53 void Run() override;
51 void* GetObject() override;54 void* GetObject() override;
52};55};
diff --git a/pcbnew/tool_pcb_editor.cpp b/pcbnew/tool_pcb_editor.cpp
index 66b6223..b5c64c3 100644
--- a/pcbnew/tool_pcb_editor.cpp
+++ b/pcbnew/tool_pcb_editor.cpp
@@ -321,6 +321,10 @@ void PCB_EDIT_FRAME::ReCreateHToolbar()
321 m_mainToolBar->AddTool( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, wxEmptyString,321 m_mainToolBar->AddTool( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, wxEmptyString,
322 KiScaledBitmap( py_script_xpm, this ),322 KiScaledBitmap( py_script_xpm, this ),
323 _( "Show/Hide the Python Scripting console" ), wxITEM_CHECK );323 _( "Show/Hide the Python Scripting console" ), wxITEM_CHECK );
324
325#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
326 AddActionPluginTools();
327#endif
324 }328 }
325#endif329#endif
326330
diff --git a/scripting/kicadplugins.i b/scripting/kicadplugins.i
index 8c1781d..ebd8db2 100644
--- a/scripting/kicadplugins.i
+++ b/scripting/kicadplugins.i
@@ -260,7 +260,7 @@ def LoadPlugins(bundlepath=None):
260 if module == '__init__.py' or module[-3:] != '.py':260 if module == '__init__.py' or module[-3:] != '.py':
261 continue261 continue
262262
263 LoadOnePlugin(plugins_dir, module);263 LoadOnePlugin(plugins_dir, module)
264264
265265
266class KiCadPlugin:266class KiCadPlugin:
@@ -268,6 +268,9 @@ class KiCadPlugin:
268 pass268 pass
269269
270 def register(self):270 def register(self):
271 import inspect
272 import os
273
271 if isinstance(self,FilePlugin):274 if isinstance(self,FilePlugin):
272 pass # register to file plugins in C++275 pass # register to file plugins in C++
273276
@@ -276,6 +279,14 @@ class KiCadPlugin:
276 return279 return
277280
278 if isinstance(self,ActionPlugin):281 if isinstance(self,ActionPlugin):
282 """
283 Get path to .py or .pyc that has definition of plugin class.
284 If path is binary but source also exists, assume definition is in source.
285 """
286 self.__plugin_path = inspect.getfile(self.__class__)
287 if self.__plugin_path.endswith('.pyc') and os.path.isfile(self.__plugin_path[:-1]):
288 self.__plugin_path = self.__plugin_path[:-1]
289 self.__plugin_path = self.__plugin_path + '/' + self.__class__.__name__
279 PYTHON_ACTION_PLUGINS.register_action(self)290 PYTHON_ACTION_PLUGINS.register_action(self)
280 return291 return
281292
@@ -295,6 +306,9 @@ class KiCadPlugin:
295306
296 return307 return
297308
309 def GetPluginPath( self ):
310 return self.__plugin_path
311
298312
299class FilePlugin(KiCadPlugin):313class FilePlugin(KiCadPlugin):
300 def __init__(self):314 def __init__(self):
@@ -633,6 +647,8 @@ class FootprintWizardPlugin(KiCadPlugin, object):
633class ActionPlugin(KiCadPlugin, object):647class ActionPlugin(KiCadPlugin, object):
634 def __init__( self ):648 def __init__( self ):
635 KiCadPlugin.__init__( self )649 KiCadPlugin.__init__( self )
650 self.icon_file_name = ""
651 self.show_toolbar_button = False
636 self.defaults()652 self.defaults()
637653
638 def defaults( self ):654 def defaults( self ):
@@ -649,6 +665,12 @@ class ActionPlugin(KiCadPlugin, object):
649 def GetDescription( self ):665 def GetDescription( self ):
650 return self.description666 return self.description
651667
668 def GetShowToolbarButton( self ):
669 return self.show_toolbar_button
670
671 def GetIconFileName( self ):
672 return self.icon_file_name
673
652 def Run(self):674 def Run(self):
653 return675 return
654676

Subscribers

People subscribed via source and target branches

to status/vote changes: