X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fgtkmm2ext%2Fstateful_button.cc;h=3880a1b35c853b5f52e00e18f5c61bd02c2e2f61;hb=99c1aacc236fcba1f297804baf9f5d1b0825e2ee;hp=000b7b8ea1dba5618eb008b3445779dfac2225df;hpb=8e79cd5610789b377d0975640a555cc45d9300cb;p=ardour.git diff --git a/libs/gtkmm2ext/stateful_button.cc b/libs/gtkmm2ext/stateful_button.cc index 000b7b8ea1..3880a1b35c 100644 --- a/libs/gtkmm2ext/stateful_button.cc +++ b/libs/gtkmm2ext/stateful_button.cc @@ -1,6 +1,26 @@ +/* + Copyright (C) 2000-2007 Paul Davis + + 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 @@ -10,24 +30,20 @@ using namespace Glib; using namespace Gtkmm2ext; using namespace std; -StateButton::StateButton () +StateButton::StateButton () + : visual_state (0) + , _self_managed (false) + , _is_realized (false) + , style_changing (false) + , state_before_prelight (Gtk::STATE_NORMAL) + , is_toggle (false) { - visual_state = 0; - have_saved_bg = false; -} - -void -StateButton::set_colors (const vector& c) -{ - colors = c; - visual_state++; // to force transition - set_visual_state (visual_state - 1); } void StateButton::set_visual_state (int n) { - if (!have_saved_bg) { + if (!_is_realized) { /* not yet realized */ visual_state = n; return; @@ -36,44 +52,126 @@ StateButton::set_visual_state (int n) if (n == visual_state) { return; } - - if (n == 0) { - - /* back to the default color */ - - if (have_saved_bg) { - bg_modify (STATE_NORMAL, saved_bg); - bg_modify (STATE_ACTIVE, saved_bg); - bg_modify (STATE_SELECTED, saved_bg); - bg_modify (STATE_PRELIGHT, saved_bg); - } - - - } else { - - int index = (n-1) % colors.size (); - - bg_modify (STATE_NORMAL, colors[index]); - bg_modify (STATE_ACTIVE, colors[index]); - bg_modify (STATE_SELECTED, colors[index]); - bg_modify (STATE_PRELIGHT, colors[index]); + + string name = get_widget_name (); + name = name.substr (0, name.find_last_of ('-')); + + switch (n) { + case 0: + /* relax */ + break; + case 1: + name += "-active"; + break; + + case 2: + name += "-alternate"; + break; + + case 3: + name += "-alternate2"; + break; } + set_widget_name (name); visual_state = n; } +void +StateButton::avoid_prelight_on_style_changed (const Glib::RefPtr& /* old_style */, GtkWidget* widget) +{ + /* don't go into an endless recursive loop if we're changing + the style in response to an existing style change. + */ + + if (style_changing) { + return; + } + + if (gtk_widget_get_state (widget) == GTK_STATE_PRELIGHT) { + + /* avoid PRELIGHT: make sure that the prelight colors in this new style match + the colors of the new style in whatever state we were in + before we switched to prelight. + */ + + GtkRcStyle* rcstyle = gtk_widget_get_modifier_style (widget); + GtkStyle* style = gtk_widget_get_style (widget); + + rcstyle->fg[GTK_STATE_PRELIGHT] = style->fg[state_before_prelight]; + rcstyle->bg[GTK_STATE_PRELIGHT] = style->bg[state_before_prelight]; + rcstyle->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) (GTK_RC_FG|GTK_RC_BG); + + style_changing = true; + g_object_ref (rcstyle); + gtk_widget_modify_style (widget, rcstyle); + + Widget* child = get_child_widget(); + if (child) { + gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle); + } + + + g_object_unref (rcstyle); + style_changing = false; + } +} + +void +StateButton::avoid_prelight_on_state_changed (Gtk::StateType old_state, GtkWidget* widget) +{ + GtkStateType state = gtk_widget_get_state (widget); + + if (state == GTK_STATE_PRELIGHT) { + + state_before_prelight = old_state; + + + /* avoid PRELIGHT when currently ACTIVE: + if we just went into PRELIGHT, make sure that the colors + match those of whatever state we were in before. + */ + + GtkRcStyle* rcstyle = gtk_widget_get_modifier_style (widget); + GtkStyle* style = gtk_widget_get_style (widget); + + rcstyle->fg[GTK_STATE_PRELIGHT] = style->fg[old_state]; + rcstyle->bg[GTK_STATE_PRELIGHT] = style->bg[old_state]; + rcstyle->color_flags[GTK_STATE_PRELIGHT] = (GtkRcFlags) (GTK_RC_FG|GTK_RC_BG); + + g_object_ref (rcstyle); + gtk_widget_modify_style (widget, rcstyle); + + Widget* child = get_child_widget (); + + if (child) { + gtk_widget_modify_style (GTK_WIDGET(child->gobj()), rcstyle); + } + + g_object_unref (rcstyle); + + } +} + /* ----------------------------------------------------------------- */ +StatefulToggleButton::StatefulToggleButton () +{ + is_toggle = true; +} + +StatefulToggleButton::StatefulToggleButton (const std::string& label) + : ToggleButton (label) +{ + is_toggle = true; +} + void StatefulToggleButton::on_realize () { ToggleButton::on_realize (); - if (!have_saved_bg) { - saved_bg = get_style()->get_bg (STATE_NORMAL); - have_saved_bg = true; - } - + _is_realized = true; visual_state++; // to force transition set_visual_state (visual_state - 1); } @@ -83,11 +181,7 @@ StatefulButton::on_realize () { Button::on_realize (); - if (!have_saved_bg) { - saved_bg = get_style()->get_bg (STATE_NORMAL); - have_saved_bg = true; - } - + _is_realized = true; visual_state++; // to force transition set_visual_state (visual_state - 1); } @@ -97,9 +191,83 @@ StatefulToggleButton::on_toggled () { if (!_self_managed) { if (get_active()) { - set_visual_state (1); + set_state (Gtk::STATE_ACTIVE); } else { - set_visual_state (0); + set_state (Gtk::STATE_NORMAL); } } } + + +void +StatefulToggleButton::on_style_changed (const Glib::RefPtr& style) +{ + avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj())); + Button::on_style_changed (style); +} + +void +StatefulToggleButton::on_state_changed (Gtk::StateType old_state) +{ + avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj())); + Button::on_state_changed (old_state); +} + +Widget* +StatefulToggleButton::get_child_widget () +{ + return get_child(); +} + +void +StatefulToggleButton::set_widget_name (const std::string& name) +{ + set_name (name); + Widget* w = get_child(); + + if (w) { + w->set_name (name); + } +} + +/*--------------------------------------------- */ + +StatefulButton::StatefulButton () +{ +} + +StatefulButton::StatefulButton (const std::string& label) + : Button (label) +{ +} + +void +StatefulButton::on_style_changed (const Glib::RefPtr& style) +{ + avoid_prelight_on_style_changed (style, GTK_WIDGET(gobj())); + Button::on_style_changed (style); +} + +void +StatefulButton::on_state_changed (Gtk::StateType old_state) +{ + avoid_prelight_on_state_changed (old_state, GTK_WIDGET(gobj())); + Button::on_state_changed (old_state); +} + +Widget* +StatefulButton::get_child_widget () +{ + return get_child(); +} + +void +StatefulButton::set_widget_name (const std::string& name) +{ + set_name (name); + Widget* w = get_child(); + + if (w) { + w->set_name (name); + } +}