source: git/src/guicontrol.cc@ a57af18

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 a57af18 was a57af18, checked in by Olly Betts <olly@…>, 12 years ago

src/guicontrol.cc: Fix assertion if two mouse buttons are held down
at the same time. Reported by Brian Clipstone.

  • Property mode set to 100644
File size: 28.5 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 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->SetCursor(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->SetCursor(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->SetCursor(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->SetCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
123 } else {
124 m_ScaleRotateLock = lock_SCALE;
125// m_View->SetCursor(GfxCore::CURSOR_ZOOM);
126 }
127 break;
128 case lock_SCALE:
129 if (dx2 >= 8 * dy2) {
130 m_ScaleRotateLock = lock_ROTATE;
131// m_View->SetCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
132 }
133 break;
134 case lock_ROTATE:
135 if (dy2 >= 8 * dx2) {
136 m_ScaleRotateLock = lock_SCALE;
137// m_View->SetCursor(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->SetCursor(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->SetCursor(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->SetCursor(GfxCore::CURSOR_POINTING_HAND);
220 } else {
221 m_View->SetCursor(GfxCore::CURSOR_DEFAULT);
222 }
223}
224
225void GUIControl::HandleNonDrag(const wxPoint & point) {
226 if (m_View->CheckHitTestGrid(point, false)) {
227 m_View->SetCursor(GfxCore::CURSOR_POINTING_HAND);
228 } else if (m_View->PointWithinScaleBar(point)) {
229 m_View->SetCursor(GfxCore::CURSOR_HORIZONTAL_RESIZE);
230 } else if (m_View->PointWithinCompass(point)) {
231 m_View->SetCursor(GfxCore::CURSOR_ROTATE_HORIZONTALLY);
232 } else if (m_View->PointWithinClino(point)) {
233 m_View->SetCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
234 } else {
235 RestoreCursor();
236 }
237}
238
239//
240// Mouse event handling methods
241//
242
243void GUIControl::OnMouseMove(wxMouseEvent& event)
244{
245 // Mouse motion event handler.
246 if (!m_View->HasData()) return;
247
248 // Ignore moves which don't change the position.
249 if (event.GetPosition() == m_DragStart) {
250 return;
251 }
252
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();
261 }
262 }
263 timestamp = event.GetTimestamp();
264
265 wxPoint point(event.GetPosition());
266
267 // Check hit-test grid (only if no buttons are pressed).
268 if (!event.LeftIsDown() && !event.MiddleIsDown() && !event.RightIsDown()) {
269 HandleNonDrag(point);
270 }
271
272 // Update coordinate display if in plan view,
273 // or altitude if in elevation view.
274 m_View->SetCoords(point);
275
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);
295 }
296 break;
297 case drag_NONE:
298 // Shouldn't happen?! FIXME: assert or something.
299 break;
300 }
301 break;
302 case MIDDLE_DRAG:
303 HandleTilt(point);
304 break;
305 case RIGHT_DRAG:
306 HandleTranslate(point);
307 break;
308 case NO_DRAG:
309 break;
310 }
311
312 m_DragLast = point;
313}
314
315void GUIControl::OnLButtonDown(wxMouseEvent& event)
316{
317 if (m_View->HasData()) {
318 m_DragStart = m_DragRealStart = event.GetPosition();
319
320 if (m_View->PointWithinCompass(m_DragStart)) {
321 m_LastDrag = drag_COMPASS;
322 } else if (m_View->PointWithinClino(m_DragStart)) {
323 m_LastDrag = drag_ELEV;
324 } else if (m_View->PointWithinScaleBar(m_DragStart)) {
325 m_LastDrag = drag_SCALE;
326 } else {
327 if (event.ControlDown()) {
328 if (m_View->IsExtendedElevation()) {
329 return;
330 }
331 m_View->SetCursor(GfxCore::CURSOR_ROTATE_EITHER_WAY);
332 } else {
333 m_View->SetCursor(GfxCore::CURSOR_ZOOM_ROTATE);
334 }
335
336 m_LastDrag = drag_MAIN;
337 m_ScaleRotateLock = lock_NONE;
338 }
339
340 // We need to release and recapture for the cursor to update (noticed
341 // with wxGTK).
342 if (dragging != NO_DRAG) m_View->ReleaseMouse();
343 m_View->CaptureMouse();
344
345 dragging = LEFT_DRAG;
346 }
347}
348
349void GUIControl::OnLButtonUp(wxMouseEvent& event)
350{
351 if (m_View->HasData()) {
352 if (dragging != LEFT_DRAG)
353 return;
354
355 if (event.GetPosition() == m_DragRealStart) {
356 // Just a "click"...
357 m_View->CheckHitTestGrid(m_DragStart, true);
358 }
359
360// m_View->RedrawIndicators();
361 m_View->ReleaseMouse();
362
363 m_LastDrag = drag_NONE;
364 dragging = NO_DRAG;
365
366 m_View->DragFinished();
367
368 if (event.GetPosition() == m_DragRealStart) {
369 RestoreCursor();
370 } else {
371 HandleNonDrag(event.GetPosition());
372 }
373 }
374}
375
376void GUIControl::OnMButtonDown(wxMouseEvent& event)
377{
378 if (m_View->HasData() && !m_View->IsExtendedElevation()) {
379 m_DragStart = event.GetPosition();
380
381 m_View->SetCursor(GfxCore::CURSOR_ROTATE_VERTICALLY);
382
383 // We need to release and recapture for the cursor to update (noticed
384 // with wxGTK).
385 if (dragging != NO_DRAG) m_View->ReleaseMouse();
386 m_View->CaptureMouse();
387 dragging = MIDDLE_DRAG;
388 }
389}
390
391void GUIControl::OnMButtonUp(wxMouseEvent&)
392{
393 if (m_View->HasData()) {
394 if (dragging != MIDDLE_DRAG)
395 return;
396
397 dragging = NO_DRAG;
398 m_View->ReleaseMouse();
399 m_View->DragFinished();
400
401 RestoreCursor();
402 }
403}
404
405void GUIControl::OnRButtonDown(wxMouseEvent& event)
406{
407 if (m_View->HasData()) {
408 if (m_View->HandleRClick(event.GetPosition()))
409 return;
410
411 m_DragStart = event.GetPosition();
412
413 m_View->SetCursor(GfxCore::CURSOR_DRAGGING_HAND);
414
415 // We need to release and recapture for the cursor to update (noticed
416 // with wxGTK).
417 if (dragging != NO_DRAG) m_View->ReleaseMouse();
418 m_View->CaptureMouse();
419 dragging = RIGHT_DRAG;
420 }
421}
422
423void GUIControl::OnRButtonUp(wxMouseEvent&)
424{
425 if (dragging != RIGHT_DRAG)
426 return;
427
428 m_LastDrag = drag_NONE;
429 m_View->ReleaseMouse();
430
431 dragging = NO_DRAG;
432
433 RestoreCursor();
434
435 m_View->DragFinished();
436}
437
438void GUIControl::OnMouseWheel(wxMouseEvent& event) {
439 int dy = event.GetWheelRotation();
440 if (m_View->GetPerspective()) {
441 m_View->MoveViewer(-dy, 0, 0);
442 } else {
443 m_View->SetScale(m_View->GetScale() * pow(1.06, -0.04 * dy));
444 m_View->ForceRefresh();
445 }
446}
447
448void GUIControl::OnDisplayOverlappingNames()
449{
450 m_View->ToggleOverlappingNames();
451}
452
453void GUIControl::OnDisplayOverlappingNamesUpdate(wxUpdateUIEvent& cmd)
454{
455 cmd.Enable(m_View->HasData() && m_View->ShowingStationNames());
456 cmd.Check(m_View->ShowingOverlappingNames());
457}
458
459void GUIControl::OnColourByDepth()
460{
461 if (m_View->ColouringBy() == COLOUR_BY_DEPTH) {
462 m_View->SetColourBy(COLOUR_BY_NONE);
463 } else {
464 m_View->SetColourBy(COLOUR_BY_DEPTH);
465 }
466}
467
468void GUIControl::OnColourByDate()
469{
470 if (m_View->ColouringBy() == COLOUR_BY_DATE) {
471 m_View->SetColourBy(COLOUR_BY_NONE);
472 } else {
473 m_View->SetColourBy(COLOUR_BY_DATE);
474 }
475}
476
477void GUIControl::OnColourByError()
478{
479 if (m_View->ColouringBy() == COLOUR_BY_ERROR) {
480 m_View->SetColourBy(COLOUR_BY_NONE);
481 } else {
482 m_View->SetColourBy(COLOUR_BY_ERROR);
483 }
484}
485
486void GUIControl::OnColourByDepthUpdate(wxUpdateUIEvent& cmd)
487{
488 cmd.Enable(m_View->HasData());
489 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DEPTH);
490}
491
492void GUIControl::OnColourByDateUpdate(wxUpdateUIEvent& cmd)
493{
494 cmd.Enable(m_View->HasData());
495 cmd.Check(m_View->ColouringBy() == COLOUR_BY_DATE);
496}
497
498void GUIControl::OnColourByErrorUpdate(wxUpdateUIEvent& cmd)
499{
500 cmd.Enable(m_View->HasData());
501 cmd.Check(m_View->ColouringBy() == COLOUR_BY_ERROR);
502}
503
504void GUIControl::OnShowCrosses()
505{
506 m_View->ToggleCrosses();
507}
508
509void GUIControl::OnShowCrossesUpdate(wxUpdateUIEvent& cmd)
510{
511 cmd.Enable(m_View->HasData());
512 cmd.Check(m_View->ShowingCrosses());
513}
514
515void GUIControl::OnShowStationNames()
516{
517 m_View->ToggleStationNames();
518}
519
520void GUIControl::OnShowStationNamesUpdate(wxUpdateUIEvent& cmd)
521{
522 cmd.Enable(m_View->HasData());
523 cmd.Check(m_View->ShowingStationNames());
524}
525
526void GUIControl::OnShowSurveyLegs()
527{
528 m_View->ToggleUndergroundLegs();
529}
530
531void GUIControl::OnShowSurveyLegsUpdate(wxUpdateUIEvent& cmd)
532{
533 cmd.Enable(m_View->HasData() && m_View->HasUndergroundLegs());
534 cmd.Check(m_View->ShowingUndergroundLegs());
535}
536
537void GUIControl::OnHideSplays()
538{
539 m_View->SetSplaysMode(SPLAYS_HIDE);
540}
541
542void GUIControl::OnShowSplaysNormal()
543{
544 m_View->SetSplaysMode(SPLAYS_SHOW_NORMAL);
545}
546
547void GUIControl::OnShowSplaysFaded()
548{
549 m_View->SetSplaysMode(SPLAYS_SHOW_FADED);
550}
551
552void GUIControl::OnSplaysUpdate(wxUpdateUIEvent& cmd)
553{
554 cmd.Enable(m_View->HasData() && m_View->HasSplays());
555}
556
557void GUIControl::OnHideSplaysUpdate(wxUpdateUIEvent& cmd)
558{
559 cmd.Enable(m_View->HasData() && m_View->HasSplays());
560 cmd.Check(m_View->ShowingSplaysMode() == SPLAYS_HIDE);
561}
562
563void GUIControl::OnShowSplaysNormalUpdate(wxUpdateUIEvent& cmd)
564{
565 cmd.Enable(m_View->HasData() && m_View->HasSplays());
566 cmd.Check(m_View->ShowingSplaysMode() == SPLAYS_SHOW_NORMAL);
567}
568
569void GUIControl::OnShowSplaysFadedUpdate(wxUpdateUIEvent& cmd)
570{
571 cmd.Enable(m_View->HasData() && m_View->HasSplays());
572 cmd.Check(m_View->ShowingSplaysMode() == SPLAYS_SHOW_FADED);
573}
574
575void GUIControl::OnMoveEast()
576{
577 m_View->TurnCaveTo(90.0);
578 m_View->ForceRefresh();
579}
580
581void GUIControl::OnMoveEastUpdate(wxUpdateUIEvent& cmd)
582{
583 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 90.0);
584}
585
586void GUIControl::OnMoveNorth()
587{
588 m_View->TurnCaveTo(0.0);
589 m_View->ForceRefresh();
590}
591
592void GUIControl::OnMoveNorthUpdate(wxUpdateUIEvent& cmd)
593{
594 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 0.0);
595}
596
597void GUIControl::OnMoveSouth()
598{
599 m_View->TurnCaveTo(180.0);
600 m_View->ForceRefresh();
601}
602
603void GUIControl::OnMoveSouthUpdate(wxUpdateUIEvent& cmd)
604{
605 cmd.Enable(m_View->HasData() && m_View->GetCompassValue() != 180.0);
606}
607
608void GUIControl::OnMoveWest()
609{
610 m_View->TurnCaveTo(270.0);
611 m_View->ForceRefresh();
612}
613
614void GUIControl::OnMoveWestUpdate(wxUpdateUIEvent& cmd)
615{
616 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && m_View->GetCompassValue() != 270.0);
617}
618
619void GUIControl::OnToggleRotation()
620{
621 m_View->ToggleRotation();
622}
623
624void GUIControl::OnToggleRotationUpdate(wxUpdateUIEvent& cmd)
625{
626 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
627 cmd.Check(m_View->HasData() && m_View->IsRotating());
628}
629
630void GUIControl::OnReverseControls()
631{
632 m_ReverseControls = !m_ReverseControls;
633}
634
635void GUIControl::OnReverseControlsUpdate(wxUpdateUIEvent& cmd)
636{
637 cmd.Enable(m_View->HasData());
638 cmd.Check(m_ReverseControls);
639}
640
641void GUIControl::OnReverseDirectionOfRotation()
642{
643 m_View->ReverseRotation();
644}
645
646void GUIControl::OnReverseDirectionOfRotationUpdate(wxUpdateUIEvent& cmd)
647{
648 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
649}
650
651void GUIControl::OnSlowDown(bool accel)
652{
653 m_View->RotateSlower(accel);
654}
655
656void GUIControl::OnSlowDownUpdate(wxUpdateUIEvent& cmd)
657{
658 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
659}
660
661void GUIControl::OnSpeedUp(bool accel)
662{
663 m_View->RotateFaster(accel);
664}
665
666void GUIControl::OnSpeedUpUpdate(wxUpdateUIEvent& cmd)
667{
668 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
669}
670
671void GUIControl::OnStepOnceAnticlockwise(bool accel)
672{
673 if (m_View->GetPerspective()) {
674 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
675 } else {
676 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
677 }
678 m_View->ForceRefresh();
679}
680
681void GUIControl::OnStepOnceAnticlockwiseUpdate(wxUpdateUIEvent& cmd)
682{
683 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->IsRotating());
684}
685
686void GUIControl::OnStepOnceClockwise(bool accel)
687{
688 if (m_View->GetPerspective()) {
689 m_View->TurnCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
690 } else {
691 m_View->TurnCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
692 }
693 m_View->ForceRefresh();
694}
695
696void GUIControl::OnStepOnceClockwiseUpdate(wxUpdateUIEvent& cmd)
697{
698 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->IsRotating());
699}
700
701void GUIControl::OnDefaults()
702{
703 m_View->Defaults();
704}
705
706void GUIControl::OnDefaultsUpdate(wxUpdateUIEvent& cmd)
707{
708 cmd.Enable(m_View->HasData());
709}
710
711void GUIControl::OnElevation()
712{
713 // Switch to elevation view.
714
715 m_View->SwitchToElevation();
716}
717
718void GUIControl::OnElevationUpdate(wxUpdateUIEvent& cmd)
719{
720 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingElevation());
721}
722
723void GUIControl::OnHigherViewpoint(bool accel)
724{
725 // Raise the viewpoint.
726 if (m_View->GetPerspective()) {
727 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
728 } else {
729 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
730 }
731 m_View->ForceRefresh();
732}
733
734void GUIControl::OnHigherViewpointUpdate(wxUpdateUIEvent& cmd)
735{
736 cmd.Enable(m_View->HasData() && m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation());
737}
738
739void GUIControl::OnLowerViewpoint(bool accel)
740{
741 // Lower the viewpoint.
742 if (m_View->GetPerspective()) {
743 m_View->TiltCave(accel ? -5.0 * ROTATE_STEP : -ROTATE_STEP);
744 } else {
745 m_View->TiltCave(accel ? 5.0 * ROTATE_STEP : ROTATE_STEP);
746 }
747 m_View->ForceRefresh();
748}
749
750void GUIControl::OnLowerViewpointUpdate(wxUpdateUIEvent& cmd)
751{
752 cmd.Enable(m_View->HasData() && m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation());
753}
754
755void GUIControl::OnPlan()
756{
757 // Switch to plan view.
758 m_View->SwitchToPlan();
759}
760
761void GUIControl::OnPlanUpdate(wxUpdateUIEvent& cmd)
762{
763 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation() && !m_View->ShowingPlan());
764}
765
766void GUIControl::OnShiftDisplayDown(bool accel)
767{
768 if (m_View->GetPerspective())
769 m_View->MoveViewer(0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0);
770 else
771 m_View->TranslateCave(0, accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT);
772}
773
774void GUIControl::OnShiftDisplayDownUpdate(wxUpdateUIEvent& cmd)
775{
776 cmd.Enable(m_View->HasData());
777}
778
779void GUIControl::OnShiftDisplayLeft(bool accel)
780{
781 if (m_View->GetPerspective())
782 m_View->MoveViewer(0, 0, accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT);
783 else
784 m_View->TranslateCave(accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT, 0);
785}
786
787void GUIControl::OnShiftDisplayLeftUpdate(wxUpdateUIEvent& cmd)
788{
789 cmd.Enable(m_View->HasData());
790}
791
792void GUIControl::OnShiftDisplayRight(bool accel)
793{
794 if (m_View->GetPerspective())
795 m_View->MoveViewer(0, 0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT);
796 else
797 m_View->TranslateCave(accel ? 5 * DISPLAY_SHIFT : DISPLAY_SHIFT, 0);
798}
799
800void GUIControl::OnShiftDisplayRightUpdate(wxUpdateUIEvent& cmd)
801{
802 cmd.Enable(m_View->HasData());
803}
804
805void GUIControl::OnShiftDisplayUp(bool accel)
806{
807 if (m_View->GetPerspective())
808 m_View->MoveViewer(0, accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0);
809 else
810 m_View->TranslateCave(0, accel ? -5 * DISPLAY_SHIFT : -DISPLAY_SHIFT);
811}
812
813void GUIControl::OnShiftDisplayUpUpdate(wxUpdateUIEvent& cmd)
814{
815 cmd.Enable(m_View->HasData());
816}
817
818void GUIControl::OnZoomIn(bool accel)
819{
820 // Increase the scale.
821
822 if (m_View->GetPerspective()) {
823 m_View->MoveViewer(accel ? 5 * FLYFREE_SHIFT : FLYFREE_SHIFT, 0, 0);
824 } else {
825 m_View->SetScale(m_View->GetScale() * (accel ? 1.1236 : 1.06));
826 m_View->ForceRefresh();
827 }
828}
829
830void GUIControl::OnZoomInUpdate(wxUpdateUIEvent& cmd)
831{
832 cmd.Enable(m_View->HasData());
833}
834
835void GUIControl::OnZoomOut(bool accel)
836{
837 // Decrease the scale.
838
839 if (m_View->GetPerspective()) {
840 m_View->MoveViewer(accel ? -5 * FLYFREE_SHIFT : -FLYFREE_SHIFT, 0, 0);
841 } else {
842 m_View->SetScale(m_View->GetScale() / (accel ? 1.1236 : 1.06));
843 m_View->ForceRefresh();
844 }
845}
846
847void GUIControl::OnZoomOutUpdate(wxUpdateUIEvent& cmd)
848{
849 cmd.Enable(m_View->HasData());
850}
851
852void GUIControl::OnToggleScalebar()
853{
854 m_View->ToggleScaleBar();
855}
856
857void GUIControl::OnToggleScalebarUpdate(wxUpdateUIEvent& cmd)
858{
859 cmd.Enable(m_View->HasData());
860 cmd.Check(m_View->ShowingScaleBar());
861}
862
863void GUIControl::OnToggleColourKey()
864{
865 m_View->ToggleColourKey();
866}
867
868void GUIControl::OnToggleColourKeyUpdate(wxUpdateUIEvent& cmd)
869{
870 cmd.Enable(m_View->HasData() && m_View->ColouringBy() != COLOUR_BY_NONE);
871 cmd.Check(m_View->ShowingColourKey());
872}
873
874void GUIControl::OnViewCompass()
875{
876 m_View->ToggleCompass();
877}
878
879void GUIControl::OnViewCompassUpdate(wxUpdateUIEvent& cmd)
880{
881 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
882 cmd.Check(m_View->ShowingCompass());
883}
884
885void GUIControl::OnViewClino()
886{
887 m_View->ToggleClino();
888}
889
890void GUIControl::OnViewClinoUpdate(wxUpdateUIEvent& cmd)
891{
892 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
893 cmd.Check(m_View->ShowingClino());
894}
895
896void GUIControl::OnShowSurface()
897{
898 m_View->ToggleSurfaceLegs();
899}
900
901void GUIControl::OnShowSurfaceUpdate(wxUpdateUIEvent& cmd)
902{
903 cmd.Enable(m_View->HasData() && m_View->HasSurfaceLegs());
904 cmd.Check(m_View->ShowingSurfaceLegs());
905}
906
907void GUIControl::OnShowEntrances()
908{
909 m_View->ToggleEntrances();
910}
911
912void GUIControl::OnShowEntrancesUpdate(wxUpdateUIEvent& cmd)
913{
914 cmd.Enable(m_View->HasData() && (m_View->GetNumEntrances() > 0));
915 cmd.Check(m_View->ShowingEntrances());
916}
917
918void GUIControl::OnShowFixedPts()
919{
920 m_View->ToggleFixedPts();
921}
922
923void GUIControl::OnShowFixedPtsUpdate(wxUpdateUIEvent& cmd)
924{
925 cmd.Enable(m_View->HasData() && (m_View->GetNumFixedPts() > 0));
926 cmd.Check(m_View->ShowingFixedPts());
927}
928
929void GUIControl::OnShowExportedPts()
930{
931 m_View->ToggleExportedPts();
932}
933
934void GUIControl::OnShowExportedPtsUpdate(wxUpdateUIEvent& cmd)
935{
936 cmd.Enable(m_View->HasData() && (m_View->GetNumExportedPts() > 0));
937 cmd.Check(m_View->ShowingExportedPts());
938}
939
940void GUIControl::OnViewGrid()
941{
942 m_View->ToggleGrid();
943}
944
945void GUIControl::OnViewGridUpdate(wxUpdateUIEvent& cmd)
946{
947 cmd.Enable(m_View->HasData());
948 cmd.Check(m_View->ShowingGrid());
949}
950
951void GUIControl::OnIndicatorsUpdate(wxUpdateUIEvent& cmd)
952{
953 cmd.Enable(m_View->HasData());
954}
955
956void GUIControl::OnViewPerspective()
957{
958 m_View->TogglePerspective();
959 // Force update of coordinate display.
960 if (m_View->GetPerspective()) {
961 m_View->MoveViewer(0, 0, 0);
962 } else {
963 m_View->ClearCoords();
964 }
965}
966
967void GUIControl::OnViewPerspectiveUpdate(wxUpdateUIEvent& cmd)
968{
969 cmd.Enable(m_View->HasData() && !m_View->IsExtendedElevation());
970 cmd.Check(m_View->GetPerspective());
971}
972
973void GUIControl::OnViewSmoothShading()
974{
975 m_View->ToggleSmoothShading();
976}
977
978void GUIControl::OnViewSmoothShadingUpdate(wxUpdateUIEvent& cmd)
979{
980 cmd.Enable(m_View->HasData());
981 cmd.Check(m_View->GetSmoothShading());
982}
983
984void GUIControl::OnViewTextured()
985{
986 m_View->ToggleTextured();
987}
988
989void GUIControl::OnViewTexturedUpdate(wxUpdateUIEvent& cmd)
990{
991 cmd.Enable(m_View->HasData());
992 cmd.Check(m_View->GetTextured());
993}
994
995void GUIControl::OnViewFog()
996{
997 m_View->ToggleFog();
998}
999
1000void GUIControl::OnViewFogUpdate(wxUpdateUIEvent& cmd)
1001{
1002 cmd.Enable(m_View->HasData());
1003 cmd.Check(m_View->GetFog());
1004}
1005
1006void GUIControl::OnViewSmoothLines()
1007{
1008 m_View->ToggleAntiAlias();
1009}
1010
1011void GUIControl::OnViewSmoothLinesUpdate(wxUpdateUIEvent& cmd)
1012{
1013 cmd.Enable(m_View->HasData());
1014 cmd.Check(m_View->GetAntiAlias());
1015}
1016
1017void GUIControl::OnToggleMetric()
1018{
1019 m_View->ToggleMetric();
1020
1021 wxConfigBase::Get()->Write(wxT("metric"), m_View->GetMetric());
1022 wxConfigBase::Get()->Flush();
1023}
1024
1025void GUIControl::OnToggleMetricUpdate(wxUpdateUIEvent& cmd)
1026{
1027 cmd.Enable(m_View->HasData());
1028 cmd.Check(m_View->GetMetric());
1029}
1030
1031void GUIControl::OnToggleDegrees()
1032{
1033 m_View->ToggleDegrees();
1034
1035 wxConfigBase::Get()->Write(wxT("degrees"), m_View->GetDegrees());
1036 wxConfigBase::Get()->Flush();
1037}
1038
1039void GUIControl::OnToggleDegreesUpdate(wxUpdateUIEvent& cmd)
1040{
1041 cmd.Enable(m_View->HasData());
1042 cmd.Check(m_View->GetDegrees());
1043}
1044
1045void GUIControl::OnToggleTubes()
1046{
1047 m_View->ToggleTubes();
1048}
1049
1050void GUIControl::OnToggleTubesUpdate(wxUpdateUIEvent& cmd)
1051{
1052 cmd.Enable(m_View->HasData() && m_View->HasTubes());
1053 cmd.Check(m_View->GetTubes());
1054}
1055
1056void GUIControl::OnCancelDistLine()
1057{
1058 m_View->ClearTreeSelection();
1059}
1060
1061void GUIControl::OnCancelDistLineUpdate(wxUpdateUIEvent& cmd)
1062{
1063 cmd.Enable(m_View->ShowingMeasuringLine());
1064}
1065
1066void GUIControl::OnKeyPress(wxKeyEvent &e)
1067{
1068 if (!m_View->HasData()) {
1069 e.Skip();
1070 return;
1071 }
1072
1073 // The changelog says this is meant to keep animation going while keys are
1074 // pressed, but that happens anyway (on linux at least - perhaps it helps
1075 // on windows?) FIXME : check!
1076 //bool refresh = m_View->Animate();
1077
1078 switch (e.GetKeyCode()) {
1079 case '/': case '?':
1080 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1081 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1082 break;
1083 case '\'': case '@': case '"': // both shifted forms - US and UK kbd
1084 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1085 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1086 break;
1087 case 'C': case 'c':
1088 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1089 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1090 break;
1091 case 'V': case 'v':
1092 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1093 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1094 break;
1095 case ']': case '}':
1096 OnZoomIn(e.GetModifiers() == wxMOD_SHIFT);
1097 break;
1098 case '[': case '{':
1099 OnZoomOut(e.GetModifiers() == wxMOD_SHIFT);
1100 break;
1101 case 'N': case 'n':
1102 OnMoveNorth();
1103 break;
1104 case 'S': case 's':
1105 OnMoveSouth();
1106 break;
1107 case 'E': case 'e':
1108 if (!m_View->IsExtendedElevation())
1109 OnMoveEast();
1110 break;
1111 case 'W': case 'w':
1112 if (!m_View->IsExtendedElevation())
1113 OnMoveWest();
1114 break;
1115 case 'Z': case 'z':
1116 if (!m_View->IsExtendedElevation())
1117 OnSpeedUp(e.GetModifiers() == wxMOD_SHIFT);
1118 break;
1119 case 'X': case 'x':
1120 if (!m_View->IsExtendedElevation())
1121 OnSlowDown(e.GetModifiers() == wxMOD_SHIFT);
1122 break;
1123 case 'R': case 'r':
1124 if (!m_View->IsExtendedElevation())
1125 OnReverseDirectionOfRotation();
1126 break;
1127 case 'P': case 'p':
1128 if (!m_View->IsExtendedElevation() && !m_View->ShowingPlan())
1129 OnPlan();
1130 break;
1131 case 'L': case 'l':
1132 if (!m_View->IsExtendedElevation() && !m_View->ShowingElevation())
1133 OnElevation();
1134 break;
1135 case 'O': case 'o':
1136 OnDisplayOverlappingNames();
1137 break;
1138 case WXK_DELETE:
1139 OnDefaults();
1140 break;
1141 case WXK_RETURN:
1142 // For compatibility with older versions.
1143 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1144 m_View->StartRotation();
1145 break;
1146 case WXK_SPACE:
1147 if (!m_View->IsExtendedElevation())
1148 OnToggleRotation();
1149 break;
1150 case WXK_LEFT:
1151 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1152 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1153 OnStepOnceAnticlockwise(e.GetModifiers() == wxMOD_SHIFT);
1154 } else {
1155 OnShiftDisplayLeft(e.GetModifiers() == wxMOD_SHIFT);
1156 }
1157 break;
1158 case WXK_RIGHT:
1159 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1160 if (!m_View->IsExtendedElevation() && !m_View->IsRotating())
1161 OnStepOnceClockwise(e.GetModifiers() == wxMOD_SHIFT);
1162 } else {
1163 OnShiftDisplayRight(e.GetModifiers() == wxMOD_SHIFT);
1164 }
1165 break;
1166 case WXK_UP:
1167 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1168 if (m_View->CanRaiseViewpoint() && !m_View->IsExtendedElevation())
1169 OnHigherViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1170 } else {
1171 OnShiftDisplayUp(e.GetModifiers() == wxMOD_SHIFT);
1172 }
1173 break;
1174 case WXK_DOWN:
1175 if ((e.GetModifiers() &~ wxMOD_SHIFT) == wxMOD_CONTROL) {
1176 if (m_View->CanLowerViewpoint() && !m_View->IsExtendedElevation())
1177 OnLowerViewpoint(e.GetModifiers() == wxMOD_SHIFT);
1178 } else {
1179 OnShiftDisplayDown(e.GetModifiers() == wxMOD_SHIFT);
1180 }
1181 break;
1182 case WXK_ESCAPE:
1183 if (m_View->ShowingMeasuringLine()) {
1184 OnCancelDistLine();
1185 }
1186 break;
1187 case WXK_F5:
1188 m_View->InvalidateAllLists();
1189 m_View->ForceRefresh();
1190 break;
1191 default:
1192 e.Skip();
1193 }
1194
1195 //if (refresh) m_View->ForceRefresh();
1196}
1197
1198void GUIControl::OnViewFullScreenUpdate(wxUpdateUIEvent& cmd)
1199{
1200 cmd.Check(m_View->IsFullScreen());
1201}
1202
1203void GUIControl::OnViewFullScreen()
1204{
1205 m_View->FullScreenMode();
1206}
1207
1208void GUIControl::OnViewBoundingBoxUpdate(wxUpdateUIEvent& cmd)
1209{
1210 cmd.Enable(m_View->HasData());
1211 cmd.Check(m_View->DisplayingBoundingBox());
1212}
1213
1214void GUIControl::OnViewBoundingBox()
1215{
1216 m_View->ToggleBoundingBox();
1217}
Note: See TracBrowser for help on using the repository browser.