+bool
+Meterbridge::on_scroll_event (GdkEventScroll* ev)
+{
+ switch (ev->direction) {
+ case GDK_SCROLL_LEFT:
+ scroll_left ();
+ return true;
+ case GDK_SCROLL_UP:
+ if (ev->state & Keyboard::TertiaryModifier) {
+ scroll_left ();
+ return true;
+ }
+ return false;
+
+ case GDK_SCROLL_RIGHT:
+ scroll_right ();
+ return true;
+
+ case GDK_SCROLL_DOWN:
+ if (ev->state & Keyboard::TertiaryModifier) {
+ scroll_right ();
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
+
+void
+Meterbridge::scroll_left ()
+{
+ if (!scroller.get_hscrollbar()) return;
+ Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
+ /* stupid GTK: can't rely on clamping across versions */
+ scroller.get_hscrollbar()->set_value (max (adj->get_lower(), adj->get_value() - adj->get_step_increment()));
+}
+
+void
+Meterbridge::scroll_right ()
+{
+ if (!scroller.get_hscrollbar()) return;
+ Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
+ /* stupid GTK: can't rely on clamping across versions */
+ scroller.get_hscrollbar()->set_value (min (adj->get_upper(), adj->get_value() + adj->get_step_increment()));
+}
+
+void
+Meterbridge::on_size_request (Gtk::Requisition* r)
+{
+ meter_clear_pattern_cache(3);
+ Gtk::Window::on_size_request(r);
+
+ Gdk::Geometry geom;
+ Gtk::Requisition mr = meterarea.size_request();
+
+ geom.max_width = mr.width + metrics_left.get_width() + metrics_right.get_width();
+ geom.max_width = std::max(50, geom.max_width);
+ geom.max_height = max_height;
+
+ if (cur_max_width != geom.max_width) {
+ cur_max_width = geom.max_width;
+ /* height resizes are 'heavy' since the metric areas and meter-patterns
+ * are re-generated. limit to 16px steps. */
+ geom.height_inc = 16;
+ geom.width_inc = 1;
+ geom.min_width = 40;
+ geom.min_height = -1;
+ set_geometry_hints(*((Gtk::Window*) this), geom, Gdk::HINT_MIN_SIZE | Gdk::HINT_MAX_SIZE | Gdk::HINT_RESIZE_INC);
+ }
+}
+
+void
+Meterbridge::on_size_allocate (Gtk::Allocation& a)
+{
+ const Gtk::Scrollbar * hsc = scroller.get_hscrollbar();
+
+ /* switch left/right edge patterns depending on horizontal scroll-position */
+ if (scroller.get_hscrollbar_visible() && hsc) {
+ if (!scroll_connection.connected()) {
+ scroll_connection = scroller.get_hscrollbar()->get_adjustment()->signal_value_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
+ scroller.get_hscrollbar()->get_adjustment()->signal_changed().connect(sigc::mem_fun (*this, &Meterbridge::on_scroll));
+ }
+ gint scrollbar_spacing;
+ gtk_widget_style_get (GTK_WIDGET (scroller.gobj()),
+ "scrollbar-spacing", &scrollbar_spacing, NULL);
+ const int h = hsc->get_height() + scrollbar_spacing + 1;
+ metrics_spacer_left.set_size_request(-1, h);
+ metrics_spacer_right.set_size_request(-1, h);
+ } else {
+ metrics_spacer_left.set_size_request(-1, 0);
+ metrics_spacer_right.set_size_request(-1, 0);
+ }
+ Gtk::Window::on_size_allocate(a);
+}
+
+void
+Meterbridge::on_scroll()
+{
+ if (!scroller.get_hscrollbar()) return;
+
+ Adjustment* adj = scroller.get_hscrollbar()->get_adjustment();
+ int leftend = adj->get_value();
+ int rightend = scroller.get_width() + leftend;
+
+ int mm_left = _mm_left;
+ int mm_right = _mm_right;
+ ARDOUR::MeterType mt_left = _mt_left;
+ ARDOUR::MeterType mt_right = _mt_right;
+
+ for (unsigned int i = 0; i < _metrics.size(); ++i) {
+ int sx, dx = 0, dy = 0;
+ int mm = _metrics[i]->get_metric_mode();
+ sx = (mm & 2) ? _metrics[i]->get_width() : 0;
+
+ _metrics[i]->translate_coordinates(meterarea, sx, 0, dx, dy);
+
+ if (dx < leftend && !(mm&2)) {
+ mm_left = mm;
+ mt_left = _metrics[i]->meter_type();
+ }
+ if (dx > rightend && (mm&2)) {
+ mm_right = mm;
+ mt_right = _metrics[i]->meter_type();
+ break;
+ }
+ }
+ metrics_left.set_metric_mode(mm_left, mt_left);
+ metrics_right.set_metric_mode(mm_right, mt_right);
+}
+