| @@ -93,6 +93,11 @@ bool ComponentDocument::loadFromXml (const XmlElement& xml) | |||
| return false; | |||
| } | |||
| void ComponentDocument::applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| backgroundGraphics->applyCustomPaintSnippets (snippets); | |||
| } | |||
| //============================================================================== | |||
| class NormalTestComponent : public Component | |||
| { | |||
| @@ -53,6 +53,7 @@ public: | |||
| bool loadFromXml (const XmlElement& xml); | |||
| void fillInGeneratedCode (GeneratedCode& code) const; | |||
| void applyCustomPaintSnippets (StringArray&); | |||
| private: | |||
| ScopedPointer<ComponentLayout> components; | |||
| @@ -294,7 +294,7 @@ static void copyAcrossUserSections (String& dest, const String& src) | |||
| { | |||
| StringArray sourceLines; | |||
| if (getUserSection (srcLines, tag, sourceLines)) | |||
| if (tag != "UserPaintCustomArguments" && getUserSection (srcLines, tag, sourceLines)) | |||
| { | |||
| for (int j = endLine - i; --j > 0;) | |||
| dstLines.remove (i + 1); | |||
| @@ -42,14 +42,7 @@ const char* const defaultParentClasses = "public Component"; | |||
| JucerDocument::JucerDocument (SourceCodeDocument* c) | |||
| : cpp (c), | |||
| className (defaultClassName), | |||
| parentClasses (defaultParentClasses), | |||
| fixedSize (false), | |||
| initialWidth (600), | |||
| initialHeight (400), | |||
| snapGridPixels (8), | |||
| snapActive (true), | |||
| snapShown (true), | |||
| componentOverlayOpacity (0.33f) | |||
| parentClasses (defaultParentClasses) | |||
| { | |||
| jassert (cpp != nullptr); | |||
| resources.setDocument (this); | |||
| @@ -599,13 +592,49 @@ bool JucerDocument::reloadFromDocument() | |||
| resources.loadFromCpp (getCppFile(), cppContent); | |||
| return loadFromXml (*currentXML); | |||
| bool result = loadFromXml (*currentXML); | |||
| extractCustomPaintSnippetsFromCppFile (cppContent); | |||
| return result; | |||
| } | |||
| void JucerDocument::refreshCustomCodeFromDocument() | |||
| { | |||
| const String cppContent (cpp->getCodeDocument().getAllContent()); | |||
| extractCustomPaintSnippetsFromCppFile (cppContent); | |||
| } | |||
| void JucerDocument::extractCustomPaintSnippetsFromCppFile (const String& cppContent) | |||
| { | |||
| StringArray customPaintSnippets; | |||
| auto lines = StringArray::fromLines (cppContent); | |||
| int last = 0; | |||
| while (last >= 0) | |||
| { | |||
| const int start = indexOfLineStartingWith (lines, "//[UserPaintCustomArguments]", last); | |||
| if (start < 0) | |||
| break; | |||
| const int end = indexOfLineStartingWith (lines, "//[/UserPaintCustomArguments]", start); | |||
| if (end < 0) | |||
| break; | |||
| last = end + 1; | |||
| String result; | |||
| for (int i = start + 1; i < end; ++i) | |||
| result << lines [i] << newLine; | |||
| customPaintSnippets.add (CodeHelpers::unindent (result, 4)); | |||
| } | |||
| applyCustomPaintSnippets (customPaintSnippets); | |||
| } | |||
| XmlElement* JucerDocument::pullMetaDataFromCppFile (const String& cpp) | |||
| { | |||
| StringArray lines; | |||
| lines.addLines (cpp); | |||
| auto lines = StringArray::fromLines (cpp); | |||
| const int startLine = indexOfLineStartingWith (lines, "BEGIN_JUCER_METADATA", 0); | |||
| @@ -624,17 +653,15 @@ XmlElement* JucerDocument::pullMetaDataFromCppFile (const String& cpp) | |||
| bool JucerDocument::isValidJucerCppFile (const File& f) | |||
| { | |||
| if (f.hasFileExtension (".cpp")) | |||
| { | |||
| const ScopedPointer<XmlElement> xml (pullMetaDataFromCppFile (f.loadFileAsString())); | |||
| return xml != nullptr && xml->hasTagName (jucerCompXmlTag); | |||
| } | |||
| if (ScopedPointer<XmlElement> xml = pullMetaDataFromCppFile (f.loadFileAsString())) | |||
| return xml->hasTagName (jucerCompXmlTag); | |||
| return false; | |||
| } | |||
| static JucerDocument* createDocument (SourceCodeDocument* cpp) | |||
| { | |||
| CodeDocument& codeDoc = cpp->getCodeDocument(); | |||
| auto& codeDoc = cpp->getCodeDocument(); | |||
| ScopedPointer<XmlElement> xml (JucerDocument::pullMetaDataFromCppFile (codeDoc.getAllContent())); | |||
| @@ -684,9 +711,9 @@ public: | |||
| bool saveHeader() | |||
| { | |||
| OpenDocumentManager& odm = ProjucerApplication::getApp().openDocumentManager; | |||
| auto& odm = ProjucerApplication::getApp().openDocumentManager; | |||
| if (OpenDocumentManager::Document* header = odm.openFile (nullptr, getFile().withFileExtension (".h"))) | |||
| if (auto* header = odm.openFile (nullptr, getFile().withFileExtension (".h"))) | |||
| return header->save(); | |||
| return false; | |||
| @@ -694,9 +721,7 @@ public: | |||
| Component* createEditor() override | |||
| { | |||
| ScopedPointer<JucerDocument> jucerDoc (JucerDocument::createForCppFile (getProject(), getFile())); | |||
| if (jucerDoc != nullptr) | |||
| if (ScopedPointer<JucerDocument> jucerDoc = JucerDocument::createForCppFile (getProject(), getFile())) | |||
| return new JucerDocumentEditor (jucerDoc.release()); | |||
| return SourceCodeDocument::createEditor(); | |||
| @@ -736,15 +761,13 @@ public: | |||
| headerFile.replaceWithText (String()); | |||
| cppFile.replaceWithText (String()); | |||
| OpenDocumentManager& odm = ProjucerApplication::getApp().openDocumentManager; | |||
| auto& odm = ProjucerApplication::getApp().openDocumentManager; | |||
| if (SourceCodeDocument* cpp = dynamic_cast<SourceCodeDocument*> (odm.openFile (nullptr, cppFile))) | |||
| if (auto* cpp = dynamic_cast<SourceCodeDocument*> (odm.openFile (nullptr, cppFile))) | |||
| { | |||
| if (SourceCodeDocument* header = dynamic_cast<SourceCodeDocument*> (odm.openFile (nullptr, headerFile))) | |||
| if (auto* header = dynamic_cast<SourceCodeDocument*> (odm.openFile (nullptr, headerFile))) | |||
| { | |||
| ScopedPointer<JucerDocument> jucerDoc (new ComponentDocument (cpp)); | |||
| if (jucerDoc != nullptr) | |||
| if (ScopedPointer<JucerDocument> jucerDoc = new ComponentDocument (cpp)) | |||
| { | |||
| jucerDoc->setClassName (newFile.getFileNameWithoutExtension()); | |||
| @@ -136,14 +136,17 @@ public: | |||
| static bool shouldUseTransMacro() noexcept { return true; } | |||
| //============================================================================== | |||
| void refreshCustomCodeFromDocument(); | |||
| protected: | |||
| SourceCodeDocument* cpp; | |||
| String className, componentName, templateFile; | |||
| String parentClasses, constructorParams, variableInitialisers; | |||
| bool fixedSize; | |||
| int initialWidth, initialHeight; | |||
| bool fixedSize = false; | |||
| int initialWidth = 600, initialHeight = 400; | |||
| BinaryResources resources; | |||
| @@ -153,6 +156,8 @@ protected: | |||
| virtual void fillInGeneratedCode (GeneratedCode&) const; | |||
| virtual void fillInPaintCode (GeneratedCode&) const; | |||
| virtual void applyCustomPaintSnippets (StringArray&) {} | |||
| static void addMethod (const String& base, const String& returnVal, | |||
| const String& method, const String& initialContent, | |||
| StringArray& baseClasses, StringArray& returnValues, | |||
| @@ -160,9 +165,9 @@ protected: | |||
| private: | |||
| UndoManager undoManager; | |||
| int snapGridPixels; | |||
| bool snapActive, snapShown; | |||
| float componentOverlayOpacity; | |||
| int snapGridPixels = 8; | |||
| bool snapActive = true, snapShown = true; | |||
| float componentOverlayOpacity = 0.33f; | |||
| StringArray activeExtraMethods; | |||
| ScopedPointer<XmlElement> currentXML; | |||
| ScopedPointer<Timer> userDocChangeTimer; | |||
| @@ -172,6 +177,7 @@ private: | |||
| void codeDocumentTextDeleted (int startIndex, int endIndex) override; | |||
| void userEditedCpp(); | |||
| bool documentAboutToClose (OpenDocumentManager::Document*) override; | |||
| void extractCustomPaintSnippetsFromCppFile (const String& cpp); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JucerDocument) | |||
| }; | |||
| @@ -293,16 +293,9 @@ void PaintRoutine::copySelectedToClipboard() | |||
| XmlElement clip (clipboardXmlTag); | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| { | |||
| PaintElement* const pe = elements.getUnchecked(i); | |||
| for (auto* pe : elements) | |||
| if (selectedElements.isSelected (pe)) | |||
| { | |||
| XmlElement* const e = pe->createXml(); | |||
| clip.addChildElement (e); | |||
| } | |||
| } | |||
| clip.addChildElement (pe->createXml()); | |||
| SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false)); | |||
| } | |||
| @@ -325,8 +318,8 @@ void PaintRoutine::paste() | |||
| void PaintRoutine::deleteSelected() | |||
| { | |||
| const SelectedItemSet <PaintElement*> temp1 (selectedElements); | |||
| const SelectedItemSet <PathPoint*> temp2 (selectedPoints); | |||
| const SelectedItemSet<PaintElement*> temp1 (selectedElements); | |||
| const SelectedItemSet<PathPoint*> temp2 (selectedPoints); | |||
| if (temp2.getNumSelected() > 0) | |||
| { | |||
| @@ -369,7 +362,7 @@ void PaintRoutine::selectAll() | |||
| void PaintRoutine::selectedToFront() | |||
| { | |||
| const SelectedItemSet <PaintElement*> temp (selectedElements); | |||
| const SelectedItemSet<PaintElement*> temp (selectedElements); | |||
| for (int i = temp.getNumSelected(); --i >= 0;) | |||
| elementToFront (temp.getSelectedItem(i), true); | |||
| @@ -377,7 +370,7 @@ void PaintRoutine::selectedToFront() | |||
| void PaintRoutine::selectedToBack() | |||
| { | |||
| const SelectedItemSet <PaintElement*> temp (selectedElements); | |||
| const SelectedItemSet<PaintElement*> temp (selectedElements); | |||
| for (int i = 0; i < temp.getNumSelected(); ++i) | |||
| elementToBack (temp.getSelectedItem(i), true); | |||
| @@ -399,11 +392,9 @@ void PaintRoutine::ungroupSelected() | |||
| void PaintRoutine::bringLostItemsBackOnScreen (const Rectangle<int>& parentArea) | |||
| { | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| for (auto* c : elements) | |||
| { | |||
| PaintElement* const c = elements[i]; | |||
| Rectangle<int> r (c->getCurrentBounds (parentArea)); | |||
| auto r = c->getCurrentBounds (parentArea); | |||
| if (! r.intersects (parentArea)) | |||
| { | |||
| @@ -415,11 +406,9 @@ void PaintRoutine::bringLostItemsBackOnScreen (const Rectangle<int>& parentArea) | |||
| void PaintRoutine::startDragging (const Rectangle<int>& parentArea) | |||
| { | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| for (auto* c : elements) | |||
| { | |||
| PaintElement* const c = elements[i]; | |||
| Rectangle<int> r (c->getCurrentBounds (parentArea)); | |||
| auto r = c->getCurrentBounds (parentArea); | |||
| c->getProperties().set ("xDragStart", r.getX()); | |||
| c->getProperties().set ("yDragStart", r.getY()); | |||
| @@ -490,8 +479,8 @@ void PaintRoutine::drawElements (Graphics& g, const Rectangle<int>& relativeTo) | |||
| Component temp; | |||
| temp.setBounds (relativeTo); | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| elements.getUnchecked (i)->draw (g, getDocument()->getComponentLayout(), relativeTo); | |||
| for (auto* e : elements) | |||
| e->draw (g, getDocument()->getComponentLayout(), relativeTo); | |||
| } | |||
| //============================================================================== | |||
| @@ -501,17 +490,16 @@ void PaintRoutine::dropImageAt (const File& f, int x, int y) | |||
| if (d != nullptr) | |||
| { | |||
| Rectangle<float> bounds (d->getDrawableBounds()); | |||
| auto bounds = d->getDrawableBounds(); | |||
| d = nullptr; | |||
| PaintElement* newElement | |||
| = addNewElement (ObjectTypes::createNewImageElement (this), -1, true); | |||
| auto* newElement = addNewElement (ObjectTypes::createNewImageElement (this), -1, true); | |||
| if (PaintElementImage* pei = dynamic_cast<PaintElementImage*> (newElement)) | |||
| if (auto* pei = dynamic_cast<PaintElementImage*> (newElement)) | |||
| { | |||
| String resourceName (getDocument()->getResources().findUniqueName (f.getFileName())); | |||
| if (const BinaryResources::BinaryResource* existingResource = getDocument()->getResources().getResourceForFile (f)) | |||
| if (auto* existingResource = getDocument()->getResources().getResourceForFile (f)) | |||
| { | |||
| resourceName = existingResource->name; | |||
| } | |||
| @@ -546,12 +534,11 @@ const char* PaintRoutine::xmlTagName = "BACKGROUND"; | |||
| XmlElement* PaintRoutine::createXml() const | |||
| { | |||
| XmlElement* const xml = new XmlElement (xmlTagName); | |||
| auto* xml = new XmlElement (xmlTagName); | |||
| xml->setAttribute ("backgroundColour", backgroundColour.toString()); | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| xml->addChildElement (elements.getUnchecked (i)->createXml()); | |||
| for (auto* e : elements) | |||
| xml->addChildElement (e->createXml()); | |||
| return xml; | |||
| } | |||
| @@ -565,7 +552,7 @@ bool PaintRoutine::loadFromXml (const XmlElement& xml) | |||
| clear(); | |||
| forEachXmlChildElement (xml, e) | |||
| if (PaintElement* const newElement = ObjectTypes::createElementForXml (e, this)) | |||
| if (auto* newElement = ObjectTypes::createElementForXml (e, this)) | |||
| elements.add (newElement); | |||
| return true; | |||
| @@ -579,6 +566,12 @@ void PaintRoutine::fillInGeneratedCode (GeneratedCode& code, String& paintMethod | |||
| if (! backgroundColour.isTransparent()) | |||
| paintMethodCode << "g.fillAll (" << CodeHelpers::colourToCode (backgroundColour) << ");\n\n"; | |||
| for (int i = 0; i < elements.size(); ++i) | |||
| elements[i]->fillInGeneratedCode (code, paintMethodCode); | |||
| for (auto* e : elements) | |||
| e->fillInGeneratedCode (code, paintMethodCode); | |||
| } | |||
| void PaintRoutine::applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| for (auto* e : elements) | |||
| e->applyCustomPaintSnippets (snippets); | |||
| } | |||
| @@ -103,6 +103,8 @@ public: | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const; | |||
| void applyCustomPaintSnippets (StringArray&); | |||
| //============================================================================== | |||
| private: | |||
| OwnedArray <PaintElement> elements; | |||
| @@ -117,58 +117,89 @@ public: | |||
| } | |||
| } | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const | |||
| String generateVariablesCode (String type) const | |||
| { | |||
| String s; | |||
| switch (mode) | |||
| { | |||
| case solidColour: | |||
| s << "g.setColour (" << CodeHelpers::colourToCode (colour) << ");\n"; | |||
| break; | |||
| case solidColour: | |||
| s << "Colour " << type << "Colour = " << CodeHelpers::colourToCode (colour) << ";\n"; | |||
| break; | |||
| case linearGradient: | |||
| case radialGradient: | |||
| { | |||
| String x1, y1, w, h, x2, y2; | |||
| positionToCode (gradPos1, code.document->getComponentLayout(), x1, y1, w, h); | |||
| positionToCode (gradPos2, code.document->getComponentLayout(), x2, y2, w, h); | |||
| case linearGradient: | |||
| case radialGradient: | |||
| s << "Colour " << type << "Colour1 = " << CodeHelpers::colourToCode (gradCol1) << ", " << type << "Colour2 = " << CodeHelpers::colourToCode (gradCol2) << ";\n"; | |||
| break; | |||
| s << "g.setGradientFill (ColourGradient ("; | |||
| case imageBrush: | |||
| break; | |||
| const String indent (String::repeatedString (" ", s.length())); | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| } | |||
| s << CodeHelpers::colourToCode (gradCol1) << ",\n" | |||
| << indent << castToFloat (x1) << ", " << castToFloat (y1) << ",\n" | |||
| << indent << CodeHelpers::colourToCode (gradCol2) << ",\n" | |||
| << indent << castToFloat (x2) << ", " << castToFloat (y2) << ",\n" | |||
| << indent << CodeHelpers::boolLiteral (mode == radialGradient) << "));\n"; | |||
| return s; | |||
| } | |||
| void fillInGeneratedCode (String type, RelativePositionedRectangle relativeTo, GeneratedCode& code, String& paintMethodCode) const | |||
| { | |||
| String s; | |||
| switch (mode) | |||
| { | |||
| case solidColour: | |||
| s << "g.setColour (" << type << "Colour);\n"; | |||
| break; | |||
| } | |||
| case imageBrush: | |||
| { | |||
| const String imageVariable ("cachedImage_" + imageResourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix())); | |||
| case linearGradient: | |||
| case radialGradient: | |||
| { | |||
| String x0, y0, x1, y1, w, h, x2, y2; | |||
| positionToCode (relativeTo, code.document->getComponentLayout(), x0, y0, w, h); | |||
| positionToCode (gradPos1, code.document->getComponentLayout(), x1, y1, w, h); | |||
| positionToCode (gradPos2, code.document->getComponentLayout(), x2, y2, w, h); | |||
| s << "g.setGradientFill (ColourGradient ("; | |||
| auto indent = String::repeatedString (" ", s.length()); | |||
| s << type << "Colour1,\n" | |||
| << indent << castToFloat (x1) << " - " << castToFloat (x0) << " + x,\n" | |||
| << indent << castToFloat (y1) << " - " << castToFloat (y0) << " + y,\n" | |||
| << indent << type << "Colour2,\n" | |||
| << indent << castToFloat (x2) << " - " << castToFloat (x0) << " + x,\n" | |||
| << indent << castToFloat (y2) << " - " << castToFloat (y0) << " + y,\n" | |||
| << indent << CodeHelpers::boolLiteral (mode == radialGradient) << "));\n"; | |||
| break; | |||
| } | |||
| code.addImageResourceLoader (imageVariable, imageResourceName); | |||
| case imageBrush: | |||
| { | |||
| auto imageVariable = "cachedImage_" + imageResourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix()); | |||
| String x, y, w, h; | |||
| positionToCode (imageAnchor, code.document->getComponentLayout(), x, y, w, h); | |||
| code.addImageResourceLoader (imageVariable, imageResourceName); | |||
| s << "g.setTiledImageFill ("; | |||
| String x0, y0, x1, y1, w, h; | |||
| positionToCode (relativeTo, code.document->getComponentLayout(), x0, y0, w, h); | |||
| positionToCode (imageAnchor, code.document->getComponentLayout(), x1, y1, w, h); | |||
| const String indent (String::repeatedString (" ", s.length())); | |||
| s << "g.setTiledImageFill ("; | |||
| s << imageVariable << ",\n" | |||
| << indent << x << ", " << y << ",\n" | |||
| << indent << CodeHelpers::floatLiteral (imageOpacity, 4) << ");\n"; | |||
| const String indent (String::repeatedString (" ", s.length())); | |||
| break; | |||
| } | |||
| s << imageVariable << ",\n" | |||
| << indent << x1 << " - " << x0 << " + x,\n" | |||
| << indent << y1 << " - " << y0 << " + y,\n" | |||
| << indent << CodeHelpers::floatLiteral (imageOpacity, 4) << ");\n"; | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| break; | |||
| } | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| } | |||
| paintMethodCode += s; | |||
| @@ -178,29 +209,29 @@ public: | |||
| { | |||
| switch (mode) | |||
| { | |||
| case solidColour: | |||
| return "solid: " + colour.toString(); | |||
| case linearGradient: | |||
| case radialGradient: | |||
| return (mode == linearGradient ? "linear: " | |||
| : " radial: ") | |||
| + gradPos1.toString() | |||
| + ", " | |||
| + gradPos2.toString() | |||
| + ", 0=" + gradCol1.toString() | |||
| + ", 1=" + gradCol2.toString(); | |||
| case imageBrush: | |||
| return "image: " + imageResourceName.replaceCharacter (':', '#') | |||
| + ", " | |||
| + String (imageOpacity) | |||
| + ", " | |||
| + imageAnchor.toString(); | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| case solidColour: | |||
| return "solid: " + colour.toString(); | |||
| case linearGradient: | |||
| case radialGradient: | |||
| return (mode == linearGradient ? "linear: " | |||
| : " radial: ") | |||
| + gradPos1.toString() | |||
| + ", " | |||
| + gradPos2.toString() | |||
| + ", 0=" + gradCol1.toString() | |||
| + ", 1=" + gradCol2.toString(); | |||
| case imageBrush: | |||
| return "image: " + imageResourceName.replaceCharacter (':', '#') | |||
| + ", " | |||
| + String (imageOpacity) | |||
| + ", " | |||
| + imageAnchor.toString(); | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| } | |||
| return {}; | |||
| @@ -94,6 +94,8 @@ public: | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| void parentHierarchyChanged(); | |||
| virtual void applyCustomPaintSnippets (StringArray&) {} | |||
| int borderThickness; | |||
| protected: | |||
| @@ -159,7 +161,7 @@ public: | |||
| void changeListenerCallback (ChangeBroadcaster*) | |||
| { | |||
| jassert (propToRefresh != nullptr); | |||
| if (propToRefresh != nullptr) | |||
| if (propToRefresh != nullptr && owner != nullptr) | |||
| propToRefresh->refresh(); | |||
| } | |||
| @@ -62,35 +62,53 @@ public: | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) | |||
| { | |||
| if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) | |||
| return; | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << "{\n" | |||
| << " float x = " << castToFloat (x) << ", y = " << castToFloat (y) << ", " | |||
| << "width = " << castToFloat (w) << ", height = " << castToFloat (h) << ";\n"; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << " " << fillType.generateVariablesCode ("fill"); | |||
| fillType.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.fillEllipse (" | |||
| << castToFloat (x) << ", " | |||
| << castToFloat (y) << ", " | |||
| << castToFloat (w) << ", " | |||
| << castToFloat (h) << ");\n\n"; | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| s << " " << strokeType.fill.generateVariablesCode ("stroke"); | |||
| paintMethodCode += s; | |||
| s << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n"; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| s << " "; | |||
| fillType.fillInGeneratedCode ("fill", position, code, s); | |||
| s << " g.fillEllipse (x, y, width, height);\n"; | |||
| } | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| strokeType.fill.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.drawEllipse (" | |||
| << castToFloat (x) << ", " | |||
| << castToFloat (y) << ", " | |||
| << castToFloat (w) << ", " | |||
| << castToFloat (h) << ", " | |||
| << CodeHelpers::floatLiteral (strokeType.stroke.getStrokeThickness(), 3) << ");\n\n"; | |||
| paintMethodCode += s; | |||
| s << " "; | |||
| strokeType.fill.fillInGeneratedCode ("stroke", position, code, s); | |||
| s << " g.drawEllipse (x, y, width, height, " << CodeHelpers::floatLiteral (strokeType.stroke.getStrokeThickness(), 3) << ");\n"; | |||
| } | |||
| s << "}\n\n"; | |||
| paintMethodCode += s; | |||
| } | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible()))) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove (0); | |||
| } | |||
| } | |||
| @@ -131,10 +149,11 @@ public: | |||
| } | |||
| private: | |||
| String customPaintCode; | |||
| //============================================================================== | |||
| class ShapeToPathProperty : public ButtonPropertyComponent | |||
| struct ShapeToPathProperty : public ButtonPropertyComponent | |||
| { | |||
| public: | |||
| ShapeToPathProperty (PaintElementEllipse* const e) | |||
| : ButtonPropertyComponent ("path", false), | |||
| element (e) | |||
| @@ -151,7 +170,6 @@ private: | |||
| return "convert to a path"; | |||
| } | |||
| private: | |||
| PaintElementEllipse* const element; | |||
| PaintElementEllipse* element; | |||
| }; | |||
| }; | |||
| @@ -209,12 +209,17 @@ public: | |||
| return false; | |||
| } | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| for (auto* e : subElements) | |||
| e->applyCustomPaintSnippets (snippets); | |||
| } | |||
| private: | |||
| OwnedArray <PaintElement> subElements; | |||
| OwnedArray<PaintElement> subElements; | |||
| class UngroupProperty : public ButtonPropertyComponent | |||
| struct UngroupProperty : public ButtonPropertyComponent | |||
| { | |||
| public: | |||
| UngroupProperty (PaintElementGroup* const e) | |||
| : ButtonPropertyComponent ("ungroup", false), | |||
| element (e) | |||
| @@ -231,7 +236,6 @@ private: | |||
| return "Ungroup"; | |||
| } | |||
| private: | |||
| PaintElementGroup* const element; | |||
| PaintElementGroup* element; | |||
| }; | |||
| }; | |||
| @@ -95,10 +95,16 @@ public: | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) | |||
| { | |||
| String r; | |||
| if (opacity > 0) | |||
| { | |||
| String x, y, w, h, r; | |||
| positionToCode (position, getDocument()->getComponentLayout(), x, y, w, h); | |||
| r << "{\n" | |||
| << " int x = " << x << ", y = " << y << ", width = " << w << ", height = " << h << ";\n" | |||
| << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n"; | |||
| if (dynamic_cast<const DrawableImage*> (getDrawable()) != 0) | |||
| { | |||
| const String imageVariable ("cachedImage_" + resourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix())); | |||
| @@ -106,36 +112,32 @@ public: | |||
| code.addImageResourceLoader (imageVariable, resourceName); | |||
| if (opacity >= 254.0 / 255.0) | |||
| r << "g.setColour (Colours::black);\n"; | |||
| r << " g.setColour (Colours::black);\n"; | |||
| else | |||
| r << "g.setColour (Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n"; | |||
| r << " g.setColour (Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n"; | |||
| String x, y, w, h; | |||
| positionToCode (position, getDocument()->getComponentLayout(), x, y, w, h); | |||
| if (mode == stretched) | |||
| { | |||
| r << "g.drawImage (" << imageVariable << ",\n " | |||
| << x << ", " << y << ", " << w << ", " << h | |||
| << ",\n 0, 0, " | |||
| << imageVariable << ".getWidth(), " | |||
| << imageVariable << ".getHeight());\n\n"; | |||
| r << " g.drawImage (" << imageVariable << ",\n" | |||
| << " x, y, width, height,\n" | |||
| << " 0, 0, " << imageVariable << ".getWidth(), " << imageVariable << ".getHeight());\n"; | |||
| } | |||
| else | |||
| { | |||
| r << "g.drawImageWithin (" << imageVariable << ",\n " | |||
| << x << ", " << y << ", " << w << ", " << h | |||
| << ",\n "; | |||
| r << " g.drawImageWithin (" << imageVariable << ",\n" | |||
| << " x, y, width, height,\n" | |||
| << " "; | |||
| if (mode == proportionalReducingOnly) | |||
| r << "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"; | |||
| else | |||
| r << "RectanglePlacement::centred"; | |||
| r << ",\n false);\n\n"; | |||
| r << ",\n" | |||
| << " false);\n"; | |||
| } | |||
| paintMethodCode += r; | |||
| } | |||
| else | |||
| { | |||
| @@ -154,28 +156,35 @@ public: | |||
| << imageVariable << " = nullptr;\n"; | |||
| if (opacity >= 254.0 / 255.0) | |||
| r << "g.setColour (Colours::black);\n"; | |||
| r << " g.setColour (Colours::black);\n"; | |||
| else | |||
| r << "g.setColour (Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n"; | |||
| String x, y, w, h; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| r << " g.setColour (Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n"; | |||
| r << "jassert (" << imageVariable << " != 0);\n" | |||
| << "if (" << imageVariable << " != 0)\n " | |||
| << imageVariable << "->drawWithin (g, Rectangle<float> (" | |||
| << x << ", " << y << ", " << w << ", " << h | |||
| << "),\n" | |||
| << String::repeatedString (" ", imageVariable.length() + 18) | |||
| r << " jassert (" << imageVariable << " != 0);\n" | |||
| << " if (" << imageVariable << " != 0)\n" | |||
| << " " << imageVariable << "->drawWithin (g, Rectangle<float> (x, y, width, height),\n" | |||
| << " " << String::repeatedString (" ", imageVariable.length() + 18) | |||
| << (mode == stretched ? "RectanglePlacement::stretchToFit" | |||
| : (mode == proportionalReducingOnly ? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize" | |||
| : "RectanglePlacement::centred")) | |||
| << ", " << CodeHelpers::floatLiteral (opacity, 3) | |||
| << ");\n\n"; | |||
| paintMethodCode += r; | |||
| << ", " << CodeHelpers::floatLiteral (opacity, 3) << ");\n"; | |||
| } | |||
| } | |||
| r << "}\n\n"; | |||
| paintMethodCode += r; | |||
| } | |||
| } | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| if (! snippets.isEmpty() && opacity > 0) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove (0); | |||
| } | |||
| } | |||
| @@ -385,6 +394,7 @@ private: | |||
| String resourceName; | |||
| double opacity; | |||
| StretchMode mode; | |||
| String customPaintCode; | |||
| //============================================================================== | |||
| class ImageElementResourceProperty : public ImageResourceProperty <PaintElementImage> | |||
| @@ -382,10 +382,8 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe | |||
| if (! nonZeroWinding) | |||
| r << pathVariable << ".setUsingNonZeroWinding (false);\n"; | |||
| for (int i = 0; i < points.size(); ++i) | |||
| for (auto* p : points) | |||
| { | |||
| const PathPoint* const p = points.getUnchecked(i); | |||
| switch (p->type) | |||
| { | |||
| case Path::Iterator::startNewSubPath: | |||
| @@ -400,15 +398,17 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe | |||
| case Path::Iterator::quadraticTo: | |||
| r << pathVariable << ".quadraticTo (" << positionToPairOfValues (p->pos[0], layout) | |||
| << ", " << positionToPairOfValues (p->pos[1], layout) << ");\n"; | |||
| << ", " << positionToPairOfValues (p->pos[1], layout) << ");\n"; | |||
| somePointsAreRelative = somePointsAreRelative || ! p->pos[0].rect.isPositionAbsolute(); | |||
| somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute(); | |||
| break; | |||
| case Path::Iterator::cubicTo: | |||
| r << pathVariable << ".cubicTo (" << positionToPairOfValues (p->pos[0], layout) | |||
| << ", " << positionToPairOfValues (p->pos[1], layout) | |||
| << ", " << positionToPairOfValues (p->pos[2], layout) << ");\n"; | |||
| << ", " << positionToPairOfValues (p->pos[1], layout) | |||
| << ", " << positionToPairOfValues (p->pos[2], layout) << ");\n"; | |||
| somePointsAreRelative = somePointsAreRelative || ! p->pos[0].rect.isPositionAbsolute(); | |||
| somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute(); | |||
| somePointsAreRelative = somePointsAreRelative || ! p->pos[2].rect.isPositionAbsolute(); | |||
| @@ -432,24 +432,50 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe | |||
| else | |||
| code.constructorCode << r; | |||
| String s; | |||
| s << "{\n" | |||
| << " float x = 0, y = 0;\n"; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| fillType.fillInGeneratedCode (code, paintMethodCode); | |||
| s << " " << fillType.generateVariablesCode ("fill"); | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| s << " " << strokeType.fill.generateVariablesCode ("stroke"); | |||
| s << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n"; | |||
| paintMethodCode << "g.fillPath (" << pathVariable << ");\n"; | |||
| RelativePositionedRectangle zero; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| s << " "; | |||
| fillType.fillInGeneratedCode ("fill", zero, code, s); | |||
| s << " g.fillPath (" << pathVariable << ", AffineTransform::translation(x, y));\n"; | |||
| } | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| { | |||
| String s; | |||
| s << " "; | |||
| strokeType.fill.fillInGeneratedCode ("stroke", zero, code, s); | |||
| s << " g.strokePath (" << pathVariable << ", " << strokeType.getPathStrokeCode() << ", AffineTransform::translation(x, y));\n"; | |||
| } | |||
| strokeType.fill.fillInGeneratedCode (code, s); | |||
| s << "g.strokePath (" << pathVariable << ", " << strokeType.getPathStrokeCode() << ");\n"; | |||
| s << "}\n\n"; | |||
| paintMethodCode += s; | |||
| } | |||
| paintMethodCode += s; | |||
| } | |||
| void PaintElementPath::applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| paintMethodCode += "\n"; | |||
| if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible()))) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove(0); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -101,6 +101,7 @@ public: | |||
| void getEditableProperties (Array<PropertyComponent*>& props); | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode); | |||
| void applyCustomPaintSnippets (StringArray& snippets); | |||
| //============================================================================== | |||
| static const char* getTagName() noexcept { return "PATH"; } | |||
| @@ -132,6 +133,7 @@ private: | |||
| mutable Rectangle<int> lastPathBounds; | |||
| int mouseDownOnSegment; | |||
| bool mouseDownSelectSegmentStatus; | |||
| String customPaintCode; | |||
| String pathToString() const; | |||
| void restorePathFromString (const String& s); | |||
| @@ -76,27 +76,52 @@ public: | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) | |||
| { | |||
| if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) | |||
| return; | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << "{\n" | |||
| << " int x = " << x << ", y = " << y << ", width = " << w << ", height = " << h << ";\n"; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << " " << fillType.generateVariablesCode ("fill"); | |||
| fillType.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.fillRect (" << x << ", " << y << ", " << w << ", " << h << ");\n\n"; | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| s << " " << strokeType.fill.generateVariablesCode ("stroke"); | |||
| s << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n"; | |||
| paintMethodCode += s; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| s << " "; | |||
| fillType.fillInGeneratedCode ("fill", position, code, s); | |||
| s << " g.fillRect (x, y, width, height);\n"; | |||
| } | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << " "; | |||
| strokeType.fill.fillInGeneratedCode ("stroke", position, code, s); | |||
| s << " g.drawRect (x, y, width, height, " << roundToInt (strokeType.stroke.getStrokeThickness()) << ");\n\n"; | |||
| } | |||
| s << "}\n\n"; | |||
| strokeType.fill.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.drawRect (" << x << ", " << y << ", " << w << ", " << h << ", " | |||
| << roundToInt (strokeType.stroke.getStrokeThickness()) << ");\n\n"; | |||
| paintMethodCode += s; | |||
| } | |||
| paintMethodCode += s; | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible()))) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove (0); | |||
| } | |||
| } | |||
| @@ -134,6 +159,8 @@ public: | |||
| } | |||
| private: | |||
| String customPaintCode; | |||
| class ShapeToPathProperty : public ButtonPropertyComponent | |||
| { | |||
| public: | |||
| @@ -116,37 +116,54 @@ public: | |||
| //============================================================================== | |||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) | |||
| { | |||
| if (fillType.isInvisible() && (strokeType.isInvisible() || ! isStrokePresent)) | |||
| return; | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| s << "{\n" | |||
| << " float x = " << castToFloat (x) << ", y = " << castToFloat (y) << ", " | |||
| << "width = " << castToFloat (w) << ", height = " << castToFloat (h) << ";\n"; | |||
| if (! fillType.isInvisible()) | |||
| s << " " << fillType.generateVariablesCode ("fill"); | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| s << " " << strokeType.fill.generateVariablesCode ("stroke"); | |||
| s << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n"; | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| fillType.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.fillRoundedRectangle (" | |||
| << castToFloat (x) << ", " | |||
| << castToFloat (y) << ", " | |||
| << castToFloat (w) << ", " | |||
| << castToFloat (h) << ", " | |||
| << CodeHelpers::floatLiteral (cornerSize, 3) << ");\n\n"; | |||
| paintMethodCode += s; | |||
| s << " "; | |||
| fillType.fillInGeneratedCode ("fill", position, code, s); | |||
| s << " g.fillRoundedRectangle (x, y, width, height, " << CodeHelpers::floatLiteral (cornerSize, 3) << ");\n"; | |||
| } | |||
| if (isStrokePresent && ! strokeType.isInvisible()) | |||
| { | |||
| String x, y, w, h, s; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| strokeType.fill.fillInGeneratedCode (code, paintMethodCode); | |||
| s << "g.drawRoundedRectangle (" | |||
| << castToFloat (x) << ", " | |||
| << castToFloat (y) << ", " | |||
| << castToFloat (w) << ", " | |||
| << castToFloat (h) << ", " | |||
| << CodeHelpers::floatLiteral (cornerSize, 3) << ", " | |||
| << CodeHelpers::floatLiteral (strokeType.stroke.getStrokeThickness(), 3) << ");\n\n"; | |||
| paintMethodCode += s; | |||
| s << " "; | |||
| strokeType.fill.fillInGeneratedCode ("stroke", position, code, s); | |||
| s << " g.drawRoundedRectangle (x, y, width, height, " << CodeHelpers::floatLiteral (cornerSize, 3) | |||
| << ", " << CodeHelpers::floatLiteral (strokeType.stroke.getStrokeThickness(), 3) << ");\n"; | |||
| } | |||
| s << "}\n\n"; | |||
| paintMethodCode += s; | |||
| } | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible()))) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove (0); | |||
| } | |||
| } | |||
| @@ -191,6 +208,7 @@ public: | |||
| private: | |||
| double cornerSize; | |||
| String customPaintCode; | |||
| //============================================================================== | |||
| class CornerSizeProperty : public SliderPropertyComponent, | |||
| @@ -83,27 +83,37 @@ public: | |||
| { | |||
| if (! fillType.isInvisible()) | |||
| { | |||
| String r; | |||
| fillType.fillInGeneratedCode (code, paintMethodCode); | |||
| String x, y, w, h; | |||
| String x, y, w, h, r; | |||
| positionToCode (position, code.document->getComponentLayout(), x, y, w, h); | |||
| r << "g.setFont (" | |||
| << FontPropertyComponent::getCompleteFontCode (font, typefaceName) | |||
| << ");\ng.drawText (" | |||
| << quotedString (text, code.shouldUseTransMacro()) | |||
| << ",\n " | |||
| << x << ", " << y << ", " << w << ", " << h | |||
| << ",\n " | |||
| << CodeHelpers::justificationToCode (justification) | |||
| << ", true);\n\n"; | |||
| r << "{\n" | |||
| << " int x = " << x << ", y = " << y << ", width = " << w << ", height = " << h << ";\n" | |||
| << " String text (" << quotedString (text, code.shouldUseTransMacro()) << ");\n" | |||
| << " " << fillType.generateVariablesCode ("fill") | |||
| << " //[UserPaintCustomArguments] Customize the painting arguments here..\n" | |||
| << customPaintCode | |||
| << " //[/UserPaintCustomArguments]\n" | |||
| << " "; | |||
| fillType.fillInGeneratedCode ("fill", position, code, r); | |||
| r << " g.setFont (" << FontPropertyComponent::getCompleteFontCode (font, typefaceName) << ");\n" | |||
| << " g.drawText (text, x, y, width, height,\n" | |||
| << " " << CodeHelpers::justificationToCode (justification) << ", true);\n" | |||
| << "}\n\n"; | |||
| paintMethodCode += r; | |||
| } | |||
| } | |||
| void applyCustomPaintSnippets (StringArray& snippets) | |||
| { | |||
| customPaintCode.clear(); | |||
| if (! snippets.isEmpty() && ! fillType.isInvisible()) | |||
| { | |||
| customPaintCode = snippets[0]; | |||
| snippets.remove (0); | |||
| } | |||
| } | |||
| static const char* getTagName() noexcept { return "TEXT"; } | |||
| XmlElement* createXml() const | |||
| @@ -376,7 +386,8 @@ private: | |||
| Font font; | |||
| String typefaceName; | |||
| Justification justification; | |||
| String customPaintCode; | |||
| Array <Justification> justificationTypes; | |||
| //============================================================================== | |||
| @@ -318,11 +318,7 @@ static SourceCodeEditor* createCodeEditor (const File& file, SourceCodeDocument& | |||
| //============================================================================== | |||
| JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc) | |||
| : document (doc), | |||
| tabbedComponent (TabbedButtonBar::TabsAtTop), | |||
| compLayoutPanel (0), | |||
| lastViewportX (0), | |||
| lastViewportY (0), | |||
| currentZoomLevel (1.0) | |||
| tabbedComponent (doc) | |||
| { | |||
| setOpaque (true); | |||
| @@ -1028,9 +1024,7 @@ bool JucerDocumentEditor::perform (const InvocationInfo& info) | |||
| case StandardApplicationCommandIDs::paste: | |||
| { | |||
| ScopedPointer<XmlElement> doc (XmlDocument::parse (SystemClipboard::getTextFromClipboard())); | |||
| if (doc != nullptr) | |||
| if (ScopedPointer<XmlElement> doc = XmlDocument::parse (SystemClipboard::getTextFromClipboard())) | |||
| { | |||
| if (doc->hasTagName (ComponentLayout::clipboardXmlTag)) | |||
| { | |||
| @@ -1095,9 +1089,8 @@ bool JucerDocumentEditor::keyPressed (const KeyPress& key) | |||
| JucerDocumentEditor* JucerDocumentEditor::getActiveDocumentHolder() | |||
| { | |||
| ApplicationCommandInfo info (0); | |||
| ApplicationCommandTarget* target = ProjucerApplication::getCommandManager().getTargetForCommand (JucerCommandIDs::editCompLayout, info); | |||
| return dynamic_cast<JucerDocumentEditor*> (target); | |||
| return dynamic_cast<JucerDocumentEditor*> (ProjucerApplication::getCommandManager() | |||
| .getTargetForCommand (JucerCommandIDs::editCompLayout, info)); | |||
| } | |||
| Image JucerDocumentEditor::createComponentLayerSnapshot() const | |||
| @@ -1105,7 +1098,7 @@ Image JucerDocumentEditor::createComponentLayerSnapshot() const | |||
| if (compLayoutPanel != nullptr) | |||
| return compLayoutPanel->createComponentSnapshot(); | |||
| return Image(); | |||
| return {}; | |||
| } | |||
| const int gridSnapMenuItemBase = 0x8723620; | |||
| @@ -1187,13 +1180,13 @@ void createGUIEditorMenu (PopupMenu& menu) | |||
| void handleGUIEditorMenuCommand (int menuItemID) | |||
| { | |||
| if (JucerDocumentEditor* ed = JucerDocumentEditor::getActiveDocumentHolder()) | |||
| if (auto* ed = JucerDocumentEditor::getActiveDocumentHolder()) | |||
| { | |||
| int gridIndex = menuItemID - gridSnapMenuItemBase; | |||
| if (isPositiveAndBelow (gridIndex, numElementsInArray (snapSizes))) | |||
| { | |||
| JucerDocument& doc = *ed->getDocument(); | |||
| auto& doc = *ed->getDocument(); | |||
| doc.setSnappingGrid (snapSizes [gridIndex], | |||
| doc.isSnapActive (false), | |||
| @@ -58,28 +58,37 @@ public: | |||
| Image createComponentLayerSnapshot() const; | |||
| //============================================================================== | |||
| void paint (Graphics& g); | |||
| void resized(); | |||
| void changeListenerCallback (ChangeBroadcaster*); | |||
| bool keyPressed (const KeyPress&); | |||
| void paint (Graphics& g) override; | |||
| void resized() override; | |||
| void changeListenerCallback (ChangeBroadcaster*) override; | |||
| bool keyPressed (const KeyPress&) override; | |||
| //============================================================================== | |||
| ApplicationCommandTarget* getNextCommandTarget(); | |||
| void getAllCommands (Array <CommandID>&); | |||
| void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result); | |||
| bool perform (const InvocationInfo&); | |||
| ApplicationCommandTarget* getNextCommandTarget() override; | |||
| void getAllCommands (Array<CommandID>&) override; | |||
| void getCommandInfo (CommandID, ApplicationCommandInfo&) override; | |||
| bool perform (const InvocationInfo&) override; | |||
| static JucerDocumentEditor* getActiveDocumentHolder(); | |||
| private: | |||
| ScopedPointer<JucerDocument> document; | |||
| TabbedComponent tabbedComponent; | |||
| ComponentLayoutPanel* compLayoutPanel; | |||
| ComponentLayoutPanel* compLayoutPanel = nullptr; | |||
| bool isSomethingSelected() const; | |||
| int lastViewportX, lastViewportY; | |||
| struct JucerDocumentTabs : public TabbedComponent | |||
| { | |||
| JucerDocumentTabs (JucerDocument* d) : TabbedComponent (TabbedButtonBar::TabsAtTop), document (d) {} | |||
| void currentTabChanged (int, const String&) override { document->refreshCustomCodeFromDocument(); } | |||
| JucerDocument* document; | |||
| }; | |||
| JucerDocumentTabs tabbedComponent; | |||
| double currentZoomLevel; | |||
| int lastViewportX = 0, lastViewportY = 0; | |||
| double currentZoomLevel = 1.0; | |||
| bool isSomethingSelected() const; | |||
| // only non-zero if a layout tab is selected | |||
| ComponentLayout* getCurrentLayout() const; | |||
| @@ -89,6 +98,6 @@ private: | |||
| void setZoom (double scale); | |||
| double getZoom() const; | |||
| void addElement (const int index); | |||
| void addComponent (const int index); | |||
| void addElement (int index); | |||
| void addComponent (int index); | |||
| }; | |||
| @@ -36,23 +36,39 @@ namespace CodeHelpers | |||
| if (numSpaces == 0) | |||
| return code; | |||
| const String space (String::repeatedString (" ", numSpaces)); | |||
| auto space = String::repeatedString (" ", numSpaces); | |||
| auto lines = StringArray::fromLines (code); | |||
| StringArray lines; | |||
| lines.addLines (code); | |||
| for (int i = (indentFirstLine ? 0 : 1); i < lines.size(); ++i) | |||
| for (auto& line : lines) | |||
| { | |||
| String s (lines[i].trimEnd()); | |||
| if (s.isNotEmpty()) | |||
| s = space + s; | |||
| if (! indentFirstLine) | |||
| { | |||
| indentFirstLine = true; | |||
| continue; | |||
| } | |||
| lines.set (i, s); | |||
| if (line.trimEnd().isNotEmpty()) | |||
| line = space + line; | |||
| } | |||
| return lines.joinIntoString (newLine); | |||
| } | |||
| String unindent (const String& code, const int numSpaces) | |||
| { | |||
| if (numSpaces == 0) | |||
| return code; | |||
| auto space = String::repeatedString (" ", numSpaces); | |||
| auto lines = StringArray::fromLines (code); | |||
| for (auto& line : lines) | |||
| if (line.startsWith (space)) | |||
| line = line.substring (numSpaces); | |||
| return lines.joinIntoString (newLine); | |||
| } | |||
| String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates) | |||
| { | |||
| if (s.isEmpty()) | |||
| @@ -30,7 +30,8 @@ | |||
| //============================================================================== | |||
| namespace CodeHelpers | |||
| { | |||
| String indent (const String& code, const int numSpaces, bool indentFirstLine); | |||
| String indent (const String& code, int numSpaces, bool indentFirstLine); | |||
| String unindent (const String& code, int numSpaces); | |||
| String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates); | |||
| String createIncludeStatement (const File& includedFile, const File& targetFile); | |||
| String createIncludeStatement (const String& includePath); | |||
| @@ -41,7 +42,7 @@ namespace CodeHelpers | |||
| String floatLiteral (double value, int numDecPlaces); | |||
| String boolLiteral (bool value); | |||
| String colourToCode (Colour col); | |||
| String colourToCode (Colour); | |||
| String justificationToCode (Justification); | |||
| String alignFunctionCallParams (const String& call, const StringArray& parameters, int maxLineLength); | |||
| @@ -50,7 +51,7 @@ namespace CodeHelpers | |||
| bool breakAtNewLines, bool allowStringBreaks); | |||
| void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, | |||
| const StringArray& strings, const StringArray& codeToExecute, const int indentLevel); | |||
| const StringArray& strings, const StringArray& codeToExecute, int indentLevel); | |||
| String getLeadingWhitespace (String line); | |||
| int getBraceCount (String::CharPointerType line); | |||