Fix message references for inches and feet
[survex.git] / src / guicontrol.cc
blob41693e982e77335337dadf3eb6666b1e67aaaf35
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 #include <config.h>
26 #include "guicontrol.h"
27 #include "gfxcore.h"
28 #include <wx/confbase.h>
30 const int DISPLAY_SHIFT = 10;
31 const double FLYFREE_SHIFT = 0.2;
32 const double ROTATE_STEP = 2.0;
34 void GUIControl::SetView(GfxCore* view)
36 m_View = view;
39 bool GUIControl::MouseDown() const
41 return (dragging != NO_DRAG);
44 void GUIControl::HandleTilt(wxPoint point)
46 // Handle a mouse movement during tilt mode.
48 // wxGTK (at least) fails to update the cursor while dragging.
49 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
51 int dy = point.y - m_DragStart.y;
53 if (m_ReverseControls != m_View->GetPerspective()) dy = -dy;
55 m_View->TiltCave(dy * 0.36);
57 m_DragStart = point;
59 m_View->ForceRefresh();
62 void GUIControl::HandleTranslate(wxPoint point)
64 // Handle a mouse movement during translation mode.
66 // wxGTK (at least) fails to update the cursor while dragging.
67 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
69 int dx = point.x - m_DragStart.x;
70 int dy = point.y - m_DragStart.y;
72 if (m_ReverseControls) {
73 dx = -dx;
74 dy = -dy;
77 if (m_View->GetPerspective())
78 m_View->MoveViewer(0, -dy * .1, dx * .1);
79 else
80 m_View->TranslateCave(dx, dy);
82 m_DragStart = point;
85 void GUIControl::HandleScaleRotate(wxPoint point)
87 // Handle a mouse movement during scale/rotate mode.
89 // wxGTK (at least) fails to update the cursor while dragging.
90 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM_ROTATE);
92 int dx, dy;
93 int threshold;
94 if (m_ScaleRotateLock == lock_NONE) {
95 // Dragging to scale or rotate but we've not decided which yet.
96 dx = point.x - m_DragRealStart.x;
97 dy = point.y - m_DragRealStart.y;
98 threshold = 8 * 8;
99 } else {
100 dx = point.x - m_DragStart.x;
101 dy = point.y - m_DragStart.y;
102 threshold = 5;
104 int dx2 = dx * dx;
105 int dy2 = dy * dy;
106 if (dx2 + dy2 < threshold) return;
108 switch (m_ScaleRotateLock) {
109 case lock_NONE:
110 if (dx2 > dy2) {
111 m_ScaleRotateLock = lock_ROTATE;
112 // m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
113 } else {
114 m_ScaleRotateLock = lock_SCALE;
115 // m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
117 break;
118 case lock_SCALE:
119 if (dx2 >= 8 * dy2) {
120 m_ScaleRotateLock = lock_ROTATE;
121 // m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
123 break;
124 case lock_ROTATE:
125 if (dy2 >= 8 * dx2) {
126 m_ScaleRotateLock = lock_SCALE;
127 // m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
129 break;
132 if (m_ScaleRotateLock == lock_ROTATE) {
133 dy = 0;
134 } else {
135 dx = 0;
138 if (m_ReverseControls) {
139 dx = -dx;
140 dy = -dy;
143 if (m_View->GetPerspective()) {
144 if (dy) m_View->MoveViewer(-dy * .1, 0, 0);
145 } else {
146 // up/down => scale.
147 if (dy) m_View->SetScale(m_View->GetScale() * pow(1.06, 0.08 * dy));
148 // left/right => rotate.
149 if (dx) m_View->TurnCave(dx * -0.36);
150 if (dx || dy) m_View->ForceRefresh();
153 m_DragStart = point;
156 void GUIControl::HandleTiltRotate(wxPoint point)
158 // Handle a mouse movement during tilt/rotate mode.
159 if (m_View->IsExtendedElevation()) return;
161 // wxGTK (at least) fails to update the cursor while dragging.
162 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
164 int dx = point.x - m_DragStart.x;
165 int dy = point.y - m_DragStart.y;
167 if (m_ReverseControls != m_View->GetPerspective()) {
168 dx = -dx;
169 dy = -dy;
172 // left/right => rotate, up/down => tilt.
173 // Make tilt less sensitive than rotate as that feels better.
174 m_View->TurnCave(dx * -0.36);
175 m_View->TiltCave(dy * 0.18);
177 m_View->ForceRefresh();
179 m_DragStart = point;
182 void GUIControl::HandleRotate(wxPoint point)
184 // Handle a mouse movement during rotate mode.
185 if (m_View->IsExtendedElevation()) return;
187 // wxGTK (at least) fails to update the cursor while dragging.
188 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
190 int dx = point.x - m_DragStart.x;
191 int dy = point.y - m_DragStart.y;
193 if (m_ReverseControls != m_View->GetPerspective()) {
194 dx = -dx;
195 dy = -dy;
198 // left/right => rotate.
199 m_View->TurnCave(dx * -0.36);
201 m_View->ForceRefresh();
203 m_DragStart = point;
206 void GUIControl::RestoreCursor()
208 if (m_View->HereIsReal()) {
209 m_View->UpdateCursor(GfxCore::CURSOR_POINTING_HAND);
210 } else {
211 m_View->UpdateCursor(GfxCore::CURSOR_DEFAULT);
215 void GUIControl::HandleNonDrag(const wxPoint & point) {
216 if (m_View->IsFullScreen()) {
217 if (m_View->FullScreenModeShowingMenus()) {
218 if (point.y > 8)
219 m_View->FullScreenModeShowMenus(false);
220 } else {
221 if (point.y == 0) {
222 m_View->FullScreenModeShowMenus(true);
226 if (m_View->CheckHitTestGrid(point, false)) {
227 m_View->UpdateCursor(GfxCore::CURSOR_POINTING_HAND);
228 } else if (m_View->PointWithinScaleBar(point)) {
229 m_View->UpdateCursor(GfxCore::CURSOR_HORIZONTAL_RESIZE);
230 } else if (m_View->PointWithinCompass(point)) {
231 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
232 } else if (m_View->PointWithinClino(point)) {
233 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
234 } else {
235 RestoreCursor();
240 // Mouse event handling methods
243 void GUIControl::OnMouseMove(wxMouseEvent& event)
245 // Mouse motion event handler.
246 if (!m_View->HasData()) return;
248 // Ignore moves which don't change the position.
249 if (event.GetPosition() == m_DragStart) {
250 return;
253 static long timestamp = LONG_MIN;
254 if (dragging != NO_DRAG && m_ScaleRotateLock != lock_NONE &&
255 timestamp != LONG_MIN) {
256 // If no motion for a second, reset the direction lock.
257 if (event.GetTimestamp() - timestamp >= 1000) {
258 m_ScaleRotateLock = lock_NONE;
259 m_DragRealStart = m_DragStart;
260 RestoreCursor();
263 timestamp = event.GetTimestamp();
265 wxPoint point(event.GetPosition());
267 // Check hit-test grid (only if no buttons are pressed).
268 if (!event.LeftIsDown() && !event.MiddleIsDown() && !event.RightIsDown()) {
269 HandleNonDrag(point);
272 // Update coordinate display if in plan view,
273 // or altitude if in elevation view.
274 m_View->SetCoords(point);
276 switch (dragging) {
277 case LEFT_DRAG:
278 switch (m_LastDrag) {
279 case drag_COMPASS:
280 // Drag in heading indicator.
281 m_View->SetCompassFromPoint(point);
282 break;
283 case drag_ELEV:
284 // Drag in clinometer.
285 m_View->SetClinoFromPoint(point);
286 break;
287 case drag_SCALE:
288 m_View->SetScaleBarFromOffset(point.x - m_DragLast.x);
289 break;
290 case drag_MAIN:
291 if (event.ControlDown()) {
292 HandleTiltRotate(point);
293 } else {
294 HandleScaleRotate(point);
296 break;
297 case drag_ZOOM:
298 m_View->SetZoomBox(m_DragStart, point, !event.ShiftDown(), event.ControlDown());
299 break;
300 case drag_NONE:
301 // Shouldn't happen?! FIXME: assert or something.
302 break;
304 break;
305 case MIDDLE_DRAG:
306 HandleTilt(point);
307 break;
308 case RIGHT_DRAG:
309 HandleTranslate(point);
310 break;
311 case NO_DRAG:
312 break;
315 m_DragLast = point;
318 void GUIControl::OnLButtonDown(wxMouseEvent& event)
320 if (m_View->HasData()) {
321 m_DragStart = m_DragRealStart = event.GetPosition();
323 if (m_View->PointWithinCompass(m_DragStart)) {
324 m_LastDrag = drag_COMPASS;
325 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
326 } else if (m_View->PointWithinClino(m_DragStart)) {
327 m_LastDrag = drag_ELEV;
328 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
329 } else if (m_View->PointWithinScaleBar(m_DragStart)) {
330 m_LastDrag = drag_SCALE;
331 m_View->UpdateCursor(GfxCore::CURSOR_HORIZONTAL_RESIZE);
332 } else if (event.ShiftDown()) {
333 m_LastDrag = drag_ZOOM;
334 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM);
335 } else {
336 if (event.ControlDown() && !m_View->IsExtendedElevation()) {
337 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
338 } else {
339 m_View->UpdateCursor(GfxCore::CURSOR_ZOOM_ROTATE);
342 m_LastDrag = drag_MAIN;
343 m_ScaleRotateLock = lock_NONE;
346 // We need to release and recapture for the cursor to update (noticed
347 // with wxGTK).
348 if (dragging != NO_DRAG) m_View->ReleaseMouse();
349 m_View->CaptureMouse();
351 dragging = LEFT_DRAG;
355 void GUIControl::OnLButtonUp(wxMouseEvent& event)
357 if (m_View->HasData()) {
358 if (dragging != LEFT_DRAG)
359 return;
361 if (event.MiddleIsDown()) {
362 if (m_LastDrag == drag_ZOOM)
363 m_View->UnsetZoomBox();
364 OnMButtonDown(event);
365 return;
368 if (event.RightIsDown()) {
369 if (m_LastDrag == drag_ZOOM)
370 m_View->UnsetZoomBox();
371 OnRButtonDown(event);
372 return;
375 if (m_LastDrag == drag_ZOOM) {
376 m_View->ZoomBoxGo();
379 m_View->ReleaseMouse();
381 m_LastDrag = drag_NONE;
382 dragging = NO_DRAG;
384 m_View->DragFinished();
386 if (event.GetPosition() == m_DragRealStart) {
387 // Just a "click"...
388 m_View->CheckHitTestGrid(m_DragStart, true);
389 RestoreCursor();
390 } else {
391 HandleNonDrag(event.GetPosition());
396 void GUIControl::OnMButtonDown(wxMouseEvent& event)
398 if (m_View->HasData() && !m_View->IsExtendedElevation()) {
399 m_DragStart = event.GetPosition();
401 m_View->UpdateCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
403 if (dragging != NO_DRAG) {
404 if (m_LastDrag == drag_ZOOM)
405 m_View->UnsetZoomBox();
406 // We need to release and recapture for the cursor to update
407 // (noticed with wxGTK).
408 m_View->ReleaseMouse();
410 m_View->CaptureMouse();
411 dragging = MIDDLE_DRAG;
415 void GUIControl::OnMButtonUp(wxMouseEvent& event)
417 if (m_View->HasData()) {
418 if (dragging != MIDDLE_DRAG)
419 return;
421 if (event.LeftIsDown()) {
422 OnLButtonDown(event);
423 return;
426 if (event.RightIsDown()) {
427 OnRButtonDown(event);
428 return;
431 dragging = NO_DRAG;
432 m_View->ReleaseMouse();
433 m_View->DragFinished();
435 RestoreCursor();
439 void GUIControl::OnRButtonDown(wxMouseEvent& event)
441 if (m_View->HasData()) {
442 if (dragging != NO_DRAG) {
443 if (m_LastDrag == drag_ZOOM)
444 m_View->UnsetZoomBox();
445 // We need to release and recapture for the cursor to update
446 // (noticed with wxGTK).
447 m_View->ReleaseMouse();
448 dragging = NO_DRAG;
451 if (m_View->HandleRClick(event.GetPosition()))
452 return;
454 m_DragStart = event.GetPosition();
456 m_View->UpdateCursor(GfxCore::CURSOR_DRAGGING_HAND);
458 m_View->CaptureMouse();
459 dragging = RIGHT_DRAG;
463 void GUIControl::OnRButtonUp(wxMouseEvent& event)
465 if (dragging != RIGHT_DRAG)
466 return;
468 if (event.LeftIsDown()) {
469 OnLButtonDown(event);
470 return;
473 if (event.MiddleIsDown()) {
474 OnMButtonDown(event);
475 return;
478 m_LastDrag = drag_NONE;
479 m_View->ReleaseMouse();
481 dragging = NO_DRAG;
483 RestoreCursor();
485 m_View->DragFinished();
488 void GUIControl::OnMouseWheel(wxMouseEvent& event) {
489 int dy = event.GetWheelRotation();
490 if (m_View->GetPerspective()) {
491 m_View->MoveViewer(-dy, 0, 0);
492 } else {
493 m_View->SetScale(m_View->GetScale() * pow(1.06, -0.04 * dy));
494 m_View->ForceRefresh();
498 void GUIControl::OnDisplayOverlappingNames()
500 m_View->ToggleOverlappingNames();
503 void GUIControl::OnDisplayOverlappingNamesUpdate(wxUpdateUIEvent& cmd)
505 cmd.Enable(m_View->HasData() && m_View->ShowingStationNames());
506 cmd.Check(m_View->ShowingOverlappingNames());
509 void GUIControl::OnColourByDepth()
511 if (m_View->ColouringBy() == COLOUR_BY_DEPTH) {
512 m_View->SetColourBy(COLOUR_BY_NONE);
513 } else {
514 m_View->SetColourBy(COLOUR_BY_DEPTH);
518 void GUIControl::OnColourByDate()
520 if (m_View->ColouringBy() == COLOUR_BY_DATE) {
521 m_View->SetColourBy(COLOUR_BY_NONE);
522 } else {
523 m_View->SetColourBy(COLOUR_BY_DATE);
527 void GUIControl::OnColourByError()
529 if (m_View->ColouringBy() == COLOUR_BY_ERROR) {
530 m_View->SetColourBy(COLOUR_BY_NONE);
531 } else {
532 m_View->SetColourBy(COLOUR_BY_ERROR);
536 void GUIControl::OnColourByHError()
538 if (m_View->ColouringBy() == COLOUR_BY_H_ERROR) {
539 m_View->SetColourBy(COLOUR_BY_NONE);
540 } else {
541 m_View->SetColourBy(COLOUR_BY_H_ERROR);
545 void GUIControl::OnColourByVError()
547 if (m_View->ColouringBy() == COLOUR_BY_V_ERROR) {
548 m_View->SetColourBy(COLOUR_BY_NONE);
549 } else {
550 m_View->SetColourBy(COLOUR_BY_V_ERROR);
554 void GUIControl::OnColourByGradient()
556 if (m_View->ColouringBy() == COLOUR_BY_GRADIENT) {
557 m_View->SetColourBy(COLOUR_BY_NONE);
558 } else {
559 m_View->SetColourBy(COLOUR_BY_GRADIENT);
563 void GUIControl::OnColourByLength()
565 if (m_View->ColouringBy() == COLOUR_BY_LENGTH) {
566 m_View->SetColourBy(COLOUR_BY_NONE);
567 } else {
568 m_View->SetColourBy(COLOUR_BY_LENGTH);
572 void GUIControl::OnColourBySurvey()
574 if (m_View->ColouringBy() == COLOUR_BY_SURVEY) {
575 m_View->SetColourBy(COLOUR_BY_NONE);
576 } else {
577 m_View->SetColourBy(COLOUR_BY_SURVEY);
581 void GUIControl::OnColourByStyle()
583 if (m_View->ColouringBy() == COLOUR_BY_STYLE) {
584 m_View->SetColourBy(COLOUR_BY_NONE);
585 } else {
586 m_View->SetColourBy(COLOUR_BY_STYLE);
590 void GUIControl::OnColourByUpdate(wxUpdateUIEvent& cmd)
592 cmd.Enable(m_View->HasData());
595 void GUIControl::OnColourByDepthUpdate(wxUpdateUIEvent& cmd)
597 cmd.Enable(m_View->HasData());
598 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DEPTH);
601 void GUIControl::OnColourByDateUpdate(wxUpdateUIEvent& cmd)
603 cmd.Enable(m_View->HasData());
604 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DATE);
607 void GUIControl::OnColourByErrorUpdate(wxUpdateUIEvent& cmd)
609 cmd.Enable(m_View->HasData());
610 cmd.Check(m_View->ColouringBy() == COLOUR_BY_ERROR);
613 void GUIControl::OnColourByHErrorUpdate(wxUpdateUIEvent& cmd)
615 cmd.Enable(m_View->HasData());
616 cmd.Check(m_View->ColouringBy() == COLOUR_BY_H_ERROR);
619 void GUIControl::OnColourByVErrorUpdate(wxUpdateUIEvent& cmd)
621 cmd.Enable(m_View->HasData());
622 cmd.Check(m_View->ColouringBy() == COLOUR_BY_V_ERROR);
625 void GUIControl::OnColourByGradientUpdate(wxUpdateUIEvent& cmd)
627 cmd.Enable(m_View->HasData());
628 cmd.Check(m_View->ColouringBy() == COLOUR_BY_GRADIENT);
631 void GUIControl::OnColourByLengthUpdate(wxUpdateUIEvent& cmd)
633 cmd.Enable(m_View->HasData());
634 cmd.Check(m_View->ColouringBy() == COLOUR_BY_LENGTH);
637 void GUIControl::OnColourBySurveyUpdate(wxUpdateUIEvent& cmd)
639 cmd.Enable(m_View->HasData());
640 cmd.Check(m_View->ColouringBy() == COLOUR_BY_SURVEY);
643 void GUIControl::OnColourByStyleUpdate(wxUpdateUIEvent& cmd)
645 cmd.Enable(m_View->HasData());
646 cmd.Check(m_View->ColouringBy() == COLOUR_BY_STYLE);
649 void GUIControl::OnShowCrosses()
651 m_View->ToggleCrosses();
654 void GUIControl::OnShowCrossesUpdate(wxUpdateUIEvent& cmd)
656 cmd.Enable(m_View->HasData());
657 cmd.Check(m_View->ShowingCrosses());
660 void GUIControl::OnShowStationNames()
662 m_View->ToggleStationNames();
665 void GUIControl::OnShowStationNamesUpdate(wxUpdateUIEvent& cmd)
667 cmd.Enable(m_View->HasData());
668 cmd.Check(m_View->ShowingStationNames());
671 void GUIControl::OnShowSurveyLegs()
673 m_View->ToggleUndergroundLegs();
676 void GUIControl::OnShowSurveyLegsUpdate(wxUpdateUIEvent& cmd)
678 cmd.Enable(m_View->HasData() && m_View->HasUndergroundLegs());
679 cmd.Check(m_View->ShowingUndergroundLegs());
682 void GUIControl::OnHideSplays()
684 m_View->SetSplaysMode(SHOW_HIDE);
687 void GUIControl::OnShowSplaysDashed()
689 m_View->SetSplaysMode(SHOW_DASHED);
692 void GUIControl::OnShowSplaysFaded()
694 m_View->SetSplaysMode(SHOW_FADED);
697 void GUIControl::OnShowSplaysNormal()
699 m_View->SetSplaysMode(SHOW_NORMAL);
702 void GUIControl::OnSplaysUpdate(wxUpdateUIEvent& cmd)
704 cmd.Enable(m_View->HasData() && m_View->HasSplays());
707 void GUIControl::OnHideSplaysUpdate(wxUpdateUIEvent& cmd)
709 cmd.Enable(m_View->HasData() && m_View->HasSplays());
710 cmd.Check(m_View->ShowingSplaysMode() == SHOW_HIDE);
713 void GUIControl::OnShowSplaysDashedUpdate(wxUpdateUIEvent& cmd)
715 cmd.Enable(m_View->HasData() && m_View->HasSplays());
716 cmd.Check(m_View->ShowingSplaysMode() == SHOW_DASHED);
719 void GUIControl::OnShowSplaysFadedUpdate(wxUpdateUIEvent& cmd)
721 cmd.Enable(m_View->HasData() && m_View->HasSplays());
722 cmd.Check(m_View->ShowingSplaysMode() == SHOW_FADED);
725 void GUIControl::OnShowSplaysNormalUpdate(wxUpdateUIEvent& cmd)
727 cmd.Enable(m_View->HasData() && m_View->HasSplays());
728 cmd.Check(m_View->ShowingSplaysMode() == SHOW_NORMAL);
731 void GUIControl::OnHideDupes() {
732 m_View->SetDupesMode(SHOW_HIDE);
735 void GUIControl::OnShowDupesDashed() {
736 m_View->SetDupesMode(SHOW_DASHED);
739 void GUIControl::OnShowDupesFaded() {
740 m_View->SetDupesMode(SHOW_FADED);
743 void GUIControl::OnShowDupesNormal() {
744 m_View->SetDupesMode(SHOW_NORMAL);
747 void GUIControl::OnDupesUpdate(wxUpdateUIEvent& cmd) {
748 cmd.Enable(m_View->HasData() && m_View->HasDupes());
751 void GUIControl::OnHideDupesUpdate(wxUpdateUIEvent& cmd) {
752 cmd.Enable(m_View->HasData() && m_View->HasDupes());
753 cmd.Check(m_View->ShowingDupesMode() == SHOW_HIDE);
756 void GUIControl::OnShowDupesDashedUpdate(wxUpdateUIEvent& cmd) {
757 cmd.Enable(m_View->HasData() && m_View->HasDupes());
758 cmd.Check(m_View->ShowingDupesMode() == SHOW_DASHED);
761 void GUIControl::OnShowDupesFadedUpdate(wxUpdateUIEvent& cmd) {
762 cmd.Enable(m_View->HasData() && m_View->HasDupes());
763 cmd.Check(m_View->ShowingDupesMode() == SHOW_FADED);
766 void GUIControl::OnShowDupesNormalUpdate(wxUpdateUIEvent& cmd) {
767 cmd.Enable(m_View->HasData() && m_View->HasDupes());
768 cmd.Check(m_View->ShowingDupesMode() == SHOW_NORMAL);
771 void GUIControl::OnMoveEast()
773 m_View->TurnCaveTo(90.0);
774 m_View->ForceRefresh();
777 void GUIControl::OnMoveEastUpdate(wxUpdateUIEvent& cmd)
779 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 90.0);
782 void GUIControl::OnMoveNorth()
784 m_View->TurnCaveTo(0.0);
785 m_View->ForceRefresh();
788 void GUIControl::OnMoveNorthUpdate(wxUpdateUIEvent& cmd)
790 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 0.0);
793 void GUIControl::OnMoveSouth()
795 m_View->TurnCaveTo(180.0);
796 m_View->ForceRefresh();
799 void GUIControl::OnMoveSouthUpdate(wxUpdateUIEvent& cmd)
801 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 180.0);
804 void GUIControl::OnMoveWest()
806 m_View->TurnCaveTo(270.0);
807 m_View->ForceRefresh();
810 void GUIControl::OnMoveWestUpdate(wxUpdateUIEvent& cmd)
812 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 270.0);
815 void GUIControl::OnToggleRotation()
817 m_View->ToggleRotation();
820 void GUIControl::OnToggleRotationUpdate(wxUpdateUIEvent& cmd)
822 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
823 cmd.Check(m_View->HasData() && m_View->IsRotating());
826 void GUIControl::OnReverseControls()
828 m_ReverseControls = !m_ReverseControls;
831 void GUIControl::OnReverseControlsUpdate(wxUpdateUIEvent& cmd)
833 cmd.Enable(m_View->HasData());
834 cmd.Check(m_ReverseControls);
837 void GUIControl::OnReverseDirectionOfRotation()
839 m_View->ReverseRotation();
842 void GUIControl::OnReverseDirectionOfRotationUpdate(wxUpdateUIEvent& cmd)
844 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
847 void GUIControl::OnStepOnceAnticlockwise(bool accel)
849 if (m_View->GetPerspective()) {
850 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
851 } else {
852 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
854 m_View->ForceRefresh();
857 void GUIControl::OnStepOnceClockwise(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::OnDefaults()
869 m_View->Defaults();
872 void GUIControl::OnDefaultsUpdate(wxUpdateUIEvent& cmd)
874 cmd.Enable(m_View->HasData());
877 void GUIControl::OnElevation()
879 // Switch to elevation view.
881 m_View->SwitchToElevation();
884 void GUIControl::OnElevationUpdate(wxUpdateUIEvent& cmd)
886 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingElevation());
889 void GUIControl::OnHigherViewpoint(bool accel)
891 // Raise the viewpoint.
892 if (m_View->GetPerspective()) {
893 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
894 } else {
895 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
897 m_View->ForceRefresh();
900 void GUIControl::OnLowerViewpoint(bool accel)
902 // Lower the viewpoint.
903 if (m_View->GetPerspective()) {
904 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
905 } else {
906 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
908 m_View->ForceRefresh();
911 void GUIControl::OnPlan()
913 // Switch to plan view.
914 m_View->SwitchToPlan();
917 void GUIControl::OnPlanUpdate(wxUpdateUIEvent& cmd)
919 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingPlan());
922 void GUIControl::OnShiftDisplayDown(bool accel)
924 if (m_View->GetPerspective())
925 m_View->MoveViewer(0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0);
926 else
927 m_View->TranslateCave(0, accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT);
930 void GUIControl::OnShiftDisplayLeft(bool accel)
932 if (m_View->GetPerspective())
933 m_View->MoveViewer(0, 0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT);
934 else
935 m_View->TranslateCave(accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT, 0);
938 void GUIControl::OnShiftDisplayRight(bool accel)
940 if (m_View->GetPerspective())
941 m_View->MoveViewer(0, 0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT);
942 else
943 m_View->TranslateCave(accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT, 0);
946 void GUIControl::OnShiftDisplayUp(bool accel)
948 if (m_View->GetPerspective())
949 m_View->MoveViewer(0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0);
950 else
951 m_View->TranslateCave(0, accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT);
954 void GUIControl::OnZoomIn(bool accel)
956 // Increase the scale.
958 if (m_View->GetPerspective()) {
959 m_View->MoveViewer(accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0, 0);
960 } else {
961 m_View->SetScale(m_View->GetScale() * (accel ? 1.1236 : 1.06));
962 m_View->ForceRefresh();
966 void GUIControl::OnZoomOut(bool accel)
968 // Decrease the scale.
970 if (m_View->GetPerspective()) {
971 m_View->MoveViewer(accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0, 0);
972 } else {
973 m_View->SetScale(m_View->GetScale() / (accel ? 1.1236 : 1.06));
974 m_View->ForceRefresh();
978 void GUIControl::OnToggleScalebar()
980 m_View->ToggleScaleBar();
983 void GUIControl::OnToggleScalebarUpdate(wxUpdateUIEvent& cmd)
985 cmd.Enable(m_View->HasData());
986 cmd.Check(m_View->ShowingScaleBar());
989 void GUIControl::OnToggleColourKey()
991 m_View->ToggleColourKey();
994 void GUIControl::OnToggleColourKeyUpdate(wxUpdateUIEvent& cmd)
996 cmd.Enable(m_View->HasData() && m_View->ColouringBy() != COLOUR_BY_NONE);
997 cmd.Check(m_View->ShowingColourKey());
1000 void GUIControl::OnViewCompass()
1002 m_View->ToggleCompass();
1005 void GUIControl::OnViewCompassUpdate(wxUpdateUIEvent& cmd)
1007 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1008 cmd.Check(m_View->ShowingCompass());
1011 void GUIControl::OnViewClino()
1013 m_View->ToggleClino();
1016 void GUIControl::OnViewClinoUpdate(wxUpdateUIEvent& cmd)
1018 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1019 cmd.Check(m_View->ShowingClino());
1022 void GUIControl::OnShowSurface()
1024 m_View->ToggleSurfaceLegs();
1027 void GUIControl::OnShowSurfaceUpdate(wxUpdateUIEvent& cmd)
1029 cmd.Enable(m_View->HasData() && m_View->HasSurfaceLegs());
1030 cmd.Check(m_View->ShowingSurfaceLegs());
1033 void GUIControl::OnShowEntrances()
1035 m_View->ToggleEntrances();
1038 void GUIControl::OnShowEntrancesUpdate(wxUpdateUIEvent& cmd)
1040 cmd.Enable(m_View->HasData() && (m_View->GetNumEntrances() > 0));
1041 cmd.Check(m_View->ShowingEntrances());
1044 void GUIControl::OnShowFixedPts()
1046 m_View->ToggleFixedPts();
1049 void GUIControl::OnShowFixedPtsUpdate(wxUpdateUIEvent& cmd)
1051 cmd.Enable(m_View->HasData() && (m_View->GetNumFixedPts() > 0));
1052 cmd.Check(m_View->ShowingFixedPts());
1055 void GUIControl::OnShowExportedPts()
1057 m_View->ToggleExportedPts();
1060 void GUIControl::OnShowExportedPtsUpdate(wxUpdateUIEvent& cmd)
1062 cmd.Enable(m_View->HasData() && (m_View->GetNumExportedPts() > 0));
1063 cmd.Check(m_View->ShowingExportedPts());
1066 void GUIControl::OnViewGrid()
1068 m_View->ToggleGrid();
1071 void GUIControl::OnViewGridUpdate(wxUpdateUIEvent& cmd)
1073 cmd.Enable(m_View->HasData());
1074 cmd.Check(m_View->ShowingGrid());
1077 void GUIControl::OnIndicatorsUpdate(wxUpdateUIEvent& cmd)
1079 cmd.Enable(m_View->HasData());
1082 void GUIControl::OnViewPerspective()
1084 m_View->TogglePerspective();
1085 // Force update of coordinate display.
1086 if (m_View->GetPerspective()) {
1087 m_View->MoveViewer(0, 0, 0);
1088 } else {
1089 m_View->ClearCoords();
1093 void GUIControl::OnViewPerspectiveUpdate(wxUpdateUIEvent& cmd)
1095 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
1096 cmd.Check(m_View->GetPerspective());
1099 void GUIControl::OnViewSmoothShading()
1101 m_View->ToggleSmoothShading();
1104 void GUIControl::OnViewSmoothShadingUpdate(wxUpdateUIEvent& cmd)
1106 cmd.Enable(m_View->HasData());
1107 cmd.Check(m_View->GetSmoothShading());
1110 void GUIControl::OnViewTextured()
1112 m_View->ToggleTextured();
1115 void GUIControl::OnViewTexturedUpdate(wxUpdateUIEvent& cmd)
1117 cmd.Enable(m_View->HasData());
1118 cmd.Check(m_View->GetTextured());
1121 void GUIControl::OnViewFog()
1123 m_View->ToggleFog();
1126 void GUIControl::OnViewFogUpdate(wxUpdateUIEvent& cmd)
1128 cmd.Enable(m_View->HasData());
1129 cmd.Check(m_View->GetFog());
1132 void GUIControl::OnViewSmoothLines()
1134 m_View->ToggleAntiAlias();
1137 void GUIControl::OnViewSmoothLinesUpdate(wxUpdateUIEvent& cmd)
1139 cmd.Enable(m_View->HasData());
1140 cmd.Check(m_View->GetAntiAlias());
1143 void GUIControl::OnToggleMetric()
1145 m_View->ToggleMetric();
1147 wxConfigBase::Get()->Write(wxT("metric"), m_View->GetMetric());
1148 wxConfigBase::Get()->Flush();
1151 void GUIControl::OnToggleMetricUpdate(wxUpdateUIEvent& cmd)
1153 cmd.Enable(m_View->HasData());
1154 cmd.Check(m_View->GetMetric());
1157 void GUIControl::OnToggleDegrees()
1159 m_View->ToggleDegrees();
1161 wxConfigBase::Get()->Write(wxT("degrees"), m_View->GetDegrees());
1162 wxConfigBase::Get()->Flush();
1165 void GUIControl::OnToggleDegreesUpdate(wxUpdateUIEvent& cmd)
1167 cmd.Enable(m_View->HasData());
1168 cmd.Check(m_View->GetDegrees());
1171 void GUIControl::OnTogglePercent()
1173 m_View->TogglePercent();
1175 wxConfigBase::Get()->Write(wxT("percent"), m_View->GetPercent());
1176 wxConfigBase::Get()->Flush();
1179 void GUIControl::OnTogglePercentUpdate(wxUpdateUIEvent& cmd)
1181 cmd.Enable(m_View->HasData());
1182 cmd.Check(m_View->GetPercent());
1185 void GUIControl::OnToggleTubes()
1187 m_View->ToggleTubes();
1190 void GUIControl::OnToggleTubesUpdate(wxUpdateUIEvent& cmd)
1192 cmd.Enable(m_View->HasData() && m_View->HasTubes());
1193 cmd.Check(m_View->GetTubes());
1196 void GUIControl::OnCancelDistLine()
1198 m_View->ClearTreeSelection();
1201 void GUIControl::OnCancelDistLineUpdate(wxUpdateUIEvent& cmd)
1203 cmd.Enable(m_View->ShowingMeasuringLine());
1206 void GUIControl::OnKeyPress(wxKeyEvent &e)
1208 if (!m_View->HasData() ||
1209 (e.GetModifiers() &~ (wxMOD_CONTROL|wxMOD_SHIFT))) {
1210 // Pass on the event if there's no survey data, or if any modifier keys
1211 // other than Ctrl and Shift are pressed.
1212 e.Skip();
1213 return;
1216 // The changelog says this is meant to keep animation going while keys are
1217 // pressed, but that happens anyway (on linux at least - perhaps it helps
1218 // on windows?) FIXME : check!
1219 //bool refresh = m_View->Animate();
1221 switch (e.GetKeyCode()) {
1222 case '/': case '?':
1223 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1224 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1225 break;
1226 case '\'': case '@': case '"': // both shifted forms - US and UK kbd
1227 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1228 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1229 break;
1230 case 'C': case 'c':
1231 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1232 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1233 break;
1234 case 'V': case 'v':
1235 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1236 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1237 break;
1238 case ']': case '}':
1239 OnZoomIn(e.GetModifiers() == wxMOD_SHIFT);
1240 break;
1241 case '[': case '{':
1242 OnZoomOut(e.GetModifiers() == wxMOD_SHIFT);
1243 break;
1244 case 'N': case 'n':
1245 OnMoveNorth();
1246 break;
1247 case 'S': case 's':
1248 OnMoveSouth();
1249 break;
1250 case 'E': case 'e':
1251 if (!m_View->IsExtendedElevation())
1252 OnMoveEast();
1253 break;
1254 case 'W': case 'w':
1255 if (!m_View->IsExtendedElevation())
1256 OnMoveWest();
1257 break;
1258 case 'Z': case 'z':
1259 if (!m_View->IsExtendedElevation())
1260 m_View->RotateFaster(e.GetModifiers() == wxMOD_SHIFT);
1261 break;
1262 case 'X': case 'x':
1263 if (!m_View->IsExtendedElevation())
1264 m_View->RotateSlower(e.GetModifiers() == wxMOD_SHIFT);
1265 break;
1266 case 'R': case 'r':
1267 if (!m_View->IsExtendedElevation())
1268 OnReverseDirectionOfRotation();
1269 break;
1270 case 'P': case 'p':
1271 if (!m_View->IsExtendedElevation() && !m_View->ShowingPlan())
1272 OnPlan();
1273 break;
1274 case 'L': case 'l':
1275 if (!m_View->IsExtendedElevation() && !m_View->ShowingElevation())
1276 OnElevation();
1277 break;
1278 case 'O': case 'o':
1279 OnDisplayOverlappingNames();
1280 break;
1281 case WXK_DELETE:
1282 if (e.GetModifiers() == 0)
1283 OnDefaults();
1284 break;
1285 case WXK_RETURN:
1286 if (e.GetModifiers() == 0) {
1287 // For compatibility with older versions.
1288 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1289 m_View->StartRotation();
1291 break;
1292 case WXK_SPACE:
1293 if (e.GetModifiers() == 0) {
1294 if (!m_View->IsExtendedElevation())
1295 OnToggleRotation();
1297 break;
1298 case WXK_LEFT:
1299 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1300 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1301 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1302 } else {
1303 OnShiftDisplayLeft(e.GetModifiers() == wxMOD_SHIFT);
1305 break;
1306 case WXK_RIGHT:
1307 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1308 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1309 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1310 } else {
1311 OnShiftDisplayRight(e.GetModifiers() == wxMOD_SHIFT);
1313 break;
1314 case WXK_UP:
1315 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1316 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1317 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1318 } else {
1319 OnShiftDisplayUp(e.GetModifiers() == wxMOD_SHIFT);
1321 break;
1322 case WXK_DOWN:
1323 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1324 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1325 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1326 } else {
1327 OnShiftDisplayDown(e.GetModifiers() == wxMOD_SHIFT);
1329 break;
1330 case WXK_ESCAPE:
1331 if (e.GetModifiers() == 0) {
1332 if (m_View->ShowingMeasuringLine()) {
1333 OnCancelDistLine();
1334 } else if (m_View->IsFullScreen()) {
1335 // Cancel full-screen mode on "Escape" if it isn't cancelling
1336 // the measuring line.
1337 m_View->FullScreenMode();
1340 break;
1341 case WXK_F2:
1342 if (e.GetModifiers() == 0)
1343 m_View->ToggleFatFinger();
1344 break;
1345 case WXK_F3:
1346 if (e.GetModifiers() == 0)
1347 m_View->ToggleHitTestDebug();
1348 break;
1349 case WXK_F4: {
1350 if (e.GetModifiers() == 0) {
1351 const wxChar * msg;
1352 #if wxDEBUG_LEVEL
1353 if (wxTheAssertHandler)
1354 wxTheAssertHandler = NULL;
1355 else
1356 wxSetDefaultAssertHandler();
1357 if (wxTheAssertHandler)
1358 msg = wxT("Assertions enabled");
1359 else
1360 msg = wxT("Assertions disabled");
1361 #else
1362 msg = wxT("wxWidgets was built without assertions");
1363 #endif
1364 wxMessageBox(msg, wxT("Aven Debug"), wxOK | wxICON_INFORMATION);
1366 break;
1368 case WXK_F5:
1369 if (e.GetModifiers() == 0) {
1370 m_View->InvalidateAllLists();
1371 m_View->ForceRefresh();
1373 break;
1374 case WXK_F6:
1375 if (e.GetModifiers() == 0)
1376 m_View->ToggleRenderStats();
1377 break;
1378 default:
1379 e.Skip();
1382 //if (refresh) m_View->ForceRefresh();
1385 void GUIControl::OnViewFullScreenUpdate(wxUpdateUIEvent& cmd)
1387 cmd.Check(m_View->IsFullScreen());
1390 void GUIControl::OnViewFullScreen()
1392 m_View->FullScreenMode();
1395 void GUIControl::OnViewBoundingBoxUpdate(wxUpdateUIEvent& cmd)
1397 cmd.Enable(m_View->HasData());
1398 cmd.Check(m_View->DisplayingBoundingBox());
1401 void GUIControl::OnViewBoundingBox()
1403 m_View->ToggleBoundingBox();
1406 void GUIControl::OnViewTerrainUpdate(wxUpdateUIEvent& cmd)
1408 cmd.Enable(m_View->HasTerrain());
1409 cmd.Check(m_View->DisplayingTerrain());
1412 void GUIControl::OnViewTerrain()
1414 m_View->ToggleTerrain();