Browse Source

Projucer: The GUI editor now generates paint code containing extra variables for the coordinates, so that these can be overridden individually in custom code blocks

tags/2021-05-28
jules 8 years ago
parent
commit
730e603b02
21 changed files with 496 additions and 298 deletions
  1. +5
    -0
      extras/Projucer/Source/ComponentEditor/documents/jucer_ComponentDocument.cpp
  2. +1
    -0
      extras/Projucer/Source/ComponentEditor/documents/jucer_ComponentDocument.h
  3. +1
    -1
      extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp
  4. +50
    -27
      extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp
  5. +11
    -5
      extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h
  6. +28
    -35
      extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp
  7. +2
    -0
      extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h
  8. +88
    -57
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_FillType.h
  9. +3
    -1
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h
  10. +44
    -26
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h
  11. +9
    -5
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h
  12. +41
    -31
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h
  13. +41
    -15
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp
  14. +2
    -0
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h
  15. +39
    -12
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h
  16. +43
    -25
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h
  17. +28
    -17
      extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h
  18. +7
    -14
      extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp
  19. +24
    -15
      extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h
  20. +25
    -9
      extras/Projucer/Source/Utility/jucer_CodeHelpers.cpp
  21. +4
    -3
      extras/Projucer/Source/Utility/jucer_CodeHelpers.h

+ 5
- 0
extras/Projucer/Source/ComponentEditor/documents/jucer_ComponentDocument.cpp View File

