2 Copyright (C) 2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "gtkmm2ext/cairo_widget.h"
21 #include "gtkmm2ext/gui_thread.h"
25 static const char* has_cairo_widget_background_info = "has_cairo_widget_background_info";
27 bool CairoWidget::_flat_buttons = false;
29 void CairoWidget::set_source_rgb_a( cairo_t* cr, Gdk::Color col, float a) //ToDo: this one and the Canvas version should be in a shared file (?)
31 float r = col.get_red_p ();
32 float g = col.get_green_p ();
33 float b = col.get_blue_p ();
35 cairo_set_source_rgba(cr, r, g, b, a);
38 CairoWidget::CairoWidget ()
39 : _active_state (Gtkmm2ext::Off)
40 , _visual_state (Gtkmm2ext::NoVisualState)
43 , _name_proxy (this, X_("name"))
46 _name_proxy.connect (sigc::mem_fun (*this, &CairoWidget::on_name_changed));
49 CairoWidget::~CairoWidget ()
51 if (_parent_style_change) _parent_style_change.disconnect();
55 CairoWidget::on_expose_event (GdkEventExpose *ev)
57 cairo_t* cr = gdk_cairo_create (get_window ()->gobj());
58 cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height);
59 cairo_clip_preserve (cr);
61 /* paint expose area the color of the parent window bg
64 Gdk::Color bg (get_parent_bg());
66 cairo_set_source_rgb (cr, bg.get_red_p(), bg.get_green_p(), bg.get_blue_p());
69 cairo_rectangle_t expose_area;
70 expose_area.x = ev->area.x;
71 expose_area.y = ev->area.y;
72 expose_area.width = ev->area.width;
73 expose_area.height = ev->area.height;
75 render (cr, &expose_area);
82 /** Marks the widget as dirty, so that render () will be called on
83 * the next GTK expose event.
87 CairoWidget::set_dirty ()
89 ENSURE_GUI_THREAD (*this, &CairoWidget::set_dirty);
93 /** Handle a size allocation.
94 * @param alloc GTK allocation.
97 CairoWidget::on_size_allocate (Gtk::Allocation& alloc)
99 Gtk::EventBox::on_size_allocate (alloc);
105 CairoWidget::get_parent_bg ()
109 parent = get_parent ();
112 void* p = g_object_get_data (G_OBJECT(parent->gobj()), has_cairo_widget_background_info);
115 Glib::RefPtr<Gtk::Style> style = parent->get_style();
116 if (_current_parent != parent) {
117 if (_parent_style_change) _parent_style_change.disconnect();
118 _current_parent = parent;
119 _parent_style_change = parent->signal_style_changed().connect (mem_fun (*this, &CairoWidget::on_style_changed));
121 return style->get_bg (get_state());
124 if (!parent->get_has_window()) {
125 parent = parent->get_parent();
131 if (parent && parent->get_has_window()) {
132 if (_current_parent != parent) {
133 if (_parent_style_change) _parent_style_change.disconnect();
134 _current_parent = parent;
135 _parent_style_change = parent->signal_style_changed().connect (mem_fun (*this, &CairoWidget::on_style_changed));
137 return parent->get_style ()->get_bg (parent->get_state());
140 return get_style ()->get_bg (get_state());
144 CairoWidget::set_active_state (Gtkmm2ext::ActiveState s)
146 if (_active_state != s) {
153 CairoWidget::set_visual_state (Gtkmm2ext::VisualState s)
155 if (_visual_state != s) {
162 CairoWidget::set_active (bool yn)
164 /* this is an API simplification for buttons
165 that only use the Active and Normal states.
169 set_active_state (Gtkmm2ext::ExplicitActive);
171 unset_active_state ();
176 CairoWidget::on_style_changed (const Glib::RefPtr<Gtk::Style>&)
182 CairoWidget::on_state_changed (Gtk::StateType)
184 /* this will catch GTK-level state changes from calls like
188 if (get_state() == Gtk::STATE_INSENSITIVE) {
189 set_visual_state (Gtkmm2ext::VisualState (visual_state() | Gtkmm2ext::Insensitive));
191 set_visual_state (Gtkmm2ext::VisualState (visual_state() & ~Gtkmm2ext::Insensitive));
198 CairoWidget::set_draw_background (bool yn)
204 CairoWidget::provide_background_for_cairo_widget (Gtk::Widget& w, const Gdk::Color& bg)
206 /* set up @w to be able to provide bg information to
207 any CairoWidgets that are packed inside it.
210 w.modify_bg (Gtk::STATE_NORMAL, bg);
211 w.modify_bg (Gtk::STATE_INSENSITIVE, bg);
212 w.modify_bg (Gtk::STATE_ACTIVE, bg);
213 w.modify_bg (Gtk::STATE_SELECTED, bg);
215 g_object_set_data (G_OBJECT(w.gobj()), has_cairo_widget_background_info, (void*) 0xfeedface);
219 CairoWidget::set_flat_buttons (bool yn)