|
3 | 3 |
|
4 | 4 | //============================================================================== |
5 | 5 | PluginEditor::PluginEditor(PluginProcessor& p) |
6 | | - : AudioProcessorEditor(&p) |
7 | | - , p(p) |
8 | | - , sizeFactor(p.scaleFactor) |
9 | | - , mainLayout({ 1.0 }, { 1.0 }) |
10 | | - , compositor("OscilloScoPe", mainLayout, p.apvts, p.properties, sizeFactor) |
11 | | - , compositorAttached(true) |
| 6 | + : dmt::app::AbstractPluginEditor( |
| 7 | + p, |
| 8 | + "Oscilloscope", |
| 9 | + 800, |
| 10 | + 400, |
| 11 | + [&p](dmt::gui::window::Layout& layout) { |
| 12 | + layout.addPanel<dmt::gui::panel::OscilloscopePanel<float>>( |
| 13 | + 0, 0, 1, 1, p.apvts, p.oscilloscopeBuffer); |
| 14 | + }) |
12 | 15 | { |
13 | | - if (OS_IS_WINDOWS) { |
14 | | - setResizable(true, true); |
15 | | - } |
16 | | - |
17 | | - if (OS_IS_DARWIN) { |
18 | | - setResizable(true, true); |
19 | | - } |
20 | | - |
21 | | - if (OS_IS_LINUX) { |
22 | | - openGLContext.setComponentPaintingEnabled(true); |
23 | | - openGLContext.setContinuousRepainting(false); |
24 | | - openGLContext.attachTo(*getTopLevelComponent()); |
25 | | - setResizable(true, true); |
26 | | - } |
27 | | - // Add Panel to Layout |
28 | | - mainLayout.addPanel<dmt::gui::panel::OscilloscopePanel<float>>( |
29 | | - 0, 0, 1, 1, p.oscilloscopeFifo, p.apvts); |
30 | | - |
31 | | - setConstraints(baseWidth, baseHeight + headerHeight); |
32 | | - addAndMakeVisible(compositor); |
33 | | - setResizable(true, true); |
34 | | - |
35 | | - const auto startWidth = baseWidth * sizeFactor; |
36 | | - const auto startHeight = (baseHeight + headerHeight) * sizeFactor; |
37 | | - setSize(startWidth, startHeight); |
38 | | - |
39 | | - // Set the callback for header visibility changes |
40 | | - compositor.setHeaderVisibilityCallback([this](bool isHeaderVisible) { |
41 | | - handleHeaderVisibilityChange(isHeaderVisible); |
42 | | - }); |
43 | 16 | } |
44 | 17 |
|
45 | | -void |
46 | | -PluginEditor::handleHeaderVisibilityChange(bool isHeaderVisible) |
47 | | -{ |
48 | | - const int adjustedHeight = |
49 | | - isHeaderVisible ? baseHeight + headerHeight : baseHeight; |
50 | | - setConstraints(baseWidth, adjustedHeight); |
51 | | - setSize(baseWidth * sizeFactor, adjustedHeight * sizeFactor); |
52 | | -} |
53 | 18 | //============================================================================== |
54 | 19 | PluginEditor::~PluginEditor() {} |
55 | | - |
56 | | -//============================================================================== |
57 | | -void |
58 | | -PluginEditor::paint(juce::Graphics& g) |
59 | | -{ |
60 | | - TRACER("PluginEditor::paint"); |
61 | | - |
62 | | - // Just painting the background |
63 | | - g.fillAll(dmt::Settings::Window::backgroundColour); |
64 | | - |
65 | | - if (!compositorAttached && compositorSnapshot.isValid()) { |
66 | | - // Draw the last compositor snapshot, scaled to fit |
67 | | - auto bounds = getLocalBounds().toFloat(); |
68 | | - g.drawImage( |
69 | | - compositorSnapshot, bounds, juce::RectanglePlacement::stretchToFit); |
70 | | - return; |
71 | | - } |
72 | | -} |
73 | | - |
74 | | -//============================================================================== |
75 | | -void |
76 | | -PluginEditor::setConstraints(int width, int height) |
77 | | -{ |
78 | | - if (auto* constrainer = this->getConstrainer()) { |
79 | | - const auto aspectRatio = (double)width / (double)height; |
80 | | - constrainer->setFixedAspectRatio(aspectRatio); |
81 | | - const auto minWidth = width / 2; |
82 | | - const auto minHeight = height / 2; |
83 | | - const auto maxWidth = width * 2; |
84 | | - const auto maxHeight = height * 2; |
85 | | - constrainer->setSizeLimits(minWidth, minHeight, maxWidth, maxHeight); |
86 | | - } else { |
87 | | - jassertfalse; // Constrainer not set |
88 | | - } |
89 | | -} |
90 | | - |
91 | | -//============================================================================== |
92 | | -void |
93 | | -PluginEditor::resized() |
94 | | -{ |
95 | | - TRACER("PluginEditor::resized"); |
96 | | - |
97 | | - // Set the global size |
98 | | - const int currentHeight = getHeight(); |
99 | | - const float newSize = |
100 | | - (float)currentHeight / |
101 | | - (compositor.isHeaderVisible() ? baseHeight + headerHeight : baseHeight); |
102 | | - |
103 | | - // Make sure the size makes sense |
104 | | - if (newSize <= 0.0f || std::isinf(newSize)) { |
105 | | - jassertfalse; |
106 | | - } |
107 | | - |
108 | | - // Update the processor's scale factor |
109 | | - sizeFactor = newSize; |
110 | | - p.setScaleFactor(newSize); |
111 | | - |
112 | | - // Debounced resizing logic |
113 | | - static bool firstDraw = true; |
114 | | - if (firstDraw) { |
115 | | - // On first draw, skip debounce and just layout normally |
116 | | - compositor.setBounds(getLocalBounds()); |
117 | | - firstDraw = false; |
118 | | - return; |
119 | | - } |
120 | | - detachCompositorForResize(); |
121 | | -} |
122 | | - |
123 | | -void |
124 | | -PluginEditor::detachCompositorForResize() |
125 | | -{ |
126 | | - if (compositorAttached) { |
127 | | - // Take a snapshot before detaching |
128 | | - updateCompositorSnapshot(); |
129 | | - |
130 | | - // Remove compositor from view |
131 | | - removeChildComponent(&compositor); |
132 | | - compositorAttached = false; |
133 | | - } |
134 | | - |
135 | | - // Restart debounce timer (100ms) |
136 | | - stopTimer(); |
137 | | - startTimer(100); |
138 | | -} |
139 | | - |
140 | | -void |
141 | | -PluginEditor::attachCompositorAfterResize() |
142 | | -{ |
143 | | - if (!compositorAttached) { |
144 | | - // Snap to the correct aspect ratio, considering header visibility |
145 | | - auto bounds = getLocalBounds(); |
146 | | - bool headerVisible = compositor.isHeaderVisible(); |
147 | | - int aspectHeight = headerVisible ? (baseHeight + headerHeight) : baseHeight; |
148 | | - const double aspect = (double)baseWidth / (double)aspectHeight; |
149 | | - int w = bounds.getWidth(); |
150 | | - int h = bounds.getHeight(); |
151 | | - double currentAspect = (double)w / (double)h; |
152 | | - |
153 | | - if (currentAspect > aspect) { |
154 | | - // Too wide, adjust width |
155 | | - w = static_cast<int>(h * aspect); |
156 | | - } else if (currentAspect < aspect) { |
157 | | - // Too tall, adjust height |
158 | | - h = static_cast<int>(w / aspect); |
159 | | - } |
160 | | - setSize(w, h); |
161 | | - |
162 | | - // Set compositor bounds to fill the editor |
163 | | - addAndMakeVisible(compositor); |
164 | | - compositor.setBounds(getLocalBounds()); |
165 | | - compositorAttached = true; |
166 | | - repaint(); |
167 | | - } |
168 | | -} |
169 | | - |
170 | | -void |
171 | | -PluginEditor::updateCompositorSnapshot() |
172 | | -{ |
173 | | - // Render compositor to an image at its current size |
174 | | - if (getWidth() > 0 && getHeight() > 0) { |
175 | | - compositorSnapshot = |
176 | | - juce::Image(juce::Image::ARGB, getWidth(), getHeight(), true); |
177 | | - juce::Graphics g(compositorSnapshot); |
178 | | - compositor.paintEntireComponent(g, true); |
179 | | - } |
180 | | -} |
181 | | - |
182 | | -void |
183 | | -PluginEditor::timerCallback() |
184 | | -{ |
185 | | - // Timer expired: reattach compositor and repaint |
186 | | - stopTimer(); |
187 | | - attachCompositorAfterResize(); |
188 | | - repaint(); |
189 | | -} |
0 commit comments