Stop survey tree opening for double click on label
[survex.git] / src / aventreectrl.cc
blob721bd9c6eef4fd342fbbb3847143630d432ed87c
1 //
2 // aventreectrl.cc
3 //
4 // Tree control used for the survey tree.
5 //
6 // Copyright (C) 2001, Mark R. Shinwell.
7 // Copyright (C) 2001-2003,2005,2006,2016,2018 Olly Betts
8 // Copyright (C) 2005 Martin Green
9 //
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
29 #include "aventreectrl.h"
30 #include "mainfrm.h"
32 enum { STATE_NONE = 0, STATE_VISIBLE };
34 /* XPM */
35 static const char *none_xpm[] = {
36 /* columns rows colors chars-per-pixel */
37 "15 15 1 1",
38 " c None",
39 /* pixels */
40 " ",
41 " ",
42 " ",
43 " ",
44 " ",
45 " ",
46 " ",
47 " ",
48 " ",
49 " ",
50 " ",
51 " ",
52 " ",
53 " ",
54 " "
57 /* XPM */
58 static const char *visible_xpm[] = {
59 /* columns rows colors chars-per-pixel */
60 "15 15 2 1",
61 "X c #007F28",
62 " c None",
63 /* pixels */
64 " ",
65 " XX",
66 " XXX",
67 " XXXX",
68 " XXXX ",
69 " XXXX ",
70 " XXXX ",
71 "XX XXXX ",
72 "XXX XXXX ",
73 "XXXX XXXX ",
74 " XXXXXXX ",
75 " XXXXX ",
76 " XXX ",
77 " X ",
78 " "
81 BEGIN_EVENT_TABLE(AvenTreeCtrl, wxTreeCtrl)
82 EVT_MOTION(AvenTreeCtrl::OnMouseMove)
83 EVT_LEAVE_WINDOW(AvenTreeCtrl::OnLeaveWindow)
84 EVT_TREE_SEL_CHANGED(-1, AvenTreeCtrl::OnSelChanged)
85 EVT_TREE_ITEM_ACTIVATED(-1, AvenTreeCtrl::OnItemActivated)
86 EVT_CHAR(AvenTreeCtrl::OnKeyPress)
87 EVT_TREE_ITEM_MENU(-1, AvenTreeCtrl::OnMenu)
88 EVT_MENU(menu_SURVEY_SHOW_ALL, AvenTreeCtrl::OnRestrict)
89 EVT_MENU(menu_SURVEY_RESTRICT, AvenTreeCtrl::OnRestrict)
90 EVT_MENU(menu_SURVEY_HIDE, AvenTreeCtrl::OnHide)
91 EVT_MENU(menu_SURVEY_SHOW, AvenTreeCtrl::OnShow)
92 EVT_MENU(menu_SURVEY_HIDE_SIBLINGS, AvenTreeCtrl::OnHideSiblings)
93 EVT_TREE_STATE_IMAGE_CLICK(-1, AvenTreeCtrl::OnStateClick)
94 END_EVENT_TABLE()
96 AvenTreeCtrl::AvenTreeCtrl(MainFrm* parent, wxWindow* window_parent) :
97 wxTreeCtrl(window_parent, -1),
98 m_Parent(parent),
99 m_Enabled(false),
100 m_LastItem(),
101 m_BackgroundColour(),
102 m_SelValid(false),
103 menu_data(NULL)
105 wxImageList* img_list = new wxImageList(15, 15, 2);
106 img_list->Add(wxBitmap(none_xpm));
107 img_list->Add(wxBitmap(visible_xpm));
108 AssignStateImageList(img_list);
111 #define TREE_MASK (wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMRIGHT)
113 void AvenTreeCtrl::OnMouseMove(wxMouseEvent& event)
115 if (m_Enabled && !m_Parent->Animating()) {
116 int flags;
117 wxTreeItemId pos = HitTest(event.GetPosition(), flags);
118 if (!(flags & TREE_MASK)) {
119 pos = wxTreeItemId();
121 if (pos == m_LastItem) return;
122 if (pos.IsOk()) {
123 m_Parent->DisplayTreeInfo(GetItemData(pos));
124 } else {
125 m_Parent->DisplayTreeInfo();
130 void AvenTreeCtrl::SetHere(wxTreeItemId pos)
132 if (pos == m_LastItem) return;
134 if (m_LastItem.IsOk()) {
135 SetItemBackgroundColour(m_LastItem, m_BackgroundColour);
137 if (pos.IsOk()) {
138 m_BackgroundColour = GetItemBackgroundColour(pos);
139 SetItemBackgroundColour(pos, wxColour(180, 180, 180));
141 m_LastItem = pos;
144 void AvenTreeCtrl::OnLeaveWindow(wxMouseEvent&)
146 if (m_LastItem.IsOk()) {
147 SetItemBackgroundColour(m_LastItem, m_BackgroundColour);
148 m_LastItem = wxTreeItemId();
150 m_Parent->DisplayTreeInfo();
153 void AvenTreeCtrl::SetEnabled(bool enabled)
155 m_Enabled = enabled;
158 void AvenTreeCtrl::OnSelChanged(wxTreeEvent& e)
160 m_SelValid = true;
163 void AvenTreeCtrl::OnItemActivated(wxTreeEvent& e)
165 if (!m_Enabled) return;
167 m_Parent->TreeItemSelected(GetItemData(e.GetItem()));
170 void AvenTreeCtrl::OnMenu(wxTreeEvent& e)
172 if (m_Enabled) {
173 const TreeData* data = static_cast<const TreeData*>(GetItemData(e.GetItem()));
174 menu_data = data;
175 menu_item = e.GetItem();
176 if (!data) {
177 // Root:
178 wxMenu menu;
179 /* TRANSLATORS: In aven's survey tree, right-clicking on the root
180 * gives a pop-up menu and this is an option (but only enabled if
181 * the view is restricted to a subsurvey). It reloads the current
182 * survey file with the who survey visible.
184 menu.Append(menu_SURVEY_SHOW_ALL, wmsg(/*Show all*/245));
185 if (m_Parent->GetSurvey().empty())
186 menu.Enable(menu_SURVEY_SHOW_ALL, false);
187 PopupMenu(&menu);
188 } else if (data->GetLabel()) {
189 // Station: name is data->GetLabel()->GetText()
190 } else {
191 // Survey:
192 wxMenu menu;
193 /* TRANSLATORS: In aven's survey tree, right-clicking on a survey
194 * name gives a pop-up menu and this is an option. It reloads the
195 * current survey file with the view restricted to the survey
196 * clicked upon.
198 menu.Append(menu_SURVEY_RESTRICT, wmsg(/*Hide others*/246));
199 menu.AppendSeparator();
200 menu.Append(menu_SURVEY_HIDE, wmsg(/*&Hide*/407));
201 menu.Append(menu_SURVEY_SHOW, wmsg(/*&Show*/409));
202 menu.Append(menu_SURVEY_HIDE_SIBLINGS, wmsg(/*Hide si&blings*/388));
203 switch (GetItemState(menu_item)) {
204 case STATE_VISIBLE: // Currently shown.
205 menu.Enable(menu_SURVEY_SHOW, false);
206 break;
207 #if 0
208 case STATE_HIDDEN: // Currently hidden.
209 menu.Enable(menu_SURVEY_RESTRICT, false);
210 menu.Enable(menu_SURVEY_HIDE, false);
211 menu.Enable(menu_SURVEY_HIDE_SIBLINGS, false);
212 break;
213 #endif
214 case STATE_NONE:
215 menu.Enable(menu_SURVEY_HIDE, false);
216 menu.Enable(menu_SURVEY_HIDE_SIBLINGS, false);
217 break;
219 PopupMenu(&menu);
221 menu_data = NULL;
222 e.Skip();
226 bool AvenTreeCtrl::GetSelectionData(wxTreeItemData** data) const
228 assert(m_Enabled);
229 assert(data);
231 if (!m_SelValid) {
232 return false;
235 wxTreeItemId id = GetSelection();
236 if (id.IsOk()) {
237 *data = GetItemData(id);
240 return id.IsOk() && *data;
243 void AvenTreeCtrl::UnselectAll()
245 m_SelValid = false;
246 wxTreeCtrl::UnselectAll();
249 void AvenTreeCtrl::DeleteAllItems()
251 m_Enabled = false;
252 m_LastItem = wxTreeItemId();
253 m_SelValid = false;
254 wxTreeCtrl::DeleteAllItems();
255 filter.clear();
256 filter.SetSeparator(m_Parent->GetSeparator());
259 void AvenTreeCtrl::OnKeyPress(wxKeyEvent &e)
261 switch (e.GetKeyCode()) {
262 case WXK_ESCAPE:
263 m_Parent->ClearTreeSelection();
264 break;
265 case WXK_RETURN: {
266 wxTreeItemId id = GetSelection();
267 if (id.IsOk()) {
268 if (ItemHasChildren(id)) {
269 // If on a branch, expand/contract it.
270 if (IsExpanded(id)) {
271 Collapse(id);
272 } else {
273 Expand(id);
275 } else {
276 // If on a station, centre on it by selecting it twice.
277 m_Parent->TreeItemSelected(GetItemData(id));
278 m_Parent->TreeItemSelected(GetItemData(id));
281 break;
283 case WXK_LEFT: case WXK_RIGHT: case WXK_UP: case WXK_DOWN:
284 case WXK_HOME: case WXK_END: case WXK_PAGEUP: case WXK_PAGEDOWN:
285 e.Skip();
286 break;
287 default:
288 // Pass key event to MainFrm which will pass to GfxCore which will
289 // pass to GUIControl.
290 m_Parent->OnKeyPress(e);
291 break;
295 void AvenTreeCtrl::OnRestrict(wxCommandEvent& e)
297 m_Parent->RestrictTo(menu_data ? menu_data->GetSurvey() : wxString());
300 void AvenTreeCtrl::OnHide(wxCommandEvent& e)
302 // Shouldn't be available for the root item.
303 wxASSERT(menu_data);
304 // Hide should be disabled unless the item is explicitly shown.
305 wxASSERT(GetItemState(menu_item) == STATE_VISIBLE);
306 SetItemState(menu_item, STATE_NONE);
307 filter.remove(menu_data->GetSurvey());
308 #if 0
309 Freeze();
310 // Show siblings if not already shown or hidden.
311 wxTreeItemId i = menu_item;
312 while ((i = GetPrevSibling(i)).IsOk()) {
313 if (GetItemState(i) == wxTREE_ITEMSTATE_NONE)
314 SetItemState(i, 1);
316 i = menu_item;
317 while ((i = GetNextSibling(i)).IsOk()) {
318 if (GetItemState(i) == wxTREE_ITEMSTATE_NONE)
319 SetItemState(i, 1);
321 Thaw();
322 #endif
323 m_Parent->ForceFullRedraw();
326 void AvenTreeCtrl::OnShow(wxCommandEvent& e)
328 // Shouldn't be available for the root item.
329 wxASSERT(menu_data);
330 // Show should be disabled for an explicitly shown item.
331 wxASSERT(GetItemState(menu_item) != STATE_VISIBLE);
332 Freeze();
333 SetItemState(menu_item, STATE_VISIBLE);
334 filter.add(menu_data->GetSurvey());
335 // Hide siblings if not already shown or hidden.
336 wxTreeItemId i = menu_item;
337 while ((i = GetPrevSibling(i)).IsOk()) {
338 if (GetItemState(i) == wxTREE_ITEMSTATE_NONE)
339 SetItemState(i, STATE_NONE);
341 i = menu_item;
342 while ((i = GetNextSibling(i)).IsOk()) {
343 if (GetItemState(i) == wxTREE_ITEMSTATE_NONE)
344 SetItemState(i, STATE_NONE);
346 Thaw();
347 m_Parent->ForceFullRedraw();
350 void AvenTreeCtrl::OnHideSiblings(wxCommandEvent& e)
352 // Shouldn't be available for the root item.
353 wxASSERT(menu_data);
354 Freeze();
355 SetItemState(menu_item, STATE_VISIBLE);
356 filter.add(menu_data->GetSurvey());
358 wxTreeItemId i = menu_item;
359 while ((i = GetPrevSibling(i)).IsOk()) {
360 const TreeData* data = static_cast<const TreeData*>(GetItemData(i));
361 filter.remove(data->GetSurvey());
362 SetItemState(i, STATE_NONE);
364 i = menu_item;
365 while ((i = GetNextSibling(i)).IsOk()) {
366 const TreeData* data = static_cast<const TreeData*>(GetItemData(i));
367 filter.remove(data->GetSurvey());
368 SetItemState(i, STATE_NONE);
370 Thaw();
371 m_Parent->ForceFullRedraw();
374 void AvenTreeCtrl::OnStateClick(wxTreeEvent& e)
376 auto item = e.GetItem();
377 const TreeData* data = static_cast<const TreeData*>(GetItemData(item));
378 if (GetItemState(item) == STATE_VISIBLE) {
379 filter.remove(data->GetSurvey());
380 SetItemState(item, STATE_NONE);
381 } else {
382 filter.add(data->GetSurvey());
383 SetItemState(item, STATE_VISIBLE);
385 e.Skip();
386 m_Parent->ForceFullRedraw();