Browse Source

Stage 1 of a redesign of Drawables - instead of a DrawableComposite storing a tranform for each child, each type of drawable now stores its own transform, and these are represented as remapped points instead of affine transforms. Plus, lots of minor tweaks and jucer development.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
9d00c15b67
65 changed files with 2410 additions and 1492 deletions
  1. +32
    -0
      extras/Jucer (experimental)/Source/jucer_Headers.h
  2. +9
    -9
      extras/Jucer (experimental)/Source/model/Component/Types/jucer_ComponentTypeManager.cpp
  3. +1
    -1
      extras/Jucer (experimental)/Source/model/Component/Types/jucer_ComponentTypeManager.h
  4. +2
    -2
      extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h
  5. +2
    -2
      extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h
  6. +84
    -73
      extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp
  7. +10
    -10
      extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h
  8. +56
    -48
      extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp
  9. +6
    -6
      extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h
  10. +11
    -10
      extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp
  11. +10
    -10
      extras/Jucer (experimental)/Source/model/Project/jucer_Project.h
  12. +4
    -4
      extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h
  13. +2
    -2
      extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h
  14. +10
    -10
      extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h
  15. +2
    -7
      extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp
  16. +0
    -1
      extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h
  17. +2
    -2
      extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h
  18. +45
    -101
      extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorToolbar.h
  19. +2
    -1
      extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentViewer.cpp
  20. +153
    -1
      extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditor.cpp
  21. +12
    -0
      extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditor.h
  22. +2
    -2
      extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h
  23. +39
    -8
      extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorToolbar.h
  24. +18
    -46
      extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h
  25. +37
    -11
      extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp
  26. +1
    -1
      extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h
  27. +266
    -189
      extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp
  28. +124
    -60
      extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h
  29. +13
    -13
      extras/Jucer (experimental)/Source/utility/jucer_CoordinatePropertyComponent.h
  30. +3
    -3
      extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h
  31. +56
    -0
      extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h
  32. +11
    -10
      extras/juce demo/Source/demos/RenderingTestComponent.cpp
  33. +506
    -375
      juce_amalgamated.cpp
  34. +181
    -43
      juce_amalgamated.h
  35. +1
    -1
      src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp
  36. +3
    -3
      src/containers/juce_ValueTree.cpp
  37. +1
    -1
      src/containers/juce_ValueTree.h
  38. +1
    -1
      src/core/juce_Atomic.h
  39. +1
    -1
      src/core/juce_StandardHeader.h
  40. +1
    -5
      src/gui/components/controls/juce_ListBox.cpp
  41. +4
    -2
      src/gui/components/juce_Component.cpp
  42. +5
    -3
      src/gui/components/layout/juce_TabbedComponent.cpp
  43. +1
    -0
      src/gui/components/layout/juce_TabbedComponent.h
  44. +1
    -2
      src/gui/components/mouse/juce_MouseInputSource.cpp
  45. +12
    -0
      src/gui/graphics/colour/juce_ColourGradient.cpp
  46. +6
    -0
      src/gui/graphics/colour/juce_ColourGradient.h
  47. +17
    -15
      src/gui/graphics/drawables/juce_Drawable.cpp
  48. +45
    -4
      src/gui/graphics/drawables/juce_Drawable.h
  49. +122
    -106
      src/gui/graphics/drawables/juce_DrawableComposite.cpp
  50. +47
    -22
      src/gui/graphics/drawables/juce_DrawableComposite.h
  51. +154
    -45
      src/gui/graphics/drawables/juce_DrawableImage.cpp
  52. +41
    -7
      src/gui/graphics/drawables/juce_DrawableImage.h
  53. +130
    -90
      src/gui/graphics/drawables/juce_DrawablePath.cpp
  54. +6
    -2
      src/gui/graphics/drawables/juce_DrawablePath.h
  55. +12
    -14
      src/gui/graphics/drawables/juce_DrawableText.cpp
  56. +6
    -2
      src/gui/graphics/drawables/juce_DrawableText.h
  57. +1
    -12
      src/gui/graphics/fonts/juce_GlyphArrangement.cpp
  58. +8
    -0
      src/gui/graphics/geometry/juce_AffineTransform.cpp
  59. +10
    -0
      src/gui/graphics/geometry/juce_AffineTransform.h
  60. +18
    -2
      src/gui/graphics/geometry/juce_Path.cpp
  61. +4
    -1
      src/gui/graphics/geometry/juce_Path.h
  62. +3
    -0
      src/gui/graphics/geometry/juce_Point.h
  63. +7
    -2
      src/gui/graphics/geometry/juce_Rectangle.h
  64. +11
    -12
      src/native/linux/juce_linux_Messaging.cpp
  65. +19
    -76
      src/native/mac/juce_iphone_MessageManager.mm

+ 32
- 0
extras/Jucer (experimental)/Source/jucer_Headers.h View File

@@ -73,6 +73,7 @@ namespace Ids
DECLARE_ID (font);
DECLARE_ID (mode);
DECLARE_ID (type);
DECLARE_ID (version);
DECLARE_ID (position);
DECLARE_ID (source);
DECLARE_ID (readOnly);
@@ -85,6 +86,9 @@ namespace Ids
DECLARE_ID (noItemsText);
DECLARE_ID (min);
DECLARE_ID (max);
DECLARE_ID (width);
DECLARE_ID (height);
DECLARE_ID (background);
DECLARE_ID (interval);
DECLARE_ID (textBoxPos);
DECLARE_ID (textBoxWidth);
@@ -102,6 +106,34 @@ namespace Ids
DECLARE_ID (connectedRight);
DECLARE_ID (connectedTop);
DECLARE_ID (connectedBottom);
DECLARE_ID (juceFolder);
DECLARE_ID (targetFolder);
DECLARE_ID (vstFolder);
DECLARE_ID (rtasFolder);
DECLARE_ID (auFolder);
DECLARE_ID (extraCompilerFlags);
DECLARE_ID (extraLinkerFlags);
DECLARE_ID (extraDefs);
DECLARE_ID (libraryName_Debug);
DECLARE_ID (libraryName_Release);
DECLARE_ID (libraryType);
DECLARE_ID (isDebug);
DECLARE_ID (targetName);
DECLARE_ID (binaryPath);
DECLARE_ID (optimisation);
DECLARE_ID (defines);
DECLARE_ID (headerPath);
DECLARE_ID (osxSDK);
DECLARE_ID (osxCompatibility);
DECLARE_ID (jucerVersion);
DECLARE_ID (projectType);
DECLARE_ID (juceLinkage);
DECLARE_ID (buildVST);
DECLARE_ID (bundleIdentifier);
DECLARE_ID (compile);
DECLARE_ID (resource);
DECLARE_ID (className);
DECLARE_ID (classDesc);
const Identifier class_ ("class");
const Identifier id_ ("id");
}


+ 9
- 9
extras/Jucer (experimental)/Source/model/Component/Types/jucer_ComponentTypeManager.cpp View File

@@ -76,7 +76,7 @@ public:
{
RectangleCoordinates r (sourceValue.toString());
Coordinate& coord = getCoord (r);
coord = Coordinate (newValue.toString(), coord.isHorizontal());
coord = Coordinate (newValue.toString(), type == left || type == right);
const String newVal (r.toString());
if (sourceValue != newVal)
@@ -123,12 +123,12 @@ public:
Coordinate coord (getCoordinate());
PopupMenu m;
document.addComponentMarkerMenuItems (compState, getTypeName(), coord, m, isAnchor1);
document.addComponentMarkerMenuItems (compState, getTypeName(), coord, m, isAnchor1, type == left || type == right);
const int r = m.showAt (button);
if (r > 0)
return document.getChosenMarkerMenuItem (compState, coord, r);
return document.getChosenMarkerMenuItem (compState, coord, r, type == left || type == right);
return String::empty;
}
@@ -142,10 +142,10 @@ private:
{
switch (type)
{
case left: return "left";
case right: return "right";
case top: return "top";
case bottom: return "bottom";
case left: return Coordinate::Strings::left;
case right: return Coordinate::Strings::right;
case top: return Coordinate::Strings::top;
case bottom: return Coordinate::Strings::bottom;
default: jassertfalse; break;
}
@@ -181,7 +181,7 @@ Component* ComponentTypeManager::createFromStoredType (ComponentDocument& docume
return c;
}
ComponentTypeHandler* ComponentTypeManager::getHandlerFor (const String& type)
ComponentTypeHandler* ComponentTypeManager::getHandlerFor (const Identifier& type)
{
for (int i = handlers.size(); --i >= 0;)
if (handlers.getUnchecked(i)->getXmlTag() == type)
@@ -248,7 +248,7 @@ public:
private:
Value sourceValue;
ComponentTypeInstance& item;
ComponentTypeInstance item;
CompMemberNameValueSource (const CompMemberNameValueSource&);
const CompMemberNameValueSource& operator= (const CompMemberNameValueSource&);


+ 1
- 1
extras/Jucer (experimental)/Source/model/Component/Types/jucer_ComponentTypeManager.h View File

@@ -130,7 +130,7 @@ public:
int getNumHandlers() const { return handlers.size(); }
ComponentTypeHandler* getHandler (const int index) const { return handlers[index]; }
ComponentTypeHandler* getHandlerFor (const String& type);
ComponentTypeHandler* getHandlerFor (const Identifier& type);
const StringArray getDisplayNames() const;
private:


+ 2
- 2
extras/Jucer (experimental)/Source/model/Component/Types/jucer_Label.h View File

@@ -71,7 +71,7 @@ public:
props.add (new TextPropertyComponent (item.getValue (Ids::text), "Text", 16384, true));
props.getLast()->setTooltip ("The label's text.");
item.addJustificationProperty (props, "Layout", item.getValue ("justification"), false);
item.addJustificationProperty (props, "Layout", item.getValue (Ids::justification), false);
const char* const editModes[] = { "Read-only", "Edit on Single-Click", "Edit on Double-Click", 0 };
const int values[] = { 1, 2, 3, 0 };
@@ -93,7 +93,7 @@ public:
<< item.getMemberName() << "->setEditable (" << CodeHelpers::boolLiteral (editMode == 2)
<< ", " << CodeHelpers::boolLiteral (editMode == 3) << ", false);" << newLine;
Justification justification ((int) item ["textJustification"]);
Justification justification ((int) item [Ids::justification]);
if (justification.getFlags() != 0)
code.constructorCode << item.getMemberName() << "->setJustificationType ("
<< CodeHelpers::justificationToCode (justification) << ");" << newLine;


+ 2
- 2
extras/Jucer (experimental)/Source/model/Component/Types/jucer_Slider.h View File

@@ -96,8 +96,8 @@ public:
props.add (new ChoicePropertyComponent (item.getValue (Ids::textBoxPos), "Text Box", StringArray (textBoxPositions), Array<var> (positionValues, numElementsInArray (positionValues))));
props.add (new BooleanPropertyComponent (item.getValue (Ids::editable), "Editable", "Value can be edited"));
props.add (new TextPropertyComponent (Value (new NumericValueSource<int> (item.getValue ("textBoxWidth"))), "Text Box Width", 8, false));
props.add (new TextPropertyComponent (Value (new NumericValueSource<int> (item.getValue ("textBoxHeight"))), "Text Box Height", 8, false));
props.add (new TextPropertyComponent (Value (new NumericValueSource<int> (item.getValue (Ids::textBoxWidth))), "Text Box Width", 8, false));
props.add (new TextPropertyComponent (Value (new NumericValueSource<int> (item.getValue (Ids::textBoxHeight))), "Text Box Height", 8, false));
props.add (new TextPropertyComponent (Value (new NumericValueSource<double> (item.getValue (Ids::skew))), "Skew Factor", 16, false));
addEditableColourProperties (item, props);


+ 84
- 73
extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.cpp View File

@@ -311,30 +311,30 @@ void ComponentDocument::checkRootObject()
if ((int) getCanvasHeight().getValue() <= 0)
getCanvasHeight() = 480;
if (! root.hasProperty ("background"))
if (! root.hasProperty (Ids::background))
getBackgroundColour() = Colours::white.toString();
}
void ComponentDocument::setUsingTemporaryCanvasSize (bool b)
{
tempCanvasWidth = root.getProperty ("width");
tempCanvasHeight = root.getProperty ("height");
tempCanvasWidth = root.getProperty (Ids::width);
tempCanvasHeight = root.getProperty (Ids::height);
usingTemporaryCanvasSize = b;
}
Value ComponentDocument::getCanvasWidth() const
{
return usingTemporaryCanvasSize ? tempCanvasWidth : getRootValueNonUndoable ("width");
return usingTemporaryCanvasSize ? tempCanvasWidth : getRootValueNonUndoable (Ids::width);
}
Value ComponentDocument::getCanvasHeight() const
{
return usingTemporaryCanvasSize ? tempCanvasHeight : getRootValueNonUndoable ("height");
return usingTemporaryCanvasSize ? tempCanvasHeight : getRootValueNonUndoable (Ids::height);
}
Value ComponentDocument::getBackgroundColour() const
{
return getRootValueUndoable ("background");
return getRootValueUndoable (Ids::background);
}
//==============================================================================
@@ -459,37 +459,42 @@ Component* ComponentDocument::createComponent (int index)
}
//==============================================================================
const Coordinate ComponentDocument::findMarker (const String& name, bool isHorizontal) const
const Coordinate ComponentDocument::findNamedCoordinate (const String& objectName, const String& edge) const
{
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) getCanvasWidth().getValue(), isHorizontal);
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) getCanvasHeight().getValue(), isHorizontal);
if (objectName == Coordinate::Strings::parent)
{
if (edge == Coordinate::Strings::right) return Coordinate ((double) getCanvasWidth().getValue(), true);
if (edge == Coordinate::Strings::bottom) return Coordinate ((double) getCanvasHeight().getValue(), false);
}
if (name.containsChar ('.'))
if (objectName.isNotEmpty() && edge.isNotEmpty())
{
const String compName (name.upToFirstOccurrenceOf (".", false, false).trim());
const String edge (name.fromFirstOccurrenceOf (".", false, false).trim());
const ValueTree comp (getComponentWithMemberName (objectName));
if (compName.isNotEmpty() && edge.isNotEmpty())
if (comp.isValid())
{
const ValueTree comp (getComponentWithMemberName (compName));
const RectangleCoordinates coords (getCoordsFor (comp));
if (comp.isValid())
{
const RectangleCoordinates coords (getCoordsFor (comp));
if (edge == "left") return coords.left;
if (edge == "right") return coords.right;
if (edge == "top") return coords.top;
if (edge == "bottom") return coords.bottom;
}
if (edge == Coordinate::Strings::left) return coords.left;
if (edge == Coordinate::Strings::right) return coords.right;
if (edge == Coordinate::Strings::top) return coords.top;
if (edge == Coordinate::Strings::bottom) return coords.bottom;
}
}
const ValueTree marker (getMarkerList (isHorizontal).getMarkerNamed (name));
if (marker.isValid())
return getMarkerList (isHorizontal).getCoordinate (marker);
{
const ValueTree marker (getMarkerListX().getMarkerNamed (objectName));
if (marker.isValid())
return getMarkerListX().getCoordinate (marker);
}
return Coordinate (isHorizontal);
{
const ValueTree marker (getMarkerListY().getMarkerNamed (objectName));
if (marker.isValid())
return getMarkerListY().getCoordinate (marker);
}
return Coordinate();
}
const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& state) const
@@ -535,45 +540,50 @@ void ComponentDocument::renameAnchor (const String& oldName, const String& newNa
markersY->renameAnchorInMarkers (oldName, newName);
}
void ComponentDocument::addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
void ComponentDocument::addMarkerMenuItem (int i, const Coordinate& coord,
const String& objectName, const String& edge, PopupMenu& menu,
bool isAnchor1, const String& fullCoordName)
{
Coordinate requestedCoord (findMarker (name, coord.isHorizontal()));
Coordinate requestedCoord (findNamedCoordinate (objectName, edge));
String name (objectName);
if (edge.isNotEmpty())
name << '.' << edge;
menu.addItem (i, name,
! (name == fullCoordName || requestedCoord.referencesIndirectly (fullCoordName, *this)),
name == (isAnchor1 ? coord.getAnchor1() : coord.getAnchor2()));
! (name == fullCoordName || requestedCoord.references (fullCoordName, *this)),
name == (isAnchor1 ? coord.getAnchorName1() : coord.getAnchorName2()));
}
void ComponentDocument::addComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
Coordinate& coord, PopupMenu& menu, bool isAnchor1)
Coordinate& coord, PopupMenu& menu, bool isAnchor1, bool isHorizontal)
{
const String componentName (componentState [memberNameProperty].toString());
const String fullCoordName (componentName + "." + coordName);
if (coord.isHorizontal())
if (isHorizontal)
{
addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (1, coord, Coordinate::Strings::parent, Coordinate::Strings::left, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (2, coord, Coordinate::Strings::parent, Coordinate::Strings::right, menu, isAnchor1, fullCoordName);
menu.addSeparator();
addMarkerMenuItem (3, coord, componentName + ".left", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (4, coord, componentName + ".right", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (3, coord, componentName, Coordinate::Strings::left, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (4, coord, componentName, Coordinate::Strings::right, menu, isAnchor1, fullCoordName);
}
else
{
addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (1, coord, Coordinate::Strings::parent, Coordinate::Strings::top, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (2, coord, Coordinate::Strings::parent, Coordinate::Strings::bottom, menu, isAnchor1, fullCoordName);
menu.addSeparator();
addMarkerMenuItem (3, coord, componentName + ".top", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (4, coord, componentName + ".bottom", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (3, coord, componentName, Coordinate::Strings::top, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (4, coord, componentName, Coordinate::Strings::bottom, menu, isAnchor1, fullCoordName);
}
menu.addSeparator();
const MarkerList& markerList = getMarkerList (coord.isHorizontal());
const MarkerList& markerList = getMarkerList (isHorizontal);
int i;
for (i = 0; i < markerList.size(); ++i)
addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, fullCoordName);
addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), String::empty, menu, isAnchor1, fullCoordName);
menu.addSeparator();
for (i = 0; i < getNumComponents(); ++i)
@@ -582,30 +592,30 @@ void ComponentDocument::addComponentMarkerMenuItems (const ValueTree& componentS
if (compName != componentName)
{
if (coord.isHorizontal())
if (isHorizontal)
{
addMarkerMenuItem (10000 + i * 4, coord, compName + ".left", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10001 + i * 4, coord, compName + ".right", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10000 + i * 4, coord, compName, Coordinate::Strings::left, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10001 + i * 4, coord, compName, Coordinate::Strings::right, menu, isAnchor1, fullCoordName);
}
else
{
addMarkerMenuItem (10002 + i * 4, coord, compName + ".top", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10003 + i * 4, coord, compName + ".bottom", menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10002 + i * 4, coord, compName, Coordinate::Strings::top, menu, isAnchor1, fullCoordName);
addMarkerMenuItem (10003 + i * 4, coord, compName, Coordinate::Strings::bottom, menu, isAnchor1, fullCoordName);
}
}
}
}
const String ComponentDocument::getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int i) const
const String ComponentDocument::getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int i, bool isHorizontal) const
{
const String componentName (componentState [memberNameProperty].toString());
if (i == 1) return coord.isHorizontal() ? Coordinate::parentLeftMarkerName : Coordinate::parentTopMarkerName;
if (i == 2) return coord.isHorizontal() ? Coordinate::parentRightMarkerName : Coordinate::parentBottomMarkerName;
if (i == 3) return componentName + (coord.isHorizontal() ? ".left" : ".top");
if (i == 4) return componentName + (coord.isHorizontal() ? ".right" : ".bottom");
if (i == 1) return isHorizontal ? Coordinate::Strings::originX : Coordinate::Strings::originY;
if (i == 2) return isHorizontal ? Coordinate::Strings::extentX : Coordinate::Strings::extentY;
if (i == 3) return componentName + (isHorizontal ? ".left" : ".top");
if (i == 4) return componentName + (isHorizontal ? ".right" : ".bottom");
const MarkerList& markerList = getMarkerList (coord.isHorizontal());
const MarkerList& markerList = getMarkerList (isHorizontal);
if (i >= 100 && i < 10000)
return markerList.getName (markerList.getMarker (i - 100));
@@ -707,49 +717,50 @@ void ComponentDocument::MarkerList::renameAnchor (const String& oldName, const S
document.renameAnchor (oldName, newName);
}
const Coordinate ComponentDocument::MarkerList::findMarker (const String& name, bool isHorizontal_) const
const Coordinate ComponentDocument::MarkerList::findNamedCoordinate (const String& objectName, const String& edge) const
{
if (isHorizontal_ == isX)
if (objectName == Coordinate::Strings::parent)
{
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) document.getCanvasWidth().getValue(), isX);
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) document.getCanvasHeight().getValue(), isX);
const ValueTree marker (document.getMarkerList (isX).getMarkerNamed (name));
if (marker.isValid())
return document.getMarkerList (isX).getCoordinate (marker);
if (edge == Coordinate::Strings::right) return Coordinate ((double) document.getCanvasWidth().getValue(), true);
if (edge == Coordinate::Strings::bottom) return Coordinate ((double) document.getCanvasHeight().getValue(), false);
}
return Coordinate (isX);
const ValueTree marker (getMarkerNamed (objectName));
if (marker.isValid())
return getCoordinate (marker);
return Coordinate();
}
void ComponentDocument::MarkerList::addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1)
{
const String fullCoordName (getName (markerState));
if (coord.isHorizontal())
if (isX)
{
document.addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (1, coord, Coordinate::Strings::parent, Coordinate::Strings::left, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::Strings::parent, Coordinate::Strings::right, menu, isAnchor1, fullCoordName);
}
else
{
document.addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (1, coord, Coordinate::Strings::parent, Coordinate::Strings::top, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::Strings::parent, Coordinate::Strings::bottom, menu, isAnchor1, fullCoordName);
}
menu.addSeparator();
const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
const MarkerList& markerList = document.getMarkerList (isX);
for (int i = 0; i < markerList.size(); ++i)
document.addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)),
String::empty, menu, isAnchor1, fullCoordName);
}
const String ComponentDocument::MarkerList::getChosenMarkerMenuItem (const Coordinate& coord, int i) const
{
if (i == 1) return coord.isHorizontal() ? Coordinate::parentLeftMarkerName : Coordinate::parentTopMarkerName;
if (i == 2) return coord.isHorizontal() ? Coordinate::parentRightMarkerName : Coordinate::parentBottomMarkerName;
if (i == 1) return isX ? "parent.left" : "parent.top";
if (i == 2) return isX ? "parent.right" : "parent.bottom";
const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
const MarkerList& markerList = document.getMarkerList (isX);
if (i >= 100 && i < 10000)
return markerList.getName (markerList.getMarker (i - 100));


+ 10
- 10
extras/Jucer (experimental)/Source/model/Component/jucer_ComponentDocument.h View File

@@ -35,7 +35,7 @@
//==============================================================================
class ComponentDocument : public ValueTree::Listener,
public Coordinate::MarkerResolver
public Coordinate::NamedCoordinateFinder
{
public:
//==============================================================================
@@ -57,8 +57,8 @@ public:
//==============================================================================
const String getUniqueId() const { return root [idProperty]; }
Value getClassName() const { return getRootValueNonUndoable ("className"); }
Value getClassDescription() const { return getRootValueNonUndoable ("classDesc"); }
Value getClassName() const { return getRootValueNonUndoable (Ids::className); }
Value getClassDescription() const { return getRootValueNonUndoable (Ids::classDesc); }
void setUsingTemporaryCanvasSize (bool b);
Value getCanvasWidth() const;
@@ -84,12 +84,12 @@ public:
bool setCoordsFor (ValueTree& componentState, const RectangleCoordinates& newSize);
void renameAnchor (const String& oldName, const String& newName);
// for Coordinate::MarkerResolver:
const Coordinate findMarker (const String& name, bool isHorizontal) const;
// for Coordinate::Resolver:
const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const;
void addComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName,
Coordinate& coord, PopupMenu& menu, bool isAnchor1);
const String getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int itemId) const;
Coordinate& coord, PopupMenu& menu, bool isAnchor1, bool isHorizontal);
const String getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int itemId, bool isHorizontal) const;
void addNewComponentMenuItems (PopupMenu& menu) const;
const ValueTree performNewComponentMenuItem (int menuResultCode);
@@ -105,7 +105,7 @@ public:
public:
MarkerList (ComponentDocument& document, bool isX);
const Coordinate findMarker (const String& name, bool isHorizontal) const;
const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const;
bool createProperties (Array <PropertyComponent*>& props, const String& itemId);
void addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1);
const String getChosenMarkerMenuItem (const Coordinate& coord, int itemId) const;
@@ -181,8 +181,8 @@ private:
void checkRootObject();
void createSubTreeIfNotThere (const Identifier& name);
void addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
bool isAnchor1, const String& fullCoordName);
void addMarkerMenuItem (int i, const Coordinate& coord, const String& objectName, const String& edge,
PopupMenu& menu, bool isAnchor1, const String& fullCoordName);
Value getRootValueUndoable (const Identifier& name) const { return root.getPropertyAsValue (name, getUndoManager()); }
Value getRootValueNonUndoable (const Identifier& name) const { return root.getPropertyAsValue (name, 0); }