@@ -93,6 +93,11 @@ bool ComponentDocument::loadFromXml (const XmlElement& xml)
return false; return false;
} }
void ComponentDocument::applyCustomPaintSnippets (StringArray& snippets)
{
backgroundGraphics->applyCustomPaintSnippets (snippets);
}
//============================================================================== //==============================================================================
class NormalTestComponent : public Component class NormalTestComponent : public Component
{ {


+ 1
- 0
extras/Projucer/Source/ComponentEditor/documents/jucer_ComponentDocument.h View File

@@ -53,6 +53,7 @@ public:
bool loadFromXml (const XmlElement& xml); bool loadFromXml (const XmlElement& xml);
void fillInGeneratedCode (GeneratedCode& code) const; void fillInGeneratedCode (GeneratedCode& code) const;
void applyCustomPaintSnippets (StringArray&);
private: private:
ScopedPointer<ComponentLayout> components; ScopedPointer<ComponentLayout> components;


+ 1
- 1
extras/Projucer/Source/ComponentEditor/jucer_GeneratedCode.cpp View File

@@ -294,7 +294,7 @@ static void copyAcrossUserSections (String& dest, const String& src)
{ {
StringArray sourceLines; StringArray sourceLines;
if (getUserSection (srcLines, tag, sourceLines))
if (tag != "UserPaintCustomArguments" && getUserSection (srcLines, tag, sourceLines))
{ {
for (int j = endLine - i; --j > 0;) for (int j = endLine - i; --j > 0;)
dstLines.remove (i + 1); dstLines.remove (i + 1);


+ 50
- 27
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp View File

@@ -42,14 +42,7 @@ const char* const defaultParentClasses = "public Component";
JucerDocument::JucerDocument (SourceCodeDocument* c) JucerDocument::JucerDocument (SourceCodeDocument* c)
: cpp (c), : cpp (c),
className (defaultClassName), className (defaultClassName),
parentClasses (defaultParentClasses),
fixedSize (false),
initialWidth (600),
initialHeight (400),
snapGridPixels (8),
snapActive (true),
snapShown (true),
componentOverlayOpacity (0.33f)
parentClasses (defaultParentClasses)
{ {
jassert (cpp != nullptr); jassert (cpp != nullptr);
resources.setDocument (this); resources.setDocument (this);
@@ -599,13 +592,49 @@ bool JucerDocument::reloadFromDocument()
resources.loadFromCpp (getCppFile(), cppContent); 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) 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); 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) bool JucerDocument::isValidJucerCppFile (const File& f)
{ {
if (f.hasFileExtension (".cpp")) 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; return false;
} }
static JucerDocument* createDocument (SourceCodeDocument* cpp) static JucerDocument* createDocument (SourceCodeDocument* cpp)
{ {
CodeDocument& codeDoc = cpp->getCodeDocument();
auto& codeDoc = cpp->getCodeDocument();
ScopedPointer<XmlElement> xml (JucerDocument::pullMetaDataFromCppFile (codeDoc.getAllContent())); ScopedPointer<XmlElement> xml (JucerDocument::pullMetaDataFromCppFile (codeDoc.getAllContent()));
@@ -684,9 +711,9 @@ public:
bool saveHeader() 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 header->save();
return false; return false;
@@ -694,9 +721,7 @@ public:
Component* createEditor() override 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 new JucerDocumentEditor (jucerDoc.release());
return SourceCodeDocument::createEditor(); return SourceCodeDocument::createEditor();
@@ -736,15 +761,13 @@ public:
headerFile.replaceWithText (String()); headerFile.replaceWithText (String());
cppFile.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()); jucerDoc->setClassName (newFile.getFileNameWithoutExtension());


+ 11
- 5
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.h View File

@@ -136,14 +136,17 @@ public:
static bool shouldUseTransMacro() noexcept { return true; } static bool shouldUseTransMacro() noexcept { return true; }
//==============================================================================
void refreshCustomCodeFromDocument();
protected: protected:
SourceCodeDocument* cpp; SourceCodeDocument* cpp;
String className, componentName, templateFile; String className, componentName, templateFile;
String parentClasses, constructorParams, variableInitialisers; String parentClasses, constructorParams, variableInitialisers;
bool fixedSize;
int initialWidth, initialHeight;
bool fixedSize = false;
int initialWidth = 600, initialHeight = 400;
BinaryResources resources; BinaryResources resources;
@@ -153,6 +156,8 @@ protected:
virtual void fillInGeneratedCode (GeneratedCode&) const; virtual void fillInGeneratedCode (GeneratedCode&) const;
virtual void fillInPaintCode (GeneratedCode&) const; virtual void fillInPaintCode (GeneratedCode&) const;
virtual void applyCustomPaintSnippets (StringArray&) {}
static void addMethod (const String& base, const String& returnVal, static void addMethod (const String& base, const String& returnVal,
const String& method, const String& initialContent, const String& method, const String& initialContent,
StringArray& baseClasses, StringArray& returnValues, StringArray& baseClasses, StringArray& returnValues,
@@ -160,9 +165,9 @@ protected:
private: private:
UndoManager undoManager; UndoManager undoManager;
int snapGridPixels;
bool snapActive, snapShown;
float componentOverlayOpacity;
int snapGridPixels = 8;
bool snapActive = true, snapShown = true;
float componentOverlayOpacity = 0.33f;
StringArray activeExtraMethods; StringArray activeExtraMethods;
ScopedPointer<XmlElement> currentXML; ScopedPointer<XmlElement> currentXML;
ScopedPointer<Timer> userDocChangeTimer; ScopedPointer<Timer> userDocChangeTimer;
@@ -172,6 +177,7 @@ private:
void codeDocumentTextDeleted (int startIndex, int endIndex) override; void codeDocumentTextDeleted (int startIndex, int endIndex) override;
void userEditedCpp(); void userEditedCpp();
bool documentAboutToClose (OpenDocumentManager::Document*) override; bool documentAboutToClose (OpenDocumentManager::Document*) override;
void extractCustomPaintSnippetsFromCppFile (const String& cpp);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JucerDocument) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JucerDocument)
}; };

+ 28
- 35
extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.cpp View File

@@ -293,16 +293,9 @@ void PaintRoutine::copySelectedToClipboard()
XmlElement clip (clipboardXmlTag); 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)) if (selectedElements.isSelected (pe))
{
XmlElement* const e = pe->createXml();
clip.addChildElement (e);
}
}
clip.addChildElement (pe->createXml());
SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false)); SystemClipboard::copyTextToClipboard (clip.createDocument ("", false, false));
} }
@@ -325,8 +318,8 @@ void PaintRoutine::paste()
void PaintRoutine::deleteSelected() 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) if (temp2.getNumSelected() > 0)
{ {
@@ -369,7 +362,7 @@ void PaintRoutine::selectAll()
void PaintRoutine::selectedToFront() void PaintRoutine::selectedToFront()
{ {
const SelectedItemSet <PaintElement*> temp (selectedElements);
const SelectedItemSet<PaintElement*> temp (selectedElements);
for (int i = temp.getNumSelected(); --i >= 0;) for (int i = temp.getNumSelected(); --i >= 0;)
elementToFront (temp.getSelectedItem(i), true); elementToFront (temp.getSelectedItem(i), true);
@@ -377,7 +370,7 @@ void PaintRoutine::selectedToFront()
void PaintRoutine::selectedToBack() void PaintRoutine::selectedToBack()
{ {
const SelectedItemSet <PaintElement*> temp (selectedElements);
const SelectedItemSet<PaintElement*> temp (selectedElements);
for (int i = 0; i < temp.getNumSelected(); ++i) for (int i = 0; i < temp.getNumSelected(); ++i)
elementToBack (temp.getSelectedItem(i), true); elementToBack (temp.getSelectedItem(i), true);
@@ -399,11 +392,9 @@ void PaintRoutine::ungroupSelected()
void PaintRoutine::bringLostItemsBackOnScreen (const Rectangle<int>& parentArea) 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)) if (! r.intersects (parentArea))
{ {
@@ -415,11 +406,9 @@ void PaintRoutine::bringLostItemsBackOnScreen (const Rectangle<int>& parentArea)
void PaintRoutine::startDragging (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 ("xDragStart", r.getX());
c->getProperties().set ("yDragStart", r.getY()); c->getProperties().set ("yDragStart", r.getY());
@@ -490,8 +479,8 @@ void PaintRoutine::drawElements (Graphics& g, const Rectangle<int>& relativeTo)
Component temp; Component temp;
temp.setBounds (relativeTo); 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) if (d != nullptr)
{ {
Rectangle<float> bounds (d->getDrawableBounds());
auto bounds = d->getDrawableBounds();
d = nullptr; 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())); 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; resourceName = existingResource->name;
} }
@@ -546,12 +534,11 @@ const char* PaintRoutine::xmlTagName = "BACKGROUND";
XmlElement* PaintRoutine::createXml() const XmlElement* PaintRoutine::createXml() const
{ {
XmlElement* const xml = new XmlElement (xmlTagName);
auto* xml = new XmlElement (xmlTagName);
xml->setAttribute ("backgroundColour", backgroundColour.toString()); 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; return xml;
} }
@@ -565,7 +552,7 @@ bool PaintRoutine::loadFromXml (const XmlElement& xml)
clear(); clear();
forEachXmlChildElement (xml, e) forEachXmlChildElement (xml, e)
if (PaintElement* const newElement = ObjectTypes::createElementForXml (e, this))
if (auto* newElement = ObjectTypes::createElementForXml (e, this))
elements.add (newElement); elements.add (newElement);
return true; return true;
@@ -579,6 +566,12 @@ void PaintRoutine::fillInGeneratedCode (GeneratedCode& code, String& paintMethod
if (! backgroundColour.isTransparent()) if (! backgroundColour.isTransparent())
paintMethodCode << "g.fillAll (" << CodeHelpers::colourToCode (backgroundColour) << ");\n\n"; 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);
} }

+ 2
- 0
extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h View File

@@ -103,6 +103,8 @@ public:
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const; void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const;
void applyCustomPaintSnippets (StringArray&);
//============================================================================== //==============================================================================
private: private:
OwnedArray <PaintElement> elements; OwnedArray <PaintElement> elements;


+ 88
- 57
extras/Projucer/Source/ComponentEditor/paintelements/jucer_FillType.h View File

@@ -117,58 +117,89 @@ public:
} }
} }
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const
String generateVariablesCode (String type) const
{ {
String s; String s;
switch (mode) 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; 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; paintMethodCode += s;
@@ -178,29 +209,29 @@ public:
{ {
switch (mode) 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 {}; return {};


+ 3
- 1
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElement.h View File

@@ -94,6 +94,8 @@ public:
void changeListenerCallback (ChangeBroadcaster*); void changeListenerCallback (ChangeBroadcaster*);
void parentHierarchyChanged(); void parentHierarchyChanged();
virtual void applyCustomPaintSnippets (StringArray&) {}
int borderThickness; int borderThickness;
protected: protected:
@@ -159,7 +161,7 @@ public:
void changeListenerCallback (ChangeBroadcaster*) void changeListenerCallback (ChangeBroadcaster*)
{ {
jassert (propToRefresh != nullptr); jassert (propToRefresh != nullptr);
if (propToRefresh != nullptr)
if (propToRefresh != nullptr && owner != nullptr)
propToRefresh->refresh(); propToRefresh->refresh();
} }


+ 44
- 26
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementEllipse.h View File

@@ -62,35 +62,53 @@ public:
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) 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()) 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()) 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: private:
String customPaintCode;
//============================================================================== //==============================================================================
class ShapeToPathProperty : public ButtonPropertyComponent
struct ShapeToPathProperty : public ButtonPropertyComponent
{ {
public:
ShapeToPathProperty (PaintElementEllipse* const e) ShapeToPathProperty (PaintElementEllipse* const e)
: ButtonPropertyComponent ("path", false), : ButtonPropertyComponent ("path", false),
element (e) element (e)
@@ -151,7 +170,6 @@ private:
return "convert to a path"; return "convert to a path";
} }
private:
PaintElementEllipse* const element;
PaintElementEllipse* element;
}; };
}; };

