/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

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