home *** CD-ROM | disk | FTP | other *** search
- /* LIBGIMP - The GIMP Library
- * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
- *
- * gimppatternmenu.c
- * Copyright (C) 1998 Andy Thomas
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
- #include "string.h"
-
- #include "gimp.h"
- #include "gimpui.h"
-
- /* Idea is to have a function to call that returns a widget that
- * completely controls the selection of a pattern.
- * you get a widget returned that you can use in a table say.
- * In:- Initial pattern name. Null means use current selection.
- * pointer to func to call when pattern changes (GimpRunPatternCallback).
- * Returned:- Pointer to a widget that you can use in UI.
- *
- * Widget simply made up of a preview widget (20x20) containing the pattern
- * and a button that can be clicked on to change the pattern.
- */
-
-
- #define PSEL_DATA_KEY "__psel_data"
- #define CELL_SIZE 20
- #define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | \
- GDK_BUTTON_PRESS_MASK | \
- GDK_BUTTON_RELEASE_MASK | \
- GDK_BUTTON1_MOTION_MASK
-
- struct __patterns_sel
- {
- gchar *dname;
- GimpRunPatternCallback cback;
- GtkWidget *pattern_preview;
- GtkWidget *device_patpopup;
- GtkWidget *device_patpreview;
- GtkWidget *button;
- GtkWidget *top_hbox;
- gchar *pattern_name; /* Local copy */
- gint width;
- gint height;
- gint bytes;
- gchar *mask_data; /* local copy */
- gchar *pattern_popup_pnt; /* Pointer use to control the popup */
- gpointer data;
- };
-
- typedef struct __patterns_sel PSelect;
-
- static void
- pattern_popup_open (gint x,
- gint y,
- PSelect *psel)
- {
- gint x_org;
- gint y_org;
- gint scr_w;
- gint scr_h;
- gchar *src;
- gchar *buf;
-
- /* make sure the popup exists and is not visible */
- if (psel->device_patpopup == NULL)
- {
- GtkWidget *frame;
-
- psel->device_patpopup = gtk_window_new (GTK_WINDOW_POPUP);
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_container_add (GTK_CONTAINER (psel->device_patpopup), frame);
- gtk_widget_show (frame);
- psel->device_patpreview = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_container_add (GTK_CONTAINER (frame), psel->device_patpreview);
- gtk_widget_show (psel->device_patpreview);
- }
- else
- {
- gtk_widget_hide (psel->device_patpopup);
- }
-
- /* decide where to put the popup */
- gdk_window_get_origin (psel->pattern_preview->window, &x_org, &y_org);
- scr_w = gdk_screen_width ();
- scr_h = gdk_screen_height ();
- x = x_org + x - (psel->width >> 1);
- y = y_org + y - (psel->height >> 1);
- x = (x < 0) ? 0 : x;
- y = (y < 0) ? 0 : y;
- x = (x + psel->width > scr_w) ? scr_w - psel->width : x;
- y = (y + psel->height > scr_h) ? scr_h - psel->height : y;
- gtk_preview_size (GTK_PREVIEW (psel->device_patpreview),
- psel->width, psel->height);
-
- gtk_widget_popup (psel->device_patpopup, x, y);
-
- /* Draw the pattern */
- buf = g_new (gchar, psel->width * 3);
- src = psel->mask_data;
- for (y = 0; y < psel->height; y++)
- {
- if (psel->bytes == 1)
- for (x = 0; x < psel->width; x++)
- {
- buf[x*3+0] = src[x];
- buf[x*3+1] = src[x];
- buf[x*3+2] = src[x];
- }
- else
- for (x = 0; x < psel->width; x++)
- {
- buf[x*3+0] = src[x*3+0];
- buf[x*3+1] = src[x*3+1];
- buf[x*3+2] = src[x*3+2];
- }
- gtk_preview_draw_row (GTK_PREVIEW (psel->device_patpreview),
- (guchar *)buf, 0, y, psel->width);
- src += psel->width * psel->bytes;
- }
- g_free (buf);
-
- /* Draw the brush preview */
- gtk_widget_draw (psel->device_patpreview, NULL);
- }
-
- static void
- pattern_popup_close (PSelect *psel)
- {
- if (psel->device_patpopup != NULL)
- gtk_widget_hide (psel->device_patpopup);
- }
-
- static gint
- pattern_preview_events (GtkWidget *widget,
- GdkEvent *event,
- gpointer data)
- {
- GdkEventButton *bevent;
- PSelect *psel = (PSelect*)data;
-
- if (psel->mask_data)
- {
- switch (event->type)
- {
- case GDK_EXPOSE:
- break;
-
- case GDK_BUTTON_PRESS:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_add (widget);
- pattern_popup_open (bevent->x, bevent->y, psel);
- }
- break;
-
- case GDK_BUTTON_RELEASE:
- bevent = (GdkEventButton *) event;
-
- if (bevent->button == 1)
- {
- gtk_grab_remove (widget);
- pattern_popup_close (psel);
- }
- break;
- case GDK_DELETE:
- break;
-
- default:
- break;
- }
- }
-
- return FALSE;
- }
-
- static void
- pattern_pre_update (GtkWidget *pattern_preview,
- gint width,
- gint height,
- gint bytes,
- gchar *mask_data)
- {
- gint x;
- gint y;
- gchar *src;
- gchar *buf;
-
- /* Draw the pattern */
- buf = g_new (gchar, width * 3);
- src = mask_data;
- for (y = 0; y < CELL_SIZE && y < height; y++)
- {
- if (bytes == 1)
- for (x = 0; x < width && x < CELL_SIZE; x++)
- {
- buf[x*3+0] = src[x];
- buf[x*3+1] = src[x];
- buf[x*3+2] = src[x];
- }
- else
- for (x = 0; x < width && x < CELL_SIZE; x++)
- {
- buf[x*3+0] = src[x*3+0];
- buf[x*3+1] = src[x*3+1];
- buf[x*3+2] = src[x*3+2];
- }
- gtk_preview_draw_row (GTK_PREVIEW (pattern_preview),
- (guchar *)buf, 0, y, (width < CELL_SIZE) ? width : CELL_SIZE);
- src += width * bytes;
- }
- g_free (buf);
-
- /* Draw the brush preview */
- gtk_widget_draw (pattern_preview, NULL);
- }
-
- static void
- pattern_select_invoker (gchar *name,
- gint width,
- gint height,
- gint bytes,
- gchar *mask_data,
- gint closing,
- gpointer data)
- {
- gint mask_d_sz;
- PSelect *psel = (PSelect*)data;
-
- if (psel->mask_data != NULL)
- g_free(psel->mask_data);
-
- psel->width = width;
- psel->height = height;
- psel->bytes = bytes;
- mask_d_sz = width * height * bytes;
- psel->mask_data = g_malloc (mask_d_sz);
- g_memmove (psel->mask_data, mask_data, mask_d_sz);
-
- pattern_pre_update (psel->pattern_preview,
- psel->width, psel->height, psel->bytes, psel->mask_data);
-
- if (psel->cback != NULL)
- (psel->cback)(name, width, height, bytes, mask_data, closing, psel->data);
-
- if(closing)
- {
- gtk_widget_set_sensitive (psel->button, TRUE);
- psel->pattern_popup_pnt = NULL;
- }
- }
-
-
- static void
- patterns_select_callback (GtkWidget *widget,
- gpointer data)
- {
- PSelect *psel = (PSelect*)data;
-
- gtk_widget_set_sensitive (psel->button, FALSE);
- psel->pattern_popup_pnt =
- gimp_interactive_selection_pattern ((psel->dname) ? psel->dname :
- "Pattern Plugin Selection",
- psel->pattern_name,
- pattern_select_invoker,psel);
- }
-
- GtkWidget *
- gimp_pattern_select_widget (gchar *dname,
- gchar *ipattern,
- GimpRunPatternCallback cback,
- gpointer data)
- {
- GtkWidget *frame;
- GtkWidget *hbox;
- GtkWidget *pattern;
- GtkWidget *button;
- gint width;
- gint height;
- gint bytes;
- gint mask_data_size;
- guint8 *mask_data;
- gchar *pattern_name;
- PSelect *psel;
-
- psel = g_new (PSelect, 1);
-
- hbox = gtk_hbox_new (FALSE, 3);
- gtk_widget_show(hbox);
-
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
- gtk_widget_show (frame);
-
- pattern = gtk_preview_new (GTK_PREVIEW_COLOR);
- gtk_preview_size (GTK_PREVIEW (pattern), CELL_SIZE, CELL_SIZE);
- gtk_widget_show (pattern);
- gtk_container_add (GTK_CONTAINER (frame), pattern);
-
- gtk_widget_set_events (pattern, PREVIEW_EVENT_MASK);
-
- gtk_signal_connect (GTK_OBJECT (pattern), "event",
- (GtkSignalFunc) pattern_preview_events,
- (gpointer)psel);
-
- psel->cback = cback;
- psel->data = data;
- psel->mask_data = NULL;
- psel->device_patpopup = psel->device_patpreview = NULL;
- psel->pattern_preview = pattern;
- psel->pattern_name = ipattern;
- psel->dname = dname;
- psel->pattern_popup_pnt = NULL;
-
- /* Do initial pattern setup */
- pattern_name =
- gimp_patterns_get_pattern_data (ipattern,
- &width,
- &height,
- &bytes,
- &mask_data_size,
- &mask_data);
-
- if(pattern_name)
- {
- pattern_pre_update (psel->pattern_preview,
- width, height, bytes, mask_data);
- psel->mask_data = mask_data;
- psel->pattern_name = pattern_name;
- psel->width = width;
- psel->height = height;
- psel->bytes = bytes;
- }
-
- gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
-
- button = gtk_button_new_with_label ("... ");
- gtk_container_add (GTK_CONTAINER (hbox), button);
- gtk_widget_show (button);
-
- psel->button = button;
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) patterns_select_callback,
- (gpointer)psel);
-
- gtk_object_set_data (GTK_OBJECT(hbox), PSEL_DATA_KEY, (gpointer)psel);
-
- return hbox;
- }
-
- void
- gimp_pattern_select_widget_close_popup (GtkWidget *widget)
- {
- PSelect *psel;
-
- psel = (PSelect *) gtk_object_get_data (GTK_OBJECT (widget), PSEL_DATA_KEY);
-
- if (psel && psel->pattern_popup_pnt)
- {
- gimp_patterns_close_popup (psel->pattern_popup_pnt);
- psel->pattern_popup_pnt = NULL;
- }
- }
-
- void
- gimp_pattern_select_widget_set_popup (GtkWidget *widget,
- gchar *pname)
- {
- gint width;
- gint height;
- gint bytes;
- gint mask_data_size;
- guint8 *mask_data;
- gchar *pattern_name;
- PSelect *psel;
-
- psel = (PSelect*) gtk_object_get_data (GTK_OBJECT (widget), PSEL_DATA_KEY);
-
- if (psel)
- {
- pattern_name =
- gimp_patterns_get_pattern_data (pname,
- &width,
- &height,
- &bytes,
- &mask_data_size,
- &mask_data);
-
- pattern_select_invoker (pname, width, height, bytes, mask_data, 0, psel);
-
- if (psel->pattern_popup_pnt)
- gimp_patterns_set_popup (psel->pattern_popup_pnt, pname);
- }
- }
-
-