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