Commit e789291f authored by BST 1999  Austin Donnelly's avatar BST 1999 Austin Donnelly Committed by Austin Donnelly
Browse files

app/brush_select.c app/brush_select.h app/pattern_select.c delay the popup

Sat May  1 22:18:55 BST 1999  Austin Donnelly  <austin@gimp.org>

	* app/brush_select.c
	* app/brush_select.h
	* app/pattern_select.c
	* app/pattern_select.h: delay the popup of pattern and brush
 	    preview window by 150 millisecs.  Allows flicker-free
 	    selection of brushes/patterns, and still have fast pattern
 	    preview like we used to.  Ideally, should really factor out
 	    the common code in these two files into one generic picker
 	    widget.

	* app/free_select.c: cosmetic whitespace change.

	* app/draw_core.c: use GDK_CAP_NOT_LAST, not GDK_CAP_BUTT,
 	    otherwise sequential line segments in XOR mode have
 	    single-pixel gaps between them.  Worse, if the segments are
 	    only one pixel long, you don't get _any_ lines.  XFree86 seems
 	    to ignore GDK_CAP_BUTT, which is why this bug hasn't been seen
 	    before.  NCD X servers comply with the spec a little more
 	    pedantically, so need GDK_CAP_NOT_LAST.  OS/2 and Win32 people
 	    should check that (eg) the lasso tool still provides proper
 	    visual feedback.
