1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Jucer development. Small safety fix for String.

This commit is contained in:
Julian Storer 2010-04-16 16:29:05 +01:00
parent 0490668407
commit 643eea5fde
7 changed files with 183 additions and 87 deletions

View file

@ -41,7 +41,8 @@ static const char* const metadataTagEnd = "JUCER_" "COMPONENT_METADATA_E
//==============================================================================
class ComponentBoundsEditor : public PropertyComponent
class ComponentBoundsEditor : public PropertyComponent,
public ButtonListener
{
public:
enum Type
@ -50,15 +51,28 @@ public:
};
//==============================================================================
ComponentBoundsEditor (const String& name, Type type_, const Value& state_)
: PropertyComponent (name, 40), type (type_), state (state_)
ComponentBoundsEditor (ComponentDocument& document_, const String& name, Type type_,
const ValueTree& compState_, const Value& boundsValue_)
: PropertyComponent (name, 40), document (document_), type (type_),
compState (compState_), boundsValue (boundsValue_)
{
addAndMakeVisible (label = new Label (String::empty, String::empty));
label->setEditable (true, true, false);
label->setColour (Label::backgroundColourId, Colours::white);
label->setColour (Label::outlineColourId, findColour (ComboBox::outlineColourId));
label->getTextValue().referTo (Value (new BoundsCoordValueSource (state, type)));
label->getTextValue().referTo (Value (new BoundsCoordValueSource (boundsValue, type)));
addAndMakeVisible (proportionButton = new TextButton ("%"));
proportionButton->addButtonListener (this);
addAndMakeVisible (anchorButton1 = new TextButton (String::empty));
anchorButton1->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
anchorButton1->addButtonListener (this);
addAndMakeVisible (anchorButton2 = new TextButton (String::empty));
anchorButton2->setConnectedEdges (Button::ConnectedOnLeft | Button::ConnectedOnTop | Button::ConnectedOnRight | Button::ConnectedOnBottom);
anchorButton2->addButtonListener (this);
}
~ComponentBoundsEditor()
@ -68,15 +82,39 @@ public:
void resized()
{
const Rectangle<int> content (getLookAndFeel().getPropertyComponentContentPosition (*this));
const Rectangle<int> r (getLookAndFeel().getPropertyComponentContentPosition (*this));
label->setBounds (content.getX(), content.getY(), content.getWidth(), content.getHeight() / 2);
label->setBounds (r.getX(), r.getY(), r.getWidth() / 2, r.getHeight() / 2);
proportionButton->setBounds (r.getX() + r.getWidth() / 2, r.getY(),
r.getWidth() / 2, r.getHeight() / 2);
anchorButton1->setBounds (r.getX(), r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
anchorButton2->setBounds (r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2, r.getWidth() / 2, r.getHeight() / 2);
}
void refresh()
{
}
void buttonClicked (Button* button)
{
if (button == proportionButton)
{
RectangleCoordinates r (boundsValue.toString());
Coordinate& coord = getCoord (r);
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (compState));
coord.toggleProportionality (*markers);
boundsValue = r.toString();
}
else if (button == anchorButton1)
{
}
else if (button == anchorButton2)
{
}
}
//==============================================================================
class BoundsCoordValueSource : public Value::ValueSource,
public Value::Listener
@ -94,6 +132,10 @@ public:
{
RectangleCoordinates r (sourceValue.toString());
Coordinate& coord = getCoord (r);
if (coord.isProportional())
return String (coord.getEditableValue()) + "%";
return coord.getEditableValue();
}
@ -123,26 +165,41 @@ public:
Coordinate& getCoord (RectangleCoordinates& r) const
{
switch (type)
{
case left: return r.left;
case right: return r.right;
case top: return r.top;
case bottom: return r.bottom;
default: jassertfalse; break;
}
return r.left;
return getCoordForType (type, r);
}
BoundsCoordValueSource (const BoundsCoordValueSource&);
const BoundsCoordValueSource& operator= (const BoundsCoordValueSource&);
};
static Coordinate& getCoordForType (const Type type, RectangleCoordinates& r)
{
switch (type)
{
case left: return r.left;
case right: return r.right;
case top: return r.top;
case bottom: return r.bottom;
default: jassertfalse; break;
}
return r.left;
}
private:
ComponentDocument& document;
Type type;
Value state;
ValueTree compState;
Value boundsValue;
Label* label;
TextButton* proportionButton;
TextButton* anchorButton1;
TextButton* anchorButton2;
Coordinate& getCoord (RectangleCoordinates& r)
{
return getCoordForType (type, r);
}
};
@ -165,12 +222,9 @@ Value ComponentTypeHandler::getValue (const var::identifier& name, ValueTree& st
void ComponentTypeHandler::updateComponent (ComponentDocument& document, Component* comp, const ValueTree& state)
{
if (comp->getParentComponent() != 0)
{
RectangleCoordinates pos (state [compBoundsProperty].toString());
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (state, comp->getParentComponent()));
comp->setBounds (pos.resolve (*markers));
}
RectangleCoordinates pos (state [compBoundsProperty].toString());
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (state));
comp->setBounds (pos.resolve (*markers));
comp->setName (state [compNameProperty]);
}
@ -188,10 +242,10 @@ void ComponentTypeHandler::initialiseNewItem (ComponentDocument& document, Value
void ComponentTypeHandler::createPropertyEditors (ComponentDocument& document, ValueTree& state, Array <PropertyComponent*>& props)
{
props.add (new ComponentBoundsEditor ("Left", ComponentBoundsEditor::left, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor ("Right", ComponentBoundsEditor::right, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor ("Top", ComponentBoundsEditor::top, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor ("Bottom", ComponentBoundsEditor::bottom, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor (document, "Left", ComponentBoundsEditor::left, state, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor (document, "Right", ComponentBoundsEditor::right, state, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor (document, "Top", ComponentBoundsEditor::top, state, getValue (compBoundsProperty, state, document)));
props.add (new ComponentBoundsEditor (document, "Bottom", ComponentBoundsEditor::bottom, state, getValue (compBoundsProperty, state, document)));
}
//==============================================================================
@ -415,6 +469,12 @@ void ComponentDocument::checkRootObject()
if (getClassName().toString().isEmpty())
getClassName() = "NewComponent";
if ((int) getCanvasWidth().getValue() <= 0)
getCanvasWidth() = 640;
if ((int) getCanvasHeight().getValue() <= 0)
getCanvasHeight() = 480;
}
//==============================================================================
@ -497,8 +557,10 @@ Component* ComponentDocument::createComponent (int index)
class ComponentMarkerResolver : public Coordinate::MarkerResolver
{
public:
ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, Component* parentComponent_)
: owner (doc), state (state_), parentComponent (parentComponent_)
ComponentMarkerResolver (ComponentDocument& doc, const ValueTree& state_, int parentWidth_, int parentHeight_)
: owner (doc), state (state_),
parentWidth (parentWidth_),
parentHeight (parentHeight_)
{}
~ComponentMarkerResolver() {}
@ -509,8 +571,8 @@ public:
else if (name == "right") return RectangleCoordinates (state [compBoundsProperty]).right;
else if (name == "top") return RectangleCoordinates (state [compBoundsProperty]).top;
else if (name == "bottom") return RectangleCoordinates (state [compBoundsProperty]).bottom;
else if (name == Coordinate::parentRightMarkerName) return Coordinate ((double) parentComponent->getWidth(), isHorizontal);
else if (name == Coordinate::parentBottomMarkerName) return Coordinate ((double) parentComponent->getHeight(), isHorizontal);
else if (name == Coordinate::parentRightMarkerName) return Coordinate (parentWidth, isHorizontal);
else if (name == Coordinate::parentBottomMarkerName) return Coordinate (parentHeight, isHorizontal);
return Coordinate (isHorizontal);
}
@ -518,7 +580,7 @@ public:
private:
ComponentDocument& owner;
ValueTree state;
Component* parentComponent;
int parentWidth, parentHeight;
};
const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& state) const
@ -526,10 +588,9 @@ const RectangleCoordinates ComponentDocument::getCoordsFor (const ValueTree& sta
return RectangleCoordinates (state [compBoundsProperty]);
}
Coordinate::MarkerResolver* ComponentDocument::createMarkerResolver (const ValueTree& state, Component* parentComponent)
Coordinate::MarkerResolver* ComponentDocument::createMarkerResolver (const ValueTree& state)
{
jassert (parentComponent != 0);
return new ComponentMarkerResolver (*this, state, parentComponent);
return new ComponentMarkerResolver (*this, state, getCanvasWidth().getValue(), getCanvasHeight().getValue());
}
void ComponentDocument::updateComponent (Component* comp)
@ -624,8 +685,7 @@ public:
const MouseEvent& e,
const ResizableBorderComponent::Zone& zone_,
Component* parentForOverlays)
: parentComponent (0),
document (document_),
: document (document_),
zone (zone_)
{
for (int i = 0; i < items.size(); ++i)
@ -633,9 +693,6 @@ public:
Component* comp = items.getUnchecked(i);
jassert (comp != 0);
if (parentComponent == 0)
parentComponent = comp->getParentComponent();
const ValueTree v (document.getComponentState (comp));
draggedComponents.add (v);
@ -643,7 +700,7 @@ public:
{
RectangleCoordinates relativePos (v [compBoundsProperty].toString());
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v, parentComponent));
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v));
pos = relativePos.resolve (*markers);
originalPositions.add (pos);
}
@ -708,7 +765,7 @@ public:
const Rectangle<int> newBounds (zone.resizeRectangleBy (originalPos, distance));
RectangleCoordinates pr (v [compBoundsProperty].toString());
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v, parentComponent));
ScopedPointer<Coordinate::MarkerResolver> markers (document.createMarkerResolver (v));
pr.moveToAbsolute (newBounds, *markers);
const String newBoundsString (pr.toString());
@ -739,7 +796,6 @@ public:
}
private:
Component* parentComponent;
ComponentDocument& document;
Array <ValueTree> draggedComponents;
Array <Rectangle<int> > originalPositions;

