migrating to the latest JUCE version
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -1,80 +1,80 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_PaintRoutine.h"
|
||||
#include "../jucer_JucerDocument.h"
|
||||
#include "jucer_StrokeType.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for paint elements that have a fill colour and stroke.
|
||||
|
||||
*/
|
||||
class ColouredElement : public PaintElement
|
||||
{
|
||||
public:
|
||||
ColouredElement (PaintRoutine* owner,
|
||||
const String& name,
|
||||
const bool showOutline_,
|
||||
const bool showJointAndEnd_);
|
||||
|
||||
~ColouredElement() override;
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;
|
||||
void getColourSpecificProperties (Array<PropertyComponent*>& props);
|
||||
|
||||
//==============================================================================
|
||||
const JucerFillType& getFillType() noexcept;
|
||||
void setFillType (const JucerFillType& newType, const bool undoable);
|
||||
|
||||
bool isStrokeEnabled() const noexcept;
|
||||
void enableStroke (bool enable, const bool undoable);
|
||||
|
||||
const StrokeType& getStrokeType() noexcept;
|
||||
void setStrokeType (const PathStrokeType& newType, const bool undoable);
|
||||
void setStrokeFill (const JucerFillType& newType, const bool undoable);
|
||||
|
||||
//==============================================================================
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;
|
||||
void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& parentArea, const bool undoable) override;
|
||||
|
||||
void createSiblingComponents() override;
|
||||
|
||||
//==============================================================================
|
||||
void addColourAttributes (XmlElement* const e) const;
|
||||
bool loadColourAttributes (const XmlElement& xml);
|
||||
|
||||
protected:
|
||||
JucerFillType fillType;
|
||||
|
||||
bool isStrokePresent;
|
||||
const bool showOutline, showJointAndEnd;
|
||||
StrokeType strokeType;
|
||||
|
||||
void convertToNewPathElement (const Path& path);
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_PaintRoutine.h"
|
||||
#include "../jucer_JucerDocument.h"
|
||||
#include "jucer_StrokeType.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for paint elements that have a fill colour and stroke.
|
||||
|
||||
*/
|
||||
class ColouredElement : public PaintElement
|
||||
{
|
||||
public:
|
||||
ColouredElement (PaintRoutine* owner,
|
||||
const String& name,
|
||||
const bool showOutline_,
|
||||
const bool showJointAndEnd_);
|
||||
|
||||
~ColouredElement() override;
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;
|
||||
void getColourSpecificProperties (Array<PropertyComponent*>& props);
|
||||
|
||||
//==============================================================================
|
||||
const JucerFillType& getFillType() noexcept;
|
||||
void setFillType (const JucerFillType& newType, const bool undoable);
|
||||
|
||||
bool isStrokeEnabled() const noexcept;
|
||||
void enableStroke (bool enable, const bool undoable);
|
||||
|
||||
const StrokeType& getStrokeType() noexcept;
|
||||
void setStrokeType (const PathStrokeType& newType, const bool undoable);
|
||||
void setStrokeFill (const JucerFillType& newType, const bool undoable);
|
||||
|
||||
//==============================================================================
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;
|
||||
void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& parentArea, const bool undoable) override;
|
||||
|
||||
void createSiblingComponents() override;
|
||||
|
||||
//==============================================================================
|
||||
void addColourAttributes (XmlElement* const e) const;
|
||||
bool loadColourAttributes (const XmlElement& xml);
|
||||
|
||||
protected:
|
||||
JucerFillType fillType;
|
||||
|
||||
bool isStrokePresent;
|
||||
const bool showOutline, showJointAndEnd;
|
||||
StrokeType strokeType;
|
||||
|
||||
void convertToNewPathElement (const Path& path);
|
||||
};
|
||||
|
@ -1,55 +1,55 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//==============================================================================
|
||||
class ElementSiblingComponent : public Component,
|
||||
public ChangeListener
|
||||
{
|
||||
public:
|
||||
ElementSiblingComponent (PaintElement* const owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
setAlwaysOnTop (true);
|
||||
|
||||
owner->getDocument()->addChangeListener (this);
|
||||
}
|
||||
|
||||
~ElementSiblingComponent() override
|
||||
{
|
||||
owner->getDocument()->removeChangeListener (this);
|
||||
}
|
||||
|
||||
virtual void updatePosition() = 0;
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
protected:
|
||||
PaintElement* const owner;
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//==============================================================================
|
||||
class ElementSiblingComponent : public Component,
|
||||
public ChangeListener
|
||||
{
|
||||
public:
|
||||
ElementSiblingComponent (PaintElement* const owner_)
|
||||
: owner (owner_)
|
||||
{
|
||||
setAlwaysOnTop (true);
|
||||
|
||||
owner->getDocument()->addChangeListener (this);
|
||||
}
|
||||
|
||||
~ElementSiblingComponent() override
|
||||
{
|
||||
owner->getDocument()->removeChangeListener (this);
|
||||
}
|
||||
|
||||
virtual void updatePosition() = 0;
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
protected:
|
||||
PaintElement* const owner;
|
||||
};
|
||||
|
@ -1,427 +1,427 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_JucerDocument.h"
|
||||
#include "../jucer_UtilityFunctions.h"
|
||||
#include "../../ProjectSaving/jucer_ResourceFile.h"
|
||||
|
||||
//==============================================================================
|
||||
class JucerFillType
|
||||
{
|
||||
public:
|
||||
JucerFillType()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
JucerFillType (const JucerFillType& other)
|
||||
{
|
||||
image = Image();
|
||||
mode = other.mode;
|
||||
colour = other.colour;
|
||||
gradCol1 = other.gradCol1;
|
||||
gradCol2 = other.gradCol2;
|
||||
gradPos1 = other.gradPos1;
|
||||
gradPos2 = other.gradPos2;
|
||||
imageResourceName = other.imageResourceName;
|
||||
imageOpacity = other.imageOpacity;
|
||||
imageAnchor = other.imageAnchor;
|
||||
}
|
||||
|
||||
JucerFillType& operator= (const JucerFillType& other)
|
||||
{
|
||||
image = Image();
|
||||
mode = other.mode;
|
||||
colour = other.colour;
|
||||
gradCol1 = other.gradCol1;
|
||||
gradCol2 = other.gradCol2;
|
||||
gradPos1 = other.gradPos1;
|
||||
gradPos2 = other.gradPos2;
|
||||
imageResourceName = other.imageResourceName;
|
||||
imageOpacity = other.imageOpacity;
|
||||
imageAnchor = other.imageAnchor;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const JucerFillType& other) const
|
||||
{
|
||||
return mode == other.mode
|
||||
&& colour == other.colour
|
||||
&& gradCol1 == other.gradCol1
|
||||
&& gradCol2 == other.gradCol2
|
||||
&& gradPos1 == other.gradPos1
|
||||
&& gradPos2 == other.gradPos2
|
||||
&& imageResourceName == other.imageResourceName
|
||||
&& imageOpacity == other.imageOpacity
|
||||
&& imageAnchor == other.imageAnchor;
|
||||
}
|
||||
|
||||
bool operator!= (const JucerFillType& other) const
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void setFillType (Graphics& g, JucerDocument* const document, const Rectangle<int>& parentArea)
|
||||
{
|
||||
if (document == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == solidColour)
|
||||
{
|
||||
image = Image();
|
||||
g.setColour (colour);
|
||||
}
|
||||
else if (mode == imageBrush)
|
||||
{
|
||||
loadImage (document);
|
||||
|
||||
Rectangle<int> r (imageAnchor.getRectangle (parentArea, document->getComponentLayout()));
|
||||
|
||||
g.setTiledImageFill (image, r.getX(), r.getY(), (float) imageOpacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = Image();
|
||||
|
||||
Rectangle<int> r1 (gradPos1.getRectangle (parentArea, document->getComponentLayout()));
|
||||
Rectangle<int> r2 (gradPos2.getRectangle (parentArea, document->getComponentLayout()));
|
||||
|
||||
g.setGradientFill (ColourGradient (gradCol1, (float) r1.getX(), (float) r1.getY(),
|
||||
gradCol2, (float) r2.getX(), (float) r2.getY(),
|
||||
mode == radialGradient));
|
||||
}
|
||||
}
|
||||
|
||||
String generateVariablesCode (String type) const
|
||||
{
|
||||
String s;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
s << "juce::Colour " << type << "Colour = " << CodeHelpers::colourToCode (colour) << ";\n";
|
||||
break;
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
s << "juce::Colour " << type << "Colour1 = " << CodeHelpers::colourToCode (gradCol1) << ", " << type << "Colour2 = " << CodeHelpers::colourToCode (gradCol2) << ";\n";
|
||||
break;
|
||||
|
||||
case imageBrush:
|
||||
break;
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
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 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 (juce::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;
|
||||
}
|
||||
|
||||
case imageBrush:
|
||||
{
|
||||
auto imageVariable = "cachedImage_" + imageResourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix());
|
||||
|
||||
code.addImageResourceLoader (imageVariable, imageResourceName);
|
||||
|
||||
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);
|
||||
|
||||
s << "g.setTiledImageFill (";
|
||||
|
||||
const String indent (String::repeatedString (" ", s.length()));
|
||||
|
||||
s << imageVariable << ",\n"
|
||||
<< indent << x1 << " - " << x0 << " + x,\n"
|
||||
<< indent << y1 << " - " << y0 << " + y,\n"
|
||||
<< indent << CodeHelpers::floatLiteral (imageOpacity, 4) << ");\n";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
paintMethodCode += s;
|
||||
}
|
||||
|
||||
String toString() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void restoreFromString (const String& s)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (s.isNotEmpty())
|
||||
{
|
||||
StringArray toks;
|
||||
toks.addTokens (s, ",:", StringRef());
|
||||
toks.trim();
|
||||
|
||||
if (toks[0] == "solid")
|
||||
{
|
||||
mode = solidColour;
|
||||
colour = Colour::fromString (toks[1]);
|
||||
}
|
||||
else if (toks[0] == "linear"
|
||||
|| toks[0] == "radial")
|
||||
{
|
||||
mode = (toks[0] == "linear") ? linearGradient : radialGradient;
|
||||
|
||||
gradPos1 = RelativePositionedRectangle();
|
||||
gradPos1.rect = PositionedRectangle (toks[1]);
|
||||
gradPos2 = RelativePositionedRectangle();
|
||||
gradPos2.rect = PositionedRectangle (toks[2]);
|
||||
|
||||
gradCol1 = Colour::fromString (toks[3].fromFirstOccurrenceOf ("=", false, false));
|
||||
gradCol2 = Colour::fromString (toks[4].fromFirstOccurrenceOf ("=", false, false));
|
||||
}
|
||||
else if (toks[0] == "image")
|
||||
{
|
||||
mode = imageBrush;
|
||||
imageResourceName = toks[1].replaceCharacter ('#', ':');
|
||||
imageOpacity = toks[2].getDoubleValue();
|
||||
imageAnchor= RelativePositionedRectangle();
|
||||
imageAnchor.rect = PositionedRectangle (toks[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isOpaque() const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
return colour.isOpaque();
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
return gradCol1.isOpaque() && gradCol2.isOpaque();
|
||||
|
||||
case imageBrush:
|
||||
return image.isValid()
|
||||
&& imageOpacity >= 1.0f
|
||||
&& ! image.hasAlphaChannel();
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInvisible() const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
return colour.isTransparent();
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
return gradCol1.isTransparent() && gradCol2.isTransparent();
|
||||
|
||||
case imageBrush:
|
||||
return imageOpacity == 0.0;
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
enum FillMode
|
||||
{
|
||||
solidColour,
|
||||
linearGradient,
|
||||
radialGradient,
|
||||
imageBrush
|
||||
};
|
||||
|
||||
FillMode mode;
|
||||
Colour colour, gradCol1, gradCol2;
|
||||
|
||||
// just the x, y, of these are used
|
||||
RelativePositionedRectangle gradPos1, gradPos2;
|
||||
|
||||
String imageResourceName;
|
||||
double imageOpacity;
|
||||
RelativePositionedRectangle imageAnchor;
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
Image image;
|
||||
|
||||
void reset()
|
||||
{
|
||||
image = Image();
|
||||
mode = solidColour;
|
||||
colour = Colours::brown.withHue (Random::getSystemRandom().nextFloat());
|
||||
gradCol1 = Colours::red;
|
||||
gradCol2 = Colours::green;
|
||||
gradPos1 = RelativePositionedRectangle();
|
||||
gradPos1.rect = PositionedRectangle ("50 50");
|
||||
gradPos2 = RelativePositionedRectangle();
|
||||
gradPos2.rect = PositionedRectangle ("100 100");
|
||||
|
||||
imageResourceName.clear();
|
||||
imageOpacity = 1.0;
|
||||
imageAnchor = RelativePositionedRectangle();
|
||||
imageAnchor.rect = PositionedRectangle ("0 0");
|
||||
}
|
||||
|
||||
void loadImage (JucerDocument* const document)
|
||||
{
|
||||
if (image.isNull())
|
||||
{
|
||||
if (document != nullptr)
|
||||
{
|
||||
if (imageResourceName.contains ("::"))
|
||||
{
|
||||
if (Project* project = document->getCppDocument().getProject())
|
||||
{
|
||||
JucerResourceFile resourceFile (*project);
|
||||
|
||||
for (int i = 0; i < resourceFile.getNumFiles(); ++i)
|
||||
{
|
||||
const File& file = resourceFile.getFile(i);
|
||||
|
||||
if (imageResourceName == resourceFile.getClassName() + "::" + resourceFile.getDataVariableFor (file))
|
||||
{
|
||||
image = ImageCache::getFromFile (file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = document->getResources().getImageFromCache (imageResourceName);
|
||||
}
|
||||
}
|
||||
|
||||
if (image.isNull())
|
||||
{
|
||||
const int hashCode = 0x3437856f;
|
||||
image = ImageCache::getFromHashCode (hashCode);
|
||||
|
||||
if (image.isNull())
|
||||
{
|
||||
image = Image (Image::RGB, 100, 100, true);
|
||||
|
||||
Graphics g (image);
|
||||
g.fillCheckerBoard (image.getBounds().toFloat(),
|
||||
(float) image.getWidth() * 0.5f, (float) image.getHeight() * 0.5f,
|
||||
Colours::white, Colours::lightgrey);
|
||||
|
||||
g.setFont (12.0f);
|
||||
g.setColour (Colours::grey);
|
||||
g.drawText ("(image missing)", 0, 0, image.getWidth(), image.getHeight() / 2, Justification::centred, true);
|
||||
|
||||
ImageCache::addImageToCache (image, hashCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_JucerDocument.h"
|
||||
#include "../jucer_UtilityFunctions.h"
|
||||
#include "../../ProjectSaving/jucer_ResourceFile.h"
|
||||
|
||||
//==============================================================================
|
||||
class JucerFillType
|
||||
{
|
||||
public:
|
||||
JucerFillType()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
JucerFillType (const JucerFillType& other)
|
||||
{
|
||||
image = Image();
|
||||
mode = other.mode;
|
||||
colour = other.colour;
|
||||
gradCol1 = other.gradCol1;
|
||||
gradCol2 = other.gradCol2;
|
||||
gradPos1 = other.gradPos1;
|
||||
gradPos2 = other.gradPos2;
|
||||
imageResourceName = other.imageResourceName;
|
||||
imageOpacity = other.imageOpacity;
|
||||
imageAnchor = other.imageAnchor;
|
||||
}
|
||||
|
||||
JucerFillType& operator= (const JucerFillType& other)
|
||||
{
|
||||
image = Image();
|
||||
mode = other.mode;
|
||||
colour = other.colour;
|
||||
gradCol1 = other.gradCol1;
|
||||
gradCol2 = other.gradCol2;
|
||||
gradPos1 = other.gradPos1;
|
||||
gradPos2 = other.gradPos2;
|
||||
imageResourceName = other.imageResourceName;
|
||||
imageOpacity = other.imageOpacity;
|
||||
imageAnchor = other.imageAnchor;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const JucerFillType& other) const
|
||||
{
|
||||
return mode == other.mode
|
||||
&& colour == other.colour
|
||||
&& gradCol1 == other.gradCol1
|
||||
&& gradCol2 == other.gradCol2
|
||||
&& gradPos1 == other.gradPos1
|
||||
&& gradPos2 == other.gradPos2
|
||||
&& imageResourceName == other.imageResourceName
|
||||
&& imageOpacity == other.imageOpacity
|
||||
&& imageAnchor == other.imageAnchor;
|
||||
}
|
||||
|
||||
bool operator!= (const JucerFillType& other) const
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void setFillType (Graphics& g, JucerDocument* const document, const Rectangle<int>& parentArea)
|
||||
{
|
||||
if (document == nullptr)
|
||||
{
|
||||
jassertfalse;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == solidColour)
|
||||
{
|
||||
image = Image();
|
||||
g.setColour (colour);
|
||||
}
|
||||
else if (mode == imageBrush)
|
||||
{
|
||||
loadImage (document);
|
||||
|
||||
Rectangle<int> r (imageAnchor.getRectangle (parentArea, document->getComponentLayout()));
|
||||
|
||||
g.setTiledImageFill (image, r.getX(), r.getY(), (float) imageOpacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = Image();
|
||||
|
||||
Rectangle<int> r1 (gradPos1.getRectangle (parentArea, document->getComponentLayout()));
|
||||
Rectangle<int> r2 (gradPos2.getRectangle (parentArea, document->getComponentLayout()));
|
||||
|
||||
g.setGradientFill (ColourGradient (gradCol1, (float) r1.getX(), (float) r1.getY(),
|
||||
gradCol2, (float) r2.getX(), (float) r2.getY(),
|
||||
mode == radialGradient));
|
||||
}
|
||||
}
|
||||
|
||||
String generateVariablesCode (String type) const
|
||||
{
|
||||
String s;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
s << "juce::Colour " << type << "Colour = " << CodeHelpers::colourToCode (colour) << ";\n";
|
||||
break;
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
s << "juce::Colour " << type << "Colour1 = " << CodeHelpers::colourToCode (gradCol1) << ", " << type << "Colour2 = " << CodeHelpers::colourToCode (gradCol2) << ";\n";
|
||||
break;
|
||||
|
||||
case imageBrush:
|
||||
break;
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
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 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 (juce::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;
|
||||
}
|
||||
|
||||
case imageBrush:
|
||||
{
|
||||
auto imageVariable = "cachedImage_" + imageResourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix());
|
||||
|
||||
code.addImageResourceLoader (imageVariable, imageResourceName);
|
||||
|
||||
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);
|
||||
|
||||
s << "g.setTiledImageFill (";
|
||||
|
||||
const String indent (String::repeatedString (" ", s.length()));
|
||||
|
||||
s << imageVariable << ",\n"
|
||||
<< indent << x1 << " - " << x0 << " + x,\n"
|
||||
<< indent << y1 << " - " << y0 << " + y,\n"
|
||||
<< indent << CodeHelpers::floatLiteral (imageOpacity, 4) << ");\n";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
paintMethodCode += s;
|
||||
}
|
||||
|
||||
String toString() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void restoreFromString (const String& s)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (s.isNotEmpty())
|
||||
{
|
||||
StringArray toks;
|
||||
toks.addTokens (s, ",:", StringRef());
|
||||
toks.trim();
|
||||
|
||||
if (toks[0] == "solid")
|
||||
{
|
||||
mode = solidColour;
|
||||
colour = Colour::fromString (toks[1]);
|
||||
}
|
||||
else if (toks[0] == "linear"
|
||||
|| toks[0] == "radial")
|
||||
{
|
||||
mode = (toks[0] == "linear") ? linearGradient : radialGradient;
|
||||
|
||||
gradPos1 = RelativePositionedRectangle();
|
||||
gradPos1.rect = PositionedRectangle (toks[1]);
|
||||
gradPos2 = RelativePositionedRectangle();
|
||||
gradPos2.rect = PositionedRectangle (toks[2]);
|
||||
|
||||
gradCol1 = Colour::fromString (toks[3].fromFirstOccurrenceOf ("=", false, false));
|
||||
gradCol2 = Colour::fromString (toks[4].fromFirstOccurrenceOf ("=", false, false));
|
||||
}
|
||||
else if (toks[0] == "image")
|
||||
{
|
||||
mode = imageBrush;
|
||||
imageResourceName = toks[1].replaceCharacter ('#', ':');
|
||||
imageOpacity = toks[2].getDoubleValue();
|
||||
imageAnchor= RelativePositionedRectangle();
|
||||
imageAnchor.rect = PositionedRectangle (toks[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isOpaque() const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
return colour.isOpaque();
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
return gradCol1.isOpaque() && gradCol2.isOpaque();
|
||||
|
||||
case imageBrush:
|
||||
return image.isValid()
|
||||
&& imageOpacity >= 1.0f
|
||||
&& ! image.hasAlphaChannel();
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isInvisible() const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case solidColour:
|
||||
return colour.isTransparent();
|
||||
|
||||
case linearGradient:
|
||||
case radialGradient:
|
||||
return gradCol1.isTransparent() && gradCol2.isTransparent();
|
||||
|
||||
case imageBrush:
|
||||
return imageOpacity == 0.0;
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
enum FillMode
|
||||
{
|
||||
solidColour,
|
||||
linearGradient,
|
||||
radialGradient,
|
||||
imageBrush
|
||||
};
|
||||
|
||||
FillMode mode;
|
||||
Colour colour, gradCol1, gradCol2;
|
||||
|
||||
// just the x, y, of these are used
|
||||
RelativePositionedRectangle gradPos1, gradPos2;
|
||||
|
||||
String imageResourceName;
|
||||
double imageOpacity;
|
||||
RelativePositionedRectangle imageAnchor;
|
||||
|
||||
//==============================================================================
|
||||
private:
|
||||
Image image;
|
||||
|
||||
void reset()
|
||||
{
|
||||
image = Image();
|
||||
mode = solidColour;
|
||||
colour = Colours::brown.withHue (Random::getSystemRandom().nextFloat());
|
||||
gradCol1 = Colours::red;
|
||||
gradCol2 = Colours::green;
|
||||
gradPos1 = RelativePositionedRectangle();
|
||||
gradPos1.rect = PositionedRectangle ("50 50");
|
||||
gradPos2 = RelativePositionedRectangle();
|
||||
gradPos2.rect = PositionedRectangle ("100 100");
|
||||
|
||||
imageResourceName.clear();
|
||||
imageOpacity = 1.0;
|
||||
imageAnchor = RelativePositionedRectangle();
|
||||
imageAnchor.rect = PositionedRectangle ("0 0");
|
||||
}
|
||||
|
||||
void loadImage (JucerDocument* const document)
|
||||
{
|
||||
if (image.isNull())
|
||||
{
|
||||
if (document != nullptr)
|
||||
{
|
||||
if (imageResourceName.contains ("::"))
|
||||
{
|
||||
if (Project* project = document->getCppDocument().getProject())
|
||||
{
|
||||
JucerResourceFile resourceFile (*project);
|
||||
|
||||
for (int i = 0; i < resourceFile.getNumFiles(); ++i)
|
||||
{
|
||||
const File& file = resourceFile.getFile(i);
|
||||
|
||||
if (imageResourceName == resourceFile.getClassName() + "::" + resourceFile.getDataVariableFor (file))
|
||||
{
|
||||
image = ImageCache::getFromFile (file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = document->getResources().getImageFromCache (imageResourceName);
|
||||
}
|
||||
}
|
||||
|
||||
if (image.isNull())
|
||||
{
|
||||
const int hashCode = 0x3437856f;
|
||||
image = ImageCache::getFromHashCode (hashCode);
|
||||
|
||||
if (image.isNull())
|
||||
{
|
||||
image = Image (Image::RGB, 100, 100, true);
|
||||
|
||||
Graphics g (image);
|
||||
g.fillCheckerBoard (image.getBounds().toFloat(),
|
||||
(float) image.getWidth() * 0.5f, (float) image.getHeight() * 0.5f,
|
||||
Colours::white, Colours::lightgrey);
|
||||
|
||||
g.setFont (12.0f);
|
||||
g.setColour (Colours::grey);
|
||||
g.drawText ("(image missing)", 0, 0, image.getWidth(), image.getHeight() / 2, Justification::centred, true);
|
||||
|
||||
ImageCache::addImageToCache (image, hashCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,99 +1,99 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_PointComponent.h"
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class GradientPointComponent : public PointComponent
|
||||
{
|
||||
public:
|
||||
GradientPointComponent (ColouredElement* const owner_,
|
||||
const bool isStroke_,
|
||||
const bool isStart_)
|
||||
: PointComponent (owner_),
|
||||
isStroke (isStroke_),
|
||||
isStart (isStart_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePositionedRectangle getPosition()
|
||||
{
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
if (isStroke)
|
||||
return isStart ? e->getStrokeType().fill.gradPos1
|
||||
: e->getStrokeType().fill.gradPos2;
|
||||
|
||||
return isStart ? e->getFillType().gradPos1
|
||||
: e->getFillType().gradPos2;
|
||||
}
|
||||
|
||||
void setPosition (const RelativePositionedRectangle& newPos)
|
||||
{
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
if (isStroke)
|
||||
{
|
||||
JucerFillType f (e->getStrokeType().fill);
|
||||
|
||||
if (isStart)
|
||||
f.gradPos1 = newPos;
|
||||
else
|
||||
f.gradPos2 = newPos;
|
||||
|
||||
e->setStrokeFill (f, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
JucerFillType f (e->getFillType());
|
||||
|
||||
if (isStart)
|
||||
f.gradPos1 = newPos;
|
||||
else
|
||||
f.gradPos2 = newPos;
|
||||
|
||||
e->setFillType (f, true);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
PointComponent::updatePosition();
|
||||
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
JucerFillType f (isStroke ? e->getStrokeType().fill
|
||||
: e->getFillType());
|
||||
|
||||
setVisible (f.mode == JucerFillType::linearGradient
|
||||
|| f.mode == JucerFillType::radialGradient);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isStroke, isStart;
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_PointComponent.h"
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class GradientPointComponent : public PointComponent
|
||||
{
|
||||
public:
|
||||
GradientPointComponent (ColouredElement* const owner_,
|
||||
const bool isStroke_,
|
||||
const bool isStart_)
|
||||
: PointComponent (owner_),
|
||||
isStroke (isStroke_),
|
||||
isStart (isStart_)
|
||||
{
|
||||
}
|
||||
|
||||
RelativePositionedRectangle getPosition()
|
||||
{
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
if (isStroke)
|
||||
return isStart ? e->getStrokeType().fill.gradPos1
|
||||
: e->getStrokeType().fill.gradPos2;
|
||||
|
||||
return isStart ? e->getFillType().gradPos1
|
||||
: e->getFillType().gradPos2;
|
||||
}
|
||||
|
||||
void setPosition (const RelativePositionedRectangle& newPos)
|
||||
{
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
if (isStroke)
|
||||
{
|
||||
JucerFillType f (e->getStrokeType().fill);
|
||||
|
||||
if (isStart)
|
||||
f.gradPos1 = newPos;
|
||||
else
|
||||
f.gradPos2 = newPos;
|
||||
|
||||
e->setStrokeFill (f, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
JucerFillType f (e->getFillType());
|
||||
|
||||
if (isStart)
|
||||
f.gradPos1 = newPos;
|
||||
else
|
||||
f.gradPos2 = newPos;
|
||||
|
||||
e->setFillType (f, true);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePosition()
|
||||
{
|
||||
PointComponent::updatePosition();
|
||||
|
||||
ColouredElement* e = dynamic_cast<ColouredElement*> (owner);
|
||||
|
||||
JucerFillType f (isStroke ? e->getStrokeType().fill
|
||||
: e->getFillType());
|
||||
|
||||
setVisible (f.mode == JucerFillType::linearGradient
|
||||
|| f.mode == JucerFillType::radialGradient);
|
||||
}
|
||||
|
||||
private:
|
||||
bool isStroke, isStart;
|
||||
};
|
||||
|
@ -1,144 +1,144 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../ProjectSaving/jucer_ResourceFile.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A property that lets you pick a resource to use as an image, or create a
|
||||
new one with a file selector.
|
||||
*/
|
||||
template <class ElementType>
|
||||
class ImageResourceProperty : public ChoicePropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
ImageResourceProperty (JucerDocument& doc,
|
||||
ElementType* const e,
|
||||
const String& name,
|
||||
const bool allowChoiceOfNoResource_)
|
||||
: ChoicePropertyComponent (name),
|
||||
element (e), document (doc),
|
||||
allowChoiceOfNoResource (allowChoiceOfNoResource_)
|
||||
{
|
||||
refreshChoices();
|
||||
doc.addChangeListener (this);
|
||||
}
|
||||
|
||||
ImageResourceProperty (ElementType* const e, const String& name,
|
||||
const bool allowChoiceOfNoResource_ = false)
|
||||
: ChoicePropertyComponent (name),
|
||||
element (e), document (*e->getDocument()),
|
||||
allowChoiceOfNoResource (allowChoiceOfNoResource_)
|
||||
{
|
||||
refreshChoices();
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ImageResourceProperty()
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
virtual void setResource (const String& newName) = 0;
|
||||
|
||||
virtual String getResource() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
void setIndex (int newIndex)
|
||||
{
|
||||
if (newIndex == 0)
|
||||
{
|
||||
document.getResources()
|
||||
.browseForResource ("Select an image file to add as a resource",
|
||||
"*.jpg;*.jpeg;*.png;*.gif;*.svg",
|
||||
File(),
|
||||
String(),
|
||||
[this] (String resource)
|
||||
{
|
||||
if (resource.isNotEmpty())
|
||||
setResource (resource);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (choices[newIndex] == getNoneText() && allowChoiceOfNoResource)
|
||||
setResource (String());
|
||||
else
|
||||
setResource (choices [newIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
if (getResource().isEmpty())
|
||||
return -1;
|
||||
|
||||
return choices.indexOf (getResource());
|
||||
}
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*)
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
void refreshChoices()
|
||||
{
|
||||
choices.clear();
|
||||
|
||||
choices.add ("-- create a new image resource -- ");
|
||||
choices.add (String());
|
||||
|
||||
if (allowChoiceOfNoResource)
|
||||
choices.add (getNoneText());
|
||||
|
||||
choices.addArray (document.getResources().getResourceNames());
|
||||
|
||||
const SourceCodeDocument& cpp = document.getCppDocument();
|
||||
|
||||
if (Project* project = cpp.getProject())
|
||||
{
|
||||
JucerResourceFile resourceFile (*project);
|
||||
|
||||
for (int i = 0; i < resourceFile.getNumFiles(); ++i)
|
||||
{
|
||||
const File& file = resourceFile.getFile(i);
|
||||
|
||||
if (ImageFileFormat::findImageFormatForFileExtension(file))
|
||||
choices.add (resourceFile.getClassName() + "::" + resourceFile.getDataVariableFor (file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* getNoneText() noexcept { return "<< none >>"; }
|
||||
|
||||
protected:
|
||||
mutable Component::SafePointer<ElementType> element;
|
||||
JucerDocument& document;
|
||||
const bool allowChoiceOfNoResource;
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../ProjectSaving/jucer_ResourceFile.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A property that lets you pick a resource to use as an image, or create a
|
||||
new one with a file selector.
|
||||
*/
|
||||
template <class ElementType>
|
||||
class ImageResourceProperty : public ChoicePropertyComponent,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
ImageResourceProperty (JucerDocument& doc,
|
||||
ElementType* const e,
|
||||
const String& name,
|
||||
const bool allowChoiceOfNoResource_)
|
||||
: ChoicePropertyComponent (name),
|
||||
element (e), document (doc),
|
||||
allowChoiceOfNoResource (allowChoiceOfNoResource_)
|
||||
{
|
||||
refreshChoices();
|
||||
doc.addChangeListener (this);
|
||||
}
|
||||
|
||||
ImageResourceProperty (ElementType* const e, const String& name,
|
||||
const bool allowChoiceOfNoResource_ = false)
|
||||
: ChoicePropertyComponent (name),
|
||||
element (e), document (*e->getDocument()),
|
||||
allowChoiceOfNoResource (allowChoiceOfNoResource_)
|
||||
{
|
||||
refreshChoices();
|
||||
document.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ImageResourceProperty()
|
||||
{
|
||||
document.removeChangeListener (this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
virtual void setResource (const String& newName) = 0;
|
||||
|
||||
virtual String getResource() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
void setIndex (int newIndex)
|
||||
{
|
||||
if (newIndex == 0)
|
||||
{
|
||||
document.getResources()
|
||||
.browseForResource ("Select an image file to add as a resource",
|
||||
"*.jpg;*.jpeg;*.png;*.gif;*.svg",
|
||||
File(),
|
||||
String(),
|
||||
[this] (String resource)
|
||||
{
|
||||
if (resource.isNotEmpty())
|
||||
setResource (resource);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (choices[newIndex] == getNoneText() && allowChoiceOfNoResource)
|
||||
setResource (String());
|
||||
else
|
||||
setResource (choices [newIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
int getIndex() const
|
||||
{
|
||||
if (getResource().isEmpty())
|
||||
return -1;
|
||||
|
||||
return choices.indexOf (getResource());
|
||||
}
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*)
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
|
||||
void refreshChoices()
|
||||
{
|
||||
choices.clear();
|
||||
|
||||
choices.add ("-- create a new image resource -- ");
|
||||
choices.add (String());
|
||||
|
||||
if (allowChoiceOfNoResource)
|
||||
choices.add (getNoneText());
|
||||
|
||||
choices.addArray (document.getResources().getResourceNames());
|
||||
|
||||
const SourceCodeDocument& cpp = document.getCppDocument();
|
||||
|
||||
if (Project* project = cpp.getProject())
|
||||
{
|
||||
JucerResourceFile resourceFile (*project);
|
||||
|
||||
for (int i = 0; i < resourceFile.getNumFiles(); ++i)
|
||||
{
|
||||
const File& file = resourceFile.getFile(i);
|
||||
|
||||
if (ImageFileFormat::findImageFormatForFileExtension(file))
|
||||
choices.add (resourceFile.getClassName() + "::" + resourceFile.getDataVariableFor (file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* getNoneText() noexcept { return "<< none >>"; }
|
||||
|
||||
protected:
|
||||
mutable Component::SafePointer<ElementType> element;
|
||||
JucerDocument& document;
|
||||
const bool allowChoiceOfNoResource;
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,175 +1,175 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_GeneratedCode.h"
|
||||
#include "../UI/jucer_RelativePositionedRectangle.h"
|
||||
class FillType;
|
||||
class PaintRoutine;
|
||||
class JucerDocument;
|
||||
class ElementSiblingComponent;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for objects that can be used in a PaintRoutine.
|
||||
|
||||
*/
|
||||
class PaintElement : public Component,
|
||||
public ComponentBoundsConstrainer,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PaintElement (PaintRoutine* owner, const String& typeName);
|
||||
~PaintElement() override;
|
||||
|
||||
//==============================================================================
|
||||
virtual void setInitialBounds (int parentWidth, int parentHeight);
|
||||
|
||||
virtual Rectangle<int> getCurrentBounds (const Rectangle<int>& activeArea) const;
|
||||
virtual void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& activeArea, const bool undoable);
|
||||
|
||||
const RelativePositionedRectangle& getPosition() const;
|
||||
void setPosition (const RelativePositionedRectangle& newPosition, const bool undoable);
|
||||
void setPaintElementBounds (const Rectangle<int>& newBounds, const bool undoable);
|
||||
void setPaintElementBoundsAndProperties (PaintElement* elementToPosition, const Rectangle<int>& newBounds,
|
||||
PaintElement* referenceElement, const bool undoable);
|
||||
|
||||
void updateBounds (const Rectangle<int>& activeArea);
|
||||
|
||||
const String& getTypeName() const noexcept { return typeName; }
|
||||
PaintRoutine* getOwner() const noexcept { return owner; }
|
||||
|
||||
//==============================================================================
|
||||
virtual void draw (Graphics& g,
|
||||
const ComponentLayout* layout,
|
||||
const Rectangle<int>& parentArea) = 0;
|
||||
|
||||
virtual void drawExtraEditorGraphics (Graphics& g, const Rectangle<int>& relativeTo);
|
||||
|
||||
virtual void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected);
|
||||
|
||||
virtual void showPopupMenu();
|
||||
|
||||
//==============================================================================
|
||||
virtual XmlElement* createXml() const = 0;
|
||||
virtual bool loadFromXml (const XmlElement& xml) = 0;
|
||||
|
||||
//==============================================================================
|
||||
virtual void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) = 0;
|
||||
|
||||
JucerDocument* getDocument() const;
|
||||
|
||||
virtual void changed();
|
||||
bool perform (UndoableAction* action, const String& actionName);
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics&) override;
|
||||
void resized() override;
|
||||
void mouseDown (const MouseEvent&) override;
|
||||
void mouseDrag (const MouseEvent&) override;
|
||||
void mouseUp (const MouseEvent&) override;
|
||||
void changeListenerCallback (ChangeBroadcaster*) override;
|
||||
void parentHierarchyChanged() override;
|
||||
|
||||
virtual void applyCustomPaintSnippets (StringArray&) {}
|
||||
|
||||
int borderThickness;
|
||||
|
||||
protected:
|
||||
PaintRoutine* const owner;
|
||||
RelativePositionedRectangle position;
|
||||
|
||||
void resizeStart() override;
|
||||
void resizeEnd() override;
|
||||
void checkBounds (Rectangle<int>& bounds,
|
||||
const Rectangle<int>& previousBounds,
|
||||
const Rectangle<int>& limits,
|
||||
bool isStretchingTop,
|
||||
bool isStretchingLeft,
|
||||
bool isStretchingBottom,
|
||||
bool isStretchingRight) override;
|
||||
|
||||
void applyBoundsToComponent (Component&, Rectangle<int>) override;
|
||||
|
||||
Rectangle<int> getCurrentAbsoluteBounds() const;
|
||||
void getCurrentAbsoluteBoundsDouble (double& x, double& y, double& w, double& h) const;
|
||||
|
||||
virtual void selectionChanged (const bool isSelected);
|
||||
|
||||
virtual void createSiblingComponents();
|
||||
|
||||
void siblingComponentsChanged();
|
||||
|
||||
OwnedArray<ElementSiblingComponent> siblingComponents;
|
||||
|
||||
void updateSiblingComps();
|
||||
|
||||
private:
|
||||
std::unique_ptr<ResizableBorderComponent> border;
|
||||
String typeName;
|
||||
bool selected, dragging, mouseDownSelectStatus;
|
||||
double originalAspectRatio;
|
||||
ChangeBroadcaster selfChangeListenerList;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
template <typename ElementType>
|
||||
class ElementListener : private ChangeListener
|
||||
{
|
||||
public:
|
||||
ElementListener (ElementType* e)
|
||||
: owner (e), broadcaster (*owner->getDocument()),
|
||||
propToRefresh (nullptr)
|
||||
{
|
||||
broadcaster.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ElementListener() override
|
||||
{
|
||||
jassert (propToRefresh != nullptr);
|
||||
broadcaster.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setPropertyToRefresh (PropertyComponent& pc)
|
||||
{
|
||||
propToRefresh = &pc;
|
||||
}
|
||||
|
||||
mutable Component::SafePointer<ElementType> owner;
|
||||
ChangeBroadcaster& broadcaster;
|
||||
PropertyComponent* propToRefresh;
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
jassert (propToRefresh != nullptr);
|
||||
if (propToRefresh != nullptr && owner != nullptr)
|
||||
propToRefresh->refresh();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (ElementListener)
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../jucer_GeneratedCode.h"
|
||||
#include "../UI/jucer_RelativePositionedRectangle.h"
|
||||
class FillType;
|
||||
class PaintRoutine;
|
||||
class JucerDocument;
|
||||
class ElementSiblingComponent;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for objects that can be used in a PaintRoutine.
|
||||
|
||||
*/
|
||||
class PaintElement : public Component,
|
||||
public ComponentBoundsConstrainer,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
PaintElement (PaintRoutine* owner, const String& typeName);
|
||||
~PaintElement() override;
|
||||
|
||||
//==============================================================================
|
||||
virtual void setInitialBounds (int parentWidth, int parentHeight);
|
||||
|
||||
virtual Rectangle<int> getCurrentBounds (const Rectangle<int>& activeArea) const;
|
||||
virtual void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& activeArea, const bool undoable);
|
||||
|
||||
const RelativePositionedRectangle& getPosition() const;
|
||||
void setPosition (const RelativePositionedRectangle& newPosition, const bool undoable);
|
||||
void setPaintElementBounds (const Rectangle<int>& newBounds, const bool undoable);
|
||||
void setPaintElementBoundsAndProperties (PaintElement* elementToPosition, const Rectangle<int>& newBounds,
|
||||
PaintElement* referenceElement, const bool undoable);
|
||||
|
||||
void updateBounds (const Rectangle<int>& activeArea);
|
||||
|
||||
const String& getTypeName() const noexcept { return typeName; }
|
||||
PaintRoutine* getOwner() const noexcept { return owner; }
|
||||
|
||||
//==============================================================================
|
||||
virtual void draw (Graphics& g,
|
||||
const ComponentLayout* layout,
|
||||
const Rectangle<int>& parentArea) = 0;
|
||||
|
||||
virtual void drawExtraEditorGraphics (Graphics& g, const Rectangle<int>& relativeTo);
|
||||
|
||||
virtual void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected);
|
||||
|
||||
virtual void showPopupMenu();
|
||||
|
||||
//==============================================================================
|
||||
virtual XmlElement* createXml() const = 0;
|
||||
virtual bool loadFromXml (const XmlElement& xml) = 0;
|
||||
|
||||
//==============================================================================
|
||||
virtual void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) = 0;
|
||||
|
||||
JucerDocument* getDocument() const;
|
||||
|
||||
virtual void changed();
|
||||
bool perform (UndoableAction* action, const String& actionName);
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics&) override;
|
||||
void resized() override;
|
||||
void mouseDown (const MouseEvent&) override;
|
||||
void mouseDrag (const MouseEvent&) override;
|
||||
void mouseUp (const MouseEvent&) override;
|
||||
void changeListenerCallback (ChangeBroadcaster*) override;
|
||||
void parentHierarchyChanged() override;
|
||||
|
||||
virtual void applyCustomPaintSnippets (StringArray&) {}
|
||||
|
||||
int borderThickness;
|
||||
|
||||
protected:
|
||||
PaintRoutine* const owner;
|
||||
RelativePositionedRectangle position;
|
||||
|
||||
void resizeStart() override;
|
||||
void resizeEnd() override;
|
||||
void checkBounds (Rectangle<int>& bounds,
|
||||
const Rectangle<int>& previousBounds,
|
||||
const Rectangle<int>& limits,
|
||||
bool isStretchingTop,
|
||||
bool isStretchingLeft,
|
||||
bool isStretchingBottom,
|
||||
bool isStretchingRight) override;
|
||||
|
||||
void applyBoundsToComponent (Component&, Rectangle<int>) override;
|
||||
|
||||
Rectangle<int> getCurrentAbsoluteBounds() const;
|
||||
void getCurrentAbsoluteBoundsDouble (double& x, double& y, double& w, double& h) const;
|
||||
|
||||
virtual void selectionChanged (const bool isSelected);
|
||||
|
||||
virtual void createSiblingComponents();
|
||||
|
||||
void siblingComponentsChanged();
|
||||
|
||||
OwnedArray<ElementSiblingComponent> siblingComponents;
|
||||
|
||||
void updateSiblingComps();
|
||||
|
||||
private:
|
||||
std::unique_ptr<ResizableBorderComponent> border;
|
||||
String typeName;
|
||||
bool selected, dragging, mouseDownSelectStatus;
|
||||
double originalAspectRatio;
|
||||
ChangeBroadcaster selfChangeListenerList;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
template <typename ElementType>
|
||||
class ElementListener : private ChangeListener
|
||||
{
|
||||
public:
|
||||
ElementListener (ElementType* e)
|
||||
: owner (e), broadcaster (*owner->getDocument()),
|
||||
propToRefresh (nullptr)
|
||||
{
|
||||
broadcaster.addChangeListener (this);
|
||||
}
|
||||
|
||||
~ElementListener() override
|
||||
{
|
||||
jassert (propToRefresh != nullptr);
|
||||
broadcaster.removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setPropertyToRefresh (PropertyComponent& pc)
|
||||
{
|
||||
propToRefresh = &pc;
|
||||
}
|
||||
|
||||
mutable Component::SafePointer<ElementType> owner;
|
||||
ChangeBroadcaster& broadcaster;
|
||||
PropertyComponent* propToRefresh;
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override
|
||||
{
|
||||
jassert (propToRefresh != nullptr);
|
||||
if (propToRefresh != nullptr && owner != nullptr)
|
||||
propToRefresh->refresh();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (ElementListener)
|
||||
};
|
||||
|
@ -1,173 +1,173 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementEllipse : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementEllipse (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Ellipse", true, false)
|
||||
{
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight());
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight(),
|
||||
getStrokeType().stroke.getStrokeThickness());
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillEllipse (x, y, width, height);\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
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) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "ELLIPSE"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
double x, y, w, h;
|
||||
getCurrentAbsoluteBoundsDouble (x, y, w, h);
|
||||
|
||||
Path path;
|
||||
path.addEllipse ((float) x, (float) y, (float) w, (float) h);
|
||||
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
struct ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
ShapeToPathProperty (PaintElementEllipse* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
PaintElementEllipse* element;
|
||||
};
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementEllipse : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementEllipse (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Ellipse", true, false)
|
||||
{
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight());
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight(),
|
||||
getStrokeType().stroke.getStrokeThickness());
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillEllipse (x, y, width, height);\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
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) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "ELLIPSE"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
double x, y, w, h;
|
||||
getCurrentAbsoluteBoundsDouble (x, y, w, h);
|
||||
|
||||
Path path;
|
||||
path.addEllipse ((float) x, (float) y, (float) w, (float) h);
|
||||
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
struct ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
ShapeToPathProperty (PaintElementEllipse* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
PaintElementEllipse* element;
|
||||
};
|
||||
};
|
||||
|
@ -1,226 +1,226 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "jucer_PaintElementGroup.h"
|
||||
|
||||
PaintElementGroup::PaintElementGroup (PaintRoutine* pr)
|
||||
: PaintElement (pr, "Group")
|
||||
{
|
||||
}
|
||||
|
||||
PaintElementGroup::~PaintElementGroup() {}
|
||||
|
||||
void PaintElementGroup::ungroup (const bool undoable)
|
||||
{
|
||||
getOwner()->getSelectedElements().deselectAll();
|
||||
getOwner()->getSelectedPoints().deselectAll();
|
||||
|
||||
const int index = getOwner()->indexOfElement (this);
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
std::unique_ptr<XmlElement> xml (subElements.getUnchecked(i)->createXml());
|
||||
|
||||
PaintElement* newOne = getOwner()->addElementFromXml (*xml, index, undoable);
|
||||
getOwner()->getSelectedElements().addToSelection (newOne);
|
||||
}
|
||||
|
||||
getOwner()->removeElement (this, undoable);
|
||||
}
|
||||
|
||||
void PaintElementGroup::groupSelected (PaintRoutine* routine)
|
||||
{
|
||||
if (routine->getSelectedElements().getNumSelected() > 1)
|
||||
{
|
||||
auto* newGroup = new PaintElementGroup (routine);
|
||||
int frontIndex = -1;
|
||||
|
||||
for (int i = 0; i < routine->getNumElements(); ++i)
|
||||
{
|
||||
if (routine->getSelectedElements().isSelected (routine->getElement (i)))
|
||||
{
|
||||
std::unique_ptr<XmlElement> xml (routine->getElement(i)->createXml());
|
||||
|
||||
if (auto* newOne = ObjectTypes::createElementForXml (xml.get(), routine))
|
||||
newGroup->subElements.add (newOne);
|
||||
|
||||
if (i > frontIndex)
|
||||
frontIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
routine->deleteSelected();
|
||||
|
||||
auto* g = routine->addNewElement (newGroup, frontIndex, true);
|
||||
routine->getSelectedElements().selectOnly (g);
|
||||
}
|
||||
}
|
||||
|
||||
int PaintElementGroup::getNumElements() const noexcept { return subElements.size(); }
|
||||
|
||||
PaintElement* PaintElementGroup::getElement (const int index) const noexcept { return subElements [index]; }
|
||||
|
||||
int PaintElementGroup::indexOfElement (const PaintElement* element) const noexcept { return subElements.indexOf (element); }
|
||||
|
||||
bool PaintElementGroup::containsElement (const PaintElement* element) const
|
||||
{
|
||||
if (subElements.contains (element))
|
||||
return true;
|
||||
|
||||
for (int i = subElements.size(); --i >= 0;)
|
||||
if (PaintElementGroup* pg = dynamic_cast<PaintElementGroup*> (subElements.getUnchecked(i)))
|
||||
if (pg->containsElement (element))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementGroup::setInitialBounds (int /*parentWidth*/, int /*parentHeight*/)
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle<int> PaintElementGroup::getCurrentBounds (const Rectangle<int>& parentArea) const
|
||||
{
|
||||
Rectangle<int> r;
|
||||
|
||||
if (subElements.size() > 0)
|
||||
{
|
||||
r = subElements.getUnchecked(0)->getCurrentBounds (parentArea);
|
||||
|
||||
for (int i = 1; i < subElements.size(); ++i)
|
||||
r = r.getUnion (subElements.getUnchecked(i)->getCurrentBounds (parentArea));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void PaintElementGroup::setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable)
|
||||
{
|
||||
Rectangle<int> newBounds (b);
|
||||
newBounds.setSize (jmax (1, newBounds.getWidth()),
|
||||
jmax (1, newBounds.getHeight()));
|
||||
|
||||
const Rectangle<int> current (getCurrentBounds (parentArea));
|
||||
|
||||
if (newBounds != current)
|
||||
{
|
||||
const int dx = newBounds.getX() - current.getX();
|
||||
const int dy = newBounds.getY() - current.getY();
|
||||
|
||||
const double scaleStartX = current.getX();
|
||||
const double scaleStartY = current.getY();
|
||||
const double scaleX = newBounds.getWidth() / (double) current.getWidth();
|
||||
const double scaleY = newBounds.getHeight() / (double) current.getHeight();
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
PaintElement* const e = subElements.getUnchecked(i);
|
||||
|
||||
Rectangle<int> pos (e->getCurrentBounds (parentArea));
|
||||
|
||||
const int newX = roundToInt ((pos.getX() - scaleStartX) * scaleX + scaleStartX + dx);
|
||||
const int newY = roundToInt ((pos.getY() - scaleStartY) * scaleY + scaleStartY + dy);
|
||||
|
||||
pos.setBounds (newX, newY,
|
||||
roundToInt ((pos.getRight() - scaleStartX) * scaleX + scaleStartX + dx) - newX,
|
||||
roundToInt ((pos.getBottom() - scaleStartY) * scaleY + scaleStartY + dy) - newY);
|
||||
|
||||
e->setCurrentBounds (pos, parentArea, undoable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementGroup::draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea)
|
||||
{
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
subElements.getUnchecked(i)->draw (g, layout, parentArea);
|
||||
}
|
||||
|
||||
void PaintElementGroup::getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected)
|
||||
{
|
||||
if (! multipleSelected)
|
||||
props.add (new UngroupProperty (this));
|
||||
}
|
||||
|
||||
void PaintElementGroup::fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
|
||||
{
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
subElements.getUnchecked(i)->fillInGeneratedCode (code, paintMethodCode);
|
||||
}
|
||||
|
||||
const char* PaintElementGroup::getTagName() noexcept { return "GROUP"; }
|
||||
|
||||
XmlElement* PaintElementGroup::createXml() const
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
XmlElement* const sub = subElements.getUnchecked(i)->createXml();
|
||||
e->addChildElement (sub);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PaintElementGroup::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
for (auto* e : xml.getChildIterator())
|
||||
if (PaintElement* const pe = ObjectTypes::createElementForXml (e, owner))
|
||||
subElements.add (pe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PaintElementGroup::applyCustomPaintSnippets (StringArray& snippets)
|
||||
{
|
||||
for (auto* e : subElements)
|
||||
e->applyCustomPaintSnippets (snippets);
|
||||
}
|
||||
|
||||
PaintElementGroup::UngroupProperty::UngroupProperty (PaintElementGroup* const e)
|
||||
: ButtonPropertyComponent ("ungroup", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementGroup::UngroupProperty::buttonClicked()
|
||||
{
|
||||
element->ungroup (true);
|
||||
}
|
||||
|
||||
String PaintElementGroup::UngroupProperty::getButtonText() const
|
||||
{
|
||||
return "Ungroup";
|
||||
}
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "jucer_PaintElementGroup.h"
|
||||
|
||||
PaintElementGroup::PaintElementGroup (PaintRoutine* pr)
|
||||
: PaintElement (pr, "Group")
|
||||
{
|
||||
}
|
||||
|
||||
PaintElementGroup::~PaintElementGroup() {}
|
||||
|
||||
void PaintElementGroup::ungroup (const bool undoable)
|
||||
{
|
||||
getOwner()->getSelectedElements().deselectAll();
|
||||
getOwner()->getSelectedPoints().deselectAll();
|
||||
|
||||
const int index = getOwner()->indexOfElement (this);
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
std::unique_ptr<XmlElement> xml (subElements.getUnchecked(i)->createXml());
|
||||
|
||||
PaintElement* newOne = getOwner()->addElementFromXml (*xml, index, undoable);
|
||||
getOwner()->getSelectedElements().addToSelection (newOne);
|
||||
}
|
||||
|
||||
getOwner()->removeElement (this, undoable);
|
||||
}
|
||||
|
||||
void PaintElementGroup::groupSelected (PaintRoutine* routine)
|
||||
{
|
||||
if (routine->getSelectedElements().getNumSelected() > 1)
|
||||
{
|
||||
auto* newGroup = new PaintElementGroup (routine);
|
||||
int frontIndex = -1;
|
||||
|
||||
for (int i = 0; i < routine->getNumElements(); ++i)
|
||||
{
|
||||
if (routine->getSelectedElements().isSelected (routine->getElement (i)))
|
||||
{
|
||||
std::unique_ptr<XmlElement> xml (routine->getElement(i)->createXml());
|
||||
|
||||
if (auto* newOne = ObjectTypes::createElementForXml (xml.get(), routine))
|
||||
newGroup->subElements.add (newOne);
|
||||
|
||||
if (i > frontIndex)
|
||||
frontIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
routine->deleteSelected();
|
||||
|
||||
auto* g = routine->addNewElement (newGroup, frontIndex, true);
|
||||
routine->getSelectedElements().selectOnly (g);
|
||||
}
|
||||
}
|
||||
|
||||
int PaintElementGroup::getNumElements() const noexcept { return subElements.size(); }
|
||||
|
||||
PaintElement* PaintElementGroup::getElement (const int index) const noexcept { return subElements [index]; }
|
||||
|
||||
int PaintElementGroup::indexOfElement (const PaintElement* element) const noexcept { return subElements.indexOf (element); }
|
||||
|
||||
bool PaintElementGroup::containsElement (const PaintElement* element) const
|
||||
{
|
||||
if (subElements.contains (element))
|
||||
return true;
|
||||
|
||||
for (int i = subElements.size(); --i >= 0;)
|
||||
if (PaintElementGroup* pg = dynamic_cast<PaintElementGroup*> (subElements.getUnchecked(i)))
|
||||
if (pg->containsElement (element))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementGroup::setInitialBounds (int /*parentWidth*/, int /*parentHeight*/)
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle<int> PaintElementGroup::getCurrentBounds (const Rectangle<int>& parentArea) const
|
||||
{
|
||||
Rectangle<int> r;
|
||||
|
||||
if (subElements.size() > 0)
|
||||
{
|
||||
r = subElements.getUnchecked(0)->getCurrentBounds (parentArea);
|
||||
|
||||
for (int i = 1; i < subElements.size(); ++i)
|
||||
r = r.getUnion (subElements.getUnchecked(i)->getCurrentBounds (parentArea));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void PaintElementGroup::setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable)
|
||||
{
|
||||
Rectangle<int> newBounds (b);
|
||||
newBounds.setSize (jmax (1, newBounds.getWidth()),
|
||||
jmax (1, newBounds.getHeight()));
|
||||
|
||||
const Rectangle<int> current (getCurrentBounds (parentArea));
|
||||
|
||||
if (newBounds != current)
|
||||
{
|
||||
const int dx = newBounds.getX() - current.getX();
|
||||
const int dy = newBounds.getY() - current.getY();
|
||||
|
||||
const double scaleStartX = current.getX();
|
||||
const double scaleStartY = current.getY();
|
||||
const double scaleX = newBounds.getWidth() / (double) current.getWidth();
|
||||
const double scaleY = newBounds.getHeight() / (double) current.getHeight();
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
PaintElement* const e = subElements.getUnchecked(i);
|
||||
|
||||
Rectangle<int> pos (e->getCurrentBounds (parentArea));
|
||||
|
||||
const int newX = roundToInt ((pos.getX() - scaleStartX) * scaleX + scaleStartX + dx);
|
||||
const int newY = roundToInt ((pos.getY() - scaleStartY) * scaleY + scaleStartY + dy);
|
||||
|
||||
pos.setBounds (newX, newY,
|
||||
roundToInt ((pos.getRight() - scaleStartX) * scaleX + scaleStartX + dx) - newX,
|
||||
roundToInt ((pos.getBottom() - scaleStartY) * scaleY + scaleStartY + dy) - newY);
|
||||
|
||||
e->setCurrentBounds (pos, parentArea, undoable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementGroup::draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea)
|
||||
{
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
subElements.getUnchecked(i)->draw (g, layout, parentArea);
|
||||
}
|
||||
|
||||
void PaintElementGroup::getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected)
|
||||
{
|
||||
if (! multipleSelected)
|
||||
props.add (new UngroupProperty (this));
|
||||
}
|
||||
|
||||
void PaintElementGroup::fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
|
||||
{
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
subElements.getUnchecked(i)->fillInGeneratedCode (code, paintMethodCode);
|
||||
}
|
||||
|
||||
const char* PaintElementGroup::getTagName() noexcept { return "GROUP"; }
|
||||
|
||||
XmlElement* PaintElementGroup::createXml() const
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
|
||||
for (int i = 0; i < subElements.size(); ++i)
|
||||
{
|
||||
XmlElement* const sub = subElements.getUnchecked(i)->createXml();
|
||||
e->addChildElement (sub);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PaintElementGroup::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
for (auto* e : xml.getChildIterator())
|
||||
if (PaintElement* const pe = ObjectTypes::createElementForXml (e, owner))
|
||||
subElements.add (pe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PaintElementGroup::applyCustomPaintSnippets (StringArray& snippets)
|
||||
{
|
||||
for (auto* e : subElements)
|
||||
e->applyCustomPaintSnippets (snippets);
|
||||
}
|
||||
|
||||
PaintElementGroup::UngroupProperty::UngroupProperty (PaintElementGroup* const e)
|
||||
: ButtonPropertyComponent ("ungroup", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementGroup::UngroupProperty::buttonClicked()
|
||||
{
|
||||
element->ungroup (true);
|
||||
}
|
||||
|
||||
String PaintElementGroup::UngroupProperty::getButtonText() const
|
||||
{
|
||||
return "Ungroup";
|
||||
}
|
||||
|
@ -1,81 +1,81 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_PaintElement.h"
|
||||
#include "../jucer_ObjectTypes.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementGroup : public PaintElement
|
||||
{
|
||||
public:
|
||||
PaintElementGroup (PaintRoutine*);
|
||||
~PaintElementGroup() override;
|
||||
|
||||
void ungroup (const bool);
|
||||
|
||||
static void groupSelected (PaintRoutine* const);
|
||||
|
||||
int getNumElements() const noexcept;
|
||||
|
||||
PaintElement* getElement (const int index) const noexcept;
|
||||
int indexOfElement (const PaintElement* element) const noexcept;
|
||||
|
||||
bool containsElement (const PaintElement* element) const;
|
||||
|
||||
//==============================================================================
|
||||
void setInitialBounds (int, int) override;
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>&) const override;
|
||||
void setCurrentBounds (const Rectangle<int>&, const Rectangle<int>&, const bool) override;
|
||||
|
||||
//==============================================================================
|
||||
void draw (Graphics&, const ComponentLayout*, const Rectangle<int>&) override;
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>&, bool) override;
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode&, String&) override;
|
||||
|
||||
static const char* getTagName() noexcept;
|
||||
|
||||
XmlElement* createXml() const override;
|
||||
|
||||
bool loadFromXml (const XmlElement&) override;
|
||||
|
||||
void applyCustomPaintSnippets (StringArray&) override;
|
||||
|
||||
private:
|
||||
OwnedArray<PaintElement> subElements;
|
||||
|
||||
struct UngroupProperty : public ButtonPropertyComponent
|
||||
{
|
||||
UngroupProperty (PaintElementGroup* const);
|
||||
|
||||
void buttonClicked();
|
||||
String getButtonText() const;
|
||||
|
||||
PaintElementGroup* element;
|
||||
};
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_PaintElement.h"
|
||||
#include "../jucer_ObjectTypes.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementGroup : public PaintElement
|
||||
{
|
||||
public:
|
||||
PaintElementGroup (PaintRoutine*);
|
||||
~PaintElementGroup() override;
|
||||
|
||||
void ungroup (const bool);
|
||||
|
||||
static void groupSelected (PaintRoutine* const);
|
||||
|
||||
int getNumElements() const noexcept;
|
||||
|
||||
PaintElement* getElement (const int index) const noexcept;
|
||||
int indexOfElement (const PaintElement* element) const noexcept;
|
||||
|
||||
bool containsElement (const PaintElement* element) const;
|
||||
|
||||
//==============================================================================
|
||||
void setInitialBounds (int, int) override;
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>&) const override;
|
||||
void setCurrentBounds (const Rectangle<int>&, const Rectangle<int>&, const bool) override;
|
||||
|
||||
//==============================================================================
|
||||
void draw (Graphics&, const ComponentLayout*, const Rectangle<int>&) override;
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>&, bool) override;
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode&, String&) override;
|
||||
|
||||
static const char* getTagName() noexcept;
|
||||
|
||||
XmlElement* createXml() const override;
|
||||
|
||||
bool loadFromXml (const XmlElement&) override;
|
||||
|
||||
void applyCustomPaintSnippets (StringArray&) override;
|
||||
|
||||
private:
|
||||
OwnedArray<PaintElement> subElements;
|
||||
|
||||
struct UngroupProperty : public ButtonPropertyComponent
|
||||
{
|
||||
UngroupProperty (PaintElementGroup* const);
|
||||
|
||||
void buttonClicked();
|
||||
String getButtonText() const;
|
||||
|
||||
PaintElementGroup* element;
|
||||
};
|
||||
};
|
||||
|
@ -1,428 +1,428 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "jucer_PaintElementImage.h"
|
||||
|
||||
PaintElementImage::PaintElementImage (PaintRoutine* pr)
|
||||
: PaintElement (pr, "Image"),
|
||||
opacity (1.0),
|
||||
mode (stretched)
|
||||
{
|
||||
}
|
||||
|
||||
PaintElementImage::~PaintElementImage() {}
|
||||
|
||||
const Drawable* PaintElementImage::getDrawable()
|
||||
{
|
||||
if (JucerDocument* const document = getDocument())
|
||||
return document->getResources().getDrawable (resourceName);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PaintElementImage::draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea)
|
||||
{
|
||||
const Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
|
||||
if (const Drawable* const image = getDrawable())
|
||||
{
|
||||
image->drawWithin (g, r.toFloat(),
|
||||
mode == stretched ? RectanglePlacement::stretchToFit
|
||||
: (mode == proportionalReducingOnly ? (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize)
|
||||
: RectanglePlacement::centred),
|
||||
(float) opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColour (Colours::grey.withAlpha (0.5f));
|
||||
g.fillRect (r);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.drawText ("(image missing)",
|
||||
r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
Justification::centred, true);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementImage::getEditableProperties (Array <PropertyComponent*>& props, bool multipleSelected)
|
||||
{
|
||||
PaintElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ImageElementResourceProperty (this));
|
||||
props.add (new StretchModeProperty (this));
|
||||
props.add (new OpacityProperty (this));
|
||||
props.add (new ResetSizeProperty (this));
|
||||
}
|
||||
|
||||
void PaintElementImage::fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
const String imageVariable ("cachedImage_" + resourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix()));
|
||||
|
||||
code.addImageResourceLoader (imageVariable, resourceName);
|
||||
|
||||
if (opacity >= 254.0 / 255.0)
|
||||
r << " g.setColour (juce::Colours::black);\n";
|
||||
else
|
||||
r << " g.setColour (juce::Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n";
|
||||
|
||||
if (mode == stretched)
|
||||
{
|
||||
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, width, height,\n"
|
||||
<< " ";
|
||||
|
||||
if (mode == proportionalReducingOnly)
|
||||
r << "juce::RectanglePlacement::centred | juce::RectanglePlacement::onlyReduceInSize";
|
||||
else
|
||||
r << "juce::RectanglePlacement::centred";
|
||||
|
||||
r << ",\n"
|
||||
<< " false);\n";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resourceName.isNotEmpty())
|
||||
{
|
||||
const String imageVariable ("drawable" + String (code.getUniqueSuffix()));
|
||||
|
||||
code.privateMemberDeclarations
|
||||
<< "std::unique_ptr<juce::Drawable> " << imageVariable << ";\n";
|
||||
|
||||
code.constructorCode
|
||||
<< imageVariable << " = juce::Drawable::createFromImageData ("
|
||||
<< resourceName << ", " << resourceName << "Size);\n";
|
||||
|
||||
code.destructorCode
|
||||
<< imageVariable << " = nullptr;\n";
|
||||
|
||||
if (opacity >= 254.0 / 255.0)
|
||||
r << " g.setColour (juce::Colours::black);\n";
|
||||
else
|
||||
r << " g.setColour (juce::Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n";
|
||||
|
||||
r << " jassert (" << imageVariable << " != nullptr);\n"
|
||||
<< " if (" << imageVariable << " != nullptr)\n"
|
||||
<< " " << imageVariable << "->drawWithin (g, juce::Rectangle<int> (x, y, width, height).toFloat(),\n"
|
||||
<< " " << String::repeatedString (" ", imageVariable.length() + 18)
|
||||
<< (mode == stretched ? "juce::RectanglePlacement::stretchToFit"
|
||||
: (mode == proportionalReducingOnly ? "juce::RectanglePlacement::centred | juce::RectanglePlacement::onlyReduceInSize"
|
||||
: "juce::RectanglePlacement::centred"))
|
||||
<< ", " << CodeHelpers::floatLiteral (opacity, 3) << ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
r << "}\n\n";
|
||||
|
||||
paintMethodCode += r;
|
||||
}
|
||||
}
|
||||
|
||||
void PaintElementImage::applyCustomPaintSnippets (StringArray& snippets)
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && opacity > 0)
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetResourceAction::SetResourceAction (PaintElementImage* const element, const String& newResource_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newResource (newResource_)
|
||||
{
|
||||
oldResource = element->getResource();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetResourceAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setResource (newResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetResourceAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setResource (oldResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintElementImage::setResource (const String& newName, const bool undoable)
|
||||
{
|
||||
if (resourceName != newName)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetResourceAction (this, newName),
|
||||
"Change image resource");
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceName = newName;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
String PaintElementImage::getResource() const
|
||||
{
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetOpacityAction::SetOpacityAction (PaintElementImage* const element, const double newOpacity_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newOpacity (newOpacity_)
|
||||
{
|
||||
oldOpacity = element->getOpacity();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetOpacityAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setOpacity (newOpacity, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetOpacityAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setOpacity (oldOpacity, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintElementImage::setOpacity (double newOpacity, const bool undoable)
|
||||
{
|
||||
newOpacity = jlimit (0.0, 1.0, newOpacity);
|
||||
|
||||
if (opacity != newOpacity)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetOpacityAction (this, newOpacity),
|
||||
"Change image opacity");
|
||||
}
|
||||
else
|
||||
{
|
||||
opacity = newOpacity;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double PaintElementImage::getOpacity() const noexcept { return opacity; }
|
||||
|
||||
//==============================================================================
|
||||
const char* PaintElementImage::getTagName() noexcept { return "IMAGE"; }
|
||||
|
||||
void PaintElementImage::resetToImageSize()
|
||||
{
|
||||
if (const Drawable* const image = getDrawable())
|
||||
{
|
||||
if (PaintRoutineEditor* ed = dynamic_cast<PaintRoutineEditor*> (getParentComponent()))
|
||||
{
|
||||
const Rectangle<int> parentArea (ed->getComponentArea());
|
||||
|
||||
Rectangle<int> r (getCurrentBounds (parentArea));
|
||||
Rectangle<float> b (image->getDrawableBounds());
|
||||
|
||||
r.setSize ((int) (b.getWidth() + 0.999f),
|
||||
(int) (b.getHeight() + 0.999f));
|
||||
|
||||
setCurrentBounds (r, parentArea, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetStretchModeAction::SetStretchModeAction (PaintElementImage* const element, const StretchMode newValue_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newValue (newValue_)
|
||||
{
|
||||
oldValue = element->getStretchMode();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetStretchModeAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setStretchMode (newValue, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetStretchModeAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setStretchMode (oldValue, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
PaintElementImage::StretchMode PaintElementImage::getStretchMode() const noexcept { return mode; }
|
||||
|
||||
void PaintElementImage::setStretchMode (const StretchMode newMode, const bool undoable)
|
||||
{
|
||||
if (mode != newMode)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetStretchModeAction (this, newMode),
|
||||
"Change image mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = newMode;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
XmlElement* PaintElementImage::createXml() const
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
e->setAttribute ("resource", resourceName);
|
||||
e->setAttribute ("opacity", opacity);
|
||||
e->setAttribute ("mode", (int) mode);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PaintElementImage::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
resourceName = xml.getStringAttribute ("resource", String());
|
||||
opacity = xml.getDoubleAttribute ("opacity", 1.0);
|
||||
mode = (StretchMode) xml.getIntAttribute ("mode", (int) stretched);
|
||||
|
||||
repaint();
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::ImageElementResourceProperty::ImageElementResourceProperty (PaintElementImage* const e)
|
||||
: ImageResourceProperty <PaintElementImage> (e, "image source")
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementImage::ImageElementResourceProperty::setResource (const String& newName)
|
||||
{
|
||||
if (element != nullptr)
|
||||
element->setResource (newName, true);
|
||||
}
|
||||
|
||||
String PaintElementImage::ImageElementResourceProperty::getResource() const
|
||||
{
|
||||
if (element != nullptr)
|
||||
return element->getResource();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::OpacityProperty::OpacityProperty (PaintElementImage* const e)
|
||||
: SliderPropertyComponent ("opacity", 0.0, 1.0, 0.001),
|
||||
listener (e)
|
||||
{
|
||||
listener.setPropertyToRefresh (*this);
|
||||
}
|
||||
|
||||
void PaintElementImage::OpacityProperty::setValue (double newValue)
|
||||
{
|
||||
listener.owner->getDocument()->getUndoManager().undoCurrentTransactionOnly();
|
||||
listener.owner->setOpacity (newValue, true);
|
||||
}
|
||||
|
||||
double PaintElementImage::OpacityProperty::getValue() const
|
||||
{
|
||||
return listener.owner->getOpacity();
|
||||
}
|
||||
|
||||
PaintElementImage::StretchModeProperty::StretchModeProperty (PaintElementImage* const e)
|
||||
: ChoicePropertyComponent ("stretch mode"),
|
||||
listener (e)
|
||||
{
|
||||
listener.setPropertyToRefresh (*this);
|
||||
|
||||
choices.add ("Stretched to fit");
|
||||
choices.add ("Maintain aspect ratio");
|
||||
choices.add ("Maintain aspect ratio, only reduce in size");
|
||||
}
|
||||
|
||||
void PaintElementImage::StretchModeProperty::setIndex (int newIndex)
|
||||
{
|
||||
listener.owner->setStretchMode ((StretchMode) newIndex, true);
|
||||
}
|
||||
|
||||
int PaintElementImage::StretchModeProperty::getIndex() const
|
||||
{
|
||||
return (int) listener.owner->getStretchMode();
|
||||
}
|
||||
|
||||
PaintElementImage::ResetSizeProperty::ResetSizeProperty (PaintElementImage* const e)
|
||||
: ButtonPropertyComponent ("reset", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementImage::ResetSizeProperty::buttonClicked()
|
||||
{
|
||||
element->resetToImageSize();
|
||||
}
|
||||
|
||||
String PaintElementImage::ResetSizeProperty::getButtonText() const { return "reset to image size"; }
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../Application/jucer_Headers.h"
|
||||
#include "jucer_PaintElementImage.h"
|
||||
|
||||
PaintElementImage::PaintElementImage (PaintRoutine* pr)
|
||||
: PaintElement (pr, "Image"),
|
||||
opacity (1.0),
|
||||
mode (stretched)
|
||||
{
|
||||
}
|
||||
|
||||
PaintElementImage::~PaintElementImage() {}
|
||||
|
||||
const Drawable* PaintElementImage::getDrawable()
|
||||
{
|
||||
if (JucerDocument* const document = getDocument())
|
||||
return document->getResources().getDrawable (resourceName);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PaintElementImage::draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea)
|
||||
{
|
||||
const Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
|
||||
if (const Drawable* const image = getDrawable())
|
||||
{
|
||||
image->drawWithin (g, r.toFloat(),
|
||||
mode == stretched ? RectanglePlacement::stretchToFit
|
||||
: (mode == proportionalReducingOnly ? (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize)
|
||||
: RectanglePlacement::centred),
|
||||
(float) opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColour (Colours::grey.withAlpha (0.5f));
|
||||
g.fillRect (r);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.drawText ("(image missing)",
|
||||
r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
Justification::centred, true);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void PaintElementImage::getEditableProperties (Array <PropertyComponent*>& props, bool multipleSelected)
|
||||
{
|
||||
PaintElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ImageElementResourceProperty (this));
|
||||
props.add (new StretchModeProperty (this));
|
||||
props.add (new OpacityProperty (this));
|
||||
props.add (new ResetSizeProperty (this));
|
||||
}
|
||||
|
||||
void PaintElementImage::fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode)
|
||||
{
|
||||
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()))
|
||||
{
|
||||
const String imageVariable ("cachedImage_" + resourceName.replace ("::", "_") + "_" + String (code.getUniqueSuffix()));
|
||||
|
||||
code.addImageResourceLoader (imageVariable, resourceName);
|
||||
|
||||
if (opacity >= 254.0 / 255.0)
|
||||
r << " g.setColour (juce::Colours::black);\n";
|
||||
else
|
||||
r << " g.setColour (juce::Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n";
|
||||
|
||||
if (mode == stretched)
|
||||
{
|
||||
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, width, height,\n"
|
||||
<< " ";
|
||||
|
||||
if (mode == proportionalReducingOnly)
|
||||
r << "juce::RectanglePlacement::centred | juce::RectanglePlacement::onlyReduceInSize";
|
||||
else
|
||||
r << "juce::RectanglePlacement::centred";
|
||||
|
||||
r << ",\n"
|
||||
<< " false);\n";
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resourceName.isNotEmpty())
|
||||
{
|
||||
const String imageVariable ("drawable" + String (code.getUniqueSuffix()));
|
||||
|
||||
code.privateMemberDeclarations
|
||||
<< "std::unique_ptr<juce::Drawable> " << imageVariable << ";\n";
|
||||
|
||||
code.constructorCode
|
||||
<< imageVariable << " = juce::Drawable::createFromImageData ("
|
||||
<< resourceName << ", " << resourceName << "Size);\n";
|
||||
|
||||
code.destructorCode
|
||||
<< imageVariable << " = nullptr;\n";
|
||||
|
||||
if (opacity >= 254.0 / 255.0)
|
||||
r << " g.setColour (juce::Colours::black);\n";
|
||||
else
|
||||
r << " g.setColour (juce::Colours::black.withAlpha (" << CodeHelpers::floatLiteral (opacity, 3) << "));\n";
|
||||
|
||||
r << " jassert (" << imageVariable << " != nullptr);\n"
|
||||
<< " if (" << imageVariable << " != nullptr)\n"
|
||||
<< " " << imageVariable << "->drawWithin (g, juce::Rectangle<int> (x, y, width, height).toFloat(),\n"
|
||||
<< " " << String::repeatedString (" ", imageVariable.length() + 18)
|
||||
<< (mode == stretched ? "juce::RectanglePlacement::stretchToFit"
|
||||
: (mode == proportionalReducingOnly ? "juce::RectanglePlacement::centred | juce::RectanglePlacement::onlyReduceInSize"
|
||||
: "juce::RectanglePlacement::centred"))
|
||||
<< ", " << CodeHelpers::floatLiteral (opacity, 3) << ");\n";
|
||||
}
|
||||
}
|
||||
|
||||
r << "}\n\n";
|
||||
|
||||
paintMethodCode += r;
|
||||
}
|
||||
}
|
||||
|
||||
void PaintElementImage::applyCustomPaintSnippets (StringArray& snippets)
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && opacity > 0)
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetResourceAction::SetResourceAction (PaintElementImage* const element, const String& newResource_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newResource (newResource_)
|
||||
{
|
||||
oldResource = element->getResource();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetResourceAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setResource (newResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetResourceAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setResource (oldResource, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintElementImage::setResource (const String& newName, const bool undoable)
|
||||
{
|
||||
if (resourceName != newName)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetResourceAction (this, newName),
|
||||
"Change image resource");
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceName = newName;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
String PaintElementImage::getResource() const
|
||||
{
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetOpacityAction::SetOpacityAction (PaintElementImage* const element, const double newOpacity_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newOpacity (newOpacity_)
|
||||
{
|
||||
oldOpacity = element->getOpacity();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetOpacityAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setOpacity (newOpacity, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetOpacityAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setOpacity (oldOpacity, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaintElementImage::setOpacity (double newOpacity, const bool undoable)
|
||||
{
|
||||
newOpacity = jlimit (0.0, 1.0, newOpacity);
|
||||
|
||||
if (opacity != newOpacity)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetOpacityAction (this, newOpacity),
|
||||
"Change image opacity");
|
||||
}
|
||||
else
|
||||
{
|
||||
opacity = newOpacity;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double PaintElementImage::getOpacity() const noexcept { return opacity; }
|
||||
|
||||
//==============================================================================
|
||||
const char* PaintElementImage::getTagName() noexcept { return "IMAGE"; }
|
||||
|
||||
void PaintElementImage::resetToImageSize()
|
||||
{
|
||||
if (const Drawable* const image = getDrawable())
|
||||
{
|
||||
if (PaintRoutineEditor* ed = dynamic_cast<PaintRoutineEditor*> (getParentComponent()))
|
||||
{
|
||||
const Rectangle<int> parentArea (ed->getComponentArea());
|
||||
|
||||
Rectangle<int> r (getCurrentBounds (parentArea));
|
||||
Rectangle<float> b (image->getDrawableBounds());
|
||||
|
||||
r.setSize ((int) (b.getWidth() + 0.999f),
|
||||
(int) (b.getHeight() + 0.999f));
|
||||
|
||||
setCurrentBounds (r, parentArea, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::SetStretchModeAction::SetStretchModeAction (PaintElementImage* const element, const StretchMode newValue_)
|
||||
: PaintElementUndoableAction <PaintElementImage> (element),
|
||||
newValue (newValue_)
|
||||
{
|
||||
oldValue = element->getStretchMode();
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetStretchModeAction::perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setStretchMode (newValue, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PaintElementImage::SetStretchModeAction::undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setStretchMode (oldValue, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
PaintElementImage::StretchMode PaintElementImage::getStretchMode() const noexcept { return mode; }
|
||||
|
||||
void PaintElementImage::setStretchMode (const StretchMode newMode, const bool undoable)
|
||||
{
|
||||
if (mode != newMode)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetStretchModeAction (this, newMode),
|
||||
"Change image mode");
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = newMode;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
XmlElement* PaintElementImage::createXml() const
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
e->setAttribute ("resource", resourceName);
|
||||
e->setAttribute ("opacity", opacity);
|
||||
e->setAttribute ("mode", (int) mode);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool PaintElementImage::loadFromXml (const XmlElement& xml)
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
resourceName = xml.getStringAttribute ("resource", String());
|
||||
opacity = xml.getDoubleAttribute ("opacity", 1.0);
|
||||
mode = (StretchMode) xml.getIntAttribute ("mode", (int) stretched);
|
||||
|
||||
repaint();
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::ImageElementResourceProperty::ImageElementResourceProperty (PaintElementImage* const e)
|
||||
: ImageResourceProperty <PaintElementImage> (e, "image source")
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementImage::ImageElementResourceProperty::setResource (const String& newName)
|
||||
{
|
||||
if (element != nullptr)
|
||||
element->setResource (newName, true);
|
||||
}
|
||||
|
||||
String PaintElementImage::ImageElementResourceProperty::getResource() const
|
||||
{
|
||||
if (element != nullptr)
|
||||
return element->getResource();
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
PaintElementImage::OpacityProperty::OpacityProperty (PaintElementImage* const e)
|
||||
: SliderPropertyComponent ("opacity", 0.0, 1.0, 0.001),
|
||||
listener (e)
|
||||
{
|
||||
listener.setPropertyToRefresh (*this);
|
||||
}
|
||||
|
||||
void PaintElementImage::OpacityProperty::setValue (double newValue)
|
||||
{
|
||||
listener.owner->getDocument()->getUndoManager().undoCurrentTransactionOnly();
|
||||
listener.owner->setOpacity (newValue, true);
|
||||
}
|
||||
|
||||
double PaintElementImage::OpacityProperty::getValue() const
|
||||
{
|
||||
return listener.owner->getOpacity();
|
||||
}
|
||||
|
||||
PaintElementImage::StretchModeProperty::StretchModeProperty (PaintElementImage* const e)
|
||||
: ChoicePropertyComponent ("stretch mode"),
|
||||
listener (e)
|
||||
{
|
||||
listener.setPropertyToRefresh (*this);
|
||||
|
||||
choices.add ("Stretched to fit");
|
||||
choices.add ("Maintain aspect ratio");
|
||||
choices.add ("Maintain aspect ratio, only reduce in size");
|
||||
}
|
||||
|
||||
void PaintElementImage::StretchModeProperty::setIndex (int newIndex)
|
||||
{
|
||||
listener.owner->setStretchMode ((StretchMode) newIndex, true);
|
||||
}
|
||||
|
||||
int PaintElementImage::StretchModeProperty::getIndex() const
|
||||
{
|
||||
return (int) listener.owner->getStretchMode();
|
||||
}
|
||||
|
||||
PaintElementImage::ResetSizeProperty::ResetSizeProperty (PaintElementImage* const e)
|
||||
: ButtonPropertyComponent ("reset", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void PaintElementImage::ResetSizeProperty::buttonClicked()
|
||||
{
|
||||
element->resetToImageSize();
|
||||
}
|
||||
|
||||
String PaintElementImage::ResetSizeProperty::getButtonText() const { return "reset to image size"; }
|
||||
|
@ -1,165 +1,165 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "../Properties/jucer_FilePropertyComponent.h"
|
||||
#include "jucer_ImageResourceProperty.h"
|
||||
#include "jucer_PaintElementUndoableAction.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementImage : public PaintElement
|
||||
{
|
||||
public:
|
||||
PaintElementImage (PaintRoutine*);
|
||||
~PaintElementImage() override;
|
||||
|
||||
enum StretchMode
|
||||
{
|
||||
stretched = 0,
|
||||
proportional = 1,
|
||||
proportionalReducingOnly = 2
|
||||
};
|
||||
|
||||
const Drawable* getDrawable();
|
||||
void draw (Graphics&, const ComponentLayout*, const Rectangle<int>&) override;
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array <PropertyComponent*>&, bool) override;
|
||||
void fillInGeneratedCode (GeneratedCode&, String&) override;
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override;
|
||||
|
||||
//==============================================================================
|
||||
class SetResourceAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetResourceAction (PaintElementImage* const, const String&);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
String newResource, oldResource;
|
||||
};
|
||||
|
||||
void setResource (const String&, const bool);
|
||||
|
||||
String getResource() const;
|
||||
|
||||
//==============================================================================
|
||||
class SetOpacityAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetOpacityAction (PaintElementImage* const, const double);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
double newOpacity, oldOpacity;
|
||||
};
|
||||
|
||||
void setOpacity (double, const bool);
|
||||
double getOpacity() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
static const char* getTagName() noexcept;
|
||||
|
||||
void resetToImageSize();
|
||||
|
||||
//==============================================================================
|
||||
class SetStretchModeAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetStretchModeAction (PaintElementImage* const, const StretchMode);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
StretchMode newValue, oldValue;
|
||||
};
|
||||
|
||||
StretchMode getStretchMode() const noexcept;
|
||||
|
||||
void setStretchMode (const StretchMode, const bool);
|
||||
|
||||
//==============================================================================
|
||||
XmlElement* createXml() const override;
|
||||
|
||||
bool loadFromXml (const XmlElement&) override;
|
||||
|
||||
private:
|
||||
String resourceName;
|
||||
double opacity;
|
||||
StretchMode mode;
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
class ImageElementResourceProperty : public ImageResourceProperty <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
ImageElementResourceProperty (PaintElementImage* const);
|
||||
|
||||
void setResource (const String&);
|
||||
String getResource() const;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OpacityProperty : public SliderPropertyComponent
|
||||
{
|
||||
public:
|
||||
OpacityProperty (PaintElementImage* const);
|
||||
|
||||
void setValue (double);
|
||||
double getValue() const;
|
||||
|
||||
ElementListener<PaintElementImage> listener;
|
||||
};
|
||||
|
||||
class StretchModeProperty : public ChoicePropertyComponent
|
||||
{
|
||||
public:
|
||||
StretchModeProperty (PaintElementImage* const);
|
||||
|
||||
void setIndex (int);
|
||||
int getIndex() const;
|
||||
|
||||
ElementListener<PaintElementImage> listener;
|
||||
};
|
||||
|
||||
class ResetSizeProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ResetSizeProperty (PaintElementImage* const);
|
||||
|
||||
void buttonClicked();
|
||||
String getButtonText() const;
|
||||
|
||||
private:
|
||||
PaintElementImage* const element;
|
||||
};
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "../Properties/jucer_FilePropertyComponent.h"
|
||||
#include "jucer_ImageResourceProperty.h"
|
||||
#include "jucer_PaintElementUndoableAction.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementImage : public PaintElement
|
||||
{
|
||||
public:
|
||||
PaintElementImage (PaintRoutine*);
|
||||
~PaintElementImage() override;
|
||||
|
||||
enum StretchMode
|
||||
{
|
||||
stretched = 0,
|
||||
proportional = 1,
|
||||
proportionalReducingOnly = 2
|
||||
};
|
||||
|
||||
const Drawable* getDrawable();
|
||||
void draw (Graphics&, const ComponentLayout*, const Rectangle<int>&) override;
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array <PropertyComponent*>&, bool) override;
|
||||
void fillInGeneratedCode (GeneratedCode&, String&) override;
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override;
|
||||
|
||||
//==============================================================================
|
||||
class SetResourceAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetResourceAction (PaintElementImage* const, const String&);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
String newResource, oldResource;
|
||||
};
|
||||
|
||||
void setResource (const String&, const bool);
|
||||
|
||||
String getResource() const;
|
||||
|
||||
//==============================================================================
|
||||
class SetOpacityAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetOpacityAction (PaintElementImage* const, const double);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
double newOpacity, oldOpacity;
|
||||
};
|
||||
|
||||
void setOpacity (double, const bool);
|
||||
double getOpacity() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
static const char* getTagName() noexcept;
|
||||
|
||||
void resetToImageSize();
|
||||
|
||||
//==============================================================================
|
||||
class SetStretchModeAction : public PaintElementUndoableAction <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
SetStretchModeAction (PaintElementImage* const, const StretchMode);
|
||||
|
||||
bool perform();
|
||||
bool undo();
|
||||
|
||||
private:
|
||||
StretchMode newValue, oldValue;
|
||||
};
|
||||
|
||||
StretchMode getStretchMode() const noexcept;
|
||||
|
||||
void setStretchMode (const StretchMode, const bool);
|
||||
|
||||
//==============================================================================
|
||||
XmlElement* createXml() const override;
|
||||
|
||||
bool loadFromXml (const XmlElement&) override;
|
||||
|
||||
private:
|
||||
String resourceName;
|
||||
double opacity;
|
||||
StretchMode mode;
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
class ImageElementResourceProperty : public ImageResourceProperty <PaintElementImage>
|
||||
{
|
||||
public:
|
||||
ImageElementResourceProperty (PaintElementImage* const);
|
||||
|
||||
void setResource (const String&);
|
||||
String getResource() const;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OpacityProperty : public SliderPropertyComponent
|
||||
{
|
||||
public:
|
||||
OpacityProperty (PaintElementImage* const);
|
||||
|
||||
void setValue (double);
|
||||
double getValue() const;
|
||||
|
||||
ElementListener<PaintElementImage> listener;
|
||||
};
|
||||
|
||||
class StretchModeProperty : public ChoicePropertyComponent
|
||||
{
|
||||
public:
|
||||
StretchModeProperty (PaintElementImage* const);
|
||||
|
||||
void setIndex (int);
|
||||
int getIndex() const;
|
||||
|
||||
ElementListener<PaintElementImage> listener;
|
||||
};
|
||||
|
||||
class ResetSizeProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ResetSizeProperty (PaintElementImage* const);
|
||||
|
||||
void buttonClicked();
|
||||
String getButtonText() const;
|
||||
|
||||
private:
|
||||
PaintElementImage* const element;
|
||||
};
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,176 +1,176 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "jucer_ElementSiblingComponent.h"
|
||||
class PathPointComponent;
|
||||
class PaintElementPath;
|
||||
|
||||
//==============================================================================
|
||||
class PathPoint
|
||||
{
|
||||
public:
|
||||
PathPoint (PaintElementPath* const owner);
|
||||
PathPoint (const PathPoint& other);
|
||||
PathPoint& operator= (const PathPoint& other);
|
||||
~PathPoint();
|
||||
|
||||
static constexpr auto maxRects = 3;
|
||||
|
||||
PaintElementPath* owner;
|
||||
Path::Iterator::PathElementType type;
|
||||
RelativePositionedRectangle pos [maxRects];
|
||||
|
||||
int getNumPoints() const;
|
||||
|
||||
void changePointType (const Path::Iterator::PathElementType newType,
|
||||
const Rectangle<int>& parentArea,
|
||||
const bool undoable);
|
||||
|
||||
void deleteFromPath();
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected);
|
||||
|
||||
private:
|
||||
PathPoint withChangedPointType (const Path::Iterator::PathElementType newType,
|
||||
const Rectangle<int>& parentArea) const;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementPath : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementPath (PaintRoutine* owner);
|
||||
~PaintElementPath() override;
|
||||
|
||||
//==============================================================================
|
||||
void setInitialBounds (int parentWidth, int parentHeight) override;
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;
|
||||
void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable) override;
|
||||
|
||||
//==============================================================================
|
||||
bool getPoint (int index, int pointNumber, double& x, double& y, const Rectangle<int>& parentArea) const;
|
||||
void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, const bool undoable);
|
||||
|
||||
RelativePositionedRectangle getPoint (int index, int pointNumber) const;
|
||||
void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, const bool undoable);
|
||||
|
||||
int getNumPoints() const noexcept { return points.size(); }
|
||||
PathPoint* getPoint (int index) const noexcept { return points [index]; }
|
||||
int indexOfPoint (PathPoint* const p) const noexcept { return points.indexOf (p); }
|
||||
|
||||
PathPoint* addPoint (int pointIndexToAddItAfter, const bool undoable);
|
||||
void deletePoint (int pointIndex, const bool undoable);
|
||||
|
||||
void pointListChanged();
|
||||
|
||||
int findSegmentAtXY (int x, int y) const;
|
||||
|
||||
//==============================================================================
|
||||
bool isSubpathClosed (int pointIndex) const;
|
||||
void setSubpathClosed (int pointIndex, const bool closed, const bool undoable);
|
||||
|
||||
bool isNonZeroWinding() const noexcept { return nonZeroWinding; }
|
||||
void setNonZeroWinding (const bool nonZero, const bool undoable);
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override;
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override;
|
||||
|
||||
//==============================================================================
|
||||
static const char* getTagName() noexcept { return "PATH"; }
|
||||
XmlElement* createXml() const override;
|
||||
bool loadFromXml (const XmlElement& xml) override;
|
||||
|
||||
void setToPath (const Path& p);
|
||||
|
||||
//==============================================================================
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override;
|
||||
void drawExtraEditorGraphics (Graphics& g, const Rectangle<int>& relativeTo) override;
|
||||
|
||||
void resized() override;
|
||||
void parentSizeChanged() override;
|
||||
|
||||
void mouseDown (const MouseEvent& e) override;
|
||||
void mouseDrag (const MouseEvent& e) override;
|
||||
void mouseUp (const MouseEvent& e) override;
|
||||
|
||||
void createSiblingComponents() override;
|
||||
void changed() override;
|
||||
|
||||
private:
|
||||
friend class PathPoint;
|
||||
friend class PathPointComponent;
|
||||
OwnedArray<PathPoint> points;
|
||||
bool nonZeroWinding;
|
||||
mutable Path path;
|
||||
mutable Rectangle<int> lastPathBounds;
|
||||
int mouseDownOnSegment;
|
||||
bool mouseDownSelectSegmentStatus;
|
||||
String customPaintCode;
|
||||
|
||||
String pathToString() const;
|
||||
void restorePathFromString (const String& s);
|
||||
void updateStoredPath (const ComponentLayout* layout, const Rectangle<int>& parentArea) const;
|
||||
int getBorderSize() const;
|
||||
|
||||
void rescalePoint (RelativePositionedRectangle& pos, int dx, int dy,
|
||||
double scaleX, double scaleY,
|
||||
double scaleStartX, double scaleStartY,
|
||||
const Rectangle<int>& parentArea) const;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PathPointComponent : public ElementSiblingComponent
|
||||
{
|
||||
public:
|
||||
PathPointComponent (PaintElementPath* const path_,
|
||||
const int index, const int pointNumber);
|
||||
|
||||
~PathPointComponent();
|
||||
|
||||
void updatePosition();
|
||||
void showPopupMenu();
|
||||
|
||||
void paint (Graphics& g);
|
||||
void mouseDown (const MouseEvent& e);
|
||||
void mouseDrag (const MouseEvent& e);
|
||||
void mouseUp (const MouseEvent& e);
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*);
|
||||
|
||||
private:
|
||||
PaintElementPath* const path;
|
||||
PaintRoutine* const routine;
|
||||
const int index;
|
||||
const int pointNumber;
|
||||
int dragX, dragY;
|
||||
bool selected, dragging, mouseDownSelectStatus;
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "jucer_ElementSiblingComponent.h"
|
||||
class PathPointComponent;
|
||||
class PaintElementPath;
|
||||
|
||||
//==============================================================================
|
||||
class PathPoint
|
||||
{
|
||||
public:
|
||||
PathPoint (PaintElementPath* const owner);
|
||||
PathPoint (const PathPoint& other);
|
||||
PathPoint& operator= (const PathPoint& other);
|
||||
~PathPoint();
|
||||
|
||||
static constexpr auto maxRects = 3;
|
||||
|
||||
PaintElementPath* owner;
|
||||
Path::Iterator::PathElementType type;
|
||||
RelativePositionedRectangle pos [maxRects];
|
||||
|
||||
int getNumPoints() const;
|
||||
|
||||
void changePointType (const Path::Iterator::PathElementType newType,
|
||||
const Rectangle<int>& parentArea,
|
||||
const bool undoable);
|
||||
|
||||
void deleteFromPath();
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected);
|
||||
|
||||
private:
|
||||
PathPoint withChangedPointType (const Path::Iterator::PathElementType newType,
|
||||
const Rectangle<int>& parentArea) const;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementPath : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementPath (PaintRoutine* owner);
|
||||
~PaintElementPath() override;
|
||||
|
||||
//==============================================================================
|
||||
void setInitialBounds (int parentWidth, int parentHeight) override;
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;
|
||||
void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable) override;
|
||||
|
||||
//==============================================================================
|
||||
bool getPoint (int index, int pointNumber, double& x, double& y, const Rectangle<int>& parentArea) const;
|
||||
void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, const bool undoable);
|
||||
|
||||
RelativePositionedRectangle getPoint (int index, int pointNumber) const;
|
||||
void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, const bool undoable);
|
||||
|
||||
int getNumPoints() const noexcept { return points.size(); }
|
||||
PathPoint* getPoint (int index) const noexcept { return points [index]; }
|
||||
int indexOfPoint (PathPoint* const p) const noexcept { return points.indexOf (p); }
|
||||
|
||||
PathPoint* addPoint (int pointIndexToAddItAfter, const bool undoable);
|
||||
void deletePoint (int pointIndex, const bool undoable);
|
||||
|
||||
void pointListChanged();
|
||||
|
||||
int findSegmentAtXY (int x, int y) const;
|
||||
|
||||
//==============================================================================
|
||||
bool isSubpathClosed (int pointIndex) const;
|
||||
void setSubpathClosed (int pointIndex, const bool closed, const bool undoable);
|
||||
|
||||
bool isNonZeroWinding() const noexcept { return nonZeroWinding; }
|
||||
void setNonZeroWinding (const bool nonZero, const bool undoable);
|
||||
|
||||
//==============================================================================
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override;
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override;
|
||||
|
||||
//==============================================================================
|
||||
static const char* getTagName() noexcept { return "PATH"; }
|
||||
XmlElement* createXml() const override;
|
||||
bool loadFromXml (const XmlElement& xml) override;
|
||||
|
||||
void setToPath (const Path& p);
|
||||
|
||||
//==============================================================================
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override;
|
||||
void drawExtraEditorGraphics (Graphics& g, const Rectangle<int>& relativeTo) override;
|
||||
|
||||
void resized() override;
|
||||
void parentSizeChanged() override;
|
||||
|
||||
void mouseDown (const MouseEvent& e) override;
|
||||
void mouseDrag (const MouseEvent& e) override;
|
||||
void mouseUp (const MouseEvent& e) override;
|
||||
|
||||
void createSiblingComponents() override;
|
||||
void changed() override;
|
||||
|
||||
private:
|
||||
friend class PathPoint;
|
||||
friend class PathPointComponent;
|
||||
OwnedArray<PathPoint> points;
|
||||
bool nonZeroWinding;
|
||||
mutable Path path;
|
||||
mutable Rectangle<int> lastPathBounds;
|
||||
int mouseDownOnSegment;
|
||||
bool mouseDownSelectSegmentStatus;
|
||||
String customPaintCode;
|
||||
|
||||
String pathToString() const;
|
||||
void restorePathFromString (const String& s);
|
||||
void updateStoredPath (const ComponentLayout* layout, const Rectangle<int>& parentArea) const;
|
||||
int getBorderSize() const;
|
||||
|
||||
void rescalePoint (RelativePositionedRectangle& pos, int dx, int dy,
|
||||
double scaleX, double scaleY,
|
||||
double scaleStartX, double scaleStartY,
|
||||
const Rectangle<int>& parentArea) const;
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class PathPointComponent : public ElementSiblingComponent
|
||||
{
|
||||
public:
|
||||
PathPointComponent (PaintElementPath* const path_,
|
||||
const int index, const int pointNumber);
|
||||
|
||||
~PathPointComponent();
|
||||
|
||||
void updatePosition();
|
||||
void showPopupMenu();
|
||||
|
||||
void paint (Graphics& g);
|
||||
void mouseDown (const MouseEvent& e);
|
||||
void mouseDrag (const MouseEvent& e);
|
||||
void mouseUp (const MouseEvent& e);
|
||||
|
||||
void changeListenerCallback (ChangeBroadcaster*);
|
||||
|
||||
private:
|
||||
PaintElementPath* const path;
|
||||
PaintRoutine* const routine;
|
||||
const int index;
|
||||
const int pointNumber;
|
||||
int dragX, dragY;
|
||||
bool selected, dragging, mouseDownSelectStatus;
|
||||
};
|
||||
|
@ -1,184 +1,184 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementRectangle : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementRectangle (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Rectangle", true, false)
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override
|
||||
{
|
||||
return PaintElement::getCurrentBounds (parentArea); // bypass the ColouredElement implementation
|
||||
}
|
||||
|
||||
void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& parentArea, const bool undoable) override
|
||||
{
|
||||
PaintElement::setCurrentBounds (newBounds, parentArea, undoable); // bypass the ColouredElement implementation
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
Component tempParentComp;
|
||||
tempParentComp.setBounds (parentArea);
|
||||
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
const Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
g.fillRect (r);
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
roundToInt (getStrokeType().stroke.getStrokeThickness()));
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array <PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillRect (x, y, width, height);\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
s << " ";
|
||||
strokeType.fill.fillInGeneratedCode ("stroke", position, code, s);
|
||||
s << " g.drawRect (x, y, width, height, " << roundToInt (strokeType.stroke.getStrokeThickness()) << ");\n\n";
|
||||
}
|
||||
|
||||
s << "}\n\n";
|
||||
|
||||
paintMethodCode += s;
|
||||
}
|
||||
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "RECT"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
Path path;
|
||||
path.addRectangle (getCurrentAbsoluteBounds());
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
String customPaintCode;
|
||||
|
||||
class ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ShapeToPathProperty (PaintElementRectangle* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
private:
|
||||
PaintElementRectangle* const element;
|
||||
};
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementRectangle : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementRectangle (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Rectangle", true, false)
|
||||
{
|
||||
}
|
||||
|
||||
Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override
|
||||
{
|
||||
return PaintElement::getCurrentBounds (parentArea); // bypass the ColouredElement implementation
|
||||
}
|
||||
|
||||
void setCurrentBounds (const Rectangle<int>& newBounds, const Rectangle<int>& parentArea, const bool undoable) override
|
||||
{
|
||||
PaintElement::setCurrentBounds (newBounds, parentArea, undoable); // bypass the ColouredElement implementation
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
Component tempParentComp;
|
||||
tempParentComp.setBounds (parentArea);
|
||||
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
const Rectangle<int> r (position.getRectangle (parentArea, layout));
|
||||
g.fillRect (r);
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
roundToInt (getStrokeType().stroke.getStrokeThickness()));
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array <PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillRect (x, y, width, height);\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
s << " ";
|
||||
strokeType.fill.fillInGeneratedCode ("stroke", position, code, s);
|
||||
s << " g.drawRect (x, y, width, height, " << roundToInt (strokeType.stroke.getStrokeThickness()) << ");\n\n";
|
||||
}
|
||||
|
||||
s << "}\n\n";
|
||||
|
||||
paintMethodCode += s;
|
||||
}
|
||||
|
||||
void applyCustomPaintSnippets (StringArray& snippets) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "RECT"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* e = new XmlElement (getTagName());
|
||||
position.applyToXml (*e);
|
||||
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
Path path;
|
||||
path.addRectangle (getCurrentAbsoluteBounds());
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
String customPaintCode;
|
||||
|
||||
class ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ShapeToPathProperty (PaintElementRectangle* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
private:
|
||||
PaintElementRectangle* const element;
|
||||
};
|
||||
};
|
||||
|
@ -1,267 +1,267 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "../jucer_UtilityFunctions.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementRoundedRectangle : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementRoundedRectangle (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Rounded Rectangle", true, false)
|
||||
{
|
||||
cornerSize = 10.0;
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
double x, y, w, h;
|
||||
position.getRectangleDouble (x, y, w, h, parentArea, layout);
|
||||
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
g.fillRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize);
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize,
|
||||
getStrokeType().stroke.getStrokeThickness());
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
props.add (new CornerSizeProperty (this));
|
||||
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class SetCornerSizeAction : public PaintElementUndoableAction <PaintElementRoundedRectangle>
|
||||
{
|
||||
public:
|
||||
SetCornerSizeAction (PaintElementRoundedRectangle* const element, const double newSize_)
|
||||
: PaintElementUndoableAction <PaintElementRoundedRectangle> (element),
|
||||
newSize (newSize_)
|
||||
{
|
||||
oldSize = element->getCornerSize();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setCornerSize (newSize, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setCornerSize (oldSize, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
double newSize, oldSize;
|
||||
};
|
||||
|
||||
void setCornerSize (const double newSize, const bool undoable)
|
||||
{
|
||||
if (newSize != cornerSize)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetCornerSizeAction (this, newSize),
|
||||
"Change rounded rectangle corner size");
|
||||
}
|
||||
else
|
||||
{
|
||||
cornerSize = newSize;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double getCornerSize() const noexcept { return cornerSize; }
|
||||
|
||||
//==============================================================================
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillRoundedRectangle (x, y, width, height, " << CodeHelpers::floatLiteral (cornerSize, 3) << ");\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
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) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "ROUNDRECT"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* const e = new XmlElement (getTagName());
|
||||
|
||||
position.applyToXml (*e);
|
||||
e->setAttribute ("cornerSize", cornerSize);
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
cornerSize = xml.getDoubleAttribute ("cornerSize", 10.0);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
double x, y, w, h;
|
||||
getCurrentAbsoluteBoundsDouble (x, y, w, h);
|
||||
|
||||
Path path;
|
||||
path.addRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize);
|
||||
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
double cornerSize;
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
class CornerSizeProperty : public SliderPropertyComponent,
|
||||
private juce::ChangeListener
|
||||
{
|
||||
public:
|
||||
CornerSizeProperty (PaintElementRoundedRectangle* const owner_)
|
||||
: SliderPropertyComponent ("corner size", 1.0, 200.0, 0.5, 0.4),
|
||||
owner (owner_)
|
||||
{
|
||||
owner->getDocument()->addChangeListener (this);
|
||||
}
|
||||
|
||||
~CornerSizeProperty() override
|
||||
{
|
||||
owner->getDocument()->removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
owner->getDocument()->getUndoManager().undoCurrentTransactionOnly();
|
||||
|
||||
owner->setCornerSize (newValue, true);
|
||||
}
|
||||
|
||||
double getValue() const override { return owner->getCornerSize(); }
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
|
||||
|
||||
PaintElementRoundedRectangle* const owner;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ShapeToPathProperty (PaintElementRoundedRectangle* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
private:
|
||||
PaintElementRoundedRectangle* const element;
|
||||
};
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ColouredElement.h"
|
||||
#include "../jucer_UtilityFunctions.h"
|
||||
|
||||
//==============================================================================
|
||||
class PaintElementRoundedRectangle : public ColouredElement
|
||||
{
|
||||
public:
|
||||
PaintElementRoundedRectangle (PaintRoutine* pr)
|
||||
: ColouredElement (pr, "Rounded Rectangle", true, false)
|
||||
{
|
||||
cornerSize = 10.0;
|
||||
}
|
||||
|
||||
void draw (Graphics& g, const ComponentLayout* layout, const Rectangle<int>& parentArea) override
|
||||
{
|
||||
double x, y, w, h;
|
||||
position.getRectangleDouble (x, y, w, h, parentArea, layout);
|
||||
|
||||
fillType.setFillType (g, getDocument(), parentArea);
|
||||
g.fillRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize);
|
||||
|
||||
if (isStrokePresent)
|
||||
{
|
||||
strokeType.fill.setFillType (g, getDocument(), parentArea);
|
||||
|
||||
g.drawRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize,
|
||||
getStrokeType().stroke.getStrokeThickness());
|
||||
}
|
||||
}
|
||||
|
||||
void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override
|
||||
{
|
||||
props.add (new CornerSizeProperty (this));
|
||||
|
||||
ColouredElement::getEditableProperties (props, multipleSelected);
|
||||
|
||||
props.add (new ShapeToPathProperty (this));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class SetCornerSizeAction : public PaintElementUndoableAction <PaintElementRoundedRectangle>
|
||||
{
|
||||
public:
|
||||
SetCornerSizeAction (PaintElementRoundedRectangle* const element, const double newSize_)
|
||||
: PaintElementUndoableAction <PaintElementRoundedRectangle> (element),
|
||||
newSize (newSize_)
|
||||
{
|
||||
oldSize = element->getCornerSize();
|
||||
}
|
||||
|
||||
bool perform()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setCornerSize (newSize, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool undo()
|
||||
{
|
||||
showCorrectTab();
|
||||
getElement()->setCornerSize (oldSize, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
double newSize, oldSize;
|
||||
};
|
||||
|
||||
void setCornerSize (const double newSize, const bool undoable)
|
||||
{
|
||||
if (newSize != cornerSize)
|
||||
{
|
||||
if (undoable)
|
||||
{
|
||||
perform (new SetCornerSizeAction (this, newSize),
|
||||
"Change rounded rectangle corner size");
|
||||
}
|
||||
else
|
||||
{
|
||||
cornerSize = newSize;
|
||||
changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double getCornerSize() const noexcept { return cornerSize; }
|
||||
|
||||
//==============================================================================
|
||||
void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) override
|
||||
{
|
||||
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())
|
||||
{
|
||||
s << " ";
|
||||
fillType.fillInGeneratedCode ("fill", position, code, s);
|
||||
s << " g.fillRoundedRectangle (x, y, width, height, " << CodeHelpers::floatLiteral (cornerSize, 3) << ");\n";
|
||||
}
|
||||
|
||||
if (isStrokePresent && ! strokeType.isInvisible())
|
||||
{
|
||||
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) override
|
||||
{
|
||||
customPaintCode.clear();
|
||||
|
||||
if (! snippets.isEmpty() && (! fillType.isInvisible() || (isStrokePresent && ! strokeType.isInvisible())))
|
||||
{
|
||||
customPaintCode = snippets[0];
|
||||
snippets.remove (0);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* getTagName() noexcept { return "ROUNDRECT"; }
|
||||
|
||||
XmlElement* createXml() const override
|
||||
{
|
||||
XmlElement* const e = new XmlElement (getTagName());
|
||||
|
||||
position.applyToXml (*e);
|
||||
e->setAttribute ("cornerSize", cornerSize);
|
||||
addColourAttributes (e);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
bool loadFromXml (const XmlElement& xml) override
|
||||
{
|
||||
if (xml.hasTagName (getTagName()))
|
||||
{
|
||||
position.restoreFromXml (xml, position);
|
||||
cornerSize = xml.getDoubleAttribute ("cornerSize", 10.0);
|
||||
loadColourAttributes (xml);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
jassertfalse;
|
||||
return false;
|
||||
}
|
||||
|
||||
void convertToPath()
|
||||
{
|
||||
double x, y, w, h;
|
||||
getCurrentAbsoluteBoundsDouble (x, y, w, h);
|
||||
|
||||
Path path;
|
||||
path.addRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize);
|
||||
|
||||
convertToNewPathElement (path);
|
||||
}
|
||||
|
||||
private:
|
||||
double cornerSize;
|
||||
String customPaintCode;
|
||||
|
||||
//==============================================================================
|
||||
class CornerSizeProperty : public SliderPropertyComponent,
|
||||
private juce::ChangeListener
|
||||
{
|
||||
public:
|
||||
CornerSizeProperty (PaintElementRoundedRectangle* const owner_)
|
||||
: SliderPropertyComponent ("corner size", 1.0, 200.0, 0.5, 0.4),
|
||||
owner (owner_)
|
||||
{
|
||||
owner->getDocument()->addChangeListener (this);
|
||||
}
|
||||
|
||||
~CornerSizeProperty() override
|
||||
{
|
||||
owner->getDocument()->removeChangeListener (this);
|
||||
}
|
||||
|
||||
void setValue (double newValue) override
|
||||
{
|
||||
owner->getDocument()->getUndoManager().undoCurrentTransactionOnly();
|
||||
|
||||
owner->setCornerSize (newValue, true);
|
||||
}
|
||||
|
||||
double getValue() const override { return owner->getCornerSize(); }
|
||||
|
||||
private:
|
||||
void changeListenerCallback (ChangeBroadcaster*) override { refresh(); }
|
||||
|
||||
PaintElementRoundedRectangle* const owner;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class ShapeToPathProperty : public ButtonPropertyComponent
|
||||
{
|
||||
public:
|
||||
ShapeToPathProperty (PaintElementRoundedRectangle* const e)
|
||||
: ButtonPropertyComponent ("path", false),
|
||||
element (e)
|
||||
{
|
||||
}
|
||||
|
||||
void buttonClicked()
|
||||
{
|
||||
element->convertToPath();
|
||||
}
|
||||
|
||||
String getButtonText() const
|
||||
{
|
||||
return "convert to a path";
|
||||
}
|
||||
|
||||
private:
|
||||
PaintElementRoundedRectangle* const element;
|
||||
};
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,142 +1,142 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../UI/jucer_JucerDocumentEditor.h"
|
||||
#include "jucer_PaintElementGroup.h"
|
||||
|
||||
//==============================================================================
|
||||
template <class ElementType>
|
||||
class PaintElementUndoableAction : public UndoableAction
|
||||
{
|
||||
public:
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
|
||||
|
||||
PaintElementUndoableAction (ElementType* const element)
|
||||
: routine (*element->getOwner()),
|
||||
elementIndex (element->getOwner()->indexOfElement (element))
|
||||
{
|
||||
jassert (element != nullptr);
|
||||
|
||||
if (element != nullptr && elementIndex < 0)
|
||||
findGroupIndices (element->getOwner(), element);
|
||||
|
||||
jassert (elementIndex >= 0);
|
||||
}
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
|
||||
ElementType* getElement() const
|
||||
{
|
||||
if (containerGroups.size() > 0)
|
||||
{
|
||||
auto group = dynamic_cast<PaintElementGroup*> (routine.getElement (containerGroups.getFirst()));
|
||||
|
||||
if (group == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (int i = 1; i < containerGroups.size(); ++i)
|
||||
{
|
||||
group = dynamic_cast<PaintElementGroup*> (group->getElement (containerGroups.getUnchecked(i)));
|
||||
|
||||
if (group == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto e = dynamic_cast<ElementType*> (group->getElement (elementIndex));
|
||||
jassert (e != nullptr);
|
||||
return e;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto e = dynamic_cast<ElementType*> (routine.getElement (elementIndex));
|
||||
jassert (e != nullptr);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
int getSizeInUnits() { return 2; }
|
||||
|
||||
protected:
|
||||
PaintRoutine& routine;
|
||||
int elementIndex;
|
||||
Array <int> containerGroups;
|
||||
|
||||
void changed() const
|
||||
{
|
||||
jassert (routine.getDocument() != nullptr);
|
||||
routine.getDocument()->changed();
|
||||
}
|
||||
|
||||
void showCorrectTab() const
|
||||
{
|
||||
if (JucerDocumentEditor* const docHolder = JucerDocumentEditor::getActiveDocumentHolder())
|
||||
docHolder->showGraphics (&routine);
|
||||
|
||||
if (routine.getSelectedElements().getNumSelected() == 0)
|
||||
if (ElementType* const e = dynamic_cast<ElementType*> (routine.getElement (elementIndex)))
|
||||
routine.getSelectedElements().selectOnly (e);
|
||||
}
|
||||
|
||||
private:
|
||||
void findGroupIndices (PaintRoutine* const pr, PaintElement* const element)
|
||||
{
|
||||
for (int i = pr->getNumElements(); --i >= 0;)
|
||||
{
|
||||
if (auto pg = dynamic_cast<PaintElementGroup*> (pr->getElement (i)))
|
||||
{
|
||||
if (pg->containsElement (element))
|
||||
{
|
||||
containerGroups.add (i);
|
||||
findGroupIndices (pg, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void findGroupIndices (PaintElementGroup* const group, PaintElement* const element)
|
||||
{
|
||||
elementIndex = group->indexOfElement (element);
|
||||
|
||||
if (elementIndex < 0)
|
||||
{
|
||||
for (int i = group->getNumElements(); --i >= 0;)
|
||||
{
|
||||
if (auto pg = dynamic_cast<PaintElementGroup*> (group->getElement (i)))
|
||||
{
|
||||
if (pg->containsElement (element))
|
||||
{
|
||||
containerGroups.add (i);
|
||||
findGroupIndices (pg, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PaintElementUndoableAction (const PaintElementUndoableAction&);
|
||||
PaintElementUndoableAction& operator= (const PaintElementUndoableAction&);
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../UI/jucer_JucerDocumentEditor.h"
|
||||
#include "jucer_PaintElementGroup.h"
|
||||
|
||||
//==============================================================================
|
||||
template <class ElementType>
|
||||
class PaintElementUndoableAction : public UndoableAction
|
||||
{
|
||||
public:
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
|
||||
|
||||
PaintElementUndoableAction (ElementType* const element)
|
||||
: routine (*element->getOwner()),
|
||||
elementIndex (element->getOwner()->indexOfElement (element))
|
||||
{
|
||||
jassert (element != nullptr);
|
||||
|
||||
if (element != nullptr && elementIndex < 0)
|
||||
findGroupIndices (element->getOwner(), element);
|
||||
|
||||
jassert (elementIndex >= 0);
|
||||
}
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
|
||||
ElementType* getElement() const
|
||||
{
|
||||
if (containerGroups.size() > 0)
|
||||
{
|
||||
auto group = dynamic_cast<PaintElementGroup*> (routine.getElement (containerGroups.getFirst()));
|
||||
|
||||
if (group == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (int i = 1; i < containerGroups.size(); ++i)
|
||||
{
|
||||
group = dynamic_cast<PaintElementGroup*> (group->getElement (containerGroups.getUnchecked(i)));
|
||||
|
||||
if (group == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto e = dynamic_cast<ElementType*> (group->getElement (elementIndex));
|
||||
jassert (e != nullptr);
|
||||
return e;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto e = dynamic_cast<ElementType*> (routine.getElement (elementIndex));
|
||||
jassert (e != nullptr);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
int getSizeInUnits() { return 2; }
|
||||
|
||||
protected:
|
||||
PaintRoutine& routine;
|
||||
int elementIndex;
|
||||
Array <int> containerGroups;
|
||||
|
||||
void changed() const
|
||||
{
|
||||
jassert (routine.getDocument() != nullptr);
|
||||
routine.getDocument()->changed();
|
||||
}
|
||||
|
||||
void showCorrectTab() const
|
||||
{
|
||||
if (JucerDocumentEditor* const docHolder = JucerDocumentEditor::getActiveDocumentHolder())
|
||||
docHolder->showGraphics (&routine);
|
||||
|
||||
if (routine.getSelectedElements().getNumSelected() == 0)
|
||||
if (ElementType* const e = dynamic_cast<ElementType*> (routine.getElement (elementIndex)))
|
||||
routine.getSelectedElements().selectOnly (e);
|
||||
}
|
||||
|
||||
private:
|
||||
void findGroupIndices (PaintRoutine* const pr, PaintElement* const element)
|
||||
{
|
||||
for (int i = pr->getNumElements(); --i >= 0;)
|
||||
{
|
||||
if (auto pg = dynamic_cast<PaintElementGroup*> (pr->getElement (i)))
|
||||
{
|
||||
if (pg->containsElement (element))
|
||||
{
|
||||
containerGroups.add (i);
|
||||
findGroupIndices (pg, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void findGroupIndices (PaintElementGroup* const group, PaintElement* const element)
|
||||
{
|
||||
elementIndex = group->indexOfElement (element);
|
||||
|
||||
if (elementIndex < 0)
|
||||
{
|
||||
for (int i = group->getNumElements(); --i >= 0;)
|
||||
{
|
||||
if (auto pg = dynamic_cast<PaintElementGroup*> (group->getElement (i)))
|
||||
{
|
||||
if (pg->containsElement (element))
|
||||
{
|
||||
containerGroups.add (i);
|
||||
findGroupIndices (pg, element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PaintElementUndoableAction (const PaintElementUndoableAction&);
|
||||
PaintElementUndoableAction& operator= (const PaintElementUndoableAction&);
|
||||
};
|
||||
|
@ -1,107 +1,107 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ElementSiblingComponent.h"
|
||||
#include "../UI/jucer_PaintRoutineEditor.h"
|
||||
|
||||
//==============================================================================
|
||||
class PointComponent : public ElementSiblingComponent
|
||||
{
|
||||
public:
|
||||
PointComponent (PaintElement* const e)
|
||||
: ElementSiblingComponent (e)
|
||||
{
|
||||
setSize (11, 11);
|
||||
setMouseCursor (MouseCursor::UpDownLeftRightResizeCursor);
|
||||
}
|
||||
|
||||
virtual RelativePositionedRectangle getPosition() = 0;
|
||||
virtual void setPosition (const RelativePositionedRectangle& newPos) = 0;
|
||||
|
||||
void updatePosition() override
|
||||
{
|
||||
if (dynamic_cast<PaintRoutineEditor*> (getParentComponent()) != nullptr)
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
const Rectangle<int> r (getPosition().getRectangle (area, owner->getDocument()->getComponentLayout()));
|
||||
|
||||
setCentrePosition (r.getX(), r.getY());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.setColour (Colours::white);
|
||||
g.drawEllipse (2.0f, 2.0f, (float) getWidth() - 4.0f, (float) getHeight() - 4.0f, 2.0f);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.drawEllipse (1.0f, 1.0f, (float) getWidth() - 2.0f, (float) getHeight() - 2.0f, 2.0f);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void mouseDown (const MouseEvent&) override
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
dragX = getX() + getWidth() / 2 - area.getX();
|
||||
dragY = getY() + getHeight() / 2 - area.getY();
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e) override
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
int x = dragX + e.getDistanceFromDragStartX();
|
||||
int y = dragY + e.getDistanceFromDragStartY();
|
||||
|
||||
if (JucerDocument* const document = owner->getDocument())
|
||||
{
|
||||
x = document->snapPosition (x);
|
||||
y = document->snapPosition (y);
|
||||
|
||||
const RelativePositionedRectangle original (getPosition());
|
||||
RelativePositionedRectangle pr (original);
|
||||
|
||||
Rectangle<int> r (pr.getRectangle (Rectangle<int> (0, 0, area.getWidth(), area.getHeight()),
|
||||
document->getComponentLayout()));
|
||||
r.setPosition (x, y);
|
||||
|
||||
pr.updateFrom (r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
Rectangle<int> (0, 0, area.getWidth(), area.getHeight()),
|
||||
document->getComponentLayout());
|
||||
|
||||
if (pr != original)
|
||||
setPosition (pr);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent&) override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
int dragX, dragY;
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_ElementSiblingComponent.h"
|
||||
#include "../UI/jucer_PaintRoutineEditor.h"
|
||||
|
||||
//==============================================================================
|
||||
class PointComponent : public ElementSiblingComponent
|
||||
{
|
||||
public:
|
||||
PointComponent (PaintElement* const e)
|
||||
: ElementSiblingComponent (e)
|
||||
{
|
||||
setSize (11, 11);
|
||||
setMouseCursor (MouseCursor::UpDownLeftRightResizeCursor);
|
||||
}
|
||||
|
||||
virtual RelativePositionedRectangle getPosition() = 0;
|
||||
virtual void setPosition (const RelativePositionedRectangle& newPos) = 0;
|
||||
|
||||
void updatePosition() override
|
||||
{
|
||||
if (dynamic_cast<PaintRoutineEditor*> (getParentComponent()) != nullptr)
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
const Rectangle<int> r (getPosition().getRectangle (area, owner->getDocument()->getComponentLayout()));
|
||||
|
||||
setCentrePosition (r.getX(), r.getY());
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
g.setColour (Colours::white);
|
||||
g.drawEllipse (2.0f, 2.0f, (float) getWidth() - 4.0f, (float) getHeight() - 4.0f, 2.0f);
|
||||
|
||||
g.setColour (Colours::black);
|
||||
g.drawEllipse (1.0f, 1.0f, (float) getWidth() - 2.0f, (float) getHeight() - 2.0f, 2.0f);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void mouseDown (const MouseEvent&) override
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
dragX = getX() + getWidth() / 2 - area.getX();
|
||||
dragY = getY() + getHeight() / 2 - area.getY();
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e) override
|
||||
{
|
||||
const Rectangle<int> area (((PaintRoutineEditor*) getParentComponent())->getComponentArea());
|
||||
int x = dragX + e.getDistanceFromDragStartX();
|
||||
int y = dragY + e.getDistanceFromDragStartY();
|
||||
|
||||
if (JucerDocument* const document = owner->getDocument())
|
||||
{
|
||||
x = document->snapPosition (x);
|
||||
y = document->snapPosition (y);
|
||||
|
||||
const RelativePositionedRectangle original (getPosition());
|
||||
RelativePositionedRectangle pr (original);
|
||||
|
||||
Rectangle<int> r (pr.getRectangle (Rectangle<int> (0, 0, area.getWidth(), area.getHeight()),
|
||||
document->getComponentLayout()));
|
||||
r.setPosition (x, y);
|
||||
|
||||
pr.updateFrom (r.getX(), r.getY(), r.getWidth(), r.getHeight(),
|
||||
Rectangle<int> (0, 0, area.getWidth(), area.getHeight()),
|
||||
document->getComponentLayout());
|
||||
|
||||
if (pr != original)
|
||||
setPosition (pr);
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent&) override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
int dragX, dragY;
|
||||
};
|
||||
|
@ -1,157 +1,157 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 6 End-User License
|
||||
Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-6-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_FillType.h"
|
||||
|
||||
//==============================================================================
|
||||
class StrokeType
|
||||
{
|
||||
public:
|
||||
StrokeType() : stroke (1.0f)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
String getPathStrokeCode() const
|
||||
{
|
||||
PathStrokeType defaultStroke (1.0f);
|
||||
|
||||
String s;
|
||||
|
||||
s << "juce::PathStrokeType (" << CodeHelpers::floatLiteral (stroke.getStrokeThickness(), 3);
|
||||
|
||||
if (stroke.getJointStyle() != defaultStroke.getJointStyle()
|
||||
|| stroke.getEndStyle() != defaultStroke.getEndStyle())
|
||||
{
|
||||
s << ", ";
|
||||
|
||||
switch (stroke.getJointStyle())
|
||||
{
|
||||
case PathStrokeType::mitered: s << "juce::PathStrokeType::mitered"; break;
|
||||
case PathStrokeType::curved: s << "juce::PathStrokeType::curved"; break;
|
||||
case PathStrokeType::beveled: s << "juce::PathStrokeType::beveled"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
if (stroke.getEndStyle() != defaultStroke.getEndStyle())
|
||||
{
|
||||
s << ", ";
|
||||
|
||||
switch (stroke.getEndStyle())
|
||||
{
|
||||
case PathStrokeType::butt: s << "juce::PathStrokeType::butt"; break;
|
||||
case PathStrokeType::square: s << "juce::PathStrokeType::square"; break;
|
||||
case PathStrokeType::rounded: s << "juce::PathStrokeType::rounded"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s << ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
String toString() const
|
||||
{
|
||||
String s;
|
||||
s << stroke.getStrokeThickness();
|
||||
|
||||
switch (stroke.getJointStyle())
|
||||
{
|
||||
case PathStrokeType::mitered: s << ", mitered"; break;
|
||||
case PathStrokeType::curved: s << ", curved"; break;
|
||||
case PathStrokeType::beveled: s << ", beveled"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
switch (stroke.getEndStyle())
|
||||
{
|
||||
case PathStrokeType::butt: s << ", butt"; break;
|
||||
case PathStrokeType::square: s << ", square"; break;
|
||||
case PathStrokeType::rounded: s << ", rounded"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void restoreFromString (const String& s)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (s.isNotEmpty())
|
||||
{
|
||||
const float thickness = (float) s.upToFirstOccurrenceOf (",", false, false).getDoubleValue();
|
||||
|
||||
PathStrokeType::JointStyle joint = stroke.getJointStyle();
|
||||
|
||||
if (s.containsIgnoreCase ("miter")) joint = PathStrokeType::mitered;
|
||||
else if (s.containsIgnoreCase ("curve")) joint = PathStrokeType::curved;
|
||||
else if (s.containsIgnoreCase ("bevel")) joint = PathStrokeType::beveled;
|
||||
|
||||
PathStrokeType::EndCapStyle end = stroke.getEndStyle();
|
||||
|
||||
if (s.containsIgnoreCase ("butt")) end = PathStrokeType::butt;
|
||||
else if (s.containsIgnoreCase ("square")) end = PathStrokeType::square;
|
||||
else if (s.containsIgnoreCase ("round")) end = PathStrokeType::rounded;
|
||||
|
||||
stroke = PathStrokeType (thickness, joint, end);
|
||||
}
|
||||
}
|
||||
|
||||
bool isOpaque() const
|
||||
{
|
||||
return fill.isOpaque();
|
||||
}
|
||||
|
||||
bool isInvisible() const
|
||||
{
|
||||
return fill.isInvisible() || stroke.getStrokeThickness() <= 0.0f;
|
||||
}
|
||||
|
||||
bool operator== (const StrokeType& other) const noexcept
|
||||
{
|
||||
return stroke == other.stroke && fill == other.fill;
|
||||
}
|
||||
|
||||
bool operator!= (const StrokeType& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PathStrokeType stroke;
|
||||
JucerFillType fill;
|
||||
|
||||
private:
|
||||
void reset()
|
||||
{
|
||||
stroke = PathStrokeType (5.0f);
|
||||
fill = JucerFillType();
|
||||
fill.colour = Colours::black;
|
||||
}
|
||||
};
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2022 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
By using JUCE, you agree to the terms of both the JUCE 7 End-User License
|
||||
Agreement and JUCE Privacy Policy.
|
||||
|
||||
End User License Agreement: www.juce.com/juce-7-licence
|
||||
Privacy Policy: www.juce.com/juce-privacy-policy
|
||||
|
||||
Or: You may also use this code under the terms of the GPL v3 (see
|
||||
www.gnu.org/licenses).
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jucer_FillType.h"
|
||||
|
||||
//==============================================================================
|
||||
class StrokeType
|
||||
{
|
||||
public:
|
||||
StrokeType() : stroke (1.0f)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
String getPathStrokeCode() const
|
||||
{
|
||||
PathStrokeType defaultStroke (1.0f);
|
||||
|
||||
String s;
|
||||
|
||||
s << "juce::PathStrokeType (" << CodeHelpers::floatLiteral (stroke.getStrokeThickness(), 3);
|
||||
|
||||
if (stroke.getJointStyle() != defaultStroke.getJointStyle()
|
||||
|| stroke.getEndStyle() != defaultStroke.getEndStyle())
|
||||
{
|
||||
s << ", ";
|
||||
|
||||
switch (stroke.getJointStyle())
|
||||
{
|
||||
case PathStrokeType::mitered: s << "juce::PathStrokeType::mitered"; break;
|
||||
case PathStrokeType::curved: s << "juce::PathStrokeType::curved"; break;
|
||||
case PathStrokeType::beveled: s << "juce::PathStrokeType::beveled"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
if (stroke.getEndStyle() != defaultStroke.getEndStyle())
|
||||
{
|
||||
s << ", ";
|
||||
|
||||
switch (stroke.getEndStyle())
|
||||
{
|
||||
case PathStrokeType::butt: s << "juce::PathStrokeType::butt"; break;
|
||||
case PathStrokeType::square: s << "juce::PathStrokeType::square"; break;
|
||||
case PathStrokeType::rounded: s << "juce::PathStrokeType::rounded"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s << ")";
|
||||
return s;
|
||||
}
|
||||
|
||||
String toString() const
|
||||
{
|
||||
String s;
|
||||
s << stroke.getStrokeThickness();
|
||||
|
||||
switch (stroke.getJointStyle())
|
||||
{
|
||||
case PathStrokeType::mitered: s << ", mitered"; break;
|
||||
case PathStrokeType::curved: s << ", curved"; break;
|
||||
case PathStrokeType::beveled: s << ", beveled"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
switch (stroke.getEndStyle())
|
||||
{
|
||||
case PathStrokeType::butt: s << ", butt"; break;
|
||||
case PathStrokeType::square: s << ", square"; break;
|
||||
case PathStrokeType::rounded: s << ", rounded"; break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void restoreFromString (const String& s)
|
||||
{
|
||||
reset();
|
||||
|
||||
if (s.isNotEmpty())
|
||||
{
|
||||
const float thickness = (float) s.upToFirstOccurrenceOf (",", false, false).getDoubleValue();
|
||||
|
||||
PathStrokeType::JointStyle joint = stroke.getJointStyle();
|
||||
|
||||
if (s.containsIgnoreCase ("miter")) joint = PathStrokeType::mitered;
|
||||
else if (s.containsIgnoreCase ("curve")) joint = PathStrokeType::curved;
|
||||
else if (s.containsIgnoreCase ("bevel")) joint = PathStrokeType::beveled;
|
||||
|
||||
PathStrokeType::EndCapStyle end = stroke.getEndStyle();
|
||||
|
||||
if (s.containsIgnoreCase ("butt")) end = PathStrokeType::butt;
|
||||
else if (s.containsIgnoreCase ("square")) end = PathStrokeType::square;
|
||||
else if (s.containsIgnoreCase ("round")) end = PathStrokeType::rounded;
|
||||
|
||||
stroke = PathStrokeType (thickness, joint, end);
|
||||
}
|
||||
}
|
||||
|
||||
bool isOpaque() const
|
||||
{
|
||||
return fill.isOpaque();
|
||||
}
|
||||
|
||||
bool isInvisible() const
|
||||
{
|
||||
return fill.isInvisible() || stroke.getStrokeThickness() <= 0.0f;
|
||||
}
|
||||
|
||||
bool operator== (const StrokeType& other) const noexcept
|
||||
{
|
||||
return stroke == other.stroke && fill == other.fill;
|
||||
}
|
||||
|
||||
bool operator!= (const StrokeType& other) const noexcept
|
||||
{
|
||||
return ! operator== (other);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
PathStrokeType stroke;
|
||||
JucerFillType fill;
|
||||
|
||||
private:
|
||||
void reset()
|
||||
{
|
||||
stroke = PathStrokeType (5.0f);
|
||||
fill = JucerFillType();
|
||||
fill.colour = Colours::black;
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user