diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index df08770f15..a482108abf 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -170,6 +170,7 @@ set( COMMON_WIDGET_SRCS widgets/widget_hotkey_list.cpp widgets/two_column_tree_list.cpp widgets/footprint_preview_panel.cpp + widgets/indicator_icon.cpp ) set( COMMON_PAGE_LAYOUT_SRCS diff --git a/common/widgets/indicator_icon.cpp b/common/widgets/indicator_icon.cpp new file mode 100644 index 0000000000..c365c390ca --- /dev/null +++ b/common/widgets/indicator_icon.cpp @@ -0,0 +1,191 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + + * Copyright (C) 2017 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + + +INDICATOR_ICON::INDICATOR_ICON( wxWindow* aParent, + ICON_PROVIDER& aIconProvider, + ICON_ID aInitialIcon, int aID ): + wxPanel( aParent, aID ), + m_iconProvider( aIconProvider ), + m_currentId( aInitialIcon ) +{ + auto sizer = new wxBoxSizer( wxHORIZONTAL ); + SetSizer( sizer ); + + const wxBitmap& initBitmap = m_iconProvider.GetIndicatorIcon( m_currentId ); + + m_bitmap = new wxStaticBitmap( this, aID, + initBitmap, wxDefaultPosition, + initBitmap.GetSize() ); + + sizer->Add( m_bitmap, 0, 0 ); + + auto evtSkipper = [this] ( wxEvent& aEvent ) { + wxPostEvent( this, aEvent ); + }; + + m_bitmap->Bind( wxEVT_LEFT_DOWN, evtSkipper ); +} + + +void INDICATOR_ICON::SetIndicatorState( ICON_ID aIconId ) +{ + if( aIconId == m_currentId ) + return; + + m_currentId = aIconId; + + m_bitmap->SetBitmap( m_iconProvider.GetIndicatorIcon( m_currentId ) ); +} + + +INDICATOR_ICON::ICON_ID INDICATOR_ICON::GetIndicatorState() const +{ + return m_currentId; +} + +// ==================================================================== +// Common icon providers + +/* XPM + * This bitmap is used for not selected layers + */ +static const char * clear_xpm[] = { +"10 14 1 1", +" c None", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; + +/* XPM + * This bitmap can be used to show a not selected layer + * with special property (mainly not selected layers not in use in GerbView) + */ +static const char * clear_alternate_xpm[] = { +"10 14 4 1", +" c None", +"X c #008080", +"o c GREEN", +"O c #00B080", +" ", +" ", +" ", +" ", +" X ", +" XXX ", +" XXXXX ", +" OOOOOOO ", +" ooooo ", +" ooo ", +" o ", +" ", +" ", +" "}; + + +/* XPM + * This bitmap is used for a normale selected layer + */ +static const char * rightarrow_xpm[] = { +"10 14 4 1", +" c None", +"X c #8080ff", +"o c BLUE", +"O c gray56", +" X ", +" XX ", +" XXX ", +" XXXX ", +" XXXXX ", +" XXXXXX ", +" XXXXXXX ", +" oooooooO", +" ooooooO ", +" oooooO ", +" ooooO ", +" oooO ", +" ooO ", +" oO "}; + +/* XPM + * This bitmap can be used to show the selected layer + * with special property (mainly a layer in use in GerbView) + */ +static const char * rightarrow_alternate_xpm[] = { +"10 14 5 1", +" c None", +". c #00B000", +"X c #8080ff", +"o c BLUE", +"O c gray56", +"..X ", +"..XX ", +"..XXX ", +"..XXXX ", +"..XXXXX ", +"..XXXXXX ", +"..XXXXXXX ", +"..oooooooO", +"..ooooooO ", +"..oooooO ", +"..ooooO ", +"..oooO ", +"..ooO ", +"..oO "}; + + + +static wxBitmap rightArrowBitmap( rightarrow_xpm ); +static wxBitmap rightArrowAlternateBitmap( rightarrow_alternate_xpm ); +static wxBitmap blankBitmap( clear_xpm ); +static wxBitmap blankAlternateBitmap( clear_alternate_xpm ); + + +ROW_ICON_PROVIDER::ROW_ICON_PROVIDER( bool aAlt ): + m_alt( aAlt ) +{} + + +const wxBitmap& ROW_ICON_PROVIDER::GetIndicatorIcon( + INDICATOR_ICON::ICON_ID aIconId ) const +{ + const bool on = ( aIconId == STATE::ON ); + + if( m_alt ) + return ( on ? rightArrowAlternateBitmap : blankAlternateBitmap ); + + return ( on ? rightArrowBitmap : blankBitmap ); +} diff --git a/gerbview/class_gerbview_layer_widget.cpp b/gerbview/class_gerbview_layer_widget.cpp index f6c6ca9bb4..1470417d44 100644 --- a/gerbview/class_gerbview_layer_widget.cpp +++ b/gerbview/class_gerbview_layer_widget.cpp @@ -314,24 +314,3 @@ bool GERBER_LAYER_WIDGET::useAlternateBitmap(int aRow) { return GetImagesList()->GetGbrImage( aRow ) != NULL; } - -/* - * Update the layer manager icons (layers only) - * Useful when loading a file or clearing a layer because they change - */ -void GERBER_LAYER_WIDGET::UpdateLayerIcons() -{ - int row_count = GetLayerRowCount(); - for( int row = 0; row < row_count ; row++ ) - { - wxStaticBitmap* bm = (wxStaticBitmap*) getLayerComp( row, COLUMN_ICON_ACTIVE ); - if( bm == NULL) - continue; - - if( row == m_CurrentRow ) - bm->SetBitmap( useAlternateBitmap(row) ? *m_RightArrowAlternateBitmap : - *m_RightArrowBitmap ); - else - bm->SetBitmap( useAlternateBitmap(row) ? *m_BlankAlternateBitmap : *m_BlankBitmap ); - } -} diff --git a/gerbview/class_gerbview_layer_widget.h b/gerbview/class_gerbview_layer_widget.h index 8e5c6ef18f..ad40533af6 100644 --- a/gerbview/class_gerbview_layer_widget.h +++ b/gerbview/class_gerbview_layer_widget.h @@ -125,13 +125,6 @@ public: bool OnLayerSelected(); // postprocess after an active layer selection // ensure active layer visible if // m_alwaysShowActiveCopperLayer is true; - - /** - * Function UpdateLayerIcons - * Update the layer manager icons (layers only) - * Useful when loading a file or clearing a layer because they change - */ - void UpdateLayerIcons(); }; #endif // _CLASS_GERBER_LAYER_WIDGET_H_ diff --git a/include/widgets/indicator_icon.h b/include/widgets/indicator_icon.h new file mode 100644 index 0000000000..fc3436ab9f --- /dev/null +++ b/include/widgets/indicator_icon.h @@ -0,0 +1,140 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 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 2 + * 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, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef ROW_INDICATOR__H_ +#define ROW_INDICATOR__H_ + +#include + +/** + * Class representing a row indicator icon for use in + * places like the layer widget + */ +class INDICATOR_ICON: public wxPanel +{ +public: + + /** + * An id that refers to a certain icon state. + * + * Exactly what that state might mean in terms of icons is up + * to the icon provider. + */ + using ICON_ID = int; + + /** + * A simple object that can provide fixed bitmaps for use as row + * indicators + */ + class ICON_PROVIDER + { + public: + + virtual ~ICON_PROVIDER() {}; + + /** + * Gets a reference to the row icon in the given mode + * + * @param aIconId the id of the icon to get (depends on the + * provider). + */ + virtual const wxBitmap& GetIndicatorIcon( ICON_ID aIconId ) const = 0; + }; + + /** + * Accessor for the default icon providers, which take + * true and false for IDs, meaining on/off. + * + * @param aAlternative false for blue arrow/blank, true for the + * green diamond + */ + static ICON_PROVIDER& GetDefaultRowIconProvider( bool aAlternative ); + + /** + * @param aParent the owning window + * @param aIconProvider the icon provider to get icons from + * @param aID the ID to use for the widgets - events will have + * this ID. + */ + INDICATOR_ICON( wxWindow* aParent, + ICON_PROVIDER& aIconProvider, + ICON_ID aInitialIcon, int aID ); + + /** + * Sets the row indiciator to the given state + * + * @param aIconId the icon ID to pass to the provider. + */ + void SetIndicatorState( ICON_ID aIconId ); + + + /** + * @return the current state of the indicator + */ + ICON_ID GetIndicatorState() const; + +private: + + ///> An class that delivers icons for the indictor (currently just + ///> uses a default implementation). + ICON_PROVIDER& m_iconProvider; + + ///> Handle on the bitmap widget + wxStaticBitmap* m_bitmap; + + ///> Is the icon currently "on" + ICON_ID m_currentId; +}; + + +/** + * Icon provider for the "standard" row indicators, for example in + * layer selection lists + */ +class ROW_ICON_PROVIDER: public INDICATOR_ICON::ICON_PROVIDER +{ +public: + + ///> State constants to select the right icons + enum STATE + { + OFF, ///> Row "off" or "deselected" + ON, ///> Row "on" or "selected" + }; + + /** + * @param aAlt false: normal icons (blue arrow/blank), true: + * alternative icons (blue arrow/green diamond) + */ + ROW_ICON_PROVIDER( bool aAlt ); + + ///> @copydoc INDICATOR_ICON::ICON_PROVIDER::GetIndicatorIcon() + const wxBitmap& GetIndicatorIcon( INDICATOR_ICON::ICON_ID aIconId ) const override; + +private: + bool m_alt; +}; + + + +#endif // ROW_INDICATOR__H_ diff --git a/pcbnew/layer_widget.cpp b/pcbnew/layer_widget.cpp index 617e0a14c4..a043930288 100644 --- a/pcbnew/layer_widget.cpp +++ b/pcbnew/layer_widget.cpp @@ -39,109 +39,18 @@ #include #include +#include #include const wxEventType LAYER_WIDGET::EVT_LAYER_COLOR_CHANGE = wxNewEventType(); -/* XPM - * This bitmap is used for not selected layers +/* + * Icon providers for the row icons */ -static const char * clear_xpm[] = { -"10 14 1 1", -" c None", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; - -/* XPM - * This bitmap can be used to show a not selected layer - * with special property (mainly not selected layers not in use in GerbView) - */ -static const char * clear_alternate_xpm[] = { -"10 14 4 1", -" c None", -"X c #008080", -"o c GREEN", -"O c #00B080", -" ", -" ", -" ", -" ", -" X ", -" XXX ", -" XXXXX ", -" OOOOOOO ", -" ooooo ", -" ooo ", -" o ", -" ", -" ", -" "}; - - -/* XPM - * This bitmap is used for a normale selected layer - */ -static const char * rightarrow_xpm[] = { -"10 14 4 1", -" c None", -"X c #8080ff", -"o c BLUE", -"O c gray56", -" X ", -" XX ", -" XXX ", -" XXXX ", -" XXXXX ", -" XXXXXX ", -" XXXXXXX ", -" oooooooO", -" ooooooO ", -" oooooO ", -" ooooO ", -" oooO ", -" ooO ", -" oO "}; - -/* XPM - * This bitmap can be used to show the selected layer - * with special property (mainly a layer in use in GerbView) - */ -static const char * rightarrow_alternate_xpm[] = { -"10 14 5 1", -" c None", -". c #00B000", -"X c #8080ff", -"o c BLUE", -"O c gray56", -"..X ", -"..XX ", -"..XXX ", -"..XXXX ", -"..XXXXX ", -"..XXXXXX ", -"..XXXXXXX ", -"..oooooooO", -"..ooooooO ", -"..oooooO ", -"..ooooO ", -"..oooO ", -"..ooO ", -"..oO "}; - +static ROW_ICON_PROVIDER defaultRowIcons( false ); +static ROW_ICON_PROVIDER alternativeRowIcons( true ); /** * Function shrinkFont @@ -336,11 +245,13 @@ void LAYER_WIDGET::insertLayerRow( int aRow, const ROW& aSpec ) int index = aRow * LYR_COLUMN_COUNT; const int flags = wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT; + auto& iconProvider = useAlternateBitmap(aRow) ? alternativeRowIcons : defaultRowIcons; + // column 0 - col = 0; - wxStaticBitmap* sbm = new wxStaticBitmap( m_LayerScrolledWindow, encodeId( col, aSpec.id ), - useAlternateBitmap(aRow) ? *m_BlankAlternateBitmap : *m_BlankBitmap, - wxDefaultPosition, m_BitmapSize ); + col = COLUMN_ICON_ACTIVE; + auto sbm = new INDICATOR_ICON( m_LayerScrolledWindow, iconProvider, + ROW_ICON_PROVIDER::STATE::OFF, + encodeId( col, aSpec.id ) ); sbm->Bind( wxEVT_LEFT_DOWN, &LAYER_WIDGET::OnLeftDownLayers, this ); m_LayersFlexGridSizer->wxSizer::Insert( index+col, sbm, 0, flags ); @@ -494,13 +405,6 @@ LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, int aPoint m_CurrentRow = -1; // hide the arrow initially - m_RightArrowBitmap = new wxBitmap( rightarrow_xpm ); - m_RightArrowAlternateBitmap = new wxBitmap( rightarrow_alternate_xpm ); - - m_BlankBitmap = new wxBitmap( clear_xpm ); // translucent - m_BlankAlternateBitmap = new wxBitmap( clear_alternate_xpm ); - m_BitmapSize = wxSize(m_BlankBitmap->GetWidth(), m_BlankBitmap->GetHeight()); - // trap the tab changes so that we can call passOnFocus(). m_notebook->Bind( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, &LAYER_WIDGET::OnTabChange, this ); @@ -510,10 +414,6 @@ LAYER_WIDGET::LAYER_WIDGET( wxWindow* aParent, wxWindow* aFocusOwner, int aPoint LAYER_WIDGET::~LAYER_WIDGET() { - delete m_BlankBitmap; - delete m_BlankAlternateBitmap; - delete m_RightArrowBitmap; - delete m_RightArrowAlternateBitmap; } @@ -616,14 +516,14 @@ void LAYER_WIDGET::SelectLayerRow( int aRow ) // enable the layer tab at index 0 m_notebook->SetSelection( 0 ); - wxStaticBitmap* oldbm = (wxStaticBitmap*) getLayerComp( m_CurrentRow, 0 ); - if( oldbm ) - oldbm->SetBitmap( useAlternateBitmap(m_CurrentRow) ? *m_BlankAlternateBitmap : *m_BlankBitmap ); + INDICATOR_ICON* oldIndicator = (INDICATOR_ICON*) getLayerComp( m_CurrentRow, 0 ); + if( oldIndicator ) + oldIndicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::OFF ); - wxStaticBitmap* newbm = (wxStaticBitmap*) getLayerComp( aRow, 0 ); - if( newbm ) + INDICATOR_ICON* newIndicator = (INDICATOR_ICON*) getLayerComp( aRow, 0 ); + if( newIndicator ) { - newbm->SetBitmap( useAlternateBitmap(aRow) ? *m_RightArrowAlternateBitmap : *m_RightArrowBitmap ); + newIndicator->SetIndicatorState( ROW_ICON_PROVIDER::STATE::ON ); // Make sure the desired layer row is visible. // It seems that as of 2.8.2, setting the focus does this. @@ -749,6 +649,24 @@ void LAYER_WIDGET::UpdateLayouts() FitInside(); } + +void LAYER_WIDGET::UpdateLayerIcons() +{ + int rowCount = GetLayerRowCount(); + for( int row = 0; row < rowCount ; row++ ) + { + INDICATOR_ICON* indicator = (INDICATOR_ICON*) getLayerComp( row, COLUMN_ICON_ACTIVE ); + + if( indicator ) + { + auto state = ( row == m_CurrentRow ) ? ROW_ICON_PROVIDER::STATE::ON + : ROW_ICON_PROVIDER::STATE::OFF; + indicator->SetIndicatorState( state ); + } + } +} + + #if defined(STAND_ALONE) #include diff --git a/pcbnew/layer_widget.h b/pcbnew/layer_widget.h index 635ee18a23..99949b59d9 100644 --- a/pcbnew/layer_widget.h +++ b/pcbnew/layer_widget.h @@ -113,11 +113,6 @@ protected: wxFlexGridSizer* m_RenderFlexGridSizer; wxWindow* m_FocusOwner; - wxBitmap* m_BlankBitmap; - wxBitmap* m_BlankAlternateBitmap; - wxBitmap* m_RightArrowBitmap; - wxBitmap* m_RightArrowAlternateBitmap; - wxSize m_BitmapSize; int m_CurrentRow; ///< selected row of layer list int m_PointSize; @@ -363,6 +358,14 @@ public: void UpdateLayouts(); + /** + * Function UpdateLayerIcons + * Update all layer manager icons (layers only) + * Useful when loading a file or clearing a layer because they change, + * and the indicator arrow icon needs to be updated + */ + void UpdateLayerIcons(); + /* did not help: void Freeze() {