From d62fde0d793477762cb9b6deb691c17b965049c7 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Mon, 24 Feb 2020 19:55:07 +0100 Subject: [PATCH] Pcbnew, Fix issue when trying to create a drawing (line,circle,arc,polygon): Display a error message if no free graphic layer is enabled, to switch from a copper layer. Fixes #3916 https://gitlab.com/kicad/code/kicad/issues/3916 --- pcbnew/tools/drawing_tool.cpp | 75 +++++++++++++++++++++++++++++++++-- pcbnew/tools/drawing_tool.h | 4 ++ 2 files changed, 75 insertions(+), 4 deletions(-) diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp index fb356c84d5..9e2bc5851a 100644 --- a/pcbnew/tools/drawing_tool.cpp +++ b/pcbnew/tools/drawing_tool.cpp @@ -220,6 +220,12 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent ) if( m_editModules && !m_frame->GetModel() ) return 0; + if( !hasDrawingLayerAvailable() ) + { + wxMessageBox( _("No enabled graphic layer to create a graphic item") ); + return 0; + } + BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); DRAWSEGMENT* line = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; @@ -264,6 +270,12 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent ) if( m_editModules && !m_frame->GetModel() ) return 0; + if( !hasDrawingLayerAvailable() ) + { + wxMessageBox( _("No enabled graphic layer to create a graphic item") ); + return 0; + } + BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; BOARD_COMMIT commit( m_frame ); @@ -301,6 +313,12 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent ) if( m_editModules && !m_frame->GetModel() ) return 0; + if( !hasDrawingLayerAvailable() ) + { + wxMessageBox( _("No enabled graphic layer to create a graphic item") ); + return 0; + } + BOARD_ITEM_CONTAINER* parent = m_frame->GetModel(); DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT; BOARD_COMMIT commit( m_frame ); @@ -508,6 +526,12 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent ) if( m_editModules && !m_frame->GetModel() ) return 0; + if( !hasDrawingLayerAvailable() ) + { + wxMessageBox( _("No enabled graphic layer to create a graphic item") ); + return 0; + } + DIMENSION* dimension = NULL; BOARD_COMMIT commit( m_frame ); GRID_HELPER grid( m_frame ); @@ -1372,7 +1396,15 @@ int DRAWING_TOOL::drawZone( bool aKeepout, ZONE_MODE aMode ) params.m_sourceZone = sourceZone; if( aMode == ZONE_MODE::GRAPHIC_POLYGON ) + { + if( !hasDrawingLayerAvailable() ) + { + wxMessageBox( _("No enabled graphic layer to create a graphic item") ); + return 0; + } + params.m_layer = getDrawingLayer(); + } else if( aMode == ZONE_MODE::SIMILAR ) params.m_layer = sourceZone->GetLayer(); else @@ -1828,19 +1860,40 @@ int DRAWING_TOOL::getSegmentWidth( PCB_LAYER_ID aLayer ) const return m_board->GetDesignSettings().GetLineThickness( aLayer ); } +// A list of suitable layers for drawings, used in getDrawingLayer() to +// automatically switch from a copper layer to a not specialized drawing layer +// and hasDrawingLayerAvailable() +static LSET suitableDrawLayers( 4, F_SilkS, B_SilkS, Dwgs_User, Cmts_User ); PCB_LAYER_ID DRAWING_TOOL::getDrawingLayer() const { + // at least one of suitableDrawLayers is expected enabled PCB_LAYER_ID layer = m_frame->GetActiveLayer(); + LSET enabledLayer = m_frame->GetBoard()->GetEnabledLayers(); if( IsCopperLayer( layer ) ) { + wxASSERT( hasDrawingLayerAvailable() ); + + layer = Dwgs_User; + + if( !enabledLayer[Dwgs_User] ) + layer = Cmts_User; + if( layer == F_Cu ) - layer = F_SilkS; + { + if( enabledLayer[F_SilkS] ) + layer = F_SilkS; + else if( enabledLayer[B_SilkS] ) + layer = B_SilkS; + } else if( layer == B_Cu ) - layer = B_SilkS; - else - layer = Dwgs_User; + { + if( enabledLayer[B_SilkS] ) + layer = B_SilkS; + else if( enabledLayer[F_SilkS] ) + layer = F_SilkS; + } m_frame->SetActiveLayer( layer ); } @@ -1849,4 +1902,18 @@ PCB_LAYER_ID DRAWING_TOOL::getDrawingLayer() const } +bool DRAWING_TOOL::hasDrawingLayerAvailable() const +{ + PCB_LAYER_ID layer = m_frame->GetActiveLayer(); + + if( !IsCopperLayer( layer ) ) // Already on a non copper layer + return true; + + // If the active layer is a copper layer, see if a graphic layer is available + LSET enabledLayer = m_frame->GetBoard()->GetEnabledLayers(); + + return ( enabledLayer & suitableDrawLayers ).any(); +} + + const unsigned int DRAWING_TOOL::WIDTH_STEP = Millimeter2iu( 0.1 ); diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h index a016916727..2e9e7f8210 100644 --- a/pcbnew/tools/drawing_tool.h +++ b/pcbnew/tools/drawing_tool.h @@ -258,6 +258,10 @@ private: ///> Selects a non-copper layer for drawing PCB_LAYER_ID getDrawingLayer() const; + ///> Test for a enabled non-copper layer suitable for drawing + ///> @return true if at lesat one is enabled + bool hasDrawingLayerAvailable() const; + KIGFX::VIEW* m_view; KIGFX::VIEW_CONTROLS* m_controls; BOARD* m_board;