1 #include "sheet_box.hpp"
2 #include <algorithm>
3 #include <iostream>
4 #include "core/core_schematic.hpp"
5 
6 namespace horizon {
SheetBox(CoreSchematic * c)7 SheetBox::SheetBox(CoreSchematic *c) : Gtk::Box(Gtk::Orientation::ORIENTATION_VERTICAL, 0), core(c)
8 {
9     auto *la = Gtk::manage(new Gtk::Label());
10     la->set_markup("<b>Sheets</b>");
11     la->show();
12     pack_start(*la, false, false, 0);
13 
14     store = Gtk::ListStore::create(list_columns);
15     store->set_sort_column(list_columns.index, Gtk::SORT_ASCENDING);
16     view = Gtk::manage(new Gtk::TreeView(store));
17 
18     view->append_column("", list_columns.index);
19 
20     {
21         auto cr = Gtk::manage(new Gtk::CellRendererText());
22         auto tvc = Gtk::manage(new Gtk::TreeViewColumn("Sheet", *cr));
23         tvc->add_attribute(*cr, "text", list_columns.name);
24         cr->property_editable().set_value(true);
25         cr->signal_edited().connect(sigc::mem_fun(*this, &SheetBox::name_edited));
26         view->append_column(*tvc);
27     }
28     {
29         auto cr = Gtk::manage(new Gtk::CellRendererPixbuf());
30         cr->property_icon_name().set_value("dialog-warning-symbolic");
31         cr->property_xalign() = 0;
32         auto cr_hi = Gtk::manage(new Gtk::CellRendererPixbuf());
33         cr_hi->property_icon_name().set_value("display-brightness-symbolic");
34         cr_hi->property_xalign() = 0;
35         auto tvc = Gtk::manage(new Gtk::TreeViewColumn("", *cr));
36         tvc->add_attribute(*cr, "visible", list_columns.has_warnings);
37         tvc->pack_start(*cr_hi, false);
38         tvc->add_attribute(*cr_hi, "visible", list_columns.has_highlights);
39         view->append_column(*tvc);
40     }
41 
42     view->show();
43     auto sc = Gtk::manage(new Gtk::ScrolledWindow());
44     sc->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
45     sc->set_shadow_type(Gtk::SHADOW_IN);
46     sc->set_min_content_height(150);
47     sc->set_propagate_natural_height(true);
48     sc->add(*view);
49     sc->show_all();
50 
51     view->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &SheetBox::selection_changed));
52     pack_start(*sc, true, true, 0);
53 
54     {
55         auto item = Gtk::manage(new Gtk::MenuItem("Copy UUID"));
56         item->signal_activate().connect([this] {
57             auto it = view->get_selection()->get_selected();
58             if (it) {
59                 Gtk::TreeModel::Row row = *it;
60                 horizon::UUID uuid = row[list_columns.uuid];
61                 std::string str = uuid;
62                 auto clip = Gtk::Clipboard::get();
63                 clip->set_text(str);
64             }
65         });
66         item->show();
67         menu.append(*item);
68     }
69 
70     view->signal_button_press_event().connect_notify([this](GdkEventButton *ev) {
71         Gtk::TreeModel::Path path;
72         if (ev->button == 3) {
73 #if GTK_CHECK_VERSION(3, 22, 0)
74             menu.popup_at_pointer((GdkEvent *)ev);
75 #else
76             menu.popup(ev->button, gtk_get_current_event_time());
77 #endif
78         }
79     });
80 
81     auto tb = Gtk::manage(new Gtk::Toolbar());
82     tb->get_style_context()->add_class("inline-toolbar");
83     tb->set_icon_size(Gtk::ICON_SIZE_MENU);
84     tb->set_toolbar_style(Gtk::TOOLBAR_ICONS);
85     {
86         auto tbo = Gtk::manage(new Gtk::ToolButton());
87         tbo->set_icon_name("list-add-symbolic");
88         tbo->signal_clicked().connect([this] { s_signal_add_sheet.emit(); });
89         tb->insert(*tbo, -1);
90     }
91     {
92         auto tbo = Gtk::manage(new Gtk::ToolButton());
93         tbo->set_icon_name("list-remove-symbolic");
94         tbo->signal_clicked().connect(sigc::mem_fun(*this, &SheetBox::remove_clicked));
95         tb->insert(*tbo, -1);
96         remove_button = tbo;
97     }
98     {
99         auto tbo = Gtk::manage(new Gtk::ToolButton());
100         tbo->set_icon_name("go-up-symbolic");
101         tbo->signal_clicked().connect([this] { sheet_move(-1); });
102         tb->insert(*tbo, -1);
103         move_up_button = tbo;
104     }
105     {
106         auto tbo = Gtk::manage(new Gtk::ToolButton());
107         tbo->set_icon_name("go-down-symbolic");
108         tbo->signal_clicked().connect([this] { sheet_move(1); });
109         tb->insert(*tbo, -1);
110         move_down_button = tbo;
111     }
112     update();
113     selection_changed();
114     tb->show_all();
115     pack_start(*tb, false, false, 0);
116 }
117 
sheet_move(int dir)118 void SheetBox::sheet_move(int dir)
119 {
120     auto it = view->get_selection()->get_selected();
121     if (it) {
122         Gtk::TreeModel::Row row = *it;
123         auto sch = core->get_schematic();
124         auto &sheets = sch->sheets;
125         auto *sheet = &sch->sheets.at(row[list_columns.uuid]);
126         if (dir < 0 && sheet->index == 1)
127             return;
128         if (dir > 0 && sheet->index == sch->sheets.size())
129             return;
130         auto sheet_other = std::find_if(sheets.begin(), sheets.end(),
131                                         [sheet, dir](const auto x) { return x.second.index == sheet->index + dir; });
132         assert(sheet_other != sheets.end());
133         std::swap(sheet_other->second.index, sheet->index);
134         core->set_needs_save();
135         core->rebuild();
136     }
137 }
138 
remove_clicked()139 void SheetBox::remove_clicked()
140 {
141     auto it = view->get_selection()->get_selected();
142     if (it) {
143         Gtk::TreeModel::Row row = *it;
144         signal_remove_sheet().emit(&core->get_schematic()->sheets.at(row[list_columns.uuid]));
145     }
146     else {
147         signal_remove_sheet().emit(nullptr);
148     }
149 }
150 
selection_changed()151 void SheetBox::selection_changed()
152 {
153     auto it = view->get_selection()->get_selected();
154     if (it) {
155         Gtk::TreeModel::Row row = *it;
156         if (core->get_schematic()->sheets.count(row[list_columns.uuid])) {
157             auto &sheets = core->get_schematic()->sheets;
158             auto sh = &sheets.at(row[list_columns.uuid]);
159             signal_select_sheet().emit(sh);
160             auto s = sh->symbols.size() == 0;
161             remove_button->set_sensitive(s);
162             move_up_button->set_sensitive(sh->index != 1);
163             move_down_button->set_sensitive(sh->index != sheets.size());
164         }
165     }
166 }
167 
name_edited(const Glib::ustring & path,const Glib::ustring & new_text)168 void SheetBox::name_edited(const Glib::ustring &path, const Glib::ustring &new_text)
169 {
170     auto it = store->get_iter(path);
171     if (it) {
172         Gtk::TreeModel::Row row = *it;
173         auto &sh = core->get_schematic()->sheets.at(row[list_columns.uuid]);
174         if (sh.name != new_text) {
175             sh.name = new_text;
176             core->set_needs_save();
177             core->rebuild();
178         }
179     }
180 }
181 
update_highlights(const UUID & uu,bool v)182 void SheetBox::update_highlights(const UUID &uu, bool v)
183 {
184     for (const auto &it : store->children()) {
185         Gtk::TreeModel::Row row = *it;
186         if (row[list_columns.uuid] == uu) {
187             row[list_columns.has_highlights] = v;
188             break;
189         }
190     }
191 }
192 
update()193 void SheetBox::update()
194 {
195     auto uuid_from_core = core->get_sheet()->uuid;
196     auto s = core->get_schematic()->sheets.size() > 1;
197     remove_button->set_sensitive(s);
198 
199     Gtk::TreeModel::Row row;
200     store->freeze_notify();
201     store->clear();
202     for (const auto &it : core->get_schematic()->sheets) {
203         row = *(store->append());
204         row[list_columns.name] = it.second.name;
205         row[list_columns.uuid] = it.first;
206         row[list_columns.has_warnings] = it.second.warnings.size() > 0;
207         row[list_columns.index] = it.second.index;
208     }
209     store->thaw_notify();
210 
211 
212     for (const auto &it : store->children()) {
213         row = *it;
214         if (row[list_columns.uuid] == uuid_from_core) {
215             view->get_selection()->select(it);
216             break;
217         }
218     }
219 }
220 
select_sheet(const UUID & sheet_uuid)221 void SheetBox::select_sheet(const UUID &sheet_uuid)
222 {
223     Gtk::TreeModel::Row row;
224     for (const auto &it : store->children()) {
225         row = *it;
226         if (row[list_columns.uuid] == sheet_uuid) {
227             view->get_selection()->select(it);
228             break;
229         }
230     }
231 }
232 } // namespace horizon
233