@@ -24,11 +24,6 @@ namespace yup
2424
2525namespace
2626{
27- constexpr float minZoom = 0 .1f ;
28- constexpr float maxZoom = 4 .0f ;
29- constexpr float wireHitDistance = 8 .0f ;
30- constexpr float dragWireThreshold = 4 .0f ;
31-
3227bool endpointsMatch (const AudioGraphEndpoint& a, const AudioGraphEndpoint& b) noexcept
3328{
3429 return a == b;
@@ -46,6 +41,10 @@ AudioGraphNodeView* findNodeViewForEventSource (Component* source) noexcept
4641}
4742} // namespace
4843
44+ // ==============================================================================
45+ const Identifier AudioGraphComponent::Style::backgroundColorId (" audioGraphBackground" );
46+ const Identifier AudioGraphComponent::Style::gridColorId (" audioGraphGrid" );
47+
4948// ==============================================================================
5049AudioGraphComponent::AudioGraphComponent (std::shared_ptr<AudioGraphProcessor> graphIn)
5150 : graph (std::move (graphIn))
@@ -186,6 +185,44 @@ void AudioGraphComponent::setZoom (float newZoom)
186185 repaint ();
187186}
188187
188+ void AudioGraphComponent::setMinZoom (float newMinZoom)
189+ {
190+ const auto clampedMinZoom = jmax (0 .001f , newMinZoom);
191+ if (minZoom == clampedMinZoom)
192+ return ;
193+
194+ minZoom = clampedMinZoom;
195+
196+ if (maxZoom < minZoom)
197+ maxZoom = minZoom;
198+
199+ setZoom (zoom);
200+ }
201+
202+ void AudioGraphComponent::setMaxZoom (float newMaxZoom)
203+ {
204+ const auto clampedMaxZoom = jmax (0 .001f , newMaxZoom);
205+ if (maxZoom == clampedMaxZoom)
206+ return ;
207+
208+ maxZoom = clampedMaxZoom;
209+
210+ if (minZoom > maxZoom)
211+ minZoom = maxZoom;
212+
213+ setZoom (zoom);
214+ }
215+
216+ void AudioGraphComponent::setWireHitDistance (float newWireHitDistance)
217+ {
218+ wireHitDistance = jmax (0 .0f , newWireHitDistance);
219+ }
220+
221+ void AudioGraphComponent::setDragWireThreshold (float newDragWireThreshold)
222+ {
223+ dragWireThreshold = jmax (0 .0f , newDragWireThreshold);
224+ }
225+
189226void AudioGraphComponent::setCanvasOffset (Point<float > offset)
190227{
191228 needsInitialReset = false ;
@@ -206,7 +243,7 @@ void AudioGraphComponent::resetView()
206243
207244 needsInitialReset = false ;
208245 needsInitialZoomToFit = false ;
209- zoom = 1 .0f ;
246+ zoom = jlimit (minZoom, maxZoom, 1 .0f ) ;
210247
211248 centerViewOnNodes ();
212249}
@@ -307,18 +344,8 @@ void AudioGraphComponent::resized()
307344
308345void AudioGraphComponent::paint (Graphics& g)
309346{
310- g.setFillColor (Color (0xff101522 ));
311- g.fillAll ();
312-
313- drawGrid (g);
314-
315- if (graph != nullptr )
316- {
317- for (const auto & connection : graph->getConnections ())
318- drawConnection (g, connection, 1 .0f );
319- }
320-
321- drawPendingWire (g);
347+ if (auto style = ApplicationTheme::findComponentStyle (*this ))
348+ style->paint (g, *ApplicationTheme::getGlobalTheme (), *this );
322349}
323350
324351// ==============================================================================
@@ -773,6 +800,21 @@ Color AudioGraphComponent::getEndpointColor (const AudioGraphEndpoint& endpoint)
773800 return AudioGraphNodeView::getPortKindColor (AudioGraphNodeView::PortKind::audio);
774801}
775802
803+ bool AudioGraphComponent::isPendingWireVisible () const noexcept
804+ {
805+ return activeEndpoint.has_value () && (interaction == Interaction::armedPort || interaction == Interaction::draggingWire);
806+ }
807+
808+ std::optional<AudioGraphEndpoint> AudioGraphComponent::getPendingWireEndpoint () const
809+ {
810+ return activeEndpoint;
811+ }
812+
813+ Point<float > AudioGraphComponent::getPendingWireEndPosition () const noexcept
814+ {
815+ return interaction == Interaction::draggingWire ? pendingWireEnd : lastMouseScreen;
816+ }
817+
776818bool AudioGraphComponent::tryConnect (const AudioGraphEndpoint& first, const AudioGraphEndpoint& second)
777819{
778820 if (graph == nullptr || ! isCompatiblePair (first, second))
@@ -842,87 +884,6 @@ AudioGraphConnection AudioGraphComponent::makeConnection (const AudioGraphEndpoi
842884 : AudioGraphConnection { second, first };
843885}
844886
845- // ==============================================================================
846- void AudioGraphComponent::drawGrid (Graphics& g)
847- {
848- const auto spacing = 24 .0f * zoom;
849- if (spacing < 6 .0f )
850- return ;
851-
852- const auto startX = std::fmod (canvasOffset.getX (), spacing);
853- const auto startY = std::fmod (canvasOffset.getY (), spacing);
854-
855- g.setFillColor (Colors::white.withAlpha (0 .045f ));
856-
857- for (auto x = startX; x < getWidth (); x += spacing)
858- {
859- for (auto y = startY; y < getHeight (); y += spacing)
860- g.fillEllipse (x - 1 .0f , y - 1 .0f , 2 .0f , 2 .0f );
861- }
862- }
863-
864- void AudioGraphComponent::drawConnection (Graphics& g, const AudioGraphConnection& connection, float opacity)
865- {
866- const auto start = getEndpointScreenPosition (connection.source );
867- const auto end = getEndpointScreenPosition (connection.destination );
868-
869- if (! getLocalBounds ().reduced (-200 .0f ).contains (start) && ! getLocalBounds ().reduced (-200 .0f ).contains (end))
870- return ;
871-
872- const auto controlOffset = jmax (60 .0f * zoom, std::abs (end.getX () - start.getX ()) * 0 .5f );
873- const auto cp1 = Point<float > { start.getX () + controlOffset, start.getY () };
874- const auto cp2 = Point<float > { end.getX () - controlOffset, end.getY () };
875-
876- drawBezierHalf (g, start, cp1, cp2, end, getEndpointColor (connection.source ).withMultipliedAlpha (opacity), true );
877- drawBezierHalf (g, start, cp1, cp2, end, getEndpointColor (connection.destination ).withMultipliedAlpha (opacity), false );
878- }
879-
880- void AudioGraphComponent::drawBezierHalf (Graphics& g, Point<float > p0, Point<float > p1, Point<float > p2, Point<float > p3, Color color, bool firstHalf)
881- {
882- const auto p01 = (p0 + p1) * 0 .5f ;
883- const auto p12 = (p1 + p2) * 0 .5f ;
884- const auto p23 = (p2 + p3) * 0 .5f ;
885- const auto p012 = (p01 + p12) * 0 .5f ;
886- const auto p123 = (p12 + p23) * 0 .5f ;
887- const auto midpoint = (p012 + p123) * 0 .5f ;
888-
889- Path path;
890- if (firstHalf)
891- path.moveTo (p0).cubicTo (p01, p012.getX (), p012.getY (), midpoint.getX (), midpoint.getY ());
892- else
893- path.moveTo (midpoint).cubicTo (p123, p23.getX (), p23.getY (), p3.getX (), p3.getY ());
894-
895- g.setStrokeColor (color);
896- g.setStrokeWidth (jmax (1 .5f , 3 .0f * zoom));
897- g.setStrokeCap (StrokeCap::Round);
898- g.strokePath (path);
899- }
900-
901- void AudioGraphComponent::drawPendingWire (Graphics& g)
902- {
903- if (! activeEndpoint.has_value () || (interaction != Interaction::armedPort && interaction != Interaction::draggingWire))
904- return ;
905-
906- const auto start = getEndpointScreenPosition (*activeEndpoint);
907- const auto end = interaction == Interaction::draggingWire ? pendingWireEnd : lastMouseScreen;
908- const auto controlOffset = jmax (60 .0f * zoom, std::abs (end.getX () - start.getX ()) * 0 .5f );
909- const auto cp1 = Point<float > { start.getX () + (activeEndpoint->isSource () ? controlOffset : -controlOffset), start.getY () };
910- const auto cp2 = Point<float > { end.getX () - (activeEndpoint->isSource () ? controlOffset : -controlOffset), end.getY () };
911-
912- Path path;
913- path.moveTo (start).cubicTo (cp1, cp2.getX (), cp2.getY (), end.getX (), end.getY ());
914-
915- g.setStrokeColor (getEndpointColor (*activeEndpoint).withAlpha (0 .55f ));
916- g.setStrokeWidth (jmax (1 .5f , 2 .5f * zoom));
917- g.setStrokeCap (StrokeCap::Round);
918- g.strokePath (path);
919-
920- g.setFillColor (getEndpointColor (*activeEndpoint).withAlpha (0 .20f ));
921- const auto center = getEndpointScreenPosition (*activeEndpoint);
922- const auto radius = 14 .0f * zoom;
923- g.fillEllipse (center.getX () - radius, center.getY () - radius, radius * 2 .0f , radius * 2 .0f );
924- }
925-
926887Point<float > AudioGraphComponent::cubicPoint (Point<float > p0, Point<float > p1, Point<float > p2, Point<float > p3, float t) const noexcept
927888{
928889 const auto u = 1 .0f - t;
0 commit comments