@@ -100,11 +100,10 @@ public: | |||
{ | |||
RectangleCoordinates r (boundsValue.toString()); | |||
Coordinate& coord = getCoord (r); | |||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createComponentMarkerResolver (compState)); | |||
if (button == proportionButton) | |||
{ | |||
coord.toggleProportionality (*markers); | |||
coord.toggleProportionality (document); | |||
boundsValue = r.toString(); | |||
} | |||
else if (button == anchorButton1) | |||
@@ -113,7 +112,7 @@ public: | |||
if (marker.isNotEmpty()) | |||
{ | |||
coord.changeAnchor1 (marker, *markers); | |||
coord.changeAnchor1 (marker, document); | |||
boundsValue = r.toString(); | |||
} | |||
} | |||
@@ -123,7 +122,7 @@ public: | |||
if (marker.isNotEmpty()) | |||
{ | |||
coord.changeAnchor2 (marker, *markers); | |||
coord.changeAnchor2 (marker, document); | |||
boundsValue = r.toString(); | |||
} | |||
} | |||
@@ -212,18 +211,18 @@ public: | |||
return r.left; | |||
} | |||
const String pickMarker (Component* button, const String& currentMarker) | |||
const String pickMarker (TextButton* button, const String& currentMarker) | |||
{ | |||
const StringArray markers (document.getComponentMarkers (type == left || type == right)); | |||
RectangleCoordinates b (boundsValue.toString()); | |||
PopupMenu m; | |||
for (int i = 0; i < markers.size(); ++i) | |||
m.addItem (i + 1, markers[i], true, currentMarker == markers[i]); | |||
document.getComponentMarkerMenuItems (compState, getTypeName(), | |||
getCoord (b), m, button == anchorButton1); | |||
const int r = m.showAt (button); | |||
if (r > 0) | |||
return markers [r - 1]; | |||
return document.getChosenMarkerMenuItem (compState, getCoord (b), r); | |||
return String::empty; | |||
} | |||
@@ -242,6 +241,20 @@ private: | |||
{ | |||
return getCoordForType (type, r); | |||
} | |||
const String getTypeName() const | |||
{ | |||
switch (type) | |||
{ | |||
case left: return "left"; | |||
case right: return "right"; | |||
case top: return "top"; | |||
case bottom: return "bottom"; | |||
default: jassertfalse; break; | |||
} | |||
return String::empty; | |||
} | |||
}; | |||
@@ -265,8 +278,7 @@ Value ComponentTypeHandler::getValue (const var::identifier& name, ValueTree& st | |||
void ComponentTypeHandler::updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state) | |||
{ | |||
RectangleCoordinates pos (state [ComponentDocument::compBoundsProperty].toString()); | |||
ScopedPointer<Coordinate::MarkerResolver> markers (document.createComponentMarkerResolver (state)); | |||
comp->setBounds (pos.resolve (*markers)); | |||
comp->setBounds (pos.resolve (document)); | |||
comp->setName (state [ComponentDocument::compNameProperty]); | |||
} | |||
@@ -279,11 +291,54 @@ void ComponentTypeHandler::initialiseNewItem (ComponentDocument& document, Value | |||
const Rectangle<int> bounds (getDefaultSize().withPosition (Point<int> (Random::getSystemRandom().nextInt (100) + 100, | |||
Random::getSystemRandom().nextInt (100) + 100))); | |||
state.setProperty (ComponentDocument::compBoundsProperty, RectangleCoordinates (bounds).toString(), 0); | |||
state.setProperty (ComponentDocument::compBoundsProperty, RectangleCoordinates (bounds, state [ComponentDocument::memberNameProperty]).toString(), 0); | |||
} | |||
//============================================================================== | |||
class CompMemberNameValueSource : public Value::ValueSource, | |||
public Value::Listener | |||
{ | |||
public: | |||
CompMemberNameValueSource (ComponentDocument& document_, const ValueTree& state_) | |||
: sourceValue (state_.getPropertyAsValue (ComponentDocument::memberNameProperty, document_.getUndoManager())), | |||
document (document_), | |||
state (state_) | |||
{ | |||
sourceValue.addListener (this); | |||
} | |||
~CompMemberNameValueSource() {} | |||
void valueChanged (Value&) { sendChangeMessage (true); } | |||
const var getValue() const { return sourceValue.toString(); } | |||
void setValue (const var& newValue) | |||
{ | |||
String newVal (newValue.toString()); | |||
//xxx check for uniqueness + rename any coords that use the name.. | |||
newVal = makeValidCppIdentifier (newVal, false, true, false); | |||
if (sourceValue != newVal) | |||
sourceValue = newVal; | |||
} | |||
private: | |||
Value sourceValue; | |||
ComponentDocument& document; | |||
ValueTree state; | |||
CompMemberNameValueSource (const CompMemberNameValueSource&); | |||
const CompMemberNameValueSource& operator= (const CompMemberNameValueSource&); | |||
}; | |||
void ComponentTypeHandler::createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props) | |||
{ | |||
props.add (new TextPropertyComponent (Value (new CompMemberNameValueSource (document, state)), "Member Name", 256, false)); | |||
props.add (new ComponentBoundsEditor (document, "Left", ComponentBoundsEditor::left, state, getValue (ComponentDocument::compBoundsProperty, state, document))); | |||
props.add (new ComponentBoundsEditor (document, "Right", ComponentBoundsEditor::right, state, getValue (ComponentDocument::compBoundsProperty, state, document))); | |||
props.add (new ComponentBoundsEditor (document, "Top", ComponentBoundsEditor::top, state, getValue (ComponentDocument::compBoundsProperty, state, document))); | |||
@@ -54,6 +54,10 @@ public: | |||
//============================================================================== | |||
protected: | |||
const String name, xmlTag, memberNameRoot; | |||
private: | |||
ComponentTypeHandler (const ComponentTypeHandler&); | |||
ComponentTypeHandler& operator= (const ComponentTypeHandler&); | |||
}; | |||
@@ -54,9 +54,6 @@ ComponentDocument::ComponentDocument (Project* project_, const File& cppFile_) | |||
reload(); | |||
checkRootObject(); | |||
markersX = new MarkerList (*this, true); | |||
markersY = new MarkerList (*this, false); | |||
root.addListener (this); | |||
} | |||
@@ -189,6 +186,8 @@ bool ComponentDocument::reload() | |||
if (newTree.isValid()) | |||
{ | |||
root = newTree; | |||
markersX = 0; | |||
markersY = 0; | |||
checkRootObject(); | |||
undoManager.clearUndoHistory(); | |||
changedSinceSaved = false; | |||
@@ -218,6 +217,12 @@ void ComponentDocument::checkRootObject() | |||
createSubTreeIfNotThere (markersGroupXTag); | |||
createSubTreeIfNotThere (markersGroupYTag); | |||
if (markersX == 0) | |||
markersX = new MarkerList (*this, true); | |||
if (markersY == 0) | |||
markersY = new MarkerList (*this, false); | |||
if (getClassName().toString().isEmpty()) | |||
getClassName() = "NewComponent"; | |||
@@ -305,34 +310,38 @@ Component* ComponentDocument::createComponent (int index) | |||
} | |||
//============================================================================== | |||
class ComponentMarkerResolver : public Coordinate::MarkerResolver | |||
const Coordinate ComponentDocument::findMarker (const String& name, bool isHorizontal) const | |||
{ | |||
public: | |||
ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, int parentWidth_, int parentHeight_) | |||
: owner (doc), state (state_), | |||
parentWidth (parentWidth_), | |||
parentHeight (parentHeight_) | |||
{} | |||
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) getCanvasWidth().getValue(), isHorizontal); | |||
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) getCanvasHeight().getValue(), isHorizontal); | |||
~ComponentMarkerResolver() {} | |||
const Coordinate findMarker (const String& name, bool isHorizontal) | |||
if (name.containsChar ('.')) | |||
{ | |||
if (name == "left") return RectangleCoordinates (state [ComponentDocument::compBoundsProperty]).left; | |||
else if (name == "right") return RectangleCoordinates (state [ComponentDocument::compBoundsProperty]).right; | |||
else if (name == "top") return RectangleCoordinates (state [ComponentDocument::compBoundsProperty]).top; | |||
else if (name == "bottom") return RectangleCoordinates (state [ComponentDocument::compBoundsProperty]).bottom; | |||
else if (name == Coordinate::parentRightMarkerName) return Coordinate (parentWidth, isHorizontal); | |||
else if (name == Coordinate::parentBottomMarkerName) return Coordinate (parentHeight, isHorizontal); | |||
return Coordinate (isHorizontal); | |||
const String compName (name.upToFirstOccurrenceOf (".", false, false).trim()); | |||
const String edge (name.fromFirstOccurrenceOf (".", false, false).trim()); | |||
if (compName.isNotEmpty() && edge.isNotEmpty()) | |||
{ | |||
const ValueTree comp (getComponentWithMemberName (compName)); | |||
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; | |||
} | |||
} | |||
} | |||
private: | |||
ComponentDocument& owner; | |||
ValueTree state; | |||
int parentWidth, parentHeight; | |||
}; | |||
const ValueTree marker (getMarkerList (isHorizontal).getMarkerNamed (name)); | |||
if (marker.isValid()) | |||
return getMarkerList (isHorizontal).getCoordinate (marker); | |||
return Coordinate (isHorizontal); | |||
} | |||
const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& state) const | |||
{ | |||
@@ -350,31 +359,97 @@ bool ComponentDocument::setCoordsFor (ValueTree& state, const RectangleCoordinat | |||
return true; | |||
} | |||
Coordinate::MarkerResolver* ComponentDocument::createComponentMarkerResolver (const ValueTree& state) | |||
void ComponentDocument::addMarkerMenuItem (int i, Coordinate& coord, const String& name, PopupMenu& menu, bool isAnchor1, | |||
const ValueTree& componentState, const String& coordName) | |||
{ | |||
return new ComponentMarkerResolver (*this, state, getCanvasWidth().getValue(), getCanvasHeight().getValue()); | |||
const String componentName (componentState [memberNameProperty].toString()); | |||
Coordinate requestedCoord (findMarker (name, coord.isHorizontal())); | |||
const String fullCoordName (componentName + "." + coordName); | |||
menu.addItem (i, name, | |||
! (name == fullCoordName || requestedCoord.referencesIndirectly (fullCoordName, *this)), | |||
name == (isAnchor1 ? coord.getAnchor1() : coord.getAnchor2())); | |||
} | |||
const StringArray ComponentDocument::getComponentMarkers (bool horizontal) const | |||
void ComponentDocument::getComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName, | |||
Coordinate& coord, PopupMenu& menu, bool isAnchor1) | |||
{ | |||
StringArray s; | |||
const String componentName (componentState [memberNameProperty].toString()); | |||
if (horizontal) | |||
if (coord.isHorizontal()) | |||
{ | |||
s.add (Coordinate::parentLeftMarkerName); | |||
s.add (Coordinate::parentRightMarkerName); | |||
s.add ("left"); | |||
s.add ("right"); | |||
addMarkerMenuItem (1, coord, Coordinate::parentLeftMarkerName, menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (2, coord, Coordinate::parentRightMarkerName, menu, isAnchor1, componentState, coordName); | |||
menu.addSeparator(); | |||
addMarkerMenuItem (3, coord, componentName + ".left", menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (4, coord, componentName + ".right", menu, isAnchor1, componentState, coordName); | |||
} | |||
else | |||
{ | |||
s.add (Coordinate::parentTopMarkerName); | |||
s.add (Coordinate::parentBottomMarkerName); | |||
s.add ("top"); | |||
s.add ("bottom"); | |||
addMarkerMenuItem (1, coord, Coordinate::parentTopMarkerName, menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (2, coord, Coordinate::parentBottomMarkerName, menu, isAnchor1, componentState, coordName); | |||
menu.addSeparator(); | |||
addMarkerMenuItem (3, coord, componentName + ".top", menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (4, coord, componentName + ".bottom", menu, isAnchor1, componentState, coordName); | |||
} | |||
menu.addSeparator(); | |||
const MarkerList& markerList = getMarkerList (coord.isHorizontal()); | |||
int i; | |||
for (i = 0; i < markerList.size(); ++i) | |||
addMarkerMenuItem (100 + i, coord, markerList.getName (markerList.getMarker (i)), menu, isAnchor1, componentState, coordName); | |||
menu.addSeparator(); | |||
for (i = 0; i < getNumComponents(); ++i) | |||
{ | |||
const String compName (getComponent (i) [memberNameProperty].toString()); | |||
if (compName != componentName) | |||
{ | |||
if (coord.isHorizontal()) | |||
{ | |||
addMarkerMenuItem (10000 + i, coord, compName + ".left", menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (10001 + i, coord, compName + ".right", menu, isAnchor1, componentState, coordName); | |||
} | |||
else | |||
{ | |||
addMarkerMenuItem (10002 + i, coord, compName + ".top", menu, isAnchor1, componentState, coordName); | |||
addMarkerMenuItem (10003 + i, coord, compName + ".bottom", menu, isAnchor1, componentState, coordName); | |||
} | |||
} | |||
} | |||
} | |||
const String ComponentDocument::getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int i) 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"); | |||
const MarkerList& markerList = getMarkerList (coord.isHorizontal()); | |||
if (i >= 100 && i < 10000) | |||
return markerList.getName (markerList.getMarker (i - 100)); | |||
if (i >= 10000) | |||
{ | |||
const String compName (getComponent ((i - 10000) / 4) [memberNameProperty].toString()); | |||
switch (i & 3) | |||
{ | |||
case 0: return compName + ".left"; | |||
case 1: return compName + ".right"; | |||
case 2: return compName + ".top"; | |||
case 3: return compName + ".bottom"; | |||
default: break; | |||
} | |||
} | |||
return s; | |||
jassertfalse; | |||
return String::empty; | |||
} | |||
void ComponentDocument::updateComponent (Component* comp) | |||
@@ -436,6 +511,12 @@ bool ComponentDocument::isStateForComponent (const ValueTree& storedState, Compo | |||
return storedState [idProperty] == comp->getProperties() [idProperty]; | |||
} | |||
void ComponentDocument::removeComponent (const ValueTree& state) | |||
{ | |||
jassert (state.isAChildOf (getComponentGroup())); | |||
getComponentGroup().removeChild (state, getUndoManager()); | |||
} | |||
const String ComponentDocument::getNonExistentMemberName (String suggestedName) | |||
{ | |||
suggestedName = makeValidCppIdentifier (suggestedName, false, true, false); | |||
@@ -460,10 +541,10 @@ ComponentDocument::MarkerList::MarkerList (ComponentDocument& document_, const b | |||
group (document_.getRoot().getChildWithName (isX_ ? markersGroupXTag : markersGroupYTag)), | |||
isX (isX_) | |||
{ | |||
jassert (group.isValid()); | |||
jassert (group.isAChildOf (document_.getRoot())); | |||
} | |||
ValueTree ComponentDocument::MarkerList::getGroup() const | |||
ValueTree& ComponentDocument::MarkerList::getGroup() | |||
{ | |||
return group; | |||
} | |||
@@ -493,6 +574,16 @@ const Coordinate ComponentDocument::MarkerList::getCoordinate (const ValueTree& | |||
return Coordinate (markerState [markerPosProperty].toString(), isX); | |||
} | |||
const String ComponentDocument::MarkerList::getName (const ValueTree& markerState) const | |||
{ | |||
return markerState [markerNameProperty].toString(); | |||
} | |||
Value ComponentDocument::MarkerList::getNameAsValue (const ValueTree& markerState) const | |||
{ | |||
return markerState.getPropertyAsValue (markerNameProperty, document.getUndoManager()); | |||
} | |||
void ComponentDocument::MarkerList::setCoordinate (ValueTree& markerState, const Coordinate& newCoord) | |||
{ | |||
markerState.setProperty (markerPosProperty, newCoord.toString(), document.getUndoManager()); | |||
@@ -511,12 +602,16 @@ void ComponentDocument::MarkerList::deleteMarker (ValueTree& markerState) | |||
group.removeChild (markerState, document.getUndoManager()); | |||
} | |||
const Coordinate ComponentDocument::MarkerList::findMarker (const String& name, bool isHorizontal) | |||
const Coordinate ComponentDocument::MarkerList::findMarker (const String& name, bool isHorizontal) const | |||
{ | |||
if (isHorizontal == isX) | |||
{ | |||
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) document.getCanvasWidth().getValue(), isHorizontal); | |||
else if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) document.getCanvasHeight().getValue(), isHorizontal); | |||
if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) document.getCanvasWidth().getValue(), isHorizontal); | |||
if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) document.getCanvasHeight().getValue(), isHorizontal); | |||
const ValueTree marker (document.getMarkerList (isHorizontal).getMarkerNamed (name)); | |||
if (marker.isValid()) | |||
return document.getMarkerList (isHorizontal).getCoordinate (marker); | |||
} | |||
return Coordinate (isX); | |||
@@ -534,7 +629,7 @@ const String ComponentDocument::getNonexistentMarkerName (const String& name) | |||
} | |||
//============================================================================== | |||
UndoManager* ComponentDocument::getUndoManager() | |||
UndoManager* ComponentDocument::getUndoManager() const | |||
{ | |||
return &undoManager; | |||
} | |||
@@ -32,7 +32,8 @@ | |||
//============================================================================== | |||
class ComponentDocument : public ValueTree::Listener | |||
class ComponentDocument : public ValueTree::Listener, | |||
public Coordinate::MarkerResolver | |||
{ | |||
public: | |||
//============================================================================== | |||
@@ -45,14 +46,12 @@ public: | |||
bool reload(); | |||
bool hasChangedSinceLastSave(); | |||
typedef SelectedItemSet<uint32> SelectedItems; | |||
//============================================================================== | |||
Value getClassName() { return getRootValueNonUndoable ("className"); } | |||
Value getClassDescription() { return getRootValueNonUndoable ("classDesc"); } | |||
Value getClassName() const { return getRootValueNonUndoable ("className"); } | |||
Value getClassDescription() const { return getRootValueNonUndoable ("classDesc"); } | |||
Value getCanvasWidth() { return getRootValueNonUndoable ("width"); } | |||
Value getCanvasHeight() { return getRootValueNonUndoable ("height"); } | |||
Value getCanvasWidth() const { return getRootValueNonUndoable ("width"); } | |||
Value getCanvasHeight() const { return getRootValueNonUndoable ("height"); } | |||
void createClassProperties (Array <PropertyComponent*>& props); | |||
@@ -68,11 +67,17 @@ public: | |||
const ValueTree getComponentState (Component* comp) const; | |||
void getComponentProperties (Array <PropertyComponent*>& props, Component* comp); | |||
bool isStateForComponent (const ValueTree& storedState, Component* comp) const; | |||
Coordinate::MarkerResolver* createComponentMarkerResolver (const ValueTree& state); | |||
const StringArray getComponentMarkers (bool horizontal) const; | |||
void removeComponent (const ValueTree& state); | |||
const RectangleCoordinates getCoordsFor (const ValueTree& componentState) const; | |||
bool setCoordsFor (ValueTree& componentState, const RectangleCoordinates& newSize); | |||
// for Coordinate::MarkerResolver: | |||
const Coordinate findMarker (const String& name, bool isHorizontal) const; | |||
void getComponentMarkerMenuItems (const ValueTree& componentState, const String& coordName, | |||
Coordinate& coord, PopupMenu& menu, bool isAnchor1); | |||
const String getChosenMarkerMenuItem (const ValueTree& componentState, Coordinate& coord, int itemId) const; | |||
void addNewComponentMenuItems (PopupMenu& menu) const; | |||
void performNewComponentMenuItem (int menuResultCode); | |||
@@ -82,28 +87,33 @@ public: | |||
public: | |||
MarkerList (ComponentDocument& document, bool isX); | |||
ValueTree getGroup() const; | |||
ValueTree& getGroup(); | |||
int size() const; | |||
ValueTree getMarker (int index) const; | |||
ValueTree getMarkerNamed (const String& name) const; | |||
bool contains (const ValueTree& markerState) const; | |||
const Coordinate getCoordinate (const ValueTree& markerState) const; | |||
const String getName (const ValueTree& markerState) const; | |||
Value getNameAsValue (const ValueTree& markerState) const; | |||
void setCoordinate (ValueTree& markerState, const Coordinate& newCoord); | |||
void createMarker (const String& name, int position); | |||
void deleteMarker (ValueTree& markerState); | |||
// for Coordinate::MarkerResolver: | |||
const Coordinate findMarker (const String& name, bool isHorizontal); | |||
const Coordinate findMarker (const String& name, bool isHorizontal) const; | |||
private: | |||
ComponentDocument& document; | |||
ValueTree group; | |||
const bool isX; | |||
MarkerList (const MarkerList&); | |||
MarkerList& operator= (const MarkerList&); | |||
}; | |||
MarkerList& getMarkerListX() { return *markersX; } | |||
MarkerList& getMarkerListY() { return *markersY; } | |||
MarkerList& getMarkerList (bool isX) { return isX ? *markersX : *markersY; } | |||
MarkerList& getMarkerListX() const { return *markersX; } | |||
MarkerList& getMarkerListY() const { return *markersY; } | |||
MarkerList& getMarkerList (bool isX) const { return isX ? *markersX : *markersY; } | |||
const String getNonexistentMarkerName (const String& name); | |||
@@ -115,7 +125,7 @@ public: | |||
//============================================================================== | |||
ValueTree& getRoot() { return root; } | |||
UndoManager* getUndoManager(); | |||
UndoManager* getUndoManager() const; | |||
void beginNewTransaction(); | |||
void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const var::identifier& property); | |||
@@ -134,15 +144,17 @@ private: | |||
File cppFile; | |||
ValueTree root; | |||
ScopedPointer<MarkerList> markersX, markersY; | |||
UndoManager undoManager; | |||
mutable UndoManager undoManager; | |||
bool changedSinceSaved; | |||
void checkRootObject(); | |||
void createSubTreeIfNotThere (const String& name); | |||
ValueTree getComponentGroup() const; | |||
void addMarkerMenuItem (int i, Coordinate& coord, const String& name, PopupMenu& menu, bool isAnchor1, | |||
const ValueTree& componentState, const String& coordName); | |||
Value getRootValueUndoable (const var::identifier& name) { return root.getPropertyAsValue (name, getUndoManager()); } | |||
Value getRootValueNonUndoable (const var::identifier& name) { return root.getPropertyAsValue (name, 0); } | |||
Value getRootValueUndoable (const var::identifier& name) const { return root.getPropertyAsValue (name, getUndoManager()); } | |||
Value getRootValueNonUndoable (const var::identifier& name) const { return root.getPropertyAsValue (name, 0); } | |||
void writeCode (OutputStream& cpp, OutputStream& header); | |||
void writeMetadata (OutputStream& out); | |||
@@ -32,23 +32,23 @@ const char* Coordinate::parentRightMarkerName = "parent.right"; | |||
const char* Coordinate::parentTopMarkerName = "parent.top"; | |||
const char* Coordinate::parentBottomMarkerName = "parent.bottom"; | |||
Coordinate::Coordinate (bool isHorizontal_) | |||
: value (0), isProportion (false), isHorizontal (isHorizontal_) | |||
Coordinate::Coordinate (bool horizontal_) | |||
: value (0), isProportion (false), horizontal (horizontal_) | |||
{ | |||
} | |||
Coordinate::Coordinate (double absoluteDistanceFromOrigin, bool isHorizontal_) | |||
: value (absoluteDistanceFromOrigin), isProportion (false), isHorizontal (isHorizontal_) | |||
Coordinate::Coordinate (double absoluteDistanceFromOrigin, bool horizontal_) | |||
: value (absoluteDistanceFromOrigin), isProportion (false), horizontal (horizontal_) | |||
{ | |||
} | |||
Coordinate::Coordinate (double absoluteDistance, const String& source, bool isHorizontal_) | |||
: anchor1 (source), value (absoluteDistance), isProportion (false), isHorizontal (isHorizontal_) | |||
Coordinate::Coordinate (double absoluteDistance, const String& source, bool horizontal_) | |||
: anchor1 (source), value (absoluteDistance), isProportion (false), horizontal (horizontal_) | |||
{ | |||
} | |||
Coordinate::Coordinate (double relativeProportion, const String& pos1, const String& pos2, bool isHorizontal_) | |||
: anchor1 (pos1), anchor2 (pos2), value (relativeProportion), isProportion (true), isHorizontal (isHorizontal_) | |||
Coordinate::Coordinate (double relativeProportion, const String& pos1, const String& pos2, bool horizontal_) | |||
: anchor1 (pos1), anchor2 (pos2), value (relativeProportion), isProportion (true), horizontal (horizontal_) | |||
{ | |||
} | |||
@@ -58,12 +58,12 @@ Coordinate::~Coordinate() | |||
const Coordinate Coordinate::getAnchorPoint1() const | |||
{ | |||
return Coordinate (0.0, anchor1, isHorizontal); | |||
return Coordinate (0.0, anchor1, horizontal); | |||
} | |||
const Coordinate Coordinate::getAnchorPoint2() const | |||
{ | |||
return Coordinate (0.0, anchor2, isHorizontal); | |||
return Coordinate (0.0, anchor2, horizontal); | |||
} | |||
bool Coordinate::isOrigin (const String& name) | |||
@@ -73,12 +73,12 @@ bool Coordinate::isOrigin (const String& name) | |||
const String Coordinate::getOriginMarkerName() const | |||
{ | |||
return isHorizontal ? parentLeftMarkerName : parentTopMarkerName; | |||
return horizontal ? parentLeftMarkerName : parentTopMarkerName; | |||
} | |||
const String Coordinate::getExtentMarkerName() const | |||
{ | |||
return isHorizontal ? parentRightMarkerName : parentBottomMarkerName; | |||
return horizontal ? parentRightMarkerName : parentBottomMarkerName; | |||
} | |||
const String Coordinate::checkName (const String& name) const | |||
@@ -86,12 +86,12 @@ const String Coordinate::checkName (const String& name) const | |||
return name.isEmpty() ? getOriginMarkerName() : name; | |||
} | |||
double Coordinate::getPosition (const String& name, MarkerResolver& markerResolver, int recursionCounter) const | |||
double Coordinate::getPosition (const String& name, const MarkerResolver& markerResolver, int recursionCounter) const | |||
{ | |||
if (isOrigin (name)) | |||
return 0.0; | |||
return markerResolver.findMarker (name, isHorizontal) | |||
return markerResolver.findMarker (name, horizontal) | |||
.resolve (markerResolver, recursionCounter + 1); | |||
} | |||
@@ -99,7 +99,7 @@ struct RecursivePositionException | |||
{ | |||
}; | |||
double Coordinate::resolve (MarkerResolver& markerResolver, int recursionCounter) const | |||
double Coordinate::resolve (const MarkerResolver& markerResolver, int recursionCounter) const | |||
{ | |||
if (recursionCounter > 100) | |||
{ | |||
@@ -113,7 +113,7 @@ double Coordinate::resolve (MarkerResolver& markerResolver, int recursionCounter | |||
: pos1 + value; | |||
} | |||
double Coordinate::resolve (MarkerResolver& markerResolver) const | |||
double Coordinate::resolve (const MarkerResolver& markerResolver) const | |||
{ | |||
try | |||
{ | |||
@@ -125,7 +125,7 @@ double Coordinate::resolve (MarkerResolver& markerResolver) const | |||
return 0.0; | |||
} | |||
void Coordinate::moveToAbsolute (double newPos, MarkerResolver& markerResolver) | |||
void Coordinate::moveToAbsolute (double newPos, const MarkerResolver& markerResolver) | |||
{ | |||
try | |||
{ | |||
@@ -147,18 +147,20 @@ void Coordinate::moveToAbsolute (double newPos, MarkerResolver& markerResolver) | |||
{} | |||
} | |||
bool Coordinate::isRecursive (MarkerResolver& markerResolver) const | |||
bool Coordinate::referencesDirectly (const String& markerName) const | |||
{ | |||
try | |||
{ | |||
resolve (markerResolver, 0); | |||
} | |||
catch (RecursivePositionException&) | |||
{ | |||
return true; | |||
} | |||
jassert (markerName.isNotEmpty()); | |||
return anchor1 == markerName || anchor2 == markerName; | |||
} | |||
bool Coordinate::referencesIndirectly (const String& markerName, const MarkerResolver& markerResolver) const | |||
{ | |||
if (isOrigin (anchor1) && ! isProportion) | |||
return isOrigin (markerName); | |||
return false; | |||
return referencesDirectly (markerName) | |||
|| markerResolver.findMarker (anchor1, horizontal).referencesIndirectly (markerName, markerResolver) | |||
|| (isProportion && markerResolver.findMarker (anchor2, horizontal).referencesIndirectly (markerName, markerResolver)); | |||
} | |||
void Coordinate::skipWhitespace (const String& s, int& i) | |||
@@ -215,8 +217,8 @@ double Coordinate::readNumber (const String& s, int& i) | |||
return value; | |||
} | |||
Coordinate::Coordinate (const String& s, bool isHorizontal_) | |||
: value (0), isProportion (false), isHorizontal (isHorizontal_) | |||
Coordinate::Coordinate (const String& s, bool horizontal_) | |||
: value (0), isProportion (false), horizontal (horizontal_) | |||
{ | |||
int i = 0; | |||
@@ -311,7 +313,7 @@ void Coordinate::setEditableValue (const double newValue) | |||
value = isProportion ? newValue / 100.0 : newValue; | |||
} | |||
void Coordinate::toggleProportionality (MarkerResolver& markerResolver) | |||
void Coordinate::toggleProportionality (const MarkerResolver& markerResolver) | |||
{ | |||
const double oldValue = resolve (markerResolver); | |||
@@ -322,14 +324,14 @@ void Coordinate::toggleProportionality (MarkerResolver& markerResolver) | |||
moveToAbsolute (oldValue, markerResolver); | |||
} | |||
void Coordinate::changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver) | |||
void Coordinate::changeAnchor1 (const String& newMarkerName, const MarkerResolver& markerResolver) | |||
{ | |||
const double oldValue = resolve (markerResolver); | |||
anchor1 = newMarkerName; | |||
moveToAbsolute (oldValue, markerResolver); | |||
} | |||
void Coordinate::changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver) | |||
void Coordinate::changeAnchor2 (const String& newMarkerName, const MarkerResolver& markerResolver) | |||
{ | |||
const double oldValue = resolve (markerResolver); | |||
anchor2 = newMarkerName; | |||
@@ -342,11 +344,11 @@ RectangleCoordinates::RectangleCoordinates() | |||
{ | |||
} | |||
RectangleCoordinates::RectangleCoordinates (const Rectangle<int>& rect) | |||
RectangleCoordinates::RectangleCoordinates (const Rectangle<int>& rect, const String& componentName) | |||
: left (rect.getX(), true), | |||
right (rect.getWidth(), "left", true), | |||
right (rect.getWidth(), componentName + ".left", true), | |||
top (rect.getY(), false), | |||
bottom (rect.getHeight(), "top", false) | |||
bottom (rect.getHeight(), componentName + ".top", false) | |||
{ | |||
} | |||
@@ -362,13 +364,7 @@ RectangleCoordinates::RectangleCoordinates (const String& stringVersion) | |||
bottom = Coordinate (tokens [3], false); | |||
} | |||
bool RectangleCoordinates::isRecursive (Coordinate::MarkerResolver& markerResolver) const | |||
{ | |||
return left.isRecursive (markerResolver) || right.isRecursive (markerResolver) | |||
|| top.isRecursive (markerResolver) || bottom.isRecursive (markerResolver); | |||
} | |||
const Rectangle<int> RectangleCoordinates::resolve (Coordinate::MarkerResolver& markerResolver) const | |||
const Rectangle<int> RectangleCoordinates::resolve (const Coordinate::MarkerResolver& markerResolver) const | |||
{ | |||
const int l = roundToInt (left.resolve (markerResolver)); | |||
const int r = roundToInt (right.resolve (markerResolver)); | |||
@@ -378,7 +374,7 @@ const Rectangle<int> RectangleCoordinates::resolve (Coordinate::MarkerResolver& | |||
return Rectangle<int> (l, t, r - l, b - t); | |||
} | |||
void RectangleCoordinates::moveToAbsolute (const Rectangle<int>& newPos, Coordinate::MarkerResolver& markerResolver) | |||
void RectangleCoordinates::moveToAbsolute (const Rectangle<int>& newPos, const Coordinate::MarkerResolver& markerResolver) | |||
{ | |||
left.moveToAbsolute (newPos.getX(), markerResolver); | |||
right.moveToAbsolute (newPos.getRight(), markerResolver); | |||
@@ -64,17 +64,21 @@ public: | |||
{ | |||
public: | |||
virtual ~MarkerResolver() {} | |||
virtual const Coordinate findMarker (const String& name, bool isHorizontal) = 0; | |||
virtual const Coordinate findMarker (const String& name, bool isHorizontal) const = 0; | |||
}; | |||
/** Calculates the absolute position of this co-ordinate. */ | |||
double resolve (MarkerResolver& markerResolver) const; | |||
double resolve (const MarkerResolver& markerResolver) const; | |||
/** Returns true if this co-ordinate is expressed in terms of markers that form a recursive loop. */ | |||
bool isRecursive (MarkerResolver& markerResolver) const; | |||
/** Returns true if this co-ordinate is expressed directly in terms of the specified marker. */ | |||
bool referencesDirectly (const String& markerName) const; | |||
/** Returns true if this co-ordinate is expressed in terms of the specified marker at any | |||
level in its evaluation. */ | |||
bool referencesIndirectly (const String& markerName, const MarkerResolver& markerResolver) const; | |||
/** Changes the value of this marker to make it resolve to the specified position. */ | |||
void moveToAbsolute (double newPos, MarkerResolver& markerResolver); | |||
void moveToAbsolute (double newPos, const MarkerResolver& markerResolver); | |||
const Coordinate getAnchorPoint1() const; | |||
const Coordinate getAnchorPoint2() const; | |||
@@ -82,14 +86,16 @@ public: | |||
const double getEditableValue() const; | |||
void setEditableValue (const double newValue); | |||
bool isHorizontal() const throw() { return horizontal; } | |||
bool isProportional() const throw() { return isProportion; } | |||
void toggleProportionality (MarkerResolver& markerResolver); | |||
void toggleProportionality (const MarkerResolver& markerResolver); | |||
const String getAnchor1() const { return checkName (anchor1); } | |||
void changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver); | |||
void changeAnchor1 (const String& newMarkerName, const MarkerResolver& markerResolver); | |||
const String getAnchor2() const { return checkName (anchor2); } | |||
void changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver); | |||
void changeAnchor2 (const String& newMarkerName, const MarkerResolver& markerResolver); | |||
//============================================================================== | |||
/* | |||
@@ -103,9 +109,8 @@ public: | |||
50% * marker1 -> marker2 = percentage between two markers | |||
standard marker names: | |||
"origin" = parent origin | |||
"size" = parent right or bottom | |||
"top", "left", "bottom", "right" = refer to the component's own left, right, top and bottom. | |||
"parent.top", "parent.left", "parent.bottom", "parent.right" | |||
"componentName.top", "componentName.left", "componentName.bottom", "componentName.right" | |||
*/ | |||
const String toString() const; | |||
@@ -119,10 +124,10 @@ private: | |||
//============================================================================== | |||
String anchor1, anchor2; | |||
double value; | |||
bool isProportion, isHorizontal; | |||
bool isProportion, horizontal; | |||
double resolve (MarkerResolver& markerResolver, int recursionCounter) const; | |||
double getPosition (const String& name, MarkerResolver& markerResolver, int recursionCounter) const; | |||
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; | |||
@@ -141,13 +146,12 @@ class RectangleCoordinates | |||
public: | |||
//============================================================================== | |||
RectangleCoordinates(); | |||
explicit RectangleCoordinates (const Rectangle<int>& rect); | |||
explicit RectangleCoordinates (const Rectangle<int>& rect, const String& componentName); | |||
explicit RectangleCoordinates (const String& stringVersion); | |||
//============================================================================== | |||
const Rectangle<int> resolve (Coordinate::MarkerResolver& markerResolver) const; | |||
bool isRecursive (Coordinate::MarkerResolver& markerResolver) const; | |||
void moveToAbsolute (const Rectangle<int>& newPos, Coordinate::MarkerResolver& markerResolver); | |||
const Rectangle<int> resolve (const Coordinate::MarkerResolver& markerResolver) const; | |||
void moveToAbsolute (const Rectangle<int>& newPos, const Coordinate::MarkerResolver& markerResolver); | |||
const String toString() const; | |||
Coordinate left, right, top, bottom; | |||
@@ -838,6 +838,9 @@ private: | |||
<< "{{{" << newLine | |||
<< "}}}" << newLine; | |||
} | |||
MSVCProjectExporter (const MSVCProjectExporter&); | |||
MSVCProjectExporter& operator= (const MSVCProjectExporter&); | |||
}; | |||
@@ -316,6 +316,9 @@ private: | |||
{ | |||
return file.withFileExtension (".o").getFileName(); | |||
} | |||
MakefileProjectExporter (const MakefileProjectExporter&); | |||
MakefileProjectExporter& operator= (const MakefileProjectExporter&); | |||
}; | |||
@@ -99,6 +99,10 @@ protected: | |||
name = name + ".a"; | |||
return name; | |||
} | |||
private: | |||
ProjectExporter (const ProjectExporter&); | |||
ProjectExporter& operator= (const ProjectExporter&); | |||
}; | |||
@@ -351,7 +351,6 @@ private: | |||
<< "#define JucePlugin_IsSynth " << ((bool) project.getPluginIsSynth().getValue() ? 1 : 0) << newLine | |||
<< "#define JucePlugin_WantsMidiInput " << ((bool) project.getPluginWantsMidiInput().getValue() ? 1 : 0) << newLine | |||
<< "#define JucePlugin_ProducesMidiOutput " << ((bool) project.getPluginProducesMidiOut().getValue() ? 1 : 0) << newLine | |||
<< "#define JucePlugin_IsSynth " << ((bool) project.getPluginIsSynth().getValue() ? 1 : 0) << newLine | |||
<< "#define JucePlugin_SilenceInProducesSilenceOut " << ((bool) project.getPluginSilenceInProducesSilenceOut().getValue() ? 1 : 0) << newLine | |||
<< "#define JucePlugin_TailLengthSeconds " << (double) project.getPluginTailLengthSeconds().getValue() << newLine | |||
<< "#define JucePlugin_EditorRequiresKeyboardFocus " << ((bool) project.getPluginEditorNeedsKeyFocus().getValue() ? 1 : 0) << newLine | |||
@@ -206,15 +206,13 @@ public: | |||
const Rectangle<int> newBounds (zone.resizeRectangleBy (originalPos, distance)); | |||
RectangleCoordinates pr (getDocument().getCoordsFor (v)); | |||
ScopedPointer<Coordinate::MarkerResolver> markers (getDocument().createComponentMarkerResolver (v)); | |||
pr.moveToAbsolute (newBounds, *markers); | |||
pr.moveToAbsolute (newBounds, getDocument()); | |||
return getDocument().setCoordsFor (v, pr); | |||
} | |||
//============================================================================== | |||
private: | |||
//============================================================================== | |||
ComponentEditorCanvas& canvas; | |||
Array <ValueTree> draggedComponents; | |||
Array <Rectangle<int> > originalPositions; | |||
@@ -229,8 +227,7 @@ private: | |||
const Rectangle<float> getComponentPosition (const ValueTree& state) | |||
{ | |||
RectangleCoordinates relativePos (getDocument().getCoordsFor (state)); | |||
ScopedPointer<Coordinate::MarkerResolver> markers (getDocument().createComponentMarkerResolver (state)); | |||
const Rectangle<int> intPos (relativePos.resolve (*markers)); | |||
const Rectangle<int> intPos (relativePos.resolve (getDocument())); | |||
originalPositions.add (intPos); | |||
return intPos.toFloat(); | |||
@@ -238,7 +238,10 @@ void ComponentEditor::getAllCommands (Array <CommandID>& commands) | |||
DocumentEditorComponent::getAllCommands (commands); | |||
const CommandID ids[] = { CommandIDs::undo, | |||
CommandIDs::redo }; | |||
CommandIDs::redo, | |||
CommandIDs::toFront, | |||
CommandIDs::toBack, | |||
StandardApplicationCommandIDs::del }; | |||
commands.addArray (ids, numElementsInArray (ids)); | |||
} | |||
@@ -250,18 +253,30 @@ void ComponentEditor::getCommandInfo (CommandID commandID, ApplicationCommandInf | |||
switch (commandID) | |||
{ | |||
case CommandIDs::undo: | |||
result.setInfo ("Undo", "Undoes the last change", | |||
CommandCategories::general, 0); | |||
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.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 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; | |||
@@ -280,6 +295,18 @@ bool ComponentEditor::perform (const InvocationInfo& info) | |||
getDocument().getUndoManager()->redo(); | |||
return true; | |||
case CommandIDs::toFront: | |||
getCanvas()->selectionToFront(); | |||
return true; | |||
case CommandIDs::toBack: | |||
getCanvas()->selectionToBack(); | |||
return true; | |||
case StandardApplicationCommandIDs::del: | |||
getCanvas()->deleteSelection(); | |||
return true; | |||
default: | |||
break; | |||
} | |||
@@ -115,13 +115,13 @@ public: | |||
//============================================================================== | |||
SizeGuideComponent (ComponentEditorCanvas& canvas_, const ValueTree& state_, Component* component_, Type type_) | |||
: OverlayItemComponent (canvas_), state (state_), component (component_), type (type_), | |||
font (10.0f) | |||
: OverlayItemComponent (canvas_), state (state_), component (component_), type (type_) | |||
{ | |||
component->addComponentListener (this); | |||
setAlwaysOnTop (true); | |||
canvas.addAndMakeVisible (this); | |||
setInterceptsMouseClicks (false, false); | |||
updatePosition(); | |||
} | |||
@@ -137,25 +137,10 @@ public: | |||
const float dashes[] = { 4.0f, 3.0f }; | |||
g.setColour (resizableBorderColour); | |||
g.drawDashedLine (lineEnd1.getX() + 0.5f, lineEnd1.getY() + 0.5f, | |||
lineEnd2.getX() + 0.5f, lineEnd2.getY() + 0.5f, | |||
dashes, 2, 1.0f); | |||
g.setFont (font); | |||
g.setColour (Colours::white); | |||
for (int y = -1; y <= 1; ++y) | |||
for (int x = -1; x <= 1; ++x) | |||
g.drawText (getName(), textArea.getX() + x, textArea.getY() + y, textArea.getWidth(), textArea.getHeight(), Justification::centred, 1); | |||
g.setColour (Colours::black); | |||
g.drawText (getName(), textArea.getX(), textArea.getY(), textArea.getWidth(), textArea.getHeight(), Justification::centred, 1); | |||
g.drawDashedLine (0.5f, 0.5f, getWidth() - 0.5f, getHeight() - 0.5f, dashes, 2, 1.0f); | |||
} | |||
void componentMovedOrResized (Component&, bool, bool) | |||
{ | |||
updatePosition(); | |||
} | |||
void componentMovedOrResized (Component&, bool, bool) { updatePosition(); } | |||
void componentBeingDeleted (Component&) | |||
{ | |||
@@ -166,72 +151,32 @@ public: | |||
//============================================================================== | |||
void updatePosition() | |||
{ | |||
RectangleCoordinates coords (getDocument().getCoordsFor (state)); | |||
Coordinate coord (false); | |||
bool isHorizontal = false; | |||
switch (type) | |||
if (component != 0) | |||
{ | |||
case left: coord = coords.left; isHorizontal = true; break; | |||
case right: coord = coords.right; isHorizontal = true; break; | |||
case top: coord = coords.top; break; | |||
case bottom: coord = coords.bottom; break; | |||
default: jassertfalse; break; | |||
} | |||
setName (coord.toString()); | |||
int textW = (int) font.getStringWidth (getName()); | |||
int textH = (int) font.getHeight(); | |||
RectangleCoordinates coords (getDocument().getCoordsFor (state)); | |||
Coordinate coord (false); | |||
Rectangle<int> r; | |||
Point<int> p1, p2; | |||
switch (type) | |||
{ | |||
case left: coord = coords.left; r.setBounds (component->getX(), 0, 1, component->getY()); break; | |||
case right: coord = coords.right; r.setBounds (component->getRight(), 0, 1, component->getY()); break; | |||
case top: coord = coords.top; r.setBounds (0, component->getY(), component->getX(), 1); break; | |||
case bottom: coord = coords.bottom; r.setBounds (0, component->getBottom(), component->getX(), 1); break; | |||
default: jassertfalse; break; | |||
} | |||
switch (type) | |||
{ | |||
case left: | |||
p1 = Point<int> (component->getX(), 0); | |||
p2 = Point<int> (component->getX(), component->getY()); | |||
textArea.setBounds (p1.getX() - textW - 2, 4, textW, textH); | |||
break; | |||
case right: | |||
p1 = Point<int> (component->getRight(), 0); | |||
p2 = Point<int> (component->getRight(), component->getY()); | |||
textArea.setBounds (p1.getX() + 2, 4, textW, textH); | |||
break; | |||
case top: | |||
p1 = Point<int> (0, component->getY()); | |||
p2 = Point<int> (component->getX(), component->getY()); | |||
textArea.setBounds (4, p1.getY() - textH - 2, textW, textH); | |||
break; | |||
case bottom: | |||
p1 = Point<int> (0, component->getBottom()); | |||
p2 = Point<int> (component->getX(), component->getBottom()); | |||
textArea.setBounds (4, p1.getY() + 2, textW, textH); | |||
break; | |||
default: | |||
jassertfalse; | |||
break; | |||
setBoundsInTargetSpace (r); | |||
label.update (getParentComponent(), coord.toString(), resizableBorderColour.withAlpha (0.9f), getX(), getY(), type != left, type != top); | |||
} | |||
setBoundsInTargetSpace (Rectangle<int> (p1, p2).expanded (2, 2).getUnion (textArea)); | |||
lineEnd1 = component->getParentComponent()->relativePositionToOtherComponent (this, p1); | |||
lineEnd2 = component->getParentComponent()->relativePositionToOtherComponent (this, p2); | |||
textArea.setPosition (component->getParentComponent()->relativePositionToOtherComponent (this, textArea.getPosition())); | |||
repaint(); | |||
} | |||
private: | |||
ValueTree state; | |||
Component* component; | |||
Type type; | |||
Font font; | |||
FloatingLabelComponent label; | |||
Point<int> lineEnd1, lineEnd2; | |||
Rectangle<int> textArea; | |||
}; | |||
void showSizeGuides() | |||
@@ -295,21 +240,33 @@ public: | |||
void paint (Graphics& g) | |||
{ | |||
g.setColour (Colours::darkgreen); | |||
g.setColour (Colours::darkgreen.withAlpha (isMouseOverOrDragging() ? 0.8f : 0.4f)); | |||
g.fillPath (path); | |||
} | |||
void updatePosition() | |||
{ | |||
ComponentDocument& doc = getDocument(); | |||
Coordinate coord (doc.getMarkerList (isX).getCoordinate (marker)); | |||
const int pos = roundToInt (coord.resolve (doc.getMarkerList (isX))); | |||
const int width = 10; | |||
Coordinate coord (getMarkerList().getCoordinate (marker)); | |||
const int pos = roundToInt (coord.resolve (getMarkerList())); | |||
const int width = 8; | |||
if (isX) | |||
setBoundsInTargetSpace (Rectangle<int> (pos - width, -headSize, width * 2, getParentHeight())); | |||
else | |||
setBoundsInTargetSpace (Rectangle<int> (-headSize, pos - width, getParentWidth(), width * 2)); | |||
labelText = "name: " + getMarkerList().getName (marker) + "\nposition: " + coord.toString(); | |||
updateLabel(); | |||
} | |||
void updateLabel() | |||
{ | |||
if (isMouseOverOrDragging() && (getWidth() > 1 || getHeight() > 1)) | |||
label.update (getParentComponent(), labelText, Colours::darkgreen, | |||
isX ? getBounds().getCentreX() : getX() + headSize, | |||
isX ? getY() + headSize : getBounds().getCentreY(), true, true); | |||
else | |||
label.remove(); | |||
} | |||
bool hitTest (int x, int y) | |||
@@ -334,10 +291,15 @@ public: | |||
path.addLineSegment (2.0f, centre, getWidth() + 1.0f, centre, lineThickness); | |||
path.addTriangle (0.0f, centre * 2.0f - 1.0f, 0.0f, 1.0f, headSize + 1.0f, centre); | |||
} | |||
updateLabel(); | |||
} | |||
void mouseDown (const MouseEvent& e) | |||
{ | |||
toFront (false); | |||
updateLabel(); | |||
if (e.mods.isPopupMenu()) | |||
{ | |||
isDragging = false; | |||
@@ -347,9 +309,8 @@ public: | |||
isDragging = true; | |||
getDocument().beginNewTransaction(); | |||
ComponentDocument& doc = getDocument(); | |||
Coordinate coord (doc.getMarkerList(isX).getCoordinate (marker)); | |||
dragStartPos = coord.resolve (doc.getMarkerList (isX)); | |||
Coordinate coord (getMarkerList().getCoordinate (marker)); | |||
dragStartPos = coord.resolve (getMarkerList()); | |||
} | |||
} | |||
@@ -360,27 +321,47 @@ public: | |||
ComponentDocument& doc = getDocument(); | |||
doc.getUndoManager()->undoCurrentTransactionOnly(); | |||
Coordinate coord (doc.getMarkerList (isX).getCoordinate (marker)); | |||
coord.moveToAbsolute (jmax (0.0, dragStartPos + (isX ? e.getDistanceFromDragStartX() | |||
: e.getDistanceFromDragStartY())), | |||
doc.getMarkerList (isX)); | |||
doc.getMarkerList(isX).setCoordinate (marker, coord); | |||
Rectangle<int> axis; | |||
if (isX) | |||
axis.setBounds (0, 0, getParentWidth(), headSize); | |||
else | |||
axis.setBounds (0, 0, headSize, getParentHeight()); | |||
if (axis.expanded (30, 30).contains (e.x, e.y)) | |||
{ | |||
Coordinate coord (getMarkerList().getCoordinate (marker)); | |||
coord.moveToAbsolute (jmax (0.0, dragStartPos + (isX ? e.getDistanceFromDragStartX() | |||
: e.getDistanceFromDragStartY())), | |||
getMarkerList()); | |||
getMarkerList().setCoordinate (marker, coord); | |||
} | |||
else | |||
{ | |||
getMarkerList().deleteMarker (marker); | |||
} | |||
} | |||
} | |||
void mouseUp (const MouseEvent& e) | |||
{ | |||
getDocument().beginNewTransaction(); | |||
updateLabel(); | |||
} | |||
void mouseEnter (const MouseEvent& e) | |||
{ | |||
updateLabel(); | |||
repaint(); | |||
} | |||
void mouseExit (const MouseEvent& e) | |||
{ | |||
updateLabel(); | |||
repaint(); | |||
} | |||
ComponentDocument::MarkerList& getMarkerList() { return getDocument().getMarkerList (isX); } | |||
void valueTreePropertyChanged (ValueTree&, const var::identifier&) { updatePosition(); } | |||
void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) {} | |||
void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) {} | |||
@@ -393,12 +374,94 @@ private: | |||
Path path; | |||
double dragStartPos; | |||
bool isDragging; | |||
FloatingLabelComponent label; | |||
String labelText; | |||
}; | |||
//============================================================================== | |||
class ComponentEditorCanvas::ComponentHolder : public Component | |||
{ | |||
public: | |||
ComponentHolder() {} | |||
~ComponentHolder() {} | |||
void updateComponents (ComponentDocument& doc, SelectedItems& selection) | |||
{ | |||
int i; | |||
for (i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* c = getChildComponent (i); | |||
if (! doc.containsComponent (c)) | |||
{ | |||
selection.deselect (c->getComponentUID()); | |||
delete c; | |||
} | |||
} | |||
Array <Component*> componentsInOrder; | |||
const int num = doc.getNumComponents(); | |||
for (i = 0; i < num; ++i) | |||
{ | |||
const ValueTree v (doc.getComponent (i)); | |||
Component* c = getComponentForState (doc, v); | |||
if (c == 0) | |||
{ | |||
c = doc.createComponent (i); | |||
addAndMakeVisible (c); | |||
} | |||
doc.updateComponent (c); | |||
componentsInOrder.add (c); | |||
} | |||
// Make sure the z-order is correct.. | |||
for (i = 0; i < num - 1; ++i) | |||
componentsInOrder.getUnchecked(i)->toBehind (componentsInOrder.getUnchecked (i + 1)); | |||
} | |||
Component* getComponentForState (ComponentDocument& doc, const ValueTree& state) | |||
{ | |||
for (int i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* const c = getChildComponent (i); | |||
if (doc.isStateForComponent (state, c)) | |||
return c; | |||
} | |||
return 0; | |||
} | |||
Component* findComponentAt (const Point<int>& pos) const | |||
{ | |||
for (int i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* const c = getChildComponent(i); | |||
if (c->getBounds().contains (pos)) | |||
return c; | |||
} | |||
return 0; | |||
} | |||
void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& lassoArea) | |||
{ | |||
for (int i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* c = getChildComponent(i); | |||
if (c->getBounds().intersects (lassoArea)) | |||
itemsFound.add (c->getComponentUID()); | |||
} | |||
} | |||
}; | |||
//============================================================================== | |||
class ComponentEditorCanvas::OverlayComponent : public Component, | |||
public LassoSource <ComponentDocument::SelectedItems::ItemType>, | |||
public LassoSource <SelectedItems::ItemType>, | |||
public ChangeListener, | |||
public ValueTree::Listener | |||
{ | |||
@@ -433,31 +496,39 @@ public: | |||
mouseDownCompUID = 0; | |||
isDraggingClickedComp = false; | |||
Component* underMouse = canvas.getComponentHolder()->findComponentAt (e.getEventRelativeTo (canvas.getComponentHolder()).getPosition()); | |||
if (e.mods.isPopupMenu()) | |||
{ | |||
if (underMouse != 0) | |||
{ | |||
if (! canvas.getSelection().isSelected (underMouse->getComponentUID())) | |||
canvas.getSelection().selectOnly (underMouse->getComponentUID()); | |||
} | |||
PopupMenu m; | |||
getDocument().addNewComponentMenuItems (m); | |||
const int r = m.show(); | |||
getDocument().performNewComponentMenuItem (r); | |||
if (underMouse != 0) | |||
{ | |||
m.addCommandItem (commandManager, CommandIDs::toFront); | |||
m.addCommandItem (commandManager, CommandIDs::toBack); | |||
m.addSeparator(); | |||
m.addCommandItem (commandManager, StandardApplicationCommandIDs::del); | |||
const int r = m.show(); | |||
(void) r; | |||
} | |||
else | |||
{ | |||
getDocument().addNewComponentMenuItems (m); | |||
const int r = m.show(); | |||
getDocument().performNewComponentMenuItem (r); | |||
} | |||
} | |||
else | |||
{ | |||
Component* underMouse = 0; | |||
for (int i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* const c = canvas.getComponentHolder()->getChildComponent(i); | |||
if (c->getBounds().contains (e.getPosition())) | |||
{ | |||
underMouse = c; | |||
break; | |||
} | |||
} | |||
if (underMouse == 0 || e.mods.isAltDown()) | |||
{ | |||
addAndMakeVisible (lasso = new LassoComponent <ComponentDocument::SelectedItems::ItemType>()); | |||
addAndMakeVisible (lasso = new LassoComponent <SelectedItems::ItemType>()); | |||
lasso->beginLasso (e, this); | |||
} | |||
else | |||
@@ -529,19 +600,13 @@ public: | |||
} | |||
} | |||
void findLassoItemsInArea (Array <ComponentDocument::SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height) | |||
void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, int x, int y, int width, int height) | |||
{ | |||
const Rectangle<int> lassoArea (x, y, width, height); | |||
for (int i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* c = canvas.getComponentHolder()->getChildComponent(i); | |||
if (c->getBounds().intersects (lassoArea)) | |||
itemsFound.add (c->getComponentUID()); | |||
} | |||
canvas.getComponentHolder()->findLassoItemsInArea (itemsFound, Rectangle<int> (x, y, width, height) | |||
+ relativePositionToOtherComponent (canvas.getComponentHolder(), Point<int>())); | |||
} | |||
ComponentDocument::SelectedItems& getLassoSelection() { return canvas.getSelection(); } | |||
SelectedItems& getLassoSelection() { return canvas.getSelection(); } | |||
void resized() | |||
{ | |||
@@ -586,13 +651,13 @@ private: | |||
//============================================================================== | |||
ComponentEditorCanvas& canvas; | |||
ValueTree markerRootX, markerRootY; | |||
ScopedPointer <LassoComponent <ComponentDocument::SelectedItems::ItemType> > lasso; | |||
ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso; | |||
bool mouseDownResult, isDraggingClickedComp; | |||
uint32 mouseDownCompUID; | |||
ComponentDocument& getDocument() { return canvas.getDocument(); } | |||
Component* getComponentWithUID (const int uid) const | |||
Component* getComponentWithUID (const uint32 uid) const | |||
{ | |||
for (int i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;) | |||
{ | |||
@@ -607,7 +672,7 @@ private: | |||
void updateResizeFrames() | |||
{ | |||
ComponentDocument::SelectedItems& selection = canvas.getSelection(); | |||
SelectedItems& selection = canvas.getSelection(); | |||
Array<int> requiredIds; | |||
int i; | |||
@@ -643,11 +708,12 @@ private: | |||
void updateMarkers (bool isX) | |||
{ | |||
ComponentDocument& doc = getDocument(); | |||
ComponentDocument::MarkerList& markerList = doc.getMarkerList (isX); | |||
Array<ValueTree> requiredMarkers; | |||
int i; | |||
for (i = doc.getMarkerList (isX).size(); --i >= 0;) | |||
requiredMarkers.add (doc.getMarkerList (isX).getMarker (i)); | |||
requiredMarkers.add (markerList.getMarker (i)); | |||
for (i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
@@ -657,12 +723,16 @@ private: | |||
{ | |||
if (requiredMarkers.contains (marker->marker)) | |||
{ | |||
marker->setVisible (true); | |||
marker->updatePosition(); | |||
requiredMarkers.removeValue (marker->marker); | |||
} | |||
else | |||
{ | |||
delete marker; | |||
if (marker->isMouseButtonDown()) | |||
marker->setBounds (-1, -1, 1, 1); | |||
else | |||
delete marker; | |||
} | |||
} | |||
} | |||
@@ -684,57 +754,6 @@ private: | |||
} | |||
}; | |||
//============================================================================== | |||
class ComponentEditorCanvas::ComponentHolder : public Component | |||
{ | |||
public: | |||
ComponentHolder() {} | |||
~ComponentHolder() {} | |||
void updateComponents (ComponentDocument& doc, ComponentDocument::SelectedItems& selection) | |||
{ | |||
int i; | |||
for (i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* c = getChildComponent (i); | |||
if (! doc.containsComponent (c)) | |||
{ | |||
selection.deselect (c->getComponentUID()); | |||
delete c; | |||
} | |||
} | |||
const int num = doc.getNumComponents(); | |||
for (i = 0; i < num; ++i) | |||
{ | |||
const ValueTree v (doc.getComponent (i)); | |||
Component* c = getComponentForState (doc, v); | |||
if (c == 0) | |||
{ | |||
c = doc.createComponent (i); | |||
addAndMakeVisible (c); | |||
} | |||
doc.updateComponent (c); | |||
} | |||
} | |||
Component* getComponentForState (ComponentDocument& doc, const ValueTree& state) | |||
{ | |||
for (int i = getNumChildComponents(); --i >= 0;) | |||
{ | |||
Component* const c = getChildComponent (i); | |||
if (doc.isStateForComponent (state, c)) | |||
return c; | |||
} | |||
return 0; | |||
} | |||
}; | |||
//============================================================================== | |||
class ComponentEditorCanvas::WholeComponentResizer : public Component | |||
{ | |||
@@ -848,10 +867,10 @@ ComponentEditorCanvas::~ComponentEditorCanvas() | |||
} | |||
//============================================================================== | |||
ComponentEditor& ComponentEditorCanvas::getEditor() { return editor; } | |||
ComponentDocument& ComponentEditorCanvas::getDocument() { return editor.getDocument(); } | |||
ComponentDocument::SelectedItems& ComponentEditorCanvas::getSelection() { return selection; } | |||
Component* ComponentEditorCanvas::getComponentHolder() const { return componentHolder; } | |||
ComponentEditor& ComponentEditorCanvas::getEditor() { return editor; } | |||
ComponentDocument& ComponentEditorCanvas::getDocument() { return editor.getDocument(); } | |||
ComponentEditorCanvas::SelectedItems& ComponentEditorCanvas::getSelection() { return selection; } | |||
ComponentEditorCanvas::ComponentHolder* ComponentEditorCanvas::getComponentHolder() const { return componentHolder; } | |||
void ComponentEditorCanvas::timerCallback() | |||
{ | |||
@@ -944,6 +963,73 @@ void ComponentEditorCanvas::getSelectedItemProperties (Array <PropertyComponent* | |||
} | |||
} | |||
void ComponentEditorCanvas::deleteSelection() | |||
{ | |||
getDocument().beginNewTransaction(); | |||
for (int i = selection.getNumSelected(); --i >= 0;) | |||
{ | |||
Component* c = getComponentForUID (selection.getSelectedItem (0)); | |||
if (c != 0) | |||
getDocument().removeComponent (getDocument().getComponentState (c)); | |||
} | |||
selection.deselectAll(); | |||
getDocument().beginNewTransaction(); | |||
} | |||
void ComponentEditorCanvas::selectionToFront() | |||
{ | |||
getDocument().beginNewTransaction(); | |||
int index = 0; | |||
for (int i = getDocument().getNumComponents(); --i >= 0;) | |||
{ | |||
const ValueTree comp (getDocument().getComponent (index)); | |||
Component* c = componentHolder->getComponentForState (getDocument(), comp); | |||
if (c != 0 && selection.isSelected (c->getComponentUID())) | |||
{ | |||
ValueTree parent (comp.getParent()); | |||
parent.removeChild (comp, getDocument().getUndoManager()); | |||
parent.addChild (comp, -1, getDocument().getUndoManager()); | |||
} | |||
else | |||
{ | |||
++index; | |||
} | |||
} | |||
getDocument().beginNewTransaction(); | |||
} | |||
void ComponentEditorCanvas::selectionToBack() | |||
{ | |||
getDocument().beginNewTransaction(); | |||
int index = getDocument().getNumComponents() - 1; | |||
for (int i = getDocument().getNumComponents(); --i >= 0;) | |||
{ | |||
const ValueTree comp (getDocument().getComponent (index)); | |||
Component* c = componentHolder->getComponentForState (getDocument(), comp); | |||
if (c != 0 && selection.isSelected (c->getComponentUID())) | |||
{ | |||
ValueTree parent (comp.getParent()); | |||
parent.removeChild (comp, getDocument().getUndoManager()); | |||
parent.addChild (comp, 0, getDocument().getUndoManager()); | |||
} | |||
else | |||
{ | |||
--index; | |||
} | |||
} | |||
getDocument().beginNewTransaction(); | |||
} | |||
//============================================================================== | |||
void ComponentEditorCanvas::showSizeGuides() { overlay->showSizeGuides(); } | |||
void ComponentEditorCanvas::hideSizeGuides() { overlay->hideSizeGuides(); } | |||
@@ -44,8 +44,12 @@ public: | |||
//============================================================================== | |||
ComponentEditor& getEditor(); | |||
ComponentDocument& getDocument(); | |||
ComponentDocument::SelectedItems& getSelection(); | |||
Component* getComponentHolder() const; | |||
typedef SelectedItemSet<uint32> SelectedItems; | |||
SelectedItems& getSelection(); | |||
class ComponentHolder; | |||
ComponentHolder* getComponentHolder() const; | |||
//============================================================================== | |||
void timerCallback(); | |||
@@ -64,6 +68,9 @@ public: | |||
//============================================================================== | |||
void getSelectedItemProperties (Array <PropertyComponent*>& props); | |||
void deleteSelection(); | |||
void selectionToFront(); | |||
void selectionToBack(); | |||
//============================================================================== | |||
void showSizeGuides(); | |||
@@ -98,7 +105,6 @@ private: | |||
friend class OverlayItemComponent; | |||
class ComponentResizeFrame; | |||
class MarkerComponent; | |||
class ComponentHolder; | |||
class WholeComponentResizer; | |||
class OverlayComponent; | |||
@@ -106,7 +112,7 @@ private: | |||
ComponentHolder* componentHolder; | |||
OverlayComponent* overlay; | |||
WholeComponentResizer* resizeFrame; | |||
ComponentDocument::SelectedItems selection; | |||
SelectedItems selection; | |||
Component* getComponentForUID (const uint32 uid) const; | |||
const Array<Component*> getSelectedComps() const; | |||
@@ -247,6 +247,9 @@ private: | |||
Project* const project; | |||
const File file; | |||
Time fileModificationTime; | |||
UnknownDocument (const UnknownDocument&); | |||
UnknownDocument& operator= (const UnknownDocument&); | |||
}; | |||
@@ -251,8 +251,9 @@ void ProjectContentComponent::getCommandInfo (const CommandID commandID, Applica | |||
case StandardApplicationCommandIDs::del: | |||
result.setInfo ("Delete", String::empty, CommandCategories::general, 0); | |||
result.setActive (projectTree != 0); | |||
result.defaultKeypresses.add (KeyPress (KeyPress::deleteKey, 0, 0)); | |||
result.defaultKeypresses.add (KeyPress (KeyPress::backspaceKey, 0, 0)); | |||
result.setActive (projectTree != 0); | |||
break; | |||
default: | |||
@@ -575,3 +575,55 @@ const String PropertyPanelWithTooltips::findTip (Component* c) | |||
return String::empty; | |||
} | |||
//============================================================================== | |||
FloatingLabelComponent::FloatingLabelComponent() | |||
: font (10.0f) | |||
{ | |||
setInterceptsMouseClicks (false ,false); | |||
} | |||
void FloatingLabelComponent::remove() | |||
{ | |||
if (getParentComponent() != 0) | |||
getParentComponent()->removeChildComponent (this); | |||
} | |||
void FloatingLabelComponent::update (Component* parent, const String& text, const Colour& textColour, int x, int y, bool toRight, bool below) | |||
{ | |||
colour = textColour; | |||
Rectangle<int> r; | |||
if (text != getName()) | |||
{ | |||
setName (text); | |||
glyphs.clear(); | |||
glyphs.addJustifiedText (font, text, 0, 0, 200.0f, Justification::left); | |||
glyphs.justifyGlyphs (0, std::numeric_limits<int>::max(), 0, 0, 1000, 1000, Justification::topLeft); | |||
r = glyphs.getBoundingBox (0, std::numeric_limits<int>::max(), false) | |||
.getSmallestIntegerContainer().expanded (2, 2); | |||
} | |||
else | |||
{ | |||
r = getLocalBounds(); | |||
} | |||
r.setPosition (x + (toRight ? 3 : -(r.getWidth() + 3)), y + (below ? 2 : -(r.getHeight() + 2))); | |||
setBounds (r); | |||
parent->addAndMakeVisible (this); | |||
} | |||
void FloatingLabelComponent::paint (Graphics& g) | |||
{ | |||
g.setFont (font); | |||
g.setColour (Colours::white); | |||
for (int y = -1; y <= 1; ++y) | |||
for (int x = -1; x <= 1; ++x) | |||
glyphs.draw (g, AffineTransform::translation (1.0f + x, 1.0f + y)); | |||
g.setColour (colour); | |||
glyphs.draw (g, AffineTransform::translation (1.0f, 1.0f)); | |||
} |
@@ -132,6 +132,21 @@ private: | |||
const String findTip (Component* c); | |||
}; | |||
//============================================================================== | |||
class FloatingLabelComponent : public Component | |||
{ | |||
public: | |||
FloatingLabelComponent(); | |||
void remove(); | |||
void update (Component* parent, const String& text, const Colour& textColour, int x, int y, bool toRight, bool below); | |||
void paint (Graphics& g); | |||
private: | |||
Font font; | |||
Colour colour; | |||
GlyphArrangement glyphs; | |||
}; | |||
//============================================================================== | |||
static const double tickSizes[] = { 1.0, 2.0, 5.0, | |||
@@ -236,4 +251,7 @@ private: | |||
{ | |||
return String (roundToInt (value)); | |||
} | |||
TickIterator (const TickIterator&); | |||
TickIterator& operator= (const TickIterator&); | |||
}; |
@@ -8224,7 +8224,7 @@ const String URL::removeEscapeChars (const String& s) | |||
if (nextPercent < 0) | |||
break; | |||
juce_wchar replacementChar = result.substring (nextPercent + 1, nextPercent + 3).getHexValue32(); | |||
juce_wchar replacementChar = (juce_wchar) result.substring (nextPercent + 1, nextPercent + 3).getHexValue32(); | |||
result = result.replaceSection (nextPercent, 3, String::charToString (replacementChar)); | |||
++nextPercent; | |||
} | |||
@@ -16286,7 +16286,7 @@ void ValueTree::removeChild (const int childIndex, UndoManager* const undoManage | |||
object->removeChild (childIndex, undoManager); | |||
} | |||
void ValueTree::removeChild (ValueTree& child, UndoManager* const undoManager) | |||
void ValueTree::removeChild (const ValueTree& child, UndoManager* const undoManager) | |||
{ | |||
if (object != 0) | |||
object->removeChild (object->children.indexOf (child.object), undoManager); | |||
@@ -17660,6 +17660,9 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return; // locking failure.. | |||
ScopedPointer<InputStream> fileStream (f.createInputStream()); | |||
if (fileStream != 0) | |||
@@ -17796,6 +17799,9 @@ bool PropertiesFile::save() | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return false; // locking failure.. | |||
if (doc.writeToFile (file, String::empty)) | |||
{ | |||
needsWriting = false; | |||
@@ -17806,6 +17812,9 @@ bool PropertiesFile::save() | |||
{ | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return false; // locking failure.. | |||
TemporaryFile tempFile (file); | |||
ScopedPointer <OutputStream> out (tempFile.getFile().createOutputStream()); | |||
@@ -23815,6 +23824,8 @@ AudioIODeviceType* juce_createAudioIODeviceType_JACK(); | |||
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list) | |||
{ | |||
(void) list; // (to avoid 'unused param' warnings) | |||
#if JUCE_WINDOWS | |||
#if JUCE_WASAPI | |||
if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) | |||
@@ -38701,9 +38712,11 @@ void Component::toFront (const bool setAsForeground) | |||
} | |||
else if (parentComponent_ != 0) | |||
{ | |||
if (parentComponent_->childComponentList_.getLast() != this) | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (childList.getLast() != this) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
const int index = childList.indexOf (this); | |||
if (index >= 0) | |||
{ | |||
@@ -38711,18 +38724,15 @@ void Component::toFront (const bool setAsForeground) | |||
if (! flags.alwaysOnTopFlag) | |||
{ | |||
insertIndex = parentComponent_->childComponentList_.size() - 1; | |||
insertIndex = childList.size() - 1; | |||
while (insertIndex > 0 | |||
&& parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
{ | |||
while (insertIndex > 0 && childList.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
--insertIndex; | |||
} | |||
} | |||
if (index != insertIndex) | |||
{ | |||
parentComponent_->childComponentList_.move (index, insertIndex); | |||
childList.move (index, insertIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
@@ -38740,28 +38750,31 @@ void Component::toFront (const bool setAsForeground) | |||
void Component::toBehind (Component* const other) | |||
{ | |||
if (other != 0) | |||
if (other != 0 && other != this) | |||
{ | |||
// the two components must belong to the same parent.. | |||
jassert (parentComponent_ == other->parentComponent_); | |||
if (parentComponent_ != 0) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
int otherIndex = parentComponent_->childComponentList_.indexOf (other); | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (index >= 0 | |||
&& otherIndex >= 0 | |||
&& index != otherIndex - 1 | |||
&& other != this) | |||
const int index = childList.indexOf (this); | |||
if (index >= 0 && childList [index + 1] != other) | |||
{ | |||
if (index < otherIndex) | |||
--otherIndex; | |||
int otherIndex = childList.indexOf (other); | |||
parentComponent_->childComponentList_.move (index, otherIndex); | |||
if (otherIndex >= 0) | |||
{ | |||
if (index < otherIndex) | |||
--otherIndex; | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
childList.move (index, otherIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
} | |||
} | |||
} | |||
else if (isOnDesktop()) | |||
@@ -38783,14 +38796,15 @@ void Component::toBehind (Component* const other) | |||
void Component::toBack() | |||
{ | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (isOnDesktop()) | |||
{ | |||
jassertfalse //xxx need to add this to native window | |||
} | |||
else if (parentComponent_ != 0 | |||
&& parentComponent_->childComponentList_.getFirst() != this) | |||
else if (parentComponent_ != 0 && childList.getFirst() != this) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
const int index = childList.indexOf (this); | |||
if (index > 0) | |||
{ | |||
@@ -38798,8 +38812,8 @@ void Component::toBack() | |||
if (flags.alwaysOnTopFlag) | |||
{ | |||
while (insertIndex < parentComponent_->childComponentList_.size() | |||
&& ! parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
while (insertIndex < childList.size() | |||
&& ! childList.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
{ | |||
++insertIndex; | |||
} | |||
@@ -38807,7 +38821,7 @@ void Component::toBack() | |||
if (index != insertIndex) | |||
{ | |||
parentComponent_->childComponentList_.move (index, insertIndex); | |||
childList.move (index, insertIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
@@ -247892,7 +247906,9 @@ public: | |||
keyCode: 0]; | |||
[menu performKeyEquivalent: f35Event]; | |||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu) | |||
if ([menu indexOfItem: item] >= 0) | |||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu) | |||
} | |||
[menu release]; | |||
@@ -6750,7 +6750,7 @@ public: | |||
void addChild (ValueTree child, int index, UndoManager* const undoManager); | |||
void removeChild (ValueTree& child, UndoManager* const undoManager); | |||
void removeChild (const ValueTree& child, UndoManager* const undoManager); | |||
void removeChild (const int childIndex, UndoManager* const undoManager); | |||
@@ -6855,6 +6855,9 @@ private: | |||
private: | |||
ElementComparator& comparator; | |||
ComparatorAdapter (const ComparatorAdapter&); | |||
ComparatorAdapter& operator= (const ComparatorAdapter&); | |||
}; | |||
friend class SharedObject; | |||
@@ -110,6 +110,8 @@ AudioIODeviceType* juce_createAudioIODeviceType_JACK(); | |||
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list) | |||
{ | |||
(void) list; // (to avoid 'unused param' warnings) | |||
#if JUCE_WINDOWS | |||
#if JUCE_WASAPI | |||
if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) | |||
@@ -622,7 +622,7 @@ void ValueTree::removeChild (const int childIndex, UndoManager* const undoManage | |||
object->removeChild (childIndex, undoManager); | |||
} | |||
void ValueTree::removeChild (ValueTree& child, UndoManager* const undoManager) | |||
void ValueTree::removeChild (const ValueTree& child, UndoManager* const undoManager) | |||
{ | |||
if (object != 0) | |||
object->removeChild (object->children.indexOf (child.object), undoManager); | |||
@@ -239,7 +239,7 @@ public: | |||
If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | |||
so that this change can be undone. | |||
*/ | |||
void removeChild (ValueTree& child, UndoManager* const undoManager); | |||
void removeChild (const ValueTree& child, UndoManager* const undoManager); | |||
/** Removes a child from this node's child-list. | |||
If the undoManager parameter is non-null, its UndoManager::perform() method will be used, | |||
@@ -457,6 +457,9 @@ private: | |||
private: | |||
ElementComparator& comparator; | |||
ComparatorAdapter (const ComparatorAdapter&); | |||
ComparatorAdapter& operator= (const ComparatorAdapter&); | |||
}; | |||
friend class SharedObject; | |||
@@ -537,9 +537,11 @@ void Component::toFront (const bool setAsForeground) | |||
} | |||
else if (parentComponent_ != 0) | |||
{ | |||
if (parentComponent_->childComponentList_.getLast() != this) | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (childList.getLast() != this) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
const int index = childList.indexOf (this); | |||
if (index >= 0) | |||
{ | |||
@@ -547,18 +549,15 @@ void Component::toFront (const bool setAsForeground) | |||
if (! flags.alwaysOnTopFlag) | |||
{ | |||
insertIndex = parentComponent_->childComponentList_.size() - 1; | |||
insertIndex = childList.size() - 1; | |||
while (insertIndex > 0 | |||
&& parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
{ | |||
while (insertIndex > 0 && childList.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
--insertIndex; | |||
} | |||
} | |||
if (index != insertIndex) | |||
{ | |||
parentComponent_->childComponentList_.move (index, insertIndex); | |||
childList.move (index, insertIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
@@ -576,28 +575,31 @@ void Component::toFront (const bool setAsForeground) | |||
void Component::toBehind (Component* const other) | |||
{ | |||
if (other != 0) | |||
if (other != 0 && other != this) | |||
{ | |||
// the two components must belong to the same parent.. | |||
jassert (parentComponent_ == other->parentComponent_); | |||
if (parentComponent_ != 0) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
int otherIndex = parentComponent_->childComponentList_.indexOf (other); | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (index >= 0 | |||
&& otherIndex >= 0 | |||
&& index != otherIndex - 1 | |||
&& other != this) | |||
const int index = childList.indexOf (this); | |||
if (index >= 0 && childList [index + 1] != other) | |||
{ | |||
if (index < otherIndex) | |||
--otherIndex; | |||
int otherIndex = childList.indexOf (other); | |||
parentComponent_->childComponentList_.move (index, otherIndex); | |||
if (otherIndex >= 0) | |||
{ | |||
if (index < otherIndex) | |||
--otherIndex; | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
childList.move (index, otherIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
} | |||
} | |||
} | |||
else if (isOnDesktop()) | |||
@@ -619,14 +621,15 @@ void Component::toBehind (Component* const other) | |||
void Component::toBack() | |||
{ | |||
Array<Component*>& childList = parentComponent_->childComponentList_; | |||
if (isOnDesktop()) | |||
{ | |||
jassertfalse //xxx need to add this to native window | |||
} | |||
else if (parentComponent_ != 0 | |||
&& parentComponent_->childComponentList_.getFirst() != this) | |||
else if (parentComponent_ != 0 && childList.getFirst() != this) | |||
{ | |||
const int index = parentComponent_->childComponentList_.indexOf (this); | |||
const int index = childList.indexOf (this); | |||
if (index > 0) | |||
{ | |||
@@ -634,8 +637,8 @@ void Component::toBack() | |||
if (flags.alwaysOnTopFlag) | |||
{ | |||
while (insertIndex < parentComponent_->childComponentList_.size() | |||
&& ! parentComponent_->childComponentList_.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
while (insertIndex < childList.size() | |||
&& ! childList.getUnchecked (insertIndex)->isAlwaysOnTop()) | |||
{ | |||
++insertIndex; | |||
} | |||
@@ -643,7 +646,7 @@ void Component::toBack() | |||
if (index != insertIndex) | |||
{ | |||
parentComponent_->childComponentList_.move (index, insertIndex); | |||
childList.move (index, insertIndex); | |||
sendFakeMouseMove(); | |||
repaintParent(); | |||
@@ -547,7 +547,7 @@ const String URL::removeEscapeChars (const String& s) | |||
if (nextPercent < 0) | |||
break; | |||
juce_wchar replacementChar = result.substring (nextPercent + 1, nextPercent + 3).getHexValue32(); | |||
juce_wchar replacementChar = (juce_wchar) result.substring (nextPercent + 1, nextPercent + 3).getHexValue32(); | |||
result = result.replaceSection (nextPercent, 3, String::charToString (replacementChar)); | |||
++nextPercent; | |||
} | |||
@@ -184,7 +184,9 @@ public: | |||
keyCode: 0]; | |||
[menu performKeyEquivalent: f35Event]; | |||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu) | |||
if ([menu indexOfItem: item] >= 0) | |||
[menu removeItem: item]; // (this throws if the item isn't actually in the menu) | |||
} | |||
[menu release]; | |||
@@ -71,6 +71,9 @@ PropertiesFile::PropertiesFile (const File& f, const int millisecondsBeforeSavin | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return; // locking failure.. | |||
ScopedPointer<InputStream> fileStream (f.createInputStream()); | |||
if (fileStream != 0) | |||
@@ -207,6 +210,9 @@ bool PropertiesFile::save() | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return false; // locking failure.. | |||
if (doc.writeToFile (file, String::empty)) | |||
{ | |||
needsWriting = false; | |||
@@ -217,6 +223,9 @@ bool PropertiesFile::save() | |||
{ | |||
ProcessScopedLock pl (createProcessLock()); | |||
if (pl != 0 && ! pl->isLocked()) | |||
return false; // locking failure.. | |||
TemporaryFile tempFile (file); | |||
ScopedPointer <OutputStream> out (tempFile.getFile().createOutputStream()); | |||