KiCad PCB EDA Suite
pl_drawing_tools.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2019 CERN
5 * Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
26#include <confirm.h>
27#include <view/view_controls.h>
28#include <tool/tool_manager.h>
29#include <bitmaps.h>
32
33#include "pl_editor_frame.h"
34#include "tools/pl_actions.h"
37#include "pgm_base.h"
38
40 TOOL_INTERACTIVE( "plEditor.InteractiveDrawing" ),
41 m_frame( nullptr ),
42 m_selectionTool( nullptr )
43{
44}
45
46
48{
49 m_frame = getEditFrame<PL_EDITOR_FRAME>();
51
52 auto& ctxMenu = m_menu.GetMenu();
53
54 // cancel current tool goes in main context menu at the top if present
56 ctxMenu.AddSeparator( 1 );
57
58 // Finally, add the standard zoom/grid items
60
61 return true;
62}
63
64
66{
67 if( aReason == MODEL_RELOAD )
68 m_frame = getEditFrame<PL_EDITOR_FRAME>();
69}
70
71
73{
75 VECTOR2I cursorPos;
76 DS_DRAW_ITEM_BASE* item = nullptr;
77 bool isText = aEvent.IsAction( &PL_ACTIONS::placeText );
78
80
81 m_frame->PushTool( aEvent );
82
83 auto setCursor =
84 [&]()
85 {
86 if( item )
88 else
90 };
91
92 auto cleanup =
93 [&] ()
94 {
96 item = nullptr;
97
98 // There's nothing to roll-back, but we still need to pop the undo stack
99 // This also deletes the item being placed.
101 };
102
103 Activate();
104 // Must be done after Activate() so that it gets set into the correct context
105 getViewControls()->ShowCursor( true );
106 // Set initial cursor
107 setCursor();
108
109 if( aEvent.HasPosition() )
110 m_toolMgr->PrimeTool( aEvent.Position() );
111
112 // Main loop: keep receiving events
113 while( TOOL_EVENT* evt = Wait() )
114 {
115 setCursor();
116 cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
117
118 if( evt->IsCancelInteractive() )
119 {
120 if( item )
121 cleanup();
122 else
123 {
124 m_frame->PopTool( aEvent );
125 break;
126 }
127 }
128 else if( evt->IsActivate() )
129 {
130 if( item )
131 cleanup();
132
133 if( evt->IsMoveTool() )
134 {
135 // leave ourselves on the stack so we come back after the move
136 break;
137 }
138 else
139 {
140 m_frame->PopTool( aEvent );
141 break;
142 }
143 }
144 else if( evt->IsClick( BUT_LEFT ) )
145 {
146 // First click creates...
147 if( !item )
148 {
149 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
150
151 if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
152 {
154
156
157 item = dataItem->GetDrawItems()[0];
158 item->SetFlags( IS_NEW | IS_MOVING );
159
160 // Select the item but don't inform other tools (to prevent the Properties
161 // panel from updating the item before it has been placed)
162 m_selectionTool->AddItemToSel( item, true );
163
164 // update the cursor so it looks correct before another event
165 setCursor();
166 }
167 }
168 // ... and second click places:
169 else
170 {
171 item->GetPeer()->MoveStartPointToUi( cursorPos );
172 item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
173 item->ClearEditFlags();
174 getView()->Update( item );
175
176 // Now we re-select and inform other tools, so that the Properties panel
177 // is updated.
179 m_selectionTool->AddItemToSel( item, false );
180
181 item = nullptr;
182
183 m_frame->OnModify();
184 }
185 }
186 else if( evt->IsClick( BUT_RIGHT ) )
187 {
188 // Warp after context menu only if dragging...
189 if( !item )
191
193 }
194 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
195 {
196 item->GetPeer()->MoveStartPointToUi( cursorPos );
197 item->SetPosition( item->GetPeer()->GetStartPosUi( 0 ) );
198 getView()->Update( item );
199 }
200 else
201 {
202 evt->SetPassEvent();
203 }
204
205 // Enable autopanning and cursor capture only when there is an item to be placed
206 getViewControls()->SetAutoPan( item != nullptr );
207 getViewControls()->CaptureCursor( item != nullptr );
208 }
209
210 getViewControls()->SetAutoPan( false );
211 getViewControls()->CaptureCursor( false );
213 return 0;
214}
215
216
218{
220 DS_DRAW_ITEM_BASE* item = nullptr;
221
222 // We might be running as the same shape in another co-routine. Make sure that one
223 // gets whacked.
225
227
228 m_frame->PushTool( aEvent );
229
230 auto setCursor =
231 [&]()
232 {
234 };
235
236 Activate();
237 // Must be done after Activate() so that it gets set into the correct context
238 getViewControls()->ShowCursor( true );
239 // Set initial cursor
240 setCursor();
241
242 if( aEvent.HasPosition() )
243 m_toolMgr->PrimeTool( aEvent.Position() );
244
245 // Main loop: keep receiving events
246 while( TOOL_EVENT* evt = Wait() )
247 {
248 setCursor();
249
250 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
251
252 if( evt->IsCancelInteractive() || evt->IsActivate() )
253 {
255
256 if( item )
257 {
258 item = nullptr;
259
260 // Pop the undo stack and delete the item being placed
262 }
263 else if( evt->IsCancelInteractive() )
264 {
265 break;
266 }
267
268 if( evt->IsActivate() && !evt->IsPointEditor() && !evt->IsMoveTool() )
269 break;
270 }
271 else if( evt->IsClick( BUT_LEFT ) )
272 {
273 if( !item ) // start drawing
274 {
277
278 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
279 dataItem->MoveToUi( cursorPos );
280
281 item = dataItem->GetDrawItems()[0];
282 item->SetFlags( IS_NEW );
283
284 // Select the item but don't inform other tools (to prevent the Properties
285 // panel from updating the item before it has been placed)
286 m_selectionTool->AddItemToSel( item, true );
287 }
288 else // finish drawing
289 {
290 // Now we re-select and inform other tools, so that the Properties panel
291 // is updated.
293 m_selectionTool->AddItemToSel( item, false );
294
295 item->ClearEditFlags();
296 item = nullptr;
297
298 // Activate point editor immediately to allow resizing of the item just created
300
301 m_frame->OnModify();
302 }
303 }
304 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
305 {
306 if( item )
307 {
308 item->GetPeer()->MoveEndPointToUi( cursorPos );
309 item->SetEnd( item->GetPeer()->GetEndPosUi( 0 ) );
310 getView()->Update( item );
311 }
312 }
313 else if( evt->IsClick( BUT_RIGHT ) )
314 {
315 // Warp after context menu only if dragging...
316 if( !item )
318
320 }
321 else
322 {
323 evt->SetPassEvent();
324 }
325
326 // Enable autopanning and cursor capture only when there is a shape being drawn
327 getViewControls()->SetAutoPan( item != nullptr );
328 getViewControls()->CaptureCursor( item != nullptr );
329 }
330
331 getViewControls()->SetAutoPan( false );
332 getViewControls()->CaptureCursor( false );
334 m_frame->PopTool( aEvent );
335 return 0;
336}
337
338
340{
345}
static TOOL_ACTION cancelInteractive
Definition: actions.h:63
static TOOL_ACTION activatePointEditor
Definition: actions.h:172
static TOOL_ACTION refreshPreview
Definition: actions.h:109
Drawing sheet structure type definitions.
Definition: ds_data_item.h:96
void MoveToUi(const VECTOR2I &aPosition)
Move item to a new position.
const VECTOR2I GetStartPosUi(int ii=0) const
void MoveStartPointToUi(const VECTOR2I &aPosition)
Move the starting point of the item to a new position.
const std::vector< DS_DRAW_ITEM_BASE * > & GetDrawItems() const
Definition: ds_data_item.h:110
Base class to handle basic graphic items.
Definition: ds_draw_item.h:59
DS_DATA_ITEM * GetPeer() const
Definition: ds_draw_item.h:63
void AddStandardSubMenus(TOOL_MENU &aMenu)
Construct a "basic" menu for a tool, containing only items that apply to all tools (e....
void SetCurrentCursor(KICURSOR aCursor)
Set the current cursor shape for this panel.
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:250
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:142
void ClearEditFlags()
Definition: eda_item.h:160
virtual void CaptureCursor(bool aEnabled)
Force the cursor to stay within the drawing panel area.
virtual void ShowCursor(bool aEnabled)
Enable or disables display of cursor.
VECTOR2D GetCursorPosition() const
Return the current cursor position in world coordinates.
virtual void SetAutoPan(bool aEnabled)
Turn on/off auto panning (this feature is used when there is a tool active (eg.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1574
static TOOL_ACTION clearSelection
Clear the current selection.
Definition: pl_actions.h:43
static TOOL_ACTION placeImage
Definition: pl_actions.h:59
static TOOL_ACTION drawRectangle
Definition: pl_actions.h:60
static TOOL_ACTION placeText
Definition: pl_actions.h:58
static TOOL_ACTION drawLine
Definition: pl_actions.h:61
PL_SELECTION_TOOL * m_selectionTool
int PlaceItem(const TOOL_EVENT &aEvent)
int DrawShape(const TOOL_EVENT &aEvent)
PL_EDITOR_FRAME * m_frame
void setTransitions() override
< Set up handlers for various events.
bool Init() override
Init() is called once upon a registration of the tool.
void Reset(RESET_REASON aReason) override
Bring the tool to a known, initial state.
void OnModify() override
Must be called after a change in order to set the "modify" flag.
DS_DATA_ITEM * AddDrawingSheetItem(int aType)
Add a new item to the drawing sheet item list.
void RollbackFromUndo()
Apply the last command in Undo List without stacking a Redo.
void SaveCopyInUndoList()
Save a copy of the description (in a S expr string) for Undo/redo commands.
PL_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
PL_SELECTION & GetSelection()
Return the set of currently selected items.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
int AddItemToSel(const TOOL_EVENT &aEvent)
virtual void PopTool(const TOOL_EVENT &aEvent)
Pops a tool from the stack.
virtual void PushTool(const TOOL_EVENT &aEvent)
NB: the definition of "tool" is different at the user level.
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition: tool_base.cpp:42
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:214
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition: tool_base.cpp:36
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
@ MODEL_RELOAD
Model changes (required full reload)
Definition: tool_base.h:80
Generic, UI-independent tool event.
Definition: tool_event.h:156
bool HasPosition() const
Definition: tool_event.h:243
T Parameter() const
Return a non-standard parameter assigned to the event.
Definition: tool_event.h:442
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:266
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
Definition: tool_event.cpp:88
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
TOOL_MENU m_menu
The functions below are not yet implemented - their interface may change.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Suspend execution of the tool until an event specified in aEventList arrives.
void Activate()
Run the tool.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Run the specified action.
Definition: tool_manager.h:142
void DeactivateTool()
Deactivate the currently active tool.
void PrimeTool(const VECTOR2D &aPosition)
"Prime" a tool by sending a cursor left-click event with the mouse position set to the passed in posi...
void VetoContextMenuMouseWarp()
Disable mouse warping after the current context menu is closed.
Definition: tool_manager.h:424
CONDITIONAL_MENU & GetMenu()
Definition: tool_menu.cpp:44
void ShowContextMenu(SELECTION &aSelection)
Helper function to set and immediately show a CONDITIONAL_MENU in concert with the given SELECTION.
Definition: tool_menu.cpp:57
This file is part of the common library.
#define IS_NEW
New item, just created.
#define IS_MOVING
Item being moved.
see class PGM_BASE
@ BUT_LEFT
Definition: tool_event.h:127
@ BUT_RIGHT
Definition: tool_event.h:128