diff options
author | Martin Mathieson <martin.r.mathieson@googlemail.com> | 2012-08-07 19:11:43 +0000 |
---|---|---|
committer | Martin Mathieson <martin.r.mathieson@googlemail.com> | 2012-08-07 19:11:43 +0000 |
commit | 41d9e150259df57a46783d0f69ab01ffbc0626d9 (patch) | |
tree | 4f5de1c9bacf69b5c8fe5305b5bac63dfe372a36 /ui | |
parent | 6c32ba5ff1a5f5ec2426d1d2c4f4f37fd136bab0 (diff) |
Redo the cross drawing/erasing.
Draw in black, erase by just redrawing the current pixmap.
Will apply to tcp_graph.c if/when this gets through the buildbots.
svn path=/trunk/; revision=44308
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gtk/rlc_lte_graph.c | 118 |
1 files changed, 62 insertions, 56 deletions
diff --git a/ui/gtk/rlc_lte_graph.c b/ui/gtk/rlc_lte_graph.c index 37424fd2fe..f9e709952c 100644 --- a/ui/gtk/rlc_lte_graph.c +++ b/ui/gtk/rlc_lte_graph.c @@ -125,11 +125,13 @@ struct element_list { struct axis { struct graph *g; /* which graph we belong to */ GtkWidget *drawing_area; + /* Double-buffering to avoid flicker */ #if GTK_CHECK_VERSION(2,22,0) cairo_surface_t *surface[2]; #else GdkPixmap *pixmap[2]; #endif + /* Which of the 2 buffers we are currently showing */ int displayed; #define AXIS_ORIENTATION 1 << 0 int flags; @@ -194,6 +196,8 @@ struct graph { GtkWidget *toplevel; /* keypress handler needs this */ GtkWidget *drawing_area; PangoFontDescription *font; /* font used for annotations etc. */ + + /* Double-buffering */ #if GTK_CHECK_VERSION(2,22,0) cairo_surface_t *title_surface; cairo_surface_t *surface[2]; @@ -302,7 +306,6 @@ static void axis_destroy(struct axis * ); static int get_label_dim(struct axis * , int , double ); static void toggle_crosshairs(struct graph *); -static void cross_xor(struct graph * , int x, int y); static void cross_draw(struct graph * , int x, int y); static void cross_erase(struct graph * ); static gboolean motion_notify_event(GtkWidget * , GdkEventMotion * , gpointer ); @@ -1125,14 +1128,13 @@ static void graph_pixmap_draw(struct graph *g) cairo_rectangle(cr, 0, 0, g->wp.width, g->wp.height); cairo_fill(cr); cairo_destroy(cr); - cr = NULL; /* Create one cairo_t for use with all of the lines, rather than continually creating and destroying one for each line */ #if GTK_CHECK_VERSION(2,22,0) - cr_lines = cairo_create(g->surface[1^g->displayed]); + cr_lines = cairo_create(g->surface[not_disp]); #else - cr_lines = gdk_cairo_create(g->pixmap[1^g->displayed]); + cr_lines = gdk_cairo_create(g->pixmap[not_disp]); #endif /* Line width is always 1 pixel */ @@ -1187,10 +1189,10 @@ static void draw_element_line(struct graph *g, struct element *e, cairo_t *cr, } /* Map point into graph area, and round to nearest int */ - xx1 = (int )rint(e->p.line.dim.x1 + g->geom.x - g->wp.x); - xx2 = (int )rint(e->p.line.dim.x2 + g->geom.x - g->wp.x); - yy1 = (int )rint((g->geom.height-1-e->p.line.dim.y1) + g->geom.y-g->wp.y); - yy2 = (int )rint((g->geom.height-1-e->p.line.dim.y2) + g->geom.y-g->wp.y); + xx1 = (int)rint(e->p.line.dim.x1 + g->geom.x - g->wp.x); + xx2 = (int)rint(e->p.line.dim.x2 + g->geom.x - g->wp.x); + yy1 = (int)rint((g->geom.height-1-e->p.line.dim.y1) + g->geom.y-g->wp.y); + yy2 = (int)rint((g->geom.height-1-e->p.line.dim.y2) + g->geom.y-g->wp.y); /* If line completely out of the area, we won't show it */ if ((xx1<0 && xx2<0) || (xx1>=g->wp.width && xx2>=g->wp.width) || @@ -1682,7 +1684,7 @@ static void graph_select_segment(struct graph *g, int x, int y) set_busy_cursor(gtk_widget_get_window(g->drawing_area)); - for (list=g->elists; list; list=list->next) + for (list=g->elists; list; list=list->next) { for (e=list->elements; e->type != ELMT_NONE; e++) { switch (e->type) { case ELMT_LINE: @@ -1695,6 +1697,7 @@ static void graph_select_segment(struct graph *g, int x, int y) break; } } + } if (num) { @@ -1706,27 +1709,33 @@ static int line_detect_collision(struct element *e, int x, int y) { int xx1, yy1, xx2, yy2; + /* Get sorted x, y co-ordinates for line */ if (e->p.line.dim.x1 < e->p.line.dim.x2) { - xx1 = (int )rint(e->p.line.dim.x1); - xx2 = (int )rint(e->p.line.dim.x2); + xx1 = (int)rint(e->p.line.dim.x1); + xx2 = (int)rint(e->p.line.dim.x2); } else { - xx1 = (int )rint(e->p.line.dim.x2); - xx2 = (int )rint(e->p.line.dim.x1); + xx1 = (int)rint(e->p.line.dim.x2); + xx2 = (int)rint(e->p.line.dim.x1); } if (e->p.line.dim.y1 < e->p.line.dim.y2) { - yy1 = (int )rint(e->p.line.dim.y1); - yy2 = (int )rint(e->p.line.dim.y2); + yy1 = (int)rint(e->p.line.dim.y1); + yy2 = (int)rint(e->p.line.dim.y2); } else { - yy1 = (int )rint(e->p.line.dim.y2); - yy2 = (int )rint(e->p.line.dim.y1); + yy1 = (int)rint(e->p.line.dim.y2); + yy2 = (int)rint(e->p.line.dim.y1); } /* printf("line: (%d,%d)->(%d,%d), clicked: (%d,%d)\n", xx1, yy1, xx2, yy2, x, y); */ - if ((xx1==x && xx2==x && yy1<=y && y<=yy2)||(yy1==y && yy2==y && xx1<=x && x<=xx2)) + + /* N.B. won't match with diagonal lines... */ + if ((xx1==x && xx2==x && yy1<=y && y<=yy2)| /* lies along vertical line */ + (yy1==y && yy2==y && xx1<=x && x<=xx2)) { /* lies along horizontal line */ return TRUE; - else + } + else { return FALSE; + } } @@ -2017,7 +2026,7 @@ static gboolean button_press_event(GtkWidget *widget _U_, GdkEventButton *event, } else if (event->button == MOUSE_BUTTON_MIDDLE) { do_zoom_mouse(g, event); } else if (event->button == MOUSE_BUTTON_LEFT) { - graph_select_segment(g, (int )event->x, (int )event->y); + graph_select_segment(g, (int)event->x, (int)event->y); } unset_busy_cursor(gtk_widget_get_window(g->drawing_area)); @@ -2036,7 +2045,7 @@ static gboolean button_release_event(GtkWidget *widget _U_, GdkEventButton *even return TRUE; } -static gboolean motion_notify_event (GtkWidget *widget _U_, GdkEventMotion *event, gpointer user_data) +static gboolean motion_notify_event(GtkWidget *widget _U_, GdkEventMotion *event, gpointer user_data) { struct graph *g = user_data; int x, y; @@ -2171,38 +2180,6 @@ static void toggle_crosshairs(struct graph *g) } } -static void cross_xor (struct graph *g, int x, int y) -{ -#if GTK_CHECK_VERSION(2,22,0) - GdkColor color_gray15 = {0x0, 0xffff, 0xffff, 0xffff}; - cairo_t *cr; - - if (x > g->wp.x && x < g->wp.x+g->wp.width && - y >= g->wp.y && y < g->wp.y+g->wp.height) { - /* Draw horizontal line */ - cr = gdk_cairo_create(gtk_widget_get_window(g->drawing_area)); - cairo_set_operator (cr, CAIRO_OPERATOR_XOR); - gdk_cairo_set_source_color (cr, &color_gray15); - cairo_set_line_width (cr, 1.0); - cairo_move_to(cr, g->wp.x+0.5, y+0.5); - cairo_line_to(cr, g->wp.x + g->wp.width+0.5, y+0.5); - /* Draw vertical line */ - cairo_move_to(cr, x+0.5, g->wp.y+0.5); - cairo_line_to(cr, x+0.5, g->wp.y + g->wp.height+0.5); - cairo_stroke(cr); - cairo_destroy(cr); - } -#else - if (x > g->wp.x && x < g->wp.x+g->wp.width && - y >= g->wp.y && y < g->wp.y+g->wp.height) { - gdk_draw_line(gtk_widget_get_window(g->drawing_area), xor_gc, g->wp.x, - y, g->wp.x + g->wp.width, y); - gdk_draw_line(gtk_widget_get_window(g->drawing_area), xor_gc, x, - g->wp.y, x, g->wp.y + g->wp.height); - } -#endif /* GTK_CHECK_VERSION(2,22,0) */ -} - static void cross_draw(struct graph *g, int x, int y) { /* Shouldn't draw twice onto the same position if haven't erased in the @@ -2210,7 +2187,27 @@ static void cross_draw(struct graph *g, int x, int y) if (g->cross.erase_needed && (g->cross.x == x) && (g->cross.y == y)) { return; } - cross_xor(g, x, y); + + /* Draw the cross */ + if (x > g->wp.x && x < g->wp.x+g->wp.width && + y >= g->wp.y && y < g->wp.y+g->wp.height) { + + cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(g->drawing_area)); + gdk_cairo_set_source_color(cr, &g->style.seq_color); + cairo_set_line_width(cr, 1.0); + + /* Horizonal line */ + cairo_move_to(cr, g->wp.x+0.5, y+0.5); + cairo_line_to(cr, g->wp.x + g->wp.width+0.5, y+0.5); + + /* Vertical line */ + cairo_move_to(cr, x+0.5, g->wp.y+0.5); + cairo_line_to(cr, x+0.5, g->wp.y + g->wp.height+0.5); + cairo_stroke(cr); + cairo_destroy(cr); + } + + /* Update state */ g->cross.x = x; g->cross.y = y; g->cross.erase_needed = TRUE; @@ -2218,8 +2215,17 @@ static void cross_draw(struct graph *g, int x, int y) static void cross_erase(struct graph *g) { - cross_xor (g, g->cross.x, g->cross.y); - g->cross.erase_needed = 0; + int x = g->cross.x; + int y = g->cross.y; + + if (x > g->wp.x && x < g->wp.x+g->wp.width && + y >= g->wp.y && y < g->wp.y+g->wp.height) { + + /* Just redraw what is in the pixmap buffer */ + graph_pixmap_display(g); + } + + g->cross.erase_needed = FALSE; } |