1 //
2 // gui.cc
3 //
4
5 #include "wx/bitmap.h"
6 #include "wx/frame.h"
7 #include "wx/gauge.h"
8 #include "wx/icon.h"
9 #include "wx/menu.h"
10 #include "wx/msgdlg.h"
11 #include "wx/statusbr.h"
12 #include "wx/string.h"
13 #include "wx/toolbar.h"
14
15 #include <math.h>
16 #include "canvas.h"
17 #include "config.h"
18 #include "edge.h"
19 #include "factory.h"
20 #include "graph.h"
21 #include "gui.h"
22 #include "lang.h"
23 #include "undo.h"
24 #include "vertex.h"
25
26
27 // Toolbar pixmaps
28 #include "edge_mode.xpm"
29 #include "vertex_mode.xpm"
30
31 #include "logo.xpm"
32
33
BEGIN_EVENT_TABLE(GTFrame,wxFrame)34 BEGIN_EVENT_TABLE(GTFrame, wxFrame)
35 EVT_SIZE (GTFrame::OnSize)
36
37 EVT_MENU (ID_FILE_LOAD, GTFrame::cb_File_Load)
38 EVT_MENU (ID_FILE_SAVE, GTFrame::cb_File_Save)
39 EVT_MENU (ID_FILE_EXIT, GTFrame::cb_File_Exit)
40
41 EVT_MENU (ID_EDIT_UNDO, GTFrame::cb_Edit_Undo)
42 EVT_MENU (ID_EDIT_SELECTALL, GTFrame::cb_Edit_SelectAll)
43 EVT_MENU (ID_EDIT_SELECTNONE, GTFrame::cb_Edit_SelectNone)
44 EVT_MENU (ID_EDIT_INVERTSELV, GTFrame::cb_Edit_InvertSelectionVertices)
45 EVT_MENU (ID_EDIT_INVERTSELE, GTFrame::cb_Edit_InvertSelectionEdges)
46 EVT_MENU (ID_EDIT_INVERTSELA, GTFrame::cb_Edit_InvertSelectionAll)
47
48 EVT_MENU (ID_VIEW_LABELS, GTFrame::cb_View)
49 EVT_MENU (ID_VIEW_WEIGHTS, GTFrame::cb_View)
50 EVT_MENU (ID_VIEW_FLOWS, GTFrame::cb_View)
51
52 EVT_MENU (ID_GRAPH_CLEAR, GTFrame::cb_Graph_Clear)
53 EVT_MENU (ID_GRAPH_COMPLEMENT, GTFrame::cb_Graph_Complement)
54 EVT_MENU (ID_GRAPH_LINEGRAPH, GTFrame::cb_Graph_LineGraph)
55 EVT_MENU (ID_GRAPH_SUBGRAPH, GTFrame::cb_Graph_Subgraph)
56
57 EVT_MENU (ID_GRAPH_FIND_SHORTESTPATH, GTFrame::cb_Graph_Find_ShortestPath)
58 EVT_MENU (ID_GRAPH_FIND_BFS, GTFrame::cb_Graph_Find_BFS)
59 EVT_MENU (ID_GRAPH_FIND_DFS, GTFrame::cb_Graph_Find_DFS)
60 EVT_MENU (ID_GRAPH_FIND_MST, GTFrame::cb_Graph_Find_MST)
61 EVT_MENU (ID_GRAPH_FIND_MAXFLOW, GTFrame::cb_Graph_Find_MaxFlow)
62
63 EVT_MENU (ID_GRAPH_PROPERTIES_CONNECTIVITY, GTFrame::cb_Graph_Properties_Connectivity)
64 EVT_MENU (ID_GRAPH_PROPERTIES_EULERICITY, GTFrame::cb_Graph_Properties_Eulericity)
65 EVT_MENU (ID_GRAPH_PROPERTIES_HAMILTONICITY, GTFrame::OnMenu)
66 EVT_MENU (ID_GRAPH_PROPERTIES_PLANARITY, GTFrame::OnMenu)
67
68 EVT_MENU (ID_GRAPH_STATISTICS_ADJMATRIX, GTFrame::cb_Graph_Statistics_AdjacencyMatrix)
69 EVT_MENU (ID_GRAPH_STATISTICS_DEGSEQ, GTFrame::cb_Graph_Statistics_DegreeSequence)
70 EVT_MENU (ID_GRAPH_STATISTICS_DIAMETER, GTFrame::cb_Graph_Statistics_Diameter)
71 EVT_MENU (ID_GRAPH_STATISTICS_GIRTH, GTFrame::OnMenu)
72 EVT_MENU (ID_GRAPH_STATISTICS_RADIUS, GTFrame::cb_Graph_Statistics_Radius)
73 EVT_MENU (ID_GRAPH_STATISTICS_CHROMNUM, GTFrame::cb_Graph_Statistics_ChromaticNumber)
74 EVT_MENU (ID_GRAPH_STATISTICS_CHROMINDEX, GTFrame::cb_Graph_Statistics_ChromaticIndex)
75 EVT_MENU (ID_GRAPH_STATISTICS_CHROMPOLY, GTFrame::cb_Graph_Statistics_ChromaticPolynomial)
76
77 EVT_MENU (ID_PREFAB_COMPLETE, GTFrame::cb_Prefab_Complete)
78 EVT_MENU (ID_PREFAB_COMPLETEBIPARTITE, GTFrame::cb_Prefab_CompleteBipartite)
79 EVT_MENU (ID_PREFAB_CYCLE, GTFrame::cb_Prefab_Cycle)
80 EVT_MENU (ID_PREFAB_GEAR, GTFrame::cb_Prefab_Gear)
81 EVT_MENU (ID_PREFAB_HANOI, GTFrame::cb_Prefab_Hanoi)
82 EVT_MENU (ID_PREFAB_LADDER, GTFrame::cb_Prefab_Ladder)
83 EVT_MENU (ID_PREFAB_LATTICE, GTFrame::cb_Prefab_Lattice)
84 EVT_MENU (ID_PREFAB_NULL, GTFrame::cb_Prefab_Null)
85 EVT_MENU (ID_PREFAB_STAR, GTFrame::cb_Prefab_Star)
86 EVT_MENU (ID_PREFAB_TREE, GTFrame::OnMenu)
87 EVT_MENU (ID_PREFAB_WHEEL, GTFrame::cb_Prefab_Wheel)
88 EVT_MENU (ID_PREFAB_PETERSEN, GTFrame::cb_Prefab_Petersen)
89
90 EVT_MENU (ID_PREFAB_PLATONIC_TETRAHEDRAL, GTFrame::cb_Prefab_Platonic_Tetrahedral)
91 EVT_MENU (ID_PREFAB_PLATONIC_CUBICAL, GTFrame::cb_Prefab_Platonic_Cubical)
92 EVT_MENU (ID_PREFAB_PLATONIC_OCTAHEDRAL, GTFrame::cb_Prefab_Platonic_Octahedral)
93 EVT_MENU (ID_PREFAB_PLATONIC_DODECAHEDRAL, GTFrame::cb_Prefab_Platonic_Dodecahedral)
94 EVT_MENU (ID_PREFAB_PLATONIC_ICOSAHEDRAL, GTFrame::cb_Prefab_Platonic_Icosahedral)
95
96 EVT_MENU (ID_HELP_ABOUT, GTFrame::cb_Help_About)
97
98 EVT_TOOL (ID_TOOL_VERTEXMODE, GTFrame::cb_Change_Mode)
99 EVT_TOOL (ID_TOOL_EDGEMODE, GTFrame::cb_Change_Mode)
100 END_EVENT_TABLE()
101
102 wxMenuBar *GTFrame::genMenuBar ()
103 {
104 // File Menu
105 wxMenu *menu_file = new wxMenu ();
106 menu_file->Append (ID_FILE_LOAD, _("&Load\tCtrl-O"));
107 menu_file->Append (ID_FILE_SAVE, _("&Save\tCtrl-S"));
108 menu_file->AppendSeparator ();
109 menu_file->Append (ID_FILE_EXIT, _("E&xit\tCtrl-Q"));
110
111 // Edit Menu
112 wxMenu *menu_edit = new wxMenu ();
113 menu_edit->Append (ID_EDIT_UNDO, _("&Undo\tCtrl-Z"));
114 menu_edit->FindItem (ID_EDIT_UNDO)->Enable (false);
115 menu_edit->AppendSeparator ();
116 menu_edit->Append (ID_EDIT_SELECTALL, _("Select &All\tCtrl-A"));
117 menu_edit->Append (ID_EDIT_SELECTNONE, _("Select &None"));
118 menu_edit->Append (ID_EDIT_INVERTSELV, _("Invert Selection (&Vertices)"));
119 menu_edit->Append (ID_EDIT_INVERTSELE, _("Invert Selection (&Edges)"));
120 menu_edit->Append (ID_EDIT_INVERTSELA, _("&Invert Selection (All)"));
121
122 // View Menu
123 wxMenu *menu_view = new wxMenu ();
124 menu_view->AppendCheckItem (ID_VIEW_LABELS, _("&Labels"));
125 menu_view->AppendSeparator ();
126 menu_view->AppendCheckItem (ID_VIEW_WEIGHTS, _("&Weights"));
127 menu_view->AppendCheckItem (ID_VIEW_FLOWS, _("&Flows"));
128
129 // Graph Menu
130 wxMenu *menu_graph = new wxMenu ();
131 menu_graph->Append (ID_GRAPH_CLEAR, _("&Clear\tCtrl-W"));
132 menu_graph->Append (ID_GRAPH_COMPLEMENT, _("C&omplement"));
133 menu_graph->Append (ID_GRAPH_LINEGRAPH, _("&Line Graph"));
134 menu_graph->Append (ID_GRAPH_SUBGRAPH, _("S&ubgraph"));
135 menu_graph->AppendSeparator ();
136
137 // Graph/Find submenu
138 wxMenu *menu_graph_find = new wxMenu ();
139 menu_graph_find->Append (ID_GRAPH_FIND_SHORTESTPATH,
140 _("&Shortest Path"));
141 menu_graph_find->Append (ID_GRAPH_FIND_BFS,
142 _("&Breadth-First Search"));
143 menu_graph_find->Append (ID_GRAPH_FIND_DFS,
144 _("&Depth-First Search"));
145 menu_graph_find->Append (ID_GRAPH_FIND_MST,
146 _("&Minimum Spanning Tree"));
147 menu_graph_find->Append (ID_GRAPH_FIND_MAXFLOW,
148 _("Maximum &Flow"));
149 menu_graph->Append (ID_GRAPH_FIND, _("&Find"), menu_graph_find);
150
151 // Graph/Properties submenu
152 wxMenu *menu_graph_prop = new wxMenu ();
153 menu_graph_prop->Append (ID_GRAPH_PROPERTIES_CONNECTIVITY,
154 _("&Connectivity"));
155 menu_graph_prop->Append (ID_GRAPH_PROPERTIES_EULERICITY,
156 _("&Eulericity"));
157 menu_graph_prop->Append (ID_GRAPH_PROPERTIES_HAMILTONICITY,
158 _("&Hamiltonicity"));
159 menu_graph_prop->FindItem (ID_GRAPH_PROPERTIES_HAMILTONICITY)->Enable (false);
160 menu_graph_prop->Append (ID_GRAPH_PROPERTIES_PLANARITY,
161 _("&Planarity"));
162 menu_graph_prop->FindItem (ID_GRAPH_PROPERTIES_PLANARITY)->Enable (false);
163 menu_graph->Append (ID_GRAPH_PROPERTIES, _("&Properties"), menu_graph_prop);
164
165 // Graph/Statistics submenu
166 wxMenu *menu_graph_stat = new wxMenu ();
167 menu_graph_stat->Append (ID_GRAPH_STATISTICS_ADJMATRIX,
168 _("&Adjacency Matrix"));
169 menu_graph_stat->Append (ID_GRAPH_STATISTICS_DEGSEQ,
170 _("&Degree Sequence"));
171 menu_graph_stat->Append (ID_GRAPH_STATISTICS_DIAMETER,
172 _("D&iameter"));
173 menu_graph_stat->Append (ID_GRAPH_STATISTICS_GIRTH,
174 _("&Girth"));
175 menu_graph_stat->FindItem (ID_GRAPH_STATISTICS_GIRTH)->Enable (false);
176 menu_graph_stat->Append (ID_GRAPH_STATISTICS_RADIUS,
177 _("&Radius"));
178 menu_graph_stat->AppendSeparator ();
179 menu_graph_stat->Append (ID_GRAPH_STATISTICS_CHROMNUM,
180 _("&Chromatic Number"));
181 menu_graph_stat->Append (ID_GRAPH_STATISTICS_CHROMINDEX,
182 _("C&hromatic Index"));
183 menu_graph_stat->Append (ID_GRAPH_STATISTICS_CHROMPOLY,
184 _("Chromatic &Polynomial"));
185 menu_graph->Append (ID_GRAPH_STATISTICS, _("&Statistics"), menu_graph_stat);
186
187 // Prefab Menu
188 wxMenu *menu_prefab = new wxMenu ();
189 menu_prefab->Append (ID_PREFAB_COMPLETE, _("Complete (&Kn)"));
190 menu_prefab->Append (ID_PREFAB_COMPLETEBIPARTITE,
191 _("Complete &Bipartite (Kn,m)"));
192 menu_prefab->Append (ID_PREFAB_CYCLE, _("Cycle (&Cn)"));
193 menu_prefab->Append (ID_PREFAB_GEAR, _("Gear (&Gn)"));
194 menu_prefab->Append (ID_PREFAB_HANOI, _("Hanoi (&Hn)"));
195 menu_prefab->Append (ID_PREFAB_LADDER, _("Ladder (&Ln)"));
196 menu_prefab->Append (ID_PREFAB_LATTICE, _("Lattice (Ln,m)"));
197 menu_prefab->Append (ID_PREFAB_NULL, _("Null (&Nn)"));
198 menu_prefab->Append (ID_PREFAB_STAR, _("Star (&Sn)"));
199 menu_prefab->Append (ID_PREFAB_TREE, _("Tree (&Tn)"));
200 menu_prefab->FindItem (ID_PREFAB_TREE)->Enable (false);
201 menu_prefab->Append (ID_PREFAB_WHEEL, _("Wheel (&Wn)"));
202 menu_prefab->AppendSeparator ();
203 menu_prefab->Append (ID_PREFAB_PETERSEN, _("Petersen"));
204
205 // Prefab/Platonic submenu
206 wxMenu *menu_prefab_platonic = new wxMenu ();
207 menu_prefab_platonic->Append (ID_PREFAB_PLATONIC_TETRAHEDRAL,
208 _("&Tetrahedral"));
209 menu_prefab_platonic->Append (ID_PREFAB_PLATONIC_CUBICAL,
210 _("&Cubical"));
211 menu_prefab_platonic->Append (ID_PREFAB_PLATONIC_OCTAHEDRAL,
212 _("&Octahedral"));
213 menu_prefab_platonic->Append (ID_PREFAB_PLATONIC_DODECAHEDRAL,
214 _("&Dodecahedral"));
215 menu_prefab_platonic->Append (ID_PREFAB_PLATONIC_ICOSAHEDRAL,
216 _("&Icosahedral"));
217 menu_prefab->Append (ID_PREFAB_PLATONIC, _("&Platonic"), menu_prefab_platonic);
218
219 // Help Menu
220 wxMenu *menu_help = new wxMenu ();
221 menu_help->Append (ID_HELP_ABOUT, _("&About\tF1"));
222
223 // Menubar
224 wxMenuBar *mb = new wxMenuBar ();
225 mb->Append (menu_file, _("&File"));
226 mb->Append (menu_edit, _("&Edit"));
227 mb->Append (menu_view, _("&View"));
228 mb->Append (menu_graph, _("&Graph"));
229 mb->Append (menu_prefab, _("&Prefab"));
230 mb->Append (menu_help, _("&Help"));
231 // TODO: right-align help menu
232
233 return mb;
234 }
235
OnMenu(wxCommandEvent & event)236 void GTFrame::OnMenu (wxCommandEvent &event)
237 {
238 // TODO
239 wxMessageDialog dlg (this, wxT("This isn't implemented yet!"), wxT("NYI."),
240 wxOK | wxICON_ERROR);
241 dlg.ShowModal ();
242 }
243
244 #include "wx/settings.h"
OnSize(wxSizeEvent & event)245 void GTFrame::OnSize (wxSizeEvent &event)
246 {
247 wxRect rect;
248
249 // Fix up progress bar
250 if (!statusBar)
251 return;
252 statusBar->GetFieldRect (2, rect);
253
254 progressBar->SetSize (rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4);
255 wxSize sz = progressBar->GetSize ();
256 progressBar->Move (rect.x + (rect.width - sz.x) / 2,
257 rect.y + (rect.height - sz.y) / 2);
258
259 // Fix up canvas
260 sz = GetClientSize ();
261 int nudge_horiz = wxSystemSettings::GetMetric (wxSYS_VSCROLL_X);
262 int nudge_vert = wxSystemSettings::GetMetric (wxSYS_HSCROLL_Y);
263 sz.SetWidth (sz.GetWidth () - nudge_horiz);
264 sz.SetHeight (sz.GetHeight () - nudge_vert);
265 canvas->SetClientSize (sz.GetWidth (), sz.GetHeight ());
266 Factory::width = sz.GetWidth ();
267 Factory::height = sz.GetHeight ();
268 }
269
setUndoText(wxString description)270 void GTFrame::setUndoText (wxString description)
271 {
272 wxString s_txt (_("&Undo"));
273 if (description != wxT(""))
274 s_txt += wxT(" (") + description + wxT(")");
275 s_txt += wxT("\tCtrl-Z");
276 edit_Undo->SetText (s_txt);
277 }
278
GTFrame()279 GTFrame::GTFrame ()
280 : wxFrame ((wxFrame *) NULL, -1, wxT("GraphThing " GT_VERSION),
281 wxDefaultPosition, wxSize (600, 500)), statusBar (0)
282 {
283 SetIcon (wxIcon (logo_xpm));
284
285 graph = new Graph ();
286
287
288 SetMenuBar (genMenuBar ());
289
290 edit_Undo = GetMenuBar ()->FindItem (ID_EDIT_UNDO);
291 view_Labels = GetMenuBar ()->FindItem (ID_VIEW_LABELS);
292 view_Weights = GetMenuBar ()->FindItem (ID_VIEW_WEIGHTS);
293 view_Flows = GetMenuBar ()->FindItem (ID_VIEW_FLOWS);
294
295 view_Labels->Check ();
296
297
298 wxToolBar *tb = CreateToolBar (wxTB_HORIZONTAL | wxTB_TEXT);
299
300 statusBar = CreateStatusBar (3);
301 int widths[] = { 0, -1, -1 };
302 statusBar->SetStatusWidths (3, widths);
303
304 progressBar = new wxGauge (statusBar, -1, 100);
305 progressBar->SetValue (0);
306
307 wxBitmap *vPix = new wxBitmap (vertex_mode_xpm);
308 wxBitmap *ePix = new wxBitmap (edge_mode_xpm);
309 tb->AddRadioTool (ID_TOOL_VERTEXMODE, _("Vertex Mode"), *vPix, *vPix,
310 _("Change to Vertex Mode"));
311 tb->AddRadioTool (ID_TOOL_EDGEMODE, _("Edge Mode"), *ePix, *ePix,
312 _("Change to Edge Mode"));
313 tb->Realize ();
314
315 canvas = new Canvas (this, &graph);
316
317 pushStatus (_("Ready."));
318 wxCommandEvent ev (0, ID_TOOL_VERTEXMODE);
319 cb_Change_Mode (ev);
320 cb_View (ev);
321 }
322
~GTFrame()323 GTFrame::~GTFrame ()
324 {
325 delete graph;
326 }
327
undoableAction(wxString description)328 void GTFrame::undoableAction (wxString description)
329 {
330 UndoStep step (new Graph (*graph), description);
331 undoStack.push (step);
332 edit_Undo->Enable ();
333
334 setUndoText (description);
335 }
336
loadGraph(const wxString fname)337 void GTFrame::loadGraph (const wxString fname)
338 {
339 bool res;
340
341 Graph *g = graph->load (fname, res);
342 if (g) {
343 // TODO: Make this undoable?
344 delete graph;
345 graph = g;
346 }
347
348 canvas->redraw ();
349 }
350
msg(const wxString & title,const wxString & s)351 void GTFrame::msg (const wxString &title, const wxString &s)
352 {
353 // TODO: pass through more flags
354 wxMessageDialog dlg (this, s, title, wxOK);
355 dlg.CentreOnParent ();
356 dlg.ShowModal ();
357 }
358
msg(const wxString & title,const char * s)359 void GTFrame::msg (const wxString &title, const char *s)
360 {
361 msg (title, wxString (s, wxConvUTF8));
362 }
363
toggleMode()364 void GTFrame::toggleMode ()
365 {
366 // TODO: toggle the toolbar buttons!
367 }
368
pushStatus(const wxString & str)369 void GTFrame::pushStatus (const wxString &str)
370 {
371 statusBar->PushStatusText (str, 1);
372 }
373
popStatus()374 void GTFrame::popStatus ()
375 {
376 statusBar->PopStatusText (1);
377 }
378
setProgress(double frac)379 void GTFrame::setProgress (double frac)
380 {
381 static double last_frac = -1.0;
382
383 // TODO: implement progress percentage text somehow
384 if (frac < 0.0) {
385 // hide progress bar
386 //progressBar->set_show_text (false);
387 progressBar->Hide ();
388 last_frac = frac - 1;
389 } else if (frac <= 1.0) {
390 progressBar->SetValue (int (frac * 100));
391 //progressBar->set_format_string ("%p%% complete");
392 //progressBar->set_show_text (true);
393 progressBar->Show ();
394 }
395
396 //progressBar->Refresh ();
397 //progressBar->Update ();
398 }
399