+ 56
- 48
extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp View File

@@ -27,15 +27,17 @@
//==============================================================================
static const char* const drawableTag = "DRAWABLE";
static const char* const markersGroupXTag = "MARKERS_X";
static const char* const markersGroupYTag = "MARKERS_Y";
namespace Tags
{
const Identifier drawableTag ("DRAWABLE");
const Identifier markersGroupXTag ("MARKERS_X");
const Identifier markersGroupYTag ("MARKERS_Y");
}
//==============================================================================
DrawableDocument::DrawableDocument (Project* project_)
: project (project_),
root (drawableTag),
root (Tags::drawableTag),
saveAsXml (true),
needsSaving (false)
{
@@ -166,7 +168,7 @@ bool DrawableDocument::load (InputStream& input)
loadedTree = ValueTree::readFromStream (input);
}
if (loadedTree.hasType (drawableTag))
if (loadedTree.hasType (Tags::drawableTag))
{
addMissingIds (loadedTree);
@@ -264,58 +266,63 @@ void DrawableDocument::valueTreeParentChanged (ValueTree& tree)
}
//==============================================================================
const Coordinate DrawableDocument::findMarker (const String& name, bool isHorizontal) const
const Coordinate DrawableDocument::findNamedCoordinate (const String& objectName, const String& edge) const
{
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) getCanvasWidth().getValue(), isHorizontal);
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) getCanvasHeight().getValue(), isHorizontal);
if (objectName == "parent")
{
if (edge == "right") return Coordinate ((double) getCanvasWidth().getValue(), true);
if (edge == "bottom") return Coordinate ((double) getCanvasHeight().getValue(), false);
}
if (name.containsChar ('.'))
if (objectName.isNotEmpty() && edge.isNotEmpty())
{
const String compName (name.upToFirstOccurrenceOf (".", false, false).trim());
const String edge (name.fromFirstOccurrenceOf (".", false, false).trim());
/* const ValueTree comp (getComponentWithMemberName (compName));
if (compName.isNotEmpty() && edge.isNotEmpty())
if (comp.isValid())
{
/* const ValueTree comp (getComponentWithMemberName (compName));
const RectangleCoordinates coords (getCoordsFor (comp));
if (comp.isValid())
{
const RectangleCoordinates coords (getCoordsFor (comp));
if (edge == Coordinate::leftName) return coords.left;
if (edge == "right") return coords.right;
if (edge == "top") return coords.top;
if (edge == "bottom") return coords.bottom;
}*/
}
if (edge == "left") return coords.left;
if (edge == "right") return coords.right;
if (edge == "top") return coords.top;
if (edge == "bottom") return coords.bottom;
}*/
}
{
const ValueTree marker (getMarkerListX().getMarkerNamed (objectName));
if (marker.isValid())
return getMarkerListX().getCoordinate (marker);
}
const ValueTree marker (getMarkerList (isHorizontal).getMarkerNamed (name));
if (marker.isValid())
return getMarkerList (isHorizontal).getCoordinate (marker);
{
const ValueTree marker (getMarkerListY().getMarkerNamed (objectName));
if (marker.isValid())
return getMarkerListY().getCoordinate (marker);
}
return Coordinate (isHorizontal);
return Coordinate();
}
DrawableDocument::MarkerList::MarkerList (DrawableDocument& document_, bool isX_)
: MarkerListBase (document_.getRoot().getChildWithName (isX_ ? markersGroupXTag : markersGroupYTag), isX_),
: MarkerListBase (document_.getRoot().getChildWithName (isX_ ? Tags::markersGroupXTag : Tags::markersGroupYTag), isX_),
document (document_)
{
}
const Coordinate DrawableDocument::MarkerList::findMarker (const String& name, bool isHorizontal_) const
const Coordinate DrawableDocument::MarkerList::findNamedCoordinate (const String& objectName, const String& edge) const
{
if (isHorizontal_ == isX)
if (objectName == "parent")
{
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) document.getCanvasWidth().getValue(), isX);
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) document.getCanvasHeight().getValue(), isX);
const ValueTree marker (document.getMarkerList (isX).getMarkerNamed (name));
if (marker.isValid())
return document.getMarkerList (isX).getCoordinate (marker);
if (edge == "right") return Coordinate ((double) document.getCanvasWidth().getValue(), true);
if (edge == "bottom") return Coordinate ((double) document.getCanvasHeight().getValue(), false);
}
return Coordinate (isX);
const ValueTree marker (getMarkerNamed (objectName));
if (marker.isValid())
return getCoordinate (marker);
return Coordinate();
}
bool DrawableDocument::MarkerList::createProperties (Array <PropertyComponent*>& props, const String& itemId)
@@ -334,10 +341,10 @@ bool DrawableDocument::MarkerList::createProperties (Array <PropertyComponent*>&
return false;
}
void DrawableDocument::addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
void DrawableDocument::addMarkerMenuItem (int i, const Coordinate& coord, const String& objectName, const String& edge, PopupMenu& menu,
bool isAnchor1, const String& fullCoordName)
{
Coordinate requestedCoord (findMarker (name, coord.isHorizontal()));
// Coordinate requestedCoord (findNamedCoordinate (objectName, edge, coord.isHorizontal()));
// menu.addItem (i, name,
// ! (name == fullCoordName || requestedCoord.referencesIndirectly (fullCoordName, *this)),
@@ -346,37 +353,38 @@ void DrawableDocument::addMarkerMenuItem (int i, const Coordinate& coord, const
void DrawableDocument::MarkerList::addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1)
{
const String fullCoordName (getName (markerState));
/* const String fullCoordName (getName (markerState));
if (coord.isHorizontal())
{
document.addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (1, coord, "parent", "left", menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, "parent", "right", menu, isAnchor1, fullCoordName);
}
else
{
document.addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (1, coord, "parent", "top", menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (2, coord, "parent", "bottom", menu, isAnchor1, fullCoordName);
}
menu.addSeparator();
const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
for (int i = 0; i < markerList.size(); ++i)
document.addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, fullCoordName);
document.addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)),
String::empty, menu, isAnchor1, fullCoordName);*/
}
const String DrawableDocument::MarkerList::getChosenMarkerMenuItem (const Coordinate& coord, int i) const
{
if (i == 1) return coord.isHorizontal() ? Coordinate::parentLeftMarkerName : Coordinate::parentTopMarkerName;
if (i == 2) return coord.isHorizontal() ? Coordinate::parentRightMarkerName : Coordinate::parentBottomMarkerName;
/* if (i == 1) return coord.isHorizontal() ? "parent.left" : "parent.top";
if (i == 2) return coord.isHorizontal() ? "parent.right" : "parent.bottom";
const MarkerList& markerList = document.getMarkerList (coord.isHorizontal());
if (i >= 100 && i < 10000)
return markerList.getName (markerList.getMarker (i - 100));
jassertfalse;
jassertfalse;*/
return String::empty;
}


+ 6
- 6
extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h View File

@@ -57,8 +57,8 @@ public:
void addCircle();
void addImage (const File& imageFile);
Value getCanvasWidth() const { return getRootValueNonUndoable ("width"); }
Value getCanvasHeight() const { return getRootValueNonUndoable ("height"); }
Value getCanvasWidth() const { return getRootValueNonUndoable (Ids::width); }
Value getCanvasHeight() const { return getRootValueNonUndoable (Ids::height); }
static const String getIdFor (const ValueTree& object);
@@ -69,7 +69,7 @@ public:
MarkerList (DrawableDocument& document, bool isX);
~MarkerList() {}
const Coordinate findMarker (const String& name, bool isHorizontal) const;
const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const;
bool createProperties (Array <PropertyComponent*>& props, const String& itemId);
void addMarkerMenuItems (const ValueTree& markerState, const Coordinate& coord, PopupMenu& menu, bool isAnchor1);
const String getChosenMarkerMenuItem (const Coordinate& coord, int itemId) const;
@@ -117,9 +117,9 @@ private:
void addMissingIds (ValueTree tree) const;
void addDrawable (Drawable& d);
const Coordinate findMarker (const String& name, bool isHorizontal) const;
void addMarkerMenuItem (int i, const Coordinate& coord, const String& name, PopupMenu& menu,
bool isAnchor1, const String& fullCoordName);
const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const;
void addMarkerMenuItem (int i, const Coordinate& coord, const String& objectName, const String& edge,
PopupMenu& menu, bool isAnchor1, const String& fullCoordName);
};


+ 11
- 10
extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp View File

@@ -40,6 +40,7 @@ namespace Tags
const Identifier configurations ("CONFIGURATIONS");
const Identifier configuration ("CONFIGURATION");
const Identifier exporters ("EXPORTFORMATS");
const Identifier configGroup ("JUCEOPTIONS");
}
const char* Project::projectFileExtension = ".jucer";
@@ -80,7 +81,7 @@ const String Project::getDocumentTitle()
void Project::updateProjectSettings()
{
projectRoot.setProperty ("jucerVersion", ProjectInfo::versionString, 0);
projectRoot.setProperty (Ids::jucerVersion, ProjectInfo::versionString, 0);
projectRoot.setProperty (Ids::name, getDocumentTitle(), 0);
}
@@ -101,13 +102,13 @@ void Project::setMissingDefaultValues()
if (getDocumentTitle().isEmpty())
setTitle ("Juce Project");
if (! projectRoot.hasProperty ("projectType"))
if (! projectRoot.hasProperty (Ids::projectType))
getProjectType() = (int) application;
if (! projectRoot.hasProperty ("version"))
if (! projectRoot.hasProperty (Ids::version))
getVersion() = "1.0.0";
if (! projectRoot.hasProperty ("juceLinkage"))
if (! projectRoot.hasProperty (Ids::juceLinkage))
getJuceLinkageModeValue() = useAmalgamatedJuceViaMultipleTemplates;
const String juceFolderPath (getRelativePathForFile (StoredSettings::getInstance()->getLastKnownJuceFolder()));
@@ -124,7 +125,7 @@ void Project::setMissingDefaultValues()
const String sanitisedProjectName (CodeHelpers::makeValidIdentifier (getProjectName().toString(), false, true, false));
if (! projectRoot.hasProperty ("buildVST"))
if (! projectRoot.hasProperty (Ids::buildVST))
{
shouldBuildVST() = true;
shouldBuildRTAS() = false;
@@ -147,7 +148,7 @@ void Project::setMissingDefaultValues()
getPluginRTASCategory() = String::empty;
}
if (! projectRoot.hasProperty ("bundleIdentifier"))
if (! projectRoot.hasProperty (Ids::bundleIdentifier))
setBundleIdentifierToDefault();
}
@@ -473,7 +474,7 @@ bool Project::Item::shouldBeCompiled() const
Value Project::Item::getShouldCompileValue() const
{
return node.getPropertyAsValue ("compile", getUndoManager());
return node.getPropertyAsValue (Ids::compile, getUndoManager());
}
bool Project::Item::shouldBeAddedToBinaryResources() const
@@ -483,7 +484,7 @@ bool Project::Item::shouldBeAddedToBinaryResources() const
Value Project::Item::getShouldAddToResourceValue() const
{
return node.getPropertyAsValue ("resource", getUndoManager());
return node.getPropertyAsValue (Ids::resource, getUndoManager());
}
const File Project::Item::getFile() const
@@ -673,11 +674,11 @@ Image* Project::Item::getIcon() const
//==============================================================================
ValueTree Project::getJuceConfigNode()
{
ValueTree configNode = projectRoot.getChildWithName ("JUCEOPTIONS");
ValueTree configNode = projectRoot.getChildWithName (Tags::configGroup);
if (! configNode.isValid())
{
configNode = ValueTree ("JUCEOPTIONS");
configNode = ValueTree (Tags::configGroup);
projectRoot.addChild (configNode, -1, 0);
}


+ 10
- 10
extras/Jucer (experimental)/Source/model/Project/jucer_Project.h View File

@@ -221,24 +221,24 @@ public:
void createPropertyEditors (Array <PropertyComponent*>& properties);
//==============================================================================
Value getName() const { return getValue ("name"); }
Value isDebug() const { return getValue ("isDebug"); }
Value getTargetBinaryName() const { return getValue ("targetName"); }
Value getName() const { return getValue (Ids::name); }
Value isDebug() const { return getValue (Ids::isDebug); }
Value getTargetBinaryName() const { return getValue (Ids::targetName); }
// the path relative to the build folder in which the binary should go
Value getTargetBinaryRelativePath() const { return getValue ("binaryPath"); }
Value getOptimisationLevel() const { return getValue ("optimisation"); }
Value getTargetBinaryRelativePath() const { return getValue (Ids::binaryPath); }
Value getOptimisationLevel() const { return getValue (Ids::optimisation); }
const String getGCCOptimisationFlag() const;
Value getPreprocessorDefs() const { return getValue ("defines"); }
Value getPreprocessorDefs() const { return getValue (Ids::defines); }
const StringArray parsePreprocessorDefs() const;
Value getHeaderSearchPath() const { return getValue ("headerPath"); }
Value getHeaderSearchPath() const { return getValue (Ids::headerPath); }
const StringArray getHeaderSearchPaths() const;
static const char* const osxVersionDefault;
static const char* const osxVersion10_4;
static const char* const osxVersion10_5;
static const char* const osxVersion10_6;
Value getMacSDKVersion() const { return getValue ("osxSDK"); }
Value getMacCompatibilityVersion() const { return getValue ("osxCompatibility"); }
Value getMacSDKVersion() const { return getValue (Ids::osxSDK); }
Value getMacCompatibilityVersion() const { return getValue (Ids::osxCompatibility); }
//==============================================================================
private:
@@ -246,7 +246,7 @@ public:
Project* project;
ValueTree config;
Value getValue (const char* name) const { return config.getPropertyAsValue (name, getUndoManager()); }
Value getValue (const Identifier& name) const { return config.getPropertyAsValue (name, getUndoManager()); }
UndoManager* getUndoManager() const { return project->getUndoManagerFor (config); }
BuildConfiguration (Project* project, const ValueTree& configNode);


+ 4
- 4
extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h View File

@@ -128,10 +128,10 @@ public:
const int libTypeValues[] = { 1, 2, 0 };
props.add (new ChoicePropertyComponent (getLibraryType(), "Library Type", StringArray (libTypes), Array<var> (libTypeValues)));
props.add (new TextPropertyComponent (getSetting ("libraryName_Debug"), "Library Name (Debug)", 128, false));
props.add (new TextPropertyComponent (getSetting (Ids::libraryName_Debug), "Library Name (Debug)", 128, false));
props.getLast()->setTooltip ("If set, this name will override the binary name specified in the configuration settings, for a debug build. You must include the .lib or .dll suffix on this filename.");
props.add (new TextPropertyComponent (getSetting ("libraryName_Release"), "Library Name (Release)", 128, false));
props.add (new TextPropertyComponent (getSetting (Ids::libraryName_Release), "Library Name (Release)", 128, false));
props.getLast()->setTooltip ("If set, this name will override the binary name specified in the configuration settings, for a release build. You must include the .lib or .dll suffix on this filename.");
}
}
@@ -195,7 +195,7 @@ private:
const File getDSPFile() const { return getProjectFile (".dsp"); }
const File getDSWFile() const { return getProjectFile (".dsw"); }
Value getLibraryType() const { return getSetting ("libraryType"); }
Value getLibraryType() const { return getSetting (Ids::libraryType); }
bool isLibraryDLL() const { return project.isLibrary() && getLibraryType() == 2; }
//==============================================================================
@@ -438,7 +438,7 @@ private:
const String getBinaryFileForConfig (const Project::BuildConfiguration& config) const
{
const String targetBinary (getSetting (config.isDebug().getValue() ? "libraryName_Debug" : "libraryName_Release").toString().trim());
const String targetBinary (getSetting (config.isDebug().getValue() ? Ids::libraryName_Debug : Ids::libraryName_Release).toString().trim());
if (targetBinary.isNotEmpty())
return targetBinary;


+ 2
- 2
extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_XCode.h View File

@@ -570,7 +570,7 @@ private:
for (int i = 0; i < objects.size(); ++i)
{
ValueTree& o = *objects.getUnchecked(i);
output << "\t\t" << o.getType() << " = { ";
output << "\t\t" << static_cast <const juce_wchar*> (o.getType()) << " = { ";
for (int j = 0; j < o.getNumProperties(); ++j)
{
@@ -814,7 +814,7 @@ private:
StringArray configIDs;
for (int i = 0; i < configsToUse.size(); ++i)
configIDs.add (configsToUse[i]->getType());
configIDs.add (configsToUse[i]->getType().toString());
ValueTree* v = new ValueTree (listID);
v->setProperty ("isa", "XCConfigurationList", 0);


+ 10
- 10
extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h View File

@@ -61,23 +61,23 @@ public:
const File getTargetFolder() const;
const ValueTree& getSettings() const { return settings; }
Value getSetting (const Identifier& name_) const { return settings.getPropertyAsValue (name_, project.getUndoManagerFor (settings)); }
Value getSetting (const Identifier& name_) const { return settings.getPropertyAsValue (name_, project.getUndoManagerFor (settings)); }
Value getJuceFolder() const { return getSetting ("juceFolder"); }
Value getTargetLocation() const { return getSetting ("targetFolder"); }
Value getJuceFolder() const { return getSetting (Ids::juceFolder); }
Value getTargetLocation() const { return getSetting (Ids::targetFolder); }
Value getVSTFolder() const { return getSetting ("vstFolder"); }
Value getRTASFolder() const { return getSetting ("rtasFolder"); }
Value getAUFolder() const { return getSetting ("auFolder"); }
Value getVSTFolder() const { return getSetting (Ids::vstFolder); }
Value getRTASFolder() const { return getSetting (Ids::rtasFolder); }
Value getAUFolder() const { return getSetting (Ids::auFolder); }
bool isVST() const { return (bool) project.isAudioPlugin() && (bool) project.shouldBuildVST().getValue(); }
bool isRTAS() const { return (bool) project.isAudioPlugin() && (bool) project.shouldBuildRTAS().getValue(); }
bool isAU() const { return (bool) project.isAudioPlugin() && (bool) project.shouldBuildAU().getValue(); }
Value getExtraCompilerFlags() const { return getSetting ("extraCompilerFlags"); }
Value getExtraLinkerFlags() const { return getSetting ("extraLinkerFlags"); }
Value getExtraCompilerFlags() const { return getSetting (Ids::extraCompilerFlags); }
Value getExtraLinkerFlags() const { return getSetting (Ids::extraLinkerFlags); }
Value getExtraPreprocessorDefs() const { return getSetting ("extraDefs"); }
Value getExtraPreprocessorDefs() const { return getSetting (Ids::extraDefs); }
const StringArray parsePreprocessorDefs() const;
// This adds the quotes, and may return angle-brackets, eg: <foo/bar.h> or normal quotes.
@@ -86,7 +86,7 @@ public:
const String getExporterIdentifierMacro() const
{
return "JUCER_" + settings.getType() + "_"
+ String::toHexString (settings ["targetFolder"].toString().hashCode()).toUpperCase();
+ String::toHexString (settings [Ids::targetFolder].toString().hashCode()).toUpperCase();
}
Array<RelativePath> juceWrapperFiles;


+ 2
- 7
extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp View File

@@ -91,9 +91,9 @@ public:
return editor.getSelection();
}
void getSelectedItemProperties (Array<PropertyComponent*>& newComps)
void getSelectedItemProperties (Array<PropertyComponent*>& props)
{
editor.getSelectedItemProperties (newComps);
editor.getDocument().createItemProperties (props, editor.getSelectedIds());
}
private:
@@ -178,11 +178,6 @@ const StringArray ComponentEditor::getSelectedIds() const
return ids;
}
void ComponentEditor::getSelectedItemProperties (Array <PropertyComponent*>& props)
{
getDocument().createItemProperties (props, getSelectedIds());
}
void ComponentEditor::deleteSelection()
{
const StringArray ids (getSelectedIds());


+ 0
- 1
extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h View File

@@ -56,7 +56,6 @@ public:
ComponentDocument& getDocument() const { return *componentDocument; }
const StringArray getSelectedIds() const;
void getSelectedItemProperties (Array <PropertyComponent*>& props);
void deleteSelection();
void deselectNonComponents();
void selectionToFront();


+ 2
- 2
extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorCanvas.h View File

@@ -90,9 +90,9 @@ public:
return String::empty;
}
void showPopupMenu (const Point<int>& position)
void showPopupMenu (bool isClickOnSelectedObject)
{
if (findObjectIdAt (position).isNotEmpty())
if (isClickOnSelectedObject)
{
PopupMenu m;
m.addCommandItem (commandManager, CommandIDs::toFront);


+ 45
- 101
extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorToolbar.h View File

@@ -29,101 +29,6 @@
#include "../../utility/jucer_ColourEditorComponent.h"
//==============================================================================
class JucerToolbarButton : public ToolbarItemComponent
{
public:
//==============================================================================
JucerToolbarButton (ComponentEditor& editor_, int itemId_, const String& labelText)
: ToolbarItemComponent (itemId_, labelText, true),
editor (editor_)
{
setClickingTogglesState (false);
}
~JucerToolbarButton()
{
}
//==============================================================================
bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize, int& minSize, int& maxSize)
{
preferredSize = minSize = maxSize = 50;
return true;
}
void paintButton (Graphics& g, bool over, bool down)
{
Path p;
p.addRoundedRectangle (1.5f, 2.5f, getWidth() - 3.0f, getHeight() - 5.0f, 3.0f);
if (getToggleState())
{
g.setColour (Colours::grey.withAlpha (0.5f));
g.fillPath (p);
}
g.setColour (Colours::darkgrey.withAlpha (0.3f));
g.strokePath (p, PathStrokeType (1.0f));
g.setFont (11.0f);
g.setColour (Colours::black.withAlpha ((over || down) ? 1.0f : 0.7f));
g.drawFittedText (getButtonText(), 2, 2, getWidth() - 4, getHeight() - 4, Justification::centred, 2);
}
void paintButtonArea (Graphics& g, int width, int height, bool isMouseOver, bool isMouseDown)
{
}
void contentAreaChanged (const Rectangle<int>& newBounds)
{
}
juce_UseDebuggingNewOperator
protected:
ComponentEditor& editor;
private:
JucerToolbarButton (const JucerToolbarButton&);
JucerToolbarButton& operator= (const JucerToolbarButton&);
};
//==============================================================================
class NewComponentToolbarButton : public JucerToolbarButton
{
public:
NewComponentToolbarButton (ComponentEditor& editor_, int itemId_)
: JucerToolbarButton (editor_, itemId_, "create...")
{
setTriggeredOnMouseDown (true);
}
void clicked()
{
editor.showNewComponentMenu (this);
}
};
//==============================================================================
class BackgroundColourToolbarButton : public JucerToolbarButton
{
public:
BackgroundColourToolbarButton (ComponentEditor& editor_, int itemId_)
: JucerToolbarButton (editor_, itemId_, "background")
{
setTriggeredOnMouseDown (true);
}
void clicked()
{
editor.getDocument().getUndoManager()->beginNewTransaction();
PopupColourSelector::showAt (this, editor.getDocument().getBackgroundColour(), Colours::white, true);
}
};
//==============================================================================
class ComponentEditorToolbarFactory : public ToolbarItemFactory
{
@@ -138,12 +43,12 @@ public:
}
//==============================================================================
enum DemoToolbarItemIds
enum ToolbarItemIds
{
createComponent = 1,
changeBackground,
showInfo,
showComponentTree,
showTree,
showOrHideMarkers,
toggleSnapping
};
@@ -153,7 +58,7 @@ public:
ids.add (createComponent);
ids.add (changeBackground);
ids.add (showInfo);
ids.add (showComponentTree);
ids.add (showTree);
ids.add (showOrHideMarkers);
ids.add (toggleSnapping);
@@ -171,7 +76,7 @@ public:
ids.add (showOrHideMarkers);
ids.add (toggleSnapping);
ids.add (flexibleSpacerId);
ids.add (showComponentTree);
ids.add (showTree);
ids.add (showInfo);
ids.add (spacerId);
}
@@ -186,17 +91,56 @@ public:
case createComponent: return new NewComponentToolbarButton (editor, itemId);
case changeBackground: return new BackgroundColourToolbarButton (editor, itemId);
case showInfo: name = "info"; commandId = CommandIDs::showOrHideProperties; break;
case showComponentTree: name = "tree"; commandId = CommandIDs::showOrHideTree; break;
case showTree: name = "tree"; commandId = CommandIDs::showOrHideTree; break;
case showOrHideMarkers: name = "markers"; commandId = CommandIDs::showOrHideMarkers; break;
case toggleSnapping: name = "snap"; commandId = CommandIDs::toggleSnapping; break;
default: jassertfalse; return 0;
}
JucerToolbarButton* b = new JucerToolbarButton (editor, itemId, name);
JucerToolbarButton* b = new JucerToolbarButton (itemId, name);
b->setCommandToTrigger (commandManager, commandId, true);
return b;
}
//==============================================================================
class NewComponentToolbarButton : public JucerToolbarButton
{
public:
NewComponentToolbarButton (ComponentEditor& editor_, int itemId_)
: JucerToolbarButton (itemId_, "create..."), editor (editor_)
{
setTriggeredOnMouseDown (true);
}
void clicked()
{
editor.showNewComponentMenu (this);
}
private:
ComponentEditor& editor;
};
//==============================================================================
class BackgroundColourToolbarButton : public JucerToolbarButton
{
public:
BackgroundColourToolbarButton (ComponentEditor& editor_, int itemId_)
: JucerToolbarButton (itemId_, "background"), editor (editor_)
{
setTriggeredOnMouseDown (true);
}
void clicked()
{
editor.getDocument().getUndoManager()->beginNewTransaction();
PopupColourSelector::showAt (this, editor.getDocument().getBackgroundColour(), Colours::white, true);
}
private:
ComponentEditor& editor;
};
private:
ComponentEditor& editor;


