| @@ -29,13 +29,13 @@ | |||||
| //============================================================================== | //============================================================================== | ||||
| class SVGPathDataComponent : public Component, | class SVGPathDataComponent : public Component, | ||||
| private TextEditor::Listener | |||||
| public FileDragAndDropTarget, | |||||
| private TextEditor::Listener, | |||||
| private Button::Listener | |||||
| { | { | ||||
| public: | public: | ||||
| SVGPathDataComponent() | 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); | desc.setJustificationType (Justification::centred); | ||||
| addAndMakeVisible (desc); | addAndMakeVisible (desc); | ||||
| @@ -53,6 +53,15 @@ public: | |||||
| addAndMakeVisible (resultText); | addAndMakeVisible (resultText); | ||||
| userText.setText (getLastText()); | userText.setText (getLastText()); | ||||
| addAndMakeVisible (copyButton); | |||||
| copyButton.addListener (this); | |||||
| } | |||||
| void buttonClicked (Button* b) override | |||||
| { | |||||
| if (b == ©Button) | |||||
| SystemClipboard::copyTextToClipboard (resultText.getText()); | |||||
| } | } | ||||
| void textEditorTextChanged (TextEditor&) override | void textEditorTextChanged (TextEditor&) override | ||||
| @@ -68,8 +77,12 @@ public: | |||||
| void update() | void update() | ||||
| { | { | ||||
| getLastText() = userText.getText(); | 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?"; | String result = "No path generated.. Not a valid SVG path string?"; | ||||
| @@ -96,7 +109,10 @@ public: | |||||
| void resized() override | void resized() override | ||||
| { | { | ||||
| Rectangle<int> r (getLocalBounds().reduced (8)); | |||||
| auto r = getLocalBounds().reduced (8); | |||||
| copyButton.setBounds (r.removeFromBottom (30).removeFromLeft (50)); | |||||
| r.removeFromBottom (5); | |||||
| desc.setBounds (r.removeFromTop (44)); | desc.setBounds (r.removeFromTop (44)); | ||||
| r.removeFromTop (8); | r.removeFromTop (8); | ||||
| userText.setBounds (r.removeFromTop (r.getHeight() / 2)); | userText.setBounds (r.removeFromTop (r.getHeight() / 2)); | ||||
| @@ -107,7 +123,11 @@ public: | |||||
| void paint (Graphics& g) override | void paint (Graphics& g) override | ||||
| { | { | ||||
| g.setColour (findColour (secondaryBackgroundColourId)); | |||||
| if (dragOver) | |||||
| { | |||||
| g.setColour (findColour (secondaryBackgroundColourId).brighter()); | |||||
| g.fillAll(); | |||||
| } | |||||
| g.setColour (findColour (defaultTextColourId)); | g.setColour (findColour (defaultTextColourId)); | ||||
| g.fillPath (path, path.getTransformToScaleToFit (previewPathArea.reduced (4).toFloat(), true)); | g.fillPath (path, path.getTransformToScaleToFit (previewPathArea.reduced (4).toFloat(), true)); | ||||
| @@ -119,11 +139,72 @@ public: | |||||
| resultText.applyFontToAllText (resultText.getFont()); | 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<XmlElement> 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: | 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; | TextEditor userText, resultText; | ||||
| Rectangle<int> previewPathArea; | Rectangle<int> previewPathArea; | ||||
| Path path; | Path path; | ||||
| bool dragOver = false; | |||||
| String& getLastText() | String& getLastText() | ||||
| { | { | ||||