X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Fpixfader.cc;h=f4e362bca1b6ec0b3670d3a110354c8fa9cd2bad;hb=93349141379343c91ea0ec2127d694f6cf2e230e;hp=43657a590256646ee5f74cd872737b8a4f1bcbea;hpb=b02e2cd25b1a7e69609f39710355fac40d3b9b21;p=ardour.git diff --git a/libs/gtkmm2ext/pixfader.cc b/libs/gtkmm2ext/pixfader.cc index 43657a5902..f4e362bca1 100644 --- a/libs/gtkmm2ext/pixfader.cc +++ b/libs/gtkmm2ext/pixfader.cc @@ -21,6 +21,8 @@ #include +#include "pbd/stacktrace.h" + #include "gtkmm2ext/pixfader.h" #include "gtkmm2ext/keyboard.h" #include "gtkmm2ext/rgb_macros.h" @@ -33,13 +35,14 @@ using namespace std; #define CORNER_RADIUS 4 #define FADER_RESERVE (2*CORNER_RADIUS) +std::list PixFader::_patterns; + PixFader::PixFader (Gtk::Adjustment& adj, int orientation, int fader_length, int fader_girth) : adjustment (adj) , span (fader_length) , girth (fader_girth) , _orien (orientation) , pattern (0) - , texture_pattern (0) , _hovering (false) , last_drawn (-1) , dragging (false) @@ -55,27 +58,24 @@ PixFader::PixFader (Gtk::Adjustment& adj, int orientation, int fader_length, int PixFader::~PixFader () { - free_patterns (); } -void -PixFader::free_patterns () +cairo_pattern_t* +PixFader::find_pattern (double afr, double afg, double afb, + double abr, double abg, double abb, + int w, int h) { - if (pattern) { - cairo_pattern_destroy (pattern); - pattern = 0; - } - if (texture_pattern) { - cairo_pattern_destroy (texture_pattern); - texture_pattern = 0; + for (list::iterator f = _patterns.begin(); f != _patterns.end(); ++f) { + if ((*f)->matches (afr, afg, afb, abr, abg, abb, w, h)) { + return (*f)->pattern; + } } + return 0; } void PixFader::create_patterns () { - free_patterns (); - Gdk::Color c = get_style()->get_fg (get_state()); float fr, fg, fb; float br, bg, bb; @@ -90,11 +90,33 @@ PixFader::create_patterns () bg = c.get_green_p (); bb = c.get_blue_p (); + if ( !_text.empty()) { + _layout->get_pixel_size (_text_width, _text_height); + } else { + _text_width = 0; + _text_height = 0; + } + + c = get_style()->get_text (get_state()); + + text_r = c.get_red_p (); + text_g = c.get_green_p (); + text_b = c.get_blue_p (); + cairo_surface_t* surface; cairo_t* tc = 0; float radius = CORNER_RADIUS; double w = get_width(); + + if (w <= 1 || get_height() <= 1) { + return; + } + + if ((pattern = find_pattern (fr, fg, fb, br, bg, bb, get_width(), get_height())) != 0) { + /* found it - use it */ + return; + } if (_orien == VERT) { @@ -154,21 +176,12 @@ PixFader::create_patterns () pattern = cairo_pattern_create_for_surface (surface); } - cairo_destroy (tc); - cairo_surface_destroy (surface); - - if ( !_text.empty()) { - _layout->get_pixel_size (_text_width, _text_height); - } else { - _text_width = 0; - _text_height = 0; - } + /* cache it for others to use */ - c = get_style()->get_text (get_state()); + _patterns.push_back (new FaderImage (pattern, fr, fg, fb, br, bg, bb, get_width(), get_height())); - text_r = c.get_red_p (); - text_g = c.get_green_p (); - text_b = c.get_blue_p (); + cairo_destroy (tc); + cairo_surface_destroy (surface); } bool @@ -177,13 +190,35 @@ PixFader::on_expose_event (GdkEventExpose* ev) Cairo::RefPtr context = get_window()->create_cairo_context(); cairo_t* cr = context->cobj(); - cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height); - cairo_clip (cr); - if (!pattern) { create_patterns(); } - + + if (!pattern) { + + /* this isn't supposed to be happen, but some wackiness whereby + the pixfader ends up with a 1xN or Nx1 size allocation + leads to it. the basic wackiness needs fixing but we + shouldn't crash. just fill in the expose area with + our bg color. + */ + + Gdk::Color c = get_style()->get_bg (get_state()); + float br, bg, bb; + + br = c.get_red_p (); + bg = c.get_green_p (); + bb = c.get_blue_p (); + cairo_set_source_rgb (cr, br, bg, bb); + cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cairo_fill (cr); + + return true; + } + + cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cairo_clip (cr); + int ds = display_span (); float w = get_width(); float h = get_height(); @@ -247,14 +282,12 @@ PixFader::on_expose_event (GdkEventExpose* ev) } } } - - if ( !_text.empty() ) { - cairo_new_path (cr); + if ( !_text.empty() ) { /* center text */ + cairo_new_path (cr); cairo_move_to (cr, (get_width() - _text_width)/2.0, get_height()/2.0 - _text_height/2.0); - cairo_set_source_rgba (cr, text_r, text_g, text_b, 0.9); pango_cairo_show_layout (cr, _layout->gobj()); } @@ -276,11 +309,11 @@ void PixFader::on_size_request (GtkRequisition* req) { if (_orien == VERT) { - req->width = girth; - req->height = span; + req->width = (girth ? girth : -1); + req->height = (span ? span : -1); } else { - req->height = girth; - req->width = span; + req->height = (girth ? girth : -1); + req->width = (span ? span : -1); } } @@ -297,12 +330,12 @@ PixFader::on_size_allocate (Gtk::Allocation& alloc) span = alloc.get_width (); } - update_unity_position (); - if (is_realized()) { - create_patterns(); - queue_draw (); + /* recreate patterns in case we've changed size */ + create_patterns (); } + + update_unity_position (); } bool @@ -507,14 +540,6 @@ PixFader::display_span () return ds; } -void -PixFader::set_fader_length (int l) -{ - span = l; - update_unity_position (); - queue_resize (); -} - void PixFader::update_unity_position () { @@ -576,6 +601,7 @@ PixFader::set_text (const std::string& str) if (_layout) { _layout->set_text (str); + _layout->get_pixel_size (_text_width, _text_height); } queue_resize (); @@ -587,3 +613,19 @@ PixFader::on_state_changed (Gtk::StateType old_state) Widget::on_state_changed (old_state); create_patterns (); } + +void +PixFader::on_style_changed (const Glib::RefPtr&) +{ + if (_layout) { + std::string txt = _layout->get_text(); + _layout.clear (); // drop reference to existing layout + set_text (txt); + } + + /* remember that all patterns are cached and not owned by an individual + pixfader. we will lazily create a new pattern when needed. + */ + + pattern = 0; +}