+ 2
- 1
extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentViewer.cpp View File

@@ -107,7 +107,8 @@ void ComponentViewer::handleAsyncUpdate()
componentsInOrder.add (c);
layoutManager->setComponentLayout (c, v [ComponentDocument::memberNameProperty], componentDocument->getCoordsFor (v));
layoutManager->setComponentBounds (c, v [ComponentDocument::memberNameProperty],
componentDocument->getCoordsFor (v));
}
// Make sure the z-order is correct..


+ 153
- 1
extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditor.cpp View File

@@ -53,7 +53,7 @@ public:
void createCanvas()
{
initialise (new DrawableEditorCanvas (editor), toolbarFactory,
DrawableTreeViewItem::createItemForNode (editor, editor.getDocument().getRootDrawableNode()));
new DrawableTreeViewItem (editor, editor.getDocument().getRootDrawableNode()));
}
SelectedItemSet<String>& getSelection()
@@ -101,3 +101,155 @@ void DrawableEditor::resized()
{
panel->setBounds (getLocalBounds());
}
//==============================================================================
void DrawableEditor::deleteSelection()
{
}
void DrawableEditor::selectionToFront()
{
}
void DrawableEditor::selectionToBack()
{
}
void DrawableEditor::showNewShapeMenu (Component* componentToAttachTo)
{
/*
PopupMenu m;
getDocument().addNewComponentMenuItems (m);
const int r = m.showAt (componentToAttachTo);
const ValueTree newComp (getDocument().performNewComponentMenuItem (r));
if (newComp.isValid())
getSelection().selectOnly (newComp [ComponentDocument::idProperty]);
*/
}
//==============================================================================
void DrawableEditor::getAllCommands (Array <CommandID>& commands)
{
DocumentEditorComponent::getAllCommands (commands);
const CommandID ids[] = { CommandIDs::undo,
CommandIDs::redo,
CommandIDs::toFront,
CommandIDs::toBack,
CommandIDs::showOrHideProperties,
CommandIDs::showOrHideTree,
CommandIDs::showOrHideMarkers,
CommandIDs::toggleSnapping,
StandardApplicationCommandIDs::del };
commands.addArray (ids, numElementsInArray (ids));
}
void DrawableEditor::getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
{
result.setActive (document != 0);
switch (commandID)
{
case CommandIDs::undo:
result.setInfo ("Undo", "Undoes the last change", CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::redo:
result.setInfo ("Redo", "Redoes the last change", CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress ('z', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
result.defaultKeypresses.add (KeyPress ('y', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::toFront:
result.setInfo ("Bring to Front", "Brings the selected items to the front", CommandCategories::editing, 0);
break;
case CommandIDs::toBack:
result.setInfo ("Send to Back", "Moves the selected items to the back", CommandCategories::editing, 0);
break;
case CommandIDs::showOrHideProperties:
result.setInfo ("Show/Hide Tree", "Shows or hides the component tree view", CommandCategories::editing, 0);
result.setTicked (panel != 0 && panel->arePropertiesVisible());
break;
case CommandIDs::showOrHideTree:
result.setInfo ("Show/Hide Properties", "Shows or hides the component properties panel", CommandCategories::editing, 0);
result.setTicked (panel != 0 && panel->isTreeVisible());
break;
case CommandIDs::showOrHideMarkers:
result.setInfo ("Show/Hide Markers", "Shows or hides the markers", CommandCategories::editing, 0);
result.setTicked (panel != 0 && panel->areMarkersVisible());
break;
case CommandIDs::toggleSnapping:
result.setInfo ("Toggle snapping", "Turns object snapping on or off", CommandCategories::editing, 0);
result.setTicked (panel != 0 && panel->isSnappingEnabled());
break;
case StandardApplicationCommandIDs::del:
result.setInfo ("Delete", String::empty, CommandCategories::general, 0);
result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0));
result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0));
break;
default:
DocumentEditorComponent::getCommandInfo (commandID, result);
break;
}
}
bool DrawableEditor::perform (const InvocationInfo& info)
{
switch (info.commandID)
{
case CommandIDs::undo:
getDocument().getUndoManager()->beginNewTransaction();
getDocument().getUndoManager()->undo();
return true;
case CommandIDs::redo:
getDocument().getUndoManager()->beginNewTransaction();
getDocument().getUndoManager()->redo();
return true;
case CommandIDs::toFront:
selectionToFront();
return true;
case CommandIDs::toBack:
selectionToBack();
return true;
case CommandIDs::showOrHideProperties:
panel->showOrHideProperties();
return true;
case CommandIDs::showOrHideTree:
panel->showOrHideTree();
return true;
case CommandIDs::showOrHideMarkers:
panel->showOrHideMarkers();
return true;
case CommandIDs::toggleSnapping:
panel->toggleSnapping();
return true;
case StandardApplicationCommandIDs::del:
deleteSelection();
return true;
default:
break;
}
return DocumentEditorComponent::perform (info);
}

+ 12
- 0
extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditor.h View File

@@ -42,9 +42,21 @@ public:
Project* project, DrawableDocument* drawableDocument);
~DrawableEditor();
//==============================================================================
void getAllCommands (Array <CommandID>& commands);
void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result);
bool perform (const InvocationInfo& info);
void paint (Graphics& g);
void resized();
//==============================================================================
void deleteSelection();
void selectionToFront();
void selectionToBack();
void showNewShapeMenu (Component* componentToAttachTo);
//==============================================================================
DrawableDocument& getDocument() const { return *drawableDocument; }
EditorCanvasBase::SelectedItems& getSelection() { return selection; }


+ 2
- 2
extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorCanvas.h View File

