/* gtkDPSpaintsel.h --- DPS paint selection widget * Copyright (C) 1999 Masatake YAMATO * * Author: Masatake YAMATO * Created: Sun Oct 3 00:00:21 1999 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library 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 Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gtkDPSpaintsel.h" #include #include #include #define DEFAULT_SPACING 1 #define DEFAULT_LINE_WITDH 3.0 #define DEFAULT_COLUMNS 8 #define DEFAULT_X_ENTRY_WIDTH 25 #define DEFAULT_X_ENTRY_HEIGHT 25 static void gtk_dps_paint_selection_class_init (GtkDPSPaintSelectionClass * klass); static void gtk_dps_paint_selection_init (GtkDPSPaintSelection * paintsel); static void gtk_dps_paint_selection_set_columns(GtkDPSPaintSelection * paintsel, gint columns); static void gtk_dps_paint_selection_set_arg(GtkObject * object, GtkArg * arg, guint arg_id); static void gtk_dps_paint_selection_get_arg(GtkObject * object, GtkArg * arg, guint arg_id); static void gtk_dps_paint_selection_destroy (GtkObject * object); static GtkScrolledWindowClass * gtk_dps_paint_selection_parent_class; static void gtk_dps_paint_selection_draw_frames(GtkDPSPaintSelection * paintsel); static void gtk_dps_paint_selection_draw_frame(GtkDPSPaintSelection * paintsel, GdkDPSRectangle * rect, gboolean currentp); static void gtk_dps_paint_selection_draw_entries(GtkDPSPaintSelection * paintsel); static void gtk_dps_paint_selection_draw_entry(GtkDPSPaintSelection * paintsel, GdkDPSRectangle * rect, GtkDPSPaintSelectionEntry * entry); static void gtk_dps_paint_selection_draw_lazy (GtkDPSArea *area, GdkRectangle *x_rectangle, GdkDPSRectangle *dps_rectangle, gpointer user_data); static void gtk_dps_paint_selection_coordtr_update(GtkDPSArea *area, GdkDPSCoordtr * coordtr, gpointer user_data); static void gtk_dps_paint_selection_button_release_event_dps(GtkDPSArea * area, GdkEventButton *event, GdkDPSPoint *dps_point, gpointer user_data); static void gtk_real_dps_paint_selection_add_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint position); static void gtk_real_dps_paint_selection_remove_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint position); static void gtk_real_dps_paint_selection_reposit_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint old, gint new); static void gtk_real_dps_paint_selection_paint_change(GtkDPSPaintSelection * paintsel, gint old, gint new); static void gtk_real_dps_paint_selection_draw_entry(GtkDPSPaintSelection * paintsel, DPSContext raw_ctxt, GdkDPSRectangle * rect, GtkDPSPaintSelectionEntry * entry); /* Entries */ static GtkDPSPaintSelectionEntries * gtk_dps_paint_selection_entries_new(void); static void gtk_dps_paint_selection_entries_init(GtkDPSPaintSelectionEntries * entries); static gint gtk_dps_paint_selection_entries_add(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelectionEntry * entry); static void gtk_dps_paint_selection_entries_remove(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelectionEntry * entry); static void gtk_dps_paint_selection_entries_repsoit(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelection * paintsel); static gint gtk_dps_paint_selection_entries_count(GtkDPSPaintSelectionEntries * entries); static void gtk_dps_paint_selection_entries_foreach(GtkDPSPaintSelectionEntries * entries, GFunc func, gpointer user_data); static GtkDPSPaintSelectionEntry* gtk_dps_paint_selection_entries_get(GtkDPSPaintSelectionEntries * entries, gint position); static void gtk_dps_paint_selection_entries_free(GtkDPSPaintSelectionEntries *); /* Entry */ static GtkDPSPaintSelectionEntry * gtk_dps_paint_selection_entry_new(gpointer *data, gboolean g_free_data, gchar * name); static void gtk_dps_paint_selection_entry_set_position(GtkDPSPaintSelectionEntry * entry, gint position); static void gtk_dps_paint_selection_entry_free(GtkDPSPaintSelectionEntry * entry); /* Geometry */ static GdkDPSRectangle gtk_dps_paint_selection_calc_rectangle(GtkDPSPaintSelection *, gint position); static gint gtk_dps_paint_selection_calc_position_from_point(GtkDPSPaintSelection *, GdkDPSPoint * dps_point); enum { PAINT_CHANGED, DRAW_ENTRY, ADD_ENTRY, REMOVE_ENTRY, REPOSIT_ENTRY, LAST_SIGNAL }; static guint dps_paintsel_signals[LAST_SIGNAL] = { 0 }; enum { ARG_0, ARG_PAINT }; /* * Initialize */ GtkWidget * gtk_dps_paint_selection_new (gint columns) { GtkDPSPaintSelection * paintsel; paintsel = gtk_type_new (gtk_dps_paint_selection_get_type ()); gtk_dps_paint_selection_set_columns(paintsel, columns); return GTK_WIDGET (paintsel); } GtkType gtk_dps_paint_selection_get_type (void) { static GtkType dps_paint_selection_type = 0; if (!dps_paint_selection_type) { GtkTypeInfo dps_paint_selection_info = { "GtkDPSPaintSelection", sizeof (GtkDPSPaintSelection), sizeof (GtkDPSPaintSelectionClass), (GtkClassInitFunc) gtk_dps_paint_selection_class_init, (GtkObjectInitFunc) gtk_dps_paint_selection_init, NULL, NULL, }; dps_paint_selection_type = gtk_type_unique(gtk_scrolled_window_get_type (), &dps_paint_selection_info); } return dps_paint_selection_type; } static void gtk_dps_paint_selection_class_init (GtkDPSPaintSelectionClass * klass) { GtkObjectClass *object_class = (GtkObjectClass *) klass; gtk_dps_paint_selection_parent_class = gtk_type_class (gtk_scrolled_window_get_type ()); gtk_object_add_arg_type ("GtkDPSPaintSelection::paint", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAINT); dps_paintsel_signals[PAINT_CHANGED] = gtk_signal_new ("paint_changed", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GtkDPSPaintSelectionClass, paint_changed), gtk_marshal_NONE__INT_INT, GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT); klass->paint_changed = gtk_real_dps_paint_selection_paint_change; dps_paintsel_signals[DRAW_ENTRY] = gtk_signal_new ("draw_entry", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GtkDPSPaintSelectionClass, draw_entry), gtk_marshal_NONE__POINTER_POINTER_POINTER, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_POINTER, GTK_TYPE_POINTER); klass->draw_entry = gtk_real_dps_paint_selection_draw_entry; dps_paintsel_signals[ADD_ENTRY] = gtk_signal_new ("add_entry", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GtkDPSPaintSelectionClass, add_entry), gtk_marshal_NONE__POINTER_INT, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT); klass->add_entry = gtk_real_dps_paint_selection_add_entry; dps_paintsel_signals[REMOVE_ENTRY] = gtk_signal_new("remove_entry", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GtkDPSPaintSelectionClass, remove_entry), gtk_marshal_NONE__POINTER_INT, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_INT); klass->remove_entry = gtk_real_dps_paint_selection_remove_entry; dps_paintsel_signals[REPOSIT_ENTRY] = gtk_signal_new("reposit_entry", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET(GtkDPSPaintSelectionClass, reposit_entry), gtk_marshal_NONE__POINTER_INT_INT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT); klass->reposit_entry = gtk_real_dps_paint_selection_reposit_entry; gtk_object_class_add_signals (object_class, dps_paintsel_signals, LAST_SIGNAL); object_class->set_arg = gtk_dps_paint_selection_set_arg; object_class->get_arg = gtk_dps_paint_selection_get_arg; object_class->destroy = gtk_dps_paint_selection_destroy; } static void gtk_dps_paint_selection_init (GtkDPSPaintSelection * paintsel) { gtk_scrolled_window_set_hadjustment(GTK_SCROLLED_WINDOW(paintsel), NULL); gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(paintsel), NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(paintsel), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); paintsel->dps_area = gtk_dps_area_new (2); paintsel->columns = DEFAULT_COLUMNS; paintsel->rows = 1; paintsel->x_entry_width = DEFAULT_X_ENTRY_WIDTH; paintsel->x_entry_height = DEFAULT_X_ENTRY_HEIGHT; paintsel->spacing = DEFAULT_SPACING; paintsel->line_width = DEFAULT_LINE_WITDH; gtk_widget_show(paintsel->dps_area); paintsel->alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0); gtk_container_add (GTK_CONTAINER (paintsel->alignment), paintsel->dps_area); gtk_widget_show(paintsel->alignment); gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (paintsel), paintsel->alignment); paintsel->entries = gtk_dps_paint_selection_entries_new(); gtk_signal_connect(GTK_OBJECT(paintsel->dps_area), "draw_lazy", (GtkSignalFunc) gtk_dps_paint_selection_draw_lazy, paintsel); gtk_signal_connect(GTK_OBJECT(paintsel->dps_area), "coordtr_update", (GtkSignalFunc) gtk_dps_paint_selection_coordtr_update, paintsel); gtk_signal_connect(GTK_OBJECT(paintsel->dps_area), "button_release_event_dps", (GtkSignalFunc) gtk_dps_paint_selection_button_release_event_dps, paintsel); gtk_dps_paint_selection_add_entry(paintsel, NULL, FALSE, "no paint"); } static void gtk_dps_paint_selection_set_columns(GtkDPSPaintSelection * paintsel, gint columns) { g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (columns >= 0); if (columns == 0) columns = DEFAULT_COLUMNS; paintsel->columns = columns; gtk_dps_area_size(GTK_DPS_AREA(paintsel->dps_area), (paintsel->x_entry_width * paintsel->columns) + (paintsel->columns + 1)*paintsel->spacing, paintsel->x_entry_height * paintsel->rows + (paintsel->rows + 1) * paintsel->spacing); } void gtk_dps_paint_selection_set_paint (GtkDPSPaintSelection * paintsel, gint paint) { g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (paint >= 0); g_return_if_fail (paint < gtk_dps_paint_selection_entries_count(paintsel->entries)); if (paintsel->paint == paint) return ; gtk_signal_emit (GTK_OBJECT(paintsel), dps_paintsel_signals[PAINT_CHANGED], paintsel->paint, paint); } gint gtk_dps_paint_selection_get_paint (GtkDPSPaintSelection * paintsel) { g_return_val_if_fail (paintsel, 0); g_return_val_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel), 0); return paintsel->paint; } void gtk_dps_paint_selection_add_entry (GtkDPSPaintSelection * paintsel, gpointer data, gboolean g_free_data, gchar * name) { gint r; gint position; GtkDPSPaintSelectionEntry * entry; g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (paintsel->entries); entry = gtk_dps_paint_selection_entry_new(data, g_free_data, name); position = gtk_dps_paint_selection_entries_add(paintsel->entries, entry); gtk_dps_paint_selection_entry_set_position(entry, position); r = position%paintsel->columns; if (((position - r)/paintsel->columns + 1) > paintsel->rows) { paintsel->rows = ((position - r)/paintsel->columns + 1); gtk_dps_area_size(GTK_DPS_AREA(paintsel->dps_area), (paintsel->x_entry_width * paintsel->columns) + (paintsel->columns + 1)* paintsel->spacing, paintsel->x_entry_height * paintsel->rows + (paintsel->rows + 1) * paintsel->spacing); } gtk_signal_emit(GTK_OBJECT(paintsel), dps_paintsel_signals[ADD_ENTRY], entry, position); } void gtk_dps_paint_selection_remove_entry (GtkDPSPaintSelection * paintsel, gint position) { GtkDPSPaintSelectionEntry * entry; g_return_if_fail ( paintsel ); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (position > -1); entry = gtk_dps_paint_selection_entries_get(paintsel->entries, position); g_return_if_fail (entry); gtk_dps_paint_selection_entries_remove(paintsel->entries, entry); gtk_signal_emit(GTK_OBJECT(paintsel), dps_paintsel_signals[REMOVE_ENTRY], entry, position); gtk_dps_paint_selection_entry_free(entry); gtk_dps_paint_selection_entries_repsoit(paintsel->entries, paintsel); } static void gtk_dps_paint_selection_set_arg(GtkObject * object, GtkArg * arg, guint arg_id) { GtkDPSPaintSelection * paintsel; paintsel = GTK_DPS_PAINT_SELECTION(object); switch (arg_id) { case ARG_PAINT: gtk_dps_paint_selection_set_paint(paintsel, GTK_VALUE_INT(*arg)); break; default: break; } } static void gtk_dps_paint_selection_get_arg(GtkObject * object, GtkArg * arg, guint arg_id) { GtkDPSPaintSelection * paintsel; paintsel = GTK_DPS_PAINT_SELECTION(object); switch (arg_id) { case ARG_PAINT: GTK_VALUE_INT(*arg) = gtk_dps_paint_selection_get_paint(paintsel); break; default: arg->type = GTK_TYPE_INVALID; break; } } static void gtk_dps_paint_selection_destroy (GtkObject * object) { GtkDPSPaintSelection *paintsel; g_return_if_fail (object != NULL); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION (object)); paintsel = GTK_DPS_PAINT_SELECTION(object); gtk_dps_paint_selection_entries_free(paintsel->entries); paintsel->entries = NULL; if (GTK_OBJECT_CLASS (gtk_dps_paint_selection_parent_class)->destroy) (* GTK_OBJECT_CLASS (gtk_dps_paint_selection_parent_class)->destroy) (object); } static void gtk_dps_paint_selection_draw_lazy (GtkDPSArea *area, GdkRectangle *x_rectangle, GdkDPSRectangle *dps_rectangle, gpointer user_data) { gtk_dps_area_map_area_on_screen(area, dps_rectangle); } static void gtk_dps_paint_selection_coordtr_update(GtkDPSArea *area, GdkDPSCoordtr * coordtr, gpointer user_data) { gtk_dps_paint_selection_draw_entries(user_data); gtk_dps_paint_selection_draw_frames(user_data); } static void gtk_dps_paint_selection_button_release_event_dps(GtkDPSArea * area, GdkEventButton *event, GdkDPSPoint *dps_point, gpointer user_data) { gint position; GtkDPSPaintSelection * paintsel; g_return_if_fail (user_data ); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(user_data)); g_return_if_fail (event); g_return_if_fail (dps_point); paintsel = GTK_DPS_PAINT_SELECTION(user_data); if (event->button != 1) return ; position = gtk_dps_paint_selection_calc_position_from_point(paintsel, dps_point); if (position < 0) return ; /* out of range */ gtk_dps_paint_selection_set_paint(paintsel, position); } static void gtk_real_dps_paint_selection_paint_change(GtkDPSPaintSelection * paintsel, gint old, gint new) { GdkDPSRectangle rect_old; GdkDPSRectangle rect_new; g_return_if_fail (paintsel->paint == old); g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (new >= 0); g_return_if_fail (old >= 0); g_return_if_fail (new < gtk_dps_paint_selection_entries_count(paintsel->entries)); g_return_if_fail (old < gtk_dps_paint_selection_entries_count(paintsel->entries)); if (new == old) return ; paintsel->paint = new; rect_old = gtk_dps_paint_selection_calc_rectangle(paintsel, old); rect_new = gtk_dps_paint_selection_calc_rectangle(paintsel, new); gtk_dps_area_switch_context_pixmap(GTK_DPS_AREA(paintsel->dps_area), 0); gtk_dps_paint_selection_draw_frame(paintsel, &rect_old, FALSE); gtk_dps_paint_selection_draw_frame(paintsel, &rect_new, TRUE); gtk_dps_area_map_area_on_screen(GTK_DPS_AREA(paintsel->dps_area), NULL); } static void gtk_real_dps_paint_selection_add_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint position) { GdkDPSRectangle rect; if (!GTK_WIDGET_REALIZED(paintsel)) return; rect = gtk_dps_paint_selection_calc_rectangle(paintsel, position); gtk_dps_paint_selection_draw_entry(paintsel, &rect, entry); } GtkDPSPaintSelectionEntry* gtk_dps_paint_selection_get_entry (GtkDPSPaintSelection * paintsel, gint position) { g_return_val_if_fail (paintsel, NULL); g_return_val_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel), NULL); g_return_val_if_fail (position > -1, NULL); return gtk_dps_paint_selection_entries_get(paintsel->entries, position); } static void gtk_real_dps_paint_selection_draw_entry(GtkDPSPaintSelection * paintsel, DPSContext raw_ctxt, GdkDPSRectangle * rect, GtkDPSPaintSelectionEntry * entry) { /* Do nothing */ } static void gtk_real_dps_paint_selection_remove_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint position) { /* Do nothing */ } static void gtk_real_dps_paint_selection_reposit_entry(GtkDPSPaintSelection * paintsel, GtkDPSPaintSelectionEntry * entry, gint old, gint new) { /* Do nothing */ } static GtkDPSPaintSelectionEntries * gtk_dps_paint_selection_entries_new(void) { GtkDPSPaintSelectionEntries * entries = g_new(GtkDPSPaintSelectionEntries, 1); gtk_dps_paint_selection_entries_init(entries); return entries; } static void gtk_dps_paint_selection_entries_init(GtkDPSPaintSelectionEntries * entries) { entries->name = NULL; entries->paints = NULL; entries->n_paints = 0; } static gint gtk_dps_paint_selection_entries_add(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelectionEntry * entry) { entries->paints = g_slist_append(entries->paints, entry); entry->position = entries->n_paints++; return entry->position; } static gint gtk_dps_paint_selection_entries_count(GtkDPSPaintSelectionEntries * entries) { return entries->n_paints; } static void gtk_dps_paint_selection_entries_foreach(GtkDPSPaintSelectionEntries * entries, GFunc func, gpointer user_data) { g_return_if_fail (entries); g_return_if_fail (func); g_slist_foreach(entries->paints, func, user_data); } static GtkDPSPaintSelectionEntry * gtk_dps_paint_selection_entries_get(GtkDPSPaintSelectionEntries * entries, gint position) { GtkDPSPaintSelectionEntry * result; gint count; gint index; g_return_val_if_fail ( entries , NULL ); g_return_val_if_fail ( position > -1, NULL ); count = gtk_dps_paint_selection_entries_count(entries); index = count - position -1; result = g_slist_nth_data(entries->paints, index); g_return_val_if_fail (result->position == index, NULL); return result; } static void gtk_dps_paint_selection_entries_remove(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelectionEntry * entry) { g_return_if_fail ( entries ); g_return_if_fail ( entry ); entries->paints = g_slist_remove(entries->paints, entry); } static void gtk_dps_paint_selection_entries_repsoit(GtkDPSPaintSelectionEntries * entries, GtkDPSPaintSelection * paintsel) { gint i; GSList * list; GSList * tmp; GtkDPSPaintSelectionEntry * entry; gint old, new; g_return_if_fail ( entries ); g_return_if_fail ( paintsel ); g_return_if_fail ( GTK_IS_DPS_PAINT_SELECTION(paintsel)); list = g_slist_reverse(entries->paints); for (tmp = list, i = 0; tmp; tmp= g_slist_next(tmp), i++) { entry = (GtkDPSPaintSelectionEntry *)tmp->data; if (entry->position == i) continue ; new = i; old = entry->position; entry->position = new; gtk_signal_emit(GTK_OBJECT(paintsel), dps_paintsel_signals[REPOSIT_ENTRY], entry, old, new); } entries->n_paints = g_slist_length(list); entries->paints = g_slist_reverse(list); } static void gtk_dps_paint_selection_entries_free_callback(gpointer data, gpointer no_use); static void gtk_dps_paint_selection_entries_free(GtkDPSPaintSelectionEntries * entries) { g_slist_foreach(entries->paints, (GFunc)gtk_dps_paint_selection_entries_free_callback, NULL); g_slist_free(entries->paints); entries->paints = NULL; g_free(entries->name); entries->name = NULL; g_free(entries); entries->n_paints = 0; } static void gtk_dps_paint_selection_entries_free_callback(gpointer data, gpointer no_use) { GtkDPSPaintSelectionEntry * entry = data; gtk_dps_paint_selection_entry_free(entry); } static GdkDPSRectangle gtk_dps_paint_selection_calc_rectangle(GtkDPSPaintSelection * paintsel, gint position) { gint row, column; gfloat entry_width, entry_height; GdkDPSRectangle rect = {0.0, 0.0, 20.0, 20.0}; g_return_val_if_fail ( paintsel , rect); g_return_val_if_fail ( GTK_IS_DPS_PAINT_SELECTION(paintsel), rect); entry_width = gtk_dps_area_coordtr_width(GTK_DPS_AREA(paintsel->dps_area), GDK_DPS_TRDIR_X2DPS, (gfloat)paintsel->x_entry_width); entry_height = gtk_dps_area_coordtr_width(GTK_DPS_AREA(paintsel->dps_area), GDK_DPS_TRDIR_X2DPS, (gfloat)paintsel->x_entry_height); column = position%(paintsel->columns); rect.x = ((column + 1) * paintsel->spacing) + (column * entry_width); row = ((position - column)/paintsel->columns); row = (paintsel->rows - row) - 1; rect.y = ((row + 1)* paintsel->spacing) + (row * entry_height); rect.width = entry_width; rect.height = entry_height; return rect; } static gint gtk_dps_paint_selection_calc_position_from_point(GtkDPSPaintSelection * paintsel, GdkDPSPoint * dps_point) { GdkDPSRectangle rect; gint i; gint count = gtk_dps_paint_selection_entries_count(paintsel->entries); for (i = 0; i < count; i++) { rect = gtk_dps_paint_selection_calc_rectangle(paintsel, i); if (TRUE == gdk_dps_rectangle_contains_point(&rect, dps_point, TRUE)) break; } if (i == count) return -1; else return i; } static void gtk_dps_paint_selection_draw_entries_callback(gpointer data, gpointer user_data) { GdkDPSRectangle rect; GtkDPSPaintSelectionEntry * entry = data; GtkDPSPaintSelection * paintsel = GTK_DPS_PAINT_SELECTION(user_data); rect = gtk_dps_paint_selection_calc_rectangle(paintsel, entry->position); gtk_dps_paint_selection_draw_entry(paintsel, &rect, entry); } static void gtk_dps_paint_selection_draw_entries(GtkDPSPaintSelection * paintsel) { GtkDPSArea * area; g_return_if_fail ( paintsel ); g_return_if_fail ( GTK_IS_DPS_PAINT_SELECTION(paintsel) ); area = GTK_DPS_AREA(paintsel->dps_area); gtk_dps_widget_begin(area); DPSerasepage(raw_ctxt); gtk_dps_widget_end(); gtk_dps_paint_selection_entries_foreach(paintsel->entries, gtk_dps_paint_selection_draw_entries_callback, paintsel); } static void gtk_dps_paint_selection_draw_entry(GtkDPSPaintSelection * paintsel, GdkDPSRectangle * rect, GtkDPSPaintSelectionEntry * entry) { g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); gtk_dps_area_switch_context_pixmap(GTK_DPS_AREA(paintsel->dps_area), 1); gtk_dps_widget_begin(paintsel->dps_area); DPSgsave(raw_ctxt); DPSrectviewclip(raw_ctxt, rect->x, rect->y, rect->width, rect->height); if (entry->position != 0) gtk_signal_emit(GTK_OBJECT(paintsel), dps_paintsel_signals[DRAW_ENTRY], raw_ctxt, rect, entry); else { DPSsetrgbcolor(raw_ctxt, 1.0, 1.0, 1.0); DPSrectfill(raw_ctxt, rect->x, rect->y, rect->width, rect->height); DPSsetrgbcolor(raw_ctxt, 1.0, 0.0, 0.0); DPSsetlinewidth(raw_ctxt, paintsel->line_width); DPSmoveto(raw_ctxt, rect->x, rect->y); DPSlineto(raw_ctxt, rect->x + rect->width, rect->y + rect->height); DPSstroke(raw_ctxt); } DPSinitviewclip(raw_ctxt); DPSgrestore(raw_ctxt); gtk_dps_widget_end(); } static void gtk_dps_paint_selection_draw_frames(GtkDPSPaintSelection * paintsel) { gint i; GtkDPSArea * area; gint n_entries; GdkDPSRectangle rect; g_return_if_fail ( paintsel ); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); n_entries = gtk_dps_paint_selection_entries_count(paintsel->entries); area = GTK_DPS_AREA(paintsel->dps_area); gtk_dps_area_map_cache_on_area(area, NULL); gtk_dps_area_switch_context_pixmap(area, 0); for (i = 0; i < n_entries; i++) { if (paintsel->paint == i) continue; rect = gtk_dps_paint_selection_calc_rectangle(paintsel, i); gtk_dps_paint_selection_draw_frame(paintsel, &rect, FALSE); } rect = gtk_dps_paint_selection_calc_rectangle(paintsel, paintsel->paint); gtk_dps_paint_selection_draw_frame(paintsel, &rect, TRUE); } static void gtk_dps_paint_selection_draw_frame(GtkDPSPaintSelection * paintsel, GdkDPSRectangle * rect, gboolean currentp) { gfloat gray = 0.8; g_return_if_fail (paintsel); g_return_if_fail (GTK_IS_DPS_PAINT_SELECTION(paintsel)); g_return_if_fail (rect); gtk_dps_widget_begin(paintsel->dps_area); DPSgsave(raw_ctxt); DPSsetlinewidth(raw_ctxt, paintsel->line_width); if (currentp == TRUE) DPSsetrgbcolor(raw_ctxt, gray, gray, gray); else DPSsetrgbcolor(raw_ctxt, 0.0, 0.0, 0.0); DPSrectstroke(raw_ctxt, rect->x, rect->y, rect->width, rect->height); DPSgrestore(raw_ctxt); gtk_dps_widget_end(); } gint gtk_dps_paint_selection_get_paint_at(GtkDPSPaintSelection * paintsel, GdkDPSPoint * point) { return gtk_dps_paint_selection_calc_position_from_point(paintsel, point); } /* Entry */ static GtkDPSPaintSelectionEntry * gtk_dps_paint_selection_entry_new(gpointer *data, gboolean g_free_data, gchar * name) { GtkDPSPaintSelectionEntry * entry; entry = g_new(GtkDPSPaintSelectionEntry, 1); entry->data = data; entry->g_free_data = g_free_data; entry->name = g_strdup(name); entry->position = -1; return entry; } static void gtk_dps_paint_selection_entry_set_position(GtkDPSPaintSelectionEntry * entry, gint position) { entry->position = position; } static void gtk_dps_paint_selection_entry_free(GtkDPSPaintSelectionEntry * entry) { g_free(entry->name); entry->name = NULL; if (entry->g_free_data) g_free(entry->data); entry->data = NULL; g_free(entry); entry->position = -1; }