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, 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{
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
59 m_frame->AddStandardSubMenus( *m_menu.get() );
60
61 return true;
62}
63
64
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.
110 m_frame->RollbackFromUndo();
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 {
166 m_frame->SaveCopyInUndoList();
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 )
207 m_toolMgr->VetoContextMenuMouseWarp();
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.
241 m_toolMgr->DeactivateTool();
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
278 m_frame->RollbackFromUndo();
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
292 m_frame->RollbackFromUndo();
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 {
305 m_frame->SaveCopyInUndoList();
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 )
347 m_toolMgr->VetoContextMenuMouseWarp();
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
static TOOL_ACTION cancelInteractive
Definition actions.h:72
static TOOL_ACTION undo
Definition actions.h:75
static TOOL_ACTION activatePointEditor
Definition actions.h:272
static TOOL_ACTION selectionClear
Clear the current selection.
Definition actions.h:223
static TOOL_ACTION refreshPreview
Definition actions.h:158
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:156
virtual void SetPosition(const VECTOR2I &aPos)
Definition eda_item.h:273
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:142
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:1685
static TOOL_ACTION placeImage
Definition pl_actions.h:41
static TOOL_ACTION drawRectangle
Definition pl_actions.h:42
static TOOL_ACTION placeText
Definition pl_actions.h:40
static TOOL_ACTION drawLine
Definition pl_actions.h:43
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:186
KIGFX::VIEW_CONTROLS * getViewControls() const
Return the instance of VIEW_CONTROLS object used in the application.
Definition tool_base.cpp:44
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:38
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:171
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:260
const VECTOR2D Position() const
Return mouse cursor position in world coordinates.
Definition tool_event.h:293
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:473
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:96
@ ARROW
Definition cursors.h:46
@ PENCIL
Definition cursors.h:50
#define IS_NEW
New item, just created.
#define IS_MOVING
Item being moved.
see class PGM_BASE
@ BUT_LEFT
Definition tool_event.h:132
@ BUT_RIGHT
Definition tool_event.h:133
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695