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
89 m_frame->GetCanvas()->SetCurrentCursor( isText ? KICURSOR::TEXT : KICURSOR::PENCIL );
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() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
119 {
120 if( item )
121 {
122 cleanup();
123 }
124 else
125 {
126 m_frame->PopTool( aEvent );
127 break;
128 }
129 }
130 else if( evt->IsActivate() )
131 {
132 if( item )
133 cleanup();
134
135 if( evt->IsMoveTool() )
136 {
137 // leave ourselves on the stack so we come back after the move
138 break;
139 }
140 else
141 {
142 m_frame->PopTool( aEvent );
143 break;
144 }
145 }
146 else if( evt->IsClick( BUT_LEFT ) )
147 {
148 bool placeItem = true;
149
150 if( !item )
151 {
152 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
153
154 if( dataItem ) // dataItem = nullptr can happens if the command was cancelled
155 {
157
159
160 item = dataItem->GetDrawItems()[0];
161 item->SetFlags( IS_NEW | IS_MOVING );
162
163 // Select the item but don't inform other tools (to prevent the Properties
164 // panel from updating the item before it has been placed)
165 m_selectionTool->AddItemToSel( item, true );
166
167 // update the cursor so it looks correct before another event
168 setCursor();
169
170 // Text is a single-click-place; all others are first-click-creates,
171 // second-click-places.
172 placeItem = dataItem->GetType() == DS_DATA_ITEM::DS_TEXT;
173 }
174 }
175
176 if( item && placeItem )
177 {
178 item->GetPeer()->MoveStartPointToIU( cursorPos );
179 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
180 item->ClearEditFlags();
181 getView()->Update( item );
182
183 // Now we re-select and inform other tools, so that the Properties panel
184 // is updated.
186 m_selectionTool->AddItemToSel( item, false );
187
188 item = nullptr;
189
190 m_frame->OnModify();
191 }
192 }
193 else if( evt->IsClick( BUT_RIGHT ) )
194 {
195 // Warp after context menu only if dragging...
196 if( !item )
198
200 }
201 else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
202 {
203 item->GetPeer()->MoveStartPointToIU( cursorPos );
204 item->SetPosition( item->GetPeer()->GetStartPosIU( 0 ) );
205 getView()->Update( item );
206 }
207 else
208 {
209 evt->SetPassEvent();
210 }
211
212 // Enable autopanning and cursor capture only when there is an item to be placed
213 getViewControls()->SetAutoPan( item != nullptr );
214 getViewControls()->CaptureCursor( item != nullptr );
215 }
216
217 getViewControls()->SetAutoPan( false );
218 getViewControls()->CaptureCursor( false );
219 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
220 return 0;
221}
222
223
225{
227 DS_DRAW_ITEM_BASE* item = nullptr;
228
229 // We might be running as the same shape in another co-routine. Make sure that one
230 // gets whacked.
232
234
235 m_frame->PushTool( aEvent );
236
237 auto setCursor =
238 [&]()
239 {
240 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
241 };
242
243 Activate();
244 // Must be done after Activate() so that it gets set into the correct context
245 getViewControls()->ShowCursor( true );
246 // Set initial cursor
247 setCursor();
248
249 if( aEvent.HasPosition() )
250 m_toolMgr->PrimeTool( aEvent.Position() );
251
252 // Main loop: keep receiving events
253 while( TOOL_EVENT* evt = Wait() )
254 {
255 setCursor();
256
257 VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
258
259 if( evt->IsCancelInteractive() || ( item && evt->IsAction( &ACTIONS::undo ) ) )
260 {
262
263 if( item )
264 {
265 item = nullptr;
266
267 // Pop the undo stack and delete the item being placed
269 }
270 else
271 {
272 break;
273 }
274 }
275 else if( evt->IsActivate() )
276 {
277 if( item )
278 {
279 item = nullptr;
280
281 // Pop the undo stack and delete the item being placed
283 }
284
285 if( evt->IsPointEditor() || evt->IsMoveTool() )
286 {
287 // leave ourselves on the stack so we come back after the move
288 break;
289 }
290 }
291 else if( evt->IsClick( BUT_LEFT ) )
292 {
293 if( !item ) // start drawing
294 {
297
298 DS_DATA_ITEM* dataItem = m_frame->AddDrawingSheetItem( type );
299 dataItem->MoveToIU( cursorPos );
300
301 item = dataItem->GetDrawItems()[0];
302 item->SetFlags( IS_NEW );
303
304 // Select the item but don't inform other tools (to prevent the Properties
305 // panel from updating the item before it has been placed)
306 m_selectionTool->AddItemToSel( item, true );
307 }
308 else // finish drawing
309 {
310 // Now we re-select and inform other tools, so that the Properties panel
311 // is updated.
313 m_selectionTool->AddItemToSel( item, false );
314
315 item->ClearEditFlags();
316 item = nullptr;
317
318 // Activate point editor immediately to allow resizing of the item just created
320
321 m_frame->OnModify();
322 }
323 }
324 else if( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() )
325 {
326 if( item )
327 {
328 item->GetPeer()->MoveEndPointToIU( cursorPos );
329 item->SetEnd( item->GetPeer()->GetEndPosIU( 0 ) );
330 getView()->Update( item );
331 }
332 }
333 else if( evt->IsClick( BUT_RIGHT ) )
334 {
335 // Warp after context menu only if dragging...
336 if( !item )
338
340 }
341 else
342 {
343 evt->SetPassEvent();
344 }
345
346 // Enable autopanning and cursor capture only when there is a shape being drawn
347 getViewControls()->SetAutoPan( item != nullptr );
348 getViewControls()->CaptureCursor( item != nullptr );
349 }
350
351 getViewControls()->SetAutoPan( false );
352 getViewControls()->CaptureCursor( false );
353 m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
354 m_frame->PopTool( aEvent );
355 return 0;
356}
357
358
360{
365}
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
static TOOL_ACTION undo
Definition: actions.h:68
static TOOL_ACTION activatePointEditor
Definition: actions.h:210
static TOOL_ACTION refreshPreview
Definition: actions.h:139
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).
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:530
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:131
@ BUT_RIGHT
Definition: tool_event.h:132