mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-24 01:54:22 +00:00
More internal changes to drawables. Linux URL header retrieval. Small fix for AudioProcessorPlayer. Jucer development.
This commit is contained in:
parent
1b6eb960e3
commit
8e1b74a8fc
21 changed files with 1222 additions and 710 deletions
|
|
@ -68,6 +68,8 @@ public:
|
|||
anotherInstanceStarted (commandLine);
|
||||
|
||||
theMainWindow->reloadLastProject();
|
||||
|
||||
theMainWindow->getLookAndFeel().setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
|
|
|
|||
|
|
@ -146,6 +146,13 @@ public:
|
|||
|
||||
void createPropertyEditors (DrawableTypeInstance& item, Array <PropertyComponent*>& props)
|
||||
{
|
||||
DrawablePath::ValueTreeWrapper wrapper (item.getState());
|
||||
|
||||
props.add (new FillTypePropertyComponent (item.getDocument().getUndoManager(),
|
||||
"Fill", wrapper.getMainFillState()));
|
||||
|
||||
props.add (new FillTypePropertyComponent (item.getDocument().getUndoManager(),
|
||||
"Stroke", wrapper.getStrokeFillState()));
|
||||
}
|
||||
|
||||
void itemDoubleClicked (const MouseEvent& e, DrawableTypeInstance& item)
|
||||
|
|
|
|||
|
|
@ -146,6 +146,10 @@ public:
|
|||
return getDocument().getCoordsFor (state);
|
||||
}
|
||||
|
||||
void updateExtraComponentsForObject (const ValueTree& state, Component* parent, OwnedArray<OverlayItemComponent>& existingComps)
|
||||
{
|
||||
}
|
||||
|
||||
SelectedItems& getSelection()
|
||||
{
|
||||
return editor.getSelection();
|
||||
|
|
|
|||
|
|
@ -207,6 +207,77 @@ public:
|
|||
return RelativeRectangle();
|
||||
}
|
||||
|
||||
class ControlPointComponent : public OverlayItemComponent
|
||||
{
|
||||
public:
|
||||
ControlPointComponent (DrawableEditorCanvas* canvas)
|
||||
: OverlayItemComponent (canvas)
|
||||
{
|
||||
}
|
||||
|
||||
~ControlPointComponent()
|
||||
{
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (Colours::pink);
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
}
|
||||
|
||||
void updatePosition (const RelativePoint& point, RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
const Point<float> p (point.resolve (nameFinder));
|
||||
setBoundsInTargetSpace (Rectangle<int> (roundToInt (p.getX()) - 2, roundToInt (p.getY()) - 2, 5, 5));
|
||||
}
|
||||
};
|
||||
|
||||
void updateExtraComponentsForObject (const ValueTree& state, Component* parent, OwnedArray<OverlayItemComponent>& comps)
|
||||
{
|
||||
if (drawable == 0)
|
||||
{
|
||||
comps.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
DrawableTypeInstance item (getDocument(), state);
|
||||
Array<RelativePoint> points;
|
||||
item.getAllControlPoints (points);
|
||||
|
||||
Drawable* d = drawable->getDrawableWithName (Drawable::ValueTreeWrapperBase (state).getID());
|
||||
DrawableComposite* parentDrawable = d->getParent();
|
||||
|
||||
comps.removeRange (points.size(), comps.size());
|
||||
|
||||
BigInteger requiredIndexes;
|
||||
requiredIndexes.setRange (0, points.size(), true);
|
||||
|
||||
for (int i = 0; i < points.size(); ++i)
|
||||
{
|
||||
ControlPointComponent* c = dynamic_cast <ControlPointComponent*> (comps[i]);
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
c = new ControlPointComponent (this);
|
||||
comps.set (i, c);
|
||||
parent->addAndMakeVisible (c);
|
||||
}
|
||||
|
||||
c->updatePosition (points.getReference(i), parentDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
SelectedItems& getSelection()
|
||||
{
|
||||
return editor.getSelection();
|
||||
|
|
|
|||
|
|
@ -114,12 +114,14 @@ public:
|
|||
const Rectangle<int> bounds (canvas->getObjectPosition (objectState));
|
||||
setBoundsInTargetSpace (bounds.expanded (borderThickness, borderThickness));
|
||||
|
||||
for (int i = sizeGuides.size(); --i >= 0;)
|
||||
int i;
|
||||
for (i = sizeGuides.size(); --i >= 0;)
|
||||
{
|
||||
sizeGuides.getUnchecked(i)->setVisible (isVisible());
|
||||
sizeGuides.getUnchecked(i)->updatePosition (bounds);
|
||||
}
|
||||
|
||||
canvas->updateExtraComponentsForObject (objectState, getParentComponent(), extraEditorComps);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -200,6 +202,7 @@ private:
|
|||
const int borderThickness;
|
||||
OwnedArray <SizeGuideComponent> sizeGuides;
|
||||
bool isDragging;
|
||||
OwnedArray <OverlayItemComponent> extraEditorComps;
|
||||
|
||||
const Rectangle<int> getCentreArea() const
|
||||
{
|
||||
|
|
@ -399,6 +402,8 @@ public:
|
|||
getSelection().removeChangeListener (this);
|
||||
lasso = 0;
|
||||
resizers.clear();
|
||||
markersX.clear();
|
||||
markersY.clear();
|
||||
deleteAllChildren();
|
||||
}
|
||||
|
||||
|
|
@ -563,6 +568,21 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
updateResizeFrames();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
EditorCanvasBase* canvas;
|
||||
ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso;
|
||||
bool mouseDownResult, isDraggingClickedComp;
|
||||
SelectedItems::ItemType mouseDownCompUID;
|
||||
OwnedArray <ResizeFrame> resizers;
|
||||
OwnedArray <MarkerComponent> markersX, markersY;
|
||||
|
||||
void updateResizeFrames()
|
||||
{
|
||||
SelectedItems& selection = getSelection();
|
||||
|
|
@ -610,49 +630,34 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void update()
|
||||
void updateMarkers (OwnedArray <MarkerComponent>& markers, const bool isX)
|
||||
{
|
||||
updateResizeFrames();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
EditorCanvasBase* canvas;
|
||||
ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso;
|
||||
bool mouseDownResult, isDraggingClickedComp;
|
||||
SelectedItems::ItemType mouseDownCompUID;
|
||||
OwnedArray <ResizeFrame> resizers;
|
||||
|
||||
void updateMarkers (bool isX)
|
||||
{
|
||||
Array<ValueTree> requiredMarkers;
|
||||
|
||||
MarkerListBase& markerList = canvas->getMarkerList (isX);
|
||||
const int num = markerList.size();
|
||||
|
||||
Array<ValueTree> requiredMarkers;
|
||||
requiredMarkers.ensureStorageAllocated (num);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num; ++i)
|
||||
requiredMarkers.add (markerList.getMarker (i));
|
||||
|
||||
for (i = getNumChildComponents(); --i >= 0;)
|
||||
for (i = markers.size(); --i >= 0;)
|
||||
{
|
||||
MarkerComponent* marker = dynamic_cast <MarkerComponent*> (getChildComponent(i));
|
||||
MarkerComponent* marker = markers.getUnchecked (i);
|
||||
const int index = requiredMarkers.indexOf (marker->marker);
|
||||
|
||||
if (marker != 0 && marker->isX == isX)
|
||||
if (index >= 0)
|
||||
{
|
||||
if (requiredMarkers.contains (marker->marker))
|
||||
{
|
||||
marker->setVisible (true);
|
||||
marker->updatePosition();
|
||||
requiredMarkers.removeValue (marker->marker);
|
||||
}
|
||||
marker->updatePosition();
|
||||
requiredMarkers.removeValue (marker->marker);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (marker->isMouseButtonDown())
|
||||
marker->setBounds (-1, -1, 1, 1);
|
||||
else
|
||||
{
|
||||
if (marker->isMouseButtonDown())
|
||||
marker->setBounds (-1, -1, 1, 1);
|
||||
else
|
||||
delete marker;
|
||||
}
|
||||
markers.remove (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -661,6 +666,7 @@ private:
|
|||
MarkerComponent* marker = new MarkerComponent (canvas, requiredMarkers.getReference(i),
|
||||
isX, isX ? canvas->border.getTop()
|
||||
: canvas->border.getLeft());
|
||||
markers.add (marker);
|
||||
addAndMakeVisible (marker);
|
||||
marker->updatePosition();
|
||||
}
|
||||
|
|
@ -668,8 +674,8 @@ private:
|
|||
|
||||
void updateMarkers()
|
||||
{
|
||||
updateMarkers (true);
|
||||
updateMarkers (false);
|
||||
updateMarkers (markersX, true);
|
||||
updateMarkers (markersY, false);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -64,27 +64,29 @@ public:
|
|||
void hideSizeGuides();
|
||||
|
||||
//==============================================================================
|
||||
virtual UndoManager& getUndoManager() = 0;
|
||||
virtual void documentChanged() = 0;
|
||||
virtual Component* createComponentHolder() = 0;
|
||||
|
||||
virtual const Rectangle<int> getCanvasBounds() = 0;
|
||||
virtual void setCanvasBounds (const Rectangle<int>& newBounds) = 0;
|
||||
virtual bool canResizeCanvas() const = 0;
|
||||
virtual MarkerListBase& getMarkerList (bool isX) = 0;
|
||||
virtual double limitMarkerPosition (double pos) = 0;
|
||||
|
||||
virtual const SelectedItems::ItemType findObjectIdAt (const Point<int>& position) = 0;
|
||||
virtual void showPopupMenu (bool isClickOnSelectedObject) = 0;
|
||||
virtual void objectDoubleClicked (const MouseEvent& e, const ValueTree& state) = 0;
|
||||
|
||||
virtual const ValueTree getObjectState (const String& objectId) = 0;
|
||||
virtual const Rectangle<int> getObjectPosition (const ValueTree& state) = 0;
|
||||
|
||||
virtual bool hasSizeGuides() const = 0;
|
||||
virtual RelativeRectangle getObjectCoords (const ValueTree& state) = 0;
|
||||
virtual const Rectangle<int> getObjectPosition (const ValueTree& state) = 0;
|
||||
virtual bool hasSizeGuides() const = 0;
|
||||
|
||||
virtual MarkerListBase& getMarkerList (bool isX) = 0;
|
||||
virtual double limitMarkerPosition (double pos) = 0;
|
||||
|
||||
virtual SelectedItems& getSelection() = 0;
|
||||
virtual UndoManager& getUndoManager() = 0;
|
||||
virtual void deselectNonDraggableObjects() = 0;
|
||||
virtual void findLassoItemsInArea (Array <SelectedItems::ItemType>& itemsFound, const Rectangle<int>& area) = 0;
|
||||
virtual Component* createComponentHolder() = 0;
|
||||
|
||||
class DragOperation
|
||||
{
|
||||
|
|
@ -126,6 +128,10 @@ public:
|
|||
EditorCanvasBase* canvas;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
virtual void updateExtraComponentsForObject (const ValueTree& state, Component* parent,
|
||||
OwnedArray<OverlayItemComponent>& existingComps) = 0;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
const BorderSize border;
|
||||
|
|
|
|||
|
|
@ -172,6 +172,11 @@ public:
|
|||
roundToInt (line.end - line.start) + extraEndLength * 2, 1));
|
||||
}
|
||||
|
||||
bool updatePosition()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (alignmentMarkerColour);
|
||||
|
|
|
|||
|
|
@ -37,15 +37,43 @@ public:
|
|||
: fillState (fillState_),
|
||||
undoManager (undoManager_)
|
||||
{
|
||||
addAndMakeVisible (&colourPicker);
|
||||
colourButton.setButtonText ("Colour");
|
||||
colourButton.setConnectedEdges (TextButton::ConnectedOnRight);
|
||||
gradientButton.setButtonText ("Gradient");
|
||||
gradientButton.setConnectedEdges (TextButton::ConnectedOnRight | TextButton::ConnectedOnLeft);
|
||||
imageButton.setButtonText ("Image");
|
||||
imageButton.setConnectedEdges (TextButton::ConnectedOnLeft);
|
||||
|
||||
addAndMakeVisible (&colourButton);
|
||||
addAndMakeVisible (&gradientButton);
|
||||
addAndMakeVisible (&imageButton);
|
||||
|
||||
addChildComponent (&colourPicker);
|
||||
colourPicker.setCurrentColour (Colours::green);
|
||||
colourPicker.setName ("Colour");
|
||||
colourPicker.addChangeListener (this);
|
||||
|
||||
addChildComponent (&gradientPicker);
|
||||
gradientPicker.addChangeListener (this);
|
||||
|
||||
fillState.addListener (this);
|
||||
|
||||
colourButton.setRadioGroupId (123);
|
||||
gradientButton.setRadioGroupId (123);
|
||||
imageButton.setRadioGroupId (123);
|
||||
|
||||
colourButton.addButtonListener (this);
|
||||
gradientButton.addButtonListener (this);
|
||||
imageButton.addButtonListener (this);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
~PopupFillSelector()
|
||||
{
|
||||
colourButton.removeButtonListener (this);
|
||||
gradientButton.removeButtonListener (this);
|
||||
imageButton.removeButtonListener (this);
|
||||
}
|
||||
|
||||
static void showAt (Component* comp, const ValueTree& fill, UndoManager* undoManager)
|
||||
|
|
@ -59,32 +87,84 @@ public:
|
|||
|
||||
void resized()
|
||||
{
|
||||
colourPicker.setBounds (0, 0, getWidth(), getHeight());
|
||||
const int y = 2, w = 80, h = 22;
|
||||
gradientButton.setBounds (getWidth() / 2 - w / 2, y, w, h);
|
||||
colourButton.setBounds (gradientButton.getX() - w, y, w, h);
|
||||
imageButton.setBounds (gradientButton.getRight(), y, w, h);
|
||||
|
||||
const Rectangle<int> content (2, y + h + 4, getWidth() - 4, getHeight() - (y + h + 6));
|
||||
colourPicker.setBounds (content);
|
||||
gradientPicker.setBounds (content);
|
||||
}
|
||||
|
||||
void buttonClicked (Button*)
|
||||
void buttonClicked (Button* b)
|
||||
{
|
||||
if (b == &colourButton)
|
||||
{
|
||||
setFillType (colourPicker.getCurrentColour());
|
||||
}
|
||||
else if (b == &gradientButton)
|
||||
{
|
||||
setFillType (gradientPicker.getGradient());
|
||||
}
|
||||
else if (b == &imageButton)
|
||||
{
|
||||
setFillType (FillType (*StoredSettings::getInstance()->getFallbackImage(),
|
||||
AffineTransform::identity));
|
||||
}
|
||||
}
|
||||
|
||||
void changeListenerCallback (void* source)
|
||||
const FillType readFillType (RelativePoint* gp1, RelativePoint* gp2) const
|
||||
{
|
||||
const FillType currentFill (Drawable::ValueTreeWrapperBase::readFillType (fillState));
|
||||
return Drawable::ValueTreeWrapperBase::readFillType (fillState, gp1, gp2, 0);
|
||||
}
|
||||
|
||||
void setFillType (const FillType& newFill)
|
||||
{
|
||||
RelativePoint gp1, gp2;
|
||||
const FillType currentFill (readFillType (&gp1, &gp2));
|
||||
|
||||
if (currentFill != newFill)
|
||||
{
|
||||
if (undoManager != 0)
|
||||
undoManager->undoCurrentTransactionOnly();
|
||||
|
||||
Drawable::ValueTreeWrapperBase::writeFillType (fillState, newFill, &gp1, &gp2, undoManager);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void changeListenerCallback (void*)
|
||||
{
|
||||
const FillType currentFill (readFillType (0, 0));
|
||||
|
||||
if (currentFill.isColour())
|
||||
{
|
||||
const FillType newFill (colourPicker.getCurrentColour());
|
||||
|
||||
if (currentFill != newFill)
|
||||
Drawable::ValueTreeWrapperBase::writeFillType (fillState, newFill, undoManager);
|
||||
}
|
||||
setFillType (colourPicker.getCurrentColour());
|
||||
else if (currentFill.isGradient())
|
||||
setFillType (gradientPicker.getGradient());
|
||||
}
|
||||
|
||||
void refresh()
|
||||
{
|
||||
const FillType newFill (Drawable::ValueTreeWrapperBase::readFillType (fillState));
|
||||
const FillType newFill (readFillType (0, 0));
|
||||
|
||||
colourPicker.setVisible (newFill.isColour());
|
||||
gradientPicker.setVisible (newFill.isGradient());
|
||||
|
||||
if (newFill.isColour())
|
||||
{
|
||||
colourButton.setToggleState (true, false);
|
||||
colourPicker.setCurrentColour (newFill.colour);
|
||||
}
|
||||
else if (newFill.isGradient())
|
||||
{
|
||||
gradientButton.setToggleState (true, false);
|
||||
gradientPicker.setGradient (*newFill.gradient);
|
||||
}
|
||||
else
|
||||
{
|
||||
imageButton.setToggleState (true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property) { refresh(); }
|
||||
|
|
@ -92,9 +172,215 @@ public:
|
|||
void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) {}
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
class GradientDesigner : public Component,
|
||||
public ChangeBroadcaster,
|
||||
private ChangeListener
|
||||
{
|
||||
public:
|
||||
GradientDesigner()
|
||||
: gradient (Colours::red, 0.0f, 0.0f, Colours::blue, 200.0f, 200.0f, false),
|
||||
selectedPoint (-1),
|
||||
dragging (false),
|
||||
draggingNewPoint (false),
|
||||
draggingPos (0)
|
||||
{
|
||||
addChildComponent (&colourPicker);
|
||||
colourPicker.addChangeListener (this);
|
||||
}
|
||||
|
||||
~GradientDesigner()
|
||||
{
|
||||
}
|
||||
|
||||
void paint (Graphics& g)
|
||||
{
|
||||
g.fillAll (getLookAndFeel().findColour (ColourSelector::backgroundColourId));
|
||||
|
||||
g.fillCheckerBoard (previewArea.getX(), previewArea.getY(),
|
||||
previewArea.getWidth(), previewArea.getHeight(), 10, 10,
|
||||
Colour (0xffdddddd), Colour (0xffffffff));
|
||||
|
||||
FillType f (gradient);
|
||||
f.gradient->point1.setXY ((float) previewArea.getX(), (float) previewArea.getCentreY());
|
||||
f.gradient->point2.setXY ((float) previewArea.getRight(), (float) previewArea.getCentreY());
|
||||
g.setFillType (f);
|
||||
g.fillRect (previewArea);
|
||||
|
||||
Path marker;
|
||||
const float headSize = 4.5f;
|
||||
marker.addLineSegment (0.0f, -2.0f, 0.0f, previewArea.getHeight() + 2.0f, 1.5f);
|
||||
marker.addTriangle (0.0f, 1.0f, -headSize, -headSize, headSize, -headSize);
|
||||
|
||||
for (int i = 0; i < gradient.getNumColours(); ++i)
|
||||
{
|
||||
const double pos = gradient.getColourPosition (i);
|
||||
const Colour col (gradient.getColour (i));
|
||||
|
||||
const AffineTransform t (AffineTransform::translation (previewArea.getX() + 0.5f + (float) (previewArea.getWidth() * pos),
|
||||
(float) previewArea.getY()));
|
||||
|
||||
g.setColour (Colours::black.withAlpha (0.8f));
|
||||
g.strokePath (marker, PathStrokeType (i == selectedPoint ? 2.0f : 1.5f), t);
|
||||
g.setColour (i == selectedPoint ? Colours::lightblue : Colours::white);
|
||||
g.fillPath (marker, t);
|
||||
}
|
||||
}
|
||||
|
||||
void resized()
|
||||
{
|
||||
previewArea.setBounds (7, 8, getWidth() - 14, 24);
|
||||
colourPicker.setBounds (0, previewArea.getBottom() + 8,
|
||||
getWidth(), getHeight() - previewArea.getBottom() - 8);
|
||||
}
|
||||
|
||||
void mouseDown (const MouseEvent& e)
|
||||
{
|
||||
dragging = false;
|
||||
draggingNewPoint = false;
|
||||
int point = getPointAt (e.x);
|
||||
|
||||
if (point >= 0)
|
||||
setSelectedPoint (point);
|
||||
}
|
||||
|
||||
void mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
if ((! dragging) && ! e.mouseWasClicked())
|
||||
{
|
||||
preDragGradient = gradient;
|
||||
const int mouseDownPoint = getPointAt (e.getMouseDownX());
|
||||
|
||||
if (mouseDownPoint >= 0)
|
||||
{
|
||||
if (mouseDownPoint > 0 && mouseDownPoint < gradient.getNumColours() - 1)
|
||||
{
|
||||
dragging = true;
|
||||
draggingNewPoint = false;
|
||||
draggingColour = gradient.getColour (mouseDownPoint);
|
||||
preDragGradient.removeColour (mouseDownPoint);
|
||||
selectedPoint = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dragging = true;
|
||||
draggingNewPoint = true;
|
||||
selectedPoint = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dragging)
|
||||
{
|
||||
draggingPos = jlimit (0.001, 0.999, (e.x - previewArea.getX()) / (double) previewArea.getWidth());
|
||||
gradient = preDragGradient;
|
||||
|
||||
if (previewArea.expanded (6, 6).contains (e.x, e.y))
|
||||
{
|
||||
if (draggingNewPoint)
|
||||
draggingColour = preDragGradient.getColourAtPosition (draggingPos);
|
||||
|
||||
selectedPoint = gradient.addColour (draggingPos, draggingColour);
|
||||
updatePicker();
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedPoint = -1;
|
||||
}
|
||||
|
||||
sendChangeMessage (this);
|
||||
repaint (previewArea.expanded (30, 30));
|
||||
}
|
||||
}
|
||||
|
||||
void mouseUp (const MouseEvent& e)
|
||||
{
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
const ColourGradient& getGradient() const throw() { return gradient; }
|
||||
|
||||
void setGradient (const ColourGradient& newGradient)
|
||||
{
|
||||
if (newGradient != gradient)
|
||||
{
|
||||
gradient = newGradient;
|
||||
|
||||
if (selectedPoint < 0)
|
||||
selectedPoint = 0;
|
||||
|
||||
updatePicker();
|
||||
sendChangeMessage (this);
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void setSelectedPoint (int newIndex)
|
||||
{
|
||||
if (selectedPoint != newIndex)
|
||||
{
|
||||
selectedPoint = newIndex;
|
||||
updatePicker();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void changeListenerCallback (void*)
|
||||
{
|
||||
if (selectedPoint >= 0 && (! dragging) && gradient.getColour (selectedPoint) != colourPicker.getCurrentColour())
|
||||
{
|
||||
gradient.setColour (selectedPoint, colourPicker.getCurrentColour());
|
||||
repaint (previewArea);
|
||||
sendChangeMessage (this);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
StoredSettings::ColourSelectorWithSwatches colourPicker;
|
||||
ColourGradient gradient;
|
||||
int selectedPoint;
|
||||
bool dragging, draggingNewPoint;
|
||||
double draggingPos;
|
||||
Colour draggingColour;
|
||||
ColourGradient preDragGradient;
|
||||
|
||||
Rectangle<int> previewArea;
|
||||
|
||||
void updatePicker()
|
||||
{
|
||||
colourPicker.setVisible (selectedPoint >= 0);
|
||||
if (selectedPoint >= 0)
|
||||
colourPicker.setCurrentColour (gradient.getColour (selectedPoint));
|
||||
}
|
||||
|
||||
int getPointAt (const int x) const
|
||||
{
|
||||
int best = -1;
|
||||
double bestDiff = 6;
|
||||
|
||||
for (int i = gradient.getNumColours(); --i >= 0;)
|
||||
{
|
||||
const double pos = previewArea.getX() + previewArea.getWidth() * gradient.getColourPosition (i);
|
||||
const double diff = std::abs (pos - x);
|
||||
|
||||
if (diff < bestDiff)
|
||||
{
|
||||
bestDiff = diff;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
StoredSettings::ColourSelectorWithSwatches colourPicker;
|
||||
GradientDesigner gradientPicker;
|
||||
ValueTree fillState;
|
||||
UndoManager* undoManager;
|
||||
|
||||
TextButton colourButton, gradientButton, imageButton;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -149,7 +435,7 @@ public:
|
|||
|
||||
void refresh()
|
||||
{
|
||||
const FillType newFill (Drawable::ValueTreeWrapperBase::readFillType (fillState));
|
||||
const FillType newFill (Drawable::ValueTreeWrapperBase::readFillType (fillState, 0, 0, 0));
|
||||
|
||||
if (newFill != fillType)
|
||||
{
|
||||
|
|
@ -185,6 +471,7 @@ public:
|
|||
: PropertyComponent (name),
|
||||
editor (fill, undoManager)
|
||||
{
|
||||
jassert (fill.isValid());
|
||||
addAndMakeVisible (&editor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,3 +134,11 @@ const StringArray& StoredSettings::getFontNames()
|
|||
|
||||
return fontNames;
|
||||
}
|
||||
|
||||
Image* StoredSettings::getFallbackImage()
|
||||
{
|
||||
if (fallbackImage == 0)
|
||||
fallbackImage = ImageFileFormat::loadFrom (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize);
|
||||
|
||||
return fallbackImage;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ public:
|
|||
const File getLastKnownJuceFolder() const;
|
||||
void setLastKnownJuceFolder (const File& file);
|
||||
|
||||
|
||||
const StringArray& getFontNames();
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -69,12 +68,17 @@ public:
|
|||
void setSwatchColour (int index, const Colour& newColour) const { StoredSettings::getInstance()->swatchColours.set (index, newColour); }
|
||||
};
|
||||
|
||||
|
||||
Image* getFallbackImage();
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
ScopedPointer<PropertiesFile> props;
|
||||
StringArray fontNames;
|
||||
|
||||
ScopedPointer<Image> fallbackImage;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -36166,7 +36166,12 @@ void AudioProcessorPlayer::audioDeviceIOCallback (const float** inputChannelData
|
|||
const ScopedLock sl (lock);
|
||||
|
||||
if (processor != 0)
|
||||
processor->processBlock (buffer, incomingMidi);
|
||||
{
|
||||
const ScopedLock sl (processor->getCallbackLock());
|
||||
|
||||
if (! processor->isSuspended())
|
||||
processor->processBlock (buffer, incomingMidi);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* device)
|
||||
|
|
@ -78867,19 +78872,15 @@ ColourGradient::ColourGradient() throw()
|
|||
#endif
|
||||
}
|
||||
|
||||
ColourGradient::ColourGradient (const Colour& colour1,
|
||||
const float x1_,
|
||||
const float y1_,
|
||||
const Colour& colour2,
|
||||
const float x2_,
|
||||
const float y2_,
|
||||
ColourGradient::ColourGradient (const Colour& colour1, const float x1_, const float y1_,
|
||||
const Colour& colour2, const float x2_, const float y2_,
|
||||
const bool isRadial_)
|
||||
: point1 (x1_, y1_),
|
||||
point2 (x2_, y2_),
|
||||
isRadial (isRadial_)
|
||||
{
|
||||
colours.add (ColourPoint (0, colour1));
|
||||
colours.add (ColourPoint (1 << 16, colour2));
|
||||
colours.add (ColourPoint (0.0, colour1));
|
||||
colours.add (ColourPoint (1.0, colour2));
|
||||
}
|
||||
|
||||
ColourGradient::~ColourGradient()
|
||||
|
|
@ -78903,13 +78904,12 @@ void ColourGradient::clearColours()
|
|||
colours.clear();
|
||||
}
|
||||
|
||||
void ColourGradient::addColour (const double proportionAlongGradient,
|
||||
const Colour& colour)
|
||||
int ColourGradient::addColour (const double proportionAlongGradient, const Colour& colour)
|
||||
{
|
||||
// must be within the two end-points
|
||||
jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
|
||||
|
||||
const uint32 pos = jlimit (0, 65535, roundToInt (proportionAlongGradient * 65536.0));
|
||||
const double pos = jlimit (0.0, 1.0, proportionAlongGradient);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < colours.size(); ++i)
|
||||
|
|
@ -78917,6 +78917,13 @@ void ColourGradient::addColour (const double proportionAlongGradient,
|
|||
break;
|
||||
|
||||
colours.insert (i, ColourPoint (pos, colour));
|
||||
return i;
|
||||
}
|
||||
|
||||
void ColourGradient::removeColour (int index)
|
||||
{
|
||||
jassert (index > 0 && index < colours.size() - 1);
|
||||
colours.remove (index);
|
||||
}
|
||||
|
||||
void ColourGradient::multiplyOpacity (const float multiplier) throw()
|
||||
|
|
@ -78936,7 +78943,7 @@ int ColourGradient::getNumColours() const throw()
|
|||
double ColourGradient::getColourPosition (const int index) const throw()
|
||||
{
|
||||
if (((unsigned int) index) < (unsigned int) colours.size())
|
||||
return jlimit (0.0, 1.0, colours.getReference (index).position / 65535.0);
|
||||
return colours.getReference (index).position;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -78949,26 +78956,31 @@ const Colour ColourGradient::getColour (const int index) const throw()
|
|||
return Colour();
|
||||
}
|
||||
|
||||
const Colour ColourGradient::getColourAtPosition (const float position) const throw()
|
||||
void ColourGradient::setColour (int index, const Colour& newColour) throw()
|
||||
{
|
||||
if (((unsigned int) index) < (unsigned int) colours.size())
|
||||
colours.getReference (index).colour = newColour;
|
||||
}
|
||||
|
||||
const Colour ColourGradient::getColourAtPosition (const double position) const throw()
|
||||
{
|
||||
jassert (colours.getReference(0).position == 0); // the first colour specified has to go at position 0
|
||||
|
||||
const int integerPos = jlimit (0, 65535, roundToInt (position * 65536.0f));
|
||||
|
||||
if (integerPos <= 0 || colours.size() <= 1)
|
||||
return getColour (0);
|
||||
if (position <= 0 || colours.size() <= 1)
|
||||
return colours.getReference(0).colour;
|
||||
|
||||
int i = colours.size() - 1;
|
||||
while (integerPos < (int) colours.getReference(i).position)
|
||||
while (position < colours.getReference(i).position)
|
||||
--i;
|
||||
|
||||
if (i >= colours.size() - 1)
|
||||
return colours.getReference(i).colour;
|
||||
|
||||
const ColourPoint& p1 = colours.getReference (i);
|
||||
|
||||
if (i >= colours.size() - 1)
|
||||
return p1.colour;
|
||||
|
||||
const ColourPoint& p2 = colours.getReference (i + 1);
|
||||
|
||||
return p1.colour.interpolatedWith (p2.colour, (integerPos - p1.position) / (float) (p2.position - p1.position));
|
||||
return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
|
||||
}
|
||||
|
||||
int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock <PixelARGB>& lookupTable) const
|
||||
|
|
@ -78994,7 +79006,7 @@ int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlo
|
|||
for (int j = 1; j < colours.size(); ++j)
|
||||
{
|
||||
const ColourPoint& p = colours.getReference (j);
|
||||
const int numToDo = ((p.position * (numEntries - 1)) >> 16) - index;
|
||||
const int numToDo = roundToInt (p.position * (numEntries - 1)) - index;
|
||||
const PixelARGB pix2 (p.colour.getPixelARGB());
|
||||
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
|
|
@ -83854,10 +83866,8 @@ Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* i
|
|||
|
||||
const Identifier Drawable::ValueTreeWrapperBase::idProperty ("id");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::type ("type");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::x1 ("x1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::x2 ("x2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::y1 ("y1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::y2 ("y2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint1 ("point1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint2 ("point2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::colour ("colour");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::radial ("radial");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::colours ("colours");
|
||||
|
|
@ -83884,7 +83894,8 @@ void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* un
|
|||
state.setProperty (idProperty, newID, undoManager);
|
||||
}
|
||||
|
||||
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
||||
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v, RelativePoint* gp1, RelativePoint* gp2,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
const String newType (v[type].toString());
|
||||
|
||||
|
|
@ -83896,9 +83907,17 @@ const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
|||
}
|
||||
else if (newType == "gradient")
|
||||
{
|
||||
RelativePoint p1 (v [gradientPoint1]), p2 (v [gradientPoint2]);
|
||||
|
||||
ColourGradient g;
|
||||
g.point1.setXY (v[x1], v[y1]);
|
||||
g.point2.setXY (v[x2], v[y2]);
|
||||
|
||||
if (gp1 != 0)
|
||||
*gp1 = p1;
|
||||
if (gp2 != 0)
|
||||
*gp2 = p2;
|
||||
|
||||
g.point1 = p1.resolve (nameFinder);
|
||||
g.point2 = p2.resolve (nameFinder);
|
||||
g.isRadial = v[radial];
|
||||
|
||||
StringArray colourSteps;
|
||||
|
|
@ -83919,26 +83938,24 @@ const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
|||
return FillType();
|
||||
}
|
||||
|
||||
void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType& fillType, UndoManager* const undoManager)
|
||||
void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
UndoManager* const undoManager)
|
||||
{
|
||||
if (fillType.isColour())
|
||||
{
|
||||
v.setProperty (type, "solid", undoManager);
|
||||
v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager);
|
||||
v.removeProperty (x1, undoManager);
|
||||
v.removeProperty (x2, undoManager);
|
||||
v.removeProperty (y1, undoManager);
|
||||
v.removeProperty (y2, undoManager);
|
||||
v.removeProperty (gradientPoint1, undoManager);
|
||||
v.removeProperty (gradientPoint2, undoManager);
|
||||
v.removeProperty (radial, undoManager);
|
||||
v.removeProperty (colours, undoManager);
|
||||
}
|
||||
else if (fillType.isGradient())
|
||||
{
|
||||
v.setProperty (type, "gradient", undoManager);
|
||||
v.setProperty (x1, fillType.gradient->point1.getX(), undoManager);
|
||||
v.setProperty (y1, fillType.gradient->point1.getY(), undoManager);
|
||||
v.setProperty (x2, fillType.gradient->point2.getX(), undoManager);
|
||||
v.setProperty (y2, fillType.gradient->point2.getY(), undoManager);
|
||||
v.setProperty (gradientPoint1, gp1 != 0 ? gp1->toString() : fillType.gradient->point1.toString(), undoManager);
|
||||
v.setProperty (gradientPoint2, gp2 != 0 ? gp2->toString() : fillType.gradient->point2.toString(), undoManager);
|
||||
v.setProperty (radial, fillType.gradient->isRadial, undoManager);
|
||||
|
||||
String s;
|
||||
|
|
@ -83955,10 +83972,8 @@ void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType
|
|||
|
||||
jassertfalse; //xxx todo
|
||||
|
||||
v.removeProperty (x1, undoManager);
|
||||
v.removeProperty (x2, undoManager);
|
||||
v.removeProperty (y1, undoManager);
|
||||
v.removeProperty (y2, undoManager);
|
||||
v.removeProperty (gradientPoint1, undoManager);
|
||||
v.removeProperty (gradientPoint2, undoManager);
|
||||
v.removeProperty (radial, undoManager);
|
||||
v.removeProperty (colours, undoManager);
|
||||
v.removeProperty (colour, undoManager);
|
||||
|
|
@ -83969,7 +83984,9 @@ void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType
|
|||
}
|
||||
}
|
||||
|
||||
void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* const undoManager)
|
||||
void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType,
|
||||
const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
UndoManager* const undoManager)
|
||||
{
|
||||
ValueTree v (state.getChildWithName (tag));
|
||||
|
||||
|
|
@ -83979,7 +83996,7 @@ void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, con
|
|||
v = state.getChildWithName (tag);
|
||||
}
|
||||
|
||||
writeFillType (v, fillType, undoManager);
|
||||
writeFillType (v, fillType, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
@ -85114,24 +85131,46 @@ DrawablePath::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
|
|||
jassert (state.hasType (valueTreeType));
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill() const
|
||||
ValueTree DrawablePath::ValueTreeWrapper::getMainFillState()
|
||||
{
|
||||
return readFillType (state.getChildWithName (fill));
|
||||
ValueTree v (state.getChildWithName (fill));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setMainFill (Colours::black, 0, 0, 0);
|
||||
return getMainFillState();
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, UndoManager* undoManager)
|
||||
ValueTree DrawablePath::ValueTreeWrapper::getStrokeFillState()
|
||||
{
|
||||
replaceFillType (fill, newFill, undoManager);
|
||||
ValueTree v (state.getChildWithName (stroke));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setStrokeFill (Colours::black, 0, 0, 0);
|
||||
return getStrokeFillState();
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill() const
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke));
|
||||
return readFillType (state.getChildWithName (fill), 0, 0, nameFinder);
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, UndoManager* undoManager)
|
||||
void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, const RelativePoint* gp1,
|
||||
const RelativePoint* gp2, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (stroke, newFill, undoManager);
|
||||
replaceFillType (fill, newFill, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke), 0, 0, nameFinder);
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, const RelativePoint* gp1,
|
||||
const RelativePoint* gp2, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (stroke, newFill, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
const PathStrokeType DrawablePath::ValueTreeWrapper::getStrokeType() const
|
||||
|
|
@ -85175,7 +85214,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
setName (v.getID());
|
||||
|
||||
bool needsRedraw = false;
|
||||
const FillType newFill (v.getMainFill());
|
||||
const FillType newFill (v.getMainFill (parent));
|
||||
|
||||
if (mainFill != newFill)
|
||||
{
|
||||
|
|
@ -85183,7 +85222,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
mainFill = newFill;
|
||||
}
|
||||
|
||||
const FillType newStrokeFill (v.getStrokeFill());
|
||||
const FillType newStrokeFill (v.getStrokeFill (parent));
|
||||
|
||||
if (strokeFill != newStrokeFill)
|
||||
{
|
||||
|
|
@ -85224,8 +85263,8 @@ const ValueTree DrawablePath::createValueTree (ImageProvider*) const
|
|||
ValueTreeWrapper v (tree);
|
||||
|
||||
v.setID (getName(), 0);
|
||||
v.setMainFill (mainFill, 0);
|
||||
v.setStrokeFill (strokeFill, 0);
|
||||
v.setMainFill (mainFill, 0, 0, 0);
|
||||
v.setStrokeFill (strokeFill, 0, 0, 0);
|
||||
v.setStrokeType (strokeType, 0);
|
||||
|
||||
if (relativePath != 0)
|
||||
|
|
@ -253051,8 +253090,8 @@ public:
|
|||
{
|
||||
//DBG (responseHeader);
|
||||
|
||||
StringArray lines;
|
||||
lines.addLines (responseHeader);
|
||||
headerLines.clear();
|
||||
headerLines.addLines (responseHeader);
|
||||
|
||||
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
|
|
@ -253060,7 +253099,7 @@ public:
|
|||
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
|
||||
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
|
||||
|
||||
String location (findHeaderItem (lines, "Location:"));
|
||||
String location (findHeaderItem (headerLines, "Location:"));
|
||||
|
||||
if (statusCode >= 300 && statusCode < 400
|
||||
&& location.isNotEmpty())
|
||||
|
|
@ -253101,6 +253140,7 @@ public:
|
|||
}
|
||||
|
||||
int readPosition;
|
||||
StringArray headerLines;
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
|
|
@ -253250,13 +253290,11 @@ void* juce_openInternetFile (const String& url,
|
|||
void* callbackContext,
|
||||
int timeOutMs)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream();
|
||||
ScopedPointer<JUCE_HTTPSocketStream> s (new JUCE_HTTPSocketStream());
|
||||
|
||||
if (s->open (url, headers, postData, isPost,
|
||||
callback, callbackContext, timeOutMs))
|
||||
return s;
|
||||
if (s->open (url, headers, postData, isPost, callback, callbackContext, timeOutMs))
|
||||
return s.release();
|
||||
|
||||
delete s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -253267,46 +253305,46 @@ void juce_closeInternetFile (void* handle)
|
|||
|
||||
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
return s->read (buffer, bytesToRead);
|
||||
|
||||
return 0;
|
||||
return s != 0 ? s->read (buffer, bytesToRead) : 0;
|
||||
}
|
||||
|
||||
int64 juce_getInternetFileContentLength (void* handle)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
//xxx todo
|
||||
jassertfalse;
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void juce_getInternetFileHeaders (void* handle, StringPairArray& headers)
|
||||
bool juce_getInternetFileHeaders (void* handle, StringPairArray& headers)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
// xxx todo
|
||||
jassertfalse;
|
||||
for (int i = 0; i < s->headerLines.size(); ++i)
|
||||
{
|
||||
const String& headersEntry = s->headerLines[i];
|
||||
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
|
||||
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
|
||||
const String previousValue (headers [key]);
|
||||
headers.set (key, previousValue.isEmpty() ? value : (previousValue + ";" + value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int juce_seekInInternetFile (void* handle, int newPosition)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
return s->readPosition;
|
||||
|
||||
return 0;
|
||||
return s != 0 ? s->readPosition : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 6
|
||||
#define JUCE_BUILDNUMBER 7
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -23179,9 +23179,13 @@ public:
|
|||
of the distance along the line between the two points
|
||||
at which the colour should occur.
|
||||
@param colour the colour that should be used at this point
|
||||
@returns the index at which the new point was added
|
||||
*/
|
||||
void addColour (double proportionAlongGradient,
|
||||
const Colour& colour);
|
||||
int addColour (double proportionAlongGradient,
|
||||
const Colour& colour);
|
||||
|
||||
/** Removes one of the colours from the gradient. */
|
||||
void removeColour (int index);
|
||||
|
||||
/** Multiplies the alpha value of all the colours by the given scale factor */
|
||||
void multiplyOpacity (float multiplier) throw();
|
||||
|
|
@ -23196,15 +23200,19 @@ public:
|
|||
double getColourPosition (int index) const throw();
|
||||
|
||||
/** Returns the colour that was added with a given index.
|
||||
|
||||
The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0
|
||||
The index is from 0 to getNumColours() - 1.
|
||||
*/
|
||||
const Colour getColour (int index) const throw();
|
||||
|
||||
/** Changes the colour at a given index.
|
||||
The index is from 0 to getNumColours() - 1.
|
||||
*/
|
||||
void setColour (int index, const Colour& newColour) throw();
|
||||
|
||||
/** Returns the an interpolated colour at any position along the gradient.
|
||||
@param position the position along the gradient, between 0 and 1
|
||||
*/
|
||||
const Colour getColourAtPosition (float position) const throw();
|
||||
const Colour getColourAtPosition (double position) const throw();
|
||||
|
||||
/** Creates a set of interpolated premultiplied ARGB values.
|
||||
This will resize the HeapBlock, fill it with the colours, and will return the number of
|
||||
|
|
@ -23237,14 +23245,14 @@ private:
|
|||
{
|
||||
ColourPoint() throw() {}
|
||||
|
||||
ColourPoint (uint32 position_, const Colour& colour_) throw()
|
||||
ColourPoint (const double position_, const Colour& colour_) throw()
|
||||
: position (position_), colour (colour_)
|
||||
{}
|
||||
|
||||
bool operator== (const ColourPoint& other) const throw() { return position == other.position && colour == other.colour; }
|
||||
bool operator!= (const ColourPoint& other) const throw() { return position != other.position || colour != other.colour; }
|
||||
|
||||
uint32 position;
|
||||
double position;
|
||||
Colour colour;
|
||||
};
|
||||
|
||||
|
|
@ -42586,14 +42594,20 @@ public:
|
|||
void setID (const String& newID, UndoManager* undoManager);
|
||||
static const Identifier idProperty;
|
||||
|
||||
static const FillType readFillType (const ValueTree& v);
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType, UndoManager* undoManager);
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1, RelativePoint* gradientPoint2,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
UndoManager* undoManager);
|
||||
|
||||
protected:
|
||||
ValueTree state;
|
||||
static const Identifier type, x1, x2, y1, y2, colour, radial, colours;
|
||||
static const Identifier type, gradientPoint1, gradientPoint2, colour, radial, colours;
|
||||
|
||||
void replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* undoManager);
|
||||
void replaceFillType (const Identifier& tag, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
UndoManager* undoManager);
|
||||
};
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
|
@ -58593,11 +58607,15 @@ public:
|
|||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill() const;
|
||||
void setMainFill (const FillType& newFill, UndoManager* undoManager);
|
||||
const FillType getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill() const;
|
||||
void setStrokeFill (const FillType& newFill, UndoManager* undoManager);
|
||||
const FillType getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, UndoManager* undoManager);
|
||||
|
||||
const PathStrokeType getStrokeType() const;
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,12 @@ void AudioProcessorPlayer::audioDeviceIOCallback (const float** inputChannelData
|
|||
const ScopedLock sl (lock);
|
||||
|
||||
if (processor != 0)
|
||||
processor->processBlock (buffer, incomingMidi);
|
||||
{
|
||||
const ScopedLock sl (processor->getCallbackLock());
|
||||
|
||||
if (! processor->isSuspended())
|
||||
processor->processBlock (buffer, incomingMidi);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioProcessorPlayer::audioDeviceAboutToStart (AudioIODevice* device)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 6
|
||||
#define JUCE_BUILDNUMBER 7
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -38,19 +38,15 @@ ColourGradient::ColourGradient() throw()
|
|||
#endif
|
||||
}
|
||||
|
||||
ColourGradient::ColourGradient (const Colour& colour1,
|
||||
const float x1_,
|
||||
const float y1_,
|
||||
const Colour& colour2,
|
||||
const float x2_,
|
||||
const float y2_,
|
||||
ColourGradient::ColourGradient (const Colour& colour1, const float x1_, const float y1_,
|
||||
const Colour& colour2, const float x2_, const float y2_,
|
||||
const bool isRadial_)
|
||||
: point1 (x1_, y1_),
|
||||
point2 (x2_, y2_),
|
||||
isRadial (isRadial_)
|
||||
{
|
||||
colours.add (ColourPoint (0, colour1));
|
||||
colours.add (ColourPoint (1 << 16, colour2));
|
||||
colours.add (ColourPoint (0.0, colour1));
|
||||
colours.add (ColourPoint (1.0, colour2));
|
||||
}
|
||||
|
||||
ColourGradient::~ColourGradient()
|
||||
|
|
@ -75,13 +71,12 @@ void ColourGradient::clearColours()
|
|||
colours.clear();
|
||||
}
|
||||
|
||||
void ColourGradient::addColour (const double proportionAlongGradient,
|
||||
const Colour& colour)
|
||||
int ColourGradient::addColour (const double proportionAlongGradient, const Colour& colour)
|
||||
{
|
||||
// must be within the two end-points
|
||||
jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);
|
||||
|
||||
const uint32 pos = jlimit (0, 65535, roundToInt (proportionAlongGradient * 65536.0));
|
||||
const double pos = jlimit (0.0, 1.0, proportionAlongGradient);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < colours.size(); ++i)
|
||||
|
|
@ -89,6 +84,13 @@ void ColourGradient::addColour (const double proportionAlongGradient,
|
|||
break;
|
||||
|
||||
colours.insert (i, ColourPoint (pos, colour));
|
||||
return i;
|
||||
}
|
||||
|
||||
void ColourGradient::removeColour (int index)
|
||||
{
|
||||
jassert (index > 0 && index < colours.size() - 1);
|
||||
colours.remove (index);
|
||||
}
|
||||
|
||||
void ColourGradient::multiplyOpacity (const float multiplier) throw()
|
||||
|
|
@ -109,7 +111,7 @@ int ColourGradient::getNumColours() const throw()
|
|||
double ColourGradient::getColourPosition (const int index) const throw()
|
||||
{
|
||||
if (((unsigned int) index) < (unsigned int) colours.size())
|
||||
return jlimit (0.0, 1.0, colours.getReference (index).position / 65535.0);
|
||||
return colours.getReference (index).position;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -122,26 +124,31 @@ const Colour ColourGradient::getColour (const int index) const throw()
|
|||
return Colour();
|
||||
}
|
||||
|
||||
const Colour ColourGradient::getColourAtPosition (const float position) const throw()
|
||||
void ColourGradient::setColour (int index, const Colour& newColour) throw()
|
||||
{
|
||||
if (((unsigned int) index) < (unsigned int) colours.size())
|
||||
colours.getReference (index).colour = newColour;
|
||||
}
|
||||
|
||||
const Colour ColourGradient::getColourAtPosition (const double position) const throw()
|
||||
{
|
||||
jassert (colours.getReference(0).position == 0); // the first colour specified has to go at position 0
|
||||
|
||||
const int integerPos = jlimit (0, 65535, roundToInt (position * 65536.0f));
|
||||
|
||||
if (integerPos <= 0 || colours.size() <= 1)
|
||||
return getColour (0);
|
||||
if (position <= 0 || colours.size() <= 1)
|
||||
return colours.getReference(0).colour;
|
||||
|
||||
int i = colours.size() - 1;
|
||||
while (integerPos < (int) colours.getReference(i).position)
|
||||
while (position < colours.getReference(i).position)
|
||||
--i;
|
||||
|
||||
if (i >= colours.size() - 1)
|
||||
return colours.getReference(i).colour;
|
||||
|
||||
const ColourPoint& p1 = colours.getReference (i);
|
||||
|
||||
if (i >= colours.size() - 1)
|
||||
return p1.colour;
|
||||
|
||||
const ColourPoint& p2 = colours.getReference (i + 1);
|
||||
|
||||
return p1.colour.interpolatedWith (p2.colour, (integerPos - p1.position) / (float) (p2.position - p1.position));
|
||||
return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -168,7 +175,7 @@ int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlo
|
|||
for (int j = 1; j < colours.size(); ++j)
|
||||
{
|
||||
const ColourPoint& p = colours.getReference (j);
|
||||
const int numToDo = ((p.position * (numEntries - 1)) >> 16) - index;
|
||||
const int numToDo = roundToInt (p.position * (numEntries - 1)) - index;
|
||||
const PixelARGB pix2 (p.colour.getPixelARGB());
|
||||
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
|
|
|
|||
|
|
@ -90,9 +90,13 @@ public:
|
|||
of the distance along the line between the two points
|
||||
at which the colour should occur.
|
||||
@param colour the colour that should be used at this point
|
||||
@returns the index at which the new point was added
|
||||
*/
|
||||
void addColour (double proportionAlongGradient,
|
||||
const Colour& colour);
|
||||
int addColour (double proportionAlongGradient,
|
||||
const Colour& colour);
|
||||
|
||||
/** Removes one of the colours from the gradient. */
|
||||
void removeColour (int index);
|
||||
|
||||
/** Multiplies the alpha value of all the colours by the given scale factor */
|
||||
void multiplyOpacity (float multiplier) throw();
|
||||
|
|
@ -108,15 +112,19 @@ public:
|
|||
double getColourPosition (int index) const throw();
|
||||
|
||||
/** Returns the colour that was added with a given index.
|
||||
|
||||
The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0
|
||||
The index is from 0 to getNumColours() - 1.
|
||||
*/
|
||||
const Colour getColour (int index) const throw();
|
||||
|
||||
/** Changes the colour at a given index.
|
||||
The index is from 0 to getNumColours() - 1.
|
||||
*/
|
||||
void setColour (int index, const Colour& newColour) throw();
|
||||
|
||||
/** Returns the an interpolated colour at any position along the gradient.
|
||||
@param position the position along the gradient, between 0 and 1
|
||||
*/
|
||||
const Colour getColourAtPosition (float position) const throw();
|
||||
const Colour getColourAtPosition (double position) const throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a set of interpolated premultiplied ARGB values.
|
||||
|
|
@ -152,14 +160,14 @@ private:
|
|||
{
|
||||
ColourPoint() throw() {}
|
||||
|
||||
ColourPoint (uint32 position_, const Colour& colour_) throw()
|
||||
ColourPoint (const double position_, const Colour& colour_) throw()
|
||||
: position (position_), colour (colour_)
|
||||
{}
|
||||
|
||||
bool operator== (const ColourPoint& other) const throw() { return position == other.position && colour == other.colour; }
|
||||
bool operator!= (const ColourPoint& other) const throw() { return position != other.position || colour != other.colour; }
|
||||
|
||||
uint32 position;
|
||||
double position;
|
||||
Colour colour;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -158,10 +158,8 @@ Drawable* Drawable::createFromValueTree (const ValueTree& tree, ImageProvider* i
|
|||
//==============================================================================
|
||||
const Identifier Drawable::ValueTreeWrapperBase::idProperty ("id");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::type ("type");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::x1 ("x1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::x2 ("x2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::y1 ("y1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::y2 ("y2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint1 ("point1");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::gradientPoint2 ("point2");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::colour ("colour");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::radial ("radial");
|
||||
const Identifier Drawable::ValueTreeWrapperBase::colours ("colours");
|
||||
|
|
@ -188,7 +186,8 @@ void Drawable::ValueTreeWrapperBase::setID (const String& newID, UndoManager* un
|
|||
state.setProperty (idProperty, newID, undoManager);
|
||||
}
|
||||
|
||||
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
||||
const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v, RelativePoint* gp1, RelativePoint* gp2,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder)
|
||||
{
|
||||
const String newType (v[type].toString());
|
||||
|
||||
|
|
@ -200,9 +199,17 @@ const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
|||
}
|
||||
else if (newType == "gradient")
|
||||
{
|
||||
RelativePoint p1 (v [gradientPoint1]), p2 (v [gradientPoint2]);
|
||||
|
||||
ColourGradient g;
|
||||
g.point1.setXY (v[x1], v[y1]);
|
||||
g.point2.setXY (v[x2], v[y2]);
|
||||
|
||||
if (gp1 != 0)
|
||||
*gp1 = p1;
|
||||
if (gp2 != 0)
|
||||
*gp2 = p2;
|
||||
|
||||
g.point1 = p1.resolve (nameFinder);
|
||||
g.point2 = p2.resolve (nameFinder);
|
||||
g.isRadial = v[radial];
|
||||
|
||||
StringArray colourSteps;
|
||||
|
|
@ -223,26 +230,24 @@ const FillType Drawable::ValueTreeWrapperBase::readFillType (const ValueTree& v)
|
|||
return FillType();
|
||||
}
|
||||
|
||||
void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType& fillType, UndoManager* const undoManager)
|
||||
void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
UndoManager* const undoManager)
|
||||
{
|
||||
if (fillType.isColour())
|
||||
{
|
||||
v.setProperty (type, "solid", undoManager);
|
||||
v.setProperty (colour, String::toHexString ((int) fillType.colour.getARGB()), undoManager);
|
||||
v.removeProperty (x1, undoManager);
|
||||
v.removeProperty (x2, undoManager);
|
||||
v.removeProperty (y1, undoManager);
|
||||
v.removeProperty (y2, undoManager);
|
||||
v.removeProperty (gradientPoint1, undoManager);
|
||||
v.removeProperty (gradientPoint2, undoManager);
|
||||
v.removeProperty (radial, undoManager);
|
||||
v.removeProperty (colours, undoManager);
|
||||
}
|
||||
else if (fillType.isGradient())
|
||||
{
|
||||
v.setProperty (type, "gradient", undoManager);
|
||||
v.setProperty (x1, fillType.gradient->point1.getX(), undoManager);
|
||||
v.setProperty (y1, fillType.gradient->point1.getY(), undoManager);
|
||||
v.setProperty (x2, fillType.gradient->point2.getX(), undoManager);
|
||||
v.setProperty (y2, fillType.gradient->point2.getY(), undoManager);
|
||||
v.setProperty (gradientPoint1, gp1 != 0 ? gp1->toString() : fillType.gradient->point1.toString(), undoManager);
|
||||
v.setProperty (gradientPoint2, gp2 != 0 ? gp2->toString() : fillType.gradient->point2.toString(), undoManager);
|
||||
v.setProperty (radial, fillType.gradient->isRadial, undoManager);
|
||||
|
||||
String s;
|
||||
|
|
@ -259,10 +264,8 @@ void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType
|
|||
|
||||
jassertfalse; //xxx todo
|
||||
|
||||
v.removeProperty (x1, undoManager);
|
||||
v.removeProperty (x2, undoManager);
|
||||
v.removeProperty (y1, undoManager);
|
||||
v.removeProperty (y2, undoManager);
|
||||
v.removeProperty (gradientPoint1, undoManager);
|
||||
v.removeProperty (gradientPoint2, undoManager);
|
||||
v.removeProperty (radial, undoManager);
|
||||
v.removeProperty (colours, undoManager);
|
||||
v.removeProperty (colour, undoManager);
|
||||
|
|
@ -273,7 +276,9 @@ void Drawable::ValueTreeWrapperBase::writeFillType (ValueTree& v, const FillType
|
|||
}
|
||||
}
|
||||
|
||||
void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* const undoManager)
|
||||
void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, const FillType& fillType,
|
||||
const RelativePoint* gp1, const RelativePoint* gp2,
|
||||
UndoManager* const undoManager)
|
||||
{
|
||||
ValueTree v (state.getChildWithName (tag));
|
||||
|
||||
|
|
@ -283,7 +288,7 @@ void Drawable::ValueTreeWrapperBase::replaceFillType (const Identifier& tag, con
|
|||
v = state.getChildWithName (tag);
|
||||
}
|
||||
|
||||
writeFillType (v, fillType, undoManager);
|
||||
writeFillType (v, fillType, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -248,14 +248,20 @@ public:
|
|||
void setID (const String& newID, UndoManager* undoManager);
|
||||
static const Identifier idProperty;
|
||||
|
||||
static const FillType readFillType (const ValueTree& v);
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType, UndoManager* undoManager);
|
||||
static const FillType readFillType (const ValueTree& v, RelativePoint* gradientPoint1, RelativePoint* gradientPoint2,
|
||||
RelativeCoordinate::NamedCoordinateFinder* nameFinder);
|
||||
|
||||
static void writeFillType (ValueTree& v, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
UndoManager* undoManager);
|
||||
|
||||
protected:
|
||||
ValueTree state;
|
||||
static const Identifier type, x1, x2, y1, y2, colour, radial, colours;
|
||||
static const Identifier type, gradientPoint1, gradientPoint2, colour, radial, colours;
|
||||
|
||||
void replaceFillType (const Identifier& tag, const FillType& fillType, UndoManager* undoManager);
|
||||
void replaceFillType (const Identifier& tag, const FillType& fillType,
|
||||
const RelativePoint* gradientPoint1, const RelativePoint* gradientPoint2,
|
||||
UndoManager* undoManager);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -197,24 +197,46 @@ DrawablePath::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_)
|
|||
jassert (state.hasType (valueTreeType));
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill() const
|
||||
ValueTree DrawablePath::ValueTreeWrapper::getMainFillState()
|
||||
{
|
||||
return readFillType (state.getChildWithName (fill));
|
||||
ValueTree v (state.getChildWithName (fill));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setMainFill (Colours::black, 0, 0, 0);
|
||||
return getMainFillState();
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, UndoManager* undoManager)
|
||||
ValueTree DrawablePath::ValueTreeWrapper::getStrokeFillState()
|
||||
{
|
||||
replaceFillType (fill, newFill, undoManager);
|
||||
ValueTree v (state.getChildWithName (stroke));
|
||||
if (v.isValid())
|
||||
return v;
|
||||
|
||||
setStrokeFill (Colours::black, 0, 0, 0);
|
||||
return getStrokeFillState();
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill() const
|
||||
const FillType DrawablePath::ValueTreeWrapper::getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke));
|
||||
return readFillType (state.getChildWithName (fill), 0, 0, nameFinder);
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, UndoManager* undoManager)
|
||||
void DrawablePath::ValueTreeWrapper::setMainFill (const FillType& newFill, const RelativePoint* gp1,
|
||||
const RelativePoint* gp2, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (stroke, newFill, undoManager);
|
||||
replaceFillType (fill, newFill, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
const FillType DrawablePath::ValueTreeWrapper::getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const
|
||||
{
|
||||
return readFillType (state.getChildWithName (stroke), 0, 0, nameFinder);
|
||||
}
|
||||
|
||||
void DrawablePath::ValueTreeWrapper::setStrokeFill (const FillType& newFill, const RelativePoint* gp1,
|
||||
const RelativePoint* gp2, UndoManager* undoManager)
|
||||
{
|
||||
replaceFillType (stroke, newFill, gp1, gp2, undoManager);
|
||||
}
|
||||
|
||||
const PathStrokeType DrawablePath::ValueTreeWrapper::getStrokeType() const
|
||||
|
|
@ -258,7 +280,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
setName (v.getID());
|
||||
|
||||
bool needsRedraw = false;
|
||||
const FillType newFill (v.getMainFill());
|
||||
const FillType newFill (v.getMainFill (parent));
|
||||
|
||||
if (mainFill != newFill)
|
||||
{
|
||||
|
|
@ -266,7 +288,7 @@ const Rectangle<float> DrawablePath::refreshFromValueTree (const ValueTree& tree
|
|||
mainFill = newFill;
|
||||
}
|
||||
|
||||
const FillType newStrokeFill (v.getStrokeFill());
|
||||
const FillType newStrokeFill (v.getStrokeFill (parent));
|
||||
|
||||
if (strokeFill != newStrokeFill)
|
||||
{
|
||||
|
|
@ -307,8 +329,8 @@ const ValueTree DrawablePath::createValueTree (ImageProvider*) const
|
|||
ValueTreeWrapper v (tree);
|
||||
|
||||
v.setID (getName(), 0);
|
||||
v.setMainFill (mainFill, 0);
|
||||
v.setStrokeFill (strokeFill, 0);
|
||||
v.setMainFill (mainFill, 0, 0, 0);
|
||||
v.setStrokeFill (strokeFill, 0, 0, 0);
|
||||
v.setStrokeType (strokeType, 0);
|
||||
|
||||
if (relativePath != 0)
|
||||
|
|
|
|||
|
|
@ -128,11 +128,15 @@ public:
|
|||
public:
|
||||
ValueTreeWrapper (const ValueTree& state);
|
||||
|
||||
const FillType getMainFill() const;
|
||||
void setMainFill (const FillType& newFill, UndoManager* undoManager);
|
||||
const FillType getMainFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
ValueTree getMainFillState();
|
||||
void setMainFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, UndoManager* undoManager);
|
||||
|
||||
const FillType getStrokeFill() const;
|
||||
void setStrokeFill (const FillType& newFill, UndoManager* undoManager);
|
||||
const FillType getStrokeFill (RelativeCoordinate::NamedCoordinateFinder* nameFinder) const;
|
||||
ValueTree getStrokeFillState();
|
||||
void setStrokeFill (const FillType& newFill, const RelativePoint* gradientPoint1,
|
||||
const RelativePoint* gradientPoint2, UndoManager* undoManager);
|
||||
|
||||
const PathStrokeType getStrokeType() const;
|
||||
void setStrokeType (const PathStrokeType& newStrokeType, UndoManager* undoManager);
|
||||
|
|
|
|||
|
|
@ -1,482 +1,481 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// (This file gets included by juce_linux_NativeCode.cpp, rather than being
|
||||
// compiled on its own).
|
||||
#if JUCE_INCLUDED_FILE
|
||||
|
||||
|
||||
//==============================================================================
|
||||
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian)
|
||||
{
|
||||
int numResults = 0;
|
||||
|
||||
const int s = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
{
|
||||
char buf [1024];
|
||||
struct ifconf ifc;
|
||||
ifc.ifc_len = sizeof (buf);
|
||||
ifc.ifc_buf = buf;
|
||||
ioctl (s, SIOCGIFCONF, &ifc);
|
||||
|
||||
for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
|
||||
|
||||
if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0
|
||||
&& (ifr.ifr_flags & IFF_LOOPBACK) == 0
|
||||
&& ioctl (s, SIOCGIFHWADDR, &ifr) == 0
|
||||
&& numResults < maxNum)
|
||||
{
|
||||
int64 a = 0;
|
||||
for (int j = 6; --j >= 0;)
|
||||
a = (a << 8) | (uint8) ifr.ifr_hwaddr.sa_data [littleEndian ? j : (5 - j)];
|
||||
|
||||
*addresses++ = a;
|
||||
++numResults;
|
||||
}
|
||||
}
|
||||
|
||||
close (s);
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
|
||||
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
|
||||
const String& emailSubject,
|
||||
const String& bodyText,
|
||||
const StringArray& filesToAttach)
|
||||
{
|
||||
jassertfalse; // xxx todo
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** A HTTP input stream that uses sockets.
|
||||
*/
|
||||
class JUCE_HTTPSocketStream
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JUCE_HTTPSocketStream()
|
||||
: readPosition (0),
|
||||
socketHandle (-1),
|
||||
levelsOfRedirection (0),
|
||||
timeoutSeconds (15)
|
||||
{
|
||||
}
|
||||
|
||||
~JUCE_HTTPSocketStream()
|
||||
{
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool open (const String& url,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost,
|
||||
URL::OpenStreamProgressCallback* callback,
|
||||
void* callbackContext,
|
||||
int timeOutMs)
|
||||
{
|
||||
closeSocket();
|
||||
|
||||
uint32 timeOutTime = Time::getMillisecondCounter();
|
||||
|
||||
if (timeOutMs == 0)
|
||||
timeOutTime += 60000;
|
||||
else if (timeOutMs < 0)
|
||||
timeOutTime = 0xffffffff;
|
||||
else
|
||||
timeOutTime += timeOutMs;
|
||||
|
||||
String hostName, hostPath;
|
||||
int hostPort;
|
||||
|
||||
if (! decomposeURL (url, hostName, hostPath, hostPort))
|
||||
return false;
|
||||
|
||||
const struct hostent* host = 0;
|
||||
int port = 0;
|
||||
|
||||
String proxyName, proxyPath;
|
||||
int proxyPort = 0;
|
||||
|
||||
String proxyURL (getenv ("http_proxy"));
|
||||
if (proxyURL.startsWithIgnoreCase ("http://"))
|
||||
{
|
||||
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
|
||||
return false;
|
||||
|
||||
host = gethostbyname (proxyName.toUTF8());
|
||||
port = proxyPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
host = gethostbyname (hostName.toUTF8());
|
||||
port = hostPort;
|
||||
}
|
||||
|
||||
if (host == 0)
|
||||
return false;
|
||||
|
||||
struct sockaddr_in address;
|
||||
zerostruct (address);
|
||||
memcpy (&address.sin_addr, host->h_addr, host->h_length);
|
||||
address.sin_family = host->h_addrtype;
|
||||
address.sin_port = htons (port);
|
||||
|
||||
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0);
|
||||
|
||||
if (socketHandle == -1)
|
||||
return false;
|
||||
|
||||
int receiveBufferSize = 16384;
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
|
||||
|
||||
#if JUCE_MAC
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
|
||||
#endif
|
||||
|
||||
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort,
|
||||
proxyName, proxyPort,
|
||||
hostPath, url,
|
||||
headers, postData,
|
||||
isPost));
|
||||
size_t totalHeaderSent = 0;
|
||||
|
||||
while (totalHeaderSent < requestHeader.getSize())
|
||||
{
|
||||
if (Time::getMillisecondCounter() > timeOutTime)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
|
||||
|
||||
if (send (socketHandle,
|
||||
((const char*) requestHeader.getData()) + totalHeaderSent,
|
||||
numToSend, 0)
|
||||
!= numToSend)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
totalHeaderSent += numToSend;
|
||||
|
||||
if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize()))
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const String responseHeader (readResponse (timeOutTime));
|
||||
|
||||
if (responseHeader.isNotEmpty())
|
||||
{
|
||||
//DBG (responseHeader);
|
||||
|
||||
StringArray lines;
|
||||
lines.addLines (responseHeader);
|
||||
|
||||
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
|
||||
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
|
||||
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
|
||||
|
||||
String location (findHeaderItem (lines, "Location:"));
|
||||
|
||||
if (statusCode >= 300 && statusCode < 400
|
||||
&& location.isNotEmpty())
|
||||
{
|
||||
if (! location.startsWithIgnoreCase ("http://"))
|
||||
location = "http://" + location;
|
||||
|
||||
if (levelsOfRedirection++ < 3)
|
||||
return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelsOfRedirection = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int read (void* buffer, int bytesToRead)
|
||||
{
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeoutSeconds;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return 0; // (timeout)
|
||||
|
||||
const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
|
||||
readPosition += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int readPosition;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
int socketHandle, levelsOfRedirection;
|
||||
const int timeoutSeconds;
|
||||
|
||||
//==============================================================================
|
||||
void closeSocket()
|
||||
{
|
||||
if (socketHandle >= 0)
|
||||
close (socketHandle);
|
||||
|
||||
socketHandle = -1;
|
||||
}
|
||||
|
||||
const MemoryBlock createRequestHeader (const String& hostName,
|
||||
const int hostPort,
|
||||
const String& proxyName,
|
||||
const int proxyPort,
|
||||
const String& hostPath,
|
||||
const String& originalURL,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost)
|
||||
{
|
||||
String header (isPost ? "POST " : "GET ");
|
||||
|
||||
if (proxyName.isEmpty())
|
||||
{
|
||||
header << hostPath << " HTTP/1.0\r\nHost: "
|
||||
<< hostName << ':' << hostPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
header << originalURL << " HTTP/1.0\r\nHost: "
|
||||
<< proxyName << ':' << proxyPort;
|
||||
}
|
||||
|
||||
header << "\r\nUser-Agent: JUCE/"
|
||||
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION
|
||||
<< "\r\nConnection: Close\r\nContent-Length: "
|
||||
<< postData.getSize() << "\r\n"
|
||||
<< headers << "\r\n";
|
||||
|
||||
MemoryBlock mb;
|
||||
mb.append (header.toUTF8(), (int) strlen (header.toUTF8()));
|
||||
mb.append (postData.getData(), postData.getSize());
|
||||
|
||||
return mb;
|
||||
}
|
||||
|
||||
const String readResponse (const uint32 timeOutTime)
|
||||
{
|
||||
int bytesRead = 0, numConsecutiveLFs = 0;
|
||||
MemoryBlock buffer (1024, true);
|
||||
|
||||
while (numConsecutiveLFs < 2 && bytesRead < 32768
|
||||
&& Time::getMillisecondCounter() <= timeOutTime)
|
||||
{
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeoutSeconds;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return String::empty; // (timeout)
|
||||
|
||||
buffer.ensureSize (bytesRead + 8, true);
|
||||
char* const dest = (char*) buffer.getData() + bytesRead;
|
||||
|
||||
if (recv (socketHandle, dest, 1, 0) == -1)
|
||||
return String::empty;
|
||||
|
||||
const char lastByte = *dest;
|
||||
++bytesRead;
|
||||
|
||||
if (lastByte == '\n')
|
||||
++numConsecutiveLFs;
|
||||
else if (lastByte != '\r')
|
||||
numConsecutiveLFs = 0;
|
||||
}
|
||||
|
||||
const String header (String::fromUTF8 ((const char*) buffer.getData()));
|
||||
|
||||
if (header.startsWithIgnoreCase ("HTTP/"))
|
||||
return header.trimEnd();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool decomposeURL (const String& url,
|
||||
String& host, String& path, int& port)
|
||||
{
|
||||
if (! url.startsWithIgnoreCase ("http://"))
|
||||
return false;
|
||||
|
||||
const int nextSlash = url.indexOfChar (7, '/');
|
||||
int nextColon = url.indexOfChar (7, ':');
|
||||
if (nextColon > nextSlash && nextSlash > 0)
|
||||
nextColon = -1;
|
||||
|
||||
if (nextColon >= 0)
|
||||
{
|
||||
host = url.substring (7, nextColon);
|
||||
|
||||
if (nextSlash >= 0)
|
||||
port = url.substring (nextColon + 1, nextSlash).getIntValue();
|
||||
else
|
||||
port = url.substring (nextColon + 1).getIntValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
port = 80;
|
||||
|
||||
if (nextSlash >= 0)
|
||||
host = url.substring (7, nextSlash);
|
||||
else
|
||||
host = url.substring (7);
|
||||
}
|
||||
|
||||
if (nextSlash >= 0)
|
||||
path = url.substring (nextSlash);
|
||||
else
|
||||
path = "/";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static const String findHeaderItem (const StringArray& lines, const String& itemName)
|
||||
{
|
||||
for (int i = 0; i < lines.size(); ++i)
|
||||
if (lines[i].startsWithIgnoreCase (itemName))
|
||||
return lines[i].substring (itemName.length()).trim();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void* juce_openInternetFile (const String& url,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost,
|
||||
URL::OpenStreamProgressCallback* callback,
|
||||
void* callbackContext,
|
||||
int timeOutMs)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = new JUCE_HTTPSocketStream();
|
||||
|
||||
if (s->open (url, headers, postData, isPost,
|
||||
callback, callbackContext, timeOutMs))
|
||||
return s;
|
||||
|
||||
delete s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void juce_closeInternetFile (void* handle)
|
||||
{
|
||||
delete static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
}
|
||||
|
||||
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
|
||||
if (s != 0)
|
||||
return s->read (buffer, bytesToRead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64 juce_getInternetFileContentLength (void* handle)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
//xxx todo
|
||||
jassertfalse;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void juce_getInternetFileHeaders (void* handle, StringPairArray& headers)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
// xxx todo
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
int juce_seekInInternetFile (void* handle, int newPosition)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = (JUCE_HTTPSocketStream*) handle;
|
||||
|
||||
if (s != 0)
|
||||
return s->readPosition;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// (This file gets included by juce_linux_NativeCode.cpp, rather than being
|
||||
// compiled on its own).
|
||||
#if JUCE_INCLUDED_FILE
|
||||
|
||||
|
||||
//==============================================================================
|
||||
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian)
|
||||
{
|
||||
int numResults = 0;
|
||||
|
||||
const int s = socket (AF_INET, SOCK_DGRAM, 0);
|
||||
if (s != -1)
|
||||
{
|
||||
char buf [1024];
|
||||
struct ifconf ifc;
|
||||
ifc.ifc_len = sizeof (buf);
|
||||
ifc.ifc_buf = buf;
|
||||
ioctl (s, SIOCGIFCONF, &ifc);
|
||||
|
||||
for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name);
|
||||
|
||||
if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0
|
||||
&& (ifr.ifr_flags & IFF_LOOPBACK) == 0
|
||||
&& ioctl (s, SIOCGIFHWADDR, &ifr) == 0
|
||||
&& numResults < maxNum)
|
||||
{
|
||||
int64 a = 0;
|
||||
for (int j = 6; --j >= 0;)
|
||||
a = (a << 8) | (uint8) ifr.ifr_hwaddr.sa_data [littleEndian ? j : (5 - j)];
|
||||
|
||||
*addresses++ = a;
|
||||
++numResults;
|
||||
}
|
||||
}
|
||||
|
||||
close (s);
|
||||
}
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
|
||||
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
|
||||
const String& emailSubject,
|
||||
const String& bodyText,
|
||||
const StringArray& filesToAttach)
|
||||
{
|
||||
jassertfalse; // xxx todo
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** A HTTP input stream that uses sockets.
|
||||
*/
|
||||
class JUCE_HTTPSocketStream
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
JUCE_HTTPSocketStream()
|
||||
: readPosition (0),
|
||||
socketHandle (-1),
|
||||
levelsOfRedirection (0),
|
||||
timeoutSeconds (15)
|
||||
{
|
||||
}
|
||||
|
||||
~JUCE_HTTPSocketStream()
|
||||
{
|
||||
closeSocket();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool open (const String& url,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost,
|
||||
URL::OpenStreamProgressCallback* callback,
|
||||
void* callbackContext,
|
||||
int timeOutMs)
|
||||
{
|
||||
closeSocket();
|
||||
|
||||
uint32 timeOutTime = Time::getMillisecondCounter();
|
||||
|
||||
if (timeOutMs == 0)
|
||||
timeOutTime += 60000;
|
||||
else if (timeOutMs < 0)
|
||||
timeOutTime = 0xffffffff;
|
||||
else
|
||||
timeOutTime += timeOutMs;
|
||||
|
||||
String hostName, hostPath;
|
||||
int hostPort;
|
||||
|
||||
if (! decomposeURL (url, hostName, hostPath, hostPort))
|
||||
return false;
|
||||
|
||||
const struct hostent* host = 0;
|
||||
int port = 0;
|
||||
|
||||
String proxyName, proxyPath;
|
||||
int proxyPort = 0;
|
||||
|
||||
String proxyURL (getenv ("http_proxy"));
|
||||
if (proxyURL.startsWithIgnoreCase ("http://"))
|
||||
{
|
||||
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
|
||||
return false;
|
||||
|
||||
host = gethostbyname (proxyName.toUTF8());
|
||||
port = proxyPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
host = gethostbyname (hostName.toUTF8());
|
||||
port = hostPort;
|
||||
}
|
||||
|
||||
if (host == 0)
|
||||
return false;
|
||||
|
||||
struct sockaddr_in address;
|
||||
zerostruct (address);
|
||||
memcpy (&address.sin_addr, host->h_addr, host->h_length);
|
||||
address.sin_family = host->h_addrtype;
|
||||
address.sin_port = htons (port);
|
||||
|
||||
socketHandle = socket (host->h_addrtype, SOCK_STREAM, 0);
|
||||
|
||||
if (socketHandle == -1)
|
||||
return false;
|
||||
|
||||
int receiveBufferSize = 16384;
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_RCVBUF, (char*) &receiveBufferSize, sizeof (receiveBufferSize));
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_KEEPALIVE, 0, 0);
|
||||
|
||||
#if JUCE_MAC
|
||||
setsockopt (socketHandle, SOL_SOCKET, SO_NOSIGPIPE, 0, 0);
|
||||
#endif
|
||||
|
||||
if (connect (socketHandle, (struct sockaddr*) &address, sizeof (address)) == -1)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort,
|
||||
proxyName, proxyPort,
|
||||
hostPath, url,
|
||||
headers, postData,
|
||||
isPost));
|
||||
size_t totalHeaderSent = 0;
|
||||
|
||||
while (totalHeaderSent < requestHeader.getSize())
|
||||
{
|
||||
if (Time::getMillisecondCounter() > timeOutTime)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent));
|
||||
|
||||
if (send (socketHandle,
|
||||
((const char*) requestHeader.getData()) + totalHeaderSent,
|
||||
numToSend, 0)
|
||||
!= numToSend)
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
totalHeaderSent += numToSend;
|
||||
|
||||
if (callback != 0 && ! callback (callbackContext, totalHeaderSent, requestHeader.getSize()))
|
||||
{
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const String responseHeader (readResponse (timeOutTime));
|
||||
|
||||
if (responseHeader.isNotEmpty())
|
||||
{
|
||||
//DBG (responseHeader);
|
||||
|
||||
headerLines.clear();
|
||||
headerLines.addLines (responseHeader);
|
||||
|
||||
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
|
||||
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
|
||||
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
|
||||
|
||||
String location (findHeaderItem (headerLines, "Location:"));
|
||||
|
||||
if (statusCode >= 300 && statusCode < 400
|
||||
&& location.isNotEmpty())
|
||||
{
|
||||
if (! location.startsWithIgnoreCase ("http://"))
|
||||
location = "http://" + location;
|
||||
|
||||
if (levelsOfRedirection++ < 3)
|
||||
return open (location, headers, postData, isPost, callback, callbackContext, timeOutMs);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelsOfRedirection = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
return false;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int read (void* buffer, int bytesToRead)
|
||||
{
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeoutSeconds;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return 0; // (timeout)
|
||||
|
||||
const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
|
||||
readPosition += bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
int readPosition;
|
||||
StringArray headerLines;
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
int socketHandle, levelsOfRedirection;
|
||||
const int timeoutSeconds;
|
||||
|
||||
//==============================================================================
|
||||
void closeSocket()
|
||||
{
|
||||
if (socketHandle >= 0)
|
||||
close (socketHandle);
|
||||
|
||||
socketHandle = -1;
|
||||
}
|
||||
|
||||
const MemoryBlock createRequestHeader (const String& hostName,
|
||||
const int hostPort,
|
||||
const String& proxyName,
|
||||
const int proxyPort,
|
||||
const String& hostPath,
|
||||
const String& originalURL,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost)
|
||||
{
|
||||
String header (isPost ? "POST " : "GET ");
|
||||
|
||||
if (proxyName.isEmpty())
|
||||
{
|
||||
header << hostPath << " HTTP/1.0\r\nHost: "
|
||||
<< hostName << ':' << hostPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
header << originalURL << " HTTP/1.0\r\nHost: "
|
||||
<< proxyName << ':' << proxyPort;
|
||||
}
|
||||
|
||||
header << "\r\nUser-Agent: JUCE/"
|
||||
<< JUCE_MAJOR_VERSION << '.' << JUCE_MINOR_VERSION
|
||||
<< "\r\nConnection: Close\r\nContent-Length: "
|
||||
<< postData.getSize() << "\r\n"
|
||||
<< headers << "\r\n";
|
||||
|
||||
MemoryBlock mb;
|
||||
mb.append (header.toUTF8(), (int) strlen (header.toUTF8()));
|
||||
mb.append (postData.getData(), postData.getSize());
|
||||
|
||||
return mb;
|
||||
}
|
||||
|
||||
const String readResponse (const uint32 timeOutTime)
|
||||
{
|
||||
int bytesRead = 0, numConsecutiveLFs = 0;
|
||||
MemoryBlock buffer (1024, true);
|
||||
|
||||
while (numConsecutiveLFs < 2 && bytesRead < 32768
|
||||
&& Time::getMillisecondCounter() <= timeOutTime)
|
||||
{
|
||||
fd_set readbits;
|
||||
FD_ZERO (&readbits);
|
||||
FD_SET (socketHandle, &readbits);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeoutSeconds;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
|
||||
return String::empty; // (timeout)
|
||||
|
||||
buffer.ensureSize (bytesRead + 8, true);
|
||||
char* const dest = (char*) buffer.getData() + bytesRead;
|
||||
|
||||
if (recv (socketHandle, dest, 1, 0) == -1)
|
||||
return String::empty;
|
||||
|
||||
const char lastByte = *dest;
|
||||
++bytesRead;
|
||||
|
||||
if (lastByte == '\n')
|
||||
++numConsecutiveLFs;
|
||||
else if (lastByte != '\r')
|
||||
numConsecutiveLFs = 0;
|
||||
}
|
||||
|
||||
const String header (String::fromUTF8 ((const char*) buffer.getData()));
|
||||
|
||||
if (header.startsWithIgnoreCase ("HTTP/"))
|
||||
return header.trimEnd();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool decomposeURL (const String& url,
|
||||
String& host, String& path, int& port)
|
||||
{
|
||||
if (! url.startsWithIgnoreCase ("http://"))
|
||||
return false;
|
||||
|
||||
const int nextSlash = url.indexOfChar (7, '/');
|
||||
int nextColon = url.indexOfChar (7, ':');
|
||||
if (nextColon > nextSlash && nextSlash > 0)
|
||||
nextColon = -1;
|
||||
|
||||
if (nextColon >= 0)
|
||||
{
|
||||
host = url.substring (7, nextColon);
|
||||
|
||||
if (nextSlash >= 0)
|
||||
port = url.substring (nextColon + 1, nextSlash).getIntValue();
|
||||
else
|
||||
port = url.substring (nextColon + 1).getIntValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
port = 80;
|
||||
|
||||
if (nextSlash >= 0)
|
||||
host = url.substring (7, nextSlash);
|
||||
else
|
||||
host = url.substring (7);
|
||||
}
|
||||
|
||||
if (nextSlash >= 0)
|
||||
path = url.substring (nextSlash);
|
||||
else
|
||||
path = "/";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static const String findHeaderItem (const StringArray& lines, const String& itemName)
|
||||
{
|
||||
for (int i = 0; i < lines.size(); ++i)
|
||||
if (lines[i].startsWithIgnoreCase (itemName))
|
||||
return lines[i].substring (itemName.length()).trim();
|
||||
|
||||
return String::empty;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
void* juce_openInternetFile (const String& url,
|
||||
const String& headers,
|
||||
const MemoryBlock& postData,
|
||||
const bool isPost,
|
||||
URL::OpenStreamProgressCallback* callback,
|
||||
void* callbackContext,
|
||||
int timeOutMs)
|
||||
{
|
||||
ScopedPointer<JUCE_HTTPSocketStream> s (new JUCE_HTTPSocketStream());
|
||||
|
||||
if (s->open (url, headers, postData, isPost, callback, callbackContext, timeOutMs))
|
||||
return s.release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void juce_closeInternetFile (void* handle)
|
||||
{
|
||||
delete static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
}
|
||||
|
||||
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
return s != 0 ? s->read (buffer, bytesToRead) : 0;
|
||||
}
|
||||
|
||||
int64 juce_getInternetFileContentLength (void* handle)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
//xxx todo
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool juce_getInternetFileHeaders (void* handle, StringPairArray& headers)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
if (s != 0)
|
||||
{
|
||||
for (int i = 0; i < s->headerLines.size(); ++i)
|
||||
{
|
||||
const String& headersEntry = s->headerLines[i];
|
||||
const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false));
|
||||
const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false));
|
||||
const String previousValue (headers [key]);
|
||||
headers.set (key, previousValue.isEmpty() ? value : (previousValue + ";" + value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int juce_seekInInternetFile (void* handle, int newPosition)
|
||||
{
|
||||
JUCE_HTTPSocketStream* const s = static_cast <JUCE_HTTPSocketStream*> (handle);
|
||||
|
||||
return s != 0 ? s->readPosition : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue