diff --git a/common/bitmap.cpp b/common/bitmap.cpp index 031b2cc556..bce8344c55 100644 --- a/common/bitmap.cpp +++ b/common/bitmap.cpp @@ -144,6 +144,25 @@ wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow ) } +wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, EDA_BASE_FRAME* aWindow ) +{ + const int scale = get_scale_factor( aWindow ); + + if( scale == 4) + { + return wxBitmap( aBitmap ); + } + else + { + wxImage image = aBitmap.ConvertToImage(); + image.Rescale( scale * image.GetWidth() / 4, scale * image.GetHeight() / 4, + wxIMAGE_QUALITY_BILINEAR ); + + return wxBitmap( image ); + } +} + + void KiScaledSeparator( wxAuiToolBar* aToolbar, EDA_BASE_FRAME* aWindow ) { 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 8d348c7d0f..b1f949e977 100644 --- a/common/widgets/grid_icon_text_helpers.cpp +++ b/common/widgets/grid_icon_text_helpers.cpp @@ -27,7 +27,7 @@ #include <wx/dc.h> -//---- Grid helpers: custom wxGridCellRenderer ------------------------------------------ +//---- Grid helpers: custom wxGridCellRenderer that renders icon and a label ------------ GRID_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 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, + 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 ) +{ + 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/bitmap_types.h b/include/bitmap_types.h index 8657df4969..f703ddbbdc 100644 --- a/include/bitmap_types.h +++ b/include/bitmap_types.h @@ -73,6 +73,14 @@ wxBitmap KiBitmap( BITMAP_DEF aBitmap ); */ wxBitmap KiScaledBitmap( BITMAP_DEF aBitmap, EDA_BASE_FRAME* aWindow ); +/** + * Function KiScaledBitmap + * Overload of the above function that takes another wxBitmap as a parameter + * + * @param aBitmap bitmap definition + * @param aWindow target window for scaling context + */ +wxBitmap KiScaledBitmap( const wxBitmap& aBitmap, EDA_BASE_FRAME* aWindow ); /** * Function KiScaledSeparator diff --git a/include/widgets/grid_icon_text_helpers.h b/include/widgets/grid_icon_text_helpers.h index 9e14829599..60ea612d32 100644 --- a/include/widgets/grid_icon_text_helpers.h +++ b/include/widgets/grid_icon_text_helpers.h @@ -34,7 +34,7 @@ class wxGrid; -//---- Grid helpers: custom wxGridCellRenderer ------------------------------------------ +//---- Grid helpers: custom wxGridCellRenderer that renders icon and a label ------------ class GRID_CELL_ICON_TEXT_RENDERER : public wxGridCellStringRenderer { @@ -49,6 +49,23 @@ private: const wxArrayString& m_names; }; +//---- Grid helpers: custom wxGridCellRenderer that renders just an icon ---------------- +// +// Note: use with read only cells + +class GRID_CELL_ICON_RENDERER : public wxGridCellRenderer +{ +public: + GRID_CELL_ICON_RENDERER( const wxBitmap& icon ); + + void Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC, + const wxRect& aRect, int aRow, int aCol, bool isSelected ) override; + wxSize GetBestSize( wxGrid & grid, wxGridCellAttr & attr, wxDC & dc, int row, int col ) override; + wxGridCellRenderer* Clone() const override; + +private: + const wxBitmap& m_icon; +}; //---- Grid helpers: custom wxGridCellEditor ------------------------------------------ // diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index a77f8ebfdb..22020800b7 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -152,8 +152,6 @@ set( PCBNEW_DIALOGS dialogs/panel_modedit_settings_base.cpp dialogs/panel_pcbnew_display_options.cpp dialogs/panel_pcbnew_display_options_base.cpp - dialogs/panel_pcbnew_display_options.cpp - dialogs/panel_pcbnew_display_options_base.cpp dialogs/panel_pcbnew_settings.cpp dialogs/panel_pcbnew_settings_base.cpp dialogs/panel_setup_mask_and_paste.cpp @@ -174,6 +172,13 @@ set( PCBNEW_DIALOGS ${GITHUB_3DLIBRARIES_WIZARD} ) +if( KICAD_SCRIPTING AND KICAD_SCRIPTING_ACTION_MENU ) + set( PCBNEW_DIALOGS ${PCBNEW_DIALOGS} + dialogs/panel_pcbnew_action_plugins.cpp + dialogs/panel_pcbnew_action_plugins_base.cpp + ) +endif() + set( PCBNEW_IMPORT_DXF import_dxf/dialog_dxf_import.cpp import_dxf/dialog_dxf_import_base.cpp diff --git a/pcbnew/action_plugin.cpp b/pcbnew/action_plugin.cpp index c10d0fafe2..e79ea29638 100644 --- a/pcbnew/action_plugin.cpp +++ b/pcbnew/action_plugin.cpp @@ -73,9 +73,37 @@ void ACTION_PLUGINS::SetActionMenu( int aIndex, int idMenu ) } -int ACTION_PLUGINS::GetActionMenu( int aIndex ) +ACTION_PLUGIN* ACTION_PLUGINS::GetActionByButton( int aButton ) { - return m_actionsList[aIndex]->m_actionMenuId; + int max = GetActionsCount(); + + for( int i = 0; i < max; i++ ) + { + if( m_actionsList[i]->m_actionButtonId == aButton ) + return m_actionsList[i]; + } + + return NULL; +} + + +void ACTION_PLUGINS::SetActionButton( ACTION_PLUGIN* aAction, int idButton ) +{ + aAction->m_actionButtonId = idButton; +} + + +ACTION_PLUGIN* ACTION_PLUGINS::GetActionByPath(const wxString& aPath) +{ + for( int i = 0; i < GetActionsCount() ; i++ ) + { + if( m_actionsList[i]->GetPluginPath() == aPath) + { + return m_actionsList[i]; + } + } + + return NULL; } @@ -127,6 +155,20 @@ void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction ) } } + // Load icon if supplied + if (!aAction->GetIconFileName().IsEmpty()) + { + { + wxLogNull eat_errors; + aAction->iconBitmap.LoadFile( aAction->GetIconFileName() , wxBITMAP_TYPE_PNG ); + } + + if ( !aAction->iconBitmap.IsOk() ) + { + wxLogVerbose( "Failed to load icon " + aAction->GetIconFileName() + " for action plugin " ); + } + } + m_actionsList.push_back( aAction ); } diff --git a/pcbnew/action_plugin.h b/pcbnew/action_plugin.h index ff3ed14559..8bb6c9c4aa 100644 --- a/pcbnew/action_plugin.h +++ b/pcbnew/action_plugin.h @@ -44,9 +44,16 @@ public: // m_actionMenuId set to 0 means the corresponding menuitem to call this // action is not yet created int m_actionMenuId; + // Same for button id + int m_actionButtonId; + // Icon for the action button and menu entry + wxBitmap iconBitmap; + // If show_on_toolbar is true a button will be added to top toolbar + bool show_on_toolbar; public: - ACTION_PLUGIN() : m_actionMenuId( 0 ) {} + ACTION_PLUGIN() : m_actionMenuId( 0 ), m_actionButtonId( 0 ), + show_on_toolbar( false ) {} virtual ~ACTION_PLUGIN(); /** @@ -68,6 +75,24 @@ public: */ virtual wxString GetDescription() = 0; + /** + * Function GetShowToolbarButton + * @return true if button should be shown on top toolbar + */ + virtual bool GetShowToolbarButton() = 0; + + /** + * Function GetIconFileName + * @return a path to icon for the action plugin button + */ + virtual wxString GetIconFileName() = 0; + + /** + * Function GetPluginPath + * @return a path this plugin was loaded from + */ + virtual wxString GetPluginPath() = 0; + /** * Function GetObject * This method gets the pointer to the object from where this action constructs @@ -137,16 +162,6 @@ public: */ static void SetActionMenu( int aIndex, int idMenu ); - - /** - * Function GetActionMenu - * Provide menu id for a plugin index - * @param aIndex is the action index - * @return associated menuitem id - */ - static int GetActionMenu( int aIndex ); - - /** * Function GetActionByMenu * find action plugin associated to a menu id @@ -155,6 +170,29 @@ public: */ static ACTION_PLUGIN* GetActionByMenu( int aMenu ); + /** + * Function SetActionButton + * Associate a button id to an action plugin + * @param aAction is the action + * @param idButton is the associated menuitem id + */ + static void SetActionButton( ACTION_PLUGIN* aAction, int idButton ); + + /** + * Function GetActionByButton + * find action plugin associated to a button id + * @param aButton is the button id (defined with SetActionButton) + * @return the associated ACTION_PLUGIN (or null if not found) + */ + static ACTION_PLUGIN* GetActionByButton( int aButton ); + + /** + * Function GetActionByPath + * find action plugin by module path + * @param aPath the path of plugin + * @return the corresponding ACTION_PLUGIN (or null if not found) + */ + static ACTION_PLUGIN* GetActionByPath( const wxString& aPath ); /** * Function GetAction diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp new file mode 100644 index 0000000000..3887fe9b2f --- /dev/null +++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp @@ -0,0 +1,199 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 Andrew Lutsenko, anlutsenko at gmail dot com + * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <pcb_edit_frame.h> +#include <panel_pcbnew_action_plugins.h> +#include <widgets/paged_dialog.h> +#include <widgets/grid_icon_text_helpers.h> +#include <bitmaps.h> +#include <action_plugin.h> +#include <grid_tricks.h> +#include <widgets/wx_grid.h> + + +PANEL_PCBNEW_ACTION_PLUGINS::PANEL_PCBNEW_ACTION_PLUGINS( PCB_EDIT_FRAME* aFrame, PAGED_DIALOG* aWindow ) : + PANEL_PCBNEW_ACTION_PLUGINS_BASE( aWindow->GetTreebook() ), + m_frame( aFrame ) +{ + m_genericIcon = KiBitmap( hammer_xpm ); + m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) ); + + m_moveUpButton->SetBitmap( KiBitmap( up_xpm ) ); + m_moveDownButton->SetBitmap( KiBitmap( down_xpm ) ); + m_reloadButton->SetBitmap( KiBitmap( refresh_xpm ) ); +} + + +PANEL_PCBNEW_ACTION_PLUGINS::~PANEL_PCBNEW_ACTION_PLUGINS() +{ + m_grid->PopEventHandler( true ); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::OnGridCellClick( wxGridEvent& event ) +{ + SelectRow( event.GetRow() ); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::SelectRow( int aRow ) +{ + m_grid->ClearSelection(); + m_grid->SelectRow( aRow ); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::OnMoveUpButtonClick( wxCommandEvent& event ) +{ + auto selectedRows = m_grid->GetSelectedRows(); + + // If nothing is selected or multiple rows are selected don't do anything. + if( selectedRows.size() != 1 ) return; + + int selectedRow = selectedRows[0]; + + // If first row is selected, then it can't go any further up. + if( selectedRow == 0 ) + { + wxBell(); + return; + } + + SwapRows( selectedRow, selectedRow - 1 ); + + SelectRow( selectedRow - 1 ); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::OnMoveDownButtonClick( wxCommandEvent& event ) +{ + auto selectedRows = m_grid->GetSelectedRows(); + + // If nothing is selected or multiple rows are selected don't do anything. + if( selectedRows.size() != 1 ) return; + + int selectedRow = selectedRows[0]; + + // If last row is selected, then it can't go any further down. + if( selectedRow + 1 == m_grid->GetNumberRows() ) + { + wxBell(); + return; + } + + SwapRows( selectedRow, selectedRow + 1 ); + + SelectRow( selectedRow + 1 ); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::SwapRows( int aRowA, int aRowB ) +{ + m_grid->Freeze(); + + // Swap all columns except icon + wxString tempStr; + + for( int column = 1; column < m_grid->GetNumberCols(); column++ ) + { + tempStr = m_grid->GetCellValue( aRowA, column ); + m_grid->SetCellValue( aRowA, column, m_grid->GetCellValue( aRowB, column ) ); + m_grid->SetCellValue( aRowB, column, tempStr ); + } + + // Swap icon column renderers + auto cellRenderer = m_grid->GetCellRenderer( aRowA, COLUMN_ICON ); + m_grid->SetCellRenderer( aRowA, COLUMN_ICON, m_grid->GetCellRenderer( aRowB, COLUMN_ICON ) ); + m_grid->SetCellRenderer( aRowB, COLUMN_ICON, cellRenderer ); + + m_grid->Thaw(); +} + + +void PANEL_PCBNEW_ACTION_PLUGINS::OnReloadButtonClick( wxCommandEvent& event ) +{ + m_frame->PythonPluginsReload(); + TransferDataToWindow(); +} + + +bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataFromWindow() +{ + std::vector< std::pair<wxString, wxString> > pluginSettings; + + for( int ii = 0; ii < m_grid->GetNumberRows(); ii++ ) + { + pluginSettings.push_back( std::make_pair( + m_grid->GetCellValue( ii, COLUMN_PATH ), + m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT("1") ? wxT( "Visible" ) : wxT( "Hidden" ) + ) ); + } + + m_frame->SetActionPluginSettings( pluginSettings ); + + return true; +} + + +bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataToWindow() +{ + m_grid->Freeze(); + m_grid->DeleteRows( 0, m_grid->GetNumberRows() ); + + const auto& orderedPlugins = m_frame->GetOrderedActionPlugins(); + m_grid->AppendRows( orderedPlugins.size() ); + + for( size_t row = 0; row < orderedPlugins.size(); row++ ) + { + ACTION_PLUGIN* ap = orderedPlugins[row]; + + // Icon + m_grid->SetCellRenderer( row, COLUMN_ICON, new GRID_CELL_ICON_RENDERER( + ap->iconBitmap.IsOk() ? ap->iconBitmap : m_genericIcon ) ); + + // Toolbar button checkbox + m_grid->SetCellRenderer( row, COLUMN_VISIBLE, new wxGridCellBoolRenderer() ); + m_grid->SetCellAlignment( row, COLUMN_VISIBLE, wxALIGN_CENTER, wxALIGN_CENTER ); + + bool showButton = m_frame->GetActionPluginButtonVisible( + ap->GetPluginPath(), ap->GetShowToolbarButton() ); + + m_grid->SetCellValue( row, COLUMN_VISIBLE, showButton ? wxT( "1" ) : wxEmptyString ); + + // Name + m_grid->SetCellValue( row, COLUMN_NAME, ap->GetName() ); + + // Category + m_grid->SetCellValue( row, COLUMN_CATEGORY, ap->GetCategoryName() ); + + // Description + m_grid->SetCellValue( row, COLUMN_DESCRIPTION, ap->GetDescription() ); + + // Path + m_grid->SetCellValue( row, COLUMN_PATH, ap->GetPluginPath() ); + } + + m_grid->AutoSizeColumns(); + m_grid->AutoSizeRows(); + + m_grid->Thaw(); + + return true; +} diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.h b/pcbnew/dialogs/panel_pcbnew_action_plugins.h new file mode 100644 index 0000000000..48e8dc0155 --- /dev/null +++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.h @@ -0,0 +1,70 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 Andrew Lutsenko, anlutsenko at gmail dot com + * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "panel_pcbnew_action_plugins_base.h" + +class PANEL_PCBNEW_ACTION_PLUGINS : public PANEL_PCBNEW_ACTION_PLUGINS_BASE +{ +public: + PANEL_PCBNEW_ACTION_PLUGINS ( PCB_EDIT_FRAME* aFrame, PAGED_DIALOG* aWindow ); + + bool TransferDataFromWindow() override; + bool TransferDataToWindow() override; + ~PANEL_PCBNEW_ACTION_PLUGINS() override; + + /** + * Selects a whole row + */ + void OnGridCellClick( wxGridEvent& event ) override; + + /** + * Moves plugin up in the grid + */ + void OnMoveUpButtonClick( wxCommandEvent& event ) override; + + /** + * Moves plugin down in the grid + */ + void OnMoveDownButtonClick( wxCommandEvent& event ) override; + + /** + * Reloads plugins and updates grid + */ + void OnReloadButtonClick( wxCommandEvent& event ) override; + +private: + + enum GRID_COLUMNS + { + COLUMN_ICON, + COLUMN_VISIBLE, + COLUMN_NAME, + COLUMN_CATEGORY, + COLUMN_DESCRIPTION, + COLUMN_PATH + }; + + PCB_EDIT_FRAME* m_frame; + wxBitmap m_genericIcon; + + void SwapRows( int aRowA, int aRowB ); + void SelectRow( int aRow ); +}; + diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp new file mode 100644 index 0000000000..d8f8909046 --- /dev/null +++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.cpp @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jul 11 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "widgets/wx_grid.h" + +#include "panel_pcbnew_action_plugins_base.h" + +/////////////////////////////////////////////////////////////////////////// + +PANEL_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 ) +{ + wxBoxSizer* bPanelSizer; + bPanelSizer = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bGridSizer; + bGridSizer = new wxBoxSizer( wxVERTICAL ); + + m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE ); + + // Grid + m_grid->CreateGrid( 3, 6 ); + m_grid->EnableEditing( false ); + m_grid->EnableGridLines( true ); + m_grid->EnableDragGridSize( false ); + m_grid->SetMargins( 0, 0 ); + + // Columns + m_grid->AutoSizeColumns(); + m_grid->EnableDragColMove( false ); + m_grid->EnableDragColSize( true ); + m_grid->SetColLabelSize( 22 ); + m_grid->SetColLabelValue( 0, wxT("Icon") ); + m_grid->SetColLabelValue( 1, wxT("Show button") ); + m_grid->SetColLabelValue( 2, wxT("Name") ); + m_grid->SetColLabelValue( 3, wxT("Category") ); + m_grid->SetColLabelValue( 4, wxT("Description") ); + m_grid->SetColLabelValue( 5, wxT("Path") ); + m_grid->SetColLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Rows + m_grid->EnableDragRowSize( true ); + m_grid->SetRowLabelSize( 0 ); + m_grid->SetRowLabelAlignment( wxALIGN_CENTRE, wxALIGN_CENTRE ); + + // Label Appearance + + // Cell Defaults + m_grid->SetDefaultCellAlignment( wxALIGN_LEFT, wxALIGN_CENTRE ); + bGridSizer->Add( m_grid, 1, wxALL|wxEXPAND, 5 ); + + + bPanelSizer->Add( bGridSizer, 1, wxALIGN_LEFT|wxEXPAND|wxLEFT, 0 ); + + wxBoxSizer* bButtonsSizer; + bButtonsSizer = new wxBoxSizer( wxVERTICAL ); + + m_moveUpButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_moveUpButton->SetMinSize( wxSize( 32,32 ) ); + + bButtonsSizer->Add( m_moveUpButton, 0, wxALIGN_TOP|wxALL, 5 ); + + m_moveDownButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_moveDownButton->SetMinSize( wxSize( 32,32 ) ); + + bButtonsSizer->Add( m_moveDownButton, 0, wxALL, 5 ); + + m_reloadButton = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 ); + m_reloadButton->SetMinSize( wxSize( 32,32 ) ); + + bButtonsSizer->Add( m_reloadButton, 0, wxALL, 5 ); + + + bPanelSizer->Add( bButtonsSizer, 0, wxALIGN_RIGHT|wxALIGN_TOP, 0 ); + + + this->SetSizer( bPanelSizer ); + this->Layout(); + + // Connect Events + m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnGridCellClick ), NULL, this ); + m_moveUpButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveUpButtonClick ), NULL, this ); + m_moveDownButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveDownButtonClick ), NULL, this ); + m_reloadButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnReloadButtonClick ), NULL, this ); +} + +PANEL_PCBNEW_ACTION_PLUGINS_BASE::~PANEL_PCBNEW_ACTION_PLUGINS_BASE() +{ + // Disconnect Events + m_grid->Disconnect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnGridCellClick ), NULL, this ); + m_moveUpButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveUpButtonClick ), NULL, this ); + m_moveDownButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnMoveDownButtonClick ), NULL, this ); + m_reloadButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnReloadButtonClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp new file mode 100644 index 0000000000..6c91f1fd1f --- /dev/null +++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.fbp @@ -0,0 +1,578 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<wxFormBuilder_Project> + <FileVersion major="1" minor="14" /> + <object class="Project" expanded="1"> + <property name="class_decoration"></property> + <property name="code_generation">C++</property> + <property name="disconnect_events">1</property> + <property name="disconnect_mode">source_name</property> + <property name="disconnect_php_events">0</property> + <property name="disconnect_python_events">0</property> + <property name="embedded_files_path">res</property> + <property name="encoding">UTF-8</property> + <property name="event_generation">connect</property> + <property name="file">panel_pcbnew_action_plugins_base</property> + <property name="first_id">1000</property> + <property name="help_provider">none</property> + <property name="indent_with_spaces">0</property> + <property name="internationalize">0</property> + <property name="name">PanelPcbnewActionPlugins</property> + <property name="namespace"></property> + <property name="path">.</property> + <property name="precompiled_header"></property> + <property name="relative_path">1</property> + <property name="skip_lua_events">1</property> + <property name="skip_php_events">1</property> + <property name="skip_python_events">1</property> + <property name="ui_table">UI</property> + <property name="use_enum">1</property> + <property name="use_microsoft_bom">0</property> + <object class="Panel" expanded="1"> + <property name="aui_managed">0</property> + <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property> + <property name="bg"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="enabled">1</property> + <property name="event_handler">impl_virtual</property> + <property name="fg"></property> + <property name="font"></property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="maximum_size"></property> + <property name="minimum_size"></property> + <property name="name">PANEL_PCBNEW_ACTION_PLUGINS_BASE</property> + <property name="pos"></property> + <property name="size">485,200</property> + <property name="subclass">; forward_declare</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxTAB_TRAVERSAL</property> + <event name="OnAuiPaneActivated"></event> + <event name="OnAuiPaneButton"></event> + <event name="OnAuiPaneClose"></event> + <event name="OnAuiPaneMaximize"></event> + <event name="OnAuiPaneRestore"></event> + <event name="OnAuiRender"></event> + <event name="OnAux1DClick"></event> + <event name="OnAux1Down"></event> + <event name="OnAux1Up"></event> + <event name="OnAux2DClick"></event> + <event name="OnAux2Down"></event> + <event name="OnAux2Up"></event> + <event name="OnChar"></event> + <event name="OnCharHook"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnInitDialog"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bPanelSizer</property> + <property name="orient">wxHORIZONTAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">0</property> + <property name="flag">wxALIGN_LEFT|wxEXPAND|wxLEFT</property> + <property name="proportion">1</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bGridSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL|wxEXPAND</property> + <property name="proportion">1</property> + <object class="wxGrid" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="autosize_cols">1</property> + <property name="autosize_rows">0</property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="cell_bg"></property> + <property name="cell_font"></property> + <property name="cell_horiz_alignment">wxALIGN_LEFT</property> + <property name="cell_text"></property> + <property name="cell_vert_alignment">wxALIGN_CENTRE</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="col_label_horiz_alignment">wxALIGN_CENTRE</property> + <property name="col_label_size">22</property> + <property name="col_label_values">"Icon" "Show button" "Name" "Category" "Description" "Path"</property> + <property name="col_label_vert_alignment">wxALIGN_CENTRE</property> + <property name="cols">6</property> + <property name="column_sizes"></property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="default_pane">0</property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="drag_col_move">0</property> + <property name="drag_col_size">1</property> + <property name="drag_grid_size">0</property> + <property name="drag_row_size">1</property> + <property name="editing">0</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="font"></property> + <property name="grid_line_color"></property> + <property name="grid_lines">1</property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label_bg"></property> + <property name="label_font"></property> + <property name="label_text"></property> + <property name="margin_height">0</property> + <property name="margin_width">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size"></property> + <property name="moveable">1</property> + <property name="name">m_grid</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="resize">Resizable</property> + <property name="row_label_horiz_alignment">wxALIGN_CENTRE</property> + <property name="row_label_size">0</property> + <property name="row_label_values"></property> + <property name="row_label_vert_alignment">wxALIGN_CENTRE</property> + <property name="row_sizes"></property> + <property name="rows">3</property> + <property name="show">1</property> + <property name="size"></property> + <property name="subclass">WX_GRID; widgets/wx_grid.h; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style">wxBORDER_SIMPLE</property> + <event name="OnAux1DClick"></event> + <event name="OnAux1Down"></event> + <event name="OnAux1Up"></event> + <event name="OnAux2DClick"></event> + <event name="OnAux2Down"></event> + <event name="OnAux2Up"></event> + <event name="OnChar"></event> + <event name="OnCharHook"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnGridCellChange"></event> + <event name="OnGridCellLeftClick">OnGridCellClick</event> + <event name="OnGridCellLeftDClick"></event> + <event name="OnGridCellRightClick"></event> + <event name="OnGridCellRightDClick"></event> + <event name="OnGridCmdCellChange"></event> + <event name="OnGridCmdCellLeftClick"></event> + <event name="OnGridCmdCellLeftDClick"></event> + <event name="OnGridCmdCellRightClick"></event> + <event name="OnGridCmdCellRightDClick"></event> + <event name="OnGridCmdColSize"></event> + <event name="OnGridCmdEditorCreated"></event> + <event name="OnGridCmdEditorHidden"></event> + <event name="OnGridCmdEditorShown"></event> + <event name="OnGridCmdLabelLeftClick"></event> + <event name="OnGridCmdLabelLeftDClick"></event> + <event name="OnGridCmdLabelRightClick"></event> + <event name="OnGridCmdLabelRightDClick"></event> + <event name="OnGridCmdRangeSelect"></event> + <event name="OnGridCmdRowSize"></event> + <event name="OnGridCmdSelectCell"></event> + <event name="OnGridColSize"></event> + <event name="OnGridEditorCreated"></event> + <event name="OnGridEditorHidden"></event> + <event name="OnGridEditorShown"></event> + <event name="OnGridLabelLeftClick"></event> + <event name="OnGridLabelLeftDClick"></event> + <event name="OnGridLabelRightClick"></event> + <event name="OnGridLabelRightDClick"></event> + <event name="OnGridRangeSelect"></event> + <event name="OnGridRowSize"></event> + <event name="OnGridSelectCell"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">0</property> + <property name="flag">wxALIGN_RIGHT|wxALIGN_TOP</property> + <property name="proportion">0</property> + <object class="wxBoxSizer" expanded="1"> + <property name="minimum_size"></property> + <property name="name">bButtonsSizer</property> + <property name="orient">wxVERTICAL</property> + <property name="permission">none</property> + <object class="sizeritem" expanded="0"> + <property name="border">5</property> + <property name="flag">wxALIGN_TOP|wxALL</property> + <property name="proportion">0</property> + <object class="wxBitmapButton" expanded="0"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="bitmap"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="current"></property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="disabled"></property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="focus"></property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Move Up</property> + <property name="margins"></property> + <property name="markup">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">32,32</property> + <property name="moveable">1</property> + <property name="name">m_moveUpButton</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="position"></property> + <property name="pressed"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnAux1DClick"></event> + <event name="OnAux1Down"></event> + <event name="OnAux1Up"></event> + <event name="OnAux2DClick"></event> + <event name="OnAux2Down"></event> + <event name="OnAux2Up"></event> + <event name="OnButtonClick">OnMoveUpButtonClick</event> + <event name="OnChar"></event> + <event name="OnCharHook"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxBitmapButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="bitmap"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="current"></property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="disabled"></property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="focus"></property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Move Down</property> + <property name="margins"></property> + <property name="markup">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">32,32</property> + <property name="moveable">1</property> + <property name="name">m_moveDownButton</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="position"></property> + <property name="pressed"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnAux1DClick"></event> + <event name="OnAux1Down"></event> + <event name="OnAux1Up"></event> + <event name="OnAux2DClick"></event> + <event name="OnAux2Down"></event> + <event name="OnAux2Up"></event> + <event name="OnButtonClick">OnMoveDownButtonClick</event> + <event name="OnChar"></event> + <event name="OnCharHook"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + <object class="sizeritem" expanded="1"> + <property name="border">5</property> + <property name="flag">wxALL</property> + <property name="proportion">0</property> + <object class="wxBitmapButton" expanded="1"> + <property name="BottomDockable">1</property> + <property name="LeftDockable">1</property> + <property name="RightDockable">1</property> + <property name="TopDockable">1</property> + <property name="aui_layer"></property> + <property name="aui_name"></property> + <property name="aui_position"></property> + <property name="aui_row"></property> + <property name="best_size"></property> + <property name="bg"></property> + <property name="bitmap"></property> + <property name="caption"></property> + <property name="caption_visible">1</property> + <property name="center_pane">0</property> + <property name="close_button">1</property> + <property name="context_help"></property> + <property name="context_menu">1</property> + <property name="current"></property> + <property name="default">0</property> + <property name="default_pane">0</property> + <property name="disabled"></property> + <property name="dock">Dock</property> + <property name="dock_fixed">0</property> + <property name="docking">Left</property> + <property name="enabled">1</property> + <property name="fg"></property> + <property name="floatable">1</property> + <property name="focus"></property> + <property name="font"></property> + <property name="gripper">0</property> + <property name="hidden">0</property> + <property name="id">wxID_ANY</property> + <property name="label">Reload Plugins</property> + <property name="margins"></property> + <property name="markup">0</property> + <property name="max_size"></property> + <property name="maximize_button">0</property> + <property name="maximum_size"></property> + <property name="min_size"></property> + <property name="minimize_button">0</property> + <property name="minimum_size">32,32</property> + <property name="moveable">1</property> + <property name="name">m_reloadButton</property> + <property name="pane_border">1</property> + <property name="pane_position"></property> + <property name="pane_size"></property> + <property name="permission">protected</property> + <property name="pin_button">1</property> + <property name="pos"></property> + <property name="position"></property> + <property name="pressed"></property> + <property name="resize">Resizable</property> + <property name="show">1</property> + <property name="size"></property> + <property name="style"></property> + <property name="subclass">; forward_declare</property> + <property name="toolbar_pane">0</property> + <property name="tooltip"></property> + <property name="validator_data_type"></property> + <property name="validator_style">wxFILTER_NONE</property> + <property name="validator_type">wxDefaultValidator</property> + <property name="validator_variable"></property> + <property name="window_extra_style"></property> + <property name="window_name"></property> + <property name="window_style"></property> + <event name="OnAux1DClick"></event> + <event name="OnAux1Down"></event> + <event name="OnAux1Up"></event> + <event name="OnAux2DClick"></event> + <event name="OnAux2Down"></event> + <event name="OnAux2Up"></event> + <event name="OnButtonClick">OnReloadButtonClick</event> + <event name="OnChar"></event> + <event name="OnCharHook"></event> + <event name="OnEnterWindow"></event> + <event name="OnEraseBackground"></event> + <event name="OnKeyDown"></event> + <event name="OnKeyUp"></event> + <event name="OnKillFocus"></event> + <event name="OnLeaveWindow"></event> + <event name="OnLeftDClick"></event> + <event name="OnLeftDown"></event> + <event name="OnLeftUp"></event> + <event name="OnMiddleDClick"></event> + <event name="OnMiddleDown"></event> + <event name="OnMiddleUp"></event> + <event name="OnMotion"></event> + <event name="OnMouseEvents"></event> + <event name="OnMouseWheel"></event> + <event name="OnPaint"></event> + <event name="OnRightDClick"></event> + <event name="OnRightDown"></event> + <event name="OnRightUp"></event> + <event name="OnSetFocus"></event> + <event name="OnSize"></event> + <event name="OnUpdateUI"></event> + </object> + </object> + </object> + </object> + </object> + </object> + </object> +</wxFormBuilder_Project> diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h new file mode 100644 index 0000000000..8766d0c95e --- /dev/null +++ b/pcbnew/dialogs/panel_pcbnew_action_plugins_base.h @@ -0,0 +1,58 @@ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Jul 11 2018) +// http://www.wxformbuilder.org/ +// +// PLEASE DO *NOT* EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__ +#define __PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__ + +#include <wx/artprov.h> +#include <wx/xrc/xmlres.h> +class WX_GRID; + +#include <wx/colour.h> +#include <wx/settings.h> +#include <wx/string.h> +#include <wx/font.h> +#include <wx/grid.h> +#include <wx/gdicmn.h> +#include <wx/sizer.h> +#include <wx/bmpbuttn.h> +#include <wx/bitmap.h> +#include <wx/image.h> +#include <wx/icon.h> +#include <wx/button.h> +#include <wx/panel.h> + +/////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +/// Class PANEL_PCBNEW_ACTION_PLUGINS_BASE +/////////////////////////////////////////////////////////////////////////////// +class PANEL_PCBNEW_ACTION_PLUGINS_BASE : public wxPanel +{ + private: + + protected: + WX_GRID* m_grid; + wxBitmapButton* m_moveUpButton; + wxBitmapButton* m_moveDownButton; + wxBitmapButton* m_reloadButton; + + // Virtual event handlers, overide them in your derived class + virtual void OnGridCellClick( wxGridEvent& event ) { event.Skip(); } + virtual void OnMoveUpButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnMoveDownButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnReloadButtonClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + 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 ); + ~PANEL_PCBNEW_ACTION_PLUGINS_BASE(); + +}; + +#endif //__PANEL_PCBNEW_ACTION_PLUGINS_BASE_H__ diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index e8bbb886d2..5c4a8d5eb5 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -1243,6 +1243,8 @@ void PCB_EDIT_FRAME::PythonPluginsReload() // Action plugins can be modified, therefore the plugins menu // must be updated: RebuildActionPluginMenus(); + // Recreate top toolbar to add action plugin buttons + ReCreateHToolbar(); #endif #endif } diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index 4179353573..4788841580 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -25,13 +25,14 @@ #define WXPCB_STRUCT_H_ #include <unordered_map> +#include <map> #include "pcb_base_edit_frame.h" #include "config_params.h" #include "undo_redo_container.h" #include "zones.h" - /* Forward declarations of classes. */ +class ACTION_PLUGIN; class PCB_SCREEN; class BOARD; class BOARD_COMMIT; @@ -117,16 +118,36 @@ protected: #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) /** * Function RebuildActionPluginMenus - * Fill action menu with all registred action plugins + * Fill action menu with all registered action plugins */ void RebuildActionPluginMenus(); /** - * Function OnActionPlugin + * Function AddActionPluginTools + * Append action plugin buttons to main toolbar + */ + void AddActionPluginTools(); + + /** + * Function RunActionPlugin + * Executes action plugin's Run() method and updates undo buffer + * @param aActionPlugin action plugin + */ + void RunActionPlugin( ACTION_PLUGIN* aActionPlugin ); + + /** + * Function OnActionPluginMenu * Launched by the menu when an action is called * @param aEvent sent by wx */ - void OnActionPlugin( wxCommandEvent& aEvent); + void OnActionPluginMenu( wxCommandEvent& aEvent); + + /** + * Function OnActionPluginButton + * Launched by the button when an action is called + * @param aEvent sent by wx + */ + void OnActionPluginButton( wxCommandEvent& aEvent ); /** * Function OnActionPluginRefresh @@ -379,6 +400,36 @@ public: // Configurations: void Process_Config( wxCommandEvent& event ); +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + + /** + * Function SetActionPluginSettings + * Set a set of plugins that have visible buttons on toolbar + * Plugins are identified by their module path + */ + void SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginsWithButtons ); + + /** + * Function GetActionPluginSettings + * Get a set of plugins that have visible buttons on toolbar + */ + std::vector< std::pair<wxString, wxString> > GetActionPluginSettings(); + + /** + * Function GetActionPluginButtonVisible + * Returns true if button visibility action plugin setting was set to true + * or it is unset and plugin defaults to true. + */ + bool GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault ); + + /** + * Function GetOrderedActionPlugins + * Returns ordered list of plugins in sequence in which they should appear on toolbar or in settings + */ + std::vector<ACTION_PLUGIN*> GetOrderedActionPlugins(); + +#endif + /** * Function GetProjectFileParameters * returns a project file parameter list for Pcbnew. diff --git a/pcbnew/pcb_general_settings.cpp b/pcbnew/pcb_general_settings.cpp index a8c70cd0aa..96c525ad3a 100644 --- a/pcbnew/pcb_general_settings.cpp +++ b/pcbnew/pcb_general_settings.cpp @@ -22,6 +22,7 @@ */ #include <pcb_general_settings.h> +#include <wx/tokenzr.h> PCB_GENERAL_SETTINGS::PCB_GENERAL_SETTINGS( FRAME_T aFrameType ) : m_frameType( aFrameType ), m_colorsSettings( aFrameType ) @@ -54,6 +55,32 @@ PCB_GENERAL_SETTINGS::PCB_GENERAL_SETTINGS( FRAME_T aFrameType ) void PCB_GENERAL_SETTINGS::Load( wxConfigBase* aCfg ) { m_colorsSettings.Load( aCfg ); + +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + + m_pluginSettings.clear(); + + wxString pluginSettings = aCfg->Read( "ActionPluginButtons" ); + + wxStringTokenizer pluginSettingsTokenizer = wxStringTokenizer( pluginSettings, ";" ); + + while( pluginSettingsTokenizer.HasMoreTokens() ) + { + wxString plugin = pluginSettingsTokenizer.GetNextToken(); + wxStringTokenizer pluginTokenizer = wxStringTokenizer( plugin, "=" ); + + if( pluginTokenizer.CountTokens() != 2 ) + { + // Bad config + continue; + } + + plugin = pluginTokenizer.GetNextToken(); + m_pluginSettings.push_back( std::make_pair( plugin, pluginTokenizer.GetNextToken() ) ); + } + +#endif + SETTINGS::Load( aCfg ); } @@ -61,6 +88,24 @@ void PCB_GENERAL_SETTINGS::Load( wxConfigBase* aCfg ) void PCB_GENERAL_SETTINGS::Save( wxConfigBase* aCfg ) { m_colorsSettings.Save( aCfg ); + +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + + wxString pluginSettings; + + for( auto const& entry : m_pluginSettings ) + { + if( !pluginSettings.IsEmpty() ) + { + pluginSettings = pluginSettings + wxT( ";" ); + } + pluginSettings = pluginSettings + entry.first + wxT( "=" ) + entry.second; + } + + aCfg->Write( "ActionPluginButtons" , pluginSettings ); + +#endif + SETTINGS::Save( aCfg ); } diff --git a/pcbnew/pcb_general_settings.h b/pcbnew/pcb_general_settings.h index bc8f953690..fbcbe90ef1 100644 --- a/pcbnew/pcb_general_settings.h +++ b/pcbnew/pcb_general_settings.h @@ -25,6 +25,7 @@ #define __PCBNEW_GENERAL_SETTINGS_H #include <colors_design_settings.h> +#include <vector> class wxConfigBase; class wxString; @@ -65,6 +66,10 @@ public: MAGNETIC_PAD_OPTION_VALUES m_magneticPads = CAPTURE_CURSOR_IN_TRACK_TOOL; MAGNETIC_PAD_OPTION_VALUES m_magneticTracks = CAPTURE_CURSOR_IN_TRACK_TOOL; +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + std::vector< std::pair<wxString, wxString> > m_pluginSettings; // Settings for action plugins +#endif + protected: const FRAME_T m_frameType; COLORS_DESIGN_SETTINGS m_colorsSettings; diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index ae164fd4cc..b6025a526d 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -45,6 +45,7 @@ #include <panel_hotkeys_editor.h> #include <panel_pcbnew_settings.h> #include <panel_pcbnew_display_options.h> +#include <panel_pcbnew_action_plugins.h> #include <fp_lib_table.h> #include <worksheet_shape_builder.h> #include <class_board.h> @@ -97,6 +98,9 @@ void PCB_EDIT_FRAME::InstallPreferences( PAGED_DIALOG* aParent ) book->AddPage( new PANEL_PCBNEW_SETTINGS( this, aParent ), _( "Pcbnew" ) ); book->AddSubPage( new PANEL_PCBNEW_DISPLAY_OPTIONS( this, aParent ), _( "Display Options" ) ); +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + book->AddSubPage( new PANEL_PCBNEW_ACTION_PLUGINS( this, aParent ), _( "Action Plugins" ) ); +#endif } diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp index 4fb232ea8f..0de652664f 100644 --- a/pcbnew/swig/pcbnew_action_plugins.cpp +++ b/pcbnew/swig/pcbnew_action_plugins.cpp @@ -140,6 +140,32 @@ wxString PYTHON_ACTION_PLUGIN::GetDescription() } +bool PYTHON_ACTION_PLUGIN::GetShowToolbarButton() +{ + PyLOCK lock; + + PyObject* result = CallMethod( "GetShowToolbarButton"); + + return PyObject_IsTrue(result); +} + + +wxString PYTHON_ACTION_PLUGIN::GetIconFileName() +{ + PyLOCK lock; + + return CallRetStrMethod( "GetIconFileName" ); +} + + +wxString PYTHON_ACTION_PLUGIN::GetPluginPath() +{ + PyLOCK lock; + + return CallRetStrMethod( "GetPluginPath" ); +} + + void PYTHON_ACTION_PLUGIN::Run() { PyLOCK lock; @@ -164,217 +190,226 @@ void PYTHON_ACTION_PLUGINS::register_action( PyObject* aPyAction ) void PYTHON_ACTION_PLUGINS::deregister_action( PyObject* aPyAction ) { - // deregister also destroyes the previously created "PYTHON_ACTION_PLUGIN object" + // deregister also destroys the previously created "PYTHON_ACTION_PLUGIN object" ACTION_PLUGINS::deregister_object( (void*) aPyAction ); } #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) -void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent ) +void PCB_EDIT_FRAME::OnActionPluginMenu( wxCommandEvent& aEvent ) { - int id = aEvent.GetId(); + ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByMenu( aEvent.GetId() ); - ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByMenu( id ); + if( actionPlugin ) + RunActionPlugin( actionPlugin ); +} - if( actionPlugin ) +void PCB_EDIT_FRAME::OnActionPluginButton( wxCommandEvent& aEvent ) +{ + ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByButton( aEvent.GetId() ); + + if( actionPlugin ) + RunActionPlugin( actionPlugin ); +} + +void PCB_EDIT_FRAME::RunActionPlugin( ACTION_PLUGIN* aActionPlugin ) +{ + PICKED_ITEMS_LIST itemsList; + BOARD* currentPcb = GetBoard(); + bool fromEmpty = false; + + itemsList.m_Status = UR_CHANGED; + + OnModify(); + + // Append tracks: + for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) { - PICKED_ITEMS_LIST itemsList; - BOARD* currentPcb = GetBoard(); - bool fromEmpty = false; + ITEM_PICKER picker( item, UR_CHANGED ); + itemsList.PushItem( picker ); + } - itemsList.m_Status = UR_CHANGED; + // Append modules: + for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) + { + ITEM_PICKER picker( item, UR_CHANGED ); + itemsList.PushItem( picker ); + } - OnModify(); + // Append drawings + for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) + { + ITEM_PICKER picker( item, UR_CHANGED ); + itemsList.PushItem( picker ); + } - // Append tracks: - for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) + // Append zones outlines + for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) + { + ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea( + ii ), UR_CHANGED ); + itemsList.PushItem( picker ); + } + + // Append zones segm: + for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) + { + ITEM_PICKER picker( item, UR_CHANGED ); + itemsList.PushItem( picker ); + } + + if( itemsList.GetCount() > 0 ) + SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) ); + else + fromEmpty = true; + + itemsList.ClearItemsList(); + + // Execute plugin itself... + ACTION_PLUGINS::SetActionRunning( true ); + aActionPlugin->Run(); + ACTION_PLUGINS::SetActionRunning( false ); + + currentPcb->m_Status_Pcb = 0; + + // Get back the undo buffer to fix some modifications + PICKED_ITEMS_LIST* oldBuffer = NULL; + + if( fromEmpty ) + { + oldBuffer = new PICKED_ITEMS_LIST(); + oldBuffer->m_Status = UR_NEW; + } + else + { + oldBuffer = GetScreen()->PopCommandFromUndoList(); + wxASSERT( oldBuffer ); + } + + // Try do discover what was modified + + PICKED_ITEMS_LIST deletedItemsList; + + // Found deleted modules + for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ ) + { + BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i ); + ITEM_PICKER picker( item, UR_DELETED ); + + wxASSERT( item ); + + switch( item->Type() ) { - ITEM_PICKER picker( item, UR_CHANGED ); - itemsList.PushItem( picker ); + case PCB_NETINFO_T: + case PCB_MARKER_T: + case PCB_MODULE_T: + case PCB_TRACE_T: + case PCB_VIA_T: + case PCB_LINE_T: + case PCB_TEXT_T: + case PCB_DIMENSION_T: + case PCB_TARGET_T: + case PCB_ZONE_T: + + // If item has a list it's mean that the element is on the board + if( item->GetList() == NULL ) + { + deletedItemsList.PushItem( picker ); + } + + break; + + case PCB_ZONE_AREA_T: + { + bool zoneFound = false; + + for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) + zoneFound |= currentPcb->GetArea( ii ) == item; + + if( !zoneFound ) + { + deletedItemsList.PushItem( picker ); + } + + break; } - // Append modules: - for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) - { - ITEM_PICKER picker( item, UR_CHANGED ); - itemsList.PushItem( picker ); + default: + wxString msg; + msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: " + "BOARD_ITEM type (%d) not handled" ), + item->Type() ); + wxFAIL_MSG( msg ); + break; } + } - // Append drawings - for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) + // Mark deleted elements in undolist + for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ ) + { + oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) ); + } + + // Find new modules + for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) + { + if( !oldBuffer->ContainsItem( item ) ) { - ITEM_PICKER picker( item, UR_CHANGED ); - itemsList.PushItem( picker ); + ITEM_PICKER picker( item, UR_NEW ); + oldBuffer->PushItem( picker ); } + } - // Append zones outlines - for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) + for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) + { + if( !oldBuffer->ContainsItem( item ) ) + { + ITEM_PICKER picker( item, UR_NEW ); + oldBuffer->PushItem( picker ); + } + } + + for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) + { + if( !oldBuffer->ContainsItem( item ) ) + { + ITEM_PICKER picker( item, UR_NEW ); + oldBuffer->PushItem( picker ); + } + } + + for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) + { + if( !oldBuffer->ContainsItem( item ) ) + { + ITEM_PICKER picker( item, UR_NEW ); + oldBuffer->PushItem( picker ); + } + } + + for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) + { + if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) ) { ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea( - ii ), UR_CHANGED ); - itemsList.PushItem( picker ); - } - - // Append zones segm: - for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) - { - ITEM_PICKER picker( item, UR_CHANGED ); - itemsList.PushItem( picker ); - } - - if( itemsList.GetCount() > 0 ) - SaveCopyInUndoList( itemsList, UR_CHANGED, wxPoint( 0.0, 0.0 ) ); - else - fromEmpty = true; - - itemsList.ClearItemsList(); - - // Execute plugin himself... - ACTION_PLUGINS::SetActionRunning( true ); - actionPlugin->Run(); - ACTION_PLUGINS::SetActionRunning( false ); - - currentPcb->m_Status_Pcb = 0; - - // Get back the undo buffer to fix some modifications - PICKED_ITEMS_LIST* oldBuffer = NULL; - - if( fromEmpty ) - { - oldBuffer = new PICKED_ITEMS_LIST(); - oldBuffer->m_Status = UR_NEW; - } - else - { - oldBuffer = GetScreen()->PopCommandFromUndoList(); - wxASSERT( oldBuffer ); - } - - // Try do discover what was modified - - PICKED_ITEMS_LIST deletedItemsList; - - // Found deleted modules - for( unsigned int i = 0; i < oldBuffer->GetCount(); i++ ) - { - BOARD_ITEM* item = (BOARD_ITEM*) oldBuffer->GetPickedItem( i ); - ITEM_PICKER picker( item, UR_DELETED ); - - wxASSERT( item ); - - switch( item->Type() ) - { - case PCB_NETINFO_T: - case PCB_MARKER_T: - case PCB_MODULE_T: - case PCB_TRACE_T: - case PCB_VIA_T: - case PCB_LINE_T: - case PCB_TEXT_T: - case PCB_DIMENSION_T: - case PCB_TARGET_T: - case PCB_ZONE_T: - - // If item has a list it's mean that the element is on the board - if( item->GetList() == NULL ) - { - deletedItemsList.PushItem( picker ); - } - - break; - - case PCB_ZONE_AREA_T: - { - bool zoneFound = false; - - for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) - zoneFound |= currentPcb->GetArea( ii ) == item; - - if( !zoneFound ) - { - deletedItemsList.PushItem( picker ); - } - - break; - } - - default: - wxString msg; - msg.Printf( _( "(PCB_EDIT_FRAME::OnActionPlugin) needs work: " - "BOARD_ITEM type (%d) not handled" ), - item->Type() ); - wxFAIL_MSG( msg ); - break; - } - } - - // Mark deleted elements in undolist - for( unsigned int i = 0; i < deletedItemsList.GetCount(); i++ ) - { - oldBuffer->PushItem( deletedItemsList.GetItemWrapper( i ) ); - } - - // Find new modules - for( BOARD_ITEM* item = currentPcb->m_Modules; item != NULL; item = item->Next() ) - { - if( !oldBuffer->ContainsItem( item ) ) - { - ITEM_PICKER picker( item, UR_NEW ); - oldBuffer->PushItem( picker ); - } - } - - for( BOARD_ITEM* item = currentPcb->m_Track; item != NULL; item = item->Next() ) - { - if( !oldBuffer->ContainsItem( item ) ) - { - ITEM_PICKER picker( item, UR_NEW ); - oldBuffer->PushItem( picker ); - } - } - - for( BOARD_ITEM* item = currentPcb->m_Drawings; item != NULL; item = item->Next() ) - { - if( !oldBuffer->ContainsItem( item ) ) - { - ITEM_PICKER picker( item, UR_NEW ); - oldBuffer->PushItem( picker ); - } - } - - for( BOARD_ITEM* item = currentPcb->m_SegZoneDeprecated; item != NULL; item = item->Next() ) - { - if( !oldBuffer->ContainsItem( item ) ) - { - ITEM_PICKER picker( item, UR_NEW ); - oldBuffer->PushItem( picker ); - } - } - - for( int ii = 0; ii < currentPcb->GetAreaCount(); ii++ ) - { - if( !oldBuffer->ContainsItem( (EDA_ITEM*) currentPcb->GetArea( ii ) ) ) - { - ITEM_PICKER picker( (EDA_ITEM*) currentPcb->GetArea( - ii ), UR_NEW ); - oldBuffer->PushItem( picker ); - } + ii ), UR_NEW ); + oldBuffer->PushItem( picker ); } + } - GetScreen()->PushCommandToUndoList( oldBuffer ); + GetScreen()->PushCommandToUndoList( oldBuffer ); - if( IsGalCanvasActive() ) - { - UseGalCanvas( GetGalCanvas() ); - } - else - { - UpdateUserInterface(); - GetScreen()->SetModify(); - Refresh(); - } + if( IsGalCanvasActive() ) + { + UseGalCanvas( GetGalCanvas() ); + } + else + { + UpdateUserInterface(); + GetScreen()->SetModify(); + Refresh(); } } @@ -409,30 +444,39 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus() // Remove menus which are not usable for our current plugin list Disconnect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & - PCB_EDIT_FRAME::OnActionPlugin ); + PCB_EDIT_FRAME::OnActionPluginMenu ); actionMenu->Delete( item ); } for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ ) { wxMenuItem* item; + ACTION_PLUGIN* ap = ACTION_PLUGINS::GetAction( ii ); + const wxBitmap& bitmap = ap->iconBitmap.IsOk() ? ap->iconBitmap : KiBitmap( hammer_xpm ); if( ii < (int) available_menus.size() ) { item = available_menus[ii]; - item->SetItemLabel( ACTION_PLUGINS::GetAction( ii )->GetName() ); - item->SetHelp( ACTION_PLUGINS::GetAction( ii )->GetDescription() ); + item->SetItemLabel( ap->GetName() ); + item->SetHelp( ap->GetDescription() ); + + // On windows we need to set "unchecked" bitmap +#if defined(__WXMSW__) + item->SetBitmap( bitmap, false ); +#else + item->SetBitmap( bitmap ); +#endif } else { item = AddMenuItem( actionMenu, wxID_ANY, - ACTION_PLUGINS::GetAction( ii )->GetName(), - ACTION_PLUGINS::GetAction( ii )->GetDescription(), - KiBitmap( hammer_xpm ) ); + ap->GetName(), + ap->GetDescription(), + bitmap ); Connect( item->GetId(), wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & - PCB_EDIT_FRAME::OnActionPlugin ); + PCB_EDIT_FRAME::OnActionPluginMenu ); } ACTION_PLUGINS::SetActionMenu( ii, item->GetId() ); @@ -440,4 +484,104 @@ void PCB_EDIT_FRAME::RebuildActionPluginMenus() } +void PCB_EDIT_FRAME::AddActionPluginTools() +{ + bool need_separator = true; + const auto& orderedPlugins = GetOrderedActionPlugins(); + + for( const auto& ap : orderedPlugins ) + { + if( GetActionPluginButtonVisible( ap->GetPluginPath(), ap->GetShowToolbarButton() ) ) + { + + if ( need_separator ) + { + KiScaledSeparator( m_mainToolBar, this ); + need_separator = false; + } + + // Add button + wxBitmap bitmap; + + if ( ap->iconBitmap.IsOk() ) + bitmap = KiScaledBitmap( ap->iconBitmap, this ); + else + bitmap = KiScaledBitmap( hammer_xpm, this ); + + wxAuiToolBarItem* button = m_mainToolBar->AddTool( + wxID_ANY, wxEmptyString, bitmap, ap->GetName() ); + + Connect( button->GetId(), wxEVT_COMMAND_MENU_SELECTED, + (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) & + PCB_EDIT_FRAME::OnActionPluginButton ); + + // Link action plugin to button + ACTION_PLUGINS::SetActionButton( ap, button->GetId() ); + } + } +} + + +void PCB_EDIT_FRAME::SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginSettings ) +{ + m_configSettings.m_pluginSettings = aPluginSettings; + ReCreateHToolbar(); +} + + +std::vector< std::pair<wxString, wxString> > PCB_EDIT_FRAME::GetActionPluginSettings() +{ + return m_configSettings.m_pluginSettings; +} + + +std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins() +{ + std::vector<ACTION_PLUGIN*> orderedPlugins; + const auto& pluginSettings = GetActionPluginSettings(); + + // First add plugins that have entries in settings + for( size_t ii = 0; ii < pluginSettings.size(); ii++ ) + { + for( int jj = 0; jj < ACTION_PLUGINS::GetActionsCount(); jj++ ) + { + if( ACTION_PLUGINS::GetAction( jj )->GetPluginPath() == pluginSettings[ii].first ) + orderedPlugins.push_back( ACTION_PLUGINS::GetAction( jj ) ); + } + } + + // Now append new plugins that have not been configured yet + for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ ) + { + bool found = false; + + for( size_t jj = 0; jj < orderedPlugins.size(); jj++ ) + { + if( ACTION_PLUGINS::GetAction( ii ) == orderedPlugins[jj] ) + found = true; + } + + if ( !found ) + orderedPlugins.push_back( ACTION_PLUGINS::GetAction( ii ) ); + } + + return orderedPlugins; +} + + +bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault ) +{ + auto& settings = m_configSettings.m_pluginSettings; + + for(const auto& entry : settings ) + { + if (entry.first == aPluginPath ) + return entry.second == wxT( "Visible" ); + } + + // Plugin is not in settings, return default. + return aPluginDefault; +} + + #endif diff --git a/pcbnew/swig/pcbnew_action_plugins.h b/pcbnew/swig/pcbnew_action_plugins.h index 08dfa14e61..a1d6d9ff0e 100644 --- a/pcbnew/swig/pcbnew_action_plugins.h +++ b/pcbnew/swig/pcbnew_action_plugins.h @@ -47,6 +47,9 @@ public: wxString GetCategoryName() override; wxString GetName() override; wxString GetDescription() override; + bool GetShowToolbarButton() override; + wxString GetIconFileName() override; + wxString GetPluginPath() override; void Run() override; void* GetObject() override; }; diff --git a/pcbnew/tool_pcb_editor.cpp b/pcbnew/tool_pcb_editor.cpp index 66b6223570..b5c64c3a10 100644 --- a/pcbnew/tool_pcb_editor.cpp +++ b/pcbnew/tool_pcb_editor.cpp @@ -321,6 +321,10 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddTool( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, wxEmptyString, KiScaledBitmap( py_script_xpm, this ), _( "Show/Hide the Python Scripting console" ), wxITEM_CHECK ); + +#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU) + AddActionPluginTools(); +#endif } #endif diff --git a/scripting/kicadplugins.i b/scripting/kicadplugins.i index 8c1781d50e..ebd8db2c86 100644 --- a/scripting/kicadplugins.i +++ b/scripting/kicadplugins.i @@ -260,7 +260,7 @@ def LoadPlugins(bundlepath=None): if module == '__init__.py' or module[-3:] != '.py': continue - LoadOnePlugin(plugins_dir, module); + LoadOnePlugin(plugins_dir, module) class KiCadPlugin: @@ -268,6 +268,9 @@ class KiCadPlugin: pass def register(self): + import inspect + import os + if isinstance(self,FilePlugin): pass # register to file plugins in C++ @@ -276,6 +279,14 @@ class KiCadPlugin: return if isinstance(self,ActionPlugin): + """ + Get path to .py or .pyc that has definition of plugin class. + If path is binary but source also exists, assume definition is in source. + """ + self.__plugin_path = inspect.getfile(self.__class__) + if self.__plugin_path.endswith('.pyc') and os.path.isfile(self.__plugin_path[:-1]): + self.__plugin_path = self.__plugin_path[:-1] + self.__plugin_path = self.__plugin_path + '/' + self.__class__.__name__ PYTHON_ACTION_PLUGINS.register_action(self) return @@ -295,6 +306,9 @@ class KiCadPlugin: return + def GetPluginPath( self ): + return self.__plugin_path + class FilePlugin(KiCadPlugin): def __init__(self): @@ -633,6 +647,8 @@ class FootprintWizardPlugin(KiCadPlugin, object): class ActionPlugin(KiCadPlugin, object): def __init__( self ): KiCadPlugin.__init__( self ) + self.icon_file_name = "" + self.show_toolbar_button = False self.defaults() def defaults( self ): @@ -649,6 +665,12 @@ class ActionPlugin(KiCadPlugin, object): def GetDescription( self ): return self.description + def GetShowToolbarButton( self ): + return self.show_toolbar_button + + def GetIconFileName( self ): + return self.icon_file_name + def Run(self): return