1/* 2 * "$Id: ui-utils.c,v 1.3 2006/05/28 16:59:04 rlk Exp $" 3 * 4 * Main window code for Print plug-in for the GIMP. 5 * 6 * Copyright 1997-2000 Michael Sweet (mike@easysw.com), 7 * Robert Krawitz (rlk@alum.mit.edu), Steve Miller (smiller@rni.net) 8 * and Michael Natterer (mitch@gimp.org) 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the Free 12 * Software Foundation; either version 2 of the License, or (at your option) 13 * any later version. 14 * 15 * This program is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 17 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 * for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include <config.h> 27#endif 28 29#include <gutenprint/gutenprint-intl-internal.h> 30#include <gutenprintui2/gutenprintui.h> 31#include "gutenprintui-internal.h" 32 33#include <stdio.h> 34#include <string.h> 35 36static void default_errfunc(void *data, const char *buffer, size_t bytes); 37static gchar *image_filename; 38static stp_outfunc_t the_errfunc = default_errfunc; 39static void *the_errdata = NULL; 40static get_thumbnail_func_t thumbnail_func; 41static void *thumbnail_private_data; 42 43/*****************************************************************\ 44* * 45* The following from libgimp/gimpdialog.c * 46* * 47\*****************************************************************/ 48 49typedef void (*StpuiBasicCallback) (GObject *object, 50 gpointer user_data); 51 52/* local callbacks of dialog_new () */ 53static gint 54dialog_delete_callback (GtkWidget *widget, 55 GdkEvent *event, 56 gpointer data) 57{ 58 StpuiBasicCallback cancel_callback; 59 GtkWidget *cancel_widget; 60 61 cancel_callback = 62 (StpuiBasicCallback) g_object_get_data (G_OBJECT (widget), 63 "dialog_cancel_callback"); 64 cancel_widget = 65 (GtkWidget*) g_object_get_data (G_OBJECT (widget), 66 "dialog_cancel_widget"); 67 68 /* the cancel callback has to destroy the dialog */ 69 if (cancel_callback) 70 (* cancel_callback) (G_OBJECT(cancel_widget), data); 71 72 return TRUE; 73} 74 75/** 76 * dialog_create_action_areav: 77 * @dialog: The #GtkDialog you want to create the action_area for. 78 * @args: A @va_list as obtained with va_start() describing the action_area 79 * buttons. 80 * 81 */ 82static void 83dialog_create_action_areav (GtkDialog *dialog, 84 va_list args) 85{ 86 GtkWidget *hbbox = NULL; 87 GtkWidget *button; 88 89 /* action area variables */ 90 const gchar *label; 91 GtkSignalFunc callback; 92 gpointer data; 93 GObject *slot_object; 94 GtkWidget **widget_ptr; 95 gboolean default_action; 96 gboolean connect_delete; 97 98 gboolean delete_connected = FALSE; 99 100 g_return_if_fail (dialog != NULL); 101 g_return_if_fail (GTK_IS_DIALOG (dialog)); 102 103 /* prepare the action_area */ 104 label = va_arg (args, const gchar *); 105 106 if (label) 107 { 108 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 2); 109 gtk_box_set_homogeneous (GTK_BOX (dialog->action_area), FALSE); 110 111 hbbox = gtk_hbutton_box_new (); 112 gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4); 113 gtk_box_pack_end (GTK_BOX (dialog->action_area), hbbox, FALSE, FALSE, 0); 114 gtk_widget_show (hbbox); 115 } 116 117 /* the action_area buttons */ 118 while (label) 119 { 120 callback = va_arg (args, GtkSignalFunc); 121 data = va_arg (args, gpointer); 122 slot_object = va_arg (args, GObject *); 123 widget_ptr = va_arg (args, GtkWidget **); 124 default_action = va_arg (args, gboolean); 125 connect_delete = va_arg (args, gboolean); 126 127 button = gtk_button_new_with_label (label); 128 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT); 129 gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0); 130 131 if (slot_object == (GObject *) 1) 132 slot_object = G_OBJECT (dialog); 133 134 if (data == NULL) 135 data = dialog; 136 137 if (callback) 138 { 139 if (slot_object) 140 g_signal_connect_object (G_OBJECT (button), "clicked", 141 G_CALLBACK (callback), 142 slot_object, G_CONNECT_SWAPPED); 143 else 144 g_signal_connect (G_OBJECT (button), "clicked", 145 G_CALLBACK (callback), 146 data); 147 } 148 149 if (widget_ptr) 150 *widget_ptr = button; 151 152 if (connect_delete && callback && !delete_connected) 153 { 154 gtk_object_set_data (GTK_OBJECT (dialog), 155 "dialog_cancel_callback", 156 (gpointer) callback); 157 gtk_object_set_data (GTK_OBJECT (dialog), 158 "dialog_cancel_widget", 159 slot_object ? slot_object : G_OBJECT (button)); 160 161 /* catch the WM delete event */ 162 g_signal_connect (G_OBJECT (dialog), "delete_event", 163 G_CALLBACK (dialog_delete_callback), 164 data); 165 166 delete_connected = TRUE; 167 } 168 169 if (default_action) 170 gtk_widget_grab_default (button); 171 gtk_widget_show (button); 172 173 label = va_arg (args, gchar *); 174 } 175} 176 177/** 178 * dialog_new: 179 * @title: The dialog's title which will be set with gtk_window_set_title(). 180 * @position: The dialog's initial position which will be set with 181 * gtk_window_set_position(). 182 * @resizable: Is the dialog resizable?, ... 183 * @allow_grow: ... it't @allow_grow flag and ... 184 * @auto_shrink: ... it's @auto_shrink flag which will all be set with 185 * gtk_window_set_policy(). 186 * @...: A #NULL terminated @va_list destribing the action_area buttons. 187 * 188 * This function simply packs the action_area arguments passed in "..." 189 * into a @va_list variable and passes everything to dialog_newv(). 190 * 191 * For a description of the format of the @va_list describing the 192 * action_area buttons see dialog_create_action_areav(). 193 * 194 * Returns: A #GtkDialog. 195 * 196 */ 197GtkWidget * 198stpui_dialog_new (const gchar *title, 199 GtkWindowPosition position, 200 gboolean resizable, 201 202 /* specify action area buttons as va_list: 203 * const gchar *label, 204 * GtkSignalFunc callback, 205 * gpointer data, 206 * GObject *slot_object, 207 * GtkWidget **widget_ptr, 208 * gboolean default_action, 209 * gboolean connect_delete, 210 */ 211 212 ...) 213{ 214 GtkWidget *dialog; 215 va_list args; 216 217 va_start (args, resizable); 218 219 g_return_val_if_fail (title != NULL, NULL); 220 221 dialog = gtk_dialog_new (); 222 gtk_window_set_title (GTK_WINDOW (dialog), title); 223 gtk_window_set_position (GTK_WINDOW (dialog), position); 224 gtk_window_set_resizable (GTK_WINDOW (dialog), resizable); 225 226 /* prepare the action_area */ 227 dialog_create_action_areav (GTK_DIALOG (dialog), args); 228 229 va_end (args); 230 231 return dialog; 232} 233 234/*****************************************************************\ 235* * 236* The following from libgimp/gimpwidgets.c * 237* * 238\*****************************************************************/ 239 240/** 241 * option_menu_new: 242 * @menu_only: #TRUE if the function should return a #GtkMenu only. 243 * @...: A #NULL terminated @va_list describing the menu items. 244 * 245 * Returns: A #GtkOptionMenu or a #GtkMenu (depending on @menu_only). 246 **/ 247GtkWidget * 248stpui_option_menu_new(gboolean menu_only, 249 250 /* specify menu items as va_list: 251 * const gchar *label, 252 * GtkSignalFunc callback, 253 * gpointer data, 254 * gpointer user_data, 255 * GtkWidget **widget_ptr, 256 * gboolean active 257 */ 258 259 ...) 260{ 261 GtkWidget *menu; 262 GtkWidget *menuitem; 263 264 /* menu item variables */ 265 const gchar *label; 266 GtkSignalFunc callback; 267 gpointer data; 268 gpointer user_data; 269 GtkWidget **widget_ptr; 270 gboolean active; 271 272 va_list args; 273 gint i; 274 gint initial_index; 275 276 menu = gtk_menu_new (); 277 278 /* create the menu items */ 279 initial_index = 0; 280 281 va_start (args, menu_only); 282 label = va_arg (args, const gchar *); 283 284 for (i = 0; label; i++) 285 { 286 callback = va_arg (args, GtkSignalFunc); 287 data = va_arg (args, gpointer); 288 user_data = va_arg (args, gpointer); 289 widget_ptr = va_arg (args, GtkWidget **); 290 active = va_arg (args, gboolean); 291 292 if (strcmp (label, "---")) 293 { 294 menuitem = gtk_menu_item_new_with_label (label); 295 296 g_signal_connect (G_OBJECT (menuitem), "activate", 297 callback, 298 data); 299 300 if (user_data) 301 gtk_object_set_user_data (GTK_OBJECT (menuitem), user_data); 302 } 303 else 304 { 305 menuitem = gtk_menu_item_new (); 306 307 gtk_widget_set_sensitive (menuitem, FALSE); 308 } 309 310 gtk_menu_append (GTK_MENU (menu), menuitem); 311 312 if (widget_ptr) 313 *widget_ptr = menuitem; 314 315 gtk_widget_show (menuitem); 316 317 /* remember the initial menu item */ 318 if (active) 319 initial_index = i; 320 321 label = va_arg (args, const gchar *); 322 } 323 va_end (args); 324 325 if (! menu_only) 326 { 327 GtkWidget *optionmenu; 328 329 optionmenu = gtk_option_menu_new (); 330 gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu); 331 332 /* select the initial menu item */ 333 gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), initial_index); 334 335 return optionmenu; 336 } 337 338 return menu; 339} 340 341/*****************************************************************\ 342* * 343* The following from libgimp/gimpwidgets.c * 344* * 345\*****************************************************************/ 346 347/** 348 * spin_button_new: 349 * @adjustment: Returns the spinbutton's #GtkAdjustment. 350 * @value: The initial value of the spinbutton. 351 * @lower: The lower boundary. 352 * @upper: The uppper boundary. 353 * @step_increment: The spinbutton's step increment. 354 * @page_increment: The spinbutton's page increment (mouse button 2). 355 * @page_size: The spinbutton's page size. 356 * @climb_rate: The spinbutton's climb rate. 357 * @digits: The spinbutton's number of decimal digits. 358 * 359 * This function is a shortcut for gtk_adjustment_new() and a subsequent 360 * gtk_spin_button_new() and does some more initialisation stuff like 361 * setting a standard minimun horizontal size. 362 * 363 * Returns: A #GtkSpinbutton and it's #GtkAdjustment. 364 **/ 365static GtkWidget * 366spin_button_new (GtkObject **adjustment, /* return value */ 367 gfloat value, 368 gfloat lower, 369 gfloat upper, 370 gfloat step_increment, 371 gfloat page_increment, 372 gfloat page_size, 373 gfloat climb_rate, 374 guint digits) 375{ 376 GtkWidget *spinbutton; 377 378 *adjustment = gtk_adjustment_new (value, lower, upper, 379 step_increment, page_increment, page_size); 380 381 spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (*adjustment), 382 climb_rate, digits); 383 gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); 384 gtk_widget_set_usize (spinbutton, 75, -1); 385 386 return spinbutton; 387} 388 389static void 390scale_entry_unconstrained_adjustment_callback (GtkAdjustment *adjustment, 391 GtkAdjustment *other_adj) 392{ 393 g_signal_handlers_block_matched (G_OBJECT (other_adj), 394 G_SIGNAL_MATCH_DATA, 395 0, 396 0, 397 NULL, 398 NULL, 399 adjustment); 400 401 gtk_adjustment_set_value (other_adj, adjustment->value); 402 403 g_signal_handlers_unblock_matched (G_OBJECT (other_adj), 404 G_SIGNAL_MATCH_DATA, 405 0, 406 0, 407 NULL, 408 NULL, 409 adjustment); 410} 411 412/** 413 * scale_entry_new: 414 * @table: The #GtkTable the widgets will be attached to. 415 * @column: The column to start with. 416 * @row: The row to attach the widgets. 417 * @text: The text for the #GtkLabel which will appear 418 * left of the #GtkHScale. 419 * @scale_usize: The minimum horizontal size of the #GtkHScale. 420 * @spinbutton_usize: The minimum horizontal size of the #GtkSpinButton. 421 * @value: The initial value. 422 * @lower: The lower boundary. 423 * @upper: The upper boundary. 424 * @step_increment: The step increment. 425 * @page_increment: The page increment. 426 * @digits: The number of decimal digits. 427 * @constrain: #TRUE if the range of possible values of the 428 * #GtkSpinButton should be the same as of the #GtkHScale. 429 * @unconstrained_lower: The spinbutton's lower boundary 430 * if @constrain == #FALSE. 431 * @unconstrained_upper: The spinbutton's upper boundary 432 * if @constrain == #FALSE. 433 * @tooltip: A tooltip message for the scale and the spinbutton. 434 * 435 * This function creates a #GtkLabel, a #GtkHScale and a #GtkSpinButton and 436 * attaches them to a 3-column #GtkTable. 437 * 438 * Returns: The #GtkSpinButton's #GtkAdjustment. 439 **/ 440GtkObject * 441stpui_scale_entry_new(GtkTable *table, 442 gint column, 443 gint row, 444 const gchar *text, 445 gint scale_usize, 446 gint spinbutton_usize, 447 gfloat value, 448 gfloat lower, 449 gfloat upper, 450 gfloat step_increment, 451 gfloat page_increment, 452 guint digits, 453 gboolean constrain, 454 gfloat unconstrained_lower, 455 gfloat unconstrained_upper, 456 const gchar *tooltip) 457{ 458 GtkWidget *label; 459 GtkWidget *scale; 460 GtkWidget *spinbutton; 461 GtkObject *adjustment; 462 GtkObject *return_adj; 463 464 label = gtk_label_new (text); 465 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); 466 gtk_table_attach (GTK_TABLE (table), label, 467 column + 1, column + 2, row, row + 1, 468 GTK_FILL, GTK_FILL, 0, 0); 469 gtk_widget_show (label); 470 471 if (! constrain && 472 unconstrained_lower <= lower && 473 unconstrained_upper >= upper) 474 { 475 GtkObject *constrained_adj; 476 477 constrained_adj = gtk_adjustment_new (value, lower, upper, 478 step_increment, page_increment, 479 0.0); 480 481 spinbutton = spin_button_new (&adjustment, value, 482 unconstrained_lower, 483 unconstrained_upper, 484 step_increment, page_increment, 0.0, 485 1.0, digits); 486 487 g_signal_connect 488 (G_OBJECT (constrained_adj), "value_changed", 489 G_CALLBACK (scale_entry_unconstrained_adjustment_callback), 490 adjustment); 491 492 g_signal_connect 493 (G_OBJECT (adjustment), "value_changed", 494 G_CALLBACK (scale_entry_unconstrained_adjustment_callback), 495 constrained_adj); 496 497 return_adj = adjustment; 498 499 adjustment = constrained_adj; 500 } 501 else 502 { 503 spinbutton = spin_button_new (&adjustment, value, lower, upper, 504 step_increment, page_increment, 0.0, 505 1.0, digits); 506 507 return_adj = adjustment; 508 } 509 510 if (spinbutton_usize > 0) 511 gtk_widget_set_usize (spinbutton, spinbutton_usize, -1); 512 513 scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment)); 514 if (scale_usize > 0) 515 gtk_widget_set_usize (scale, scale_usize, -1); 516 gtk_scale_set_digits (GTK_SCALE (scale), digits); 517 gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); 518 gtk_table_attach (GTK_TABLE (table), scale, 519 column + 2, column + 3, row, row + 1, 520 GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); 521 gtk_widget_show (scale); 522 523 gtk_table_attach (GTK_TABLE (table), spinbutton, 524 column + 3, column + 4, row, row + 1, 525 GTK_SHRINK, GTK_SHRINK, 0, 0); 526 gtk_widget_show (spinbutton); 527 528 if (tooltip) 529 { 530 stpui_set_help_data (scale, tooltip); 531 stpui_set_help_data (spinbutton, tooltip); 532 } 533 534 gtk_object_set_data (GTK_OBJECT (return_adj), "label", label); 535 gtk_object_set_data (GTK_OBJECT (return_adj), "scale", scale); 536 gtk_object_set_data (GTK_OBJECT (return_adj), "spinbutton", spinbutton); 537 538 return return_adj; 539} 540 541/** 542 * table_attach_aligned: 543 * @table: The #GtkTable the widgets will be attached to. 544 * @column: The column to start with. 545 * @row: The row to attach the eidgets. 546 * @label_text: The text for the #GtkLabel which will be attached left of the 547 * widget. 548 * @xalign: The horizontal alignment of the #GtkLabel. 549 * @yalign: The vertival alignment of the #GtkLabel. 550 * @widget: The #GtkWidget to attach right of the label. 551 * @colspan: The number of columns the widget will use. 552 * @left_align: #TRUE if the widget should be left-aligned. 553 * 554 * Note that the @label_text can be #NULL and that the widget will be attached 555 * starting at (@column + 1) in this case, too. 556 **/ 557void 558stpui_table_attach_aligned (GtkTable *table, 559 gint column, 560 gint row, 561 const gchar *label_text, 562 gfloat xalign, 563 gfloat yalign, 564 GtkWidget *widget, 565 gint colspan, 566 gboolean left_align) 567{ 568 if (label_text) 569 { 570 GtkWidget *label; 571 572 label = gtk_label_new (label_text); 573 gtk_misc_set_alignment (GTK_MISC (label), xalign, yalign); 574 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT); 575 gtk_table_attach (table, label, column, column + 1, row, row + 1, 576 GTK_FILL, GTK_FILL, 0, 0); 577 gtk_widget_show (label); 578 } 579 580 gtk_widget_show (widget); 581 if (left_align) 582 { 583 GtkWidget *alignment; 584 585 alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0); 586 gtk_container_add (GTK_CONTAINER (alignment), widget); 587 588 widget = alignment; 589 } 590 591 gtk_table_attach (table, widget, column + 1, column + 1 + colspan, 592 row, row + 1, 593 GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); 594 595 gtk_widget_show (widget); 596} 597 598/*****************************************************************\ 599* * 600* The following borrowed from libgimp/gimphelpui.c * 601* * 602\*****************************************************************/ 603 604static GtkTooltips * tool_tips = NULL; 605 606/** 607 * stpui_help_init: 608 * 609 * This function initializes GIMP's help system. 610 * 611 * Currently it only creates a #GtkTooltips object with gtk_tooltips_new() 612 * which will be used by help_stpui_set_help_data(). 613 **/ 614void 615stpui_help_init (void) 616{ 617 tool_tips = gtk_tooltips_new (); 618} 619 620/** 621 * stpui_help_free: 622 * 623 * This function frees the memory used by the #GtkTooltips created by 624 * stpui_help_init(). 625 **/ 626void 627stpui_help_free (void) 628{ 629 gtk_object_destroy (GTK_OBJECT (tool_tips)); 630 gtk_object_unref (GTK_OBJECT (tool_tips)); 631} 632 633/** 634 * help_enable_tooltips: 635 * 636 * This function calls gtk_tooltips_enable(). 637 **/ 638void 639stpui_enable_help (void) 640{ 641 gtk_tooltips_enable (tool_tips); 642} 643 644/** 645 * help_disable_tooltips: 646 * 647 * This function calls gtk_tooltips_disable(). 648 **/ 649 650void 651stpui_disable_help (void) 652{ 653 gtk_tooltips_disable (tool_tips); 654} 655 656void 657stpui_set_help_data (GtkWidget *widget, const gchar *tooltip) 658{ 659 g_return_if_fail (widget != NULL); 660 g_return_if_fail (GTK_IS_WIDGET (widget)); 661 662 if (tooltip) 663 { 664 gtk_tooltips_set_tip (tool_tips, widget, tooltip, NULL); 665 } 666} 667 668/*****************************************************************\ 669* * 670* The below is new code * 671* * 672\*****************************************************************/ 673 674 675void 676stpui_set_image_filename(const char *name) 677{ 678 if (name && name == image_filename) 679 return; 680 if (image_filename) 681 g_free(image_filename); 682 if (name) 683 image_filename = g_strdup(name); 684 else 685 image_filename = g_strdup(""); 686} 687 688const char * 689stpui_get_image_filename(void) 690{ 691 stpui_set_image_filename(image_filename); 692 return(image_filename); 693} 694 695static void 696default_errfunc(void *data, const char *buffer, size_t bytes) 697{ 698 fwrite(buffer, 1, bytes, data ? data : stderr); 699} 700 701void 702stpui_set_errfunc(stp_outfunc_t wfunc) 703{ 704 the_errfunc = wfunc; 705} 706 707stp_outfunc_t 708stpui_get_errfunc(void) 709{ 710 return the_errfunc; 711} 712 713void 714stpui_set_errdata(void *errdata) 715{ 716 the_errdata = errdata; 717} 718 719void * 720stpui_get_errdata(void) 721{ 722 return the_errdata; 723} 724 725void 726stpui_set_thumbnail_func(get_thumbnail_func_t func) 727{ 728 thumbnail_func = func; 729} 730 731get_thumbnail_func_t 732stpui_get_thumbnail_func(void) 733{ 734 return thumbnail_func; 735} 736 737void 738stpui_set_thumbnail_data(void *data) 739{ 740 thumbnail_private_data = data; 741} 742 743void * 744stpui_get_thumbnail_data(void) 745{ 746 return thumbnail_private_data; 747} 748 749GtkWidget * 750stpui_create_entry(GtkWidget *table, int hpos, int vpos, const char *text, 751 const char *help, GCallback callback) 752{ 753 GtkWidget *entry = gtk_entry_new(); 754 gtk_widget_set_usize(entry, 60, 0); 755 stpui_table_attach_aligned(GTK_TABLE(table), hpos, vpos, text, 756 0.0, 0.5, entry, 1, TRUE); 757 stpui_set_help_data(entry, help); 758 g_signal_connect(G_OBJECT(entry), "activate", 759 G_CALLBACK(callback), NULL); 760 return entry; 761} 762 763GSList * 764stpui_create_radio_button(radio_group_t *radio, GSList *group, 765 GtkWidget *table, int hpos, int vpos, 766 GCallback callback) 767{ 768 radio->button = gtk_radio_button_new_with_label(group, gettext(radio->name)); 769 group = gtk_radio_button_group(GTK_RADIO_BUTTON(radio->button)); 770 stpui_table_attach_aligned(GTK_TABLE(table), hpos, vpos, NULL, 0.5, 0.5, 771 radio->button, 1, FALSE); 772 stpui_set_help_data(radio->button, gettext(radio->help)); 773 g_signal_connect(G_OBJECT(radio->button), "toggled", 774 G_CALLBACK(callback), (gpointer) radio->value); 775 return group; 776} 777 778void 779stpui_set_adjustment_tooltip (GtkObject *adj, const gchar *tip) 780{ 781 stpui_set_help_data (GTK_WIDGET (SCALE_ENTRY_SCALE (adj)), tip); 782 stpui_set_help_data (GTK_WIDGET (SCALE_ENTRY_SPINBUTTON (adj)), tip); 783} 784 785static GtkWidget * 786table_label(GtkTable *table, gint column, gint row) 787{ 788 GList *children = table->children;; 789 while (children) 790 { 791 GtkTableChild *child = (GtkTableChild *)children->data; 792 if (child->left_attach == column + 1 && child->top_attach == row) 793 return child->widget; 794 children = children->next; 795 } 796 return NULL; 797} 798 799void 800stpui_create_new_combo(option_t *option, GtkWidget *table, 801 int hpos, int vpos, gboolean is_optional) 802{ 803 GtkWidget *event_box = gtk_event_box_new(); 804 GtkWidget *combo = gtk_combo_new(); 805 806 option->checkbox = gtk_check_button_new(); 807 gtk_table_attach(GTK_TABLE(table), option->checkbox, 808 hpos, hpos + 1, vpos, vpos + 1, 809 GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0); 810 811 option->info.list.combo = combo; 812 gtk_container_add(GTK_CONTAINER(event_box), combo); 813 gtk_widget_show(combo); 814 gtk_widget_show(event_box); 815 stpui_set_help_data(event_box, gettext(option->fast_desc->help)); 816 stpui_table_attach_aligned 817 (GTK_TABLE(table), hpos + 1, vpos, gettext(option->fast_desc->text), 818 0.0, 0.5, event_box, 2, TRUE); 819 option->info.list.label = table_label(GTK_TABLE(table), hpos, vpos); 820} 821 822const char * 823stpui_combo_get_name(GtkWidget *combo, 824 const stp_string_list_t *options) 825{ 826 if (options) 827 { 828 gint i; 829 gint num_options = stp_string_list_count(options); 830 const gchar *text = (gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry))); 831 832 if (text == NULL) 833 return (NULL); 834 835 if (num_options == 0) 836 return ((const char *)text); 837 838 for (i = 0; i < num_options; i ++) 839 if (strcmp(stp_string_list_param(options, i)->text, text) == 0) 840 return (stp_string_list_param(options, i)->name); 841 } 842 return (NULL); 843} 844 845void 846stpui_create_scale_entry(option_t *opt, 847 GtkTable *table, 848 gint column, 849 gint row, 850 const gchar *text, 851 gint scale_usize, 852 gint spinbutton_usize, 853 gfloat value, 854 gfloat lower, 855 gfloat upper, 856 gfloat step_increment, 857 gfloat page_increment, 858 guint digits, 859 gboolean constrain, 860 gfloat unconstrained_lower, 861 gfloat unconstrained_upper, 862 const gchar *tooltip, 863 gboolean is_optional) 864{ 865 opt->checkbox = gtk_check_button_new(); 866 gtk_table_attach(GTK_TABLE(table), opt->checkbox, 867 column, column + 1, row, row + 1, 868 GTK_EXPAND|GTK_FILL, GTK_FILL, 0, 0); 869 opt->info.flt.adjustment = 870 stpui_scale_entry_new(table, column, row, text, scale_usize, 871 spinbutton_usize, value, lower, upper, 872 step_increment, page_increment, digits, constrain, 873 unconstrained_lower, unconstrained_upper, tooltip); 874} 875