Updated copyright text/header in most source files.
[geda-gaf.git] / gschem / src / x_preview.c
blobceb04dadb241a039806e1f2a2b31806b79a0ec7d
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 #include <config.h>
22 #include <stdio.h>
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
33 #include <libgeda/libgeda.h>
35 #include "../include/globals.h"
36 #include "../include/prototype.h"
38 #ifdef HAVE_LIBDMALLOC
39 #include <dmalloc.h>
40 #endif
42 #include "../include/x_preview.h"
45 extern int mouse_x, mouse_y;
48 enum {
49 PROP_FILENAME=1,
50 PROP_ACTIVE
53 static GObjectClass *preview_parent_class = NULL;
56 static void preview_class_init (PreviewClass *class);
57 static void preview_init (Preview *preview);
58 static void preview_set_property (GObject *object,
59 guint property_id,
60 const GValue *value,
61 GParamSpec *pspec);
62 static void preview_get_property (GObject *object,
63 guint property_id,
64 GValue *value,
65 GParamSpec *pspec);
66 static void preview_dispose (GObject *self);
69 /*! \brief Completes initialitation of the widget after realization.
70 * \par Function Description
71 * This function terminates the initialization of preview's toplevel
72 * environment after the widget has been realized.
74 * It creates a preview page in the toplevel environment.
76 * \param [in] widget The preview widget.
77 * \param [in] user_data Unused user data.
79 static void
80 preview_callback_realize (GtkWidget *widget,
81 gpointer user_data)
83 Preview *preview = PREVIEW (widget);
84 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
85 PAGE *preview_page;
87 preview_toplevel->window = preview_toplevel->drawing_area->window;
88 gtk_widget_grab_focus (preview_toplevel->drawing_area);
90 preview_toplevel->backingstore = gdk_pixmap_new (
91 preview_toplevel->window,
92 preview_toplevel->drawing_area->allocation.width,
93 preview_toplevel->drawing_area->allocation.height, -1);
95 x_window_setup_gc (preview_toplevel);
97 preview_page = s_page_new (preview_toplevel, "unknown");
98 s_page_goto (preview_toplevel, preview_page);
100 i_vars_set (preview_toplevel);
102 /* be sure to turn off the grid */
103 preview_toplevel->grid = FALSE;
105 /* preview_toplevel windows don't have toolbars */
106 preview_toplevel->handleboxes = FALSE;
107 preview_toplevel->toolbars = FALSE;
109 x_repaint_background(preview_toplevel);
111 preview_toplevel->DONT_RECALC = 0;
112 preview_toplevel->DONT_RESIZE = 0;
113 preview_toplevel->DONT_REDRAW = 0;
115 a_zoom_extents(preview_toplevel,
116 preview_page->object_head,
117 A_PAN_DONT_REDRAW);
119 o_redraw_all(preview_toplevel);
123 /*! \brief Redraws the view when widget is exposed.
124 * \par Function Description
125 * It redraws the preview pixmap every time the widget is exposed.
127 * \param [in] widget The preview widget.
128 * \param [in] event The event structure.
129 * \param [in] user_data Unused user data.
130 * \returns FALSE to propagate the event further.
132 static gboolean
133 preview_callback_expose (GtkWidget *widget,
134 GdkEventExpose *event,
135 gpointer user_data)
137 Preview *preview = PREVIEW (widget);
138 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
140 gdk_draw_pixmap(widget->window,
141 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
142 preview_toplevel->backingstore,
143 event->area.x, event->area.y,
144 event->area.x, event->area.y,
145 event->area.width, event->area.height);
147 return FALSE;
150 /*! \brief Handles the press on a mouse button.
151 * \par Function Description
152 * It handles the user inputs.
154 * Three action are available: zoom in, pan and zoom out on preview display.
156 * \param [in] widget The preview widget.
157 * \param [in] event The event structure.
158 * \param [in] user_data Unused user data.
159 * \returns FALSE to propagate the event further.
161 static gboolean
162 preview_callback_button_press (GtkWidget *widget,
163 GdkEventButton *event,
164 gpointer user_data)
166 Preview *preview = PREVIEW (widget);
167 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
169 if (!preview->active || preview->filename == NULL) {
170 return TRUE;
173 switch (event->button) {
174 case 1: /* left mouse button: zoom in */
175 a_zoom (preview_toplevel, ZOOM_IN, HOTKEY, 0);
176 o_redraw_all_fast (preview_toplevel);
177 break;
178 case 2: /* middle mouse button: pan */
179 a_pan (preview_toplevel, mouse_x, mouse_y);
180 break;
181 case 3: /* right mouse button: zoom out */
182 a_zoom (preview_toplevel, ZOOM_OUT, HOTKEY, 0);
183 o_redraw_all_fast (preview_toplevel);
184 break;
187 return FALSE;
190 /*! \brief Handles the displacement of the pointer.
191 * \par Function Description
192 * This function temporary saves the position of the mouse pointer
193 * over the preview widget.
195 * This position can be later used when the user press a button of
196 * the mouse (see <B>preview_callback_button_press()</B>).
198 * \param [in] widget The preview widget.
199 * \param [in] event The event structure.
200 * \param [in] user_data Unused user data.
201 * \returns FALSE to propagate the event further.
203 static gboolean
204 preview_callback_motion_notify (GtkWidget *widget,
205 GdkEventMotion *event,
206 gpointer user_data)
208 Preview *preview = PREVIEW (widget);
210 if (!preview->active || preview->filename == NULL) {
211 return TRUE;
214 mouse_x = (int)event->x;
215 mouse_y = (int)event->y;
217 return FALSE;
220 /*! \brief Updates the preview widget.
221 * \par Function Description
222 * This function update the preview: if the preview is active and a
223 * filename has been given, it opens the file and display
224 * it. Otherwise it display a blank page.
226 * \param [in] preview The preview widget.
228 static void
229 preview_update (Preview *preview)
231 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
233 if (preview_toplevel->page_current == NULL) {
234 return;
237 /* delete old preview, create new page */
238 /* it would be better to just resets current page - Fix me */
239 s_page_delete (preview_toplevel, preview_toplevel->page_current);
240 s_page_goto (preview_toplevel, s_page_new (preview_toplevel, "preview"));
242 if (preview->active && preview->filename != NULL) {
243 /* open up file in current page */
244 f_open (preview_toplevel, preview->filename);
245 /* test value returned by f_open... - Fix me */
246 /* we should display something if there an error occured - Fix me */
249 /* display current page (possibly empty) */
250 a_zoom_extents (preview_toplevel,
251 preview_toplevel->page_current->object_head,
252 A_PAN_DONT_REDRAW);
253 o_redraw_all (preview_toplevel);
257 GType
258 preview_get_type ()
260 static GType preview_type = 0;
262 if (!preview_type) {
263 static const GTypeInfo preview_info = {
264 sizeof(PreviewClass),
265 NULL, /* base_init */
266 NULL, /* base_finalize */
267 (GClassInitFunc) preview_class_init,
268 NULL, /* class_finalize */
269 NULL, /* class_data */
270 sizeof(Preview),
271 0, /* n_preallocs */
272 (GInstanceInitFunc) preview_init,
275 preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA,
276 "Preview",
277 &preview_info, 0);
280 return preview_type;
283 static void
284 preview_class_init (PreviewClass *klass)
286 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
288 preview_parent_class = g_type_class_peek_parent (klass);
290 gobject_class->set_property = preview_set_property;
291 gobject_class->get_property = preview_get_property;
292 gobject_class->dispose = preview_dispose;
294 g_object_class_install_property (
295 gobject_class, PROP_FILENAME,
296 g_param_spec_string ("filename",
299 NULL,
300 G_PARAM_READWRITE));
301 g_object_class_install_property(
302 gobject_class, PROP_ACTIVE,
303 g_param_spec_boolean ("active",
306 FALSE,
307 G_PARAM_READWRITE));
312 static void
313 preview_init (Preview *preview)
315 struct event_reg_t {
316 gchar *detailed_signal;
317 GCallback c_handler;
318 } drawing_area_events[] = {
319 { "realize", G_CALLBACK (preview_callback_realize) },
320 { "expose_event", G_CALLBACK (preview_callback_expose) },
321 { "button_press_event", G_CALLBACK (preview_callback_button_press) },
322 { "motion_notify_event", G_CALLBACK (preview_callback_motion_notify) },
323 { NULL, NULL }
324 }, *tmp;
325 TOPLEVEL *preview_toplevel;
327 preview_toplevel = s_toplevel_new ();
329 preview_toplevel->init_left = 0;
330 preview_toplevel->init_top = 0;
331 preview_toplevel->init_right = WIDTH_C;
332 preview_toplevel->init_bottom = HEIGHT_C;
333 preview_toplevel->width = 160;
334 preview_toplevel->height = 120;
335 preview_toplevel->win_width = preview_toplevel->width;
336 preview_toplevel->win_height = preview_toplevel->height;
337 /* be sure to turn off scrollbars */
338 preview_toplevel->scrollbars_flag = FALSE;
340 preview_toplevel->drawing_area = GTK_WIDGET (preview);
341 preview->preview_toplevel = preview_toplevel;
343 g_object_set (GTK_WIDGET (preview),
344 "width-request", preview_toplevel->width,
345 "height-request", preview_toplevel->height,
346 NULL);
348 preview->active = FALSE;
349 preview->filename = NULL;
351 gtk_widget_set_events (GTK_WIDGET (preview),
352 GDK_EXPOSURE_MASK |
353 GDK_POINTER_MOTION_MASK |
354 GDK_BUTTON_PRESS_MASK);
355 for (tmp = drawing_area_events; tmp->detailed_signal != NULL; tmp++) {
356 g_signal_connect (preview,
357 tmp->detailed_signal,
358 tmp->c_handler,
359 NULL);
364 static void
365 preview_set_property (GObject *object,
366 guint property_id,
367 const GValue *value,
368 GParamSpec *pspec)
370 Preview *preview = PREVIEW (object);
371 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
373 g_assert (preview_toplevel != NULL);
375 switch(property_id) {
376 case PROP_FILENAME:
377 g_free (preview->filename);
378 preview->filename = g_strdup (g_value_get_string (value));
379 if (preview->active) preview_update (preview);
380 break;
381 case PROP_ACTIVE:
382 preview->active = g_value_get_boolean (value);
383 preview_update (preview);
384 break;
385 default:
386 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
391 static void
392 preview_get_property (GObject *object,
393 guint property_id,
394 GValue *value,
395 GParamSpec *pspec)
397 Preview *preview = PREVIEW (object);
398 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
400 switch(property_id) {
401 case PROP_FILENAME:
402 g_assert (preview_toplevel != NULL);
403 /* return the filename of the current page in toplevel */
404 g_value_set_string (value,
405 preview_toplevel->page_current->page_filename);
406 break;
407 case PROP_ACTIVE:
408 g_value_set_boolean (value, preview->active);
409 break;
410 default:
411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
416 static void
417 preview_dispose (GObject *self)
419 Preview *preview = PREVIEW (self);
420 TOPLEVEL *preview_toplevel = preview->preview_toplevel;
422 if (preview_toplevel != NULL) {
423 preview_toplevel->drawing_area = NULL;
425 o_attrib_free_current (preview_toplevel);
426 o_complex_free_filename (preview_toplevel);
428 if (preview_toplevel->backingstore) {
429 gdk_pixmap_unref (preview_toplevel->backingstore);
432 x_window_free_gc (preview_toplevel);
434 s_toplevel_delete (preview_toplevel);
436 preview->preview_toplevel = NULL;
439 G_OBJECT_CLASS (preview_parent_class)->dispose (self);