X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Fbarcontroller.cc;h=3e998bbcdbe6ec69df121db08cf52d1921f3e423;hb=51ad790745400eeb38547fa4de842202fec934b8;hp=c8a211a48fb721c394550272262c5fee5be22c2d;hpb=2e582e03e433d4fab22b8dcd1d46b9caef387cb5;p=ardour.git diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc index c8a211a48f..3e998bbcdb 100644 --- a/libs/gtkmm2ext/barcontroller.cc +++ b/libs/gtkmm2ext/barcontroller.cc @@ -18,15 +18,18 @@ */ #include +#include #include #include #include #include -#include +#include -#include -#include +#include "gtkmm2ext/gtk_ui.h" +#include "gtkmm2ext/utils.h" +#include "gtkmm2ext/keyboard.h" +#include "gtkmm2ext/barcontroller.h" #include "i18n.h" @@ -35,24 +38,19 @@ using namespace Gtk; using namespace Gtkmm2ext; BarController::BarController (Gtk::Adjustment& adj, - MIDI::Controllable *mc, - sigc::slot lc) + boost::shared_ptr mc) : adjustment (adj), - prompter (Gtk::WIN_POS_MOUSE, 30000, false), - midi_control (mc), - label_callback (lc), - spinner (adjustment), - bind_button (2), - bind_statemask (Gdk::CONTROL_MASK) + binding_proxy (mc), + spinner (adjustment) { _style = LeftToRight; grabbed = false; switching = false; switch_on_release = false; - with_text = true; use_parent = false; + logarithmic = false; layout = darea.create_pango_layout(""); @@ -67,53 +65,50 @@ BarController::BarController (Gtk::Adjustment& adj, Gdk::BUTTON_PRESS_MASK| Gdk::POINTER_MOTION_MASK| Gdk::ENTER_NOTIFY_MASK| - Gdk::LEAVE_NOTIFY_MASK); + Gdk::LEAVE_NOTIFY_MASK| + Gdk::SCROLL_MASK); darea.signal_expose_event().connect (mem_fun (*this, &BarController::expose)); darea.signal_motion_notify_event().connect (mem_fun (*this, &BarController::motion)); - darea.signal_button_press_event().connect (mem_fun (*this, &BarController::button_press)); - darea.signal_button_release_event().connect (mem_fun (*this, &BarController::button_release)); - - prompter.signal_unmap_event().connect (mem_fun (*this, &BarController::prompter_hiding)); - - prompting = false; - unprompting = false; - - if (mc) { - mc->learning_started.connect (mem_fun (*this, &BarController::midicontrol_prompt)); - mc->learning_stopped.connect (mem_fun (*this, &BarController::midicontrol_unprompt)); - } + darea.signal_button_press_event().connect (mem_fun (*this, &BarController::button_press), false); + darea.signal_button_release_event().connect (mem_fun (*this, &BarController::button_release), false); + darea.signal_scroll_event().connect (mem_fun (*this, &BarController::scroll)); spinner.signal_activate().connect (mem_fun (*this, &BarController::entry_activated)); spinner.signal_focus_out_event().connect (mem_fun (*this, &BarController::entry_focus_out)); + spinner.signal_input().connect (mem_fun (*this, &BarController::entry_input)); + spinner.signal_output().connect (mem_fun (*this, &BarController::entry_output)); spinner.set_digits (3); + spinner.set_numeric (true); add (darea); show_all (); } void -BarController::set_bind_button_state (guint button, guint statemask) +BarController::drop_grab () { - bind_button = button; - bind_statemask = statemask; + if (grabbed) { + grabbed = false; + darea.remove_modal_grab(); + StopGesture (); + } } -void -BarController::get_bind_button_state (guint &button, guint &statemask) +bool +BarController::button_press (GdkEventButton* ev) { - button = bind_button; - statemask = bind_statemask; -} + double fract; + if (binding_proxy.button_press_handler (ev)) { + return true; + } -gint -BarController::button_press (GdkEventButton* ev) -{ switch (ev->button) { case 1: if (ev->type == GDK_2BUTTON_PRESS) { switch_on_release = true; + drop_grab (); } else { switch_on_release = false; darea.add_modal_grab(); @@ -122,10 +117,13 @@ BarController::button_press (GdkEventButton* ev) grab_window = ev->window; StartGesture (); } - return TRUE; + return true; break; case 2: + fract = ev->x / (darea.get_width() - 2.0); + adjustment.set_value (adjustment.get_lower() + fract * (adjustment.get_upper() - adjustment.get_lower())); + case 3: break; @@ -134,27 +132,29 @@ BarController::button_press (GdkEventButton* ev) break; } - return FALSE; + return false; } -gint +bool BarController::button_release (GdkEventButton* ev) { + drop_grab (); + switch (ev->button) { case 1: if (switch_on_release) { Glib::signal_idle().connect (mem_fun (*this, &BarController::switch_to_spinner)); - return TRUE; + return true; } - if ((ev->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == GDK_SHIFT_MASK) { + if ((ev->state & (Keyboard::TertiaryModifier|Keyboard::PrimaryModifier)) == Keyboard::TertiaryModifier) { adjustment.set_value (initial_value); } else { double scale; - if (ev->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK) == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) { + if ((ev->state & (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) == (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) { scale = 0.01; - } else if (ev->state & GDK_CONTROL_MASK) { + } else if (ev->state & Keyboard::PrimaryModifier) { scale = 0.1; } else { scale = 1.0; @@ -162,58 +162,65 @@ BarController::button_release (GdkEventButton* ev) mouse_control (ev->x, ev->window, scale); } - grabbed = false; - darea.remove_modal_grab(); - StopGesture (); break; case 2: - if ((ev->state & bind_statemask) && bind_button == 2) { - midi_learn (); - } else { - double fract; - fract = ev->x / (darea.get_width() - 2.0); - adjustment.set_value (adjustment.get_lower() + - fract * (adjustment.get_upper() - adjustment.get_lower())); - } - return TRUE; - + break; + case 3: - if ((ev->state & bind_statemask) && bind_button == 3) { - midi_learn (); - return TRUE; - } - return FALSE; + return false; - case 4: - adjustment.set_value (adjustment.get_value() + - adjustment.get_step_increment()); + default: break; - case 5: - adjustment.set_value (adjustment.get_value() - - adjustment.get_step_increment()); + } + + return true; +} + +bool +BarController::scroll (GdkEventScroll* ev) +{ + double scale; + + if ((ev->state & (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) == (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) { + scale = 0.01; + } else if (ev->state & Keyboard::PrimaryModifier) { + scale = 0.1; + } else { + scale = 1.0; + } + + switch (ev->direction) { + case GDK_SCROLL_UP: + case GDK_SCROLL_RIGHT: + adjustment.set_value (adjustment.get_value() + (scale * adjustment.get_step_increment())); + break; + + case GDK_SCROLL_DOWN: + case GDK_SCROLL_LEFT: + adjustment.set_value (adjustment.get_value() - (scale * adjustment.get_step_increment())); break; } - return TRUE; + return true; } -gint +bool BarController::motion (GdkEventMotion* ev) { double scale; if (!grabbed) { - return TRUE; + return true; } - if ((ev->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == GDK_SHIFT_MASK) { + if ((ev->state & (Keyboard::TertiaryModifier|Keyboard::PrimaryModifier)) == Keyboard::TertiaryModifier) { return TRUE; } - if (ev->state & (GDK_CONTROL_MASK|GDK_SHIFT_MASK) == (GDK_CONTROL_MASK|GDK_SHIFT_MASK)) { + if ((ev->state & (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) == (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) { scale = 0.01; - } else if (ev->state & GDK_CONTROL_MASK) { + } else if (ev->state & Keyboard::PrimaryModifier) { scale = 0.1; } else { scale = 1.0; @@ -225,7 +232,7 @@ BarController::motion (GdkEventMotion* ev) gint BarController::mouse_control (double x, GdkWindow* window, double scaling) { - double fract; + double fract = 0.0; double delta; if (window != grab_window) { @@ -254,23 +261,22 @@ BarController::mouse_control (double x, GdkWindow* window, double scaling) return TRUE; } -gint -BarController::expose (GdkEventExpose* event) +bool +BarController::expose (GdkEventExpose* /*event*/) { Glib::RefPtr win (darea.get_window()); Widget* parent; - gint x1, x2, y1, y2; + gint x1=0, x2=0, y1=0, y2=0; gint w, h; double fract; - w = darea.get_width() - 2; - h = darea.get_height() - 2; - fract = ((adjustment.get_value() - adjustment.get_lower()) / (adjustment.get_upper() - adjustment.get_lower())); switch (_style) { case Line: + w = darea.get_width() - 1; + h = darea.get_height(); x1 = (gint) floor (w * fract); x2 = x1; y1 = 0; @@ -281,28 +287,28 @@ BarController::expose (GdkEventExpose* event) if (parent) { win->draw_rectangle (parent->get_style()->get_fg_gc (parent->get_state()), - true, - 0, 0, darea.get_width(), darea.get_height()); + true, + 0, 0, darea.get_width(), darea.get_height()); } - } else { - win->draw_rectangle (get_style()->get_bg_gc (get_state()), - true, - 0, 0, darea.get_width(), darea.get_height()); - } - if (fract == 0.0) { - win->draw_rectangle (get_style()->get_fg_gc (get_state()), - true, x1, 1, 2, darea.get_height() - 2); } else { - win->draw_rectangle (get_style()->get_fg_gc (get_state()), - true, x1 - 1, 1, 3, darea.get_height() - 2); + + win->draw_rectangle (get_style()->get_bg_gc (get_state()), + true, + 0, 0, darea.get_width() - ((darea.get_width()+1) % 2), darea.get_height()); } + + win->draw_line (get_style()->get_fg_gc (get_state()), x1, 0, x1, h); break; case CenterOut: break; case LeftToRight: + + w = darea.get_width() - 2; + h = darea.get_height() - 2; + x1 = 0; x2 = (gint) floor (w * fract); y1 = 0; @@ -340,103 +346,34 @@ BarController::expose (GdkEventExpose* event) break; } - if (with_text) { - /* draw label */ - - char buf[64]; - buf[0] = '\0'; - - label_callback (buf, 64); + /* draw label */ - if (buf[0] != '\0') { + int xpos = -1; + std::string const label = get_label (xpos); - int width; - int height; - - layout->set_text (buf); - layout->get_pixel_size(width, height); - - int xpos; + if (!label.empty()) { + + layout->set_text (label); + + int width, height; + layout->get_pixel_size (width, height); + if (xpos == -1) { xpos = max (3, 1 + (x2 - (width/2))); xpos = min (darea.get_width() - width - 3, xpos); - - win->draw_layout (get_style()->get_text_gc (get_state()), - xpos, - (darea.get_height()/2) - (height/2), - layout); } - } - - return TRUE; -} - -void -BarController::set_with_text (bool yn) -{ - if (with_text != yn) { - with_text = yn; - queue_draw (); - } -} - -void -BarController::midicontrol_set_tip () -{ - if (midi_control) { - // Gtkmm2ext::UI::instance()->set_tip (&darea, midi_control->control_description()); - } -} - -void -BarController::midi_learn() -{ - if (midi_control) { - prompting = true; - midi_control->learn_about_external_control (); - } -} - - -void -BarController::midicontrol_prompt () -{ - if (prompting) { - string prompt = _("operate MIDI controller now"); - prompter.set_text (prompt); - Gtkmm2ext::UI::instance()->touch_display (&prompter); - - unprompting = true; - prompting = false; - } -} - -void -BarController::midicontrol_unprompt () -{ - if (unprompting) { - Gtkmm2ext::UI::instance()->touch_display (&prompter); - unprompting = false; - } -} - -gint -BarController::prompter_hiding (GdkEventAny *ev) -{ - if (unprompting) { - if (midi_control) { - midi_control->stop_learning(); - } - unprompting = false; + win->draw_layout (get_style()->get_text_gc (get_state()), + xpos, + (darea.get_height()/2) - (height/2), + layout); } - return FALSE; + return true; } - void -BarController::set_style (Style s) +BarController::set_style (barStyle s) { _style = s; darea.queue_draw (); @@ -479,6 +416,7 @@ BarController::switch_to_spinner () remove (); add (spinner); spinner.show (); + spinner.select_region (0, spinner.get_text_length()); spinner.grab_focus (); switching = false; @@ -488,21 +426,14 @@ BarController::switch_to_spinner () void BarController::entry_activated () { - string text = spinner.get_text (); - float val; - - if (sscanf (text.c_str(), "%f", &val) == 1) { - adjustment.set_value (val); - } - switch_to_bar (); } -gint -BarController::entry_focus_out (GdkEventFocus* ev) +bool +BarController::entry_focus_out (GdkEventFocus* /*ev*/) { entry_activated (); - return TRUE; + return true; } void @@ -511,3 +442,92 @@ BarController::set_use_parent (bool yn) use_parent = yn; queue_draw (); } + +void +BarController::set_sensitive (bool yn) +{ + Frame::set_sensitive (yn); + darea.set_sensitive (yn); +} + +/* + This is called when we need to update the adjustment with the value + from the spinner's text entry. + + We need to use Gtk::Entry::get_text to avoid recursive nastiness :) + + If we're not in logarithmic mode we can return false to use the + default conversion. + + In theory we should check for conversion errors but set numeric + mode to true on the spinner prevents invalid input. +*/ +int +BarController::entry_input (double* new_value) +{ + if (!logarithmic) { + return false; + } + + // extract a double from the string and take its log + Entry *entry = dynamic_cast(&spinner); + stringstream stream(entry->get_text()); + stream.imbue(std::locale("")); + + double value; + stream >> value; + + *new_value = log(value); + return true; +} + +/* + This is called when we need to update the spinner's text entry + with the value of the adjustment. + + We need to use Gtk::Entry::set_text to avoid recursive nastiness :) + + If we're not in logarithmic mode we can return false to use the + default conversion. +*/ +bool +BarController::entry_output () +{ + if (!logarithmic) { + return false; + } + + // generate the exponential and turn it into a string + // convert to correct locale. + + stringstream stream; + string str; + size_t found; + + // Gtk.Entry does not like the thousands separator, so we have to + // remove it after conversion from float to string. + + stream.imbue(std::locale("")); + stream.precision(spinner.get_digits()); + + stream << fixed << exp(spinner.get_adjustment()->get_value()); + + str=stream.str(); + + // find thousands separators, remove them + found = str.find(use_facet >(std::locale("")).thousands_sep()); + while(found != str.npos) { + str.erase(found,1); + + //find next + found = str.find(use_facet >(std::locale("")).thousands_sep()); + } + + Entry *entry = dynamic_cast(&spinner); + entry->set_text(str); + + return true; +} + + +