1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-18 08:07:31 +02:00
fped/gui.c
Werner Almesberger 86c082f5a9 track bounding box also on a per-package basis and use this to scale Postscript
Until now, everything used the bounding box of the root frame which
contains all the packages, visible or not. We now also record what
ends up in which package, allowing inst_get_bbox to return the
bounding box of a specific package.

This is mainly useful for scaling Postscript output where only one
package is printed per sheet and there is not much point in reserving
space for any other packages that may be generated from the same
footprint definition.
2012-07-12 17:40:31 -03:00

426 lines
11 KiB
C

/*
* gui.c - Editor GUI core
*
* Written 2009-2012 by Werner Almesberger
* Copyright 2009-2012 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <locale.h>
#include <gtk/gtk.h>
#include "inst.h"
#include "file.h"
#include "gui_util.h"
#include "gui_style.h"
#include "gui_status.h"
#include "gui_canvas.h"
#include "gui_tool.h"
#include "gui_frame.h"
#include "gui.h"
#include "fped.h"
#include "icons/stuff.xpm"
#include "icons/stuff_off.xpm"
#include "icons/meas.xpm"
#include "icons/meas_off.xpm"
#include "icons/all.xpm"
#include "icons/all_off.xpm"
#include "icons/bright.xpm"
#include "icons/bright_off.xpm"
GtkWidget *root;
int show_all = 1;
int show_stuff = 1;
int show_meas = 1;
int show_bright = 0;
static GtkWidget *paned;
static GtkWidget *frames_box;
static GtkWidget *ev_stuff, *ev_meas, *ev_all, *ev_bright;
static GtkWidget *stuff_image[2], *meas_image[2], *all_image[2];
static GtkWidget *bright_image[2];
static void do_build_frames(void);
/* ----- save callbacks ---------------------------------------------------- */
static void save_as_fpd(void)
{
GtkWidget *dialog;
dialog = gtk_file_chooser_dialog_new("Save File",
NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
gtk_file_chooser_set_do_overwrite_confirmation(
GTK_FILE_CHOOSER(dialog), TRUE);
if (save_file_name)
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
save_file_name);
if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
save_file_name =
gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
save_fpd();
/* @@@ we may leak save_file_name */
no_save = 0;
}
gtk_widget_destroy(dialog);
}
/* ----- view callbacks ---------------------------------------------------- */
static void swap_var_code(void)
{
extern int show_vars;
show_vars = !show_vars;
change_world();
}
/* ----- menu bar ---------------------------------------------------------- */
static GtkItemFactoryEntry menu_entries[] = {
{ "/File", NULL, NULL, 0, "<Branch>" },
{ "/File/Save", NULL, save_fpd, 0, "<Item>" },
{ "/File/Save as", NULL, save_as_fpd, 0, "<Item>" },
{ "/File/sep1", NULL, NULL, 0, "<Separator>" },
{ "/File/Write KiCad", NULL, write_kicad, 0, "<Item>" },
{ "/File/Write Postscript",
NULL, write_ps, 0, "<Item>" },
{ "/File/sep2", NULL, NULL, 0, "<Separator>" },
{ "/File/Quit", NULL, gtk_main_quit, 0, "<Item>" },
{ "/View", NULL, NULL, 0, "<Branch>" },
{ "/View/Zoom in", NULL, zoom_in_center, 0, "<Item>" },
{ "/View/Zoom out", NULL, zoom_out_center,0, "<Item>" },
{ "/View/Zoom all", NULL, zoom_to_extents,0, "<Item>" },
{ "/View/Zoom frame", NULL, zoom_to_frame, 0, "<Item>" },
{ "/View/sep1", NULL, NULL, 0, "<Separator>" },
{ "/View/Swap var&code",NULL, swap_var_code, 0, "<Item>" },
};
static void make_menu_bar(GtkWidget *hbox)
{
GtkItemFactory *factory;
GtkWidget *bar;
factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<FpedMenu>", NULL);
gtk_item_factory_create_items(factory,
sizeof(menu_entries)/sizeof(*menu_entries), menu_entries, NULL);
bar = gtk_item_factory_get_widget(factory, "<FpedMenu>");
gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
gtk_widget_set_sensitive(
gtk_item_factory_get_item(factory, "/File/Save"), !no_save);
}
static gboolean toggle_all(GtkWidget *widget, GdkEventButton *event,
gpointer data)
{
switch (event->button) {
case 1:
show_all = !show_all;
set_image(ev_all, all_image[show_all]);
inst_deselect();
redraw();
break;
}
return TRUE;
}
static gboolean toggle_stuff(GtkWidget *widget, GdkEventButton *event,
gpointer data)
{
switch (event->button) {
case 1:
show_stuff = !show_stuff;
set_image(ev_stuff, stuff_image[show_stuff]);
inst_deselect();
redraw();
break;
}
return TRUE;
}
static gboolean toggle_meas(GtkWidget *widget, GdkEventButton *event,
gpointer data)
{
switch (event->button) {
case 1:
show_meas = !show_meas;
set_image(ev_meas, meas_image[show_meas]);
inst_deselect();
redraw();
break;
}
return TRUE;
}
static gboolean toggle_bright(GtkWidget *widget, GdkEventButton *event,
gpointer data)
{
switch (event->button) {
case 1:
show_bright = !show_bright;
set_image(ev_bright, bright_image[show_bright]);
inst_deselect();
redraw();
break;
}
return TRUE;
}
static void make_tool_bar(GtkWidget *hbox, GdkDrawable *drawable)
{
GtkWidget *bar;
bar = gtk_toolbar_new();
gtk_box_pack_end(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
//gtk_box_pack_end(GTK_BOX(hbox), bar, FALSE, FALSE, 0);
gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
ev_all = tool_button(bar, drawable, NULL, NULL, toggle_all, NULL);
ev_stuff = tool_button(bar, drawable, NULL, NULL, toggle_stuff, NULL);
ev_meas = tool_button(bar, drawable, NULL, NULL, toggle_meas, NULL);
ev_bright = tool_button(bar, drawable, NULL, NULL, toggle_bright, NULL);
stuff_image[0] = gtk_widget_ref(make_image(drawable, xpm_stuff_off,
"Show vectors and frame references (disabled)"));
stuff_image[1] = gtk_widget_ref(make_image(drawable, xpm_stuff,
"Show vectors and frame references (enabled)"));
meas_image[0] = gtk_widget_ref(make_image(drawable, xpm_meas_off,
"Show measurements (disabled)"));
meas_image[1] = gtk_widget_ref(make_image(drawable, xpm_meas,
"Show measurements (enabled)"));
all_image[0] = gtk_widget_ref(make_image(drawable, xpm_all_off,
"Show all frames (currently showing only the active frame)"));
all_image[1] = gtk_widget_ref(make_image(drawable, xpm_all,
"Show all frames (enabled)"));
bright_image[0] = gtk_widget_ref(make_image(drawable, xpm_bright_off,
"Highlight elements (disabled)"));
bright_image[1] = gtk_widget_ref(make_image(drawable, xpm_bright,
"Highlight elements (enabled)"));
set_image(ev_stuff, stuff_image[show_stuff]);
set_image(ev_meas, meas_image[show_meas]);
set_image(ev_all, all_image[show_all]);
set_image(ev_bright, bright_image[show_bright]);
}
static void cleanup_tool_bar(void)
{
g_object_unref(stuff_image[0]);
g_object_unref(stuff_image[1]);
g_object_unref(meas_image[0]);
g_object_unref(meas_image[1]);
g_object_unref(all_image[0]);
g_object_unref(all_image[1]);
g_object_unref(bright_image[0]);
g_object_unref(bright_image[1]);
}
static void make_top_bar(GtkWidget *vbox)
{
GtkWidget *hbox;
hbox = gtk_hbox_new(FALSE, 0);
make_menu_bar(hbox);
make_tool_bar(hbox, root->window);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
}
/* ----- central screen area ----------------------------------------------- */
static void resize_frames_area(GtkWidget *widget, GtkAllocation *allocation,
gpointer user_data)
{
static int width = 0;
if (allocation->width == width)
return;
width = allocation->width;
do_build_frames();
}
static void make_center_area(GtkWidget *vbox)
{
GtkWidget *hbox, *frames_area;//, *paned;
GtkWidget *tools;
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
paned = gtk_hpaned_new();
gtk_box_pack_start(GTK_BOX(hbox), paned, TRUE, TRUE, 0);
/* Frames */
frames_area = gtk_scrolled_window_new(NULL, NULL);
gtk_paned_add1(GTK_PANED(paned), frames_area);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(frames_area),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_set_size_request(frames_area,
DEFAULT_FRAME_AREA_WIDTH, DEFAULT_FRAME_AREA_HEIGHT);
frames_box = gtk_vbox_new(FALSE, 0);
build_frames(frames_box, DEFAULT_FRAME_AREA_WIDTH);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(frames_area),
frames_box);
g_signal_connect(G_OBJECT(frames_area), "size-allocate",
G_CALLBACK(resize_frames_area), NULL);
/* Canvas */
gtk_paned_add2(GTK_PANED(paned), make_canvas());
/* Icon bar */
tools = gui_setup_tools(root->window);
gtk_box_pack_end(GTK_BOX(hbox), tools, FALSE, FALSE, 0);
}
/* ----- GUI construction -------------------------------------------------- */
static void do_build_frames(void)
{
int width;
width = gtk_paned_get_position(GTK_PANED(paned));
build_frames(frames_box, width > 0 ? width : DEFAULT_FRAME_AREA_WIDTH);
}
void change_world(void)
{
struct bbox before, after;
int reachable_is_active;
inst_deselect();
status_begin_reporting();
before = inst_get_bbox(NULL);
reachable_is_active = reachable_pkg && reachable_pkg == active_pkg;
instantiate();
if (reachable_is_active && reachable_pkg &&
reachable_pkg != active_pkg) {
active_pkg = reachable_pkg;
instantiate();
}
after = inst_get_bbox(NULL);
label_in_box_bg(active_frame->label, COLOR_FRAME_SELECTED);
do_build_frames();
if (after.min.x < before.min.x || after.min.y < before.min.y ||
after.max.x > before.max.x || after.max.y > before.max.y)
zoom_to_extents();
else
redraw();
}
void change_world_reselect(void)
{
struct obj *selected_obj;
/*
* We can edit an object even if it's not selected if it was picked
* via the item view. inst_select_obj tries to find an instance, but
* if there's never been a successful instantiation since creation of
* the object or if the object is unreachable for some other reason,
* then selected_inst will be NULL.
*/
if (!selected_inst) {
change_world();
return;
}
selected_obj = selected_inst->obj;
change_world();
inst_select_obj(selected_obj);
}
static void make_screen(GtkWidget *window)
{
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
make_top_bar(vbox);
make_center_area(vbox);
make_status_area(vbox);
}
int gui_init(int *argc, char ***argv)
{
gtk_init(argc, argv);
setlocale(LC_ALL, "C"); /* damage control */
return 0;
}
int gui_main(void)
{
root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(root), 620, 460);
if (*VERSION)
gtk_window_set_title(GTK_WINDOW(root),
"fped (rev " VERSION ")");
else
gtk_window_set_title(GTK_WINDOW(root), "fped");
/* get root->window */
gtk_widget_show_all(root);
g_signal_connect(G_OBJECT(root), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
make_screen(root);
gtk_widget_show_all(root);
gui_setup_style(root->window);
init_canvas();
edit_nothing();
select_frame(frames);
make_popups();
gtk_main();
gui_cleanup_style();
gui_cleanup_tools();
cleanup_tool_bar();
cleanup_status_area();
return 0;
}