diff --git a/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h b/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h index 00278bf77e..f9c82cce92 100644 --- a/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h +++ b/extras/Projucer/Source/Application/Windows/jucer_SVGPathDataWindowComponent.h @@ -29,13 +29,13 @@ //============================================================================== class SVGPathDataComponent : public Component, - private TextEditor::Listener + public FileDragAndDropTarget, + private TextEditor::Listener, + private Button::Listener + { public: SVGPathDataComponent() - : desc (String(), - "Paste an SVG path string into the top box, and it'll be converted to some C++ " - "code that will load it as a Path object..") { desc.setJustificationType (Justification::centred); addAndMakeVisible (desc); @@ -53,6 +53,15 @@ public: addAndMakeVisible (resultText); userText.setText (getLastText()); + + addAndMakeVisible (copyButton); + copyButton.addListener (this); + } + + void buttonClicked (Button* b) override + { + if (b == ©Button) + SystemClipboard::copyTextToClipboard (resultText.getText()); } void textEditorTextChanged (TextEditor&) override @@ -68,8 +77,12 @@ public: void update() { getLastText() = userText.getText(); + auto text = getLastText().trim().unquoted().trim(); - path = Drawable::parseSVGPath (getLastText().trim().unquoted().trim()); + path = Drawable::parseSVGPath (text); + + if (path.isEmpty()) + path = pathFromPoints (text); String result = "No path generated.. Not a valid SVG path string?"; @@ -96,7 +109,10 @@ public: void resized() override { - Rectangle r (getLocalBounds().reduced (8)); + auto r = getLocalBounds().reduced (8); + + copyButton.setBounds (r.removeFromBottom (30).removeFromLeft (50)); + r.removeFromBottom (5); desc.setBounds (r.removeFromTop (44)); r.removeFromTop (8); userText.setBounds (r.removeFromTop (r.getHeight() / 2)); @@ -107,7 +123,11 @@ public: void paint (Graphics& g) override { - g.setColour (findColour (secondaryBackgroundColourId)); + if (dragOver) + { + g.setColour (findColour (secondaryBackgroundColourId).brighter()); + g.fillAll(); + } g.setColour (findColour (defaultTextColourId)); g.fillPath (path, path.getTransformToScaleToFit (previewPathArea.reduced (4).toFloat(), true)); @@ -119,11 +139,72 @@ public: resultText.applyFontToAllText (resultText.getFont()); } + bool isInterestedInFileDrag (const StringArray& files) override + { + return files.size() == 1 + && File (files[0]).hasFileExtension ("svg"); + } + + void fileDragEnter (const StringArray&, int, int) override + { + dragOver = true; + repaint(); + } + + void fileDragExit (const StringArray&) override + { + dragOver = false; + repaint(); + } + + void filesDropped (const StringArray& files, int, int) override + { + dragOver = false; + repaint(); + + if (ScopedPointer e = XmlDocument::parse (File (files[0]))) + { + if (auto* ePath = e->getChildByName ("path")) + userText.setText (ePath->getStringAttribute ("d"), true); + else if (auto* ePolygon = e->getChildByName ("polygon")) + userText.setText (ePolygon->getStringAttribute ("points"), true); + } + } + + Path pathFromPoints (String pointsText) + { + auto points = StringArray::fromTokens (pointsText, " ,", ""); + points.removeEmptyStrings(); + + jassert (points.size() % 2 == 0); + + Path p; + + for (int i = 0; i < points.size() / 2; i++) + { + auto x = points[i * 2].getFloatValue(); + auto y = points[i * 2 + 1].getFloatValue(); + + if (i == 0) + p.startNewSubPath ({ x, y }); + else + p.lineTo ({ x, y }); + } + + p.closeSubPath(); + + return p; + } + private: - Label desc; + Label desc { {}, "Paste an SVG path string into the top box, and it'll be converted to some C++ " + "code that will load it as a Path object.." }; + TextButton copyButton { "Copy" }; TextEditor userText, resultText; + Rectangle previewPathArea; Path path; + bool dragOver = false; String& getLastText() {