tracktion-engine 3.0-10-g034fdde4aa5
Tracktion Engine — High level data model for audio applications

« « « Anklang Documentation
Loading...
Searching...
No Matches
tracktion_UIBehaviour.cpp
Go to the documentation of this file.
1 /*
2 ,--. ,--. ,--. ,--.
3 ,-' '-.,--.--.,--,--.,---.| |,-.,-' '-.`--' ,---. ,--,--, Copyright 2024
4 '-. .-'| .--' ,-. | .--'| /'-. .-',--.| .-. || \ Tracktion Software
5 | | | | \ '-' \ `--.| \ \ | | | |' '-' '| || | Corporation
6 `---' `--' `--`--'`---'`--'`--' `---' `--' `---' `--''--' www.tracktion.com
7
8 Tracktion Engine uses a GPL/commercial licence - see LICENCE.md for details.
9*/
10
11namespace tracktion { inline namespace engine
12{
13
14bool UIBehaviour::paste (const Clipboard& clipboard)
15{
16 if (auto content = clipboard.getContent())
17 {
18 if (auto sm = getCurrentlyFocusedSelectionManager())
19 {
20 if (sm->pasteSelected())
21 return true;
22
23 if (sm->insertPoint != nullptr && sm->getEdit() != nullptr)
24 return content->pasteIntoEdit (*sm->getEdit(), *sm->insertPoint, sm);
25 }
26 }
27
28 return false;
29}
30
31//==============================================================================
32void UIBehaviour::showWarningAlert (const juce::String& title, const juce::String& message)
33{
34 juce::AlertWindow::showMessageBoxAsync (juce::AlertWindow::WarningIcon, title, message);
35}
36
38 const juce::String& ok, const juce::String& cancel)
39{
40 #if JUCE_MODAL_LOOPS_PERMITTED
41 return juce::AlertWindow::showOkCancelBox (juce::AlertWindow::QuestionIcon, title, message, ok, cancel);
42 #else
43 jassertfalse; // These methods are currently unsupported in non-modal mode and calls to them from within the Engine will be replaced
44 return true;
45 #endif
46}
47
49 const juce::String& yes, const juce::String& no, const juce::String& cancel)
50{
51 #if JUCE_MODAL_LOOPS_PERMITTED
52 return juce::AlertWindow::showYesNoCancelBox (juce::AlertWindow::QuestionIcon, title, message, yes, no, cancel);
53 #else
54 jassertfalse; // These methods are currently unsupported in non-modal mode and calls to them from within the Engine will be replaced
55 return 1;
56 #endif
57}
58
60{
61 if (auto c = juce::Desktop::getInstance().getMainMouseSource().getComponentUnderMouse())
62 {
63 auto bmc = new juce::BubbleMessageComponent();
64 bmc->addToDesktop (0);
65 bmc->showAt (c, juce::AttributedString (message), 2000, true, true);
66 }
67}
68
70{
71 showInfoMessage (message);
72}
73
74//==============================================================================
75void UIBehaviour::nudgeSelectedClips (TimecodeSnapType snapType, const juce::String& commandDesc,
76 SelectionManager& sm, const juce::Array<Clip*>& clips, bool automationLocked)
77{
78 jassert (clips.size() > 0);
79 auto& ed = clips.getFirst()->edit;
81
82 TimeDuration delta;
83 int trackDelta = 0;
84
85 if (commandDesc.contains ("right")) delta = TimeDuration::fromSeconds (0.00001);
86 else if (commandDesc.contains ("left")) delta = TimeDuration::fromSeconds (-0.00001);
87 else if (commandDesc.contains ("up")) trackDelta = -1;
88 else if (commandDesc.contains ("down")) trackDelta = 1;
89
90 if (trackDelta != 0)
91 {
92 int minTrack = 0xffff;
93 int maxTrack = 0;
94 auto allTracks = getAllTracks (ed);
95
96 for (int i = clips.size(); --i >= 0;)
97 {
98 minTrack = std::min (minTrack, allTracks.indexOf (clips.getUnchecked (i)->getTrack()));
99 maxTrack = std::max (maxTrack, allTracks.indexOf (clips.getUnchecked (i)->getTrack()));
100 }
101
102 if (trackDelta < 0)
103 {
104 if (minTrack == 0)
105 trackDelta = 0;
106 }
107 else
108 {
109 if (allTracks.size() - maxTrack < 2)
110 trackDelta = 0;
111 }
112
113 if (trackDelta != 0)
114 {
116
117 if (automationLocked)
118 {
119 for (auto&& clip : clips)
120 {
121 TrackAutomationSection ts (*clip);
122
123 if (auto t = allTracks [allTracks.indexOf (clip->getTrack()) + trackDelta])
124 ts.dst = t;
125
126 sections.add (ts);
127 }
128 }
129
130 for (int i = clips.size(); --i >= 0;)
131 if (auto targetTrack = allTracks[allTracks.indexOf (clips.getUnchecked (i)->getTrack()) + trackDelta])
132 if (auto ct = dynamic_cast<ClipTrack*> (targetTrack))
133 clips.getUnchecked (i)->moveTo (*ct);
134
135 if (sections.size())
136 moveAutomation (sections, {}, false);
137 }
138 }
139 else if (delta != TimeDuration())
140 {
142
143 if (automationLocked)
144 for (auto&& clip : clips)
145 sections.add (TrackAutomationSection (*clip));
146
147 if (auto first = clips.getFirst())
148 {
149 // if there's one clip, move it to the nearest interval, else
150 // move all the clips by the same amount
151 auto origClip1Start = first->getPosition().getStart();
152 auto clipStart = origClip1Start;
153
154 if (delta > TimeDuration())
155 first->setStart (snapType.roundTimeUp (origClip1Start + delta, ed.tempoSequence), false, true);
156 else
157 first->setStart (snapType.roundTimeDown (origClip1Start + delta, ed.tempoSequence), false, true);
158
159 if (clips.size() > 1)
160 {
161 delta = first->getPosition().getStart() - origClip1Start;
162
163 for (int i = clips.size(); --i > 0;)
164 clips[i]->setStart (clips.getUnchecked (i)->getPosition().getStart() + delta, false, true);
165 }
166
167 if (sections.size())
168 moveAutomation (sections, first->getPosition().getStart() - clipStart, false);
169 }
170 else
171 {
173 }
174 }
175}
176
177void UIBehaviour::nudgeSelected (TimecodeSnapType snapType, const juce::String& commandDesc, bool automationLocked)
178{
179 if (auto sm = getCurrentlyFocusedSelectionManager())
180 {
181 auto clips = sm->getItemsOfType<Clip>();
182
183 for (auto cc : sm->getItemsOfType<CollectionClip>())
184 clips.addArray (cc->getClips());
185
186 clips = getAssociatedClipsToEdit (clips).getItemsOfType<Clip>();
187
188 if (clips.size() > 0)
189 {
190 nudgeSelectedClips (snapType, commandDesc, *sm, clips, automationLocked);
191 }
192 else
193 {
194 if (auto s = sm->getFirstItemOfType<SelectedMidiEvents>())
195 {
196 int leftRight = 0, upDown = 0;
197
198 if (commandDesc.contains ("right")) leftRight = 1;
199 else if (commandDesc.contains ("left")) leftRight = -1;
200 else if (commandDesc.contains ("up")) upDown = 1;
201 else if (commandDesc.contains ("down")) upDown = -1;
202
203 s->nudge (snapType, leftRight, upDown);
204 }
205 }
206 }
207}
208
209void UIBehaviour::nudgeSelected (const juce::String& commandDesc)
210{
211 if (auto edit = getCurrentlyFocusedEdit())
212 nudgeSelected (edit->getTransport().getSnapType(), commandDesc, false);
213}
214
215//==============================================================================
220
222{
223 return e.getTransport().getLoopRange();
224}
225
227{
228 p.windowState->recreateWindowIfShowing();
229}
230
231}} // namespace tracktion { inline namespace engine
static int JUCE_CALLTYPE showYesNoCancelBox(MessageBoxIconType iconType, const String &title, const String &message, const String &button1Text, const String &button2Text, const String &button3Text, Component *associatedComponent, ModalComponentManager::Callback *callback)
static bool JUCE_CALLTYPE showOkCancelBox(MessageBoxIconType iconType, const String &title, const String &message, const String &button1Text, const String &button2Text, Component *associatedComponent, ModalComponentManager::Callback *callback)
static void JUCE_CALLTYPE showMessageBoxAsync(MessageBoxIconType iconType, const String &title, const String &message, const String &buttonText=String(), Component *associatedComponent=nullptr, ModalComponentManager::Callback *callback=nullptr)
ElementType getUnchecked(int index) const
int size() const noexcept
ElementType getFirst() const noexcept
void add(const ElementType &newElement)
static Desktop &JUCE_CALLTYPE getInstance()
bool contains(StringRef text) const noexcept
The Tracktion Edit class!
TransportControl & getTransport() const noexcept
Returns the TransportControl which is used to stop/stop/position playback and recording.
Manages a list of items that are currently selected.
void keepSelectedObjectsOnScreen()
Scrolls whatever is necessary to keep the selected stuff visible.
TimePosition getPosition() const
Returns the current transport position.
TimeRange getLoopRange() const noexcept
Returns the loop range.
virtual bool showOkCancelAlertBox(const juce::String &title, const juce::String &message, const juce::String &ok={}, const juce::String &cancel={})
Should display a dismissable alert window.
virtual void recreatePluginWindowContentAsync(Plugin &)
Should trigger an asynchronous refresh of any editor components showing for this plugin.
virtual void showInfoMessage(const juce::String &message)
Should display a temporary information message, usually in the same place.
virtual SelectableList getAssociatedClipsToEdit(const SelectableList &items)
If your UI has the concept of edit groups, you should return an expanded list of selected items that ...
virtual TimeRange getEditingRange(Edit &)
Should return the range which used be used for edit operations such as coping or deleting.
virtual void showWarningAlert(const juce::String &title, const juce::String &message)
Should display a dismissable alert window.
virtual int showYesNoCancelAlertBox(const juce::String &title, const juce::String &message, const juce::String &yes={}, const juce::String &no={}, const juce::String &cancel={})
Should display a dismissable alert window.
virtual void showWarningMessage(const juce::String &message)
Should display a temporary warning message.
virtual TimePosition getEditingPosition(Edit &)
Should return the position which used be used for edit operations such as splitting.
#define jassert(expression)
#define jassertfalse
T max(T... args)
T min(T... args)
juce::Array< Track * > getAllTracks(const Edit &edit)
Returns all the tracks in an Edit.
void moveAutomation(const juce::Array< TrackAutomationSection > &origSections, TimeDuration offset, bool copy)
Moves a set of automation optionally applying an offset and copying the automation (rather than movin...
Represents a duration in real-life time.
Represents a position in real-life time.