1 /* Demo Recorder for MAEMO 5
2 * Copyright (C) 2010 Dru Moore <usr@dru-id.co.uk>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2,
5 * or (at your option) any later version, as published by the Free
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 public class DbMonitorWidget : Gtk.Widget {
22 public static enum Layout {
27 private static const int BORDER_WIDTH = 4;
28 private static const int BORDER_HEIGHT = 4;
29 //private Pango.Layout layout;
30 private static const double MIN_VALUE = 0.0;
31 private static const double MAX_VALUE = 1.5;
33 private static const double ZERO_VALUE = 1.0;
37 public void set_peak(double val) {
38 this.peak = (MAX_VALUE > val) ? val : MAX_VALUE;
41 public void set_decay(double val) {
42 this.decay = (MAX_VALUE > val) ? val : MAX_VALUE;
45 private Layout layout = Layout.VERTICAL;
46 public void set_layout(Layout layout) {
55 * This method Gtk+ is calling on a widget to ask
56 * the widget how large it wishes to be. It's not guaranteed
57 * that Gtk+ will actually give this size to the widget.
59 public override void size_request (out Gtk.Requisition requisition) {
60 requisition.width = (Layout.VERTICAL == this.layout) ? 40 : 250;
61 requisition.height = (Layout.VERTICAL == this.layout) ? 250 : 40;
65 * This method gets called by Gtk+ when the actual size is known
66 * and the widget is told how much space could actually be allocated.
67 * It is called every time the widget size changes, for example when the
68 * user resizes the window.
70 public override void size_allocate (Gdk.Rectangle allocation) {
71 // The base method will save the allocation and move/resize the
72 // widget's GDK window if the widget is already realized.
73 base.size_allocate (allocation);
75 // Move/resize other realized windows if necessary
78 private void redraw_canvas () {
79 if (null == this.window) {
82 unowned Gdk.Region region = this.window.get_clip_region ();
83 // redraw the cairo canvas completely by exposing it
84 this.window.invalidate_region (region, true);
85 this.window.process_updates (true);
89 // Cairo context to draw on
90 Cairo.Context cr = Gdk.cairo_create (this.window);
91 // In this example, draw a rectangle in the foreground color
92 Gdk.cairo_set_source_color (cr, this.style.fg[this.state]);
93 cr.rectangle (BORDER_WIDTH, BORDER_HEIGHT,
94 this.allocation.width - 2 * BORDER_WIDTH,
95 this.allocation.height - 2 * BORDER_HEIGHT);
96 cr.set_line_width (1.0);
97 //cr.set_line_join (LineJoin.ROUND);
100 // draw the bar for the peak level
101 if (0.0 < this.peak) {
102 if (Layout.VERTICAL == this.layout) {
103 cr.rectangle (BORDER_WIDTH
104 , (this.allocation.height - 2 * BORDER_HEIGHT) - ( (this.allocation.height - 2 * BORDER_HEIGHT) / (MAX_VALUE - MIN_VALUE) ) * this.peak
105 , this.allocation.width - 2 * BORDER_WIDTH
106 , (((this.allocation.height - 2 * BORDER_HEIGHT) / (MAX_VALUE - MIN_VALUE)) * this.peak) + BORDER_HEIGHT
110 cr.rectangle (BORDER_WIDTH
112 , (((this.allocation.width - 2 * BORDER_WIDTH) / (MAX_VALUE - MIN_VALUE)) * this.peak) + BORDER_WIDTH
113 , this.allocation.height - 2 * BORDER_HEIGHT
116 cr.set_line_width (2.0);
120 // draw a line for the decay level
121 if (0.0 < this.decay) {
122 if (Layout.VERTICAL == this.layout) {
123 cr.rectangle (BORDER_WIDTH
124 , (this.allocation.height - 2 * BORDER_HEIGHT) - ( (this.allocation.height - 2 * BORDER_HEIGHT) / (MAX_VALUE - MIN_VALUE) ) * this.decay
125 , this.allocation.width - 2 * BORDER_WIDTH
130 cr.rectangle ((((this.allocation.width - 2 * BORDER_WIDTH) / (MAX_VALUE - MIN_VALUE)) * this.decay) + BORDER_WIDTH
133 , this.allocation.height - 2 * BORDER_HEIGHT
136 cr.set_line_width (2.0);
141 if (Layout.VERTICAL == this.layout) {
143 , (this.allocation.height) - ( (this.allocation.height) / (MAX_VALUE - MIN_VALUE) ) * ZERO_VALUE
144 , this.allocation.width
149 cr.rectangle ((((this.allocation.width) / (MAX_VALUE - MIN_VALUE)) * ZERO_VALUE)
152 , this.allocation.height
155 cr.set_line_width (1.0);
161 * This method is responsible for creating GDK (windowing system)
162 * resources. In this example we will create a new GDK window which we
165 public override void realize () {
166 // Create a new Gdk.Window which we can draw on.
167 // Also say that we want to receive exposure events by setting
169 var attrs = Gdk.WindowAttr () {
170 window_type = Gdk.WindowType.CHILD,
171 wclass = Gdk.WindowClass.INPUT_OUTPUT,
172 event_mask = get_events () | Gdk.EventMask.EXPOSURE_MASK
174 this.window = new Gdk.Window (get_parent_window (), attrs, 0);
175 this.window.move_resize (this.allocation.x, this.allocation.y,
176 this.allocation.width, this.allocation.height);
178 // Associate the GDK window with ourselves, Gtk+ needs a reference
179 // between the widget and the GDK window
180 this.window.set_user_data (this);
182 // Attach the style to the GDK window. A style contains colors and
183 // GC contexts used for drawing
184 this.style = this.style.attach (this.window);
186 // The default color of the background should be what
187 // the style (theme engine) tells us
188 this.style.set_background (this.window, Gtk.StateType.NORMAL);
190 // Set an internal flag telling that we're realized
191 set_flags (Gtk.WidgetFlags.REALIZED);
195 * This method is called when the widget is asked to draw itself.
196 * Remember that this will be called a lot of times, so it's usually
197 * a good idea to write this code as optimized as it can be, don't
198 * create any resources in here.
200 public override bool expose_event (Gdk.EventExpose event) {
206 * This method is responsible for freeing the GDK resources.
208 public override void unrealize () {
209 // The base method will de-associate the GDK window we created in
210 // method 'realize' with ourselves.
213 // De-associate other windows with 'set_user_data (null)' if necessary