1 /**
2 * Copyright (C) 2012 hejian <hejian.he@gmail.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <libgimp/gimp.h>
19 #include <libgimp/gimpui.h>
20
21 /* fix gimp_context_set_pattern ("Clipboard") only works on English versions of Gimp */
22 #include <glib/gi18n.h>
23 #define GETTEXT_PACKAGE "gimp20"
24 #define INIT_I18N() G_STMT_START{ \
25 bindtextdomain (GETTEXT_PACKAGE, \
26 gimp_locale_directory ()); \
27 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); \
28 textdomain (GETTEXT_PACKAGE); \
29 }G_STMT_END
30
31 #include "simple-border-textures.h"
32
33 #define PLUG_IN_PROC "plug-in-simple-border"
34 #define PLUG_IN_BINARY "border"
35 #define PLUG_IN_ROLE "gimp-border"
36
37 #define TEXTURE_PATH "simple-border"
38
39 #define PREVIEW_SIZE 480
40 #define THUMBNAIL_SIZE 80
41
42 typedef struct
43 {
44 const gchar *id;
45 gint32 top;
46 gint32 bottom;
47 gint32 left;
48 gint32 right;
49 gint32 length;
50 const guint8 *texture;
51 } Border;
52
53 typedef struct
54 {
55 const Border* border;
56 const gchar *custom_texture;
57 } BorderValues;
58
59 static void query (void);
60 static void run (const gchar *name,
61 gint nparams,
62 const GimpParam *param,
63 gint *nreturn_vals,
64 GimpParam **return_vals);
65
66 static void border (gint32 image_ID);
67
68 static gboolean border_dialog (gint32 image_ID,
69 GimpDrawable *drawable);
70
71 static void create_texture_page (GtkNotebook *notebook, const gchar *category, const Border* textures, guint n_textures);
72 static gboolean create_custom_texture_pages (GtkNotebook *notebook, const gchar *texture_path);
73 static void create_custom_texture_page (GtkNotebook *notebook, const gchar *category, const gchar *path);
74 static void textures_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, const gchar *texture_path);
75 static GtkWidget* effect_icon_new (const Border *border);
76
77 static gboolean texture_press (GtkWidget *event_box, GdkEventButton *event, const Border *border);
78 static gboolean custom_texture_press (GtkWidget *event_box, GdkEventButton *event, const gchar *texture);
79 static void do_texture_press ();
80
81 static inline gboolean
is_hidden(const gchar * filename)82 is_hidden (const gchar *filename)
83 {
84 /* skip files starting with '.' so we don't try to parse
85 * stuff like .DS_Store or other metadata storage files
86 */
87 return (filename[0] == '.');
88 }
89
90 const GimpPlugInInfo PLUG_IN_INFO =
91 {
92 NULL, /* init_proc */
93 NULL, /* quit_proc */
94 query, /* query_proc */
95 run, /* run_proc */
96 };
97
98 static BorderValues bvals =
99 {
100 NULL, /* border */
101 };
102
103 static gint32 image_ID = 0;
104 static gint width;
105 static gint height;
106
107 static GtkWidget *preview = NULL;
108 static gint32 preview_image = 0;
109
110 static const Border textures[] =
111 {
112 {"15356", 0, 0, 0, 0, 10, texture_15356},
113 {"15327", 24,37,29,41,10, texture_15327},
114 {"201544", 12,12,12,12,10, texture_201544},
115 {"15352", 9, 35,7, 6, 10, texture_15352},
116 {"201365", 24,23,23,23,10, texture_201365},
117 {"15349", 56,63,54,56,10, texture_15349},
118 {"24252", 40,43,35,38,90, texture_24252},
119 {"114844", 14,13,14,14,10, texture_114844},
120 {"200832", 14,14,14,14,10, texture_200832},
121 {"200878", 12,12,12,12,10, texture_200878},
122 {"201017", 0, 0, 0, 0, 10, texture_201017},
123 {"114568", 0, 0, 0, 0, 10, texture_114568},
124 {"111026", 0, 0, 0, 0, 10, texture_111026},
125 {"200377", 20,166,20,20,10,texture_200377},
126 {"201385", 11,12,12,12,10, texture_201385},
127 {"111025", 25,56,16,16,10, texture_111025},
128 {"200547", 21,21,17,17,10, texture_200547},
129 {"200776", 16,16,16,16,10, texture_200776},
130 {"200646", 18,18, 8, 8,18, texture_200646},
131 {"200282", 0, 0, 0, 0, 16, texture_200282},
132 {"111020", 16,18,17,19,10, texture_111020},
133 {"113579", 28,28,25,25,42, texture_113579},
134 {"111569", 0, 0, 0, 0, 10, texture_111569},
135 {"200031", 0, 0, 0, 0, 10, texture_200031},
136 {"113576", 39,39,40,40,36, texture_113576},
137 {"114907", 0, 0, 0, 0, 16, texture_114907},
138 {"114577", 0, 0, 0, 0, 44, texture_114577},
139 {"113575", 38,38,38,38,34, texture_113575},
140 {"113573", 27,22,26,24,10, texture_113573},
141 {"114576", 0, 0, 0, 0, 10, texture_114576},
142 {"111013", 35,35,35,35,10, texture_111013},
143 {"114575", 0, 0, 0, 0, 10, texture_114575},
144 {"111017", 31,31,31,31,10, texture_111017},
145 {"114573", 10,10,10,10,10, texture_114573},
146 {"111027", 17,16,16,19,10, texture_111027},
147 {"111021", 18,18,21,22,22, texture_111021},
148 {"114572", 16,16,14,14,10, texture_114572},
149 {"114570", 20,22,21,19,21, texture_114570},
150 {"22753", 34,36,34,36,53, texture_22753},
151 {"20130", 59,59,0, 0, 10, texture_20130},
152 {"114569", 20,20,20,19,21, texture_114569},
153 {"20129", 83,82,0, 0, 10, texture_20129},
154 {"15354", 30,45,47,58,10, texture_15354},
155 {"15357", 45,45,0, 0, 32, texture_15357},
156 {"15353", 13,48,10,11,10, texture_15353},
157 {"15351", 15,73,16,17,10, texture_15351},
158 {"15328", 7, 7, 7, 7, 16, texture_15328},
159 {"15350", 0, 0, 0, 0, 10, texture_15350},
160 {"15329", 13,14,20,19,10, texture_15329},
161 {"15330", 26,23,25,27,10, texture_15330},
162 {"114567", 14,13,13,13,10, texture_114567},
163 {"15870", 39,50,41,192,63,texture_15870},
164 {"21926", 43,53,43,212,429,texture_21926},
165 {"21959", 42,50,44,216,74,texture_21959},
166 {"21927", 43,53,43,212,23,texture_21927},
167 {"15871", 39,50,41,210,16,texture_15871},
168 };
169
170 static GArray *textures_timestamps = NULL;
171
172 /* compatable with gtk2 */
173 #if GTK_MAJOR_VERSION < 3
174 GtkWidget *
gtk_box_new(GtkOrientation orientation,gint spacing)175 gtk_box_new (GtkOrientation orientation,
176 gint spacing)
177 {
178 if (orientation == GTK_ORIENTATION_HORIZONTAL)
179 return gtk_hbox_new (FALSE, spacing);
180 else
181 return gtk_vbox_new (FALSE, spacing);
182 }
183 #endif
184
MAIN()185 MAIN ()
186
187 static void
188 query (void)
189 {
190 static const GimpParamDef args[] =
191 {
192 { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
193 { GIMP_PDB_IMAGE, "image", "Input image" },
194 { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
195 };
196
197 gimp_install_procedure (PLUG_IN_PROC,
198 "Create an simple border effect",
199 "Create an simple border effect",
200 "Hejian <hejian.he@gmail.com>",
201 "Hejian <hejian.he@gmail.com>",
202 "2012",
203 "_Simple Border...",
204 "RGB*, GRAY*",
205 GIMP_PLUGIN,
206 G_N_ELEMENTS (args), 0,
207 args, NULL);
208
209 gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Beautify/Border");
210 }
211
212 static void
run(const gchar * name,gint nparams,const GimpParam * param,gint * nreturn_vals,GimpParam ** return_vals)213 run (const gchar *name,
214 gint nparams,
215 const GimpParam *param,
216 gint *nreturn_vals,
217 GimpParam **return_vals)
218 {
219 static GimpParam values[2];
220 GimpDrawable *drawable;
221 GimpRunMode run_mode;
222 GimpPDBStatusType status = GIMP_PDB_SUCCESS;
223
224 run_mode = param[0].data.d_int32;
225
226 *nreturn_vals = 1;
227 *return_vals = values;
228
229 values[0].type = GIMP_PDB_STATUS;
230 values[0].data.d_status = status;
231
232 image_ID = param[1].data.d_image;
233 drawable = gimp_drawable_get (param[2].data.d_drawable);
234
235 width = gimp_image_width (image_ID);
236 height = gimp_image_height (image_ID);
237
238 switch (run_mode)
239 {
240 case GIMP_RUN_INTERACTIVE:
241 if (! border_dialog (image_ID, drawable))
242 return;
243 break;
244
245 case GIMP_RUN_NONINTERACTIVE:
246 break;
247
248 case GIMP_RUN_WITH_LAST_VALS:
249 break;
250
251 default:
252 break;
253 }
254
255 if ((status == GIMP_PDB_SUCCESS) &&
256 (gimp_drawable_is_rgb(drawable->drawable_id) ||
257 gimp_drawable_is_gray(drawable->drawable_id)))
258 {
259 /* Run! */
260 gimp_image_undo_group_start (image_ID);
261 border (image_ID);
262 gimp_image_undo_group_end (image_ID);
263
264 /* If run mode is interactive, flush displays */
265 if (run_mode != GIMP_RUN_NONINTERACTIVE)
266 gimp_displays_flush ();
267
268 /* Store data */
269 /*if (run_mode == GIMP_RUN_INTERACTIVE)
270 gimp_set_data (PLUG_IN_PROC, &rbvals, sizeof (BorderValues));*/
271
272 }
273
274 gimp_drawable_detach (drawable);
275 }
276
277 static void
border(gint32 image_ID)278 border (gint32 image_ID)
279 {
280 GdkPixbuf *pixbuf = NULL;
281 int texture_width;
282 int texture_height;
283 gdouble margin_top;
284 gdouble margin_bottom;
285 gdouble margin_left;
286 gdouble margin_right;
287
288 pixbuf = gdk_pixbuf_new_from_inline (-1, bvals.border->texture, FALSE, NULL);
289
290 if (pixbuf)
291 {
292 texture_width = gdk_pixbuf_get_width (pixbuf);
293 texture_height = gdk_pixbuf_get_height (pixbuf);
294
295 gint32 texture_image = gimp_image_new (texture_width, texture_height, GIMP_RGB);
296 gint32 texture_layer = gimp_layer_new_from_pixbuf (texture_image, "texture", pixbuf, 100, GIMP_NORMAL_MODE, 0, 0);
297 gimp_image_add_layer (texture_image, texture_layer, -1);
298
299 gint width = gimp_image_width (image_ID);
300 gint height = gimp_image_height (image_ID);
301
302 if (bvals.border->top || bvals.border->bottom || bvals.border->left || bvals.border->right)
303 {
304 width += bvals.border->left + bvals.border->right;
305 height += bvals.border->top + bvals.border->bottom;
306 gimp_image_resize (image_ID,
307 width,
308 height,
309 bvals.border->left,
310 bvals.border->top);
311 }
312
313 gint32 layer = gimp_layer_new (image_ID, "border",
314 width, height,
315 GIMP_RGBA_IMAGE,
316 100,
317 GIMP_NORMAL_MODE);
318 gimp_image_add_layer (image_ID, layer, -1);
319
320 if (width > texture_width - bvals.border->length)
321 {
322 margin_left = ((gdouble) texture_width - bvals.border->left - bvals.border->right - bvals.border->length) / 2;
323 margin_right = margin_left;
324 }
325 else
326 {
327 margin_left = ((gdouble) width - bvals.border->left - bvals.border->right) / 2;
328 margin_right = margin_left;
329 }
330 margin_left += bvals.border->left;
331 margin_right += bvals.border->right;
332
333 if (height > texture_height - bvals.border->length)
334 {
335 margin_top = ((gdouble) texture_height - bvals.border->top - bvals.border->bottom - bvals.border->length) / 2;
336 margin_bottom = margin_top;
337 }
338 else
339 {
340 margin_top = ((gdouble) height - bvals.border->top - bvals.border->bottom) / 2;
341 margin_bottom = margin_top;
342 }
343 margin_top += bvals.border->top;
344 margin_bottom += bvals.border->bottom;
345
346 /* fix gimp_context_set_pattern ("Clipboard") only works on English versions of Gimp */
347 //gimp_context_set_pattern ("Clipboard");
348 INIT_I18N ();
349 gimp_context_set_pattern (_("Clipboard"));
350
351 if (width > margin_left + margin_right) {
352 /* top */
353 gimp_rect_select (texture_image,
354 margin_left,
355 0,
356 (gdouble) texture_width - margin_left - margin_right,
357 margin_top,
358 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
359 gimp_edit_copy (texture_layer);
360 gimp_rect_select (image_ID,
361 margin_left,
362 0,
363 (gdouble) width - margin_left - margin_right,
364 margin_top,
365 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
366 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
367
368 /* bottom */
369 gimp_rect_select (texture_image,
370 margin_left,
371 (gdouble) texture_height - margin_bottom,
372 (gdouble) texture_width - margin_left - margin_right,
373 margin_bottom,
374 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
375 gimp_edit_copy (texture_layer);
376 gimp_rect_select (image_ID,
377 margin_left,
378 (gdouble) height - margin_bottom,
379 (gdouble) width - margin_left - margin_right,
380 margin_bottom,
381 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
382 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
383 }
384
385 if (height > margin_top + margin_bottom) {
386 /* left */
387 gimp_rect_select (texture_image,
388 0,
389 margin_top,
390 margin_left,
391 (gdouble) texture_height - margin_top - margin_bottom,
392 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
393 gimp_edit_copy (texture_layer);
394 gimp_rect_select (image_ID,
395 0,
396 margin_top,
397 margin_left,
398 (gdouble) height - margin_top - margin_bottom,
399 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
400 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
401
402 /* right */
403 gimp_rect_select (texture_image,
404 (gdouble) texture_width - margin_right,
405 margin_top,
406 margin_right,
407 (gdouble) texture_height - margin_top - margin_bottom,
408 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
409 gimp_edit_copy (texture_layer);
410 gimp_rect_select (image_ID,
411 (gdouble) width - margin_right,
412 margin_top,
413 margin_right,
414 (gdouble) height - margin_top - margin_bottom,
415 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
416 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
417 }
418
419 /* top left */
420 gimp_rect_select (texture_image,
421 0,
422 0,
423 margin_left,
424 margin_top,
425 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
426 gimp_edit_copy (texture_layer);
427 gimp_rect_select (image_ID,
428 0,
429 0,
430 margin_left,
431 margin_top,
432 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
433 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
434
435 /* top right */
436 gimp_rect_select (texture_image,
437 (gdouble) texture_width - margin_right,
438 0,
439 margin_right,
440 margin_top,
441 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
442 gimp_edit_copy (texture_layer);
443 gimp_rect_select (image_ID,
444 (gdouble) width - margin_right,
445 0,
446 margin_right,
447 margin_top,
448 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
449 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
450
451 /* bottom left */
452 gimp_rect_select (texture_image,
453 0,
454 (gdouble) texture_height - margin_bottom,
455 margin_left,
456 margin_bottom,
457 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
458 gimp_edit_copy (texture_layer);
459 gimp_rect_select (image_ID,
460 0,
461 (gdouble) height - margin_bottom,
462 margin_left,
463 margin_bottom,
464 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
465 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
466
467 /* bottom right */
468 gimp_rect_select (texture_image,
469 (gdouble) texture_width - margin_right,
470 (gdouble) texture_height - margin_bottom,
471 margin_right,
472 margin_bottom,
473 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
474 gimp_edit_copy (texture_layer);
475 gimp_rect_select (image_ID,
476 (gdouble) width - margin_right,
477 (gdouble) height - margin_bottom,
478 margin_right,
479 margin_bottom,
480 GIMP_CHANNEL_OP_REPLACE, FALSE, 0);
481 gimp_edit_fill (layer, GIMP_PATTERN_FILL);
482
483 gimp_image_merge_down(image_ID, layer, GIMP_CLIP_TO_IMAGE);
484
485 gimp_selection_none (image_ID);
486 }
487 }
488
489 static void
preview_update(GtkWidget * preview)490 preview_update (GtkWidget *preview)
491 {
492 gint preview_size = PREVIEW_SIZE;
493 gint max_size = height;
494 if (height < width)
495 max_size = width;
496 if (preview_size > max_size)
497 preview_size = max_size;
498 GdkPixbuf *pixbuf = gimp_image_get_thumbnail (preview_image, preview_size, preview_size, GIMP_PIXBUF_SMALL_CHECKS);
499 gtk_image_set_from_pixbuf (GTK_IMAGE(preview), pixbuf);
500 }
501
502 static gboolean
border_dialog(gint32 image_ID,GimpDrawable * drawable)503 border_dialog (gint32 image_ID,
504 GimpDrawable *drawable)
505 {
506 GtkWidget *dialog;
507 GtkWidget *main_hbox;
508 GtkWidget *middle_vbox;
509 GtkWidget *right_vbox;
510 GtkWidget *label;
511
512 gboolean run;
513
514 gimp_ui_init (PLUG_IN_BINARY, FALSE);
515
516 dialog = gimp_dialog_new ("Simple Border", PLUG_IN_ROLE,
517 NULL, 0,
518 gimp_standard_help_func, PLUG_IN_PROC,
519
520 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
521 GTK_STOCK_OK, GTK_RESPONSE_OK,
522
523 NULL);
524
525 gimp_window_set_transient (GTK_WINDOW (dialog));
526
527 gtk_widget_show (dialog);
528
529 main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
530 gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12);
531 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
532 main_hbox, TRUE, TRUE, 0);
533 gtk_widget_show (main_hbox);
534
535 middle_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
536 gtk_container_set_border_width (GTK_CONTAINER (middle_vbox), 12);
537 gtk_box_pack_start (GTK_BOX (main_hbox), middle_vbox, TRUE, TRUE, 0);
538 gtk_widget_show (middle_vbox);
539
540 right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
541 gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12);
542 gtk_widget_set_size_request (right_vbox, 320, -1);
543 gtk_box_pack_start (GTK_BOX (main_hbox), right_vbox, TRUE, TRUE, 0);
544 gtk_widget_show (right_vbox);
545
546 /* preview */
547 label = gtk_label_new ("Preview");
548 gtk_box_pack_start (GTK_BOX (middle_vbox), label, FALSE, FALSE, 0);
549 gtk_widget_show (label);
550
551 preview_image = gimp_image_duplicate(image_ID);
552
553 preview = gtk_image_new();
554 preview_update (preview);
555
556 gtk_box_pack_start (GTK_BOX (middle_vbox), preview, TRUE, TRUE, 0);
557 gtk_widget_show (preview);
558
559 /* textures */
560 label = gtk_label_new ("Textures");
561 gtk_box_pack_start (GTK_BOX (right_vbox), label, FALSE, FALSE, 0);
562 gtk_widget_show (label);
563
564 GtkWidget *notebook = gtk_notebook_new ();
565 gtk_box_pack_start (GTK_BOX (right_vbox), notebook, FALSE, FALSE, 0);
566 gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
567 gtk_widget_show (notebook);
568
569 create_texture_page (GTK_NOTEBOOK (notebook), "Top", textures, G_N_ELEMENTS (textures));
570
571 run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
572
573 gtk_widget_destroy (dialog);
574
575 return run;
576 }
577
578 static void
create_texture_page(GtkNotebook * notebook,const gchar * category,const Border * textures,guint n_textures)579 create_texture_page (GtkNotebook *notebook, const gchar* category, const Border* textures, guint n_textures) {
580 GtkWidget *label = gtk_label_new (category);
581
582 GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
583 gtk_container_set_border_width (GTK_CONTAINER (thispage), 0);
584 gtk_widget_set_size_request (thispage, -1, 480);
585 gtk_widget_show (thispage);
586
587 /* scrolled window */
588 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
589 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
590 gtk_box_pack_start (GTK_BOX (thispage), scrolled_window, TRUE, TRUE, 0);
591 gtk_widget_show (scrolled_window);
592
593 /* table */
594 gint rows = 5;
595 gint cols = 3;
596 GtkWidget *table = gtk_table_new (rows, cols, FALSE);
597 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
598 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
599 //gtk_box_pack_start (GTK_BOX (thispage), table, FALSE, FALSE, 0);
600 gtk_container_set_border_width (GTK_CONTAINER (table), 10);
601 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
602 gtk_widget_show (table);
603
604 gint row = 1;
605 gint col = 1;
606
607 gint i;
608 for (i = 0; i < n_textures; i++)
609 {
610 GtkWidget *icon = effect_icon_new (&textures[i]);
611 gtk_table_attach_defaults (GTK_TABLE (table), icon, col - 1, col, row - 1, row);
612 gtk_widget_show (icon);
613
614 col++;
615 if (col > cols)
616 {
617 row++;
618 col = 1;
619 }
620 }
621
622 gtk_notebook_append_page_menu (notebook, thispage, label, NULL);
623 }
624
625 static gboolean
create_custom_texture_pages(GtkNotebook * notebook,const gchar * texture_path)626 create_custom_texture_pages (GtkNotebook *notebook, const gchar *texture_path)
627 {
628 gboolean has_custom_texture = FALSE;
629
630 const gchar *gimp_dir = gimp_directory ();
631 const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
632 GDir *dir = g_dir_open (texture_dir, 0, NULL);
633 if (dir)
634 {
635 const gchar *dir_ent;
636 while (dir_ent = g_dir_read_name (dir))
637 {
638 if (is_hidden (dir_ent))
639 continue;
640
641 gchar *filename = g_build_filename (texture_dir, dir_ent, NULL);
642 if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
643 create_custom_texture_page (GTK_NOTEBOOK (notebook), dir_ent, filename);
644 has_custom_texture = TRUE;
645 }
646 }
647 }
648
649 return has_custom_texture;
650 }
651
652 static void
create_custom_texture_page(GtkNotebook * notebook,const gchar * category,const gchar * path)653 create_custom_texture_page (GtkNotebook *notebook, const gchar* category, const gchar* path) {
654 GtkWidget *label = gtk_label_new (category);
655
656 GtkWidget *thispage = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
657 gtk_container_set_border_width (GTK_CONTAINER (thispage), 12);
658 gtk_widget_show (thispage);
659
660 gtk_notebook_append_page_menu (notebook, thispage, label, NULL);
661 }
662
663 static GtkWidget *
effect_icon_new(const Border * border)664 effect_icon_new (const Border *border)
665 {
666 GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
667
668 /* image */
669 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_inline (-1, border->texture, FALSE, NULL);
670 pixbuf = gdk_pixbuf_scale_simple (pixbuf, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GDK_INTERP_BILINEAR);
671 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
672 GtkWidget *event_box = gtk_event_box_new ();
673 gtk_container_add (GTK_CONTAINER (event_box), image);
674 gtk_widget_show (image);
675 gtk_box_pack_start (GTK_BOX (box), event_box, FALSE, FALSE, 0);
676 gtk_widget_show (event_box);
677
678 g_signal_connect (event_box, "button_press_event", G_CALLBACK (texture_press), (gpointer)border);
679
680 /* label */
681 GtkWidget *label = gtk_label_new (border->id);
682 gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 0);
683 gtk_widget_show (label);
684
685 return box;
686 }
687
688 static void
textures_switch_page(GtkNotebook * notebook,GtkWidget * page,guint page_num,const gchar * texture_path)689 textures_switch_page (GtkNotebook *notebook, GtkWidget *page, guint page_num, const gchar *texture_path)
690 {
691 if (page_num == 0 || g_array_index (textures_timestamps, time_t, page_num) > 0)
692 return;
693
694 // fix gtk2
695 page = gtk_notebook_get_nth_page (notebook, page_num);
696
697 gtk_container_set_border_width (GTK_CONTAINER (page), 0);
698 gtk_widget_set_size_request (page, -1, 480);
699
700 const gchar *category = gtk_notebook_get_tab_label_text(notebook, page);
701
702 /* scrolled window */
703 GtkWidget *scrolled_window = gtk_scrolled_window_new (NULL, NULL);
704 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
705 gtk_box_pack_start (GTK_BOX (page), scrolled_window, TRUE, TRUE, 0);
706 gtk_widget_show (scrolled_window);
707
708 /* table */
709 gint rows = 5;
710 gint cols = 3;
711 GtkWidget *table = gtk_table_new (rows, cols, FALSE);
712 gtk_table_set_col_spacings (GTK_TABLE (table), 6);
713 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
714 gtk_container_set_border_width (GTK_CONTAINER (table), 10);
715 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
716 gtk_widget_show (table);
717
718 gint row = 1;
719 gint col = 1;
720
721 const gchar *gimp_dir = gimp_directory ();
722 const gchar *texture_dir = g_build_filename (gimp_dir, texture_path, NULL);
723 const gchar *path = g_build_filename (texture_dir, category, NULL);
724
725 GDir *dir = g_dir_open (path, 0, NULL);
726 if (dir)
727 {
728 const gchar *dir_ent;
729 while (dir_ent = g_dir_read_name (dir))
730 {
731 if (is_hidden (dir_ent))
732 continue;
733
734 gchar *filename = g_build_filename (path, dir_ent, NULL);
735 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
736 pixbuf = gdk_pixbuf_scale_simple (pixbuf, THUMBNAIL_SIZE, THUMBNAIL_SIZE, GDK_INTERP_BILINEAR);
737 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
738 GtkWidget *event_box = gtk_event_box_new ();
739 gtk_container_add (GTK_CONTAINER (event_box), image);
740 gtk_widget_show (image);
741 gtk_table_attach_defaults (GTK_TABLE (table), event_box, col - 1, col, row - 1, row);
742 gtk_widget_show (event_box);
743
744 col++;
745 if (col > cols)
746 {
747 row++;
748 col = 1;
749 }
750
751 g_signal_connect (event_box, "button_press_event", G_CALLBACK (custom_texture_press), filename);
752 }
753 }
754
755 g_array_index (textures_timestamps, time_t, page_num) = time (NULL);
756 }
757
758 static gboolean
texture_press(GtkWidget * event_box,GdkEventButton * event,const Border * texture)759 texture_press (GtkWidget *event_box, GdkEventButton *event, const Border* texture)
760 {
761 bvals.border = texture;
762 bvals.custom_texture = NULL;
763
764 do_texture_press ();
765 }
766
767 static gboolean
custom_texture_press(GtkWidget * event_box,GdkEventButton * event,const gchar * texture)768 custom_texture_press (GtkWidget *event_box, GdkEventButton *event, const gchar *texture)
769 {
770 bvals.border = NULL;
771 bvals.custom_texture = texture;
772
773 do_texture_press ();
774 }
775
776 static void
do_texture_press()777 do_texture_press ()
778 {
779 gimp_image_delete (preview_image);
780 preview_image = gimp_image_duplicate(image_ID);
781
782 border (preview_image);
783
784 preview_update (preview);
785 }
786
787