1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * \file gschem_preview.c
23 * \brief A widget for viewing a symbol or schematic
41 #define OVER_ZOOM_FACTOR 0.1
50 static GObjectClass
*preview_parent_class
= NULL
;
53 static void preview_zoom (GschemPreview
*preview
);
55 static void preview_class_init (GschemPreviewClass
*class);
56 static void preview_init (GschemPreview
*preview
);
57 static void preview_set_property (GObject
*object
,
61 static void preview_get_property (GObject
*object
,
65 static void preview_dispose (GObject
*self
);
68 /*! \brief create a new preview widget
73 return GTK_WIDGET (g_object_new (GSCHEM_TYPE_PREVIEW
, NULL
));
77 /*! \brief get the filename for the current page
80 preview_get_filename (GschemPreview
*preview
)
82 PAGE
*page
= gschem_page_view_get_page (GSCHEM_PAGE_VIEW (preview
));
84 g_return_val_if_fail (page
!= NULL
, "");
86 return page
->page_filename
;
90 /*! \brief Completes initialitation of the widget after realization.
91 * \par Function Description
92 * This function terminates the initialization of the preview widget
93 * after it has been realized.
95 * \param [in] widget The preview widget.
96 * \param [in] user_data Unused user data.
99 preview_callback_realize (GtkWidget
*widget
, gpointer user_data
)
101 g_return_if_fail (widget
!= NULL
);
103 gtk_widget_grab_focus (widget
);
104 gschem_page_view_zoom_extents (GSCHEM_PAGE_VIEW (widget
), NULL
);
108 /*! \brief Trigger deferred zoom and redraw preview widget.
111 preview_callback_expose_event (GtkWidget
*widget
,
115 GschemPreview
*preview
= GSCHEM_PREVIEW (widget
);
117 if (preview
->needs_zoom
) {
118 preview_zoom (preview
);
119 preview
->needs_zoom
= FALSE
;
122 return x_event_expose (GSCHEM_PAGE_VIEW (widget
), &event
->expose
, user_data
);
126 /*! \brief Handles the press on a mouse button.
127 * \par Function Description
128 * It handles the user inputs.
130 * Three action are available: zoom in, pan and zoom out on preview display.
132 * \param [in] widget The preview widget.
133 * \param [in] event The event structure.
134 * \param [in] user_data Unused user data.
135 * \returns FALSE to propagate the event further.
138 preview_callback_button_press (GtkWidget
*widget
,
139 GdkEventButton
*event
,
142 GschemPreview
*preview
= GSCHEM_PREVIEW (widget
);
143 GschemToplevel
*preview_w_current
= preview
->preview_w_current
;
146 if (!preview
->active
) {
150 switch (event
->button
) {
151 case 1: /* left mouse button: zoom in */
152 a_zoom (preview_w_current
,
153 GSCHEM_PAGE_VIEW (preview
),
156 gschem_page_view_invalidate_all (GSCHEM_PAGE_VIEW (widget
));
158 case 2: /* middle mouse button: pan */
159 if (!x_event_get_pointer_position(preview_w_current
, FALSE
, &wx
, &wy
))
161 gschem_page_view_pan (GSCHEM_PAGE_VIEW (preview
), wx
, wy
);
163 case 3: /* right mouse button: zoom out */
164 a_zoom (preview_w_current
,
165 GSCHEM_PAGE_VIEW (preview
),
168 gschem_page_view_invalidate_all (GSCHEM_PAGE_VIEW (widget
));
176 /*! \brief Updates the preview widget.
177 * \par Function Description
178 * This function updates the preview: if the preview is active and a
179 * filename has been given, it opens the file and displays
180 * it. Otherwise it displays a blank page.
182 * \param [in] preview The preview widget.
185 preview_update (GschemPreview
*preview
)
189 GschemPageView
*preview_view
= GSCHEM_PAGE_VIEW (preview
);
191 g_return_if_fail (preview_view
!= NULL
);
192 PAGE
*preview_page
= gschem_page_view_get_page (preview_view
);
194 if (preview_page
== NULL
) {
198 TOPLEVEL
*preview_toplevel
= preview_page
->toplevel
;
200 /* delete old preview */
201 s_page_delete_objects (preview_toplevel
, preview_page
);
203 if (preview
->active
) {
204 g_assert ((preview
->filename
== NULL
) || (preview
->buffer
== NULL
));
205 if (preview
->filename
!= NULL
) {
206 /* open up file in current page */
207 f_open_flags (preview_toplevel
, preview_page
,
209 F_OPEN_RC
| F_OPEN_RESTORE_CWD
, NULL
);
210 /* test value returned by f_open... - Fix me */
211 /* we should display something if there an error occured - Fix me */
213 if (preview
->buffer
!= NULL
) {
214 /* Load the data buffer */
215 GList
* objects
= o_read_buffer (preview_toplevel
,
216 NULL
, preview
->buffer
, -1,
217 _("Preview Buffer"), &err
);
220 s_page_append_list (preview_toplevel
, preview_page
,
224 s_page_append (preview_toplevel
, preview_page
,
225 o_text_new(preview_toplevel
, 2, 100, 100, LOWER_MIDDLE
, 0,
226 err
->message
, 10, VISIBLE
, SHOW_NAME_VALUE
));
232 if (gtk_widget_get_window (GTK_WIDGET (preview
)) != NULL
) {
233 preview_zoom (preview
);
234 preview
->needs_zoom
= FALSE
;
236 preview
->needs_zoom
= TRUE
;
240 preview_zoom (GschemPreview
*preview
)
242 GschemPageView
*preview_view
= GSCHEM_PAGE_VIEW (preview
);
243 PAGE
*preview_page
= gschem_page_view_get_page (preview_view
);
244 if (preview_page
== NULL
)
247 int left
, top
, right
, bottom
;
250 if (world_get_object_glist_bounds (preview_page
->toplevel
,
251 s_page_objects (preview_page
),
254 /* Clamp the canvas size to the extents of the page being previewed */
255 width
= right
- left
;
256 height
= bottom
- top
;
258 GschemPageGeometry
*geometry
= gschem_page_view_get_page_geometry (preview_view
);
259 geometry
->world_left
= left
- ((double)width
* OVER_ZOOM_FACTOR
);
260 geometry
->world_right
= right
+ ((double)width
* OVER_ZOOM_FACTOR
);
261 geometry
->world_top
= top
- ((double)height
* OVER_ZOOM_FACTOR
);
262 geometry
->world_bottom
= bottom
+ ((double)height
* OVER_ZOOM_FACTOR
);
265 /* display current page (possibly empty) */
266 gschem_page_view_zoom_extents (preview_view
, NULL
);
270 gschem_preview_get_type ()
272 static GType preview_type
= 0;
275 static const GTypeInfo preview_info
= {
276 sizeof(GschemPreviewClass
),
277 NULL
, /* base_init */
278 NULL
, /* base_finalize */
279 (GClassInitFunc
) preview_class_init
,
280 NULL
, /* class_finalize */
281 NULL
, /* class_data */
282 sizeof(GschemPreview
),
284 (GInstanceInitFunc
) preview_init
,
287 preview_type
= g_type_register_static (GSCHEM_TYPE_PAGE_VIEW
,
296 preview_class_init (GschemPreviewClass
*klass
)
298 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
300 preview_parent_class
= g_type_class_peek_parent (klass
);
302 gobject_class
->set_property
= preview_set_property
;
303 gobject_class
->get_property
= preview_get_property
;
304 gobject_class
->dispose
= preview_dispose
;
306 g_object_class_install_property (
307 gobject_class
, PROP_FILENAME
,
308 g_param_spec_string ("filename",
313 g_object_class_install_property (
314 gobject_class
, PROP_BUFFER
,
315 g_param_spec_string ("buffer",
320 g_object_class_install_property(
321 gobject_class
, PROP_ACTIVE
,
322 g_param_spec_boolean ("active",
333 preview_event_scroll (GtkWidget
*widget
,
334 GdkEventScroll
*event
,
335 GschemToplevel
*w_current
)
337 if (!GSCHEM_PREVIEW (widget
)->active
) {
340 return x_event_scroll (widget
, event
, GSCHEM_PREVIEW (widget
)->preview_w_current
);
344 preview_init (GschemPreview
*preview
)
347 gchar
*detailed_signal
;
349 } drawing_area_events
[] = {
350 { "realize", G_CALLBACK (preview_callback_realize
) },
351 { "expose_event", G_CALLBACK (preview_callback_expose_event
) },
352 { "button_press_event", G_CALLBACK (preview_callback_button_press
) },
353 { "configure_event", G_CALLBACK (x_event_configure
) },
354 { "scroll_event", G_CALLBACK (preview_event_scroll
) },
358 GschemToplevel
*preview_w_current
;
359 preview_w_current
= gschem_toplevel_new ();
360 gschem_toplevel_set_toplevel (preview_w_current
, s_toplevel_new ());
362 preview_w_current
->toplevel
->load_newer_backup_func
=
363 x_fileselect_load_backup
;
364 preview_w_current
->toplevel
->load_newer_backup_data
=
366 o_text_set_rendered_bounds_func (preview_w_current
->toplevel
,
367 o_text_get_rendered_bounds
,
370 i_vars_set (preview_w_current
);
372 /* be sure to turn off scrollbars */
373 preview_w_current
->scrollbars_flag
= FALSE
;
375 /* be sure to turn off the grid */
376 gschem_options_set_grid_mode (preview_w_current
->options
, GRID_MODE_NONE
);
378 /* preview_w_current windows don't have toolbars */
379 preview_w_current
->handleboxes
= FALSE
;
380 preview_w_current
->toolbars
= FALSE
;
382 preview_w_current
->drawing_area
= GTK_WIDGET (preview
);
383 preview
->preview_w_current
= preview_w_current
;
385 preview
->active
= FALSE
;
386 preview
->needs_zoom
= FALSE
;
387 preview
->filename
= NULL
;
388 preview
->buffer
= NULL
;
389 gschem_page_view_set_page (GSCHEM_PAGE_VIEW (preview
),
390 s_page_new (preview
->preview_w_current
->toplevel
,
393 gtk_widget_set_events (GTK_WIDGET (preview
),
395 GDK_POINTER_MOTION_MASK
|
396 GDK_BUTTON_PRESS_MASK
);
397 for (tmp
= drawing_area_events
; tmp
->detailed_signal
!= NULL
; tmp
++) {
398 g_signal_connect (GTK_WIDGET (preview
),
399 tmp
->detailed_signal
,
407 preview_set_property (GObject
*object
,
412 GschemPreview
*preview
= GSCHEM_PREVIEW (object
);
413 GschemToplevel
*preview_w_current
= preview
->preview_w_current
;
415 g_assert (preview_w_current
!= NULL
);
417 switch(property_id
) {
419 if (preview
->buffer
!= NULL
) {
420 g_free (preview
->buffer
);
421 preview
->buffer
= NULL
;
422 g_object_notify (object
, "buffer");
424 g_free (preview
->filename
);
425 preview
->filename
= g_strdup (g_value_get_string (value
));
429 if (preview
->filename
!= NULL
) {
430 g_free (preview
->filename
);
431 preview
->filename
= NULL
;
432 g_object_notify (object
, "filename");
434 g_free (preview
->buffer
);
435 preview
->buffer
= g_strdup (g_value_get_string (value
));
439 preview
->active
= g_value_get_boolean (value
);
440 preview_update (preview
);
443 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
449 preview_get_property (GObject
*object
,
454 GschemPreview
*preview
= GSCHEM_PREVIEW (object
);
456 switch(property_id
) {
458 g_value_set_string (value
, preview_get_filename (preview
));
462 g_value_set_boolean (value
, preview
->active
);
466 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
471 preview_dispose (GObject
*self
)
473 GschemPreview
*preview
= GSCHEM_PREVIEW (self
);
474 GschemToplevel
*preview_w_current
= preview
->preview_w_current
;
476 if (preview_w_current
!= NULL
) {
477 preview_w_current
->drawing_area
= NULL
;
479 gschem_toplevel_free (preview_w_current
);
481 preview
->preview_w_current
= NULL
;
484 G_OBJECT_CLASS (preview_parent_class
)->dispose (self
);