2 * gEDA - GNU Electronic Design Automation
3 * This file is a part of gerbv.
5 * Copyright (C) 2000-2003 Stefan Petersen (spe@stacken.kth.se)
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 \brief Callback functions for the GUI widgets
36 #if !defined(WIN32) && !defined(QUARTZ)
39 #include <gdk/gdkkeysyms.h>
61 #include "callbacks.h"
62 #include "interface.h"
63 #include "attribute.h"
70 #include <cairo-win32.h>
72 #include <cairo-quartz.h>
74 #include <cairo-xlib.h>
78 #define dprintf if(DEBUG) printf
80 /* This default extension should really not be changed, but if it absolutely
81 * must change, the ../win32/gerbv.nsi.in *must* be changed to reflect that.
82 * Just grep for the extension (gvp) and change it in two places in that file.
84 #define GERBV_PROJECT_FILE_NAME "Gerbv Project"
85 #define GERBV_PROJECT_FILE_EXT ".gvp"
86 #define GERBV_PROJECT_FILE_PAT "*.gvp"
88 #define SAVE_PROJECT 0
89 #define SAVE_AS_PROJECT 1
90 #define OPEN_PROJECT 2
91 # define _(String) (String)
93 /**Global variable to keep track of what's happening on the screen.
94 Declared extern in gerbv_screen.h
96 extern gerbv_screen_t screen
;
97 extern gerbv_render_info_t screenRenderInfo
;
100 /* These are the names of the valid apertures. These
101 * values are used in several places in this file.
102 * Please keep this in sync with the gerbv_aperture_type_t
103 * enum defined in gerbv.h */
104 char *ap_names
[] = {"NONE",
107 "OVAL", /* an ovular (obround) aperture */
108 "POLYGON", /* a polygon aperture */
109 "MACRO", /* a RS274X macro */
110 "MACRO_CIRCLE", /* a RS274X circle macro */
111 "MACRO_OUTLINE", /* a RS274X outline macro */
112 "MACRO_POLYGON", /* a RS274X polygon macro */
113 "MACRO_MOIRE", /* a RS274X moire macro */
114 "MACRO_THERMAL", /* a RS274X thermal macro */
115 "MACRO_LINE20", /* a RS274X line (code 20) macro */
116 "MACRO_LINE21", /* a RS274X line (code 21) macro */
117 "MACRO_LINE22" /* a RS274X line (code 22) macro */
120 static gint
callbacks_get_selected_row_index (void);
121 static void callbacks_units_changed (gerbv_gui_unit_t unit
);
122 static void callbacks_update_statusbar_coordinates (gint x
, gint y
);
123 static void callbacks_update_ruler_scales (void);
124 static void callbacks_render_type_changed (void);
125 static void show_no_layers_warning (void);
127 /* --------------------------------------------------------- */
129 static void show_no_layers_warning (void) {
130 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
131 "<b>No layers are currently loaded. A layer must be loaded first.</b>");
132 callbacks_update_statusbar();
135 /* --------------------------------------------------------- */
137 callbacks_generate_alert_dialog (gchar
*primaryText
, gchar
*secondaryText
){
138 GtkWidget
*dialog
, *label
;
140 dialog
= gtk_dialog_new_with_buttons (primaryText
,
141 (GtkWindow
*)screen
.win
.topLevelWindow
,
142 GTK_DIALOG_DESTROY_WITH_PARENT
,
143 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
144 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
146 label
= gtk_label_new (secondaryText
);
147 /* Add the label, and show everything we've added to the dialog. */
148 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog
)->vbox
),
150 gtk_widget_show_all (dialog
);
154 /* --------------------------------------------------------- */
156 * The file -> new menu item was selected. Create new
161 callbacks_new_activate (GtkMenuItem
*menuitem
, gpointer user_data
)
163 if (mainProject
->last_loaded
>= 0) {
164 if (!interface_get_alert_dialog_response (
165 "Do you want to close any open layers and start a new project?",
166 "Starting a new project will cause all currently open layers to be closed. Any unsaved changes will be lost.",
171 /* Unload all layers and then clear layer window */
172 gerbv_unload_all_layers (mainProject
);
173 callbacks_update_layer_tree ();
174 render_clear_selection_buffer ();
176 /* Destroy project info */
177 if (mainProject
->project
) {
178 g_free(mainProject
->project
);
179 mainProject
->project
= NULL
;
181 render_refresh_rendered_image_on_screen();
185 /* --------------------------------------------------------- */
187 * The file -> open menu item was selected. Open a
192 callbacks_open_project_activate (GtkMenuItem
*menuitem
,
195 gchar
*filename
=NULL
;
196 GtkFileFilter
* filter
;
198 if (mainProject
->last_loaded
>= 0) {
199 if (!interface_get_alert_dialog_response (
200 "Do you want to close any open layers and load an existing project?",
201 "Loading a project will cause all currently open layers to be closed. Any unsaved changes will be lost.",
208 gtk_file_chooser_dialog_new ("Open project file...",
210 GTK_FILE_CHOOSER_ACTION_OPEN
,
211 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
212 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
214 gtk_file_chooser_set_current_folder ((GtkFileChooser
*) screen
.win
.gerber
,
217 filter
= gtk_file_filter_new();
218 gtk_file_filter_set_name(filter
, GERBV_PROJECT_FILE_NAME
);
219 gtk_file_filter_add_pattern(filter
, GERBV_PROJECT_FILE_PAT
);
220 gtk_file_chooser_add_filter ((GtkFileChooser
*) screen
.win
.gerber
,
223 filter
= gtk_file_filter_new();
224 gtk_file_filter_set_name(filter
, "All");
225 gtk_file_filter_add_pattern(filter
, "*");
226 gtk_file_chooser_add_filter ((GtkFileChooser
*) screen
.win
.gerber
,
229 gtk_widget_show (screen
.win
.gerber
);
230 if (gtk_dialog_run ((GtkDialog
*)screen
.win
.gerber
) == GTK_RESPONSE_ACCEPT
) {
232 gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (screen
.win
.gerber
));
233 /* update the last folder */
234 g_free (mainProject
->path
);
235 mainProject
->path
= gtk_file_chooser_get_current_folder ((GtkFileChooser
*) screen
.win
.gerber
);
237 gtk_widget_destroy (screen
.win
.gerber
);
240 gerbv_unload_all_layers (mainProject
);
241 main_open_project_from_filename (mainProject
, filename
);
243 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
244 render_refresh_rendered_image_on_screen();
245 callbacks_update_layer_tree();
251 /* --------------------------------------------------------- */
253 * The file -> open layer menu item was selected. Open a
254 * layer (or layers) from a file.
258 callbacks_open_layer_activate (GtkMenuItem
*menuitem
,
261 GSList
*filenames
=NULL
;
262 GSList
*filename
=NULL
;
265 gtk_file_chooser_dialog_new ("Open Gerber, drill, or pick & place file(s)...",
267 GTK_FILE_CHOOSER_ACTION_OPEN
,
268 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
269 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
272 gtk_file_chooser_set_select_multiple((GtkFileChooser
*) screen
.win
.gerber
, TRUE
);
273 gtk_file_chooser_set_current_folder ((GtkFileChooser
*) screen
.win
.gerber
,
275 gtk_widget_show (screen
.win
.gerber
);
276 if (gtk_dialog_run ((GtkDialog
*)screen
.win
.gerber
) == GTK_RESPONSE_ACCEPT
) {
278 gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (screen
.win
.gerber
));
279 /* update the last folder */
280 g_free (mainProject
->path
);
281 mainProject
->path
= gtk_file_chooser_get_current_folder ((GtkFileChooser
*) screen
.win
.gerber
);
283 gtk_widget_destroy (screen
.win
.gerber
);
285 /* Now try to open all gerbers specified */
286 for (filename
=filenames
; filename
; filename
=filename
->next
) {
287 gerbv_open_layer_from_filename (mainProject
, filename
->data
);
289 g_slist_free(filenames
);
291 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
292 render_refresh_rendered_image_on_screen();
293 callbacks_update_layer_tree();
298 /* --------------------------------------------------------- */
300 callbacks_revert_activate (GtkMenuItem
*menuitem
,
303 gerbv_revert_all_files (mainProject
);
304 render_clear_selection_buffer();
305 callbacks_update_selected_object_message(FALSE
);
306 render_refresh_rendered_image_on_screen();
307 callbacks_update_layer_tree();
310 /* --------------------------------------------------------- */
312 callbacks_save_project_activate (GtkMenuItem
*menuitem
,
315 if (mainProject
->project
)
316 main_save_project_from_filename (mainProject
, mainProject
->project
);
318 callbacks_generic_save_activate (menuitem
, (gpointer
) CALLBACKS_SAVE_PROJECT_AS
);
319 callbacks_update_layer_tree();
323 /* --------------------------------------------------------- */
325 callbacks_save_layer_activate (GtkMenuItem
*menuitem
,
328 /* first figure out which layer in the layer side menu is selected */
329 gint index
=callbacks_get_selected_row_index();
331 /* Now save that layer */
333 if (!gerbv_save_layer_from_index (mainProject
, index
, mainProject
->file
[index
]->fullPathname
)) {
334 interface_show_alert_dialog("Gerbv cannot export this file type",
338 mainProject
->file
[index
]->layer_dirty
= FALSE
;
339 callbacks_update_layer_tree();
343 callbacks_update_layer_tree();
346 struct l_image_info
{
347 gerbv_image_t
*image
;
348 gerbv_user_transformation_t
*transform
;
350 /* --------------------------------------------------------- */
351 /**Go through each file and look at visibility, then type.
352 Make sure we have at least 2 files.
355 gerbv_image_t
*merge_images (int type
)
357 gint i
, filecount
, img
;
358 /* struct l_image_info *images; */
360 struct l_image_info
{
361 gerbv_image_t
*image
;
362 gerbv_user_transformation_t
*transform
;
366 images
=(struct l_image_info
*)g_new0(struct l_image_info
,1);
369 case CALLBACKS_SAVE_FILE_DRILLM
:
370 type
=GERBV_LAYERTYPE_DRILL
;
372 case CALLBACKS_SAVE_FILE_RS274XM
:
373 type
=GERBV_LAYERTYPE_RS274X
;
376 GERB_MESSAGE("Unknown Layer type for merge\n");
379 dprintf("Looking for matching files\n");
380 for (i
=img
=filecount
=0;i
<mainProject
->max_files
;++i
){
381 if (mainProject
->file
[i
] && mainProject
->file
[i
]->isVisible
&&
382 (mainProject
->file
[i
]->image
->layertype
== type
) ) {
384 dprintf("Adding '%s'\n",mainProject
->file
[i
]->name
);
385 images
[img
].image
=mainProject
->file
[i
]->image
;
386 /* printf("Adding transform\n"); */
387 images
[img
++].transform
=&mainProject
->file
[i
]->transform
;
388 /* printf("Realloc\n"); */
389 images
=(struct l_image_info
*)g_renew(struct l_image_info
, images
,img
+1);
391 /* printf("Done with add\n"); */
394 GERB_MESSAGE ("Not Enough Files of same type to merge\n");
397 dprintf("Now merging files\n");
399 gerbv_user_transformation_t
*thisTransform
;
400 gerbv_user_transformation_t identityTransform
= {0,0,1,1,0,FALSE
,FALSE
,FALSE
};
401 thisTransform
=images
[i
].transform
;
402 if (NULL
== thisTransform
)
403 thisTransform
= &identityTransform
;
405 out
= gerbv_image_duplicate_image (images
[i
].image
, thisTransform
);
407 gerbv_image_copy_image(images
[i
].image
,thisTransform
,out
);
413 /* --------------------------------------------------------- */
415 callbacks_generic_save_activate (GtkMenuItem
*menuitem
,
418 gchar
*filename
=NULL
;
419 gint processType
= GPOINTER_TO_INT (user_data
);
420 gchar
*windowTitle
=NULL
;
421 GtkFileFilter
* filter
;
423 gint index
=callbacks_get_selected_row_index ();
425 interface_show_alert_dialog("No layer is currently selected",
426 "Please select a layer and try again.",
432 if (processType
== CALLBACKS_SAVE_PROJECT_AS
)
433 windowTitle
= g_strdup ("Save project as...");
434 else if (processType
== CALLBACKS_SAVE_FILE_PS
)
435 windowTitle
= g_strdup ("Export PS file as...");
436 else if (processType
== CALLBACKS_SAVE_FILE_PDF
)
437 windowTitle
= g_strdup ("Export PDF file as...");
438 else if (processType
== CALLBACKS_SAVE_FILE_SVG
)
439 windowTitle
= g_strdup ("Export SVG file as...");
440 else if (processType
== CALLBACKS_SAVE_FILE_PNG
)
441 windowTitle
= g_strdup ("Export PNG file as...");
442 else if (processType
== CALLBACKS_SAVE_FILE_RS274X
)
443 windowTitle
= g_strdup ("Export RS-274X file as...");
444 else if (processType
== CALLBACKS_SAVE_FILE_DRILL
)
445 windowTitle
= g_strdup ("Export Excellon drill file as...");
446 else if (processType
== CALLBACKS_SAVE_FILE_RS274XM
)
447 windowTitle
= g_strdup ("Export RS-274Xm file as...");
448 else if (processType
== CALLBACKS_SAVE_FILE_DRILLM
)
449 windowTitle
= g_strdup ("Export Excellon drillm file as...");
450 else if (processType
== CALLBACKS_SAVE_LAYER_AS
)
451 windowTitle
= g_strdup ("Save layer as...");
454 gtk_file_chooser_dialog_new (windowTitle
, NULL
,
455 GTK_FILE_CHOOSER_ACTION_SAVE
,
456 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
457 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
,
459 g_free (windowTitle
);
461 /* if we're saving or exporting a layer, start off in the location of the
463 if (processType
!= CALLBACKS_SAVE_PROJECT_AS
) {
464 gint index
=callbacks_get_selected_row_index();
466 gchar
*dirName
= g_path_get_dirname (mainProject
->file
[index
]->fullPathname
);
467 gtk_file_chooser_set_current_folder ((GtkFileChooser
*) screen
.win
.gerber
,
473 if (processType
== CALLBACKS_SAVE_PROJECT_AS
) {
474 filter
= gtk_file_filter_new();
475 gtk_file_filter_set_name(filter
, GERBV_PROJECT_FILE_NAME
);
476 gtk_file_filter_add_pattern(filter
, GERBV_PROJECT_FILE_PAT
);
477 gtk_file_chooser_add_filter ((GtkFileChooser
*) screen
.win
.gerber
,
480 filter
= gtk_file_filter_new();
481 gtk_file_filter_set_name(filter
, "All");
482 gtk_file_filter_add_pattern(filter
, "*");
483 gtk_file_chooser_add_filter ((GtkFileChooser
*) screen
.win
.gerber
,
486 gtk_file_chooser_set_current_name ((GtkFileChooser
*) screen
.win
.gerber
,
487 "untitled" GERBV_PROJECT_FILE_EXT
);
490 gtk_widget_show (screen
.win
.gerber
);
491 if (gtk_dialog_run ((GtkDialog
*)screen
.win
.gerber
) == GTK_RESPONSE_ACCEPT
) {
492 filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (screen
.win
.gerber
));
494 gtk_widget_destroy (screen
.win
.gerber
);
497 if (processType
== CALLBACKS_SAVE_PROJECT_AS
) {
498 main_save_as_project_from_filename (mainProject
, filename
);
499 rename_main_window(filename
, NULL
);
501 else if (processType
== CALLBACKS_SAVE_FILE_PS
)
502 gerbv_export_postscript_file_from_project_autoscaled (mainProject
, filename
);
503 else if (processType
== CALLBACKS_SAVE_FILE_PDF
)
504 gerbv_export_pdf_file_from_project_autoscaled (mainProject
, filename
);
505 else if (processType
== CALLBACKS_SAVE_FILE_SVG
)
506 gerbv_export_svg_file_from_project_autoscaled (mainProject
, filename
);
507 else if (processType
== CALLBACKS_SAVE_FILE_PNG
)
508 gerbv_export_png_file_from_project_autoscaled (mainProject
,
509 screenRenderInfo
.displayWidth
, screenRenderInfo
.displayHeight
,
511 else if (processType
== CALLBACKS_SAVE_LAYER_AS
) {
512 gint index
=callbacks_get_selected_row_index();
514 gerbv_save_layer_from_index (mainProject
, index
, filename
);
515 /* rename the file path in the index, so future saves will reference the new file path */
516 g_free (mainProject
->file
[index
]->fullPathname
);
517 mainProject
->file
[index
]->fullPathname
= g_strdup (filename
);
518 g_free (mainProject
->file
[index
]->name
);
519 mainProject
->file
[index
]->name
= g_path_get_basename (filename
);
521 else if (processType
== CALLBACKS_SAVE_FILE_RS274X
) {
522 gint index
=callbacks_get_selected_row_index();
524 gerbv_export_rs274x_file_from_image (filename
, mainProject
->file
[index
]->image
,
525 &mainProject
->file
[index
]->transform
);
527 else if (processType
== CALLBACKS_SAVE_FILE_DRILL
) {
528 gint index
=callbacks_get_selected_row_index();
530 gerbv_export_drill_file_from_image (filename
, mainProject
->file
[index
]->image
,
531 &mainProject
->file
[index
]->transform
);
532 } /**create new image.... */
533 else if (processType
== CALLBACKS_SAVE_FILE_RS274XM
) {
534 gerbv_image_t
*image
;
535 gerbv_user_transformation_t t
= {0,0,1,1,0,FALSE
,FALSE
,FALSE
};
536 if(NULL
!= (image
=merge_images(processType
)) ){
537 /*printf("Preparing to export merge\n"); */
538 gerbv_export_rs274x_file_from_image (filename
, image
, &t
);
539 gerbv_destroy_image(image
);
540 GERB_MESSAGE ("Merged visible gerber layers and placed in '%s'\n",filename
);
543 else if (processType
== CALLBACKS_SAVE_FILE_DRILLM
) {
544 gerbv_image_t
*image
;
545 gerbv_user_transformation_t t
= {0,0,1,1,0,FALSE
,FALSE
,FALSE
};
546 if(NULL
!= (image
=merge_images(processType
)) ){
547 gerbv_export_drill_file_from_image (filename
, image
,&t
);
548 gerbv_destroy_image(image
);
549 GERB_MESSAGE ("Merged visible drill layers and placed in '%s'\n",filename
);
554 callbacks_update_layer_tree();
558 /* --------------------------------------------------------- */
559 #if GTK_CHECK_VERSION(2,10,0)
562 callbacks_begin_print (GtkPrintOperation
*operation
, GtkPrintContext
*context
,
563 gpointer user_data
) {
564 gtk_print_operation_set_n_pages (operation
, 1);
568 /* --------------------------------------------------------- */
570 callbacks_print_render_page (GtkPrintOperation
*operation
,
571 GtkPrintContext
*context
,
575 GtkPrintSettings
*pSettings
= gtk_print_operation_get_print_settings (operation
);
576 gerbv_render_info_t renderInfo
= {1.0, 1.0, 0, 0, 3,
577 (gint
) gtk_print_context_get_width (context
),
578 (gint
) gtk_print_context_get_height (context
)};
581 /* have to assume x and y resolutions are the same for now, since we
582 don't support differing scales in the gerb_render_info_t struct yet */
583 gdouble xres
= gtk_print_context_get_dpi_x (context
);
584 gdouble yres
= gtk_print_context_get_dpi_y (context
);
585 gdouble scalePercentage
= gtk_print_settings_get_scale (pSettings
);
586 renderInfo
.scaleFactorX
= scalePercentage
/ 100 * xres
;
587 renderInfo
.scaleFactorY
= scalePercentage
/ 100 * yres
;
589 gerbv_render_translate_to_fit_display (mainProject
, &renderInfo
);
590 cr
= gtk_print_context_get_cairo_context (context
);
591 gerbv_render_all_layers_to_cairo_target_for_vector_output (mainProject
, cr
, &renderInfo
);
594 /* --------------------------------------------------------- */
596 callbacks_print_activate (GtkMenuItem
*menuitem
, gpointer user_data
)
598 GtkPrintOperation
*print
;
599 GtkPrintOperationResult res
;
601 print
= gtk_print_operation_new ();
603 g_signal_connect (print
, "begin_print", G_CALLBACK (callbacks_begin_print
), NULL
);
604 g_signal_connect (print
, "draw_page", G_CALLBACK (callbacks_print_render_page
), NULL
);
606 //GtkPrintSettings *pSettings = gtk_print_operation_get_print_settings (print);
608 res
= gtk_print_operation_run (print
, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
,
609 (GtkWindow
*) screen
.win
.topLevelWindow
, NULL
);
611 g_object_unref (print
);
613 #endif /* GTK_CHECK_VERSION(2,10,0) */
615 /* --------------------------------------------------------- */
617 callbacks_fullscreen_toggled (GtkMenuItem
*menuitem
, gpointer user_data
)
619 //struct GtkWindow *win = (struct GtkWindow *)(screen.win.topLevelWindow);
620 GdkWindowState state
= gdk_window_get_state (gtk_widget_get_window(screen
.win
.topLevelWindow
));
621 if(state
& GDK_WINDOW_STATE_FULLSCREEN
)
622 gtk_window_unfullscreen (GTK_WINDOW(screen
.win
.topLevelWindow
));
624 gtk_window_fullscreen (GTK_WINDOW(screen
.win
.topLevelWindow
));
627 /* --------------------------------------------------------- */
629 callbacks_show_toolbar_toggled (GtkMenuItem
*menuitem
, gpointer user_data
)
631 gtk_widget_set_visible (user_data
, GTK_CHECK_MENU_ITEM(menuitem
)->active
);
634 /* --------------------------------------------------------- */
636 callbacks_show_sidepane_toggled (GtkMenuItem
*menuitem
, gpointer user_data
)
638 gtk_widget_set_visible (user_data
, GTK_CHECK_MENU_ITEM(menuitem
)->active
);
641 /* --------------------------------------------------------- */
642 /** View/"Toggle visibility layer X" or Current layer/"Toggle visibility" menu item was activated.
643 * Set the isVisible flag on file X and update the treeview and rendering.
646 callbacks_toggle_layer_visibility_activate (GtkMenuItem
*menuitem
, gpointer user_data
)
648 int i
= GPOINTER_TO_INT(user_data
);
650 i
= callbacks_get_selected_row_index ();
652 if (0 <= i
&& i
<= mainProject
->last_loaded
) {
653 mainProject
->file
[i
]->isVisible
= !mainProject
->file
[i
]->isVisible
;
654 /* clear any selected items so they don't show after the layer is hidden */
655 render_clear_selection_buffer();
657 callbacks_update_layer_tree ();
658 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
659 render_refresh_rendered_image_on_screen();
662 render_recreate_composite_surface (screen
.drawing_area
);
663 callbacks_force_expose_event_for_screen ();
668 /* --------------------------------------------------------- */
670 callbacks_zoom_in_activate (GtkMenuItem
*menuitem
,
673 render_zoom_display (ZOOM_IN
, 0, 0, 0);
676 /* --------------------------------------------------------- */
678 callbacks_zoom_out_activate (GtkMenuItem
*menuitem
,
681 render_zoom_display (ZOOM_OUT
, 0, 0, 0);
684 /* --------------------------------------------------------- */
686 callbacks_fit_to_window_activate (GtkMenuItem
*menuitem
,
689 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
690 render_refresh_rendered_image_on_screen();
694 /* --------------------------------------------------------- */
696 * The analyze -> analyze Gerbers menu item was selected.
697 * Compile statistics on all open Gerber layers and then display
702 callbacks_analyze_active_gerbers_activate(GtkMenuItem
*menuitem
,
705 gerbv_stats_t
*stats_report
;
706 GString
*G_report_string
= g_string_new(NULL
);
707 GString
*D_report_string
= g_string_new(NULL
);
708 GString
*M_report_string
= g_string_new(NULL
);
709 GString
*misc_report_string
= g_string_new(NULL
);
710 GString
*general_report_string
= g_string_new(NULL
);
711 GString
*error_report_string
= g_string_new(NULL
);
712 gerbv_error_list_t
*my_error_list
;
713 gchar
*error_level
= NULL
;
714 GString
*aperture_def_report_string
= g_string_new(NULL
);
715 GString
*aperture_use_report_string
= g_string_new(NULL
);
716 gerbv_aperture_list_t
*my_aperture_list
;
718 int aperture_count
= 0;
720 /* First get a report of stats & errors accumulated from all layers */
721 stats_report
= generate_gerber_analysis();
723 /* General info report */
724 g_string_printf(general_report_string
,
725 "General information\n");
726 g_string_append_printf(general_report_string
,
727 " Active layer count = %d\n",
728 stats_report
->layer_count
);
729 g_string_append_printf(general_report_string
,
733 for (idx
= 0; idx
<= mainProject
->last_loaded
; idx
++) {
734 if (mainProject
->file
[idx
] &&
735 mainProject
->file
[idx
]->isVisible
&&
736 (mainProject
->file
[idx
]->image
->layertype
== GERBV_LAYERTYPE_RS274X
) ) {
737 g_string_append_printf(general_report_string
,
738 " %-45s %-10d\n", mainProject
->file
[idx
]->name
, idx
+1);
742 /* Error report (goes into general report tab) */
743 if (stats_report
->layer_count
== 0) {
744 g_string_printf(error_report_string
,
745 "\n\nNo Gerber files active (visible)!\n");
746 } else if (stats_report
->error_list
->error_text
== NULL
) {
747 g_string_printf(error_report_string
,
748 "\n\nNo errors found in active Gerber file(s)!\n");
750 g_string_printf(error_report_string
,
751 "\n\nErrors found in active Gerber file(s):\n");
752 for(my_error_list
= stats_report
->error_list
;
753 my_error_list
!= NULL
;
754 my_error_list
= my_error_list
->next
) {
755 switch(my_error_list
->type
) {
756 case GERBV_MESSAGE_FATAL
: /* We should never get this one since the
757 * program should terminate first.... */
758 error_level
= g_strdup_printf("FATAL: ");
760 case GERBV_MESSAGE_ERROR
:
761 error_level
= g_strdup_printf("ERROR: ");
763 case GERBV_MESSAGE_WARNING
:
764 error_level
= g_strdup_printf("WARNING: ");
766 case GERBV_MESSAGE_NOTE
:
767 error_level
= g_strdup_printf("NOTE: ");
770 g_string_append_printf(error_report_string
,
772 my_error_list
->layer
,
774 my_error_list
->error_text
);
780 g_string_append_printf(general_report_string
,
782 error_report_string
->str
);
783 g_string_free(error_report_string
, TRUE
);
785 /* Now compile stats related to reading G codes */
786 g_string_printf(G_report_string
,
787 "G code statistics (all active layers)\n");
788 g_string_append_printf(G_report_string
,
789 "<code> = <number of incidences>\n");
790 g_string_append_printf(G_report_string
,
794 g_string_append_printf(G_report_string
,
797 "1X linear interpolation");
798 g_string_append_printf(G_report_string
,
802 g_string_append_printf(G_report_string
,
805 "CCW interpolation");
806 g_string_append_printf(G_report_string
,
809 "Comment/ignore block");
810 g_string_append_printf(G_report_string
,
813 "10X linear interpolation");
814 g_string_append_printf(G_report_string
,
817 "0.1X linear interpolation");
818 g_string_append_printf(G_report_string
,
821 "0.01X linear interpolation");
822 g_string_append_printf(G_report_string
,
826 g_string_append_printf(G_report_string
,
830 g_string_append_printf(G_report_string
,
834 g_string_append_printf(G_report_string
,
838 g_string_append_printf(G_report_string
,
842 g_string_append_printf(G_report_string
,
846 g_string_append_printf(G_report_string
,
849 "Disable 360 circ. interpolation");
850 g_string_append_printf(G_report_string
,
853 "Enable 360 circ. interpolation");
854 g_string_append_printf(G_report_string
,
858 g_string_append_printf(G_report_string
,
861 "Incremental units");
862 g_string_append_printf(G_report_string
,
863 "Unknown G codes = %d\n",
864 stats_report
->G_unknown
);
867 g_string_printf(D_report_string
, "D code statistics (all active layers)\n");
868 g_string_append_printf(D_report_string
,
869 "<code> = <number of incidences>\n");
870 g_string_append_printf(D_report_string
,
874 g_string_append_printf(D_report_string
,
878 g_string_append_printf(D_report_string
,
882 g_string_append_printf(D_report_string
,
883 "Undefined D codes = %d\n",
884 stats_report
->D_unknown
);
885 g_string_append_printf(D_report_string
,
886 "D code Errors = %d\n",
887 stats_report
->D_error
);
890 g_string_printf(M_report_string
, "M code statistics (all active layers)\n");
891 g_string_append_printf(M_report_string
,
892 "<code> = <number of incidences>\n");
893 g_string_append_printf(M_report_string
,
897 g_string_append_printf(M_report_string
,
901 g_string_append_printf(M_report_string
,
905 g_string_append_printf(M_report_string
,
906 "Unknown M codes = %d\n",
907 stats_report
->M_unknown
);
910 g_string_printf(misc_report_string
, "Misc code statistics (all active layers)\n");
911 g_string_append_printf(misc_report_string
,
912 "<code> = <number of incidences>\n");
913 g_string_append_printf(misc_report_string
,
914 "X = %d\n", stats_report
->X
);
915 g_string_append_printf(misc_report_string
,
916 "Y = %d\n", stats_report
->Y
);
917 g_string_append_printf(misc_report_string
,
918 "I = %d\n", stats_report
->I
);
919 g_string_append_printf(misc_report_string
,
920 "J = %d\n", stats_report
->J
);
921 g_string_append_printf(misc_report_string
,
922 "* = %d\n", stats_report
->star
);
923 g_string_append_printf(misc_report_string
,
924 "Unknown codes = %d\n",
925 stats_report
->unknown
);
927 /* Report apertures defined in input files. */
929 if (stats_report
->aperture_list
->number
== -1) {
930 g_string_printf(aperture_def_report_string
,
931 "No aperture definitions found in Gerber file(s)!\n");
933 g_string_printf(aperture_def_report_string
,
934 "Apertures defined in Gerber file(s) (by layer)\n");
935 g_string_append_printf(aperture_def_report_string
,
936 " %-6s %-8s %12s %8s %8s %8s\n",
944 for(my_aperture_list
= stats_report
->aperture_list
;
945 my_aperture_list
!= NULL
;
946 my_aperture_list
= my_aperture_list
->next
) {
948 g_string_append_printf(aperture_def_report_string
,
949 " %-6d D%-4d%13s %8.3f %8.3f %8.3f\n",
950 my_aperture_list
->layer
,
951 my_aperture_list
->number
,
952 ap_names
[my_aperture_list
->type
],
953 my_aperture_list
->parameter
[0],
954 my_aperture_list
->parameter
[1],
955 my_aperture_list
->parameter
[2]
960 /* Report apertures usage count in input files. */
961 if (stats_report
->D_code_list
->number
== -1) {
962 g_string_printf(aperture_use_report_string
,
963 "No apertures used in Gerber file(s)!\n");
966 /* Now add list of user-defined D codes (apertures) */
968 g_string_printf(aperture_use_report_string
,
969 "Apertures used in Gerber file(s) (all active layers)\n");
970 g_string_append_printf(aperture_use_report_string
,
971 "<aperture code> = <number of uses>\n");
972 for (my_aperture_list
= stats_report
->D_code_list
;
973 my_aperture_list
!= NULL
;
974 my_aperture_list
= my_aperture_list
->next
) {
976 g_string_append_printf(aperture_use_report_string
,
978 my_aperture_list
->number
,
979 my_aperture_list
->count
981 aperture_count
+= my_aperture_list
->count
;
984 g_string_append_printf(aperture_use_report_string
,
985 "\nTotal number of aperture uses: %d\n", aperture_count
);
988 /* Create top level dialog window for report */
989 GtkWidget
*analyze_active_gerbers
;
990 analyze_active_gerbers
= gtk_dialog_new_with_buttons("Gerber codes report",
992 GTK_DIALOG_DESTROY_WITH_PARENT
,
996 gtk_container_set_border_width (GTK_CONTAINER (analyze_active_gerbers
), 5);
998 gtk_dialog_set_default_response (GTK_DIALOG(analyze_active_gerbers
),
999 GTK_RESPONSE_ACCEPT
);
1000 g_signal_connect (G_OBJECT(analyze_active_gerbers
),
1002 G_CALLBACK (gtk_widget_destroy
),
1003 GTK_WIDGET(analyze_active_gerbers
));
1005 /* Use fixed width font for all reports */
1006 PangoFontDescription
*font
=
1007 pango_font_description_from_string ("monospace");
1009 /* Create GtkLabel to hold general report text */
1010 GtkWidget
*general_report_label
= gtk_label_new (general_report_string
->str
);
1011 g_string_free (general_report_string
, TRUE
);
1012 gtk_misc_set_alignment(GTK_MISC(general_report_label
), 0, 0);
1013 gtk_misc_set_padding(GTK_MISC(general_report_label
), 13, 13);
1014 gtk_label_set_selectable(GTK_LABEL(general_report_label
), TRUE
);
1015 gtk_widget_modify_font (GTK_WIDGET(general_report_label
),
1017 /* Put general report text into scrolled window */
1018 GtkWidget
*general_code_report_window
= gtk_scrolled_window_new (NULL
, NULL
);
1019 /* This throws a warning. Must find different approach.... */
1020 gtk_widget_set_size_request(GTK_WIDGET(general_code_report_window
),
1023 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(general_code_report_window
),
1024 GTK_WIDGET(general_report_label
));
1026 /* Create GtkLabel to hold G code text */
1027 GtkWidget
*G_report_label
= gtk_label_new (G_report_string
->str
);
1028 g_string_free (G_report_string
, TRUE
);
1029 gtk_misc_set_alignment(GTK_MISC(G_report_label
), 0, 0);
1030 gtk_misc_set_padding(GTK_MISC(G_report_label
), 13, 13);
1031 gtk_label_set_selectable(GTK_LABEL(G_report_label
), TRUE
);
1032 gtk_widget_modify_font (GTK_WIDGET(G_report_label
),
1035 /* Create GtkLabel to hold D code text */
1036 GtkWidget
*D_report_label
= gtk_label_new (D_report_string
->str
);
1037 g_string_free (D_report_string
, TRUE
);
1038 gtk_misc_set_alignment(GTK_MISC(D_report_label
), 0, 0);
1039 gtk_misc_set_padding(GTK_MISC(D_report_label
), 13, 13);
1040 gtk_label_set_selectable(GTK_LABEL(D_report_label
), TRUE
);
1041 gtk_widget_modify_font (GTK_WIDGET(D_report_label
),
1044 /* Create GtkLabel to hold M code text */
1045 GtkWidget
*M_report_label
= gtk_label_new (M_report_string
->str
);
1046 g_string_free (M_report_string
, TRUE
);
1047 gtk_misc_set_alignment(GTK_MISC(M_report_label
), 0, 0);
1048 gtk_misc_set_padding(GTK_MISC(M_report_label
), 13, 13);
1049 gtk_label_set_selectable(GTK_LABEL(M_report_label
), TRUE
);
1050 gtk_widget_modify_font (GTK_WIDGET(M_report_label
),
1053 /* Create GtkLabel to hold misc code text */
1054 GtkWidget
*misc_report_label
= gtk_label_new (misc_report_string
->str
);
1055 g_string_free (misc_report_string
, TRUE
);
1056 gtk_misc_set_alignment(GTK_MISC(misc_report_label
), 0, 0);
1057 gtk_misc_set_padding(GTK_MISC(misc_report_label
), 13, 13);
1058 gtk_label_set_selectable(GTK_LABEL(misc_report_label
), TRUE
);
1059 gtk_widget_modify_font (GTK_WIDGET(misc_report_label
),
1062 /* Create GtkLabel to hold aperture defintion text */
1063 GtkWidget
*aperture_def_report_label
= gtk_label_new (aperture_def_report_string
->str
);
1064 g_string_free (aperture_def_report_string
, TRUE
);
1065 gtk_misc_set_alignment(GTK_MISC(aperture_def_report_label
), 0, 0);
1066 gtk_misc_set_padding(GTK_MISC(aperture_def_report_label
), 13, 13);
1067 gtk_label_set_selectable(GTK_LABEL(aperture_def_report_label
), TRUE
);
1068 gtk_widget_modify_font (GTK_WIDGET(aperture_def_report_label
),
1070 /* Put aperture definintion text into scrolled window */
1071 GtkWidget
*aperture_def_report_window
= gtk_scrolled_window_new (NULL
, NULL
);
1072 /* This throws a warning. Must find different approach.... */
1073 gtk_widget_set_size_request(GTK_WIDGET(aperture_def_report_window
),
1076 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(aperture_def_report_window
),
1077 GTK_WIDGET(aperture_def_report_label
));
1079 /* Create GtkLabel to hold aperture use text */
1080 GtkWidget
*aperture_use_report_label
= gtk_label_new (aperture_use_report_string
->str
);
1081 g_string_free (aperture_use_report_string
, TRUE
);
1082 gtk_misc_set_alignment(GTK_MISC(aperture_use_report_label
), 0, 0);
1083 gtk_misc_set_padding(GTK_MISC(aperture_use_report_label
), 13, 13);
1084 gtk_label_set_selectable(GTK_LABEL(aperture_use_report_label
), TRUE
);
1085 gtk_widget_modify_font (GTK_WIDGET(aperture_use_report_label
),
1087 /* Put aperture definintion text into scrolled window */
1088 GtkWidget
*aperture_use_report_window
= gtk_scrolled_window_new (NULL
, NULL
);
1089 /* This throws a warning. Must find different approach.... */
1090 gtk_widget_set_size_request(GTK_WIDGET(aperture_use_report_window
),
1093 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(aperture_use_report_window
),
1094 GTK_WIDGET(aperture_use_report_label
));
1096 /* Create tabbed notebook widget and add report label widgets. */
1097 GtkWidget
*notebook
= gtk_notebook_new();
1099 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1100 GTK_WIDGET(general_code_report_window
),
1101 gtk_label_new("General"));
1103 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1104 GTK_WIDGET(G_report_label
),
1105 gtk_label_new("G codes"));
1107 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1108 GTK_WIDGET(D_report_label
),
1109 gtk_label_new("D codes"));
1111 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1112 GTK_WIDGET(M_report_label
),
1113 gtk_label_new("M codes"));
1115 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1116 GTK_WIDGET(misc_report_label
),
1117 gtk_label_new("Misc. codes"));
1119 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1120 GTK_WIDGET(aperture_def_report_window
),
1121 gtk_label_new("Aperture definitions"));
1123 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1124 GTK_WIDGET(aperture_use_report_window
),
1125 gtk_label_new("Aperture usage"));
1128 /* Now put notebook into dialog window and show the whole thing */
1129 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(analyze_active_gerbers
)->vbox
),
1130 GTK_WIDGET(notebook
));
1132 gtk_widget_show_all(analyze_active_gerbers
);
1134 /* free the stats report */
1135 gerbv_stats_destroy (stats_report
);
1140 /* --------------------------------------------------------- */
1142 * The analyze -> analyze drill file menu item was selected.
1143 * Complie statistics on all open drill layers and then display
1148 callbacks_analyze_active_drill_activate(GtkMenuItem
*menuitem
,
1151 gerbv_drill_stats_t
*stats_report
;
1152 GString
*G_report_string
= g_string_new(NULL
);
1153 GString
*M_report_string
= g_string_new(NULL
);
1154 GString
*misc_report_string
= g_string_new(NULL
);
1155 gerbv_drill_list_t
*my_drill_list
;
1156 GString
*drill_report_string
= g_string_new(NULL
);
1157 GString
*general_report_string
= g_string_new(NULL
);
1158 GString
*error_report_string
= g_string_new(NULL
);
1159 gerbv_error_list_t
*my_error_list
;
1160 gchar
*error_level
= NULL
;
1163 stats_report
= (gerbv_drill_stats_t
*) generate_drill_analysis();
1165 /* General and error window strings */
1166 g_string_printf(general_report_string
, "General information\n");
1167 g_string_append_printf(general_report_string
,
1168 " Active layer count = %d\n",
1169 stats_report
->layer_count
);
1171 g_string_append_printf(general_report_string
,
1172 "\n\nFiles processed:\n");
1173 for (idx
= mainProject
->last_loaded
; idx
>= 0; idx
--) {
1174 if (mainProject
->file
[idx
] &&
1175 mainProject
->file
[idx
]->isVisible
&&
1176 (mainProject
->file
[idx
]->image
->layertype
== GERBV_LAYERTYPE_DRILL
) ) {
1177 g_string_append_printf(general_report_string
,
1179 mainProject
->file
[idx
]->name
);
1184 if (stats_report
->layer_count
== 0) {
1185 g_string_printf(error_report_string
, "\n\nNo drill files active (visible)!\n");
1186 } else if (stats_report
->error_list
->error_text
== NULL
) {
1187 g_string_printf(error_report_string
,
1188 "\n\nNo errors found in active drill file(s)!\n");
1190 g_string_printf(error_report_string
,
1191 "\n\nErrors found in active drill file(s):\n");
1192 for(my_error_list
= stats_report
->error_list
;
1193 my_error_list
!= NULL
;
1194 my_error_list
= my_error_list
->next
) {
1195 switch(my_error_list
->type
) {
1196 case GERBV_MESSAGE_FATAL
: /* We should never get this one since the
1197 * program should terminate first.... */
1198 error_level
= g_strdup_printf("FATAL: ");
1200 case GERBV_MESSAGE_ERROR
:
1201 error_level
= g_strdup_printf("ERROR: ");
1203 case GERBV_MESSAGE_WARNING
:
1204 error_level
= g_strdup_printf("WARNING: ");
1206 case GERBV_MESSAGE_NOTE
:
1207 error_level
= g_strdup_printf("NOTE: ");
1210 g_string_append_printf(error_report_string
,
1212 my_error_list
->layer
,
1214 my_error_list
->error_text
);
1218 g_string_append_printf(general_report_string
,
1219 "%s", error_report_string
->str
);
1220 g_string_free(error_report_string
, TRUE
);
1223 /* G code window strings */
1224 g_string_printf(G_report_string
, "G code statistics (all active layers)\n");
1225 g_string_append_printf(G_report_string
,
1226 "<code> = <number of incidences>\n");
1227 g_string_append_printf(G_report_string
,
1228 "G00 = %-6d (%s)\n",
1231 g_string_append_printf(G_report_string
,
1232 "G01 = %-6d (%s)\n",
1234 "1X linear interpolation");
1235 g_string_append_printf(G_report_string
,
1236 "G02 = %-6d (%s)\n",
1238 "CW interpolation");
1239 g_string_append_printf(G_report_string
,
1240 "G03 = %-6d (%s)\n",
1242 "CCW interpolation");
1243 g_string_append_printf(G_report_string
,
1244 "G04 = %-6d (%s)\n",
1247 g_string_append_printf(G_report_string
,
1248 "G05 = %-6d (%s)\n",
1251 g_string_append_printf(G_report_string
,
1252 "G90 = %-6d (%s)\n",
1255 g_string_append_printf(G_report_string
,
1256 "G91 = %-6d (%s)\n",
1258 "Incremental units");
1259 g_string_append_printf(G_report_string
,
1260 "G93 = %-6d (%s)\n",
1263 g_string_append_printf(G_report_string
,
1264 "Unknown G codes = %d\n",
1265 stats_report
->G_unknown
);
1267 /* M code window strings */
1268 g_string_printf(M_report_string
, "M code statistics (all active layers)\n");
1269 g_string_append_printf(M_report_string
,
1270 "<code> = <number of incidences>\n");
1271 g_string_append_printf(M_report_string
,
1272 "M00 = %-6d (%s)\n",
1275 g_string_append_printf(M_report_string
,
1276 "M01 = %-6d (%s)\n",
1279 g_string_append_printf(M_report_string
,
1280 "M18 = %-6d (%s)\n",
1283 g_string_append_printf(M_report_string
,
1284 "M25 = %-6d (%s)\n",
1287 g_string_append_printf(M_report_string
,
1288 "M30 = %-6d (%s)\n",
1290 "End program rewind");
1291 g_string_append_printf(M_report_string
,
1292 "M31 = %-6d (%s)\n",
1295 g_string_append_printf(M_report_string
,
1296 "M45 = %-6d (%s)\n",
1299 g_string_append_printf(M_report_string
,
1300 "M47 = %-6d (%s)\n",
1302 "Operator message");
1303 g_string_append_printf(M_report_string
,
1304 "M48 = %-6d (%s)\n",
1306 "Begin program header");
1307 g_string_append_printf(M_report_string
,
1308 "M71 = %-6d (%s)\n",
1311 g_string_append_printf(M_report_string
,
1312 "M72 = %-6d (%s)\n",
1315 g_string_append_printf(M_report_string
,
1316 "M95 = %-6d (%s)\n",
1318 "End program header");
1319 g_string_append_printf(M_report_string
,
1320 "M97 = %-6d (%s)\n",
1323 g_string_append_printf(M_report_string
,
1324 "M98 = %-6d (%s)\n",
1327 g_string_append_printf(M_report_string
,
1328 "Unknown M codes = %d\n",
1329 stats_report
->M_unknown
);
1332 /* misc report strings */
1333 g_string_printf(misc_report_string
, "Misc code statistics (all active layers)\n");
1334 g_string_append_printf(misc_report_string
,
1335 "<code> = <number of incidences>\n");
1336 g_string_append_printf(misc_report_string
,
1338 stats_report
->comment
);
1339 g_string_append_printf(misc_report_string
,
1340 "Unknown codes = %d\n",
1341 stats_report
->unknown
);
1343 g_string_append_printf(misc_report_string
,
1348 if (stats_report
->detect
!= NULL
) {
1349 g_string_append_printf(misc_report_string
,
1351 stats_report
->detect
);
1353 /* drill report window strings */
1354 g_string_printf(drill_report_string
, "Drills used (all active layers)\n");
1355 g_string_append_printf(drill_report_string
, "%10s %8s %8s %8s\n",
1356 "Drill no.", "Dia.", "Units", "Count");
1357 for(my_drill_list
= stats_report
->drill_list
;
1358 my_drill_list
!= NULL
;
1359 my_drill_list
= my_drill_list
->next
) {
1360 if (my_drill_list
->drill_num
== -1) break; /* No drill list */
1361 g_string_append_printf(drill_report_string
,
1362 "%10d %8.3f %8s %8d\n",
1363 my_drill_list
->drill_num
,
1364 my_drill_list
->drill_size
,
1365 my_drill_list
->drill_unit
,
1366 my_drill_list
->drill_count
);
1369 g_string_append_printf(drill_report_string
, "Total drill count %d\n",
1370 stats_report
->total_count
);
1372 /* Use fixed width font for all reports */
1373 PangoFontDescription
*font
=
1374 pango_font_description_from_string ("monospace");
1376 /* Create top level dialog window for report */
1377 GtkWidget
*analyze_active_drill
;
1378 analyze_active_drill
= gtk_dialog_new_with_buttons("Drill file codes report",
1380 GTK_DIALOG_DESTROY_WITH_PARENT
,
1382 GTK_RESPONSE_ACCEPT
,
1384 gtk_container_set_border_width (GTK_CONTAINER (analyze_active_drill
), 5);
1385 gtk_dialog_set_default_response (GTK_DIALOG(analyze_active_drill
),
1386 GTK_RESPONSE_ACCEPT
);
1387 g_signal_connect (G_OBJECT(analyze_active_drill
),
1389 G_CALLBACK (gtk_widget_destroy
),
1390 GTK_WIDGET(analyze_active_drill
));
1392 /* Create GtkLabel to hold general report text */
1393 GtkWidget
*general_report_label
= gtk_label_new (general_report_string
->str
);
1394 g_string_free(general_report_string
, TRUE
);
1395 gtk_misc_set_alignment(GTK_MISC(general_report_label
), 0, 0);
1396 gtk_misc_set_padding(GTK_MISC(general_report_label
), 13, 13);
1397 gtk_label_set_selectable(GTK_LABEL(general_report_label
), TRUE
);
1398 gtk_widget_modify_font (GTK_WIDGET(general_report_label
),
1401 /* Create GtkLabel to hold G code text */
1402 GtkWidget
*G_report_label
= gtk_label_new (G_report_string
->str
);
1403 g_string_free(G_report_string
, TRUE
);
1404 gtk_misc_set_alignment(GTK_MISC(G_report_label
), 0, 0);
1405 gtk_misc_set_padding(GTK_MISC(G_report_label
), 13, 13);
1406 gtk_label_set_selectable(GTK_LABEL(G_report_label
), TRUE
);
1407 gtk_widget_modify_font (GTK_WIDGET(G_report_label
),
1410 /* Create GtkLabel to hold M code text */
1411 GtkWidget
*M_report_label
= gtk_label_new (M_report_string
->str
);
1412 g_string_free(M_report_string
, TRUE
);
1413 gtk_misc_set_alignment(GTK_MISC(M_report_label
), 0, 0);
1414 gtk_misc_set_padding(GTK_MISC(M_report_label
), 13, 13);
1415 gtk_label_set_selectable(GTK_LABEL(M_report_label
), TRUE
);
1416 gtk_widget_modify_font (GTK_WIDGET(M_report_label
),
1419 /* Create GtkLabel to hold misc code text */
1420 GtkWidget
*misc_report_label
= gtk_label_new (misc_report_string
->str
);
1421 g_string_free(misc_report_string
, TRUE
);
1422 gtk_misc_set_alignment(GTK_MISC(misc_report_label
), 0, 0);
1423 gtk_misc_set_padding(GTK_MISC(misc_report_label
), 13, 13);
1424 gtk_label_set_selectable(GTK_LABEL(misc_report_label
), TRUE
);
1425 gtk_widget_modify_font (GTK_WIDGET(misc_report_label
),
1428 /* Create GtkLabel to hold drills used text */
1429 GtkWidget
*drill_report_label
= gtk_label_new (drill_report_string
->str
);
1430 g_string_free(drill_report_string
, TRUE
);
1431 gtk_misc_set_alignment(GTK_MISC(drill_report_label
), 0, 0);
1432 gtk_misc_set_padding(GTK_MISC(drill_report_label
), 13, 13);
1433 gtk_label_set_selectable(GTK_LABEL(drill_report_label
), TRUE
);
1434 gtk_widget_modify_font (GTK_WIDGET(drill_report_label
),
1437 /* Create tabbed notebook widget and add report label widgets. */
1438 GtkWidget
*notebook
= gtk_notebook_new();
1440 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1441 GTK_WIDGET(general_report_label
),
1442 gtk_label_new("General"));
1444 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1445 GTK_WIDGET(G_report_label
),
1446 gtk_label_new("G codes"));
1448 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1449 GTK_WIDGET(M_report_label
),
1450 gtk_label_new("M codes"));
1452 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1453 GTK_WIDGET(misc_report_label
),
1454 gtk_label_new("Misc. codes"));
1456 gtk_notebook_append_page(GTK_NOTEBOOK(notebook
),
1457 GTK_WIDGET(drill_report_label
),
1458 gtk_label_new("Drills used"));
1460 /* Now put notebook into dialog window and show the whole thing */
1461 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(analyze_active_drill
)->vbox
),
1462 GTK_WIDGET(notebook
));
1463 gtk_widget_show_all(analyze_active_drill
);
1464 gerbv_drill_stats_destroy (stats_report
);
1468 /* --------------------------------------------------------- */
1470 callbacks_control_gerber_options_activate (GtkMenuItem
*menuitem
,
1476 /* --------------------------------------------------------- */
1478 callbacks_online_manual_activate (GtkMenuItem
*menuitem
,
1484 /* --------------------------------------------------------- */
1486 * The file -> quit menu item was selected or
1487 * the user requested the main window to be closed by other means.
1488 * Check that all changes have been saved, and then quit.
1492 callbacks_quit_activate (GtkMenuItem
*menuitem
,
1495 gboolean layers_dirty
= FALSE
;
1498 for (idx
= 0; idx
<=mainProject
->last_loaded
; idx
++) {
1499 if (mainProject
->file
[idx
] == NULL
) break;
1500 layers_dirty
= layers_dirty
|| mainProject
->file
[idx
]->layer_dirty
;
1504 !interface_get_alert_dialog_response(
1505 "Do you want to close all open layers and quit the program?",
1506 "Quitting the program will cause any unsaved changes to be lost.",
1509 return TRUE
; // stop propagation of the delete_event.
1510 // this would destroy the gui but not return from the gtk event loop.
1512 gerbv_unload_all_layers (mainProject
);
1514 return FALSE
; // more or less... meaningless :)
1517 /* --------------------------------------------------------- */
1519 * The help -> about menu item was selected.
1520 * Show the about dialog.
1524 callbacks_about_activate (GtkMenuItem
*menuitem
,
1527 GtkWidget
*aboutdialog1
;
1528 /* TRANSLATORS: Replace this string with your names, one name per line. */
1529 /* gchar *translators = _("translator-credits"); */
1531 gchar
*string
= g_strdup_printf ( "gerbv -- a Gerber (RS-274/X) viewer.\n\n"
1532 "This is gerbv version %s\n"
1533 "Compiled on %s at %s\n"
1535 "gerbv is part of the gEDA Project.\n"
1537 "For more information see:\n"
1538 " gerbv homepage: http://gerbv.gpleda.org/\n"
1539 " gEDA homepage: http://gpleda.org/\n"
1540 " gEDA Wiki: http://geda.seul.org/wiki/",
1541 VERSION
, __DATE__
, __TIME__
);
1542 #if GTK_CHECK_VERSION(2,6,0)
1543 gchar
*license
= g_strdup_printf("gerbv -- a Gerber (RS-274/X) viewer.\n\n"
1544 "Copyright (C) 2000-2007 Stefan Petersen\n\n"
1545 "This program is free software: you can redistribute it and/or modify\n"
1546 "it under the terms of the GNU General Public License as published by\n"
1547 "the Free Software Foundation, either version 2 of the License, or\n"
1548 "(at your option) any later version.\n\n"
1549 "This program is distributed in the hope that it will be useful,\n"
1550 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1551 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1552 "GNU General Public License for more details.\n\n"
1553 "You should have received a copy of the GNU General Public License\n"
1554 "along with this program. If not, see <http://www.gnu.org/licenses/>.");
1555 #include "authors.c"
1557 aboutdialog1
= gtk_about_dialog_new ();
1558 gtk_container_set_border_width (GTK_CONTAINER (aboutdialog1
), 5);
1559 gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (aboutdialog1
), VERSION
);
1560 gtk_about_dialog_set_name (GTK_ABOUT_DIALOG (aboutdialog1
), _("Gerbv"));
1562 /* gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG (aboutdialog1), translators); */
1563 gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG (aboutdialog1
), string
);
1564 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG (aboutdialog1
), license
);
1566 /* The authors.c file is autogenerated at build time */
1567 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG (aboutdialog1
), authors_string_array
);
1568 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG (aboutdialog1
), "http://gerbv.gpleda.org/");
1570 g_signal_connect (G_OBJECT(aboutdialog1
),"response",
1571 G_CALLBACK (gtk_widget_destroy
), GTK_WIDGET(aboutdialog1
));
1576 aboutdialog1
= gtk_message_dialog_new ( GTK_WINDOW (screen
.win
.topLevelWindow
),
1577 GTK_DIALOG_DESTROY_WITH_PARENT
,
1583 gtk_window_set_title ( GTK_WINDOW (aboutdialog1
), _("About Gerbv"));
1585 /* Destroy the dialog when the user responds to it (e.g. clicks a button) */
1586 g_signal_connect_swapped (aboutdialog1
, "response",
1587 G_CALLBACK (gtk_widget_destroy
),
1592 gtk_widget_show_all(GTK_WIDGET(aboutdialog1
));
1596 /* --------------------------------------------------------- */
1598 * The help -> bugs menu item was selected.
1599 * Show the known bugs window
1603 callbacks_bugs_activate (GtkMenuItem
*menuitem
,
1609 /* Create the top level dialog widget with an OK button */
1610 GtkWidget
*bugs_dialog
= gtk_dialog_new_with_buttons("Known bugs in gerbv",
1612 GTK_DIALOG_DESTROY_WITH_PARENT
,
1613 GTK_STOCK_OK
, GTK_RESPONSE_ACCEPT
,
1615 gtk_container_set_border_width (GTK_CONTAINER (bugs_dialog
), 5);
1616 gtk_dialog_set_default_response (GTK_DIALOG(bugs_dialog
),
1617 GTK_RESPONSE_ACCEPT
);
1618 g_signal_connect (G_OBJECT(bugs_dialog
), "response",
1619 G_CALLBACK (gtk_widget_destroy
), GTK_WIDGET(bugs_dialog
));
1621 /* First create single bugs_string from bugs_string_array */
1622 GString
*bugs_string
= g_string_new(NULL
);
1623 for (i
=0; bugs_string_array
[i
] != NULL
; i
++) {
1624 g_string_append_printf(bugs_string
,
1626 bugs_string_array
[i
]);
1629 /* Create GtkLabel to hold text */
1630 GtkWidget
*bugs_label
= gtk_label_new (bugs_string
->str
);
1631 g_string_free(bugs_string
, TRUE
);
1632 gtk_misc_set_alignment(GTK_MISC(bugs_label
), 0, 0);
1633 gtk_misc_set_padding(GTK_MISC(bugs_label
), 13, 13);
1635 /* Put text into scrolled window */
1636 GtkWidget
*bugs_window
= gtk_scrolled_window_new (NULL
, NULL
);
1637 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(bugs_window
),
1638 GTK_WIDGET(bugs_label
));
1639 gtk_widget_set_size_request(GTK_WIDGET(bugs_window
), 600, 300);
1640 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(bugs_dialog
)->vbox
),
1641 GTK_WIDGET(bugs_window
));
1643 gtk_widget_show_all(GTK_WIDGET(bugs_dialog
));
1644 gtk_dialog_run(GTK_DIALOG(bugs_dialog
));
1648 /* --------------------------------------------------------- */
1649 gdouble
callbacks_calculate_actual_distance (gdouble inputDimension
) {
1650 gdouble returnValue
= 0.0;
1652 if (screen
.unit
== GERBV_MILS
) {
1653 returnValue
= COORD2MILS(inputDimension
);
1654 } else if (screen
.unit
== GERBV_MMS
) {
1655 returnValue
= COORD2MMS(inputDimension
);
1657 returnValue
= COORD2MILS(inputDimension
)/1000;
1662 /* --------------------------------------------------------- */
1663 void callbacks_update_ruler_pointers (void) {
1664 double xPosition
, yPosition
;
1665 xPosition
= screenRenderInfo
.lowerLeftX
+ (screen
.last_x
/ screenRenderInfo
.scaleFactorX
);
1666 yPosition
= screenRenderInfo
.lowerLeftY
+ ((screenRenderInfo
.displayHeight
- screen
.last_y
) / screenRenderInfo
.scaleFactorY
);
1668 if (!((screen
.unit
== GERBV_MILS
) && ((screenRenderInfo
.scaleFactorX
< 80)||(screenRenderInfo
.scaleFactorY
< 80)))) {
1669 xPosition
= callbacks_calculate_actual_distance (xPosition
);
1670 yPosition
= callbacks_calculate_actual_distance (yPosition
);
1672 g_object_set (G_OBJECT (screen
.win
.hRuler
), "position", xPosition
, NULL
);
1673 g_object_set (G_OBJECT (screen
.win
.vRuler
), "position", yPosition
, NULL
);
1676 /* --------------------------------------------------------- */
1678 callbacks_render_type_changed () {
1679 static gboolean isChanging
= FALSE
;
1684 gerbv_render_types_t type
= screenRenderInfo
.renderType
;
1685 GtkCheckMenuItem
*check_item
= screen
.win
.menu_view_render_group
[type
];
1686 dprintf ("%s(): type = %d, check_item = %p\n", __FUNCTION__
, type
, check_item
);
1687 gtk_check_menu_item_set_active (check_item
, TRUE
);
1688 gtk_combo_box_set_active (screen
.win
.sidepaneRenderComboBox
, type
);
1690 render_refresh_rendered_image_on_screen();
1694 /* --------------------------------------------------------- */
1696 callbacks_units_changed (gerbv_gui_unit_t unit
) {
1697 static gboolean isChanging
= FALSE
;
1705 if (unit
== GERBV_MILS
){
1706 gtk_combo_box_set_active (GTK_COMBO_BOX (screen
.win
.statusUnitComboBox
), GERBV_MILS
);
1707 gtk_check_menu_item_set_active (screen
.win
.menu_view_unit_group
[GERBV_MILS
], TRUE
);
1708 } else if (unit
== GERBV_MMS
){
1709 gtk_combo_box_set_active (GTK_COMBO_BOX (screen
.win
.statusUnitComboBox
), GERBV_MMS
);
1710 gtk_check_menu_item_set_active (screen
.win
.menu_view_unit_group
[GERBV_MMS
], TRUE
);
1712 gtk_combo_box_set_active (GTK_COMBO_BOX (screen
.win
.statusUnitComboBox
), GERBV_INS
);
1713 gtk_check_menu_item_set_active (screen
.win
.menu_view_unit_group
[GERBV_INS
], TRUE
);
1716 callbacks_update_ruler_scales ();
1717 callbacks_update_statusbar_coordinates (screen
.last_x
, screen
.last_y
);
1719 if (screen
.tool
== MEASURE
)
1720 callbacks_update_statusbar_measured_distance (screen
.win
.lastMeasuredX
, screen
.win
.lastMeasuredY
);
1725 /* --------------------------------------------------------- */
1727 callbacks_update_ruler_scales (void) {
1728 double xStart
, xEnd
, yStart
, yEnd
;
1730 xStart
= screenRenderInfo
.lowerLeftX
;
1731 yStart
= screenRenderInfo
.lowerLeftY
;
1732 xEnd
= screenRenderInfo
.lowerLeftX
+ (screenRenderInfo
.displayWidth
/ screenRenderInfo
.scaleFactorX
);
1733 yEnd
= screenRenderInfo
.lowerLeftY
+ (screenRenderInfo
.displayHeight
/ screenRenderInfo
.scaleFactorY
);
1734 /* mils can get super crowded with large boards, but inches are too
1735 large for most boards. So, we leave mils in for now and just switch
1736 to inches if the scale factor gets too small */
1737 if (!((screen
.unit
== GERBV_MILS
) && ((screenRenderInfo
.scaleFactorX
< 80)||(screenRenderInfo
.scaleFactorY
< 80)))) {
1738 xStart
= callbacks_calculate_actual_distance (xStart
);
1739 xEnd
= callbacks_calculate_actual_distance (xEnd
);
1740 yStart
= callbacks_calculate_actual_distance (yStart
);
1741 yEnd
= callbacks_calculate_actual_distance (yEnd
);
1743 /* make sure the widgets actually exist before setting (in case this gets
1744 called before everything is realized */
1745 if (screen
.win
.hRuler
)
1746 gtk_ruler_set_range (GTK_RULER (screen
.win
.hRuler
), xStart
, xEnd
, 0, xEnd
- xStart
);
1747 /* reverse y min and max, since the ruler starts at the top */
1748 if (screen
.win
.vRuler
)
1749 gtk_ruler_set_range (GTK_RULER (screen
.win
.vRuler
), yEnd
, yStart
, 0, yEnd
- yStart
);
1752 /* --------------------------------------------------------- */
1753 void callbacks_update_scrollbar_limits (void){
1754 gerbv_render_info_t tempRenderInfo
= {0, 0, 0, 0, 3, screenRenderInfo
.displayWidth
,
1755 screenRenderInfo
.displayHeight
};
1757 GtkAdjustment
*hAdjust
= (GtkAdjustment
*)screen
.win
.hAdjustment
;
1758 GtkAdjustment
*vAdjust
= (GtkAdjustment
*)screen
.win
.vAdjustment
;
1759 gerbv_render_zoom_to_fit_display (mainProject
, &tempRenderInfo
);
1760 hAdjust
->lower
= tempRenderInfo
.lowerLeftX
;
1761 hAdjust
->page_increment
= hAdjust
->page_size
;
1762 hAdjust
->step_increment
= hAdjust
->page_size
/ 10.0;
1763 vAdjust
->lower
= tempRenderInfo
.lowerLeftY
;
1764 vAdjust
->page_increment
= vAdjust
->page_size
;
1765 vAdjust
->step_increment
= vAdjust
->page_size
/ 10.0;
1766 hAdjust
->upper
= tempRenderInfo
.lowerLeftX
+ (tempRenderInfo
.displayWidth
/ tempRenderInfo
.scaleFactorX
);
1767 hAdjust
->page_size
= screenRenderInfo
.displayWidth
/ screenRenderInfo
.scaleFactorX
;
1768 vAdjust
->upper
= tempRenderInfo
.lowerLeftY
+ (tempRenderInfo
.displayHeight
/ tempRenderInfo
.scaleFactorY
);
1769 vAdjust
->page_size
= screenRenderInfo
.displayHeight
/ screenRenderInfo
.scaleFactorY
;
1770 callbacks_update_scrollbar_positions ();
1773 /* --------------------------------------------------------- */
1774 void callbacks_update_scrollbar_positions (void){
1775 gdouble positionX
,positionY
;
1777 positionX
= screenRenderInfo
.lowerLeftX
;
1778 if (positionX
< ((GtkAdjustment
*)screen
.win
.hAdjustment
)->lower
)
1779 positionX
= ((GtkAdjustment
*)screen
.win
.hAdjustment
)->lower
;
1780 if (positionX
> (((GtkAdjustment
*)screen
.win
.hAdjustment
)->upper
- ((GtkAdjustment
*)screen
.win
.hAdjustment
)->page_size
))
1781 positionX
= (((GtkAdjustment
*)screen
.win
.hAdjustment
)->upper
- ((GtkAdjustment
*)screen
.win
.hAdjustment
)->page_size
);
1782 gtk_adjustment_set_value ((GtkAdjustment
*)screen
.win
.hAdjustment
, positionX
);
1784 positionY
= ((GtkAdjustment
*)screen
.win
.vAdjustment
)->upper
- screenRenderInfo
.lowerLeftY
-
1785 ((GtkAdjustment
*)screen
.win
.vAdjustment
)->page_size
+
1786 ((GtkAdjustment
*)screen
.win
.vAdjustment
)->lower
;
1787 if (positionY
< ((GtkAdjustment
*)screen
.win
.vAdjustment
)->lower
)
1788 positionY
= ((GtkAdjustment
*)screen
.win
.vAdjustment
)->lower
;
1789 if (positionY
> (((GtkAdjustment
*)screen
.win
.vAdjustment
)->upper
- ((GtkAdjustment
*)screen
.win
.vAdjustment
)->page_size
))
1790 positionY
= (((GtkAdjustment
*)screen
.win
.vAdjustment
)->upper
- ((GtkAdjustment
*)screen
.win
.vAdjustment
)->page_size
);
1791 gtk_adjustment_set_value ((GtkAdjustment
*)screen
.win
.vAdjustment
, positionY
);
1794 /* --------------------------------------------------------- */
1796 callbacks_scrollbar_button_released (GtkWidget
*widget
, GdkEventButton
*event
){
1799 screen
.state
= NORMAL
;
1800 render_refresh_rendered_image_on_screen();
1804 /* --------------------------------------------------------- */
1806 callbacks_scrollbar_button_pressed (GtkWidget
*widget
, GdkEventButton
*event
){
1807 //screen.last_x = ((GtkAdjustment *)screen.win.hAdjustment)->value;
1808 screen
.state
= SCROLLBAR
;
1812 /* --------------------------------------------------------- */
1813 void callbacks_hadjustment_value_changed (GtkAdjustment
*adjustment
, gpointer user_data
){
1814 /* make sure we're actually using the scrollbar to make sure we don't reset
1815 lowerLeftX during a scrollbar redraw during something else */
1816 if (screen
.state
== SCROLLBAR
) {
1817 screenRenderInfo
.lowerLeftX
= gtk_adjustment_get_value (adjustment
);
1821 /* --------------------------------------------------------- */
1822 void callbacks_vadjustment_value_changed (GtkAdjustment
*adjustment
, gpointer user_data
){
1823 /* make sure we're actually using the scrollbar to make sure we don't reset
1824 lowerLeftY during a scrollbar redraw during something else */
1825 if (screen
.state
== SCROLLBAR
) {
1826 screenRenderInfo
.lowerLeftY
= adjustment
->upper
-
1827 (gtk_adjustment_get_value (adjustment
) + adjustment
->page_size
) + adjustment
->lower
;
1831 /* --------------------------------------------------------- */
1833 callbacks_layer_tree_visibility_button_toggled (GtkCellRendererToggle
*cell_renderer
,
1835 gpointer user_data
){
1836 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
1837 ((GtkTreeView
*) screen
.win
.layerTree
);
1839 gboolean newVisibility
=TRUE
;
1842 gtk_tree_model_get_iter_from_string ((GtkTreeModel
*)list_store
, &iter
, path
);
1844 GtkTreePath
*treePath
= gtk_tree_path_new_from_string (path
);
1845 if (gtk_tree_model_get_iter((GtkTreeModel
*)list_store
, &iter
, treePath
)) {
1848 indices
= gtk_tree_path_get_indices (treePath
);
1850 if (mainProject
->file
[index
]->isVisible
)
1851 newVisibility
= FALSE
;
1852 mainProject
->file
[index
]->isVisible
= newVisibility
;
1853 /* clear any selected items so they don't show after the layer is hidden */
1854 render_clear_selection_buffer();
1856 callbacks_update_layer_tree ();
1857 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
1858 render_refresh_rendered_image_on_screen();
1861 render_recreate_composite_surface (screen
.drawing_area
);
1862 callbacks_force_expose_event_for_screen ();
1867 /* --------------------------------------------------------- */
1869 callbacks_get_col_number_from_tree_view_column (GtkTreeViewColumn
*col
)
1874 g_return_val_if_fail ( col
!= NULL
, -1 );
1875 g_return_val_if_fail ( col
->tree_view
!= NULL
, -1 );
1876 cols
= gtk_tree_view_get_columns(GTK_TREE_VIEW(col
->tree_view
));
1877 num
= g_list_index(cols
, (gpointer
) col
);
1882 /* --------------------------------------------------------- */
1884 callbacks_add_layer_button_clicked (GtkButton
*button
, gpointer user_data
) {
1885 callbacks_open_layer_activate (NULL
, NULL
);
1888 /* --------------------------------------------------------- */
1890 callbacks_unselect_all_tool_buttons (void) {
1895 callbacks_switch_to_normal_tool_cursor (gint toolNumber
) {
1898 switch (toolNumber
) {
1900 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1904 cursor
= gdk_cursor_new(GDK_FLEUR
);
1905 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1907 gdk_cursor_destroy(cursor
);
1910 cursor
= gdk_cursor_new(GDK_SIZING
);
1911 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1913 gdk_cursor_destroy(cursor
);
1916 cursor
= gdk_cursor_new(GDK_CROSSHAIR
);
1917 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1919 gdk_cursor_destroy(cursor
);
1926 /* --------------------------------------------------------- */
1928 callbacks_switch_to_correct_cursor (void) {
1931 if (screen
.state
== IN_MOVE
) {
1932 cursor
= gdk_cursor_new(GDK_FLEUR
);
1933 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1935 gdk_cursor_destroy(cursor
);
1938 else if (screen
.state
== IN_ZOOM_OUTLINE
) {
1939 cursor
= gdk_cursor_new(GDK_SIZING
);
1940 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
1942 gdk_cursor_destroy(cursor
);
1945 callbacks_switch_to_normal_tool_cursor (screen
.tool
);
1948 /* --------------------------------------------------------- */
1950 callbacks_change_tool (GtkButton
*button
, gpointer user_data
) {
1951 gint toolNumber
= GPOINTER_TO_INT (user_data
);
1953 /* make sure se don't get caught in endless recursion here */
1954 if (screen
.win
.updatingTools
)
1956 screen
.win
.updatingTools
= TRUE
;
1957 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonPointer
), FALSE
);
1958 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonPan
), FALSE
);
1959 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonZoom
), FALSE
);
1960 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonMeasure
), FALSE
);
1961 switch (toolNumber
) {
1963 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonPointer
), TRUE
);
1964 screen
.tool
= POINTER
;
1965 screen
.state
= NORMAL
;
1966 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
1967 "Click to select objects in the current layer. Middle click and drag to pan.");
1970 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonPan
), TRUE
);
1972 screen
.state
= NORMAL
;
1973 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
1974 "Click and drag to pan. Right click and drag to zoom.");
1977 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonZoom
), TRUE
);
1979 screen
.state
= NORMAL
;
1980 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
1981 "Click and drag to zoom in. Shift+click to zoom out.");
1984 gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (screen
.win
.toolButtonMeasure
), TRUE
);
1985 screen
.tool
= MEASURE
;
1986 screen
.state
= NORMAL
;
1987 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
, "Click and drag to measure a distance.");
1992 callbacks_switch_to_normal_tool_cursor (toolNumber
);
1993 callbacks_update_statusbar();
1994 screen
.win
.updatingTools
= FALSE
;
1995 callbacks_force_expose_event_for_screen();
1998 /* --------------------------------------------------------- */
2000 callbacks_select_row (gint rowIndex
) {
2001 GtkTreeSelection
*selection
;
2003 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
2004 ((GtkTreeView
*) screen
.win
.layerTree
);
2006 selection
= gtk_tree_view_get_selection((GtkTreeView
*) screen
.win
.layerTree
);
2007 if (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store
), &iter
, NULL
, rowIndex
)) {
2008 gtk_tree_selection_select_iter (selection
, &iter
);
2012 /* --------------------------------------------------------- */
2014 * This fcn returns the index of selected layer (selected in
2015 * the layer window on left).
2019 callbacks_get_selected_row_index (void) {
2020 GtkTreeSelection
*selection
;
2022 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
2023 ((GtkTreeView
*) screen
.win
.layerTree
);
2026 /* This will only work in single or browse selection mode! */
2027 selection
= gtk_tree_view_get_selection((GtkTreeView
*) screen
.win
.layerTree
);
2028 if (gtk_tree_selection_get_selected(selection
, NULL
, &iter
)) {
2029 while (gtk_tree_model_iter_nth_child ((GtkTreeModel
*)list_store
,
2031 if (gtk_tree_selection_iter_is_selected (selection
, &iter
)) {
2040 /* --------------------------------------------------------- */
2042 callbacks_remove_layer_button_clicked (GtkButton
*button
, gpointer user_data
) {
2043 gint index
=callbacks_get_selected_row_index();
2045 if ((index
>= 0) && (index
<= mainProject
->last_loaded
)) {
2046 render_remove_selected_objects_belonging_to_layer (index
);
2047 gerbv_unload_layer (mainProject
, index
);
2048 callbacks_update_layer_tree ();
2049 callbacks_select_row (0);
2051 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
2052 render_refresh_rendered_image_on_screen();
2055 render_recreate_composite_surface (screen
.drawing_area
);
2056 callbacks_force_expose_event_for_screen ();
2061 /* --------------------------------------------------------- */
2063 callbacks_move_layer_down_menu_activate (GtkMenuItem
*menuitem
, gpointer user_data
) {
2064 callbacks_move_layer_down_button_clicked(NULL
, NULL
);
2065 gtk_widget_grab_focus (screen
.win
.layerTree
);
2068 /* --------------------------------------------------------- */
2070 callbacks_move_layer_down_button_clicked (GtkButton
*button
, gpointer user_data
) {
2071 gint index
=callbacks_get_selected_row_index();
2073 show_no_layers_warning ();
2077 if (index
< mainProject
->last_loaded
) {
2078 gerbv_change_layer_order (mainProject
, index
, index
+ 1);
2079 callbacks_update_layer_tree ();
2080 callbacks_select_row (index
+ 1);
2081 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
2082 render_refresh_rendered_image_on_screen ();
2085 render_recreate_composite_surface (screen
.drawing_area
);
2086 callbacks_force_expose_event_for_screen ();
2091 /* --------------------------------------------------------- */
2093 callbacks_move_layer_up_menu_activate (GtkMenuItem
*menuitem
, gpointer user_data
) {
2094 callbacks_move_layer_up_button_clicked (NULL
, NULL
);
2095 gtk_widget_grab_focus (screen
.win
.layerTree
);
2098 /* --------------------------------------------------------- */
2100 callbacks_move_layer_up_button_clicked (GtkButton
*button
, gpointer user_data
) {
2101 gint index
=callbacks_get_selected_row_index();
2103 show_no_layers_warning ();
2107 gerbv_change_layer_order (mainProject
, index
, index
- 1);
2108 callbacks_update_layer_tree ();
2109 callbacks_select_row (index
- 1);
2110 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
2111 render_refresh_rendered_image_on_screen();
2114 render_recreate_composite_surface (screen
.drawing_area
);
2115 callbacks_force_expose_event_for_screen ();
2120 /* --------------------------------------------------------- */
2121 void callbacks_layer_tree_row_inserted (GtkTreeModel
*tree_model
, GtkTreePath
*path
,
2122 GtkTreeIter
*oIter
, gpointer user_data
) {
2123 gint
*indices
=NULL
,oldPosition
,newPosition
;
2125 if ((!screen
.win
.treeIsUpdating
)&&(path
!= NULL
)) {
2126 indices
= gtk_tree_path_get_indices (path
);
2128 newPosition
= indices
[0];
2129 oldPosition
= callbacks_get_selected_row_index ();
2130 /* compensate for the fact that the old row has already
2132 if (oldPosition
< newPosition
)
2136 gerbv_change_layer_order (mainProject
, oldPosition
, newPosition
);
2138 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
2139 render_refresh_rendered_image_on_screen();
2142 render_recreate_composite_surface (screen
.drawing_area
);
2143 callbacks_force_expose_event_for_screen ();
2145 /* select the new line */
2146 GtkTreeSelection
*selection
;
2148 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
2149 ((GtkTreeView
*) screen
.win
.layerTree
);
2151 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(screen
.win
.layerTree
));
2152 if (gtk_tree_model_get_iter ((GtkTreeModel
*)list_store
, &iter
, path
))
2153 gtk_tree_selection_select_iter (selection
, &iter
);
2158 /* --------------------------------------------------------- */
2160 callbacks_show_color_picker_dialog (gint index
){
2161 screen
.win
.colorSelectionDialog
= NULL
;
2162 GtkColorSelectionDialog
*cs
= (GtkColorSelectionDialog
*) gtk_color_selection_dialog_new ("Select a color");
2163 GtkColorSelection
*colorsel
= (GtkColorSelection
*) cs
->colorsel
;
2165 screen
.win
.colorSelectionDialog
= (GtkWidget
*) cs
;
2166 screen
.win
.colorSelectionIndex
= index
;
2168 gtk_color_selection_set_current_color (colorsel
, &mainProject
->file
[index
]->color
);
2170 gtk_color_selection_set_current_color (colorsel
, &mainProject
->background
);
2171 if ((screenRenderInfo
.renderType
>= GERBV_RENDER_TYPE_CAIRO_NORMAL
)&&(index
>= 0)) {
2172 gtk_color_selection_set_has_opacity_control (colorsel
, TRUE
);
2173 gtk_color_selection_set_current_alpha (colorsel
, mainProject
->file
[index
]->alpha
);
2175 gtk_widget_show_all((GtkWidget
*)cs
);
2176 if (gtk_dialog_run ((GtkDialog
*)cs
) == GTK_RESPONSE_OK
) {
2177 GtkColorSelection
*colorsel
= (GtkColorSelection
*) cs
->colorsel
;
2178 gint rowIndex
= screen
.win
.colorSelectionIndex
;
2181 gtk_color_selection_get_current_color (colorsel
, &mainProject
->file
[rowIndex
]->color
);
2182 gdk_colormap_alloc_color(gdk_colormap_get_system(), &mainProject
->file
[rowIndex
]->color
, FALSE
, TRUE
);
2185 gtk_color_selection_get_current_color (colorsel
, &mainProject
->background
);
2186 gdk_colormap_alloc_color(gdk_colormap_get_system(), &mainProject
->background
, FALSE
, TRUE
);
2188 if ((screenRenderInfo
.renderType
>= GERBV_RENDER_TYPE_CAIRO_NORMAL
)&&(index
>= 0)) {
2189 mainProject
->file
[rowIndex
]->alpha
= gtk_color_selection_get_current_alpha (colorsel
);
2192 callbacks_update_layer_tree ();
2193 render_refresh_rendered_image_on_screen();
2195 gtk_widget_destroy ((GtkWidget
*)cs
);
2196 screen
.win
.colorSelectionDialog
= NULL
;
2199 /* --------------------------------------------------------- */
2201 callbacks_invert_layer_clicked (GtkButton
*button
, gpointer user_data
) {
2202 gint index
=callbacks_get_selected_row_index();
2204 show_no_layers_warning ();
2207 mainProject
->file
[index
]->transform
.inverted
= !mainProject
->file
[index
]->transform
.inverted
;
2208 render_refresh_rendered_image_on_screen ();
2209 callbacks_update_layer_tree ();
2212 /* --------------------------------------------------------- */
2214 callbacks_change_layer_color_clicked (GtkButton
*button
, gpointer user_data
) {
2215 gint index
=callbacks_get_selected_row_index();
2217 show_no_layers_warning ();
2220 callbacks_show_color_picker_dialog (index
);
2224 callbacks_change_background_color_clicked (GtkButton
*button
, gpointer user_data
) {
2225 callbacks_show_color_picker_dialog (-1);
2228 /* --------------------------------------------------------------------------- */
2230 callbacks_reload_layer_clicked (GtkButton
*button
, gpointer user_data
) {
2231 gint index
= callbacks_get_selected_row_index();
2233 show_no_layers_warning ();
2236 render_remove_selected_objects_belonging_to_layer (index
);
2237 gerbv_revert_file (mainProject
, index
);
2238 render_refresh_rendered_image_on_screen ();
2239 callbacks_update_layer_tree();
2243 callbacks_change_layer_orientation_clicked (GtkButton
*button
, gpointer userData
){
2244 gint index
= callbacks_get_selected_row_index();
2247 show_no_layers_warning ();
2251 interface_show_modify_orientation_dialog(&mainProject
->file
[index
]->transform
,screen
.unit
);
2252 render_refresh_rendered_image_on_screen ();
2253 callbacks_update_layer_tree ();
2256 /* --------------------------------------------------------------------------- */
2258 callbacks_change_layer_format_clicked (GtkButton
*button
, gpointer user_data
)
2260 gerbv_HID_Attribute
*attr
= NULL
;
2263 gerbv_HID_Attr_Val
* results
= NULL
;
2264 gint index
= callbacks_get_selected_row_index();
2268 show_no_layers_warning ();
2271 dprintf ("%s(): index = %d\n", __FUNCTION__
, index
);
2272 attr
= mainProject
->file
[index
]->image
->info
->attr_list
;
2273 n
= mainProject
->file
[index
]->image
->info
->n_attr
;
2274 type
= mainProject
->file
[index
]->image
->info
->type
;
2278 if (attr
== NULL
|| n
== 0)
2280 interface_show_alert_dialog("This file type does not currently have any editable features",
2281 "Format editing is currently only supported for Excellon drill file formats.",
2287 dprintf ("%s(): n = %d, attr = %p\n", __FUNCTION__
, n
, attr
);
2290 if (mainProject
->file
[index
]->layer_dirty
) {
2291 rc
= interface_get_alert_dialog_response ("This layer has changed!",
2292 "Editing the file type will reload the layer, destroying your changes. Click OK to edit the file type and destroy your changes, or Cancel to leave.",
2295 if (rc
== 0) return; /* Return if user hit Cancel */
2298 results
= (gerbv_HID_Attr_Val
*) malloc (n
* sizeof (gerbv_HID_Attr_Val
));
2299 if (results
== NULL
)
2301 fprintf (stderr
, "%s() -- malloc failed\n", __FUNCTION__
);
2305 /* non-zero means cancel was picked */
2306 if (attribute_interface_dialog (attr
, n
, results
,
2315 dprintf ("%s(): Reloading layer\n", __FUNCTION__
);
2316 gerbv_revert_file (mainProject
, index
);
2318 for (i
= 0; i
< n
; i
++)
2320 if (results
[i
].str_value
)
2321 free (results
[i
].str_value
);
2326 render_refresh_rendered_image_on_screen();
2327 callbacks_update_layer_tree();
2330 /* --------------------------------------------------------------------------- */
2332 callbacks_layer_tree_key_press (GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
) {
2333 /* if space is pressed while a color picker icon is in focus,
2334 show the color picker dialog. */
2335 if(event
->keyval
== GDK_space
){
2338 GtkTreeViewColumn
*col
;
2342 tree
= (GtkTreeView
*) screen
.win
.layerTree
;
2343 gtk_tree_view_get_cursor (tree
, &path
, &col
);
2345 indices
= gtk_tree_path_get_indices (path
);
2347 idx
= callbacks_get_col_number_from_tree_view_column (col
);
2348 if ((idx
== 1) && (indices
[0] <= mainProject
->last_loaded
)){
2349 callbacks_show_color_picker_dialog (indices
[0]);
2352 gtk_tree_path_free (path
);
2355 /* by default propagate the key press */
2359 /* --------------------------------------------------------------------------- */
2361 callbacks_layer_tree_button_press (GtkWidget
*widget
, GdkEventButton
*event
,
2362 gpointer user_data
) {
2365 GtkTreeViewColumn
*column
;
2369 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
2370 ((GtkTreeView
*) screen
.win
.layerTree
);
2371 if (event
->button
== 1) {
2372 if (gtk_tree_view_get_path_at_pos ((GtkTreeView
*) widget
, event
->x
, event
->y
,
2373 &path
, &column
, &x
, &y
)) {
2374 if (gtk_tree_model_get_iter((GtkTreeModel
*)list_store
, &iter
, path
)) {
2376 indices
= gtk_tree_path_get_indices (path
);
2378 columnIndex
= callbacks_get_col_number_from_tree_view_column (column
);
2379 if ((columnIndex
== 1) && (indices
[0] <= mainProject
->last_loaded
)){
2380 callbacks_show_color_picker_dialog (indices
[0]);
2381 /* don't propagate the signal, since drag and drop can
2382 sometimes activated during color selection */
2389 /* don't pop up the menu if we don't have any loaded files */
2390 else if ((event
->button
== 3)&&(mainProject
->last_loaded
>= 0)) {
2391 gtk_menu_popup(GTK_MENU(screen
.win
.layerTreePopupMenu
), NULL
, NULL
, NULL
, NULL
,
2392 event
->button
, event
->time
);
2394 /* always allow the click to propagate and make sure the line is activated */
2398 /* --------------------------------------------------------------------------- */
2400 callbacks_update_layer_tree (void) {
2401 GtkListStore
*list_store
= (GtkListStore
*) gtk_tree_view_get_model
2402 ((GtkTreeView
*) screen
.win
.layerTree
);
2405 GtkTreeSelection
*selection
;
2406 gint oldSelectedRow
;
2408 if (!screen
.win
.treeIsUpdating
) {
2409 screen
.win
.treeIsUpdating
= TRUE
;
2411 oldSelectedRow
= callbacks_get_selected_row_index();
2412 if (oldSelectedRow
< 0)
2414 gtk_list_store_clear (list_store
);
2416 for (idx
= 0; idx
<= mainProject
->last_loaded
; idx
++) {
2417 if (mainProject
->file
[idx
]) {
2418 GdkPixbuf
*pixbuf
,*blackPixbuf
;
2421 unsigned char red
, green
, blue
, alpha
;
2423 red
= (unsigned char) (mainProject
->file
[idx
]->color
.red
* 255 / G_MAXUINT16
) ;
2424 green
= (unsigned char) (mainProject
->file
[idx
]->color
.green
* 255 / G_MAXUINT16
) ;
2425 blue
= (unsigned char) (mainProject
->file
[idx
]->color
.blue
*255 / G_MAXUINT16
) ;
2426 alpha
= (unsigned char) (mainProject
->file
[idx
]->alpha
* 255 / G_MAXUINT16
) ;
2428 color
= (red
)* (256*256*256) + (green
) * (256*256) + (blue
)* (256) + (alpha
);
2429 pixbuf
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
, TRUE
, 8, 20, 15);
2430 gdk_pixbuf_fill (pixbuf
, color
);
2432 blackPixbuf
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
, TRUE
, 8, 20, 15);
2433 color
= (100 )* (256*256*256) + (100 ) * (256*256) + (100 )* (256) + (150 );
2434 gdk_pixbuf_fill (blackPixbuf
, color
);
2436 /* copy the color area into the black pixbuf */
2437 gdk_pixbuf_copy_area (pixbuf
, 1, 1, 18, 13, blackPixbuf
, 1, 1);
2438 /* free the color buffer, since we don't need it anymore */
2439 g_object_unref(pixbuf
);
2441 gtk_list_store_append (list_store
, &iter
);
2443 gchar startChar
[2],*modifiedCode
;
2444 /* terminate the letter string */
2447 gint numberOfModifications
= 0;
2448 if (mainProject
->file
[idx
]->transform
.inverted
) {
2450 numberOfModifications
++;
2452 if (mainProject
->file
[idx
]->transform
.mirrorAroundX
||
2453 mainProject
->file
[idx
]->transform
.mirrorAroundY
) {
2455 numberOfModifications
++;
2457 if ((fabs(mainProject
->file
[idx
]->transform
.translateX
) > 0.000001) ||
2458 (fabs(mainProject
->file
[idx
]->transform
.translateY
) > 0.000001)) {
2460 numberOfModifications
++;
2462 if ((fabs(mainProject
->file
[idx
]->transform
.scaleX
- 1) > 0.000001) ||
2463 (fabs(mainProject
->file
[idx
]->transform
.scaleY
- 1) > 0.000001)) {
2465 numberOfModifications
++;
2467 if ((fabs(mainProject
->file
[idx
]->transform
.rotation
) > 0.000001)) {
2469 numberOfModifications
++;
2471 if (numberOfModifications
> 1)
2473 if (numberOfModifications
== 0)
2474 modifiedCode
= g_strdup ("");
2476 modifiedCode
= g_strdup (startChar
);
2478 /* display any unsaved layers differently to show the user they are
2481 if (mainProject
->file
[idx
]->layer_dirty
== TRUE
) {
2482 /* The layer has unsaved changes in it. Show layer name in italics. */
2483 layerName
= g_strconcat ("*","<i>",mainProject
->file
[idx
]->name
,"</i>",NULL
);
2486 /* layer is clean. Show layer name using normal font. */
2487 layerName
= g_strdup (mainProject
->file
[idx
]->name
);
2489 gtk_list_store_set (list_store
, &iter
,
2490 0, mainProject
->file
[idx
]->isVisible
,
2496 g_free (modifiedCode
);
2497 /* pixbuf has a refcount of 2 now, as the list store has added its own reference */
2498 g_object_unref(blackPixbuf
);
2502 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(screen
.win
.layerTree
));
2504 /* if no line is selected yet, select the first row (if it has data) */
2505 /* or, select the line that was previously selected */
2507 if (!gtk_tree_selection_get_selected (selection
, NULL
, &iter
)) {
2508 if (gtk_tree_model_iter_nth_child ((GtkTreeModel
*) list_store
,
2509 &iter
, NULL
, oldSelectedRow
)) {
2510 gtk_tree_selection_select_iter (selection
, &iter
);
2513 gboolean showItems
= (mainProject
->last_loaded
>= 0);
2514 gtk_widget_set_sensitive (screen
.win
.curLayerMenuItem
, showItems
);
2515 gtk_widget_set_sensitive (screen
.win
.curAnalyzeMenuItem
, showItems
);
2516 gtk_widget_set_sensitive (screen
.win
.curEditMenuItem
, showItems
);
2517 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem1
, showItems
);
2518 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem2
, showItems
);
2519 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem3
, showItems
);
2520 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem4
, showItems
);
2521 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem5
, showItems
);
2522 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem6
, showItems
);
2523 gtk_widget_set_sensitive (screen
.win
.curFileMenuItem7
, showItems
);
2524 screen
.win
.treeIsUpdating
= FALSE
;
2528 /* --------------------------------------------------------------------------- */
2530 callbacks_display_object_properties_clicked (GtkButton
*button
, gpointer user_data
) {
2534 gboolean validAperture
;
2536 gint index
=callbacks_get_selected_row_index ();
2537 if (index
< 0 || screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
) {
2538 interface_show_alert_dialog("No object is currently selected",
2539 "Objects must be selected using the pointer tool before you can view the object properties.",
2545 for (i
=0; i
<screen
.selectionInfo
.selectedNodeArray
->len
; i
++){
2546 gerbv_selection_item_t sItem
= g_array_index (screen
.selectionInfo
.selectedNodeArray
,
2547 gerbv_selection_item_t
, i
);
2549 gerbv_net_t
*net
= sItem
.net
;
2550 gerbv_image_t
*image
= sItem
.image
;
2553 /* get the aperture definition for the selected item */
2554 if (net
->aperture
> 0) {
2555 ap_type
= image
->aperture
[net
->aperture
]->type
;
2556 validAperture
= TRUE
;
2559 validAperture
= FALSE
;
2562 /* Also get layer name specified in file by %LN directive
2563 * (if it exists). */
2564 if (net
->layer
->name
== NULL
) {
2565 layer_name
= g_strdup("<unnamed layer>");
2567 layer_name
= g_strdup(net
->layer
->name
);
2570 if (net
->label
== NULL
) {
2571 net_label
= g_strdup("<unlabeled net>");
2573 net_label
= g_strdup((gchar
*)net
->label
);
2575 if (net
->interpolation
== GERBV_INTERPOLATION_PAREA_START
) {
2576 g_message ("Object type: Polygon\n");
2579 switch (net
->aperture_state
){
2580 case GERBV_APERTURE_STATE_OFF
:
2582 case GERBV_APERTURE_STATE_ON
:
2583 if (i
!=0) g_message ("\n"); /* Spacing for a pretty display */
2584 switch (net
->interpolation
) {
2585 case GERBV_INTERPOLATION_x10
:
2586 case GERBV_INTERPOLATION_LINEARx01
:
2587 case GERBV_INTERPOLATION_LINEARx001
:
2588 case GERBV_INTERPOLATION_LINEARx1
:
2589 g_message ("Object type: Line\n");
2591 case GERBV_INTERPOLATION_CW_CIRCULAR
:
2592 case GERBV_INTERPOLATION_CCW_CIRCULAR
:
2593 g_message ("Object type: Arc\n");
2596 g_message ("Object type: Unknown\n");
2599 g_message (" Exposure: On\n");
2600 if (validAperture
) {
2601 g_message (" Aperture used: D%d\n", net
->aperture
);
2602 g_message (" Aperture type: %s\n", ap_names
[ap_type
]);
2604 g_message (" Start location: (%g, %g)\n", net
->start_x
, net
->start_y
);
2605 g_message (" Stop location: (%g, %g)\n", net
->stop_x
, net
->stop_y
);
2606 g_message (" Layer name: %s\n", layer_name
);
2607 g_message (" Net label: %s\n", net_label
);
2608 g_message (" In file: %s\n", mainProject
->file
[index
]->name
);
2610 case GERBV_APERTURE_STATE_FLASH
:
2611 if (i
!=0) g_message ("\n"); /* Spacing for a pretty display */
2612 g_message ("Object type: Flashed aperture\n");
2613 if (validAperture
) {
2614 g_message (" Aperture used: D%d\n", net
->aperture
);
2615 g_message (" Aperture type: %s\n", ap_names
[ap_type
]);
2617 g_message (" Location: (%g, %g)\n", net
->stop_x
, net
->stop_y
);
2618 g_message (" Layer name: %s\n", layer_name
);
2619 g_message (" Net label: %s\n", net_label
);
2620 g_message (" In file: %s\n", mainProject
->file
[index
]->name
);
2625 g_free (layer_name
);
2627 /* Use separator for different report requests */
2628 g_message ("---------------------------------------\n");
2632 callbacks_support_benchmark (gerbv_render_info_t
*renderInfo
) {
2635 GdkPixmap
*renderedPixmap
= gdk_pixmap_new (NULL
, renderInfo
->displayWidth
,
2636 renderInfo
->displayHeight
, 24);
2638 // start by running the GDK (fast) rendering test
2642 while( now
- 30 < start
) {
2644 dprintf("Benchmark(): Starting redraw #%d\n", i
);
2645 gerbv_render_to_pixmap_using_gdk (mainProject
, renderedPixmap
, renderInfo
, NULL
, NULL
);
2647 dprintf("Elapsed time = %ld seconds\n", (long int) (now
- start
));
2649 g_message("FAST (=GDK) mode benchmark: %d redraws in %ld seconds (%g redraws/second)\n",
2650 i
, (long int) (now
- start
), (double) i
/ (double)(now
- start
));
2651 gdk_pixmap_unref(renderedPixmap
);
2653 // run the cairo (normal) render mode
2657 renderInfo
->renderType
= GERBV_RENDER_TYPE_CAIRO_NORMAL
;
2658 while( now
- 30 < start
) {
2660 dprintf("Benchmark(): Starting redraw #%d\n", i
);
2661 cairo_surface_t
*cSurface
= cairo_image_surface_create (CAIRO_FORMAT_ARGB32
,
2662 renderInfo
->displayWidth
, renderInfo
->displayHeight
);
2663 cairo_t
*cairoTarget
= cairo_create (cSurface
);
2664 gerbv_render_all_layers_to_cairo_target (mainProject
, cairoTarget
, renderInfo
);
2665 cairo_destroy (cairoTarget
);
2666 cairo_surface_destroy (cSurface
);
2668 dprintf("Elapsed time = %ld seconds\n", (long int) (now
- start
));
2670 g_message("NORMAL (=Cairo) mode benchmark: %d redraws in %ld seconds (%g redraws/second)\n",
2671 i
, (long int) (now
- start
), (double) i
/ (double)(now
- start
));
2674 /* --------------------------------------------------------------------------- */
2676 callbacks_benchmark_clicked (GtkButton
*button
, gpointer user_data
)
2678 // prepare render size and options (canvas size width and height are last 2 variables)
2679 gerbv_render_info_t renderInfo
= {1.0, 1.0, 0, 0, 0, 640, 480};
2680 // autoscale the image for now...maybe we don't want to do this in order to
2681 // allow benchmarking of different zoom levels?
2682 gerbv_render_zoom_to_fit_display (mainProject
, &renderInfo
);
2684 g_message("Full zoom benchmarks\n");
2685 callbacks_support_benchmark (&renderInfo
);
2688 g_message("x5 zoom benchmarks\n");
2689 renderInfo
.lowerLeftX
+= (screenRenderInfo
.displayWidth
/
2690 screenRenderInfo
.scaleFactorX
) / 3.0;
2691 renderInfo
.lowerLeftY
+= (screenRenderInfo
.displayHeight
/
2692 screenRenderInfo
.scaleFactorY
) / 3.0;
2693 renderInfo
.scaleFactorX
*= 5;
2694 renderInfo
.scaleFactorY
*= 5;
2695 callbacks_support_benchmark (&renderInfo
);
2698 /* --------------------------------------------------------------------------- */
2700 callbacks_edit_object_properties_clicked (GtkButton
*button
, gpointer user_data
){
2703 /* --------------------------------------------------------------------------- */
2705 callbacks_move_objects_clicked (GtkButton
*button
, gpointer user_data
){
2706 /* for testing, just hard code in some translations here */
2707 gerbv_image_move_selected_objects (screen
.selectionInfo
.selectedNodeArray
, -0.050, 0.050);
2708 callbacks_update_layer_tree();
2709 render_clear_selection_buffer ();
2710 render_refresh_rendered_image_on_screen ();
2713 /* --------------------------------------------------------------------------- */
2715 callbacks_reduce_object_area_clicked (GtkButton
*button
, gpointer user_data
){
2716 /* for testing, just hard code in some parameters */
2717 gerbv_image_reduce_area_of_selected_objects (screen
.selectionInfo
.selectedNodeArray
, 0.20, 3, 3, 0.01);
2718 render_clear_selection_buffer ();
2719 render_refresh_rendered_image_on_screen ();
2722 /* --------------------------------------------------------------------------- */
2724 callbacks_delete_objects_clicked (GtkButton
*button
, gpointer user_data
){
2725 if (screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
) {
2726 interface_show_alert_dialog("No object is currently selected",
2727 "Objects must be selected using the pointer tool before they can be deleted.",
2733 gint index
=callbacks_get_selected_row_index();
2737 if (mainProject
->check_before_delete
== TRUE
) {
2738 if (!interface_get_alert_dialog_response(
2739 "Do you want to permanently delete the selected objects?",
2740 "Gerbv currently has no undo function, so this action cannot be undone. This action will not change the saved file unless you save the file afterwards.",
2742 &(mainProject
->check_before_delete
)))
2746 gerbv_image_delete_selected_nets (mainProject
->file
[index
]->image
,
2747 screen
.selectionInfo
.selectedNodeArray
);
2748 render_refresh_rendered_image_on_screen ();
2749 /* Set layer_dirty flag to TRUE */
2750 mainProject
->file
[index
]->layer_dirty
= TRUE
;
2751 callbacks_update_layer_tree();
2753 render_clear_selection_buffer ();
2754 callbacks_update_selected_object_message(FALSE
);
2757 /* --------------------------------------------------------------------------- */
2759 callbacks_drawingarea_configure_event (GtkWidget
*widget
, GdkEventConfigure
*event
)
2761 GdkDrawable
*drawable
= widget
->window
;
2763 gdk_drawable_get_size (drawable
, &screenRenderInfo
.displayWidth
, &screenRenderInfo
.displayHeight
);
2765 /* set this up if cairo is compiled, since we may need to switch over to
2766 using the surface at any time */
2767 int x_off
=0, y_off
=0;
2770 if (GDK_IS_WINDOW(widget
->window
)) {
2771 /* query the window's backbuffer if it has one */
2772 GdkWindow
*window
= GDK_WINDOW(widget
->window
);
2773 gdk_window_get_internal_paint_info (window
, &drawable
, &x_off
, &y_off
);
2775 visual
= gdk_drawable_get_visual (drawable
);
2776 if (screen
.windowSurface
)
2777 cairo_surface_destroy ((cairo_surface_t
*)
2778 screen
.windowSurface
);
2780 #if defined(WIN32) || defined(QUARTZ)
2781 cairo_t
*cairoTarget
= gdk_cairo_create (GDK_WINDOW(widget
->window
));
2783 screen
.windowSurface
= cairo_get_target (cairoTarget
);
2784 /* increase surface reference by one so it isn't freed when the cairo_t
2785 is destroyed next */
2786 screen
.windowSurface
= cairo_surface_reference (screen
.windowSurface
);
2787 cairo_destroy (cairoTarget
);
2789 screen
.windowSurface
= (gpointer
) cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable
),
2790 GDK_DRAWABLE_XID (drawable
),
2791 GDK_VISUAL_XVISUAL (visual
),
2792 screenRenderInfo
.displayWidth
,
2793 screenRenderInfo
.displayHeight
);
2795 /* if this is the first time, go ahead and call autoscale even if we don't
2796 have a model loaded */
2797 if ((screenRenderInfo
.scaleFactorX
< 0.001)||(screenRenderInfo
.scaleFactorY
< 0.001)) {
2798 gerbv_render_zoom_to_fit_display (mainProject
, &screenRenderInfo
);
2800 render_refresh_rendered_image_on_screen();
2804 /* --------------------------------------------------------- */
2806 callbacks_drawingarea_expose_event (GtkWidget
*widget
, GdkEventExpose
*event
)
2808 if (screenRenderInfo
.renderType
<= GERBV_RENDER_TYPE_GDK_XOR
) {
2809 GdkPixmap
*new_pixmap
;
2810 GdkGC
*gc
= gdk_gc_new(widget
->window
);
2813 * Create a pixmap with default background
2815 new_pixmap
= gdk_pixmap_new(widget
->window
,
2816 widget
->allocation
.width
,
2817 widget
->allocation
.height
,
2820 gdk_gc_set_foreground(gc
, &mainProject
->background
);
2822 gdk_draw_rectangle(new_pixmap
, gc
, TRUE
,
2823 event
->area
.x
, event
->area
.y
,
2824 event
->area
.width
, event
->area
.height
);
2827 * Copy gerber pixmap onto background if we have one to copy.
2828 * Do translation at the same time.
2830 if (screen
.pixmap
!= NULL
) {
2831 gdk_draw_pixmap(new_pixmap
,
2832 widget
->style
->fg_gc
[GTK_WIDGET_STATE (widget
)],
2834 event
->area
.x
- screen
.off_x
,
2835 event
->area
.y
- screen
.off_y
,
2836 event
->area
.x
, event
->area
.y
,
2837 event
->area
.width
, event
->area
.height
);
2841 * Draw the whole thing onto screen
2843 gdk_draw_pixmap(widget
->window
,
2844 widget
->style
->fg_gc
[GTK_WIDGET_STATE (widget
)],
2846 event
->area
.x
, event
->area
.y
,
2847 event
->area
.x
, event
->area
.y
,
2848 event
->area
.width
, event
->area
.height
);
2850 gdk_pixmap_unref(new_pixmap
);
2854 * Draw Zooming outline if we are in that mode
2856 if (screen
.state
== IN_ZOOM_OUTLINE
) {
2857 render_draw_zoom_outline(screen
.centered_outline_zoom
);
2859 else if (screen
.state
== IN_MEASURE
) {
2860 render_draw_measure_distance();
2862 if (screen
.tool
== MEASURE
&& screen
.state
!= IN_MEASURE
) {
2863 render_toggle_measure_line();
2871 int x_off
=0, y_off
=0;
2872 GdkDrawable
*drawable
= widget
->window
;
2875 if (GDK_IS_WINDOW(widget
->window
)) {
2876 /* query the window's backbuffer if it has one */
2877 GdkWindow
*window
= GDK_WINDOW(widget
->window
);
2878 gdk_window_get_internal_paint_info (window
,
2879 &drawable
, &x_off
, &y_off
);
2881 visual
= gdk_drawable_get_visual (drawable
);
2882 gdk_drawable_get_size (drawable
, &width
, &height
);
2884 #if defined(WIN32) || defined(QUARTZ)
2886 cr
= gdk_cairo_create (GDK_WINDOW(widget
->window
));
2888 cairo_surface_t
*buffert
;
2890 buffert
= (gpointer
) cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY (drawable
),
2891 GDK_DRAWABLE_XID (drawable
),
2892 GDK_VISUAL_XVISUAL (visual
),
2893 event
->area
.width
, event
->area
.height
);
2894 cr
= cairo_create (buffert
);
2896 cairo_translate (cr
, -event
->area
.x
+ screen
.off_x
, -event
->area
.y
+ screen
.off_y
);
2897 render_project_to_cairo_target (cr
);
2899 #if !defined(WIN32) && !defined(QUARTZ)
2900 cairo_surface_destroy (buffert
);
2903 if (screen
.tool
== MEASURE
)
2904 render_toggle_measure_line();
2908 /* Transforms screen coordinates to board ones */
2910 callbacks_screen2board(gdouble
*X
, gdouble
*Y
, gint x
, gint y
) {
2912 /* make sure we don't divide by zero (which is possible if the gui
2913 isn't displayed yet */
2914 if ((screenRenderInfo
.scaleFactorX
> 0.001)||(screenRenderInfo
.scaleFactorY
> 0.001)) {
2915 *X
= screenRenderInfo
.lowerLeftX
+ (x
/ screenRenderInfo
.scaleFactorX
);
2916 *Y
= screenRenderInfo
.lowerLeftY
+ ((screenRenderInfo
.displayHeight
- y
)
2917 / screenRenderInfo
.scaleFactorY
);
2924 /* --------------------------------------------------------- */
2926 callbacks_update_statusbar_coordinates (gint x
, gint y
) {
2929 callbacks_screen2board(&X
, &Y
, x
, y
);
2930 if (screen
.unit
== GERBV_MILS
) {
2931 snprintf(screen
.statusbar
.coordstr
, MAX_COORDLEN
,
2933 COORD2MILS(X
), COORD2MILS(Y
));
2934 } else if (screen
.unit
== GERBV_MMS
) {
2935 snprintf(screen
.statusbar
.coordstr
, MAX_COORDLEN
,
2937 COORD2MMS(X
), COORD2MMS(Y
));
2939 snprintf(screen
.statusbar
.coordstr
, MAX_COORDLEN
,
2941 COORD2MILS(X
) / 1000.0, COORD2MILS(Y
) / 1000.0);
2943 callbacks_update_statusbar();
2947 callbacks_update_selected_object_message (gboolean userTriedToSelect
) {
2948 if (screen
.tool
!= POINTER
)
2951 gint selectionLength
= screen
.selectionInfo
.selectedNodeArray
->len
;
2952 if ((selectionLength
== 0)&&(userTriedToSelect
)) {
2953 /* update status bar message to make sure the user knows
2954 about needing to select the layer */
2955 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
2956 "<b>No object selected. Objects can only be selected in the active layer.</b>");
2958 else if (selectionLength
== 0) {
2959 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
2960 "Click to select objects in the current layer. Middle click and drag to pan.");
2962 else if (selectionLength
== 1) {
2963 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
2964 "1 object is currently selected");
2967 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
2968 "%d objects are currently selected",selectionLength
);
2970 callbacks_update_statusbar();
2973 /* --------------------------------------------------------- */
2975 callbacks_drawingarea_motion_notify_event (GtkWidget
*widget
, GdkEventMotion
*event
)
2978 GdkModifierType state
;
2981 gdk_window_get_pointer (event
->window
, &x
, &y
, &state
);
2985 state
= event
->state
;
2988 switch (screen
.state
) {
2990 if (screen
.last_x
!= 0 || screen
.last_y
!= 0) {
2991 /* Move pixmap to get a snappier feel of movement */
2992 screen
.off_x
+= x
- screen
.last_x
;
2993 screen
.off_y
+= y
- screen
.last_y
;
2995 screenRenderInfo
.lowerLeftX
-= ((x
- screen
.last_x
) / screenRenderInfo
.scaleFactorX
);
2996 screenRenderInfo
.lowerLeftY
+= ((y
- screen
.last_y
) / screenRenderInfo
.scaleFactorY
);
2997 callbacks_force_expose_event_for_screen ();
2998 callbacks_update_scrollbar_positions ();
3003 case IN_ZOOM_OUTLINE
: {
3004 if (screen
.last_x
|| screen
.last_y
)
3005 render_draw_zoom_outline(screen
.centered_outline_zoom
);
3008 render_draw_zoom_outline(screen
.centered_outline_zoom
);
3012 /* clear the previous drawn line by drawing over it */
3013 render_toggle_measure_line();
3014 callbacks_screen2board(&(screen
.measure_last_x
), &(screen
.measure_last_y
),
3016 /* screen.last_[xy] are updated to move the ruler pointers */
3019 /* draw the new line and write the new distance */
3020 render_draw_measure_distance();
3023 case IN_SELECTION_DRAG
: {
3024 if (screen
.last_x
|| screen
.last_y
)
3025 render_draw_selection_box_outline();
3028 render_draw_selection_box_outline();
3036 callbacks_update_statusbar_coordinates (x
, y
);
3037 callbacks_update_ruler_pointers ();
3039 } /* motion_notify_event */
3041 /* --------------------------------------------------------- */
3043 callbacks_drawingarea_button_press_event (GtkWidget
*widget
, GdkEventButton
*event
)
3047 switch (event
->button
) {
3049 if (screen
.tool
== POINTER
) {
3051 /* selection will only work with cairo, so do nothing if it's
3053 screen
.state
= IN_SELECTION_DRAG
;
3054 screen
.start_x
= event
->x
;
3055 screen
.start_y
= event
->y
;
3057 else if (screen
.tool
== PAN
) {
3059 screen
.state
= IN_MOVE
;
3060 screen
.last_x
= event
->x
;
3061 screen
.last_y
= event
->y
;
3063 else if (screen
.tool
== ZOOM
) {
3064 screen
.state
= IN_ZOOM_OUTLINE
;
3065 /* Zoom outline mode initiated */
3066 screen
.start_x
= event
->x
;
3067 screen
.start_y
= event
->y
;
3068 screen
.centered_outline_zoom
= event
->state
;
3070 else if (screen
.tool
== MEASURE
) {
3071 screen
.state
= IN_MEASURE
;
3072 callbacks_screen2board(&(screen
.measure_start_x
), &(screen
.measure_start_y
),
3073 event
->x
, event
->y
);
3074 screen
.measure_last_x
= screen
.measure_start_x
;
3075 screen
.measure_last_y
= screen
.measure_start_y
;
3076 /* force an expose event to clear any previous measure lines */
3077 callbacks_force_expose_event_for_screen ();
3081 screen
.state
= IN_MOVE
;
3082 screen
.last_x
= event
->x
;
3083 screen
.last_y
= event
->y
;
3084 cursor
= gdk_cursor_new(GDK_FLEUR
);
3085 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
3087 gdk_cursor_destroy(cursor
);
3090 if (screen
.tool
== POINTER
) {
3091 /* if no items are selected, try and find the item the user
3093 if (screen
.selectionInfo
.type
== GERBV_SELECTION_EMPTY
) {
3094 gint index
=callbacks_get_selected_row_index();
3096 (index
<= mainProject
->last_loaded
) &&
3097 (mainProject
->file
[index
]->isVisible
)) {
3098 render_fill_selection_buffer_from_mouse_click(event
->x
,event
->y
,index
,TRUE
);
3100 render_clear_selection_buffer ();
3101 render_refresh_rendered_image_on_screen ();
3104 /* only show the popup if we actually have something selected now */
3105 if (screen
.selectionInfo
.type
!= GERBV_SELECTION_EMPTY
)
3106 gtk_menu_popup(GTK_MENU(screen
.win
.drawWindowPopupMenu
), NULL
, NULL
, NULL
, NULL
,
3107 event
->button
, event
->time
);
3109 /* Zoom outline mode initiated */
3110 screen
.state
= IN_ZOOM_OUTLINE
;
3111 screen
.start_x
= event
->x
;
3112 screen
.start_y
= event
->y
;
3113 screen
.centered_outline_zoom
= event
->state
& GDK_SHIFT_MASK
;
3114 cursor
= gdk_cursor_new(GDK_SIZING
);
3115 gdk_window_set_cursor(GDK_WINDOW(screen
.drawing_area
->window
),
3117 gdk_cursor_destroy(cursor
);
3120 case 4 : /* Scroll wheel */
3121 render_zoom_display (ZOOM_IN_CMOUSE
, 0, event
->x
, event
->y
);
3123 case 5 : /* Scroll wheel */
3124 render_zoom_display (ZOOM_OUT_CMOUSE
, 0, event
->x
, event
->y
);
3129 callbacks_switch_to_correct_cursor ();
3133 /* --------------------------------------------------------- */
3135 callbacks_drawingarea_button_release_event (GtkWidget
*widget
, GdkEventButton
*event
)
3137 if (event
->type
== GDK_BUTTON_RELEASE
) {
3138 if (screen
.state
== IN_MOVE
) {
3141 render_refresh_rendered_image_on_screen();
3142 callbacks_switch_to_normal_tool_cursor (screen
.tool
);
3144 else if (screen
.state
== IN_ZOOM_OUTLINE
) {
3145 if ((event
->state
& GDK_SHIFT_MASK
) != 0) {
3146 render_zoom_display (ZOOM_OUT_CMOUSE
, 0, event
->x
, event
->y
);
3148 /* if the user just clicks without dragging, then simply
3149 zoom in a preset amount */
3150 else if ((abs(screen
.start_x
- event
->x
) < 4) &&
3151 (abs(screen
.start_y
- event
->y
) < 4)) {
3152 render_zoom_display (ZOOM_IN_CMOUSE
, 0, event
->x
, event
->y
);
3155 render_calculate_zoom_from_outline (widget
, event
);
3156 callbacks_switch_to_normal_tool_cursor (screen
.tool
);
3158 else if (screen
.state
== IN_SELECTION_DRAG
) {
3159 /* selection will only work with cairo, so do nothing if it's
3161 gint index
=callbacks_get_selected_row_index();
3162 /* determine if this was just a click or a box drag */
3164 (mainProject
->file
[index
]->isVisible
)) {
3165 gboolean eraseOldSelection
= TRUE
;
3167 if ((event
->state
& GDK_SHIFT_MASK
) ||
3168 (event
->state
& GDK_CONTROL_MASK
)) {
3169 eraseOldSelection
= FALSE
;
3171 if ((fabs((double)(screen
.last_x
- screen
.start_x
)) < 5) &&
3172 (fabs((double)(screen
.last_y
- screen
.start_y
)) < 5))
3173 render_fill_selection_buffer_from_mouse_click(event
->x
,event
->y
,index
,eraseOldSelection
);
3175 render_fill_selection_buffer_from_mouse_drag(event
->x
,event
->y
,
3176 screen
.start_x
,screen
.start_y
,index
,eraseOldSelection
);
3177 /* check if anything was selected */
3178 callbacks_update_selected_object_message (TRUE
);
3180 render_clear_selection_buffer ();
3181 render_refresh_rendered_image_on_screen ();
3184 screen
.last_x
= screen
.last_y
= 0;
3185 screen
.state
= NORMAL
;
3188 } /* button_release_event */
3190 /* --------------------------------------------------------- */
3192 callbacks_window_key_press_event (GtkWidget
*widget
, GdkEventKey
*event
)
3194 switch(event
->keyval
) {
3196 if (screen
.tool
== POINTER
) {
3197 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
3198 "No objects are currently selected");
3199 callbacks_update_statusbar();
3200 render_clear_selection_buffer ();
3207 /* Escape may be used to abort outline zoom and just plain repaint */
3208 if (event
->keyval
== GDK_Escape
) {
3209 screen
.state
= NORMAL
;
3210 render_refresh_rendered_image_on_screen();
3214 } /* key_press_event */
3216 /* --------------------------------------------------------- */
3218 callbacks_window_key_release_event (GtkWidget
*widget
, GdkEventKey
*event
)
3221 } /* key_release_event */
3223 /* --------------------------------------------------------- */
3226 callbacks_window_scroll_event(GtkWidget
*widget
, GdkEventScroll
*event
)
3228 switch (event
->direction
) {
3230 render_zoom_display (ZOOM_IN_CMOUSE
, 0, event
->x
, event
->y
);
3232 case GDK_SCROLL_DOWN
:
3233 render_zoom_display (ZOOM_OUT_CMOUSE
, 0, event
->x
, event
->y
);
3235 case GDK_SCROLL_LEFT
:
3237 case GDK_SCROLL_RIGHT
:
3243 } /* scroll_event */
3246 /* ------------------------------------------------------------------ */
3247 /** Displays additional information in the statusbar.
3248 The Statusbar is divided into three sections:\n
3249 statusbar.coordstr for coords\n
3250 statusbar.diststr for displaying measured distances or the designator
3251 (right click on a graphically marked and also actively selected part)\n
3252 statusbar.msg for e.g. showing progress of actions*/
3254 callbacks_update_statusbar(void)
3256 if ((screen
.statusbar
.coordstr
!= NULL
)&&(GTK_IS_LABEL(screen
.win
.statusMessageLeft
))) {
3257 gtk_label_set_text(GTK_LABEL(screen
.win
.statusMessageLeft
), screen
.statusbar
.coordstr
);
3259 if ((screen
.statusbar
.diststr
!= NULL
)&&(GTK_IS_LABEL(screen
.win
.statusMessageRight
))) {
3260 gtk_label_set_markup(GTK_LABEL(screen
.win
.statusMessageRight
), screen
.statusbar
.diststr
);
3264 /* --------------------------------------------------------- */
3266 callbacks_update_statusbar_measured_distance (gdouble dx
, gdouble dy
){
3267 gdouble delta
= sqrt(dx
*dx
+ dy
*dy
);
3269 if (screen
.unit
== GERBV_MILS
) {
3270 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
3271 "Measured distance: %8.2f mils (%8.2f x, %8.2f y)",
3272 COORD2MILS(delta
), COORD2MILS(dx
), COORD2MILS(dy
));
3274 else if (screen
.unit
== GERBV_MMS
) {
3275 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
3276 "Measured distance: %8.3f mms (%8.3f x, %8.3f y)",
3277 COORD2MMS(delta
), COORD2MMS(dx
), COORD2MMS(dy
));
3280 snprintf(screen
.statusbar
.diststr
, MAX_DISTLEN
,
3281 "Measured distance: %4.5f inches (%4.5f x, %4.5f y)",
3282 COORD2MILS(delta
) / 1000.0, COORD2MILS(dx
) / 1000.0,
3283 COORD2MILS(dy
) / 1000.0);
3285 callbacks_update_statusbar();
3288 /* --------------------------------------------------------- */
3290 callbacks_sidepane_render_type_combo_box_changed (GtkComboBox
*widget
, gpointer user_data
) {
3291 int type
= gtk_combo_box_get_active (widget
);
3293 dprintf ("%s(): type = %d\n", __FUNCTION__
, type
);
3295 if (type
< 0 || type
== screenRenderInfo
.renderType
)
3298 screenRenderInfo
.renderType
= type
;
3299 callbacks_render_type_changed ();
3302 /* --------------------------------------------------------- */
3304 callbacks_viewmenu_rendertype_changed (GtkCheckMenuItem
*widget
, gpointer user_data
) {
3305 gint type
= GPOINTER_TO_INT(user_data
);
3307 if (type
== screenRenderInfo
.renderType
)
3310 dprintf ("%s(): type = %d\n", __FUNCTION__
, type
);
3312 screenRenderInfo
.renderType
= type
;
3313 callbacks_render_type_changed ();
3316 /* --------------------------------------------------------- */
3318 callbacks_viewmenu_units_changed (GtkCheckMenuItem
*widget
, gpointer user_data
) {
3319 gint unit
= GPOINTER_TO_INT(user_data
);
3321 if (unit
< 0 || unit
== screen
.unit
)
3324 dprintf ("%s(): unit = %d, screen.unit = %d\n", __FUNCTION__
, unit
, screen
.unit
);
3326 callbacks_units_changed (unit
);
3329 /* --------------------------------------------------------- */
3331 callbacks_statusbar_unit_combo_box_changed (GtkComboBox
*widget
, gpointer user_data
) {
3332 int unit
= gtk_combo_box_get_active (widget
);
3334 if (unit
< 0 || unit
== screen
.unit
)
3337 callbacks_units_changed (unit
);
3340 /* --------------------------------------------------------- */
3342 callbacks_clear_messages_button_clicked (GtkButton
*button
, gpointer user_data
) {
3343 GtkTextBuffer
*textbuffer
;
3344 GtkTextIter start
, end
;
3346 textbuffer
= gtk_text_view_get_buffer((GtkTextView
*)screen
.win
.messageTextView
);
3347 gtk_text_buffer_get_start_iter(textbuffer
, &start
);
3348 gtk_text_buffer_get_end_iter(textbuffer
, &end
);
3349 gtk_text_buffer_delete (textbuffer
, &start
, &end
);
3352 /* --------------------------------------------------------- */
3354 callbacks_handle_log_messages(const gchar
*log_domain
, GLogLevelFlags log_level
,
3355 const gchar
*message
, gpointer user_data
) {
3356 GtkTextBuffer
*textbuffer
= NULL
;
3359 GtkTextMark
*StartMark
= NULL
, *StopMark
= NULL
;
3360 GtkTextIter StartIter
, StopIter
;
3362 if (!screen
.win
.messageTextView
)
3365 textbuffer
= gtk_text_view_get_buffer((GtkTextView
*)screen
.win
.messageTextView
);
3367 /* create a mark for the end of the text. */
3368 gtk_text_buffer_get_end_iter(textbuffer
, &iter
);
3370 /* get the current end position of the text (it will be the
3371 start of the new text. */
3372 StartMark
= gtk_text_buffer_create_mark(textbuffer
,
3373 "NewTextStart", &iter
, TRUE
);
3375 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3377 /* the tag does not exist: create it and let them exist in the tag table.*/
3379 tag
= gtk_text_buffer_create_tag(textbuffer
, "black_foreground",
3380 "foreground", "black", NULL
);
3381 tag
= gtk_text_buffer_create_tag(textbuffer
, "blue_foreground",
3382 "foreground", "blue", NULL
);
3383 tag
= gtk_text_buffer_create_tag(textbuffer
, "red_foreground",
3384 "foreground", "red", NULL
);
3385 tag
= gtk_text_buffer_create_tag(textbuffer
, "darkred_foreground",
3386 "foreground", "darkred", NULL
);
3387 tag
= gtk_text_buffer_create_tag(textbuffer
, "darkblue_foreground",
3388 "foreground", "darkblue", NULL
);
3389 tag
= gtk_text_buffer_create_tag (textbuffer
, "darkgreen_foreground",
3390 "foreground", "darkgreen", NULL
);
3391 tag
= gtk_text_buffer_create_tag (textbuffer
,
3392 "saddlebrown_foreground",
3393 "foreground", "saddlebrown", NULL
);
3397 * See rgb.txt for the color names definition
3398 * (on my PC it is on /usr/X11R6/lib/X11/rgb.txt)
3400 switch (log_level
& G_LOG_LEVEL_MASK
) {
3401 case G_LOG_LEVEL_ERROR
:
3402 /* a message of this kind aborts the application calling abort() */
3403 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3405 gtk_notebook_set_current_page(GTK_NOTEBOOK(screen
.win
.sidepane_notebook
), 1);
3406 gtk_widget_show(screen
.win
.sidepane_notebook
);
3408 case G_LOG_LEVEL_CRITICAL
:
3409 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3411 gtk_notebook_set_current_page(GTK_NOTEBOOK(screen
.win
.sidepane_notebook
), 1);
3412 gtk_widget_show(screen
.win
.sidepane_notebook
);
3414 case G_LOG_LEVEL_WARNING
:
3415 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3416 "darkred_foreground");
3417 gtk_notebook_set_current_page(GTK_NOTEBOOK(screen
.win
.sidepane_notebook
), 1);
3418 gtk_widget_show(screen
.win
.sidepane_notebook
);
3420 case G_LOG_LEVEL_MESSAGE
:
3421 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3422 "darkblue_foreground");
3423 gtk_notebook_set_current_page(GTK_NOTEBOOK(screen
.win
.sidepane_notebook
), 1);
3424 gtk_widget_show(screen
.win
.sidepane_notebook
);
3426 case G_LOG_LEVEL_INFO
:
3427 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3428 "darkgreen_foreground");
3430 case G_LOG_LEVEL_DEBUG
:
3431 tag
= gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(textbuffer
),
3432 "saddlebrown_foreground");
3435 tag
= gtk_text_tag_table_lookup (gtk_text_buffer_get_tag_table(textbuffer
),
3436 "black_foreground");
3441 * Fatal aborts application. We will try to get the message out anyhow.
3443 if (log_level
& G_LOG_FLAG_FATAL
)
3444 fprintf(stderr
, "Fatal error : %s\n", message
);
3446 gtk_text_buffer_insert(textbuffer
, &iter
, message
, -1);
3448 gtk_text_buffer_get_end_iter(textbuffer
, &iter
);
3450 StopMark
= gtk_text_buffer_create_mark(textbuffer
,
3451 "NewTextStop", &iter
, TRUE
);
3453 gtk_text_buffer_get_iter_at_mark(textbuffer
, &StartIter
, StartMark
);
3454 gtk_text_buffer_get_iter_at_mark(textbuffer
, &StopIter
, StopMark
);
3456 gtk_text_buffer_apply_tag(textbuffer
, tag
, &StartIter
, &StopIter
);
3459 /* --------------------------------------------------------- */
3460 void callbacks_force_expose_event_for_screen (void){
3462 GdkRectangle update_rect
;
3466 update_rect
.width
= screenRenderInfo
.displayWidth
;
3467 update_rect
.height
= screenRenderInfo
.displayHeight
;
3469 /* Calls expose_event */
3470 gdk_window_invalidate_rect (screen
.drawing_area
->window
, &update_rect
, FALSE
);
3472 /* update other gui things that could have changed */
3473 callbacks_update_ruler_scales ();
3474 callbacks_update_scrollbar_limits ();
3475 callbacks_update_scrollbar_positions ();