source: git/src/guicontrol.cc@ 2102591

RELEASE/1.2 debug-ci debug-ci-sanitisers faster-cavernlog log-select main stereo stereo-2025 walls-data walls-data-hanging-as-warning warn-only-for-hanging-survey
Last change on this file since 2102591 was b96edeb, checked in by Olly Betts <olly@…>, 9 years ago

Partition traverses into list by flag combinations

Instead of a list for surface and one for underground, we now have
8 lists of traverses, one for each combination of img_FLAG_SURFACE,
img_FLAG_SPLAY and img_FLAG_DUPLICATE.

Also allow "Dashed" for splays and "Faded" for duplicate legs.

  • Property mode set to 100644
File size: 32.1 KB
Line 
1//
2// guicontrol.cc
3//
4// Handlers for events relating to the display of a survey.
5//
6// Copyright (C) 2000-2002,2005 Mark R. Shinwell
7// Copyright (C) 2001,2003,2004,2005,2006,2011,2012,2014,2015,2016 Olly Betts
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 2 of the License, or
12// (at your option) any later version.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22//
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include "guicontrol.h"
29#include "gfxcore.h"
30#include <wx/confbase.h>
31
32const int DISPLAY_SHIFT = 10;
33const double FLYFREE_SHIFT = 0.2;
34const double ROTATE_STEP = 2.0;
35
36GUIControl::GUIControl()
37 : dragging(NO_DRAG)
38{
39 m_View = NULL;
40 m_ReverseControls = false;
41 m_LastDrag = drag_NONE;
42}
43
44void GUIControl::SetView(GfxCore* view)
45{
46 m_View = view;
47}
48
49bool GUIControl::MouseDown() const
50{
51 return (dragging != NO_DRAG);
52}
53
54void GUIControl::HandleTilt(wxPoint point)
55{
56 // Handle a mouse movement during tilt mode.
57
58 // wxGTK (at least) fails to update the cursor while dragging.
59 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
60
61 int dy = point.y - m_DragStart.y;
62
63 if (m_ReverseControls != m_View->GetPerspective()) dy = -dy;
64
65 m_View->TiltCave(Double(dy) * 0.36);
66
67 m_DragStart = point;
68
69 m_View->ForceRefresh();
70}
71
72void GUIControl::HandleTranslate(wxPoint point)
73{
74 // Handle a mouse movement during translation mode.
75
76 // wxGTK (at least) fails to update the cursor while dragging.
77 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
78
79 int dx = point.x - m_DragStart.x;
80 int dy = point.y - m_DragStart.y;
81
82 if (m_ReverseControls) {
83 dx = -dx;
84 dy = -dy;
85 }
86
87 if (m_View->GetPerspective())
88 m_View->MoveViewer(0, -dy * .1, dx * .1);
89 else
90 m_View->TranslateCave(dx, dy);
91
92 m_DragStart = point;
93}
94
95void GUIControl::HandleScaleRotate(wxPoint point)
96{
97 // Handle a mouse movement during scale/rotate mode.
98
99 // wxGTK (at least) fails to update the cursor while dragging.
100 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM_ROTATE);
101
102 int dx, dy;
103 int threshold;
104 if (m_ScaleRotateLock == lock_NONE) {
105 // Dragging to scale or rotate but we've not decided which yet.
106 dx = point.x - m_DragRealStart.x;
107 dy = point.y - m_DragRealStart.y;
108 threshold = 8 * 8;
109 } else {
110 dx = point.x - m_DragStart.x;
111 dy = point.y - m_DragStart.y;
112 threshold = 5;
113 }
114 int dx2 = dx * dx;
115 int dy2 = dy * dy;
116 if (dx2 + dy2 < threshold) return;
117
118 switch (m_ScaleRotateLock) {
119 case lock_NONE:
120 if (dx2 > dy2) {
121 m_ScaleRotateLock = lock_ROTATE;
122// m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
123 } else {
124 m_ScaleRotateLock = lock_SCALE;
125// m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
126 }
127 break;
128 case lock_SCALE:
129 if (dx2 >= 8 * dy2) {
130 m_ScaleRotateLock = lock_ROTATE;
131// m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
132 }
133 break;
134 case lock_ROTATE:
135 if (dy2 >= 8 * dx2) {
136 m_ScaleRotateLock = lock_SCALE;
137// m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
138 }
139 break;
140 }
141
142 if (m_ScaleRotateLock == lock_ROTATE) {
143 dy = 0;
144 } else {
145 dx = 0;
146 }
147
148 if (m_ReverseControls) {
149 dx = -dx;
150 dy = -dy;
151 }
152
153 if (m_View->GetPerspective()) {
154 if (dy) m_View->MoveViewer(-dy * .1, 0, 0);
155 } else {
156 // up/down => scale.
157 if (dy) m_View->SetScale(m_View->GetScale() * pow(1.06, 0.08 * dy));
158 // left/right => rotate.
159 if (dx) m_View->TurnCave(Double(dx) * -0.36);
160 if (dx || dy) m_View->ForceRefresh();
161 }
162
163 m_DragStart = point;
164}
165
166void GUIControl::HandleTiltRotate(wxPoint point)
167{
168 // Handle a mouse movement during tilt/rotate mode.
169 if (m_View->IsExtendedElevation()) return;
170
171 // wxGTK (at least) fails to update the cursor while dragging.
172 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
173
174 int dx = point.x - m_DragStart.x;
175 int dy = point.y - m_DragStart.y;
176
177 if (m_ReverseControls != m_View->GetPerspective()) {
178 dx = -dx;
179 dy = -dy;
180 }
181
182 // left/right => rotate, up/down => tilt.
183 // Make tilt less sensitive than rotate as that feels better.
184 m_View->TurnCave(Double(dx) * -0.36);
185 m_View->TiltCave(Double(dy) * 0.18);
186
187 m_View->ForceRefresh();
188
189 m_DragStart = point;
190}
191
192void GUIControl::HandleRotate(wxPoint point)
193{
194 // Handle a mouse movement during rotate mode.
195 if (m_View->IsExtendedElevation()) return;
196
197 // wxGTK (at least) fails to update the cursor while dragging.
198 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
199
200 int dx = point.x - m_DragStart.x;
201 int dy = point.y - m_DragStart.y;
202
203 if (m_ReverseControls != m_View->GetPerspective()) {
204 dx = -dx;
205 dy = -dy;
206 }
207
208 // left/right => rotate.
209 m_View->TurnCave(Double(dx) * -0.36);
210
211 m_View->ForceRefresh();
212
213 m_DragStart = point;
214}
215
216void GUIControl::RestoreCursor()
217{
218 if (m_View->HereIsReal()) {
219 m_View->UpdateCursor(GfxCore::CURSOR_POINTING_HAND);
220 } else {
221 m_View->UpdateCursor(GfxCore::CURSOR_DEFAULT);
222 }
223}
224
225void GUIControl::HandleNonDrag(const wxPoint & point) {
226 if (m_View->IsFullScreen()) {
227 if (m_View->FullScreenModeShowingMenus()) {
228 if (point.y > 8)
229 m_View->FullScreenModeShowMenus(false);
230 } else {
231 if (point.y == 0) {
232 m_View->FullScreenModeShowMenus(true);
233 }
234 }
235 }
236 if (m_View->CheckHitTestGrid(point, false)) {
237 m_View->UpdateCursor(GfxCore::CURSOR_POINTING_HAND);
238 } else if (m_View->PointWithinScaleBar(point)) {
239 m_View->UpdateCursor(GfxCore::CURSOR_HORIZONTAL_RESIZE);
240 } else if (m_View->PointWithinCompass(point)) {
241 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
242 } else if (m_View->PointWithinClino(point)) {
243 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
244 } else {
245 RestoreCursor();
246 }
247}
248
249//
250// Mouse event handling methods
251//
252
253void GUIControl::OnMouseMove(wxMouseEvent& event)
254{
255 // Mouse motion event handler.
256 if (!m_View->HasData()) return;
257
258 // Ignore moves which don't change the position.
259 if (event.GetPosition() == m_DragStart) {
260 return;
261 }
262
263 static long timestamp = LONG_MIN;
264 if (dragging != NO_DRAG && m_ScaleRotateLock != lock_NONE &&
265 timestamp != LONG_MIN) {
266 // If no motion for a second, reset the direction lock.
267 if (event.GetTimestamp() - timestamp >= 1000) {
268 m_ScaleRotateLock = lock_NONE;
269 m_DragRealStart = m_DragStart;
270 RestoreCursor();
271 }
272 }
273 timestamp = event.GetTimestamp();
274
275 wxPoint point(event.GetPosition());
276
277 // Check hit-test grid (only if no buttons are pressed).
278 if (!event.LeftIsDown() && !event.MiddleIsDown() && !event.RightIsDown()) {
279 HandleNonDrag(point);
280 }
281
282 // Update coordinate display if in plan view,
283 // or altitude if in elevation view.
284 m_View->SetCoords(point);
285
286 switch (dragging) {
287 case LEFT_DRAG:
288 switch (m_LastDrag) {
289 case drag_COMPASS:
290 // Drag in heading indicator.
291 m_View->SetCompassFromPoint(point);
292 break;
293 case drag_ELEV:
294 // Drag in clinometer.
295 m_View->SetClinoFromPoint(point);
296 break;
297 case drag_SCALE:
298 m_View->SetScaleBarFromOffset(point.x - m_DragLast.x);
299 break;
300 case drag_MAIN:
301 if (event.ControlDown()) {
302 HandleTiltRotate(point);
303 } else {
304 HandleScaleRotate(point);
305 }
306 break;
307 case drag_ZOOM:
308 m_View->SetZoomBox(m_DragStart, point, !event.ShiftDown(), event.ControlDown());
309 break;
310 case drag_NONE:
311 // Shouldn't happen?! FIXME: assert or something.
312 break;
313 }
314 break;
315 case MIDDLE_DRAG:
316 HandleTilt(point);
317 break;
318 case RIGHT_DRAG:
319 HandleTranslate(point);
320 break;
321 case NO_DRAG:
322 break;
323 }
324
325 m_DragLast = point;
326}
327
328void GUIControl::OnLButtonDown(wxMouseEvent& event)
329{
330 if (m_View->HasData()) {
331 m_DragStart = m_DragRealStart = event.GetPosition();
332
333 if (m_View->PointWithinCompass(m_DragStart)) {
334 m_LastDrag = drag_COMPASS;
335 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
336 } else if (m_View->PointWithinClino(m_DragStart)) {
337 m_LastDrag = drag_ELEV;
338 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
339 } else if (m_View->PointWithinScaleBar(m_DragStart)) {
340 m_LastDrag = drag_SCALE;
341 m_View->UpdateCursor(GfxCore::CURSOR_HORIZONTAL_RESIZE);
342 } else if (event.ShiftDown()) {
343 m_LastDrag = drag_ZOOM;
344 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
345 } else {
346 if (event.ControlDown() && !m_View->IsExtendedElevation()) {
347 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
348 } else {
349 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM_ROTATE);
350 }
351
352 m_LastDrag = drag_MAIN;
353 m_ScaleRotateLock = lock_NONE;
354 }
355
356 // We need to release and recapture for the cursor to update (noticed
357 // with wxGTK).
358 if (dragging != NO_DRAG) m_View->ReleaseMouse();
359 m_View->CaptureMouse();
360
361 dragging = LEFT_DRAG;
362 }
363}
364
365void GUIControl::OnLButtonUp(wxMouseEvent& event)
366{
367 if (m_View->HasData()) {
368 if (dragging != LEFT_DRAG)
369 return;
370
371 if (event.MiddleIsDown()) {
372 if (m_LastDrag == drag_ZOOM)
373 m_View->UnsetZoomBox();
374 OnMButtonDown(event);
375 return;
376 }
377
378 if (event.RightIsDown()) {
379 if (m_LastDrag == drag_ZOOM)
380 m_View->UnsetZoomBox();
381 OnRButtonDown(event);
382 return;
383 }
384
385 if (m_LastDrag == drag_ZOOM) {
386 m_View->ZoomBoxGo();
387 }
388
389 m_View->ReleaseMouse();
390
391 m_LastDrag = drag_NONE;
392 dragging = NO_DRAG;
393
394 m_View->DragFinished();
395
396 if (event.GetPosition() == m_DragRealStart) {
397 // Just a "click"...
398 m_View->CheckHitTestGrid(m_DragStart, true);
399 RestoreCursor();
400 } else {
401 HandleNonDrag(event.GetPosition());
402 }
403 }
404}
405
406void GUIControl::OnMButtonDown(wxMouseEvent& event)
407{
408 if (m_View->HasData() && !m_View->IsExtendedElevation()) {
409 m_DragStart = event.GetPosition();
410
411 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
412
413 if (dragging != NO_DRAG) {
414 if (m_LastDrag == drag_ZOOM)
415 m_View->UnsetZoomBox();
416 // We need to release and recapture for the cursor to update
417 // (noticed with wxGTK).
418 m_View->ReleaseMouse();
419 }
420 m_View->CaptureMouse();
421 dragging = MIDDLE_DRAG;
422 }
423}
424
425void GUIControl::OnMButtonUp(wxMouseEvent& event)
426{
427 if (m_View->HasData()) {
428 if (dragging != MIDDLE_DRAG)
429 return;
430
431 if (event.LeftIsDown()) {
432 OnLButtonDown(event);
433 return;
434 }
435
436 if (event.RightIsDown()) {
437 OnRButtonDown(event);
438 return;
439 }
440
441 dragging = NO_DRAG;
442 m_View->ReleaseMouse();
443 m_View->DragFinished();
444
445 RestoreCursor();
446 }
447}
448
449void GUIControl::OnRButtonDown(wxMouseEvent& event)
450{
451 if (m_View->HasData()) {
452 if (m_View->HandleRClick(event.GetPosition()))
453 return;
454
455 m_DragStart = event.GetPosition();
456
457 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
458
459 if (dragging != NO_DRAG) {
460 if (m_LastDrag == drag_ZOOM)
461 m_View->UnsetZoomBox();
462 // We need to release and recapture for the cursor to update
463 // (noticed with wxGTK).
464 m_View->ReleaseMouse();
465 }
466 m_View->CaptureMouse();
467 dragging = RIGHT_DRAG;
468 }
469}
470
471void GUIControl::OnRButtonUp(wxMouseEvent& event)
472{
473 if (dragging != RIGHT_DRAG)
474 return;
475
476 if (event.LeftIsDown()) {
477 OnLButtonDown(event);
478 return;
479 }
480
481 if (event.MiddleIsDown()) {
482 OnMButtonDown(event);
483 return;
484 }
485
486 m_LastDrag = drag_NONE;
487 m_View->ReleaseMouse();
488
489 dragging = NO_DRAG;
490
491 RestoreCursor();
492
493 m_View->DragFinished();
494}
495
496void GUIControl::OnMouseWheel(wxMouseEvent& event) {
497 int dy = event.GetWheelRotation();
498 if (m_View->GetPerspective()) {
499 m_View->MoveViewer(-dy, 0, 0);
500 } else {
501 m_View->SetScale(m_View->GetScale() * pow(1.06, -0.04 * dy));
502 m_View->ForceRefresh();
503 }
504}
505
506void GUIControl::OnDisplayOverlappingNames()
507{
508 m_View->ToggleOverlappingNames();
509}
510
511void GUIControl::OnDisplayOverlappingNamesUpdate(wxUpdateUIEvent& cmd)
512{
513 cmd.Enable(m_View->HasData() && m_View->ShowingStationNames());
514 cmd.Check(m_View->ShowingOverlappingNames());
515}
516
517void GUIControl::OnColourByDepth()
518{
519 if (m_View->ColouringBy() == COLOUR_BY_DEPTH) {
520 m_View->SetColourBy(COLOUR_BY_NONE);
521 } else {
522 m_View->SetColourBy(COLOUR_BY_DEPTH);
523 }
524}
525
526void GUIControl::OnColourByDate()
527{
528 if (m_View->ColouringBy() == COLOUR_BY_DATE) {
529 m_View->SetColourBy(COLOUR_BY_NONE);
530 } else {
531 m_View->SetColourBy(COLOUR_BY_DATE);
532 }
533}
534
535void GUIControl::OnColourByError()
536{
537 if (m_View->ColouringBy() == COLOUR_BY_ERROR) {
538 m_View->SetColourBy(COLOUR_BY_NONE);
539 } else {
540 m_View->SetColourBy(COLOUR_BY_ERROR);
541 }
542}
543
544void GUIControl::OnColourByGradient()
545{
546 if (m_View->ColouringBy() == COLOUR_BY_GRADIENT) {
547 m_View->SetColourBy(COLOUR_BY_NONE);
548 } else {
549 m_View->SetColourBy(COLOUR_BY_GRADIENT);
550 }
551}
552
553void GUIControl::OnColourByLength()
554{
555 if (m_View->ColouringBy() == COLOUR_BY_LENGTH) {
556 m_View->SetColourBy(COLOUR_BY_NONE);
557 } else {
558 m_View->SetColourBy(COLOUR_BY_LENGTH);
559 }
560}
561
562void GUIControl::OnColourByUpdate(wxUpdateUIEvent& cmd)
563{
564 cmd.Enable(m_View->HasData());
565}
566
567void GUIControl::OnColourByDepthUpdate(wxUpdateUIEvent& cmd)
568{
569 cmd.Enable(m_View->HasData());
570 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DEPTH);
571}
572
573void GUIControl::OnColourByDateUpdate(wxUpdateUIEvent& cmd)
574{
575 cmd.Enable(m_View->HasData());
576 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DATE);
577}
578
579void GUIControl::OnColourByErrorUpdate(wxUpdateUIEvent& cmd)
580{
581 cmd.Enable(m_View->HasData());
582 cmd.Check(m_View->ColouringBy() == COLOUR_BY_ERROR);
583}
584
585void GUIControl::OnColourByGradientUpdate(wxUpdateUIEvent& cmd)
586{
587 cmd.Enable(m_View->HasData());
588 cmd.Check(m_View->ColouringBy() == COLOUR_BY_GRADIENT);
589}
590
591void GUIControl::OnColourByLengthUpdate(wxUpdateUIEvent& cmd)
592{
593 cmd.Enable(m_View->HasData());
594 cmd.Check(m_View->ColouringBy() == COLOUR_BY_LENGTH);
595}
596
597void GUIControl::OnShowCrosses()
598{
599 m_View->ToggleCrosses();
600}
601
602void GUIControl::OnShowCrossesUpdate(wxUpdateUIEvent& cmd)
603{
604 cmd.Enable(m_View->HasData());
605 cmd.Check(m_View->ShowingCrosses());
606}
607
608void GUIControl::OnShowStationNames()
609{
610 m_View->ToggleStationNames();
611}
612
613void GUIControl::OnShowStationNamesUpdate(wxUpdateUIEvent& cmd)
614{
615 cmd.Enable(m_View->HasData());
616 cmd.Check(m_View->ShowingStationNames());
617}
618
619void GUIControl::OnShowSurveyLegs()
620{
621 m_View->ToggleUndergroundLegs();
622}
623
624void GUIControl::OnShowSurveyLegsUpdate(wxUpdateUIEvent& cmd)
625{
626 cmd.Enable(m_View->HasData() && m_View->HasUndergroundLegs());
627 cmd.Check(m_View->ShowingUndergroundLegs());
628}
629
630void GUIControl::OnHideSplays()
631{
632 m_View->SetSplaysMode(SHOW_HIDE);
633}
634
635void GUIControl::OnShowSplaysDashed()
636{
637 m_View->SetSplaysMode(SHOW_DASHED);
638}
639
640void GUIControl::OnShowSplaysFaded()
641{
642 m_View->SetSplaysMode(SHOW_FADED);
643}
644
645void GUIControl::OnShowSplaysNormal()
646{
647 m_View->SetSplaysMode(SHOW_NORMAL);
648}
649
650void GUIControl::OnSplaysUpdate(wxUpdateUIEvent& cmd)
651{
652 cmd.Enable(m_View->HasData() && m_View->HasSplays());
653}
654
655void GUIControl::OnHideSplaysUpdate(wxUpdateUIEvent& cmd)
656{
657 cmd.Enable(m_View->HasData() && m_View->HasSplays());
658 cmd.Check(m_View->ShowingSplaysMode() == SHOW_HIDE);
659}
660
661void GUIControl::OnShowSplaysDashedUpdate(wxUpdateUIEvent& cmd)
662{
663 cmd.Enable(m_View->HasData() && m_View->HasSplays());
664 cmd.Check(m_View->ShowingSplaysMode() == SHOW_DASHED);
665}
666
667void GUIControl::OnShowSplaysFadedUpdate(wxUpdateUIEvent& cmd)
668{
669 cmd.Enable(m_View->HasData() && m_View->HasSplays());
670 cmd.Check(m_View->ShowingSplaysMode() == SHOW_FADED);
671}
672
673void GUIControl::OnShowSplaysNormalUpdate(wxUpdateUIEvent& cmd)
674{
675 cmd.Enable(m_View->HasData() && m_View->HasSplays());
676 cmd.Check(m_View->ShowingSplaysMode() == SHOW_NORMAL);
677}
678
679void GUIControl::OnHideDupes() {
680 m_View->SetDupesMode(SHOW_HIDE);
681}
682
683void GUIControl::OnShowDupesDashed() {
684 m_View->SetDupesMode(SHOW_DASHED);
685}
686
687void GUIControl::OnShowDupesFaded() {
688 m_View->SetDupesMode(SHOW_FADED);
689}
690
691void GUIControl::OnShowDupesNormal() {
692 m_View->SetDupesMode(SHOW_NORMAL);
693}
694
695void GUIControl::OnDupesUpdate(wxUpdateUIEvent& cmd) {
696 cmd.Enable(m_View->HasData() && m_View->HasDupes());
697}
698
699void GUIControl::OnHideDupesUpdate(wxUpdateUIEvent& cmd) {
700 cmd.Enable(m_View->HasData() && m_View->HasDupes());
701 cmd.Check(m_View->ShowingDupesMode() == SHOW_HIDE);
702}
703
704void GUIControl::OnShowDupesDashedUpdate(wxUpdateUIEvent& cmd) {
705 cmd.Enable(m_View->HasData() && m_View->HasDupes());
706 cmd.Check(m_View->ShowingDupesMode() == SHOW_DASHED);
707}
708
709void GUIControl::OnShowDupesFadedUpdate(wxUpdateUIEvent& cmd) {
710 cmd.Enable(m_View->HasData() && m_View->HasDupes());
711 cmd.Check(m_View->ShowingDupesMode() == SHOW_FADED);
712}
713
714void GUIControl::OnShowDupesNormalUpdate(wxUpdateUIEvent& cmd) {
715 cmd.Enable(m_View->HasData() && m_View->HasDupes());
716 cmd.Check(m_View->ShowingDupesMode() == SHOW_NORMAL);
717}
718
719void GUIControl::OnMoveEast()
720{
721 m_View->TurnCaveTo(90.0);
722 m_View->ForceRefresh();
723}
724
725void GUIControl::OnMoveEastUpdate(wxUpdateUIEvent& cmd)
726{
727 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 90.0);
728}
729
730void GUIControl::OnMoveNorth()
731{
732 m_View->TurnCaveTo(0.0);
733 m_View->ForceRefresh();
734}
735
736void GUIControl::OnMoveNorthUpdate(wxUpdateUIEvent& cmd)
737{
738 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 0.0);
739}
740
741void GUIControl::OnMoveSouth()
742{
743 m_View->TurnCaveTo(180.0);
744 m_View->ForceRefresh();
745}
746
747void GUIControl::OnMoveSouthUpdate(wxUpdateUIEvent& cmd)
748{
749 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 180.0);
750}
751
752void GUIControl::OnMoveWest()
753{
754 m_View->TurnCaveTo(270.0);
755 m_View->ForceRefresh();
756}
757
758void GUIControl::OnMoveWestUpdate(wxUpdateUIEvent& cmd)
759{
760 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 270.0);
761}
762
763void GUIControl::OnToggleRotation()
764{
765 m_View->ToggleRotation();
766}
767
768void GUIControl::OnToggleRotationUpdate(wxUpdateUIEvent& cmd)
769{
770 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
771 cmd.Check(m_View->HasData() && m_View->IsRotating());
772}
773
774void GUIControl::OnReverseControls()
775{
776 m_ReverseControls = !m_ReverseControls;
777}
778
779void GUIControl::OnReverseControlsUpdate(wxUpdateUIEvent& cmd)
780{
781 cmd.Enable(m_View->HasData());
782 cmd.Check(m_ReverseControls);
783}
784
785void GUIControl::OnReverseDirectionOfRotation()
786{
787 m_View->ReverseRotation();
788}
789
790void GUIControl::OnReverseDirectionOfRotationUpdate(wxUpdateUIEvent& cmd)
791{
792 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
793}
794
795void GUIControl::OnStepOnceAnticlockwise(bool accel)
796{
797 if (m_View->GetPerspective()) {
798 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
799 } else {
800 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
801 }
802 m_View->ForceRefresh();
803}
804
805void GUIControl::OnStepOnceClockwise(bool accel)
806{
807 if (m_View->GetPerspective()) {
808 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
809 } else {
810 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
811 }
812 m_View->ForceRefresh();
813}
814
815void GUIControl::OnDefaults()
816{
817 m_View->Defaults();
818}
819
820void GUIControl::OnDefaultsUpdate(wxUpdateUIEvent& cmd)
821{
822 cmd.Enable(m_View->HasData());
823}
824
825void GUIControl::OnElevation()
826{
827 // Switch to elevation view.
828
829 m_View->SwitchToElevation();
830}
831
832void GUIControl::OnElevationUpdate(wxUpdateUIEvent& cmd)
833{
834 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingElevation());
835}
836
837void GUIControl::OnHigherViewpoint(bool accel)
838{
839 // Raise the viewpoint.
840 if (m_View->GetPerspective()) {
841 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
842 } else {
843 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
844 }
845 m_View->ForceRefresh();
846}
847
848void GUIControl::OnLowerViewpoint(bool accel)
849{
850 // Lower the viewpoint.
851 if (m_View->GetPerspective()) {
852 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
853 } else {
854 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
855 }
856 m_View->ForceRefresh();
857}
858
859void GUIControl::OnPlan()
860{
861 // Switch to plan view.
862 m_View->SwitchToPlan();
863}
864
865void GUIControl::OnPlanUpdate(wxUpdateUIEvent& cmd)
866{
867 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingPlan());
868}
869
870void GUIControl::OnShiftDisplayDown(bool accel)
871{
872 if (m_View->GetPerspective())
873 m_View->MoveViewer(0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0);
874 else
875 m_View->TranslateCave(0, accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT);
876}
877
878void GUIControl::OnShiftDisplayLeft(bool accel)
879{
880 if (m_View->GetPerspective())
881 m_View->MoveViewer(0, 0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT);
882 else
883 m_View->TranslateCave(accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT, 0);
884}
885
886void GUIControl::OnShiftDisplayRight(bool accel)
887{
888 if (m_View->GetPerspective())
889 m_View->MoveViewer(0, 0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT);
890 else
891 m_View->TranslateCave(accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT, 0);
892}
893
894void GUIControl::OnShiftDisplayUp(bool accel)
895{
896 if (m_View->GetPerspective())
897 m_View->MoveViewer(0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0);
898 else
899 m_View->TranslateCave(0, accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT);
900}
901
902void GUIControl::OnZoomIn(bool accel)
903{
904 // Increase the scale.
905
906 if (m_View->GetPerspective()) {
907 m_View->MoveViewer(accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0, 0);
908 } else {
909 m_View->SetScale(m_View->GetScale() * (accel ? 1.1236 : 1.06));
910 m_View->ForceRefresh();
911 }
912}
913
914void GUIControl::OnZoomOut(bool accel)
915{
916 // Decrease the scale.
917
918 if (m_View->GetPerspective()) {
919 m_View->MoveViewer(accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0, 0);
920 } else {
921 m_View->SetScale(m_View->GetScale() / (accel ? 1.1236 : 1.06));
922 m_View->ForceRefresh();
923 }
924}
925
926void GUIControl::OnToggleScalebar()
927{
928 m_View->ToggleScaleBar();
929}
930
931void GUIControl::OnToggleScalebarUpdate(wxUpdateUIEvent& cmd)
932{
933 cmd.Enable(m_View->HasData());
934 cmd.Check(m_View->ShowingScaleBar());
935}
936
937void GUIControl::OnToggleColourKey()
938{
939 m_View->ToggleColourKey();
940}
941
942void GUIControl::OnToggleColourKeyUpdate(wxUpdateUIEvent& cmd)
943{
944 cmd.Enable(m_View->HasData() && m_View->ColouringBy() != COLOUR_BY_NONE);
945 cmd.Check(m_View->ShowingColourKey());
946}
947
948void GUIControl::OnViewCompass()
949{
950 m_View->ToggleCompass();
951}
952
953void GUIControl::OnViewCompassUpdate(wxUpdateUIEvent& cmd)
954{
955 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
956 cmd.Check(m_View->ShowingCompass());
957}
958
959void GUIControl::OnViewClino()
960{
961 m_View->ToggleClino();
962}
963
964void GUIControl::OnViewClinoUpdate(wxUpdateUIEvent& cmd)
965{
966 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
967 cmd.Check(m_View->ShowingClino());
968}
969
970void GUIControl::OnShowSurface()
971{
972 m_View->ToggleSurfaceLegs();
973}
974
975void GUIControl::OnShowSurfaceUpdate(wxUpdateUIEvent& cmd)
976{
977 cmd.Enable(m_View->HasData() && m_View->HasSurfaceLegs());
978 cmd.Check(m_View->ShowingSurfaceLegs());
979}
980
981void GUIControl::OnShowEntrances()
982{
983 m_View->ToggleEntrances();
984}
985
986void GUIControl::OnShowEntrancesUpdate(wxUpdateUIEvent& cmd)
987{
988 cmd.Enable(m_View->HasData() && (m_View->GetNumEntrances() > 0));
989 cmd.Check(m_View->ShowingEntrances());
990}
991
992void GUIControl::OnShowFixedPts()
993{
994 m_View->ToggleFixedPts();
995}
996
997void GUIControl::OnShowFixedPtsUpdate(wxUpdateUIEvent& cmd)
998{
999 cmd.Enable(m_View->HasData() && (m_View->GetNumFixedPts() > 0));
1000 cmd.Check(m_View->ShowingFixedPts());
1001}
1002
1003void GUIControl::OnShowExportedPts()
1004{
1005 m_View->ToggleExportedPts();
1006}
1007
1008void GUIControl::OnShowExportedPtsUpdate(wxUpdateUIEvent& cmd)
1009{
1010 cmd.Enable(m_View->HasData() && (m_View->GetNumExportedPts() > 0));
1011 cmd.Check(m_View->ShowingExportedPts());
1012}
1013
1014void GUIControl::OnViewGrid()
1015{
1016 m_View->ToggleGrid();
1017}
1018
1019void GUIControl::OnViewGridUpdate(wxUpdateUIEvent& cmd)
1020{
1021 cmd.Enable(m_View->HasData());
1022 cmd.Check(m_View->ShowingGrid());
1023}
1024
1025void GUIControl::OnIndicatorsUpdate(wxUpdateUIEvent& cmd)
1026{
1027 cmd.Enable(m_View->HasData());
1028}
1029
1030void GUIControl::OnViewPerspective()
1031{
1032 m_View->TogglePerspective();
1033 // Force update of coordinate display.
1034 if (m_View->GetPerspective()) {
1035 m_View->MoveViewer(0, 0, 0);
1036 } else {
1037 m_View->ClearCoords();
1038 }
1039}
1040
1041void GUIControl::OnViewPerspectiveUpdate(wxUpdateUIEvent& cmd)
1042{
1043 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1044 cmd.Check(m_View->GetPerspective());
1045}
1046
1047void GUIControl::OnViewSmoothShading()
1048{
1049 m_View->ToggleSmoothShading();
1050}
1051
1052void GUIControl::OnViewSmoothShadingUpdate(wxUpdateUIEvent& cmd)
1053{
1054 cmd.Enable(m_View->HasData());
1055 cmd.Check(m_View->GetSmoothShading());
1056}
1057
1058void GUIControl::OnViewTextured()
1059{
1060 m_View->ToggleTextured();
1061}
1062
1063void GUIControl::OnViewTexturedUpdate(wxUpdateUIEvent& cmd)
1064{
1065 cmd.Enable(m_View->HasData());
1066 cmd.Check(m_View->GetTextured());
1067}
1068
1069void GUIControl::OnViewFog()
1070{
1071 m_View->ToggleFog();
1072}
1073
1074void GUIControl::OnViewFogUpdate(wxUpdateUIEvent& cmd)
1075{
1076 cmd.Enable(m_View->HasData());
1077 cmd.Check(m_View->GetFog());
1078}
1079
1080void GUIControl::OnViewSmoothLines()
1081{
1082 m_View->ToggleAntiAlias();
1083}
1084
1085void GUIControl::OnViewSmoothLinesUpdate(wxUpdateUIEvent& cmd)
1086{
1087 cmd.Enable(m_View->HasData());
1088 cmd.Check(m_View->GetAntiAlias());
1089}
1090
1091void GUIControl::OnToggleMetric()
1092{
1093 m_View->ToggleMetric();
1094
1095 wxConfigBase::Get()->Write(wxT("metric"), m_View->GetMetric());
1096 wxConfigBase::Get()->Flush();
1097}
1098
1099void GUIControl::OnToggleMetricUpdate(wxUpdateUIEvent& cmd)
1100{
1101 cmd.Enable(m_View->HasData());
1102 cmd.Check(m_View->GetMetric());
1103}
1104
1105void GUIControl::OnToggleDegrees()
1106{
1107 m_View->ToggleDegrees();
1108
1109 wxConfigBase::Get()->Write(wxT("degrees"), m_View->GetDegrees());
1110 wxConfigBase::Get()->Flush();
1111}
1112
1113void GUIControl::OnToggleDegreesUpdate(wxUpdateUIEvent& cmd)
1114{
1115 cmd.Enable(m_View->HasData());
1116 cmd.Check(m_View->GetDegrees());
1117}
1118
1119void GUIControl::OnTogglePercent()
1120{
1121 m_View->TogglePercent();
1122
1123 wxConfigBase::Get()->Write(wxT("percent"), m_View->GetPercent());
1124 wxConfigBase::Get()->Flush();
1125}
1126
1127void GUIControl::OnTogglePercentUpdate(wxUpdateUIEvent& cmd)
1128{
1129 cmd.Enable(m_View->HasData());
1130 cmd.Check(m_View->GetPercent());
1131}
1132
1133void GUIControl::OnToggleTubes()
1134{
1135 m_View->ToggleTubes();
1136}
1137
1138void GUIControl::OnToggleTubesUpdate(wxUpdateUIEvent& cmd)
1139{
1140 cmd.Enable(m_View->HasData() && m_View->HasTubes());
1141 cmd.Check(m_View->GetTubes());
1142}
1143
1144void GUIControl::OnCancelDistLine()
1145{
1146 m_View->ClearTreeSelection();
1147}
1148
1149void GUIControl::OnCancelDistLineUpdate(wxUpdateUIEvent& cmd)
1150{
1151 cmd.Enable(m_View->ShowingMeasuringLine());
1152}
1153
1154void GUIControl::OnKeyPress(wxKeyEvent &e)
1155{
1156 if (!m_View->HasData() ||
1157 (e.GetModifiers() &~ (wxMOD_CONTROL|wxMOD_SHIFT))) {
1158 // Pass on the event if there's no survey data, or if any modifier keys
1159 // other than Ctrl and Shift are pressed.
1160 e.Skip();
1161 return;
1162 }
1163
1164 // The changelog says this is meant to keep animation going while keys are
1165 // pressed, but that happens anyway (on linux at least - perhaps it helps
1166 // on windows?) FIXME : check!
1167 //bool refresh = m_View->Animate();
1168
1169 switch (e.GetKeyCode()) {
1170 case '/': case '?':
1171 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1172 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1173 break;
1174 case '\'': case '@': case '"': // both shifted forms - US and UK kbd
1175 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1176 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1177 break;
1178 case 'C': case 'c':
1179 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1180 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1181 break;
1182 case 'V': case 'v':
1183 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1184 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1185 break;
1186 case ']': case '}':
1187 OnZoomIn(e.GetModifiers() == wxMOD_SHIFT);
1188 break;
1189 case '[': case '{':
1190 OnZoomOut(e.GetModifiers() == wxMOD_SHIFT);
1191 break;
1192 case 'N': case 'n':
1193 OnMoveNorth();
1194 break;
1195 case 'S': case 's':
1196 OnMoveSouth();
1197 break;
1198 case 'E': case 'e':
1199 if (!m_View->IsExtendedElevation())
1200 OnMoveEast();
1201 break;
1202 case 'W': case 'w':
1203 if (!m_View->IsExtendedElevation())
1204 OnMoveWest();
1205 break;
1206 case 'Z': case 'z':
1207 if (!m_View->IsExtendedElevation())
1208 m_View->RotateFaster(e.GetModifiers() == wxMOD_SHIFT);
1209 break;
1210 case 'X': case 'x':
1211 if (!m_View->IsExtendedElevation())
1212 m_View->RotateSlower(e.GetModifiers() == wxMOD_SHIFT);
1213 break;
1214 case 'R': case 'r':
1215 if (!m_View->IsExtendedElevation())
1216 OnReverseDirectionOfRotation();
1217 break;
1218 case 'P': case 'p':
1219 if (!m_View->IsExtendedElevation() && !m_View->ShowingPlan())
1220 OnPlan();
1221 break;
1222 case 'L': case 'l':
1223 if (!m_View->IsExtendedElevation() && !m_View->ShowingElevation())
1224 OnElevation();
1225 break;
1226 case 'O': case 'o':
1227 OnDisplayOverlappingNames();
1228 break;
1229 case WXK_DELETE:
1230 if (e.GetModifiers() == 0)
1231 OnDefaults();
1232 break;
1233 case WXK_RETURN:
1234 if (e.GetModifiers() == 0) {
1235 // For compatibility with older versions.
1236 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1237 m_View->StartRotation();
1238 }
1239 break;
1240 case WXK_SPACE:
1241 if (e.GetModifiers() == 0) {
1242 if (!m_View->IsExtendedElevation())
1243 OnToggleRotation();
1244 }
1245 break;
1246 case WXK_LEFT:
1247 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1248 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1249 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1250 } else {
1251 OnShiftDisplayLeft(e.GetModifiers() == wxMOD_SHIFT);
1252 }
1253 break;
1254 case WXK_RIGHT:
1255 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1256 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1257 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1258 } else {
1259 OnShiftDisplayRight(e.GetModifiers() == wxMOD_SHIFT);
1260 }
1261 break;
1262 case WXK_UP:
1263 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1264 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1265 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1266 } else {
1267 OnShiftDisplayUp(e.GetModifiers() == wxMOD_SHIFT);
1268 }
1269 break;
1270 case WXK_DOWN:
1271 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1272 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1273 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1274 } else {
1275 OnShiftDisplayDown(e.GetModifiers() == wxMOD_SHIFT);
1276 }
1277 break;
1278 case WXK_ESCAPE:
1279 if (e.GetModifiers() == 0) {
1280 if (m_View->ShowingMeasuringLine()) {
1281 OnCancelDistLine();
1282 } else if (m_View->IsFullScreen()) {
1283 // Cancel full-screen mode on "Escape" if it isn't cancelling
1284 // the measuring line.
1285 m_View->FullScreenMode();
1286 }
1287 }
1288 break;
1289 case WXK_F2:
1290 if (e.GetModifiers() == 0)
1291 m_View->ToggleFatFinger();
1292 break;
1293 case WXK_F3:
1294 if (e.GetModifiers() == 0)
1295 m_View->ToggleHitTestDebug();
1296 break;
1297 case WXK_F4: {
1298 if (e.GetModifiers() == 0) {
1299 const wxChar * msg;
1300#if wxDEBUG_LEVEL
1301 if (wxTheAssertHandler)
1302 wxTheAssertHandler = NULL;
1303 else
1304 wxSetDefaultAssertHandler();
1305 if (wxTheAssertHandler)
1306 msg = wxT("Assertions enabled");
1307 else
1308 msg = wxT("Assertions disabled");
1309#else
1310 msg = wxT("wxWidgets was built without assertions");
1311#endif
1312 wxMessageBox(msg, wxT("Aven Debug"), wxOK | wxICON_INFORMATION);
1313 }
1314 break;
1315 }
1316 case WXK_F5:
1317 if (e.GetModifiers() == 0) {
1318 m_View->InvalidateAllLists();
1319 m_View->ForceRefresh();
1320 }
1321 break;
1322 case WXK_F6:
1323 if (e.GetModifiers() == 0)
1324 m_View->ToggleRenderStats();
1325 break;
1326 default:
1327 e.Skip();
1328 }
1329
1330 //if (refresh) m_View->ForceRefresh();
1331}
1332
1333void GUIControl::OnViewFullScreenUpdate(wxUpdateUIEvent& cmd)
1334{
1335 cmd.Check(m_View->IsFullScreen());
1336}
1337
1338void GUIControl::OnViewFullScreen()
1339{
1340 m_View->FullScreenMode();
1341}
1342
1343void GUIControl::OnViewBoundingBoxUpdate(wxUpdateUIEvent& cmd)
1344{
1345 cmd.Enable(m_View->HasData());
1346 cmd.Check(m_View->DisplayingBoundingBox());
1347}
1348
1349void GUIControl::OnViewBoundingBox()
1350{
1351 m_View->ToggleBoundingBox();
1352}
1353
1354void GUIControl::OnViewTerrainUpdate(wxUpdateUIEvent& cmd)
1355{
1356 cmd.Enable(m_View->HasTerrain());
1357 cmd.Check(m_View->DisplayingTerrain());
1358}
1359
1360void GUIControl::OnViewTerrain()
1361{
1362 m_View->ToggleTerrain();
1363}
Note: See TracBrowser for help on using the repository browser.