KiCad PCB EDA Suite
tool_manager.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) 2013-2018 CERN
5  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <map>
27 #include <stack>
28 #include <algorithm>
29 
30 #include <core/optional.h>
31 
32 #include <wx/event.h>
33 #include <wx/clipbrd.h>
34 
35 #include <view/view.h>
36 
37 #include <tool/tool_base.h>
38 #include <tool/tool_interactive.h>
39 #include <tool/tool_manager.h>
40 #include <tool/context_menu.h>
41 #include <tool/coroutine.h>
42 #include <tool/action_manager.h>
43 
44 #include <pcb_edit_frame.h>
45 #include <class_draw_panel_gal.h>
46 
49 {
50  TOOL_STATE( TOOL_BASE* aTool ) :
51  theTool( aTool )
52  {
53  clear();
54  }
55 
56  TOOL_STATE( const TOOL_STATE& aState )
57  {
58  theTool = aState.theTool;
59  idle = aState.idle;
60  pendingWait = aState.pendingWait;
62  contextMenu = aState.contextMenu;
64  cofunc = aState.cofunc;
65  wakeupEvent = aState.wakeupEvent;
66  waitEvents = aState.waitEvents;
67  transitions = aState.transitions;
68  vcSettings = aState.vcSettings;
69  // do not copy stateStack
70  }
71 
73  {
74  assert( stateStack.empty() );
75  }
76 
79 
81  bool idle;
82 
86 
89 
92 
95 
98 
101 
104 
107  std::vector<TRANSITION> transitions;
108 
111 
112  void operator=( const TOOL_STATE& aState )
113  {
114  theTool = aState.theTool;
115  idle = aState.idle;
116  pendingWait = aState.pendingWait;
117  pendingContextMenu = aState.pendingContextMenu;
118  contextMenu = aState.contextMenu;
119  contextMenuTrigger = aState.contextMenuTrigger;
120  cofunc = aState.cofunc;
121  wakeupEvent = aState.wakeupEvent;
122  waitEvents = aState.waitEvents;
123  transitions = aState.transitions;
124  vcSettings = aState.vcSettings;
125  // do not copy stateStack
126  }
127 
128  bool operator==( const TOOL_MANAGER::TOOL_STATE& aRhs ) const
129  {
130  return aRhs.theTool == this->theTool;
131  }
132 
133  bool operator!=( const TOOL_MANAGER::TOOL_STATE& aRhs ) const
134  {
135  return aRhs.theTool != this->theTool;
136  }
137 
143  void Push()
144  {
145  auto state = std::make_unique<TOOL_STATE>( *this );
146  stateStack.push( std::move( state ) );
147  clear();
148  }
149 
156  bool Pop()
157  {
158  delete cofunc;
159 
160  if( !stateStack.empty() )
161  {
162  *this = *stateStack.top().get();
163  stateStack.pop();
164  return true;
165  }
166  else
167  {
168  cofunc = NULL;
169  return false;
170  }
171  }
172 
173 private:
175  std::stack<std::unique_ptr<TOOL_STATE>> stateStack;
176 
178  void clear()
179  {
180  idle = true;
181  pendingWait = false;
182  pendingContextMenu = false;
183  cofunc = NULL;
184  contextMenu = NULL;
185  contextMenuTrigger = CMENU_OFF;
186  vcSettings.Reset();
187  transitions.clear();
188  }
189 };
190 
191 
193  m_model( NULL ),
194  m_view( NULL ),
195  m_viewControls( NULL ),
196  m_editFrame( NULL ),
197  m_passEvent( false ),
198  m_menuActive( false ),
199  m_menuOwner( -1 ),
200  m_activeState( nullptr )
201 {
202  m_actionMgr = new ACTION_MANAGER( this );
203 }
204 
205 
207 {
208  std::map<TOOL_BASE*, TOOL_STATE*>::iterator it, it_end;
209 
210  for( it = m_toolState.begin(), it_end = m_toolState.end(); it != it_end; ++it )
211  {
212  delete it->second->cofunc; // delete cofunction
213  delete it->second; // delete TOOL_STATE
214  delete it->first; // delete the tool itself
215  }
216 
217  delete m_actionMgr;
218 }
219 
220 
222 {
223  wxASSERT_MSG( m_toolNameIndex.find( aTool->GetName() ) == m_toolNameIndex.end(),
224  wxT( "Adding two tools with the same name may result in unexpected behaviour.") );
225  wxASSERT_MSG( m_toolIdIndex.find( aTool->GetId() ) == m_toolIdIndex.end(),
226  wxT( "Adding two tools with the same ID may result in unexpected behaviour.") );
227  wxASSERT_MSG( m_toolTypes.find( typeid( *aTool ).name() ) == m_toolTypes.end(),
228  wxT( "Adding two tools of the same type may result in unexpected behaviour.") );
229 
230  TOOL_STATE* st = new TOOL_STATE( aTool );
231 
232  m_toolState[aTool] = st;
233  m_toolNameIndex[aTool->GetName()] = st;
234  m_toolIdIndex[aTool->GetId()] = st;
235  m_toolTypes[typeid( *aTool ).name()] = st->theTool;
236 
237  aTool->attachManager( this );
238 }
239 
240 
242 {
243  TOOL_BASE* tool = FindTool( aToolId );
244 
245  if( tool && tool->GetType() == INTERACTIVE )
246  return invokeTool( tool );
247 
248  return false; // there is no tool with the given id
249 }
250 
251 
252 bool TOOL_MANAGER::InvokeTool( const std::string& aToolName )
253 {
254  TOOL_BASE* tool = FindTool( aToolName );
255 
256  if( tool && tool->GetType() == INTERACTIVE )
257  return invokeTool( tool );
258 
259  return false; // there is no tool with the given name
260 }
261 
262 
264 {
265  m_actionMgr->RegisterAction( aAction );
266 }
267 
268 
270 {
271  m_actionMgr->UnregisterAction( aAction );
272 }
273 
274 
275 bool TOOL_MANAGER::RunAction( const std::string& aActionName, bool aNow, void* aParam )
276 {
277  TOOL_ACTION* action = m_actionMgr->FindAction( aActionName );
278 
279  if( !action )
280  {
281  wxASSERT_MSG( false, wxString::Format( wxT( "Could not find action %s." ), aActionName ) );
282  return false;
283  }
284 
285  RunAction( *action, aNow, aParam );
286 
287  return false;
288 }
289 
290 
291 void TOOL_MANAGER::RunAction( const TOOL_ACTION& aAction, bool aNow, void* aParam )
292 {
293  TOOL_EVENT event = aAction.MakeEvent();
294 
295  // Allow to override the action parameter
296  if( aParam )
297  event.SetParameter( aParam );
298 
299  if( aNow )
300  {
301  TOOL_STATE* current = m_activeState;
302  processEvent( event );
303  setActiveState( current );
304  }
305  else
306  {
307  PostEvent( event );
308  }
309 }
310 
311 
313 {
314  return m_actionMgr->GetHotKey( aAction );
315 }
316 
317 
319 {
321 }
322 
323 
325 {
326  wxASSERT( aTool != NULL );
327 
328  TOOL_EVENT evt( TC_COMMAND, TA_ACTIVATE, aTool->GetName() );
329  processEvent( evt );
330 
331  if( TOOL_STATE* active = GetCurrentToolState() )
332  setActiveState( active );
333 
334  return true;
335 }
336 
337 
339 {
340  TOOL_BASE* tool = FindTool( aToolId );
341 
342  if( tool && tool->GetType() == INTERACTIVE )
343  return runTool( tool );
344 
345  return false; // there is no tool with the given id
346 }
347 
348 
349 bool TOOL_MANAGER::runTool( const std::string& aToolName )
350 {
351  TOOL_BASE* tool = FindTool( aToolName );
352 
353  if( tool && tool->GetType() == INTERACTIVE )
354  return runTool( tool );
355 
356  return false; // there is no tool with the given name
357 }
358 
359 
361 {
362  wxASSERT( aTool != NULL );
363 
364  if( !isRegistered( aTool ) )
365  {
366  wxASSERT_MSG( false, wxT( "You cannot run unregistered tools" ) );
367  return false;
368  }
369 
370  TOOL_ID id = aTool->GetId();
371 
372  if( aTool->GetType() == INTERACTIVE )
373  static_cast<TOOL_INTERACTIVE*>( aTool )->resetTransitions();
374 
375  // If the tool is already active, bring it to the top of the active tools stack
376  if( isActive( aTool ) )
377  {
378  m_activeTools.erase( std::find( m_activeTools.begin(), m_activeTools.end(), id ) );
379  m_activeTools.push_front( id );
380  return false;
381  }
382 
384  aTool->Reset( TOOL_INTERACTIVE::RUN );
385 
386  // Add the tool on the front of the processing queue (it gets events first)
387  m_activeTools.push_front( id );
388 
389  return true;
390 }
391 
392 
394 {
395  std::map<TOOL_ID, TOOL_STATE*>::const_iterator it = m_toolIdIndex.find( aId );
396 
397  if( it != m_toolIdIndex.end() )
398  return it->second->theTool;
399 
400  return NULL;
401 }
402 
403 
404 TOOL_BASE* TOOL_MANAGER::FindTool( const std::string& aName ) const
405 {
406  std::map<std::string, TOOL_STATE*>::const_iterator it = m_toolNameIndex.find( aName );
407 
408  if( it != m_toolNameIndex.end() )
409  return it->second->theTool;
410 
411  return NULL;
412 }
413 
414 
416 {
417  // Deactivate the active tool, but do not run anything new
419  processEvent( evt );
420 }
421 
422 
424 {
425  DeactivateTool();
426 
427  for( auto& state : m_toolState )
428  {
429  TOOL_BASE* tool = state.first;
430  setActiveState( state.second );
431  tool->Reset( aReason );
432 
433  if( tool->GetType() == INTERACTIVE )
434  static_cast<TOOL_INTERACTIVE*>( tool )->resetTransitions();
435  }
436 }
437 
438 
440 {
441  for( auto it = m_toolState.begin(); it != m_toolState.end(); /* iteration in the loop */ )
442  {
443  TOOL_BASE* tool = it->first;
444  TOOL_STATE* state = it->second;
445  setActiveState( state );
446  ++it; // keep the iterator valid if the element is going to be erased
447 
448  if( !tool->Init() )
449  {
450  wxMessageBox(
451  wxString::Format( "Initialization of tool \"%s\" failed", tool->GetName() ) );
452 
453  // Unregister the tool
454  setActiveState( nullptr );
455  m_toolState.erase( tool );
456  m_toolNameIndex.erase( tool->GetName() );
457  m_toolIdIndex.erase( tool->GetId() );
458  m_toolTypes.erase( typeid( *tool ).name() );
459 
460  delete state;
461  delete tool;
462  }
463  }
464 
466 }
467 
468 
469 int TOOL_MANAGER::GetPriority( int aToolId ) const
470 {
471  int priority = 0;
472 
473  for( auto it = m_activeTools.begin(), itEnd = m_activeTools.end(); it != itEnd; ++it )
474  {
475  if( *it == aToolId )
476  return priority;
477 
478  ++priority;
479  }
480 
481  return -1;
482 }
483 
484 
486  const TOOL_EVENT_LIST& aConditions )
487 {
488  TOOL_STATE* st = m_toolState[aTool];
489 
490  st->transitions.push_back( TRANSITION( aConditions, aHandler ) );
491 }
492 
493 
495 {
496  m_toolState[aTool]->transitions.clear();
497 }
498 
499 
500 void TOOL_MANAGER::RunMainStack( TOOL_BASE* aTool, std::function<void()> aFunc )
501 {
502  TOOL_STATE* st = m_toolState[aTool];
503  setActiveState( st );
504  st->cofunc->RunMainStack( std::move( aFunc ) );
505 }
506 
507 
509 {
510  TOOL_STATE* st = m_toolState[aTool];
511 
512  assert( !st->pendingWait ); // everything collapses on two KiYield() in a row
513 
514  // indicate to the manager that we are going to sleep and we shall be
515  // woken up when an event matching aConditions arrive
516  st->pendingWait = true;
517  st->waitEvents = aConditions;
518 
519  // switch context back to event dispatcher loop
520  st->cofunc->KiYield();
521 
522  return st->wakeupEvent;
523 }
524 
525 
527 {
528  // iterate over all registered tools
529  for( auto it = m_activeTools.begin(); it != m_activeTools.end(); ++it )
530  {
531  TOOL_STATE* st = m_toolIdIndex[*it];
532 
533  // forward context menu events to the tool that created the menu
534  if( aEvent.IsMenu() )
535  {
536  if( *it != m_menuOwner )
537  continue;
538  }
539 
540  // the tool state handler is waiting for events (i.e. called Wait() method)
541  if( st->pendingWait )
542  {
543  if( st->waitEvents.Matches( aEvent ) )
544  {
545  // By default only messages are passed further
546  m_passEvent = ( aEvent.Category() == TC_MESSAGE );
547 
548  // got matching event? clear wait list and wake up the coroutine
549  st->wakeupEvent = aEvent;
550  st->pendingWait = false;
551  st->waitEvents.clear();
552 
553  if( st->cofunc )
554  {
555  setActiveState( st );
556  bool end = !st->cofunc->Resume();
557 
558  if( end )
559  it = finishTool( st );
560  }
561 
562  // If the tool did not request to propagate
563  // the event to other tools, we should stop it now
564  if( !m_passEvent )
565  break;
566  }
567  }
568  }
569 
570  for( auto& state : m_toolState )
571  {
572  TOOL_STATE* st = state.second;
573  bool finished = false;
574 
575  // no state handler in progress - check if there are any transitions (defined by
576  // Go() method that match the event.
577  if( !st->transitions.empty() )
578  {
579  for( TRANSITION& tr : st->transitions )
580  {
581  if( tr.first.Matches( aEvent ) )
582  {
583  auto func_copy = tr.second;
584 
585  // if there is already a context, then push it on the stack
586  // and transfer the previous view control settings to the new context
587  if( st->cofunc )
588  {
589  auto vc = st->vcSettings;
590  st->Push();
591  st->vcSettings = vc;
592  }
593 
594  st->cofunc = new COROUTINE<int, const TOOL_EVENT&>( std::move( func_copy ) );
595 
596  // as the state changes, the transition table has to be set up again
597  st->transitions.clear();
598 
599  // got match? Run the handler.
600  setActiveState( st );
601  st->idle = false;
602  st->cofunc->Call( aEvent );
603 
604  if( !st->cofunc->Running() )
605  finishTool( st ); // The couroutine has finished immediately?
606 
607  // if it is a message, continue processing
608  finished = !( aEvent.Category() == TC_MESSAGE );
609 
610  // there is no point in further checking, as transitions got cleared
611  break;
612  }
613  }
614  }
615 
616  if( finished )
617  break; // only the first tool gets the event
618  }
619 }
620 
621 
623 {
624  if( aEvent.Action() == TA_KEY_PRESSED )
625  {
626  // Check if there is a hotkey associated
627  if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
628  return false; // hotkey event was handled so it does not go any further
629  }
630 
631  return true;
632 }
633 
634 
636 {
637  if( aEvent.IsActivate() )
638  {
639  std::map<std::string, TOOL_STATE*>::iterator tool = m_toolNameIndex.find( *aEvent.GetCommandStr() );
640 
641  if( tool != m_toolNameIndex.end() )
642  {
643  runTool( tool->second->theTool );
644  return true;
645  }
646  }
647 
648  return false;
649 }
650 
652 {
653  for( TOOL_ID toolId : m_activeTools )
654  {
655  TOOL_STATE* st = m_toolIdIndex[toolId];
656 
657  // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
658  // or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
659  if( st->contextMenuTrigger == CMENU_OFF )
660  continue;
661 
662  if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) )
663  break;
664 
665  st->pendingWait = true;
667 
668  // Store the menu pointer in case it is changed by the TOOL when handling menu events
669  CONTEXT_MENU* m = st->contextMenu;
670 
671  if( st->contextMenuTrigger == CMENU_NOW )
673 
674  // Store the cursor position, so the tools could execute actions
675  // using the point where the user has invoked a context menu
677 
678  // Save all tools cursor settings, as they will be overridden
679  for( auto idState : m_toolIdIndex )
680  {
681  TOOL_STATE* s = idState.second;
682  const auto& vc = s->vcSettings;
683 
684  if( vc.m_forceCursorPosition )
685  m_cursorSettings[idState.first] = vc.m_forcedPosition;
686  else
687  m_cursorSettings[idState.first] = NULLOPT;
688  }
689 
691 
692  // Display a copy of menu
693  std::unique_ptr<CONTEXT_MENU> menu( m->Clone() );
694 
695  // Run update handlers on the created copy
696  menu->UpdateAll();
697  m_menuOwner = toolId;
698  m_menuActive = true;
699 
700  auto frame = dynamic_cast<wxFrame*>( m_editFrame );
701 
702  if( frame )
703  frame->PopupMenu( menu.get() );
704 
705  // Warp the cursor as long as the menu wasn't clicked out of
706  if( menu->GetSelected() >= 0 )
707  m_viewControls->WarpCursor( m_menuCursor, true, false );
708  // Otherwise notify the tool of a cancelled menu
709  else
710  {
712  evt.SetParameter( m );
713  dispatchInternal( evt );
714  }
715 
716  // Notify the tools that menu has been closed
718  evt.SetParameter( m );
719  dispatchInternal( evt );
720 
721  m_menuActive = false;
722  m_menuOwner = -1;
723 
724  // Restore cursor settings
725  for( auto cursorSetting : m_cursorSettings )
726  {
727  auto it = m_toolIdIndex.find( cursorSetting.first );
728  wxASSERT( it != m_toolIdIndex.end() );
729 
730  if( it == m_toolIdIndex.end() )
731  continue;
732 
733  KIGFX::VC_SETTINGS& vc = it->second->vcSettings;
734  vc.m_forceCursorPosition = (bool) cursorSetting.second;
735  vc.m_forcedPosition = cursorSetting.second ? *cursorSetting.second : VECTOR2D( 0, 0 );
736  }
737 
738  m_cursorSettings.clear();
739  break;
740  }
741 }
742 
743 
744 TOOL_MANAGER::ID_LIST::iterator TOOL_MANAGER::finishTool( TOOL_STATE* aState )
745 {
746  auto it = std::find( m_activeTools.begin(), m_activeTools.end(), aState->theTool->GetId() );
747 
748  if( !aState->Pop() )
749  {
750  // Deactivate the tool if there are no other contexts saved on the stack
751  if( it != m_activeTools.end() )
752  it = m_activeTools.erase( it );
753  }
754 
755  if( aState == m_activeState )
756  setActiveState( nullptr );
757 
758  // Set transitions to be ready for future TOOL_EVENTs
759  TOOL_BASE* tool = aState->theTool;
760 
761  if( tool->GetType() == INTERACTIVE )
762  static_cast<TOOL_INTERACTIVE*>( tool )->resetTransitions();
763 
764  aState->idle = true;
765 
766  return it;
767 }
768 
769 
771 {
772  bool hotkey_handled = processEvent( aEvent );
773 
774  if( TOOL_STATE* active = GetCurrentToolState() )
775  setActiveState( active );
776 
777  if( m_view->IsDirty() )
778  {
779  auto f = dynamic_cast<EDA_DRAW_FRAME*>( GetEditFrame() );
780 
781  if( f )
782  f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER.
783 
784 #if defined( __WXMAC__ ) || defined( __WINDOWS__ )
785  wxTheApp->ProcessPendingEvents(); // required for updating brightening behind a popup menu
786 #endif
787  }
788 
789  return hotkey_handled;
790 }
791 
792 
794  CONTEXT_MENU_TRIGGER aTrigger )
795 {
796  TOOL_STATE* st = m_toolState[aTool];
797 
798  st->contextMenu = aMenu;
799  st->contextMenuTrigger = aTrigger;
800 }
801 
802 
803 bool TOOL_MANAGER::SaveClipboard( const std::string& aText )
804 {
805  if( wxTheClipboard->Open() )
806  {
807  wxTheClipboard->SetData( new wxTextDataObject( wxString( aText.c_str(), wxConvUTF8 ) ) );
808  wxTheClipboard->Close();
809 
810  return true;
811  }
812 
813  return false;
814 }
815 
816 
817 std::string TOOL_MANAGER::GetClipboard() const
818 {
819  std::string result;
820 
821  if( wxTheClipboard->Open() )
822  {
823  if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
824  {
825  wxTextDataObject data;
826  wxTheClipboard->GetData( data );
827 
828  result = data.GetText().mb_str();
829  }
830 
831  wxTheClipboard->Close();
832  }
833 
834  return result;
835 }
836 
837 
839 {
840  if( TOOL_STATE* active = GetCurrentToolState() )
841  return active->vcSettings;
842 
843  return m_viewControls->GetSettings();
844 }
845 
846 
847 TOOL_ID TOOL_MANAGER::MakeToolId( const std::string& aToolName )
848 {
849  static int currentId;
850 
851  return currentId++;
852 }
853 
854 
856  KIGFX::VIEW_CONTROLS* aViewControls, wxWindow* aFrame )
857 {
858  m_model = aModel;
859  m_view = aView;
860  m_viewControls = aViewControls;
861  m_editFrame = aFrame;
863 }
864 
865 
867 {
868  if( !isRegistered( aTool ) )
869  return false;
870 
871  // Just check if the tool is on the active tools stack
872  return std::find( m_activeTools.begin(), m_activeTools.end(), aTool->GetId() ) != m_activeTools.end();
873 }
874 
875 
877 {
879 
880  if( m_menuActive )
881  {
882  // Context menu is active, so the cursor settings are overridden (see dispatchContextMenu())
883  auto it = m_cursorSettings.find( aState->theTool->GetId() );
884 
885  if( it != m_cursorSettings.end() )
886  {
888 
889  // Tool has overridden the cursor position, so store the new settings
891  {
892  if( !curr.m_forceCursorPosition )
893  it->second = NULLOPT;
894  else
895  it->second = curr.m_forcedPosition;
896  }
897  else
898  {
899  OPT<VECTOR2D> cursor = it->second;
900 
901  if( cursor )
902  {
903  aState->vcSettings.m_forceCursorPosition = true;
904  aState->vcSettings.m_forcedPosition = *cursor;
905  }
906  else
907  {
908  aState->vcSettings.m_forceCursorPosition = false;
909  }
910  }
911  }
912  }
913 }
914 
915 
917 {
919 }
920 
921 
923 {
924  // Early dispatch of events destined for the TOOL_MANAGER
925  if( !dispatchStandardEvents( aEvent ) )
926  return true;
927 
928  dispatchInternal( aEvent );
929  dispatchActivation( aEvent );
930  dispatchContextMenu( aEvent );
931 
932  // Dispatch queue
933  while( !m_eventQueue.empty() )
934  {
935  TOOL_EVENT event = m_eventQueue.front();
936  m_eventQueue.pop_front();
937  processEvent( event );
938  }
939 
940  return false;
941 }
942 
943 
945 {
946  if( m_activeState )
948 
949  m_activeState = aState;
950 
951  if( m_activeState )
952  applyViewControls( aState );
953 }
954 
955 
957 {
958  auto it = m_toolIdIndex.find( aId );
959  return !it->second->idle;
960 }
void RunMainStack(std::function< void()> func)
Function RunMainStack()
Definition: coroutine.h:191
bool m_menuActive
Flag indicating whether a context menu is currently displayed.
Definition: tool_manager.h:535
const KIGFX::VC_SETTINGS & GetCurrentToolVC() const
Returns the view controls settings for the current tool or the general settings if there is no active...
bool operator==(const TOOL_MANAGER::TOOL_STATE &aRhs) const
VECTOR2D m_menuCursor
Right click context menu position.
Definition: tool_manager.h:532
bool IsToolActive(TOOL_ID aId) const
Function IsToolActive() Returns true if a tool with given id is active (executing) ...
virtual bool Init()
Function Init() Init() is called once upon a registration of the tool.
Definition: tool_base.h:93
TOOL_BASE * FindTool(int aId) const
Function FindTool() Searches for a tool with given ID.
void Reset()
Restores the default settings
TOOL_STATE(TOOL_BASE *aTool)
int GetHotKey(const TOOL_ACTION &aAction)
>
TOOL_BASE * theTool
The tool itself.
ACTION_MANAGER * m_actionMgr
Instance of ACTION_MANAGER that handles TOOL_ACTIONs.
Definition: tool_manager.h:515
bool processEvent(const TOOL_EVENT &aEvent)
Main function for event processing.
static TOOL_ID MakeToolId(const std::string &aToolName)
Generates a unique ID from for a tool with given name.
std::vector< TRANSITION > transitions
List of possible transitions (ie.
ID_STATE_MAP m_toolIdIndex
Index of the registered tools current states, associated by tools&#39; ID numbers.
Definition: tool_manager.h:506
void ScheduleNextState(TOOL_BASE *aTool, TOOL_STATE_FUNC &aHandler, const TOOL_EVENT_LIST &aConditions)
Defines a state transition - the events that cause a given handler method in the tool to be called...
void RegisterAction(TOOL_ACTION *aAction)
Function RegisterAction() Registers an action that can be used to control tools (eg.
bool dispatchStandardEvents(const TOOL_EVENT &aEvent)
Function dispatchStandardEvents() Handles specific events, that are intended for TOOL_MANAGER rather ...
bool SaveClipboard(const std::string &aText)
Stores an information to the system clipboard.
bool Call(ArgType aArg)
Function Call()
Definition: coroutine.h:205
void UpdateHotKeys()
Function UpdateHotKeys() Updates TOOL_ACTIONs hot key assignment according to the current frame&#39;s Hot...
Class CONTEXT_MENU.
Definition: context_menu.h:44
void ApplySettings(const VC_SETTINGS &aSettings)
Applies VIEW_CONTROLS settings from an object
KIGFX::VC_SETTINGS vcSettings
VIEW_CONTROLS settings to preserve settings when the tools are switched.
wxWindow * GetEditFrame() const
Definition: tool_manager.h:267
std::map< TOOL_ID, OPT< VECTOR2D > > m_cursorSettings
Original cursor position, if overridden by the context menu handler.
Definition: tool_manager.h:518
Tool is invoked after being inactive.
Definition: tool_base.h:82
ID_LIST::iterator finishTool(TOOL_STATE *aState)
Function finishTool() Deactivates a tool and does the necessary clean up.
bool dispatchActivation(const TOOL_EVENT &aEvent)
Function dispatchActivation() Checks if it is a valid activation event and invokes a proper tool...
VECTOR2D m_forcedPosition
Forced cursor position (world coordinates)
Definition: view_controls.h:58
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
void attachManager(TOOL_MANAGER *aManager)
Function attachManager()
Definition: tool_base.cpp:59
Class ACTION_MANAGER.
void ScheduleContextMenu(TOOL_BASE *aTool, CONTEXT_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger)
Sets behaviour of the tool&#39;s context popup menu.
int Modifier(int aMask=MD_MODIFIER_MASK) const
Returns information about key modifiers state (Ctrl, Alt, etc.)
Definition: tool_event.h:316
TOOL_ACTION * FindAction(const std::string &aActionName) const
Function FindAction() Finds an action with a given name (if there is one available).
void applyViewControls(TOOL_STATE *aState)
Function applyViewControls() Applies VIEW_CONTROLS settings stored in a TOOL_STATE object...
Class EDA_DRAW_FRAME is the base class for create windows for drawing purpose.
Definition: draw_frame.h:55
int KeyCode() const
Definition: tool_event.h:321
bool IsDirty() const
Function IsDirty() Returns true if any of the VIEW layers needs to be refreshened.
Definition: view.h:548
void Push()
Function Push() Stores the current state of the tool on stack.
void dispatchContextMenu(const TOOL_EVENT &aEvent)
Function dispatchContextMenu() Handles context menu related events.
OPT< TOOL_EVENT > ScheduleWait(TOOL_BASE *aTool, const TOOL_EVENT_LIST &aConditions)
Pauses execution of a given tool until one or more events matching aConditions arrives.
bool runTool(TOOL_ID aToolId)
Function runTool() Makes a tool active, so it can receive events and react to them.
void DeactivateTool()
Function DeactivateTool() Deactivates the currently active tool.
bool InvokeTool(TOOL_ID aToolId)
Function InvokeTool() Calls a tool by sending a tool activation event to tool of given ID...
bool m_passEvent
Flag saying if the currently processed event should be passed to other tools.
Definition: tool_manager.h:529
EDA_ITEM * m_model
Definition: tool_manager.h:520
bool pendingWait
Flag defining if the tool is waiting for any event (i.e.
void SetParameter(T aParam)
Function SetParameter() Sets a non-standard parameter assigned to the event.
Definition: tool_event.h:390
virtual void Reset(RESET_REASON aReason)=0
Function Reset() Brings the tool to a known, initial state.
bool pendingContextMenu
Is there a context menu being displayed.
NAME_STATE_MAP m_toolNameIndex
Index of the registered tools current states, associated by tools&#39; names.
Definition: tool_manager.h:503
int TOOL_ID
Unique identifier for tools.
Definition: tool_base.h:57
virtual void WarpCursor(const VECTOR2D &aPosition, bool aWorldCoordinates=false, bool aWarpView=false)=0
Function WarpCursor() If enabled (.
Class TOOL_EVENT_LIST.
Definition: tool_event.h:473
bool operator!=(const TOOL_MANAGER::TOOL_STATE &aRhs) const
Tool that interacts with the user
Definition: tool_base.h:50
CONTEXT_MENU * Clone() const
Creates a deep, recursive copy of this CONTEXT_MENU.
const auto NULLOPT
Definition: optional.h:9
bool m_forceCursorPosition
Is the forced cursor position enabled
Definition: view_controls.h:61
TOOL_ID m_menuOwner
Tool currently displaying a popup menu. It is negative when there is no menu displayed.
Definition: tool_manager.h:538
wxWindow * m_editFrame
Definition: tool_manager.h:523
void SetEnvironment(EDA_ITEM *aModel, KIGFX::VIEW *aView, KIGFX::VIEW_CONTROLS *aViewControls, wxWindow *aFrame)
Sets the work environment (model, view, view controls and the parent window).
void setActiveState(TOOL_STATE *aState)
Saves the previous active state and sets a new one.
bool ProcessEvent(const TOOL_EVENT &aEvent)
Propagates an event to tools that requested events of matching type(s).
CONTEXT_MENU_TRIGGER
Defines when a context menu is opened.
Definition: tool_event.h:150
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.
void dispatchInternal(const TOOL_EVENT &aEvent)
Function dispatchInternal Passes an event at first to the active tools, then to all others...
Class TOOL_EVENT.
Definition: tool_event.h:162
bool idle
Is the tool active (pending execution) or disabled at the moment.
bool IsActivate() const
Definition: tool_event.h:300
std::stack< std::unique_ptr< TOOL_STATE > > stateStack
Stack preserving previous states of a TOOL.
CONTEXT_MENU * contextMenu
Context menu currently used by the tool.
int GetHotKey(const TOOL_ACTION &aAction) const
Function GetHotKey() Returns the hot key associated with a given action or 0 if there is none...
bool RunHotKey(int aHotKey) const
Function RunHotKey() Runs an action associated with a hotkey (if there is one available).
Structure to keep VIEW_CONTROLS settings for easy store/restore operations
Definition: view_controls.h:44
void ResetTools(TOOL_BASE::RESET_REASON aReason)
Function ResetTools() Resets all tools (i.e.
OPT< std::string > GetCommandStr() const
Definition: tool_event.h:400
Class VIEW_CONTROLS is an interface for classes handling user events controlling the view behaviour (...
int GetPriority(int aToolId) const
Returns priority of a given tool.
virtual void ForceCursorPosition(bool aEnabled, const VECTOR2D &aPosition=VECTOR2D(0, 0))
Function ForceCursorPosition() Places the cursor immediately at a given point.
TOOL_ID GetId() const
Function GetId() Returns the unique identifier of the tool.
Definition: tool_base.h:122
Struct describing the current execution state of a TOOL.
KIGFX::VIEW_CONTROLS * m_viewControls
Definition: tool_manager.h:522
bool Resume()
Function Resume()
Definition: coroutine.h:239
TOOL_STATE * GetCurrentToolState() const
Returns the TOOL_STATE object representing the state of the active tool.
Definition: tool_manager.h:296
void UnregisterAction(TOOL_ACTION *aAction)
Function UnregisterAction() Removes a tool action from the manager and makes it unavailable for furth...
std::function< int(const TOOL_EVENT &)> TOOL_STATE_FUNC
Definition: tool_base.h:59
TOOL_ACTIONS Action() const
Returns more specific information about the type of an event.
Definition: tool_event.h:234
bool isActive(TOOL_BASE *aTool)
Function isActive() Returns information about a tool activation status.
KIGFX::VIEW * m_view
Definition: tool_manager.h:521
std::string GetClipboard() const
Returns the information currently stored in the system clipboard.
void RunMainStack(TOOL_BASE *aTool, std::function< void()> aFunc)
OPT< const TOOL_EVENT & > Matches(const TOOL_EVENT &aEvent) const
Definition: tool_event.h:498
void Refresh(bool aEraseBackground=true, const wxRect *aRect=NULL) override
Update the board display after modifying it bu a python script (note: it is automatically called by a...
TOOL_EVENT_CATEGORY Category() const
Returns the category (eg. mouse/keyboard/action) of an event..
Definition: tool_event.h:228
const VC_SETTINGS & GetSettings() const
Returns the current VIEW_CONTROLS settings
TOOL_EVENT wakeupEvent
The event that triggered the execution/wakeup of the tool after Wait() call.
bool IsMenu() const
Definition: tool_event.h:310
void RegisterAction(TOOL_ACTION *aAction)
Function RegisterAction() Adds a tool action to the manager and sets it up.
TOOL_TYPE GetType() const
Function GetType() Returns the type of the tool.
Definition: tool_base.h:111
TOOL_EVENT MakeEvent() const
Function HasHotKey() Checks if the action has a hot key assigned.
Definition: tool_action.h:104
std::list< TOOL_EVENT > m_eventQueue
Queue that stores events to be processed at the end of the event processing cycle.
Definition: tool_manager.h:526
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void operator=(const TOOL_STATE &aState)
bool Pop()
Function Pop() Restores state of the tool from stack.
TOOL_STATE * m_activeState
Pointer to the state object corresponding to the currently executed tool.
Definition: tool_manager.h:541
COROUTINE< int, const TOOL_EVENT & > * cofunc
Tool execution context.
Class TOOL_BASE.
Definition: tool_base.h:68
Class TOOL_ACTION.
Definition: tool_action.h:46
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:162
bool isRegistered(TOOL_BASE *aTool) const
Function isRegistered() Returns information about a tool registration status.
Definition: tool_manager.h:461
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:80
boost::optional< T > OPT
Definition: optional.h:7
EDA_DRAW_PANEL_GAL * GetGalCanvas() const
Function GetGalCanvas returns a pointer to GAL-based canvas of given EDA draw frame.
Definition: draw_frame.h:895
CONTEXT_MENU_TRIGGER contextMenuTrigger
Defines when the context menu is opened.
void InitTools()
Function InitTools() Initializes all registered tools.
Class VIEW.
Definition: view.h:58
void ClearTransitions(TOOL_BASE *aTool)
Clears the state transition map for a tool.
ID_LIST m_activeTools
Stack of the active tools.
Definition: tool_manager.h:512
TOOL_EVENT_LIST waitEvents
List of events the tool is currently waiting for.
const std::string & GetName() const
Function GetName() Returns the name of the tool.
Definition: tool_base.h:133
bool Running() const
Function Running()
Definition: coroutine.h:280
bool IsClick(int aButtonMask=BUT_ANY) const
Definition: tool_event.h:268
void clear()
Restores the initial state.
void PostEvent(const TOOL_EVENT &aEvent)
Puts an event to the event queue to be processed at the end of event processing cycle.
Definition: tool_manager.h:238
TOOL_STATE_MAP m_toolState
Index of registered tools current states, associated by tools&#39; objects.
Definition: tool_manager.h:500
TOOL_STATE(const TOOL_STATE &aState)
void saveViewControls(TOOL_STATE *aState)
Function saveViewControls() Saves the VIEW_CONTROLS settings to the tool state object.
void UpdateHotKeys()
>
bool invokeTool(TOOL_BASE *aTool)
Function invokeTool() Invokes a tool by sending a proper event (in contrary to runTool, which makes the tool run for real).
void RegisterTool(TOOL_BASE *aTool)
Function RegisterTool() Adds a tool to the manager set and sets it up.
void UnregisterAction(TOOL_ACTION *aAction)
Function UnregisterAction() Unregisters an action, so it is no longer active.
void KiYield()
Function KiYield()
Definition: coroutine.h:156
std::pair< TOOL_EVENT_LIST, TOOL_STATE_FUNC > TRANSITION
Definition: tool_manager.h:376
std::map< const char *, TOOL_BASE * > m_toolTypes
Index of the registered tools to easily lookup by their type.
Definition: tool_manager.h:509