00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00029
00030 #include <gtk/gtk.h>
00031
00032
00033
00034
00035 #include "ergtklog.h"
00036 #include "erGtkSelectionGroup.h"
00037 #include "erGtkSelectionList.h"
00038 #include "erGtkToggleButton.h"
00039
00040
00041
00042 static erGtkSelectionGroupClass* g_parent_class = NULL;
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static void ergtk_selection_list_class_init(erGtkSelectionListClass* klass);
00054 static void ergtk_selection_list_init(erGtkSelectionList* selection);
00055
00056 static GtkToggleButton* create_button(const erGtkSelectionList_displayAs_e display_as, const gchar* label_text);
00057 static guint button_height_from_display_as(const erGtkSelectionList_displayAs_e display_as);
00058
00059 static void add_buttons_to_screen_layout(erGtkSelectionList* item,
00060 GtkVBox* parent_vbox,
00061 const GSList* buttons,
00062 const guint first_item,
00063 const guint max_height,
00064 guint* allocated_buttons,
00065 guint* allocated_height);
00066
00067
00068
00069 GtkWidget *ergtk_selection_list_new(const erGtkSelectionList_displayAs_e display_as,
00070 const gchar* title,
00071 const gchar* instruction,
00072 const gchar** item_names,
00073 const guint max_height,
00074 guint* allocated_items,
00075 guint* allocated_height)
00076 {
00077 int i;
00078 const gchar** cpp;
00079 guint height;
00080 guint num_items = 0;
00081 guint item_height = 0;
00082 GtkToggleButton** button_tbl = NULL;
00083 guint items_allocated = 0;
00084 gboolean instruction_added = FALSE;
00085
00086 GtkWidget* widget;
00087 GtkWidget* alignment;
00088 GtkWidget* background;
00089 GtkWidget* vbox;
00090
00091 LOGPRINTF("entry: title [%s]", title);
00092
00093
00094 erGtkSelectionList* item = (erGtkSelectionList*) g_object_new(ERGTK_SELECTION_LIST_TYPE, NULL);
00095 gtk_widget_show(GTK_WIDGET(item));
00096 item->display_as = display_as;
00097
00098
00099 for (cpp = item_names ; *cpp != NULL ; cpp++)
00100 {
00101 num_items++;
00102 }
00103 button_tbl = g_new0(GtkToggleButton*, num_items + 1);
00104 g_assert(button_tbl != NULL);
00105 for (i = 0 ; i < num_items ; i++)
00106 {
00107 button_tbl[i] = create_button(display_as, item_names[i]);
00108 }
00109 button_tbl[i] = NULL;
00110
00111
00112 g_parent_class->add_buttons(&(item->parent), button_tbl);
00113
00114
00115
00116
00117
00118
00119
00120 widget = gtk_vbox_new(FALSE, ERGTK_SELECTION_LIST_TITLE_SPACING);
00121 gtk_widget_show(widget);
00122 gtk_container_add(GTK_CONTAINER(item), widget);
00123 vbox = widget;
00124
00125
00126
00127
00128
00129 widget = gtk_event_box_new();
00130 gtk_widget_show(widget);
00131 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_TITLE_BACKGROUND_STYLE);
00132 gtk_widget_set_size_request(widget, -1, ERGTK_SELECTION_LIST_TITLE_HEIGHT);
00133 gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
00134 item_height += ERGTK_SELECTION_LIST_TITLE_HEIGHT;
00135 item->titlebar = widget;
00136
00137 widget = gtk_label_new(title);
00138 gtk_widget_show(widget);
00139 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_TITLE_TEXT_STYLE);
00140 gtk_misc_set_padding(GTK_MISC(widget), ERGTK_SELECTION_LIST_H_PADDING, 0);
00141 gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
00142 gtk_container_add(GTK_CONTAINER(item->titlebar), widget);
00143
00144
00145
00146
00147
00148
00149 widget = gtk_event_box_new();
00150 gtk_widget_show(widget);
00151 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_BACKGROUND_STYLE);
00152 gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
00153 item_height += ERGTK_SELECTION_LIST_TITLE_SPACING;
00154 background = widget;
00155
00156 widget = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
00157 gtk_widget_show(widget);
00158 gtk_alignment_set_padding(GTK_ALIGNMENT(widget),
00159 ERGTK_SELECTION_LIST_V_PADDING, ERGTK_SELECTION_LIST_V_PADDING,
00160 ERGTK_SELECTION_LIST_H_PADDING, ERGTK_SELECTION_LIST_H_PADDING);
00161 gtk_container_add(GTK_CONTAINER(background), widget);
00162 item_height += 2 * ERGTK_SELECTION_LIST_V_PADDING;
00163 alignment = widget;
00164
00165 widget = gtk_vbox_new(FALSE, ERGTK_SELECTION_LIST_BUTTON_V_SPACING);
00166 gtk_widget_show(widget);
00167 gtk_container_add(GTK_CONTAINER(alignment), widget);
00168 vbox = widget;
00169
00170
00171 if (instruction && instruction[0] != '\0')
00172 {
00173 instruction_added = TRUE;
00174 widget = gtk_label_new(instruction);
00175 gtk_widget_show(widget);
00176 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_INSTRUCTION_STYLE);
00177 gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.5);
00178 gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0);
00179 item_height += ERGTK_SELECTION_LIST_INSTRUCTION_HEIGHT;
00180 }
00181
00182 add_buttons_to_screen_layout( item,
00183 GTK_VBOX(vbox),
00184 item->parent.buttons,
00185 0,
00186 max_height - item_height,
00187 &items_allocated,
00188 &height );
00189 item_height += height;
00190
00191 if (instruction_added && items_allocated > 0)
00192 {
00193 item_height += ERGTK_SELECTION_LIST_BUTTON_V_SPACING;
00194 }
00195
00196
00197 *allocated_items = items_allocated;
00198 *allocated_height = item_height;
00199 g_free(button_tbl);
00200 if (item_height <= max_height)
00201 {
00202 return GTK_WIDGET(item);
00203 }
00204 else
00205 {
00206 gtk_widget_destroy(GTK_WIDGET(item));
00207 return NULL;
00208 }
00209 }
00210
00211
00212 GtkWidget* ergtk_selection_list_new_from_master(const erGtkSelectionList* master,
00213 const guint first_item,
00214 const guint max_height,
00215 guint* allocated_items,
00216 guint* allocated_height)
00217 {
00218 g_return_val_if_fail(ERGTK_IS_SELECTION_LIST(master), FALSE);
00219
00220 guint height;
00221 guint item_height = 0;
00222 guint items_allocated = 0;
00223
00224 GtkWidget* widget;
00225 GtkWidget* alignment;
00226 GtkWidget* vbox;
00227
00228
00229 erGtkSelectionList* item = (erGtkSelectionList*) g_object_new(ERGTK_SELECTION_LIST_TYPE, NULL);
00230 item->display_as = master->display_as;
00231 gtk_widget_show(GTK_WIDGET(item));
00232
00233
00234
00235
00236
00237
00238 gtk_widget_set_name(GTK_WIDGET(item), ERGTK_SELECTION_LIST_BACKGROUND_STYLE);
00239
00240
00241
00242
00243
00244 widget = gtk_alignment_new(0.0, 0.0, 0.0, 0.0);
00245 gtk_widget_show(widget);
00246 gtk_alignment_set_padding(GTK_ALIGNMENT(widget),
00247 ERGTK_SELECTION_LIST_V_PADDING, ERGTK_SELECTION_LIST_V_PADDING,
00248 ERGTK_SELECTION_LIST_H_PADDING, ERGTK_SELECTION_LIST_H_PADDING);
00249 gtk_container_add(GTK_CONTAINER(item), widget);
00250 item_height += 2 * ERGTK_SELECTION_LIST_V_PADDING;
00251 alignment = widget;
00252
00253 widget = gtk_vbox_new(FALSE, ERGTK_SELECTION_LIST_BUTTON_V_SPACING);
00254 gtk_widget_show(widget);
00255 gtk_container_add(GTK_CONTAINER(alignment), widget);
00256 vbox = widget;
00257
00258
00259 add_buttons_to_screen_layout( item,
00260 GTK_VBOX(vbox),
00261 master->parent.buttons,
00262 first_item,
00263 max_height,
00264 &items_allocated,
00265 &height);
00266 item_height += height;
00267
00268
00269 *allocated_items = items_allocated;
00270 *allocated_height = item_height;
00271 if (item_height <= max_height)
00272 {
00273 return GTK_WIDGET(item);
00274 }
00275 else
00276 {
00277 gtk_widget_destroy(GTK_WIDGET(item));
00278 return NULL;
00279 }
00280 }
00281
00282
00283 static GtkToggleButton* create_button(const erGtkSelectionList_displayAs_e display_as, const gchar* label_text)
00284 {
00285 GtkWidget* widget = NULL;
00286 const guint button_height = button_height_from_display_as(display_as);
00287
00288 switch (display_as)
00289 {
00290 case esl_Checklist:
00291 widget = gtk_check_button_new_with_label(label_text);
00292 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_CHECKBUTTON_STYLE);
00293 gtk_widget_set_size_request(widget, -1, button_height);
00294 break;
00295
00296 case esl_RadioButton:
00297 widget = gtk_check_button_new_with_label(label_text);
00298 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_RADIOBUTTON_STYLE);
00299 gtk_widget_set_size_request(widget, -1, button_height);
00300 break;
00301
00302 case esl_TextButton:
00303 default:
00304 widget = ergtk_toggle_button_new_with_label(label_text);
00305 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_TEXTBUTTON_STYLE);
00306 gtk_widget_set_size_request(widget, ERGTK_SELECTION_LIST_TEXTBUTTON_WIDTH, button_height);
00307 }
00308
00309 GtkToggleButton* button = GTK_TOGGLE_BUTTON(widget);
00310 gtk_toggle_button_set_active(button, FALSE);
00311
00312 return button;
00313 }
00314
00315 static guint button_height_from_display_as(const erGtkSelectionList_displayAs_e display_as)
00316 {
00317 guint height = 0;
00318
00319 switch (display_as)
00320 {
00321 case esl_Checklist:
00322 height = ERGTK_SELECTION_LIST_CHECKBUTTON_HEIGHT;
00323 break;
00324
00325 case esl_RadioButton:
00326 height = ERGTK_SELECTION_LIST_RADIOBUTTON_HEIGHT;
00327 break;
00328
00329 case esl_TextButton:
00330 height = ERGTK_SELECTION_LIST_TEXTBUTTON_HEIGHT;
00331 break;
00332
00333 default:
00334 ;
00335 }
00336
00337 return height;
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 static void add_buttons_to_screen_layout(erGtkSelectionList* item,
00356 GtkVBox* parent_vbox,
00357 const GSList* buttons,
00358 const guint first_button,
00359 const guint max_height,
00360 guint* allocated_buttons,
00361 guint* allocated_height)
00362 {
00363 guint item_height = 0;
00364 guint buttons_added = 0;
00365 GtkWidget* hbox = NULL;
00366
00367 GtkWidget* widget;
00368 GtkWidget* button;
00369 const GSList* button_node;
00370
00371 const guint num_buttons = g_slist_length((GSList*)buttons);
00372 const guint buttons_per_line = (item->display_as == esl_TextButton) ? 4 : 1;
00373 guint button_height = button_height_from_display_as(item->display_as);
00374
00375 guint lines_needed;
00376 guint lines_available;
00377 guint lines_used;
00378 guint line;
00379
00380 if (first_button > 0)
00381 {
00382
00383 widget = gtk_label_new(ERGTK_SELECTION_LIST_CONTINUATION_TEXT);
00384 gtk_widget_show(widget);
00385 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_CONTINUATION_STYLE);
00386 gtk_widget_set_size_request(widget, -1, button_height);
00387 gtk_misc_set_padding(GTK_MISC(widget), ERGTK_SELECTION_LIST_CONTINUATION_H_PADDING, 0);
00388 gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.0);
00389 gtk_box_pack_start(GTK_BOX(parent_vbox), widget, FALSE, FALSE, 0);
00390 item_height += button_height;
00391 }
00392
00393
00394 lines_available = (max_height - item_height + ERGTK_SELECTION_LIST_BUTTON_V_SPACING) / (button_height + ERGTK_SELECTION_LIST_BUTTON_V_SPACING);
00395 lines_needed = ((num_buttons - first_button) + (buttons_per_line - 1)) / buttons_per_line;
00396 if (lines_needed <= lines_available)
00397 {
00398
00399 lines_used = lines_needed;
00400 }
00401 else
00402 {
00403
00404 lines_used = lines_available - 1;
00405
00406
00407 widget = gtk_label_new(ERGTK_SELECTION_LIST_CONTINUATION_TEXT);
00408 gtk_widget_show(widget);
00409 gtk_widget_set_name(widget, ERGTK_SELECTION_LIST_CONTINUATION_STYLE);
00410 gtk_widget_set_size_request(widget, -1, button_height);
00411 gtk_misc_set_padding(GTK_MISC(widget), ERGTK_SELECTION_LIST_CONTINUATION_H_PADDING, 0);
00412 gtk_misc_set_alignment(GTK_MISC(widget), 0.0, 0.0);
00413 gtk_box_pack_end(GTK_BOX(parent_vbox), widget, FALSE, FALSE, 0);
00414 item_height += button_height;
00415 }
00416
00417
00418 line = 0;
00419 for ( button_node = g_slist_nth((GSList*)buttons, first_button) ;
00420 button_node != NULL ;
00421 button_node = g_slist_next(button_node) )
00422 {
00423
00424 button = GTK_WIDGET(button_node->data);
00425 gtk_widget_show(button);
00426
00427 if (buttons_added % buttons_per_line == 0)
00428 {
00429
00430 if (line < lines_used)
00431 {
00432
00433 line++;
00434 if (buttons_per_line == 1)
00435 {
00436
00437 gtk_box_pack_start(GTK_BOX(parent_vbox), button, FALSE, FALSE, 0);
00438 item_height += button_height;
00439 buttons_added++;
00440 }
00441 else
00442 {
00443
00444 hbox = gtk_hbox_new(FALSE, ERGTK_SELECTION_LIST_BUTTON_H_SPACING);
00445 gtk_widget_show(hbox);
00446 gtk_box_pack_start(GTK_BOX(parent_vbox), hbox, FALSE, FALSE, 0);
00447 item_height += button_height;
00448
00449
00450 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
00451 buttons_added++;
00452 }
00453 }
00454 }
00455 else
00456 {
00457
00458 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
00459 buttons_added++;
00460 }
00461 }
00462
00463
00464 if (item_height >= ERGTK_SELECTION_LIST_BUTTON_V_SPACING)
00465 {
00466 item_height -= ERGTK_SELECTION_LIST_BUTTON_V_SPACING;
00467 }
00468
00469
00470 *allocated_buttons = buttons_added;
00471 *allocated_height = item_height;
00472 }
00473
00474 void ergtk_selection_list_show_titlebar(const erGtkSelectionList* item, const gboolean show)
00475 {
00476 g_return_if_fail(item != NULL);
00477 g_return_if_fail(ERGTK_IS_SELECTION_LIST(item));
00478
00479 if (show)
00480 {
00481 gtk_widget_show(item->titlebar);
00482 }
00483 else
00484 {
00485 gtk_widget_hide(item->titlebar);
00486 }
00487 }
00488
00489
00490 GType ergtk_selection_list_get_type(void)
00491 {
00492 static GType class_type = 0;
00493
00494 if (class_type == 0)
00495 {
00496 static const GTypeInfo class_info =
00497 {
00498 sizeof(erGtkSelectionListClass),
00499 NULL,
00500 NULL,
00501 (GClassInitFunc) ergtk_selection_list_class_init,
00502 NULL,
00503 NULL,
00504 sizeof(erGtkSelectionList),
00505 0,
00506 (GInstanceInitFunc) ergtk_selection_list_init,
00507 };
00508
00509 class_type = g_type_register_static(ERGTK_SELECTION_GROUP_TYPE, "erGtkSelectionList", &class_info, 0);
00510 }
00511 return class_type;
00512 }
00513
00514
00515 static void ergtk_selection_list_class_init(erGtkSelectionListClass* klass)
00516 {
00517
00518 g_parent_class = g_type_class_peek_parent(klass);
00519
00520
00521 }
00522
00523
00524 static void ergtk_selection_list_init(erGtkSelectionList* item)
00525 {
00526 g_return_if_fail(ERGTK_IS_SELECTION_LIST(item));
00527
00528
00529 item->dispose_has_run = FALSE;
00530 item->display_as = esl_TextButton;
00531 item->titlebar = NULL;
00532 }
00533
00534
00535
00536
00537
00538