@@ -490,6 +490,7 @@ | |||
F77C9170829579FABA5679AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DynamicObject.cpp; path = ../../src/containers/juce_DynamicObject.cpp; sourceTree = SOURCE_ROOT; }; | |||
34C402EF9ADCAD34FB657D43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DynamicObject.h; path = ../../src/containers/juce_DynamicObject.h; sourceTree = SOURCE_ROOT; }; | |||
7DA9AC75A4D9227C8FC4B2F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ElementComparator.h; path = ../../src/containers/juce_ElementComparator.h; sourceTree = SOURCE_ROOT; }; | |||
9289A1E6B141F24C57FF0927 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_LinkedListPointer.h; path = ../../src/containers/juce_LinkedListPointer.h; sourceTree = SOURCE_ROOT; }; | |||
70E5409425A76782B6188B31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_NamedValueSet.cpp; path = ../../src/containers/juce_NamedValueSet.cpp; sourceTree = SOURCE_ROOT; }; | |||
BB4A73064B0FC74ECCA19116 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NamedValueSet.h; path = ../../src/containers/juce_NamedValueSet.h; sourceTree = SOURCE_ROOT; }; | |||
C1913C90ED7BE51E823887CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_OwnedArray.h; path = ../../src/containers/juce_OwnedArray.h; sourceTree = SOURCE_ROOT; }; | |||
@@ -1217,6 +1218,7 @@ | |||
F77C9170829579FABA5679AD, | |||
34C402EF9ADCAD34FB657D43, | |||
7DA9AC75A4D9227C8FC4B2F7, | |||
9289A1E6B141F24C57FF0927, | |||
70E5409425A76782B6188B31, | |||
BB4A73064B0FC74ECCA19116, | |||
C1913C90ED7BE51E823887CD, | |||
@@ -353,6 +353,7 @@ | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | |||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/> | |||
<File RelativePath="..\..\src\containers\juce_LinkedListPointer.h"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | |||
<File RelativePath="..\..\src\containers\juce_OwnedArray.h"/> | |||
@@ -353,6 +353,7 @@ | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | |||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/> | |||
<File RelativePath="..\..\src\containers\juce_LinkedListPointer.h"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | |||
<File RelativePath="..\..\src\containers\juce_OwnedArray.h"/> | |||
@@ -355,6 +355,7 @@ | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | |||
<File RelativePath="..\..\src\containers\juce_ElementComparator.h"/> | |||
<File RelativePath="..\..\src\containers\juce_LinkedListPointer.h"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.cpp"/> | |||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | |||
<File RelativePath="..\..\src\containers\juce_OwnedArray.h"/> | |||
@@ -509,6 +509,7 @@ | |||
<ClInclude Include="..\..\src\containers\juce_ArrayAllocationBase.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_DynamicObject.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_LinkedListPointer.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_NamedValueSet.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_OwnedArray.h"/> | |||
<ClInclude Include="..\..\src\containers\juce_PropertySet.h"/> | |||
@@ -1455,6 +1455,9 @@ | |||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.h"> | |||
<Filter>Juce\Source\containers</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\..\src\containers\juce_LinkedListPointer.h"> | |||
<Filter>Juce\Source\containers</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\..\src\containers\juce_NamedValueSet.h"> | |||
<Filter>Juce\Source\containers</Filter> | |||
</ClInclude> | |||
@@ -490,6 +490,7 @@ | |||
F77C9170829579FABA5679AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DynamicObject.cpp; path = ../../src/containers/juce_DynamicObject.cpp; sourceTree = SOURCE_ROOT; }; | |||
34C402EF9ADCAD34FB657D43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_DynamicObject.h; path = ../../src/containers/juce_DynamicObject.h; sourceTree = SOURCE_ROOT; }; | |||
7DA9AC75A4D9227C8FC4B2F7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ElementComparator.h; path = ../../src/containers/juce_ElementComparator.h; sourceTree = SOURCE_ROOT; }; | |||
9289A1E6B141F24C57FF0927 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_LinkedListPointer.h; path = ../../src/containers/juce_LinkedListPointer.h; sourceTree = SOURCE_ROOT; }; | |||
70E5409425A76782B6188B31 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_NamedValueSet.cpp; path = ../../src/containers/juce_NamedValueSet.cpp; sourceTree = SOURCE_ROOT; }; | |||
BB4A73064B0FC74ECCA19116 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_NamedValueSet.h; path = ../../src/containers/juce_NamedValueSet.h; sourceTree = SOURCE_ROOT; }; | |||
C1913C90ED7BE51E823887CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_OwnedArray.h; path = ../../src/containers/juce_OwnedArray.h; sourceTree = SOURCE_ROOT; }; | |||
@@ -1217,6 +1218,7 @@ | |||
F77C9170829579FABA5679AD, | |||
34C402EF9ADCAD34FB657D43, | |||
7DA9AC75A4D9227C8FC4B2F7, | |||
9289A1E6B141F24C57FF0927, | |||
70E5409425A76782B6188B31, | |||
BB4A73064B0FC74ECCA19116, | |||
C1913C90ED7BE51E823887CD, | |||
@@ -365,6 +365,8 @@ | |||
file="src/containers/juce_DynamicObject.h"/> | |||
<FILE id="RNHQjBFmS" name="juce_ElementComparator.h" compile="0" resource="0" | |||
file="src/containers/juce_ElementComparator.h"/> | |||
<FILE id="pnNXeAf" name="juce_LinkedListPointer.h" compile="0" resource="0" | |||
file="src/containers/juce_LinkedListPointer.h"/> | |||
<FILE id="zy1yAvLC1" name="juce_NamedValueSet.cpp" compile="1" resource="0" | |||
file="src/containers/juce_NamedValueSet.cpp"/> | |||
<FILE id="YIzV0n7ns" name="juce_NamedValueSet.h" compile="0" resource="0" | |||
@@ -64,7 +64,7 @@ | |||
*/ | |||
#define JUCE_MAJOR_VERSION 1 | |||
#define JUCE_MINOR_VERSION 52 | |||
#define JUCE_BUILDNUMBER 110 | |||
#define JUCE_BUILDNUMBER 111 | |||
/** Current Juce version number. | |||
@@ -6624,6 +6624,325 @@ private: | |||
#endif | |||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ | |||
#endif | |||
#ifndef __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
/*** Start of inlined file: juce_LinkedListPointer.h ***/ | |||
#ifndef __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
#define __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
/** | |||
Helps to manipulate singly-linked lists of objects. | |||
For objects that are designed to contain a pointer to the subsequent item in the | |||
list, this class contains methods to deal with the list. To use it, the ObjectType | |||
class that it points to must contain a LinkedListPointer called nextListItem, e.g. | |||
@code | |||
struct MyObject | |||
{ | |||
int x, y, z; | |||
// A linkable object must contain a member with this name and type, which must be | |||
// accessible by the LinkedListPointer class. (This doesn't mean it has to be public - | |||
// you could make your class a friend of a LinkedListPointer<MyObject> instead). | |||
LinkedListPointer<MyObject> nextListItem; | |||
}; | |||
LinkedListPointer<MyObject> myList; | |||
myList.append (new MyObject()); | |||
myList.append (new MyObject()); | |||
int numItems = myList.size(); // returns 2 | |||
MyObject* lastInList = myList.getLast(); | |||
@endcode | |||
*/ | |||
template <class ObjectType> | |||
class LinkedListPointer | |||
{ | |||
public: | |||
/** Creates a null pointer to an empty list. */ | |||
LinkedListPointer() throw() | |||
: item (0) | |||
{ | |||
} | |||
/** Creates a pointer to a list whose head is the item provided. */ | |||
explicit LinkedListPointer (ObjectType* const headItem) throw() | |||
: item (headItem) | |||
{ | |||
} | |||
/** Sets this pointer to point to a new list. */ | |||
LinkedListPointer& operator= (ObjectType* const newItem) throw() | |||
{ | |||
item = newItem; | |||
return *this; | |||
} | |||
/** Returns the item which this pointer points to. */ | |||
inline operator ObjectType*() const throw() | |||
{ | |||
return item; | |||
} | |||
/** Returns the item which this pointer points to. */ | |||
inline ObjectType* get() const throw() | |||
{ | |||
return item; | |||
} | |||
/** Returns the last item in the list which this pointer points to. | |||
This will iterate the list and return the last item found. Obviously the speed | |||
of this operation will be proportional to the size of the list. If the list is | |||
empty the return value will be this object. | |||
If you're planning on appending a number of items to your list, it's much more | |||
efficient to use the Appender class than to repeatedly call getLast() to find the end. | |||
*/ | |||
LinkedListPointer& getLast() throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns the number of items in the list. | |||
Obviously with a simple linked list, getting the size involves iterating the list, so | |||
this can be a lengthy operation - be careful when using this method in your code. | |||
*/ | |||
int size() const throw() | |||
{ | |||
int total = 0; | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
++total; | |||
return total; | |||
} | |||
/** Returns the item at a given index in the list. | |||
Since the only way to find an item is to iterate the list, this operation can obviously | |||
be slow, depending on its size, so you should be careful when using this in algorithms. | |||
*/ | |||
LinkedListPointer& operator[] (int index) throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (--index >= 0 && l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns the item at a given index in the list. | |||
Since the only way to find an item is to iterate the list, this operation can obviously | |||
be slow, depending on its size, so you should be careful when using this in algorithms. | |||
*/ | |||
const LinkedListPointer& operator[] (int index) const throw() | |||
{ | |||
const LinkedListPointer* l = this; | |||
while (--index >= 0 && l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns true if the list contains the given item. */ | |||
bool contains (const ObjectType* const itemToLookFor) const throw() | |||
{ | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
if (itemToLookFor == i) | |||
return true; | |||
return false; | |||
} | |||
/** Inserts an item into the list, placing it before the item that this pointer | |||
currently points to. | |||
*/ | |||
void insertNext (ObjectType* const newItem) | |||
{ | |||
jassert (newItem != 0); | |||
jassert (newItem->nextListItem == 0); | |||
newItem->nextListItem = item; | |||
item = newItem; | |||
} | |||
/** Inserts an item at a numeric index in the list. | |||
Obviously this will involve iterating the list to find the item at the given index, | |||
so be careful about the impact this may have on execution time. | |||
*/ | |||
void insertAtIndex (int index, ObjectType* newItem) | |||
{ | |||
jassert (newItem != 0); | |||
LinkedListPointer* l = this; | |||
while (index != 0 && l->item != 0) | |||
{ | |||
l = &(l->item->nextListItem); | |||
--index; | |||
} | |||
l->insertNext (newItem); | |||
} | |||
/** Replaces the object that this pointer points to, appending the rest of the list to | |||
the new object, and returning the old one. | |||
*/ | |||
ObjectType* replaceNext (ObjectType* const newItem) throw() | |||
{ | |||
jassert (newItem != 0); | |||
jassert (newItem->nextListItem == 0); | |||
ObjectType* const oldItem = item; | |||
item = newItem; | |||
item->nextListItem = oldItem->nextListItem; | |||
oldItem->nextListItem = 0; | |||
return oldItem; | |||
} | |||
/** Adds an item to the end of the list. | |||
This operation involves iterating the whole list, so can be slow - if you need to | |||
append a number of items to your list, it's much more efficient to use the Appender | |||
class than to repeatedly call append(). | |||
*/ | |||
void append (ObjectType* const newItem) | |||
{ | |||
getLast().item = newItem; | |||
} | |||
/** Creates copies of all the items in another list and adds them to this one. | |||
This will use the ObjectType's copy constructor to try to create copies of each | |||
item in the other list, and appends them to this list. | |||
*/ | |||
void addCopyOfList (const LinkedListPointer& other) | |||
{ | |||
LinkedListPointer* insertPoint = this; | |||
for (ObjectType* i = other.item; i != 0; i = i->nextListItem) | |||
{ | |||
insertPoint->insertNext (new ObjectType (*i)); | |||
insertPoint = &(insertPoint->item->nextListItem); | |||
} | |||
} | |||
/** Removes the head item from the list. | |||
This won't delete the object that is removed, but returns it, so the caller can | |||
delete it if necessary. | |||
*/ | |||
ObjectType* removeNext() throw() | |||
{ | |||
if (item == 0) | |||
return 0; | |||
ObjectType* const oldItem = item; | |||
oldItem->nextListItem = 0; | |||
item = item->nextListItem; | |||
return oldItem; | |||
} | |||
/** Removes a specific item from the list. | |||
Note that this will not delete the item, it simply unlinks it from the list. | |||
*/ | |||
void remove (ObjectType* const item) | |||
{ | |||
LinkedListPointer* l = findPointerTo (item); | |||
if (l != 0) | |||
l->removeNext(); | |||
} | |||
/** Iterates the list, calling the delete operator on all of its elements and | |||
leaving this pointer empty. | |||
*/ | |||
void deleteAll() | |||
{ | |||
while (item != 0) | |||
{ | |||
ObjectType* const oldItem = item; | |||
item = oldItem->nextListItem; | |||
delete oldItem; | |||
} | |||
} | |||
/** Finds a pointer to a given item. | |||
If the item is found in the list, this returns the pointer that points to it. If | |||
the item isn't found, this returns null. | |||
*/ | |||
LinkedListPointer* findPointerTo (ObjectType* const itemToLookFor) throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (l->item != 0) | |||
{ | |||
if (l->item == itemToLookFor) | |||
return l; | |||
l = &(l->item->nextListItem); | |||
} | |||
return 0; | |||
} | |||
/** Copies the items in the list to an array. | |||
The destArray must contain enough elements to hold the entire list - no checks are | |||
made for this! | |||
*/ | |||
void copyToArray (ObjectType** destArray) const throw() | |||
{ | |||
jassert (destArray != 0); | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
*destArray++ = i; | |||
} | |||
/** | |||
Allows efficient repeated insertions into a list. | |||
You can create an Appender object which points to the last element in your | |||
list, and then repeatedly call Appender::append() to add items to the end | |||
of the list in O(1) time. | |||
*/ | |||
class Appender | |||
{ | |||
public: | |||
/** Creates an appender which will add items to the given list. | |||
*/ | |||
Appender (LinkedListPointer& endOfListPointer) throw() | |||
: endOfList (&endOfListPointer) | |||
{ | |||
// This can only be used to add to the end of a list. | |||
jassert (endOfListPointer.item == 0); | |||
} | |||
/** Appends an item to the list. */ | |||
void append (ObjectType* const newItem) throw() | |||
{ | |||
*endOfList = newItem; | |||
endOfList = &(newItem->nextListItem); | |||
} | |||
private: | |||
LinkedListPointer* endOfList; | |||
JUCE_DECLARE_NON_COPYABLE (Appender); | |||
}; | |||
private: | |||
ObjectType* item; | |||
}; | |||
#endif // __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
/*** End of inlined file: juce_LinkedListPointer.h ***/ | |||
#endif | |||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | |||
@@ -9835,7 +10154,7 @@ public: | |||
@see getNextElement, isTextElement, forEachXmlChildElement | |||
*/ | |||
inline XmlElement* getNextElement() const throw() { return nextElement; } | |||
inline XmlElement* getNextElement() const throw() { return nextListItem; } | |||
/** Returns the next of this element's siblings which has the specified tag | |||
name. | |||
@@ -10070,8 +10389,9 @@ private: | |||
friend class XmlDocument; | |||
String tagName; | |||
XmlElement* firstChildElement; | |||
XmlElement* nextElement; | |||
friend class LinkedListPointer <XmlElement>; | |||
LinkedListPointer <XmlElement> firstChildElement; | |||
LinkedListPointer <XmlElement> nextListItem; | |||
struct XmlAttributeNode | |||
{ | |||
@@ -10079,7 +10399,7 @@ private: | |||
XmlAttributeNode (const String& name, const String& value) throw(); | |||
String name, value; | |||
XmlAttributeNode* next; | |||
LinkedListPointer<XmlAttributeNode> nextListItem; | |||
bool hasName (const String& name) const throw(); | |||
@@ -10087,7 +10407,8 @@ private: | |||
XmlAttributeNode& operator= (const XmlAttributeNode&); | |||
}; | |||
XmlAttributeNode* attributes; | |||
friend class LinkedListPointer<XmlAttributeNode>; | |||
LinkedListPointer <XmlAttributeNode> attributes; | |||
XmlElement (int) throw(); | |||
void copyChildrenAndAttributesFrom (const XmlElement& other); | |||
@@ -28618,9 +28939,10 @@ private: | |||
void internalMouseMove (MouseInputSource& source, const Point<int>& relativePos, const Time& time); | |||
void internalMouseWheel (MouseInputSource& source, const Point<int>& relativePos, const Time& time, float amountX, float amountY); | |||
void internalBroughtToFront(); | |||
void internalFocusGain (const FocusChangeType cause, const WeakReference<Component>&); | |||
void internalFocusGain (const FocusChangeType cause); | |||
void internalFocusLoss (const FocusChangeType cause); | |||
void internalChildFocusChange (FocusChangeType cause); | |||
void internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>&); | |||
void internalModalInputAttempt(); | |||
void internalModifierKeysChanged(); | |||
void internalChildrenChanged(); | |||
@@ -53892,11 +54214,6 @@ private: | |||
#define __JUCE_DOCUMENTWINDOW_JUCEHEADER__ | |||
/*** Start of inlined file: juce_MenuBarComponent.h ***/ | |||
#ifndef __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
#define __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
/*** Start of inlined file: juce_MenuBarModel.h ***/ | |||
#ifndef __JUCE_MENUBARMODEL_JUCEHEADER__ | |||
#define __JUCE_MENUBARMODEL_JUCEHEADER__ | |||
@@ -54043,97 +54360,6 @@ typedef MenuBarModel::Listener MenuBarModelListener; | |||
#endif // __JUCE_MENUBARMODEL_JUCEHEADER__ | |||
/*** End of inlined file: juce_MenuBarModel.h ***/ | |||
/** | |||
A menu bar component. | |||
@see MenuBarModel | |||
*/ | |||
class JUCE_API MenuBarComponent : public Component, | |||
private MenuBarModel::Listener, | |||
private Timer | |||
{ | |||
public: | |||
/** Creates a menu bar. | |||
@param model the model object to use to control this bar. You can | |||
pass 0 into this if you like, and set the model later | |||
using the setModel() method | |||
*/ | |||
MenuBarComponent (MenuBarModel* model); | |||
/** Destructor. */ | |||
~MenuBarComponent(); | |||
/** Changes the model object to use to control the bar. | |||
This can be 0, in which case the bar will be empty. Don't delete the object | |||
that is passed-in while it's still being used by this MenuBar. | |||
*/ | |||
void setModel (MenuBarModel* newModel); | |||
/** Returns the current menu bar model being used. | |||
*/ | |||
MenuBarModel* getModel() const throw(); | |||
/** Pops up one of the menu items. | |||
This lets you manually open one of the menus - it could be triggered by a | |||
key shortcut, for example. | |||
*/ | |||
void showMenu (int menuIndex); | |||
/** @internal */ | |||
void paint (Graphics& g); | |||
/** @internal */ | |||
void resized(); | |||
/** @internal */ | |||
void mouseEnter (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseExit (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseDown (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseDrag (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseUp (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseMove (const MouseEvent& e); | |||
/** @internal */ | |||
void handleCommandMessage (int commandId); | |||
/** @internal */ | |||
bool keyPressed (const KeyPress& key); | |||
/** @internal */ | |||
void menuBarItemsChanged (MenuBarModel* menuBarModel); | |||
/** @internal */ | |||
void menuCommandInvoked (MenuBarModel* menuBarModel, | |||
const ApplicationCommandTarget::InvocationInfo& info); | |||
private: | |||
class AsyncCallback; | |||
friend class AsyncCallback; | |||
MenuBarModel* model; | |||
StringArray menuNames; | |||
Array <int> xPositions; | |||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked; | |||
int lastMouseX, lastMouseY; | |||
int getItemAt (int x, int y); | |||
void setItemUnderMouse (int index); | |||
void setOpenItem (int index); | |||
void updateItemUnderMouse (int x, int y); | |||
void timerCallback(); | |||
void repaintMenuItem (int index); | |||
void menuDismissed (int topLevelIndex, int itemId); | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarComponent); | |||
}; | |||
#endif // __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
/*** End of inlined file: juce_MenuBarComponent.h ***/ | |||
/** | |||
A resizable window with a title bar and maximise, minimise and close buttons. | |||
@@ -54256,6 +54482,17 @@ public: | |||
void setMenuBar (MenuBarModel* menuBarModel, | |||
int menuBarHeight = 0); | |||
/** Returns the current menu bar component, or null if there isn't one. | |||
This is probably a MenuBarComponent, unless a custom one has been set using | |||
setMenuBarComponent(). | |||
*/ | |||
Component* getMenuBarComponent() const throw(); | |||
/** Replaces the current menu bar with a custom component. | |||
The component will be owned and deleted by the document window. | |||
*/ | |||
void setMenuBarComponent (Component* newMenuBarComponent); | |||
/** This method is called when the user tries to close the window. | |||
This is triggered by the user clicking the close button, or using some other | |||
@@ -54344,7 +54581,7 @@ private: | |||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | |||
ScopedPointer <Button> titleBarButtons [3]; | |||
Image titleBarIcon; | |||
ScopedPointer <MenuBarComponent> menuBar; | |||
ScopedPointer <Component> menuBar; | |||
MenuBarModel* menuBarModel; | |||
class ButtonListenerProxy; | |||
@@ -56229,6 +56466,102 @@ private: | |||
#endif | |||
#ifndef __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
/*** Start of inlined file: juce_MenuBarComponent.h ***/ | |||
#ifndef __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
#define __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
/** | |||
A menu bar component. | |||
@see MenuBarModel | |||
*/ | |||
class JUCE_API MenuBarComponent : public Component, | |||
private MenuBarModel::Listener, | |||
private Timer | |||
{ | |||
public: | |||
/** Creates a menu bar. | |||
@param model the model object to use to control this bar. You can | |||
pass 0 into this if you like, and set the model later | |||
using the setModel() method | |||
*/ | |||
MenuBarComponent (MenuBarModel* model); | |||
/** Destructor. */ | |||
~MenuBarComponent(); | |||
/** Changes the model object to use to control the bar. | |||
This can be 0, in which case the bar will be empty. Don't delete the object | |||
that is passed-in while it's still being used by this MenuBar. | |||
*/ | |||
void setModel (MenuBarModel* newModel); | |||
/** Returns the current menu bar model being used. | |||
*/ | |||
MenuBarModel* getModel() const throw(); | |||
/** Pops up one of the menu items. | |||
This lets you manually open one of the menus - it could be triggered by a | |||
key shortcut, for example. | |||
*/ | |||
void showMenu (int menuIndex); | |||
/** @internal */ | |||
void paint (Graphics& g); | |||
/** @internal */ | |||
void resized(); | |||
/** @internal */ | |||
void mouseEnter (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseExit (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseDown (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseDrag (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseUp (const MouseEvent& e); | |||
/** @internal */ | |||
void mouseMove (const MouseEvent& e); | |||
/** @internal */ | |||
void handleCommandMessage (int commandId); | |||
/** @internal */ | |||
bool keyPressed (const KeyPress& key); | |||
/** @internal */ | |||
void menuBarItemsChanged (MenuBarModel* menuBarModel); | |||
/** @internal */ | |||
void menuCommandInvoked (MenuBarModel* menuBarModel, | |||
const ApplicationCommandTarget::InvocationInfo& info); | |||
private: | |||
class AsyncCallback; | |||
friend class AsyncCallback; | |||
MenuBarModel* model; | |||
StringArray menuNames; | |||
Array <int> xPositions; | |||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked; | |||
int lastMouseX, lastMouseY; | |||
int getItemAt (int x, int y); | |||
void setItemUnderMouse (int index); | |||
void setOpenItem (int index); | |||
void updateItemUnderMouse (int x, int y); | |||
void timerCallback(); | |||
void repaintMenuItem (int index); | |||
void menuDismissed (int topLevelIndex, int itemId); | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarComponent); | |||
}; | |||
#endif // __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | |||
/*** End of inlined file: juce_MenuBarComponent.h ***/ | |||
#endif | |||
#ifndef __JUCE_MENUBARMODEL_JUCEHEADER__ | |||
@@ -0,0 +1,343 @@ | |||
/* | |||
============================================================================== | |||
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. | |||
============================================================================== | |||
*/ | |||
#ifndef __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
#define __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
//============================================================================== | |||
/** | |||
Helps to manipulate singly-linked lists of objects. | |||
For objects that are designed to contain a pointer to the subsequent item in the | |||
list, this class contains methods to deal with the list. To use it, the ObjectType | |||
class that it points to must contain a LinkedListPointer called nextListItem, e.g. | |||
@code | |||
struct MyObject | |||
{ | |||
int x, y, z; | |||
// A linkable object must contain a member with this name and type, which must be | |||
// accessible by the LinkedListPointer class. (This doesn't mean it has to be public - | |||
// you could make your class a friend of a LinkedListPointer<MyObject> instead). | |||
LinkedListPointer<MyObject> nextListItem; | |||
}; | |||
LinkedListPointer<MyObject> myList; | |||
myList.append (new MyObject()); | |||
myList.append (new MyObject()); | |||
int numItems = myList.size(); // returns 2 | |||
MyObject* lastInList = myList.getLast(); | |||
@endcode | |||
*/ | |||
template <class ObjectType> | |||
class LinkedListPointer | |||
{ | |||
public: | |||
//============================================================================== | |||
/** Creates a null pointer to an empty list. */ | |||
LinkedListPointer() throw() | |||
: item (0) | |||
{ | |||
} | |||
/** Creates a pointer to a list whose head is the item provided. */ | |||
explicit LinkedListPointer (ObjectType* const headItem) throw() | |||
: item (headItem) | |||
{ | |||
} | |||
/** Sets this pointer to point to a new list. */ | |||
LinkedListPointer& operator= (ObjectType* const newItem) throw() | |||
{ | |||
item = newItem; | |||
return *this; | |||
} | |||
//============================================================================== | |||
/** Returns the item which this pointer points to. */ | |||
inline operator ObjectType*() const throw() | |||
{ | |||
return item; | |||
} | |||
/** Returns the item which this pointer points to. */ | |||
inline ObjectType* get() const throw() | |||
{ | |||
return item; | |||
} | |||
/** Returns the last item in the list which this pointer points to. | |||
This will iterate the list and return the last item found. Obviously the speed | |||
of this operation will be proportional to the size of the list. If the list is | |||
empty the return value will be this object. | |||
If you're planning on appending a number of items to your list, it's much more | |||
efficient to use the Appender class than to repeatedly call getLast() to find the end. | |||
*/ | |||
LinkedListPointer& getLast() throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns the number of items in the list. | |||
Obviously with a simple linked list, getting the size involves iterating the list, so | |||
this can be a lengthy operation - be careful when using this method in your code. | |||
*/ | |||
int size() const throw() | |||
{ | |||
int total = 0; | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
++total; | |||
return total; | |||
} | |||
/** Returns the item at a given index in the list. | |||
Since the only way to find an item is to iterate the list, this operation can obviously | |||
be slow, depending on its size, so you should be careful when using this in algorithms. | |||
*/ | |||
LinkedListPointer& operator[] (int index) throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (--index >= 0 && l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns the item at a given index in the list. | |||
Since the only way to find an item is to iterate the list, this operation can obviously | |||
be slow, depending on its size, so you should be careful when using this in algorithms. | |||
*/ | |||
const LinkedListPointer& operator[] (int index) const throw() | |||
{ | |||
const LinkedListPointer* l = this; | |||
while (--index >= 0 && l->item != 0) | |||
l = &(l->item->nextListItem); | |||
return *l; | |||
} | |||
/** Returns true if the list contains the given item. */ | |||
bool contains (const ObjectType* const itemToLookFor) const throw() | |||
{ | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
if (itemToLookFor == i) | |||
return true; | |||
return false; | |||
} | |||
//============================================================================== | |||
/** Inserts an item into the list, placing it before the item that this pointer | |||
currently points to. | |||
*/ | |||
void insertNext (ObjectType* const newItem) | |||
{ | |||
jassert (newItem != 0); | |||
jassert (newItem->nextListItem == 0); | |||
newItem->nextListItem = item; | |||
item = newItem; | |||
} | |||
/** Inserts an item at a numeric index in the list. | |||
Obviously this will involve iterating the list to find the item at the given index, | |||
so be careful about the impact this may have on execution time. | |||
*/ | |||
void insertAtIndex (int index, ObjectType* newItem) | |||
{ | |||
jassert (newItem != 0); | |||
LinkedListPointer* l = this; | |||
while (index != 0 && l->item != 0) | |||
{ | |||
l = &(l->item->nextListItem); | |||
--index; | |||
} | |||
l->insertNext (newItem); | |||
} | |||
/** Replaces the object that this pointer points to, appending the rest of the list to | |||
the new object, and returning the old one. | |||
*/ | |||
ObjectType* replaceNext (ObjectType* const newItem) throw() | |||
{ | |||
jassert (newItem != 0); | |||
jassert (newItem->nextListItem == 0); | |||
ObjectType* const oldItem = item; | |||
item = newItem; | |||
item->nextListItem = oldItem->nextListItem; | |||
oldItem->nextListItem = 0; | |||
return oldItem; | |||
} | |||
/** Adds an item to the end of the list. | |||
This operation involves iterating the whole list, so can be slow - if you need to | |||
append a number of items to your list, it's much more efficient to use the Appender | |||
class than to repeatedly call append(). | |||
*/ | |||
void append (ObjectType* const newItem) | |||
{ | |||
getLast().item = newItem; | |||
} | |||
/** Creates copies of all the items in another list and adds them to this one. | |||
This will use the ObjectType's copy constructor to try to create copies of each | |||
item in the other list, and appends them to this list. | |||
*/ | |||
void addCopyOfList (const LinkedListPointer& other) | |||
{ | |||
LinkedListPointer* insertPoint = this; | |||
for (ObjectType* i = other.item; i != 0; i = i->nextListItem) | |||
{ | |||
insertPoint->insertNext (new ObjectType (*i)); | |||
insertPoint = &(insertPoint->item->nextListItem); | |||
} | |||
} | |||
/** Removes the head item from the list. | |||
This won't delete the object that is removed, but returns it, so the caller can | |||
delete it if necessary. | |||
*/ | |||
ObjectType* removeNext() throw() | |||
{ | |||
if (item == 0) | |||
return 0; | |||
ObjectType* const oldItem = item; | |||
oldItem->nextListItem = 0; | |||
item = item->nextListItem; | |||
return oldItem; | |||
} | |||
/** Removes a specific item from the list. | |||
Note that this will not delete the item, it simply unlinks it from the list. | |||
*/ | |||
void remove (ObjectType* const item) | |||
{ | |||
LinkedListPointer* l = findPointerTo (item); | |||
if (l != 0) | |||
l->removeNext(); | |||
} | |||
/** Iterates the list, calling the delete operator on all of its elements and | |||
leaving this pointer empty. | |||
*/ | |||
void deleteAll() | |||
{ | |||
while (item != 0) | |||
{ | |||
ObjectType* const oldItem = item; | |||
item = oldItem->nextListItem; | |||
delete oldItem; | |||
} | |||
} | |||
/** Finds a pointer to a given item. | |||
If the item is found in the list, this returns the pointer that points to it. If | |||
the item isn't found, this returns null. | |||
*/ | |||
LinkedListPointer* findPointerTo (ObjectType* const itemToLookFor) throw() | |||
{ | |||
LinkedListPointer* l = this; | |||
while (l->item != 0) | |||
{ | |||
if (l->item == itemToLookFor) | |||
return l; | |||
l = &(l->item->nextListItem); | |||
} | |||
return 0; | |||
} | |||
/** Copies the items in the list to an array. | |||
The destArray must contain enough elements to hold the entire list - no checks are | |||
made for this! | |||
*/ | |||
void copyToArray (ObjectType** destArray) const throw() | |||
{ | |||
jassert (destArray != 0); | |||
for (ObjectType* i = item; i != 0; i = i->nextListItem) | |||
*destArray++ = i; | |||
} | |||
//============================================================================== | |||
/** | |||
Allows efficient repeated insertions into a list. | |||
You can create an Appender object which points to the last element in your | |||
list, and then repeatedly call Appender::append() to add items to the end | |||
of the list in O(1) time. | |||
*/ | |||
class Appender | |||
{ | |||
public: | |||
/** Creates an appender which will add items to the given list. | |||
*/ | |||
Appender (LinkedListPointer& endOfListPointer) throw() | |||
: endOfList (&endOfListPointer) | |||
{ | |||
// This can only be used to add to the end of a list. | |||
jassert (endOfListPointer.item == 0); | |||
} | |||
/** Appends an item to the list. */ | |||
void append (ObjectType* const newItem) throw() | |||
{ | |||
*endOfList = newItem; | |||
endOfList = &(newItem->nextListItem); | |||
} | |||
private: | |||
LinkedListPointer* endOfList; | |||
JUCE_DECLARE_NON_COPYABLE (Appender); | |||
}; | |||
private: | |||
//============================================================================== | |||
ObjectType* item; | |||
}; | |||
#endif // __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ |
@@ -33,7 +33,7 @@ | |||
*/ | |||
#define JUCE_MAJOR_VERSION 1 | |||
#define JUCE_MINOR_VERSION 52 | |||
#define JUCE_BUILDNUMBER 110 | |||
#define JUCE_BUILDNUMBER 111 | |||
/** Current Juce version number. | |||
@@ -147,9 +147,10 @@ void Button::setToggleState (const bool shouldBeOn, | |||
lastToggleState = shouldBeOn; | |||
repaint(); | |||
WeakReference<Component> deletionWatcher (this); | |||
if (sendChangeNotification) | |||
{ | |||
WeakReference<Component> deletionWatcher (this); | |||
sendClickMessage (ModifierKeys()); | |||
if (deletionWatcher == 0) | |||
@@ -157,7 +158,14 @@ void Button::setToggleState (const bool shouldBeOn, | |||
} | |||
if (lastToggleState) | |||
{ | |||
turnOffOtherButtonsInGroup (sendChangeNotification); | |||
if (deletionWatcher == 0) | |||
return; | |||
} | |||
sendStateMessage(); | |||
} | |||
} | |||
@@ -1018,33 +1018,40 @@ void Component::setBounds (const int x, const int y, int w, int h) | |||
void Component::sendMovedResizedMessages (const bool wasMoved, const bool wasResized) | |||
{ | |||
JUCE_TRY | |||
BailOutChecker checker (this); | |||
if (wasMoved) | |||
{ | |||
if (wasMoved) | |||
moved(); | |||
moved(); | |||
if (wasResized) | |||
{ | |||
resized(); | |||
if (checker.shouldBailOut()) | |||
return; | |||
} | |||
for (int i = childComponentList_.size(); --i >= 0;) | |||
{ | |||
childComponentList_.getUnchecked(i)->parentSizeChanged(); | |||
if (wasResized) | |||
{ | |||
resized(); | |||
i = jmin (i, childComponentList_.size()); | |||
} | |||
} | |||
if (checker.shouldBailOut()) | |||
return; | |||
BailOutChecker checker (this); | |||
for (int i = childComponentList_.size(); --i >= 0;) | |||
{ | |||
childComponentList_.getUnchecked(i)->parentSizeChanged(); | |||
if (parentComponent_ != 0) | |||
parentComponent_->childBoundsChanged (this); | |||
if (checker.shouldBailOut()) | |||
return; | |||
if (! checker.shouldBailOut()) | |||
componentListeners.callChecked (checker, &ComponentListener::componentMovedOrResized, | |||
*this, wasMoved, wasResized); | |||
i = jmin (i, childComponentList_.size()); | |||
} | |||
} | |||
JUCE_CATCH_EXCEPTION | |||
if (parentComponent_ != 0) | |||
parentComponent_->childBoundsChanged (this); | |||
if (! checker.shouldBailOut()) | |||
componentListeners.callChecked (checker, &ComponentListener::componentMovedOrResized, | |||
*this, wasMoved, wasResized); | |||
} | |||
void Component::setSize (const int w, const int h) | |||
@@ -2561,12 +2568,15 @@ void Component::focusGained (FocusChangeType) | |||
void Component::internalFocusGain (const FocusChangeType cause) | |||
{ | |||
WeakReference<Component> safePointer (this); | |||
internalFocusGain (cause, WeakReference<Component> (this)); | |||
} | |||
void Component::internalFocusGain (const FocusChangeType cause, const WeakReference<Component>& safePointer) | |||
{ | |||
focusGained (cause); | |||
if (safePointer != 0) | |||
internalChildFocusChange (cause); | |||
internalChildFocusChange (cause, safePointer); | |||
} | |||
void Component::focusLost (FocusChangeType) | |||
@@ -2581,7 +2591,7 @@ void Component::internalFocusLoss (const FocusChangeType cause) | |||
focusLost (focusChangedDirectly); | |||
if (safePointer != 0) | |||
internalChildFocusChange (cause); | |||
internalChildFocusChange (cause, safePointer); | |||
} | |||
void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) | |||
@@ -2589,7 +2599,7 @@ void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) | |||
// base class does nothing | |||
} | |||
void Component::internalChildFocusChange (FocusChangeType cause) | |||
void Component::internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>& safePointer) | |||
{ | |||
const bool childIsNowFocused = hasKeyboardFocus (true); | |||
@@ -2597,7 +2607,6 @@ void Component::internalChildFocusChange (FocusChangeType cause) | |||
{ | |||
flags.childCompFocusedFlag = childIsNowFocused; | |||
WeakReference<Component> safePointer (this); | |||
focusOfChildComponentChanged (cause); | |||
if (safePointer == 0) | |||
@@ -2605,7 +2614,7 @@ void Component::internalChildFocusChange (FocusChangeType cause) | |||
} | |||
if (parentComponent_ != 0) | |||
parentComponent_->internalChildFocusChange (cause); | |||
parentComponent_->internalChildFocusChange (cause, WeakReference<Component> (parentComponent_)); | |||
} | |||
//============================================================================== | |||
@@ -2711,54 +2720,32 @@ void Component::takeKeyboardFocus (const FocusChangeType cause) | |||
// give the focus to this component | |||
if (currentlyFocusedComponent != this) | |||
{ | |||
JUCE_TRY | |||
{ | |||
// get the focus onto our desktop window | |||
ComponentPeer* const peer = getPeer(); | |||
if (peer != 0) | |||
{ | |||
WeakReference<Component> safePointer (this); | |||
// get the focus onto our desktop window | |||
ComponentPeer* const peer = getPeer(); | |||
peer->grabFocus(); | |||
if (peer != 0) | |||
{ | |||
WeakReference<Component> safePointer (this); | |||
if (peer->isFocused() && currentlyFocusedComponent != this) | |||
{ | |||
WeakReference<Component> componentLosingFocus (currentlyFocusedComponent); | |||
peer->grabFocus(); | |||
currentlyFocusedComponent = this; | |||
if (peer->isFocused() && currentlyFocusedComponent != this) | |||
{ | |||
WeakReference<Component> componentLosingFocus (currentlyFocusedComponent); | |||
Desktop::getInstance().triggerFocusCallback(); | |||
currentlyFocusedComponent = this; | |||
// call this after setting currentlyFocusedComponent so that the one that's | |||
// losing it has a chance to see where focus is going | |||
if (componentLosingFocus != 0) | |||
componentLosingFocus->internalFocusLoss (cause); | |||
Desktop::getInstance().triggerFocusCallback(); | |||
if (currentlyFocusedComponent == this) | |||
{ | |||
focusGained (cause); | |||
// call this after setting currentlyFocusedComponent so that the one that's | |||
// losing it has a chance to see where focus is going | |||
if (componentLosingFocus != 0) | |||
componentLosingFocus->internalFocusLoss (cause); | |||
if (safePointer != 0) | |||
internalChildFocusChange (cause); | |||
} | |||
} | |||
if (currentlyFocusedComponent == this) | |||
internalFocusGain (cause, safePointer); | |||
} | |||
} | |||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
catch (const std::exception& e) | |||
{ | |||
currentlyFocusedComponent = 0; | |||
Desktop::getInstance().triggerFocusCallback(); | |||
JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__); | |||
} | |||
catch (...) | |||
{ | |||
currentlyFocusedComponent = 0; | |||
Desktop::getInstance().triggerFocusCallback(); | |||
JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__); | |||
} | |||
#endif | |||
} | |||
} | |||
@@ -2180,9 +2180,10 @@ private: | |||
void internalMouseMove (MouseInputSource& source, const Point<int>& relativePos, const Time& time); | |||
void internalMouseWheel (MouseInputSource& source, const Point<int>& relativePos, const Time& time, float amountX, float amountY); | |||
void internalBroughtToFront(); | |||
void internalFocusGain (const FocusChangeType cause, const WeakReference<Component>&); | |||
void internalFocusGain (const FocusChangeType cause); | |||
void internalFocusLoss (const FocusChangeType cause); | |||
void internalChildFocusChange (FocusChangeType cause); | |||
void internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>&); | |||
void internalModalInputAttempt(); | |||
void internalModifierKeysChanged(); | |||
void internalChildrenChanged(); | |||
@@ -43,6 +43,7 @@ BEGIN_JUCE_NAMESPACE | |||
#include "../juce_Desktop.h" | |||
#include "../../graphics/drawables/juce_DrawableComposite.h" | |||
#include "../../graphics/drawables/juce_DrawablePath.h" | |||
#include "../menus/juce_MenuBarComponent.h" | |||
//============================================================================== | |||
@@ -30,6 +30,7 @@ BEGIN_JUCE_NAMESPACE | |||
#include "juce_DocumentWindow.h" | |||
#include "juce_ComponentPeer.h" | |||
#include "../lookandfeel/juce_LookAndFeel.h" | |||
#include "../menus/juce_MenuBarComponent.h" | |||
#include "../../graphics/imaging/juce_Image.h" | |||
@@ -67,11 +68,11 @@ DocumentWindow::DocumentWindow (const String& title, | |||
titleBarHeight (26), | |||
menuBarHeight (24), | |||
requiredButtons (requiredButtons_), | |||
#if JUCE_MAC | |||
#if JUCE_MAC | |||
positionTitleBarButtonsOnLeft (true), | |||
#else | |||
#else | |||
positionTitleBarButtonsOnLeft (false), | |||
#endif | |||
#endif | |||
drawTitleTextCentred (true), | |||
menuBarModel (0) | |||
{ | |||
@@ -138,28 +139,39 @@ void DocumentWindow::setTitleBarTextCentred (const bool textShouldBeCentred) | |||
repaintTitleBar(); | |||
} | |||
void DocumentWindow::setMenuBar (MenuBarModel* menuBarModel_, | |||
const int menuBarHeight_) | |||
//============================================================================== | |||
void DocumentWindow::setMenuBar (MenuBarModel* newMenuBarModel, const int newMenuBarHeight) | |||
{ | |||
if (menuBarModel != menuBarModel_) | |||
if (menuBarModel != newMenuBarModel) | |||
{ | |||
menuBar = 0; | |||
menuBarModel = menuBarModel_; | |||
menuBarHeight = (menuBarHeight_ > 0) ? menuBarHeight_ | |||
menuBarModel = newMenuBarModel; | |||
menuBarHeight = newMenuBarHeight > 0 ? newMenuBarHeight | |||
: getLookAndFeel().getDefaultMenuBarHeight(); | |||
if (menuBarModel != 0) | |||
{ | |||
// (call the Component method directly to avoid the assertion in ResizableWindow) | |||
Component::addAndMakeVisible (menuBar = new MenuBarComponent (menuBarModel)); | |||
menuBar->setEnabled (isActiveWindow()); | |||
} | |||
setMenuBarComponent (new MenuBarComponent (menuBarModel)); | |||
resized(); | |||
} | |||
} | |||
Component* DocumentWindow::getMenuBarComponent() const throw() | |||
{ | |||
return menuBar; | |||
} | |||
void DocumentWindow::setMenuBarComponent (Component* newMenuBarComponent) | |||
{ | |||
// (call the Component method directly to avoid the assertion in ResizableWindow) | |||
Component::addAndMakeVisible (menuBar = newMenuBarComponent); | |||
if (menuBar != 0) | |||
menuBar->setEnabled (isActiveWindow()); | |||
resized(); | |||
} | |||
//============================================================================== | |||
void DocumentWindow::closeButtonPressed() | |||
@@ -269,8 +281,8 @@ const BorderSize DocumentWindow::getContentComponentBorder() | |||
BorderSize border (getBorderThickness()); | |||
border.setTop (border.getTop() | |||
+ (isUsingNativeTitleBar() ? 0 : titleBarHeight) | |||
+ (menuBar != 0 ? menuBarHeight : 0)); | |||
+ (isUsingNativeTitleBar() ? 0 : titleBarHeight) | |||
+ (menuBar != 0 ? menuBarHeight : 0)); | |||
return border; | |||
} | |||
@@ -289,20 +301,9 @@ const Rectangle<int> DocumentWindow::getTitleBarArea() | |||
getTitleBarHeight()); | |||
} | |||
Button* DocumentWindow::getCloseButton() const throw() | |||
{ | |||
return titleBarButtons[2]; | |||
} | |||
Button* DocumentWindow::getMinimiseButton() const throw() | |||
{ | |||
return titleBarButtons[0]; | |||
} | |||
Button* DocumentWindow::getMaximiseButton() const throw() | |||
{ | |||
return titleBarButtons[1]; | |||
} | |||
Button* DocumentWindow::getCloseButton() const throw() { return titleBarButtons[2]; } | |||
Button* DocumentWindow::getMinimiseButton() const throw() { return titleBarButtons[0]; } | |||
Button* DocumentWindow::getMaximiseButton() const throw() { return titleBarButtons[1]; } | |||
int DocumentWindow::getDesktopWindowStyleFlags() const | |||
{ | |||
@@ -328,14 +329,16 @@ void DocumentWindow::lookAndFeelChanged() | |||
if (! isUsingNativeTitleBar()) | |||
{ | |||
titleBarButtons[0] = ((requiredButtons & minimiseButton) != 0) | |||
? getLookAndFeel().createDocumentWindowButton (minimiseButton) : 0; | |||
LookAndFeel& lf = getLookAndFeel(); | |||
if ((requiredButtons & minimiseButton) != 0) | |||
titleBarButtons[0] = lf.createDocumentWindowButton (minimiseButton); | |||
titleBarButtons[1] = ((requiredButtons & maximiseButton) != 0) | |||
? getLookAndFeel().createDocumentWindowButton (maximiseButton) : 0; | |||
if ((requiredButtons & maximiseButton) != 0) | |||
titleBarButtons[1] = lf.createDocumentWindowButton (maximiseButton); | |||
titleBarButtons[2] = ((requiredButtons & closeButton) != 0) | |||
? getLookAndFeel().createDocumentWindowButton (closeButton) : 0; | |||
if ((requiredButtons & closeButton) != 0) | |||
titleBarButtons[2] = lf.createDocumentWindowButton (closeButton); | |||
for (i = 0; i < 3; ++i) | |||
{ | |||
@@ -354,11 +357,11 @@ void DocumentWindow::lookAndFeelChanged() | |||
if (getCloseButton() != 0) | |||
{ | |||
#if JUCE_MAC | |||
#if JUCE_MAC | |||
getCloseButton()->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | |||
#else | |||
#else | |||
getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); | |||
#endif | |||
#endif | |||
} | |||
} | |||
@@ -28,7 +28,7 @@ | |||
#include "juce_ResizableWindow.h" | |||
#include "../buttons/juce_Button.h" | |||
#include "../menus/juce_MenuBarComponent.h" | |||
#include "../menus/juce_MenuBarModel.h" | |||
//============================================================================== | |||
@@ -142,6 +142,7 @@ public: | |||
*/ | |||
void setTitleBarTextCentred (bool textShouldBeCentred); | |||
//============================================================================== | |||
/** Creates a menu inside this window. | |||
@param menuBarModel this specifies a MenuBarModel that should be used to | |||
@@ -156,6 +157,17 @@ public: | |||
void setMenuBar (MenuBarModel* menuBarModel, | |||
int menuBarHeight = 0); | |||
/** Returns the current menu bar component, or null if there isn't one. | |||
This is probably a MenuBarComponent, unless a custom one has been set using | |||
setMenuBarComponent(). | |||
*/ | |||
Component* getMenuBarComponent() const throw(); | |||
/** Replaces the current menu bar with a custom component. | |||
The component will be owned and deleted by the document window. | |||
*/ | |||
void setMenuBarComponent (Component* newMenuBarComponent); | |||
//============================================================================== | |||
/** This method is called when the user tries to close the window. | |||
@@ -248,7 +260,7 @@ private: | |||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | |||
ScopedPointer <Button> titleBarButtons [3]; | |||
Image titleBarIcon; | |||
ScopedPointer <MenuBarComponent> menuBar; | |||
ScopedPointer <Component> menuBar; | |||
MenuBarModel* menuBarModel; | |||
class ButtonListenerProxy; | |||
@@ -244,13 +244,18 @@ void DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* | |||
const RelativeParallelogram newBounds (controller.getBoundingBox()); | |||
if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage) | |||
if (bounds != newBounds || newOpacity != opacity | |||
|| overlayColour != newOverlayColour || image != newImage) | |||
{ | |||
repaint(); | |||
opacity = newOpacity; | |||
overlayColour = newOverlayColour; | |||
bounds = newBounds; | |||
setImage (newImage); | |||
if (image != newImage) | |||
setImage (newImage); | |||
else | |||
refreshTransformFromBounds(); | |||
} | |||
} | |||
@@ -129,6 +129,7 @@ void DrawableShape::paint (Graphics& g) | |||
void DrawableShape::pathChanged() | |||
{ | |||
rebuildPath (path); | |||
strokeChanged(); | |||
} | |||
@@ -41,6 +41,9 @@ | |||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ | |||
#include "containers/juce_ElementComparator.h" | |||
#endif | |||
#ifndef __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||
#include "containers/juce_LinkedListPointer.h" | |||
#endif | |||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | |||
#include "containers/juce_NamedValueSet.h" | |||
#endif | |||
@@ -59,7 +59,7 @@ void* juce_load_jack_function (const char* const name) | |||
} | |||
//============================================================================== | |||
JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status), (client_name, options, status)); | |||
JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status, ...), (client_name, options, status)); | |||
JUCE_DECL_JACK_FUNCTION (int, jack_client_close, (jack_client_t *client), (client)); | |||
JUCE_DECL_JACK_FUNCTION (int, jack_activate, (jack_client_t* client), (client)); | |||
JUCE_DECL_JACK_FUNCTION (int, jack_deactivate, (jack_client_t* client), (client)); | |||
@@ -44,4 +44,4 @@ | |||
#define appendMacro1(a, b, c, d, e) a ## _ ## b ## _ ## c ## _ ## d ## _ ## e | |||
#define appendMacro2(a, b, c, d, e) appendMacro1(a, b, c, d, e) | |||
#define MakeObjCClassName(rootName) appendMacro2 (rootName, JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_BUILDNUMBER, JUCE_ObjCExtraSuffix) | |||
#endif | |||
#endif |
@@ -492,6 +492,7 @@ public: | |||
isDragging (false), | |||
isMouseOver (false), | |||
hasCreatedCaret (false), | |||
constrainerIsResizing (false), | |||
currentWindowIcon (0), | |||
dropTarget (0), | |||
updateLayeredWindowAlpha (255), | |||
@@ -1029,7 +1030,7 @@ private: | |||
#if JUCE_DIRECT2D | |||
ScopedPointer<Direct2DLowLevelGraphicsContext> direct2DContext; | |||
#endif | |||
bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; | |||
bool fullScreen, isDragging, isMouseOver, hasCreatedCaret, constrainerIsResizing; | |||
BorderSize windowBorder; | |||
HICON currentWindowIcon; | |||
ScopedPointer<NOTIFYICONDATA> taskBarIcon; | |||
@@ -1542,6 +1543,14 @@ private: | |||
void doCaptureChanged() | |||
{ | |||
if (constrainerIsResizing) | |||
{ | |||
if (constrainer != 0) | |||
constrainer->resizeEnd(); | |||
constrainerIsResizing = false; | |||
} | |||
if (isDragging) | |||
doMouseUp (getCurrentMousePos(), (WPARAM) 0); | |||
} | |||
@@ -1764,9 +1773,15 @@ private: | |||
return false; | |||
} | |||
bool isConstrainedNativeWindow() const | |||
{ | |||
return constrainer != 0 | |||
&& (styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable); | |||
} | |||
LRESULT handleSizeConstraining (RECT* const r, const WPARAM wParam) | |||
{ | |||
if (constrainer != 0 && (styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable)) | |||
if (isConstrainedNativeWindow()) | |||
{ | |||
Rectangle<int> pos (r->left, r->top, r->right - r->left, r->bottom - r->top); | |||
@@ -1787,7 +1802,7 @@ private: | |||
LRESULT handlePositionChanging (WINDOWPOS* const wp) | |||
{ | |||
if (constrainer != 0 && (styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable)) | |||
if (isConstrainedNativeWindow()) | |||
{ | |||
if ((wp->flags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE) | |||
&& ! Component::isMouseButtonDownAnywhere()) | |||
@@ -2279,6 +2294,32 @@ private: | |||
break; | |||
case WM_NCLBUTTONDOWN: | |||
if (! sendInputAttemptWhenModalMessage()) | |||
{ | |||
switch (wParam) | |||
{ | |||
case HTBOTTOM: | |||
case HTBOTTOMLEFT: | |||
case HTBOTTOMRIGHT: | |||
case HTGROWBOX: | |||
case HTLEFT: | |||
case HTRIGHT: | |||
case HTTOP: | |||
case HTTOPLEFT: | |||
case HTTOPRIGHT: | |||
if (isConstrainedNativeWindow()) | |||
{ | |||
constrainerIsResizing = true; | |||
constrainer->resizeStart(); | |||
} | |||
break; | |||
default: | |||
break; | |||
}; | |||
} | |||
break; | |||
case WM_NCRBUTTONDOWN: | |||
case WM_NCMBUTTONDOWN: | |||
sendInputAttemptWhenModalMessage(); | |||
@@ -385,7 +385,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
node = new XmlElement (String (input, tagLen)); | |||
input += tagLen; | |||
XmlElement::XmlAttributeNode* lastAttribute = 0; | |||
LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | |||
// look for attributes | |||
for (;;) | |||
@@ -437,14 +437,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
String::empty); | |||
readQuotedString (newAtt->value); | |||
if (lastAttribute == 0) | |||
node->attributes = newAtt; | |||
else | |||
lastAttribute->next = newAtt; | |||
lastAttribute = newAtt; | |||
attributeAppender.append (newAtt); | |||
continue; | |||
} | |||
} | |||
@@ -465,7 +458,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||
void XmlDocument::readChildElements (XmlElement* parent) | |||
{ | |||
XmlElement* lastChildNode = 0; | |||
LinkedListPointer<XmlElement>::Appender childAppender (parent->firstChildElement); | |||
for (;;) | |||
{ | |||
@@ -521,14 +514,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
++len; | |||
} | |||
XmlElement* const e = XmlElement::createTextElement (String (inputStart, len)); | |||
if (lastChildNode != 0) | |||
lastChildNode->nextElement = e; | |||
else | |||
parent->addChildElement (e); | |||
lastChildNode = e; | |||
childAppender.append (XmlElement::createTextElement (String (inputStart, len))); | |||
} | |||
else | |||
{ | |||
@@ -536,18 +522,9 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
XmlElement* const n = readNextElement (true); | |||
if (n != 0) | |||
{ | |||
if (lastChildNode == 0) | |||
parent->addChildElement (n); | |||
else | |||
lastChildNode->nextElement = n; | |||
lastChildNode = n; | |||
} | |||
childAppender.append (n); | |||
else | |||
{ | |||
return; | |||
} | |||
} | |||
} | |||
else // must be a character block | |||
@@ -589,12 +566,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
if (n == 0) | |||
break; | |||
if (lastChildNode == 0) | |||
parent->addChildElement (n); | |||
else | |||
lastChildNode->nextElement = n; | |||
lastChildNode = n; | |||
childAppender.append (n); | |||
} | |||
input = oldInput; | |||
@@ -635,14 +607,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||
if ((! ignoreEmptyTextElements) || textElementContent.containsNonWhitespaceChars()) | |||
{ | |||
XmlElement* const textElement = XmlElement::createTextElement (textElementContent); | |||
if (lastChildNode != 0) | |||
lastChildNode->nextElement = textElement; | |||
else | |||
parent->addChildElement (textElement); | |||
lastChildNode = textElement; | |||
childAppender.append (XmlElement::createTextElement (textElementContent)); | |||
} | |||
} | |||
} | |||
@@ -870,18 +835,16 @@ const String XmlDocument::getParameterEntity (const String& entity) | |||
{ | |||
for (int i = 0; i < tokenisedDTD.size(); ++i) | |||
{ | |||
if (tokenisedDTD[i] == entity) | |||
if (tokenisedDTD[i] == entity | |||
&& tokenisedDTD [i - 1] == "%" | |||
&& tokenisedDTD [i - 2].equalsIgnoreCase ("<!entity")) | |||
{ | |||
if (tokenisedDTD [i - 1] == "%" | |||
&& tokenisedDTD [i - 2].equalsIgnoreCase ("<!entity")) | |||
{ | |||
const String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">")); | |||
const String ent (tokenisedDTD [i + 1].trimCharactersAtEnd (">")); | |||
if (ent.equalsIgnoreCase ("system")) | |||
return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">")); | |||
else | |||
return ent.trim().unquoted(); | |||
} | |||
if (ent.equalsIgnoreCase ("system")) | |||
return getFileContents (tokenisedDTD [i + 2].trimCharactersAtEnd (">")); | |||
else | |||
return ent.trim().unquoted(); | |||
} | |||
} | |||
@@ -37,15 +37,13 @@ BEGIN_JUCE_NAMESPACE | |||
//============================================================================== | |||
XmlElement::XmlAttributeNode::XmlAttributeNode (const XmlAttributeNode& other) throw() | |||
: name (other.name), | |||
value (other.value), | |||
next (0) | |||
value (other.value) | |||
{ | |||
} | |||
XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const String& value_) throw() | |||
: name (name_), | |||
value (value_), | |||
next (0) | |||
value (value_) | |||
{ | |||
#if JUCE_DEBUG | |||
// this checks whether the attribute name string contains any illegals characters.. | |||
@@ -61,10 +59,7 @@ inline bool XmlElement::XmlAttributeNode::hasName (const String& nameToMatch) co | |||
//============================================================================== | |||
XmlElement::XmlElement (const String& tagName_) throw() | |||
: tagName (tagName_), | |||
firstChildElement (0), | |||
nextElement (0), | |||
attributes (0) | |||
: tagName (tagName_) | |||
{ | |||
// the tag name mustn't be empty, or it'll look like a text element! | |||
jassert (tagName_.containsNonWhitespaceChars()) | |||
@@ -74,17 +69,11 @@ XmlElement::XmlElement (const String& tagName_) throw() | |||
} | |||
XmlElement::XmlElement (int /*dummy*/) throw() | |||
: firstChildElement (0), | |||
nextElement (0), | |||
attributes (0) | |||
{ | |||
} | |||
XmlElement::XmlElement (const XmlElement& other) | |||
: tagName (other.tagName), | |||
firstChildElement (0), | |||
nextElement (0), | |||
attributes (0) | |||
: tagName (other.tagName) | |||
{ | |||
copyChildrenAndAttributesFrom (other); | |||
} | |||
@@ -106,58 +95,17 @@ XmlElement& XmlElement::operator= (const XmlElement& other) | |||
void XmlElement::copyChildrenAndAttributesFrom (const XmlElement& other) | |||
{ | |||
XmlElement* child = other.firstChildElement; | |||
XmlElement* lastChild = 0; | |||
jassert (firstChildElement.get() == 0); | |||
firstChildElement.addCopyOfList (other.firstChildElement); | |||
while (child != 0) | |||
{ | |||
XmlElement* const copiedChild = new XmlElement (*child); | |||
if (lastChild != 0) | |||
lastChild->nextElement = copiedChild; | |||
else | |||
firstChildElement = copiedChild; | |||
lastChild = copiedChild; | |||
child = child->nextElement; | |||
} | |||
const XmlAttributeNode* att = other.attributes; | |||
XmlAttributeNode* lastAtt = 0; | |||
while (att != 0) | |||
{ | |||
XmlAttributeNode* const newAtt = new XmlAttributeNode (*att); | |||
if (lastAtt != 0) | |||
lastAtt->next = newAtt; | |||
else | |||
attributes = newAtt; | |||
lastAtt = newAtt; | |||
att = att->next; | |||
} | |||
jassert (attributes.get() == 0); | |||
attributes.addCopyOfList (other.attributes); | |||
} | |||
XmlElement::~XmlElement() throw() | |||
{ | |||
XmlElement* child = firstChildElement; | |||
while (child != 0) | |||
{ | |||
XmlElement* const nextChild = child->nextElement; | |||
delete child; | |||
child = nextChild; | |||
} | |||
XmlAttributeNode* att = attributes; | |||
while (att != 0) | |||
{ | |||
XmlAttributeNode* const nextAtt = att->next; | |||
delete att; | |||
att = nextAtt; | |||
} | |||
firstChildElement.deleteAll(); | |||
attributes.deleteAll(); | |||
} | |||
//============================================================================== | |||
@@ -279,7 +227,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||
const int attIndent = indentationLevel + tagName.length() + 1; | |||
int lineLen = 0; | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
{ | |||
if (lineLen > lineWrapLength && indentationLevel >= 0) | |||
{ | |||
@@ -322,7 +270,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||
lastWasTextNode = false; | |||
} | |||
child = child->nextElement; | |||
child = child->getNextElement(); | |||
} | |||
if (indentationLevel >= 0 && ! lastWasTextNode) | |||
@@ -438,10 +386,10 @@ bool XmlElement::hasTagName (const String& tagNameWanted) const throw() | |||
XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName) const | |||
{ | |||
XmlElement* e = nextElement; | |||
XmlElement* e = nextListItem; | |||
while (e != 0 && ! e->hasTagName (requiredTagName)) | |||
e = e->nextElement; | |||
e = e->nextListItem; | |||
return e; | |||
} | |||
@@ -449,47 +397,24 @@ XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName | |||
//============================================================================== | |||
int XmlElement::getNumAttributes() const throw() | |||
{ | |||
int count = 0; | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
++count; | |||
return count; | |||
return attributes.size(); | |||
} | |||
const String& XmlElement::getAttributeName (const int index) const throw() | |||
{ | |||
int count = 0; | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
{ | |||
if (count == index) | |||
return att->name; | |||
++count; | |||
} | |||
return String::empty; | |||
const XmlAttributeNode* const att = attributes [index]; | |||
return att != 0 ? att->name : String::empty; | |||
} | |||
const String& XmlElement::getAttributeValue (const int index) const throw() | |||
{ | |||
int count = 0; | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
{ | |||
if (count == index) | |||
return att->value; | |||
++count; | |||
} | |||
return String::empty; | |||
const XmlAttributeNode* const att = attributes [index]; | |||
return att != 0 ? att->value : String::empty; | |||
} | |||
bool XmlElement::hasAttribute (const String& attributeName) const throw() | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return true; | |||
@@ -499,7 +424,7 @@ bool XmlElement::hasAttribute (const String& attributeName) const throw() | |||
//============================================================================== | |||
const String& XmlElement::getStringAttribute (const String& attributeName) const throw() | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return att->value; | |||
@@ -508,7 +433,7 @@ const String& XmlElement::getStringAttribute (const String& attributeName) const | |||
const String XmlElement::getStringAttribute (const String& attributeName, const String& defaultReturnValue) const | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return att->value; | |||
@@ -517,7 +442,7 @@ const String XmlElement::getStringAttribute (const String& attributeName, const | |||
int XmlElement::getIntAttribute (const String& attributeName, const int defaultReturnValue) const | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return att->value.getIntValue(); | |||
@@ -526,7 +451,7 @@ int XmlElement::getIntAttribute (const String& attributeName, const int defaultR | |||
double XmlElement::getDoubleAttribute (const String& attributeName, const double defaultReturnValue) const | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return att->value.getDoubleValue(); | |||
@@ -535,7 +460,7 @@ double XmlElement::getDoubleAttribute (const String& attributeName, const double | |||
bool XmlElement::getBoolAttribute (const String& attributeName, const bool defaultReturnValue) const | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
{ | |||
if (att->hasName (attributeName)) | |||
{ | |||
@@ -559,7 +484,7 @@ bool XmlElement::compareAttribute (const String& attributeName, | |||
const String& stringToCompareAgainst, | |||
const bool ignoreCase) const throw() | |||
{ | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
for (const XmlAttributeNode* att = attributes; att != 0; att = att->nextListItem) | |||
if (att->hasName (attributeName)) | |||
return ignoreCase ? att->value.equalsIgnoreCase (stringToCompareAgainst) | |||
: att->value == stringToCompareAgainst; | |||
@@ -585,13 +510,13 @@ void XmlElement::setAttribute (const String& attributeName, const String& value) | |||
att->value = value; | |||
break; | |||
} | |||
else if (att->next == 0) | |||
else if (att->nextListItem == 0) | |||
{ | |||
att->next = new XmlAttributeNode (attributeName, value); | |||
att->nextListItem = new XmlAttributeNode (attributeName, value); | |||
break; | |||
} | |||
att = att->next; | |||
att = att->nextListItem; | |||
} | |||
} | |||
} | |||
@@ -608,62 +533,34 @@ void XmlElement::setAttribute (const String& attributeName, const double number) | |||
void XmlElement::removeAttribute (const String& attributeName) throw() | |||
{ | |||
XmlAttributeNode* lastAtt = 0; | |||
LinkedListPointer<XmlAttributeNode>* att = &attributes; | |||
for (XmlAttributeNode* att = attributes; att != 0; att = att->next) | |||
while (att->get() != 0) | |||
{ | |||
if (att->hasName (attributeName)) | |||
if (att->get()->hasName (attributeName)) | |||
{ | |||
if (lastAtt == 0) | |||
attributes = att->next; | |||
else | |||
lastAtt->next = att->next; | |||
delete att; | |||
delete att->removeNext(); | |||
break; | |||
} | |||
lastAtt = att; | |||
att = &(att->get()->nextListItem); | |||
} | |||
} | |||
void XmlElement::removeAllAttributes() throw() | |||
{ | |||
while (attributes != 0) | |||
{ | |||
XmlAttributeNode* const nextAtt = attributes->next; | |||
delete attributes; | |||
attributes = nextAtt; | |||
} | |||
attributes.deleteAll(); | |||
} | |||
//============================================================================== | |||
int XmlElement::getNumChildElements() const throw() | |||
{ | |||
int count = 0; | |||
const XmlElement* child = firstChildElement; | |||
while (child != 0) | |||
{ | |||
++count; | |||
child = child->nextElement; | |||
} | |||
return count; | |||
return firstChildElement.size(); | |||
} | |||
XmlElement* XmlElement::getChildElement (const int index) const throw() | |||
{ | |||
int count = 0; | |||
XmlElement* child = firstChildElement; | |||
while (child != 0 && count < index) | |||
{ | |||
child = child->nextElement; | |||
++count; | |||
} | |||
return child; | |||
return firstChildElement [index].get(); | |||
} | |||
XmlElement* XmlElement::getChildByName (const String& childName) const throw() | |||
@@ -675,7 +572,7 @@ XmlElement* XmlElement::getChildByName (const String& childName) const throw() | |||
if (child->hasTagName (childName)) | |||
break; | |||
child = child->nextElement; | |||
child = child->nextListItem; | |||
} | |||
return child; | |||
@@ -684,25 +581,7 @@ XmlElement* XmlElement::getChildByName (const String& childName) const throw() | |||
void XmlElement::addChildElement (XmlElement* const newNode) throw() | |||
{ | |||
if (newNode != 0) | |||
{ | |||
if (firstChildElement == 0) | |||
{ | |||
firstChildElement = newNode; | |||
} | |||
else | |||
{ | |||
XmlElement* child = firstChildElement; | |||
while (child->nextElement != 0) | |||
child = child->nextElement; | |||
child->nextElement = newNode; | |||
// if this is non-zero, then something's probably | |||
// gone wrong.. | |||
jassert (newNode->nextElement == 0); | |||
} | |||
} | |||
firstChildElement.append (newNode); | |||
} | |||
void XmlElement::insertChildElement (XmlElement* const newNode, | |||
@@ -711,32 +590,7 @@ void XmlElement::insertChildElement (XmlElement* const newNode, | |||
if (newNode != 0) | |||
{ | |||
removeChildElement (newNode, false); | |||
if (indexToInsertAt == 0) | |||
{ | |||
newNode->nextElement = firstChildElement; | |||
firstChildElement = newNode; | |||
} | |||
else | |||
{ | |||
if (firstChildElement == 0) | |||
{ | |||
firstChildElement = newNode; | |||
} | |||
else | |||
{ | |||
if (indexToInsertAt < 0) | |||
indexToInsertAt = std::numeric_limits<int>::max(); | |||
XmlElement* child = firstChildElement; | |||
while (child->nextElement != 0 && --indexToInsertAt > 0) | |||
child = child->nextElement; | |||
newNode->nextElement = child->nextElement; | |||
child->nextElement = newNode; | |||
} | |||
} | |||
firstChildElement.insertAtIndex (indexToInsertAt, newNode); | |||
} | |||
} | |||
@@ -752,30 +606,14 @@ bool XmlElement::replaceChildElement (XmlElement* const currentChildElement, | |||
{ | |||
if (newNode != 0) | |||
{ | |||
XmlElement* child = firstChildElement; | |||
XmlElement* previousNode = 0; | |||
LinkedListPointer<XmlElement>* const p = firstChildElement.findPointerTo (currentChildElement); | |||
while (child != 0) | |||
if (p != 0) | |||
{ | |||
if (child == currentChildElement) | |||
{ | |||
if (child != newNode) | |||
{ | |||
if (previousNode == 0) | |||
firstChildElement = newNode; | |||
else | |||
previousNode->nextElement = newNode; | |||
newNode->nextElement = child->nextElement; | |||
delete child; | |||
} | |||
return true; | |||
} | |||
if (currentChildElement != newNode) | |||
delete p->replaceNext (newNode); | |||
previousNode = child; | |||
child = child->nextElement; | |||
return true; | |||
} | |||
} | |||
@@ -787,33 +625,7 @@ void XmlElement::removeChildElement (XmlElement* const childToRemove, | |||
{ | |||
if (childToRemove != 0) | |||
{ | |||
if (firstChildElement == childToRemove) | |||
{ | |||
firstChildElement = childToRemove->nextElement; | |||
childToRemove->nextElement = 0; | |||
} | |||
else | |||
{ | |||
XmlElement* child = firstChildElement; | |||
XmlElement* last = 0; | |||
while (child != 0) | |||
{ | |||
if (child == childToRemove) | |||
{ | |||
if (last == 0) | |||
firstChildElement = child->nextElement; | |||
else | |||
last->nextElement = child->nextElement; | |||
childToRemove->nextElement = 0; | |||
break; | |||
} | |||
last = child; | |||
child = child->nextElement; | |||
} | |||
} | |||
firstChildElement.remove (childToRemove); | |||
if (shouldDeleteTheChild) | |||
delete childToRemove; | |||
@@ -838,7 +650,7 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||
if (! other->compareAttribute (att->name, att->value)) | |||
return false; | |||
att = att->next; | |||
att = att->nextListItem; | |||
++totalAtts; | |||
} | |||
@@ -866,8 +678,8 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||
return false; | |||
} | |||
thisAtt = thisAtt->next; | |||
otherAtt = otherAtt->next; | |||
thisAtt = thisAtt->nextListItem; | |||
otherAtt = otherAtt->nextListItem; | |||
} | |||
} | |||
@@ -887,8 +699,8 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||
if (! thisChild->isEquivalentTo (otherChild, ignoreOrderOfAttributes)) | |||
return false; | |||
thisChild = thisChild->nextElement; | |||
otherChild = otherChild->nextElement; | |||
thisChild = thisChild->nextListItem; | |||
otherChild = otherChild->nextListItem; | |||
} | |||
} | |||
@@ -897,12 +709,7 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||
void XmlElement::deleteAllChildElements() throw() | |||
{ | |||
while (firstChildElement != 0) | |||
{ | |||
XmlElement* const nextChild = firstChildElement->nextElement; | |||
delete firstChildElement; | |||
firstChildElement = nextChild; | |||
} | |||
firstChildElement.deleteAll(); | |||
} | |||
void XmlElement::deleteAllChildElementsWithTagName (const String& name) throw() | |||
@@ -911,32 +718,18 @@ void XmlElement::deleteAllChildElementsWithTagName (const String& name) throw() | |||
while (child != 0) | |||
{ | |||
XmlElement* const nextChild = child->nextListItem; | |||
if (child->hasTagName (name)) | |||
{ | |||
XmlElement* const nextChild = child->nextElement; | |||
removeChildElement (child, true); | |||
child = nextChild; | |||
} | |||
else | |||
{ | |||
child = child->nextElement; | |||
} | |||
child = nextChild; | |||
} | |||
} | |||
bool XmlElement::containsChildElement (const XmlElement* const possibleChild) const throw() | |||
{ | |||
const XmlElement* child = firstChildElement; | |||
while (child != 0) | |||
{ | |||
if (child == possibleChild) | |||
return true; | |||
child = child->nextElement; | |||
} | |||
return false; | |||
return firstChildElement.contains (possibleChild); | |||
} | |||
XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLookFor) throw() | |||
@@ -956,7 +749,7 @@ XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLo | |||
if (found != 0) | |||
return found; | |||
child = child->nextElement; | |||
child = child->nextListItem; | |||
} | |||
return 0; | |||
@@ -964,13 +757,7 @@ XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLo | |||
void XmlElement::getChildElementsAsArray (XmlElement** elems) const throw() | |||
{ | |||
XmlElement* e = firstChildElement; | |||
while (e != 0) | |||
{ | |||
*elems++ = e; | |||
e = e->nextElement; | |||
} | |||
firstChildElement.copyToArray (elems); | |||
} | |||
void XmlElement::reorderChildElements (XmlElement** const elems, const int num) throw() | |||
@@ -979,11 +766,11 @@ void XmlElement::reorderChildElements (XmlElement** const elems, const int num) | |||
for (int i = 1; i < num; ++i) | |||
{ | |||
e->nextElement = elems[i]; | |||
e = e->nextElement; | |||
e->nextListItem = elems[i]; | |||
e = e->nextListItem; | |||
} | |||
e->nextElement = 0; | |||
e->nextListItem = 0; | |||
} | |||
//============================================================================== | |||
@@ -1023,7 +810,7 @@ const String XmlElement::getAllSubText() const | |||
while (child != 0) | |||
{ | |||
concatenator.append (child->getAllSubText()); | |||
child = child->nextElement; | |||
child = child->nextListItem; | |||
} | |||
return result; | |||
@@ -1058,7 +845,7 @@ void XmlElement::deleteAllTextElements() throw() | |||
while (child != 0) | |||
{ | |||
XmlElement* const next = child->nextElement; | |||
XmlElement* const next = child->nextListItem; | |||
if (child->isTextElement()) | |||
removeChildElement (child, true); | |||
@@ -29,6 +29,7 @@ | |||
#include "juce_String.h" | |||
#include "../io/streams/juce_OutputStream.h" | |||
#include "../io/files/juce_File.h" | |||
#include "../containers/juce_LinkedListPointer.h" | |||
//============================================================================== | |||
@@ -451,7 +452,7 @@ public: | |||
@see getNextElement, isTextElement, forEachXmlChildElement | |||
*/ | |||
inline XmlElement* getNextElement() const throw() { return nextElement; } | |||
inline XmlElement* getNextElement() const throw() { return nextListItem; } | |||
/** Returns the next of this element's siblings which has the specified tag | |||
name. | |||
@@ -690,8 +691,9 @@ private: | |||
friend class XmlDocument; | |||
String tagName; | |||
XmlElement* firstChildElement; | |||
XmlElement* nextElement; | |||
friend class LinkedListPointer <XmlElement>; | |||
LinkedListPointer <XmlElement> firstChildElement; | |||
LinkedListPointer <XmlElement> nextListItem; | |||
struct XmlAttributeNode | |||
{ | |||
@@ -699,7 +701,7 @@ private: | |||
XmlAttributeNode (const String& name, const String& value) throw(); | |||
String name, value; | |||
XmlAttributeNode* next; | |||
LinkedListPointer<XmlAttributeNode> nextListItem; | |||
bool hasName (const String& name) const throw(); | |||
@@ -707,7 +709,8 @@ private: | |||
XmlAttributeNode& operator= (const XmlAttributeNode&); | |||
}; | |||
XmlAttributeNode* attributes; | |||
friend class LinkedListPointer<XmlAttributeNode>; | |||
LinkedListPointer <XmlAttributeNode> attributes; | |||
XmlElement (int) throw(); | |||
void copyChildrenAndAttributesFrom (const XmlElement& other); | |||