source: git/src/guicontrol.cc @ a57af18

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
Last change on this file since a57af18 was a57af18, checked in by Olly Betts <olly@…>, 10 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.