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 The 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, see <https://www.gnu.org/licenses/>.
19 */
20
22#include <confirm.h>
23#include <view/view_controls.h>
24#include <tool/tool_manager.h>
25#include <bitmaps.h>
28
29#include "pl_editor_frame.h"
30#include "tools/pl_actions.h"
33#include "pgm_base.h"
34
36 TOOL_INTERACTIVE( "plEditor.InteractiveDrawing" ),
37 m_frame( nullptr ),
38 m_selectionTool( nullptr )
39{
40}
41
42
44{
47
48 auto& ctxMenu = m_menu->GetMenu();
49
50 // cancel current tool goes in main context menu at the top if present
52 ctxMenu.AddSeparator( 1 );
53
54 // Finally, add the standard zoom/grid items
55 m_frame->AddStandardSubMenus( *m_menu.get() );
56
57 return true;
58}
59
60
66
67
69{
71 VECTOR2I cursorPos;
72 DS_DRAW_ITEM_BASE* item = nullptr;
73 bool isText = aEvent.IsAction( &PL_ACTIONS::placeText );
74
76
77 m_frame->PushTool( aEvent );
78
79 auto setCursor =
80 [&]()
81 {
82 if( item )
83 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PLACE );
84 else if( isText )
85 {
86 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::TEXT );
87 }
88 else if( aEvent.IsAction( &PL_ACTIONS::placeImage ) )
89 {
90 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
91 }
92 else
93 {
94 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
95 }
96 };
97
98 auto cleanup =
99 [&] ()
100 {
102 item = nullptr;
103
104 // There's nothing to roll-back, but we still need to pop the undo stack
105 // This also deletes the item being placed.
106 m_frame->RollbackFromUndo();
107 };
108
109 Activate();
110 // Must be done after Activate() so that it gets set into the correct context
111 getViewControls()->ShowCursor( true );
112 // Set initial cursor
113 setCursor();
114
115 if( aEvent.HasPosition() )
116 m_toolMgr->PrimeTool( aEvent.Position() );
117
118 // Main loop: keep receiving events
119 while( TOOL_EVENT* evt = Wait() )
120 {
121 setCursor();
122 cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
123
124 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
125 {
126 if( item )
127 {
128 cleanup();
129 }
130 else
131 {
132 m_frame->PopTool( aEvent );
133 break;
134 }
135 }
136 else if( evt->IsActivate() )
137 {
138 if( item )
139 cleanup();
140
141 if( evt->IsMoveTool() )
142 {
143 // leave ourselves on the stack so we come back after the move
144 break;
145 }
146 else
147 {
148 m_frame->PopTool( aEvent );
149 break;
150 }
151 }
152 else if( evt->IsClick( BUT_LEFT ) )
153 {
154 bool placeItem = true;
155
156 if( !item )
157 {
158 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
159
160 if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
161 {
162 m_frame->SaveCopyInUndoList();
163
165
166 item = dataItem->GetDrawItems()[0];
167 item->SetFlags( IS_NEW | IS_MOVING );
168
169 // Select the item but don't inform other tools (to prevent the Properties
170 // panel from updating the item before it has been placed)
171 m_selectionTool->AddItemToSel( item, true );
172
173 // update the cursor so it looks correct before another event
174 setCursor();
175
176 // Text is a single-click-place; all others are first-click-creates,
177 // second-click-places.
178 placeItem = dataItem->GetType() == DS_DATA_ITEM::DS_TEXT;
179 }
180 }
181
182 if( item && placeItem )
183 {
184 item->GetPeer()->MoveStartPointToIU( cursorPos );
185 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
186 item->ClearEditFlags();
187 getView()->Update( item );
188
189 // Now we re-select and inform other tools, so that the Properties panel
190 // is updated.
192 m_selectionTool->AddItemToSel( item, false );
193
194 item = nullptr;
195
196 m_frame->OnModify();
197 }
198 }
199 else if( evt->IsClick( BUT_RIGHT ) )
200 {
201 // Warp after context menu only if dragging...
202 if( !item )
203 m_toolMgr->VetoContextMenuMouseWarp();
204
205 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
206 }
207 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
208 {
209 item->GetPeer()->MoveStartPointToIU( cursorPos );
210 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
211 getView()->Update( item );
212 }
213 else
214 {
215 evt->SetPassEvent();
216 }
217
218 // Enable autopanning and cursor capture only when there is an item to be placed
219 getViewControls()->SetAutoPan( item != nullptr );
220 getViewControls()->CaptureCursor( item != nullptr );
221 }
222
223 getViewControls()->SetAutoPan( false );
224 getViewControls()->CaptureCursor( false );
225 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
226 return 0;
227}
228
229
231{
233 DS_DRAW_ITEM_BASE* item = nullptr;
234
235 // We might be running as the same shape in another co-routine. Make sure that one
236 // gets whacked.
237 m_toolMgr->DeactivateTool();
238
240
241 m_frame->PushTool( aEvent );
242
243 auto setCursor =
244 [&]()
245 {
246 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
247 };
248
249 Activate();
250 // Must be done after Activate() so that it gets set into the correct context
251 getViewControls()->ShowCursor( true );
252 // Set initial cursor
253 setCursor();
254
255 if( aEvent.HasPosition() )
256 m_toolMgr->PrimeTool( aEvent.Position() );
257
258 // Main loop: keep receiving events
259 while( TOOL_EVENT* evt = Wait() )
260 {
261 setCursor();
262
263 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
264
265 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
266 {
268
269 if( item )
270 {
271 item = nullptr;
272
273 // Pop the undo stack and delete the item being placed
274 m_frame->RollbackFromUndo();
275 }
276 else
277 {
278 break;
279 }
280 }
281 else if( evt->IsActivate() )
282 {
283 if( item )
284 {
285 item = nullptr;
286
287 // Pop the undo stack and delete the item being placed
288 m_frame->RollbackFromUndo();
289 }
290
291 if( evt->IsPointEditor() || evt->IsMoveTool() )
292 {
293 // leave ourselves on the stack so we come back after the move
294 break;
295 }
296 }
297 else if( evt->IsClick( BUT_LEFT ) )
298 {
299 if( !item ) // start drawing
300 {
301 m_frame->SaveCopyInUndoList();
303
304 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
305 dataItem->MoveToIU( cursorPos );
306
307 item = dataItem->GetDrawItems()[0];
308 item->SetFlags( IS_NEW );
309
310 // Select the item but don't inform other tools (to prevent the Properties
311 // panel from updating the item before it has been placed)
312 m_selectionTool->AddItemToSel( item, true );
313 }
314 else // finish drawing
315 {
316 // Now we re-select and inform other tools, so that the Properties panel
317 // is updated.
319 m_selectionTool->AddItemToSel( item, false );
320
321 item->ClearEditFlags();
322 item = nullptr;
323
324 // Activate point editor immediately to allow resizing of the item just created
326
327 m_frame->OnModify();
328 }
329 }
330 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
331 {
332 if( item )
333 {
334 item->GetPeer()->MoveEndPointToIU( cursorPos );
335 item->SetEnd( item->GetPeer()->GetEndPosIU( 0 ) );
336 getView()->Update( item );
337 }
338 }
339 else if( evt->IsClick( BUT_RIGHT ) )
340 {
341 // Warp after context menu only if dragging...
342 if( !item )
343 m_toolMgr->VetoContextMenuMouseWarp();
344
345 m_menu->ShowContextMenu( m_selectionTool->GetSelection() );
346 }
347 else
348 {
349 evt->SetPassEvent();
350 }
351
352 // Enable autopanning and cursor capture only when there is a shape being drawn
353 getViewControls()->SetAutoPan( item != nullptr );
354 getViewControls()->CaptureCursor( item != nullptr );
355 }
356
357 getViewControls()->SetAutoPan( false );
358 getViewControls()->CaptureCursor( false );
359 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
360 m_frame->PopTool( aEvent );
361 return 0;
362}
363
364
static TOOL_ACTION cancelInteractive
Definition actions.h:68
static TOOL_ACTION undo
Definition actions.h:71
static TOOL_ACTION activatePointEditor
Definition actions.h:267
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:220
static TOOL_ACTION refreshPreview
Definition actions.h:155
Drawing sheet structure type definitions.
void MoveStartPointToIU(const VECTOR2I &aPosition)
Move the starting point of the item to a new position.
DS_ITEM_TYPE GetType() const
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
Base class to handle basic graphic items.
DS_DATA_ITEM * GetPeer() const
virtual void ClearEditFlags()
Definition eda_item.h:166
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:283
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:152
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:1835
static TOOL_ACTION placeImage
Definition pl_actions.h:37
static TOOL_ACTION drawRectangle
Definition pl_actions.h:38
static TOOL_ACTION placeText
Definition pl_actions.h:36
static TOOL_ACTION drawLine
Definition pl_actions.h:39
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.
static bool ShowAlways(const SELECTION &aSelection)
The default condition function (always returns true).
T * getEditFrame() const
Return the application window object, casted to requested user type.
Definition tool_base.h:182
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:40
TOOL_MANAGER * m_toolMgr
Definition tool_base.h:220
KIGFX::VIEW * getView() const
Returns the instance of #VIEW object used in the application.
Definition tool_base.cpp:34
RESET_REASON
Determine the reason of reset for a tool.
Definition tool_base.h:74
@ MODEL_RELOAD
Model changes (the sheet for a schematic)
Definition tool_base.h:76
Generic, UI-independent tool event.
Definition tool_event.h:167
bool HasPosition() const
Returns if it this event has a valid position (true for mouse events and context-menu or hotkey-based...
Definition tool_event.h:256
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:289
bool IsAction(const TOOL_ACTION *aAction) const
Test if the event contains an action issued upon activation of the given TOOL_ACTION.
T Parameter() const
Return a parameter assigned to the event.
Definition tool_event.h:469
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_INTERACTIVE(TOOL_ID aId, const std::string &aName)
Create a tool with given id & name.
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.
This file is part of the common library.
@ PLACE
Definition cursors.h:94
@ ARROW
Definition cursors.h:42
@ PENCIL
Definition cursors.h:48
#define IS_NEW
New item, just created.
#define IS_MOVING
Item being moved.
see class PGM_BASE
@ BUT_LEFT
Definition tool_event.h:128
@ BUT_RIGHT
Definition tool_event.h:129
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683