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