1 //
2 // This file is part of Gambit
3 // Copyright (c) 1994-2016, The Gambit Project (http://www.gambit-project.org)
4 //
5 // FILE: src/gui/dlefglayout.cc
6 // Declaration of dialog to set tree layout parameters
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 //
22 
23 #include <wx/wxprec.h>
24 #ifndef WX_PRECOMP
25 #include <wx/wx.h>
26 #endif  // WX_PRECOMP
27 #include <wx/spinctrl.h>
28 #include "dlefglayout.h"
29 
30 //==========================================================================
31 //                  class gbtLayoutDialog: Implementation
32 //==========================================================================
33 
34 class gbtLayoutNodesPanel : public wxPanel {
35 private:
36   wxChoice *m_chanceToken, *m_playerToken, *m_terminalToken;
37   wxSpinCtrl *m_nodeSize, *m_terminalSpacing;
38 
39 public:
40   gbtLayoutNodesPanel(wxWindow *p_parent, const gbtStyle &p_settings);
41 
NodeSize(void) const42   int NodeSize(void) const { return m_nodeSize->GetValue(); }
TerminalSpacing(void) const43   int TerminalSpacing(void) const { return m_terminalSpacing->GetValue(); }
44 
ChanceToken(void) const45   int ChanceToken(void) const { return m_chanceToken->GetSelection(); }
PlayerToken(void) const46   int PlayerToken(void) const { return m_playerToken->GetSelection(); }
TerminalToken(void) const47   int TerminalToken(void) const { return m_terminalToken->GetSelection(); }
48 };
49 
50 
gbtLayoutNodesPanel(wxWindow * p_parent,const gbtStyle & p_settings)51 gbtLayoutNodesPanel::gbtLayoutNodesPanel(wxWindow *p_parent,
52 					 const gbtStyle &p_settings)
53   : wxPanel(p_parent, -1)
54 {
55   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
56 
57   wxStaticBoxSizer *nodeSizer = new wxStaticBoxSizer(wxVERTICAL, this,
58 						     _T("Drawing nodes"));
59 
60   wxFlexGridSizer *tokenSizer = new wxFlexGridSizer(2);
61 
62   wxString tokenChoices[] = { _("a line"),
63 			      _("a box"),
64 			      _("an unfilled circle"),
65 			      _("a diamond"),
66 			      _("a filled circle") };
67 
68   tokenSizer->Add(new wxStaticText(this, wxID_STATIC,
69 				    _("Indicate chance nodes with")),
70 		  0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
71   m_chanceToken = new wxChoice(this, -1,
72 			       wxDefaultPosition, wxDefaultSize,
73 			       5, tokenChoices);
74   m_chanceToken->SetSelection(p_settings.ChanceToken());
75   tokenSizer->Add(m_chanceToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5);
76 
77   tokenSizer->Add(new wxStaticText(this, wxID_STATIC,
78 				   _("Indicate player nodes with")),
79 		  0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
80   m_playerToken = new wxChoice(this, -1,
81 			       wxDefaultPosition, wxDefaultSize,
82 			       5, tokenChoices);
83   m_playerToken->SetSelection(p_settings.PlayerToken());
84   tokenSizer->Add(m_playerToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5);
85 
86   tokenSizer->Add(new wxStaticText(this, wxID_STATIC,
87 				   _("Indicate terminal nodes with")),
88 		     0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
89   m_terminalToken = new wxChoice(this, -1,
90 				 wxDefaultPosition, wxDefaultSize,
91 				 5, tokenChoices);
92   m_terminalToken->SetSelection(p_settings.TerminalToken());
93   tokenSizer->Add(m_terminalToken, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 5);
94 
95   nodeSizer->Add(tokenSizer, 1, wxALL | wxEXPAND, 5);
96   topSizer->Add(nodeSizer, 0, wxALL | wxALIGN_CENTER, 5);
97 
98 
99   wxStaticBoxSizer *sizeSizer = new wxStaticBoxSizer(wxVERTICAL, this,
100 						     _("Layout sizing"));
101 
102   wxFlexGridSizer *gridSizer = new wxFlexGridSizer(2);
103   gridSizer->AddGrowableCol(1);
104 
105   gridSizer->Add(new wxStaticText(this, -1, _("Horizontal size of nodes")),
106 		 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
107 
108   const int NODE_LENGTH_MIN = 5;
109   const int NODE_LENGTH_MAX = 100;
110 
111   m_nodeSize = new wxSpinCtrl(this, -1,
112 			      wxString::Format(_T("%d"),
113 					       p_settings.NodeSize()),
114 			      wxDefaultPosition, wxDefaultSize,
115 			      wxSP_ARROW_KEYS,
116 			      NODE_LENGTH_MIN, NODE_LENGTH_MAX);
117   gridSizer->Add(m_nodeSize, 1, wxEXPAND | wxALL, 5);
118 
119   gridSizer->Add(new wxStaticText(this, -1,
120 				  _("Vertical spacing between terminal nodes")),
121 		 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
122 
123   const int Y_SPACING_MIN = 15;
124   const int Y_SPACING_MAX = 60;
125 
126   m_terminalSpacing =
127     new wxSpinCtrl(this, -1,
128 		   wxString::Format(_T("%d"), p_settings.TerminalSpacing()),
129 		   wxDefaultPosition, wxDefaultSize,
130 		   wxSP_ARROW_KEYS, Y_SPACING_MIN, Y_SPACING_MAX);
131   gridSizer->Add(m_terminalSpacing, 1, wxEXPAND | wxALL, 5);
132 
133   sizeSizer->Add(gridSizer, 1, wxALL | wxEXPAND, 5);
134   topSizer->Add(sizeSizer, 0, wxALL | wxALIGN_CENTER, 5);
135 
136   SetSizer(topSizer);
137   topSizer->Fit(this);
138   topSizer->SetSizeHints(this);
139   Layout();
140 }
141 
142 class gbtLayoutBranchesPanel : public wxPanel {
143 private:
144   wxChoice *m_branchStyle, *m_branchLabels;
145   wxSpinCtrl *m_branchLength, *m_tineLength;
146 
147 public:
148   gbtLayoutBranchesPanel(wxWindow *p_parent, const gbtStyle &);
149 
BranchLength(void) const150   int BranchLength(void) const { return m_branchLength->GetValue(); }
TineLength(void) const151   int TineLength(void) const { return m_tineLength->GetValue(); }
152 
BranchStyle(void) const153   int BranchStyle(void) const { return m_branchStyle->GetSelection(); }
BranchLabels(void) const154   int BranchLabels(void) const { return m_branchLabels->GetSelection(); }
155 };
156 
gbtLayoutBranchesPanel(wxWindow * p_parent,const gbtStyle & p_settings)157 gbtLayoutBranchesPanel::gbtLayoutBranchesPanel(wxWindow *p_parent,
158 			     const gbtStyle &p_settings)
159   : wxPanel(p_parent, -1)
160 {
161   const int BRANCH_LENGTH_MIN = 0;
162   const int BRANCH_LENGTH_MAX = 100;
163 
164   const int TINE_LENGTH_MIN = 20;
165   const int TINE_LENGTH_MAX = 100;
166 
167   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
168 
169   wxStaticBoxSizer *styleBoxSizer =
170     new wxStaticBoxSizer(wxHORIZONTAL, this, _("Drawing branches"));
171 
172   wxFlexGridSizer *styleSizer = new wxFlexGridSizer(2);
173 
174   styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Draw branches")),
175 		  0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
176   wxString styleChoices[] = { _("using straight lines between nodes"),
177 			      _("with a tine for branch labels") };
178   m_branchStyle = new wxChoice(this, -1,
179 			       wxDefaultPosition, wxDefaultSize,
180 			       2, styleChoices);
181   m_branchStyle->SetSelection(p_settings.BranchStyle());
182   styleSizer->Add(m_branchStyle, 1, wxALL | wxEXPAND, 5);
183 
184   styleSizer->Add(new wxStaticText(this, wxID_STATIC, _("Draw labels")),
185 		  1, wxALL | wxALIGN_CENTER_VERTICAL, 5);
186   wxString labelChoices[] = { _("horizontally"),
187 			      _("rotated parallel to the branch") };
188   m_branchLabels = new wxChoice(this, -1,
189 				wxDefaultPosition, wxDefaultSize,
190 				2, labelChoices);
191   m_branchLabels->SetSelection(p_settings.BranchLabels());
192   styleSizer->Add(m_branchLabels, 1, wxALL | wxEXPAND, 5);
193 
194   styleBoxSizer->Add(styleSizer, 1, wxALL | wxEXPAND, 5);
195   topSizer->Add(styleBoxSizer, 0, wxALL | wxALIGN_CENTER, 5);
196 
197   wxStaticBoxSizer *lengthSizer =
198     new wxStaticBoxSizer(wxHORIZONTAL, this, _T("Length of branches"));
199 
200   wxFlexGridSizer *gridSizer = new wxFlexGridSizer(2);
201   gridSizer->AddGrowableCol(1);
202 
203   gridSizer->Add(new wxStaticText(this, -1, _("Length of branch fork")),
204 		 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
205   m_branchLength = new wxSpinCtrl(this, -1,
206 				  wxString::Format(_T("%d"),
207 						   p_settings.BranchLength()),
208 				  wxDefaultPosition, wxDefaultSize,
209 				  wxSP_ARROW_KEYS,
210 				  BRANCH_LENGTH_MIN, BRANCH_LENGTH_MAX);
211   gridSizer->Add(m_branchLength, 1, wxALL | wxEXPAND, 5);
212 
213   gridSizer->Add(new wxStaticText(this, -1, _("Length of branch tine")),
214 		 1, wxALIGN_CENTER_VERTICAL | wxALL, 5);
215   m_tineLength = new wxSpinCtrl(this, -1,
216 				wxString::Format(_T("%d"),
217 						 p_settings.TineLength()),
218 				wxDefaultPosition, wxDefaultSize,
219 				wxSP_ARROW_KEYS,
220 				TINE_LENGTH_MIN, TINE_LENGTH_MAX);
221   gridSizer->Add(m_tineLength, 1, wxALL | wxEXPAND, 5);
222 
223   lengthSizer->Add(gridSizer, 1, wxALL | wxEXPAND, 5);
224   topSizer->Add(lengthSizer, 0, wxALL | wxALIGN_CENTER, 5);
225 
226   SetSizer(topSizer);
227   topSizer->Fit(this);
228   topSizer->SetSizeHints(this);
229   Layout();
230 }
231 
232 class gbtLayoutInfosetsPanel : public wxPanel {
233 private:
234   wxChoice *m_infosetConnect, *m_infosetJoin;
235 
236 public:
237   gbtLayoutInfosetsPanel(wxWindow *p_parent, const gbtStyle &);
238 
InfosetConnect(void) const239   int InfosetConnect(void) const { return m_infosetConnect->GetSelection(); }
InfosetJoin(void) const240   int InfosetJoin(void) const { return m_infosetJoin->GetSelection(); }
241 };
242 
gbtLayoutInfosetsPanel(wxWindow * p_parent,const gbtStyle & p_settings)243 gbtLayoutInfosetsPanel::gbtLayoutInfosetsPanel(wxWindow *p_parent,
244 			     const gbtStyle &p_settings)
245   : wxPanel(p_parent, -1)
246 {
247   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
248 
249   wxStaticBoxSizer *infosetSizer =
250     new wxStaticBoxSizer(wxVERTICAL, this, _("Drawing information sets"));
251 
252   wxFlexGridSizer *styleSizer = new wxFlexGridSizer(2);
253 
254   styleSizer->Add(new wxStaticText(this, wxID_STATIC,
255 				   _("Connect members of information sets")),
256 		  0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
257   wxString connectChoices[] = { _("invisibly (don't draw indicators)"),
258 				_("only when on the same level"),
259 				_("regardless of level") };
260   m_infosetConnect = new wxChoice(this, -1,
261 				  wxDefaultPosition, wxDefaultSize,
262 				  3, connectChoices);
263   m_infosetConnect->SetSelection(p_settings.InfosetConnect());
264   styleSizer->Add(m_infosetConnect, 0, wxALL, 5);
265 
266   styleSizer->Add(new wxStaticText(this, wxID_STATIC,
267 				   _("Draw information set connections")),
268 		  0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
269   wxString joinChoices[] = { _("using lines"),
270 			     _("using bubbles") };
271   m_infosetJoin = new wxChoice(this, -1,
272 			       wxDefaultPosition, wxDefaultSize,
273 			       2, joinChoices);
274   m_infosetJoin->SetSelection(p_settings.InfosetJoin());
275   styleSizer->Add(m_infosetJoin, 0, wxALL | wxEXPAND, 5);
276   infosetSizer->Add(styleSizer, 0, wxALL | wxALIGN_CENTER, 5);
277   topSizer->Add(infosetSizer, 0, wxALL, 5);
278 
279   SetSizer(topSizer);
280   topSizer->Fit(this);
281   topSizer->SetSizeHints(this);
282   Layout();
283 }
284 
gbtLayoutDialog(wxWindow * p_parent,const gbtStyle & p_settings)285 gbtLayoutDialog::gbtLayoutDialog(wxWindow *p_parent,
286 				 const gbtStyle &p_settings)
287   : wxDialog(p_parent, -1, _("Layout options"), wxDefaultPosition),
288     m_toDefaults(false)
289 {
290   m_notebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize);
291   m_notebook->AddPage(new gbtLayoutNodesPanel(m_notebook, p_settings), _("Nodes"));
292   m_notebook->AddPage(new gbtLayoutBranchesPanel(m_notebook, p_settings), _("Branches"));
293   m_notebook->AddPage(new gbtLayoutInfosetsPanel(m_notebook, p_settings),
294 		      _("Information sets"));
295 
296   wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
297   wxButton *defaultsButton = new wxButton(this, -1, _("Set to defaults"));
298   Connect(defaultsButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED,
299 	  wxCommandEventHandler(gbtLayoutDialog::OnSetDefaults));
300   buttonSizer->Add(defaultsButton, 0, wxALL, 5);
301   buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")), 0, wxALL, 5);
302   wxButton *okButton = new wxButton(this, wxID_OK, _("OK"));
303   okButton->SetDefault();
304   buttonSizer->Add(okButton, 0, wxALL, 5);
305 
306   wxBoxSizer *topSizer = new wxBoxSizer(wxVERTICAL);
307   topSizer->Add(m_notebook, 0, wxEXPAND | wxALL, 5);
308   topSizer->Add(buttonSizer, 0, wxALL | wxALIGN_RIGHT, 5);
309 
310   SetSizer(topSizer);
311   topSizer->Fit(this);
312   topSizer->SetSizeHints(this);
313 
314   Layout();
315   CenterOnParent();
316 }
317 
GetSettings(gbtStyle & p_settings)318 void gbtLayoutDialog::GetSettings(gbtStyle &p_settings)
319 {
320   if (m_toDefaults) {
321     p_settings.SetDefaults();
322     return;
323   }
324 
325   gbtLayoutNodesPanel *nodes = (gbtLayoutNodesPanel *) m_notebook->GetPage(0);
326   p_settings.SetNodeSize(nodes->NodeSize());
327   p_settings.SetTerminalSpacing(nodes->TerminalSpacing());
328   p_settings.SetChanceToken(nodes->ChanceToken());
329   p_settings.SetPlayerToken(nodes->PlayerToken());
330   p_settings.SetTerminalToken(nodes->TerminalToken());
331 
332   gbtLayoutBranchesPanel *branches = (gbtLayoutBranchesPanel *) m_notebook->GetPage(1);
333   p_settings.SetBranchLength(branches->BranchLength());
334   p_settings.SetTineLength(branches->TineLength());
335   p_settings.SetBranchStyle(branches->BranchStyle());
336   p_settings.SetBranchLabels(branches->BranchLabels());
337 
338   gbtLayoutInfosetsPanel *infosets = (gbtLayoutInfosetsPanel *) m_notebook->GetPage(2);
339   p_settings.SetInfosetConnect(infosets->InfosetConnect());
340   p_settings.SetInfosetJoin(infosets->InfosetJoin());
341 }
342 
OnSetDefaults(wxCommandEvent &)343 void gbtLayoutDialog::OnSetDefaults(wxCommandEvent &)
344 {
345   m_toDefaults = true;
346   EndModal(wxID_OK);
347 }
348