pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00013 #include <glib.h> 00014 #include <glib-object.h> 00015 #include <gtk/gtk.h> 00016 00017 #include "gtkhid.h" 00018 #include "gui.h" 00019 #include "pcb-printf.h" 00020 00021 #include "ghid-coord-entry.h" 00022 00023 enum { 00024 UNIT_CHANGE_SIGNAL, 00025 LAST_SIGNAL 00026 }; 00027 00028 static guint ghid_coord_entry_signals[LAST_SIGNAL] = { 0 }; 00029 00030 struct _GHidCoordEntry 00031 { 00032 GtkSpinButton parent; 00033 00034 Coord min_value; 00035 Coord max_value; 00036 Coord value; 00037 00038 enum ce_step_size step_size; 00039 const Unit *unit; 00040 }; 00041 00042 struct _GHidCoordEntryClass 00043 { 00044 GtkSpinButtonClass parent_class; 00045 00046 void (* change_unit) (GHidCoordEntry *, const Unit *); 00047 }; 00048 00049 /* SIGNAL HANDLERS */ 00051 static void 00052 menu_item_activate_cb (GtkMenuItem *item, GHidCoordEntry *ce) 00053 { 00054 const char *text = gtk_menu_item_get_label (item); 00055 const Unit *unit = get_unit_struct (text); 00056 00057 g_signal_emit (ce, ghid_coord_entry_signals[UNIT_CHANGE_SIGNAL], 0, unit); 00058 } 00059 00061 static void 00062 ghid_coord_entry_popup_cb (GHidCoordEntry *ce, GtkMenu *menu, gpointer data) 00063 { 00064 int i, n; 00065 const Unit *unit_list; 00066 GtkWidget *menu_item, *submenu; 00067 00068 /* Build submenu */ 00069 n = get_n_units (); 00070 unit_list = get_unit_list (); 00071 00072 submenu = gtk_menu_new (); 00073 for (i = 0; i < n; ++i) 00074 { 00075 menu_item = gtk_menu_item_new_with_label (unit_list[i].suffix); 00076 g_signal_connect (G_OBJECT (menu_item), "activate", 00077 G_CALLBACK (menu_item_activate_cb), ce); 00078 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), menu_item); 00079 gtk_widget_show (menu_item); 00080 } 00081 00082 /* Add submenu to menu */ 00083 menu_item = gtk_separator_menu_item_new (); 00084 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); 00085 gtk_widget_show (menu_item); 00086 00087 menu_item = gtk_menu_item_new_with_label (_("Change Units")); 00088 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item), submenu); 00089 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menu_item); 00090 gtk_widget_show (menu_item); 00091 } 00092 00094 static gboolean 00095 ghid_coord_entry_output_cb (GHidCoordEntry *ce, gpointer data) 00096 { 00097 GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (ce)); 00098 double value = gtk_adjustment_get_value (adj); 00099 gchar *text; 00100 00101 text = pcb_g_strdup_printf ("%.*f %s", ce->unit->default_prec, value, ce->unit->suffix); 00102 gtk_entry_set_text (GTK_ENTRY (ce), text); 00103 g_free (text); 00104 00105 return TRUE; 00106 } 00107 00109 static gboolean 00110 ghid_coord_text_changed_cb (GHidCoordEntry *entry, gpointer data) 00111 { 00112 const char *text; 00113 char *suffix; 00114 const Unit *new_unit; 00115 double value; 00116 00117 /* Check if units have changed */ 00118 text = gtk_entry_get_text (GTK_ENTRY (entry)); 00119 value = strtod (text, &suffix); 00120 new_unit = get_unit_struct (suffix); 00121 if (new_unit && new_unit != entry->unit) 00122 { 00123 entry->value = unit_to_coord (new_unit, value); 00124 g_signal_emit (entry, ghid_coord_entry_signals[UNIT_CHANGE_SIGNAL], 0, new_unit); 00125 } 00126 00127 return FALSE; 00128 } 00129 00131 static gboolean 00132 ghid_coord_value_changed_cb (GHidCoordEntry *ce, gpointer data) 00133 { 00134 GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (ce)); 00135 00136 /* Re-calculate internal value */ 00137 double value = gtk_adjustment_get_value (adj); 00138 ce->value = unit_to_coord (ce->unit, value); 00139 /* Handle potential unit changes */ 00140 ghid_coord_text_changed_cb (ce, data); 00141 00142 return FALSE; 00143 } 00144 00150 static void 00151 ghid_coord_entry_change_unit (GHidCoordEntry *ce, const Unit *new_unit) 00152 { 00153 double climb_rate = 0.0; 00154 GtkAdjustment *adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (ce)); 00155 00156 ce->unit = new_unit; 00157 /* Re-calculate min/max values for spinbox */ 00158 gtk_adjustment_configure (adj, coord_to_unit (new_unit, ce->value), 00159 coord_to_unit (new_unit, ce->min_value), 00160 coord_to_unit (new_unit, ce->max_value), 00161 ce->unit->step_small, 00162 ce->unit->step_medium, 00163 0.0); 00164 00165 switch (ce->step_size) 00166 { 00167 case CE_TINY: climb_rate = new_unit->step_tiny; break; 00168 case CE_SMALL: climb_rate = new_unit->step_small; break; 00169 case CE_MEDIUM: climb_rate = new_unit->step_medium; break; 00170 case CE_LARGE: climb_rate = new_unit->step_large; break; 00171 } 00172 gtk_spin_button_configure (GTK_SPIN_BUTTON (ce), adj, climb_rate, 00173 new_unit->default_prec + strlen (new_unit->suffix)); 00174 } 00175 00176 /* CONSTRUCTOR */ 00177 static void 00178 ghid_coord_entry_init (GHidCoordEntry *ce) 00179 { 00180 /* Hookup signal handlers */ 00181 g_signal_connect (G_OBJECT (ce), "focus_out_event", 00182 G_CALLBACK (ghid_coord_text_changed_cb), NULL); 00183 g_signal_connect (G_OBJECT (ce), "value_changed", 00184 G_CALLBACK (ghid_coord_value_changed_cb), NULL); 00185 g_signal_connect (G_OBJECT (ce), "populate_popup", 00186 G_CALLBACK (ghid_coord_entry_popup_cb), NULL); 00187 g_signal_connect (G_OBJECT (ce), "output", 00188 G_CALLBACK (ghid_coord_entry_output_cb), NULL); 00189 } 00190 00191 static void 00192 ghid_coord_entry_class_init (GHidCoordEntryClass *klass) 00193 { 00194 klass->change_unit = ghid_coord_entry_change_unit; 00195 00196 /* GtkAutoComplete *ce : the object acted on */ 00197 /* const Unit *new_unit: the new unit that was set */ 00198 ghid_coord_entry_signals[UNIT_CHANGE_SIGNAL] = 00199 g_signal_new ("change-unit", 00200 G_TYPE_FROM_CLASS (klass), 00201 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, 00202 G_STRUCT_OFFSET (GHidCoordEntryClass, change_unit), 00203 NULL, NULL, 00204 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 00205 1, G_TYPE_POINTER); 00206 00207 } 00208 00209 /* PUBLIC FUNCTIONS */ 00210 GType 00211 ghid_coord_entry_get_type (void) 00212 { 00213 static GType ce_type = 0; 00214 00215 if (!ce_type) 00216 { 00217 const GTypeInfo ce_info = 00218 { 00219 sizeof (GHidCoordEntryClass), 00220 NULL, /* base_init */ 00221 NULL, /* base_finalize */ 00222 (GClassInitFunc) ghid_coord_entry_class_init, 00223 NULL, /* class_finalize */ 00224 NULL, /* class_data */ 00225 sizeof (GHidCoordEntry), 00226 0, /* n_preallocs */ 00227 (GInstanceInitFunc) ghid_coord_entry_init, 00228 }; 00229 00230 ce_type = g_type_register_static (GTK_TYPE_SPIN_BUTTON, 00231 "GHidCoordEntry", 00232 &ce_info, 00233 0); 00234 } 00235 00236 return ce_type; 00237 } 00238 00249 GtkWidget * 00250 ghid_coord_entry_new (Coord min_val, Coord max_val, Coord value, 00251 const Unit *unit, enum ce_step_size step_size) 00252 { 00253 /* Setup spinbox min/max values */ 00254 double small_step, big_step; 00255 GtkAdjustment *adj; 00256 GHidCoordEntry *ce = g_object_new (GHID_COORD_ENTRY_TYPE, NULL); 00257 00258 ce->unit = unit; 00259 ce->min_value = min_val; 00260 ce->max_value = max_val; 00261 ce->value = value; 00262 00263 ce->step_size = step_size; 00264 switch (step_size) 00265 { 00266 case CE_TINY: 00267 small_step = unit->step_tiny; 00268 big_step = unit->step_small; 00269 break; 00270 case CE_SMALL: 00271 small_step = unit->step_small; 00272 big_step = unit->step_medium; 00273 break; 00274 case CE_MEDIUM: 00275 small_step = unit->step_medium; 00276 big_step = unit->step_large; 00277 break; 00278 case CE_LARGE: 00279 small_step = unit->step_large; 00280 big_step = unit->step_huge; 00281 break; 00282 default: 00283 small_step = big_step = 0; 00284 break; 00285 } 00286 00287 adj = GTK_ADJUSTMENT (gtk_adjustment_new (coord_to_unit (unit, value), 00288 coord_to_unit (unit, min_val), 00289 coord_to_unit (unit, max_val), 00290 small_step, big_step, 0.0)); 00291 gtk_spin_button_configure (GTK_SPIN_BUTTON (ce), adj, small_step, 00292 unit->default_prec + strlen (unit->suffix)); 00293 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (ce), FALSE); 00294 00295 return GTK_WIDGET (ce); 00296 } 00297 00299 Coord 00300 ghid_coord_entry_get_value (GHidCoordEntry *ce) 00301 { 00302 return ce->value; 00303 } 00304 00306 void 00307 ghid_coord_entry_set_value (GHidCoordEntry *ce, Coord val) 00308 { 00309 gtk_spin_button_set_value (GTK_SPIN_BUTTON (ce), 00310 coord_to_unit (ce->unit, val)); 00311 } 00312