Fix aven startup with no file on macos
[survex.git] / src / guicontrol.cc
blobde83345bd099458b75a001628cb6a9100d9228bb
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.
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.
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
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
28 #include "guicontrol.h"
29 #include "gfxcore.h"
30 #include <wx/confbase.h>
32 const int DISPLAY_SHIFT = 10;
33 const double FLYFREE_SHIFT = 0.2;
34 const double ROTATE_STEP = 2.0;
36 GUIControl::GUIControl()
37 : dragging(NO_DRAG)
39 m_View = NULL;
40 m_ReverseControls = false;
41 m_LastDrag = drag_NONE;
44 void GUIControl::SetView(GfxCore* view)
46 m_View = view;
49 bool GUIControl::MouseDown() const
51 return (dragging != NO_DRAG);
54 void GUIControl::HandleTilt(wxPoint point)
56 // Handle a mouse movement during tilt mode.
58 // wxGTK (at least) fails to update the cursor while dragging.
59 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
61 int dy = point.y - m_DragStart.y;
63 if (m_ReverseControls != m_View->GetPerspective()) dy = -dy;
65 m_View->TiltCave(Double(dy) * 0.36);
67 m_DragStart = point;
69 m_View->ForceRefresh();
72 void GUIControl::HandleTranslate(wxPoint point)
74 // Handle a mouse movement during translation mode.
76 // wxGTK (at least) fails to update the cursor while dragging.
77 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
79 int dx = point.x - m_DragStart.x;
80 int dy = point.y - m_DragStart.y;
82 if (m_ReverseControls) {
83 dx = -dx;
84 dy = -dy;
87 if (m_View->GetPerspective())
88 m_View->MoveViewer(0, -dy * .1, dx * .1);
89 else
90 m_View->TranslateCave(dx, dy);
92 m_DragStart = point;
95 void GUIControl::HandleScaleRotate(wxPoint point)
97 // Handle a mouse movement during scale/rotate mode.
99 // wxGTK (at least) fails to update the cursor while dragging.
100 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM_ROTATE);
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;
114 int dx2 = dx * dx;
115 int dy2 = dy * dy;
116 if (dx2 + dy2 < threshold) return;
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);
127 break;
128 case lock_SCALE:
129 if (dx2 >= 8 * dy2) {
130 m_ScaleRotateLock = lock_ROTATE;
131 // m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
133 break;
134 case lock_ROTATE:
135 if (dy2 >= 8 * dx2) {
136 m_ScaleRotateLock = lock_SCALE;
137 // m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
139 break;
142 if (m_ScaleRotateLock == lock_ROTATE) {
143 dy = 0;
144 } else {
145 dx = 0;
148 if (m_ReverseControls) {
149 dx = -dx;
150 dy = -dy;
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();
163 m_DragStart = point;
166 void GUIControl::HandleTiltRotate(wxPoint point)
168 // Handle a mouse movement during tilt/rotate mode.
169 if (m_View->IsExtendedElevation()) return;
171 // wxGTK (at least) fails to update the cursor while dragging.
172 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
174 int dx = point.x - m_DragStart.x;
175 int dy = point.y - m_DragStart.y;
177 if (m_ReverseControls != m_View->GetPerspective()) {
178 dx = -dx;
179 dy = -dy;
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);
187 m_View->ForceRefresh();
189 m_DragStart = point;
192 void GUIControl::HandleRotate(wxPoint point)
194 // Handle a mouse movement during rotate mode.
195 if (m_View->IsExtendedElevation()) return;
197 // wxGTK (at least) fails to update the cursor while dragging.
198 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
200 int dx = point.x - m_DragStart.x;
201 int dy = point.y - m_DragStart.y;
203 if (m_ReverseControls != m_View->GetPerspective()) {
204 dx = -dx;
205 dy = -dy;
208 // left/right => rotate.
209 m_View->TurnCave(Double(dx) * -0.36);
211 m_View->ForceRefresh();
213 m_DragStart = point;
216 void GUIControl::RestoreCursor()
218 if (m_View->HereIsReal()) {
219 m_View->UpdateCursor(GfxCore::CURSOR_POINTING_HAND);
220 } else {
221 m_View->UpdateCursor(GfxCore::CURSOR_DEFAULT);
225 void 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);
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();
250 // Mouse event handling methods
253 void GUIControl::OnMouseMove(wxMouseEvent& event)
255 // Mouse motion event handler.
256 if (!m_View->HasData()) return;
258 // Ignore moves which don't change the position.
259 if (event.GetPosition() == m_DragStart) {
260 return;
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();
273 timestamp = event.GetTimestamp();
275 wxPoint point(event.GetPosition());
277 // Check hit-test grid (only if no buttons are pressed).
278 if (!event.LeftIsDown() && !event.MiddleIsDown() && !event.RightIsDown()) {
279 HandleNonDrag(point);
282 // Update coordinate display if in plan view,
283 // or altitude if in elevation view.
284 m_View->SetCoords(point);
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);
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;
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;
325 m_DragLast = point;
328 void GUIControl::OnLButtonDown(wxMouseEvent& event)
330 if (m_View->HasData()) {
331 m_DragStart = m_DragRealStart = event.GetPosition();
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);
352 m_LastDrag = drag_MAIN;
353 m_ScaleRotateLock = lock_NONE;
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();
361 dragging = LEFT_DRAG;
365 void GUIControl::OnLButtonUp(wxMouseEvent& event)
367 if (m_View->HasData()) {
368 if (dragging != LEFT_DRAG)
369 return;
371 if (event.MiddleIsDown()) {
372 if (m_LastDrag == drag_ZOOM)
373 m_View->UnsetZoomBox();
374 OnMButtonDown(event);
375 return;
378 if (event.RightIsDown()) {
379 if (m_LastDrag == drag_ZOOM)
380 m_View->UnsetZoomBox();
381 OnRButtonDown(event);
382 return;
385 if (m_LastDrag == drag_ZOOM) {
386 m_View->ZoomBoxGo();
389 m_View->ReleaseMouse();
391 m_LastDrag = drag_NONE;
392 dragging = NO_DRAG;
394 m_View->DragFinished();
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());
406 void GUIControl::OnMButtonDown(wxMouseEvent& event)
408 if (m_View->HasData() && !m_View->IsExtendedElevation()) {
409 m_DragStart = event.GetPosition();
411 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
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();
420 m_View->CaptureMouse();
421 dragging = MIDDLE_DRAG;
425 void GUIControl::OnMButtonUp(wxMouseEvent& event)
427 if (m_View->HasData()) {
428 if (dragging != MIDDLE_DRAG)
429 return;
431 if (event.LeftIsDown()) {
432 OnLButtonDown(event);
433 return;
436 if (event.RightIsDown()) {
437 OnRButtonDown(event);
438 return;
441 dragging = NO_DRAG;
442 m_View->ReleaseMouse();
443 m_View->DragFinished();
445 RestoreCursor();
449 void GUIControl::OnRButtonDown(wxMouseEvent& event)
451 if (m_View->HasData()) {
452 if (dragging != NO_DRAG) {
453 if (m_LastDrag == drag_ZOOM)
454 m_View->UnsetZoomBox();
455 // We need to release and recapture for the cursor to update
456 // (noticed with wxGTK).
457 m_View->ReleaseMouse();
458 dragging = NO_DRAG;
461 if (m_View->HandleRClick(event.GetPosition()))
462 return;
464 m_DragStart = event.GetPosition();
466 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
468 m_View->CaptureMouse();
469 dragging = RIGHT_DRAG;
473 void GUIControl::OnRButtonUp(wxMouseEvent& event)
475 if (dragging != RIGHT_DRAG)
476 return;
478 if (event.LeftIsDown()) {
479 OnLButtonDown(event);
480 return;
483 if (event.MiddleIsDown()) {
484 OnMButtonDown(event);
485 return;
488 m_LastDrag = drag_NONE;
489 m_View->ReleaseMouse();
491 dragging = NO_DRAG;
493 RestoreCursor();
495 m_View->DragFinished();
498 void GUIControl::OnMouseWheel(wxMouseEvent& event) {
499 int dy = event.GetWheelRotation();
500 if (m_View->GetPerspective()) {
501 m_View->MoveViewer(-dy, 0, 0);
502 } else {
503 m_View->SetScale(m_View->GetScale() * pow(1.06, -0.04 * dy));
504 m_View->ForceRefresh();
508 void GUIControl::OnDisplayOverlappingNames()
510 m_View->ToggleOverlappingNames();
513 void GUIControl::OnDisplayOverlappingNamesUpdate(wxUpdateUIEvent& cmd)
515 cmd.Enable(m_View->HasData() && m_View->ShowingStationNames());
516 cmd.Check(m_View->ShowingOverlappingNames());
519 void GUIControl::OnColourByDepth()
521 if (m_View->ColouringBy() == COLOUR_BY_DEPTH) {
522 m_View->SetColourBy(COLOUR_BY_NONE);
523 } else {
524 m_View->SetColourBy(COLOUR_BY_DEPTH);
528 void GUIControl::OnColourByDate()
530 if (m_View->ColouringBy() == COLOUR_BY_DATE) {
531 m_View->SetColourBy(COLOUR_BY_NONE);
532 } else {
533 m_View->SetColourBy(COLOUR_BY_DATE);
537 void GUIControl::OnColourByError()
539 if (m_View->ColouringBy() == COLOUR_BY_ERROR) {
540 m_View->SetColourBy(COLOUR_BY_NONE);
541 } else {
542 m_View->SetColourBy(COLOUR_BY_ERROR);
546 void GUIControl::OnColourByHError()
548 if (m_View->ColouringBy() == COLOUR_BY_H_ERROR) {
549 m_View->SetColourBy(COLOUR_BY_NONE);
550 } else {
551 m_View->SetColourBy(COLOUR_BY_H_ERROR);
555 void GUIControl::OnColourByVError()
557 if (m_View->ColouringBy() == COLOUR_BY_V_ERROR) {
558 m_View->SetColourBy(COLOUR_BY_NONE);
559 } else {
560 m_View->SetColourBy(COLOUR_BY_V_ERROR);
564 void GUIControl::OnColourByGradient()
566 if (m_View->ColouringBy() == COLOUR_BY_GRADIENT) {
567 m_View->SetColourBy(COLOUR_BY_NONE);
568 } else {
569 m_View->SetColourBy(COLOUR_BY_GRADIENT);
573 void GUIControl::OnColourByLength()
575 if (m_View->ColouringBy() == COLOUR_BY_LENGTH) {
576 m_View->SetColourBy(COLOUR_BY_NONE);
577 } else {
578 m_View->SetColourBy(COLOUR_BY_LENGTH);
582 void GUIControl::OnColourBySurvey()
584 if (m_View->ColouringBy() == COLOUR_BY_SURVEY) {
585 m_View->SetColourBy(COLOUR_BY_NONE);
586 } else {
587 m_View->SetColourBy(COLOUR_BY_SURVEY);
591 void GUIControl::OnColourByStyle()
593 if (m_View->ColouringBy() == COLOUR_BY_STYLE) {
594 m_View->SetColourBy(COLOUR_BY_NONE);
595 } else {
596 m_View->SetColourBy(COLOUR_BY_STYLE);
600 void GUIControl::OnColourByUpdate(wxUpdateUIEvent& cmd)
602 cmd.Enable(m_View->HasData());
605 void GUIControl::OnColourByDepthUpdate(wxUpdateUIEvent& cmd)
607 cmd.Enable(m_View->HasData());
608 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DEPTH);
611 void GUIControl::OnColourByDateUpdate(wxUpdateUIEvent& cmd)
613 cmd.Enable(m_View->HasData());
614 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DATE);
617 void GUIControl::OnColourByErrorUpdate(wxUpdateUIEvent& cmd)
619 cmd.Enable(m_View->HasData());
620 cmd.Check(m_View->ColouringBy() == COLOUR_BY_ERROR);
623 void GUIControl::OnColourByHErrorUpdate(wxUpdateUIEvent& cmd)
625 cmd.Enable(m_View->HasData());
626 cmd.Check(m_View->ColouringBy() == COLOUR_BY_H_ERROR);
629 void GUIControl::OnColourByVErrorUpdate(wxUpdateUIEvent& cmd)
631 cmd.Enable(m_View->HasData());
632 cmd.Check(m_View->ColouringBy() == COLOUR_BY_V_ERROR);
635 void GUIControl::OnColourByGradientUpdate(wxUpdateUIEvent& cmd)
637 cmd.Enable(m_View->HasData());
638 cmd.Check(m_View->ColouringBy() == COLOUR_BY_GRADIENT);
641 void GUIControl::OnColourByLengthUpdate(wxUpdateUIEvent& cmd)
643 cmd.Enable(m_View->HasData());
644 cmd.Check(m_View->ColouringBy() == COLOUR_BY_LENGTH);
647 void GUIControl::OnColourBySurveyUpdate(wxUpdateUIEvent& cmd)
649 cmd.Enable(m_View->HasData());
650 cmd.Check(m_View->ColouringBy() == COLOUR_BY_SURVEY);
653 void GUIControl::OnColourByStyleUpdate(wxUpdateUIEvent& cmd)
655 cmd.Enable(m_View->HasData());
656 cmd.Check(m_View->ColouringBy() == COLOUR_BY_STYLE);
659 void GUIControl::OnShowCrosses()
661 m_View->ToggleCrosses();
664 void GUIControl::OnShowCrossesUpdate(wxUpdateUIEvent& cmd)
666 cmd.Enable(m_View->HasData());
667 cmd.Check(m_View->ShowingCrosses());
670 void GUIControl::OnShowStationNames()
672 m_View->ToggleStationNames();
675 void GUIControl::OnShowStationNamesUpdate(wxUpdateUIEvent& cmd)
677 cmd.Enable(m_View->HasData());
678 cmd.Check(m_View->ShowingStationNames());
681 void GUIControl::OnShowSurveyLegs()
683 m_View->ToggleUndergroundLegs();
686 void GUIControl::OnShowSurveyLegsUpdate(wxUpdateUIEvent& cmd)
688 cmd.Enable(m_View->HasData() && m_View->HasUndergroundLegs());
689 cmd.Check(m_View->ShowingUndergroundLegs());
692 void GUIControl::OnHideSplays()
694 m_View->SetSplaysMode(SHOW_HIDE);
697 void GUIControl::OnShowSplaysDashed()
699 m_View->SetSplaysMode(SHOW_DASHED);
702 void GUIControl::OnShowSplaysFaded()
704 m_View->SetSplaysMode(SHOW_FADED);
707 void GUIControl::OnShowSplaysNormal()
709 m_View->SetSplaysMode(SHOW_NORMAL);
712 void GUIControl::OnSplaysUpdate(wxUpdateUIEvent& cmd)
714 cmd.Enable(m_View->HasData() && m_View->HasSplays());
717 void GUIControl::OnHideSplaysUpdate(wxUpdateUIEvent& cmd)
719 cmd.Enable(m_View->HasData() && m_View->HasSplays());
720 cmd.Check(m_View->ShowingSplaysMode() == SHOW_HIDE);
723 void GUIControl::OnShowSplaysDashedUpdate(wxUpdateUIEvent& cmd)
725 cmd.Enable(m_View->HasData() && m_View->HasSplays());
726 cmd.Check(m_View->ShowingSplaysMode() == SHOW_DASHED);
729 void GUIControl::OnShowSplaysFadedUpdate(wxUpdateUIEvent& cmd)
731 cmd.Enable(m_View->HasData() && m_View->HasSplays());
732 cmd.Check(m_View->ShowingSplaysMode() == SHOW_FADED);
735 void GUIControl::OnShowSplaysNormalUpdate(wxUpdateUIEvent& cmd)
737 cmd.Enable(m_View->HasData() && m_View->HasSplays());
738 cmd.Check(m_View->ShowingSplaysMode() == SHOW_NORMAL);
741 void GUIControl::OnHideDupes() {
742 m_View->SetDupesMode(SHOW_HIDE);
745 void GUIControl::OnShowDupesDashed() {
746 m_View->SetDupesMode(SHOW_DASHED);
749 void GUIControl::OnShowDupesFaded() {
750 m_View->SetDupesMode(SHOW_FADED);
753 void GUIControl::OnShowDupesNormal() {
754 m_View->SetDupesMode(SHOW_NORMAL);
757 void GUIControl::OnDupesUpdate(wxUpdateUIEvent& cmd) {
758 cmd.Enable(m_View->HasData() && m_View->HasDupes());
761 void GUIControl::OnHideDupesUpdate(wxUpdateUIEvent& cmd) {
762 cmd.Enable(m_View->HasData() && m_View->HasDupes());
763 cmd.Check(m_View->ShowingDupesMode() == SHOW_HIDE);
766 void GUIControl::OnShowDupesDashedUpdate(wxUpdateUIEvent& cmd) {
767 cmd.Enable(m_View->HasData() && m_View->HasDupes());
768 cmd.Check(m_View->ShowingDupesMode() == SHOW_DASHED);
771 void GUIControl::OnShowDupesFadedUpdate(wxUpdateUIEvent& cmd) {
772 cmd.Enable(m_View->HasData() && m_View->HasDupes());
773 cmd.Check(m_View->ShowingDupesMode() == SHOW_FADED);
776 void GUIControl::OnShowDupesNormalUpdate(wxUpdateUIEvent& cmd) {
777 cmd.Enable(m_View->HasData() && m_View->HasDupes());
778 cmd.Check(m_View->ShowingDupesMode() == SHOW_NORMAL);
781 void GUIControl::OnMoveEast()
783 m_View->TurnCaveTo(90.0);
784 m_View->ForceRefresh();
787 void GUIControl::OnMoveEastUpdate(wxUpdateUIEvent& cmd)
789 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 90.0);
792 void GUIControl::OnMoveNorth()
794 m_View->TurnCaveTo(0.0);
795 m_View->ForceRefresh();
798 void GUIControl::OnMoveNorthUpdate(wxUpdateUIEvent& cmd)
800 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 0.0);
803 void GUIControl::OnMoveSouth()
805 m_View->TurnCaveTo(180.0);
806 m_View->ForceRefresh();
809 void GUIControl::OnMoveSouthUpdate(wxUpdateUIEvent& cmd)
811 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 180.0);
814 void GUIControl::OnMoveWest()
816 m_View->TurnCaveTo(270.0);
817 m_View->ForceRefresh();
820 void GUIControl::OnMoveWestUpdate(wxUpdateUIEvent& cmd)
822 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 270.0);
825 void GUIControl::OnToggleRotation()
827 m_View->ToggleRotation();
830 void GUIControl::OnToggleRotationUpdate(wxUpdateUIEvent& cmd)
832 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
833 cmd.Check(m_View->HasData() && m_View->IsRotating());
836 void GUIControl::OnReverseControls()
838 m_ReverseControls = !m_ReverseControls;
841 void GUIControl::OnReverseControlsUpdate(wxUpdateUIEvent& cmd)
843 cmd.Enable(m_View->HasData());
844 cmd.Check(m_ReverseControls);
847 void GUIControl::OnReverseDirectionOfRotation()
849 m_View->ReverseRotation();
852 void GUIControl::OnReverseDirectionOfRotationUpdate(wxUpdateUIEvent& cmd)
854 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
857 void GUIControl::OnStepOnceAnticlockwise(bool accel)
859 if (m_View->GetPerspective()) {
860 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
861 } else {
862 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
864 m_View->ForceRefresh();
867 void GUIControl::OnStepOnceClockwise(bool accel)
869 if (m_View->GetPerspective()) {
870 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
871 } else {
872 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
874 m_View->ForceRefresh();
877 void GUIControl::OnDefaults()
879 m_View->Defaults();
882 void GUIControl::OnDefaultsUpdate(wxUpdateUIEvent& cmd)
884 cmd.Enable(m_View->HasData());
887 void GUIControl::OnElevation()
889 // Switch to elevation view.
891 m_View->SwitchToElevation();
894 void GUIControl::OnElevationUpdate(wxUpdateUIEvent& cmd)
896 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingElevation());
899 void GUIControl::OnHigherViewpoint(bool accel)
901 // Raise the viewpoint.
902 if (m_View->GetPerspective()) {
903 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
904 } else {
905 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
907 m_View->ForceRefresh();
910 void GUIControl::OnLowerViewpoint(bool accel)
912 // Lower the viewpoint.
913 if (m_View->GetPerspective()) {
914 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
915 } else {
916 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
918 m_View->ForceRefresh();
921 void GUIControl::OnPlan()
923 // Switch to plan view.
924 m_View->SwitchToPlan();
927 void GUIControl::OnPlanUpdate(wxUpdateUIEvent& cmd)
929 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingPlan());
932 void GUIControl::OnShiftDisplayDown(bool accel)
934 if (m_View->GetPerspective())
935 m_View->MoveViewer(0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0);
936 else
937 m_View->TranslateCave(0, accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT);
940 void GUIControl::OnShiftDisplayLeft(bool accel)
942 if (m_View->GetPerspective())
943 m_View->MoveViewer(0, 0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT);
944 else
945 m_View->TranslateCave(accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT, 0);
948 void GUIControl::OnShiftDisplayRight(bool accel)
950 if (m_View->GetPerspective())
951 m_View->MoveViewer(0, 0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT);
952 else
953 m_View->TranslateCave(accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT, 0);
956 void GUIControl::OnShiftDisplayUp(bool accel)
958 if (m_View->GetPerspective())
959 m_View->MoveViewer(0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0);
960 else
961 m_View->TranslateCave(0, accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT);
964 void GUIControl::OnZoomIn(bool accel)
966 // Increase the scale.
968 if (m_View->GetPerspective()) {
969 m_View->MoveViewer(accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0, 0);
970 } else {
971 m_View->SetScale(m_View->GetScale() * (accel ? 1.1236 : 1.06));
972 m_View->ForceRefresh();
976 void GUIControl::OnZoomOut(bool accel)
978 // Decrease the scale.
980 if (m_View->GetPerspective()) {
981 m_View->MoveViewer(accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0, 0);
982 } else {
983 m_View->SetScale(m_View->GetScale() / (accel ? 1.1236 : 1.06));
984 m_View->ForceRefresh();
988 void GUIControl::OnToggleScalebar()
990 m_View->ToggleScaleBar();
993 void GUIControl::OnToggleScalebarUpdate(wxUpdateUIEvent& cmd)
995 cmd.Enable(m_View->HasData());
996 cmd.Check(m_View->ShowingScaleBar());
999 void GUIControl::OnToggleColourKey()
1001 m_View->ToggleColourKey();
1004 void GUIControl::OnToggleColourKeyUpdate(wxUpdateUIEvent& cmd)
1006 cmd.Enable(m_View->HasData() && m_View->ColouringBy() != COLOUR_BY_NONE);
1007 cmd.Check(m_View->ShowingColourKey());
1010 void GUIControl::OnViewCompass()
1012 m_View->ToggleCompass();
1015 void GUIControl::OnViewCompassUpdate(wxUpdateUIEvent& cmd)
1017 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1018 cmd.Check(m_View->ShowingCompass());
1021 void GUIControl::OnViewClino()
1023 m_View->ToggleClino();
1026 void GUIControl::OnViewClinoUpdate(wxUpdateUIEvent& cmd)
1028 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1029 cmd.Check(m_View->ShowingClino());
1032 void GUIControl::OnShowSurface()
1034 m_View->ToggleSurfaceLegs();
1037 void GUIControl::OnShowSurfaceUpdate(wxUpdateUIEvent& cmd)
1039 cmd.Enable(m_View->HasData() && m_View->HasSurfaceLegs());
1040 cmd.Check(m_View->ShowingSurfaceLegs());
1043 void GUIControl::OnShowEntrances()
1045 m_View->ToggleEntrances();
1048 void GUIControl::OnShowEntrancesUpdate(wxUpdateUIEvent& cmd)
1050 cmd.Enable(m_View->HasData() && (m_View->GetNumEntrances() > 0));
1051 cmd.Check(m_View->ShowingEntrances());
1054 void GUIControl::OnShowFixedPts()
1056 m_View->ToggleFixedPts();
1059 void GUIControl::OnShowFixedPtsUpdate(wxUpdateUIEvent& cmd)
1061 cmd.Enable(m_View->HasData() && (m_View->GetNumFixedPts() > 0));
1062 cmd.Check(m_View->ShowingFixedPts());
1065 void GUIControl::OnShowExportedPts()
1067 m_View->ToggleExportedPts();
1070 void GUIControl::OnShowExportedPtsUpdate(wxUpdateUIEvent& cmd)
1072 cmd.Enable(m_View->HasData() && (m_View->GetNumExportedPts() > 0));
1073 cmd.Check(m_View->ShowingExportedPts());
1076 void GUIControl::OnViewGrid()
1078 m_View->ToggleGrid();
1081 void GUIControl::OnViewGridUpdate(wxUpdateUIEvent& cmd)
1083 cmd.Enable(m_View->HasData());
1084 cmd.Check(m_View->ShowingGrid());
1087 void GUIControl::OnIndicatorsUpdate(wxUpdateUIEvent& cmd)
1089 cmd.Enable(m_View->HasData());
1092 void GUIControl::OnViewPerspective()
1094 m_View->TogglePerspective();
1095 // Force update of coordinate display.
1096 if (m_View->GetPerspective()) {
1097 m_View->MoveViewer(0, 0, 0);
1098 } else {
1099 m_View->ClearCoords();
1103 void GUIControl::OnViewPerspectiveUpdate(wxUpdateUIEvent& cmd)
1105 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1106 cmd.Check(m_View->GetPerspective());
1109 void GUIControl::OnViewSmoothShading()
1111 m_View->ToggleSmoothShading();
1114 void GUIControl::OnViewSmoothShadingUpdate(wxUpdateUIEvent& cmd)
1116 cmd.Enable(m_View->HasData());
1117 cmd.Check(m_View->GetSmoothShading());
1120 void GUIControl::OnViewTextured()
1122 m_View->ToggleTextured();
1125 void GUIControl::OnViewTexturedUpdate(wxUpdateUIEvent& cmd)
1127 cmd.Enable(m_View->HasData());
1128 cmd.Check(m_View->GetTextured());
1131 void GUIControl::OnViewFog()
1133 m_View->ToggleFog();
1136 void GUIControl::OnViewFogUpdate(wxUpdateUIEvent& cmd)
1138 cmd.Enable(m_View->HasData());
1139 cmd.Check(m_View->GetFog());
1142 void GUIControl::OnViewSmoothLines()
1144 m_View->ToggleAntiAlias();
1147 void GUIControl::OnViewSmoothLinesUpdate(wxUpdateUIEvent& cmd)
1149 cmd.Enable(m_View->HasData());
1150 cmd.Check(m_View->GetAntiAlias());
1153 void GUIControl::OnToggleMetric()
1155 m_View->ToggleMetric();
1157 wxConfigBase::Get()->Write(wxT("metric"), m_View->GetMetric());
1158 wxConfigBase::Get()->Flush();
1161 void GUIControl::OnToggleMetricUpdate(wxUpdateUIEvent& cmd)
1163 cmd.Enable(m_View->HasData());
1164 cmd.Check(m_View->GetMetric());
1167 void GUIControl::OnToggleDegrees()
1169 m_View->ToggleDegrees();
1171 wxConfigBase::Get()->Write(wxT("degrees"), m_View->GetDegrees());
1172 wxConfigBase::Get()->Flush();
1175 void GUIControl::OnToggleDegreesUpdate(wxUpdateUIEvent& cmd)
1177 cmd.Enable(m_View->HasData());
1178 cmd.Check(m_View->GetDegrees());
1181 void GUIControl::OnTogglePercent()
1183 m_View->TogglePercent();
1185 wxConfigBase::Get()->Write(wxT("percent"), m_View->GetPercent());
1186 wxConfigBase::Get()->Flush();
1189 void GUIControl::OnTogglePercentUpdate(wxUpdateUIEvent& cmd)
1191 cmd.Enable(m_View->HasData());
1192 cmd.Check(m_View->GetPercent());
1195 void GUIControl::OnToggleTubes()
1197 m_View->ToggleTubes();
1200 void GUIControl::OnToggleTubesUpdate(wxUpdateUIEvent& cmd)
1202 cmd.Enable(m_View->HasData() && m_View->HasTubes());
1203 cmd.Check(m_View->GetTubes());
1206 void GUIControl::OnCancelDistLine()
1208 m_View->ClearTreeSelection();
1211 void GUIControl::OnCancelDistLineUpdate(wxUpdateUIEvent& cmd)
1213 cmd.Enable(m_View->ShowingMeasuringLine());
1216 void GUIControl::OnKeyPress(wxKeyEvent &e)
1218 if (!m_View->HasData() ||
1219 (e.GetModifiers() &~ (wxMOD_CONTROL|wxMOD_SHIFT))) {
1220 // Pass on the event if there's no survey data, or if any modifier keys
1221 // other than Ctrl and Shift are pressed.
1222 e.Skip();
1223 return;
1226 // The changelog says this is meant to keep animation going while keys are
1227 // pressed, but that happens anyway (on linux at least - perhaps it helps
1228 // on windows?) FIXME : check!
1229 //bool refresh = m_View->Animate();
1231 switch (e.GetKeyCode()) {
1232 case '/': case '?':
1233 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1234 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1235 break;
1236 case '\'': case '@': case '"': // both shifted forms - US and UK kbd
1237 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1238 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1239 break;
1240 case 'C': case 'c':
1241 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1242 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1243 break;
1244 case 'V': case 'v':
1245 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1246 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1247 break;
1248 case ']': case '}':
1249 OnZoomIn(e.GetModifiers() == wxMOD_SHIFT);
1250 break;
1251 case '[': case '{':
1252 OnZoomOut(e.GetModifiers() == wxMOD_SHIFT);
1253 break;
1254 case 'N': case 'n':
1255 OnMoveNorth();
1256 break;
1257 case 'S': case 's':
1258 OnMoveSouth();
1259 break;
1260 case 'E': case 'e':
1261 if (!m_View->IsExtendedElevation())
1262 OnMoveEast();
1263 break;
1264 case 'W': case 'w':
1265 if (!m_View->IsExtendedElevation())
1266 OnMoveWest();
1267 break;
1268 case 'Z': case 'z':
1269 if (!m_View->IsExtendedElevation())
1270 m_View->RotateFaster(e.GetModifiers() == wxMOD_SHIFT);
1271 break;
1272 case 'X': case 'x':
1273 if (!m_View->IsExtendedElevation())
1274 m_View->RotateSlower(e.GetModifiers() == wxMOD_SHIFT);
1275 break;
1276 case 'R': case 'r':
1277 if (!m_View->IsExtendedElevation())
1278 OnReverseDirectionOfRotation();
1279 break;
1280 case 'P': case 'p':
1281 if (!m_View->IsExtendedElevation() && !m_View->ShowingPlan())
1282 OnPlan();
1283 break;
1284 case 'L': case 'l':
1285 if (!m_View->IsExtendedElevation() && !m_View->ShowingElevation())
1286 OnElevation();
1287 break;
1288 case 'O': case 'o':
1289 OnDisplayOverlappingNames();
1290 break;
1291 case WXK_DELETE:
1292 if (e.GetModifiers() == 0)
1293 OnDefaults();
1294 break;
1295 case WXK_RETURN:
1296 if (e.GetModifiers() == 0) {
1297 // For compatibility with older versions.
1298 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1299 m_View->StartRotation();
1301 break;
1302 case WXK_SPACE:
1303 if (e.GetModifiers() == 0) {
1304 if (!m_View->IsExtendedElevation())
1305 OnToggleRotation();
1307 break;
1308 case WXK_LEFT:
1309 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1310 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1311 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1312 } else {
1313 OnShiftDisplayLeft(e.GetModifiers() == wxMOD_SHIFT);
1315 break;
1316 case WXK_RIGHT:
1317 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1318 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1319 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1320 } else {
1321 OnShiftDisplayRight(e.GetModifiers() == wxMOD_SHIFT);
1323 break;
1324 case WXK_UP:
1325 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1326 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1327 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1328 } else {
1329 OnShiftDisplayUp(e.GetModifiers() == wxMOD_SHIFT);
1331 break;
1332 case WXK_DOWN:
1333 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1334 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1335 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1336 } else {
1337 OnShiftDisplayDown(e.GetModifiers() == wxMOD_SHIFT);
1339 break;
1340 case WXK_ESCAPE:
1341 if (e.GetModifiers() == 0) {
1342 if (m_View->ShowingMeasuringLine()) {
1343 OnCancelDistLine();
1344 } else if (m_View->IsFullScreen()) {
1345 // Cancel full-screen mode on "Escape" if it isn't cancelling
1346 // the measuring line.
1347 m_View->FullScreenMode();
1350 break;
1351 case WXK_F2:
1352 if (e.GetModifiers() == 0)
1353 m_View->ToggleFatFinger();
1354 break;
1355 case WXK_F3:
1356 if (e.GetModifiers() == 0)
1357 m_View->ToggleHitTestDebug();
1358 break;
1359 case WXK_F4: {
1360 if (e.GetModifiers() == 0) {
1361 const wxChar * msg;
1362 #if wxDEBUG_LEVEL
1363 if (wxTheAssertHandler)
1364 wxTheAssertHandler = NULL;
1365 else
1366 wxSetDefaultAssertHandler();
1367 if (wxTheAssertHandler)
1368 msg = wxT("Assertions enabled");
1369 else
1370 msg = wxT("Assertions disabled");
1371 #else
1372 msg = wxT("wxWidgets was built without assertions");
1373 #endif
1374 wxMessageBox(msg, wxT("Aven Debug"), wxOK | wxICON_INFORMATION);
1376 break;
1378 case WXK_F5:
1379 if (e.GetModifiers() == 0) {
1380 m_View->InvalidateAllLists();
1381 m_View->ForceRefresh();
1383 break;
1384 case WXK_F6:
1385 if (e.GetModifiers() == 0)
1386 m_View->ToggleRenderStats();
1387 break;
1388 default:
1389 e.Skip();
1392 //if (refresh) m_View->ForceRefresh();
1395 void GUIControl::OnViewFullScreenUpdate(wxUpdateUIEvent& cmd)
1397 cmd.Check(m_View->IsFullScreen());
1400 void GUIControl::OnViewFullScreen()
1402 m_View->FullScreenMode();
1405 void GUIControl::OnViewBoundingBoxUpdate(wxUpdateUIEvent& cmd)
1407 cmd.Enable(m_View->HasData());
1408 cmd.Check(m_View->DisplayingBoundingBox());
1411 void GUIControl::OnViewBoundingBox()
1413 m_View->ToggleBoundingBox();
1416 void GUIControl::OnViewTerrainUpdate(wxUpdateUIEvent& cmd)
1418 cmd.Enable(m_View->HasTerrain());
1419 cmd.Check(m_View->DisplayingTerrain());
1422 void GUIControl::OnViewTerrain()
1424 m_View->ToggleTerrain();