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