void TOOL_BASE::updateStartItem( const TOOL_EVENT& aEvent, bool aIgnorePads ) { int tl = getView()->GetTopLayer(); VECTOR2I cp = controls()->GetCursorPosition( !aEvent.Modifier( MD_SHIFT ) ); VECTOR2I p; controls()->ForceCursorPosition( false ); m_gridHelper->SetUseGrid( !aEvent.Modifier( MD_ALT ) ); m_gridHelper->SetSnap( !aEvent.Modifier( MD_SHIFT ) ); bool snapEnabled = true; if( aEvent.IsMotion() || aEvent.IsClick() ) { snapEnabled = !aEvent.Modifier( MD_SHIFT ); p = aEvent.Position(); } else { p = cp; } m_startItem = pickSingleItem( p, -1, -1, aIgnorePads ); if( !snapEnabled && m_startItem && !m_startItem->Layers().Overlaps( tl ) ) m_startItem = nullptr; m_startSnapPoint = snapToItem( snapEnabled, m_startItem, p ); if( checkSnap( m_startItem ) ) { controls()->ForceCursorPosition( true, m_startSnapPoint ); } }
void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) { for( TOOL_ID toolId : m_activeTools ) { TOOL_STATE* st = m_toolIdIndex[toolId]; // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode) // or immediately (CMENU_NOW) mode. The latter is used for clarification lists. if( st->contextMenuTrigger != CMENU_OFF ) { if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) ) break; st->pendingWait = true; st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY ); // Store the menu pointer in case it is changed by the TOOL when handling menu events CONTEXT_MENU* m = st->contextMenu; if( st->contextMenuTrigger == CMENU_NOW ) st->contextMenuTrigger = CMENU_OFF; // Temporarily store the cursor position, so the tools could execute actions // using the point where the user has invoked a context menu bool forcedCursor = m_viewControls->IsCursorPositionForced(); VECTOR2D cursorPos = m_viewControls->GetCursorPosition(); m_viewControls->ForceCursorPosition( true, m_viewControls->GetCursorPosition() ); // Run update handlers m->UpdateAll(); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *m ) ); GetEditFrame()->PopupMenu( menu.get() ); // If nothing was chosen from the context menu, we must notify the tool as well if( menu->GetSelected() < 0 ) { TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 ); evt.SetParameter( m ); dispatchInternal( evt ); } TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED ); evt.SetParameter( m ); dispatchInternal( evt ); m_viewControls->ForceCursorPosition( forcedCursor, cursorPos ); break; } } }
void PNS_TOOL_BASE::updateStartItem( TOOL_EVENT& aEvent ) { int tl = getView()->GetTopLayer(); VECTOR2I cp = m_ctls->GetCursorPosition(); VECTOR2I p; PNS_ITEM* startItem = NULL; bool snapEnabled = true; if( aEvent.IsMotion() || aEvent.IsClick() ) { snapEnabled = !aEvent.Modifier( MD_SHIFT ); p = aEvent.Position(); } else { p = cp; } startItem = pickSingleItem( p ); m_router->EnableSnapping( snapEnabled ); if( !snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) ) startItem = NULL; if( startItem && startItem->Net() >= 0 ) { bool dummy; VECTOR2I psnap = snapToItem( startItem, p, dummy ); if( snapEnabled ) { m_startSnapPoint = psnap; m_ctls->ForceCursorPosition( true, psnap ); } else { m_startSnapPoint = cp; m_ctls->ForceCursorPosition( false ); } m_startItem = startItem; } else { m_startItem = NULL; m_startSnapPoint = cp; m_ctls->ForceCursorPosition( false ); } }
void TOOL_MANAGER::dispatchContextMenu( const TOOL_EVENT& aEvent ) { for( TOOL_ID toolId : m_activeTools ) { TOOL_STATE* st = m_toolIdIndex[toolId]; // the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode) // or immediately (CMENU_NOW) mode. The latter is used for clarification lists. if( st->contextMenuTrigger == CMENU_OFF ) continue; if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( BUT_RIGHT ) ) break; st->pendingWait = true; st->waitEvents = TOOL_EVENT( TC_ANY, TA_ANY ); // Store the menu pointer in case it is changed by the TOOL when handling menu events CONTEXT_MENU* m = st->contextMenu; if( st->contextMenuTrigger == CMENU_NOW ) st->contextMenuTrigger = CMENU_OFF; // Store the cursor position, so the tools could execute actions // using the point where the user has invoked a context menu m_menuCursor = m_viewControls->GetCursorPosition(); // Save all tools cursor settings, as they will be overridden for( auto idState : m_toolIdIndex ) { TOOL_STATE* s = idState.second; const auto& vc = s->vcSettings; if( vc.m_forceCursorPosition ) m_cursorSettings[idState.first] = vc.m_forcedPosition; else m_cursorSettings[idState.first] = NULLOPT; } m_viewControls->ForceCursorPosition( true, m_menuCursor ); // Display a copy of menu std::unique_ptr<CONTEXT_MENU> menu( m->Clone() ); // Run update handlers on the created copy menu->UpdateAll(); m_menuOwner = toolId; m_menuActive = true; auto frame = dynamic_cast<wxFrame*>( m_editFrame ); if( frame ) frame->PopupMenu( menu.get() ); // Warp the cursor as long as the menu wasn't clicked out of if( menu->GetSelected() >= 0 ) m_viewControls->WarpCursor( m_menuCursor, true, false ); // Otherwise notify the tool of a cancelled menu else { TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CHOICE, -1 ); evt.SetParameter( m ); dispatchInternal( evt ); } // Notify the tools that menu has been closed TOOL_EVENT evt( TC_COMMAND, TA_CONTEXT_MENU_CLOSED ); evt.SetParameter( m ); dispatchInternal( evt ); m_menuActive = false; m_menuOwner = -1; // Restore cursor settings for( auto cursorSetting : m_cursorSettings ) { auto it = m_toolIdIndex.find( cursorSetting.first ); wxASSERT( it != m_toolIdIndex.end() ); if( it == m_toolIdIndex.end() ) continue; KIGFX::VC_SETTINGS& vc = it->second->vcSettings; vc.m_forceCursorPosition = (bool) cursorSetting.second; vc.m_forcedPosition = cursorSetting.second ? *cursorSetting.second : VECTOR2D( 0, 0 ); } m_cursorSettings.clear(); break; } }