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