parent 0080b4e0
Sat May 1 22:18:55 BST 1999 Austin Donnelly <austin@gimp.org>
* app/brush_select.c
* app/brush_select.h
* app/pattern_select.c
* app/pattern_select.h: delay the popup of pattern and brush
preview window by 150 millisecs. Allows flicker-free
selection of brushes/patterns, and still have fast pattern
preview like we used to. Ideally, should really factor out
the common code in these two files into one generic picker
widget.
* app/free_select.c: cosmetic whitespace change.
* app/draw_core.c: use GDK_CAP_NOT_LAST, not GDK_CAP_BUTT,
otherwise sequential line segments in XOR mode have
single-pixel gaps between them. Worse, if the segments are
only one pixel long, you don't get _any_ lines. XFree86 seems
to ignore GDK_CAP_BUTT, which is why this bug hasn't been seen
before. NCD X servers comply with the spec a little more
pedantically, so need GDK_CAP_NOT_LAST. OS/2 and Win32 people
should check that (eg) the lasso tool still provides proper
visual feedback.
Sat May 1 12:14:54 PDT 1999 Manish Singh <yosh@gimp.org>
* acinclude.m4
......
......@@ -37,6 +37,9 @@
#define STD_BRUSH_COLUMNS 5
#define STD_BRUSH_ROWS 5
/* how long to wait after mouse-down before showing pattern popup */
#define POPUP_DELAY_MS 150
#define MAX_WIN_WIDTH(bsp) (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_COLUMNS))
#define MAX_WIN_HEIGHT(bsp) (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_ROWS))
#define MARGIN_WIDTH 3
......@@ -137,6 +140,7 @@ brush_select_new (gchar *title,
bsp->old_row = bsp->old_col = 0;
bsp->brush = NULL; /* NULL -> main dialog window */
bsp->brush_popup = NULL;
bsp->popup_timeout_tag = 0;
bsp->NUM_BRUSH_COLUMNS = STD_BRUSH_COLUMNS;
bsp->NUM_BRUSH_ROWS = STD_BRUSH_ROWS;
......@@ -652,24 +656,37 @@ brush_removed_callback (GimpBrushList *list,
/*
* Local functions
*/
static void
brush_popup_open (BrushSelectP bsp,
int x,
int y,
GimpBrushP brush)
typedef struct {
BrushSelectP bsp;
int x;
int y;
GimpBrushP brush;
} popup_timeout_args_t;
static gboolean
brush_popup_timeout (gpointer data)
{
popup_timeout_args_t *args = data;
BrushSelectP bsp = args->bsp;
GimpBrushP brush = args->brush;
gint x, y;
gint x_org, y_org;
gint scr_w, scr_h;
gchar *src, *buf;
/* timeout has gone off so our tag is now invalid */
bsp->popup_timeout_tag = 0;
/* make sure the popup exists and is not visible */
if (bsp->brush_popup == NULL)
{
GtkWidget *frame;
bsp->brush_popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_policy (GTK_WINDOW (bsp->brush_popup), FALSE, FALSE, TRUE);
gtk_window_set_policy (GTK_WINDOW (bsp->brush_popup),
FALSE, FALSE, TRUE);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
gtk_container_add (GTK_CONTAINER (bsp->brush_popup), frame);
......@@ -687,8 +704,8 @@ brush_popup_open (BrushSelectP bsp,
gdk_window_get_origin (bsp->preview->window, &x_org, &y_org);
scr_w = gdk_screen_width ();
scr_h = gdk_screen_height ();
x = x_org + x - brush->mask->width * 0.5;
y = y_org + y - brush->mask->height * 0.5;
x = x_org + args->x - brush->mask->width * 0.5;
y = y_org + args->y - brush->mask->height * 0.5;
x = (x < 0) ? 0 : x;
y = (y < 0) ? 0 : y;
x = (x + brush->mask->width > scr_w) ? scr_w - brush->mask->width : x;
......@@ -714,16 +731,41 @@ brush_popup_open (BrushSelectP bsp,
0, y, brush->mask->width);
src += brush->mask->width;
}
g_free(buf);
g_free (buf);
/* Draw the brush preview */
gtk_widget_draw (bsp->brush_preview, NULL);
return FALSE; /* don't repeat */
}
static void
brush_popup_open (BrushSelectP bsp,
int x,
int y,
GimpBrushP brush)
{
static popup_timeout_args_t popup_timeout_args;
/* if we've already got a timeout scheduled, then we complain */
g_return_if_fail (bsp->popup_timeout_tag == 0);
popup_timeout_args.bsp = bsp;
popup_timeout_args.x = x;
popup_timeout_args.y = y;
popup_timeout_args.brush = brush;
bsp->popup_timeout_tag = gtk_timeout_add (POPUP_DELAY_MS,
brush_popup_timeout,
&popup_timeout_args);
}
static void
brush_popup_close (BrushSelectP bsp)
{
if (bsp->popup_timeout_tag != 0)
gtk_timeout_remove (bsp->popup_timeout_tag);
bsp->popup_timeout_tag = 0;
if (bsp->brush_popup != NULL)
gtk_widget_hide (bsp->brush_popup);
}
......
......@@ -49,6 +49,7 @@ struct _BrushSelect {
/* Brush preview */
GtkWidget *brush_popup;
GtkWidget *brush_preview;
guint popup_timeout_tag;
/* Call back function name */
gchar *callback_name;
......
......@@ -35,7 +35,7 @@ draw_core_new (draw_func)
core->data = NULL;
core->line_width = 1;
core->line_style = GDK_LINE_SOLID;
core->cap_style = GDK_CAP_BUTT;
core->cap_style = GDK_CAP_NOT_LAST;
core->join_style = GDK_JOIN_MITER;
return core;
......
......@@ -405,6 +405,7 @@ free_select_motion (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr)
global_pts[free_sel->num_pts - 1].y,
global_pts[free_sel->num_pts].x,
global_pts[free_sel->num_pts].y);
free_sel->num_pts ++;
}
}
......
......@@ -37,6 +37,9 @@
#define STD_BRUSH_COLUMNS 5
#define STD_BRUSH_ROWS 5
/* how long to wait after mouse-down before showing pattern popup */
#define POPUP_DELAY_MS 150
#define MAX_WIN_WIDTH(bsp) (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_COLUMNS))
#define MAX_WIN_HEIGHT(bsp) (MIN_CELL_SIZE * ((bsp)->NUM_BRUSH_ROWS))
#define MARGIN_WIDTH 3
......@@ -137,6 +140,7 @@ brush_select_new (gchar *title,
bsp->old_row = bsp->old_col = 0;
bsp->brush = NULL; /* NULL -> main dialog window */
bsp->brush_popup = NULL;
bsp->popup_timeout_tag = 0;
bsp->NUM_BRUSH_COLUMNS = STD_BRUSH_COLUMNS;
bsp->NUM_BRUSH_ROWS = STD_BRUSH_ROWS;
......@@ -652,24 +656,37 @@ brush_removed_callback (GimpBrushList *list,
/*
* Local functions
*/
static void
brush_popup_open (BrushSelectP bsp,
int x,
int y,
GimpBrushP brush)
typedef struct {
BrushSelectP bsp;
int x;
int y;
GimpBrushP brush;
} popup_timeout_args_t;
static gboolean
brush_popup_timeout (gpointer data)
{
popup_timeout_args_t *args = data;
BrushSelectP bsp = args->bsp;
GimpBrushP brush = args->brush;
gint x, y;
gint x_org, y_org;
gint scr_w, scr_h;
gchar *src, *buf;
/* timeout has gone off so our tag is now invalid */
bsp->popup_timeout_tag = 0;
/* make sure the popup exists and is not visible */
if (bsp->brush_popup == NULL)
{
GtkWidget *frame;
bsp->brush_popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_policy (GTK_WINDOW (bsp->brush_popup), FALSE, FALSE, TRUE);
gtk_window_set_policy (GTK_WINDOW (bsp->brush_popup),
FALSE, FALSE, TRUE);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
gtk_container_add (GTK_CONTAINER (bsp->brush_popup), frame);
......@@ -687,8 +704,8 @@ brush_popup_open (BrushSelectP bsp,
gdk_window_get_origin (bsp->preview->window, &x_org, &y_org);
scr_w = gdk_screen_width ();
scr_h = gdk_screen_height ();
x = x_org + x - brush->mask->width * 0.5;
y = y_org + y - brush->mask->height * 0.5;
x = x_org + args->x - brush->mask->width * 0.5;
y = y_org + args->y - brush->mask->height * 0.5;
x = (x < 0) ? 0 : x;
y = (y < 0) ? 0 : y;
x = (x + brush->mask->width > scr_w) ? scr_w - brush->mask->width : x;
......@@ -714,16 +731,41 @@ brush_popup_open (BrushSelectP bsp,
0, y, brush->mask->width);
src += brush->mask->width;
}
g_free(buf);
g_free (buf);
/* Draw the brush preview */
gtk_widget_draw (bsp->brush_preview, NULL);
return FALSE; /* don't repeat */
}
static void
brush_popup_open (BrushSelectP bsp,
int x,
int y,
GimpBrushP brush)
{
static popup_timeout_args_t popup_timeout_args;
/* if we've already got a timeout scheduled, then we complain */
g_return_if_fail (bsp->popup_timeout_tag == 0);
popup_timeout_args.bsp = bsp;
popup_timeout_args.x = x;
popup_timeout_args.y = y;
popup_timeout_args.brush = brush;
bsp->popup_timeout_tag = gtk_timeout_add (POPUP_DELAY_MS,
brush_popup_timeout,
&popup_timeout_args);
}
static void
brush_popup_close (BrushSelectP bsp)
{
if (bsp->popup_timeout_tag != 0)
gtk_timeout_remove (bsp->popup_timeout_tag);
bsp->popup_timeout_tag = 0;
if (bsp->brush_popup != NULL)
gtk_widget_hide (bsp->brush_popup);
}
......
......@@ -49,6 +49,7 @@ struct _BrushSelect {
/* Brush preview */
GtkWidget *brush_popup;
GtkWidget *brush_preview;
guint popup_timeout_tag;
/* Call back function name */
gchar *callback_name;
......
......@@ -35,6 +35,9 @@
#define STD_PATTERN_COLUMNS 6
#define STD_PATTERN_ROWS 5
/* how long to wait after mouse-down before showing pattern popup */
#define POPUP_DELAY_MS 150
#define MAX_WIN_WIDTH(psp) (MIN_CELL_SIZE * (psp)->NUM_PATTERN_COLUMNS)
#define MAX_WIN_HEIGHT(psp) (MIN_CELL_SIZE * (psp)->NUM_PATTERN_ROWS)
#define MARGIN_WIDTH 1
......@@ -92,6 +95,7 @@ pattern_select_new (gchar *title,
psp->old_col = psp->old_row = 0;
psp->callback_name = NULL;
psp->pattern_popup = NULL;
psp->popup_timeout_tag = 0;
psp->NUM_PATTERN_COLUMNS = STD_PATTERN_COLUMNS;
psp->NUM_PATTERN_ROWS = STD_PATTERN_COLUMNS;
......@@ -275,6 +279,8 @@ pattern_select_free (PatternSelectP psp)
session_get_window_info (psp->shell, &pattern_select_session_info);
if (psp->pattern_popup != NULL)
gtk_widget_destroy (psp->pattern_popup);
if (psp->popup_timeout_tag != 0)
gtk_timeout_remove (psp->popup_timeout_tag);
if(psp->callback_name)
g_free(psp->callback_name);
......@@ -289,22 +295,36 @@ pattern_select_free (PatternSelectP psp)
/*
* Local functions
*/
static void
pattern_popup_open (PatternSelectP psp,
int x,
int y,
GPatternP pattern)
typedef struct {
PatternSelectP psp;
int x;
int y;
GPatternP pattern;
} popup_timeout_args_t;
static gboolean
pattern_popup_timeout (gpointer data)
{
popup_timeout_args_t *args = data;
PatternSelectP psp = args->psp;
GPatternP pattern = args->pattern;
gint x, y;
gint x_org, y_org;
gint scr_w, scr_h;
gchar *src, *buf;
/* timeout has gone off so our tag is now invalid */
psp->popup_timeout_tag = 0;
/* make sure the popup exists and is not visible */
if (psp->pattern_popup == NULL)
{
GtkWidget *frame;
psp->pattern_popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_policy (GTK_WINDOW (psp->pattern_popup), FALSE, FALSE, TRUE);
gtk_window_set_policy (GTK_WINDOW (psp->pattern_popup),
FALSE, FALSE, TRUE);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
gtk_container_add (GTK_CONTAINER (psp->pattern_popup), frame);
......@@ -322,13 +342,14 @@ pattern_popup_open (PatternSelectP psp,
gdk_window_get_origin (psp->preview->window, &x_org, &y_org);
scr_w = gdk_screen_width ();
scr_h = gdk_screen_height ();
x = x_org + x - pattern->mask->width * 0.5;
y = y_org + y - pattern->mask->height * 0.5;
x = x_org + args->x - pattern->mask->width * 0.5;
y = y_org + args->y - pattern->mask->height * 0.5;
x = (x < 0) ? 0 : x;
y = (y < 0) ? 0 : y;
x = (x + pattern->mask->width > scr_w) ? scr_w - pattern->mask->width : x;
y = (y + pattern->mask->height > scr_h) ? scr_h - pattern->mask->height : y;
gtk_preview_size (GTK_PREVIEW (psp->pattern_preview), pattern->mask->width, pattern->mask->height);
gtk_preview_size (GTK_PREVIEW (psp->pattern_preview),
pattern->mask->width, pattern->mask->height);
gtk_widget_popup (psp->pattern_popup, x, y);
/* Draw the pattern */
......@@ -353,15 +374,42 @@ pattern_popup_open (PatternSelectP psp,
gtk_preview_draw_row (GTK_PREVIEW (psp->pattern_preview), (guchar *)buf, 0, y, pattern->mask->width);
src += pattern->mask->width * pattern->mask->bytes;
}
g_free(buf);
g_free (buf);
/* Draw the pattern preview */
gtk_widget_draw (psp->pattern_preview, NULL);
return FALSE; /* don't repeat */
}
static void
pattern_popup_open (PatternSelectP psp,
int x,
int y,
GPatternP pattern)
{
static popup_timeout_args_t popup_timeout_args;
/* if we've already got a timeout scheduled, then we complain */
g_return_if_fail (psp->popup_timeout_tag == 0);
popup_timeout_args.psp = psp;
popup_timeout_args.x = x;
popup_timeout_args.y = y;
popup_timeout_args.pattern = pattern;
psp->popup_timeout_tag = gtk_timeout_add (POPUP_DELAY_MS,
pattern_popup_timeout,
&popup_timeout_args);
}
static void
pattern_popup_close (PatternSelectP psp)
{
if (psp->popup_timeout_tag != 0)
gtk_timeout_remove (psp->popup_timeout_tag);
psp->popup_timeout_tag = 0;
if (psp->pattern_popup != NULL)
gtk_widget_hide (psp->pattern_popup);
}
......
......@@ -38,6 +38,7 @@ struct _PatternSelect {
/* Pattern popup */
GtkWidget *pattern_popup;
GtkWidget *pattern_preview;
guint popup_timeout_tag;
/* Call back function name */
gchar * callback_name;
......
......@@ -35,6 +35,9 @@
#define STD_PATTERN_COLUMNS 6
#define STD_PATTERN_ROWS 5
/* how long to wait after mouse-down before showing pattern popup */
#define POPUP_DELAY_MS 150
#define MAX_WIN_WIDTH(psp) (MIN_CELL_SIZE * (psp)->NUM_PATTERN_COLUMNS)
#define MAX_WIN_HEIGHT(psp) (MIN_CELL_SIZE * (psp)->NUM_PATTERN_ROWS)
#define MARGIN_WIDTH 1
......@@ -92,6 +95,7 @@ pattern_select_new (gchar *title,
psp->old_col = psp->old_row = 0;
psp->callback_name = NULL;
psp->pattern_popup = NULL;
psp->popup_timeout_tag = 0;
psp->NUM_PATTERN_COLUMNS = STD_PATTERN_COLUMNS;
psp->NUM_PATTERN_ROWS = STD_PATTERN_COLUMNS;
......@@ -275,6 +279,8 @@ pattern_select_free (PatternSelectP psp)
session_get_window_info (psp->shell, &pattern_select_session_info);
if (psp->pattern_popup != NULL)
gtk_widget_destroy (psp->pattern_popup);
if (psp->popup_timeout_tag != 0)
gtk_timeout_remove (psp->popup_timeout_tag);
if(psp->callback_name)
g_free(psp->callback_name);
......@@ -289,22 +295,36 @@ pattern_select_free (PatternSelectP psp)
/*
* Local functions
*/
static void
pattern_popup_open (PatternSelectP psp,
int x,
int y,
GPatternP pattern)
typedef struct {
PatternSelectP psp;
int x;
int y;
GPatternP pattern;
} popup_timeout_args_t;
static gboolean
pattern_popup_timeout (gpointer data)
{
popup_timeout_args_t *args = data;
PatternSelectP psp = args->psp;
GPatternP pattern = args->pattern;
gint x, y;
gint x_org, y_org;
gint scr_w, scr_h;
gchar *src, *buf;
/* timeout has gone off so our tag is now invalid */
psp->popup_timeout_tag = 0;
/* make sure the popup exists and is not visible */
if (psp->pattern_popup == NULL)
{
GtkWidget *frame;
psp->pattern_popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_policy (GTK_WINDOW (psp->pattern_popup), FALSE, FALSE, TRUE);
gtk_window_set_policy (GTK_WINDOW (psp->pattern_popup),
FALSE, FALSE, TRUE);
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
gtk_container_add (GTK_CONTAINER (psp->pattern_popup), frame);
......@@ -322,13 +342,14 @@ pattern_popup_open (PatternSelectP psp,
gdk_window_get_origin (psp->preview->window, &x_org, &y_org);
scr_w = gdk_screen_width ();
scr_h = gdk_screen_height ();
x = x_org + x - pattern->mask->width * 0.5;
y = y_org + y - pattern->mask->height * 0.5;
x = x_org + args->x - pattern->mask->width * 0.5;
y = y_org + args->y - pattern->mask->height * 0.5;
x = (x < 0) ? 0 : x;
y = (y < 0) ? 0 : y;
x = (x + pattern->mask->width > scr_w) ? scr_w - pattern->mask->width : x;
y = (y + pattern->mask->height > scr_h) ? scr_h - pattern->mask->height : y;
gtk_preview_size (GTK_PREVIEW (psp->pattern_preview), pattern->mask->width, pattern->mask->height);
gtk_preview_size (GTK_PREVIEW (psp->pattern_preview),
pattern->mask->width, pattern->mask->height);
gtk_widget_popup (psp->pattern_popup, x, y);
/* Draw the pattern */
......@@ -353,15 +374,42 @@ pattern_popup_open (PatternSelectP psp,
gtk_preview_draw_row (GTK_PREVIEW (psp->pattern_preview), (guchar *)buf, 0, y, pattern->mask->width);
src += pattern->mask->width * pattern->mask->bytes;
}
g_free(buf);
g_free (buf);
/* Draw the pattern preview */
gtk_widget_draw (psp->pattern_preview, NULL);
return FALSE; /* don't repeat */
}
static void
pattern_popup_open (PatternSelectP psp,
int x,
int y,
GPatternP pattern)
{
static popup_timeout_args_t popup_timeout_args;
/* if we've already got a timeout scheduled, then we complain */
g_return_if_fail (psp->popup_timeout_tag == 0);
popup_timeout_args.psp = psp;
popup_timeout_args.x = x;
popup_timeout_args.y = y;
popup_timeout_args.pattern = pattern;
psp->popup_timeout_tag = gtk_timeout_add (POPUP_DELAY_MS,
pattern_popup_timeout,
&popup_timeout_args);
}
static void
pattern_popup_close (PatternSelectP psp)
{
if (psp->popup_timeout_tag != 0)
gtk_timeout_remove (psp->popup_timeout_tag);
psp->popup_timeout_tag = 0;
if (psp->pattern_popup != NULL)
gtk_widget_hide (psp->pattern_popup);
}
......
......@@ -38,6 +38,7 @@ struct _PatternSelect {
/* Pattern popup */
GtkWidget *pattern_popup;
GtkWidget *pattern_preview;
guint popup_timeout_tag;
/* Call back function name */
gchar * callback_name;
......
......@@ -405,6 +405,7 @@ free_select_motion (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr)
global_pts[free_sel->num_pts - 1].y,
global_pts[free_sel->num_pts].x,
global_pts[free_sel->num_pts].y);
free_sel->num_pts ++;
}
}
......
......@@ -405,6 +405,7 @@ free_select_motion (Tool *tool, GdkEventMotion *mevent, gpointer gdisp_ptr)
global_pts[free_sel->num_pts - 1].y,
global_pts[free_sel->num_pts].x,
global_pts[free_sel->num_pts].y);
free_sel->num_pts ++;
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment