Root/gui.c

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

Archive Download this file

Branches:
master



interactive