@@ -490,6 +490,7 @@ | |||||
F77C9170829579FABA5679AD = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_DynamicObject.cpp; path = ../../src/containers/juce_DynamicObject.cpp; sourceTree = SOURCE_ROOT; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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, | F77C9170829579FABA5679AD, | ||||
34C402EF9ADCAD34FB657D43, | 34C402EF9ADCAD34FB657D43, | ||||
7DA9AC75A4D9227C8FC4B2F7, | 7DA9AC75A4D9227C8FC4B2F7, | ||||
9289A1E6B141F24C57FF0927, | |||||
70E5409425A76782B6188B31, | 70E5409425A76782B6188B31, | ||||
BB4A73064B0FC74ECCA19116, | BB4A73064B0FC74ECCA19116, | ||||
C1913C90ED7BE51E823887CD, | C1913C90ED7BE51E823887CD, | ||||
@@ -353,6 +353,7 @@ | |||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/> | <File RelativePath="..\..\src\containers\juce_DynamicObject.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | <File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.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.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | <File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_OwnedArray.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.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | <File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.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.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | <File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_OwnedArray.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.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | <File RelativePath="..\..\src\containers\juce_DynamicObject.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_ElementComparator.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.cpp"/> | ||||
<File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | <File RelativePath="..\..\src\containers\juce_NamedValueSet.h"/> | ||||
<File RelativePath="..\..\src\containers\juce_OwnedArray.h"/> | <File RelativePath="..\..\src\containers\juce_OwnedArray.h"/> | ||||
@@ -509,6 +509,7 @@ | |||||
<ClInclude Include="..\..\src\containers\juce_ArrayAllocationBase.h"/> | <ClInclude Include="..\..\src\containers\juce_ArrayAllocationBase.h"/> | ||||
<ClInclude Include="..\..\src\containers\juce_DynamicObject.h"/> | <ClInclude Include="..\..\src\containers\juce_DynamicObject.h"/> | ||||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.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_NamedValueSet.h"/> | ||||
<ClInclude Include="..\..\src\containers\juce_OwnedArray.h"/> | <ClInclude Include="..\..\src\containers\juce_OwnedArray.h"/> | ||||
<ClInclude Include="..\..\src\containers\juce_PropertySet.h"/> | <ClInclude Include="..\..\src\containers\juce_PropertySet.h"/> | ||||
@@ -1455,6 +1455,9 @@ | |||||
<ClInclude Include="..\..\src\containers\juce_ElementComparator.h"> | <ClInclude Include="..\..\src\containers\juce_ElementComparator.h"> | ||||
<Filter>Juce\Source\containers</Filter> | <Filter>Juce\Source\containers</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="..\..\src\containers\juce_LinkedListPointer.h"> | |||||
<Filter>Juce\Source\containers</Filter> | |||||
</ClInclude> | |||||
<ClInclude Include="..\..\src\containers\juce_NamedValueSet.h"> | <ClInclude Include="..\..\src\containers\juce_NamedValueSet.h"> | ||||
<Filter>Juce\Source\containers</Filter> | <Filter>Juce\Source\containers</Filter> | ||||
</ClInclude> | </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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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, | F77C9170829579FABA5679AD, | ||||
34C402EF9ADCAD34FB657D43, | 34C402EF9ADCAD34FB657D43, | ||||
7DA9AC75A4D9227C8FC4B2F7, | 7DA9AC75A4D9227C8FC4B2F7, | ||||
9289A1E6B141F24C57FF0927, | |||||
70E5409425A76782B6188B31, | 70E5409425A76782B6188B31, | ||||
BB4A73064B0FC74ECCA19116, | BB4A73064B0FC74ECCA19116, | ||||
C1913C90ED7BE51E823887CD, | C1913C90ED7BE51E823887CD, | ||||
@@ -365,6 +365,8 @@ | |||||
file="src/containers/juce_DynamicObject.h"/> | file="src/containers/juce_DynamicObject.h"/> | ||||
<FILE id="RNHQjBFmS" name="juce_ElementComparator.h" compile="0" resource="0" | <FILE id="RNHQjBFmS" name="juce_ElementComparator.h" compile="0" resource="0" | ||||
file="src/containers/juce_ElementComparator.h"/> | 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 id="zy1yAvLC1" name="juce_NamedValueSet.cpp" compile="1" resource="0" | ||||
file="src/containers/juce_NamedValueSet.cpp"/> | file="src/containers/juce_NamedValueSet.cpp"/> | ||||
<FILE id="YIzV0n7ns" name="juce_NamedValueSet.h" compile="0" resource="0" | <FILE id="YIzV0n7ns" name="juce_NamedValueSet.h" compile="0" resource="0" | ||||
@@ -64,7 +64,7 @@ | |||||
*/ | */ | ||||
#define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
#define JUCE_BUILDNUMBER 110 | |||||
#define JUCE_BUILDNUMBER 111 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -6624,6 +6624,325 @@ private: | |||||
#endif | #endif | ||||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ | #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 | #endif | ||||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | #ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | ||||
@@ -9835,7 +10154,7 @@ public: | |||||
@see getNextElement, isTextElement, forEachXmlChildElement | @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 | /** Returns the next of this element's siblings which has the specified tag | ||||
name. | name. | ||||
@@ -10070,8 +10389,9 @@ private: | |||||
friend class XmlDocument; | friend class XmlDocument; | ||||
String tagName; | String tagName; | ||||
XmlElement* firstChildElement; | |||||
XmlElement* nextElement; | |||||
friend class LinkedListPointer <XmlElement>; | |||||
LinkedListPointer <XmlElement> firstChildElement; | |||||
LinkedListPointer <XmlElement> nextListItem; | |||||
struct XmlAttributeNode | struct XmlAttributeNode | ||||
{ | { | ||||
@@ -10079,7 +10399,7 @@ private: | |||||
XmlAttributeNode (const String& name, const String& value) throw(); | XmlAttributeNode (const String& name, const String& value) throw(); | ||||
String name, value; | String name, value; | ||||
XmlAttributeNode* next; | |||||
LinkedListPointer<XmlAttributeNode> nextListItem; | |||||
bool hasName (const String& name) const throw(); | bool hasName (const String& name) const throw(); | ||||
@@ -10087,7 +10407,8 @@ private: | |||||
XmlAttributeNode& operator= (const XmlAttributeNode&); | XmlAttributeNode& operator= (const XmlAttributeNode&); | ||||
}; | }; | ||||
XmlAttributeNode* attributes; | |||||
friend class LinkedListPointer<XmlAttributeNode>; | |||||
LinkedListPointer <XmlAttributeNode> attributes; | |||||
XmlElement (int) throw(); | XmlElement (int) throw(); | ||||
void copyChildrenAndAttributesFrom (const XmlElement& other); | void copyChildrenAndAttributesFrom (const XmlElement& other); | ||||
@@ -28618,9 +28939,10 @@ private: | |||||
void internalMouseMove (MouseInputSource& source, const Point<int>& relativePos, const Time& time); | 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 internalMouseWheel (MouseInputSource& source, const Point<int>& relativePos, const Time& time, float amountX, float amountY); | ||||
void internalBroughtToFront(); | void internalBroughtToFront(); | ||||
void internalFocusGain (const FocusChangeType cause, const WeakReference<Component>&); | |||||
void internalFocusGain (const FocusChangeType cause); | void internalFocusGain (const FocusChangeType cause); | ||||
void internalFocusLoss (const FocusChangeType cause); | void internalFocusLoss (const FocusChangeType cause); | ||||
void internalChildFocusChange (FocusChangeType cause); | |||||
void internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>&); | |||||
void internalModalInputAttempt(); | void internalModalInputAttempt(); | ||||
void internalModifierKeysChanged(); | void internalModifierKeysChanged(); | ||||
void internalChildrenChanged(); | void internalChildrenChanged(); | ||||
@@ -53892,11 +54214,6 @@ private: | |||||
#define __JUCE_DOCUMENTWINDOW_JUCEHEADER__ | #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 ***/ | /*** Start of inlined file: juce_MenuBarModel.h ***/ | ||||
#ifndef __JUCE_MENUBARMODEL_JUCEHEADER__ | #ifndef __JUCE_MENUBARMODEL_JUCEHEADER__ | ||||
#define __JUCE_MENUBARMODEL_JUCEHEADER__ | #define __JUCE_MENUBARMODEL_JUCEHEADER__ | ||||
@@ -54043,97 +54360,6 @@ typedef MenuBarModel::Listener MenuBarModelListener; | |||||
#endif // __JUCE_MENUBARMODEL_JUCEHEADER__ | #endif // __JUCE_MENUBARMODEL_JUCEHEADER__ | ||||
/*** End of inlined file: juce_MenuBarModel.h ***/ | /*** 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. | A resizable window with a title bar and maximise, minimise and close buttons. | ||||
@@ -54256,6 +54482,17 @@ public: | |||||
void setMenuBar (MenuBarModel* menuBarModel, | void setMenuBar (MenuBarModel* menuBarModel, | ||||
int menuBarHeight = 0); | 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 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 | This is triggered by the user clicking the close button, or using some other | ||||
@@ -54344,7 +54581,7 @@ private: | |||||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | ||||
ScopedPointer <Button> titleBarButtons [3]; | ScopedPointer <Button> titleBarButtons [3]; | ||||
Image titleBarIcon; | Image titleBarIcon; | ||||
ScopedPointer <MenuBarComponent> menuBar; | |||||
ScopedPointer <Component> menuBar; | |||||
MenuBarModel* menuBarModel; | MenuBarModel* menuBarModel; | ||||
class ButtonListenerProxy; | class ButtonListenerProxy; | ||||
@@ -56229,6 +56466,102 @@ private: | |||||
#endif | #endif | ||||
#ifndef __JUCE_MENUBARCOMPONENT_JUCEHEADER__ | #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 | #endif | ||||
#ifndef __JUCE_MENUBARMODEL_JUCEHEADER__ | #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_MAJOR_VERSION 1 | ||||
#define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
#define JUCE_BUILDNUMBER 110 | |||||
#define JUCE_BUILDNUMBER 111 | |||||
/** Current Juce version number. | /** Current Juce version number. | ||||
@@ -147,9 +147,10 @@ void Button::setToggleState (const bool shouldBeOn, | |||||
lastToggleState = shouldBeOn; | lastToggleState = shouldBeOn; | ||||
repaint(); | repaint(); | ||||
WeakReference<Component> deletionWatcher (this); | |||||
if (sendChangeNotification) | if (sendChangeNotification) | ||||
{ | { | ||||
WeakReference<Component> deletionWatcher (this); | |||||
sendClickMessage (ModifierKeys()); | sendClickMessage (ModifierKeys()); | ||||
if (deletionWatcher == 0) | if (deletionWatcher == 0) | ||||
@@ -157,7 +158,14 @@ void Button::setToggleState (const bool shouldBeOn, | |||||
} | } | ||||
if (lastToggleState) | if (lastToggleState) | ||||
{ | |||||
turnOffOtherButtonsInGroup (sendChangeNotification); | 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) | 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) | void Component::setSize (const int w, const int h) | ||||
@@ -2561,12 +2568,15 @@ void Component::focusGained (FocusChangeType) | |||||
void Component::internalFocusGain (const FocusChangeType cause) | 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); | focusGained (cause); | ||||
if (safePointer != 0) | if (safePointer != 0) | ||||
internalChildFocusChange (cause); | |||||
internalChildFocusChange (cause, safePointer); | |||||
} | } | ||||
void Component::focusLost (FocusChangeType) | void Component::focusLost (FocusChangeType) | ||||
@@ -2581,7 +2591,7 @@ void Component::internalFocusLoss (const FocusChangeType cause) | |||||
focusLost (focusChangedDirectly); | focusLost (focusChangedDirectly); | ||||
if (safePointer != 0) | if (safePointer != 0) | ||||
internalChildFocusChange (cause); | |||||
internalChildFocusChange (cause, safePointer); | |||||
} | } | ||||
void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) | void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) | ||||
@@ -2589,7 +2599,7 @@ void Component::focusOfChildComponentChanged (FocusChangeType /*cause*/) | |||||
// base class does nothing | // base class does nothing | ||||
} | } | ||||
void Component::internalChildFocusChange (FocusChangeType cause) | |||||
void Component::internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>& safePointer) | |||||
{ | { | ||||
const bool childIsNowFocused = hasKeyboardFocus (true); | const bool childIsNowFocused = hasKeyboardFocus (true); | ||||
@@ -2597,7 +2607,6 @@ void Component::internalChildFocusChange (FocusChangeType cause) | |||||
{ | { | ||||
flags.childCompFocusedFlag = childIsNowFocused; | flags.childCompFocusedFlag = childIsNowFocused; | ||||
WeakReference<Component> safePointer (this); | |||||
focusOfChildComponentChanged (cause); | focusOfChildComponentChanged (cause); | ||||
if (safePointer == 0) | if (safePointer == 0) | ||||
@@ -2605,7 +2614,7 @@ void Component::internalChildFocusChange (FocusChangeType cause) | |||||
} | } | ||||
if (parentComponent_ != 0) | 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 | // give the focus to this component | ||||
if (currentlyFocusedComponent != this) | 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 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 internalMouseWheel (MouseInputSource& source, const Point<int>& relativePos, const Time& time, float amountX, float amountY); | ||||
void internalBroughtToFront(); | void internalBroughtToFront(); | ||||
void internalFocusGain (const FocusChangeType cause, const WeakReference<Component>&); | |||||
void internalFocusGain (const FocusChangeType cause); | void internalFocusGain (const FocusChangeType cause); | ||||
void internalFocusLoss (const FocusChangeType cause); | void internalFocusLoss (const FocusChangeType cause); | ||||
void internalChildFocusChange (FocusChangeType cause); | |||||
void internalChildFocusChange (FocusChangeType cause, const WeakReference<Component>&); | |||||
void internalModalInputAttempt(); | void internalModalInputAttempt(); | ||||
void internalModifierKeysChanged(); | void internalModifierKeysChanged(); | ||||
void internalChildrenChanged(); | void internalChildrenChanged(); | ||||
@@ -43,6 +43,7 @@ BEGIN_JUCE_NAMESPACE | |||||
#include "../juce_Desktop.h" | #include "../juce_Desktop.h" | ||||
#include "../../graphics/drawables/juce_DrawableComposite.h" | #include "../../graphics/drawables/juce_DrawableComposite.h" | ||||
#include "../../graphics/drawables/juce_DrawablePath.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_DocumentWindow.h" | ||||
#include "juce_ComponentPeer.h" | #include "juce_ComponentPeer.h" | ||||
#include "../lookandfeel/juce_LookAndFeel.h" | #include "../lookandfeel/juce_LookAndFeel.h" | ||||
#include "../menus/juce_MenuBarComponent.h" | |||||
#include "../../graphics/imaging/juce_Image.h" | #include "../../graphics/imaging/juce_Image.h" | ||||
@@ -67,11 +68,11 @@ DocumentWindow::DocumentWindow (const String& title, | |||||
titleBarHeight (26), | titleBarHeight (26), | ||||
menuBarHeight (24), | menuBarHeight (24), | ||||
requiredButtons (requiredButtons_), | requiredButtons (requiredButtons_), | ||||
#if JUCE_MAC | |||||
#if JUCE_MAC | |||||
positionTitleBarButtonsOnLeft (true), | positionTitleBarButtonsOnLeft (true), | ||||
#else | |||||
#else | |||||
positionTitleBarButtonsOnLeft (false), | positionTitleBarButtonsOnLeft (false), | ||||
#endif | |||||
#endif | |||||
drawTitleTextCentred (true), | drawTitleTextCentred (true), | ||||
menuBarModel (0) | menuBarModel (0) | ||||
{ | { | ||||
@@ -138,28 +139,39 @@ void DocumentWindow::setTitleBarTextCentred (const bool textShouldBeCentred) | |||||
repaintTitleBar(); | 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; | menuBar = 0; | ||||
menuBarModel = menuBarModel_; | |||||
menuBarHeight = (menuBarHeight_ > 0) ? menuBarHeight_ | |||||
menuBarModel = newMenuBarModel; | |||||
menuBarHeight = newMenuBarHeight > 0 ? newMenuBarHeight | |||||
: getLookAndFeel().getDefaultMenuBarHeight(); | : getLookAndFeel().getDefaultMenuBarHeight(); | ||||
if (menuBarModel != 0) | 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(); | 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() | void DocumentWindow::closeButtonPressed() | ||||
@@ -269,8 +281,8 @@ const BorderSize DocumentWindow::getContentComponentBorder() | |||||
BorderSize border (getBorderThickness()); | BorderSize border (getBorderThickness()); | ||||
border.setTop (border.getTop() | border.setTop (border.getTop() | ||||
+ (isUsingNativeTitleBar() ? 0 : titleBarHeight) | |||||
+ (menuBar != 0 ? menuBarHeight : 0)); | |||||
+ (isUsingNativeTitleBar() ? 0 : titleBarHeight) | |||||
+ (menuBar != 0 ? menuBarHeight : 0)); | |||||
return border; | return border; | ||||
} | } | ||||
@@ -289,20 +301,9 @@ const Rectangle<int> DocumentWindow::getTitleBarArea() | |||||
getTitleBarHeight()); | 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 | int DocumentWindow::getDesktopWindowStyleFlags() const | ||||
{ | { | ||||
@@ -328,14 +329,16 @@ void DocumentWindow::lookAndFeelChanged() | |||||
if (! isUsingNativeTitleBar()) | 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) | for (i = 0; i < 3; ++i) | ||||
{ | { | ||||
@@ -354,11 +357,11 @@ void DocumentWindow::lookAndFeelChanged() | |||||
if (getCloseButton() != 0) | if (getCloseButton() != 0) | ||||
{ | { | ||||
#if JUCE_MAC | |||||
#if JUCE_MAC | |||||
getCloseButton()->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | getCloseButton()->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | ||||
#else | |||||
#else | |||||
getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); | getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); | ||||
#endif | |||||
#endif | |||||
} | } | ||||
} | } | ||||
@@ -28,7 +28,7 @@ | |||||
#include "juce_ResizableWindow.h" | #include "juce_ResizableWindow.h" | ||||
#include "../buttons/juce_Button.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); | void setTitleBarTextCentred (bool textShouldBeCentred); | ||||
//============================================================================== | |||||
/** Creates a menu inside this window. | /** Creates a menu inside this window. | ||||
@param menuBarModel this specifies a MenuBarModel that should be used to | @param menuBarModel this specifies a MenuBarModel that should be used to | ||||
@@ -156,6 +157,17 @@ public: | |||||
void setMenuBar (MenuBarModel* menuBarModel, | void setMenuBar (MenuBarModel* menuBarModel, | ||||
int menuBarHeight = 0); | 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 method is called when the user tries to close the window. | ||||
@@ -248,7 +260,7 @@ private: | |||||
bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; | ||||
ScopedPointer <Button> titleBarButtons [3]; | ScopedPointer <Button> titleBarButtons [3]; | ||||
Image titleBarIcon; | Image titleBarIcon; | ||||
ScopedPointer <MenuBarComponent> menuBar; | |||||
ScopedPointer <Component> menuBar; | |||||
MenuBarModel* menuBarModel; | MenuBarModel* menuBarModel; | ||||
class ButtonListenerProxy; | class ButtonListenerProxy; | ||||
@@ -244,13 +244,18 @@ void DrawableImage::refreshFromValueTree (const ValueTree& tree, ImageProvider* | |||||
const RelativeParallelogram newBounds (controller.getBoundingBox()); | const RelativeParallelogram newBounds (controller.getBoundingBox()); | ||||
if (newOpacity != opacity || overlayColour != newOverlayColour || image != newImage) | |||||
if (bounds != newBounds || newOpacity != opacity | |||||
|| overlayColour != newOverlayColour || image != newImage) | |||||
{ | { | ||||
repaint(); | repaint(); | ||||
opacity = newOpacity; | opacity = newOpacity; | ||||
overlayColour = newOverlayColour; | overlayColour = newOverlayColour; | ||||
bounds = newBounds; | bounds = newBounds; | ||||
setImage (newImage); | |||||
if (image != newImage) | |||||
setImage (newImage); | |||||
else | |||||
refreshTransformFromBounds(); | |||||
} | } | ||||
} | } | ||||
@@ -129,6 +129,7 @@ void DrawableShape::paint (Graphics& g) | |||||
void DrawableShape::pathChanged() | void DrawableShape::pathChanged() | ||||
{ | { | ||||
rebuildPath (path); | |||||
strokeChanged(); | strokeChanged(); | ||||
} | } | ||||
@@ -41,6 +41,9 @@ | |||||
#ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ | #ifndef __JUCE_ELEMENTCOMPARATOR_JUCEHEADER__ | ||||
#include "containers/juce_ElementComparator.h" | #include "containers/juce_ElementComparator.h" | ||||
#endif | #endif | ||||
#ifndef __JUCE_LINKEDLISTPOINTER_JUCEHEADER__ | |||||
#include "containers/juce_LinkedListPointer.h" | |||||
#endif | |||||
#ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | #ifndef __JUCE_NAMEDVALUESET_JUCEHEADER__ | ||||
#include "containers/juce_NamedValueSet.h" | #include "containers/juce_NamedValueSet.h" | ||||
#endif | #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_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_activate, (jack_client_t* client), (client)); | ||||
JUCE_DECL_JACK_FUNCTION (int, jack_deactivate, (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 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 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) | #define MakeObjCClassName(rootName) appendMacro2 (rootName, JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_BUILDNUMBER, JUCE_ObjCExtraSuffix) | ||||
#endif | |||||
#endif |
@@ -492,6 +492,7 @@ public: | |||||
isDragging (false), | isDragging (false), | ||||
isMouseOver (false), | isMouseOver (false), | ||||
hasCreatedCaret (false), | hasCreatedCaret (false), | ||||
constrainerIsResizing (false), | |||||
currentWindowIcon (0), | currentWindowIcon (0), | ||||
dropTarget (0), | dropTarget (0), | ||||
updateLayeredWindowAlpha (255), | updateLayeredWindowAlpha (255), | ||||
@@ -1029,7 +1030,7 @@ private: | |||||
#if JUCE_DIRECT2D | #if JUCE_DIRECT2D | ||||
ScopedPointer<Direct2DLowLevelGraphicsContext> direct2DContext; | ScopedPointer<Direct2DLowLevelGraphicsContext> direct2DContext; | ||||
#endif | #endif | ||||
bool fullScreen, isDragging, isMouseOver, hasCreatedCaret; | |||||
bool fullScreen, isDragging, isMouseOver, hasCreatedCaret, constrainerIsResizing; | |||||
BorderSize windowBorder; | BorderSize windowBorder; | ||||
HICON currentWindowIcon; | HICON currentWindowIcon; | ||||
ScopedPointer<NOTIFYICONDATA> taskBarIcon; | ScopedPointer<NOTIFYICONDATA> taskBarIcon; | ||||
@@ -1542,6 +1543,14 @@ private: | |||||
void doCaptureChanged() | void doCaptureChanged() | ||||
{ | { | ||||
if (constrainerIsResizing) | |||||
{ | |||||
if (constrainer != 0) | |||||
constrainer->resizeEnd(); | |||||
constrainerIsResizing = false; | |||||
} | |||||
if (isDragging) | if (isDragging) | ||||
doMouseUp (getCurrentMousePos(), (WPARAM) 0); | doMouseUp (getCurrentMousePos(), (WPARAM) 0); | ||||
} | } | ||||
@@ -1764,9 +1773,15 @@ private: | |||||
return false; | return false; | ||||
} | } | ||||
bool isConstrainedNativeWindow() const | |||||
{ | |||||
return constrainer != 0 | |||||
&& (styleFlags & (windowHasTitleBar | windowIsResizable)) == (windowHasTitleBar | windowIsResizable); | |||||
} | |||||
LRESULT handleSizeConstraining (RECT* const r, const WPARAM wParam) | 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); | 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) | 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) | if ((wp->flags & (SWP_NOMOVE | SWP_NOSIZE)) != (SWP_NOMOVE | SWP_NOSIZE) | ||||
&& ! Component::isMouseButtonDownAnywhere()) | && ! Component::isMouseButtonDownAnywhere()) | ||||
@@ -2279,6 +2294,32 @@ private: | |||||
break; | break; | ||||
case WM_NCLBUTTONDOWN: | 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_NCRBUTTONDOWN: | ||||
case WM_NCMBUTTONDOWN: | case WM_NCMBUTTONDOWN: | ||||
sendInputAttemptWhenModalMessage(); | sendInputAttemptWhenModalMessage(); | ||||
@@ -385,7 +385,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||||
node = new XmlElement (String (input, tagLen)); | node = new XmlElement (String (input, tagLen)); | ||||
input += tagLen; | input += tagLen; | ||||
XmlElement::XmlAttributeNode* lastAttribute = 0; | |||||
LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); | |||||
// look for attributes | // look for attributes | ||||
for (;;) | for (;;) | ||||
@@ -437,14 +437,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||||
String::empty); | String::empty); | ||||
readQuotedString (newAtt->value); | readQuotedString (newAtt->value); | ||||
if (lastAttribute == 0) | |||||
node->attributes = newAtt; | |||||
else | |||||
lastAttribute->next = newAtt; | |||||
lastAttribute = newAtt; | |||||
attributeAppender.append (newAtt); | |||||
continue; | continue; | ||||
} | } | ||||
} | } | ||||
@@ -465,7 +458,7 @@ XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) | |||||
void XmlDocument::readChildElements (XmlElement* parent) | void XmlDocument::readChildElements (XmlElement* parent) | ||||
{ | { | ||||
XmlElement* lastChildNode = 0; | |||||
LinkedListPointer<XmlElement>::Appender childAppender (parent->firstChildElement); | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
@@ -521,14 +514,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||||
++len; | ++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 | else | ||||
{ | { | ||||
@@ -536,18 +522,9 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||||
XmlElement* const n = readNextElement (true); | XmlElement* const n = readNextElement (true); | ||||
if (n != 0) | if (n != 0) | ||||
{ | |||||
if (lastChildNode == 0) | |||||
parent->addChildElement (n); | |||||
else | |||||
lastChildNode->nextElement = n; | |||||
lastChildNode = n; | |||||
} | |||||
childAppender.append (n); | |||||
else | else | ||||
{ | |||||
return; | return; | ||||
} | |||||
} | } | ||||
} | } | ||||
else // must be a character block | else // must be a character block | ||||
@@ -589,12 +566,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||||
if (n == 0) | if (n == 0) | ||||
break; | break; | ||||
if (lastChildNode == 0) | |||||
parent->addChildElement (n); | |||||
else | |||||
lastChildNode->nextElement = n; | |||||
lastChildNode = n; | |||||
childAppender.append (n); | |||||
} | } | ||||
input = oldInput; | input = oldInput; | ||||
@@ -635,14 +607,7 @@ void XmlDocument::readChildElements (XmlElement* parent) | |||||
if ((! ignoreEmptyTextElements) || textElementContent.containsNonWhitespaceChars()) | 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) | 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() | XmlElement::XmlAttributeNode::XmlAttributeNode (const XmlAttributeNode& other) throw() | ||||
: name (other.name), | : name (other.name), | ||||
value (other.value), | |||||
next (0) | |||||
value (other.value) | |||||
{ | { | ||||
} | } | ||||
XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const String& value_) throw() | XmlElement::XmlAttributeNode::XmlAttributeNode (const String& name_, const String& value_) throw() | ||||
: name (name_), | : name (name_), | ||||
value (value_), | |||||
next (0) | |||||
value (value_) | |||||
{ | { | ||||
#if JUCE_DEBUG | #if JUCE_DEBUG | ||||
// this checks whether the attribute name string contains any illegals characters.. | // 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() | 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! | // the tag name mustn't be empty, or it'll look like a text element! | ||||
jassert (tagName_.containsNonWhitespaceChars()) | jassert (tagName_.containsNonWhitespaceChars()) | ||||
@@ -74,17 +69,11 @@ XmlElement::XmlElement (const String& tagName_) throw() | |||||
} | } | ||||
XmlElement::XmlElement (int /*dummy*/) throw() | XmlElement::XmlElement (int /*dummy*/) throw() | ||||
: firstChildElement (0), | |||||
nextElement (0), | |||||
attributes (0) | |||||
{ | { | ||||
} | } | ||||
XmlElement::XmlElement (const XmlElement& other) | XmlElement::XmlElement (const XmlElement& other) | ||||
: tagName (other.tagName), | |||||
firstChildElement (0), | |||||
nextElement (0), | |||||
attributes (0) | |||||
: tagName (other.tagName) | |||||
{ | { | ||||
copyChildrenAndAttributesFrom (other); | copyChildrenAndAttributesFrom (other); | ||||
} | } | ||||
@@ -106,58 +95,17 @@ XmlElement& XmlElement::operator= (const XmlElement& other) | |||||
void XmlElement::copyChildrenAndAttributesFrom (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::~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; | const int attIndent = indentationLevel + tagName.length() + 1; | ||||
int lineLen = 0; | 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) | if (lineLen > lineWrapLength && indentationLevel >= 0) | ||||
{ | { | ||||
@@ -322,7 +270,7 @@ void XmlElement::writeElementAsText (OutputStream& outputStream, | |||||
lastWasTextNode = false; | lastWasTextNode = false; | ||||
} | } | ||||
child = child->nextElement; | |||||
child = child->getNextElement(); | |||||
} | } | ||||
if (indentationLevel >= 0 && ! lastWasTextNode) | if (indentationLevel >= 0 && ! lastWasTextNode) | ||||
@@ -438,10 +386,10 @@ bool XmlElement::hasTagName (const String& tagNameWanted) const throw() | |||||
XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName) const | XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName) const | ||||
{ | { | ||||
XmlElement* e = nextElement; | |||||
XmlElement* e = nextListItem; | |||||
while (e != 0 && ! e->hasTagName (requiredTagName)) | while (e != 0 && ! e->hasTagName (requiredTagName)) | ||||
e = e->nextElement; | |||||
e = e->nextListItem; | |||||
return e; | return e; | ||||
} | } | ||||
@@ -449,47 +397,24 @@ XmlElement* XmlElement::getNextElementWithTagName (const String& requiredTagName | |||||
//============================================================================== | //============================================================================== | ||||
int XmlElement::getNumAttributes() const throw() | 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() | 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() | 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() | 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)) | if (att->hasName (attributeName)) | ||||
return true; | return true; | ||||
@@ -499,7 +424,7 @@ bool XmlElement::hasAttribute (const String& attributeName) const throw() | |||||
//============================================================================== | //============================================================================== | ||||
const String& XmlElement::getStringAttribute (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)) | if (att->hasName (attributeName)) | ||||
return att->value; | 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 | 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)) | if (att->hasName (attributeName)) | ||||
return att->value; | 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 | 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)) | if (att->hasName (attributeName)) | ||||
return att->value.getIntValue(); | 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 | 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)) | if (att->hasName (attributeName)) | ||||
return att->value.getDoubleValue(); | 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 | 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)) | if (att->hasName (attributeName)) | ||||
{ | { | ||||
@@ -559,7 +484,7 @@ bool XmlElement::compareAttribute (const String& attributeName, | |||||
const String& stringToCompareAgainst, | const String& stringToCompareAgainst, | ||||
const bool ignoreCase) const throw() | 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)) | if (att->hasName (attributeName)) | ||||
return ignoreCase ? att->value.equalsIgnoreCase (stringToCompareAgainst) | return ignoreCase ? att->value.equalsIgnoreCase (stringToCompareAgainst) | ||||
: att->value == stringToCompareAgainst; | : att->value == stringToCompareAgainst; | ||||
@@ -585,13 +510,13 @@ void XmlElement::setAttribute (const String& attributeName, const String& value) | |||||
att->value = value; | att->value = value; | ||||
break; | break; | ||||
} | } | ||||
else if (att->next == 0) | |||||
else if (att->nextListItem == 0) | |||||
{ | { | ||||
att->next = new XmlAttributeNode (attributeName, value); | |||||
att->nextListItem = new XmlAttributeNode (attributeName, value); | |||||
break; | 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() | 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; | break; | ||||
} | } | ||||
lastAtt = att; | |||||
att = &(att->get()->nextListItem); | |||||
} | } | ||||
} | } | ||||
void XmlElement::removeAllAttributes() throw() | void XmlElement::removeAllAttributes() throw() | ||||
{ | { | ||||
while (attributes != 0) | |||||
{ | |||||
XmlAttributeNode* const nextAtt = attributes->next; | |||||
delete attributes; | |||||
attributes = nextAtt; | |||||
} | |||||
attributes.deleteAll(); | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
int XmlElement::getNumChildElements() const throw() | 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() | 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() | XmlElement* XmlElement::getChildByName (const String& childName) const throw() | ||||
@@ -675,7 +572,7 @@ XmlElement* XmlElement::getChildByName (const String& childName) const throw() | |||||
if (child->hasTagName (childName)) | if (child->hasTagName (childName)) | ||||
break; | break; | ||||
child = child->nextElement; | |||||
child = child->nextListItem; | |||||
} | } | ||||
return child; | return child; | ||||
@@ -684,25 +581,7 @@ XmlElement* XmlElement::getChildByName (const String& childName) const throw() | |||||
void XmlElement::addChildElement (XmlElement* const newNode) throw() | void XmlElement::addChildElement (XmlElement* const newNode) throw() | ||||
{ | { | ||||
if (newNode != 0) | 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, | void XmlElement::insertChildElement (XmlElement* const newNode, | ||||
@@ -711,32 +590,7 @@ void XmlElement::insertChildElement (XmlElement* const newNode, | |||||
if (newNode != 0) | if (newNode != 0) | ||||
{ | { | ||||
removeChildElement (newNode, false); | 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) | 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 (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) | if (shouldDeleteTheChild) | ||||
delete childToRemove; | delete childToRemove; | ||||
@@ -838,7 +650,7 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||||
if (! other->compareAttribute (att->name, att->value)) | if (! other->compareAttribute (att->name, att->value)) | ||||
return false; | return false; | ||||
att = att->next; | |||||
att = att->nextListItem; | |||||
++totalAtts; | ++totalAtts; | ||||
} | } | ||||
@@ -866,8 +678,8 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, | |||||
return false; | 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)) | if (! thisChild->isEquivalentTo (otherChild, ignoreOrderOfAttributes)) | ||||
return false; | 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() | 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() | void XmlElement::deleteAllChildElementsWithTagName (const String& name) throw() | ||||
@@ -911,32 +718,18 @@ void XmlElement::deleteAllChildElementsWithTagName (const String& name) throw() | |||||
while (child != 0) | while (child != 0) | ||||
{ | { | ||||
XmlElement* const nextChild = child->nextListItem; | |||||
if (child->hasTagName (name)) | if (child->hasTagName (name)) | ||||
{ | |||||
XmlElement* const nextChild = child->nextElement; | |||||
removeChildElement (child, true); | removeChildElement (child, true); | ||||
child = nextChild; | |||||
} | |||||
else | |||||
{ | |||||
child = child->nextElement; | |||||
} | |||||
child = nextChild; | |||||
} | } | ||||
} | } | ||||
bool XmlElement::containsChildElement (const XmlElement* const possibleChild) const throw() | 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() | XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLookFor) throw() | ||||
@@ -956,7 +749,7 @@ XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLo | |||||
if (found != 0) | if (found != 0) | ||||
return found; | return found; | ||||
child = child->nextElement; | |||||
child = child->nextListItem; | |||||
} | } | ||||
return 0; | return 0; | ||||
@@ -964,13 +757,7 @@ XmlElement* XmlElement::findParentElementOf (const XmlElement* const elementToLo | |||||
void XmlElement::getChildElementsAsArray (XmlElement** elems) const throw() | 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() | 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) | 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) | while (child != 0) | ||||
{ | { | ||||
concatenator.append (child->getAllSubText()); | concatenator.append (child->getAllSubText()); | ||||
child = child->nextElement; | |||||
child = child->nextListItem; | |||||
} | } | ||||
return result; | return result; | ||||
@@ -1058,7 +845,7 @@ void XmlElement::deleteAllTextElements() throw() | |||||
while (child != 0) | while (child != 0) | ||||
{ | { | ||||
XmlElement* const next = child->nextElement; | |||||
XmlElement* const next = child->nextListItem; | |||||
if (child->isTextElement()) | if (child->isTextElement()) | ||||
removeChildElement (child, true); | removeChildElement (child, true); | ||||
@@ -29,6 +29,7 @@ | |||||
#include "juce_String.h" | #include "juce_String.h" | ||||
#include "../io/streams/juce_OutputStream.h" | #include "../io/streams/juce_OutputStream.h" | ||||
#include "../io/files/juce_File.h" | #include "../io/files/juce_File.h" | ||||
#include "../containers/juce_LinkedListPointer.h" | |||||
//============================================================================== | //============================================================================== | ||||
@@ -451,7 +452,7 @@ public: | |||||
@see getNextElement, isTextElement, forEachXmlChildElement | @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 | /** Returns the next of this element's siblings which has the specified tag | ||||
name. | name. | ||||
@@ -690,8 +691,9 @@ private: | |||||
friend class XmlDocument; | friend class XmlDocument; | ||||
String tagName; | String tagName; | ||||
XmlElement* firstChildElement; | |||||
XmlElement* nextElement; | |||||
friend class LinkedListPointer <XmlElement>; | |||||
LinkedListPointer <XmlElement> firstChildElement; | |||||
LinkedListPointer <XmlElement> nextListItem; | |||||
struct XmlAttributeNode | struct XmlAttributeNode | ||||
{ | { | ||||
@@ -699,7 +701,7 @@ private: | |||||
XmlAttributeNode (const String& name, const String& value) throw(); | XmlAttributeNode (const String& name, const String& value) throw(); | ||||
String name, value; | String name, value; | ||||
XmlAttributeNode* next; | |||||
LinkedListPointer<XmlAttributeNode> nextListItem; | |||||
bool hasName (const String& name) const throw(); | bool hasName (const String& name) const throw(); | ||||
@@ -707,7 +709,8 @@ private: | |||||
XmlAttributeNode& operator= (const XmlAttributeNode&); | XmlAttributeNode& operator= (const XmlAttributeNode&); | ||||
}; | }; | ||||
XmlAttributeNode* attributes; | |||||
friend class LinkedListPointer<XmlAttributeNode>; | |||||
LinkedListPointer <XmlAttributeNode> attributes; | |||||
XmlElement (int) throw(); | XmlElement (int) throw(); | ||||
void copyChildrenAndAttributesFrom (const XmlElement& other); | void copyChildrenAndAttributesFrom (const XmlElement& other); | ||||