diff --git a/gerbview/clear_gbr_drawlayers.cpp b/gerbview/clear_gbr_drawlayers.cpp index c4456afb4b..bf4fe66805 100644 --- a/gerbview/clear_gbr_drawlayers.cpp +++ b/gerbview/clear_gbr_drawlayers.cpp @@ -83,7 +83,7 @@ void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query ) if( m_toolManager ) m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD ); - GetImagesList()->DeleteImage( layer ); + RemapLayers( GetImagesList()->RemoveImage( layer ) ); ReFillLayerWidget(); syncLayerBox(); diff --git a/gerbview/gerber_file_image_list.cpp b/gerbview/gerber_file_image_list.cpp index dde575ec58..2734133fc9 100644 --- a/gerbview/gerber_file_image_list.cpp +++ b/gerbview/gerber_file_image_list.cpp @@ -410,11 +410,8 @@ static bool sortZorder( const GERBER_FILE_IMAGE* const& ref, const GERBER_FILE_I } -std::unordered_map -GERBER_FILE_IMAGE_LIST::SortImagesByFunction( LayerSortFunction sortFunction ) +std::unordered_map GERBER_FILE_IMAGE_LIST::GetLayerRemap() { - std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortFunction ); - // The image order has changed. // Graphic layer numbering must be updated to match the widgets layer order @@ -436,6 +433,14 @@ GERBER_FILE_IMAGE_LIST::SortImagesByFunction( LayerSortFunction sortFunction ) } +std::unordered_map +GERBER_FILE_IMAGE_LIST::SortImagesByFunction( LayerSortFunction sortFunction ) +{ + std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortFunction ); + return GetLayerRemap(); +} + + std::unordered_map GERBER_FILE_IMAGE_LIST::SortImagesByFileExtension() { return SortImagesByFunction( sortFileExtension ); @@ -446,3 +451,29 @@ std::unordered_map GERBER_FILE_IMAGE_LIST::SortImagesByZOrder() { return SortImagesByFunction( sortZorder ); } + + +std::unordered_map GERBER_FILE_IMAGE_LIST::SwapImages( unsigned int layer1, + unsigned int layer2 ) +{ + if( ( layer1 < 0 || layer1 >= m_GERBER_List.size() ) + || ( layer2 < 0 || layer2 >= m_GERBER_List.size() ) ) + { + return std::unordered_map(); + } + + std::swap( m_GERBER_List[layer1], m_GERBER_List[layer2] ); + return GetLayerRemap(); +} + +std::unordered_map GERBER_FILE_IMAGE_LIST::RemoveImage( unsigned int layer ) +{ + if( layer < 0 || layer >= m_GERBER_List.size() ) + return std::unordered_map(); + + DeleteImage( layer ); + // Move deleted image to end of list, move all other images up + std::rotate( m_GERBER_List.begin() + layer, m_GERBER_List.begin() + layer + 1, + m_GERBER_List.end() ); + return GetLayerRemap(); +} diff --git a/gerbview/gerber_file_image_list.h b/gerbview/gerber_file_image_list.h index 2c8ec0a4dc..5d594ed4f8 100644 --- a/gerbview/gerber_file_image_list.h +++ b/gerbview/gerber_file_image_list.h @@ -171,6 +171,20 @@ public: */ std::unordered_map SortImagesByZOrder(); + /** + * Swap two images and their orders. + * + * @return a mapping of old to new layer index + */ + std::unordered_map SwapImages( unsigned int layer1, unsigned int layer2 ); + + /** + * Removes (and deletes) an image, rotating the removed image to the end. + * + * @return a mapping of old to new layer index + */ + std::unordered_map RemoveImage( unsigned int layer ); + /** * Get number of loaded images * @@ -179,6 +193,15 @@ public: unsigned GetLoadedImageCount(); private: + /** + * When the image order has changed, call this to get a mapping + * to pass to the frame's Remap() function to remap the widgets + * layer order. + * + * @return Map describing the remap. + */ + std::unordered_map GetLayerRemap(); + // the list of loaded images (1 image = 1 gerber file) std::vector m_GERBER_List; }; diff --git a/gerbview/widgets/gerbview_layer_widget.cpp b/gerbview/widgets/gerbview_layer_widget.cpp index 6b559c5da4..7031179cce 100644 --- a/gerbview/widgets/gerbview_layer_widget.cpp +++ b/gerbview/widgets/gerbview_layer_widget.cpp @@ -140,6 +140,16 @@ void GERBER_LAYER_WIDGET::AddRightClickMenuItems( wxMenu* aMenu ) AddMenuItem( aMenu, ID_SORT_GBR_LAYERS_FILE_EXT, _( "Sort Layers by File Extension" ), KiBitmap( BITMAPS::reload ) ); + + aMenu->AppendSeparator(); + + AddMenuItem( aMenu, ID_LAYER_MOVE_UP, _( "Move Current Layer Up" ), KiBitmap( BITMAPS::up ) ); + + AddMenuItem( aMenu, ID_LAYER_MOVE_DOWN, _( "Move Current Layer Down" ), + KiBitmap( BITMAPS::down ) ); + + AddMenuItem( aMenu, ID_LAYER_DELETE, _( "Clear Current Layer..." ), + KiBitmap( BITMAPS::delete_gerber ) ); } @@ -156,6 +166,7 @@ void GERBER_LAYER_WIDGET::onRightDownLayers( wxMouseEvent& event ) void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) { + int layer; int rowCount; int menuId = event.GetId(); bool visible = (menuId == ID_SHOW_ALL_LAYERS) ? true : false; @@ -179,7 +190,7 @@ void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) for( int row = 0; row < rowCount; ++row ) { wxCheckBox* cb = (wxCheckBox*) getLayerComp( row, COLUMN_COLOR_LYR_CB ); - int layer = getDecodedId( cb->GetId() ); + layer = getDecodedId( cb->GetId() ); bool loc_visible = visible; if( force_active_layer_visible && (layer == m_frame->GetActiveLayer() ) ) @@ -200,6 +211,31 @@ void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) case ID_SORT_GBR_LAYERS_FILE_EXT: m_frame->SortLayersByFileExtension(); break; + + case ID_LAYER_MOVE_UP: + layer = m_frame->GetActiveLayer(); + + if( layer > 0 ) + { + m_frame->RemapLayers( GetImagesList()->SwapImages( layer, layer - 1 ) ); + m_frame->SetActiveLayer( layer - 1 ); + } + break; + + case ID_LAYER_MOVE_DOWN: + layer = m_frame->GetActiveLayer(); + + if( layer < ( GetImagesList()->GetLoadedImageCount() - 1 ) ) + { + m_frame->RemapLayers( GetImagesList()->SwapImages( layer, layer + 1 ) ); + m_frame->SetActiveLayer( layer + 1 ); + } + break; + + case ID_LAYER_DELETE: + m_frame->Erase_Current_DrawLayer( false ); + + break; } } diff --git a/gerbview/widgets/gerbview_layer_widget.h b/gerbview/widgets/gerbview_layer_widget.h index a0355c4c57..5ed1472a19 100644 --- a/gerbview/widgets/gerbview_layer_widget.h +++ b/gerbview/widgets/gerbview_layer_widget.h @@ -97,7 +97,10 @@ protected: ID_ALWAYS_SHOW_NO_LAYERS_BUT_ACTIVE, ID_SORT_GBR_LAYERS_X2, ID_SORT_GBR_LAYERS_FILE_EXT, - ID_LAYER_MANAGER_END = ID_SORT_GBR_LAYERS_FILE_EXT, + ID_LAYER_MOVE_UP, + ID_LAYER_MOVE_DOWN, + ID_LAYER_DELETE, + ID_LAYER_MANAGER_END = ID_LAYER_DELETE, }; private: