| @@ -271,6 +271,45 @@ void MessageManager::stopDispatchLoop() | |||||
| [NSApp stop: nil]; | [NSApp stop: nil]; | ||||
| } | } | ||||
| static bool isEventBlockedByModalComps (NSEvent* e) | |||||
| { | |||||
| if (Component::getNumCurrentlyModalComponents() == 0) | |||||
| return false; | |||||
| [[NSApp mainMenu] update]; | |||||
| NSWindow* const w = [e window]; | |||||
| if (w == 0 || [w worksWhenModal]) | |||||
| return false; | |||||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||||
| { | |||||
| ComponentPeer* const peer = ComponentPeer::getPeer (i); | |||||
| NSView* const compView = (NSView*) peer->getNativeHandle(); | |||||
| if ([compView window] == w | |||||
| && (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], | |||||
| [compView bounds]) | |||||
| || peer->getComponent()->isMouseButtonDown())) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| if ([e type] == NSLeftMouseDown | |||||
| || [e type] == NSRightMouseDown | |||||
| || [e type] == NSOtherMouseDown) | |||||
| { | |||||
| if (! [NSApp isActive]) | |||||
| [NSApp activateIgnoringOtherApps: YES]; | |||||
| Component* const modal = Component::getCurrentlyModalComponent (0); | |||||
| if (modal != 0) | |||||
| modal->inputAttemptWhenModal(); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | ||||
| { | { | ||||
| const ScopedAutoReleasePool pool; | const ScopedAutoReleasePool pool; | ||||
| @@ -290,7 +329,9 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||||
| untilDate: endDate | untilDate: endDate | ||||
| inMode: NSDefaultRunLoopMode | inMode: NSDefaultRunLoopMode | ||||
| dequeue: YES]; | dequeue: YES]; | ||||
| [NSApp sendEvent: e]; | |||||
| if (! isEventBlockedByModalComps (e)) | |||||
| [NSApp sendEvent: e]; | |||||
| } | } | ||||
| return ! quitMessagePosted; | return ! quitMessagePosted; | ||||
| @@ -325,8 +366,6 @@ void MessageManager::doPlatformSpecificShutdown() | |||||
| getInstance()->runDispatchLoopUntil (10); | getInstance()->runDispatchLoopUntil (10); | ||||
| } | } | ||||
| jassert (numPendingMessages == 0); // failed to get all the pending messages cleared before quitting.. | |||||
| [juceAppDelegate release]; | [juceAppDelegate release]; | ||||
| juceAppDelegate = 0; | juceAppDelegate = 0; | ||||
| } | } | ||||
| @@ -54,7 +54,9 @@ END_JUCE_NAMESPACE | |||||
| - (void) drawRect: (NSRect) r; | - (void) drawRect: (NSRect) r; | ||||
| - (void) mouseDown: (NSEvent*) ev; | - (void) mouseDown: (NSEvent*) ev; | ||||
| - (void) asyncMouseDown: (NSEvent*) ev; | |||||
| - (void) mouseUp: (NSEvent*) ev; | - (void) mouseUp: (NSEvent*) ev; | ||||
| - (void) asyncMouseUp: (NSEvent*) ev; | |||||
| - (void) mouseDragged: (NSEvent*) ev; | - (void) mouseDragged: (NSEvent*) ev; | ||||
| - (void) mouseMoved: (NSEvent*) ev; | - (void) mouseMoved: (NSEvent*) ev; | ||||
| - (void) mouseEntered: (NSEvent*) ev; | - (void) mouseEntered: (NSEvent*) ev; | ||||
| @@ -252,12 +254,38 @@ END_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| - (void) mouseDown: (NSEvent*) ev | - (void) mouseDown: (NSEvent*) ev | ||||
| { | |||||
| // In some host situations, the host will stop modal loops from working | |||||
| // correctly if they're called from a mouse event, so we'll trigger | |||||
| // the event asynchronously.. | |||||
| if (JUCEApplication::getInstance() == 0) | |||||
| [self performSelectorOnMainThread: @selector (asyncMouseDown:) | |||||
| withObject: ev | |||||
| waitUntilDone: NO]; | |||||
| else | |||||
| [self asyncMouseDown: ev]; | |||||
| } | |||||
| - (void) asyncMouseDown: (NSEvent*) ev | |||||
| { | { | ||||
| if (owner != 0) | if (owner != 0) | ||||
| owner->redirectMouseDown (ev); | owner->redirectMouseDown (ev); | ||||
| } | } | ||||
| - (void) mouseUp: (NSEvent*) ev | - (void) mouseUp: (NSEvent*) ev | ||||
| { | |||||
| // In some host situations, the host will stop modal loops from working | |||||
| // correctly if they're called from a mouse event, so we'll trigger | |||||
| // the event asynchronously.. | |||||
| if (JUCEApplication::getInstance() == 0) | |||||
| [self performSelectorOnMainThread: @selector (asyncMouseUp:) | |||||
| withObject: ev | |||||
| waitUntilDone: NO]; | |||||
| else | |||||
| [self asyncMouseUp: ev]; | |||||
| } | |||||
| - (void) asyncMouseUp: (NSEvent*) ev | |||||
| { | { | ||||
| if (owner != 0) | if (owner != 0) | ||||
| owner->redirectMouseUp (ev); | owner->redirectMouseUp (ev); | ||||
| @@ -92,6 +92,59 @@ static LRESULT CALLBACK juce_MessageWndProc (HWND h, | |||||
| return DefWindowProc (h, message, wParam, lParam); | return DefWindowProc (h, message, wParam, lParam); | ||||
| } | } | ||||
| static bool isEventBlockedByModalComps (MSG& m) | |||||
| { | |||||
| if (Component::getNumCurrentlyModalComponents() == 0 | |||||
| || GetWindowLong (m.hwnd, GWLP_USERDATA) == improbableWindowNumber) | |||||
| return false; | |||||
| switch (m.message) | |||||
| { | |||||
| case WM_MOUSEMOVE: | |||||
| case WM_NCMOUSEMOVE: | |||||
| case 0x020A: /* WM_MOUSEWHEEL */ | |||||
| case 0x020E: /* WM_MOUSEHWHEEL */ | |||||
| case WM_KEYUP: | |||||
| case WM_SYSKEYUP: | |||||
| case WM_CHAR: | |||||
| case WM_APPCOMMAND: | |||||
| case WM_LBUTTONUP: | |||||
| case WM_MBUTTONUP: | |||||
| case WM_RBUTTONUP: | |||||
| case WM_MOUSEACTIVATE: | |||||
| case WM_NCMOUSEHOVER: | |||||
| case WM_MOUSEHOVER: | |||||
| return true; | |||||
| case WM_NCLBUTTONDOWN: | |||||
| case WM_NCLBUTTONDBLCLK: | |||||
| case WM_NCRBUTTONDOWN: | |||||
| case WM_NCRBUTTONDBLCLK: | |||||
| case WM_NCMBUTTONDOWN: | |||||
| case WM_NCMBUTTONDBLCLK: | |||||
| case WM_LBUTTONDOWN: | |||||
| case WM_LBUTTONDBLCLK: | |||||
| case WM_MBUTTONDOWN: | |||||
| case WM_MBUTTONDBLCLK: | |||||
| case WM_RBUTTONDOWN: | |||||
| case WM_RBUTTONDBLCLK: | |||||
| case WM_KEYDOWN: | |||||
| case WM_SYSKEYDOWN: | |||||
| { | |||||
| Component* const modal = Component::getCurrentlyModalComponent (0); | |||||
| if (modal != 0) | |||||
| modal->inputAttemptWhenModal(); | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) | bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) | ||||
| { | { | ||||
| MSG m; | MSG m; | ||||
| @@ -106,7 +159,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages | |||||
| { | { | ||||
| MessageManager::getInstance()->deliverMessage ((void*) m.lParam); | MessageManager::getInstance()->deliverMessage ((void*) m.lParam); | ||||
| } | } | ||||
| else | |||||
| else if (! isEventBlockedByModalComps (m)) | |||||
| { | { | ||||
| if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber | if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber | ||||
| && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) | && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) | ||||
| @@ -155,7 +155,7 @@ void AudioFilterStreamingDeviceManager::setFilter (AudioProcessor* filterToStrea | |||||
| if (streamer != 0) | if (streamer != 0) | ||||
| { | { | ||||
| removeMidiInputCallback (String::empty, streamer); | removeMidiInputCallback (String::empty, streamer); | ||||
| setAudioCallback (0); | |||||
| removeAudioCallback (streamer); | |||||
| delete streamer; | delete streamer; | ||||
| streamer = 0; | streamer = 0; | ||||
| @@ -165,7 +165,7 @@ void AudioFilterStreamingDeviceManager::setFilter (AudioProcessor* filterToStrea | |||||
| { | { | ||||
| streamer = new AudioFilterStreamer (*filterToStream); | streamer = new AudioFilterStreamer (*filterToStream); | ||||
| setAudioCallback (streamer); | |||||
| addAudioCallback (streamer); | |||||
| addMidiInputCallback (String::empty, streamer); | addMidiInputCallback (String::empty, streamer); | ||||
| } | } | ||||
| } | } | ||||
| @@ -3562,6 +3562,12 @@ var::var (DynamicObject* const object) throw() | |||||
| object->incReferenceCount(); | object->incReferenceCount(); | ||||
| } | } | ||||
| var::var (MethodFunction method_) throw() | |||||
| : type (methodType) | |||||
| { | |||||
| value.methodValue = method_; | |||||
| } | |||||
| const var& var::operator= (const var& valueToCopy) throw() | const var& var::operator= (const var& valueToCopy) throw() | ||||
| { | { | ||||
| if (this != &valueToCopy) | if (this != &valueToCopy) | ||||
| @@ -3643,6 +3649,14 @@ const var& var::operator= (DynamicObject* const value_) throw() | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| const var& var::operator= (MethodFunction method_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = doubleType; | |||||
| value.methodValue = method_; | |||||
| return *this; | |||||
| } | |||||
| var::operator int() const throw() | var::operator int() const throw() | ||||
| { | { | ||||
| switch (type) | switch (type) | ||||
| @@ -3714,6 +3728,74 @@ DynamicObject* var::getObject() const throw() | |||||
| return type == objectType ? value.objectValue : 0; | return type == objectType ? value.objectValue : 0; | ||||
| } | } | ||||
| const var var::operator[] (const var::identifier& propertyName) const throw() | |||||
| { | |||||
| if (type == objectType && value.objectValue != 0) | |||||
| return value.objectValue->getProperty (propertyName); | |||||
| return var(); | |||||
| } | |||||
| const var var::invoke (const var::identifier& method, const var* arguments, int numArguments) const | |||||
| { | |||||
| if (type == objectType && value.objectValue != 0) | |||||
| return value.objectValue->invokeMethod (method, arguments, numArguments); | |||||
| return var(); | |||||
| } | |||||
| const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const | |||||
| { | |||||
| if (isMethod()) | |||||
| return value.methodValue (targetObject, arguments, numArguments); | |||||
| return var(); | |||||
| } | |||||
| const var var::call (const var::identifier& method) const | |||||
| { | |||||
| return invoke (method, 0, 0); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1) const | |||||
| { | |||||
| return invoke (method, &arg1, 1); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2) const | |||||
| { | |||||
| var args[] = { arg1, arg2 }; | |||||
| return invoke (method, args, 2); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3) | |||||
| { | |||||
| var args[] = { arg1, arg2, arg3 }; | |||||
| return invoke (method, args, 3); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const | |||||
| { | |||||
| var args[] = { arg1, arg2, arg3, arg4 }; | |||||
| return invoke (method, args, 4); | |||||
| } | |||||
| var::identifier::identifier (const String& name_) throw() | |||||
| : name (name_), | |||||
| hashCode (name_.hashCode()) | |||||
| { | |||||
| } | |||||
| var::identifier::identifier (const char* const name_) throw() | |||||
| : name (name_), | |||||
| hashCode (name.hashCode()) | |||||
| { | |||||
| } | |||||
| var::identifier::~identifier() throw() | |||||
| { | |||||
| } | |||||
| DynamicObject::DynamicObject() | DynamicObject::DynamicObject() | ||||
| { | { | ||||
| } | } | ||||
| @@ -3722,23 +3804,24 @@ DynamicObject::~DynamicObject() | |||||
| { | { | ||||
| } | } | ||||
| bool DynamicObject::hasProperty (const String& propertyName) const | |||||
| bool DynamicObject::hasProperty (const var::identifier& propertyName) const | |||||
| { | { | ||||
| return propertyNames.contains (propertyName, false); | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| return index >= 0 && ! propertyValues.getUnchecked (index)->isMethod(); | |||||
| } | } | ||||
| const var DynamicObject::getProperty (const String& propertyName) const | |||||
| const var DynamicObject::getProperty (const var::identifier& propertyName) const | |||||
| { | { | ||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| return *propertyValues.getUnchecked (index); | return *propertyValues.getUnchecked (index); | ||||
| return var(); | return var(); | ||||
| } | } | ||||
| void DynamicObject::setProperty (const String& propertyName, const var& newValue) | |||||
| void DynamicObject::setProperty (const var::identifier& propertyName, const var& newValue) | |||||
| { | { | ||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| { | { | ||||
| @@ -3746,60 +3829,32 @@ void DynamicObject::setProperty (const String& propertyName, const var& newValue | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| propertyNames.add (propertyName); | |||||
| propertyIds.add (propertyName.hashCode); | |||||
| propertyValues.add (new var (newValue)); | propertyValues.add (new var (newValue)); | ||||
| } | } | ||||
| } | } | ||||
| void DynamicObject::removeProperty (const String& propertyName) | |||||
| void DynamicObject::removeProperty (const var::identifier& propertyName) | |||||
| { | { | ||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | if (index >= 0) | ||||
| { | { | ||||
| propertyNames.remove (index); | |||||
| propertyIds.remove (index); | |||||
| propertyValues.remove (index); | propertyValues.remove (index); | ||||
| } | } | ||||
| } | } | ||||
| bool DynamicObject::hasMethod (const String& methodName) const | |||||
| bool DynamicObject::hasMethod (const var::identifier& methodName) const | |||||
| { | { | ||||
| return false; | |||||
| return getProperty (methodName).isMethod(); | |||||
| } | } | ||||
| const var DynamicObject::invokeMethod (const String& methodName, | |||||
| const var DynamicObject::invokeMethod (const var::identifier& methodName, | |||||
| const var* parameters, | const var* parameters, | ||||
| int numParameters) | int numParameters) | ||||
| { | { | ||||
| return var(); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName) | |||||
| { | |||||
| return invokeMethod (methodName, 0, 0); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1) | |||||
| { | |||||
| return invokeMethod (methodName, &arg1, 1); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2) | |||||
| { | |||||
| var params[] = { arg1, arg2 }; | |||||
| return invokeMethod (methodName, params, 2); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3) | |||||
| { | |||||
| var params[] = { arg1, arg2, arg3 }; | |||||
| return invokeMethod (methodName, params, 3); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3, const var& arg4) | |||||
| { | |||||
| var params[] = { arg1, arg2, arg3, arg4 }; | |||||
| return invokeMethod (methodName, params, 4); | |||||
| return getProperty (methodName).invoke (this, parameters, numParameters); | |||||
| } | } | ||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -23037,7 +23092,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
| { | { | ||||
| const double callbackStartTime = Time::getMillisecondCounterHiRes(); | const double callbackStartTime = Time::getMillisecondCounterHiRes(); | ||||
| tempBuffer.setSize (numOutputChannels, numSamples, false, false, true); | |||||
| tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true); | |||||
| callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, | callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, | ||||
| outputChannelData, numOutputChannels, numSamples); | outputChannelData, numOutputChannels, numSamples); | ||||
| @@ -61038,6 +61093,31 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, | |||||
| } | } | ||||
| } | } | ||||
| void LookAndFeel::drawSpinningWaitAnimation (Graphics& g, int x, int y, int w, int h) | |||||
| { | |||||
| const float radius = jmin (w, h) * 0.4f; | |||||
| const float thickness = radius * 0.15f; | |||||
| Path p; | |||||
| p.addRoundedRectangle (radius * 0.4f, thickness * -0.5f, | |||||
| radius * 0.6f, thickness, | |||||
| thickness * 0.5f); | |||||
| const float cx = x + w * 0.5f; | |||||
| const float cy = y + h * 0.5f; | |||||
| const uint32 animationIndex = (Time::getMillisecondCounter() / (1000 / 10)) % 12; | |||||
| const Colour col (g.getCurrentColour()); | |||||
| for (int i = 0; i < 12; ++i) | |||||
| { | |||||
| const int n = (i + 12 - animationIndex) % 12; | |||||
| g.setColour (col.withMultipliedAlpha ((n + 1) / 12.0f)); | |||||
| g.fillPath (p, AffineTransform::rotation (i * (float_Pi / 6.0f)) | |||||
| .translated (cx, cy)); | |||||
| } | |||||
| } | |||||
| void LookAndFeel::drawScrollbarButton (Graphics& g, | void LookAndFeel::drawScrollbarButton (Graphics& g, | ||||
| ScrollBar& scrollbar, | ScrollBar& scrollbar, | ||||
| int width, int height, | int width, int height, | ||||
| @@ -242763,6 +242843,59 @@ static LRESULT CALLBACK juce_MessageWndProc (HWND h, | |||||
| return DefWindowProc (h, message, wParam, lParam); | return DefWindowProc (h, message, wParam, lParam); | ||||
| } | } | ||||
| static bool isEventBlockedByModalComps (MSG& m) | |||||
| { | |||||
| if (Component::getNumCurrentlyModalComponents() == 0 | |||||
| || GetWindowLong (m.hwnd, GWLP_USERDATA) == improbableWindowNumber) | |||||
| return false; | |||||
| switch (m.message) | |||||
| { | |||||
| case WM_MOUSEMOVE: | |||||
| case WM_NCMOUSEMOVE: | |||||
| case 0x020A: /* WM_MOUSEWHEEL */ | |||||
| case 0x020E: /* WM_MOUSEHWHEEL */ | |||||
| case WM_KEYUP: | |||||
| case WM_SYSKEYUP: | |||||
| case WM_CHAR: | |||||
| case WM_APPCOMMAND: | |||||
| case WM_LBUTTONUP: | |||||
| case WM_MBUTTONUP: | |||||
| case WM_RBUTTONUP: | |||||
| case WM_MOUSEACTIVATE: | |||||
| case WM_NCMOUSEHOVER: | |||||
| case WM_MOUSEHOVER: | |||||
| return true; | |||||
| case WM_NCLBUTTONDOWN: | |||||
| case WM_NCLBUTTONDBLCLK: | |||||
| case WM_NCRBUTTONDOWN: | |||||
| case WM_NCRBUTTONDBLCLK: | |||||
| case WM_NCMBUTTONDOWN: | |||||
| case WM_NCMBUTTONDBLCLK: | |||||
| case WM_LBUTTONDOWN: | |||||
| case WM_LBUTTONDBLCLK: | |||||
| case WM_MBUTTONDOWN: | |||||
| case WM_MBUTTONDBLCLK: | |||||
| case WM_RBUTTONDOWN: | |||||
| case WM_RBUTTONDBLCLK: | |||||
| case WM_KEYDOWN: | |||||
| case WM_SYSKEYDOWN: | |||||
| { | |||||
| Component* const modal = Component::getCurrentlyModalComponent (0); | |||||
| if (modal != 0) | |||||
| modal->inputAttemptWhenModal(); | |||||
| return true; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) | bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) | ||||
| { | { | ||||
| MSG m; | MSG m; | ||||
| @@ -242777,7 +242910,7 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages | |||||
| { | { | ||||
| MessageManager::getInstance()->deliverMessage ((void*) m.lParam); | MessageManager::getInstance()->deliverMessage ((void*) m.lParam); | ||||
| } | } | ||||
| else | |||||
| else if (! isEventBlockedByModalComps (m)) | |||||
| { | { | ||||
| if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber | if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber | ||||
| && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) | && (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)) | ||||
| @@ -266715,7 +266848,9 @@ END_JUCE_NAMESPACE | |||||
| - (void) drawRect: (NSRect) r; | - (void) drawRect: (NSRect) r; | ||||
| - (void) mouseDown: (NSEvent*) ev; | - (void) mouseDown: (NSEvent*) ev; | ||||
| - (void) asyncMouseDown: (NSEvent*) ev; | |||||
| - (void) mouseUp: (NSEvent*) ev; | - (void) mouseUp: (NSEvent*) ev; | ||||
| - (void) asyncMouseUp: (NSEvent*) ev; | |||||
| - (void) mouseDragged: (NSEvent*) ev; | - (void) mouseDragged: (NSEvent*) ev; | ||||
| - (void) mouseMoved: (NSEvent*) ev; | - (void) mouseMoved: (NSEvent*) ev; | ||||
| - (void) mouseEntered: (NSEvent*) ev; | - (void) mouseEntered: (NSEvent*) ev; | ||||
| @@ -266904,12 +267039,38 @@ END_JUCE_NAMESPACE | |||||
| } | } | ||||
| - (void) mouseDown: (NSEvent*) ev | - (void) mouseDown: (NSEvent*) ev | ||||
| { | |||||
| // In some host situations, the host will stop modal loops from working | |||||
| // correctly if they're called from a mouse event, so we'll trigger | |||||
| // the event asynchronously.. | |||||
| if (JUCEApplication::getInstance() == 0) | |||||
| [self performSelectorOnMainThread: @selector (asyncMouseDown:) | |||||
| withObject: ev | |||||
| waitUntilDone: NO]; | |||||
| else | |||||
| [self asyncMouseDown: ev]; | |||||
| } | |||||
| - (void) asyncMouseDown: (NSEvent*) ev | |||||
| { | { | ||||
| if (owner != 0) | if (owner != 0) | ||||
| owner->redirectMouseDown (ev); | owner->redirectMouseDown (ev); | ||||
| } | } | ||||
| - (void) mouseUp: (NSEvent*) ev | - (void) mouseUp: (NSEvent*) ev | ||||
| { | |||||
| // In some host situations, the host will stop modal loops from working | |||||
| // correctly if they're called from a mouse event, so we'll trigger | |||||
| // the event asynchronously.. | |||||
| if (JUCEApplication::getInstance() == 0) | |||||
| [self performSelectorOnMainThread: @selector (asyncMouseUp:) | |||||
| withObject: ev | |||||
| waitUntilDone: NO]; | |||||
| else | |||||
| [self asyncMouseUp: ev]; | |||||
| } | |||||
| - (void) asyncMouseUp: (NSEvent*) ev | |||||
| { | { | ||||
| if (owner != 0) | if (owner != 0) | ||||
| owner->redirectMouseUp (ev); | owner->redirectMouseUp (ev); | ||||
| @@ -270811,6 +270972,45 @@ void MessageManager::stopDispatchLoop() | |||||
| [NSApp stop: nil]; | [NSApp stop: nil]; | ||||
| } | } | ||||
| static bool isEventBlockedByModalComps (NSEvent* e) | |||||
| { | |||||
| if (Component::getNumCurrentlyModalComponents() == 0) | |||||
| return false; | |||||
| [[NSApp mainMenu] update]; | |||||
| NSWindow* const w = [e window]; | |||||
| if (w == 0 || [w worksWhenModal]) | |||||
| return false; | |||||
| for (int i = ComponentPeer::getNumPeers(); --i >= 0;) | |||||
| { | |||||
| ComponentPeer* const peer = ComponentPeer::getPeer (i); | |||||
| NSView* const compView = (NSView*) peer->getNativeHandle(); | |||||
| if ([compView window] == w | |||||
| && (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], | |||||
| [compView bounds]) | |||||
| || peer->getComponent()->isMouseButtonDown())) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| if ([e type] == NSLeftMouseDown | |||||
| || [e type] == NSRightMouseDown | |||||
| || [e type] == NSOtherMouseDown) | |||||
| { | |||||
| if (! [NSApp isActive]) | |||||
| [NSApp activateIgnoringOtherApps: YES]; | |||||
| Component* const modal = Component::getCurrentlyModalComponent (0); | |||||
| if (modal != 0) | |||||
| modal->inputAttemptWhenModal(); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | ||||
| { | { | ||||
| const ScopedAutoReleasePool pool; | const ScopedAutoReleasePool pool; | ||||
| @@ -270830,7 +271030,9 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||||
| untilDate: endDate | untilDate: endDate | ||||
| inMode: NSDefaultRunLoopMode | inMode: NSDefaultRunLoopMode | ||||
| dequeue: YES]; | dequeue: YES]; | ||||
| [NSApp sendEvent: e]; | |||||
| if (! isEventBlockedByModalComps (e)) | |||||
| [NSApp sendEvent: e]; | |||||
| } | } | ||||
| return ! quitMessagePosted; | return ! quitMessagePosted; | ||||
| @@ -270864,8 +271066,6 @@ void MessageManager::doPlatformSpecificShutdown() | |||||
| getInstance()->runDispatchLoopUntil (10); | getInstance()->runDispatchLoopUntil (10); | ||||
| } | } | ||||
| jassert (numPendingMessages == 0); // failed to get all the pending messages cleared before quitting.. | |||||
| [juceAppDelegate release]; | [juceAppDelegate release]; | ||||
| juceAppDelegate = 0; | juceAppDelegate = 0; | ||||
| } | } | ||||
| @@ -9812,12 +9812,12 @@ public: | |||||
| @see getUnchecked | @see getUnchecked | ||||
| */ | */ | ||||
| inline ObjectClass* operator[] (const int index) const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> operator[] (const int index) const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (((unsigned int) index) < (unsigned int) numUsed) | |||||
| ? this->elements [index] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((((unsigned int) index) < (unsigned int) numUsed) | |||||
| ? this->elements [index] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -9827,11 +9827,11 @@ public: | |||||
| This is a faster and less safe version of operator[] which doesn't check the index passed in, so | This is a faster and less safe version of operator[] which doesn't check the index passed in, so | ||||
| it can be used when you're sure the index if always going to be legal. | it can be used when you're sure the index if always going to be legal. | ||||
| */ | */ | ||||
| inline ObjectClass* getUnchecked (const int index) const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getUnchecked (const int index) const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | jassert (((unsigned int) index) < (unsigned int) numUsed); | ||||
| ObjectClass* const result = this->elements [index]; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result (this->elements [index]); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -9841,11 +9841,11 @@ public: | |||||
| This will return a null pointer if the array's empty. | This will return a null pointer if the array's empty. | ||||
| @see getLast | @see getLast | ||||
| */ | */ | ||||
| inline ObjectClass* getFirst() const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getFirst() const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (numUsed > 0) ? this->elements [0] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? this->elements [0] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| @@ -9856,11 +9856,11 @@ public: | |||||
| This will return a null pointer if the array's empty. | This will return a null pointer if the array's empty. | ||||
| @see getFirst | @see getFirst | ||||
| */ | */ | ||||
| inline ObjectClass* getLast() const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getLast() const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (numUsed > 0) ? this->elements [numUsed - 1] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? this->elements [numUsed - 1] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| @@ -11384,6 +11384,8 @@ class JUCE_API var | |||||
| { | { | ||||
| public: | public: | ||||
| typedef const var (MethodFunction) (const var& thisObject, const var* arguments, int numArguments); | |||||
| /** Creates a void variant. */ | /** Creates a void variant. */ | ||||
| var() throw(); | var() throw(); | ||||
| @@ -11398,6 +11400,7 @@ public: | |||||
| var (const juce_wchar* const value) throw(); | var (const juce_wchar* const value) throw(); | ||||
| var (const String& value) throw(); | var (const String& value) throw(); | ||||
| var (DynamicObject* const object) throw(); | var (DynamicObject* const object) throw(); | ||||
| var (MethodFunction method) throw(); | |||||
| const var& operator= (const var& valueToCopy) throw(); | const var& operator= (const var& valueToCopy) throw(); | ||||
| const var& operator= (const int value) throw(); | const var& operator= (const int value) throw(); | ||||
| @@ -11407,6 +11410,7 @@ public: | |||||
| const var& operator= (const juce_wchar* const value) throw(); | const var& operator= (const juce_wchar* const value) throw(); | ||||
| const var& operator= (const String& value) throw(); | const var& operator= (const String& value) throw(); | ||||
| const var& operator= (DynamicObject* const object) throw(); | const var& operator= (DynamicObject* const object) throw(); | ||||
| const var& operator= (MethodFunction method) throw(); | |||||
| operator int() const throw(); | operator int() const throw(); | ||||
| operator bool() const throw(); | operator bool() const throw(); | ||||
| @@ -11420,6 +11424,40 @@ public: | |||||
| bool isDouble() const throw() { return type == doubleType; } | bool isDouble() const throw() { return type == doubleType; } | ||||
| bool isString() const throw() { return type == stringType; } | bool isString() const throw() { return type == stringType; } | ||||
| bool isObject() const throw() { return type == objectType; } | bool isObject() const throw() { return type == objectType; } | ||||
| bool isMethod() const throw() { return type == methodType; } | |||||
| class identifier | |||||
| { | |||||
| public: | |||||
| identifier (const char* const name) throw(); | |||||
| identifier (const String& name) throw(); | |||||
| ~identifier() throw(); | |||||
| bool operator== (const identifier& other) const throw() { return hashCode == other.hashCode; } | |||||
| String name; | |||||
| int hashCode; | |||||
| }; | |||||
| /** If this variant is an object, this returns one of its properties. */ | |||||
| const var operator[] (const identifier& propertyName) const throw(); | |||||
| /** If this variant is an object, this invokes one of its methods with no arguments. */ | |||||
| const var call (const identifier& method) const; | |||||
| /** If this variant is an object, this invokes one of its methods with one argument. */ | |||||
| const var call (const identifier& method, const var& arg1) const; | |||||
| /** If this variant is an object, this invokes one of its methods with 2 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2) const; | |||||
| /** If this variant is an object, this invokes one of its methods with 3 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); | |||||
| /** If this variant is an object, this invokes one of its methods with 4 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; | |||||
| /** If this variant is an object, this invokes one of its methods with a list of arguments. */ | |||||
| const var invoke (const identifier& method, const var* arguments, int numArguments) const; | |||||
| /** If this variant is a method pointer, this invokes it on a target object. */ | |||||
| const var invoke (const var& targetObject, const var* arguments, int numArguments) const; | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -11431,7 +11469,8 @@ private: | |||||
| boolType, | boolType, | ||||
| doubleType, | doubleType, | ||||
| stringType, | stringType, | ||||
| objectType | |||||
| objectType, | |||||
| methodType | |||||
| }; | }; | ||||
| Type type; | Type type; | ||||
| @@ -11443,6 +11482,7 @@ private: | |||||
| double doubleValue; | double doubleValue; | ||||
| String* stringValue; | String* stringValue; | ||||
| DynamicObject* objectValue; | DynamicObject* objectValue; | ||||
| MethodFunction* methodValue; | |||||
| } value; | } value; | ||||
| void releaseValue() throw(); | void releaseValue() throw(); | ||||
| @@ -11466,32 +11506,21 @@ public: | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| virtual ~DynamicObject(); | virtual ~DynamicObject(); | ||||
| virtual bool hasProperty (const String& propertyName) const; | |||||
| virtual const var getProperty (const String& propertyName) const; | |||||
| virtual void setProperty (const String& propertyName, const var& newValue); | |||||
| virtual void removeProperty (const String& propertyName); | |||||
| virtual bool hasProperty (const var::identifier& propertyName) const; | |||||
| virtual const var getProperty (const var::identifier& propertyName) const; | |||||
| virtual void setProperty (const var::identifier& propertyName, const var& newValue); | |||||
| virtual void removeProperty (const var::identifier& propertyName); | |||||
| virtual bool hasMethod (const String& methodName) const; | |||||
| virtual bool hasMethod (const var::identifier& methodName) const; | |||||
| virtual const var invokeMethod (const String& methodName, | |||||
| virtual const var invokeMethod (const var::identifier& methodName, | |||||
| const var* parameters, | const var* parameters, | ||||
| int numParameters); | int numParameters); | ||||
| /** Shortcut method for invoking a method with no arguments. */ | |||||
| const var invoke (const String& methodName); | |||||
| /** Shortcut method for invoking a method with one argument. */ | |||||
| const var invoke (const String& methodName, const var& arg1); | |||||
| /** Shortcut method for invoking a method with 2 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2); | |||||
| /** Shortcut method for invoking a method with 3 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3); | |||||
| /** Shortcut method for invoking a method with 4 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3, const var& arg4); | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| StringArray propertyNames; | |||||
| Array <int> propertyIds; | |||||
| OwnedArray <var> propertyValues; | OwnedArray <var> propertyValues; | ||||
| }; | }; | ||||
| @@ -53529,6 +53558,11 @@ public: | |||||
| int width, int height, | int width, int height, | ||||
| double progress, const String& textToShow); | double progress, const String& textToShow); | ||||
| // Draws a small image that spins to indicate that something's happening.. | |||||
| // This method should use the current time to animate itself, so just keep | |||||
| // repainting it every so often. | |||||
| virtual void drawSpinningWaitAnimation (Graphics& g, int x, int y, int w, int h); | |||||
| /** Draws one of the buttons on a scrollbar. | /** Draws one of the buttons on a scrollbar. | ||||
| @param g the context to draw into | @param g the context to draw into | ||||
| @@ -663,7 +663,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat | |||||
| { | { | ||||
| const double callbackStartTime = Time::getMillisecondCounterHiRes(); | const double callbackStartTime = Time::getMillisecondCounterHiRes(); | ||||
| tempBuffer.setSize (numOutputChannels, numSamples, false, false, true); | |||||
| tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true); | |||||
| callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, | callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels, | ||||
| outputChannelData, numOutputChannels, numSamples); | outputChannelData, numOutputChannels, numSamples); | ||||
| @@ -656,6 +656,31 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, | |||||
| } | } | ||||
| } | } | ||||
| void LookAndFeel::drawSpinningWaitAnimation (Graphics& g, int x, int y, int w, int h) | |||||
| { | |||||
| const float radius = jmin (w, h) * 0.4f; | |||||
| const float thickness = radius * 0.15f; | |||||
| Path p; | |||||
| p.addRoundedRectangle (radius * 0.4f, thickness * -0.5f, | |||||
| radius * 0.6f, thickness, | |||||
| thickness * 0.5f); | |||||
| const float cx = x + w * 0.5f; | |||||
| const float cy = y + h * 0.5f; | |||||
| const uint32 animationIndex = (Time::getMillisecondCounter() / (1000 / 10)) % 12; | |||||
| const Colour col (g.getCurrentColour()); | |||||
| for (int i = 0; i < 12; ++i) | |||||
| { | |||||
| const int n = (i + 12 - animationIndex) % 12; | |||||
| g.setColour (col.withMultipliedAlpha ((n + 1) / 12.0f)); | |||||
| g.fillPath (p, AffineTransform::rotation (i * (float_Pi / 6.0f)) | |||||
| .translated (cx, cy)); | |||||
| } | |||||
| } | |||||
| void LookAndFeel::drawScrollbarButton (Graphics& g, | void LookAndFeel::drawScrollbarButton (Graphics& g, | ||||
| ScrollBar& scrollbar, | ScrollBar& scrollbar, | ||||
| int width, int height, | int width, int height, | ||||
| @@ -210,6 +210,12 @@ public: | |||||
| int width, int height, | int width, int height, | ||||
| double progress, const String& textToShow); | double progress, const String& textToShow); | ||||
| //============================================================================== | |||||
| // Draws a small image that spins to indicate that something's happening.. | |||||
| // This method should use the current time to animate itself, so just keep | |||||
| // repainting it every so often. | |||||
| virtual void drawSpinningWaitAnimation (Graphics& g, int x, int y, int w, int h); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Draws one of the buttons on a scrollbar. | /** Draws one of the buttons on a scrollbar. | ||||
| @@ -158,12 +158,12 @@ public: | |||||
| @see getUnchecked | @see getUnchecked | ||||
| */ | */ | ||||
| inline ObjectClass* operator[] (const int index) const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> operator[] (const int index) const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (((unsigned int) index) < (unsigned int) numUsed) | |||||
| ? this->elements [index] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((((unsigned int) index) < (unsigned int) numUsed) | |||||
| ? this->elements [index] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -173,11 +173,11 @@ public: | |||||
| This is a faster and less safe version of operator[] which doesn't check the index passed in, so | This is a faster and less safe version of operator[] which doesn't check the index passed in, so | ||||
| it can be used when you're sure the index if always going to be legal. | it can be used when you're sure the index if always going to be legal. | ||||
| */ | */ | ||||
| inline ObjectClass* getUnchecked (const int index) const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getUnchecked (const int index) const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| jassert (((unsigned int) index) < (unsigned int) numUsed); | jassert (((unsigned int) index) < (unsigned int) numUsed); | ||||
| ObjectClass* const result = this->elements [index]; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result (this->elements [index]); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -187,11 +187,11 @@ public: | |||||
| This will return a null pointer if the array's empty. | This will return a null pointer if the array's empty. | ||||
| @see getLast | @see getLast | ||||
| */ | */ | ||||
| inline ObjectClass* getFirst() const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getFirst() const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (numUsed > 0) ? this->elements [0] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? this->elements [0] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| @@ -202,11 +202,11 @@ public: | |||||
| This will return a null pointer if the array's empty. | This will return a null pointer if the array's empty. | ||||
| @see getFirst | @see getFirst | ||||
| */ | */ | ||||
| inline ObjectClass* getLast() const throw() | |||||
| inline const ReferenceCountedObjectPtr<ObjectClass> getLast() const throw() | |||||
| { | { | ||||
| lock.enter(); | lock.enter(); | ||||
| ObjectClass* const result = (numUsed > 0) ? this->elements [numUsed - 1] | |||||
| : (ObjectClass*) 0; | |||||
| const ReferenceCountedObjectPtr<ObjectClass> result ((numUsed > 0) ? this->elements [numUsed - 1] | |||||
| : (ObjectClass*) 0); | |||||
| lock.exit(); | lock.exit(); | ||||
| return result; | return result; | ||||
| @@ -1,361 +1,416 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| 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. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_Variant.h" | |||||
| //============================================================================== | |||||
| var::var() throw() | |||||
| : type (voidType) | |||||
| { | |||||
| value.doubleValue = 0; | |||||
| } | |||||
| void var::releaseValue() throw() | |||||
| { | |||||
| if (type == stringType) | |||||
| delete value.stringValue; | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->decReferenceCount(); | |||||
| } | |||||
| var::~var() | |||||
| { | |||||
| releaseValue(); | |||||
| } | |||||
| //============================================================================== | |||||
| var::var (const var& valueToCopy) throw() | |||||
| : type (valueToCopy.type), | |||||
| value (valueToCopy.value) | |||||
| { | |||||
| if (type == stringType) | |||||
| value.stringValue = new String (*(value.stringValue)); | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->incReferenceCount(); | |||||
| } | |||||
| var::var (const int value_) throw() | |||||
| : type (intType) | |||||
| { | |||||
| value.intValue = value_; | |||||
| } | |||||
| var::var (const bool value_) throw() | |||||
| : type (boolType) | |||||
| { | |||||
| value.boolValue = value_; | |||||
| } | |||||
| var::var (const double value_) throw() | |||||
| : type (doubleType) | |||||
| { | |||||
| value.doubleValue = value_; | |||||
| } | |||||
| var::var (const String& value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (const char* const value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (const juce_wchar* const value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (DynamicObject* const object) throw() | |||||
| : type (objectType) | |||||
| { | |||||
| value.objectValue = object; | |||||
| if (object != 0) | |||||
| object->incReferenceCount(); | |||||
| } | |||||
| //============================================================================== | |||||
| const var& var::operator= (const var& valueToCopy) throw() | |||||
| { | |||||
| if (this != &valueToCopy) | |||||
| { | |||||
| if (type == stringType) | |||||
| delete value.stringValue; | |||||
| DynamicObject* const oldObject = getObject(); | |||||
| type = valueToCopy.type; | |||||
| value = valueToCopy.value; | |||||
| if (type == stringType) | |||||
| value.stringValue = new String (*(value.stringValue)); | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->incReferenceCount(); | |||||
| if (oldObject != 0) | |||||
| oldObject->decReferenceCount(); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const int value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = intType; | |||||
| value.intValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const bool value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = boolType; | |||||
| value.boolValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const double value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = doubleType; | |||||
| value.doubleValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const char* const value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const juce_wchar* const value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const String& value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (DynamicObject* const value_) throw() | |||||
| { | |||||
| value_->incReferenceCount(); | |||||
| releaseValue(); | |||||
| type = objectType; | |||||
| value.objectValue = value_; | |||||
| return *this; | |||||
| } | |||||
| //============================================================================== | |||||
| var::operator int() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: break; | |||||
| case intType: return value.intValue; | |||||
| case boolType: return value.boolValue ? 1 : 0; | |||||
| case doubleType: return (int) value.doubleValue; | |||||
| case stringType: return value.stringValue->getIntValue(); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| var::operator bool() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: break; | |||||
| case objectType: return value.objectValue != 0; | |||||
| case intType: return value.intValue != 0; | |||||
| case boolType: return value.boolValue; | |||||
| case doubleType: return value.doubleValue != 0; | |||||
| case stringType: return value.stringValue->getIntValue() != 0 | |||||
| || value.stringValue->trim().equalsIgnoreCase (T("true")) | |||||
| || value.stringValue->trim().equalsIgnoreCase (T("yes")); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| var::operator double() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: break; | |||||
| case intType: return value.intValue; | |||||
| case boolType: return value.boolValue ? 1.0 : 0.0; | |||||
| case doubleType: return value.doubleValue; | |||||
| case stringType: return value.stringValue->getDoubleValue(); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| const String var::toString() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: return "Object 0x" + String::toHexString ((pointer_sized_int) value.objectValue); | |||||
| case intType: return String (value.intValue); | |||||
| case boolType: return value.boolValue ? T("1") : T("0"); | |||||
| case doubleType: return String (value.doubleValue); | |||||
| case stringType: return *(value.stringValue); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return String::empty; | |||||
| } | |||||
| DynamicObject* var::getObject() const throw() | |||||
| { | |||||
| return type == objectType ? value.objectValue : 0; | |||||
| } | |||||
| //============================================================================== | |||||
| //============================================================================== | |||||
| DynamicObject::DynamicObject() | |||||
| { | |||||
| } | |||||
| DynamicObject::~DynamicObject() | |||||
| { | |||||
| } | |||||
| bool DynamicObject::hasProperty (const String& propertyName) const | |||||
| { | |||||
| return propertyNames.contains (propertyName, false); | |||||
| } | |||||
| const var DynamicObject::getProperty (const String& propertyName) const | |||||
| { | |||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| if (index >= 0) | |||||
| return *propertyValues.getUnchecked (index); | |||||
| return var(); | |||||
| } | |||||
| void DynamicObject::setProperty (const String& propertyName, const var& newValue) | |||||
| { | |||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| if (index >= 0) | |||||
| { | |||||
| propertyValues.set (index, new var (newValue)); | |||||
| } | |||||
| else | |||||
| { | |||||
| propertyNames.add (propertyName); | |||||
| propertyValues.add (new var (newValue)); | |||||
| } | |||||
| } | |||||
| void DynamicObject::removeProperty (const String& propertyName) | |||||
| { | |||||
| const int index = propertyNames.indexOf (propertyName, false); | |||||
| if (index >= 0) | |||||
| { | |||||
| propertyNames.remove (index); | |||||
| propertyValues.remove (index); | |||||
| } | |||||
| } | |||||
| bool DynamicObject::hasMethod (const String& methodName) const | |||||
| { | |||||
| return false; | |||||
| } | |||||
| const var DynamicObject::invokeMethod (const String& methodName, | |||||
| const var* parameters, | |||||
| int numParameters) | |||||
| { | |||||
| return var(); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName) | |||||
| { | |||||
| return invokeMethod (methodName, 0, 0); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1) | |||||
| { | |||||
| return invokeMethod (methodName, &arg1, 1); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2) | |||||
| { | |||||
| var params[] = { arg1, arg2 }; | |||||
| return invokeMethod (methodName, params, 2); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3) | |||||
| { | |||||
| var params[] = { arg1, arg2, arg3 }; | |||||
| return invokeMethod (methodName, params, 3); | |||||
| } | |||||
| const var DynamicObject::invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3, const var& arg4) | |||||
| { | |||||
| var params[] = { arg1, arg2, arg3, arg4 }; | |||||
| return invokeMethod (methodName, params, 4); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-7 by Raw Material Software ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the | |||||
| GNU General Public License, as published by the Free Software Foundation; | |||||
| either version 2 of the License, or (at your option) any later version. | |||||
| 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. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with JUCE; if not, visit www.gnu.org/licenses or write to the | |||||
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, | |||||
| Boston, MA 02111-1307 USA | |||||
| ------------------------------------------------------------------------------ | |||||
| If you'd like to release a closed-source product which uses JUCE, commercial | |||||
| licenses are also available: visit www.rawmaterialsoftware.com/juce for | |||||
| more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../basics/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_Variant.h" | |||||
| //============================================================================== | |||||
| var::var() throw() | |||||
| : type (voidType) | |||||
| { | |||||
| value.doubleValue = 0; | |||||
| } | |||||
| void var::releaseValue() throw() | |||||
| { | |||||
| if (type == stringType) | |||||
| delete value.stringValue; | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->decReferenceCount(); | |||||
| } | |||||
| var::~var() | |||||
| { | |||||
| releaseValue(); | |||||
| } | |||||
| //============================================================================== | |||||
| var::var (const var& valueToCopy) throw() | |||||
| : type (valueToCopy.type), | |||||
| value (valueToCopy.value) | |||||
| { | |||||
| if (type == stringType) | |||||
| value.stringValue = new String (*(value.stringValue)); | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->incReferenceCount(); | |||||
| } | |||||
| var::var (const int value_) throw() | |||||
| : type (intType) | |||||
| { | |||||
| value.intValue = value_; | |||||
| } | |||||
| var::var (const bool value_) throw() | |||||
| : type (boolType) | |||||
| { | |||||
| value.boolValue = value_; | |||||
| } | |||||
| var::var (const double value_) throw() | |||||
| : type (doubleType) | |||||
| { | |||||
| value.doubleValue = value_; | |||||
| } | |||||
| var::var (const String& value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (const char* const value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (const juce_wchar* const value_) throw() | |||||
| : type (stringType) | |||||
| { | |||||
| value.stringValue = new String (value_); | |||||
| } | |||||
| var::var (DynamicObject* const object) throw() | |||||
| : type (objectType) | |||||
| { | |||||
| value.objectValue = object; | |||||
| if (object != 0) | |||||
| object->incReferenceCount(); | |||||
| } | |||||
| var::var (MethodFunction method_) throw() | |||||
| : type (methodType) | |||||
| { | |||||
| value.methodValue = method_; | |||||
| } | |||||
| //============================================================================== | |||||
| const var& var::operator= (const var& valueToCopy) throw() | |||||
| { | |||||
| if (this != &valueToCopy) | |||||
| { | |||||
| if (type == stringType) | |||||
| delete value.stringValue; | |||||
| DynamicObject* const oldObject = getObject(); | |||||
| type = valueToCopy.type; | |||||
| value = valueToCopy.value; | |||||
| if (type == stringType) | |||||
| value.stringValue = new String (*(value.stringValue)); | |||||
| else if (type == objectType && value.objectValue != 0) | |||||
| value.objectValue->incReferenceCount(); | |||||
| if (oldObject != 0) | |||||
| oldObject->decReferenceCount(); | |||||
| } | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const int value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = intType; | |||||
| value.intValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const bool value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = boolType; | |||||
| value.boolValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const double value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = doubleType; | |||||
| value.doubleValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const char* const value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const juce_wchar* const value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (const String& value_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = stringType; | |||||
| value.stringValue = new String (value_); | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (DynamicObject* const value_) throw() | |||||
| { | |||||
| value_->incReferenceCount(); | |||||
| releaseValue(); | |||||
| type = objectType; | |||||
| value.objectValue = value_; | |||||
| return *this; | |||||
| } | |||||
| const var& var::operator= (MethodFunction method_) throw() | |||||
| { | |||||
| releaseValue(); | |||||
| type = doubleType; | |||||
| value.methodValue = method_; | |||||
| return *this; | |||||
| } | |||||
| //============================================================================== | |||||
| var::operator int() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: break; | |||||
| case intType: return value.intValue; | |||||
| case boolType: return value.boolValue ? 1 : 0; | |||||
| case doubleType: return (int) value.doubleValue; | |||||
| case stringType: return value.stringValue->getIntValue(); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| var::operator bool() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: break; | |||||
| case objectType: return value.objectValue != 0; | |||||
| case intType: return value.intValue != 0; | |||||
| case boolType: return value.boolValue; | |||||
| case doubleType: return value.doubleValue != 0; | |||||
| case stringType: return value.stringValue->getIntValue() != 0 | |||||
| || value.stringValue->trim().equalsIgnoreCase (T("true")) | |||||
| || value.stringValue->trim().equalsIgnoreCase (T("yes")); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| var::operator double() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: break; | |||||
| case intType: return value.intValue; | |||||
| case boolType: return value.boolValue ? 1.0 : 0.0; | |||||
| case doubleType: return value.doubleValue; | |||||
| case stringType: return value.stringValue->getDoubleValue(); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| const String var::toString() const throw() | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case voidType: | |||||
| case objectType: return "Object 0x" + String::toHexString ((pointer_sized_int) value.objectValue); | |||||
| case intType: return String (value.intValue); | |||||
| case boolType: return value.boolValue ? T("1") : T("0"); | |||||
| case doubleType: return String (value.doubleValue); | |||||
| case stringType: return *(value.stringValue); | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return String::empty; | |||||
| } | |||||
| DynamicObject* var::getObject() const throw() | |||||
| { | |||||
| return type == objectType ? value.objectValue : 0; | |||||
| } | |||||
| const var var::operator[] (const var::identifier& propertyName) const throw() | |||||
| { | |||||
| if (type == objectType && value.objectValue != 0) | |||||
| return value.objectValue->getProperty (propertyName); | |||||
| return var(); | |||||
| } | |||||
| const var var::invoke (const var::identifier& method, const var* arguments, int numArguments) const | |||||
| { | |||||
| if (type == objectType && value.objectValue != 0) | |||||
| return value.objectValue->invokeMethod (method, arguments, numArguments); | |||||
| return var(); | |||||
| } | |||||
| const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const | |||||
| { | |||||
| if (isMethod()) | |||||
| return value.methodValue (targetObject, arguments, numArguments); | |||||
| return var(); | |||||
| } | |||||
| const var var::call (const var::identifier& method) const | |||||
| { | |||||
| return invoke (method, 0, 0); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1) const | |||||
| { | |||||
| return invoke (method, &arg1, 1); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2) const | |||||
| { | |||||
| var args[] = { arg1, arg2 }; | |||||
| return invoke (method, args, 2); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3) | |||||
| { | |||||
| var args[] = { arg1, arg2, arg3 }; | |||||
| return invoke (method, args, 3); | |||||
| } | |||||
| const var var::call (const var::identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const | |||||
| { | |||||
| var args[] = { arg1, arg2, arg3, arg4 }; | |||||
| return invoke (method, args, 4); | |||||
| } | |||||
| //============================================================================== | |||||
| var::identifier::identifier (const String& name_) throw() | |||||
| : name (name_), | |||||
| hashCode (name_.hashCode()) | |||||
| { | |||||
| } | |||||
| var::identifier::identifier (const char* const name_) throw() | |||||
| : name (name_), | |||||
| hashCode (name.hashCode()) | |||||
| { | |||||
| } | |||||
| var::identifier::~identifier() throw() | |||||
| { | |||||
| } | |||||
| //============================================================================== | |||||
| //============================================================================== | |||||
| DynamicObject::DynamicObject() | |||||
| { | |||||
| } | |||||
| DynamicObject::~DynamicObject() | |||||
| { | |||||
| } | |||||
| bool DynamicObject::hasProperty (const var::identifier& propertyName) const | |||||
| { | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| return index >= 0 && ! propertyValues.getUnchecked (index)->isMethod(); | |||||
| } | |||||
| const var DynamicObject::getProperty (const var::identifier& propertyName) const | |||||
| { | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | |||||
| return *propertyValues.getUnchecked (index); | |||||
| return var(); | |||||
| } | |||||
| void DynamicObject::setProperty (const var::identifier& propertyName, const var& newValue) | |||||
| { | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | |||||
| { | |||||
| propertyValues.set (index, new var (newValue)); | |||||
| } | |||||
| else | |||||
| { | |||||
| propertyIds.add (propertyName.hashCode); | |||||
| propertyValues.add (new var (newValue)); | |||||
| } | |||||
| } | |||||
| void DynamicObject::removeProperty (const var::identifier& propertyName) | |||||
| { | |||||
| const int index = propertyIds.indexOf (propertyName.hashCode); | |||||
| if (index >= 0) | |||||
| { | |||||
| propertyIds.remove (index); | |||||
| propertyValues.remove (index); | |||||
| } | |||||
| } | |||||
| bool DynamicObject::hasMethod (const var::identifier& methodName) const | |||||
| { | |||||
| return getProperty (methodName).isMethod(); | |||||
| } | |||||
| const var DynamicObject::invokeMethod (const var::identifier& methodName, | |||||
| const var* parameters, | |||||
| int numParameters) | |||||
| { | |||||
| return getProperty (methodName).invoke (this, parameters, numParameters); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -52,6 +52,9 @@ class JUCE_API DynamicObject; | |||||
| class JUCE_API var | class JUCE_API var | ||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | |||||
| typedef const var (MethodFunction) (const var& thisObject, const var* arguments, int numArguments); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Creates a void variant. */ | /** Creates a void variant. */ | ||||
| var() throw(); | var() throw(); | ||||
| @@ -67,6 +70,7 @@ public: | |||||
| var (const juce_wchar* const value) throw(); | var (const juce_wchar* const value) throw(); | ||||
| var (const String& value) throw(); | var (const String& value) throw(); | ||||
| var (DynamicObject* const object) throw(); | var (DynamicObject* const object) throw(); | ||||
| var (MethodFunction method) throw(); | |||||
| const var& operator= (const var& valueToCopy) throw(); | const var& operator= (const var& valueToCopy) throw(); | ||||
| const var& operator= (const int value) throw(); | const var& operator= (const int value) throw(); | ||||
| @@ -76,6 +80,7 @@ public: | |||||
| const var& operator= (const juce_wchar* const value) throw(); | const var& operator= (const juce_wchar* const value) throw(); | ||||
| const var& operator= (const String& value) throw(); | const var& operator= (const String& value) throw(); | ||||
| const var& operator= (DynamicObject* const object) throw(); | const var& operator= (DynamicObject* const object) throw(); | ||||
| const var& operator= (MethodFunction method) throw(); | |||||
| operator int() const throw(); | operator int() const throw(); | ||||
| operator bool() const throw(); | operator bool() const throw(); | ||||
| @@ -89,6 +94,43 @@ public: | |||||
| bool isDouble() const throw() { return type == doubleType; } | bool isDouble() const throw() { return type == doubleType; } | ||||
| bool isString() const throw() { return type == stringType; } | bool isString() const throw() { return type == stringType; } | ||||
| bool isObject() const throw() { return type == objectType; } | bool isObject() const throw() { return type == objectType; } | ||||
| bool isMethod() const throw() { return type == methodType; } | |||||
| //============================================================================== | |||||
| class identifier | |||||
| { | |||||
| public: | |||||
| identifier (const char* const name) throw(); | |||||
| identifier (const String& name) throw(); | |||||
| ~identifier() throw(); | |||||
| bool operator== (const identifier& other) const throw() { return hashCode == other.hashCode; } | |||||
| String name; | |||||
| int hashCode; | |||||
| }; | |||||
| /** If this variant is an object, this returns one of its properties. */ | |||||
| const var operator[] (const identifier& propertyName) const throw(); | |||||
| //============================================================================== | |||||
| /** If this variant is an object, this invokes one of its methods with no arguments. */ | |||||
| const var call (const identifier& method) const; | |||||
| /** If this variant is an object, this invokes one of its methods with one argument. */ | |||||
| const var call (const identifier& method, const var& arg1) const; | |||||
| /** If this variant is an object, this invokes one of its methods with 2 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2) const; | |||||
| /** If this variant is an object, this invokes one of its methods with 3 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3); | |||||
| /** If this variant is an object, this invokes one of its methods with 4 arguments. */ | |||||
| const var call (const identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; | |||||
| /** If this variant is an object, this invokes one of its methods with a list of arguments. */ | |||||
| const var invoke (const identifier& method, const var* arguments, int numArguments) const; | |||||
| //============================================================================== | |||||
| /** If this variant is a method pointer, this invokes it on a target object. */ | |||||
| const var invoke (const var& targetObject, const var* arguments, int numArguments) const; | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -101,7 +143,8 @@ private: | |||||
| boolType, | boolType, | ||||
| doubleType, | doubleType, | ||||
| stringType, | stringType, | ||||
| objectType | |||||
| objectType, | |||||
| methodType | |||||
| }; | }; | ||||
| Type type; | Type type; | ||||
| @@ -113,6 +156,7 @@ private: | |||||
| double doubleValue; | double doubleValue; | ||||
| String* stringValue; | String* stringValue; | ||||
| DynamicObject* objectValue; | DynamicObject* objectValue; | ||||
| MethodFunction* methodValue; | |||||
| } value; | } value; | ||||
| void releaseValue() throw(); | void releaseValue() throw(); | ||||
| @@ -138,35 +182,23 @@ public: | |||||
| virtual ~DynamicObject(); | virtual ~DynamicObject(); | ||||
| //============================================================================== | //============================================================================== | ||||
| virtual bool hasProperty (const String& propertyName) const; | |||||
| virtual const var getProperty (const String& propertyName) const; | |||||
| virtual void setProperty (const String& propertyName, const var& newValue); | |||||
| virtual void removeProperty (const String& propertyName); | |||||
| virtual bool hasProperty (const var::identifier& propertyName) const; | |||||
| virtual const var getProperty (const var::identifier& propertyName) const; | |||||
| virtual void setProperty (const var::identifier& propertyName, const var& newValue); | |||||
| virtual void removeProperty (const var::identifier& propertyName); | |||||
| //============================================================================== | //============================================================================== | ||||
| virtual bool hasMethod (const String& methodName) const; | |||||
| virtual bool hasMethod (const var::identifier& methodName) const; | |||||
| virtual const var invokeMethod (const String& methodName, | |||||
| virtual const var invokeMethod (const var::identifier& methodName, | |||||
| const var* parameters, | const var* parameters, | ||||
| int numParameters); | int numParameters); | ||||
| //============================================================================== | |||||
| /** Shortcut method for invoking a method with no arguments. */ | |||||
| const var invoke (const String& methodName); | |||||
| /** Shortcut method for invoking a method with one argument. */ | |||||
| const var invoke (const String& methodName, const var& arg1); | |||||
| /** Shortcut method for invoking a method with 2 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2); | |||||
| /** Shortcut method for invoking a method with 3 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3); | |||||
| /** Shortcut method for invoking a method with 4 arguments. */ | |||||
| const var invoke (const String& methodName, const var& arg1, const var& arg2, const var& arg3, const var& arg4); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| StringArray propertyNames; | |||||
| Array <int> propertyIds; | |||||
| OwnedArray <var> propertyValues; | OwnedArray <var> propertyValues; | ||||
| }; | }; | ||||