Text samples
[dia.git] / app / linewidth_area.c
blobeb35d1c71819e82d1db19fe9210586a15af27da7
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include "linewidth_area.h"
24 #include "attributes.h"
25 #include "persistence.h"
26 #include "interface.h"
27 #include "intl.h"
29 #if !defined(rint)
30 # include <math.h>
31 # define rint(x) floor ((x) + 0.5)
32 #endif
34 #define BASE_WIDTH 0.05
35 #define PIXELS_BETWEEN_LINES 6
36 #define NUMLINES 5
38 #define X_OFFSET(i) (PIXELS_BETWEEN_LINES*(i)+((i)-1)*(i)/2)
40 #define AREA_WIDTH X_OFFSET(NUMLINES+1)
41 #define AREA_HEIGHT 42
43 static void linewidth_create_dialog(void);
45 static int active_linewidth = 2;
46 static GdkGC *linewidth_area_gc = NULL;
47 static GdkPixmap *linewidth_area_pixmap = NULL;
49 static GtkWidget *linewidth_area_widget = NULL;
50 static GtkWidget *linewidth_dialog = NULL;
51 static GtkWidget *linewidth_button = NULL;
53 static int
54 linewidth_area_target (int x, int y)
56 int i;
57 int x_offs;
58 for (i=1;i<=NUMLINES;i++) {
59 x_offs = X_OFFSET(i);
60 if ((x>=x_offs-PIXELS_BETWEEN_LINES/2) &&
61 (x<x_offs+i+PIXELS_BETWEEN_LINES/2))
62 return i;
64 return 0;
67 static void
68 linewidth_area_draw (GtkWidget *linewidth_area)
70 GdkColor *win_bg;
71 GdkColor line;
72 int width, height;
73 int i;
74 int x_offs;
76 if (!linewidth_area_pixmap) /* we haven't gotten initial expose yet,
77 * no point in drawing anything */
78 return;
81 if (!linewidth_area_gc) {
82 linewidth_area_gc = gdk_gc_new (linewidth_area_pixmap);
83 gdk_gc_set_line_attributes(linewidth_area_gc, 1,
84 GDK_LINE_ON_OFF_DASH,
85 GDK_CAP_BUTT,
86 GDK_JOIN_MITER);
89 gdk_window_get_size (linewidth_area_pixmap, &width, &height);
91 win_bg = &(linewidth_area->style->bg[GTK_STATE_NORMAL]);
92 line = color_gdk_black;
94 gdk_gc_set_foreground (linewidth_area_gc, win_bg);
95 gdk_draw_rectangle (linewidth_area_pixmap, linewidth_area_gc, 1,
96 0, 0, width, height);
98 gdk_gc_set_foreground (linewidth_area_gc, &line);
100 for (i=0;i<=NUMLINES;i++) {
101 x_offs = X_OFFSET(i);
103 gdk_draw_rectangle (linewidth_area_pixmap, linewidth_area_gc, 1,
104 x_offs, 2, i, height-4);
108 if (active_linewidth != 0) {
109 gdk_draw_rectangle (linewidth_area_pixmap, linewidth_area_gc, 0,
110 X_OFFSET(active_linewidth)-2, 0,
111 active_linewidth+4, height-1);
114 gdk_draw_pixmap (linewidth_area->window, linewidth_area_gc, linewidth_area_pixmap,
115 0, 0, 0, 0, width, height);
118 static gint
119 linewidth_area_events (GtkWidget *widget,
120 GdkEvent *event)
122 GdkEventButton *bevent;
123 GdkEventConfigure *cevent;
124 int target;
126 switch (event->type)
128 case GDK_CONFIGURE:
129 cevent = (GdkEventConfigure *) event;
130 if (cevent->width > 1) {
131 linewidth_area_pixmap = gdk_pixmap_new (widget->window,
132 cevent->width,
133 cevent->height, -1);
135 break;
136 case GDK_EXPOSE:
137 linewidth_area_draw (linewidth_area_widget);
138 break;
140 case GDK_BUTTON_PRESS:
141 bevent = (GdkEventButton *) event;
142 if (bevent->button == 1) {
143 target = linewidth_area_target (bevent->x, bevent->y);
145 if (target != 0) {
146 active_linewidth = target;
147 linewidth_area_draw(linewidth_area_widget);
148 attributes_set_default_linewidth(BASE_WIDTH*(target-1));
151 break;
153 case GDK_2BUTTON_PRESS:
154 if (linewidth_dialog == NULL)
155 linewidth_create_dialog();
156 else
157 gtk_widget_grab_focus(linewidth_button);
158 gtk_spin_button_set_value(GTK_SPIN_BUTTON(linewidth_button), attributes_get_default_linewidth());
160 gtk_widget_show(linewidth_dialog);
161 break;
163 default:
164 break;
167 return FALSE;
171 static int
172 linewidth_number_from_width(real width)
174 if (fabs(width/BASE_WIDTH-rint(width/BASE_WIDTH)) > 0.0005 ||
175 (width/BASE_WIDTH > NUMLINES)) {
176 return 0;
177 } else {
178 return width/BASE_WIDTH+1.0005;
182 GtkWidget *
183 linewidth_area_create (void)
185 GtkWidget *linewidth_area;
186 GtkWidget *event_box;
188 attributes_set_default_linewidth(persistence_register_real("linewidth", 0.1));
189 active_linewidth = linewidth_number_from_width(attributes_get_default_linewidth());
191 event_box = gtk_event_box_new();
192 linewidth_area = gtk_drawing_area_new ();
193 gtk_drawing_area_size (GTK_DRAWING_AREA (linewidth_area),
194 AREA_WIDTH, AREA_HEIGHT);
195 gtk_widget_set_events (linewidth_area, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
196 g_signal_connect (GTK_OBJECT (linewidth_area), "event",
197 G_CALLBACK(linewidth_area_events),
198 NULL);
200 linewidth_area_widget = linewidth_area;
202 gtk_container_add(GTK_CONTAINER(event_box), linewidth_area);
203 gtk_widget_show(linewidth_area);
204 return event_box;
207 static void
208 get_current_line_width() {
209 float newvalue = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(linewidth_button));
210 active_linewidth = linewidth_number_from_width(newvalue);
211 linewidth_area_draw(GTK_WIDGET(linewidth_area_widget));
212 attributes_set_default_linewidth(newvalue);
215 static void
216 linewidth_dialog_respond(GtkWidget *widget, gint response_id, gpointer data)
218 if (response_id == GTK_RESPONSE_OK) {
219 get_current_line_width();
221 gtk_widget_hide(linewidth_dialog);
224 static void
225 linewidth_dialog_ok(GtkWidget *widget, gpointer data)
227 gtk_dialog_response(GTK_DIALOG(linewidth_dialog), GTK_RESPONSE_OK);
230 /* Crashes with gtk_widget_destroyed, so use this instead */
231 static void
232 dialog_destroyed(GtkWidget *widget, gpointer data)
234 GtkWidget **wid = (GtkWidget**)data;
235 if (wid) *wid = NULL;
238 static void
239 linewidth_create_dialog()
241 GtkWidget *hbox;
242 GtkWidget *label;
243 GtkAdjustment *adj;
245 linewidth_dialog = gtk_dialog_new_with_buttons(
246 _("Line width"), GTK_WINDOW(interface_get_toolbox_shell()),
248 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
249 GTK_STOCK_OK, GTK_RESPONSE_OK,
250 NULL);
252 gtk_dialog_set_default_response (GTK_DIALOG(linewidth_dialog), GTK_RESPONSE_OK);
253 gtk_window_set_role (GTK_WINDOW (linewidth_dialog), "linewidth_window");
254 gtk_window_set_resizable (GTK_WINDOW (linewidth_dialog), TRUE);
255 gtk_container_set_border_width (GTK_CONTAINER (linewidth_dialog), 2);
257 hbox = gtk_hbox_new(FALSE, 5);
258 label = gtk_label_new(_("Line width:"));
259 gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
260 gtk_widget_show (label);
261 adj = (GtkAdjustment *) gtk_adjustment_new(0.1, 0.00, 10.0, 0.01, 0.05, 0.0);
262 linewidth_button = gtk_spin_button_new(adj, attributes_get_default_linewidth(), 2);
263 gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(linewidth_button), TRUE);
264 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(linewidth_button), TRUE);
265 gtk_box_pack_start(GTK_BOX (hbox), linewidth_button, TRUE, TRUE, 0);
266 gtk_widget_show (linewidth_button);
267 gtk_widget_show(hbox);
268 gtk_box_pack_start (GTK_BOX(GTK_DIALOG (linewidth_dialog)->vbox), hbox, TRUE, TRUE, 0);
270 gtk_widget_show (linewidth_button);
272 g_signal_connect(G_OBJECT (linewidth_dialog), "response",
273 G_CALLBACK (linewidth_dialog_respond), NULL);
274 g_signal_connect_after(G_OBJECT (linewidth_button), "activate",
275 G_CALLBACK (linewidth_dialog_ok), NULL);
277 g_signal_connect (GTK_OBJECT (linewidth_dialog), "delete_event",
278 G_CALLBACK(gtk_widget_hide), NULL);
279 g_signal_connect (GTK_OBJECT (linewidth_dialog), "destroy",
280 G_CALLBACK(dialog_destroyed), &linewidth_dialog);
282 persistence_register_window (GTK_WINDOW (linewidth_dialog));