diff --git a/common/page_layout/ws_draw_item.cpp b/common/page_layout/ws_draw_item.cpp index 7d4259842c..d6b12c3fd1 100644 --- a/common/page_layout/ws_draw_item.cpp +++ b/common/page_layout/ws_draw_item.cpp @@ -65,6 +65,12 @@ void WS_DRAW_ITEM_BASE::ViewGetLayers( int aLayers[], int& aCount ) const WS_DATA_ITEM* dataItem = GetPeer(); + if( !dataItem ) // No peer: this item is like a WS_DRAW_ITEM_PAGE + { + aLayers[0] = LAYER_WORKSHEET; + return; + } + if( dataItem->GetPage1Option() == FIRST_PAGE_ONLY ) aLayers[0] = LAYER_WORKSHEET_PAGE1; else if( dataItem->GetPage1Option() == SUBSEQUENT_PAGES ) @@ -94,6 +100,10 @@ void WS_DRAW_ITEM_BASE::GetMsgPanelInfo( EDA_UNITS_T aUnits, MSG_PANEL_ITEMS& aL wxString msg; WS_DATA_ITEM* dataItem = GetPeer(); + if( dataItem == nullptr ) // Is only a pure graphic item used in page layout editor + // to handle the page limits + return; + switch( dataItem->GetType() ) { case WS_DATA_ITEM::WS_SEGMENT: @@ -405,7 +415,24 @@ wxString WS_DRAW_ITEM_BITMAP::GetSelectMenuText( EDA_UNITS_T aUnits ) const } -// ============================ LIST ============================== +wxString WS_DRAW_ITEM_PAGE::GetSelectMenuText( EDA_UNITS_T aUnits ) const +{ + wxString txt( "Page limits" ); + return txt; +} + + +const EDA_RECT WS_DRAW_ITEM_PAGE::GetBoundingBox() const +{ + EDA_RECT dummy; + + // We want this graphic item alway visible. So gives the max size to the + // bounding box to avoid any clamping: + dummy.SetSize( wxSize( std::numeric_limits::max(), std::numeric_limits::max() ) ); + return dummy; +} + +// ====================== WS_DRAW_ITEM_LIST ============================== void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList( const PAGE_INFO& aPageInfo, const TITLE_BLOCK& aTitleBlock ) diff --git a/common/page_layout/ws_painter.cpp b/common/page_layout/ws_painter.cpp index 7e952a0308..f5c9251e60 100644 --- a/common/page_layout/ws_painter.cpp +++ b/common/page_layout/ws_painter.cpp @@ -247,6 +247,7 @@ bool KIGFX::WS_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer ) case WSG_RECT_T: draw( (WS_DRAW_ITEM_RECT*) item, aLayer ); break; case WSG_TEXT_T: draw( (WS_DRAW_ITEM_TEXT*) item, aLayer ); break; case WSG_BITMAP_T: draw( (WS_DRAW_ITEM_BITMAP*) item, aLayer ); break; + case WSG_PAGE_T: draw( (WS_DRAW_ITEM_PAGE*) item, aLayer ); break; default: return false; } @@ -334,6 +335,34 @@ void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_BITMAP* aItem, int aLayer ) con } +void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_PAGE* aItem, int aLayer ) const +{ + VECTOR2D origin = VECTOR2D( 0.0, 0.0 ); + VECTOR2D end = VECTOR2D( aItem->GetPageSize().x, + aItem->GetPageSize().y ); + + m_gal->SetIsStroke( true ); + + // Use a gray color for the border color + m_gal->SetStrokeColor( COLOR4D( 0.4, 0.4, 0.4, 1.0 ) ); + m_gal->SetIsFill( false ); + m_gal->DrawRectangle( origin, end ); + + // Draw the corner marker + double marker_size = aItem->GetMarkerSize(); + + m_gal->SetStrokeColor( COLOR4D( 0.4, 0.4, 1.0, 1.0 ) ); + VECTOR2D pos = VECTOR2D( aItem->GetMarkerPos().x, aItem->GetMarkerPos().y ); + + // Draw a cirle and a X + m_gal->DrawCircle( pos, marker_size ); + m_gal->DrawLine( VECTOR2D( pos.x - marker_size, pos.y - marker_size), + VECTOR2D( pos.x + marker_size, pos.y + marker_size ) ); + m_gal->DrawLine( VECTOR2D( pos.x + marker_size, pos.y - marker_size), + VECTOR2D( pos.x - marker_size, pos.y + marker_size ) ); +} + + void KIGFX::WS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor ) const { VECTOR2D origin = VECTOR2D( 0.0, 0.0 ); diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index 98ce4a91aa..4478d25474 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -180,6 +180,7 @@ enum KICAD_T WSG_POLY_T, WSG_TEXT_T, WSG_BITMAP_T, + WSG_PAGE_T, // serialized layout used in undo/redo commands WS_PROXY_UNDO_ITEM_T, // serialized layout used in undo/redo commands diff --git a/include/ws_draw_item.h b/include/ws_draw_item.h index 7a5579a417..b6c082295c 100644 --- a/include/ws_draw_item.h +++ b/include/ws_draw_item.h @@ -222,6 +222,49 @@ public: #endif }; + +// This class draws a rectangle with thick segment showing the page limits +// and a marker showing the coord origin +class WS_DRAW_ITEM_PAGE : public WS_DRAW_ITEM_BASE +{ + wxPoint m_markerPos; // position of the marker + wxSize m_pageSize; // full size of the page + int m_penWidth; + double m_markerSize; + +public: + WS_DRAW_ITEM_PAGE( int aPenWidth, double aMarkerSize ) : + WS_DRAW_ITEM_BASE( nullptr, 0, WSG_PAGE_T ) + { + m_penWidth = aPenWidth; + m_markerSize = aMarkerSize; + } + + virtual wxString GetClass() const override { return wxT( "WS_DRAW_ITEM_PAGE" ); } + + // Accessors: + int GetPenWidth() const { return m_penWidth; } + void SetPageSize( wxSize aSize ) { m_pageSize = aSize; } + wxSize GetPageSize() const { return m_pageSize; } + const wxPoint& GetMarkerPos() const { return m_markerPos; } + void SetMarkerPos( wxPoint aPos ) { m_markerPos = aPos; } + double GetMarkerSize() const { return m_markerSize; } + + const wxPoint GetPosition() const override { return wxPoint( 0, 0 ); } + void SetPosition( wxPoint aPos ) override { /* do nothing */ } + + void PrintWsItem( wxDC* aDC, const wxPoint& aOffset, COLOR4D aColor ) override { /* do nothing */ } + + const EDA_RECT GetBoundingBox() const override; + bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override { return false; } + + wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override; + +#if defined(DEBUG) + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } +#endif +}; + // This class draws a graphic text. // it is derived from an EDA_TEXT, so it handle all caracteristics // of this graphic text (justification, rotation ... ) diff --git a/include/ws_painter.h b/include/ws_painter.h index 919311d3b0..369c599a00 100644 --- a/include/ws_painter.h +++ b/include/ws_painter.h @@ -119,6 +119,7 @@ private: void draw( const WS_DRAW_ITEM_POLYGON* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_TEXT* aItem, int aLayer ) const; void draw( const WS_DRAW_ITEM_BITMAP* aItem, int aLayer ) const; + void draw( const WS_DRAW_ITEM_PAGE* aItem, int aLayer ) const; private: WS_RENDER_SETTINGS m_renderSettings; diff --git a/pagelayout_editor/pl_draw_panel_gal.cpp b/pagelayout_editor/pl_draw_panel_gal.cpp index d7439d0657..7a3231dc8c 100644 --- a/pagelayout_editor/pl_draw_panel_gal.cpp +++ b/pagelayout_editor/pl_draw_panel_gal.cpp @@ -88,6 +88,13 @@ void PL_DRAW_PANEL_GAL::DisplayWorksheet() for( WS_DATA_ITEM* dataItem : model.GetItems() ) dataItem->SyncDrawItems( nullptr, m_view ); + // Build and add a WS_DRAW_ITEM_PAGE to show the page limits and the corner position + // of the selected corner for coord origin of new items + const int penWidth = 0; // This value is to use the default thickness line + constexpr double markerSize = Millimeter2iu( 5 ); + WS_DRAW_ITEM_PAGE* pageDrawing = new WS_DRAW_ITEM_PAGE( penWidth, markerSize ); + m_view->Add( pageDrawing ); + selTool->RebuildSelection(); // Gives a reasonable boundary to the view area @@ -100,6 +107,9 @@ void PL_DRAW_PANEL_GAL::DisplayWorksheet() VECTOR2D( size_x * 1.5, size_y * 1.5) ); m_view->SetBoundary( boundary ); + pageDrawing->SetPageSize( m_edaFrame->GetPageSizeIU() ); + wxPoint originCoord = static_cast( m_edaFrame )->ReturnCoordOriginCorner(); + pageDrawing->SetMarkerPos( originCoord ); } diff --git a/pagelayout_editor/pl_draw_panel_gal.h b/pagelayout_editor/pl_draw_panel_gal.h index 80deea8c3d..d2e4935f88 100644 --- a/pagelayout_editor/pl_draw_panel_gal.h +++ b/pagelayout_editor/pl_draw_panel_gal.h @@ -37,8 +37,12 @@ public: ///> @copydoc EDA_DRAW_PANEL_GAL::GetMsgPanelInfo() void GetMsgPanelInfo( EDA_UNITS_T aUnits, std::vector& aList ) override; + /** + * Build and update the list of WS_DRAW_ITEM_xxx showing the frame layout + */ void DisplayWorksheet(); + ///> @copydoc EDA_DRAW_PANEL_GAL::SwitchBackend bool SwitchBackend( GAL_TYPE aGalType ) override; ///> @copydoc EDA_DRAW_PANEL_GAL::SetTopLayer diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp index 0abb785751..17a4abd9bf 100644 --- a/pagelayout_editor/pl_editor_frame.cpp +++ b/pagelayout_editor/pl_editor_frame.cpp @@ -179,6 +179,9 @@ PL_EDITOR_FRAME::PL_EDITOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) : m_auimgr.Update(); + wxPoint originCoord = ReturnCoordOriginCorner(); + SetGridOrigin( originCoord ); + // Initialize the current page layout WS_DATA_MODEL& pglayout = WS_DATA_MODEL::GetTheInstance(); #if 0 //start with empty layout @@ -301,6 +304,7 @@ void PL_EDITOR_FRAME::OnSelectCoordOriginCorner( wxCommandEvent& event ) { m_originSelectChoice = m_originSelectBox->GetSelection(); UpdateStatusBar(); // Update grid origin + static_cast( GetGalCanvas() )->DisplayWorksheet(); GetGalCanvas()->Refresh(); } @@ -481,6 +485,46 @@ void PL_EDITOR_FRAME::SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) } +wxPoint PL_EDITOR_FRAME::ReturnCoordOriginCorner() const +{ + // calculate the position (in page, in iu) of the corner used as coordinate origin + // coordinate origin can be the paper Top Left corner, or each of 4 page corners + wxPoint originCoord; + + // To avoid duplicate code, we use a dummy segment starting at 0,0 in relative coord + WS_DATA_ITEM dummy( WS_DATA_ITEM::WS_SEGMENT ); + + switch( m_originSelectChoice ) + { + default: + case 0: // Origin = paper Left Top corner + break; + + case 1: // Origin = page Right Bottom corner + dummy.SetStart( 0, 0, RB_CORNER ); + originCoord = dummy.GetStartPosUi(); + break; + + case 2: // Origin = page Left Bottom corner + dummy.SetStart( 0, 0, LB_CORNER ); + originCoord = dummy.GetStartPosUi(); + break; + + case 3: // Origin = page Right Top corner + dummy.SetStart( 0, 0, RT_CORNER ); + originCoord = dummy.GetStartPosUi(); + break; + + case 4: // Origin = page Left Top corner + dummy.SetStart( 0, 0, LT_CORNER ); + originCoord = dummy.GetStartPosUi(); + break; + } + + return originCoord; +} + + void PL_EDITOR_FRAME::UpdateStatusBar() { PL_EDITOR_SCREEN* screen = (PL_EDITOR_SCREEN*) GetScreen(); @@ -492,12 +536,13 @@ void PL_EDITOR_FRAME::UpdateStatusBar() EDA_DRAW_FRAME::UpdateStatusBar(); // coordinate origin can be the paper Top Left corner, or each of 4 page corners - wxPoint originCoord; + wxPoint originCoord = ReturnCoordOriginCorner(); + SetGridOrigin( originCoord ); + + // We need the orientation of axis (sign of coordinates) int Xsign = 1; int Ysign = 1; - WS_DATA_ITEM dummy( WS_DATA_ITEM::WS_SEGMENT ); - switch( m_originSelectChoice ) { default: @@ -507,30 +552,20 @@ void PL_EDITOR_FRAME::UpdateStatusBar() case 1: // Origin = page Right Bottom corner Xsign = -1; Ysign = -1; - dummy.SetStart( 0, 0, RB_CORNER ); - originCoord = dummy.GetStartPosUi(); break; case 2: // Origin = page Left Bottom corner Ysign = -1; - dummy.SetStart( 0, 0, LB_CORNER ); - originCoord = dummy.GetStartPosUi(); - break; + break; case 3: // Origin = page Right Top corner Xsign = -1; - dummy.SetStart( 0, 0, RT_CORNER ); - originCoord = dummy.GetStartPosUi(); break; case 4: // Origin = page Left Top corner - dummy.SetStart( 0, 0, LT_CORNER ); - originCoord = dummy.GetStartPosUi(); break; } - SetGridOrigin( originCoord ); - // Display absolute coordinates: wxPoint coord = GetCrossHairPosition() - originCoord; double dXpos = To_User_Unit( GetUserUnits(), coord.x*Xsign ); diff --git a/pagelayout_editor/pl_editor_frame.h b/pagelayout_editor/pl_editor_frame.h index f5a413d5e4..19c65021f4 100644 --- a/pagelayout_editor/pl_editor_frame.h +++ b/pagelayout_editor/pl_editor_frame.h @@ -126,11 +126,18 @@ public: { return m_grid_origin; } + void SetGridOrigin( const wxPoint& aPoint ) override { m_grid_origin = aPoint; } + /** + * calculate the position (in page, in iu) of the corner used as coordinate origin + * of items + */ + wxPoint ReturnCoordOriginCorner() const; + const TITLE_BLOCK& GetTitleBlock() const override; void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) override;