Root/gui.c

Source at commit 5a1fd80fc852b784d74b5a3e7fd1ca5225a68d6b created 5 years 5 months ago.
By Werner Almesberger, new sidebar mode "Show packages"
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
98static void show_pkg(void)
99{
100    sidebar = sidebar_pkg;
101    change_world();
102}
103
104
105/* ----- menu bar ---------------------------------------------------------- */
106
107
108static GtkItemFactoryEntry menu_entries[] = {
109    { "/File", NULL, NULL, 0, "<Branch>" },
110    { "/File/Save", NULL, save_fpd, 0, "<Item>" },
111    { "/File/Save as", NULL, save_as_fpd, 0, "<Item>" },
112        { "/File/sep1", NULL, NULL, 0, "<Separator>" },
113        { "/File/Write KiCad", NULL, write_kicad, 0, "<Item>" },
114        { "/File/Write Postscript",
115                NULL, write_ps, 0, "<Item>" },
116        { "/File/sep2", NULL, NULL, 0, "<Separator>" },
117        { "/File/Reload", NULL, reload, 0, "<Item>" },
118        { "/File/sep3", NULL, NULL, 0, "<Separator>" },
119        { "/File/Quit", NULL, gtk_main_quit, 0, "<Item>" },
120    { "/View", NULL, NULL, 0, "<Branch>" },
121    { "/View/Zoom in", NULL, zoom_in_center, 0, "<Item>" },
122    { "/View/Zoom out", NULL, zoom_out_center,0, "<Item>" },
123    { "/View/Zoom all", NULL, zoom_to_extents,0, "<Item>" },
124    { "/View/Zoom frame", NULL, zoom_to_frame, 0, "<Item>" },
125    { "/View/sep1", NULL, NULL, 0, "<Separator>" },
126    { "/View/Show variables",
127                NULL, show_var, 0, "<RadioItem>" },
128    { "/View/Show code", NULL, show_code, 0,
129                        "/View/Show variables" },
130    { "/View/Show packages",NULL, show_pkg, 0,
131                        "/View/Show variables" },
132};
133
134
135static void make_menu_bar(GtkWidget *hbox)
136{
137    GtkItemFactory *factory;
138    GtkWidget *bar;
139
140    factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<FpedMenu>", NULL);
141        gtk_item_factory_create_items(factory,
142        sizeof(menu_entries)/sizeof(*menu_entries), menu_entries, NULL);
143
144    bar = gtk_item_factory_get_widget(factory, "<FpedMenu>");
145    gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
146
147    gtk_widget_set_sensitive(
148        gtk_item_factory_get_item(factory, "/File/Save"), !no_save);
149    gtk_widget_set_sensitive(
150        gtk_item_factory_get_item(factory, "/File/Reload"),
151        no_save && !!save_file_name);
152}
153
154
155static gboolean toggle_all(GtkWidget *widget, GdkEventButton *event,
156    gpointer data)
157{
158    switch (event->button) {
159    case 1:
160        show_all = !show_all;
161        set_image(ev_all, all_image[show_all]);
162        inst_deselect();
163        redraw();
164        break;
165    }
166        return TRUE;
167}
168
169
170static gboolean toggle_stuff(GtkWidget *widget, GdkEventButton *event,
171    gpointer data)
172{
173    switch (event->button) {
174    case 1:
175        show_stuff = !show_stuff;
176        set_image(ev_stuff, stuff_image[show_stuff]);
177        inst_deselect();
178        redraw();
179        break;
180    }
181        return TRUE;
182}
183
184
185static gboolean toggle_meas(GtkWidget *widget, GdkEventButton *event,
186    gpointer data)
187{
188    switch (event->button) {
189    case 1:
190        show_meas = !show_meas;
191        set_image(ev_meas, meas_image[show_meas]);
192        inst_deselect();
193        redraw();
194        break;
195    }
196        return TRUE;
197}
198
199
200static gboolean toggle_bright(GtkWidget *widget, GdkEventButton *event,
201    gpointer data)
202{
203    switch (event->button) {
204    case 1:
205        show_bright = !show_bright;
206        set_image(ev_bright, bright_image[show_bright]);
207        inst_deselect();
208        redraw();
209        break;
210    }
211        return TRUE;
212}
213
214
215static void make_tool_bar(GtkWidget *hbox, GdkDrawable *drawable)
216{
217    GtkWidget *bar;
218
219    bar = gtk_toolbar_new();
220    gtk_box_pack_end(GTK_BOX(hbox), bar, TRUE, TRUE, 0);
221    //gtk_box_pack_end(GTK_BOX(hbox), bar, FALSE, FALSE, 0);
222    gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
223
224    ev_all = tool_button(bar, drawable, NULL, NULL, toggle_all, NULL);
225    ev_stuff = tool_button(bar, drawable, NULL, NULL, toggle_stuff, NULL);
226    ev_meas = tool_button(bar, drawable, NULL, NULL, toggle_meas, NULL);
227    ev_bright = tool_button(bar, drawable, NULL, NULL, toggle_bright, NULL);
228
229    stuff_image[0] = gtk_widget_ref(make_image(drawable, xpm_stuff_off,
230        "Show vectors and frame references (disabled)"));
231    stuff_image[1] = gtk_widget_ref(make_image(drawable, xpm_stuff,
232        "Show vectors and frame references (enabled)"));
233    meas_image[0] = gtk_widget_ref(make_image(drawable, xpm_meas_off,
234        "Show measurements (disabled)"));
235    meas_image[1] = gtk_widget_ref(make_image(drawable, xpm_meas,
236        "Show measurements (enabled)"));
237    all_image[0] = gtk_widget_ref(make_image(drawable, xpm_all_off,
238        "Show all frames (currently showing only the active frame)"));
239    all_image[1] = gtk_widget_ref(make_image(drawable, xpm_all,
240        "Show all frames (enabled)"));
241    bright_image[0] = gtk_widget_ref(make_image(drawable, xpm_bright_off,
242        "Highlight elements (disabled)"));
243    bright_image[1] = gtk_widget_ref(make_image(drawable, xpm_bright,
244        "Highlight elements (enabled)"));
245
246    set_image(ev_stuff, stuff_image[show_stuff]);
247    set_image(ev_meas, meas_image[show_meas]);
248    set_image(ev_all, all_image[show_all]);
249    set_image(ev_bright, bright_image[show_bright]);
250}
251
252
253static void cleanup_tool_bar(void)
254{
255    g_object_unref(stuff_image[0]);
256    g_object_unref(stuff_image[1]);
257    g_object_unref(meas_image[0]);
258    g_object_unref(meas_image[1]);
259    g_object_unref(all_image[0]);
260    g_object_unref(all_image[1]);
261    g_object_unref(bright_image[0]);
262    g_object_unref(bright_image[1]);
263}
264
265
266static void make_top_bar(GtkWidget *vbox)
267{
268    GtkWidget *hbox;
269
270    hbox = gtk_hbox_new(FALSE, 0);
271    make_menu_bar(hbox);
272    make_tool_bar(hbox, root->window);
273    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
274}
275
276
277/* ----- central screen area ----------------------------------------------- */
278
279
280static void resize_frames_area(GtkWidget *widget, GtkAllocation *allocation,
281    gpointer user_data)
282{
283    static int width = 0;
284
285    if (allocation->width == width)
286        return;
287    width = allocation->width;
288    do_build_frames();
289}
290
291
292static void make_center_area(GtkWidget *vbox)
293{
294    GtkWidget *hbox, *frames_area;//, *paned;
295    GtkWidget *tools;
296
297    hbox = gtk_hbox_new(FALSE, 0);
298    gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
299
300    paned = gtk_hpaned_new();
301    gtk_box_pack_start(GTK_BOX(hbox), paned, TRUE, TRUE, 0);
302
303    /* Frames */
304
305    frames_area = gtk_scrolled_window_new(NULL, NULL);
306    gtk_paned_add1(GTK_PANED(paned), frames_area);
307    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(frames_area),
308        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
309    gtk_widget_set_size_request(frames_area,
310        DEFAULT_FRAME_AREA_WIDTH, DEFAULT_FRAME_AREA_HEIGHT);
311
312    frames_box = gtk_vbox_new(FALSE, 0);
313    build_frames(frames_box, DEFAULT_FRAME_AREA_WIDTH);
314
315    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(frames_area),
316        frames_box);
317
318    g_signal_connect(G_OBJECT(frames_area), "size-allocate",
319        G_CALLBACK(resize_frames_area), NULL);
320
321    /* Canvas */
322
323    gtk_paned_add2(GTK_PANED(paned), make_canvas());
324
325    /* Icon bar */
326
327    tools = gui_setup_tools(root->window);
328    gtk_box_pack_end(GTK_BOX(hbox), tools, FALSE, FALSE, 0);
329}
330
331
332/* ----- GUI construction -------------------------------------------------- */
333
334
335static void do_build_frames(void)
336{
337    int width;
338
339    width = gtk_paned_get_position(GTK_PANED(paned));
340    build_frames(frames_box, width > 0 ? width : DEFAULT_FRAME_AREA_WIDTH);
341}
342
343
344void change_world(void)
345{
346    struct bbox before, after;
347    int reachable_is_active;
348
349    inst_deselect();
350    status_begin_reporting();
351    before = inst_get_bbox(NULL);
352    reachable_is_active = reachable_pkg && reachable_pkg == active_pkg;
353    instantiate();
354    if (reachable_is_active && reachable_pkg &&
355         reachable_pkg != active_pkg) {
356        active_pkg = reachable_pkg;
357        instantiate();
358    }
359    after = inst_get_bbox(NULL);
360    do_build_frames();
361    if (after.min.x < before.min.x || after.min.y < before.min.y ||
362        after.max.x > before.max.x || after.max.y > before.max.y)
363        zoom_to_extents();
364    else
365        redraw();
366}
367
368
369void change_world_reselect(void)
370{
371    struct obj *selected_obj;
372
373    /*
374     * We can edit an object even if it's not selected if it was picked
375     * via the item view. inst_select_obj tries to find an instance, but
376     * if there's never been a successful instantiation since creation of
377     * the object or if the object is unreachable for some other reason,
378     * then selected_inst will be NULL.
379     */
380    if (!selected_inst) {
381        change_world();
382        return;
383    }
384    selected_obj = selected_inst->obj;
385    change_world();
386    inst_select_obj(selected_obj);
387}
388
389
390static void make_screen(GtkWidget *window)
391{
392    GtkWidget *vbox;
393
394    vbox = gtk_vbox_new(FALSE, 0);
395    gtk_container_add(GTK_CONTAINER(window), vbox);
396
397    make_top_bar(vbox);
398    make_center_area(vbox);
399    make_status_area(vbox);
400}
401
402
403int gui_init(int *argc, char ***argv)
404{
405    gtk_init(argc, argv);
406    setlocale(LC_ALL, "C"); /* damage control */
407    return 0;
408}
409
410
411int gui_main(void)
412{
413    root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
414    gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
415    gtk_window_set_default_size(GTK_WINDOW(root), 620, 460);
416    if (*VERSION)
417        gtk_window_set_title(GTK_WINDOW(root),
418            "fped (rev " VERSION ")");
419    else
420        gtk_window_set_title(GTK_WINDOW(root), "fped");
421
422    /* get root->window */
423    gtk_widget_show_all(root);
424
425    g_signal_connect(G_OBJECT(root), "destroy",
426        G_CALLBACK(gtk_main_quit), NULL);
427
428    make_screen(root);
429
430    gtk_widget_show_all(root);
431
432    gui_setup_style(root->window);
433    init_canvas();
434    edit_nothing();
435    select_frame(frames);
436    make_popups();
437
438    gtk_main();
439
440    gui_cleanup_style();
441    gui_cleanup_tools();
442    cleanup_tool_bar();
443    cleanup_status_area();
444
445    return 0;
446}
447

Archive Download this file

Branches:
master



interactive