[DataView] Fix bold of playing song, italic 'prioritized songs'
[gmpc.git] / src / Widgets / gmpc-progress.vala
blobfe5bd9f15b7ceefed7c1c92160bf06fd2018ba40
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 using GLib;
21 using Gtk;
22 using Gdk;
25 private const bool use_transition = Gmpc.use_transition;
27 public class Gmpc.Progress : Gtk.VBox
29 private uint total = 0;
30 private uint current = 0;
31 private bool do_countdown = false;
32 public bool _hide_text = false;
33 private Gtk.Scale scale = null;
34 private Gtk.Label label = null;
35 private ulong set_value_handler = 0;
36 private Gtk.Window tooltip = null;
37 private Gtk.Label tooltip_label = null;
39 /**
40 * Destructor
42 ~Progress()
44 /* If there is a tooltip on destruction of slider, destroy it */
45 if(this.tooltip != null)
47 this.tooltip.destroy();
48 this.tooltip = null;
52 /* Set/getter for enabling/disabling text label */
53 public bool hide_text
55 get {
56 return _hide_text;
58 set {
59 _hide_text = value;
60 if(_hide_text)
62 this.label.hide();
64 else{
65 this.label.show();
69 /**
70 * Paint a nice box around it
72 private bool tooltip_expose_event_callback(Gtk.Widget tooltip, Cairo.Context ctx)
74 /* TODO:
75 Gtk.render_frame(tooltip.get_style_context(),
76 Gdk.cairo_create(tooltip.get_window()),
77 0,0,
78 tooltip.get_allocated_width(), tooltip.get_allocated_height());
80 return false;
83 private bool enter_notify_event_callback(Gtk.Widget scale, Gdk.EventCrossing event)
85 /* Create tooltip if mouse enters the event window */
86 if (event.type == Gdk.EventType.ENTER_NOTIFY)
88 if ( tooltip != null ) tooltip.destroy();
89 tooltip = new Gtk.Window(Gtk.WindowType.POPUP);
90 tooltip_label = new Gtk.Label("test");
91 tooltip.add(tooltip_label);
92 tooltip.border_width = 4;
93 tooltip.set_app_paintable(true);
94 tooltip.draw.connect(tooltip_expose_event_callback);
96 /* Destroy tooltip if mouse leaves the event window */
97 if (event.type == Gdk.EventType.LEAVE_NOTIFY)
99 if(tooltip != null)
101 tooltip.destroy();
102 tooltip = null;
105 return false;
107 private bool motion_notify_event_callback(Gtk.Widget scale, Gdk.EventMotion event)
109 if(event.type == Gdk.EventType.MOTION_NOTIFY)
111 if(tooltip != null)
113 int e_hour, e_minutes, e_seconds;
114 int t_hour = (int) this.total / 3600;
115 int t_minutes = (int) this.total%3600/60;
116 int t_seconds = (int) this.total%60;
117 string a = "";
118 uint p = (uint)(this.total * (event.x/(double)(scale.get_allocated_width()-scale.style.xthickness)));
119 /* Don't show beyond end time */
120 p = (p > this.total)? this.total:p;
121 if(this.do_countdown)
123 a += "-";
124 p = this.total-p;
126 e_hour = (int) p/3600;
127 e_minutes = (int) (p%3600)/60;
128 e_seconds = (int) (p%60);
129 if(e_hour>0)
131 a += "%02i:".printf(e_hour);
133 a += "%02i:%02i".printf(e_minutes, e_seconds);
134 if(this.total > 0)
136 a += " - ";
137 if(t_hour>0)
139 a += "%02i:".printf(t_hour);
141 a += "%02i:%02i".printf(t_minutes,t_seconds);
143 if(this.do_countdown)
144 this.tooltip_label.width_chars = (int)a.length;
145 else
146 this.tooltip_label.width_chars = (int)a.length+1;
147 this.tooltip_label.set_text(a);
149 tooltip.show_all();
150 tooltip.realize();
151 tooltip.move((int)event.x_root-tooltip.get_allocated_width()/2, (int)event.y_root+tooltip.get_allocated_height());
154 return false;
157 /* Construct function */
158 construct
161 this.scale = new Gtk.HScale(null);
162 this.scale.set_range(0.0,1.0);
163 this.scale.draw_value = false;
164 this.set_value_handler = GLib.Signal.connect_swapped(this.scale,"value_changed",(GLib.Callback)value_changed,this);
165 // this.scale.update_policy = Gtk.UpdateType.DISCONTINUOUS;//DELAYED;//DISCONTINUOUS;
166 this.scale.sensitive = false;
167 this.set_spacing(0);
168 this.scale.add_events((int)Gdk.EventMask.SCROLL_MASK);
169 this.scale.add_events((int)Gdk.EventMask.POINTER_MOTION_MASK);
170 this.scale.add_events((int)Gdk.EventMask.ENTER_NOTIFY_MASK);
171 this.scale.add_events((int)Gdk.EventMask.LEAVE_NOTIFY_MASK);
172 this.scale.scroll_event.connect(scroll_event_callback);
173 GLib.Signal.connect_object(this.scale, "button-press-event",
174 (GLib.Callback)button_press_event_callback, this, GLib.ConnectFlags.SWAPPED|GLib.ConnectFlags.AFTER);
175 this.scale.button_release_event.connect(button_release_event_callback);
176 this.scale.motion_notify_event.connect(motion_notify_event_callback);
177 this.scale.enter_notify_event.connect(enter_notify_event_callback);
178 this.scale.leave_notify_event.connect(enter_notify_event_callback);
180 this.label = new Gtk.Label("");
181 this.label.set_alignment(0.5f,0.5f);
182 this.label.set_no_show_all(true);
184 this.pack_start(this.scale, true,true,0);
185 this.pack_end(this.label, false,false,0);
186 this.scale.show();
187 this.label.show();
189 this.show();
192 public signal void seek_event (uint seek_time);
195 private void value_changed (Gtk.Scale range)
197 if(this.total > 0)
199 uint seconds = (uint)(this.total*(range.get_value()));
200 if(seconds != this.current)
201 seek_event(seconds);
204 private int press = 0;
205 private bool button_release_event_callback (Gtk.Widget scale, Gdk.EventButton event)
207 this.press--;
208 return false;
210 private bool button_press_event_callback (Gdk.EventButton event, Gtk.Scale scale)
212 this.press++;
213 if(event.type == Gdk.EventType.BUTTON_PRESS)
215 if(event.button == 3)
217 this.do_countdown = !this.do_countdown;
218 var cur = this.current;
219 var tot = this.total;
220 this.total=this.current = 0;
221 set_time(tot,cur);
223 if(event.button == 2 || event.button == 1)
225 uint p = (uint)(this.total * (event.x/(double)(scale.get_allocated_width()-scale.style.xthickness)));
226 p = (p > this.total)? this.total:p;
227 seek_event(p);
228 return true;
231 else if (event.type == Gdk.EventType.2BUTTON_PRESS)
233 if(event.button == 2 || event.button == 1)
235 uint p = (uint)(this.total * (event.x/(double)(scale.get_allocated_width()-scale.style.xthickness)));
236 p = (p > this.total)? this.total:p;
237 seek_event(p);
238 return true;
241 return false;
244 private bool scroll_event_callback (Gtk.Widget scale,Gdk.EventScroll event)
246 if(event.direction == Gdk.ScrollDirection.UP)
248 seek_event(this.current+5);
250 else if (event.direction == Gdk.ScrollDirection.DOWN)
252 seek_event(this.current-5);
254 return false;
257 public void set_time(uint total, uint current)
259 if(this.press > 0) return;
260 if(this.total != total)
262 this.scale.sensitive = (total > 0);
265 if(this.total != total || this.current != current)
267 this.total = total;
268 this.current = current;
270 GLib.SignalHandler.block(this.scale, this.set_value_handler);
271 if(this.total > 0)
273 this.scale.set_value(this.current/(double)this.total);
275 else
277 this.scale.set_value(0.0);
280 GLib.SignalHandler.unblock(this.scale, this.set_value_handler);
282 if(this.hide_text == false)
284 int e_hour, e_minutes, e_seconds;
285 int t_hour = (int) this.total / 3600;
286 int t_minutes = (int) this.total%3600/60;
287 int t_seconds = (int) this.total%60;
288 string a = "";
289 uint p = this.current;
290 if(this.do_countdown)
292 p = this.total-this.current;
293 a += "-";
295 e_hour = (int) p/3600;
296 e_minutes = (int) (p%3600)/60;
297 e_seconds = (int) (p%60);
298 if(e_hour>0)
300 a += "%02i:".printf(e_hour);
302 a += "%02i:%02i".printf(e_minutes, e_seconds);
303 if(this.total > 0)
305 a += " - ";
306 if(t_hour>0)
308 a += "%02i:".printf(t_hour);
310 a += "%02i:%02i".printf(t_minutes,t_seconds);
312 if(this.do_countdown)
313 this.label.width_chars = (int)a.length;
314 else
315 this.label.width_chars = (int)a.length+1;
316 this.label.set_text(a);
322 /* vim: set noexpandtab ts=4 sw=4 sts=4 tw=120: */