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
86std::shared_ptr<const Track> ZoomHandle::FindTrack() const
87{
88 return nullptr;
89}
90
92{
93 return true;
94}
95
98{
99 const wxMouseEvent &event = evt.event;
100 if (event.ButtonDown() || event.LeftDClick()) {
102 mZoomStart = event.m_x;
103 mZoomEnd = event.m_x;
104 mRect = evt.rect;
105 }
107}
108
111{
112 const wxMouseEvent &event = evt.event;
113 const int left = mRect.GetLeft();
114 const int right = mRect.GetRight();
115
116 mZoomEnd = event.m_x;
117
118 if (event.m_x < left) {
119 mZoomEnd = left;
120 }
121 else if (event.m_x > right) {
122 mZoomEnd = right;
123 }
124
125 // Refresh tracks ALWAYS. Even if IsDragZooming() becomes false, make the
126 // dashed lines disappear. -- PRL
127 return RefreshCode::RefreshAll; // (IsDragZooming() ? RefreshAllTracks : RefreshNone),
128}
129
131(const TrackPanelMouseState &st, AudacityProject *pProject)
132{
133 return HitPreview(st.state, pProject);
134}
135
137(const TrackPanelMouseEvent &evt, AudacityProject *pProject,
138 wxWindow *)
139{
140 const wxMouseEvent &event = evt.event;
141 auto &viewInfo = ViewInfo::Get( *pProject );
142 if (mZoomEnd < mZoomStart)
144
145 const int trackLeftEdge = mRect.x;
146 if (IsDragZooming())
147 {
150 double left = viewInfo.PositionToTime(mZoomStart, trackLeftEdge);
151 double right = viewInfo.PositionToTime(mZoomEnd, trackLeftEdge);
152
153 double multiplier =
154 (viewInfo.PositionToTime(mRect.width) - viewInfo.PositionToTime(0)) /
155 (right - left);
156 if (event.ShiftDown())
157 multiplier = 1.0 / multiplier;
158
159 viewInfo.ZoomBy(multiplier);
160
161 viewInfo.hpos = left;
162 }
163 else
164 {
168 const double center_h =
169 viewInfo.PositionToTime(event.m_x, trackLeftEdge);
170
171 const double multiplier =
172 (event.RightUp() || event.RightDClick() || event.ShiftDown())
173 ? 0.5 : 2.0;
174 viewInfo.ZoomBy(multiplier);
175
176 if (event.MiddleUp() || event.MiddleDClick())
177 viewInfo.SetZoom(ZoomInfo::GetDefaultZoom()); // AS: Reset zoom.
178
179 const double new_center_h =
180 viewInfo.PositionToTime(event.m_x, trackLeftEdge);
181
182 viewInfo.hpos += (center_h - new_center_h);
183 }
184
185 mZoomEnd = mZoomStart = 0;
186
187 using namespace RefreshCode;
188 return RefreshAll | FixScrollbars;
189}
190
192{
193 // Cancel is implemented! And there is no initial state to restore,
194 // so just return a code.
196}
197
200 const wxRect &rect, unsigned iPass )
201{
202 if ( iPass == TrackArtist::PassZooming &&
203 // PRL: Draw dashed lines only if we would zoom in
204 // for button up.
205 IsDragZooming() ) {
206 auto &dc = context.dc;
207 dc.SetBrush(*wxTRANSPARENT_BRUSH);
208 dc.SetPen(*wxBLACK_DASHED_PEN);
209 // Make the top and bottom of the dashed rectangle disappear out of
210 // bounds, so that you only see vertical dashed lines.
211 dc.DrawRectangle( {
213 rect.y - 1,
214 1 + abs(mZoomEnd - mZoomStart),
215 rect.height + 2
216 } );
217 }
218}
219
222 const wxRect &rect, const wxRect &panelRect, unsigned iPass )
223{
224 if ( iPass == TrackArtist::PassZooming )
225 return MaximizeHeight( rect, panelRect );
226 else
227 return rect;
228}
229
231{
232 const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
233 return (abs(mZoomEnd - mZoomStart) > DragThreshold);
234}
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:189
const int DragThreshold
Definition: TrackPanel.h:57
std::shared_ptr< Subclass > AssignUIHandlePtr(std::weak_ptr< Subclass > &holder, const std::shared_ptr< Subclass > &pNew)
Definition: UIHandle.h:164
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:40
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:97
Result Cancel(AudacityProject *pProject) override
Definition: ZoomHandle.cpp:191
int mZoomStart
Definition: ZoomHandle.h:70
bool IsDragZooming() const
Definition: ZoomHandle.cpp:230
Result Release(const TrackPanelMouseEvent &event, AudacityProject *pProject, wxWindow *pParent) override
Definition: ZoomHandle.cpp:137
static UIHandlePtr HitAnywhere(std::weak_ptr< ZoomHandle > &holder)
Definition: ZoomHandle.cpp:65
int mZoomEnd
Definition: ZoomHandle.h:70
HitTestPreview Preview(const TrackPanelMouseState &state, AudacityProject *pProject) override
Definition: ZoomHandle.cpp:131
bool HandlesRightClick() override
Whether the handle has any special right-button handling.
Definition: ZoomHandle.cpp:91
wxRect mRect
Definition: ZoomHandle.h:71
static HitTestPreview HitPreview(const wxMouseState &state, const AudacityProject *pProject)
Definition: ZoomHandle.cpp:43
std::shared_ptr< const Track > FindTrack() const override
Definition: ZoomHandle.cpp:86
void Draw(TrackPanelDrawingContext &context, const wxRect &rect, unsigned iPass) override
Definition: ZoomHandle.cpp:198
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:110
wxRect DrawingArea(TrackPanelDrawingContext &, const wxRect &rect, const wxRect &panelRect, unsigned iPass) override
Definition: ZoomHandle.cpp:220
static double GetDefaultZoom()
Definition: ZoomInfo.h:116
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:634