PageRenderTime 46ms CodeModel.GetById 16ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/packages/gtk2/examples/gtk_demo/stock_browser.inc

https://github.com/slibre/freepascal
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