Add context menu to GAL DRAWING_TOOL, including the zone menu
Includes a tiny class for scoped set-reset of a variable, which is used here to store the current drawing mode. Fixes: lp:1218629 * https://bugs.launchpad.net/kicad/+bug/1518629
This commit is contained in:
parent
6baf0edc08
commit
f1c5b9a9ae
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2016 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 __SCOPED_SET_RESET_H
|
||||
#define __SCOPED_SET_RESET_H
|
||||
|
||||
/**
|
||||
* @class SCOPED_SET_RESET
|
||||
* @brief RAII class that sets an value at construction and resets
|
||||
* it to the original value at destruction.
|
||||
*
|
||||
* @note There is no type deduction for template classes until C++17, \
|
||||
* so you can't do this:
|
||||
*
|
||||
* int target = 0;
|
||||
* SCOPED_SET_RESET( target, 42 );
|
||||
*
|
||||
* Instead, you can use a type alias, for example:
|
||||
*
|
||||
* using SCOPED_INT_SET_RESET = SCOPED_SET_RESET<int>;
|
||||
* int target = 0;
|
||||
* SCOPED_INT_SET_RESET( target , 42 );
|
||||
*/
|
||||
template <typename VAL_TYPE>
|
||||
class SCOPED_SET_RESET
|
||||
{
|
||||
public:
|
||||
|
||||
SCOPED_SET_RESET( VAL_TYPE& target,
|
||||
VAL_TYPE value ):
|
||||
m_target( target )
|
||||
{
|
||||
m_original = target;
|
||||
m_target = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ~SCOPED_SET_RESET
|
||||
*
|
||||
* Destruct the class, and return the target to its original
|
||||
* value.
|
||||
*/
|
||||
~SCOPED_SET_RESET()
|
||||
{
|
||||
m_target = m_original;
|
||||
}
|
||||
|
||||
private:
|
||||
VAL_TYPE m_original;
|
||||
VAL_TYPE& m_target;
|
||||
};
|
||||
|
||||
#endif // __SCOPED_SET_RESET_H
|
|
@ -51,11 +51,23 @@
|
|||
#include <class_zone.h>
|
||||
#include <class_module.h>
|
||||
|
||||
#include <scoped_set_reset.h>
|
||||
|
||||
#include "zoom_menu.h"
|
||||
#include "grid_menu.h"
|
||||
|
||||
#include <tools/selection_tool.h>
|
||||
|
||||
|
||||
using SCOPED_DRAW_MODE = SCOPED_SET_RESET<DRAWING_TOOL::MODE>;
|
||||
|
||||
DRAWING_TOOL::DRAWING_TOOL() :
|
||||
PCB_TOOL( "pcbnew.InteractiveDrawing" ), m_view( NULL ),
|
||||
m_controls( NULL ), m_board( NULL ), m_frame( NULL ), m_lineWidth( 1 )
|
||||
PCB_TOOL( "pcbnew.InteractiveDrawing" ),
|
||||
m_view( nullptr ), m_controls( nullptr ),
|
||||
m_board( nullptr ), m_frame( nullptr ), m_mode( MODE::NONE ),
|
||||
m_lineWidth( 1 ),
|
||||
m_menu( this ), m_contextMenu( nullptr ),
|
||||
m_gridMenu( nullptr), m_zoomMenu( nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -65,6 +77,27 @@ DRAWING_TOOL::~DRAWING_TOOL()
|
|||
}
|
||||
|
||||
|
||||
bool DRAWING_TOOL::Init()
|
||||
{
|
||||
// Drawing type-specific options will be added by the PCB control tool
|
||||
|
||||
m_menu.AddItem( COMMON_ACTIONS::zoomCenter, SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
m_menu.AddItem( COMMON_ACTIONS::zoomIn, SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
m_menu.AddItem( COMMON_ACTIONS::zoomOut , SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
m_menu.AddItem( COMMON_ACTIONS::zoomFitScreen , SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
|
||||
PCB_BASE_FRAME* frame = getEditFrame<PCB_BASE_FRAME>();
|
||||
|
||||
m_zoomMenu = new ZOOM_MENU( frame );
|
||||
m_menu.AddMenu( m_zoomMenu, _( "Zoom" ), false, SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
|
||||
m_gridMenu = new GRID_MENU( frame );
|
||||
m_menu.AddMenu( m_gridMenu, _( "Grid" ), false, SELECTION_CONDITIONS::ShowAlways, 1000 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DRAWING_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
// Init variables used by every drawing tool
|
||||
|
@ -75,6 +108,12 @@ void DRAWING_TOOL::Reset( RESET_REASON aReason )
|
|||
}
|
||||
|
||||
|
||||
DRAWING_TOOL::MODE DRAWING_TOOL::GetDrawingMode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
|
||||
int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD_ITEM_CONTAINER* parent = m_frame->GetModel();
|
||||
|
@ -82,6 +121,8 @@ int DRAWING_TOOL::DrawLine( const TOOL_EVENT& aEvent )
|
|||
boost::optional<VECTOR2D> startingPoint;
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::LINE );
|
||||
|
||||
m_frame->SetToolID( m_editModules ? ID_MODEDIT_LINE_TOOL : ID_PCB_ADD_LINE_BUTT,
|
||||
wxCURSOR_PENCIL, _( "Add graphic line" ) );
|
||||
|
||||
|
@ -113,6 +154,8 @@ int DRAWING_TOOL::DrawCircle( const TOOL_EVENT& aEvent )
|
|||
DRAWSEGMENT* circle = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::CIRCLE );
|
||||
|
||||
m_frame->SetToolID( m_editModules ? ID_MODEDIT_CIRCLE_TOOL : ID_PCB_CIRCLE_BUTT,
|
||||
wxCURSOR_PENCIL, _( "Add graphic circle" ) );
|
||||
|
||||
|
@ -139,6 +182,8 @@ int DRAWING_TOOL::DrawArc( const TOOL_EVENT& aEvent )
|
|||
DRAWSEGMENT* arc = m_editModules ? new EDGE_MODULE( (MODULE*) parent ) : new DRAWSEGMENT;
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ARC );
|
||||
|
||||
m_frame->SetToolID( m_editModules ? ID_MODEDIT_ARC_TOOL : ID_PCB_ARC_BUTT,
|
||||
wxCURSOR_PENCIL, _( "Add graphic arc" ) );
|
||||
|
||||
|
@ -174,6 +219,8 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
|
|||
m_controls->SetSnapping( true );
|
||||
// do not capture or auto-pan until we start placing some text
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
|
||||
|
||||
Activate();
|
||||
m_frame->SetToolID( m_editModules ? ID_MODEDIT_TEXT_TOOL : ID_PCB_ADD_TEXT_BUTT,
|
||||
wxCURSOR_PENCIL, _( "Add text" ) );
|
||||
|
@ -219,6 +266,11 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
else if ( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
if( !text )
|
||||
|
@ -336,6 +388,8 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
|
|||
m_controls->ShowCursor( true );
|
||||
m_controls->SetSnapping( true );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DIMENSION );
|
||||
|
||||
Activate();
|
||||
m_frame->SetToolID( ID_PCB_DIMENSION_BUTT, wxCURSOR_PENCIL, _( "Add dimension" ) );
|
||||
|
||||
|
@ -386,6 +440,11 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
else if ( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
switch( step )
|
||||
|
@ -502,6 +561,7 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
|
|||
|
||||
int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ZONE );
|
||||
m_frame->SetToolID( ID_PCB_ZONES_BUTT, wxCURSOR_PENCIL, _( "Add zones" ) );
|
||||
|
||||
return drawZone( false );
|
||||
|
@ -510,6 +570,7 @@ int DRAWING_TOOL::DrawZone( const TOOL_EVENT& aEvent )
|
|||
|
||||
int DRAWING_TOOL::DrawKeepout( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::KEEPOUT );
|
||||
m_frame->SetToolID( ID_PCB_KEEPOUT_AREA_BUTT, wxCURSOR_PENCIL, _( "Add keepout" ) );
|
||||
|
||||
return drawZone( true );
|
||||
|
@ -551,6 +612,8 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
|
|||
m_controls->ShowCursor( true );
|
||||
m_controls->SetSnapping( true );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
|
||||
|
||||
Activate();
|
||||
|
||||
// Main loop: keep receiving events
|
||||
|
@ -593,6 +656,11 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
else if ( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
// Place the drawing
|
||||
|
@ -690,6 +758,8 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
assert( m_editModules );
|
||||
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::ANCHOR );
|
||||
|
||||
Activate();
|
||||
m_frame->SetToolID( ID_MODEDIT_ANCHOR_TOOL, wxCURSOR_PENCIL,
|
||||
_( "Place the footprint anchor" ) );
|
||||
|
@ -718,7 +788,10 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
|
|||
// so deselect the active tool
|
||||
break;
|
||||
}
|
||||
|
||||
else if ( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
else if( evt->IsCancel() || evt->IsActivate() )
|
||||
break;
|
||||
}
|
||||
|
@ -734,6 +807,17 @@ int DRAWING_TOOL::SetAnchor( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
|
||||
void DRAWING_TOOL::showContextMenu()
|
||||
{
|
||||
// Dummy selection - the drawing tool doesn't depend on a selection
|
||||
SELECTION aSelection;
|
||||
m_contextMenu = m_menu.Generate( aSelection );
|
||||
|
||||
if( m_contextMenu->GetMenuItemCount() > 0 )
|
||||
SetContextMenu( m_contextMenu, CMENU_NOW );
|
||||
}
|
||||
|
||||
|
||||
bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
||||
boost::optional<VECTOR2D> aStartingPoint )
|
||||
{
|
||||
|
@ -812,7 +896,10 @@ bool DRAWING_TOOL::drawSegment( int aShape, DRAWSEGMENT*& aGraphic,
|
|||
aGraphic = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
|
||||
{
|
||||
if( !started )
|
||||
|
@ -958,7 +1045,10 @@ bool DRAWING_TOOL::drawArc( DRAWSEGMENT*& aGraphic )
|
|||
aGraphic = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
switch( step )
|
||||
|
@ -1168,7 +1258,10 @@ int DRAWING_TOOL::drawZone( bool aKeepout )
|
|||
if( evt->IsActivate() ) // now finish unconditionally
|
||||
break;
|
||||
}
|
||||
|
||||
else if( evt->IsClick( BUT_RIGHT ) )
|
||||
{
|
||||
showContextMenu();
|
||||
}
|
||||
else if( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT ) )
|
||||
{
|
||||
// Check if it is double click / closing line (so we have to finish the zone)
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <tools/pcb_tool.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#include "conditional_menu.h"
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class VIEW;
|
||||
|
@ -36,6 +38,9 @@ namespace KIGFX
|
|||
class BOARD;
|
||||
class PCB_BASE_EDIT_FRAME;
|
||||
class DRAWSEGMENT;
|
||||
class CONTEXT_MENU;
|
||||
class GRID_MENU;
|
||||
class ZOOM_MENU;
|
||||
|
||||
/**
|
||||
* Class DRAWING_TOOL
|
||||
|
@ -49,9 +54,41 @@ public:
|
|||
DRAWING_TOOL();
|
||||
~DRAWING_TOOL();
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Init()
|
||||
bool Init() override;
|
||||
|
||||
/// @copydoc TOOL_INTERACTIVE::Reset()
|
||||
void Reset( RESET_REASON aReason ) override;
|
||||
|
||||
///> Get the DRAWING_TOOL top-level context menu
|
||||
inline CONDITIONAL_MENU& GetMenu()
|
||||
{
|
||||
return m_menu;
|
||||
}
|
||||
|
||||
///> The possible drawing modes of DRAWING_TOOL
|
||||
enum class MODE
|
||||
{
|
||||
NONE,
|
||||
LINE,
|
||||
CIRCLE,
|
||||
ARC,
|
||||
TEXT,
|
||||
ANCHOR,
|
||||
DXF,
|
||||
DIMENSION,
|
||||
KEEPOUT,
|
||||
ZONE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Function GetDrawingMode
|
||||
*
|
||||
* Returns the current drawing mode of the DRAWING_TOOL, or
|
||||
* MODE::NONE if not currently in any drawing mode
|
||||
*/
|
||||
MODE GetDrawingMode() const;
|
||||
|
||||
/**
|
||||
* Function DrawLine()
|
||||
* Starts interactively drawing a line. After invoking the function it expects the user
|
||||
|
@ -125,6 +162,11 @@ public:
|
|||
void SetTransitions() override;
|
||||
|
||||
private:
|
||||
///> Shows the context menu for the drawing tool
|
||||
///> This menu consists of normal UI functions (zoom, grid, etc)
|
||||
///> And any suitable global functions for the active drawing type.
|
||||
void showContextMenu();
|
||||
|
||||
///> Starts drawing a selected shape (i.e. DRAWSEGMENT).
|
||||
///> @param aShape is the type of created shape (@see STROKE_T).
|
||||
///> @param aGraphic is an object that is going to be used by the tool for drawing. It has to
|
||||
|
@ -161,10 +203,19 @@ private:
|
|||
KIGFX::VIEW_CONTROLS* m_controls;
|
||||
BOARD* m_board;
|
||||
PCB_BASE_EDIT_FRAME* m_frame;
|
||||
MODE m_mode;
|
||||
|
||||
/// Stores the current line width for multisegment drawing.
|
||||
unsigned int m_lineWidth;
|
||||
|
||||
/// Menu displayed by the tool.
|
||||
CONDITIONAL_MENU m_menu;
|
||||
|
||||
/// Pointers to context menus
|
||||
CONTEXT_MENU* m_contextMenu;
|
||||
GRID_MENU* m_gridMenu;
|
||||
ZOOM_MENU* m_zoomMenu;
|
||||
|
||||
// How does line width change after one -/+ key press.
|
||||
static const int WIDTH_STEP;
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <tool/tool_manager.h>
|
||||
|
||||
#include "selection_tool.h"
|
||||
#include "drawing_tool.h"
|
||||
#include "picker_tool.h"
|
||||
|
||||
#include <painter.h>
|
||||
|
@ -72,6 +73,12 @@ private:
|
|||
{
|
||||
SELECTION_TOOL* selTool = getToolManager()->GetTool<SELECTION_TOOL>();
|
||||
|
||||
// enable zone actions that ably to a specific set of zones (as opposed to all of them)
|
||||
bool nonGlobalActionsEnabled = ( SELECTION_CONDITIONS::MoreThan( 0 ) )( selTool->GetSelection() );
|
||||
|
||||
Enable( getMenuId( COMMON_ACTIONS::zoneFill ), nonGlobalActionsEnabled );
|
||||
Enable( getMenuId( COMMON_ACTIONS::zoneUnfill ), nonGlobalActionsEnabled );
|
||||
|
||||
// lines like this make me really think about a better name for SELECTION_CONDITIONS class
|
||||
bool mergeEnabled = ( SELECTION_CONDITIONS::MoreThan( 1 ) &&
|
||||
/*SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) &&*/
|
||||
|
@ -131,21 +138,43 @@ void PCB_EDITOR_CONTROL::Reset( RESET_REASON aReason )
|
|||
|
||||
bool PCB_EDITOR_CONTROL::Init()
|
||||
{
|
||||
m_zoneMenu = new ZONE_CONTEXT_MENU;
|
||||
m_zoneMenu->SetTool( this );
|
||||
|
||||
m_lockMenu = new LOCK_CONTEXT_MENU;
|
||||
m_lockMenu->SetTool( this );
|
||||
|
||||
// Add the PCB control menus to relevant other tools
|
||||
|
||||
SELECTION_TOOL* selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
|
||||
if( selTool )
|
||||
{
|
||||
m_zoneMenu = new ZONE_CONTEXT_MENU;
|
||||
m_zoneMenu->SetTool( this );
|
||||
selTool->GetMenu().AddMenu( m_zoneMenu, _( "Zones" ), false,
|
||||
SELECTION_CONDITIONS::OnlyType( PCB_ZONE_AREA_T ) );
|
||||
|
||||
m_lockMenu = new LOCK_CONTEXT_MENU;
|
||||
m_lockMenu->SetTool( this );
|
||||
selTool->GetMenu().AddMenu( m_lockMenu, _( "Locking" ), false,
|
||||
SELECTION_CONDITIONS::OnlyTypes( GENERAL_COLLECTOR::Tracks ) );
|
||||
}
|
||||
|
||||
DRAWING_TOOL* drawingTool = m_toolMgr->GetTool<DRAWING_TOOL>();
|
||||
|
||||
if( drawingTool )
|
||||
{
|
||||
// Functor to say if the PCB_EDIT_FRAME is in a given mode
|
||||
// Capture the tool pointer and tool mode by value
|
||||
auto toolActiveFunctor = [=]( DRAWING_TOOL::MODE aMode )
|
||||
{
|
||||
return [=]( const SELECTION& sel )
|
||||
{
|
||||
return drawingTool->GetDrawingMode() == aMode;
|
||||
};
|
||||
};
|
||||
|
||||
drawingTool->GetMenu().AddMenu( m_zoneMenu, _( "Zones" ), false,
|
||||
toolActiveFunctor( DRAWING_TOOL::MODE::ZONE ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue