From 09424db68fe2085ec66d7c86e61e9581911701f9 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 24 May 2019 11:11:18 +0100 Subject: [PATCH] Restore selection around undo/redo. --- common/page_layout/worksheet_dataitem.cpp | 94 +++++++++++++------ include/tool/selection.h | 2 +- pagelayout_editor/pl_draw_panel_gal.cpp | 8 +- pagelayout_editor/pl_editor_frame.cpp | 13 ++- pagelayout_editor/pl_editor_undo_redo.cpp | 86 +++++++++++++---- pagelayout_editor/tools/pl_selection_tool.cpp | 15 +++ pagelayout_editor/tools/pl_selection_tool.h | 6 ++ 7 files changed, 175 insertions(+), 49 deletions(-) diff --git a/common/page_layout/worksheet_dataitem.cpp b/common/page_layout/worksheet_dataitem.cpp index eba4fed699..bcbbd4aa6f 100644 --- a/common/page_layout/worksheet_dataitem.cpp +++ b/common/page_layout/worksheet_dataitem.cpp @@ -89,8 +89,14 @@ void WORKSHEET_DATAITEM::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGFX::VI if( pensize == 0 ) pensize = aCollector ? aCollector->GetDefaultPenSize() : 0; - for( WS_DRAW_ITEM_BASE* item : m_drawItems ) + std::map itemFlags; + WS_DRAW_ITEM_BASE* item = nullptr; + + for( int ii = 0; ii < m_drawItems.size(); ++ii ) { + item = m_drawItems[ ii ]; + itemFlags[ ii ] = item->GetFlags(); + if( aCollector ) aCollector->Remove( item ); @@ -108,29 +114,18 @@ void WORKSHEET_DATAITEM::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGFX::VI continue; if( m_type == WS_SEGMENT ) - { - auto line = new WS_DRAW_ITEM_LINE( this, GetStartPosUi( jj ), GetEndPosUi( jj ), - pensize ); - m_drawItems.push_back( line ); - - if( aCollector ) - aCollector->Append( line ); - - if( aView ) - aView->Add( line ); - } + item = new WS_DRAW_ITEM_LINE( this, GetStartPosUi( jj ), GetEndPosUi( jj ), pensize ); else if( m_type == WS_RECT ) - { - auto rect = new WS_DRAW_ITEM_RECT( this, GetStartPosUi( jj ), GetEndPosUi( jj ), - pensize ); - m_drawItems.push_back( rect ); + item = new WS_DRAW_ITEM_RECT( this, GetStartPosUi( jj ), GetEndPosUi( jj ), pensize ); - if( aCollector ) - aCollector->Append( rect ); + item->SetFlags( itemFlags[ jj ] ); + m_drawItems.push_back( item ); - if( aView ) - aView->Add( rect ); - } + if( aCollector ) + aCollector->Append( item ); + + if( aView ) + aView->Add( item ); } } @@ -406,8 +401,22 @@ WORKSHEET_DATAITEM_POLYPOLYGON::WORKSHEET_DATAITEM_POLYPOLYGON() : void WORKSHEET_DATAITEM_POLYPOLYGON::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGFX::VIEW* aView ) { - for( WS_DRAW_ITEM_BASE* item : m_drawItems ) + std::map itemFlags; + WS_DRAW_ITEM_BASE* item = nullptr; + + for( int ii = 0; ii < m_drawItems.size(); ++ii ) + { + item = m_drawItems[ ii ]; + itemFlags[ ii ] = item->GetFlags(); + + if( aCollector ) + aCollector->Remove( item ); + + if( aView ) + aView->Remove( item ); + delete item; + } m_drawItems.clear(); @@ -421,6 +430,7 @@ void WORKSHEET_DATAITEM_POLYPOLYGON::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollecto const bool fill = true; int pensize = GetPenSizeUi(); auto poly = new WS_DRAW_ITEM_POLYGON( this, GetStartPosUi( jj ), fill, pensize ); + item->SetFlags( itemFlags[ jj ] ); m_drawItems.push_back( poly ); if( aCollector ) @@ -552,8 +562,22 @@ void WORKSHEET_DATAITEM_TEXT::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGF if( m_Bold ) pensize = GetPenSizeForBold( std::min( textsize.x, textsize.y ) ); - for( WS_DRAW_ITEM_BASE* item : m_drawItems ) - delete item; + std::map itemFlags; + WS_DRAW_ITEM_TEXT* text = nullptr; + + for( int ii = 0; ii < m_drawItems.size(); ++ii ) + { + text = (WS_DRAW_ITEM_TEXT*) m_drawItems[ ii ]; + itemFlags[ ii ] = text->GetFlags(); + + if( aCollector ) + aCollector->Remove( text ); + + if( aView ) + aView->Remove( text ); + + delete text; + } m_drawItems.clear(); @@ -562,8 +586,9 @@ void WORKSHEET_DATAITEM_TEXT::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGF if( jj > 0 && !IsInsidePage( jj ) ) continue; - auto text = new WS_DRAW_ITEM_TEXT( this, m_FullText, GetStartPosUi( jj ), textsize, - pensize, m_Italic, m_Bold ); + text = new WS_DRAW_ITEM_TEXT( this, m_FullText, GetStartPosUi( jj ), textsize, pensize, + m_Italic, m_Bold ); + text->SetFlags( itemFlags[ jj ] ); m_drawItems.push_back( text ); if( aCollector ) @@ -682,8 +707,22 @@ void WORKSHEET_DATAITEM_TEXT::SetConstrainedTextSize() void WORKSHEET_DATAITEM_BITMAP::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KIGFX::VIEW* aView ) { - for( WS_DRAW_ITEM_BASE* item : m_drawItems ) + std::map itemFlags; + WS_DRAW_ITEM_BASE* item = nullptr; + + for( int ii = 0; ii < m_drawItems.size(); ++ii ) + { + item = m_drawItems[ ii ]; + itemFlags[ ii ] = item->GetFlags(); + + if( aCollector ) + aCollector->Remove( item ); + + if( aView ) + aView->Remove( item ); + delete item; + } m_drawItems.clear(); @@ -693,6 +732,7 @@ void WORKSHEET_DATAITEM_BITMAP::SyncDrawItems( WS_DRAW_ITEM_LIST* aCollector, KI continue; auto bitmap = new WS_DRAW_ITEM_BITMAP( this, GetStartPosUi( jj ) ); + item->SetFlags( itemFlags[ jj ] ); m_drawItems.push_back( bitmap ); if( aCollector ) diff --git a/include/tool/selection.h b/include/tool/selection.h index 9ab99e9d35..f2f0fa51b6 100644 --- a/include/tool/selection.h +++ b/include/tool/selection.h @@ -46,7 +46,7 @@ public: m_isHover = aOther.m_isHover; } - const SELECTION& operator= ( const SELECTION& aOther ) + SELECTION& operator= ( const SELECTION& aOther ) { m_items = aOther.m_items; m_isHover = aOther.m_isHover; diff --git a/pagelayout_editor/pl_draw_panel_gal.cpp b/pagelayout_editor/pl_draw_panel_gal.cpp index 6f6f2811cc..260fbd7d06 100644 --- a/pagelayout_editor/pl_draw_panel_gal.cpp +++ b/pagelayout_editor/pl_draw_panel_gal.cpp @@ -30,6 +30,8 @@ #include #include +#include + using namespace std::placeholders; @@ -64,13 +66,17 @@ void PL_DRAW_PANEL_GAL::GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vectorGetToolManager()->RunAction( PL_ACTIONS::clearSelection, true ); + PL_SELECTION_TOOL* selTool = m_edaFrame->GetToolManager()->GetTool(); + + selTool->GetSelection().Clear(); m_view->Clear(); WS_DRAW_ITEM_LIST::SetupDrawEnvironment( m_edaFrame->GetPageSettings() ); for( WORKSHEET_DATAITEM* dataItem : WORKSHEET_LAYOUT::GetTheInstance().GetItems() ) dataItem->SyncDrawItems( nullptr, m_view ); + + selTool->RebuildSelection(); } diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp index 7112a5eeb7..a088b7b9da 100644 --- a/pagelayout_editor/pl_editor_frame.cpp +++ b/pagelayout_editor/pl_editor_frame.cpp @@ -502,7 +502,18 @@ void PL_EDITOR_FRAME::RedrawActiveWindow( wxDC* aDC, bool aEraseBg ) void PL_EDITOR_FRAME::HardRedraw() { - static_cast( GetGalCanvas() )->DisplayWorksheet(); + PL_DRAW_PANEL_GAL* drawPanel = static_cast( GetGalCanvas() ); + + drawPanel->DisplayWorksheet(); + + PL_SELECTION_TOOL* selTool = m_toolManager->GetTool(); + SELECTION& selection = selTool->GetSelection(); + WORKSHEET_DATAITEM* item = nullptr; + + if( selection.GetSize() == 1 ) + item = static_cast( selection.Front() )->GetPeer(); + + m_propertiesPagelayout->CopyPrmsFromItemToPanel( item ); m_propertiesPagelayout->CopyPrmsFromGeneralToPanel(); m_canvas->Refresh(); } diff --git a/pagelayout_editor/pl_editor_undo_redo.cpp b/pagelayout_editor/pl_editor_undo_redo.cpp index b5ed9a7962..9873bfc454 100644 --- a/pagelayout_editor/pl_editor_undo_redo.cpp +++ b/pagelayout_editor/pl_editor_undo_redo.cpp @@ -26,9 +26,12 @@ #include #include #include +#include #include #include +#include +#include /* Note: the Undo/redo commands use a "brute" method: * the full page layout is converted to a S expression, and saved as string. @@ -43,11 +46,63 @@ // A helper class used in undo/redo commad: class PL_ITEM_LAYOUT: public EDA_ITEM { -public: - wxString m_Layout; + wxString m_serialization; + int m_selectedDataItem; + int m_selectedDrawItem; public: - PL_ITEM_LAYOUT() : EDA_ITEM( TYPE_PL_EDITOR_LAYOUT ) {} + PL_ITEM_LAYOUT() : + EDA_ITEM( TYPE_PL_EDITOR_LAYOUT ), + m_selectedDataItem( INT_MAX ), + m_selectedDrawItem( INT_MAX ) + { + WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); + pglayout.SaveInString( m_serialization ); + + for( int ii = 0; ii < pglayout.GetItems().size(); ++ii ) + { + WORKSHEET_DATAITEM* dataItem = pglayout.GetItem( ii ); + + for( int jj = 0; jj < dataItem->GetDrawItems().size(); ++jj ) + { + WS_DRAW_ITEM_BASE* drawItem = dataItem->GetDrawItems()[ jj ]; + + if( drawItem->IsSelected() ) + { + m_selectedDataItem = ii; + m_selectedDrawItem = jj; + break; + } + } + } + } + + void RestoreLayout( PL_EDITOR_FRAME* aFrame ) + { + WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); + PL_SELECTION_TOOL* selTool = aFrame->GetToolManager()->GetTool(); + KIGFX::VIEW* view = aFrame->GetGalCanvas()->GetView(); + + pglayout.SetPageLayout( TO_UTF8( m_serialization ) ); + + selTool->ClearSelection(); + view->Clear(); + + for( int ii = 0; ii < pglayout.GetItems().size(); ++ii ) + { + WORKSHEET_DATAITEM* dataItem = pglayout.GetItem( ii ); + + dataItem->SyncDrawItems( nullptr, view ); + + if( ii == m_selectedDataItem && m_selectedDrawItem < dataItem->GetDrawItems().size() ) + { + WS_DRAW_ITEM_BASE* drawItem = dataItem->GetDrawItems()[ m_selectedDrawItem ]; + drawItem->SetSelected(); + } + } + + selTool->RebuildSelection(); + } // Required to keep compiler happy on debug builds. #if defined(DEBUG) @@ -65,9 +120,7 @@ public: void PL_EDITOR_FRAME::SaveCopyInUndoList() { - PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; - WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); - pglayout.SaveInString( copyItem->m_Layout ); + PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; // constructor stores current layout PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); ITEM_PICKER wrapper( copyItem, UR_LIBEDIT ); @@ -89,9 +142,7 @@ void PL_EDITOR_FRAME::GetLayoutFromRedoList() return; PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; - WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); - pglayout.SaveInString( copyItem->m_Layout ); + PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; // constructor stores current layout ITEM_PICKER wrapper( copyItem, UR_LIBEDIT ); @@ -102,10 +153,10 @@ void PL_EDITOR_FRAME::GetLayoutFromRedoList() wrapper = lastcmd->PopItem(); copyItem = static_cast( wrapper.GetItem() ); - pglayout.SetPageLayout( TO_UTF8(copyItem->m_Layout) ); + copyItem->RestoreLayout( this ); delete copyItem; - HardRedraw(); + GetCanvas()->Refresh(); OnModify(); } @@ -120,9 +171,7 @@ void PL_EDITOR_FRAME::GetLayoutFromUndoList() return; PICKED_ITEMS_LIST* lastcmd = new PICKED_ITEMS_LIST(); - PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; - WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); - pglayout.SaveInString( copyItem->m_Layout ); + PL_ITEM_LAYOUT* copyItem = new PL_ITEM_LAYOUT; // constructor stores current layout ITEM_PICKER wrapper( copyItem, UR_LIBEDIT ); lastcmd->PushItem( wrapper ); @@ -132,10 +181,10 @@ void PL_EDITOR_FRAME::GetLayoutFromUndoList() wrapper = lastcmd->PopItem(); copyItem = static_cast( wrapper.GetItem() ); - pglayout.SetPageLayout( TO_UTF8(copyItem->m_Layout) ); + copyItem->RestoreLayout( this ); delete copyItem; - HardRedraw(); + GetCanvas()->Refresh(); OnModify(); } @@ -147,13 +196,12 @@ void PL_EDITOR_FRAME::RollbackFromUndo() if ( GetScreen()->GetUndoCommandCount() <= 0 ) return; - WORKSHEET_LAYOUT& pglayout = WORKSHEET_LAYOUT::GetTheInstance(); PICKED_ITEMS_LIST* lastcmd = GetScreen()->PopCommandFromUndoList(); ITEM_PICKER wrapper = lastcmd->PopItem(); PL_ITEM_LAYOUT* copyItem = static_cast( wrapper.GetItem() ); - pglayout.SetPageLayout( TO_UTF8(copyItem->m_Layout) ); + copyItem->RestoreLayout( this ); delete copyItem; - HardRedraw(); + GetCanvas()->Refresh(); } diff --git a/pagelayout_editor/tools/pl_selection_tool.cpp b/pagelayout_editor/tools/pl_selection_tool.cpp index 1543473c1a..7e4b50cfe7 100644 --- a/pagelayout_editor/tools/pl_selection_tool.cpp +++ b/pagelayout_editor/tools/pl_selection_tool.cpp @@ -504,6 +504,21 @@ int PL_SELECTION_TOOL::ClearSelection( const TOOL_EVENT& aEvent ) } +void PL_SELECTION_TOOL::RebuildSelection() +{ + m_selection.Clear(); + + for( WORKSHEET_DATAITEM* dataItem : WORKSHEET_LAYOUT::GetTheInstance().GetItems() ) + { + for( WS_DRAW_ITEM_BASE* item : dataItem->GetDrawItems() ) + { + if( item->IsSelected() ) + select( item ); + } + } +} + + int PL_SELECTION_TOOL::SelectionMenu( const TOOL_EVENT& aEvent ) { COLLECTOR* collector = aEvent.Parameter(); diff --git a/pagelayout_editor/tools/pl_selection_tool.h b/pagelayout_editor/tools/pl_selection_tool.h index da9715a881..7a51c16ceb 100644 --- a/pagelayout_editor/tools/pl_selection_tool.h +++ b/pagelayout_editor/tools/pl_selection_tool.h @@ -110,6 +110,12 @@ public: void ClearSelection(); + /** + * Rebuild the selection from the flags in the view items. Useful after a hard redraw + * or an undo or redo operation. + */ + void RebuildSelection(); + /** * Function SelectionMenu() * Shows a popup menu to trim the COLLECTOR passed as aEvent's parameter down to a single