ardour
pixfader.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18  $Id: fastmeter.h 570 2006-06-07 21:21:21Z sampo $
19 */
20 
21 
22 #include <iostream>
23 #include <assert.h>
24 
25 #include "pbd/stacktrace.h"
26 
27 #include "gtkmm2ext/cairo_widget.h"
28 #include "gtkmm2ext/keyboard.h"
29 #include "gtkmm2ext/pixfader.h"
30 #include "gtkmm2ext/utils.h"
31 
32 using namespace Gtkmm2ext;
33 using namespace Gtk;
34 using namespace std;
35 
36 #define CORNER_RADIUS 2.5
37 #define CORNER_SIZE 2
38 #define CORNER_OFFSET 1
39 #define FADER_RESERVE 6
40 
41 std::list<PixFader::FaderImage*> PixFader::_patterns;
42 
43 PixFader::PixFader (Gtk::Adjustment& adj, int orientation, int fader_length, int fader_girth)
44  : _layout (0)
45  , _tweaks (Tweaks(0))
46  , _adjustment (adj)
47  , _text_width (0)
48  , _text_height (0)
49  , _span (fader_length)
50  , _girth (fader_girth)
51  , _min_span (fader_length)
52  , _min_girth (fader_girth)
53  , _orien (orientation)
54  , _pattern (0)
55  , _hovering (false)
56  , _dragging (false)
57  , _centered_text (true)
58  , _current_parent (0)
59 {
60  _default_value = _adjustment.get_value();
62 
63  add_events (
64  Gdk::BUTTON_PRESS_MASK
65  | Gdk::BUTTON_RELEASE_MASK
66  | Gdk::POINTER_MOTION_MASK
67  | Gdk::SCROLL_MASK
68  | Gdk::ENTER_NOTIFY_MASK
69  | Gdk::LEAVE_NOTIFY_MASK
70  );
71 
72  _adjustment.signal_value_changed().connect (mem_fun (*this, &PixFader::adjustment_changed));
73  _adjustment.signal_changed().connect (mem_fun (*this, &PixFader::adjustment_changed));
74 
75  if (_orien == VERT) {
76  CairoWidget::set_size_request(_girth, _span);
77  } else {
78  CairoWidget::set_size_request(_span, _girth);
79  }
80 }
81 
83 {
85  if (_layout) _layout.clear (); // drop reference to existing layout
86 }
87 
88 cairo_pattern_t*
89 PixFader::find_pattern (double afr, double afg, double afb,
90  double abr, double abg, double abb,
91  int w, int h)
92 {
93  for (list<FaderImage*>::iterator f = _patterns.begin(); f != _patterns.end(); ++f) {
94  if ((*f)->matches (afr, afg, afb, abr, abg, abb, w, h)) {
95  return (*f)->pattern;
96  }
97  }
98  return 0;
99 }
100 
101 void
103 {
104  Gdk::Color c = get_style()->get_fg (get_state());
105  float fr, fg, fb;
106  float br, bg, bb;
107 
108  fr = c.get_red_p ();
109  fg = c.get_green_p ();
110  fb = c.get_blue_p ();
111 
112  c = get_style()->get_bg (get_state());
113 
114  br = c.get_red_p ();
115  bg = c.get_green_p ();
116  bb = c.get_blue_p ();
117 
118  cairo_surface_t* surface;
119  cairo_t* tc = 0;
120 
121  if (get_width() <= 1 || get_height() <= 1) {
122  return;
123  }
124 
125  if ((_pattern = find_pattern (fr, fg, fb, br, bg, bb, get_width(), get_height())) != 0) {
126  /* found it - use it */
127  return;
128  }
129 
130  if (_orien == VERT) {
131 
132  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, get_width(), get_height() * 2.0);
133  tc = cairo_create (surface);
134 
135  /* paint background + border */
136 
137  cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, get_width(), 0);
138  cairo_pattern_add_color_stop_rgba (shade_pattern, 0, br*0.4,bg*0.4,bb*0.4, 1.0);
139  cairo_pattern_add_color_stop_rgba (shade_pattern, 0.25, br*0.6,bg*0.6,bb*0.6, 1.0);
140  cairo_pattern_add_color_stop_rgba (shade_pattern, 1, br*0.8,bg*0.8,bb*0.8, 1.0);
141  cairo_set_source (tc, shade_pattern);
142  cairo_rectangle (tc, 0, 0, get_width(), get_height() * 2.0);
143  cairo_fill (tc);
144 
145  cairo_pattern_destroy (shade_pattern);
146 
147  /* paint lower shade */
148 
149  shade_pattern = cairo_pattern_create_linear (0.0, 0.0, get_width() - 2 - CORNER_OFFSET , 0);
150  cairo_pattern_add_color_stop_rgba (shade_pattern, 0, fr*0.8,fg*0.8,fb*0.8, 1.0);
151  cairo_pattern_add_color_stop_rgba (shade_pattern, 1, fr*0.6,fg*0.6,fb*0.6, 1.0);
152  cairo_set_source (tc, shade_pattern);
154  get_width() - CORNER_SIZE, get_height(), CORNER_RADIUS);
155  cairo_fill (tc);
156 
157  cairo_pattern_destroy (shade_pattern);
158 
159  _pattern = cairo_pattern_create_for_surface (surface);
160 
161  } else {
162 
163  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, get_width() * 2.0, get_height());
164  tc = cairo_create (surface);
165 
166  /* paint right shade (background section)*/
167 
168  cairo_pattern_t* shade_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
169  cairo_pattern_add_color_stop_rgba (shade_pattern, 0, br*0.4,bg*0.4,bb*0.4, 1.0);
170  cairo_pattern_add_color_stop_rgba (shade_pattern, 0.25, br*0.6,bg*0.6,bb*0.6, 1.0);
171  cairo_pattern_add_color_stop_rgba (shade_pattern, 1, br*0.8,bg*0.8,bb*0.8, 1.0);
172  cairo_set_source (tc, shade_pattern);
173  cairo_rectangle (tc, 0, 0, get_width() * 2.0, get_height());
174  cairo_fill (tc);
175 
176  /* paint left shade (active section/foreground) */
177 
178  shade_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height());
179  cairo_pattern_add_color_stop_rgba (shade_pattern, 0, fr*0.8,fg*0.8,fb*0.8, 1.0);
180  cairo_pattern_add_color_stop_rgba (shade_pattern, 1, fr*0.6,fg*0.6,fb*0.6, 1.0);
181  cairo_set_source (tc, shade_pattern);
183  get_width() - CORNER_OFFSET, get_height() - CORNER_SIZE, CORNER_RADIUS);
184  cairo_fill (tc);
185  cairo_pattern_destroy (shade_pattern);
186 
187  _pattern = cairo_pattern_create_for_surface (surface);
188  }
189 
190  /* cache it for others to use */
191 
192  _patterns.push_back (new FaderImage (_pattern, fr, fg, fb, br, bg, bb, get_width(), get_height()));
193 
194  cairo_destroy (tc);
195  cairo_surface_destroy (surface);
196 }
197 
198 void
199 PixFader::render (cairo_t *cr, cairo_rectangle_t* area)
200 {
201  if (!_pattern) {
202  create_patterns();
203  }
204 
205  if (!_pattern) {
206  /* this isn't supposed to be happen, but some wackiness whereby
207  * the pixfader ends up with a 1xN or Nx1 size allocation
208  * leads to it. the basic wackiness needs fixing but we
209  * shouldn't crash. just fill in the expose area with
210  * our bg color.
211  */
212 
213  CairoWidget::set_source_rgb_a (cr, get_style()->get_bg (get_state()), 1);
214  cairo_rectangle (cr, area->x, area->y, area->width, area->height);
215  cairo_fill (cr);
216  return;
217  }
218 
219  OnExpose();
220  int ds = display_span ();
221  const float w = get_width();
222  const float h = get_height();
223 
225  cairo_rectangle (cr, 0, 0, w, h);
226  cairo_fill(cr);
227 
228  cairo_set_line_width (cr, 2);
229  cairo_set_source_rgba (cr, 0, 0, 0, 1.0);
230 
231  cairo_matrix_t matrix;
233  // we use a 'trick' here: The stoke is off by .5px but filling the interior area
234  // after a stroke of 2px width results in an outline of 1px
235  cairo_stroke_preserve(cr);
236 
237  if (_orien == VERT) {
238 
239  if (ds > h - FADER_RESERVE - CORNER_OFFSET) {
240  ds = h - FADER_RESERVE - CORNER_OFFSET;
241  }
242 
243  if (!CairoWidget::flat_buttons() ) {
244  cairo_set_source (cr, _pattern);
245  cairo_matrix_init_translate (&matrix, 0, (h - ds));
246  cairo_pattern_set_matrix (_pattern, &matrix);
247  } else {
248  CairoWidget::set_source_rgb_a (cr, get_style()->get_bg (get_state()), 1);
249  cairo_fill (cr);
250  CairoWidget::set_source_rgb_a (cr, get_style()->get_fg (get_state()), 1);
252  w - CORNER_SIZE, h - ds - CORNER_SIZE, CORNER_RADIUS);
253  }
254  cairo_fill (cr);
255 
256  } else {
257 
258  if (ds < FADER_RESERVE) {
259  ds = FADER_RESERVE;
260  }
261  assert(ds <= w);
262 
263  /*
264  * if ds == w, the pattern does not need to be translated
265  * if ds == 0 (or FADER_RESERVE), the pattern needs to be moved
266  * w to the left, which is -w in pattern space, and w in user space
267  * if ds == 10, then the pattern needs to be moved w - 10
268  * to the left, which is -(w-10) in pattern space, which
269  * is (w - 10) in user space
270  * thus: translation = (w - ds)
271  */
272 
273  if (!CairoWidget::flat_buttons() ) {
274  cairo_set_source (cr, _pattern);
275  cairo_matrix_init_translate (&matrix, w - ds, 0);
276  cairo_pattern_set_matrix (_pattern, &matrix);
277  } else {
278  CairoWidget::set_source_rgb_a (cr, get_style()->get_bg (get_state()), 1);
279  cairo_fill (cr);
280  CairoWidget::set_source_rgb_a (cr, get_style()->get_fg (get_state()), 1);
283  }
284  cairo_fill (cr);
285  }
286 
287  /* draw the unity-position line if it's not at either end*/
289  cairo_set_line_width(cr, 1);
290  cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
291  Gdk::Color c = get_style()->get_fg (Gtk::STATE_ACTIVE);
292  cairo_set_source_rgba (cr, c.get_red_p() * 1.5, c.get_green_p() * 1.5, c.get_blue_p() * 1.5, 0.85);
293  if (_orien == VERT) {
294  if (_unity_loc < h - CORNER_RADIUS) {
295  cairo_move_to (cr, 1.5, _unity_loc + CORNER_OFFSET + .5);
296  cairo_line_to (cr, _girth - 1.5, _unity_loc + CORNER_OFFSET + .5);
297  cairo_stroke (cr);
298  }
299  } else {
300  if (_unity_loc < w - CORNER_RADIUS) {
301  cairo_move_to (cr, _unity_loc - CORNER_OFFSET + .5, 1.5);
302  cairo_line_to (cr, _unity_loc - CORNER_OFFSET + .5, _girth - 1.5);
303  cairo_stroke (cr);
304  }
305  }
306  }
307 
308  if (_layout && !_text.empty() && _orien == HORIZ) {
309  cairo_save (cr);
310  if (_centered_text) {
311  /* center text */
312  cairo_move_to (cr, (w - _text_width)/2.0, h/2.0 - _text_height/2.0);
313  } else if (ds > .5 * w) {
314  cairo_move_to (cr, CORNER_OFFSET + 3, h/2.0 - _text_height/2.0);
315  cairo_set_operator(cr, CAIRO_OPERATOR_XOR);
316  } else {
317  cairo_move_to (cr, w - _text_width - CORNER_OFFSET - 3, h/2.0 - _text_height/2.0);
318  }
319  CairoWidget::set_source_rgb_a (cr, get_style()->get_text (get_state()), 1);
320  pango_cairo_show_layout (cr, _layout->gobj());
321  cairo_restore (cr);
322  }
323 
324  if (!get_sensitive()) {
326  cairo_set_source_rgba (cr, 0.505, 0.517, 0.525, 0.4);
327  cairo_fill (cr);
328  } else if (_hovering && CairoWidget::widget_prelight()) {
330  cairo_set_source_rgba (cr, 0.905, 0.917, 0.925, 0.1);
331  cairo_fill (cr);
332  }
333 }
334 
335 void
336 PixFader::on_size_request (GtkRequisition* req)
337 {
338  if (_orien == VERT) {
339  req->width = (_min_girth ? _min_girth : -1);
340  req->height = (_min_span ? _min_span : -1);
341  } else {
342  req->height = (_min_girth ? _min_girth : -1);
343  req->width = (_min_span ? _min_span : -1);
344  }
345 }
346 
347 void
348 PixFader::on_size_allocate (Gtk::Allocation& alloc)
349 {
351 
352  if (_orien == VERT) {
353  _girth = alloc.get_width ();
354  _span = alloc.get_height ();
355  } else {
356  _girth = alloc.get_height ();
357  _span = alloc.get_width ();
358  }
359 
360  if (is_realized()) {
361  /* recreate patterns in case we've changed size */
362  create_patterns ();
363  }
364 
366 }
367 
368 bool
370 {
371  if (ev->type != GDK_BUTTON_PRESS) {
372  if (_dragging) {
373  remove_modal_grab();
374  _dragging = false;
375  gdk_pointer_ungrab (GDK_CURRENT_TIME);
376  StopGesture ();
377  }
378  return (_tweaks & NoButtonForward) ? true : false;
379  }
380 
381  if (ev->button != 1 && ev->button != 2) {
382  return false;
383  }
384 
385  add_modal_grab ();
386  StartGesture ();
387  _grab_loc = (_orien == VERT) ? ev->y : ev->x;
388  _grab_start = (_orien == VERT) ? ev->y : ev->x;
389  _grab_window = ev->window;
390  _dragging = true;
391  gdk_pointer_grab(ev->window,false,
392  GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
393  NULL,NULL,ev->time);
394 
395  if (ev->button == 2) {
397  }
398 
399  return (_tweaks & NoButtonForward) ? true : false;
400 }
401 
402 bool
404 {
405  double ev_pos = (_orien == VERT) ? ev->y : ev->x;
406 
407  switch (ev->button) {
408  case 1:
409  if (_dragging) {
410  remove_modal_grab();
411  _dragging = false;
412  gdk_pointer_ungrab (GDK_CURRENT_TIME);
413  StopGesture ();
414 
415  if (!_hovering) {
416  if (!(_tweaks & NoVerticalScroll)) {
418  }
419  queue_draw ();
420  }
421 
422  if (ev_pos == _grab_start) {
423  /* no motion - just a click */
424  ev_pos = rint(ev_pos);
425 
426  if (ev->state & Keyboard::TertiaryModifier) {
427  _adjustment.set_value (_default_value);
428  } else if (ev->state & Keyboard::GainFineScaleModifier) {
429  _adjustment.set_value (_adjustment.get_lower());
430 #if 0 // ignore clicks
431  } else if (ev_pos == slider_pos) {
432  ; // click on current position, no move.
433  } else if ((_orien == VERT && ev_pos < slider_pos) || (_orien == HORIZ && ev_pos > slider_pos)) {
434  /* above the current display height, remember X Window coords */
435  _adjustment.set_value (_adjustment.get_value() + _adjustment.get_step_increment());
436  } else {
437  _adjustment.set_value (_adjustment.get_value() - _adjustment.get_step_increment());
438 #endif
439  }
440  }
441  return true;
442  }
443  break;
444 
445  case 2:
446  if (_dragging) {
447  remove_modal_grab();
448  _dragging = false;
449  StopGesture ();
451  gdk_pointer_ungrab (GDK_CURRENT_TIME);
452  return true;
453  }
454  break;
455 
456  default:
457  break;
458  }
459  return false;
460 }
461 
462 bool
463 PixFader::on_scroll_event (GdkEventScroll* ev)
464 {
465  double scale;
466  bool ret = false;
467 
468  if (ev->state & Keyboard::GainFineScaleModifier) {
469  if (ev->state & Keyboard::GainExtraFineScaleModifier) {
470  scale = 0.005;
471  } else {
472  scale = 0.1;
473  }
474  } else {
475  scale = 1.0;
476  }
477 
478  if (_orien == VERT) {
479  switch (ev->direction) {
480  case GDK_SCROLL_UP:
481  _adjustment.set_value (_adjustment.get_value() + (_adjustment.get_page_increment() * scale));
482  ret = true;
483  break;
484  case GDK_SCROLL_DOWN:
485  _adjustment.set_value (_adjustment.get_value() - (_adjustment.get_page_increment() * scale));
486  ret = true;
487  break;
488  default:
489  break;
490  }
491  } else {
492  int dir = ev->direction;
493 
495  if (ev->direction == GDK_SCROLL_UP) dir = GDK_SCROLL_RIGHT;
496  if (ev->direction == GDK_SCROLL_DOWN) dir = GDK_SCROLL_LEFT;
497  }
498 
499  switch (dir) {
500  case GDK_SCROLL_RIGHT:
501  _adjustment.set_value (_adjustment.get_value() + (_adjustment.get_page_increment() * scale));
502  ret = true;
503  break;
504  case GDK_SCROLL_LEFT:
505  _adjustment.set_value (_adjustment.get_value() - (_adjustment.get_page_increment() * scale));
506  ret = true;
507  break;
508  default:
509  break;
510  }
511  }
512  return ret;
513 }
514 
515 bool
517 {
518  if (_dragging) {
519  double scale = 1.0;
520  double const ev_pos = (_orien == VERT) ? ev->y : ev->x;
521 
522  if (ev->window != _grab_window) {
523  _grab_loc = ev_pos;
524  _grab_window = ev->window;
525  return true;
526  }
527 
528  if (ev->state & Keyboard::GainFineScaleModifier) {
529  if (ev->state & Keyboard::GainExtraFineScaleModifier) {
530  scale = 0.005;
531  } else {
532  scale = 0.1;
533  }
534  }
535 
536  double const delta = ev_pos - _grab_loc;
537  _grab_loc = ev_pos;
538 
539  const double off = FADER_RESERVE + ((_orien == VERT) ? CORNER_OFFSET : 0);
540  const double span = _span - off;
541  double fract = (delta / span);
542 
543  fract = min (1.0, fract);
544  fract = max (-1.0, fract);
545 
546  // X Window is top->bottom for 0..Y
547 
548  if (_orien == VERT) {
549  fract = -fract;
550  }
551 
552  _adjustment.set_value (_adjustment.get_value() + scale * fract * (_adjustment.get_upper() - _adjustment.get_lower()));
553  }
554 
555  return true;
556 }
557 
558 void
560 {
561  queue_draw ();
562 }
563 
565 int
567 {
568  float fract = (_adjustment.get_value () - _adjustment.get_lower()) / ((_adjustment.get_upper() - _adjustment.get_lower()));
569  int ds;
570  if (_orien == VERT) {
571  const double off = FADER_RESERVE + CORNER_OFFSET;
572  const double span = _span - off;
573  ds = (int)rint (span * (1.0 - fract));
574  } else {
575  const double off = FADER_RESERVE;
576  const double span = _span - off;
577  ds = (int)rint (span * fract + off);
578  }
579 
580  return ds;
581 }
582 
583 void
585 {
586  if (_orien == VERT) {
587  const double span = _span - FADER_RESERVE - CORNER_OFFSET;
588  _unity_loc = (int) rint (span * (1 - ((_default_value - _adjustment.get_lower()) / (_adjustment.get_upper() - _adjustment.get_lower())))) - 1;
589  } else {
590  const double span = _span - FADER_RESERVE;
591  _unity_loc = (int) rint (FADER_RESERVE + (_default_value - _adjustment.get_lower()) * span / (_adjustment.get_upper() - _adjustment.get_lower()));
592  }
593 
594  queue_draw ();
595 }
596 
597 bool
599 {
600  _hovering = true;
601  if (!(_tweaks & NoVerticalScroll)) {
603  }
604  queue_draw ();
605  return false;
606 }
607 
608 bool
610 {
611  if (!_dragging) {
612  _hovering = false;
613  if (!(_tweaks & NoVerticalScroll)) {
615  }
616  queue_draw ();
617  }
618  return false;
619 }
620 
621 void
623 {
624  const double off = FADER_RESERVE + ((_orien == VERT) ? CORNER_OFFSET : 0);
625  const double span = _span - off;
626  double fract = (_orien == VERT) ? (1.0 - ((ev->y - off) / span)) : ((ev->x - off) / span);
627 
628  fract = min (1.0, fract);
629  fract = max (0.0, fract);
630 
631  _adjustment.set_value (fract * (_adjustment.get_upper () - _adjustment.get_lower ()));
632 }
633 
634 void
636 {
637  _default_value = d;
639 }
640 
641 void
643 {
644  bool need_redraw = false;
645  if ((_tweaks & NoShowUnityLine) ^ (t & NoShowUnityLine)) {
646  need_redraw = true;
647  }
648  _tweaks = t;
649  if (need_redraw) {
650  queue_draw();
651  }
652 }
653 
654 void
655 PixFader::set_text (const std::string& str, bool centered, bool expose)
656 {
657  if (_layout && _text == str) {
658  return;
659  }
660  if (!_layout && !str.empty()) {
661  _layout = Pango::Layout::create (get_pango_context());
662  }
663 
664  _text = str;
665  _centered_text = centered;
666  if (_layout) {
667  _layout->set_text (str);
668  _layout->get_pixel_size (_text_width, _text_height);
669  // queue_resize ();
670  if (expose) queue_draw ();
671  }
672 }
673 
674 void
675 PixFader::on_state_changed (Gtk::StateType old_state)
676 {
677  Widget::on_state_changed (old_state);
678  create_patterns ();
679  queue_draw ();
680 }
681 
682 void
683 PixFader::on_style_changed (const Glib::RefPtr<Gtk::Style>&)
684 {
685  if (_layout) {
686  std::string txt = _layout->get_text();
687  _layout.clear (); // drop reference to existing layout
688  _text = "";
689  set_text (txt, _centered_text, false);
690  }
691  /* patterns are cached and re-created as needed
692  * during 'expose' in the GUI thread */
693  _pattern = 0;
694  queue_draw ();
695 }
696 
697 Gdk::Color
699 {
700  Widget* parent = get_parent ();
701 
702  while (parent) {
703  if (parent->get_has_window()) {
704  break;
705  }
706  parent = parent->get_parent();
707  }
708 
709  if (parent && parent->get_has_window()) {
710  if (_current_parent != parent) {
711  if (_parent_style_change) _parent_style_change.disconnect();
712  _current_parent = parent;
713  _parent_style_change = parent->signal_style_changed().connect (mem_fun (*this, &PixFader::on_style_changed));
714  }
715  return parent->get_style ()->get_bg (parent->get_state());
716  }
717 
718  return get_style ()->get_bg (get_state());
719 }
static void magic_widget_grab_focus()
Definition: keyboard.cc:123
bool on_enter_notify_event(GdkEventCrossing *ev)
Definition: pixfader.cc:598
virtual ~PixFader()
Definition: pixfader.cc:82
void on_size_allocate(Gtk::Allocation &alloc)
Definition: pixfader.cc:348
Gdk::Color get_parent_bg()
Definition: pixfader.cc:698
static uint32_t GainFineScaleModifier
Definition: keyboard.h:61
#define CORNER_OFFSET
Definition: pixfader.cc:38
bool on_scroll_event(GdkEventScroll *ev)
Definition: pixfader.cc:463
Gtk::Adjustment & _adjustment
Definition: pixfader.h:81
sigc::signal< void > StartGesture
Definition: pixfader.h:40
Definition: ardour_ui.h:130
void set_tweaks(Tweaks)
Definition: pixfader.cc:642
tuple f
Definition: signals.py:35
bool on_leave_notify_event(GdkEventCrossing *ev)
Definition: pixfader.cc:609
Definition: Beats.hpp:239
static bool flat_buttons()
Definition: cairo_widget.h:74
Glib::RefPtr< Pango::Layout > _layout
Definition: pixfader.h:78
static uint32_t ScrollHorizontalModifier
Definition: keyboard.h:67
void adjustment_changed()
Definition: pixfader.cc:559
LIBGTKMM2EXT_API void rounded_top_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:540
bool on_button_release_event(GdkEventButton *)
Definition: pixfader.cc:403
static void set_source_rgb_a(cairo_t *cr, Gdk::Color, float a=1.0)
Definition: cairo_widget.cc:36
static uint32_t TertiaryModifier
Definition: keyboard.h:57
#define FADER_RESERVE
Definition: pixfader.cc:39
static bool widget_prelight()
Definition: cairo_widget.h:77
Widget * _current_parent
Definition: pixfader.h:99
void on_size_request(GtkRequisition *)
Definition: pixfader.cc:336
double _grab_start
Definition: pixfader.h:92
void on_style_changed(const Glib::RefPtr< Gtk::Style > &)
Definition: pixfader.cc:683
static std::list< FaderImage * > _patterns
Definition: pixfader.h:148
void set_default_value(float)
Definition: pixfader.cc:635
sigc::connection _parent_style_change
Definition: pixfader.h:98
PixFader(Gtk::Adjustment &adjustment, int orientation, int span, int girth)
Definition: pixfader.cc:43
void update_unity_position()
Definition: pixfader.cc:584
void set_text(const std::string &, bool centered=true, bool expose=true)
Definition: pixfader.cc:655
LIBGTKMM2EXT_API void rounded_right_half_rectangle(Cairo::RefPtr< Cairo::Context >, double x, double y, double w, double h, double r=10)
Definition: utils.cc:557
void set_adjustment_from_event(GdkEventButton *)
Definition: pixfader.cc:622
bool on_motion_notify_event(GdkEventMotion *)
Definition: pixfader.cc:516
#define CORNER_RADIUS
Definition: pixfader.cc:36
static cairo_pattern_t * find_pattern(double afr, double afg, double afb, double abr, double abg, double abb, int w, int h)
Definition: pixfader.cc:89
#define CORNER_SIZE
Definition: pixfader.cc:37
void render(cairo_t *, cairo_rectangle_t *)
Definition: pixfader.cc:199
GdkWindow * _grab_window
Definition: pixfader.h:90
void create_patterns()
Definition: pixfader.cc:102
float _default_value
Definition: pixfader.h:94
std::string _text
Definition: pixfader.h:79
bool on_button_press_event(GdkEventButton *)
Definition: pixfader.cc:369
LIBGTKMM2EXT_API void rounded_rectangle(Cairo::RefPtr< Cairo::Context > context, double x, double y, double w, double h, double r=10)
Definition: utils.cc:520
void on_state_changed(Gtk::StateType)
Definition: pixfader.cc:675
cairo_pattern_t * _pattern
Definition: pixfader.h:88
sigc::signal< void > OnExpose
Definition: pixfader.h:42
sigc::signal< void > StopGesture
Definition: pixfader.h:41
static void magic_widget_drop_focus()
Definition: keyboard.cc:129
static uint32_t GainExtraFineScaleModifier
Definition: keyboard.h:62
void on_size_allocate(Gtk::Allocation &)