+ 9
- 5
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementGroup.h View File

@@ -209,12 +209,17 @@ public:
return false; return false;
} }
void applyCustomPaintSnippets (StringArray& snippets)
{
for (auto* e : subElements)
e->applyCustomPaintSnippets (snippets);
}
private: private:
OwnedArray <PaintElement> subElements;
OwnedArray<PaintElement> subElements;
class UngroupProperty : public ButtonPropertyComponent
struct UngroupProperty : public ButtonPropertyComponent
{ {
public:
UngroupProperty (PaintElementGroup* const e) UngroupProperty (PaintElementGroup* const e)
: ButtonPropertyComponent ("ungroup", false), : ButtonPropertyComponent ("ungroup", false),
element (e) element (e)
@@ -231,7 +236,6 @@ private:
return "Ungroup"; return "Ungroup";
} }
private:
PaintElementGroup* const element;
PaintElementGroup* element;
}; };
}; };

+ 41
- 31
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementImage.h View File

@@ -95,10 +95,16 @@ public:
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
{ {
String r;
if (opacity > 0) 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) if (dynamic_cast<const DrawableImage*> (getDrawable()) != 0)
{ {
const String imageVariable ("cachedImage_" + resourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix())); const String imageVariable ("cachedImage_" + resourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix()));
@@ -106,36 +112,32 @@ public:
code.addImageResourceLoader (imageVariable, resourceName); code.addImageResourceLoader (imageVariable, resourceName);
if (opacity >= 254.0 / 255.0) if (opacity >= 254.0 / 255.0)
r << "g.setColour (Colours::black);\n";
r << " g.setColour (Colours::black);\n";
else 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) 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 else
{ {
r << "g.drawImageWithin (" << imageVariable << ",\n "
<< x << ", " << y << ", " << w << ", " << h
<< ",\n ";
r << " g.drawImageWithin (" << imageVariable << ",\n"
<< " x, y, width, height,\n"
<< " ";
if (mode == proportionalReducingOnly) if (mode == proportionalReducingOnly)
r << "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"; r << "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize";
else else
r << "RectanglePlacement::centred"; r << "RectanglePlacement::centred";
r << ",\n false);\n\n";
r << ",\n"
<< " false);\n";
} }
paintMethodCode += r;
} }
else else
{ {
@@ -154,28 +156,35 @@ public:
<< imageVariable << " = nullptr;\n"; << imageVariable << " = nullptr;\n";
if (opacity >= 254.0 / 255.0) if (opacity >= 254.0 / 255.0)
r << "g.setColour (Colours::black);\n";
r << " g.setColour (Colours::black);\n";
else 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 == stretched ? "RectanglePlacement::stretchToFit"
: (mode == proportionalReducingOnly ? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize" : (mode == proportionalReducingOnly ? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"
: "RectanglePlacement::centred")) : "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; String resourceName;
double opacity; double opacity;
StretchMode mode; StretchMode mode;
String customPaintCode;
//============================================================================== //==============================================================================
class ImageElementResourceProperty : public ImageResourceProperty <PaintElementImage> class ImageElementResourceProperty : public ImageResourceProperty <PaintElementImage>


+ 41
- 15
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.cpp View File

@@ -382,10 +382,8 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe
if (! nonZeroWinding) if (! nonZeroWinding)
r << pathVariable << ".setUsingNonZeroWinding (false);\n"; 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) switch (p->type)
{ {
case Path::Iterator::startNewSubPath: case Path::Iterator::startNewSubPath:
@@ -400,15 +398,17 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe
case Path::Iterator::quadraticTo: case Path::Iterator::quadraticTo:
r << pathVariable << ".quadraticTo (" << positionToPairOfValues (p->pos[0], layout) 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[0].rect.isPositionAbsolute();
somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute(); somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute();
break; break;
case Path::Iterator::cubicTo: case Path::Iterator::cubicTo:
r << pathVariable << ".cubicTo (" << positionToPairOfValues (p->pos[0], layout) 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[0].rect.isPositionAbsolute();
somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute(); somePointsAreRelative = somePointsAreRelative || ! p->pos[1].rect.isPositionAbsolute();
somePointsAreRelative = somePointsAreRelative || ! p->pos[2].rect.isPositionAbsolute(); somePointsAreRelative = somePointsAreRelative || ! p->pos[2].rect.isPositionAbsolute();
@@ -432,24 +432,50 @@ void PaintElementPath::fillInGeneratedCode (GeneratedCode& code, String& paintMe
else else
code.constructorCode << r; code.constructorCode << r;
String s;
s << "{\n"
<< " float x = 0, y = 0;\n";
if (! fillType.isInvisible()) 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()) 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);
}
} }
//============================================================================== //==============================================================================


