1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.txt for contributors.
5  *
6  * This program is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <class_draw_panel_gal.h>
21 #include <eda_draw_frame.h>
22 #include <id.h>
23 #include <preview_items/selection_area.h>
24 #include <tool/actions.h>
25 #include <tool/tool_manager.h>
26 #include <tool/zoom_tool.h>
27 #include <view/view.h>
28 #include <view/view_controls.h>
29 
30 
ZOOM_TOOL()31 ZOOM_TOOL::ZOOM_TOOL() :
32         TOOL_INTERACTIVE( "common.Control.zoomTool" )
33 {
34     m_frame = nullptr;
35 }
36 
37 
~ZOOM_TOOL()38 ZOOM_TOOL::~ZOOM_TOOL() {}
39 
40 
Reset(RESET_REASON aReason)41 void ZOOM_TOOL::Reset( RESET_REASON aReason )
42 {
43     m_frame = getEditFrame<EDA_DRAW_FRAME>();
44 }
45 
46 
Main(const TOOL_EVENT & aEvent)47 int ZOOM_TOOL::Main( const TOOL_EVENT& aEvent )
48 {
49     std::string tool = aEvent.GetCommandStr().get();
50     m_frame->PushTool( tool );
51 
52     auto setCursor =
53         [&]()
54         {
55             m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ZOOM_IN );
56         };
57 
58     // Set initial cursor
59     setCursor();
60 
61     while( TOOL_EVENT* evt = Wait() )
62     {
63         setCursor();
64 
65         if( evt->IsCancelInteractive() || evt->IsActivate() )
66         {
67             break;
68         }
69         else if( evt->IsDrag( BUT_LEFT ) || evt->IsDrag( BUT_RIGHT ) )
70         {
71             if( selectRegion() )
72                 break;
73         }
74         else
75         {
76             evt->SetPassEvent();
77         }
78     }
79 
80     // Exit zoom tool
81     m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
82     m_frame->PopTool( tool );
83     return 0;
84 }
85 
86 
selectRegion()87 bool ZOOM_TOOL::selectRegion()
88 {
89     bool                cancelled = false;
90     KIGFX::VIEW*        view = getView();
91     EDA_DRAW_PANEL_GAL* canvas = m_frame->GetCanvas();
92 
93     getViewControls()->SetAutoPan( true );
94 
95     KIGFX::PREVIEW::SELECTION_AREA area;
96     view->Add( &area );
97 
98     while( TOOL_EVENT* evt = Wait() )
99     {
100         if( evt->IsCancelInteractive() || evt->IsActivate() )
101         {
102             cancelled = true;
103             break;
104         }
105 
106         if( evt->IsDrag( BUT_LEFT ) || evt->IsDrag( BUT_RIGHT ) )
107         {
108             area.SetOrigin( evt->DragOrigin() );
109             area.SetEnd( evt->Position() );
110             view->SetVisible( &area, true );
111             view->Update( &area, KIGFX::GEOMETRY );
112         }
113 
114         if( evt->IsMouseUp( BUT_LEFT ) || evt->IsMouseUp( BUT_RIGHT ) )
115         {
116             view->SetVisible( &area, false );
117             auto selectionBox = area.ViewBBox();
118 
119             if( selectionBox.GetWidth() == 0 || selectionBox.GetHeight() == 0 )
120             {
121                 break;
122             }
123             else
124             {
125                 VECTOR2D sSize = view->ToWorld( canvas->GetClientSize(), false );
126                 VECTOR2D vSize = selectionBox.GetSize();
127                 double scale;
128                 double ratio = std::max( fabs( vSize.x / sSize.x ), fabs( vSize.y / sSize.y ) );
129 
130                 if( evt->IsMouseUp( BUT_LEFT ) )
131                     scale = view->GetScale() / ratio;
132                 else
133                     scale = view->GetScale() * ratio;
134 
135                 view->SetScale( scale );
136                 view->SetCenter( selectionBox.Centre() );
137 
138                 break;
139             }
140         }
141     }
142 
143     view->SetVisible( &area, false );
144     view->Remove( &area );
145     getViewControls()->SetAutoPan( false );
146 
147     return cancelled;
148 }
149 
150 
setTransitions()151 void ZOOM_TOOL::setTransitions()
152 {
153     Go( &ZOOM_TOOL::Main, ACTIONS::zoomTool.MakeEvent() );
154 }
155