@@ -74,11 +74,11 @@ public:
return String::empty;
}
void showPopupMenu (const Point<int>& position)
void showPopupMenu (bool isClickOnSelectedObject)
{
PopupMenu m;
if (findObjectIdAt (position).isNotEmpty())
if (isClickOnSelectedObject)
{
m.addCommandItem (commandManager, CommandIDs::toFront);
m.addCommandItem (commandManager, CommandIDs::toBack);


+ 39
- 8
extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorToolbar.h View File

@@ -41,17 +41,22 @@ public:
}
//==============================================================================
enum DemoToolbarItemIds
enum ToolbarItemIds
{
createComponent = 1,
showInfo = 2,
showComponentTree = 3,
createShape = 1,
showInfo,
showTree,
showOrHideMarkers,
toggleSnapping
};
void getAllToolbarItemIds (Array <int>& ids)
{
ids.add (createShape);
ids.add (showInfo);
ids.add (showComponentTree);
ids.add (showTree);
ids.add (showOrHideMarkers);
ids.add (toggleSnapping);
ids.add (separatorBarId);
ids.add (spacerId);
@@ -61,8 +66,12 @@ public:
void getDefaultItemSet (Array <int>& ids)
{
ids.add (spacerId);
ids.add (createShape);
ids.add (flexibleSpacerId);
ids.add (showComponentTree);
ids.add (showOrHideMarkers);
ids.add (toggleSnapping);
ids.add (flexibleSpacerId);
ids.add (showTree);
ids.add (showInfo);
ids.add (spacerId);
}
@@ -74,16 +83,38 @@ public:
switch (itemId)
{
case createShape: return new NewShapeToolbarButton (editor, itemId);
case showInfo: name = "info"; commandId = CommandIDs::showOrHideProperties; break;
case showComponentTree: name = "tree"; commandId = CommandIDs::showOrHideTree; break;
case showTree: name = "tree"; commandId = CommandIDs::showOrHideTree; break;
case showOrHideMarkers: name = "markers"; commandId = CommandIDs::showOrHideMarkers; break;
case toggleSnapping: name = "snap"; commandId = CommandIDs::toggleSnapping; break;
default: jassertfalse; return 0;
}
ToolbarButton* b = new ToolbarButton (itemId, name, new DrawablePath(), 0);
JucerToolbarButton* b = new JucerToolbarButton (itemId, name);
b->setCommandToTrigger (commandManager, commandId, true);
return b;
}
//==============================================================================
class NewShapeToolbarButton : public JucerToolbarButton
{
public:
NewShapeToolbarButton (DrawableEditor& editor_, int itemId_)
: JucerToolbarButton (itemId_, "create..."), editor (editor_)
{
setTriggeredOnMouseDown (true);
}
void clicked()
{
editor.showNewShapeMenu (this);
}
private:
DrawableEditor& editor;
};
private:
DrawableEditor& editor;


+ 18
- 46
extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h View File

@@ -34,44 +34,14 @@ class DrawableTreeViewItem : public JucerTreeViewBase,
public ValueTree::Listener,
public ChangeListener
{
DrawableTreeViewItem (DrawableEditor& editor_, const ValueTree& drawableRoot, const String& typeName_)
: editor (editor_), node (drawableRoot), typeName (typeName_)
public:
DrawableTreeViewItem (DrawableEditor& editor_, const ValueTree& drawableRoot)
: editor (editor_), node (drawableRoot), typeName (drawableRoot.getType().toString())
{
node.addListener (this);
editor.getSelection().addChangeListener (this);
}
public:
static DrawableTreeViewItem* createItemForNode (DrawableEditor& editor, const ValueTree& drawableRoot)
{
const char* typeName = 0;
{
ScopedPointer <Drawable> d (Drawable::createFromValueTree (drawableRoot));
if (d != 0)
{
if (dynamic_cast <DrawablePath*> ((Drawable*) d) != 0)
typeName = "Path";
else if (dynamic_cast <DrawableImage*> ((Drawable*) d) != 0)
typeName = "Image";
else if (dynamic_cast <DrawableComposite*> ((Drawable*) d) != 0)
typeName = "Group";
else if (dynamic_cast <DrawableText*> ((Drawable*) d) != 0)
typeName = "Text";
else
{
jassertfalse
}
}
}
if (typeName != 0)
return new DrawableTreeViewItem (editor, drawableRoot, typeName);
return 0;
}
~DrawableTreeViewItem()
{
editor.getSelection().removeChangeListener (this);
@@ -97,7 +67,8 @@ public:
// TreeViewItem stuff..
bool mightContainSubItems()
{
return node.getNumChildren() > 0;
return node.getType() == DrawableComposite::valueTreeType
&& node.getNumChildren() > 0;
}
const String getUniqueName() const
@@ -114,23 +85,24 @@ public:
void refreshSubItems()
{
ScopedPointer <XmlElement> oldOpenness (getOpennessState());
clearSubItems();
for (int i = 0; i < node.getNumChildren(); ++i)
if (node.getType() == DrawableComposite::valueTreeType)
{
ValueTree subNode (node.getChild (i));
DrawableTreeViewItem* const item = createItemForNode (editor, subNode);
ScopedPointer <XmlElement> oldOpenness (getOpennessState());
if (item != 0)
clearSubItems();
for (int i = 0; i < node.getNumChildren(); ++i)
{
ValueTree subNode (node.getChild (i));
DrawableTreeViewItem* const item = new DrawableTreeViewItem (editor, subNode);
addSubItem (item);
}
}
if (oldOpenness != 0)
restoreOpennessState (*oldOpenness);
if (oldOpenness != 0)
restoreOpennessState (*oldOpenness);
editor.getSelection().changed();
editor.getSelection().changed();
}
}
const String getDisplayName() const


+ 37
- 11
extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp View File

@@ -37,7 +37,8 @@ public:
: OverlayItemComponent (canvas_),
objectState (objectState_),
objectId (objectId_),
borderThickness (4)
borderThickness (4),
isDragging (false)
{
jassert (objectState.isValid());
}
@@ -59,26 +60,50 @@ public:
void mouseDown (const MouseEvent& e)
{
updateDragZone (e.getPosition());
canvas->beginDrag (e.getEventRelativeTo (getParentComponent()), dragZone);
canvas->showSizeGuides();
if (e.mods.isPopupMenu())
{
isDragging = false;
canvas->showPopupMenu (true);
}
else
{
isDragging = true;
canvas->beginDrag (e.getEventRelativeTo (getParentComponent()), dragZone);
canvas->showSizeGuides();
}
}
void mouseDrag (const MouseEvent& e)
{
canvas->continueDrag (e.getEventRelativeTo (getParentComponent()));
autoScrollForMouseEvent (e);
if (isDragging)
{
canvas->continueDrag (e.getEventRelativeTo (getParentComponent()));
autoScrollForMouseEvent (e);
}
}
void mouseUp (const MouseEvent& e)
{
canvas->hideSizeGuides();
canvas->endDrag (e.getEventRelativeTo (getParentComponent()));
updateDragZone (e.getPosition());
if (isDragging)
{
canvas->hideSizeGuides();
canvas->endDrag (e.getEventRelativeTo (getParentComponent()));
updateDragZone (e.getPosition());
}
}
void mouseDoubleClick (const MouseEvent& e)
{
canvas->objectDoubleClicked (e, objectState);
}
bool hitTest (int x, int y)
{
return ! getCentreArea().contains (x, y);
if (ModifierKeys::getCurrentModifiers().isAnyModifierKeyDown())
return ! getCentreArea().contains (x, y);
return true;
}
bool updatePosition()
@@ -130,7 +155,7 @@ public:
void updatePosition (const Rectangle<int>& bounds)
{
RectangleCoordinates coords (canvas->getObjectCoords (state));
Coordinate coord (false);
Coordinate coord;
Rectangle<int> r;
switch (type)
@@ -174,6 +199,7 @@ private:
ResizableBorderComponent::Zone dragZone;
const int borderThickness;
OwnedArray <SizeGuideComponent> sizeGuides;
bool isDragging;
const Rectangle<int> getCentreArea() const
{
@@ -389,7 +415,7 @@ public:
if (underMouse.isNotEmpty() && ! getSelection().isSelected (underMouse))
getSelection().selectOnly (underMouse);
canvas->showPopupMenu (e2.getPosition());
canvas->showPopupMenu (underMouse.isNotEmpty());
}
else
{


+ 1
- 1
extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.h View File

@@ -72,7 +72,7 @@ public:
virtual MarkerListBase& getMarkerList (bool isX) = 0;
virtual const SelectedItems::ItemType findObjectIdAt (const Point<int>& position) = 0;
virtual void showPopupMenu (const Point<int>& position) = 0;
virtual void showPopupMenu (bool isClickOnSelectedObject) = 0;
virtual void objectDoubleClicked (const MouseEvent& e, const ValueTree& state) = 0;
virtual const ValueTree getObjectState (const String& objectId) = 0;


+ 266
- 189
extras/Jucer (experimental)/Source/utility/jucer_Coordinate.cpp View File

@@ -27,113 +27,140 @@
//==============================================================================
const char* Coordinate::parentLeftMarkerName = "parent.left";
const char* Coordinate::parentRightMarkerName = "parent.right";
const char* Coordinate::parentTopMarkerName = "parent.top";
const char* Coordinate::parentBottomMarkerName = "parent.bottom";
Coordinate::Coordinate (bool horizontal_)
: value (0), isProportion (false), horizontal (horizontal_)
Coordinate::Coordinate()
: value (0)
{
}
Coordinate::Coordinate (double absoluteDistanceFromOrigin, bool horizontal_)
: value (absoluteDistanceFromOrigin), isProportion (false), horizontal (horizontal_)
Coordinate::Coordinate (const double absoluteDistanceFromOrigin, const bool horizontal_)
: anchor1 (getOriginAnchorName (horizontal_)),
value (absoluteDistanceFromOrigin)
{
}
Coordinate::Coordinate (double absoluteDistance, const String& source, bool horizontal_)
: anchor1 (source), value (absoluteDistance), isProportion (false), horizontal (horizontal_)
Coordinate::Coordinate (const double absoluteDistance, const String& source)
: anchor1 (source.trim()),
value (absoluteDistance)
{
jassert (anchor1.isNotEmpty());
}
Coordinate::Coordinate (double relativeProportion, const String& pos1, const String& pos2, bool horizontal_)
: anchor1 (pos1), anchor2 (pos2), value (relativeProportion), isProportion (true), horizontal (horizontal_)
Coordinate::Coordinate (const double relativeProportion, const String& pos1, const String& pos2)
: anchor1 (pos1.trim()),
anchor2 (pos2.trim()),
value (relativeProportion)
{
jassert (anchor1.isNotEmpty());
jassert (anchor2.isNotEmpty());
}
Coordinate::~Coordinate()
{
}
const Coordinate Coordinate::getAnchorPoint1() const
//==============================================================================
const String Coordinate::Strings::parent ("parent");
const String Coordinate::Strings::left ("left");
const String Coordinate::Strings::right ("right");
const String Coordinate::Strings::top ("top");
const String Coordinate::Strings::bottom ("bottom");
const String Coordinate::Strings::originX ("parent.left");
const String Coordinate::Strings::originY ("parent.top");
const String Coordinate::Strings::extentX ("parent.right");
const String Coordinate::Strings::extentY ("parent.bottom");
const String Coordinate::getObjectName (const String& fullName)
{
return Coordinate (0.0, anchor1, horizontal);
return fullName.upToFirstOccurrenceOf (".", false, false);
}
const Coordinate Coordinate::getAnchorPoint2() const
const String Coordinate::getEdgeName (const String& fullName)
{
return Coordinate (0.0, anchor2, horizontal);
return fullName.fromFirstOccurrenceOf (".", false, false);
}
bool Coordinate::isOrigin (const String& name)
const Coordinate Coordinate::getAnchorCoordinate1() const
{
return Coordinate (0.0, anchor1);
}
const Coordinate Coordinate::getAnchorCoordinate2() const
{
return name.isEmpty() || name == parentLeftMarkerName || name == parentTopMarkerName;
return Coordinate (0.0, anchor2);
}
const String Coordinate::getOriginMarkerName() const
bool Coordinate::isOrigin (const String& name)
{
return horizontal ? parentLeftMarkerName : parentTopMarkerName;
return name.isEmpty()
|| name == Strings::originX
|| name == Strings::originY;
}
const String Coordinate::getExtentMarkerName() const
const String Coordinate::getOriginAnchorName (const bool isHorizontal) const throw()
{
return horizontal ? parentRightMarkerName : parentBottomMarkerName;
return isHorizontal ? Strings::originX : Strings::originY;
}
const String Coordinate::checkName (const String& name) const
const String Coordinate::getExtentAnchorName (const bool isHorizontal) const throw()
{
return name.isEmpty() ? getOriginMarkerName() : name;
return isHorizontal ? Strings::extentX : Strings::extentY;
}
double Coordinate::getPosition (const String& name, const MarkerResolver& markerResolver, int recursionCounter) const
//==============================================================================
Coordinate::RecursiveCoordinateException::RecursiveCoordinateException()
: std::runtime_error ("Coordinate::RecursiveCoordinateException")
{
if (isOrigin (name))
return 0.0;
}
return markerResolver.findMarker (name, horizontal)
.resolve (markerResolver, recursionCounter + 1);
const Coordinate Coordinate::lookUpName (const String& name, const NamedCoordinateFinder& nameSource) const
{
return nameSource.findNamedCoordinate (getObjectName (name), getEdgeName (name));
}
struct RecursivePositionException
double Coordinate::resolveAnchor (const String& anchorName, const NamedCoordinateFinder& nameSource, int recursionCounter) const
{
};
if (isOrigin (anchorName))
return 0.0;
return lookUpName (anchorName, nameSource).resolve (nameSource, recursionCounter + 1);
}
double Coordinate::resolve (const MarkerResolver& markerResolver, int recursionCounter) const
double Coordinate::resolve (const NamedCoordinateFinder& nameSource, int recursionCounter) const
{
if (recursionCounter > 100)
{
jassertfalse
throw RecursivePositionException();
throw RecursiveCoordinateException();
}
const double pos1 = getPosition (anchor1, markerResolver, recursionCounter);
const double pos1 = resolveAnchor (anchor1, nameSource, recursionCounter);
return isProportion ? pos1 + (getPosition (anchor2, markerResolver, recursionCounter) - pos1) * value
: pos1 + value;
return isProportional() ? pos1 + (resolveAnchor (anchor2, nameSource, recursionCounter) - pos1) * value
: pos1 + value;
}
double Coordinate::resolve (const MarkerResolver& markerResolver) const
double Coordinate::resolve (const NamedCoordinateFinder& nameSource) const
{
try
{
return resolve (markerResolver, 0);
return resolve (nameSource, 0);
}
catch (RecursivePositionException&)
catch (RecursiveCoordinateException&)
{}
return 0.0;
}
void Coordinate::moveToAbsolute (double newPos, const MarkerResolver& markerResolver)
void Coordinate::moveToAbsolute (double newPos, const NamedCoordinateFinder& nameSource)
{
try
{
const double pos1 = getPosition (anchor1, markerResolver, 0);
const double pos1 = resolveAnchor (anchor1, nameSource, 0);
if (isProportion)
if (isProportional())
{
const double size = getPosition (anchor2, markerResolver, 0) - pos1;
const double size = resolveAnchor (anchor2, nameSource, 0) - pos1;
if (size != 0)
value = (newPos - pos1) / size;
@@ -143,242 +170,295 @@ void Coordinate::moveToAbsolute (double newPos, const MarkerResolver& markerReso
value = newPos - pos1;
}
}
catch (RecursivePositionException&)
catch (RecursiveCoordinateException&)
{}
}
bool Coordinate::referencesDirectly (const String& markerName) const
void Coordinate::toggleProportionality (const NamedCoordinateFinder& nameSource, bool isHorizontal)
{
jassert (markerName.isNotEmpty());
return anchor1 == markerName || anchor2 == markerName;
}
const double oldValue = resolve (nameSource);
bool Coordinate::referencesIndirectly (const String& markerName, const MarkerResolver& markerResolver) const
{
if (isOrigin (anchor1) && ! isProportion)
return isOrigin (markerName);
anchor1 = getOriginAnchorName (isHorizontal);
anchor2 = isProportional() ? String::empty
: getExtentAnchorName (isHorizontal);
return referencesDirectly (markerName)
|| markerResolver.findMarker (anchor1, horizontal).referencesIndirectly (markerName, markerResolver)
|| (isProportion && markerResolver.findMarker (anchor2, horizontal).referencesIndirectly (markerName, markerResolver));
moveToAbsolute (oldValue, nameSource);
}
void Coordinate::skipWhitespace (const String& s, int& i)
//==============================================================================
bool Coordinate::references (const String& coordName, const NamedCoordinateFinder& nameSource) const
{
while (CharacterFunctions::isWhitespace (s[i]))
++i;
if (isOrigin (anchor1) && ! isProportional())
return isOrigin (coordName);
return anchor1 == coordName
|| anchor2 == coordName
|| lookUpName (anchor1, nameSource).references (coordName, nameSource)
|| (isProportional() && lookUpName (anchor2, nameSource).references (coordName, nameSource));
}
const String Coordinate::readMarkerName (const String& s, int& i)
//==============================================================================
namespace CoordParserHelpers
{
skipWhitespace (s, i);
if (CharacterFunctions::isLetter (s[i]) || s[i] == '_')
static void skipWhitespace (const String& s, int& i)
{
int start = i;
while (CharacterFunctions::isLetterOrDigit (s[i]) || s[i] == '_' || s[i] == '.')
while (CharacterFunctions::isWhitespace (s[i]))
++i;
return s.substring (start, i);
}
return String::empty;
}
static const String readAnchorName (const String& s, int& i)
{
skipWhitespace (s, i);
double Coordinate::readNumber (const String& s, int& i)
{
skipWhitespace (s, i);
if (CharacterFunctions::isLetter (s[i]) || s[i] == '_')
{
int start = i;
int start = i;
while (CharacterFunctions::isLetterOrDigit (s[i]) || s[i] == '_' || s[i] == '.')
++i;
if (CharacterFunctions::isDigit (s[i]) || s[i] == '.' || s[i] == '-')
++i;
return s.substring (start, i);
}
while (CharacterFunctions::isDigit (s[i]) || s[i] == '.')
++i;
return String::empty;
}
if ((s[i] == 'e' || s[i] == 'E')
&& (CharacterFunctions::isDigit (s[i + 1])
|| s[i + 1] == '-'
|| s[i + 1] == '+'))
static double readNumber (const String& s, int& i)
{
i += 2;
skipWhitespace (s, i);
while (CharacterFunctions::isDigit (s[i]))
int start = i;
if (CharacterFunctions::isDigit (s[i]) || s[i] == '.' || s[i] == '-')
++i;
}
const double value = s.substring (start, i).getDoubleValue();
while (CharacterFunctions::isDigit (s[i]) || s[i] == '.')
++i;
if ((s[i] == 'e' || s[i] == 'E')
&& (CharacterFunctions::isDigit (s[i + 1])
|| s[i + 1] == '-'
|| s[i + 1] == '+'))
{
i += 2;
while (CharacterFunctions::isWhitespace (s[i]) || s[i] == ',')
++i;
while (CharacterFunctions::isDigit (s[i]))
++i;
}
const double value = s.substring (start, i).getDoubleValue();
return value;
while (CharacterFunctions::isWhitespace (s[i]) || s[i] == ',')
++i;
return value;
}
static const String limitedAccuracyString (const double n)
{
return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd (".");
}
}
Coordinate::Coordinate (const String& s, bool horizontal_)
: value (0), isProportion (false), horizontal (horizontal_)
Coordinate::Coordinate (const String& s, bool isHorizontal)
: value (0)
{
int i = 0;
anchor1 = readMarkerName (s, i);
anchor1 = CoordParserHelpers::readAnchorName (s, i);
if (anchor1.isNotEmpty())
{
skipWhitespace (s, i);
CoordParserHelpers::skipWhitespace (s, i);
if (s[i] == '+')
value = readNumber (s, ++i);
value = CoordParserHelpers::readNumber (s, ++i);
else if (s[i] == '-')
value = -readNumber (s, ++i);
value = -CoordParserHelpers::readNumber (s, ++i);
}
else
{
value = readNumber (s, i);
skipWhitespace (s, i);
anchor1 = getOriginAnchorName (isHorizontal);
value = CoordParserHelpers::readNumber (s, i);
CoordParserHelpers::skipWhitespace (s, i);
if (s[i] == '%')
{
isProportion = true;
value /= 100.0;
skipWhitespace (s, ++i);
CoordParserHelpers::skipWhitespace (s, ++i);
if (s[i] == '*')
{
anchor1 = readMarkerName (s, ++i);
skipWhitespace (s, i);
anchor1 = CoordParserHelpers::readAnchorName (s, ++i);
if (anchor1.isEmpty())
anchor1 = getOriginAnchorName (isHorizontal);
CoordParserHelpers::skipWhitespace (s, i);
if (s[i] == '-' && s[i + 1] == '>')
{
i += 2;
anchor2 = readMarkerName (s, i);
anchor2 = CoordParserHelpers::readAnchorName (s, i);
}
else
{
anchor2 = anchor1;
anchor1 = getOriginMarkerName();
anchor1 = getOriginAnchorName (isHorizontal);
}
}
else
{
anchor1 = getOriginMarkerName();
anchor2 = getExtentMarkerName();
anchor1 = getOriginAnchorName (isHorizontal);
anchor2 = getExtentAnchorName (isHorizontal);
}
}
}
}
static const String limitedAccuracyString (const double n)
{
return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd (".");
}
const String Coordinate::toString() const
{
if (isProportion)
if (isProportional())
{
const String percent (limitedAccuracyString (value * 100.0));
const String percent (CoordParserHelpers::limitedAccuracyString (value * 100.0));
if (isOrigin (anchor1))
{
if (anchor2 == parentRightMarkerName || anchor2 == parentBottomMarkerName)
if (anchor2 == "parent.right" || anchor2 == "parent.bottom")
return percent + "%";
else
return percent + "% * " + checkName (anchor2);
return percent + "% * " + anchor2;
}
else
return percent + "% * " + checkName (anchor1) + " -> " + checkName (anchor2);
return percent + "% * " + anchor1 + " -> " + anchor2;
}
else
{
if (isOrigin (anchor1))
return limitedAccuracyString (value);
return CoordParserHelpers::limitedAccuracyString (value);
else if (value > 0)
return checkName (anchor1) + " + " + limitedAccuracyString (value);
return anchor1 + " + " + CoordParserHelpers::limitedAccuracyString (value);
else if (value < 0)
return checkName (anchor1) + " - " + limitedAccuracyString (-value);
return anchor1 + " - " + CoordParserHelpers::limitedAccuracyString (-value);
else
return checkName (anchor1);
return anchor1;
}
}
const double Coordinate::getEditableValue() const
//==============================================================================
const double Coordinate::getEditableNumber() const
{
return isProportion ? value * 100.0 : value;
return isProportional() ? value * 100.0 : value;
}
void Coordinate::setEditableValue (const double newValue)
void Coordinate::setEditableNumber (const double newValue)
{
value = isProportion ? newValue / 100.0 : newValue;
value = isProportional() ? newValue / 100.0 : newValue;
}
void Coordinate::toggleProportionality (const MarkerResolver& markerResolver)
//==============================================================================
void Coordinate::changeAnchor1 (const String& newAnchorName, const NamedCoordinateFinder& nameSource)
{
const double oldValue = resolve (markerResolver);
isProportion = ! isProportion;
anchor1 = getOriginMarkerName();
anchor2 = getExtentMarkerName();
jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
moveToAbsolute (oldValue, markerResolver);
const double oldValue = resolve (nameSource);
anchor1 = newAnchorName;
moveToAbsolute (oldValue, nameSource);
}
void Coordinate::changeAnchor1 (const String& newMarkerName, const MarkerResolver& markerResolver)
void Coordinate::changeAnchor2 (const String& newAnchorName, const NamedCoordinateFinder& nameSource)
{
const double oldValue = resolve (markerResolver);
anchor1 = newMarkerName;
moveToAbsolute (oldValue, markerResolver);
}
jassert (isProportional());
jassert (newAnchorName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_."));
void Coordinate::changeAnchor2 (const String& newMarkerName, const MarkerResolver& markerResolver)
{
const double oldValue = resolve (markerResolver);
anchor2 = newMarkerName;
moveToAbsolute (oldValue, markerResolver);
const double oldValue = resolve (nameSource);
anchor2 = newAnchorName;
moveToAbsolute (oldValue, nameSource);
}
void Coordinate::renameAnchorIfUsed (const String& oldName, const String& newName, const MarkerResolver& markerResolver)
void Coordinate::renameAnchorIfUsed (const String& oldName, const String& newName, const NamedCoordinateFinder& nameSource)
{
jassert (oldName.isNotEmpty());
jassert (newName.toLowerCase().containsOnly ("abcdefghijklmnopqrstuvwxyz0123456789_"));
if (newName.isEmpty())
{
if (anchor1.upToFirstOccurrenceOf (".", false, false) == oldName
|| anchor2.upToFirstOccurrenceOf (".", false, false) == oldName)
if (getObjectName (anchor1) == oldName
|| getObjectName (anchor2) == oldName)
{
value = resolve (markerResolver);
isProportion = false;
value = resolve (nameSource);
anchor1 = String::empty;
anchor2 = String::empty;
}
}
else
{
if (anchor1.upToFirstOccurrenceOf (".", false, false) == oldName)
anchor1 = newName + anchor1.fromFirstOccurrenceOf (".", true, false);
if (getObjectName (anchor1) == oldName)
anchor1 = newName + "." + getEdgeName (anchor1);
if (anchor2.upToFirstOccurrenceOf (".", false, false) == oldName)
anchor2 = newName + anchor2.fromFirstOccurrenceOf (".", true, false);
if (getObjectName (anchor2) == oldName)
anchor2 = newName + "." + getEdgeName (anchor2);
}
}
//==============================================================================
CoordinatePair::CoordinatePair()
{
}
CoordinatePair::CoordinatePair (const Point<float>& absolutePoint)
: x (absolutePoint.getX(), true), y (absolutePoint.getY(), false)
{
}
CoordinatePair::CoordinatePair (const String& stringVersion)
{
StringArray tokens;
tokens.addTokens (stringVersion, ",", String::empty);
x = Coordinate (tokens [0], true);
y = Coordinate (tokens [1], false);
}
const Point<float> CoordinatePair::resolve (const Coordinate::NamedCoordinateFinder& nameSource) const
{
return Point<float> ((float) x.resolve (nameSource),
(float) y.resolve (nameSource));
}
void CoordinatePair::moveToAbsolute (const Point<float>& newPos, const Coordinate::NamedCoordinateFinder& nameSource)
{
x.moveToAbsolute (newPos.getX(), nameSource);
y.moveToAbsolute (newPos.getY(), nameSource);
}
const String CoordinatePair::toString() const
{
return x.toString() + ", " + y.toString();
}
void CoordinatePair::renameAnchorIfUsed (const String& oldName, const String& newName, const Coordinate::NamedCoordinateFinder& nameSource)
{
x.renameAnchorIfUsed (oldName, newName, nameSource);
y.renameAnchorIfUsed (oldName, newName, nameSource);
}
//==============================================================================
RectangleCoordinates::RectangleCoordinates()
: left (true), right (true), top (false), bottom (false)
{
}
RectangleCoordinates::RectangleCoordinates (const Rectangle<float>& rect, const String& componentName)
: left (rect.getX(), true),
right (rect.getWidth(), componentName + ".left", true),
right (rect.getWidth(), componentName + "." + Coordinate::Strings::left),
top (rect.getY(), false),
bottom (rect.getHeight(), componentName + ".top", false)
bottom (rect.getHeight(), componentName + "." + Coordinate::Strings::top)
{
}
RectangleCoordinates::RectangleCoordinates (const String& stringVersion)
: left (true), right (true), top (false), bottom (false)
{
StringArray tokens;
tokens.addTokens (stringVersion, ",", String::empty);
@@ -389,22 +469,22 @@ RectangleCoordinates::RectangleCoordinates (const String& stringVersion)
bottom = Coordinate (tokens [3], false);
}
const Rectangle<int> RectangleCoordinates::resolve (const Coordinate::MarkerResolver& markerResolver) const
const Rectangle<int> RectangleCoordinates::resolve (const Coordinate::NamedCoordinateFinder& nameSource) const
{
const int l = roundToInt (left.resolve (markerResolver));
const int r = roundToInt (right.resolve (markerResolver));
const int t = roundToInt (top.resolve (markerResolver));
const int b = roundToInt (bottom.resolve (markerResolver));
const int l = roundToInt (left.resolve (nameSource));
const int r = roundToInt (right.resolve (nameSource));
const int t = roundToInt (top.resolve (nameSource));
const int b = roundToInt (bottom.resolve (nameSource));
return Rectangle<int> (l, t, r - l, b - t);
}
void RectangleCoordinates::moveToAbsolute (const Rectangle<float>& newPos, const Coordinate::MarkerResolver& markerResolver)
void RectangleCoordinates::moveToAbsolute (const Rectangle<float>& newPos, const Coordinate::NamedCoordinateFinder& nameSource)
{
left.moveToAbsolute (newPos.getX(), markerResolver);
right.moveToAbsolute (newPos.getRight(), markerResolver);
top.moveToAbsolute (newPos.getY(), markerResolver);
bottom.moveToAbsolute (newPos.getBottom(), markerResolver);
left.moveToAbsolute (newPos.getX(), nameSource);
right.moveToAbsolute (newPos.getRight(), nameSource);
top.moveToAbsolute (newPos.getY(), nameSource);
bottom.moveToAbsolute (newPos.getBottom(), nameSource);
}
const String RectangleCoordinates::toString() const
@@ -413,12 +493,12 @@ const String RectangleCoordinates::toString() const
}
void RectangleCoordinates::renameAnchorIfUsed (const String& oldName, const String& newName,
const Coordinate::MarkerResolver& markerResolver)
const Coordinate::NamedCoordinateFinder& nameSource)
{
left.renameAnchorIfUsed (oldName, newName, markerResolver);
right.renameAnchorIfUsed (oldName, newName, markerResolver);
top.renameAnchorIfUsed (oldName, newName, markerResolver);
bottom.renameAnchorIfUsed (oldName, newName, markerResolver);
left.renameAnchorIfUsed (oldName, newName, nameSource);
right.renameAnchorIfUsed (oldName, newName, nameSource);
top.renameAnchorIfUsed (oldName, newName, nameSource);
bottom.renameAnchorIfUsed (oldName, newName, nameSource);
}
@@ -455,7 +535,7 @@ void ComponentAutoLayoutManager::setMarker (const String& name, const Coordinate
applyLayout();
}
void ComponentAutoLayoutManager::setComponentLayout (Component* comp, const String& name, const RectangleCoordinates& coords)
void ComponentAutoLayoutManager::setComponentBounds (Component* comp, const String& name, const RectangleCoordinates& coords)
{
jassert (comp != 0);
@@ -492,29 +572,26 @@ void ComponentAutoLayoutManager::applyLayout()
}
}
const Coordinate ComponentAutoLayoutManager::findMarker (const String& name, bool isHorizontal) const
const Coordinate ComponentAutoLayoutManager::findNamedCoordinate (const String& objectName, const String& edge) const
{
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) parent->getWidth(), isHorizontal);
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) parent->getHeight(), isHorizontal);
if (name.containsChar ('.'))
if (objectName == Coordinate::Strings::parent)
{
const String compName (name.upToFirstOccurrenceOf (".", false, false).trim());
const String edge (name.fromFirstOccurrenceOf (".", false, false).trim());
if (edge == Coordinate::Strings::right) return Coordinate ((double) parent->getWidth(), true);
if (edge == Coordinate::Strings::bottom) return Coordinate ((double) parent->getHeight(), false);
}
if (compName.isNotEmpty() && edge.isNotEmpty())
if (objectName.isNotEmpty() && edge.isNotEmpty())
{
for (int i = components.size(); --i >= 0;)
{
for (int i = components.size(); --i >= 0;)
{
ComponentPosition* c = components.getUnchecked(i);
ComponentPosition* c = components.getUnchecked(i);
if (c->name == compName)
{
if (edge == "left") return c->coords.left;
if (edge == "right") return c->coords.right;
if (edge == "top") return c->coords.top;
if (edge == "bottom") return c->coords.bottom;
}
if (c->name == objectName)
{
if (edge == Coordinate::Strings::left) return c->coords.left;
if (edge == Coordinate::Strings::right) return c->coords.right;
if (edge == Coordinate::Strings::top) return c->coords.top;
if (edge == Coordinate::Strings::bottom) return c->coords.bottom;
}
}
}
@@ -523,11 +600,11 @@ const Coordinate ComponentAutoLayoutManager::findMarker (const String& name, boo
{
MarkerPosition* m = markers.getUnchecked(i);
if (m->markerName == name)
if (m->markerName == objectName)
return m->position;
}
return Coordinate (isHorizontal);
return Coordinate();
}
void ComponentAutoLayoutManager::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized)


+ 124
- 60
extras/Jucer (experimental)/Source/utility/jucer_Coordinate.h View File

@@ -31,15 +31,15 @@
//==============================================================================
/**
Holds a co-ordinate along the x or y axis, expressed either as an absolute
position, or relative to other named marker positions.
Describes a coordinate's, either as an absolute position, or relative to
other named positions.
*/
class Coordinate
{
public:
//==============================================================================
/** Creates a zero coordinate. */
explicit Coordinate (bool isHorizontal);
Coordinate();
/** Recreates a coordinate from its stringified version. */
Coordinate (const String& stringVersion, bool isHorizontal);
@@ -47,99 +47,143 @@ public:
/** Creates an absolute position from the parent origin. */
Coordinate (double absoluteDistanceFromOrigin, bool isHorizontal);
/** Creates an absolute position relative to a named marker. */
Coordinate (double absolutePosition, const String& relativeToMarker, bool isHorizontal);
/** Creates an absolute position relative to a named anchor. */
Coordinate (double absoluteDistanceFromAnchor, const String& anchorPoint);
/** Creates a relative position between two named markers. */
Coordinate (double relativePosition, const String& marker1, const String& marker2, bool isHorizontal);
/** Creates a relative position between two named points. */
Coordinate (double relativeProportionBetweenAnchors, const String& anchorPoint1, const String& anchorPoint2);
/** Destructor. */
~Coordinate();
//==============================================================================
/**
Provides an interface for looking up the position of a named marker.
Provides an interface for looking up the position of a named anchor.
*/
class MarkerResolver
class NamedCoordinateFinder
{
public:
virtual ~MarkerResolver() {}
virtual const Coordinate findMarker (const String& name, bool isHorizontal) const = 0;
virtual ~NamedCoordinateFinder() {}
virtual const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const = 0;
};
//==============================================================================
/** Calculates the absolute position of this co-ordinate. */
double resolve (const MarkerResolver& markerResolver) const;
/** Returns true if this co-ordinate is expressed directly in terms of the specified marker. */
bool referencesDirectly (const String& markerName) const;
double resolve (const NamedCoordinateFinder& nameSource) const;
/** Returns true if this co-ordinate is expressed in terms of the specified marker at any
/** Returns true if this co-ordinate is expressed in terms of the specified coord at any
level in its evaluation. */
bool referencesIndirectly (const String& markerName, const MarkerResolver& markerResolver) const;
bool references (const String& coordName, const NamedCoordinateFinder& nameSource) const;
//==============================================================================
/** Changes the value of this coord to make it resolve to the specified position. */
void moveToAbsolute (double newPos, const NamedCoordinateFinder& nameSource);
/** */
bool isProportional() const throw() { return anchor2.isNotEmpty(); }
/** Changes the value of this marker to make it resolve to the specified position. */
void moveToAbsolute (double newPos, const MarkerResolver& markerResolver);
/** */
void toggleProportionality (const NamedCoordinateFinder& nameSource, bool isHorizontal);
const Coordinate getAnchorPoint1() const;
const Coordinate getAnchorPoint2() const;
/** */
const double getEditableNumber() const;
const double getEditableValue() const;
void setEditableValue (const double newValue);
/** */
void setEditableNumber (const double newValue);
bool isHorizontal() const throw() { return horizontal; }
//==============================================================================
/** */
const String getAnchorName1() const { return anchor1; }
bool isProportional() const throw() { return isProportion; }
void toggleProportionality (const MarkerResolver& markerResolver);
/** */
const String getAnchorName2() const { return anchor2; }
const String getAnchor1() const { return checkName (anchor1); }
void changeAnchor1 (const String& newMarkerName, const MarkerResolver& markerResolver);
/** */
const Coordinate getAnchorCoordinate1() const;
const String getAnchor2() const { return checkName (anchor2); }
void changeAnchor2 (const String& newMarkerName, const MarkerResolver& markerResolver);
/** */
const Coordinate getAnchorCoordinate2() const;
/** */
void changeAnchor1 (const String& newAnchor, const NamedCoordinateFinder& nameSource);
/** */
void changeAnchor2 (const String& newAnchor, const NamedCoordinateFinder& nameSource);
/** Tells the coord that an anchor is changing its name.
If the new name is empty, it removes the anchor.
*/
void renameAnchorIfUsed (const String& oldName, const String& newName, const MarkerResolver& markerResolver);
void renameAnchorIfUsed (const String& oldName, const String& newName, const NamedCoordinateFinder& nameSource);
//==============================================================================
/*
Position string formats:
123 = absolute pixels from parent origin
marker
marker + 123
marker - 123
anchor
anchor + 123
anchor - 123
50% = percentage between parent origin and parent extent
50% * marker = percentage between parent origin and marker
50% * marker1 -> marker2 = percentage between two markers
50% * anchor = percentage between parent origin and anchor
50% * anchor1 -> anchor2 = percentage between two named points
standard marker names:
where an anchor name can be:
"parent.top", "parent.left", "parent.bottom", "parent.right"
"componentName.top", "componentName.left", "componentName.bottom", "componentName.right"
"objectName.top", "objectName.left", "objectName.bottom", "objectName.right"
"markerName"
*/
const String toString() const;
//==============================================================================
static const char* parentLeftMarkerName;
static const char* parentRightMarkerName;
static const char* parentTopMarkerName;
static const char* parentBottomMarkerName;
struct Strings
{
static const String parent;
static const String left;
static const String right;
static const String top;
static const String bottom;
static const String originX;
static const String originY;
static const String extentX;
static const String extentY;
};
//==============================================================================
struct RecursiveCoordinateException : public std::runtime_error
{
RecursiveCoordinateException();
};
private:
//==============================================================================
String anchor1, anchor2;
double value;
bool isProportion, horizontal;
double resolve (const MarkerResolver& markerResolver, int recursionCounter) const;
double getPosition (const String& name, const MarkerResolver& markerResolver, int recursionCounter) const;
const String checkName (const String& name) const;
const String getOriginMarkerName() const;
const String getExtentMarkerName() const;
double resolve (const NamedCoordinateFinder& nameSource, int recursionCounter) const;
double resolveAnchor (const String& name, const NamedCoordinateFinder& nameSource, int recursionCounter) const;
const String getOriginAnchorName (bool isHorizontal) const throw();
const String getExtentAnchorName (bool isHorizontal) const throw();
const Coordinate lookUpName (const String& name, const NamedCoordinateFinder& nameSource) const;
static bool isOrigin (const String& name);
static void skipWhitespace (const String& s, int& i);
static const String readMarkerName (const String& s, int& i);
static double readNumber (const String& s, int& i);
static const String getObjectName (const String& fullName);
static const String getEdgeName (const String& fullName);
};
//==============================================================================
class CoordinatePair
{
public:
CoordinatePair();
CoordinatePair (const Point<float>& absolutePoint);
CoordinatePair (const String& stringVersion);
const Point<float> resolve (const Coordinate::NamedCoordinateFinder& nameSource) const;
void moveToAbsolute (const Point<float>& newPos, const Coordinate::NamedCoordinateFinder& nameSource);
const String toString() const;
// Tells the coord that an anchor is changing its name.
void renameAnchorIfUsed (const String& oldName, const String& newName, const Coordinate::NamedCoordinateFinder& nameSource);
Coordinate x, y;
};
//==============================================================================
@@ -155,42 +199,58 @@ public:
explicit RectangleCoordinates (const String& stringVersion);
//==============================================================================
const Rectangle<int> resolve (const Coordinate::MarkerResolver& markerResolver) const;
void moveToAbsolute (const Rectangle<float>& newPos, const Coordinate::MarkerResolver& markerResolver);
const Rectangle<int> resolve (const Coordinate::NamedCoordinateFinder& nameSource) const;
void moveToAbsolute (const Rectangle<float>& newPos, const Coordinate::NamedCoordinateFinder& nameSource);
const String toString() const;
// Tells the coord that an anchor is changing its name.
void renameAnchorIfUsed (const String& oldName, const String& newName,
const Coordinate::MarkerResolver& markerResolver);
void renameAnchorIfUsed (const String& oldName, const String& newName, const Coordinate::NamedCoordinateFinder& nameSource);
Coordinate left, right, top, bottom;
};
//==============================================================================
/**
*/
class ComponentAutoLayoutManager : public ComponentListener,
public Coordinate::MarkerResolver,
public Coordinate::NamedCoordinateFinder,
public AsyncUpdater
{
public:
//==============================================================================
/**
*/
ComponentAutoLayoutManager (Component* parentComponent);
/** Destructor. */
~ComponentAutoLayoutManager();
//==============================================================================
/**
*/
void setMarker (const String& name, const Coordinate& coord);
void setComponentLayout (Component* comp, const String& name, const RectangleCoordinates& coords);
/**
*/
void setComponentBounds (Component* component, const String& componentName, const RectangleCoordinates& bounds);
/**
*/
void applyLayout();
const Coordinate findMarker (const String& name, bool isHorizontal) const;
//==============================================================================
/** @internal */
const Coordinate findNamedCoordinate (const String& objectName, const String& edge) const;
/** @internal */
void componentMovedOrResized (Component& component, bool wasMoved, bool wasResized);
/** @internal */
void componentBeingDeleted (Component& component);
/** @internal */
void handleAsyncUpdate();
juce_UseDebuggingNewOperator
private:
//==============================================================================
struct ComponentPosition
@@ -213,6 +273,10 @@ private:
Component* parent;
OwnedArray <ComponentPosition> components;
OwnedArray <MarkerPosition> markers;
ComponentAutoLayoutManager (const ComponentAutoLayoutManager&);
ComponentAutoLayoutManager& operator= (const ComponentAutoLayoutManager&);
};
#endif // __JUCER_COORDINATE_H_EF56ACFA__

+ 13
- 13
extras/Jucer (experimental)/Source/utility/jucer_CoordinatePropertyComponent.h View File

