From c28c6c3e7cec388f9bb2e403b64f01a61c06edc1 Mon Sep 17 00:00:00 2001 From: jules Date: Sat, 23 Nov 2013 16:08:05 +0000 Subject: [PATCH] Introjucer: added a utility tool that converts an SVG path string into code that creates a Path object. --- .../Source/Application/jucer_Application.h | 13 +- .../Source/Application/jucer_CommandIDs.h | 1 + .../Source/Utility/jucer_MiscUtilities.cpp | 126 +++++++++++++++++- .../Source/Utility/jucer_MiscUtilities.h | 1 + 4 files changed, 135 insertions(+), 6 deletions(-) diff --git a/extras/Introjucer/Source/Application/jucer_Application.h b/extras/Introjucer/Source/Application/jucer_Application.h index 5b383a0857..6a97538ab8 100644 --- a/extras/Introjucer/Source/Application/jucer_Application.h +++ b/extras/Introjucer/Source/Application/jucer_Application.h @@ -97,6 +97,7 @@ public: { appearanceEditorWindow = nullptr; utf8Window = nullptr; + svgPathWindow = nullptr; #if JUCE_MAC MenuBarModel::setMacMainMenu (nullptr); @@ -311,6 +312,7 @@ public: virtual void createToolsMenu (PopupMenu& menu) { menu.addCommandItem (commandManager, CommandIDs::showUTF8Tool); + menu.addCommandItem (commandManager, CommandIDs::showSVGPathTool); menu.addCommandItem (commandManager, CommandIDs::showTranslationTool); } @@ -348,7 +350,8 @@ public: CommandIDs::closeAllDocuments, CommandIDs::saveAll, CommandIDs::showAppearanceSettings, - CommandIDs::showUTF8Tool }; + CommandIDs::showUTF8Tool, + CommandIDs::showSVGPathTool }; commands.addArray (ids, numElementsInArray (ids)); } @@ -385,6 +388,10 @@ public: result.setInfo ("UTF-8 String-Literal Helper", "Shows the UTF-8 string literal utility", CommandCategories::general, 0); break; + case CommandIDs::showSVGPathTool: + result.setInfo ("SVG Path Helper", "Shows the SVG->Path data conversion utility", CommandCategories::general, 0); + break; + default: JUCEApplication::getCommandInfo (commandID, result); break; @@ -400,6 +407,8 @@ public: case CommandIDs::saveAll: openDocumentManager.saveAll(); break; case CommandIDs::closeAllDocuments: closeAllDocuments (true); break; case CommandIDs::showUTF8Tool: showUTF8ToolWindow (utf8Window); break; + case CommandIDs::showSVGPathTool: showSVGPathDataToolWindow (svgPathWindow); break; + case CommandIDs::showAppearanceSettings: AppearanceSettings::showEditorWindow (appearanceEditorWindow); break; default: return JUCEApplication::perform (info); } @@ -531,7 +540,7 @@ public: OpenDocumentManager openDocumentManager; ScopedPointer commandManager; - ScopedPointer appearanceEditorWindow, utf8Window; + ScopedPointer appearanceEditorWindow, utf8Window, svgPathWindow; ScopedPointer logger; diff --git a/extras/Introjucer/Source/Application/jucer_CommandIDs.h b/extras/Introjucer/Source/Application/jucer_CommandIDs.h index 8faa4df613..e1b20ed197 100644 --- a/extras/Introjucer/Source/Application/jucer_CommandIDs.h +++ b/extras/Introjucer/Source/Application/jucer_CommandIDs.h @@ -48,6 +48,7 @@ namespace CommandIDs showTranslationTool = 0x200079, showProjectSettings = 0x20007a, showProjectModules = 0x20007b, + showSVGPathTool = 0x20007c, closeWindow = 0x201001, closeAllDocuments = 0x201000, diff --git a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.cpp b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.cpp index 79c902ccce..8cc445a55f 100644 --- a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.cpp +++ b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.cpp @@ -316,6 +316,7 @@ public: addAndMakeVisible (&userText); userText.addListener (this); + resultText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f)); resultText.setMultiLine (true, true); resultText.setColour (TextEditor::backgroundColourId, bkgd); resultText.setReadOnly (true); @@ -343,9 +344,12 @@ public: void resized() { - desc.setBounds (8, 8, getWidth() - 16, 44); - userText.setBounds (desc.getX(), desc.getBottom() + 8, getWidth() - 16, getHeight() / 2 - desc.getBottom() - 8); - resultText.setBounds (desc.getX(), userText.getBottom() + 4, getWidth() - 16, getHeight() - userText.getBottom() - 12); + Rectangle r (getLocalBounds().reduced (8)); + desc.setBounds (r.removeFromTop (44)); + r.removeFromTop (8); + userText.setBounds (r.removeFromTop (r.getHeight() / 2)); + r.removeFromTop (8); + resultText.setBounds (r); } private: @@ -370,11 +374,125 @@ void showUTF8ToolWindow (ScopedPointer& ownerPointer) new FloatingToolWindow ("UTF-8 String Literal Converter", "utf8WindowPos", new UTF8Component(), ownerPointer, - 400, 300, + 500, 500, 300, 300, 1000, 1000); } } +//============================================================================== +class SVGPathDataComponent : public Component, + private TextEditorListener +{ +public: + SVGPathDataComponent() + : desc (String::empty, + "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.setColour (Label::textColourId, Colours::white); + addAndMakeVisible (&desc); + + const Colour bkgd (Colours::white.withAlpha (0.6f)); + + userText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f)); + userText.setMultiLine (true, true); + userText.setReturnKeyStartsNewLine (true); + userText.setColour (TextEditor::backgroundColourId, bkgd); + addAndMakeVisible (&userText); + userText.addListener (this); + + resultText.setFont (getAppSettings().appearance.getCodeFont().withHeight (13.0f)); + resultText.setMultiLine (true, true); + resultText.setColour (TextEditor::backgroundColourId, bkgd); + resultText.setReadOnly (true); + resultText.setSelectAllWhenFocused (true); + addAndMakeVisible (&resultText); + + userText.setText (getLastText()); + } + + void textEditorTextChanged (TextEditor&) + { + update(); + } + + void textEditorEscapeKeyPressed (TextEditor&) + { + getTopLevelComponent()->exitModalState (0); + } + + void update() + { + getLastText() = userText.getText(); + + path = Drawable::parseSVGPath (getLastText().trim().unquoted().trim()); + + String result = "No path generated.. Not a valid SVG path string?"; + + if (! path.isEmpty()) + { + MemoryOutputStream data; + path.writePathToStream (data); + + MemoryOutputStream out; + + out << "static const unsigned char pathData[] = "; + CodeHelpers::writeDataAsCppLiteral (data.getMemoryBlock(), out, false, true); + out << newLine + << newLine + << "Path path;" << newLine + << "path.loadPathFromData (pathData, sizeof (pathData));" << newLine; + + result = out.toString(); + } + + resultText.setText (result, false); + repaint (previewPathArea); + } + + void resized() + { + Rectangle r (getLocalBounds().reduced (8)); + desc.setBounds (r.removeFromTop (44)); + r.removeFromTop (8); + userText.setBounds (r.removeFromTop (r.getHeight() / 2)); + r.removeFromTop (8); + previewPathArea = r.removeFromRight (r.getHeight()); + resultText.setBounds (r); + } + + void paint (Graphics& g) + { + g.setColour (Colours::white); + g.fillPath (path, path.getTransformToScaleToFit (previewPathArea.reduced (4).toFloat(), true)); + } + +private: + Label desc; + TextEditor userText, resultText; + Rectangle previewPathArea; + Path path; + + String& getLastText() + { + static String t; + return t; + } +}; + +void showSVGPathDataToolWindow (ScopedPointer& ownerPointer) +{ + if (ownerPointer != nullptr) + ownerPointer->toFront (true); + else + new FloatingToolWindow ("SVG Path Converter", + "svgPathWindowPos", + new SVGPathDataComponent(), ownerPointer, + 500, 500, + 300, 300, 1000, 1000); +} + //============================================================================== bool cancelAnyModalComponents() { diff --git a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h index 10faf1e1d5..152ab784e2 100644 --- a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h +++ b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h @@ -50,6 +50,7 @@ int indexOfLineStartingWith (const StringArray& lines, const String& text, int s void autoScrollForMouseEvent (const MouseEvent& e, bool scrollX = true, bool scrollY = true); void showUTF8ToolWindow (ScopedPointer& ownerPointer); +void showSVGPathDataToolWindow (ScopedPointer& ownerPointer); bool cancelAnyModalComponents(); bool reinvokeCommandAfterCancellingModalComps (const ApplicationCommandTarget::InvocationInfo&);