+ 2
- 0
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementPath.h View File

@@ -101,6 +101,7 @@ public:
void getEditableProperties (Array<PropertyComponent*>& props); void getEditableProperties (Array<PropertyComponent*>& props);
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode); void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode);
void applyCustomPaintSnippets (StringArray& snippets);
//============================================================================== //==============================================================================
static const char* getTagName() noexcept { return "PATH"; } static const char* getTagName() noexcept { return "PATH"; }
@@ -132,6 +133,7 @@ private:
mutable Rectangle<int> lastPathBounds; mutable Rectangle<int> lastPathBounds;
int mouseDownOnSegment; int mouseDownOnSegment;
bool mouseDownSelectSegmentStatus; bool mouseDownSelectSegmentStatus;
String customPaintCode;
String pathToString() const; String pathToString() const;
void restorePathFromString (const String& s); void restorePathFromString (const String& s);


+ 39
- 12
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRectangle.h View File

@@ -76,27 +76,52 @@ public:
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) 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()) 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()) 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: private:
String customPaintCode;
class ShapeToPathProperty : public ButtonPropertyComponent class ShapeToPathProperty : public ButtonPropertyComponent
{ {
public: public:


+ 43
- 25
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementRoundedRectangle.h View File

@@ -116,37 +116,54 @@ public:
//============================================================================== //==============================================================================
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) 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()) 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()) 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: private:
double cornerSize; double cornerSize;
String customPaintCode;
//============================================================================== //==============================================================================
class CornerSizeProperty : public SliderPropertyComponent, class CornerSizeProperty : public SliderPropertyComponent,