@@ -34,9 +34,9 @@ class CoordinatePropertyComponent : public PropertyComponent,
{
public:
//==============================================================================
CoordinatePropertyComponent (Coordinate::MarkerResolver& resolver_, const String& name,
CoordinatePropertyComponent (Coordinate::NamedCoordinateFinder& nameSource_, const String& name,
const Value& coordValue_, bool isHorizontal_)
: PropertyComponent (name, 40), resolver (resolver_),
: PropertyComponent (name, 40), nameSource (nameSource_),
coordValue (coordValue_),
textValue (Value (new CoordEditableValueSource (coordValue_, isHorizontal_))),
isHorizontal (isHorizontal_)
@@ -98,26 +98,26 @@ public:
if (button == proportionButton)
{
coord.toggleProportionality (resolver);
coord.toggleProportionality (nameSource, isHorizontal);
coordValue = coord.toString();
}
else if (button == anchorButton1)
{
const String marker (pickMarker (anchorButton1, coord.getAnchor1(), true));
const String marker (pickMarker (anchorButton1, coord.getAnchorName1(), true));
if (marker.isNotEmpty())
{
coord.changeAnchor1 (marker, resolver);
coord.changeAnchor1 (marker, nameSource);
coordValue = coord.toString();
}
}
else if (button == anchorButton2)
{
const String marker (pickMarker (anchorButton2, coord.getAnchor2(), false));
const String marker (pickMarker (anchorButton2, coord.getAnchorName2(), false));
if (marker.isNotEmpty())
{
coord.changeAnchor2 (marker, resolver);
coord.changeAnchor2 (marker, nameSource);
coordValue = coord.toString();
}
}
@@ -127,10 +127,10 @@ public:
{
Coordinate coord (getCoordinate());
anchorButton1->setButtonText (coord.getAnchor1());
anchorButton1->setButtonText (coord.getAnchorName1());
anchorButton2->setVisible (coord.isProportional());
anchorButton2->setButtonText (coord.getAnchor2());
anchorButton2->setButtonText (coord.getAnchorName2());
resized();
}
@@ -142,7 +142,7 @@ public:
virtual const String pickMarker (TextButton* button, const String& currentMarker, bool isAnchor1) = 0;
protected:
Coordinate::MarkerResolver& resolver;
Coordinate::NamedCoordinateFinder& nameSource;
Value coordValue, textValue;
Label* label;
TextButton* proportionButton;
@@ -168,15 +168,15 @@ protected:
Coordinate coord (sourceValue.toString(), isHorizontal);
if (coord.isProportional())
return String (coord.getEditableValue()) + "%";
return String (coord.getEditableNumber()) + "%";
return coord.getEditableValue();
return coord.getEditableNumber();
}
void setValue (const var& newValue)
{
Coordinate coord (sourceValue.toString(), isHorizontal);
coord.setEditableValue ((double) newValue);
coord.setEditableNumber ((double) newValue);
const String newVal (coord.toString());
if (sourceValue != newVal)


+ 3
- 3
extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h View File

@@ -30,7 +30,7 @@
//==============================================================================
class MarkerListBase : public Coordinate::MarkerResolver
class MarkerListBase : public Coordinate::NamedCoordinateFinder
{
public:
MarkerListBase (const ValueTree& group_, bool isX_) : group (group_), isX (isX_) {}
@@ -133,10 +133,10 @@ public:
{
public:
//==============================================================================
PositionPropertyComponent (MarkerResolver& resolver_, MarkerListBase& markerList_,
PositionPropertyComponent (NamedCoordinateFinder& nameSource_, MarkerListBase& markerList_,
const String& name, const ValueTree& markerState_,
const Value& coordValue_)
: CoordinatePropertyComponent (resolver_, name, coordValue_, markerList_.isHorizontal()),
: CoordinatePropertyComponent (nameSource_, name, coordValue_, markerList_.isHorizontal()),
markerList (markerList_),
markerState (markerState_)
{


+ 56
- 0
extras/Jucer (experimental)/Source/utility/jucer_MiscUtilities.h View File

@@ -80,3 +80,59 @@ private:
Colour colour;
GlyphArrangement glyphs;
};
//==============================================================================
class JucerToolbarButton : public ToolbarItemComponent
{
public:
//==============================================================================
JucerToolbarButton (int itemId_, const String& labelText)
: ToolbarItemComponent (itemId_, labelText, true)
{
setClickingTogglesState (false);
}
~JucerToolbarButton()
{
}
//==============================================================================
bool getToolbarItemSizes (int toolbarDepth, bool isToolbarVertical, int& preferredSize, int& minSize, int& maxSize)
{
preferredSize = minSize = maxSize = 50;
return true;
}
void paintButton (Graphics& g, bool over, bool down)
{
Path p;
p.addRoundedRectangle (1.5f, 2.5f, getWidth() - 3.0f, getHeight() - 5.0f, 3.0f);
if (getToggleState())
{
g.setColour (Colours::grey.withAlpha (0.5f));
g.fillPath (p);
}
g.setColour (Colours::darkgrey.withAlpha (0.3f));
g.strokePath (p, PathStrokeType (1.0f));
g.setFont (11.0f);
g.setColour (Colours::black.withAlpha ((over || down) ? 1.0f : 0.7f));
g.drawFittedText (getButtonText(), 2, 2, getWidth() - 4, getHeight() - 4, Justification::centred, 2);
}
void paintButtonArea (Graphics& g, int width, int height, bool isMouseOver, bool isMouseDown)
{
}
void contentAreaChanged (const Rectangle<int>& newBounds)
{
}
juce_UseDebuggingNewOperator
private:
JucerToolbarButton (const JucerToolbarButton&);
JucerToolbarButton& operator= (const JucerToolbarButton&);
};

+ 11
- 10
extras/juce demo/Source/demos/RenderingTestComponent.cpp View File

@@ -296,7 +296,7 @@ private:
void drawSVG (Graphics& g)
{
if (Time::getCurrentTime().toMilliseconds() > lastSVGLoadTime.toMilliseconds() + 3000)
if (Time::getCurrentTime().toMilliseconds() > lastSVGLoadTime.toMilliseconds() + 2000)
{
lastSVGLoadTime = Time::getCurrentTime();
createSVGDrawable();
@@ -344,22 +344,23 @@ private:
if (svgFileStream != 0)
{
Drawable* loadedSVG = Drawable::createFromImageDataStream (*svgFileStream);
svgDrawable = dynamic_cast <DrawableComposite*> (Drawable::createFromImageDataStream (*svgFileStream));
delete svgFileStream;
if (loadedSVG != 0)
if (svgDrawable != 0)
{
// to make our icon the right size, we'll put it inside a DrawableComposite, and apply
// a transform to get it to the size we want.
Rectangle<float> bounds = loadedSVG->getBounds();
const float scaleFactor = 300.0f / jmax (bounds.getWidth(), bounds.getHeight());
Rectangle<float> bounds = svgDrawable->getBounds();
const float scaleFactor = 200.0f / jmax (bounds.getWidth(), bounds.getHeight());
svgDrawable = new DrawableComposite();
svgDrawable->insertDrawable (loadedSVG,
AffineTransform::translation (-bounds.getCentreX(),
-bounds.getCentreY())
.scaled (scaleFactor, scaleFactor));
Point<float> topLeft (-bounds.getCentreX() * scaleFactor,
-bounds.getCentreY() * scaleFactor);
svgDrawable->setTransform (topLeft,
topLeft + Point<float> (scaleFactor, 0),
topLeft + Point<float> (0, scaleFactor));
}
}
}


+ 506
- 375
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 181
- 43
juce_amalgamated.h View File

@@ -64,7 +64,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 3
#define JUCE_BUILDNUMBER 4

/** Current Juce version number.

@@ -5759,7 +5759,7 @@ public:
The following code is in the header so that the atomics can be inlined where possible...
*/
#if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \
|| (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
|| (JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
#define JUCE_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier

#if JUCE_PPC || JUCE_IPHONE
@@ -12955,7 +12955,7 @@ public:
The type is specified when the ValueTree is created.
@see hasType
*/
const String getType() const;
const Identifier getType() const;

/** Returns true if the node has this type.
The comparison is case-sensitive.
@@ -18856,6 +18856,16 @@ public:
*/
const AffineTransform inverted() const throw();

/** Returns the transform that will map three known points onto three coordinates
that are supplied.

This returns the transform that will transform (0, 0) into (x00, y00),
(1, 0) to (x10, y10), and (0, 1) to (x01, y01).
*/
static const AffineTransform fromTargetPoints (float x00, float y00,
float x10, float y10,
float x01, float y01) throw();

/** Returns the result of concatenating another transformation after this one. */
const AffineTransform followedBy (const AffineTransform& other) const throw();

@@ -19006,6 +19016,9 @@ public:
/** Returns the position of this point, if it is transformed by a given AffineTransform. */
const Point transformedBy (const AffineTransform& transform) const throw() { ValueType x2 (x), y2 (y); transform.transformPoint (x2, y2); return Point (x2, y2); }

/** Casts this point to a Point<float> object. */
const Point<float> toFloat() const throw() { return Point<float> (static_cast <float> (x), static_cast<float> (y)); }

/** Returns the point as a string in the form "x, y". */
const String toString() const { return String (x) + ", " + String (y); }

@@ -20451,11 +20464,16 @@ public:
return false;
}

/** Returns the smallest rectangle that contains both this one and the one
passed-in.
/** Returns the smallest rectangle that contains both this one and the one passed-in.

If either this or the other rectangle are empty, they will not be counted as
part of the resulting region.
*/
const Rectangle getUnion (const Rectangle& other) const throw()
{
if (other.isEmpty()) return *this;
if (isEmpty()) return other;

const ValueType newX = jmin (x, other.x);
const ValueType newY = jmin (y, other.y);

@@ -20839,6 +20857,9 @@ public:
/** Copies this path from another one. */
Path& operator= (const Path& other);

bool operator== (const Path& other) const throw();
bool operator!= (const Path& other) const throw();

/** Returns true if the path doesn't contain any lines or curves. */
bool isEmpty() const throw();

@@ -21224,7 +21245,7 @@ public:
The internal data of the two paths is swapped over, so this is much faster than
copying it to a temp variable and back.
*/
void swapWithPath (Path& other);
void swapWithPath (Path& other) throw();

/** Applies a 2D transform to all the vertices in the path.

@@ -23140,6 +23161,9 @@ public:
*/
bool isRadial;

bool operator== (const ColourGradient& other) const throw();
bool operator!= (const ColourGradient& other) const throw();

juce_UseDebuggingNewOperator

private:
@@ -23151,6 +23175,9 @@ private:
: position (position_), colour (colour_)
{}

bool operator== (const ColourPoint& other) const throw() { return position == other.position && colour == other.colour; }
bool operator!= (const ColourPoint& other) const throw() { return position != other.position || colour != other.colour; }

uint32 position;
Colour colour;
};
@@ -41889,24 +41916,65 @@ public:
*/
static Drawable* createFromSVG (const XmlElement& svgDocument);

/** This class is used when loading Drawables that contain images, and retrieves
the image for a stored identifier.
@see Drawable::createFromValueTree
*/
class JUCE_API ImageProvider
{
public:
ImageProvider() {}
virtual ~ImageProvider() {}

/** Retrieves the image associated with this identifier, which could be any
kind of string, number, filename, etc.

The image that is returned will be owned by the caller, but it may come
from the ImageCache.
*/
virtual Image* getImageForIdentifier (const var& imageIdentifier) = 0;

/** Returns an identifier to be used to refer to a given image.
This is used when converting a drawable into a ValueTree, so if you're
only loading drawables, you can just return a var::null here.
*/
virtual const var getIdentifierForImage (Image* image) = 0;
};

/** Tries to create a Drawable from a previously-saved ValueTree.
The ValueTree must have been created by the createValueTree() method.
If there are any images used within the drawable, you'll need to provide a valid
ImageProvider object that can be used to retrieve these images from whatever type
of identifier is used to represent them.
*/
static Drawable* createFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);

/** Tries to refresh a Drawable from the same ValueTree that was used to create it.
@returns the damage rectangle that will need repainting due to any changes that were made.
*/
static Drawable* createFromValueTree (const ValueTree& tree);
virtual const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) = 0;

/** Creates a ValueTree to represent this Drawable.
The VarTree that is returned can be turned back into a Drawable with
createFromValueTree().
If there are any images used in this drawable, you'll need to provide a valid
ImageProvider object that can be used to create storable representations of them.
*/
virtual ValueTree createValueTree() const = 0;
virtual const ValueTree createValueTree (ImageProvider* imageProvider) const = 0;

/** Returns the tag ID that is used for a ValueTree that stores this type of drawable. */
virtual const Identifier getValueTreeType() const = 0;

juce_UseDebuggingNewOperator

protected:
static const Identifier idProperty;

private:
String name;

Drawable (const Drawable&);
Drawable& operator= (const Drawable&);

String name;
};

#endif // __JUCE_DRAWABLE_JUCEHEADER__
@@ -50657,6 +50725,7 @@ private:
Component* panelComponent;
int tabDepth;
int outlineThickness, edgeIndent;
static const Identifier deleteComponentId;

friend class TabCompButtonBar;
void changeCallback (int newCurrentTabIndex, const String& newTabName);
@@ -57436,16 +57505,12 @@ public:
@param drawable the object to add - this will be deleted automatically
when no longer needed, so the caller mustn't keep any
pointers to it.
@param transform the transform to apply to this drawable when it's being
drawn
@param index where to insert it in the list of drawables. 0 is the back,
-1 is the front, or any value from 0 and getNumDrawables()
can be used
@see removeDrawable
*/
void insertDrawable (Drawable* drawable,
const AffineTransform& transform = AffineTransform::identity,
int index = -1);
void insertDrawable (Drawable* drawable, int index = -1);

/** Adds a new sub-drawable to this one.

@@ -57454,16 +57519,12 @@ public:
pointer instead.

@param drawable the object to add - an internal copy will be made of this object
@param transform the transform to apply to this drawable when it's being
drawn
@param index where to insert it in the list of drawables. 0 is the back,
-1 is the front, or any value from 0 and getNumDrawables()
can be used
@see removeDrawable
*/
void insertDrawable (const Drawable& drawable,
const AffineTransform& transform = AffineTransform::identity,
int index = -1);
void insertDrawable (const Drawable& drawable, int index = -1);

/** Deletes one of the Drawable objects.

@@ -57493,15 +57554,6 @@ public:
*/
Drawable* getDrawable (int index) const throw() { return drawables [index]; }

/** Returns the transform that applies to one of the drawables that are contained in this one.

The pointer returned is managed by this object and will be deleted when no longer
needed, so be careful what you do with it.

@see getNumDrawables
*/
const AffineTransform* getDrawableTransform (int index) const throw() { return transforms [index]; }

/** Brings one of the Drawables to the front.

@param index the index of the drawable to move, between 0
@@ -57510,6 +57562,38 @@ public:
*/
void bringToFront (int index);

/** Sets the transform to be applied to this drawable, by defining the positions
where three anchor points should end up in the target rendering space.

@param targetPositionForOrigin the position that the local coordinate (0, 0) should be
mapped onto when rendering this object.
@param targetPositionForX1Y0 the position that the local coordinate (1, 0) should be
mapped onto when rendering this object.
@param targetPositionForX0Y1 the position that the local coordinate (0, 1) should be
mapped onto when rendering this object.
*/
void setTransform (const Point<float>& targetPositionForOrigin,
const Point<float>& targetPositionForX1Y0,
const Point<float>& targetPositionForX0Y1);

/** Returns the position to which the local coordinate (0, 0) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForOrigin() const throw() { return controlPoints[0]; }

/** Returns the position to which the local coordinate (1, 0) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForX1Y0() const throw() { return controlPoints[1]; }

/** Returns the position to which the local coordinate (0, 1) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForX0Y1() const throw() { return controlPoints[2]; }

/** @internal */
void render (const Drawable::RenderingContext& context) const;
/** @internal */
@@ -57517,17 +57601,28 @@ public:
/** @internal */
bool hitTest (float x, float y) const;
/** @internal */
int getNumControlPoints() const;
/** @internal */
const Point<float> getControlPoint (int index) const;
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
static DrawableComposite* createFromValueTree (const ValueTree& tree);
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }

juce_UseDebuggingNewOperator

private:
OwnedArray <Drawable> drawables;
OwnedArray <AffineTransform> transforms;
Point<float> controlPoints[3];

const Rectangle<float> getUntransformedBounds() const;
const AffineTransform getTransform() const;

DrawableComposite (const DrawableComposite&);
DrawableComposite& operator= (const DrawableComposite&);
@@ -57568,9 +57663,6 @@ public:

/** Sets the image that this drawable will render.

An internal copy of this will not be made, so the caller mustn't delete
the image while it's still being used by this object.

A good way to use this is with the ImageCache - if you create an image
with ImageCache and pass it in here with releaseWhenNotNeeded = true, then
it'll be released neatly with its reference count being decreased.
@@ -57581,8 +57673,7 @@ public:
needs it - unless the image was created by the ImageCache,
in which case it will be released with ImageCache::release().
*/
void setImage (Image* imageToUse,
bool releaseWhenNotNeeded);
void setImage (Image* imageToUse, bool releaseWhenNotNeeded);

/** Returns the current image. */
Image* getImage() const throw() { return image; }
@@ -57610,6 +57701,38 @@ public:
/** Returns the overlay colour. */
const Colour& getOverlayColour() const throw() { return overlayColour; }

/** Sets the transform to be applied to this image, by defining the positions
where three anchor points should end up in the target rendering space.

@param imageTopLeftPosition the position that the image's top-left corner should be mapped to
in the target coordinate space.
@param imageTopRightPosition the position that the image's top-right corner should be mapped to
in the target coordinate space.
@param imageBottomLeftPosition the position that the image's bottom-left corner should be mapped to
in the target coordinate space.
*/
void setTransform (const Point<float>& imageTopLeftPosition,
const Point<float>& imageTopRightPosition,
const Point<float>& imageBottomLeftPosition);

/** Returns the position to which the image's top-left corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForTopLeft() const throw() { return controlPoints[0]; }

/** Returns the position to which the image's top-right corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForTopRight() const throw() { return controlPoints[1]; }

/** Returns the position to which the image's bottom-left corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; }

/** @internal */
void render (const Drawable::RenderingContext& context) const;
/** @internal */
@@ -57619,9 +57742,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static DrawableImage* createFromValueTree (const ValueTree& tree);
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }

juce_UseDebuggingNewOperator

@@ -57630,6 +57757,9 @@ private:
bool canDeleteImage;
float opacity;
Colour overlayColour;
Point<float> controlPoints[3];

const AffineTransform getTransform() const;

DrawableImage (const DrawableImage&);
DrawableImage& operator= (const DrawableImage&);
@@ -57719,9 +57849,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
static DrawablePath* createFromValueTree (const ValueTree& tree);
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }

juce_UseDebuggingNewOperator

@@ -57791,9 +57925,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
static DrawableText* createFromValueTree (const ValueTree& tree);
const Identifier getValueTreeType() const { return valueTreeType; }

juce_UseDebuggingNewOperator



+ 1
- 1
src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp View File

@@ -88,7 +88,7 @@ public:
{
bufferList.calloc (256, 1);
#ifdef WIN32
#if JUCE_WINDOWS
if (InitializeQTML (0) != noErr)
return;
#endif


+ 3
- 3
src/containers/juce_ValueTree.cpp View File

@@ -566,9 +566,9 @@ bool ValueTree::hasType (const Identifier& typeName) const
return object != 0 && object->type == typeName;
}
const String ValueTree::getType() const
const Identifier ValueTree::getType() const
{
return object != 0 ? object->type.toString() : String::empty;
return object != 0 ? object->type : Identifier();
}
ValueTree ValueTree::getParent() const
@@ -807,7 +807,7 @@ ValueTree ValueTree::fromXml (const XmlElement& xml)
//==============================================================================
void ValueTree::writeToStream (OutputStream& output)
{
output.writeString (getType());
output.writeString (getType().toString());
const int numProps = getNumProperties();
output.writeCompressedInt (numProps);


+ 1
- 1
src/containers/juce_ValueTree.h View File

@@ -125,7 +125,7 @@ public:
The type is specified when the ValueTree is created.
@see hasType
*/
const String getType() const;
const Identifier getType() const;
/** Returns true if the node has this type.
The comparison is case-sensitive.


+ 1
- 1
src/core/juce_Atomic.h View File

@@ -153,7 +153,7 @@ public:
The following code is in the header so that the atomics can be inlined where possible...
*/
#if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \
|| (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
|| (JUCE_MAC && (JUCE_PPC || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)))
#define JUCE_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier
#if JUCE_PPC || JUCE_IPHONE


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -33,7 +33,7 @@
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 52
#define JUCE_BUILDNUMBER 3
#define JUCE_BUILDNUMBER 4
/** Current Juce version number.


+ 1
- 5
src/gui/components/controls/juce_ListBox.cpp View File

@@ -895,11 +895,7 @@ Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY)
{
const Point<int> pos (rowComp->relativePositionToOtherComponent (this, Point<int>()));
const Rectangle<int> rowRect (pos.getX(), pos.getY(), rowComp->getWidth(), rowComp->getHeight());
if (imageArea.isEmpty())
imageArea = rowRect;
else
imageArea = imageArea.getUnion (rowRect);
imageArea = imageArea.getUnion (rowRect);
}
}


+ 4
- 2
src/gui/components/juce_Component.cpp View File

@@ -2929,14 +2929,16 @@ bool Component::isFocusContainer() const throw()
return flags.isFocusContainerFlag;
}
static const Identifier juce_explicitFocusOrderId ("_jexfo");
int Component::getExplicitFocusOrder() const
{
return properties ["_jexfo"];
return properties [juce_explicitFocusOrderId];
}
void Component::setExplicitFocusOrder (const int newFocusOrderIndex)
{
properties.set ("_jexfo", newFocusOrderIndex);
properties.set (juce_explicitFocusOrderId, newFocusOrderIndex);
}
KeyboardFocusTraverser* Component::createFocusTraverser()


+ 5
- 3
src/gui/components/layout/juce_TabbedComponent.cpp View File

@@ -118,6 +118,8 @@ TabBarButton* TabbedComponent::createTabButton (const String& tabName, const int
}
//==============================================================================
const Identifier TabbedComponent::deleteComponentId ("deleteByTabComp_");
void TabbedComponent::clearTabs()
{
if (panelComponent != 0)
@@ -136,7 +138,7 @@ void TabbedComponent::clearTabs()
// be careful not to delete these components until they've been removed from the tab component
jassert (c == 0 || c->isValidComponent());
if (c != 0 && (bool) c->getProperties() ["deleteByTabComp_"])
if (c != 0 && (bool) c->getProperties() [deleteComponentId])
delete c;
}
@@ -152,7 +154,7 @@ void TabbedComponent::addTab (const String& tabName,
contentComponents.insert (insertIndex, contentComponent);
if (contentComponent != 0)
contentComponent->getProperties().set ("deleteByTabComp_", deleteComponentWhenNotNeeded);
contentComponent->getProperties().set (deleteComponentId, deleteComponentWhenNotNeeded);
tabs->addTab (tabName, tabBackgroundColour, insertIndex);
}
@@ -166,7 +168,7 @@ void TabbedComponent::removeTab (const int tabIndex)
{
Component* const c = contentComponents [tabIndex];
if (c != 0 && (bool) c->getProperties() ["deleteByTabComp_"])
if (c != 0 && (bool) c->getProperties() [deleteComponentId])
{
if (c == panelComponent)
panelComponent = 0;


+ 1
- 0
src/gui/components/layout/juce_TabbedComponent.h View File

@@ -232,6 +232,7 @@ private:
Component* panelComponent;
int tabDepth;
int outlineThickness, edgeIndent;
static const Identifier deleteComponentId;
friend class TabCompButtonBar;
void changeCallback (int newCurrentTabIndex, const String& newTabName);


+ 1
- 2
src/gui/components/mouse/juce_MouseInputSource.cpp View File

@@ -328,8 +328,7 @@ public:
{
if (mouseDowns[0].time - mouseDowns[i].time < (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1)))
&& abs (mouseDowns[0].position.getX() - mouseDowns[i].position.getX()) < 8
&& abs (mouseDowns[0].position.getY() - mouseDowns[i].position.getY()) < 8
&& mouseDowns[0].component == mouseDowns[i].component)
&& abs (mouseDowns[0].position.getY() - mouseDowns[i].position.getY()) < 8)
{
++numClicks;
}


+ 12
- 0
src/gui/graphics/colour/juce_ColourGradient.cpp View File

@@ -57,6 +57,18 @@ ColourGradient::~ColourGradient()
{
}
bool ColourGradient::operator== (const ColourGradient& other) const throw()
{
return point1 == other.point1 && point2 == other.point2
&& isRadial == other.isRadial
&& colours == other.colours;
}
bool ColourGradient::operator!= (const ColourGradient& other) const throw()
{
return ! operator== (other);
}
//==============================================================================
void ColourGradient::clearColours()
{


+ 6
- 0
src/gui/graphics/colour/juce_ColourGradient.h View File

@@ -141,6 +141,9 @@ public:
*/
bool isRadial;
bool operator== (const ColourGradient& other) const throw();
bool operator!= (const ColourGradient& other) const throw();
//==============================================================================
juce_UseDebuggingNewOperator
@@ -153,6 +156,9 @@ private:
: position (position_), colour (colour_)
{}
bool operator== (const ColourPoint& other) const throw() { return position == other.position && colour == other.colour; }
bool operator!= (const ColourPoint& other) const throw() { return position != other.position || colour != other.colour; }
uint32 position;
Colour colour;
};


+ 17
- 15
src/gui/graphics/drawables/juce_Drawable.cpp View File

@@ -36,6 +36,8 @@ BEGIN_JUCE_NAMESPACE
#include "../../../text/juce_XmlDocument.h"
#include "../../../io/files/juce_FileInputStream.h"
const Identifier Drawable::idProperty ("id");
//==============================================================================
Drawable::RenderingContext::RenderingContext (Graphics& g_,
const AffineTransform& transform_,
@@ -133,22 +135,22 @@ Drawable* Drawable::createFromImageFile (const File& file)
}
//==============================================================================
Drawable* Drawable::createFromValueTree (const ValueTree& tree)
Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
{
Drawable* d = DrawablePath::createFromValueTree (tree);
if (d == 0)
{
d = DrawableComposite::createFromValueTree (tree);
if (d == 0)
{
d = DrawableImage::createFromValueTree (tree);
if (d == 0)
d = DrawableText::createFromValueTree (tree);
}
}
const Identifier type (tree.getType());
Drawable* d = 0;
if (type == DrawablePath::valueTreeType)
d = new DrawablePath();
else if (type == DrawableComposite::valueTreeType)
d = new DrawableComposite();
else if (type == DrawableImage::valueTreeType)
d = new DrawableImage();
else if (type == DrawableText::valueTreeType)
d = new DrawableText();
if (d != 0)
d->refreshFromValueTree (tree, imageProvider);
return d;
}


+ 45
- 4
src/gui/graphics/drawables/juce_Drawable.h View File

@@ -180,25 +180,66 @@ public:
static Drawable* createFromSVG (const XmlElement& svgDocument);
//==============================================================================
/** This class is used when loading Drawables that contain images, and retrieves
the image for a stored identifier.
@see Drawable::createFromValueTree
*/
class JUCE_API ImageProvider
{
public:
ImageProvider() {}
virtual ~ImageProvider() {}
/** Retrieves the image associated with this identifier, which could be any
kind of string, number, filename, etc.
The image that is returned will be owned by the caller, but it may come
from the ImageCache.
*/
virtual Image* getImageForIdentifier (const var& imageIdentifier) = 0;
/** Returns an identifier to be used to refer to a given image.
This is used when converting a drawable into a ValueTree, so if you're
only loading drawables, you can just return a var::null here.
*/
virtual const var getIdentifierForImage (Image* image) = 0;
};
/** Tries to create a Drawable from a previously-saved ValueTree.
The ValueTree must have been created by the createValueTree() method.
If there are any images used within the drawable, you'll need to provide a valid
ImageProvider object that can be used to retrieve these images from whatever type
of identifier is used to represent them.
*/
static Drawable* createFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** Tries to refresh a Drawable from the same ValueTree that was used to create it.
@returns the damage rectangle that will need repainting due to any changes that were made.
*/
static Drawable* createFromValueTree (const ValueTree& tree);
virtual const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider) = 0;
/** Creates a ValueTree to represent this Drawable.
The VarTree that is returned can be turned back into a Drawable with
createFromValueTree().
If there are any images used in this drawable, you'll need to provide a valid
ImageProvider object that can be used to create storable representations of them.
*/
virtual ValueTree createValueTree() const = 0;
virtual const ValueTree createValueTree (ImageProvider* imageProvider) const = 0;
/** Returns the tag ID that is used for a ValueTree that stores this type of drawable. */
virtual const Identifier getValueTreeType() const = 0;
//==============================================================================
juce_UseDebuggingNewOperator
protected:
static const Identifier idProperty;
private:
String name;
Drawable (const Drawable&);
Drawable& operator= (const Drawable&);
String name;
};


+ 122
- 106
src/gui/graphics/drawables/juce_DrawableComposite.cpp View File

