KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 )
87 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
88 else if( isText )
89 {
90 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
91 }
92 else if( aEvent.IsAction( &PL_ACTIONS::placeImage ) )
93 {
94 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
95 }
96 else
97 {
98 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
99 }
100 };
101
102 auto cleanup =
103 [&] ()
104 {
106 item = nullptr;
107
108 // There's nothing to roll-back, but we still need to pop the undo stack
109 // This also deletes the item being placed.
111 };
112
113 Activate();
114 // Must be done after Activate() so that it gets set into the correct context
115 getViewControls()->ShowCursor( true );
116 // Set initial cursor
117 setCursor();
118
119 if( aEvent.HasPosition() )
120 m_toolMgr->PrimeTool( aEvent.Position() );
121
122 // Main loop: keep receiving events
123 while( TOOL_EVENT* evt = Wait() )
124 {
125 setCursor();
126 cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
127
128 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
129 {
130 if( item )
131 {
132 cleanup();
133 }
134 else
135 {
136 m_frame->PopTool( aEvent );
137 break;
138 }
139 }
140 else if( evt->IsActivate() )
141 {
142 if( item )
143 cleanup();
144
145 if( evt->IsMoveTool() )
146 {
147 // leave ourselves on the stack so we come back after the move
148 break;
149 }
150 else
151 {
152 m_frame->PopTool( aEvent );
153 break;
154 }
155 }
156 else if( evt->IsClick( BUT_LEFT ) )
157 {
158 bool placeItem = true;
159
160 if( !item )
161 {
162 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
163
164 if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
165 {
167
169
170 item = dataItem->GetDrawItems()[0];
171 item->SetFlags( IS_NEW | IS_MOVING );
172
173 // Select the item but don't inform other tools (to prevent the Properties
174 // panel from updating the item before it has been placed)
175 m_selectionTool->AddItemToSel( item, true );
176
177 // update the cursor so it looks correct before another event
178 setCursor();
179
180 // Text is a single-click-place; all others are first-click-creates,
181 // second-click-places.
182 placeItem = dataItem->GetType() == DS_DATA_ITEM::DS_TEXT;
183 }
184 }
185
186 if( item && placeItem )
187 {
188 item->GetPeer()->MoveStartPointToIU( cursorPos );
189 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
190 item->ClearEditFlags();
191 getView()->Update( item );
192
193 // Now we re-select and inform other tools, so that the Properties panel
194 // is updated.
196 m_selectionTool->AddItemToSel( item, false );
197
198 item = nullptr;
199
200 m_frame->OnModify();
201 }
202 }
203 else if( evt->IsClick( BUT_RIGHT ) )
204 {
205 // Warp after context menu only if dragging...
206 if( !item )
208
209 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
210 }
211 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
212 {
213 item->GetPeer()->MoveStartPointToIU( cursorPos );
214 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
215 getView()->Update( item );
216 }
217 else
218 {
219 evt->SetPassEvent();
220 }
221
222 // Enable autopanning and cursor capture only when there is an item to be placed
223 getViewControls()->SetAutoPan( item != nullptr );
224 getViewControls()->CaptureCursor( item != nullptr );
225 }
226
227 getViewControls()->SetAutoPan( false );
228 getViewControls()->CaptureCursor( false );
229 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
230 return 0;
231}
232
233
235{
237 DS_DRAW_ITEM_BASE* item = nullptr;
238
239 // We might be running as the same shape in another co-routine. Make sure that one
240 // gets whacked.
242
244
245 m_frame->PushTool( aEvent );
246
247 auto setCursor =
248 [&]()
249 {
250 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
251 };
252
253 Activate();
254 // Must be done after Activate() so that it gets set into the correct context
255 getViewControls()->ShowCursor( true );
256 // Set initial cursor
257 setCursor();
258
259 if( aEvent.HasPosition() )
260 m_toolMgr->PrimeTool( aEvent.Position() );
261
262 // Main loop: keep receiving events
263 while( TOOL_EVENT* evt = Wait() )
264 {
265 setCursor();
266
267 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
268
269 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
270 {
272
273 if( item )
274 {
275 item = nullptr;
276
277 // Pop the undo stack and delete the item being placed
279 }
280 else
281 {
282 break;
283 }
284 }
285 else if( evt->IsActivate() )
286 {
287 if( item )
288 {
289 item = nullptr;
290
291 // Pop the undo stack and delete the item being placed
293 }
294
295 if( evt->IsPointEditor() || evt->IsMoveTool() )
296 {
297 // leave ourselves on the stack so we come back after the move
298 break;
299 }
300 }
301 else if( evt->IsClick( BUT_LEFT ) )
302 {
303 if( !item ) // start drawing
304 {
307
308 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
309 dataItem->MoveToIU( cursorPos );
310
311 item = dataItem->GetDrawItems()[0];
312 item->SetFlags( IS_NEW );
313
314 // Select the item but don't inform other tools (to prevent the Properties
315 // panel from updating the item before it has been placed)
316 m_selectionTool->AddItemToSel( item, true );
317 }
318 else // finish drawing
319 {
320 // Now we re-select and inform other tools, so that the Properties panel
321 // is updated.
323 m_selectionTool->AddItemToSel( item, false );
324
325 item->ClearEditFlags();
326 item = nullptr;
327
328 // Activate point editor immediately to allow resizing of the item just created
330
331 m_frame->OnModify();
332 }
333 }
334 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
335 {
336 if( item )
337 {
338 item->GetPeer()->MoveEndPointToIU( cursorPos );
339 item->SetEnd( item->GetPeer()->GetEndPosIU( 0 ) );
340 getView()->Update( item );
341 }
342 }
343 else if( evt->IsClick( BUT_RIGHT ) )
344 {
345 // Warp after context menu only if dragging...
346 if( !item )
348
349 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
350 }
351 else
352 {
353 evt->SetPassEvent();
354 }
355
356 // Enable autopanning and cursor capture only when there is a shape being drawn
357 getViewControls()->SetAutoPan( item != nullptr );
358 getViewControls()->CaptureCursor( item != nullptr );
359 }
360
361 getViewControls()->SetAutoPan( false );
362 getViewControls()->CaptureCursor( false );
363 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
364 m_frame->PopTool( aEvent );
365 return 0;
366}
367
368
370{
375}
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION undo
Definition: actions.h:68
static TOOL_ACTION activatePointEditor
Definition: actions.h:221
static TOOL_ACTION refreshPreview
Definition: actions.h:149
Drawing sheet structure type definitions.
Definition: ds_data_item.h:96
void MoveStartPointToIU(const VECTOR2I &aPosition)
Move the starting point of the item to a new position.
DS_ITEM_TYPE GetType() const
Definition: ds_data_item.h:128
void MoveToIU(const VECTOR2I &aPosition)
Move item to a new position.
const VECTOR2I GetStartPosIU(int ii=0) const
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 ClearEditFlags()
Definition: eda_item.h:141
virtual void SetPosition(const VECTOR2I &aPos)
Definition: eda_item.h:244
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition: eda_item.h:127
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:1687
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:218
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 (the sheet for a schematic)
Definition: tool_base.h:80
Generic, UI-independent tool event.
Definition: tool_event.h:167
bool HasPosition() const
Definition: tool_event.h:256
const VECTOR2D Position() const
Returns the point where dragging has started.
Definition: tool_event.h:285
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:82
T Parameter() const
Return a parameter assigned to the event.
Definition: tool_event.h:460
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).
std::unique_ptr< 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.
void DeactivateTool()
Deactivate the currently active tool.
bool RunAction(const std::string &aActionName, T aParam)
Run the specified action immediately, pausing the current action to run the new one.
Definition: tool_manager.h:150
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:511
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:131
@ BUT_RIGHT
Definition: tool_event.h:132