FreeCAD

Форк
0
/
TouchpadNavigationStyle.cpp 
277 строк · 10.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2012 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <QApplication>
26
#endif
27

28
#include "NavigationStyle.h"
29
#include "View3DInventorViewer.h"
30

31

32
using namespace Gui;
33

34
// ----------------------------------------------------------------------------------
35

36
/* TRANSLATOR Gui::TouchpadNavigationStyle */
37

38
TYPESYSTEM_SOURCE(Gui::TouchpadNavigationStyle, Gui::UserNavigationStyle)
39

40
TouchpadNavigationStyle::TouchpadNavigationStyle() = default;
41

42
TouchpadNavigationStyle::~TouchpadNavigationStyle() = default;
43

44
const char* TouchpadNavigationStyle::mouseButtons(ViewerMode mode)
45
{
46
    switch (mode) {
47
    case NavigationStyle::SELECTION:
48
        return QT_TR_NOOP("Press left mouse button");
49
    case NavigationStyle::PANNING:
50
        return QT_TR_NOOP("Press SHIFT button");
51
    case NavigationStyle::DRAGGING:
52
        return QT_TR_NOOP("Press ALT button");
53
    case NavigationStyle::ZOOMING:
54
        return QT_TR_NOOP("Press CTRL and SHIFT buttons");
55
    default:
56
        return "No description";
57
    }
58
}
59

60
SbBool TouchpadNavigationStyle::processSoEvent(const SoEvent * const ev)
61
{
62
    // Events when in "ready-to-seek" mode are ignored, except those
63
    // which influence the seek mode itself -- these are handled further
64
    // up the inheritance hierarchy.
65
    if (this->isSeekMode()) {
66
        return inherited::processSoEvent(ev);
67
    }
68
    // Switch off viewing mode (Bug #0000911)
69
    if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
70
        this->setViewing(false); // by default disable viewing mode to render the scene
71

72
    const SoType type(ev->getTypeId());
73

74
    const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
75
    const SbVec2s pos(ev->getPosition());
76
    const SbVec2f posn = normalizePixelPos(pos);
77

78
    const SbVec2f prevnormalized = this->lastmouseposition;
79
    this->lastmouseposition = posn;
80

81
    // Set to true if any event processing happened. Note that it is not
82
    // necessary to restrict ourselves to only do one "action" for an
83
    // event, we only need this flag to see if any processing happened
84
    // at all.
85
    SbBool processed = false;
86

87
    const ViewerMode curmode = this->currentmode;
88
    ViewerMode newmode = curmode;
89

90
    // Mismatches in state of the modifier keys happens if the user
91
    // presses or releases them outside the viewer window.
92
    syncModifierKeys(ev);
93

94
    // give the nodes in the foreground root the chance to handle events (e.g color bar)
95
    if (!viewer->isEditing()) {
96
        processed = handleEventInForeground(ev);
97
        if (processed)
98
            return true;
99
    }
100

101
    // Keyboard handling
102
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
103
        const auto event = static_cast<const SoKeyboardEvent *>(ev);
104
        processed = processKeyboardEvent(event);
105
    }
106

107
    // Mouse Button / Spaceball Button handling
108
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
109
        const auto event = (const SoMouseButtonEvent *) ev;
110
        const int button = event->getButton();
111
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
112

113
        // SoDebugError::postInfo("processSoEvent", "button = %d", button);
114
        switch (button) {
115
        case SoMouseButtonEvent::BUTTON1:
116
            this->lockrecenter = true;
117
            this->button1down = press;
118
            if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
119
                newmode = NavigationStyle::SEEK_MODE;
120
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
121
                processed = true;
122
            }
123
            else if (press && (this->currentmode == NavigationStyle::PANNING ||
124
                               this->currentmode == NavigationStyle::ZOOMING)) {
125
                newmode = NavigationStyle::DRAGGING;
126
                saveCursorPosition(ev);
127
                this->centerTime = ev->getTime();
128
                processed = true;
129
            }
130
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
131
                processed = true;
132
            }
133
            else {
134
                processed = processClickEvent(event);
135
            }
136
            break;
137
        case SoMouseButtonEvent::BUTTON2:
138
            // If we are in edit mode then simply ignore the RMB events
139
            // to pass the event to the base class.
140
            this->lockrecenter = true;
141

142
            // Don't show the context menu after dragging, panning or zooming
143
            if (!press && (hasDragged || hasPanned || hasZoomed)) {
144
                processed = true;
145
            }
146
            else if (!press && !viewer->isEditing()) {
147
                if (this->currentmode != NavigationStyle::ZOOMING &&
148
                    this->currentmode != NavigationStyle::PANNING &&
149
                    this->currentmode != NavigationStyle::DRAGGING) {
150
                    if (this->isPopupMenuEnabled()) {
151
                        this->openPopupMenu(event->getPosition());
152
                    }
153
                }
154
            }
155
            // Alternative way of rotating & zooming
156
            if (press && (this->currentmode == NavigationStyle::PANNING ||
157
                          this->currentmode == NavigationStyle::ZOOMING)) {
158
                newmode = NavigationStyle::DRAGGING;
159
                saveCursorPosition(ev);
160
                this->centerTime = ev->getTime();
161
                processed = true;
162
            }
163
            this->button2down = press;
164
            break;
165
        default:
166
            break;
167
        }
168
    }
169

170
    // Mouse Movement handling
171
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
172
        this->lockrecenter = true;
173
        const auto event = (const SoLocation2Event *) ev;
174
        if (this->currentmode == NavigationStyle::ZOOMING) {
175
            this->zoomByCursor(posn, prevnormalized);
176
            processed = true;
177
        }
178
        else if (this->currentmode == NavigationStyle::PANNING) {
179
            float ratio = vp.getViewportAspectRatio();
180
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
181
            processed = true;
182
        }
183
        else if (this->currentmode == NavigationStyle::DRAGGING) {
184
            this->addToLog(event->getPosition(), event->getTime());
185
            this->spin(posn);
186
            moveCursorPosition();
187
            processed = true;
188
        }
189
    }
190

191
    // Spaceball & Joystick handling
192
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
193
        const auto event = static_cast<const SoMotion3Event *>(ev);
194
        if (event)
195
            this->processMotionEvent(event);
196
        processed = true;
197
    }
198

199
    enum {
200
        BUTTON1DOWN = 1 << 0,
201
        BUTTON2DOWN = 1 << 1,
202
        CTRLDOWN =    1 << 2,
203
        SHIFTDOWN =   1 << 3,
204
        ALTDOWN =     1 << 4
205
    };
206
    unsigned int combo =
207
        (this->button1down ? BUTTON1DOWN : 0) |
208
        (this->button2down ? BUTTON2DOWN : 0) |
209
        (this->ctrldown ? CTRLDOWN : 0) |
210
        (this->shiftdown ? SHIFTDOWN : 0) |
211
        (this->altdown ? ALTDOWN : 0);
212

213
    switch (combo) {
214
    case 0:
215
        if (curmode == NavigationStyle::SPINNING) { break; }
216
        newmode = NavigationStyle::IDLE;
217
        break;
218
    case BUTTON1DOWN:
219
        // make sure not to change the selection when stopping spinning
220
        if (curmode == NavigationStyle::SPINNING)
221
            newmode = NavigationStyle::IDLE;
222
        else
223
            newmode = NavigationStyle::SELECTION;
224
        break;
225
    case CTRLDOWN:
226
        newmode = NavigationStyle::IDLE;
227
        break;
228
    case SHIFTDOWN:
229
        // Shift + left mouse click enables dragging.
230
        // If the mouse is released the event should not be forwarded to the base
231
        // class that eventually performs a selection.
232
        if (newmode == NavigationStyle::DRAGGING) {
233
            processed = true;
234
        }
235
        newmode = NavigationStyle::PANNING;
236
        break;
237
    case ALTDOWN:
238
        if (newmode != NavigationStyle::DRAGGING) {
239
            saveCursorPosition(ev);
240
        }
241
        newmode = NavigationStyle::DRAGGING;
242
        break;
243
    case CTRLDOWN|SHIFTDOWN:
244
    case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
245
        // Left mouse button doesn't change the zoom
246
        // behaviour but when pressing or releasing it then do not forward the
247
        // event to the base class that eventually performs a selection.
248
        if (newmode == NavigationStyle::ZOOMING) {
249
            processed = true;
250
        }
251
        newmode = NavigationStyle::ZOOMING;
252
        break;
253
    default:
254
        break;
255
    }
256

257
    // Process when selection button is pressed together with other buttons that could trigger different actions.
258
    if (this->button1down && (this->button2down || this->button3down || this->altdown)) {
259
        processed = true;
260
    }
261

262
    // Prevent interrupting rubber-band selection in sketcher
263
    if (viewer->isEditing() && curmode == NavigationStyle::SELECTION && newmode != NavigationStyle::IDLE) {
264
        newmode = NavigationStyle::SELECTION;
265
        processed = false;
266
    }
267

268
    if (newmode != curmode) {
269
        this->setViewingMode(newmode);
270
    }
271

272
    // If not handled in this class, pass on upwards in the inheritance
273
    // hierarchy.
274
    if (!processed)
275
        processed = inherited::processSoEvent(ev);
276
    return processed;
277
}
278

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.