Root/gui.c

Source at commit 809e8142b53ba7227241d39d2c4057f7201087a9 created 4 years 7 months ago.
By Werner Almesberger, gui.c (change_world): don't change color of the active frame
1/*
2 * gui.c - Editor GUI core
3 *
4 * Written 2009-2012, 2015 by Werner Almesberger
5 * Copyright 2009-2012, 2015 by Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <locale.h>
15#include <gtk/gtk.h>
16
17#include "inst.h"
18#include "file.h"
19#include "gui_util.h"
20#include "gui_style.h"
21#include "gui_status.h"
22#include "gui_canvas.h"
23#include "gui_tool.h"
24#include "gui_frame.h"
25#include "gui.h"
26#include "fped.h"
27
28#include "icons/stuff.xpm"
29#include "icons/stuff_off.xpm"
30#include "icons/meas.xpm"
31#include "icons/meas_off.xpm"
32#include "icons/all.xpm"
33#include "icons/all_off.xpm"
34#include "icons/bright.xpm"
35#include "icons/bright_off.xpm"
36
37
38GtkWidget *root;
39int show_all = 1;
40int show_stuff = 1;
41int show_meas = 1;
42int show_bright = 0;
43
44
45static GtkWidget *paned;
46static GtkWidget *frames_box;
47static GtkWidget *ev_stuff, *ev_meas, *ev_all, *ev_bright;
48static GtkWidget *stuff_image[2], *meas_image[2], *all_image[2];
49static GtkWidget *bright_image[2];
50
51static void do_build_frames(void);
52
53
54/* ----- save callbacks ---------------------------------------------------- */
55
56
57static void save_as_fpd(void)
58{
59    GtkWidget *dialog;
60
61    dialog = gtk_file_chooser_dialog_new("Save File",
62        NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
63        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
64        GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
65    gtk_file_chooser_set_do_overwrite_confirmation(
66        GTK_FILE_CHOOSER(dialog), TRUE);
67    if (save_file_name)
68        gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
69            save_file_name);
70    if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
71        save_file_name =
72            gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
73        save_fpd();
74        /* @@@ we may leak save_file_name */
75        no_save = 0;
76    }
77    gtk_widget_destroy(dialog);
78}
79
80
81/* ----- view callbacks ---------------------------------------------------- */
82
83
84static void show_var(void)
85{
86    sidebar = sidebar_var;
87    change_world();
88}
89
90
91static void show_code(void)
92{
93    sidebar = sidebar_code;
94    change_world();
95}
96
97
98/* ----- menu bar ---------------------------------------------------------- */
99
100
101static GtkItemFactoryEntry menu_entries[] = {
102    { "/File", NULL, NULL, 0, "<Branch>" },
103    { "/File/Save", NULL, save_fpd, 0, "<Item>" },
104    { "/File/Save as", NULL, save_as_fpd, 0, "<Item>" },
105        { "/File/sep1", NULL, NULL, 0, "<Separator>" },
106        { "/File/Write KiCad", NULL, write_kicad, 0, "<Item>" },
107        { "/File/Write Postscript",
108                NULL, write_ps, 0, "<Item>" },
109        { "/File/sep2", NULL, NULL, 0, "<Separator>" },
110        { "/File/Reload", NULL, reload, 0, "<Item>" },
111        { "/File/sep3", NULL, NULL, 0, "<Separator>" },
112        { "/File/Quit", NULL, gtk_main_quit, 0, "<Item>" },
113    { "/View", NULL, NULL, 0, "<Branch>" },
114    { "/View/Zoom in", NULL, zoom_in_center, 0, "<Item>" },
115    { "/View/Zoom out", NULL, zoom_out_center,0, "<Item>" },
116    { "/View/Zoom all", NULL, zoom_to_extents,0, "<Item>" },
117    { "/View/Zoom frame", NULL, zoom_to_frame, 0, "<Item>" },
118    { "/View/sep1", NULL, NULL, 0, "<Separator>" },
119    { "/View/Show variables",
120                NULL, show_var, 0, "<RadioItem>" },
121    { "/View/Show code", NULL, show_code, 0,
122                        "/View/Show variables" },
123};
124
125
126static void make_menu_bar(GtkWidget *hbox)
127{
128    GtkItemFactory *factory;
129    GtkWidget *bar;
130
131    factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<FpedMenu>", NULL);
132        gtk_item_factory_create_items(factory,
133        sizeof(menu_entries)/sizeof(*menu_entries), menu_entries, NULL);
134
135    bar = gtk_item_factory_get_widget(factory, "<FpedMenu>");
136    gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
137
138    gtk_widget_set_sensitive(
139        gtk_item_factory_get_item(factory, "/File/Save"), !no_save);
140    gtk_widget_set_sensitive(
141        gtk_item_factory_get_item(factory, "/File/Reload"),
142        no_save && !!save_file_name);
143}
144
145
146static gboolean toggle_all(GtkWidget *widget, GdkEventButton *event,
147    gpointer data)
148{
149    switch (event->button) {
150    case 1:
151        show_all = !show_all;
152        set_image(ev_all, all_image[show_all]);
153        inst_deselect();
154        redraw();
155        break;
156    }
157        return TRUE;
158}
159
160
161static gboolean toggle_stuff(GtkWidget *widget, GdkEventButton *event,
162    gpointer data)
163{
164    switch (event->button) {
165    case 1:
166        show_stuff = !show_stuff;
167        set_image(ev_stuff, stuff_image[show_stuff]);
168        inst_deselect();
169        redraw();
170        break;
171    }
172        return TRUE;
173}
174
175
176static gboolean toggle_meas(GtkWidget *widget, GdkEventButton *event,
177    gpointer data)
178{
179    switch (event->button) {
180    case 1:
181        show_meas = !show_meas;
182        set_image(ev_meas, meas_image[show_meas]);
183        inst_deselect();
184        redraw();
185        break;
186    }
187        return TRUE;
188}
189
190
191static gboolean toggle_bright(GtkWidget *widget, GdkEventButton *event,
192    gpointer data)
193{
194    switch (event->button) {
195    case 1:
196        show_bright = !show_bright;
197        set_image(ev_bright, bright_image[show_bright]);
198        inst_deselect();
199        redraw();
200        break;
201    }
202        return TRUE;
203}
204
205
206static void make_tool_bar(GtkWidget *hbox, GdkDrawable *drawable)
207{
208    GtkWidget *bar;
209
210    bar = gtk_toolbar_new();
211    gtk_box_pack_end(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
212    //gtk_box_pack_end(GTK_BOX(hbox), bar, FALSE, FALSE, 0);
213    gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
214
215    ev_all = tool_button(bar, drawable, NULL, NULL, toggle_all, NULL);
216    ev_stuff = tool_button(bar, drawable, NULL, NULL, toggle_stuff, NULL);
217    ev_meas = tool_button(bar, drawable, NULL, NULL, toggle_meas, NULL);
218    ev_bright = tool_button(bar, drawable, NULL, NULL, toggle_bright, NULL);
219
220    stuff_image[0] = gtk_widget_ref(make_image(drawable, xpm_stuff_off,
221        "Show vectors and frame references (disabled)"));
222    stuff_image[1] = gtk_widget_ref(make_image(drawable, xpm_stuff,
223        "Show vectors and frame references (enabled)"));
224    meas_image[0] = gtk_widget_ref(make_image(drawable, xpm_meas_off,
225        "Show measurements (disabled)"));
226    meas_image[1] = gtk_widget_ref(make_image(drawable, xpm_meas,
227        "Show measurements (enabled)"));
228    all_image[0] = gtk_widget_ref(make_image(drawable, xpm_all_off,
229        "Show all frames (currently showing only the active frame)"));
230    all_image[1] = gtk_widget_ref(make_image(drawable, xpm_all,
231        "Show all frames (enabled)"));
232    bright_image[0] = gtk_widget_ref(make_image(drawable, xpm_bright_off,
233        "Highlight elements (disabled)"));
234    bright_image[1] = gtk_widget_ref(make_image(drawable, xpm_bright,
235        "Highlight elements (enabled)"));
236
237    set_image(ev_stuff, stuff_image[show_stuff]);
238    set_image(ev_meas, meas_image[show_meas]);
239    set_image(ev_all, all_image[show_all]);
240    set_image(ev_bright, bright_image[show_bright]);
241}
242
243
244static void cleanup_tool_bar(void)
245{
246    g_object_unref(stuff_image[0]);
247    g_object_unref(stuff_image[1]);
248    g_object_unref(meas_image[0]);
249    g_object_unref(meas_image[1]);
250    g_object_unref(all_image[0]);
251    g_object_unref(all_image[1]);
252    g_object_unref(bright_image[0]);
253    g_object_unref(bright_image[1]);
254}
255
256
257static void make_top_bar(GtkWidget *vbox)
258{
259    GtkWidget *hbox;
260
261    hbox = gtk_hbox_new(FALSE, 0);
262    make_menu_bar(hbox);
263    make_tool_bar(hbox, root->window);
264    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
265}
266
267
268/* ----- central screen area ----------------------------------------------- */
269
270
271static void resize_frames_area(GtkWidget *widget, GtkAllocation *allocation,
272    gpointer user_data)
273{
274    static int width = 0;
275
276    if (allocation->width == width)
277        return;
278    width = allocation->width;
279    do_build_frames();
280}
281
282
283static void make_center_area(GtkWidget *vbox)
284{
285    GtkWidget *hbox, *frames_area;//, *paned;
286    GtkWidget *tools;
287
288    hbox = gtk_hbox_new(FALSE, 0);
289    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
290
291    paned = gtk_hpaned_new();
292    gtk_box_pack_start(GTK_BOX(hbox), paned, TRUE, TRUE, 0);
293
294    /* Frames */
295
296    frames_area = gtk_scrolled_window_new(NULL, NULL);
297    gtk_paned_add1(GTK_PANED(paned), frames_area);
298    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(frames_area),
299        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
300    gtk_widget_set_size_request(frames_area,
301        DEFAULT_FRAME_AREA_WIDTH, DEFAULT_FRAME_AREA_HEIGHT);
302
303    frames_box = gtk_vbox_new(FALSE, 0);
304    build_frames(frames_box, DEFAULT_FRAME_AREA_WIDTH);
305
306    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(frames_area),
307        frames_box);
308
309    g_signal_connect(G_OBJECT(frames_area), "size-allocate",
310        G_CALLBACK(resize_frames_area), NULL);
311
312    /* Canvas */
313
314    gtk_paned_add2(GTK_PANED(paned), make_canvas());
315
316    /* Icon bar */
317
318    tools = gui_setup_tools(root->window);
319    gtk_box_pack_end(GTK_BOX(hbox), tools, FALSE, FALSE, 0);
320}
321
322
323/* ----- GUI construction -------------------------------------------------- */
324
325
326static void do_build_frames(void)
327{
328    int width;
329
330    width = gtk_paned_get_position(GTK_PANED(paned));
331    build_frames(frames_box, width > 0 ? width : DEFAULT_FRAME_AREA_WIDTH);
332}
333
334
335void change_world(void)
336{
337    struct bbox before, after;
338    int reachable_is_active;
339
340    inst_deselect();
341    status_begin_reporting();
342    before = inst_get_bbox(NULL);
343    reachable_is_active = reachable_pkg && reachable_pkg == active_pkg;
344    instantiate();
345    if (reachable_is_active && reachable_pkg &&
346         reachable_pkg != active_pkg) {
347        active_pkg = reachable_pkg;
348        instantiate();
349    }
350    after = inst_get_bbox(NULL);
351    do_build_frames();
352    if (after.min.x < before.min.x || after.min.y < before.min.y ||
353        after.max.x > before.max.x || after.max.y > before.max.y)
354        zoom_to_extents();
355    else
356        redraw();
357}
358
359
360void change_world_reselect(void)
361{
362    struct obj *selected_obj;
363
364    /*
365     * We can edit an object even if it's not selected if it was picked
366     * via the item view. inst_select_obj tries to find an instance, but
367     * if there's never been a successful instantiation since creation of
368     * the object or if the object is unreachable for some other reason,
369     * then selected_inst will be NULL.
370     */
371    if (!selected_inst) {
372        change_world();
373        return;
374    }
375    selected_obj = selected_inst->obj;
376    change_world();
377    inst_select_obj(selected_obj);
378}
379
380
381static void make_screen(GtkWidget *window)
382{
383    GtkWidget *vbox;
384
385    vbox = gtk_vbox_new(FALSE, 0);
386    gtk_container_add(GTK_CONTAINER(window), vbox);
387
388    make_top_bar(vbox);
389    make_center_area(vbox);
390    make_status_area(vbox);
391}
392
393
394int gui_init(int *argc, char ***argv)
395{
396    gtk_init(argc, argv);
397    setlocale(LC_ALL, "C"); /* damage control */
398    return 0;
399}
400
401
402int gui_main(void)
403{
404    root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
405    gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
406    gtk_window_set_default_size(GTK_WINDOW(root), 620, 460);
407    if (*VERSION)
408        gtk_window_set_title(GTK_WINDOW(root),
409            "fped (rev " VERSION ")");
410    else
411        gtk_window_set_title(GTK_WINDOW(root), "fped");
412
413    /* get root->window */
414    gtk_widget_show_all(root);
415
416    g_signal_connect(G_OBJECT(root), "destroy",
417        G_CALLBACK(gtk_main_quit), NULL);
418
419    make_screen(root);
420
421    gtk_widget_show_all(root);
422
423    gui_setup_style(root->window);
424    init_canvas();
425    edit_nothing();
426    select_frame(frames);
427    make_popups();
428
429    gtk_main();
430
431    gui_cleanup_style();
432    gui_cleanup_tools();
433    cleanup_tool_bar();
434    cleanup_status_area();
435
436    return 0;
437}
438

Archive Download this file

Branches:
master



interactive