ardour
pixscroller.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2005 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$
19 */
20 #include <iostream>
21 #include <algorithm>
22 #include <cmath>
23 
24 #include <gtkmm.h>
25 
26 #include "gtkmm2ext/pixscroller.h"
27 #include "gtkmm2ext/keyboard.h"
28 
29 using namespace std;
30 using namespace Gtk;
31 using namespace Gtkmm2ext;
32 
33 PixScroller::PixScroller (Adjustment& a,
34  Glib::RefPtr<Gdk::Pixbuf> s,
35  Glib::RefPtr<Gdk::Pixbuf> r)
36  : adj (a),
37  rail (r),
38  slider (s)
39 {
40  Cairo::Format format;
41 
42  dragging = false;
43  add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
44 
45  adj.signal_value_changed().connect (mem_fun (*this, &PixScroller::adjustment_changed));
46  default_value = adj.get_value();
47 
48  sliderrect.set_width(slider->get_width());
49  sliderrect.set_height(slider->get_height());
50  railrect.set_width(rail->get_width());
51  railrect.set_height(rail->get_height());
52 
53  railrect.set_y(sliderrect.get_height() / 2);
54  sliderrect.set_x(0);
55 
56  overall_height = railrect.get_height() + sliderrect.get_height();
57 
58  sliderrect.set_y((int) rint ((overall_height - sliderrect.get_height()) * (adj.get_upper() - adj.get_value())));
59  railrect.set_x((sliderrect.get_width() / 2) - 2);
60 
61  if (rail->get_has_alpha()) {
62  format = Cairo::FORMAT_ARGB32;
63  } else {
64  format = Cairo::FORMAT_RGB24;
65  }
66  rail_surface = Cairo::ImageSurface::create (format, rail->get_width(), rail->get_height());
67  rail_context = Cairo::Context::create (rail_surface);
68  Gdk::Cairo::set_source_pixbuf (rail_context, rail, 0.0, 0.0);
69  rail_context->paint();
70 
71  if (slider->get_has_alpha()) {
72  format = Cairo::FORMAT_ARGB32;
73  } else {
74  format = Cairo::FORMAT_RGB24;
75  }
76  slider_surface = Cairo::ImageSurface::create (format, slider->get_width(), slider->get_height());
77  slider_context = Cairo::Context::create (slider_surface);
78  Gdk::Cairo::set_source_pixbuf (slider_context, slider, 0.0, 0.0);
79  slider_context->paint();
80 }
81 
82 void
83 PixScroller::on_size_request (GtkRequisition* requisition)
84 {
85  requisition->width = sliderrect.get_width();
86  requisition->height = overall_height;
87 }
88 
89 bool
90 PixScroller::on_expose_event (GdkEventExpose* ev)
91 {
92  GdkRectangle intersect;
93  Glib::RefPtr<Gdk::Window> win (get_window());
94  Cairo::RefPtr<Cairo::Context> context = get_window()->create_cairo_context();
95 
96  if (gdk_rectangle_intersect (railrect.gobj(), &ev->area, &intersect)) {
97 
98  context->save();
99  context->rectangle (intersect.x, intersect.y, intersect.width, intersect.height);
100  context->clip();
101  context->set_source (rail_surface, intersect.x - railrect.get_x(), intersect.y - railrect.get_y());
102  context->rectangle (intersect.x, intersect.y, intersect.width, intersect.height);
103  context->clip();
104  context->paint();
105  context->restore();
106  }
107 
108  if (gdk_rectangle_intersect (sliderrect.gobj(), &ev->area, &intersect)) {
109 
110  context->save();
111  context->rectangle (intersect.x, intersect.y, intersect.width, intersect.height);
112  context->clip();
113  context->set_source (rail_surface, intersect.x - sliderrect.get_x(), intersect.y - sliderrect.get_y());
114  context->rectangle (intersect.x, intersect.y, intersect.width, intersect.height);
115  context->clip();
116  context->paint();
117  context->restore();
118  }
119 
120  return true;
121 }
122 
123 bool
125 {
126  switch (ev->button) {
127  case 1:
128  if (!(ev->state & Keyboard::TertiaryModifier)) {
129  add_modal_grab();
130  grab_y = ev->y;
131  grab_start = ev->y;
132  grab_window = ev->window;
133  dragging = true;
134  }
135  break;
136  default:
137  break;
138  }
139 
140 
141  return false;
142 }
143 
144 bool
146 {
147  double scale;
148 
149  if (ev->state & Keyboard::PrimaryModifier) {
150  if (ev->state & Keyboard::SecondaryModifier) {
151  scale = 0.05;
152  } else {
153  scale = 0.1;
154  }
155  } else {
156  scale = 1.0;
157  }
158 
159  switch (ev->button) {
160  case 1:
161  if (dragging) {
162  remove_modal_grab();
163  dragging = false;
164 
165  if (ev->y == grab_start) {
166  /* no motion - just a click */
167  double fract;
168 
169  if (ev->y < sliderrect.get_height()/2) {
170  /* near the top */
171  fract = 1.0;
172  } else {
173  fract = 1.0 - (ev->y - sliderrect.get_height()/2) / railrect.get_height();
174  }
175 
176  fract = min (1.0, fract);
177  fract = max (0.0, fract);
178 
179  adj.set_value (scale * fract * (adj.get_upper() - adj.get_lower()));
180  }
181  } else {
182  if (ev->state & Keyboard::TertiaryModifier) {
183  adj.set_value (default_value);
184  cerr << "default value = " << default_value << endl;
185  }
186  }
187  break;
188  default:
189  break;
190  }
191  return false;
192 }
193 
194 bool
195 PixScroller::on_scroll_event (GdkEventScroll* ev)
196 {
197  double scale;
198 
199  if (ev->state & Keyboard::PrimaryModifier) {
200  if (ev->state & Keyboard::SecondaryModifier) {
201  scale = 0.05;
202  } else {
203  scale = 0.1;
204  }
205  } else {
206  scale = 0.5;
207  }
208 
209  switch (ev->direction) {
210 
211  case GDK_SCROLL_UP:
212  /* wheel up */
213  adj.set_value (adj.get_value() + (adj.get_page_increment() * scale));
214  break;
215  case GDK_SCROLL_DOWN:
216  /* wheel down */
217  adj.set_value (adj.get_value() - (adj.get_page_increment() * scale));
218  break;
219  default:
220  break;
221  }
222  return false;
223 }
224 
225 bool
227 {
228  if (dragging) {
229  double fract;
230  double delta;
231  double scale;
232 
233  if (ev->window != grab_window) {
234  grab_y = ev->y;
235  grab_window = ev->window;
236  return true;
237  }
238 
239  if (ev->state & Keyboard::PrimaryModifier) {
240  if (ev->state & Keyboard::SecondaryModifier) {
241  scale = 0.05;
242  } else {
243  scale = 0.1;
244  }
245  } else {
246  scale = 1.0;
247  }
248 
249  delta = ev->y - grab_y;
250  grab_y = ev->y;
251 
252  fract = (delta / railrect.get_height());
253 
254  fract = min (1.0, fract);
255  fract = max (-1.0, fract);
256 
257  fract = -fract;
258 
259  adj.set_value (adj.get_value() + scale * fract * (adj.get_upper() - adj.get_lower()));
260  }
261 
262  return true;
263 }
264 
265 void
267 {
268  int y = (int) rint ((overall_height - sliderrect.get_height()) * (adj.get_upper() - adj.get_value()));
269 
270  if (y != sliderrect.get_y()) {
271  sliderrect.set_y(y);
272  queue_draw ();
273  }
274 }
GdkWindow * grab_window
Definition: pixscroller.h:58
Definition: ardour_ui.h:130
Definition: Beats.hpp:239
Gdk::Rectangle sliderrect
Definition: pixscroller.h:56
static uint32_t TertiaryModifier
Definition: keyboard.h:57
Cairo::RefPtr< Cairo::ImageSurface > rail_surface
Definition: pixscroller.h:51
bool on_scroll_event(GdkEventScroll *)
Definition: pixscroller.cc:195
static uint32_t PrimaryModifier
Definition: keyboard.h:55
Cairo::RefPtr< Cairo::Context > slider_context
Definition: pixscroller.h:53
static uint32_t SecondaryModifier
Definition: keyboard.h:56
Cairo::RefPtr< Cairo::ImageSurface > slider_surface
Definition: pixscroller.h:54
void on_size_request(GtkRequisition *)
Definition: pixscroller.cc:83
Glib::RefPtr< Gdk::Pixbuf > rail
Definition: pixscroller.h:52
Gdk::Rectangle railrect
Definition: pixscroller.h:57
bool on_expose_event(GdkEventExpose *)
Definition: pixscroller.cc:90
bool on_button_release_event(GdkEventButton *)
Definition: pixscroller.cc:145
Gtk::Adjustment & adj
Definition: pixscroller.h:46
Cairo::RefPtr< Cairo::Context > rail_context
Definition: pixscroller.h:50
Glib::RefPtr< Gdk::Pixbuf > slider
Definition: pixscroller.h:55
bool on_motion_notify_event(GdkEventMotion *)
Definition: pixscroller.cc:226
bool on_button_press_event(GdkEventButton *)
Definition: pixscroller.cc:124