Audacity  3.0.3
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 
41 DEFINE_EVENT_TYPE(EVT_GRABBER_CLICKED)
42 
43 BEGIN_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 //
56 Grabber::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 //
86 void 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 
100 void 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 //
118 void 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 //
188 void 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 //
205 void 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 //
219 void 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 //
232 void 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 //
261 void 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 
280 void Grabber::OnErase( wxEraseEvent & WXUNUSED(event) )
281 {
282  // Ignore it to prevent flashing
283 }
284 
285 //
286 // Handle the paint events
287 //
288 void Grabber::OnPaint(wxPaintEvent & WXUNUSED(event))
289 {
290  wxPaintDC dc(this);
291 
292  // Redraw the grabber
293  DrawGrabber(dc);
294 }
295 
296 void 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.
310 BEGIN_EVENT_TABLE(AStaticBitmap,wxStaticBitmap)
311  EVT_ERASE_BACKGROUND(AStaticBitmap::OnErase)
313 
314 
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
Grabber.h
Grabber::OnPaint
void OnPaint(wxPaintEvent &event)
Definition: Grabber.cpp:288
AllThemeResources.h
Grabber::OnEnter
void OnEnter(wxMouseEvent &event)
Definition: Grabber.cpp:232
Grabber::~Grabber
virtual ~Grabber()
Definition: Grabber.cpp:79
DEFINE_EVENT_TYPE
DEFINE_EVENT_TYPE(EVT_FREQWINDOW_RECALC)
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:109
AStaticBitmap
A widget for bitmaps which ignores the erase event for flicker-free use.
Definition: Grabber.h:150
Grabber
The widget to the left of a ToolBar that allows it to be dragged around to NEW positions.
Definition: Grabber.h:103
grabberWidth
#define grabberWidth
Definition: Grabber.h:100
Grabber::OnErase
void OnErase(wxEraseEvent &event)
Definition: Grabber.cpp:280
Grabber::SetToolTip
void SetToolTip(const TranslatableString &toolTip)
Definition: Grabber.cpp:110
Grabber::mOver
bool mOver
Definition: Grabber.h:139
AColor::Light
static void Light(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:321
Theme.h
Grabber::OnLeftUp
void OnLeftUp(wxMouseEvent &event)
Definition: Grabber.cpp:219
Grabber::PushButton
void PushButton(bool state)
Definition: Grabber.cpp:188
AStaticBitmap::OnErase
void OnErase(wxEraseEvent &event)
Definition: Grabber.h:168
GrabberEvent
Grabber Class.
Definition: Grabber.h:48
AColor::Medium
static void Medium(wxDC *dc, bool selected)
Definition: AColor.cpp:332
Grabber::OnLeave
void OnLeave(wxMouseEvent &event)
Definition: Grabber.cpp:261
Grabber::SetAsSpacer
void SetAsSpacer(bool bIsSpacer)
Definition: Grabber.cpp:100
theTheme
THEME_API Theme theTheme
Definition: Theme.cpp:79
Internat.h
AColor::Bevel
static void Bevel(wxDC &dc, bool up, const wxRect &r)
Definition: AColor.cpp:188
Grabber::mAsSpacer
bool mAsSpacer
Definition: Grabber.h:141
AColor::Dark
static void Dark(wxDC *dc, bool selected, bool highlight=false)
Definition: AColor.cpp:351
_
#define _(s)
Definition: Internat.h:75
Grabber::OnKeyDown
void OnKeyDown(wxKeyEvent &event)
Definition: Grabber.cpp:296
ThemeBase::Colour
wxColour & Colour(int iIndex)
Definition: Theme.cpp:1189
Grabber::SendEvent
void SendEvent(wxEventType type, const wxPoint &pos, bool escaping)
Definition: Grabber.cpp:86
Grabber::DrawGrabber
void DrawGrabber(wxDC &dc)
Definition: Grabber.cpp:118
TranslatableString::Translation
wxString Translation() const
Definition: TranslatableString.h:79
Grabber::OnLeftDown
void OnLeftDown(wxMouseEvent &event)
Definition: Grabber.cpp:205
TranslatableString::Stripped
TranslatableString Stripped(unsigned options=MenuCodes) const
non-mutating, constructs another TranslatableString object
Definition: TranslatableString.h:198
AColor.h
END_EVENT_TABLE
END_EVENT_TABLE()
Grabber::mPressed
bool mPressed
Definition: Grabber.h:140