@@ -37,6 +37,8 @@ BEGIN_JUCE_NAMESPACE
//==============================================================================
DrawableComposite::DrawableComposite()
{
controlPoints[1].setXY (1.0f, 0.0f);
controlPoints[2].setXY (0.0f, 1.0f);
}
DrawableComposite::~DrawableComposite()
@@ -44,51 +46,48 @@ DrawableComposite::~DrawableComposite()
}
//==============================================================================
void DrawableComposite::insertDrawable (Drawable* drawable,
const AffineTransform& transform,
const int index)
void DrawableComposite::insertDrawable (Drawable* drawable, const int index)
{
if (drawable != 0)
{
if (! drawables.contains (drawable))
{
drawables.insert (index, drawable);
if (transform.isIdentity())
transforms.insert (index, 0);
else
transforms.insert (index, new AffineTransform (transform));
}
else
{
jassertfalse; // trying to add a drawable that's already in here!
}
jassert (! drawables.contains (drawable)); // trying to add a drawable that's already in here!
drawables.insert (index, drawable);
}
}
void DrawableComposite::insertDrawable (const Drawable& drawable,
const AffineTransform& transform,
const int index)
void DrawableComposite::insertDrawable (const Drawable& drawable, const int index)
{
insertDrawable (drawable.createCopy(), transform, index);
insertDrawable (drawable.createCopy(), index);
}
void DrawableComposite::removeDrawable (const int index, const bool deleteDrawable)
{
drawables.remove (index, deleteDrawable);
transforms.remove (index);
}
void DrawableComposite::bringToFront (const int index)
{
if (index >= 0 && index < drawables.size() - 1)
{
drawables.move (index, -1);
transforms.move (index, -1);
}
}
void DrawableComposite::setTransform (const Point<float>& targetPositionForOrigin,
const Point<float>& targetPositionForX1Y0,
const Point<float>& targetPositionForX0Y1)
{
controlPoints[0] = targetPositionForOrigin;
controlPoints[1] = targetPositionForX1Y0;
controlPoints[2] = targetPositionForX0Y1;
}
//==============================================================================
const AffineTransform DrawableComposite::getTransform() const
{
return AffineTransform::fromTargetPoints (controlPoints[0].getX(), controlPoints[0].getY(),
controlPoints[1].getX(), controlPoints[1].getY(),
controlPoints[2].getX(), controlPoints[2].getY());
}
void DrawableComposite::render (const Drawable::RenderingContext& context) const
{
if (drawables.size() > 0 && context.opacity > 0)
@@ -96,15 +95,10 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const
if (context.opacity >= 1.0f || drawables.size() == 1)
{
Drawable::RenderingContext contextCopy (context);
contextCopy.transform = getTransform().followedBy (context.transform);
for (int i = 0; i < drawables.size(); ++i)
{
const AffineTransform* const t = transforms.getUnchecked(i);
contextCopy.transform = (t == 0) ? context.transform
: t->followedBy (context.transform);
drawables.getUnchecked(i)->render (contextCopy);
}
}
else
{
@@ -127,42 +121,28 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const
}
}
const Rectangle<float> DrawableComposite::getBounds() const
const Rectangle<float> DrawableComposite::getUntransformedBounds() const
{
Rectangle<float> bounds;
for (int i = 0; i < drawables.size(); ++i)
{
const Drawable* const d = drawables.getUnchecked(i);
const AffineTransform* const t = transforms.getUnchecked(i);
const Rectangle<float> childBounds (t == 0 ? d->getBounds()
: d->getBounds().transformed (*t));
if (bounds.isEmpty())
bounds = childBounds;
else if (! childBounds.isEmpty())
bounds = bounds.getUnion (childBounds);
}
bounds = bounds.getUnion (drawables.getUnchecked(i)->getBounds());
return bounds;
}
bool DrawableComposite::hitTest (float x, float y) const
const Rectangle<float> DrawableComposite::getBounds() const
{
for (int i = 0; i < drawables.size(); ++i)
{
float tx = x;
float ty = y;
const AffineTransform* const t = transforms.getUnchecked(i);
return getUntransformedBounds().transformed (getTransform());
}
if (t != 0)
t->inverted().transformPoint (tx, ty);
bool DrawableComposite::hitTest (float x, float y) const
{
getTransform().inverted().transformPoint (x, y);
if (drawables.getUnchecked(i)->hitTest (tx, ty))
for (int i = 0; i < drawables.size(); ++i)
if (drawables.getUnchecked(i)->hitTest (x, y))
return true;
}
return false;
}
@@ -171,87 +151,123 @@ Drawable* DrawableComposite::createCopy() const
{
DrawableComposite* const dc = new DrawableComposite();
for (int i = 0; i < 3; ++i)
dc->controlPoints[i] = controlPoints[i];
for (int i = 0; i < drawables.size(); ++i)
{
dc->drawables.add (drawables.getUnchecked(i)->createCopy());
const AffineTransform* const t = transforms.getUnchecked(i);
dc->transforms.add (t != 0 ? new AffineTransform (*t) : 0);
}
return dc;
}
//==============================================================================
ValueTree DrawableComposite::createValueTree() const
{
ValueTree v ("Group");
const Identifier DrawableComposite::valueTreeType ("Group");
if (getName().isNotEmpty())
v.setProperty ("id", getName(), 0);
namespace DrawableCompositeHelpers
{
static const Identifier topLeft ("topLeft");
static const Identifier topRight ("topRight");
static const Identifier bottomLeft ("bottomLeft");
for (int i = 0; i < drawables.size(); ++i)
static void stringToPoint (const String& coords, Point<float>& point)
{
Drawable* const d = drawables.getUnchecked(i);
ValueTree child (d->createValueTree());
AffineTransform* transform = transforms.getUnchecked(i);
if (transform != 0)
if (coords.isNotEmpty())
{
String t;
t << transform->mat00 << " " << transform->mat01 << " " << transform->mat02 << " "
<< transform->mat10 << " " << transform->mat11 << " " << transform->mat12;
child.setProperty ("transform", t, 0);
const int comma = coords.indexOfChar (',');
point.setXY (coords.substring (0, comma).getFloatValue(),
coords.substring (comma).getFloatValue());
}
v.addChild (child, -1, 0);
}
return v;
static const var pointToString (const Point<float>& point)
{
return String (point.getX()) + ", " + String (point.getY());
}
}
DrawableComposite* DrawableComposite::createFromValueTree (const ValueTree& tree)
const Rectangle<float> DrawableComposite::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
{
if (! tree.hasType ("Group"))
return 0;
jassert (tree.hasType (valueTreeType));
Rectangle<float> damageRect;
DrawableComposite* dc = new DrawableComposite();
dc->setName (tree ["id"]);
setName (tree [idProperty]);
Point<float> newControlPoint[3];
DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::topLeft].toString(), newControlPoint[0]);
DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::topRight].toString(), newControlPoint[1]);
DrawableCompositeHelpers::stringToPoint (tree [DrawableCompositeHelpers::bottomLeft].toString(), newControlPoint[2]);
bool controlPointsChanged = false;
if (controlPoints[0] != newControlPoint[0]
|| controlPoints[1] != newControlPoint[1]
|| controlPoints[2] != newControlPoint[2])
{
controlPointsChanged = true;
damageRect = getUntransformedBounds();
controlPoints[0] = newControlPoint[0];
controlPoints[1] = newControlPoint[1];
controlPoints[2] = newControlPoint[2];
}
int i;
for (i = drawables.size(); --i >= tree.getNumChildren();)
{
damageRect = damageRect.getUnion (drawables.getUnchecked(i)->getBounds());
drawables.remove (i);
}
for (int i = 0; i < tree.getNumChildren(); ++i)
{
ValueTree childTree (tree.getChild (i));
Drawable* d = Drawable::createFromValueTree (childTree);
const ValueTree childTree (tree.getChild (i));
Drawable* d = drawables[i];
if (d != 0)
{
AffineTransform transform;
const String transformAtt (childTree ["transform"].toString());
if (transformAtt.isNotEmpty())
if (childTree.hasType (d->getValueTreeType()))
{
StringArray tokens;
tokens.addTokens (transformAtt.trim(), false);
tokens.removeEmptyStrings (true);
if (tokens.size() == 6)
{
float f[6];
for (int j = 0; j < 6; ++j)
f[j] = (float) tokens[j].getDoubleValue();
transform = AffineTransform (f[0], f[1], f[2], f[3], f[4], f[5]);
}
damageRect = damageRect.getUnion (d->refreshFromValueTree (childTree, imageProvider));
}
dc->insertDrawable (d, transform);
else
{
damageRect = damageRect.getUnion (d->getBounds());
d = createFromValueTree (childTree, imageProvider);
drawables.set (i, d);
damageRect = damageRect.getUnion (d->getBounds());
}
}
else
{
d = createFromValueTree (childTree, imageProvider);
drawables.set (i, d);
damageRect = damageRect.getUnion (d->getBounds());
}
}
return dc;
if (controlPointsChanged)
damageRect = damageRect.getUnion (getUntransformedBounds());
return damageRect.transformed (getTransform());
}
const ValueTree DrawableComposite::createValueTree (ImageProvider* imageProvider) const
{
ValueTree v (valueTreeType);
if (getName().isNotEmpty())
v.setProperty (idProperty, getName(), 0);
if (! getTransform().isIdentity())
{
v.setProperty (DrawableCompositeHelpers::topLeft, DrawableCompositeHelpers::pointToString (controlPoints[0]), 0);
v.setProperty (DrawableCompositeHelpers::topRight, DrawableCompositeHelpers::pointToString (controlPoints[1]), 0);
v.setProperty (DrawableCompositeHelpers::bottomLeft, DrawableCompositeHelpers::pointToString (controlPoints[2]), 0);
}
for (int i = 0; i < drawables.size(); ++i)
v.addChild (drawables.getUnchecked(i)->createValueTree (imageProvider), -1, 0);
return v;
}


+ 47
- 22
src/gui/graphics/drawables/juce_DrawableComposite.h View File

@@ -55,16 +55,12 @@ public:
@param drawable the object to add - this will be deleted automatically
when no longer needed, so the caller mustn't keep any
pointers to it.
@param transform the transform to apply to this drawable when it's being
drawn
@param index where to insert it in the list of drawables. 0 is the back,
-1 is the front, or any value from 0 and getNumDrawables()
can be used
@see removeDrawable
*/
void insertDrawable (Drawable* drawable,
const AffineTransform& transform = AffineTransform::identity,
int index = -1);
void insertDrawable (Drawable* drawable, int index = -1);
/** Adds a new sub-drawable to this one.
@@ -73,16 +69,12 @@ public:
pointer instead.
@param drawable the object to add - an internal copy will be made of this object
@param transform the transform to apply to this drawable when it's being
drawn
@param index where to insert it in the list of drawables. 0 is the back,
-1 is the front, or any value from 0 and getNumDrawables()
can be used
@see removeDrawable
*/
void insertDrawable (const Drawable& drawable,
const AffineTransform& transform = AffineTransform::identity,
int index = -1);
void insertDrawable (const Drawable& drawable, int index = -1);
/** Deletes one of the Drawable objects.
@@ -112,15 +104,6 @@ public:
*/
Drawable* getDrawable (int index) const throw() { return drawables [index]; }
/** Returns the transform that applies to one of the drawables that are contained in this one.
The pointer returned is managed by this object and will be deleted when no longer
needed, so be careful what you do with it.
@see getNumDrawables
*/
const AffineTransform* getDrawableTransform (int index) const throw() { return transforms [index]; }
/** Brings one of the Drawables to the front.
@param index the index of the drawable to move, between 0
@@ -129,6 +112,37 @@ public:
*/
void bringToFront (int index);
/** Sets the transform to be applied to this drawable, by defining the positions
where three anchor points should end up in the target rendering space.
@param targetPositionForOrigin the position that the local coordinate (0, 0) should be
mapped onto when rendering this object.
@param targetPositionForX1Y0 the position that the local coordinate (1, 0) should be
mapped onto when rendering this object.
@param targetPositionForX0Y1 the position that the local coordinate (0, 1) should be
mapped onto when rendering this object.
*/
void setTransform (const Point<float>& targetPositionForOrigin,
const Point<float>& targetPositionForX1Y0,
const Point<float>& targetPositionForX0Y1);
/** Returns the position to which the local coordinate (0, 0) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForOrigin() const throw() { return controlPoints[0]; }
/** Returns the position to which the local coordinate (1, 0) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForX1Y0() const throw() { return controlPoints[1]; }
/** Returns the position to which the local coordinate (0, 1) should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForX0Y1() const throw() { return controlPoints[2]; }
//==============================================================================
/** @internal */
@@ -138,18 +152,29 @@ public:
/** @internal */
bool hitTest (float x, float y) const;
/** @internal */
int getNumControlPoints() const;
/** @internal */
const Point<float> getControlPoint (int index) const;
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static DrawableComposite* createFromValueTree (const ValueTree& tree);
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }
//==============================================================================
juce_UseDebuggingNewOperator
private:
OwnedArray <Drawable> drawables;
OwnedArray <AffineTransform> transforms;
Point<float> controlPoints[3];
const Rectangle<float> getUntransformedBounds() const;
const AffineTransform getTransform() const;
DrawableComposite (const DrawableComposite&);
DrawableComposite& operator= (const DrawableComposite&);


+ 154
- 45
src/gui/graphics/drawables/juce_DrawableImage.cpp View File

@@ -30,8 +30,7 @@ BEGIN_JUCE_NAMESPACE
#include "juce_DrawableImage.h"
#include "../imaging/juce_ImageCache.h"
#include "../imaging/juce_ImageFileFormat.h"
#include "../../../io/streams/juce_MemoryOutputStream.h"
//==============================================================================
DrawableImage::DrawableImage()
@@ -40,6 +39,8 @@ DrawableImage::DrawableImage()
opacity (1.0f),
overlayColour (0x00000000)
{
controlPoints[1].setXY (1.0f, 0.0f);
controlPoints[2].setXY (0.0f, 1.0f);
}
DrawableImage::~DrawableImage()
@@ -61,6 +62,10 @@ void DrawableImage::setImage (const Image& imageToCopy)
clearImage();
image = new Image (imageToCopy);
canDeleteImage = true;
controlPoints[0].setXY (0.0f, 0.0f);
controlPoints[1].setXY ((float) image->getWidth(), 0.0f);
controlPoints[2].setXY (0.0f, (float) image->getHeight());
}
void DrawableImage::setImage (Image* imageToUse,
@@ -69,6 +74,13 @@ void DrawableImage::setImage (Image* imageToUse,
clearImage();
image = imageToUse;
canDeleteImage = releaseWhenNotNeeded;
if (image != 0)
{
controlPoints[0].setXY (0.0f, 0.0f);
controlPoints[1].setXY ((float) image->getWidth(), 0.0f);
controlPoints[2].setXY (0.0f, (float) image->getHeight());
}
}
void DrawableImage::setOpacity (const float newOpacity)
@@ -81,23 +93,45 @@ void DrawableImage::setOverlayColour (const Colour& newOverlayColour)
overlayColour = newOverlayColour;
}
void DrawableImage::setTransform (const Point<float>& imageTopLeftPosition,
const Point<float>& imageTopRightPosition,
const Point<float>& imageBottomLeftPosition)
{
controlPoints[0] = imageTopLeftPosition;
controlPoints[1] = imageTopRightPosition;
controlPoints[2] = imageBottomLeftPosition;
}
//==============================================================================
const AffineTransform DrawableImage::getTransform() const
{
if (image == 0)
return AffineTransform::identity;
const Point<float> tr (controlPoints[0] + (controlPoints[1] - controlPoints[0]) / image->getWidth());
const Point<float> bl (controlPoints[0] + (controlPoints[2] - controlPoints[0]) / image->getHeight());
return AffineTransform::fromTargetPoints (controlPoints[0].getX(), controlPoints[0].getY(),
tr.getX(), tr.getY(),
bl.getX(), bl.getY());
}
void DrawableImage::render (const Drawable::RenderingContext& context) const
{
if (image != 0)
{
const AffineTransform t (getTransform().followedBy (context.transform));
if (opacity > 0.0f && ! overlayColour.isOpaque())
{
context.g.setOpacity (context.opacity * opacity);
context.g.drawImageTransformed (image, image->getBounds(),
context.transform, false);
context.g.drawImageTransformed (image, image->getBounds(), t, false);
}
if (! overlayColour.isTransparent())
{
context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity));
context.g.drawImageTransformed (image, image->getBounds(),
context.transform, true);
context.g.drawImageTransformed (image, image->getBounds(), t, true);
}
}
}
@@ -107,17 +141,38 @@ const Rectangle<float> DrawableImage::getBounds() const
if (image == 0)
return Rectangle<float>();
return Rectangle<float> (0, 0, (float) image->getWidth(), (float) image->getHeight());
const Point<float> bottomRight (controlPoints[1] + (controlPoints[2] - controlPoints[0]));
float minX = bottomRight.getX();
float maxX = minX;
float minY = bottomRight.getY();
float maxY = minY;
for (int i = 0; i < 3; ++i)
{
minX = jmin (minX, controlPoints[i].getX());
maxX = jmax (maxX, controlPoints[i].getX());
minY = jmin (minY, controlPoints[i].getY());
maxY = jmax (maxY, controlPoints[i].getY());
}
return Rectangle<float> (minX, minY, maxX - minX, maxY - minY);
}
bool DrawableImage::hitTest (float x, float y) const
{
return image != 0
&& x >= 0.0f
&& y >= 0.0f
&& x < image->getWidth()
&& y < image->getHeight()
&& image->getPixelAt (roundToInt (x), roundToInt (y)).getAlpha() >= 127;
if (image == 0)
return false;
getTransform().inverted().transformPoint (x, y);
const int ix = roundToInt (x);
const int iy = roundToInt (y);
return ix >= 0
&& iy >= 0
&& ix < image->getWidth()
&& iy < image->getHeight()
&& image->getPixelAt (ix, iy).getAlpha() >= 127;
}
Drawable* DrawableImage::createCopy() const
@@ -127,6 +182,9 @@ Drawable* DrawableImage::createCopy() const
di->opacity = opacity;
di->overlayColour = overlayColour;
for (int i = 0; i < 4; ++i)
di->controlPoints[i] = controlPoints[i];
if (image != 0)
{
if ((! canDeleteImage) || ! ImageCache::isImageInCache (image))
@@ -144,59 +202,110 @@ Drawable* DrawableImage::createCopy() const
}
//==============================================================================
ValueTree DrawableImage::createValueTree() const
const Identifier DrawableImage::valueTreeType ("Image");
namespace DrawableImageHelpers
{
ValueTree v ("Image");
static const Identifier opacity ("opacity");
static const Identifier overlay ("overlay");
static const Identifier image ("image");
static const Identifier topLeft ("topLeft");
static const Identifier topRight ("topRight");
static const Identifier bottomLeft ("bottomLeft");
static void stringToPoint (const String& coords, Point<float>& point)
{
if (coords.isNotEmpty())
{
const int comma = coords.indexOfChar (',');
point.setXY (coords.substring (0, comma).getFloatValue(),
coords.substring (comma).getFloatValue());
}
}
if (getName().isNotEmpty())
v.setProperty ("id", getName(), 0);
static const var pointToString (const Point<float>& point)
{
return String (point.getX()) + ", " + String (point.getY());
}
}
if (opacity < 1.0f)
v.setProperty ("opacity", (double) opacity, 0);
const Rectangle<float> DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
{
jassert (tree.hasType (valueTreeType));
if (! overlayColour.isTransparent())
v.setProperty ("overlay", String::toHexString ((int) overlayColour.getARGB()), 0);
setName (tree [idProperty]);
if (image != 0)
const float newOpacity = tree.getProperty (DrawableImageHelpers::opacity, 1.0);
const Colour newOverlayColour (tree [DrawableImageHelpers::overlay].toString().getHexValue32());
Image* newImage = 0;
const String imageIdentifier (tree [DrawableImageHelpers::image].toString());
if (imageIdentifier.isNotEmpty())
{
MemoryOutputStream imageData;
PNGImageFormat pngFormat;
if (pngFormat.writeImageToStream (*image, imageData))
{
String base64 (MemoryBlock (imageData.getData(), imageData.getDataSize()).toBase64Encoding());
jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them!
if (imageProvider != 0)
newImage = imageProvider->getImageForIdentifier (imageIdentifier);
}
Point<float> newControlPoint[3];
DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::topLeft].toString(), newControlPoint[0]);
DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::topRight].toString(), newControlPoint[1]);
DrawableImageHelpers::stringToPoint (tree [DrawableImageHelpers::bottomLeft].toString(), newControlPoint[2]);
for (int i = (base64.length() & ~127); i >= 0; i -= 128)
base64 = base64.substring (0, i) + "\n" + base64.substring (i);
if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage
|| controlPoints[0] != newControlPoint[0]
|| controlPoints[1] != newControlPoint[1]
|| controlPoints[2] != newControlPoint[2])
{
opacity = newOpacity;
overlayColour = newOverlayColour;
controlPoints[0] = newControlPoint[0];
controlPoints[1] = newControlPoint[1];
controlPoints[2] = newControlPoint[2];
v.setProperty ("data", base64, 0);
if (image != newImage)
{
ImageCache::release (image);
image = newImage;
}
return getBounds();
}
return v;
ImageCache::release (newImage);
return Rectangle<float>();
}
DrawableImage* DrawableImage::createFromValueTree (const ValueTree& tree)
const ValueTree DrawableImage::createValueTree (ImageProvider* imageProvider) const
{
if (! tree.hasType ("Image"))
return 0;
ValueTree v (valueTreeType);
if (getName().isNotEmpty())
v.setProperty (idProperty, getName(), 0);
if (opacity < 1.0f)
v.setProperty (DrawableImageHelpers::opacity, (double) opacity, 0);
DrawableImage* di = new DrawableImage();
if (! overlayColour.isTransparent())
v.setProperty (DrawableImageHelpers::overlay, String::toHexString ((int) overlayColour.getARGB()), 0);
di->setName (tree ["id"]);
di->opacity = tree.hasProperty ("opacity") ? (float) tree ["opacity"] : 1.0f;
di->overlayColour = Colour (tree ["overlay"].toString().getHexValue32());
if (! getTransform().isIdentity())
{
v.setProperty (DrawableImageHelpers::topLeft, DrawableImageHelpers::pointToString (controlPoints[0]), 0);
v.setProperty (DrawableImageHelpers::topRight, DrawableImageHelpers::pointToString (controlPoints[1]), 0);
v.setProperty (DrawableImageHelpers::bottomLeft, DrawableImageHelpers::pointToString (controlPoints[2]), 0);
}
MemoryBlock imageData;
if (imageData.fromBase64Encoding (tree ["data"]))
if (image != 0)
{
Image* const im = ImageFileFormat::loadFrom (imageData.getData(), (int) imageData.getSize());
if (im == 0)
return false;
jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them!
di->setImage (im, true);
if (imageProvider != 0)
v.setProperty (DrawableImageHelpers::image, imageProvider->getIdentifierForImage (image), 0);
}
return di;
return v;
}


+ 41
- 7
src/gui/graphics/drawables/juce_DrawableImage.h View File

@@ -55,9 +55,6 @@ public:
/** Sets the image that this drawable will render.
An internal copy of this will not be made, so the caller mustn't delete
the image while it's still being used by this object.
A good way to use this is with the ImageCache - if you create an image
with ImageCache and pass it in here with releaseWhenNotNeeded = true, then
it'll be released neatly with its reference count being decreased.
@@ -68,8 +65,7 @@ public:
needs it - unless the image was created by the ImageCache,
in which case it will be released with ImageCache::release().
*/
void setImage (Image* imageToUse,
bool releaseWhenNotNeeded);
void setImage (Image* imageToUse, bool releaseWhenNotNeeded);
/** Returns the current image. */
Image* getImage() const throw() { return image; }
@@ -97,6 +93,37 @@ public:
/** Returns the overlay colour. */
const Colour& getOverlayColour() const throw() { return overlayColour; }
/** Sets the transform to be applied to this image, by defining the positions
where three anchor points should end up in the target rendering space.
@param imageTopLeftPosition the position that the image's top-left corner should be mapped to
in the target coordinate space.
@param imageTopRightPosition the position that the image's top-right corner should be mapped to
in the target coordinate space.
@param imageBottomLeftPosition the position that the image's bottom-left corner should be mapped to
in the target coordinate space.
*/
void setTransform (const Point<float>& imageTopLeftPosition,
const Point<float>& imageTopRightPosition,
const Point<float>& imageBottomLeftPosition);
/** Returns the position to which the image's top-left corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForTopLeft() const throw() { return controlPoints[0]; }
/** Returns the position to which the image's top-right corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForTopRight() const throw() { return controlPoints[1]; }
/** Returns the position to which the image's bottom-left corner should be remapped in the target
coordinate space when rendering this object.
@see setTransform
*/
const Point<float>& getTargetPositionForBottomLeft() const throw() { return controlPoints[2]; }
//==============================================================================
/** @internal */
@@ -108,9 +135,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
static DrawableImage* createFromValueTree (const ValueTree& tree);
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }
//==============================================================================
juce_UseDebuggingNewOperator
@@ -120,6 +151,9 @@ private:
bool canDeleteImage;
float opacity;
Colour overlayColour;
Point<float> controlPoints[3];
const AffineTransform getTransform() const;
DrawableImage (const DrawableImage&);
DrawableImage& operator= (const DrawableImage&);


