Allow CairoWidget to be backed by NSGLView
[ardour.git] / libs / gtkmm2ext / gtkmm2ext / cairo_widget.h
1 /*
2     Copyright (C) 2009 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #ifndef __gtk2_ardour_cairo_widget_h__
21 #define __gtk2_ardour_cairo_widget_h__
22
23 #include <cairomm/surface.h>
24 #include <gtkmm/eventbox.h>
25
26 #include "gtkmm2ext/visibility.h"
27 #include "gtkmm2ext/cairo_canvas.h"
28 #include "gtkmm2ext/widget_state.h"
29
30 /** A parent class for widgets that are rendered using Cairo.
31  */
32
33 class LIBGTKMM2EXT_API CairoWidget : public Gtk::EventBox, public Gtkmm2ext::CairoCanvas
34 {
35 public:
36         CairoWidget ();
37         virtual ~CairoWidget ();
38
39         void set_canvas_widget ();
40         void use_nsglview ();
41
42         /* swizzle Gtk::Widget methods for Canvas::Widget */
43         void queue_draw ();
44         void queue_resize ();
45         int get_width () const;
46         int get_height () const;
47         void size_allocate (Gtk::Allocation&);
48
49         void set_dirty (cairo_rectangle_t *area = 0);
50
51         Gtkmm2ext::ActiveState active_state() const { return _active_state; }
52         Gtkmm2ext::VisualState visual_state() const { return _visual_state; }
53
54         /* derived widgets can override these two to catch
55            changes in active & visual state
56         */
57
58         virtual void set_active_state (Gtkmm2ext::ActiveState);
59         virtual void set_visual_state (Gtkmm2ext::VisualState);
60
61         void unset_active_state () { set_active_state (Gtkmm2ext::Off); }
62         void unset_visual_state () { set_visual_state (Gtkmm2ext::NoVisualState); }
63
64         /* this is an API simplification for widgets
65            that only use the Active and Normal active states.
66         */
67         void set_active (bool);
68         bool get_active () const { return active_state() != Gtkmm2ext::Off; }
69
70         /* widgets can be told to only draw their "foreground, and thus leave
71            in place whatever background is drawn by their parent. the default
72            is that the widget will fill its event window with the background
73            color of the parent container.
74         */
75
76         void set_draw_background (bool yn);
77
78         sigc::signal<void> StateChanged;
79         sigc::signal<bool> QueueDraw;
80         sigc::signal<bool> QueueResize;
81
82         static void provide_background_for_cairo_widget (Gtk::Widget& w, const Gdk::Color& bg);
83
84         virtual void render (cairo_t *, cairo_rectangle_t*) = 0;
85
86         virtual void render (Cairo::RefPtr<Cairo::Context> const & ctx, cairo_rectangle_t* r) {
87                 render (ctx->cobj(), r);
88         }
89
90         uint32_t background_color ();
91
92         static void set_flat_buttons (bool yn);
93         static bool flat_buttons() { return _flat_buttons; }
94
95         static void set_widget_prelight (bool yn);
96         static bool widget_prelight() { return _widget_prelight; }
97
98         static void set_source_rgb_a( cairo_t* cr, Gdk::Color, float a=1.0 );
99
100         /* set_focus_handler() will cause all button-press events on any
101            CairoWidget to invoke this slot/functor/function/method/callback.
102
103            We do this because in general, CairoWidgets do not grab
104            keyboard focus, but a button press on them should
105            clear focus from any active text entry.
106
107            This is global to all CairoWidgets and derived types.
108
109            However, derived types can override the behaviour by defining their
110            own on_button_press_event() handler which returns true under all
111            conditions (which will block this handler from being called). If
112            they wish to invoke any existing focus handler from their own
113            button press handler, they can just use: focus_handler();
114         */
115         static void set_focus_handler (sigc::slot<void,Gtk::Widget*>);
116
117 protected:
118         /** Render the widget to the given Cairo context */
119         virtual bool on_expose_event (GdkEventExpose *);
120         void on_size_allocate (Gtk::Allocation &);
121         void on_state_changed (Gtk::StateType);
122         void on_style_changed (const Glib::RefPtr<Gtk::Style>&);
123         void on_realize ();
124         bool on_button_press_event (GdkEventButton*);
125         Gdk::Color get_parent_bg ();
126
127         /* this is an additional virtual "on_..." method. Glibmm does not
128            provide a direct signal for name changes, so this acts as a proxy.
129         */
130
131         virtual void on_name_changed () {};
132
133         Gtkmm2ext::ActiveState _active_state;
134         Gtkmm2ext::VisualState _visual_state;
135         bool                   _need_bg;
136
137         static bool     _flat_buttons;
138         static bool     _widget_prelight;
139         bool            _grabbed;
140
141         static sigc::slot<void,Gtk::Widget*> focus_handler;
142
143   private:
144         Cairo::RefPtr<Cairo::Surface> image_surface;
145         Glib::SignalProxyProperty _name_proxy;
146         sigc::connection _parent_style_change;
147         Widget * _current_parent;
148         bool _canvas_widget;
149         void* _nsglview;
150         Gdk::Rectangle _allocation;
151
152 };
153
154 #endif