+ 28
- 17
extras/Projucer/Source/ComponentEditor/paintelements/jucer_PaintElementText.h View File

@@ -83,27 +83,37 @@ public:
{ {
if (! fillType.isInvisible()) 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); 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; 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"; } static const char* getTagName() noexcept { return "TEXT"; }
XmlElement* createXml() const XmlElement* createXml() const
@@ -376,7 +386,8 @@ private:
Font font; Font font;
String typefaceName; String typefaceName;
Justification justification; Justification justification;
String customPaintCode;
Array <Justification> justificationTypes; Array <Justification> justificationTypes;
//============================================================================== //==============================================================================


+ 7
- 14
extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.cpp View File

@@ -318,11 +318,7 @@ static SourceCodeEditor* createCodeEditor (const File& file, SourceCodeDocument&
//============================================================================== //==============================================================================
JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc) JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc)
: document (doc), : document (doc),
tabbedComponent (TabbedButtonBar::TabsAtTop),
compLayoutPanel (0),
lastViewportX (0),
lastViewportY (0),
currentZoomLevel (1.0)
tabbedComponent (doc)
{ {
setOpaque (true); setOpaque (true);
@@ -1028,9 +1024,7 @@ bool JucerDocumentEditor::perform (const InvocationInfo& info)
case StandardApplicationCommandIDs::paste: 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)) if (doc->hasTagName (ComponentLayout::clipboardXmlTag))
{ {
@@ -1095,9 +1089,8 @@ bool JucerDocumentEditor::keyPressed (const KeyPress& key)
JucerDocumentEditor* JucerDocumentEditor::getActiveDocumentHolder() JucerDocumentEditor* JucerDocumentEditor::getActiveDocumentHolder()
{ {
ApplicationCommandInfo info (0); 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 Image JucerDocumentEditor::createComponentLayerSnapshot() const
@@ -1105,7 +1098,7 @@ Image JucerDocumentEditor::createComponentLayerSnapshot() const
if (compLayoutPanel != nullptr) if (compLayoutPanel != nullptr)
return compLayoutPanel->createComponentSnapshot(); return compLayoutPanel->createComponentSnapshot();
return Image();
return {};
} }
const int gridSnapMenuItemBase = 0x8723620; const int gridSnapMenuItemBase = 0x8723620;
@@ -1187,13 +1180,13 @@ void createGUIEditorMenu (PopupMenu& menu)
void handleGUIEditorMenuCommand (int menuItemID) void handleGUIEditorMenuCommand (int menuItemID)
{ {
if (JucerDocumentEditor* ed = JucerDocumentEditor::getActiveDocumentHolder())
if (auto* ed = JucerDocumentEditor::getActiveDocumentHolder())
{ {
int gridIndex = menuItemID - gridSnapMenuItemBase; int gridIndex = menuItemID - gridSnapMenuItemBase;
if (isPositiveAndBelow (gridIndex, numElementsInArray (snapSizes))) if (isPositiveAndBelow (gridIndex, numElementsInArray (snapSizes)))
{ {
JucerDocument& doc = *ed->getDocument();
auto& doc = *ed->getDocument();
doc.setSnappingGrid (snapSizes [gridIndex], doc.setSnappingGrid (snapSizes [gridIndex],
doc.isSnapActive (false), doc.isSnapActive (false),


+ 24
- 15
extras/Projucer/Source/ComponentEditor/ui/jucer_JucerDocumentEditor.h View File

@@ -58,28 +58,37 @@ public:
Image createComponentLayerSnapshot() const; 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(); static JucerDocumentEditor* getActiveDocumentHolder();
private: private:
ScopedPointer<JucerDocument> document; 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 // only non-zero if a layout tab is selected
ComponentLayout* getCurrentLayout() const; ComponentLayout* getCurrentLayout() const;
@@ -89,6 +98,6 @@ private:
void setZoom (double scale); void setZoom (double scale);
double getZoom() const; double getZoom() const;
void addElement (const int index);
void addComponent (const int index);
void addElement (int index);
void addComponent (int index);
}; };

+ 25
- 9
extras/Projucer/Source/Utility/jucer_CodeHelpers.cpp View File

@@ -36,23 +36,39 @@ namespace CodeHelpers
if (numSpaces == 0) if (numSpaces == 0)
return code; 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); 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) String makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates)
{ {
if (s.isEmpty()) if (s.isEmpty())


+ 4
- 3
extras/Projucer/Source/Utility/jucer_CodeHelpers.h View File

@@ -30,7 +30,8 @@
//============================================================================== //==============================================================================
namespace CodeHelpers 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 makeValidIdentifier (String s, bool capitalise, bool removeColons, bool allowTemplates);
String createIncludeStatement (const File& includedFile, const File& targetFile); String createIncludeStatement (const File& includedFile, const File& targetFile);
String createIncludeStatement (const String& includePath); String createIncludeStatement (const String& includePath);
@@ -41,7 +42,7 @@ namespace CodeHelpers
String floatLiteral (double value, int numDecPlaces); String floatLiteral (double value, int numDecPlaces);
String boolLiteral (bool value); String boolLiteral (bool value);
String colourToCode (Colour col);
String colourToCode (Colour);
String justificationToCode (Justification); String justificationToCode (Justification);
String alignFunctionCallParams (const String& call, const StringArray& parameters, int maxLineLength); String alignFunctionCallParams (const String& call, const StringArray& parameters, int maxLineLength);
@@ -50,7 +51,7 @@ namespace CodeHelpers
bool breakAtNewLines, bool allowStringBreaks); bool breakAtNewLines, bool allowStringBreaks);
void createStringMatcher (OutputStream& out, const String& utf8PointerVariable, 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); String getLeadingWhitespace (String line);
int getBraceCount (String::CharPointerType line); int getBraceCount (String::CharPointerType line);


Loading…
Cancel
Save