Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2025 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 : #pragma once
23 :
24 : #include "../inotationcommandscontroller.h"
25 :
26 : #include "types/ret.h"
27 : #include "async/asyncable.h"
28 : #include "rcommand/commandable.h"
29 :
30 : #include "modularity/ioc.h"
31 : #include "interactive/iinteractive.h"
32 : #include "rcommand/commandtypes.h"
33 : #include "rcommand/icommandsstate.h"
34 : #include "rcommand/icommanddispatcher.h"
35 : #include "project/iprojectsession.h"
36 : #include "playback/iplaybackcontroller.h"
37 : #include "engraving/iengravingconfiguration.h"
38 : #include "notation/inotationconfiguration.h"
39 : #include "notationscene/inotationsceneconfiguration.h"
40 :
41 : #include "notation/inotation_fwd.h"
42 : #include "notation/notationtypes.h"
43 :
44 : #include "inotationviewcontroller.h"
45 : #include "notationcommands.h"
46 :
47 : namespace mu::notation {
48 : class NotationActionController : public INotationCommandsController, public muse::rcommand::Commandable, public muse::async::Asyncable,
49 : public muse::Contextable
50 : {
51 : muse::GlobalInject<INotationConfiguration> configuration;
52 : muse::GlobalInject<INotationSceneConfiguration> sceneConfiguration;
53 : muse::GlobalInject<engraving::IEngravingConfiguration> engravingConfiguration;
54 : muse::ContextInject<muse::rcommand::ICommandDispatcher> commandDispatcher = { this };
55 : muse::ContextInject<muse::rcommand::ICommandsState> commandsState = { this };
56 : muse::ContextInject<project::IProjectSession> projectSession = { this };
57 : muse::ContextInject<muse::IInteractive> interactive = { this };
58 : muse::ContextInject<playback::IPlaybackController> playbackController = { this };
59 :
60 : public:
61 :
62 0 : NotationActionController(const muse::modularity::ContextPtr& iocCtx)
63 0 : : muse::Contextable(iocCtx) {}
64 :
65 : void init();
66 :
67 : void setViewController(INotationViewController* controller) override;
68 : INotationViewController* viewController() const override;
69 :
70 : bool hasSelection() const override;
71 : bool isSingleSelection() const override;
72 : bool isRangeSelection() const override;
73 : muse::async::Notification selectionChanged() const override;
74 : bool selectionHasTie() const override;
75 : bool selectionHasLaissezVib() const override;
76 : bool selectionHasSlur() const override;
77 :
78 : bool canUndo() const override;
79 : bool canRedo() const override;
80 : muse::async::Notification stackChanged() const override;
81 :
82 : bool isTextEditing() const override;
83 : bool isLyricsEditing() const override;
84 : muse::async::Channel<bool> textEditingChanged() const override;
85 :
86 : bool isNoteInputAllowed() const override;
87 : muse::async::Channel<bool> isNoteInputAllowedChanged() const override;
88 :
89 : muse::async::Notification noteInputStateChanged() const override;
90 : bool isNoteInputMode() const override;
91 : NoteInputMethod noteInputMethod() const override;
92 : engraving::DurationType currentDurationType() const override;
93 : int currentDotCount() const override;
94 : bool currentIsRest() const override;
95 : engraving::AccidentalType currentAccidentalType() const override;
96 : std::set<engraving::SymId> currentArticulations() const override;
97 : engraving::voice_idx_t currentVoice() const override;
98 :
99 : bool isNoteInputActionAllowed() const override;
100 : bool isNoteOrRestSelected() const override;
101 : bool isHairpinSelected() const override;
102 : bool isMoveSelectionAvailable(MoveSelectionType type) const override;
103 :
104 : bool isToggleLayoutBreakAvailable() const override;
105 :
106 : ScoreConfig scoreConfig() const override;
107 : muse::async::Channel<ScoreConfigType> scoreConfigChanged() const override;
108 :
109 : INotationStylePtr notationStyle() const override;
110 : muse::async::Notification notationStyleChanged() const override;
111 :
112 : bool isTablatureStaff() const override;
113 :
114 : INotationAutomationPtr automation() const;
115 :
116 : bool isAutomationModeEnabled() const override;
117 : muse::async::Notification automationModeEnabledChanged() const override;
118 :
119 : bool isDebuggingCommandEnabled(const muse::rcommand::Command& command) const override;
120 : muse::async::Notification debuggingOptionsChanged() const override;
121 :
122 : muse::async::Notification currentNotationChanged() const;
123 :
124 : INotationNoteInputPtr currentNotationNoteInput() const;
125 : INotationInteractionPtr currentNotationInteraction() const;
126 : INotationUndoStackPtr currentNotationUndoStack() const;
127 :
128 : IMasterNotationPtr currentMasterNotation() const;
129 : muse::async::Notification currentMasterNotationChanged() const;
130 :
131 : private:
132 : INotationPtr currentNotation() const;
133 : INotationElementsPtr currentNotationElements() const;
134 : INotationSelectionPtr currentNotationSelection() const;
135 : INotationMidiInputPtr currentNotationMidiInput() const;
136 :
137 : mu::engraving::Score* currentNotationScore() const;
138 :
139 : void toggleNoteInput(NoteInputMethod method);
140 : void toggleNoteInputInsert();
141 : muse::RetVal<GetNoteInputStateCommand::Output> getNoteInputState() const;
142 :
143 : muse::Ret flipSelection();
144 :
145 : muse::Ret addNote(const AddNoteCommand& command);
146 : void addNote(NoteName noteName, NoteAddingMode addingMode);
147 : muse::Ret addDrumNote(const muse::rcommand::Params& params);
148 : void doAddNote(const NoteInputParams& params, const NoteAddingMode& addingMode);
149 : void setDuration(engraving::DurationType duration);
150 : void toggleRest();
151 : void toggleDots(int dots);
152 : muse::Ret putNote(const muse::rcommand::Params& params);
153 : muse::Ret removeNote(const muse::rcommand::Params& params);
154 : void increaseDecreaseDuration(int steps, bool stepByDots);
155 : void realtimeAdvance();
156 :
157 : void toggleAccidental(engraving::AccidentalType type);
158 : void toggleArticulation(SymbolId articulationSymbolId);
159 :
160 : muse::Ret putTuplet(const muse::rcommand::Params& params);
161 : void putTuplet(const TupletOptions& options);
162 : void putTuplet(int tupletCount);
163 :
164 : muse::Ret moveWithRet(MoveDirection direction, bool quickly = false);
165 : void move(MoveDirection direction, bool quickly = false);
166 : void moveInputNotes(bool up, PitchMode mode);
167 : void movePitchDiatonic(MoveDirection direction, bool);
168 :
169 : void changeVoice(voice_idx_t voiceIndex);
170 : void swapVoices(voice_idx_t voiceIndex1, voice_idx_t voiceIndex2);
171 :
172 : void cutSelection();
173 : void repeatSelection();
174 : void addTie();
175 : void addLaissezVib();
176 : void addSlur();
177 : void addHammerOnPullOff();
178 : void addFret(int num);
179 :
180 : void insertClef(mu::engraving::ClefType type);
181 :
182 : void addText(TextStyleType type);
183 : void addDynamic();
184 : void addImage();
185 : void addFiguredBass();
186 : void addGuitarBend(GuitarBendType bendType);
187 : void addFretboardDiagram();
188 :
189 : void openSelectionMoreOptions();
190 :
191 : muse::Ret startEditSelectedElement(const muse::rcommand::Params& params);
192 : muse::Ret startEditSelectedText(const muse::rcommand::Params& params);
193 :
194 : muse::Ret addMeasures(const muse::rcommand::Params& params, AddBoxesTarget target);
195 : void addBoxes(BoxType boxType, int count, AddBoxesTarget target);
196 :
197 : void addStretch(qreal value);
198 :
199 : void unrollRepeats();
200 :
201 : void toggleMmrest();
202 : void toggleHideEmpty();
203 : void addFullMeasureRest();
204 :
205 : void resetState();
206 : void resetStretch();
207 : void resetBeamMode();
208 :
209 : muse::Ret openEditStyleDialog(const muse::rcommand::Params& params);
210 : void openPageSettingsDialog();
211 : void openStaffProperties();
212 : void openEditStringsDialog();
213 : void openBreaksDialog();
214 : void openTransposeDialog();
215 : void openPartsDialog();
216 : void openTupletOtherDialog();
217 : void openStaffTextPropertiesDialog();
218 : void openMeasurePropertiesDialog();
219 : void openEditGridSizeDialog();
220 : void openRealizeChordSymbolsDialog();
221 : muse::io::path_t selectStyleFile(bool forLoad);
222 : void loadStyle();
223 : void saveStyle();
224 :
225 : void toggleScoreConfig(ScoreConfigType configType);
226 : void toggleConcertPitch();
227 :
228 : void seekAndPlaySelectedElement(bool playChord = true);
229 : void seekSelectedElement();
230 : void playSelectedElement(bool playChord = true);
231 :
232 : bool isEditingText() const;
233 : bool isEditingElement() const;
234 : bool isNotEditingElement() const;
235 :
236 : void pasteSelection(PastingType type = PastingType::Default);
237 : Fraction resolvePastingScale(const INotationInteractionPtr& interaction, PastingType type) const;
238 :
239 : enum class TextNavigationType {
240 : NearNoteOrRest,
241 : NearBeat,
242 : Fraction
243 : };
244 :
245 : bool textNavigationAvailable() const;
246 : bool textNavigationByBeatsAvailable() const;
247 : bool textNavigationByFractionAvailable() const;
248 : bool resolveTextNavigationAvailable(TextNavigationType type = TextNavigationType::NearNoteOrRest) const;
249 :
250 : muse::Ret nextTextElement();
251 : muse::Ret prevTextElement();
252 : muse::Ret nextWord();
253 : void nextBeatTextElement();
254 : void prevBeatTextElement();
255 : void navigateToTextElement(MoveDirection direction, bool nearNoteOrRest = false, bool moveOnly = true);
256 : void navigateToTextItemByFraction(const Fraction& fraction);
257 : void navigateToTextElementInNearMeasure(MoveDirection direction);
258 :
259 : bool toggleNoteInputAllowed() const;
260 : void startNoteInput();
261 :
262 : mu::engraving::EngravingItem* selectedElement() const;
263 :
264 : const mu::engraving::Harmony* editedChordSymbol() const;
265 :
266 : bool elementHasPopup(const EngravingItem* e) const;
267 :
268 : void checkForScoreCorruptions();
269 :
270 : void toggleAutomation();
271 : muse::Ret selectAutomationType(const muse::rcommand::Params& params);
272 :
273 : // commands
274 : template<muse::rcommand::TypedCommand C>
275 : void registerCommand(muse::Ret (NotationActionController::*)());
276 : template<muse::rcommand::TypedCommand C>
277 : void registerCommand(muse::Ret (NotationActionController::*)(const C&));
278 : template<muse::rcommand::HasOutput C>
279 : void registerGetCommand(muse::RetVal<typename C::Output>(NotationActionController::*)() const);
280 : template<muse::rcommand::HasOutput C>
281 : void registerGetCommand(muse::RetVal<typename C::Output>(NotationActionController::*)(const C&) const);
282 :
283 : void registerCommand(const muse::rcommand::Command&, std::function<void()>);
284 : void registerCommand(const muse::rcommand::Command&, std::function<void()>, bool (NotationActionController::*)() const);
285 : void registerCommandWithParams(const muse::rcommand::Command&, std::function<muse::Ret(const muse::rcommand::Params&)>);
286 : void registerCommand(const muse::rcommand::Command&, void (NotationActionController::*)());
287 : void registerCommand(const muse::rcommand::Command&, void (NotationActionController::*)(), bool (NotationActionController::*)() const);
288 : void registerCommandWithParams(const muse::rcommand::Command&, muse::Ret (NotationActionController::*)(const muse::rcommand::Params&));
289 :
290 : void registerCommand(const muse::rcommand::Command&, void (INotationInteraction::*)(), PlayMode = PlayMode::NoPlay,
291 : bool (NotationActionController::*)() const = nullptr);
292 : template<typename P1>
293 : void registerCommand(const muse::rcommand::Command&, void (INotationInteraction::*)(P1), P1, PlayMode = PlayMode::NoPlay,
294 : bool (NotationActionController::*)() const = nullptr);
295 : void registerNoteInputCommand(const muse::rcommand::Command& command, NoteInputMethod method);
296 : void registerNoteCommand(const muse::rcommand::Command&, NoteName, NoteAddingMode addingMode = NoteAddingMode::NextChord);
297 : void registerNavigationByFractionCommand(const muse::rcommand::Command&, const Fraction&);
298 :
299 : void registerGetCommand(const muse::rcommand::Command&, std::function<muse::RetVal<muse::rcommand::Params>()>);
300 : void registerGetCommand(const muse::rcommand::Command&, muse::RetVal<muse::rcommand::Params>(NotationActionController::*)() const);
301 :
302 : muse::Ret select(const muse::rcommand::Params& params);
303 : void select(SelectionTarget target, PlayMode playMode = PlayMode::NoPlay);
304 :
305 : void registerViewCommand(const muse::rcommand::Command&, void (INotationViewController::*)());
306 : template<typename P1>
307 : void registerViewCommand(const muse::rcommand::Command&, void (INotationViewController::*)(P1), P1);
308 :
309 : muse::Ret zoomToPercent(const muse::rcommand::Params& params);
310 :
311 : muse::Ret setPianoKeyboardNumberOfKeys(const muse::rcommand::Params& params);
312 :
313 : INotationViewController* m_viewController = nullptr;
314 :
315 : muse::async::Channel<bool> m_hasSelectionChanged;
316 : muse::async::Channel<bool> m_textEditingChanged;
317 : muse::async::Notification m_stackChanged;
318 : muse::async::Notification m_selectionChanged;
319 :
320 : muse::async::Channel<bool> m_isNoteInputAllowedChanged;
321 : muse::async::Notification m_noteInputStateChanged;
322 :
323 : muse::async::Channel<ScoreConfigType> m_scoreConfigChanged;
324 : muse::async::Notification m_currentNotationStyleChanged;
325 : muse::async::Notification m_automationModeEnabledChanged;
326 : };
327 : }
|