View file

@ -49,6 +49,10 @@ public:
//==============================================================================
Value getClassName() { return getRootValue ("className"); }
Value getClassDescription() { return getRootValue ("classDesc"); }
Value getCanvasWidth() { return root.getPropertyAsValue ("width", 0); } // (deliberately not undoable)
Value getCanvasHeight() { return root.getPropertyAsValue ("height", 0); }
const String getNonExistentMemberName (String suggestedName);
//==============================================================================
@ -61,7 +65,7 @@ public:
const ValueTree getComponentState (Component* comp) const;
void getComponentProperties (Array <PropertyComponent*>& props, Component* comp);
bool isStateForComponent (const ValueTree& storedState, Component* comp) const;
Coordinate::MarkerResolver* createMarkerResolver (const ValueTree& state, Component* parentComponent);
Coordinate::MarkerResolver* createMarkerResolver (const ValueTree& state);
const RectangleCoordinates getCoordsFor (const ValueTree& state) const;
void addNewComponentMenuItems (PopupMenu& menu) const;

View file

@ -272,7 +272,8 @@ class ComponentEditor::Canvas : public Component,
{
public:
Canvas (ComponentEditor& editor_)
: editor (editor_), border (14), resizerThickness (4)
: editor (editor_), border (14), resizerThickness (4),
dragStartWidth (0), dragStartHeight (0)
{
setOpaque (true);
addAndMakeVisible (componentHolder = new Component());
@ -301,48 +302,48 @@ public:
g.setFont (border.getBottom() - 5.0f);
g.setColour (Colours::grey);
g.drawText (String (componentHolder->getWidth()) + " x " + String (componentHolder->getHeight()),
0, 0, getWidth() - border.getRight(), getHeight(), Justification::bottomRight, false);
0, 0, jmax (getWidth() - border.getRight(), jmin (60, getWidth())), getHeight(), Justification::bottomRight, false);
g.setFont (border.getTop() - 5.0f);
g.setColour (Colours::darkgrey);
const int x = border.getLeft();
const int y = border.getTop();
g.drawHorizontalLine (border.getTop() - 1, 2.0f, (float) getWidth() - border.getRight());
g.drawVerticalLine (border.getLeft() - 1, 2.0f, (float) getHeight() - border.getBottom());
drawXAxis (g, Rectangle<int> (border.getLeft(), 0, componentHolder->getWidth(), border.getTop()));
drawYAxis (g, Rectangle<int> (0, border.getTop(), border.getLeft(), componentHolder->getHeight()));
}
g.drawHorizontalLine (y, 2.0f, (float) getWidth() - border.getRight());
g.drawVerticalLine (x, 2.0f, (float) getHeight() - border.getBottom());
void drawXAxis (Graphics& g, const Rectangle<int>& r)
{
TickIterator ticks (0, r.getWidth(), 1.0, 10, 50);
float pos, tickLength;
String label;
while (ticks.getNextTick (pos, tickLength, label))
{
TickIterator ticks (0, componentHolder->getWidth(), 1.0, 10, 50);
float pos, tickLength;
String label;
while (ticks.getNextTick (pos, tickLength, label))
if (pos > 0)
{
if (pos > 0)
{
g.drawVerticalLine (x + (int) pos, y - tickLength * y, (float) y);
g.drawSingleLineText (label, x + (int) pos + 2, (int) y - 6);
}
g.drawVerticalLine (r.getX() + (int) pos, r.getBottom() - tickLength * r.getHeight(), (float) r.getBottom());
g.drawSingleLineText (label, r.getX() + (int) pos + 2, (int) r.getBottom() - 6);
}
}
}
void drawYAxis (Graphics& g, const Rectangle<int>& r)
{
TickIterator ticks (0, r.getHeight(), 1.0, 10, 80);
float pos, tickLength;
String label;
while (ticks.getNextTick (pos, tickLength, label))
{
TickIterator ticks (0, componentHolder->getHeight(), 1.0, 10, 80);
float pos, tickLength;
String label;
while (ticks.getNextTick (pos, tickLength, label))
if (pos > 0)
{
if (pos > 0)
{
g.drawHorizontalLine (y + (int) pos, x - tickLength * x, (float) x);
g.drawTextAsPath (label, AffineTransform::rotation (float_Pi / -2.0f)
.translated (x - 6.0f, y + pos - 2.0f));
}
g.drawHorizontalLine (r.getY() + (int) pos, r.getRight() - tickLength * r.getWidth(), (float) r.getRight());
g.drawTextAsPath (label, AffineTransform::rotation (float_Pi / -2.0f)
.translated (r.getRight() - 6.0f, r.getY() + pos - 2.0f));
}
}
}
@ -380,6 +381,8 @@ public:
void updateComponents()
{
ComponentDocument& doc = getDocument();
setSize ((int) doc.getCanvasWidth().getValue() + border.getLeftAndRight(),
(int) doc.getCanvasHeight().getValue() + border.getTopAndBottom());
int i;
for (i = componentHolder->getNumChildComponents(); --i >= 0;)
@ -469,19 +472,18 @@ public:
void mouseDown (const MouseEvent& e)
{
updateDragZone (e.getPosition());
dragStartSize = getBounds();
dragStartWidth = getDocument().getCanvasWidth().getValue();
dragStartHeight = getDocument().getCanvasHeight().getValue();
showSizeGuides();
}
void mouseDrag (const MouseEvent& e)
{
if (dragZone.isDraggingRightEdge() || dragZone.isDraggingBottomEdge())
{
setSize (dragZone.isDraggingRightEdge() ? jmax (0, dragStartSize.getWidth() + e.getDistanceFromDragStartX())
: dragStartSize.getWidth(),
dragZone.isDraggingBottomEdge() ? jmax (0, dragStartSize.getHeight() + e.getDistanceFromDragStartY())
: dragStartSize.getHeight());
}
if (dragZone.isDraggingRightEdge())
getDocument().getCanvasWidth() = jmax (1, dragStartWidth + e.getDistanceFromDragStartX());
if (dragZone.isDraggingBottomEdge())
getDocument().getCanvasHeight() = jmax (1, dragStartHeight + e.getDistanceFromDragStartY());
}
void mouseUp (const MouseEvent& e)
@ -511,7 +513,7 @@ private:
const BorderSize border;
const int resizerThickness;
ResizableBorderComponent::Zone dragZone;
Rectangle<int> dragStartSize;
int dragStartWidth, dragStartHeight;
const Rectangle<int> getContentArea() const
{

View file

@ -784,6 +784,31 @@ void Coordinate::setEditableValue (const double newValue)
value = isProportion ? newValue / 100.0 : newValue;
}
void Coordinate::toggleProportionality (MarkerResolver& markerResolver)
{
const double oldValue = resolve (markerResolver);
isProportion = ! isProportion;
anchor1 = getOriginMarkerName();
anchor2 = getExtentMarkerName();
moveToAbsolute (oldValue, markerResolver);
}
void Coordinate::changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver)
{
const double oldValue = resolve (markerResolver);
anchor1 = newMarkerName;
moveToAbsolute (oldValue, markerResolver);
}
void Coordinate::changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver)
{
const double oldValue = resolve (markerResolver);
anchor2 = newMarkerName;
moveToAbsolute (oldValue, markerResolver);
}
//==============================================================================
RectangleCoordinates::RectangleCoordinates()
: left (true), right (true), top (false), bottom (false)

