/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2018-2019 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include using namespace std::placeholders; #include #include #include #include #include #include #include #include #include CVPCB_SELECTION_TOOL::CVPCB_SELECTION_TOOL() : TOOL_INTERACTIVE( "cvpcb.InteractiveSelection" ), m_frame( nullptr ) { } bool CVPCB_SELECTION_TOOL::Init() { getEditFrame()->AddStandardSubMenus( m_menu ); return true; } void CVPCB_SELECTION_TOOL::Reset( RESET_REASON aReason ) { m_frame = getEditFrame(); } int CVPCB_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent ) { // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { // This is kind of hacky: activate RMB drag on any event. // There doesn't seem to be any other good way to tell when another tool // is canceled and control returns to the selection tool, except by the // fact that the selection tool starts to get events again. if( m_frame->GetToolId() == ID_NO_TOOL_SELECTED) { getViewControls()->SetAdditionalPanButtons( false, true ); } // Disable RMB pan for other tools; they can re-enable if desired if( evt->IsActivate() ) { getViewControls()->SetAdditionalPanButtons( false, false ); } // single click? Select single object if( evt->IsClick( BUT_LEFT ) ) { clearSelection(); } // right click? if there is any object - show the context menu else if( evt->IsClick( BUT_RIGHT ) ) { m_menu.ShowContextMenu( m_selection ); } else if( evt->IsCancel() || evt->Action() == TA_UNDO_REDO_PRE ) { clearSelection(); } else if( evt->Action() == TA_CHOICE_MENU_CLOSED ) { m_menu.CloseContextMenu( evt ); } else evt->SetPassEvent(); } // This tool is supposed to be active forever wxASSERT( false ); return 0; } int CVPCB_SELECTION_TOOL::MeasureTool( const TOOL_EVENT& aEvent ) { auto& view = *getView(); auto& controls = *getViewControls(); auto previous_settings = controls.GetSettings(); Activate(); m_frame->SetToolID( ID_TB_MEASUREMENT_TOOL, wxCURSOR_PENCIL, _( "Measure distance" ) ); KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER twoPtMgr; KIGFX::PREVIEW::RULER_ITEM ruler( twoPtMgr, m_frame->GetUserUnits() ); view.Add( &ruler ); view.SetVisible( &ruler, false ); bool originSet = false; controls.ShowCursor( true ); controls.SetSnapping( true ); controls.SetAdditionalPanButtons( false, true ); while( auto evt = Wait() ) { const VECTOR2I cursorPos = controls.GetCursorPosition(); if( evt->IsCancel() || evt->IsActivate() ) { break; } // click or drag starts else if( !originSet && ( evt->IsDrag( BUT_LEFT ) || evt->IsClick( BUT_LEFT ) ) ) { if( !evt->IsDrag( BUT_LEFT ) ) { twoPtMgr.SetOrigin( cursorPos ); twoPtMgr.SetEnd( cursorPos ); } controls.CaptureCursor( true ); controls.SetAutoPan( true ); originSet = true; } else if( !originSet && evt->IsMotion() ) { // make sure the origin is set before a drag starts // otherwise you can miss a step twoPtMgr.SetOrigin( cursorPos ); twoPtMgr.SetEnd( cursorPos ); } // second click or mouse up after drag ends else if( originSet && ( evt->IsClick( BUT_LEFT ) || evt->IsMouseUp( BUT_LEFT ) ) ) { originSet = false; controls.SetAutoPan( false ); controls.CaptureCursor( false ); view.SetVisible( &ruler, false ); } // move or drag when origin set updates rules else if( originSet && ( evt->IsMotion() || evt->IsDrag( BUT_LEFT ) ) ) { twoPtMgr.SetAngleSnap( evt->Modifier( MD_CTRL ) ); twoPtMgr.SetEnd( cursorPos ); view.SetVisible( &ruler, true ); view.Update( &ruler, KIGFX::GEOMETRY ); } else if( evt->IsClick( BUT_RIGHT ) ) { m_menu.ShowContextMenu( m_selection ); } } view.SetVisible( &ruler, false ); view.Remove( &ruler ); controls.ApplySettings( previous_settings ); m_frame->SetNoToolSelected(); return 0; } void CVPCB_SELECTION_TOOL::setTransitions() { Go( &CVPCB_SELECTION_TOOL::Main, CVPCB_ACTIONS::selectionActivate.MakeEvent() ); Go( &CVPCB_SELECTION_TOOL::MeasureTool, ACTIONS::measureTool.MakeEvent() ); }