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