1
#define __SP_UNIT_MENU_C__
4
* Unit selector with autupdate capability
7
* Lauris Kaplinski <lauris@kaplinski.com>
8
* bulia byak <buliabyak@users.sf.net>
10
* Copyright (C) 2000-2002 Authors
12
* Released under GNU GPL, read the file 'COPYING' for more information
15
#define noUNIT_SELECTOR_VERBOSE
20
#include <gtk/gtksignal.h>
21
#include <gtk/gtkhbox.h>
22
#include <gtk/gtkmenu.h>
23
#include <gtk/gtkmenuitem.h>
24
#include "helper/sp-marshal.h"
25
#include "helper/units.h"
26
#include "helper/unit-menu.h"
27
#include "widgets/spw-utilities.h"
29
struct SPUnitSelector {
46
struct SPUnitSelectorClass {
47
GtkHBoxClass parent_class;
49
gboolean (* set_unit)(SPUnitSelector *us, SPUnit const *old, SPUnit const *new_unit);
52
enum {SET_UNIT, LAST_SIGNAL};
54
static void sp_unit_selector_class_init(SPUnitSelectorClass *klass);
55
static void sp_unit_selector_init(SPUnitSelector *selector);
56
static void sp_unit_selector_finalize(GObject *object);
58
static GtkHBoxClass *unit_selector_parent_class;
59
static guint signals[LAST_SIGNAL] = {0};
61
GType sp_unit_selector_get_type(void)
63
static GType type = 0;
66
sizeof(SPUnitSelectorClass),
69
(GClassInitFunc)sp_unit_selector_class_init,
72
sizeof(SPUnitSelector),
74
(GInstanceInitFunc)sp_unit_selector_init,
77
type = g_type_register_static(GTK_TYPE_HBOX, "SPUnitSelector", &info, static_cast<GTypeFlags>(0));
83
sp_unit_selector_class_init(SPUnitSelectorClass *klass)
85
GObjectClass *object_class;
86
GtkWidgetClass *widget_class;
88
object_class = G_OBJECT_CLASS(klass);
89
widget_class = GTK_WIDGET_CLASS(klass);
91
unit_selector_parent_class = (GtkHBoxClass*)gtk_type_class(GTK_TYPE_HBOX);
93
signals[SET_UNIT] = g_signal_new("set_unit",
94
G_TYPE_FROM_CLASS(klass),
96
G_STRUCT_OFFSET(SPUnitSelectorClass, set_unit),
98
sp_marshal_BOOLEAN__POINTER_POINTER,
100
G_TYPE_POINTER, G_TYPE_POINTER);
102
object_class->finalize = sp_unit_selector_finalize;
106
sp_unit_selector_init(SPUnitSelector *us)
112
us->menu = gtk_option_menu_new();
114
gtk_widget_show(us->menu);
115
gtk_box_pack_start(GTK_BOX(us), us->menu, TRUE, TRUE, 0);
119
sp_unit_selector_finalize(GObject *object)
121
SPUnitSelector *selector = SP_UNIT_SELECTOR(object);
123
if (selector->menu) {
124
selector->menu = NULL;
127
while (selector->adjustments) {
128
gtk_object_unref(GTK_OBJECT(selector->adjustments->data));
129
selector->adjustments = g_slist_remove(selector->adjustments, selector->adjustments->data);
132
if (selector->units) {
133
sp_unit_free_list(selector->units);
136
selector->unit = NULL;
138
G_OBJECT_CLASS(unit_selector_parent_class)->finalize(object);
142
sp_unit_selector_new(guint bases)
144
SPUnitSelector *us = (SPUnitSelector*)gtk_type_new(SP_TYPE_UNIT_SELECTOR);
146
sp_unit_selector_set_bases(us, bases);
148
return (GtkWidget *) us;
152
sp_unit_selector_setsize(GtkWidget *us, guint w, guint h)
154
gtk_widget_set_size_request(((SPUnitSelector *) us)->menu, w, h);
158
sp_unit_selector_get_unit(SPUnitSelector const *us)
160
g_return_val_if_fail(us != NULL, NULL);
161
g_return_val_if_fail(SP_IS_UNIT_SELECTOR(us), NULL);
167
spus_unit_activate(GtkWidget *widget, SPUnitSelector *us)
169
SPUnit const *unit = (SPUnit const *) gtk_object_get_data(GTK_OBJECT(widget), "unit");
170
g_return_if_fail(unit != NULL);
172
#ifdef UNIT_SELECTOR_VERBOSE
173
g_print("Old unit %s new unit %s\n", us->unit->name, unit->name);
176
SPUnit const *old = us->unit;
181
gboolean consumed = FALSE;
182
g_signal_emit(G_OBJECT(us), signals[SET_UNIT], 0, old, unit, &consumed);
185
&& ( unit->base == old->base
186
|| ( unit->base == SP_UNIT_ABSOLUTE && old->base == SP_UNIT_DEVICE )
187
|| ( old->base == SP_UNIT_ABSOLUTE && unit->base == SP_UNIT_DEVICE ) ) ) {
188
// Either the same base, or absolute<->device:
189
/* Recalculate adjustments. */
190
for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) {
191
GtkAdjustment *adj = GTK_ADJUSTMENT(l->data);
192
gdouble val = adj->value;
193
#ifdef UNIT_SELECTOR_VERBOSE
194
g_print("Old val %g ... ", val);
196
val = sp_convert_distance_full(val, *old, *unit);
197
#ifdef UNIT_SELECTOR_VERBOSE
198
g_print("new val %g\n", val);
202
/* need to separate the value changing from the notification
203
* or else the unit changes can break the calculations */
204
for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) {
205
gtk_adjustment_value_changed(GTK_ADJUSTMENT(l->data));
207
} else if (!consumed && unit->base != old->base) {
208
/* when the base changes, signal all the adjustments to get them
210
for (GSList *l = us->adjustments; l != NULL; l = g_slist_next(l)) {
211
gtk_signal_emit_by_name(GTK_OBJECT(l->data), "value_changed");
219
spus_rebuild_menu(SPUnitSelector *us)
221
if (GTK_OPTION_MENU(us->menu)->menu) {
222
gtk_option_menu_remove_menu(GTK_OPTION_MENU(us->menu));
225
GtkWidget *m = gtk_menu_new();
231
for (GSList *l = us->units; l != NULL; l = l->next) {
232
SPUnit const *u = (SPUnit*)l->data;
234
// use only abbreviations in the menu
235
// i = gtk_menu_item_new_with_label((us->abbr) ? (us->plural) ? u->abbr_plural : u->abbr : (us->plural) ? u->plural : u->name);
236
GtkWidget *i = gtk_menu_item_new_with_label( u->abbr );
238
gtk_object_set_data(GTK_OBJECT(i), "unit", (gpointer) u);
239
gtk_signal_connect(GTK_OBJECT(i), "activate", GTK_SIGNAL_FUNC(spus_unit_activate), us);
241
sp_set_font_size_smaller (i);
245
gtk_menu_shell_append(GTK_MENU_SHELL(m), i);
246
if (u == us->unit) pos = p;
250
gtk_option_menu_set_menu(GTK_OPTION_MENU(us->menu), m);
252
gtk_option_menu_set_history(GTK_OPTION_MENU(us->menu), pos);
256
sp_unit_selector_set_bases(SPUnitSelector *us, guint bases)
258
g_return_if_fail(us != NULL);
259
g_return_if_fail(SP_IS_UNIT_SELECTOR(us));
261
if (bases == us->bases) return;
263
GSList *units = sp_unit_get_list(bases);
264
g_return_if_fail(units != NULL);
265
sp_unit_free_list(us->units);
267
us->unit = (SPUnit*)units->data;
269
spus_rebuild_menu(us);
273
sp_unit_selector_add_unit(SPUnitSelector *us, SPUnit const *unit, int position)
275
if (!g_slist_find(us->units, (gpointer) unit)) {
276
us->units = g_slist_insert(us->units, (gpointer) unit, position);
278
spus_rebuild_menu(us);
283
sp_unit_selector_set_unit(SPUnitSelector *us, SPUnit const *unit)
285
g_return_if_fail(us != NULL);
286
g_return_if_fail(SP_IS_UNIT_SELECTOR(us));
289
return; // silently return, by default a newly created selector uses pt
291
if (unit == us->unit) {
295
gint const pos = g_slist_index(us->units, (gpointer) unit);
296
g_return_if_fail(pos >= 0);
298
gtk_option_menu_set_history(GTK_OPTION_MENU(us->menu), pos);
300
SPUnit const *old = us->unit;
303
/* Recalculate adjustments */
304
for (GSList *l = us->adjustments; l != NULL; l = l->next) {
305
GtkAdjustment *adj = GTK_ADJUSTMENT(l->data);
306
gdouble const val = sp_convert_distance_full(adj->value, *old, *unit);
307
gtk_adjustment_set_value(adj, val);
312
sp_unit_selector_add_adjustment(SPUnitSelector *us, GtkAdjustment *adj)
314
g_return_if_fail(us != NULL);
315
g_return_if_fail(SP_IS_UNIT_SELECTOR(us));
316
g_return_if_fail(adj != NULL);
317
g_return_if_fail(GTK_IS_ADJUSTMENT(adj));
319
g_return_if_fail(!g_slist_find(us->adjustments, adj));
321
gtk_object_ref(GTK_OBJECT(adj));
322
us->adjustments = g_slist_prepend(us->adjustments, adj);
326
sp_unit_selector_remove_adjustment(SPUnitSelector *us, GtkAdjustment *adj)
328
g_return_if_fail(us != NULL);
329
g_return_if_fail(SP_IS_UNIT_SELECTOR(us));
330
g_return_if_fail(adj != NULL);
331
g_return_if_fail(GTK_IS_ADJUSTMENT(adj));
333
g_return_if_fail(g_slist_find(us->adjustments, adj));
335
us->adjustments = g_slist_remove(us->adjustments, adj);
336
gtk_object_unref(GTK_OBJECT(adj));
340
sp_unit_selector_update_test(SPUnitSelector const *selector)
342
g_return_val_if_fail(selector != NULL, FALSE);
343
g_return_val_if_fail(SP_IS_UNIT_SELECTOR(selector), FALSE);
345
return selector->update;
349
sp_unit_selector_get_value_in_pixels(SPUnitSelector const *selector, GtkAdjustment *adj)
351
g_return_val_if_fail(selector != NULL, adj->value);
352
g_return_val_if_fail(SP_IS_UNIT_SELECTOR(selector), adj->value);
354
return sp_units_get_pixels(adj->value, *(selector->unit));
358
sp_unit_selector_set_value_in_pixels(SPUnitSelector *selector, GtkAdjustment *adj, double value)
360
g_return_if_fail(selector != NULL);
361
g_return_if_fail(SP_IS_UNIT_SELECTOR(selector));
363
gtk_adjustment_set_value(adj, sp_pixels_get_units(value, *(selector->unit)));
369
c-file-style:"stroustrup"
370
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
375
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :