Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
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, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #pragma once
24 :
25 : #include <QObject>
26 : #include <QList>
27 :
28 : #include "modularity/ioc.h"
29 : #include "rcommand/commandable.h"
30 : #include "rcommand/icommanddispatcher.h"
31 : #include "actions/actionable.h"
32 : #include "actions/iactionsdispatcher.h"
33 : #include "async/asyncable.h"
34 : #include "ui/imainwindow.h"
35 : #include "interactive/iinteractive.h"
36 :
37 : #include "../inavigationcontroller.h"
38 :
39 : namespace muse::ui {
40 : class NavigationController : public QObject, public INavigationController, public Contextable, public async::Asyncable,
41 : public rcommand::Commandable, public actions::Actionable
42 : {
43 : public:
44 : ContextInject<rcommand::ICommandDispatcher> dispatcher = { this };
45 : ContextInject<actions::IActionsDispatcher> actionsDispatcher = { this };
46 : ContextInject<IInteractive> interactive = { this };
47 : ContextInject<IMainWindow> mainWindow = { this };
48 :
49 : public:
50 32 : NavigationController(const modularity::ContextPtr& iocCtx)
51 32 : : Contextable(iocCtx) {}
52 :
53 : enum MoveDirection {
54 : First = 0,
55 : Last,
56 : Right,
57 : Left,
58 : Up,
59 : Down
60 : };
61 :
62 : void reg(INavigationSection* section) override;
63 : void unreg(INavigationSection* section) override;
64 :
65 : bool requestActivateByName(const std::string& section, const std::string& panel, const std::string& controlName) override;
66 : bool requestActivateByIndex(const std::string& section, const std::string& panel, const INavigation::Index& controlIndex) override;
67 :
68 : INavigationSection* activeSection() const override;
69 : INavigationPanel* activePanel() const override;
70 : INavigationControl* activeControl() const override;
71 :
72 : const std::set<INavigationSection*>& sections() const override;
73 : const INavigationSection* findSection(const std::string& sectionName) const override;
74 : const INavigationPanel* findPanel(const std::string& sectionName, const std::string& panelName) const override;
75 : const INavigationControl* findControl(const std::string& sectionName, const std::string& panelName,
76 : const std::string& controlName) const override;
77 :
78 : void setDefaultNavigationControl(INavigationControl* control) override;
79 : void setPrioritySection(INavigationSection* section) override;
80 :
81 : void resetNavigation() override;
82 :
83 : async::Notification navigationChanged() const override;
84 :
85 : bool isHighlight() const override;
86 : void setIsHighlight(bool isHighlight) override;
87 : async::Notification highlightChanged() const override;
88 :
89 : void setIsResetOnMousePress(bool arg) override;
90 :
91 : void dump() const override;
92 :
93 : void init();
94 :
95 : private:
96 :
97 : enum class NavigationType {
98 : NextSection,
99 : PrevSection,
100 : PrevSectionActiveLastPanel,
101 : NextPanel,
102 : PrevPanel,
103 : Left,
104 : Right,
105 : Up,
106 : Down,
107 : FirstControl,
108 : LastControl,
109 : NextRowControl,
110 : PrevRowControl
111 : };
112 :
113 : bool eventFilter(QObject* watched, QEvent* event) override;
114 :
115 : void navigateTo(NavigationType type);
116 :
117 : void goToNextSection();
118 : void goToPrevSection(bool isActivateLastPanel = false);
119 : void goToNextPanel();
120 : void goToPrevPanel();
121 :
122 : void goToFirstControl();
123 : void goToLastControl();
124 : void goToNextRowControl();
125 : void goToPrevRowControl();
126 :
127 : void goToControl(MoveDirection direction, INavigationPanel* activePanel = nullptr);
128 :
129 : void onLeft();
130 : void onRight();
131 : void onUp();
132 : void onDown();
133 : void onEscape();
134 :
135 : void doTriggerControl();
136 : void onActiveRequested(INavigationSection* sect, INavigationPanel* panel, INavigationControl* ctrl, bool force = false);
137 :
138 : void doActivateSection(INavigationSection* sect, bool isActivateLastPanel = false);
139 : void doDeactivateSection(INavigationSection* sect);
140 : void doActivatePanel(INavigationPanel* panel);
141 : void doDeactivatePanel(INavigationPanel* panel);
142 : void doActivateControl(INavigationControl* ctrl);
143 : void doDeactivateControl(INavigationControl* ctrl);
144 :
145 : void doActivateFirst();
146 : void doActivateLast();
147 :
148 : INavigationSection* takePrioritySection(const INavigationSection* activeSec);
149 :
150 : void saveLastActiveControl(INavigationSection* prioritySec);
151 : void restoreLastActiveControl(INavigationSection* prioritySec);
152 : INavigationControl* takeLastActiveControl();
153 :
154 : void resetIfNeed(QObject* watched);
155 :
156 : std::set<INavigationSection*> m_sections;
157 : async::Notification m_navigationChanged;
158 : async::Notification m_highlightChanged;
159 :
160 : INavigationControl* m_defaultNavigationControl = nullptr;
161 : INavigationSection* m_prioritySection = nullptr;
162 : INavigationControl* m_lastActiveControl = nullptr;
163 :
164 : bool m_isHighlight = false;
165 :
166 : bool m_isResetOnMousePress = true;
167 : };
168 : }
|