+ 130
- 90
src/gui/graphics/drawables/juce_DrawablePath.cpp View File

@@ -129,118 +129,158 @@ Drawable* DrawablePath::createCopy() const
}
//==============================================================================
static const FillType readFillTypeFromTree (const ValueTree& v)
{
const String type (v["type"].toString());
const Identifier DrawablePath::valueTreeType ("Path");
if (type.equalsIgnoreCase ("solid"))
namespace DrawablePathHelpers
{
static const Identifier type ("type");
static const Identifier solid ("solid");
static const Identifier colour ("colour");
static const Identifier gradient ("gradient");
static const Identifier x1 ("x1");
static const Identifier x2 ("x2");
static const Identifier y1 ("y1");
static const Identifier y2 ("y2");
static const Identifier radial ("radial");
static const Identifier colours ("colours");
static const Identifier fill ("fill");
static const Identifier stroke ("stroke");
static const Identifier jointStyle ("jointStyle");
static const Identifier capStyle ("capStyle");
static const Identifier strokeWidth ("strokeWidth");
static const Identifier path ("path");
static bool updateFillType (const ValueTree& v, FillType& fillType)
{
const String colour (v ["colour"].toString());
return Colour (colour.isEmpty() ? (uint32) 0xff000000
: (uint32) colour.getHexValue32());
const String type (v[type].toString());
if (type.equalsIgnoreCase (solid))
{
const String colourString (v [colour].toString());
const Colour newColour (colourString.isEmpty() ? (uint32) 0xff000000
: (uint32) colourString.getHexValue32());
if (fillType.isColour() && fillType.colour == newColour)
return false;
fillType.setColour (newColour);
return true;
}
else if (type.equalsIgnoreCase (gradient))
{
ColourGradient g;
g.point1.setXY (v[x1], v[y1]);
g.point2.setXY (v[x2], v[y2]);
g.isRadial = v[radial];
StringArray colourSteps;
colourSteps.addTokens (v[colours].toString(), false);
for (int i = 0; i < colourSteps.size() / 2; ++i)
g.addColour (colourSteps[i * 2].getDoubleValue(),
Colour ((uint32) colourSteps[i * 2 + 1].getHexValue32()));
if (fillType.isGradient() && *fillType.gradient == g)
return false;
fillType.setGradient (g);
return true;
}
jassertfalse;
return false;
}
else if (type.equalsIgnoreCase ("gradient"))
{
ColourGradient g;
g.point1.setXY (v["x1"], v["y1"]);
g.point2.setXY (v["x2"], v["y2"]);
g.isRadial = v["radial"];
StringArray colours;
colours.addTokens (v["colours"].toString(), false);
for (int i = 0; i < colours.size() / 2; ++i)
g.addColour (colours[i * 2].getDoubleValue(),
Colour ((uint32) colours[i * 2 + 1].getHexValue32()));
return g;
static ValueTree createFillType (const Identifier& tagName, const FillType& fillType)
{
ValueTree v (tagName);
if (fillType.isColour())
{
v.setProperty (type, "solid", 0);
v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), 0);
}
else if (fillType.isGradient())
{
v.setProperty (type, "gradient", 0);
v.setProperty (x1, fillType.gradient->point1.getX(), 0);
v.setProperty (y1, fillType.gradient->point1.getY(), 0);
v.setProperty (x2, fillType.gradient->point2.getX(), 0);
v.setProperty (y2, fillType.gradient->point2.getY(), 0);
v.setProperty (radial, fillType.gradient->isRadial, 0);
String s;
for (int i = 0; i < fillType.gradient->getNumColours(); ++i)
s << " " << fillType.gradient->getColourPosition (i)
<< " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB());
v.setProperty (colours, s.trimStart(), 0);
}
else
{
jassertfalse; //xxx
}
return v;
}
jassertfalse;
return FillType();
}
static ValueTree createTreeForFillType (const String& tagName, const FillType& fillType)
const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
{
ValueTree v (tagName);
jassert (tree.hasType (valueTreeType));
if (fillType.isColour())
{
v.setProperty ("type", "solid", 0);
v.setProperty ("colour", String::toHexString ((int) fillType.colour.getARGB()), 0);
}
else if (fillType.isGradient())
{
v.setProperty ("type", "gradient", 0);
v.setProperty ("x1", fillType.gradient->point1.getX(), 0);
v.setProperty ("y1", fillType.gradient->point1.getY(), 0);
v.setProperty ("x2", fillType.gradient->point2.getX(), 0);
v.setProperty ("y2", fillType.gradient->point2.getY(), 0);
v.setProperty ("radial", fillType.gradient->isRadial, 0);
String s;
for (int i = 0; i < fillType.gradient->getNumColours(); ++i)
s << " " << fillType.gradient->getColourPosition (i)
<< " " << String::toHexString ((int) fillType.gradient->getColour(i).getARGB());
v.setProperty ("colours", s.trimStart(), 0);
}
else
{
jassertfalse; //xxx
}
Rectangle<float> damageRect;
setName (tree [idProperty]);
return v;
}
bool needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::fill), mainFill);
needsRedraw = DrawablePathHelpers::updateFillType (tree.getChildWithName (DrawablePathHelpers::stroke), strokeFill) || needsRedraw;
ValueTree DrawablePath::createValueTree() const
{
ValueTree v ("Path");
const String jointStyle (tree [DrawablePathHelpers::jointStyle].toString());
const String endStyle (tree [DrawablePathHelpers::capStyle].toString());
v.addChild (createTreeForFillType ("fill", mainFill), -1, 0);
v.addChild (createTreeForFillType ("stroke", strokeFill), -1, 0);
PathStrokeType newStroke (tree [DrawablePathHelpers::strokeWidth],
jointStyle == "curved" ? PathStrokeType::curved
: (jointStyle == "bevel" ? PathStrokeType::beveled
: PathStrokeType::mitered),
endStyle == "square" ? PathStrokeType::square
: (endStyle == "round" ? PathStrokeType::rounded
: PathStrokeType::butt));
if (getName().isNotEmpty())
v.setProperty ("id", getName(), 0);
Path newPath;
newPath.restoreFromString (tree [DrawablePathHelpers::path]);
v.setProperty ("strokeWidth", (double) strokeType.getStrokeThickness(), 0);
v.setProperty ("jointStyle", strokeType.getJointStyle() == PathStrokeType::mitered
? "miter" : (strokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), 0);
v.setProperty ("capStyle", strokeType.getEndStyle() == PathStrokeType::butt
? "butt" : (strokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), 0);
v.setProperty ("path", path.toString(), 0);
if (strokeType != newStroke || path != newPath)
{
damageRect = getBounds();
path.swapWithPath (newPath);
strokeType = newStroke;
needsRedraw = true;
}
return v;
if (needsRedraw)
damageRect = damageRect.getUnion (getBounds());
return damageRect;
}
DrawablePath* DrawablePath::createFromValueTree (const ValueTree& tree)
const ValueTree DrawablePath::createValueTree (ImageProvider* imageProvider) const
{
if (! tree.hasType ("Path"))
return 0;
DrawablePath* p = new DrawablePath();
ValueTree v (valueTreeType);
p->setName (tree ["id"]);
p->mainFill = readFillTypeFromTree (tree.getChildWithName ("fill"));
p->strokeFill = readFillTypeFromTree (tree.getChildWithName ("stroke"));
v.addChild (DrawablePathHelpers::createFillType (DrawablePathHelpers::fill, mainFill), -1, 0);
v.addChild (DrawablePathHelpers::createFillType (DrawablePathHelpers::stroke, strokeFill), -1, 0);
const String jointStyle (tree ["jointStyle"].toString());
const String endStyle (tree ["capStyle"].toString());
p->strokeType
= PathStrokeType (tree ["strokeWidth"],
jointStyle.equalsIgnoreCase ("curved") ? PathStrokeType::curved
: (jointStyle.equalsIgnoreCase ("bevel") ? PathStrokeType::beveled
: PathStrokeType::mitered),
endStyle.equalsIgnoreCase ("square") ? PathStrokeType::square
: (endStyle.equalsIgnoreCase ("round") ? PathStrokeType::rounded
: PathStrokeType::butt));
if (getName().isNotEmpty())
v.setProperty (idProperty, getName(), 0);
p->path.clear();
p->path.restoreFromString (tree ["path"]);
p->updateOutline();
v.setProperty (DrawablePathHelpers::strokeWidth, (double) strokeType.getStrokeThickness(), 0);
v.setProperty (DrawablePathHelpers::jointStyle, strokeType.getJointStyle() == PathStrokeType::mitered
? "miter" : (strokeType.getJointStyle() == PathStrokeType::curved ? "curved" : "bevel"), 0);
v.setProperty (DrawablePathHelpers::capStyle, strokeType.getEndStyle() == PathStrokeType::butt
? "butt" : (strokeType.getEndStyle() == PathStrokeType::square ? "square" : "round"), 0);
v.setProperty (DrawablePathHelpers::path, path.toString(), 0);
return p;
return v;
}


+ 6
- 2
src/gui/graphics/drawables/juce_DrawablePath.h View File

@@ -107,9 +107,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
static DrawablePath* createFromValueTree (const ValueTree& tree);
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }
//==============================================================================
juce_UseDebuggingNewOperator


+ 12
- 14
src/gui/graphics/drawables/juce_DrawableText.cpp View File

@@ -85,29 +85,27 @@ Drawable* DrawableText::createCopy() const
}
//==============================================================================
ValueTree DrawableText::createValueTree() const
{
ValueTree v ("Text");
const Identifier DrawableText::valueTreeType ("Text");
if (getName().isNotEmpty())
v.setProperty ("id", getName(), 0);
const Rectangle<float> DrawableText::refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider)
{
jassert (tree.hasType (valueTreeType));
setName (tree [idProperty]);
jassertfalse; // xxx not finished!
return v;
return Rectangle<float>();
}
DrawableText* DrawableText::createFromValueTree (const ValueTree& tree)
const ValueTree DrawableText::createValueTree (ImageProvider* imageProvider) const
{
if (! tree.hasType ("Text"))
return 0;
ValueTree v (valueTreeType);
DrawableText* dt = new DrawableText();
dt->setName (tree ["id"]);
if (getName().isNotEmpty())
v.setProperty (idProperty, getName(), 0);
jassertfalse; // xxx not finished!
return dt;
return v;
}


+ 6
- 2
src/gui/graphics/drawables/juce_DrawableText.h View File

@@ -78,9 +78,13 @@ public:
/** @internal */
Drawable* createCopy() const;
/** @internal */
ValueTree createValueTree() const;
const Rectangle<float> refreshFromValueTree (const ValueTree& tree, ImageProvider* imageProvider);
/** @internal */
static DrawableText* createFromValueTree (const ValueTree& tree);
const ValueTree createValueTree (ImageProvider* imageProvider) const;
/** @internal */
static const Identifier valueTreeType;
/** @internal */
const Identifier getValueTreeType() const { return valueTreeType; }
//==============================================================================
juce_UseDebuggingNewOperator


+ 1
- 12
src/gui/graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -615,24 +615,13 @@ const Rectangle<float> GlyphArrangement::getBoundingBox (int startIndex, int num
num = glyphs.size() - startIndex;
Rectangle<float> result;
bool isFirst = true;
while (--num >= 0)
{
const PositionedGlyph* const pg = glyphs.getUnchecked (startIndex++);
if (includeWhitespace || ! pg->isWhitespace())
{
if (isFirst)
{
isFirst = false;
result = pg->getBounds();
}
else
{
result = result.getUnion (pg->getBounds());
}
}
result = result.getUnion (pg->getBounds());
}
return result;


+ 8
- 0
src/gui/graphics/geometry/juce_AffineTransform.cpp View File

@@ -233,6 +233,14 @@ bool AffineTransform::isSingularity() const throw()
return (mat00 * mat11 - mat10 * mat01) == 0.0;
}
const AffineTransform AffineTransform::fromTargetPoints (const float x00, const float y00,
const float x10, const float y10,
const float x01, const float y01) throw()
{
return AffineTransform (x10 - x00, x01 - x00, x00,
y10 - y00, y01 - y00, y00);
}
bool AffineTransform::isOnlyTranslation() const throw()
{
return (mat01 == 0)


+ 10
- 0
src/gui/graphics/geometry/juce_AffineTransform.h View File

@@ -146,6 +146,16 @@ public:
*/
const AffineTransform inverted() const throw();
/** Returns the transform that will map three known points onto three coordinates
that are supplied.
This returns the transform that will transform (0, 0) into (x00, y00),
(1, 0) to (x10, y10), and (0, 1) to (x01, y01).
*/
static const AffineTransform fromTargetPoints (float x00, float y00,
float x10, float y10,
float x01, float y01) throw();
//==============================================================================
/** Returns the result of concatenating another transformation after this one. */
const AffineTransform followedBy (const AffineTransform& other) const throw();


+ 18
- 2
src/gui/graphics/geometry/juce_Path.cpp View File

@@ -141,6 +141,23 @@ Path& Path::operator= (const Path& other)
return *this;
}
bool Path::operator== (const Path& other) const throw()
{
return ! operator!= (other);
}
bool Path::operator!= (const Path& other) const throw()
{
if (numElements != other.numElements || useNonZeroWinding != other.useNonZeroWinding)
return true;
for (int i = 0; i < numElements; ++i)
if (data.elements[i] != other.data.elements[i])
return true;
return false;
}
void Path::clear() throw()
{
numElements = 0;
@@ -150,7 +167,7 @@ void Path::clear() throw()
pathXMax = 0;
}
void Path::swapWithPath (Path& other)
void Path::swapWithPath (Path& other) throw()
{
data.swapWith (other.data);
swapVariables <size_t> (numElements, other.numElements);
@@ -204,7 +221,6 @@ const Rectangle<float> Path::getBounds() const throw()
pathYMax - pathYMin);
}
const Rectangle<float> Path::getBoundsTransformed (const AffineTransform& transform) const throw()
{
return getBounds().transformed (transform);


+ 4
- 1
src/gui/graphics/geometry/juce_Path.h View File

@@ -84,6 +84,9 @@ public:
/** Copies this path from another one. */
Path& operator= (const Path& other);
bool operator== (const Path& other) const throw();
bool operator!= (const Path& other) const throw();
//==============================================================================
/** Returns true if the path doesn't contain any lines or curves. */
bool isEmpty() const throw();
@@ -472,7 +475,7 @@ public:
The internal data of the two paths is swapped over, so this is much faster than
copying it to a temp variable and back.
*/
void swapWithPath (Path& other);
void swapWithPath (Path& other) throw();
//==============================================================================
/** Applies a 2D transform to all the vertices in the path.


+ 3
- 0
src/gui/graphics/geometry/juce_Point.h View File

@@ -138,6 +138,9 @@ public:
/** Returns the position of this point, if it is transformed by a given AffineTransform. */
const Point transformedBy (const AffineTransform& transform) const throw() { ValueType x2 (x), y2 (y); transform.transformPoint (x2, y2); return Point (x2, y2); }
/** Casts this point to a Point<float> object. */
const Point<float> toFloat() const throw() { return Point<float> (static_cast <float> (x), static_cast<float> (y)); }
/** Returns the point as a string in the form "x, y". */
const String toString() const { return String (x) + ", " + String (y); }


+ 7
- 2
src/gui/graphics/geometry/juce_Rectangle.h View File

@@ -395,11 +395,16 @@ public:
return false;
}
/** Returns the smallest rectangle that contains both this one and the one
passed-in.
/** Returns the smallest rectangle that contains both this one and the one passed-in.
If either this or the other rectangle are empty, they will not be counted as
part of the resulting region.
*/
const Rectangle getUnion (const Rectangle& other) const throw()
{
if (other.isEmpty()) return *this;
if (isEmpty()) return other;
const ValueType newX = jmin (x, other.x);
const ValueType newY = jmin (y, other.y);


+ 11
- 12
src/native/linux/juce_linux_Messaging.cpp View File

@@ -127,18 +127,6 @@ private:
}
};
//==============================================================================
struct MessageThreadFuncCall
{
enum { uniqueID = 0x73774623 };
MessageCallbackFunction* func;
void* parameter;
void* result;
CriticalSection lock;
WaitableEvent event;
};
//==============================================================================
static InternalMessageQueue* juce_internalMessageQueue = 0;
@@ -327,6 +315,17 @@ void MessageManager::broadcastMessage (const String& value) throw()
/* TODO */
}
struct MessageThreadFuncCall
{
enum { uniqueID = 0x73774623 };
MessageCallbackFunction* func;
void* parameter;
void* result;
CriticalSection lock;
WaitableEvent event;
};
void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* func,
void* parameter)
{


+ 19
- 76
src/native/mac/juce_iphone_MessageManager.mm View File

@@ -36,81 +36,24 @@ struct CallbackMessagePayload
};
END_JUCE_NAMESPACE
using namespace JUCE_NAMESPACE;
@interface JuceAppDelegate : NSObject <UIApplicationDelegate>
//==============================================================================
@interface JuceCustomMessageHandler : NSObject
{
}
- (JuceAppDelegate*) init;
- (void) dealloc;
- (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url;
- (void) applicationDidBecomeActive: (NSNotification*) aNotification;
- (void) applicationDidResignActive: (NSNotification*) aNotification;
- (void) applicationWillUnhide: (NSNotification*) aNotification;
- (void) customEvent: (id) data;
- (void) performCallback: (id) info;
@end
@implementation JuceAppDelegate
- (JuceAppDelegate*) init
{
[super init];
[[UIApplication sharedApplication] setDelegate: self];
return self;
}
- (void) dealloc
{
[[UIApplication sharedApplication] setDelegate: nil];
[super dealloc];
}
- (BOOL) application: (UIApplication*) application handleOpenURL: (NSURL*) url
{
if (JUCEApplication::getInstance() != 0)
{
JUCEApplication::getInstance()->anotherInstanceStarted (nsStringToJuce ([url absoluteString]));
return YES;
}
return NO;
}
- (void) applicationDidBecomeActive: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) applicationDidResignActive: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) applicationWillUnhide: (NSNotification*) aNotification
{
juce_HandleProcessFocusChange();
}
- (void) customEvent: (id) n
{
NSData* data = (NSData*) n;
void* message = 0;
[data getBytes: &message length: sizeof (message)];
[data release];
@end
if (message != 0)
MessageManager::getInstance()->deliverMessage (message);
}
//==============================================================================
@implementation JuceCustomMessageHandler
- (void) performCallback: (id) info
{
if ([info isKindOfClass: [NSData class]])
{
CallbackMessagePayload* pl = (CallbackMessagePayload*) [((NSData*) info) bytes];
JUCE_NAMESPACE::CallbackMessagePayload* pl = (JUCE_NAMESPACE::CallbackMessagePayload*) [((NSData*) info) bytes];
if (pl != 0)
{
@@ -128,8 +71,7 @@ using namespace JUCE_NAMESPACE;
BEGIN_JUCE_NAMESPACE
static JuceAppDelegate* juceAppDelegate = 0;
//==============================================================================
void MessageManager::runDispatchLoop()
{
jassert (isThisTheMessageThread()); // must only be called by the message thread
@@ -167,6 +109,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
static CFRunLoopRef runLoop = 0;
static CFRunLoopSourceRef runLoopSource = 0;
static Array <void*, CriticalSection>* pendingMessages = 0;
static JuceCustomMessageHandler* juceCustomMessageHandler = 0;
static void runLoopSourceCallback (void*)
{
@@ -202,8 +145,8 @@ void MessageManager::doPlatformSpecificInitialisation()
runLoopSource = CFRunLoopSourceCreate (kCFAllocatorDefault, 1, &sourceContext);
CFRunLoopAddSource (runLoop, runLoopSource, kCFRunLoopCommonModes);
if (juceAppDelegate == 0)
juceAppDelegate = [[JuceAppDelegate alloc] init];
if (juceCustomMessageHandler == 0)
juceCustomMessageHandler = [[JuceCustomMessageHandler alloc] init];
}
void MessageManager::doPlatformSpecificShutdown()
@@ -220,11 +163,11 @@ void MessageManager::doPlatformSpecificShutdown()
deleteAndZero (pendingMessages);
}
if (juceAppDelegate != 0)
if (juceCustomMessageHandler != 0)
{
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate];
[juceAppDelegate release];
juceAppDelegate = 0;
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceCustomMessageHandler];
[juceCustomMessageHandler release];
juceCustomMessageHandler = 0;
}
}
@@ -266,11 +209,11 @@ void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* call
cmp.result = 0;
cmp.hasBeenExecuted = false;
[juceAppDelegate performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy: &cmp
length: sizeof (cmp)
freeWhenDone: NO]
waitUntilDone: YES];
[juceCustomMessageHandler performSelectorOnMainThread: @selector (performCallback:)
withObject: [NSData dataWithBytesNoCopy: &cmp
length: sizeof (cmp)
freeWhenDone: NO]
waitUntilDone: YES];
return cmp.result;
}


Loading…
Cancel
Save