Audacity 3.2.0
Grabber.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Grabber.cpp
6
7 Leland Lucius
8
9*******************************************************************//*******************************************************************//**********************************************************************/
22
23
24#include "Grabber.h"
25
26#include <wx/defs.h>
27#include <wx/dcclient.h>
28#include <wx/event.h>
29#include <wx/intl.h>
30#include <wx/window.h>
31
32#include "AColor.h"
33#include "AllThemeResources.h"
34#include "Internat.h"
35#include "Theme.h"
36
40
41DEFINE_EVENT_TYPE(EVT_GRABBER_CLICKED)
42
43BEGIN_EVENT_TABLE(Grabber, wxWindow)
44 EVT_ENTER_WINDOW(Grabber::OnEnter)
45 EVT_LEAVE_WINDOW(Grabber::OnLeave)
46 EVT_LEFT_DOWN(Grabber::OnLeftDown)
47 EVT_LEFT_UP(Grabber::OnLeftUp)
48 EVT_ERASE_BACKGROUND( Grabber::OnErase )
49 EVT_PAINT(Grabber::OnPaint)
50 EVT_KEY_DOWN(Grabber::OnKeyDown)
52
53//
54// Constructor
55//
56Grabber::Grabber(wxWindow * parent, wxWindowID id)
57: wxWindow(parent,
58 id,
59 wxDefaultPosition,
60 wxSize(grabberWidth, 27),
61 wxFULL_REPAINT_ON_RESIZE)
62{
63 mOver = false;
64 mPressed = false;
65 mAsSpacer = false;
66 SetBackgroundColour( theTheme.Colour( clrMedium ) );
67
68 /* i18n-hint: A 'Grabber' is a region you can click and drag on
69 It's used to drag a track around (when in multi-tool mode) rather
70 than requiring that you use the drag tool. It's shown as a series
71 of horizontal bumps */
72 SetLabel(_("Grabber"));
73 SetName(_("Grabber"));
74}
75
76//
77// Destructor
78//
80{
81}
82
83//
84// Queue a drag event
85//
86void Grabber::SendEvent(wxEventType type, const wxPoint & pos, bool escaping)
87{
88 wxWindow *parent = GetParent();
89
90 // Initialize event and convert mouse coordinates to screen space
91 GrabberEvent e(type, GetId(), parent->ClientToScreen(pos), escaping);
92
93 // Set the object of our desire
94 e.SetEventObject(parent);
95
96 // Queue the event
97 parent->GetEventHandler()->AddPendingEvent(e);
98}
99
100void Grabber::SetAsSpacer( bool bIsSpacer ) {
101 if( mAsSpacer != bIsSpacer ){
102 // HACK: Use a wider rectangle to also cover one pixel of space just to the right.
103 wxSize siz = GetSize();
104 siz.IncBy( bIsSpacer ? 1:-1, 0 );
105 SetSize( siz );
106 }
107 mAsSpacer = bIsSpacer;
108};
109
111{
112 wxWindow::SetToolTip( toolTip.Stripped().Translation() );
113}
114
115//
116// Draw the grabber
117//
118void Grabber::DrawGrabber( wxDC & dc )
119{
120 wxRect r = GetRect();
121 // PaintDC positions are relative to the grabber, not the parent window.
122 // So use 0,0 as origin for draw, so that the grabber draws right if
123 // positioned in its parent at some non zero position.
124 r.SetPosition( wxPoint(0,0) );
125 int y, left, right, top, bottom;
126
127 AColor::Medium(&dc, mOver );
128 dc.DrawRectangle(r);
129
130 // HACK: We used a wider rectangle to also cover one pixel of space just to the right.
131 if( mAsSpacer )
132 r.width -= 1;
133
134#ifndef __WXMAC__
135
136 // Add a box
137 r.width -= 1;
138 r.height -= 1;
139 AColor::Bevel(dc, !mPressed, r);
140 r.width += 1;
141 r.height += 1;
142
143#endif
144
145 // No bumps in a spacer grabber.
146 if( mAsSpacer )
147 return;
148 // Calculate the bump rectangle
149 r.Deflate(3, 3);
150 if ((r.GetHeight() % 4) < 2) {
151 r.Offset(0, 1);
152 }
153
154 // Cache
155 left = r.GetLeft();
156 right = r.GetRight();
157 top = r.GetTop();
158 bottom = r.GetBottom();
159
160 // Draw the raised bumps
161 if (mPressed) {
162 AColor::Dark(&dc, false);
163 }
164 else {
165 AColor::Light(&dc, false);
166 }
167
168 for (y = top; y < bottom; y += 4) {
169 AColor::Line(dc, left, y, right, y);
170 }
171
172 // Draw the pushed bumps
173 if (mPressed) {
174 AColor::Light(&dc, false);
175 }
176 else {
177 AColor::Dark(&dc, false);
178 }
179
180 for (y = top + 1; y <= bottom; y += 4) {
181 AColor::Line(dc, left, y, right, y);
182 }
183}
184
185//
186// Change the button state
187//
188void Grabber::PushButton(bool state )
189{
190 if( mAsSpacer )
191 return;
192 if (!state)
193 mPressed = state;
194 wxRect r = GetRect();
195 mOver = r.Contains(ScreenToClient(wxGetMousePosition()));
196
197 // Redraw button
198 mPressed = state;
199 Refresh(false);
200}
201
202//
203// Handle left button down events
204//
205void Grabber::OnLeftDown(wxMouseEvent & event)
206{
207 // Button should be drawn pushed
208 PushButton(true);
209
210 // Notify parent
211 SendEvent(EVT_GRABBER_CLICKED, event.GetPosition(), false);
212
213 event.Skip();
214}
215
216//
217// Handle left button up events
218//
219void Grabber::OnLeftUp(wxMouseEvent & event)
220{
221 // Normally, "left up" events are handled by the ToolManager::OnMouse() method
222 // but, if the user double clicks a grabber, the "left up" event will come here
223 // instead, so just "unpush" the button.
224 PushButton(false);
225
226 event.Skip();
227}
228
229//
230// Handle mouse enter events
231//
232void Grabber::OnEnter(wxMouseEvent & WXUNUSED(event))
233{
234#if defined(__WXMAC__)
235 // Bug 2416: On Mac, we can get Enter events from grabbers other
236 // than the one being dragged. So, ignore Enter events if another
237 // window has captured the mouse.
238 if (wxWindow::GetCapture() != nullptr)
239 {
240 return;
241 }
242#endif
243
244 // Bug 1201: On Mac, unsetting and re-setting the tooltip may be needed
245 // to make it pop up when we want it.
246 const auto text = GetToolTipText();
247 UnsetToolTip();
248 wxWindow::SetToolTip(text);
249
250 if( mAsSpacer )
251 return;
252
253 // Redraw highlighted
254 mOver = true;
255 Refresh(false);
256}
257
258//
259// Handle mouse leave events
260//
261void Grabber::OnLeave(wxMouseEvent & WXUNUSED(event))
262{
263#if defined(__WXMAC__)
264 // Bug 2416: On Mac, we can get Leave events from grabbers other
265 // than the one being dragged. So, ignore Leave events if another
266 // window has captured the mouse.
267 if (wxWindow::GetCapture() != nullptr)
268 {
269 return;
270 }
271#endif
272
273 if (!GetCapture()) {
274 // Redraw plain
275 mOver = false;
276 Refresh(false);
277 }
278}
279
280void Grabber::OnErase( wxEraseEvent & WXUNUSED(event) )
281{
282 // Ignore it to prevent flashing
283}
284
285//
286// Handle the paint events
287//
288void Grabber::OnPaint(wxPaintEvent & WXUNUSED(event))
289{
290 wxPaintDC dc(this);
291
292 // Redraw the grabber
293 DrawGrabber(dc);
294}
295
296void Grabber::OnKeyDown(wxKeyEvent &event)
297{
298 event.Skip();
299
300 if(event.GetKeyCode() == WXK_ESCAPE) {
301 // We must not only skip this key event, but propagate it up the window
302 // hierarchy, so that ToolFrame detects it too.
303 event.ResumePropagation(wxEVENT_PROPAGATE_MAX);
304 SendEvent(EVT_GRABBER_CLICKED, wxPoint{ -1, -1 }, true);
305 }
306}
307
308// Piggy back in same source file as Grabber.
309// Audacity Flicker-free StaticBitmap.
310BEGIN_EVENT_TABLE(AStaticBitmap,wxStaticBitmap)
311 EVT_ERASE_BACKGROUND(AStaticBitmap::OnErase)
313
314
END_EVENT_TABLE()
DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC)
#define grabberWidth
Definition: Grabber.h:100
#define _(s)
Definition: Internat.h:75
THEME_API Theme theTheme
Definition: Theme.cpp:82
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:187
static void Bevel(wxDC &dc, bool up, const wxRect &r)
Definition: AColor.cpp:266
static void Light(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:413
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:443
static void Medium(wxDC *dc, bool selected)
Definition: AColor.cpp:424
A widget for bitmaps which ignores the erase event for flicker-free use.
Definition: Grabber.h:150
void OnErase(wxEraseEvent &event)
Definition: Grabber.h:168
Grabber Class.
Definition: Grabber.h:48
The widget to the left of a ToolBar that allows it to be dragged around to NEW positions.
Definition: Grabber.h:103
void SendEvent(wxEventType type, const wxPoint &pos, bool escaping)
Definition: Grabber.cpp:86
void OnLeftUp(wxMouseEvent &event)
Definition: Grabber.cpp:219
void SetAsSpacer(bool bIsSpacer)
Definition: Grabber.cpp:100
bool mAsSpacer
Definition: Grabber.h:141
void DrawGrabber(wxDC &dc)
Definition: Grabber.cpp:118
virtual ~Grabber()
Definition: Grabber.cpp:79
void OnLeave(wxMouseEvent &event)
Definition: Grabber.cpp:261
bool mOver
Definition: Grabber.h:139
void OnErase(wxEraseEvent &event)
Definition: Grabber.cpp:280
void OnPaint(wxPaintEvent &event)
Definition: Grabber.cpp:288
void OnLeftDown(wxMouseEvent &event)
Definition: Grabber.cpp:205
void OnKeyDown(wxKeyEvent &event)
Definition: Grabber.cpp:296
void OnEnter(wxMouseEvent &event)
Definition: Grabber.cpp:232
bool mPressed
Definition: Grabber.h:140
void SetToolTip(const TranslatableString &toolTip)
Definition: Grabber.cpp:110
void PushButton(bool state)
Definition: Grabber.cpp:188
wxColour & Colour(int iIndex)
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
TranslatableString Stripped(unsigned options=MenuCodes) const
non-mutating, constructs another TranslatableString object