gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 00022 #include <stdio.h> 00023 #ifdef HAVE_STDLIB_H 00024 #include <stdlib.h> 00025 #endif 00026 #ifdef HAVE_STRING_H 00027 #include <string.h> 00028 #endif 00029 #ifdef HAVE_UNISTD_H 00030 #include <unistd.h> 00031 #endif 00032 00033 #include "gschem.h" 00034 00035 #ifdef HAVE_LIBDMALLOC 00036 #include <dmalloc.h> 00037 #endif 00038 00039 #define OVER_ZOOM_FACTOR 0.1 00040 00041 00042 enum { 00043 PROP_FILENAME=1, 00044 PROP_BUFFER, 00045 PROP_ACTIVE 00046 }; 00047 00048 static GObjectClass *preview_parent_class = NULL; 00049 00050 00051 static void preview_class_init (PreviewClass *class); 00052 static void preview_init (Preview *preview); 00053 static void preview_set_property (GObject *object, 00054 guint property_id, 00055 const GValue *value, 00056 GParamSpec *pspec); 00057 static void preview_get_property (GObject *object, 00058 guint property_id, 00059 GValue *value, 00060 GParamSpec *pspec); 00061 static void preview_dispose (GObject *self); 00062 00073 static void 00074 preview_callback_realize (GtkWidget *widget, 00075 gpointer user_data) 00076 { 00077 Preview *preview = PREVIEW (widget); 00078 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00079 TOPLEVEL *preview_toplevel = preview_w_current->toplevel; 00080 PAGE *preview_page; 00081 00082 preview_w_current->window = preview_w_current->drawing_area->window; 00083 gtk_widget_grab_focus (preview_w_current->drawing_area); 00084 00085 preview_toplevel->width = preview_w_current->drawing_area->allocation.width; 00086 preview_toplevel->height = preview_w_current->drawing_area->allocation.height; 00087 preview_w_current->win_width = preview_toplevel->width; 00088 preview_w_current->win_height = preview_toplevel->height; 00089 00090 preview_w_current->drawable = preview_w_current->window; 00091 00092 x_window_setup_gc (preview_w_current); 00093 00094 preview_page = s_page_new (preview_toplevel, "unknown"); 00095 s_page_goto (preview_toplevel, preview_page); 00096 00097 a_zoom_extents(preview_w_current, 00098 s_page_objects (preview_page), 00099 A_PAN_DONT_REDRAW); 00100 00101 o_invalidate_all (preview_w_current); 00102 00103 } 00104 00114 static gboolean 00115 preview_callback_expose (GtkWidget *widget, 00116 GdkEventExpose *event, 00117 gpointer user_data) 00118 { 00119 Preview *preview = PREVIEW (widget); 00120 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00121 GdkRectangle *rectangles; 00122 int n_rectangles; 00123 cairo_t *save_cr; 00124 PangoLayout *save_pl; 00125 00126 save_cr = preview_w_current->cr; 00127 save_pl = preview_w_current->pl; 00128 00129 preview_w_current->cr = gdk_cairo_create (widget->window); 00130 preview_w_current->pl = pango_cairo_create_layout (preview_w_current->cr); 00131 00132 gdk_region_get_rectangles (event->region, &rectangles, &n_rectangles); 00133 o_redraw_rects (preview_w_current, rectangles, n_rectangles); 00134 g_free (rectangles); 00135 00136 g_object_unref (preview_w_current->pl); 00137 cairo_destroy (preview_w_current->cr); 00138 00139 preview_w_current->cr = save_cr; 00140 preview_w_current->pl = save_pl; 00141 00142 return FALSE; 00143 } 00144 00156 static gboolean 00157 preview_callback_button_press (GtkWidget *widget, 00158 GdkEventButton *event, 00159 gpointer user_data) 00160 { 00161 Preview *preview = PREVIEW (widget); 00162 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00163 gint wx, wy; 00164 00165 if (!preview->active) { 00166 return TRUE; 00167 } 00168 00169 switch (event->button) { 00170 case 1: /* left mouse button: zoom in */ 00171 a_zoom (preview_w_current, ZOOM_IN, HOTKEY, 00172 A_PAN_DONT_REDRAW); 00173 o_invalidate_all (preview_w_current); 00174 break; 00175 case 2: /* middle mouse button: pan */ 00176 if (!x_event_get_pointer_position(preview_w_current, FALSE, &wx, &wy)) 00177 return FALSE; 00178 a_pan (preview_w_current, wx, wy); 00179 break; 00180 case 3: /* right mouse button: zoom out */ 00181 a_zoom (preview_w_current, ZOOM_OUT, HOTKEY, 00182 A_PAN_DONT_REDRAW); 00183 o_invalidate_all (preview_w_current); 00184 break; 00185 } 00186 00187 return FALSE; 00188 } 00189 00190 00199 static void 00200 preview_update (Preview *preview) 00201 { 00202 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00203 TOPLEVEL *preview_toplevel = preview_w_current->toplevel; 00204 int left, top, right, bottom; 00205 int width, height; 00206 GError * err = NULL; 00207 00208 if (preview_toplevel->page_current == NULL) { 00209 return; 00210 } 00211 00212 /* delete old preview, create new page */ 00213 /* it would be better to just resets current page - Fix me */ 00214 s_page_delete (preview_toplevel, preview_toplevel->page_current); 00215 s_page_goto (preview_toplevel, s_page_new (preview_toplevel, "preview")); 00216 00217 if (preview->active) { 00218 g_assert ((preview->filename == NULL) || (preview->buffer == NULL)); 00219 if (preview->filename != NULL) { 00220 /* open up file in current page */ 00221 f_open_flags (preview_toplevel, preview_toplevel->page_current, 00222 preview->filename, 00223 F_OPEN_RC | F_OPEN_RESTORE_CWD, NULL); 00224 /* test value returned by f_open... - Fix me */ 00225 /* we should display something if there an error occured - Fix me */ 00226 } 00227 if (preview->buffer != NULL) { 00228 /* Load the data buffer */ 00229 GList * objects = o_read_buffer (preview_toplevel, 00230 NULL, preview->buffer, -1, 00231 _("Preview Buffer"), &err); 00232 00233 if (err == NULL) { 00234 s_page_append_list (preview_toplevel, preview_toplevel->page_current, 00235 objects); 00236 } 00237 else { 00238 s_page_append (preview_toplevel, preview_toplevel->page_current, 00239 o_text_new(preview_toplevel, OBJ_TEXT, 2, 100, 100, LOWER_MIDDLE, 0, 00240 err->message, 10, VISIBLE, SHOW_NAME_VALUE)); 00241 g_error_free(err); 00242 } 00243 } 00244 } 00245 00246 if (world_get_object_glist_bounds (preview_toplevel, 00247 s_page_objects (preview_toplevel->page_current), 00248 &left, &top, 00249 &right, &bottom)) { 00250 /* Clamp the canvas size to the extents of the page being previewed */ 00251 width = right - left; 00252 height = bottom - top; 00253 preview_toplevel->init_left = left - ((double)width * OVER_ZOOM_FACTOR); 00254 preview_toplevel->init_right = right + ((double)width * OVER_ZOOM_FACTOR); 00255 preview_toplevel->init_top = top - ((double)height * OVER_ZOOM_FACTOR); 00256 preview_toplevel->init_bottom = bottom + ((double)height * OVER_ZOOM_FACTOR); 00257 } 00258 00259 /* display current page (possibly empty) */ 00260 a_zoom_extents (preview_w_current, 00261 s_page_objects (preview_toplevel->page_current), 00262 A_PAN_DONT_REDRAW); 00263 o_invalidate_all (preview_w_current); 00264 00265 } 00266 00267 GType 00268 preview_get_type () 00269 { 00270 static GType preview_type = 0; 00271 00272 if (!preview_type) { 00273 static const GTypeInfo preview_info = { 00274 sizeof(PreviewClass), 00275 NULL, /* base_init */ 00276 NULL, /* base_finalize */ 00277 (GClassInitFunc) preview_class_init, 00278 NULL, /* class_finalize */ 00279 NULL, /* class_data */ 00280 sizeof(Preview), 00281 0, /* n_preallocs */ 00282 (GInstanceInitFunc) preview_init, 00283 }; 00284 00285 preview_type = g_type_register_static (GTK_TYPE_DRAWING_AREA, 00286 "Preview", 00287 &preview_info, 0); 00288 } 00289 00290 return preview_type; 00291 } 00292 00293 static void 00294 preview_class_init (PreviewClass *klass) 00295 { 00296 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 00297 00298 preview_parent_class = g_type_class_peek_parent (klass); 00299 00300 gobject_class->set_property = preview_set_property; 00301 gobject_class->get_property = preview_get_property; 00302 gobject_class->dispose = preview_dispose; 00303 00304 g_object_class_install_property ( 00305 gobject_class, PROP_FILENAME, 00306 g_param_spec_string ("filename", 00307 "", 00308 "", 00309 NULL, 00310 G_PARAM_READWRITE)); 00311 g_object_class_install_property ( 00312 gobject_class, PROP_BUFFER, 00313 g_param_spec_string ("buffer", 00314 "", 00315 "", 00316 NULL, 00317 G_PARAM_WRITABLE)); 00318 g_object_class_install_property( 00319 gobject_class, PROP_ACTIVE, 00320 g_param_spec_boolean ("active", 00321 "", 00322 "", 00323 FALSE, 00324 G_PARAM_READWRITE)); 00325 00326 00327 } 00328 00329 static gboolean 00330 preview_event_configure (GtkWidget *widget, 00331 GdkEventConfigure *event, 00332 gpointer user_data) 00333 { 00334 gboolean retval; 00335 GSCHEM_TOPLEVEL *preview_w_current = PREVIEW (widget)->preview_w_current; 00336 PAGE *preview_page = preview_w_current->toplevel->page_current; 00337 00338 retval = x_event_configure (widget, event, preview_w_current); 00339 if (preview_page != NULL) { 00340 a_zoom_extents(preview_w_current, s_page_objects (preview_page), 0); 00341 } 00342 return retval; 00343 } 00344 00345 00346 static gboolean 00347 preview_event_scroll (GtkWidget *widget, 00348 GdkEventScroll *event, 00349 GSCHEM_TOPLEVEL *w_current) 00350 { 00351 if (!PREVIEW (widget)->active) { 00352 return TRUE; 00353 } 00354 return x_event_scroll (widget, event, PREVIEW (widget)->preview_w_current); 00355 } 00356 00357 static void 00358 preview_init (Preview *preview) 00359 { 00360 struct event_reg_t { 00361 gchar *detailed_signal; 00362 GCallback c_handler; 00363 } drawing_area_events[] = { 00364 { "realize", G_CALLBACK (preview_callback_realize) }, 00365 { "expose_event", G_CALLBACK (preview_callback_expose) }, 00366 { "button_press_event", G_CALLBACK (preview_callback_button_press) }, 00367 { "configure_event", G_CALLBACK (preview_event_configure) }, 00368 { "scroll_event", G_CALLBACK (preview_event_scroll) }, 00369 { NULL, NULL } 00370 }, *tmp; 00371 GSCHEM_TOPLEVEL *preview_w_current; 00372 preview_w_current = gschem_toplevel_new (); 00373 preview_w_current->toplevel = s_toplevel_new (); 00374 00375 preview_w_current->toplevel->load_newer_backup_func = 00376 x_fileselect_load_backup; 00377 preview_w_current->toplevel->load_newer_backup_data = 00378 preview_w_current; 00379 o_text_set_rendered_bounds_func (preview_w_current->toplevel, 00380 o_text_get_rendered_bounds, 00381 preview_w_current); 00382 00383 o_add_change_notify (preview_w_current->toplevel, 00384 (ChangeNotifyFunc) o_invalidate, 00385 (ChangeNotifyFunc) o_invalidate, 00386 preview_w_current); 00387 00388 i_vars_set (preview_w_current); 00389 00390 /* be sure to turn off scrollbars */ 00391 preview_w_current->scrollbars_flag = FALSE; 00392 00393 /* be sure to turn off the grid */ 00394 preview_w_current->grid = FALSE; 00395 00396 /* preview_w_current windows don't have toolbars */ 00397 preview_w_current->handleboxes = FALSE; 00398 preview_w_current->toolbars = FALSE; 00399 00400 preview_w_current->toplevel->width = 160; 00401 preview_w_current->toplevel->height = 120; 00402 preview_w_current->win_width = preview_w_current->toplevel->width; 00403 preview_w_current->win_height = preview_w_current->toplevel->height; 00404 00405 preview_w_current->drawing_area = GTK_WIDGET (preview); 00406 preview->preview_w_current = preview_w_current; 00407 00408 g_object_set (GTK_WIDGET (preview), 00409 "width-request", preview_w_current->toplevel->width, 00410 "height-request", preview_w_current->toplevel->height, 00411 NULL); 00412 00413 preview->active = FALSE; 00414 preview->filename = NULL; 00415 preview->buffer = NULL; 00416 00417 gtk_widget_set_events (GTK_WIDGET (preview), 00418 GDK_EXPOSURE_MASK | 00419 GDK_POINTER_MOTION_MASK | 00420 GDK_BUTTON_PRESS_MASK); 00421 for (tmp = drawing_area_events; tmp->detailed_signal != NULL; tmp++) { 00422 g_signal_connect (preview, 00423 tmp->detailed_signal, 00424 tmp->c_handler, 00425 NULL); 00426 } 00427 00428 } 00429 00430 static void 00431 preview_set_property (GObject *object, 00432 guint property_id, 00433 const GValue *value, 00434 GParamSpec *pspec) 00435 { 00436 Preview *preview = PREVIEW (object); 00437 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00438 00439 g_assert (preview_w_current != NULL); 00440 00441 switch(property_id) { 00442 case PROP_FILENAME: 00443 if (preview->buffer != NULL) { 00444 g_free (preview->buffer); 00445 preview->buffer = NULL; 00446 g_object_notify (object, "buffer"); 00447 } 00448 g_free (preview->filename); 00449 preview->filename = g_strdup (g_value_get_string (value)); 00450 preview_update (preview); 00451 break; 00452 00453 case PROP_BUFFER: 00454 if (preview->filename != NULL) { 00455 g_free (preview->filename); 00456 preview->filename = NULL; 00457 g_object_notify (object, "filename"); 00458 } 00459 g_free (preview->buffer); 00460 preview->buffer = g_strdup (g_value_get_string (value)); 00461 preview_update (preview); 00462 break; 00463 00464 case PROP_ACTIVE: 00465 preview->active = g_value_get_boolean (value); 00466 preview_update (preview); 00467 break; 00468 default: 00469 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 00470 } 00471 00472 } 00473 00474 static void 00475 preview_get_property (GObject *object, 00476 guint property_id, 00477 GValue *value, 00478 GParamSpec *pspec) 00479 { 00480 Preview *preview = PREVIEW (object); 00481 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00482 00483 switch(property_id) { 00484 case PROP_FILENAME: 00485 g_assert (preview_w_current != NULL); 00486 /* return the filename of the current page in toplevel */ 00487 g_value_set_string (value, 00488 preview_w_current->toplevel->page_current->page_filename); 00489 break; 00490 case PROP_ACTIVE: 00491 g_value_set_boolean (value, preview->active); 00492 break; 00493 default: 00494 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); 00495 } 00496 00497 } 00498 00499 static void 00500 preview_dispose (GObject *self) 00501 { 00502 Preview *preview = PREVIEW (self); 00503 GSCHEM_TOPLEVEL *preview_w_current = preview->preview_w_current; 00504 00505 if (preview_w_current != NULL) { 00506 preview_w_current->drawing_area = NULL; 00507 00508 x_window_free_gc (preview_w_current); 00509 00510 s_toplevel_delete (preview_w_current->toplevel); 00511 g_free (preview_w_current); 00512 00513 preview->preview_w_current = NULL; 00514 } 00515 00516 G_OBJECT_CLASS (preview_parent_class)->dispose (self); 00517 00518 } 00519 00520 00521