View file

@ -163,6 +163,15 @@ public:
const double getEditableValue() const;
void setEditableValue (const double newValue);
bool isProportional() const throw() { return isProportion; }
void toggleProportionality (MarkerResolver& markerResolver);
const String getAnchor1() const { return anchor1; }
void changeAnchor1 (const String& newMarkerName, MarkerResolver& markerResolver);
const String getAnchor2() const { return anchor2; }
void changeAnchor2 (const String& newMarkerName, MarkerResolver& markerResolver);
//==============================================================================
/*
Position string formats:

View file

@ -12019,7 +12019,7 @@ const char* String::toUTF8() const
String* const mutableThis = const_cast <String*> (this);
mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, currentLen + 1 + utf8BytesNeeded / sizeof (juce_wchar));
char* const otherCopy = reinterpret_cast <char*> (text + currentLen);
char* const otherCopy = reinterpret_cast <char*> (mutableThis->text + currentLen);
copyToUTF8 (otherCopy, std::numeric_limits<int>::max());
return otherCopy;
@ -12210,7 +12210,7 @@ const char* String::toCString() const
String* const mutableThis = const_cast <String*> (this);
mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, (len + 1) * 2);
char* otherCopy = reinterpret_cast <char*> (text + len + 1);
char* otherCopy = reinterpret_cast <char*> (mutableThis->text + len + 1);
CharacterFunctions::copy (otherCopy, text, len);
otherCopy [len] = 0;
return otherCopy;

View file

@ -1931,7 +1931,7 @@ const char* String::toUTF8() const
String* const mutableThis = const_cast <String*> (this);
mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, currentLen + 1 + utf8BytesNeeded / sizeof (juce_wchar));
char* const otherCopy = reinterpret_cast <char*> (text + currentLen);
char* const otherCopy = reinterpret_cast <char*> (mutableThis->text + currentLen);
copyToUTF8 (otherCopy, std::numeric_limits<int>::max());
return otherCopy;
@ -2123,7 +2123,7 @@ const char* String::toCString() const
String* const mutableThis = const_cast <String*> (this);
mutableThis->text = StringHolder::makeUniqueWithSize (mutableThis->text, (len + 1) * 2);
char* otherCopy = reinterpret_cast <char*> (text + len + 1);
char* otherCopy = reinterpret_cast <char*> (mutableThis->text + len + 1);
CharacterFunctions::copy (otherCopy, text, len);
otherCopy [len] = 0;
return otherCopy;