/packages/gtk2/examples/gtk_demo/stock_browser.inc
Pascal | 551 lines | 410 code | 123 blank | 18 comment | 31 complexity | df3b02f59e32ea7d42dbc2a33c059bc4 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0
1(* Stock Item and Icon Browser 2 * 3 * This source code for this demo doesn't demonstrate anything 4 * particularly useful in applications. The purpose of the "demo" is 5 * just to provide a handy place to browse the available stock icons 6 * and stock items. 7 *) 8 9var 10 stock_window : PGtkWidget; 11 12type 13 PStockItemInfo = ^TStockItemInfo; 14 TStockItemInfo = record 15 id : pgchar; 16 item : TGtkStockItem; 17 small_icon : PGdkPixbuf; 18 macro : pgchar; 19 accel_str : pgchar; 20 end; 21 22 23(* Make StockItemInfo a boxed type so we can automatically 24 * manage memory 25 *) 26 27procedure stock_item_info_free (info : PStockItemInfo); cdecl; 28begin 29 g_free (info^.id); 30 g_free (info^.macro); 31 g_free (info^.accel_str); 32 if info^.small_icon <> NULL then 33 g_object_unref (pGObject(info^.small_icon)); 34 35 g_free (info); 36end; 37 38function stock_item_info_copy (src : PStockItemInfo): PStockItemInfo; cdecl; 39var 40 info : PStockItemInfo; 41 42begin 43 info := g_malloc0 (sizeof(TStockItemInfo)); 44 info^.id := g_strdup (src^.id); 45 info^.macro := g_strdup (src^.macro); 46 info^.accel_str := g_strdup (src^.accel_str); 47 48 info^.item := src^.item; 49 50 info^.small_icon := src^.small_icon; 51 if info^.small_icon <> NULL then 52 g_object_ref (pGObject(info^.small_icon)); 53 54 stock_item_info_copy := info; 55end; 56 57var 58 StockItemInfoType : GType; 59 60function stock_item_info_get_type: GType; 61begin 62 63 if StockItemInfoType = 0 then 64 StockItemInfoType := g_boxed_type_register_static ('StockItemInfo', 65 TGBoxedCopyFunc(@stock_item_info_copy), 66 TGBoxedFreeFunc (@stock_item_info_free)); 67 68 stock_item_info_get_type := StockItemInfoType; 69end; 70 71function STOCK_ITEM_INFO_TYPE: GType; 72begin 73 STOCK_ITEM_INFO_TYPE := stock_item_info_get_type; 74end; 75 76 77type 78 PStockItemDisplay = ^TStockItemDisplay; 79 TStockItemDisplay = record 80 type_label : PGtkWidget; 81 macro_label : PGtkWidget; 82 id_label : PGtkWidget; 83 label_accel_label : PGtkWidget; 84 icon_image : PGtkWidget; 85 end; 86 87 88function id_to_macro (id : pgchar): pgchar; 89var 90 macro : PGString; 91 cp : pgchar; 92 93begin 94 (* gtk-foo-bar -> GTK_STOCK_FOO_BAR *) 95 96 macro := g_string_new (NULL); 97 cp := id; 98 99 if StrLComp (cp, 'gtk-', 4) = 0 then 100 begin 101 g_string_append (macro, 'GTK_STOCK_'); 102 cp := cp + 4; 103 end; 104 105 while cp[0] <> #0 do 106 begin 107 if cp[0] = '-' then 108 g_string_append_c (macro, '_') 109 else if g_ascii_islower (cp[0]) then 110 g_string_append_c (macro, g_ascii_toupper (cp[0])) 111 else 112 g_string_append_c (macro, cp[0]); 113 114 inc(cp); 115 end; 116 117 id_to_macro := g_string_free (macro, FALSE); 118end; 119 120function CompareString (string1 : pgchar; 121 string2 : pgchar): gint; cdecl; 122begin 123 CompareString := StrComp (string1, string2); // maped to strcomp 124end; 125 126 127function create_model : PGtkTreeModel; 128var 129 store : PGtkListStore; 130 ids, 131 tmp_list : PGSList; 132 133 info : TStockItemInfo; 134 item : TGtkStockItem; 135 iter : TGtkTreeIter; 136 icon_set : PGtkIconSet; 137 138 sizes : PGtkIconSize; 139 i, n_sizes : gint; 140 size : TGtkIconSize; 141 142 w, h : gint; 143 scaled : PGdkPixbuf; 144 145begin 146 store := gtk_list_store_new (1, [STOCK_ITEM_INFO_TYPE]); 147 148 ids := gtk_stock_list_ids (); 149 ids := g_slist_sort (ids, TGCompareFunc (@CompareString)); 150 tmp_list := ids; 151 152 while tmp_list <> NULL do 153 begin 154 info.id := tmp_list^.data; 155 156 if gtk_stock_lookup (info.id, @item) then 157 info.item := item 158 else begin 159 info.item._label := NULL; 160 info.item.stock_id := NULL; 161 info.item.modifier := 0; 162 info.item.keyval := 0; 163 info.item.translation_domain := NULL; 164 end; 165 166 (* only show icons for stock IDs that have default icons *) 167 icon_set := gtk_icon_factory_lookup_default (info.id); 168 if icon_set <> NULL then 169 begin 170 sizes := NULL; 171 n_sizes := 0; 172 173 (* See what sizes this stock icon really exists at *) 174 gtk_icon_set_get_sizes (icon_set, @sizes, @n_sizes); 175 176 (* Use menu size if it exists, otherwise first size found *) 177 size := sizes[0]; 178 i := 0; 179 while i < n_sizes do 180 begin 181 if sizes[i] = GTK_ICON_SIZE_MENU then 182 begin 183 size := GTK_ICON_SIZE_MENU; 184 break; 185 end; {of size[i] = GTK_ICON_SIZE_MENU} 186 inc(i); 187 end; {of while} 188 189 g_free (sizes); 190 191 info.small_icon := gtk_widget_render_icon (stock_window, info.id, size, NULL); 192 193 if size <> GTK_ICON_SIZE_MENU then 194 begin 195 (* Make the result the proper size for our thumbnail *) 196 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, @w, @h); 197 198 scaled := gdk_pixbuf_scale_simple (info.small_icon, 199 w, h, 200 GDK_INTERP_BILINEAR); 201 202 g_object_unref (pGObject(info.small_icon)); 203 info.small_icon := scaled; 204 end; {of size <> GTK_ICON_SIZE_MENU} 205 end else {icon_set = NULL} 206 info.small_icon := NULL; 207 208 if info.item.keyval <> 0 then 209 210 info.accel_str := gtk_accelerator_name (info.item.keyval, 211 info.item.modifier) 212 213 else 214 info.accel_str := g_strdup (''); 215 216 217 info.macro := id_to_macro (info.id); 218 219 gtk_list_store_append (store, @iter); 220 gtk_list_store_set (store, @iter, [0, @info, -1]); 221 222 g_free (info.macro); 223 g_free (info.accel_str); 224 225 if info.small_icon <> NULL then 226 g_object_unref (pGObject(info.small_icon)); 227 228 tmp_list := g_slist_next (tmp_list); 229 end; {of while tmp_list <> NULL} 230 231 g_slist_foreach (ids, TGFunc(@g_free), NULL); 232 g_slist_free (ids); 233 234 create_model := pGtkTreeModel(store); 235end; 236 237(* Finds the largest size at which the given image stock id is 238 * available. This would not be useful for a normal application 239 *) 240 241function get_largest_size (id : pgchar): TGtkIconSize; 242var 243 theset : PGtkIconSet; 244 sizes : PGtkIconSize; 245 n_sizes, 246 i : gint; 247 best_size : TGtkIconsize; 248 best_pixels : gint; 249 250 width, 251 height : gint; 252 253begin 254 theset := gtk_icon_factory_lookup_default (id); 255 best_size := GTK_ICON_SIZE_INVALID; 256 best_pixels := 0; 257 258 gtk_icon_set_get_sizes (theset, @sizes, @n_sizes); 259 260 for i:=0 to n_sizes-1 do 261 begin 262 gtk_icon_size_lookup (sizes[i], @width, @height); 263 264 if (width * height) > best_pixels then 265 begin 266 best_size := sizes[i]; 267 best_pixels := width * height; 268 end; {of if} 269 end; {of for} 270 271 g_free (sizes); 272 273 get_largest_size := best_size; 274end; 275 276procedure selection_changed (selection : PGtkTreeSelection); cdecl; 277var 278 treeview : PGtkTreeView; 279 display : PStockItemDisplay; 280 model : PGtkTreeModel; 281 iter : TGtkTreeIter; 282 283 info : PStockItemInfo; 284 str : pgchar; 285 286begin 287 288 treeview := gtk_tree_selection_get_tree_view (selection); 289 display := g_object_get_data (pGObject(treeview), 'stock-display'); 290 291 if gtk_tree_selection_get_selected (selection, @model, @iter) then 292 begin 293 gtk_tree_model_get (model, @iter, [0, @info, -1]); 294 295 if (info^.small_icon <> NULL) and (info^.item._label <> NULL) then 296 gtk_label_set_text (pGtkLabel(display^.type_label), 'Icon and Item') 297 else if info^.small_icon <> NULL then 298 gtk_label_set_text (pGtkLabel(display^.type_label), 'Icon Only') 299 else if info^.item._label <> NULL then 300 gtk_label_set_text (pGtkLabel(display^.type_label), 'Item Only') 301 else 302 gtk_label_set_text (pGtkLabel(display^.type_label), '???????'); 303 304 gtk_label_set_text (pGtkLabel(display^.macro_label), info^.macro); 305 gtk_label_set_text (pGtkLabel(display^.id_label), info^.id); 306 307 if info^.item._label <> NULL then 308 begin 309 str := g_strdup_printf ('%s %s', [info^.item._label, info^.accel_str] ); 310 gtk_label_set_text_with_mnemonic (pGtkLabel(display^.label_accel_label), str); 311 g_free (str); 312 end else 313 gtk_label_set_text (pGtkLabel(display^.label_accel_label), ''); 314 315 if info^.small_icon <> NULL then 316 gtk_image_set_from_stock (pGtkImage(display^.icon_image), info^.id, 317 get_largest_size (info^.id)) 318 else 319 gtk_image_set_from_pixbuf (pGtkImage(display^.icon_image), NULL); 320 321 stock_item_info_free (info); 322 end { of if gtk_tree_selection_get_selected } 323 else 324 begin 325 gtk_label_set_text (pGtkLabel(display^.type_label), 'No selected item'); 326 gtk_label_set_text (pGtkLabel(display^.macro_label), ''); 327 gtk_label_set_text (pGtkLabel(display^.id_label), ''); 328 gtk_label_set_text (pGtkLabel(display^.label_accel_label), ''); 329 gtk_image_set_from_pixbuf (pGtkImage(display^.icon_image), NULL); 330 end; 331end; 332 333procedure macro_set_func_text (tree_column : PGtkTreeViewColumn; 334 cell : PGtkCellRenderer; 335 model : PGtkTreeModel; 336 iter : PGtkTreeIter; 337 data : gpointer); cdecl; 338var 339 info : PStockItemInfo; 340 341begin 342 gtk_tree_model_get (model, iter, [0, @info, -1]); 343 344 g_object_set (pGtkCellRenderer(cell), 'text', [info^.macro, NULL]); 345 346 stock_item_info_free (info); 347end; 348 349procedure macro_set_func_pixbuf (tree_column : PGtkTreeViewColumn; 350 cell : PGtkCellRenderer; 351 model : PGtkTreeModel; 352 iter : PGtkTreeIter; 353 data : gpointer); cdecl; 354var 355 info : PStockItemInfo; 356 357begin 358 gtk_tree_model_get (model, iter, [0, @info, -1]); 359 360 g_object_set (pGtkCellRenderer(cell), 'pixbuf', [info^.small_icon, NULL]); 361 362 stock_item_info_free (info); 363end; 364 365procedure id_set_func (tree_column : PGtkTreeViewColumn; 366 cell : PGtkCellRenderer; 367 model : PGtkTreeModel; 368 iter : PGtkTreeIter; 369 data : gpointer); cdecl; 370var 371 info : PStockItemInfo; 372 373begin 374 gtk_tree_model_get (model, iter, [0, @info, -1]); 375 376 g_object_set (pGtkCellRenderer(cell), 'text', [info^.id, NULL]); 377 378 stock_item_info_free (info); 379end; 380 381procedure accel_set_func (tree_column : PGtkTreeViewColumn; 382 cell : PGtkCellRenderer; 383 model : PGtkTreeModel; 384 iter : PGtkTreeIter; 385 data : gpointer); cdecl; 386var 387 info : PStockItemInfo; 388 389begin 390 gtk_tree_model_get (model, iter, [0, @info, -1]); 391 392 g_object_set (pGtkCellRenderer(cell),'text', [info^.accel_str, NULL]); 393 394 stock_item_info_free (info); 395end; 396 397procedure label_set_func (tree_column : PGtkTreeViewColumn; 398 cell : PGtkCellRenderer; 399 model : PGtkTreeModel; 400 iter : PGtkTreeIter; 401 data : gpointer); cdecl; 402var 403 info : PStockItemInfo; 404 405begin 406 gtk_tree_model_get (model, iter, [0, @info, -1]); 407 408 g_object_set (pGtkCellRenderer(cell), 'text', [info^.item._label, NULL]); 409 410 stock_item_info_free (info); 411end; 412 413function do_stock_browser : PGtkWidget; 414var 415 frame, 416 vbox, 417 hbox, 418 sw, 419 treeview, 420 align : PGtkWidget; 421 model : PGtkTreeModel; 422 cell_renderer : PGtkCellRenderer; 423 display : PStockItemDisplay; 424 selection : PGtkTreeSelection; 425 column : PGtkTreeViewColumn; 426 427begin 428 if stock_window = NULL then 429 begin 430 stock_window := gtk_window_new (GTK_WINDOW_TOPLEVEL); 431 gtk_window_set_title (pGtkWindow(stock_window), 'Stock Icons and Items'); 432 gtk_window_set_default_size (pGtkWindow(stock_window), -1, 500); 433 434 g_signal_connect (stock_window, 'destroy', TGCallback(@gtk_widget_destroyed), @stock_window); 435 gtk_container_set_border_width (pGtkContainer(stock_window), 8); 436 437 hbox := gtk_hbox_new (FALSE, 8); 438 gtk_container_add (pGtkContainer(stock_window), hbox); 439 440 sw := gtk_scrolled_window_new (NULL, NULL); 441 gtk_scrolled_window_set_policy (pGtkScrolledWindow(sw), 442 GTK_POLICY_NEVER, 443 GTK_POLICY_AUTOMATIC); 444 gtk_box_pack_start (pGtkBox(hbox), sw, FALSE, FALSE, 0); 445 446 model := create_model (); 447 448 treeview := gtk_tree_view_new_with_model (model); 449 450 g_object_unref (pGObject(model)); 451 452 gtk_container_add (pGtkContainer(sw), treeview); 453 454 column := gtk_tree_view_column_new (); 455 gtk_tree_view_column_set_title (column, 'Macro'); 456 457 cell_renderer := gtk_cell_renderer_pixbuf_new (); 458 gtk_tree_view_column_pack_start (column, 459 cell_renderer, 460 FALSE); 461 gtk_tree_view_column_set_cell_data_func (column, cell_renderer, 462 @macro_set_func_pixbuf, NULL, NULL); 463 cell_renderer := gtk_cell_renderer_text_new (); 464 gtk_tree_view_column_pack_start (column, 465 cell_renderer, 466 TRUE); 467 gtk_tree_view_column_set_cell_data_func (column, cell_renderer, 468 @macro_set_func_text, NULL, NULL); 469 470 gtk_tree_view_append_column (pGtkTreeView(treeview), column); 471 472 cell_renderer := gtk_cell_renderer_text_new (); 473 474 gtk_tree_view_insert_column_with_data_func (pGtkTreeView(treeview), 475 -1, 476 'Label', 477 cell_renderer, 478 @label_set_func, 479 NULL, 480 NULL); 481 482 gtk_tree_view_insert_column_with_data_func (pGtkTreeView(treeview), 483 -1, 484 'Accel', 485 cell_renderer, 486 @accel_set_func, 487 NULL, 488 NULL); 489 490 gtk_tree_view_insert_column_with_data_func (pGtkTreeView(treeview), 491 -1, 492 'ID', 493 cell_renderer, 494 @id_set_func, 495 NULL, 496 NULL); 497 498 align := gtk_alignment_new (0.5, 0.0, 0.0, 0.0); 499 gtk_box_pack_end (pGtkBox(hbox), align, FALSE, FALSE, 0); 500 501 frame := gtk_frame_new ('Selected Item'); 502 gtk_container_add (pGtkContainer(align), frame); 503 504 vbox := gtk_vbox_new (FALSE, 8); 505 gtk_container_set_border_width (pGtkContainer(vbox), 4); 506 gtk_container_add (pGtkContainer(frame), vbox); 507 508 display := g_malloc0 (sizeof(TStockItemDisplay)); 509 g_object_set_data_full (pGObject(treeview), 510 'stock-display', 511 display, 512 @g_free); (* free display with treeview *) 513 514 display^.type_label := gtk_label_new (NULL); 515 display^.macro_label := gtk_label_new (NULL); 516 display^.id_label := gtk_label_new (NULL); 517 display^.label_accel_label := gtk_label_new (NULL); 518 display^.icon_image := gtk_image_new_from_pixbuf (NULL); (* empty image *) 519 520 gtk_box_pack_start (pGtkBox(vbox), display^.type_label, 521 FALSE, FALSE, 0); 522 523 gtk_box_pack_start (pGtkBox(vbox), display^.icon_image, 524 FALSE, FALSE, 0); 525 526 gtk_box_pack_start (pGtkBox(vbox), display^.label_accel_label, 527 FALSE, FALSE, 0); 528 gtk_box_pack_start (pGtkBox(vbox), display^.macro_label, 529 FALSE, FALSE, 0); 530 gtk_box_pack_start (pGtkBox(vbox), display^.id_label, 531 FALSE, FALSE, 0); 532 533 selection := gtk_tree_view_get_selection (pGtkTreeView(treeview)); 534 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); 535 536 g_signal_connect (pGObject(selection), 537 'changed', 538 TGCallback(@selection_changed), 539 NULL); 540 end; 541 542 if not GTK_WIDGET_VISIBLE (stock_window) then 543 gtk_widget_show_all (stock_window) 544 else begin 545 gtk_widget_destroy (stock_window); 546 stock_window := NULL; 547 end; 548 549 do_stock_browser := stock_window; 550end; 551