diff --git a/gtk2_ardour/ui/tracks_preferences.xml b/gtk2_ardour/ui/tracks_preferences.xml index 67afe20d56..3d3112d570 100644 --- a/gtk2_ardour/ui/tracks_preferences.xml +++ b/gtk2_ardour/ui/tracks_preferences.xml @@ -1,107 +1,189 @@ + title="Tracks Preferences"> - + diff --git a/gtk2_ardour/waves_button.cc b/gtk2_ardour/waves_button.cc index 330a892ab6..2169f7e0e1 100644 --- a/gtk2_ardour/waves_button.cc +++ b/gtk2_ardour/waves_button.cc @@ -39,107 +39,36 @@ using std::max; using std::min; using namespace std; -WavesButton::Element WavesButton::default_elements = WavesButton::Element (WavesButton::Edge|WavesButton::Body|WavesButton::Text); -WavesButton::Element WavesButton::led_default_elements = WavesButton::Element (WavesButton::default_elements|WavesButton::Indicator); -WavesButton::Element WavesButton::just_led_default_elements = WavesButton::Element (WavesButton::Edge|WavesButton::Body|WavesButton::Indicator); -bool WavesButton::_flat_buttons = false; - -WavesButton::WavesButton (Element e) - : _elements (e) - , _tweaks (Tweaks (0)) - , _text_width (0) +WavesButton::WavesButton () + : _text_width (0) , _text_height (0) - , _diameter (11.0) - , _corner_radius (1.0) + , _corner_radius (0.0) , _corner_mask (0xf) , _angle(0) - , _xalign(.5) - , _yalign(.5) - , bg_color (0) - , border_color (0) - , fill_start_inactive_color (0) - , fill_end_inactive_color (0) - , fill_start_active_color (0) - , fill_end_active_color (0) - , text_active_color(0) - , text_inactive_color(0) - , led_active_color(0) - , led_inactive_color(0) - , fill_pattern (0) - , fill_pattern_active (0) - , shine_pattern (0) - , led_inset_pattern (0) - , reflection_pattern (0) - , _led_rect (0) , _act_on_release (true) - , _led_left (false) - , _fixed_diameter (true) - , _distinct_led_click (false) , _hovering (false) + , _pushed (false) + , _border_width(0) { ColorsChanged.connect (sigc::mem_fun (*this, &WavesButton::color_handler)); } -WavesButton::WavesButton (const std::string& str, Element e) - : _elements (e) - , _tweaks (Tweaks (0)) - , _text_width (0) +WavesButton::WavesButton (const std::string& str) + : _text_width (0) , _text_height (0) - , _diameter (11.0) - , _corner_radius (1.0) + , _corner_radius (0.0) , _corner_mask (0xf) , _angle(0) - , _xalign(.5) - , _yalign(.5) - , bg_color (0) - , border_color (0) - , fill_start_inactive_color (0) - , fill_end_inactive_color (0) - , fill_start_active_color (0) - , fill_end_active_color (0) - , text_active_color(0) - , text_inactive_color(0) - , led_active_color(0) - , led_inactive_color(0) - , fill_pattern (0) - , fill_pattern_active (0) - , shine_pattern (0) - , led_inset_pattern (0) - , reflection_pattern (0) - , _led_rect (0) , _act_on_release (true) - , _led_left (false) - , _fixed_diameter (true) - , _distinct_led_click (false) , _hovering (false) + , _pushed (false) + , _border_width(0) { set_text (str); } WavesButton::~WavesButton() { - delete _led_rect; - - if (shine_pattern) { - cairo_pattern_destroy (shine_pattern); - } - - if (fill_pattern) { - cairo_pattern_destroy (fill_pattern); - } - - if (fill_pattern_active) { - cairo_pattern_destroy (fill_pattern_active); - } - - if (led_inset_pattern) { - cairo_pattern_destroy (led_inset_pattern); - } - - if (reflection_pattern) { - cairo_pattern_destroy (reflection_pattern); - } - } void @@ -177,13 +106,6 @@ WavesButton::set_angle (const double angle) _angle = angle; } -void -WavesButton::set_alignment (const float xa, const float ya) -{ - _xalign = xa; - _yalign = ya; -} - void WavesButton::render (cairo_t* cr) { @@ -206,484 +128,105 @@ WavesButton::render (cairo_t* cr) rounded_function = Gtkmm2ext::rounded_rectangle; } - if (!_fixed_diameter) { - _diameter = std::min (get_width(), get_height()); - } + Glib::RefPtr style = get_style(); + Gdk::Color bgcolor = style->get_bg (_hovering ? + (_pushed ? + Gtk::STATE_ACTIVE : + Gtk::STATE_PRELIGHT ) : + (get_active() ? + Gtk::STATE_ACTIVE : + Gtk::STATE_NORMAL)); - float r,g,b,a; - - if ((_elements & Body)==Body) { - if (_elements & Edge) { - - cairo_set_source_rgba (cr, 0, 0, 0, 1); - rounded_function(cr, 0, 0, get_width(), get_height(), _corner_radius); - cairo_fill (cr); - - rounded_function (cr, 1, 1, get_width()-2, get_height()-2, _corner_radius - 1.5); - } else { - rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius); - } - - if (active_state() == Gtkmm2ext::ImplicitActive) { - - if (!(_tweaks & ImplicitUsesSolidColor)) { - cairo_set_source (cr, fill_pattern); - } else { - cairo_set_source (cr, fill_pattern_active); - } - cairo_fill (cr); - - if (!(_tweaks & ImplicitUsesSolidColor)) { - //border - UINT_TO_RGBA (fill_end_active_color, &r, &g, &b, &a); - cairo_set_line_width (cr, 1.0); - rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 1.5); - cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0); - cairo_stroke (cr); - } - - } else if (active_state() == Gtkmm2ext::ExplicitActive || ((_elements & Indicator)==Indicator) ) { - - //background color - cairo_set_source (cr, fill_pattern_active); - cairo_fill (cr); - - } else { - - //background color - cairo_set_source (cr, fill_pattern); - cairo_fill (cr); - - } - } - - if ( ((_elements & FlatFace)==FlatFace) && (active_state() != Gtkmm2ext::ExplicitActive) ) { - - if ( !(((_elements & FlatFace) == FlatFace) || _flat_buttons) ) { - float rheight = get_height()*0.5-REFLECTION_HEIGHT; - Gtkmm2ext::rounded_rectangle (cr, 2, 3, get_width()-4, rheight, _corner_radius-1); - cairo_set_source (cr, shine_pattern); - cairo_fill (cr); - } - - if (active_state() == Gtkmm2ext::ExplicitActive) { - - UINT_TO_RGBA (fill_start_active_color, &r, &g, &b, &a); - cairo_set_line_width (cr, 2.0); - rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 2.0); - cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0); - cairo_fill (cr); - - } else { - - UINT_TO_RGBA (fill_start_inactive_color, &r, &g, &b, &a); - cairo_set_line_width (cr, 2.0); - rounded_function (cr, 2, 2, get_width()-4, get_height()-4, _corner_radius - 2.0); - cairo_set_source_rgba (cr, r/255.0, g/255.0, b/255.0, a/255.0); - cairo_fill (cr); - - } - } - - if (_pixbuf) { - - double x,y; - x = (get_width() - _pixbuf->get_width())/2.0; - y = (get_height() - _pixbuf->get_height())/2.0; - - cairo_rectangle (cr, x, y, _pixbuf->get_width(), _pixbuf->get_height()); - gdk_cairo_set_source_pixbuf (cr, _pixbuf->gobj(), x, y); + if (_border_width != 0) { + cairo_set_source_rgba (cr, 0, 0, 0, 1); + rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius); cairo_fill (cr); } - /* text, if any */ + rounded_function (cr, _border_width, _border_width, get_width()-_border_width*2.0, get_height()-_border_width*2.0, _corner_radius); + cairo_set_source_rgba (cr, bgcolor.get_red_p(), bgcolor.get_green_p(), bgcolor.get_blue_p(), 1); + cairo_fill (cr); - int text_margin; + // text, if any - if (get_width() < 75) { - text_margin = 5; - } else { - text_margin = 10; - } - - if ( ((_elements & Text)==Text) && !_text.empty()) { + if (!_text.empty()) { cairo_save (cr); cairo_rectangle (cr, 2, 1, get_width()-4, get_height()-2); - cairo_clip(cr); + cairo_clip (cr); cairo_new_path (cr); - cairo_set_source_rgba (cr, text_r, text_g, text_b, text_a); - if (_elements & Indicator) { - if (_led_left) { - cairo_move_to (cr, text_margin + _diameter + 4, get_height()/2.0 - _text_height/2.0); - } else { - cairo_move_to (cr, text_margin, get_height()/2.0 - _text_height/2.0); - } - pango_cairo_show_layout (cr, _layout->gobj()); - } else { - /* align text */ + Gdk::Color fgcolor = style->get_fg (_hovering ? + (_pushed ? + Gtk::STATE_ACTIVE : + Gtk::STATE_PRELIGHT ) : + (get_active() ? + Gtk::STATE_ACTIVE : + Gtk::STATE_NORMAL)); + cairo_set_source_rgba (cr, fgcolor.get_red_p(), fgcolor.get_green_p(), fgcolor.get_blue_p(), 1); - double ww, wh; - double xa, ya; - ww = get_width(); - wh = get_height(); - cairo_save (cr); // TODO retain rotataion.. adj. LED,... - cairo_rotate(cr, _angle * M_PI / 180.0); - cairo_device_to_user(cr, &ww, &wh); - xa = (ww - _text_width) * _xalign; - ya = (wh - _text_height) * _yalign; + /* align text */ - /* quick hack for left/bottom alignment at -90deg - * TODO this should be generalized incl rotation. - * currently only 'user' of this API is meter_strip.cc - */ - if (_xalign < 0) xa = (ww * fabs(_xalign) + text_margin); + double ww, wh; + double xa, ya; + ww = get_width (); + wh = get_height (); + cairo_save (cr); // TODO retain rotataion.. adj. LED,... + cairo_rotate(cr, _angle * M_PI / 180.0); + cairo_device_to_user(cr, &ww, &wh); + xa = (ww - _text_width) * 0.5; + ya = (wh - _text_height) * 0.5; - // TODO honor left/right text_margin with min/max() + cairo_move_to (cr, xa, ya); + pango_cairo_update_layout(cr, _layout->gobj()); + pango_cairo_show_layout (cr, _layout->gobj()); + cairo_restore (cr); - cairo_move_to (cr, xa, ya); - pango_cairo_update_layout(cr, _layout->gobj()); - pango_cairo_show_layout (cr, _layout->gobj()); - cairo_restore (cr); - - /* use old center'ed layout for follow up items - until rotation/aligment code is completed */ - cairo_move_to (cr, (get_width() - _text_width)/2.0, get_height()/2.0 - _text_height/2.0); - } + /* use old center'ed layout for follow up items - until rotation/aligment code is completed */ + cairo_move_to (cr, (get_width() - _text_width)/2.0, get_height()/2.0 - _text_height/2.0); cairo_restore (cr); } - - if (((_elements & Indicator)==Indicator)) { - - /* move to the center of the indicator/led */ - - cairo_save (cr); - - if (_elements & Text) { - if (_led_left) { - cairo_translate (cr, text_margin + (_diameter/2.0), get_height()/2.0); - } else { - cairo_translate (cr, get_width() - ((_diameter/2.0) + 4.0), get_height()/2.0); - } - } else { - cairo_translate (cr, get_width()/2.0, get_height()/2.0); - } - - //inset - cairo_arc (cr, 0, 0, _diameter/2, 0, 2 * M_PI); - cairo_set_source (cr, led_inset_pattern); - cairo_fill (cr); - - //black ring - cairo_set_source_rgb (cr, 0, 0, 0); - cairo_arc (cr, 0, 0, _diameter/2-2, 0, 2 * M_PI); - cairo_fill(cr); - - //led color - cairo_set_source_rgba (cr, led_r, led_g, led_b, led_a); - cairo_arc (cr, 0, 0, _diameter/2-3, 0, 2 * M_PI); - cairo_fill(cr); - - cairo_restore (cr); - } - - - /* a partially transparent gray layer to indicate insensitivity */ - - if ((visual_state() & Gtkmm2ext::Insensitive)) { - rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius); - cairo_set_source_rgba (cr, 0.505, 0.517, 0.525, 0.6); - cairo_fill (cr); - } - - //reflection - bool show_reflection = (active_state() == Gtkmm2ext::ExplicitActive); - show_reflection &= !(((_elements & FlatFace) == FlatFace) || _flat_buttons); - show_reflection &= !((_elements & Indicator) == Indicator); - if ( show_reflection ) { - float rheight = get_height()*0.5-REFLECTION_HEIGHT; - Gtkmm2ext::rounded_rectangle (cr, 2, get_height()*0.5-1, get_width()-4, rheight, _corner_radius-1); - cairo_set_source (cr, shine_pattern); - cairo_fill (cr); - } - - /* if requested, show hovering */ - - if (ARDOUR::Config->get_widget_prelight() - && !((visual_state() & Gtkmm2ext::Insensitive))) { - if (_hovering) { - rounded_function (cr, 0, 0, get_width(), get_height(), _corner_radius); - cairo_set_source_rgba (cr, 0.905, 0.917, 0.925, 0.2); - cairo_fill (cr); - } - } -} - -void -WavesButton::set_diameter (float d) -{ - _diameter = (d*2) + 5.0; - - if (_diameter != 0.0) { - _fixed_diameter = true; - } - - build_patterns (); - queue_resize (); } void WavesButton::set_corner_radius (float r) { - _corner_radius = r; + _corner_radius = fabs(r); + set_dirty (); +} + +void +WavesButton::set_border_width (float border_width) +{ + _border_width = fabs(border_width); set_dirty (); } void WavesButton::on_size_request (Gtk::Requisition* req) { - int xpad = 0; - int ypad = 6; - CairoWidget::on_size_request (req); - if ((_elements & Text) && !_text.empty()) { + if (!_text.empty()) { _layout->get_pixel_size (_text_width, _text_height); - if (_text_width + _diameter < 75) { - xpad = 7; - } else { - xpad = 12; - } } else { _text_width = 0; _text_height = 0; } - if (_pixbuf) { - xpad = 6; - } - - if ((_elements & Indicator) && _fixed_diameter) { - if (_pixbuf) { - req->width = _pixbuf->get_width() + lrint (_diameter) + xpad; - req->height = max (_pixbuf->get_height(), (int) lrint (_diameter)) + ypad; - } else { - req->width = _text_width + lrint (_diameter) + xpad * 2; // margin left+right * 2 - req->height = max (_text_height, (int) lrint (_diameter)) + ypad; - } - } else { - if (_pixbuf) { - req->width = _pixbuf->get_width() + xpad; - req->height = _pixbuf->get_height() + ypad; - } else { - req->width = _text_width + xpad; - req->height = _text_height + ypad; - } - } req->width += _corner_radius; } -/** - * This sets the colors used for rendering based on the name of the button, and - * thus uses information from the GUI config data. - */ -void -WavesButton::set_colors () -{ - std::string name = get_name(); - border_color = ARDOUR_UI::config()->color_by_name ("button border"); - - fill_start_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start active", name)); - fill_end_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end active", name)); - - fill_start_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill start", name)); - fill_end_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: fill end", name)); - - text_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text active", name)); - text_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: text", name)); - - led_active_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led active", name)); - led_inactive_color = ARDOUR_UI::config()->color_by_name (string_compose ("%1: led", name)); -} -/** - * This sets the colors used for rendering based on two fixed values, rather - * than basing them on the button name, and thus information in the GUI config - * data. - */ -void WavesButton::set_fixed_colors (const uint32_t color_active, const uint32_t color_inactive) -{ - set_name (""); /* this will trigger a "style-changed" message and then - set_colors() - */ - - fill_start_active_color = fill_end_active_color = color_active; - - unsigned char r, g, b, a; - UINT_TO_RGBA(color_active, &r, &g, &b, &a); - - double white_contrast = (max (double(r), 255.) - min (double(r), 255.)) + - (max (double(g), 255.) - min (double(g), 255.)) + - (max (double(b), 255.) - min (double(b), 255.)); - - double black_contrast = (max (double(r), 0.) - min (double(r), 0.)) + - (max (double(g), 0.) - min (double(g), 0.)) + - (max (double(b), 0.) - min (double(b), 0.)); - - text_active_color = - text_inactive_color = (white_contrast > black_contrast) ? - RGBA_TO_UINT(255, 255, 255, 255) : /* use white */ - RGBA_TO_UINT( 0, 0, 0, 255); /* use black */ - - fill_start_inactive_color = fill_end_inactive_color = color_inactive; - - /* XXX what about led colors ? */ - - build_patterns (); -} - -void -WavesButton::build_patterns () -{ - uint32_t start_color; - uint32_t end_color; - uint32_t text_color; - uint32_t led_color; - uint32_t r, g, b, a; - - if (shine_pattern) { - cairo_pattern_destroy (shine_pattern); - shine_pattern = 0; - } - - if (fill_pattern) { - cairo_pattern_destroy (fill_pattern); - fill_pattern = 0; - } - - if (fill_pattern_active) { - cairo_pattern_destroy (fill_pattern_active); - fill_pattern_active = 0; - } - - if (_elements & Body) { - - if (_flat_buttons || ((_elements & FlatFace) == FlatFace)) { - end_color = start_color = fill_start_active_color; - } else { - start_color = fill_start_active_color; - end_color = fill_end_active_color; - } - UINT_TO_RGBA (start_color, &r, &g, &b, &a); - - active_r = r/255.0; - active_g = g/255.0; - active_b = b/255.0; - active_a = a/255.0; - - shine_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height()); - cairo_pattern_add_color_stop_rgba (shine_pattern, 0, 1,1,1,0.0); - cairo_pattern_add_color_stop_rgba (shine_pattern, 0.5, 1,1,1,0.1); - cairo_pattern_add_color_stop_rgba (shine_pattern, 0.7, 1,1,1,0.2); - cairo_pattern_add_color_stop_rgba (shine_pattern, 1, 1,1,1,0.1); - - fill_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height()-3); - if (_flat_buttons || ((_elements & FlatFace) == FlatFace)) { - end_color = start_color = fill_start_inactive_color; - } else { - start_color = fill_start_inactive_color; - end_color = fill_end_inactive_color; - } - UINT_TO_RGBA (start_color, &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgba (fill_pattern, 0, r/255.0,g/255.0,b/255.0, a/255.0); - UINT_TO_RGBA (end_color, &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgba (fill_pattern, 1, r/255.0,g/255.0,b/255.0, a/255.0); - - fill_pattern_active = cairo_pattern_create_linear (0.0, 0.0, 0.0, get_height()-3); - if (_flat_buttons || ((_elements & FlatFace) == FlatFace)) { - if (active_state() == Gtkmm2ext::ImplicitActive && (_tweaks & ImplicitUsesSolidColor)) { - end_color = start_color = led_active_color; - } else { - end_color = start_color = fill_end_active_color; - } - } else { - if (active_state() == Gtkmm2ext::ImplicitActive && (_tweaks & ImplicitUsesSolidColor)) { - end_color = start_color = led_active_color; - } else { - start_color = fill_start_active_color; - end_color = fill_end_active_color; - } - } - UINT_TO_RGBA (start_color, &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgba (fill_pattern_active, 0, r/255.0,g/255.0,b/255.0, a/255.0); - UINT_TO_RGBA (end_color, &r, &g, &b, &a); - cairo_pattern_add_color_stop_rgba (fill_pattern_active, 1, r/255.0,g/255.0,b/255.0, a/255.0); - } - - if (led_inset_pattern) { - cairo_pattern_destroy (led_inset_pattern); - } - - if (reflection_pattern) { - cairo_pattern_destroy (reflection_pattern); - } - - if (_elements & Indicator) { - led_inset_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter); - cairo_pattern_add_color_stop_rgba (led_inset_pattern, 0, 0,0,0, 0.4); - cairo_pattern_add_color_stop_rgba (led_inset_pattern, 1, 1,1,1, 0.7); - - reflection_pattern = cairo_pattern_create_linear (0.0, 0.0, 0.0, _diameter/2-3); - cairo_pattern_add_color_stop_rgba (reflection_pattern, 0, 1,1,1, active_state() ? 0.4 : 0.2); - cairo_pattern_add_color_stop_rgba (reflection_pattern, 1, 1,1,1, 0.0); - } - - if (active_state() == Gtkmm2ext::ExplicitActive || ((_tweaks & ImplicitUsesSolidColor) && active_state() == Gtkmm2ext::ImplicitActive)) { - text_color = text_active_color; - led_color = led_active_color; - } else { - text_color = text_inactive_color; - led_color = led_inactive_color; - } - - UINT_TO_RGBA (text_color, &r, &g, &b, &a); - text_r = r/255.0; - text_g = g/255.0; - text_b = b/255.0; - text_a = a/255.0; - UINT_TO_RGBA (led_color, &r, &g, &b, &a); - led_r = r/255.0; - led_g = g/255.0; - led_b = b/255.0; - led_a = a/255.0; - - set_dirty (); -} - -void -WavesButton::set_led_left (bool yn) -{ - _led_left = yn; -} bool WavesButton::on_button_press_event (GdkEventButton *ev) { - if ((_elements & Indicator) && _led_rect && _distinct_led_click) { - if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width && - ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) { - return true; - } - } - - if (_tweaks & ShowClick) { - set_active_state (Gtkmm2ext::ExplicitActive); - } - + _pushed = true; + queue_draw (); if (binding_proxy.button_press_handler (ev)) { return true; } - if (!_act_on_release) { if (_action) { _action->activate (); @@ -697,18 +240,8 @@ WavesButton::on_button_press_event (GdkEventButton *ev) bool WavesButton::on_button_release_event (GdkEventButton *ev) { - if (_hovering && (_elements & Indicator) && _led_rect && _distinct_led_click) { - if (ev->x >= _led_rect->x && ev->x < _led_rect->x + _led_rect->width && - ev->y >= _led_rect->y && ev->y < _led_rect->y + _led_rect->height) { - signal_led_clicked(); /* EMIT SIGNAL */ - return true; - } - } - - if (_tweaks & ShowClick) { - unset_active_state (); - } - + _pushed = false; + queue_draw (); if (_hovering) { signal_clicked (); @@ -723,18 +256,9 @@ WavesButton::on_button_release_event (GdkEventButton *ev) return false; } -void -WavesButton::set_distinct_led_click (bool yn) -{ - _distinct_led_click = yn; - setup_led_rect (); -} - void WavesButton::color_handler () { - set_colors (); - build_patterns (); set_dirty (); } @@ -742,8 +266,6 @@ void WavesButton::on_size_allocate (Allocation& alloc) { CairoWidget::on_size_allocate (alloc); - setup_led_rect (); - build_patterns (); } void @@ -816,90 +338,34 @@ WavesButton::action_toggled () void WavesButton::on_style_changed (const RefPtr&) { - set_colors (); - build_patterns (); + set_dirty(); } void WavesButton::on_name_changed () { - set_colors (); - build_patterns (); -} - -void -WavesButton::setup_led_rect () -{ - int text_margin; - - if (get_width() < 75) { - text_margin = 3; - } else { - text_margin = 10; - } - - if (_elements & Indicator) { - _led_rect = new cairo_rectangle_t; - - if (_elements & Text) { - if (_led_left) { - _led_rect->x = text_margin; - } else { - _led_rect->x = get_width() - text_margin - _diameter/2.0; - } - } else { - /* centered */ - _led_rect->x = get_width()/2.0 - _diameter/2.0; - } - - _led_rect->y = get_height()/2.0 - _diameter/2.0; - _led_rect->width = _diameter; - _led_rect->height = _diameter; - - } else { - delete _led_rect; - _led_rect = 0; - } -} - -void -WavesButton::set_image (const RefPtr& img) -{ - _pixbuf = img; - queue_draw (); + set_dirty(); } void WavesButton::set_active_state (Gtkmm2ext::ActiveState s) { - bool changed = (_active_state != s); CairoWidget::set_active_state (s); - if (changed) { - set_colors (); - build_patterns (); - } + set_dirty(); } void WavesButton::set_visual_state (Gtkmm2ext::VisualState s) { - bool changed = (_visual_state != s); CairoWidget::set_visual_state (s); - if (changed) { - set_colors (); - build_patterns (); - } + set_dirty(); } bool WavesButton::on_enter_notify_event (GdkEventCrossing* ev) { _hovering = true; - - if (ARDOUR::Config->get_widget_prelight()) { - queue_draw (); - } - + queue_draw (); return CairoWidget::on_enter_notify_event (ev); } @@ -907,23 +373,10 @@ bool WavesButton::on_leave_notify_event (GdkEventCrossing* ev) { _hovering = false; - - if (ARDOUR::Config->get_widget_prelight()) { - queue_draw (); - } - + queue_draw (); return CairoWidget::on_leave_notify_event (ev); } -void -WavesButton::set_tweaks (Tweaks t) -{ - if (_tweaks != t) { - _tweaks = t; - queue_draw (); - } -} - void WavesButton::action_sensitivity_changed () { @@ -959,21 +412,3 @@ WavesButton::set_rounded_corner_mask (int mask) _corner_mask = mask; queue_draw (); } - -void -WavesButton::set_elements (Element e) -{ - _elements = e; -} - -void -WavesButton::add_elements (Element e) -{ - _elements = (WavesButton::Element) (_elements | e); -} - -void -WavesButton::set_flat_buttons (bool yn) -{ - _flat_buttons = yn; -} diff --git a/gtk2_ardour/waves_button.h b/gtk2_ardour/waves_button.h index cba33078ec..566131cd13 100644 --- a/gtk2_ardour/waves_button.h +++ b/gtk2_ardour/waves_button.h @@ -32,57 +32,22 @@ class WavesButton : public CairoWidget , public Gtkmm2ext::Activatable { public: - enum Element { - Edge = 0x1, - Body = 0x2, - Text = 0x4, - Indicator = 0x8, - FlatFace = 0x10, - }; - - static Element default_elements; - static Element led_default_elements; - static Element just_led_default_elements; - - static void set_flat_buttons (bool yn); - static bool flat_buttons() { return _flat_buttons; } - - WavesButton (Element e = default_elements); - WavesButton (const std::string&, Element e = default_elements); + WavesButton (); + WavesButton (const std::string&); virtual ~WavesButton (); - enum Tweaks { - ShowClick = 0x1, - NoModel = 0x2, - ImplicitUsesSolidColor = 0x4, - }; - - Tweaks tweaks() const { return _tweaks; } - void set_tweaks (Tweaks); - void set_active_state (Gtkmm2ext::ActiveState); void set_visual_state (Gtkmm2ext::VisualState); - Element elements() const { return _elements; } - void set_elements (Element); - void add_elements (Element); - void set_corner_radius (float); void set_rounded_corner_mask (int); - void set_diameter (float); void set_text (const std::string&); void set_markup (const std::string&); void set_angle (const double); - void set_alignment (const float, const float); - void get_alignment (float& xa, float& ya) {xa = _xalign; ya = _yalign;}; - - void set_led_left (bool yn); - void set_distinct_led_click (bool yn); - + void set_border_width(float); Glib::RefPtr layout() const { return _layout; } - sigc::signal signal_led_clicked; sigc::signal signal_clicked; boost::shared_ptr get_controllable() { return binding_proxy.get_controllable(); } @@ -94,10 +59,6 @@ class WavesButton : public CairoWidget , public Gtkmm2ext::Activatable bool on_button_press_event (GdkEventButton*); bool on_button_release_event (GdkEventButton*); - void set_image (const Glib::RefPtr&); - - void set_fixed_colors (const uint32_t active_color, const uint32_t inactive_color); - protected: void render (cairo_t *); void on_size_request (Gtk::Requisition* req); @@ -112,67 +73,21 @@ class WavesButton : public CairoWidget , public Gtkmm2ext::Activatable private: Glib::RefPtr _layout; - Glib::RefPtr _pixbuf; std::string _text; - Element _elements; - Tweaks _tweaks; BindingProxy binding_proxy; int _text_width; int _text_height; - float _diameter; float _corner_radius; int _corner_mask; - + float _border_width; double _angle; - float _xalign, _yalign; - - uint32_t bg_color; - uint32_t border_color; - uint32_t fill_start_inactive_color; - uint32_t fill_end_inactive_color; - uint32_t fill_start_active_color; - uint32_t fill_end_active_color; - uint32_t text_active_color; - uint32_t text_inactive_color; - uint32_t led_active_color; - uint32_t led_inactive_color; - - cairo_pattern_t* fill_pattern; - cairo_pattern_t* fill_pattern_active; - cairo_pattern_t* shine_pattern; - cairo_pattern_t* led_inset_pattern; - cairo_pattern_t* reflection_pattern; - - cairo_rectangle_t* _led_rect; - - double text_r; - double text_g; - double text_b; - double text_a; - - double led_r; - double led_g; - double led_b; - double led_a; - - double active_r; - double active_g; - double active_b; - double active_a; bool _act_on_release; - bool _led_left; - bool _fixed_diameter; - bool _distinct_led_click; bool _hovering; + bool _pushed; - static bool _flat_buttons; - - void setup_led_rect (); - void set_colors (); void color_handler (); - void build_patterns (); void action_toggled (); diff --git a/gtk2_ardour/waves_ui.cc b/gtk2_ardour/waves_ui.cc new file mode 100644 index 0000000000..78acab8100 --- /dev/null +++ b/gtk2_ardour/waves_ui.cc @@ -0,0 +1,185 @@ +/* + Copyright (C) 2014 Valeriy Kamyshniy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ +#include "waves_ui.h" + +std::ofstream WavesUI::dbg_out("/users/WavesUILog.txt"); + +double +WavesUI::xml_property (const XMLNode &node, const char *prop_name, double default_value) +{ + return node.property (prop_name) ? atof(node.property(prop_name)->value().c_str()) : default_value; +} + +int +WavesUI::xml_property (const XMLNode &node, const char *prop_name, int default_value) +{ + return node.property (prop_name) ? atoi(node.property(prop_name)->value().c_str()) : default_value; +} + +bool +WavesUI::xml_property (const XMLNode &node, const char *prop_name, bool default_value) +{ + std::string property = node.property (prop_name) ? node.property(prop_name)->value() : std::string(""); + if (property.empty()) + return default_value; + std::transform(property.begin(), property.end(), property.begin(), ::toupper); + return property == "TRUE"; +} + +std::string +WavesUI::xml_property (const XMLNode &node, const char *prop_name, const std::string default_value) +{ + return node.property (prop_name) ? node.property(prop_name)->value() : default_value; +} + +std::string +WavesUI::xml_property (const XMLNode& node, const char* prop_name, const char* default_value) +{ + return xml_property (node, prop_name, std::string(default_value)); +} + +Gtk::Widget* +WavesUI::create_widget (const XMLNode& definition, std::map &named_widgets) +{ + Gtk::Widget* child = NULL; + std::string widget_type = definition.name(); + std::string widget_id = WavesUI::xml_property (definition, "id", ""); + std::string style = WavesUI::xml_property (definition, "style", ""); + + std::string text = WavesUI::xml_property (definition, "text", ""); + boost::replace_all(text, "\\n", "\n"); + + int height = WavesUI::xml_property (definition, "height", -1); + int width = WavesUI::xml_property (definition, "width", -1); + + std::transform(widget_type.begin(), widget_type.end(), widget_type.begin(), ::toupper); + if (widget_type == "BUTTON") { + child = manage (new WavesButton(text)); + double border_width = WavesUI::xml_property (definition, "borderwidth", 0.0); + ((WavesButton*)child)->set_border_width(border_width); + } else if (widget_type == "COMBOBOXTEXT") { + child = manage (new Gtk::ComboBoxText); + } else if (widget_type == "LABEL") { + child = manage (new Gtk::Label(text)); + } else if (widget_type == "LAYOUT") { + child = manage (new Gtk::Layout); + } + + if (child != NULL) { + if (!style.empty()) { + child->set_name (style); + } + + child->set_size_request (width, height); + if (!widget_id.empty()) + { + named_widgets[widget_id] = child; + } + + std::string property = WavesUI::xml_property (definition, "bgnormal", ""); + if (!property.empty()) { + child->modify_bg(Gtk::STATE_NORMAL, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "bgactive", ""); + if (!property.empty()) { + child->modify_bg(Gtk::STATE_ACTIVE, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "bghover", ""); + if (!property.empty()) { + child->modify_bg(Gtk::STATE_PRELIGHT, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "fgnormal", ""); + if (!property.empty()) { + child->modify_fg(Gtk::STATE_NORMAL, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "fgactive", ""); + if (!property.empty()) { + child->modify_fg(Gtk::STATE_ACTIVE, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "fghover", ""); + if (!property.empty()) { + child->modify_fg(Gtk::STATE_PRELIGHT, Gdk::Color(property)); + } + + property = WavesUI::xml_property (definition, "font", ""); + if (!property.empty()) { + child->modify_font(Pango::FontDescription(property)); + } + } + return child; +} + + +Gtk::Widget* +WavesUI::add_widget (Gtk::Box& parent, const XMLNode& definition, std::map &named_widgets) +{ + Gtk::Widget* child = create_widget(definition, named_widgets); + + if (child != NULL) + { + parent.pack_start(*child, false, false); + } + return child; +} + + +Gtk::Widget* +WavesUI::add_widget (Gtk::Layout& parent, const XMLNode& definition, std::map &named_widgets) +{ + Gtk::Widget* child = create_widget(definition, named_widgets); + + if (child != NULL) + { + parent.put (*child, + WavesUI::xml_property (definition, "x", 0), + WavesUI::xml_property (definition, "y", 0)); + } + return child; +} + + +Gtk::Widget* +WavesUI::add_widget (Gtk::Widget& parent, const XMLNode &definition, std::map &named_widgets) +{ + Gtk::Widget* child = NULL; + if(dynamic_cast (&parent)) { + child = add_widget (*dynamic_cast (&parent), definition, named_widgets); + } + else if(dynamic_cast (&parent)) { + child = add_widget (*dynamic_cast (&parent), definition, named_widgets); + } + + if (child != NULL) + { + create_ui (definition.children(), *child, named_widgets); + } + return child; +} + +void WavesUI::create_ui (const XMLNodeList& definition, Gtk::Widget& root, std::map &named_widgets) +{ + for (XMLNodeList::const_iterator i = definition.begin(); i != definition.end(); ++i) { + WavesUI::add_widget ((Gtk::Widget&)root, **i, named_widgets); + } +} \ No newline at end of file diff --git a/gtk2_ardour/waves_ui.h b/gtk2_ardour/waves_ui.h new file mode 100644 index 0000000000..c12691bb6a --- /dev/null +++ b/gtk2_ardour/waves_ui.h @@ -0,0 +1,43 @@ +/* + Copyright (C) 2014 Valeriy Kamyshniy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include "gtkmm/box.h" +#include "gtkmm/layout.h" +#include "gtkmm/label.h" +#include "pbd/xml++.h" +#include "waves_button.h" + +namespace WavesUI { + double xml_property (const XMLNode& node, const char* prop_name, double default_value); + int xml_property (const XMLNode& node, const char* prop_name, int default_value); + bool xml_property (const XMLNode& node, const char* prop_name, bool default_value); + std::string xml_property (const XMLNode& node, const char* prop_name, const std::string default_value); + std::string xml_property (const XMLNode& node, const char* prop_name, const char* default_value); + + void create_ui (const XMLNodeList& definition, Gtk::Widget& root, std::map &named_widgets); + Gtk::Widget* create_widget (const XMLNode& definition, std::map &named_widgets); + Gtk::Widget* add_widget (Gtk::Box& parent, const XMLNode &definition, std::map &named_widgets); + Gtk::Widget* add_widget (Gtk::Layout& parent, const XMLNode &definition, std::map &named_widgets); + Gtk::Widget* add_widget (Gtk::Widget& parent, const XMLNode &definition, std::map &named_widgets); + + extern std::ofstream dbg_out; +} \ No newline at end of file