/* * GdiffOverview widget module * * Copyright INOUE Seiichiro , licensed under the GPL. */ #include #include "gdiffoverview.h" #include "style.h" /* Keys for gtk_object_[get|set]_data() for drawing area */ #define OV_DAREA_KEY "n" /* Private function declarations */ static void gdiff_overview_class_init(GdiffOverviewClass *klass); static void gdiff_overview_init(GdiffOverview *overview); static void gdiff_overview_draw_lines(GtkWidget *darea, GdkEventExpose *event, gpointer data); static GtkHBoxClass *parent_class = NULL; GtkType gdiff_overview_get_type(void) { static GtkType overview_type = 0; if (!overview_type) { static const GtkTypeInfo overview_info = { "GdiffOverview", sizeof(GdiffOverview), sizeof(GdiffOverviewClass), (GtkClassInitFunc)gdiff_overview_class_init, (GtkObjectInitFunc)gdiff_overview_init, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc)NULL, }; overview_type = gtk_type_unique(GTK_TYPE_HBOX, &overview_info); } return overview_type; } static void gdiff_overview_class_init(GdiffOverviewClass *klass) { parent_class = gtk_type_class(GTK_TYPE_HBOX); } static void gdiff_overview_init(GdiffOverview *overview) { overview->num_ranges = 0; overview->ranges = NULL; overview->dareas = NULL; } GtkWidget* gdiff_overview_new(int num_ranges, GtkAdjustment **adj_array) { GdiffOverview *overview; GtkHBox *hbox; GtkWidget *range; GtkWidget *darea; int n; overview = gtk_type_new(GDIFF_TYPE_OVERVIEW); overview->num_ranges = num_ranges; overview->ranges = g_new(GdiffRange*, num_ranges); overview->dareas = g_new(GtkDrawingArea*, num_ranges-1); hbox = GTK_HBOX(overview); for (n = 0; n < overview->num_ranges; n++) { char *style_name; range = gdiff_range_new(NULL); overview->ranges[n] = GDIFF_RANGE(range); style_name = g_strdup_printf("file%d overview", n+1); gtk_widget_set_name(range, style_name); g_free(style_name); style_set_gdiff_range(range, n); gdiff_range_size(GDIFF_RANGE(range), WIDTH_OVERVIEW, 0); gtk_box_pack_start(GTK_BOX(hbox), range, FALSE, FALSE, 0); gtk_widget_show(range); if (n != overview->num_ranges-1) { darea = gtk_drawing_area_new(); overview->dareas[n] = GTK_DRAWING_AREA(darea); gtk_widget_set_name(darea, "drawing overview"); style_set_drawingarea(darea); gtk_drawing_area_size(GTK_DRAWING_AREA(darea), WIDTH_OVERVIEW, 0); gtk_object_set_data(GTK_OBJECT(darea), OV_DAREA_KEY, GINT_TO_POINTER(n)); gtk_signal_connect(GTK_OBJECT(darea), "expose_event", GTK_SIGNAL_FUNC(gdiff_overview_draw_lines), overview); gtk_box_pack_start(GTK_BOX(hbox), darea, FALSE, FALSE, 0); gtk_widget_show(darea); } } gdiff_overview_set_adjustment(overview, adj_array); return GTK_WIDGET(overview); } /** Interfaces **/ void gdiff_overview_set_adjustment(GdiffOverview *overview, GtkAdjustment **adj_array) { int n; g_return_if_fail(overview != NULL); g_return_if_fail(GDIFF_IS_OVERVIEW(overview)); for (n = 0; n < overview->num_ranges; n++) { gdiff_range_set_adjustment(overview->ranges[n], adj_array[n]); } } /** * gdiff_overview_insert_paintrange: * Internally, set it for GdiffRange widgets. **/ void gdiff_overview_insert_paintrange(GdiffOverview *overview, const gdouble *begin_array, const gdouble *end_array) { int n; g_return_if_fail(overview != NULL); g_return_if_fail(GDIFF_IS_OVERVIEW(overview)); for (n = 0; n < overview->num_ranges; n++) { gdiff_range_insert_paintrange(overview->ranges[n], begin_array[n], end_array[n]); } } /** * gdiff_overview_set_color: **/ void gdiff_overview_set_color(GdiffOverview *overview, GdkColor **fg_array, GdkColor **bg_array) { int n; g_return_if_fail(overview != NULL); g_return_if_fail(GDIFF_IS_OVERVIEW(overview)); for (n = 0; n < overview->num_ranges; n++) { if (fg_array[n]) gdiff_range_set_foreground(overview->ranges[n], fg_array[n]); if (bg_array[n]) gdiff_range_set_background(overview->ranges[n], bg_array[n]); } } /** Internal functions **/ #define lines_intersect(y1, y2, top, bottom) \ ((y1 >= top && y1 <= bottom) || (y2 >= top && y2 <= bottom)) /** * gdiff_overview_draw_lines: * Using range values, which are kept in GdiffRange widgets, * draw lines on drawingarea widget. **/ static void gdiff_overview_draw_lines(GtkWidget *darea, GdkEventExpose *event, gpointer data) { GdiffOverview *overview = data; int num = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(darea), OV_DAREA_KEY)); GdkWindow *w = darea->window; GdkGC *gc = darea->style->fg_gc[GTK_STATE_NORMAL]; int darea_width; int darea_height; const GSList *list1 = overview->ranges[num]->range_list;/* left GdiffRange */ const GSList *list2 = overview->ranges[num+1]->range_list;/* right GdiffRange */ gdk_window_get_size(w, &darea_width, &darea_height); while (list1 && list2) { const PaintRange *pr1 = list1->data; const PaintRange *pr2 = list2->data; int y1, y2; y1 = darea_height * (pr1->begin + pr1->end) / 2; y2 = darea_height * (pr2->begin + pr2->end) / 2.0; if (lines_intersect(y1, y2, event->area.y, event->area.y+event->area.height)) { gdk_draw_line(w, gc, 0, y1, darea_width, y2); } list1 = g_slist_next(list1); list2 = g_slist_next(list2); } }