Audacity 3.2.0
ZoomHandle.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5ZoomHandle.cpp
6
7Paul Licameli split from TrackPanel.cpp
8
9**********************************************************************/
10
11
12#include "ZoomHandle.h"
13
14#include <algorithm>
15
16#include <wx/dc.h>
17#include <wx/event.h>
18#include <wx/gdicmn.h>
19
20#include "../../HitTestResult.h"
21#include "../../RefreshCode.h"
22#include "../../TrackArtist.h"
23#include "../../TrackPanelDrawingContext.h"
24#include "../../TrackPanelMouseEvent.h"
25#include "ViewInfo.h"
26#include "../../../images/Cursors.h"
27
38
40{}
41
43 (const wxMouseState &state, const AudacityProject *WXUNUSED(pProject))
44{
45 static auto zoomInCursor =
46 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomInCursorXpm, 19, 15);
47 static auto zoomOutCursor =
48 ::MakeCursor(wxCURSOR_MAGNIFIER, ZoomOutCursorXpm, 19, 15);
49 TranslatableString message;
50 // TODO: Why not mention middle click to zoom normal on Windows too?
51#if defined( __WXMAC__ )
52 message = XO("Click to Zoom In, Shift-Click to Zoom Out");
53#elif defined( __WXMSW__ )
54 message = XO("Drag to Zoom Into Region, Right-Click to Zoom Out");
55#elif defined( __WXGTK__ )
56 message = XO("Left=Zoom In, Right=Zoom Out, Middle=Normal");
57#endif
58 return {
59 message,
60 (state.ShiftDown() ? &*zoomOutCursor : &*zoomInCursor)
61 };
62}
63
65(std::weak_ptr<ZoomHandle> &holder)
66{
67 auto result = std::make_shared<ZoomHandle>();
68 result = AssignUIHandlePtr(holder, result);
69 return result;
70}
71
73(std::weak_ptr<ZoomHandle> &holder,
74 const wxMouseState &state)
75{
76 if (state.ButtonIsDown(wxMOUSE_BTN_RIGHT))
77 return HitAnywhere(holder);
78 else
79 return {};
80}
81
83{
84}
85
87{
88 return true;
89}
90
93{
94 const wxMouseEvent &event = evt.event;
95 if (event.ButtonDown() || event.LeftDClick()) {
97 mZoomStart = event.m_x;
98 mZoomEnd = event.m_x;
99 mRect = evt.rect;
100 }
102}
103
106{
107 const wxMouseEvent &event = evt.event;
108 const int left = mRect.GetLeft();
109 const int right = mRect.GetRight();
110
111 mZoomEnd = event.m_x;
112
113 if (event.m_x < left) {
114 mZoomEnd = left;
115 }
116 else if (event.m_x > right) {
117 mZoomEnd = right;
118 }
119
120 // Refresh tracks ALWAYS. Even if IsDragZooming() becomes false, make the
121 // dashed lines disappear. -- PRL
122 return RefreshCode::RefreshAll; // (IsDragZooming() ? RefreshAllTracks : RefreshNone),
123}
124
126(const TrackPanelMouseState &st, AudacityProject *pProject)
127{
128 return HitPreview(st.state, pProject);
129}
130
132(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
133 wxWindow *)
134{
135 const wxMouseEvent &event = evt.event;
136 auto &viewInfo = ViewInfo::Get( *pProject );
137 if (mZoomEnd < mZoomStart)
139
140 const int trackLeftEdge = mRect.x;
141 if (IsDragZooming())
142 {
145 double left = viewInfo.PositionToTime(mZoomStart, trackLeftEdge);
146 double right = viewInfo.PositionToTime(mZoomEnd, trackLeftEdge);
147
148 double multiplier =
149 (viewInfo.PositionToTime(mRect.width) - viewInfo.PositionToTime(0)) /
150 (right - left);
151 if (event.ShiftDown())
152 multiplier = 1.0 / multiplier;
153
154 viewInfo.ZoomBy(multiplier);
155
156 viewInfo.h = left;
157 }
158 else
159 {
163 const double center_h =
164 viewInfo.PositionToTime(event.m_x, trackLeftEdge);
165
166 const double multiplier =
167 (event.RightUp() || event.RightDClick() || event.ShiftDown())
168 ? 0.5 : 2.0;
169 viewInfo.ZoomBy(multiplier);
170
171 if (event.MiddleUp() || event.MiddleDClick())
172 viewInfo.SetZoom(ZoomInfo::GetDefaultZoom()); // AS: Reset zoom.
173
174 const double new_center_h =
175 viewInfo.PositionToTime(event.m_x, trackLeftEdge);
176
177 viewInfo.h += (center_h - new_center_h);
178 }
179
180 mZoomEnd = mZoomStart = 0;
181
182 using namespace RefreshCode;
183 return RefreshAll | FixScrollbars;
184}
185
187{
188 // Cancel is implemented! And there is no initial state to restore,
189 // so just return a code.
191}
192
195 const wxRect &rect, unsigned iPass )
196{
197 if ( iPass == TrackArtist::PassZooming &&
198 // PRL: Draw dashed lines only if we would zoom in
199 // for button up.
200 IsDragZooming() ) {
201 auto &dc = context.dc;
202 dc.SetBrush(*wxTRANSPARENT_BRUSH);
203 dc.SetPen(*wxBLACK_DASHED_PEN);
204 // Make the top and bottom of the dashed rectangle disappear out of
205 // bounds, so that you only see vertical dashed lines.
206 dc.DrawRectangle( {
208 rect.y - 1,
209 1 + abs(mZoomEnd - mZoomStart),
210 rect.height + 2
211 } );
212 }
213}
214
217 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
218{
219 if ( iPass == TrackArtist::PassZooming )
220 return MaximizeHeight( rect, panelRect );
221 else
222 return rect;
223}
224
226{
227 const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
228 return (abs(mZoomEnd - mZoomStart) > DragThreshold);
229}
std::shared_ptr< UIHandle > UIHandlePtr
Definition: CellularPanel.h:28
int min(int a, int b)
XO("Cut/Copy/Paste")
std::unique_ptr< wxCursor > MakeCursor(int WXUNUSED(CursorId), const char *const pXpm[36], int HotX, int HotY)
Definition: TrackPanel.cpp:186
const int DragThreshold
Definition: TrackPanel.h:59
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:151
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
static wxRect MaximizeHeight(const wxRect &rect, const wxRect &panelRect)
Holds a msgid for the translation catalog; may also bind format arguments.
unsigned Result
Definition: UIHandle.h:38
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
virtual ~ZoomHandle()
Definition: ZoomHandle.cpp:82
Result Click(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: ZoomHandle.cpp:92
Result Cancel(AudacityProject *pProject) override
Definition: ZoomHandle.cpp:186
int mZoomStart
Definition: ZoomHandle.h:68
bool IsDragZooming() const
Definition: ZoomHandle.cpp:225
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: ZoomHandle.cpp:132
static UIHandlePtr HitAnywhere(std::weak_ptr< ZoomHandle > &holder)
Definition: ZoomHandle.cpp:65
int mZoomEnd
Definition: ZoomHandle.h:68
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: ZoomHandle.cpp:126
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
Definition: ZoomHandle.cpp:86
wxRect mRect
Definition: ZoomHandle.h:69
static HitTestPreview HitPreview(const wxMouseState &state, const AudacityProject *pProject)
Definition: ZoomHandle.cpp:43
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: ZoomHandle.cpp:193
static UIHandlePtr HitTest(std::weak_ptr< ZoomHandle > &holder, const wxMouseState &state)
Definition: ZoomHandle.cpp:73
Result Drag(const TrackPanelMouseEvent &event, AudacityProject *pProject) override
Definition: ZoomHandle.cpp:105
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
Definition: ZoomHandle.cpp:215
static double GetDefaultZoom()
Definition: ZoomInfo.h:113
Namespace containing an enum 'what to do on a refresh?'.
Definition: RefreshCode.h:16
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:752