Update FSF address
[lttv.git] / lttv / modules / gui / lttvwindow / lttvwindow / timebar.c
CommitLineData
4172f013
YB
1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2010 Yannick Brosseau
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 Version 2 as
6 * published by the Free Software Foundation;
7 *
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.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
b9ce0bad
YB
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 * MA 02110-1301, USA.
4172f013
YB
17 */
18#include "timebar.h"
19
20#include "timeentry.h"
21
22#include <gtk/gtkeventbox.h>
23#include <gtk/gtkvseparator.h>
190724cd 24#include <lttv/time.h>
4172f013
YB
25
26enum {
27 SIGNAL_START_TIME_CHANGED,
28 SIGNAL_END_TIME_CHANGED,
29 SIGNAL_CURRENT_TIME_CHANGED,
30 LAST_SIGNAL
31};
32
33static void timebar_class_init(TimebarClass *klass);
34static void timebar_init(Timebar *ttt);
35
36static guint timebar_signals[LAST_SIGNAL] = { 0 };
37
38static void on_start_time_value_changed(Timeentry *spinbutton,
39 gpointer user_data);
40static void on_end_time_value_changed(Timeentry *spinbutton,
41 gpointer user_data);
42static void on_interval_time_value_changed(Timeentry *spinbutton,
43 gpointer user_data);
44static void on_current_time_value_changed(Timeentry *spinbutton,
45 gpointer user_data);
46
47static void update_interval(Timebar *timebar);
48
49static inline LttTime timeentry_get_ltt_time(Timeentry *timeentry)
50{
51 LttTime time;
52
53 timeentry_get_time(timeentry,
54 &time.tv_sec,
55 &time.tv_nsec);
56 return time;
57}
58
59GType timebar_get_type(void)
60{
61 static GType tb_type = 0;
62
63 if (!tb_type) {
64 const GTypeInfo tb_info =
65 {
66 sizeof (TimebarClass),
67 NULL, /* base_init */
68 NULL, /* base_finalize */
69 (GClassInitFunc) timebar_class_init,
70 NULL, /* class_finalize */
71 NULL, /* class_data */
72 sizeof (Timebar),
73 0, /* n_preallocs */
74 (GInstanceInitFunc) timebar_init,
75 };
76
77 tb_type = g_type_register_static(GTK_TYPE_HBOX,
78 "Timebar",
79 &tb_info,
80 0);
81 }
82
83 return tb_type;
84}
85
86
87static void timebar_class_init(TimebarClass *klass)
88{
89 timebar_signals[SIGNAL_START_TIME_CHANGED] = g_signal_new("start-time-changed",
90 G_TYPE_FROM_CLASS(klass),
91 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
92 G_STRUCT_OFFSET(TimebarClass, timebar),
93 NULL,
94 NULL,
95 g_cclosure_marshal_VOID__VOID,
96 G_TYPE_NONE, 0);
97
98 timebar_signals[SIGNAL_END_TIME_CHANGED] = g_signal_new("end-time-changed",
99 G_TYPE_FROM_CLASS(klass),
100 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
101 G_STRUCT_OFFSET(TimebarClass, timebar),
102 NULL,
103 NULL,
104 g_cclosure_marshal_VOID__VOID,
105 G_TYPE_NONE, 0);
106 timebar_signals[SIGNAL_CURRENT_TIME_CHANGED] = g_signal_new("current-time-changed",
107 G_TYPE_FROM_CLASS(klass),
108 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
109 G_STRUCT_OFFSET(TimebarClass, timebar),
110 NULL,
111 NULL,
112 g_cclosure_marshal_VOID__VOID,
113 G_TYPE_NONE, 0);
114}
115
116
117static void timebar_init(Timebar *timebar)
118{
119 /* Title label */
120 timebar->title_eventbox = gtk_event_box_new();
121 gtk_widget_show(timebar->title_eventbox);
122
123 timebar->title_label = gtk_label_new("Time Frame ");
124 gtk_widget_show(timebar->title_label);
125 gtk_container_add(GTK_CONTAINER(timebar->title_eventbox), timebar->title_label);
126
127 /* Start time entry */
128 timebar->start_timeentry = timeentry_new("Start: ");
129 gtk_widget_show(timebar->start_timeentry);
130
131 /* End time entry */
132 timebar->end_timeentry = timeentry_new("End: ");
133 gtk_widget_show(timebar->end_timeentry);
134
135 /* Interval time entry */
136 timebar->interval_timeentry = timeentry_new("Time Interval: ");
137 gtk_widget_show(timebar->interval_timeentry);
138
139 /* Current time entry */
140 timebar->current_timeentry = timeentry_new("Current Time: ");
141 gtk_widget_show(timebar->current_timeentry);
142
143 /* Pack all the widget in the timebar box */
144 GtkWidget *temp_widget;
145
146 gtk_box_pack_start (GTK_BOX(timebar), timebar->title_eventbox, FALSE, FALSE, 2);
147
148 gtk_box_pack_start (GTK_BOX(timebar), timebar->start_timeentry, FALSE, FALSE, 0);
149
150 temp_widget = gtk_vseparator_new();
151 gtk_widget_show(temp_widget);
152 gtk_box_pack_start (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2);
153
154 gtk_box_pack_start (GTK_BOX(timebar), timebar->end_timeentry, FALSE, FALSE, 0);
155
156 temp_widget = gtk_vseparator_new();
157 gtk_widget_show(temp_widget);
158 gtk_box_pack_start (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2);
159
160 gtk_box_pack_start (GTK_BOX(timebar), timebar->interval_timeentry, FALSE, FALSE, 0);
161
162 gtk_box_pack_end (GTK_BOX(timebar), timebar->current_timeentry, FALSE, FALSE, 0);
163 temp_widget = gtk_vseparator_new();
164 gtk_widget_show(temp_widget);
165 gtk_box_pack_end (GTK_BOX(timebar), temp_widget, FALSE, FALSE, 2);
166
167 /* Set an initial time */
168 timebar_set_minmax_time(timebar, &ltt_time_zero, &ltt_time_one);
169
170 /* Connect signals */
171 g_signal_connect ((gpointer) timebar->start_timeentry, "time-changed",
172 G_CALLBACK(on_start_time_value_changed),
173 timebar);
174 g_signal_connect ((gpointer) timebar->end_timeentry, "time-changed",
175 G_CALLBACK(on_end_time_value_changed),
176 timebar);
177 timebar->interval_handler_id =
178 g_signal_connect ((gpointer) timebar->interval_timeentry, "time-changed",
179 G_CALLBACK (on_interval_time_value_changed),
180 timebar);
181 g_signal_connect ((gpointer) timebar->current_timeentry, "time-changed",
182 G_CALLBACK(on_current_time_value_changed),
183 timebar);
184}
185
186GtkWidget *timebar_new(void)
187{
188 return GTK_WIDGET(g_object_new (TIMEBAR_TYPE, NULL));
189}
190
191void timebar_set_current_time(Timebar *timebar, const LttTime* time)
192{
193 if (time == NULL) {
194 return;
195 }
196
197 timeentry_set_time(TIMEENTRY(timebar->current_timeentry),
198 time->tv_sec,
199 time->tv_nsec);
200}
201
202void timebar_set_start_time(Timebar *timebar, const LttTime* time)
203{
204 if (time == NULL) {
205 return;
206 }
207
208 timeentry_set_time(TIMEENTRY(timebar->start_timeentry),
209 time->tv_sec,
210 time->tv_nsec);
211
212 update_interval(timebar);
213}
214
215void timebar_set_end_time(Timebar *timebar, const LttTime* time)
216{
217 if (time == NULL) {
218 return;
219 }
220
221 timeentry_set_time(TIMEENTRY(timebar->end_timeentry),
222 time->tv_sec,
223 time->tv_nsec);
224 update_interval(timebar);
225}
226
227void timebar_set_minmax_time(Timebar *timebar,
228 const LttTime *min_time,
229 const LttTime *max_time)
230{
231 LttTime new_interval_length;
232 LttTime start_max_time;
233 LttTime end_min_time;
234
235 /* Need to set both min_time and max_time */
236 if (min_time == NULL || max_time == NULL) {
237 return;
238 }
239 /* Do nothing if there is no change */
240 if (ltt_time_compare(timebar->min_time, *min_time) == 0 &&
241 ltt_time_compare(timebar->max_time, *max_time) == 0
242 ) {
243 return;
244 }
451aaf27
FD
245 /* null-checked already */
246 timebar->min_time = *min_time;
247 timebar->max_time = *max_time;
4172f013
YB
248
249 if (ltt_time_compare(timebar->min_time, timebar->max_time) == 0) {
250
251 /* If the min and max are equal set the same values, which will
252 disable all the widgets of the timebar */
253 new_interval_length.tv_sec = 0;
254 new_interval_length.tv_nsec = 1;
255
256 start_max_time.tv_sec = timebar->max_time.tv_sec;
257 start_max_time.tv_nsec = timebar->max_time.tv_nsec;
258
259 end_min_time.tv_sec = timebar->min_time.tv_sec;
260 end_min_time.tv_nsec = timebar->min_time.tv_nsec;
261
262 } else {
263 /* Special minmax (to keep a minimum interval of 1 nsec */
264 /* start max time is max minus 1 nsec */
265 if (timebar->max_time.tv_nsec == 0) {
266 start_max_time.tv_sec = timebar->max_time.tv_sec - 1;
267 start_max_time.tv_nsec = NANOSECONDS_PER_SECOND - 1;
268 } else {
269 start_max_time.tv_sec = timebar->max_time.tv_sec;
270 start_max_time.tv_nsec = timebar->max_time.tv_nsec - 1;
271 }
272
273 /* end min time is min plus 1 nsec */
274 if (timebar->min_time.tv_nsec + 1 == NANOSECONDS_PER_SECOND) {
275 end_min_time.tv_sec = timebar->min_time.tv_sec + 1;
276 end_min_time.tv_nsec = 0;
277 } else {
278 end_min_time.tv_sec = timebar->min_time.tv_sec;
279 end_min_time.tv_nsec = timebar->min_time.tv_nsec + 1;
280 }
281
282 /* Compute max interval */
283 new_interval_length = ltt_time_sub(timebar->max_time,
284 timebar->min_time);
285 }
286
287
288 /* Update widgets */
289 timeentry_set_minmax_time(TIMEENTRY(timebar->start_timeentry),
290 timebar->min_time.tv_sec,
291 timebar->min_time.tv_nsec,
292 start_max_time.tv_sec,
293 start_max_time.tv_nsec);
294 timeentry_set_minmax_time(TIMEENTRY(timebar->end_timeentry),
295 end_min_time.tv_sec,
296 end_min_time.tv_nsec,
297 timebar->max_time.tv_sec,
298 timebar->max_time.tv_nsec);
299 timeentry_set_minmax_time(TIMEENTRY(timebar->current_timeentry),
300 timebar->min_time.tv_sec,
301 timebar->min_time.tv_nsec,
302 timebar->max_time.tv_sec,
303 timebar->max_time.tv_nsec);
304
305
306 timeentry_set_minmax_time(TIMEENTRY(timebar->interval_timeentry),
307 0,
308 1,
309 new_interval_length.tv_sec,
310 new_interval_length.tv_nsec);
311}
312
313LttTime timebar_get_start_time(Timebar *timebar)
314{
315 return timeentry_get_ltt_time(TIMEENTRY(timebar->start_timeentry));
316}
317
318LttTime timebar_get_end_time(Timebar *timebar)
319{
320 return timeentry_get_ltt_time(TIMEENTRY(timebar->end_timeentry));
321}
322
323LttTime timebar_get_current_time(Timebar *timebar)
324{
325 return timeentry_get_ltt_time(TIMEENTRY(timebar->current_timeentry));
326}
327
328static void update_interval(Timebar *timebar)
329{
330 LttTime start_time = timeentry_get_ltt_time(TIMEENTRY(timebar->start_timeentry));
331 LttTime end_time = timeentry_get_ltt_time(TIMEENTRY(timebar->end_timeentry));
332 LttTime new_interval;
333
334 /* Compute max interval */
335 new_interval = ltt_time_sub(end_time,
336 start_time);
337
338 /* Don't trigger the signal when we update the interval */
339 g_signal_handler_block(timebar->interval_timeentry,
340 timebar->interval_handler_id);
341
342 timeentry_set_time(TIMEENTRY(timebar->interval_timeentry),
343 new_interval.tv_sec,
344 new_interval.tv_nsec);
345
346 g_signal_handler_unblock(timebar->interval_timeentry,
347 timebar->interval_handler_id);
348}
349
350static void on_start_time_value_changed(Timeentry *timeentry,
351 gpointer user_data)
352{
353 Timebar *timebar = (Timebar *)user_data;
354
355 update_interval(timebar);
356
357 g_signal_emit(timebar,
358 timebar_signals[SIGNAL_START_TIME_CHANGED], 0);
359}
360
361static void on_end_time_value_changed(Timeentry *timeentry,
362 gpointer user_data)
363{
364 Timebar *timebar = (Timebar *)user_data;
365
366 update_interval(timebar);
367
368 g_signal_emit(timebar,
369 timebar_signals[SIGNAL_END_TIME_CHANGED], 0);
370}
371
372static void on_interval_time_value_changed (Timeentry *timeentry,
373 gpointer user_data)
374{
375 Timebar *timebar = (Timebar *)user_data;
376
377 LttTime new_interval = timeentry_get_ltt_time(TIMEENTRY(timebar->interval_timeentry));
378
379 LttTime start_time = timebar_get_start_time(timebar);
380
381 LttTime new_end_time;
382
383 gboolean need_interval_update = FALSE;
384
385 /* Lock the start and change the end */
386 new_end_time = ltt_time_add(start_time, new_interval);
387
388 /* We cannot push further the max end */
389 if (ltt_time_compare(new_end_time, timebar->max_time) > 0) {
390 /* Set the end to the max and pull on the start */
391 new_end_time = timebar->max_time;
392 LttTime new_start_time = ltt_time_sub(new_end_time, new_interval);
393
394 /* We cannot pull before the min start */
395 if (ltt_time_compare(new_start_time, timebar->min_time) < 0) {
396 /* Set the interval to the max */
397 new_start_time = timebar->min_time;
398 need_interval_update = TRUE;
399 }
400 timebar_set_start_time(timebar, &new_start_time);
401 }
402 timebar_set_end_time(timebar, &new_end_time);
403
404 if (need_interval_update) {
405 update_interval(timebar);
406 }
407}
408
409static void on_current_time_value_changed(Timeentry *timeentry,
410 gpointer user_data)
411{
412 Timebar *timebar = (Timebar *)user_data;
413
414 g_signal_emit(timebar,
415 timebar_signals[SIGNAL_CURRENT_TIME_CHANGED], 0);
416}
417
418
This page took 0.039605 seconds and 4 git commands to generate.