diff --git a/examples/Demo/Source/Demos/UnitTestsDemo.cpp b/examples/Demo/Source/Demos/UnitTestsDemo.cpp index fce56fd093..91add7ff52 100644 --- a/examples/Demo/Source/Demos/UnitTestsDemo.cpp +++ b/examples/Demo/Source/Demos/UnitTestsDemo.cpp @@ -183,7 +183,6 @@ struct UnitTestClasses TextButton startTestButton; TextEditor testResultsBox; - Label label; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UnitTestsDemo); }; diff --git a/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h b/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h index efa27b9dcd..ee1cefe728 100644 --- a/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h +++ b/extras/Introjucer/Source/Project/jucer_ConfigTree_Modules.h @@ -88,8 +88,9 @@ private: props.add (new MissingDependenciesComponent (project, moduleID)); for (Project::ExporterIterator exporter (project); exporter.next();) - props.add (new TextPropertyComponent (exporter->getPathForModuleValue (moduleID), - "Path for " + exporter->getName().quoted(), 1024, false), + props.add (new FilePathPropertyComponent (exporter->getPathForModuleValue (moduleID), + "Path for " + exporter->getName().quoted(), + true, "*", project.getProjectFolder()), "A path to the folder that contains the " + moduleID + " module when compiling the " + exporter->getName().quoted() + " target. " "This can be an absolute path, or relative to the jucer project folder, but it " @@ -146,28 +147,37 @@ private: String moduleID; //============================================================================== - class ModuleInfoComponent : public PropertyComponent + class ModuleInfoComponent : public PropertyComponent, + private Value::Listener { public: ModuleInfoComponent (Project& p, const String& modID) : PropertyComponent ("Module", 150), project (p), moduleID (modID) { + for (Project::ExporterIterator exporter (project); exporter.next();) + listeningValues.add (new Value (exporter->getPathForModuleValue (moduleID))) + ->addListener (this); + + refresh(); } - void refresh() {} + private: + void refresh() override + { + info = project.getModules().getModuleInfo (moduleID); + repaint(); + } - void paint (Graphics& g) + void paint (Graphics& g) override { g.setColour (Colours::white.withAlpha (0.4f)); - g.fillRect (0, 0, getWidth(), getHeight() - 1); + g.fillRect (getLocalBounds().withTrimmedBottom (1)); AttributedString s; s.setJustification (Justification::topLeft); Font f (14.0f); - ModuleDescription info (project.getModules().getModuleInfo (moduleID)); - if (info.isValid()) { s.append (info.getName() + "\n\n", f.boldened()); @@ -184,9 +194,15 @@ private: s.draw (g, getLocalBounds().reduced (6, 5).toFloat()); } - private: + void valueChanged (Value&) override + { + refresh(); + } + Project& project; String moduleID; + OwnedArray listeningValues; + ModuleDescription info; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ModuleInfoComponent) }; @@ -208,9 +224,9 @@ private: fixButton.addListener (this); } - void refresh() {} + void refresh() override {} - void paint (Graphics& g) + void paint (Graphics& g) override { g.setColour (Colours::white.withAlpha (0.4f)); g.fillRect (0, 0, getWidth(), getHeight() - 1); @@ -225,7 +241,7 @@ private: s.draw (g, getLocalBounds().reduced (4, 16).toFloat()); } - void buttonClicked (Button*) + void buttonClicked (Button*) override { bool anyFailed = false; @@ -250,7 +266,7 @@ private: "folders manually and add them to the list."); } - void resized() + void resized() override { fixButton.setBounds (getWidth() - 168, getHeight() - 26, 160, 22); } @@ -289,7 +305,7 @@ public: bool isMissing() override { return false; } Icon getIcon() const override { return Icon (getIcons().graph, getContrastingColour (Colours::red, 0.5f)); } - void showDocument() + void showDocument() override { if (ProjectContentComponent* pcc = getProjectContentComponent()) pcc->setEditorComponent (new ModulesPanel (project), nullptr); diff --git a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h index 1b0a8355fc..e9598ba915 100644 --- a/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h +++ b/extras/Introjucer/Source/Utility/jucer_MiscUtilities.h @@ -380,3 +380,119 @@ public: protected: ColourEditorComponent colourEditor; }; + +//============================================================================== +class FilePathPropertyComponent : public PropertyComponent +{ +public: + /** A Property Component for selecting files or folders. + + The user may drag files over the property box, enter the path + manually and/or click the '...' button to open a file selection + dialog box + */ + FilePathPropertyComponent (Value valueToControl, + const String& propertyDescription, + bool isDirectory, + const String& wildcards = "*", + const File& rootToUseForRelativePaths = File::nonexistent) + : PropertyComponent (propertyDescription), + innerComp (valueToControl, isDirectory, wildcards, rootToUseForRelativePaths) + { + addAndMakeVisible (innerComp); + } + + void refresh() override {} // N/A + +private: + struct InnerComponent : public Component, + public FileDragAndDropTarget, + private Button::Listener + { + InnerComponent (Value v, bool isDir, const String& wc, const File& rt) + : value (v), + isDirectory (isDir), + highlightForDragAndDrop (false), + wildcards (wc), + root (rt), + button ("...") + { + addAndMakeVisible (textbox); + textbox.getTextValue().referTo (value); + + addAndMakeVisible (button); + button.addListener (this); + } + + void paintOverChildren (Graphics& g) override + { + if (highlightForDragAndDrop) + { + g.setColour (Colours::green.withAlpha (0.1f)); + g.fillRect (getLocalBounds()); + } + } + + void resized() override + { + Rectangle r (getLocalBounds()); + + button.setBounds (r.removeFromRight (24)); + textbox.setBounds (r); + } + + bool isInterestedInFileDrag (const StringArray&) override { return true; } + void fileDragEnter (const StringArray&, int, int) override { highlightForDragAndDrop = true; repaint(); } + void fileDragExit (const StringArray&) override { highlightForDragAndDrop = false; repaint(); } + + void filesDropped (const StringArray& files, int, int) override + { + const File firstFile (files[0]); + + if (isDirectory) + setTo (firstFile.isDirectory() ? firstFile + : firstFile.getParentDirectory()); + else + setTo (firstFile); + } + + void buttonClicked (Button*) override + { + const File currentFile (root.getChildFile (value.toString())); + + if (isDirectory) + { + FileChooser chooser ("Select directory", currentFile); + + if (chooser.browseForDirectory()) + setTo (chooser.getResult()); + } + else + { + FileChooser chooser ("Select file", currentFile, wildcards); + + if (chooser.browseForFileToOpen()) + setTo (chooser.getResult()); + } + } + + void setTo (const File& f) + { + value = (root == File::nonexistent) ? f.getFullPathName() + : f.getRelativePathFrom (root); + } + + Value value; + bool isDirectory, highlightForDragAndDrop; + String wildcards; + File root; + TextEditor textbox; + TextButton button; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InnerComponent) + }; + + InnerComponent innerComp; // Used so that the PropertyComponent auto first-child positioning works + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilePathPropertyComponent) +}; diff --git a/extras/Introjucer/Source/Wizards/jucer_NewProjectWizardComponent.h b/extras/Introjucer/Source/Wizards/jucer_NewProjectWizardComponent.h old mode 100644 new mode 100755 index cd96575f96..8ba2960bf2 --- a/extras/Introjucer/Source/Wizards/jucer_NewProjectWizardComponent.h +++ b/extras/Introjucer/Source/Wizards/jucer_NewProjectWizardComponent.h @@ -256,7 +256,8 @@ private: class WizardComp : public Component, private ButtonListener, private ComboBoxListener, - private TextEditorListener + private TextEditorListener, + private FileBrowserListener { public: WizardComp() @@ -264,7 +265,9 @@ public: projectName (TRANS("Project name")), nameLabel (String::empty, TRANS("Project Name") + ":"), typeLabel (String::empty, TRANS("Project Type") + ":"), - fileBrowser (FileBrowserComponent::saveMode | FileBrowserComponent::canSelectDirectories, + fileBrowser (FileBrowserComponent::saveMode + | FileBrowserComponent::canSelectDirectories + | FileBrowserComponent::doNotClearFileNameOnRootChange, NewProjectWizardClasses::getLastWizardFolder(), nullptr, nullptr), fileOutline (String::empty, TRANS("Project Folder") + ":"), targetsOutline (String::empty, TRANS("Target Platforms") + ":"), @@ -303,6 +306,8 @@ public: addChildAndSetID (&fileBrowser, "fileBrowser"); fileBrowser.setBounds ("fileOutline.left + 10, fileOutline.top + 20, fileOutline.right - 10, fileOutline.bottom - 32"); fileBrowser.setFilenameBoxLabel ("Folder:"); + fileBrowser.setFileName (File::createLegalFileName (projectName.getText())); + fileBrowser.addListener (this); addChildAndSetID (&createButton, "createButton"); createButton.setBounds ("right - 130, bottom - 34, parent.width - 30, parent.height - 30"); @@ -409,6 +414,16 @@ public: fileBrowser.setFileName (File::createLegalFileName (projectName.getText())); } + void selectionChanged() override {} + + void fileClicked (const File&, const MouseEvent&) override {} + void fileDoubleClicked (const File&) override {} + + void browserRootChanged (const File&) override + { + fileBrowser.setFileName (File::createLegalFileName (projectName.getText())); + } + ComboBox projectType; PlatformTargetsComp platformTargets; diff --git a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 497f54305b..1820e46967 100644 --- a/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -318,6 +318,8 @@ namespace static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) noexcept { + ignoreUnused (e); + if (increment < 0) { ev.xbutton.button = Button5; @@ -1633,7 +1635,7 @@ public: void* data = nullptr; const size_t bytes = (size_t) dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); - if (data != nullptr && bytes <= maxSizeMB * 1024 * 1024) + if (data != nullptr && bytes <= (size_t) maxSizeMB * 1024 * 1024) { mb.setSize (bytes); mb.copyFrom (data, 0, bytes); diff --git a/modules/juce_browser_plugin_client/wrapper/juce_NPAPI_GlueCode.cpp b/modules/juce_browser_plugin_client/wrapper/juce_NPAPI_GlueCode.cpp index e41feda6af..42748b9230 100644 --- a/modules/juce_browser_plugin_client/wrapper/juce_NPAPI_GlueCode.cpp +++ b/modules/juce_browser_plugin_client/wrapper/juce_NPAPI_GlueCode.cpp @@ -584,7 +584,7 @@ public: }; //============================================================================== -static NPIdentifier getIdentifierFromString (const var::identifier& s) noexcept +static NPIdentifier getIdentifierFromString (const Identifier& s) noexcept { return browser.getstringidentifier (s.toString().toUTF8()); } @@ -601,6 +601,7 @@ class DynamicObjectWrappingNPObject : public DynamicObject { NPP npp; NPObject* const source; + mutable var returnValue; public: DynamicObjectWrappingNPObject (NPP npp_, NPObject* const source_) @@ -616,17 +617,20 @@ public: DBG ("num NP wrapper objs: " + String (--numDOWNP)); } - var getProperty (const var::identifier& propertyName) const override + const var& getProperty (const Identifier& propertyName) const override { NPVariant result; VOID_TO_NPVARIANT (result); browser.getproperty (npp, source, getIdentifierFromString (propertyName), &result); - const var v (createValueFromNPVariant (npp, result)); + + // NB: this is just a workaorund for the return type being a reference - not too bothered + // about threading implications of this since this code will all soon be deprecated anyway. + returnValue = createValueFromNPVariant (npp, result); browser.releasevariantvalue (&result); - return v; + return returnValue; } - bool hasProperty (const var::identifier& propertyName) const override + bool hasProperty (const Identifier& propertyName) const override { NPVariant result; VOID_TO_NPVARIANT (result); @@ -635,7 +639,7 @@ public: return hasProp; } - void setProperty (const var::identifier& propertyName, const var& newValue) override + void setProperty (const Identifier& propertyName, const var& newValue) override { NPVariant value; createNPVariantFromValue (npp, value, newValue); @@ -644,12 +648,12 @@ public: browser.releasevariantvalue (&value); } - void removeProperty (const var::identifier& propertyName) override + void removeProperty (const Identifier& propertyName) override { browser.removeproperty (npp, source, getIdentifierFromString (propertyName)); } - bool hasMethod (const var::identifier& methodName) const override + bool hasMethod (const Identifier& methodName) const override { return browser.hasmethod (npp, source, getIdentifierFromString (methodName)); } @@ -721,7 +725,7 @@ private: bool invoke (NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* out) { DynamicObject* const o = object.getDynamicObject(); - const var::identifier methodName (identifierToString (name)); + const Identifier methodName (identifierToString (name)); if (o == nullptr || ! o->hasMethod (methodName)) return false; @@ -761,7 +765,7 @@ private: bool getProperty (NPIdentifier name, NPVariant* out) { DynamicObject* const o = object.getDynamicObject(); - const var::identifier propName (identifierToString (name)); + const Identifier propName (identifierToString (name)); if (o == nullptr || ! o->hasProperty (propName)) return false; @@ -788,7 +792,7 @@ private: bool removeProperty (NPIdentifier name) { DynamicObject* const o = object.getDynamicObject(); - const var::identifier propName (identifierToString (name)); + const Identifier propName (identifierToString (name)); if (o == nullptr || ! o->hasProperty (propName)) return false; @@ -806,10 +810,10 @@ private: NPP npp; var object; - static var::identifier identifierToString (NPIdentifier id) + static Identifier identifierToString (NPIdentifier id) { NPUTF8* const name = browser.utf8fromidentifier (id); - const var::identifier result ((const char*) name); + const Identifier result ((const char*) name); browser.memfree (name); return result; } diff --git a/modules/juce_core/containers/juce_NamedValueSet.cpp b/modules/juce_core/containers/juce_NamedValueSet.cpp index 504ab784f4..8955b126d4 100644 --- a/modules/juce_core/containers/juce_NamedValueSet.cpp +++ b/modules/juce_core/containers/juce_NamedValueSet.cpp @@ -29,7 +29,7 @@ struct NamedValueSet::NamedValue { NamedValue() noexcept {} - NamedValue (Identifier n, const var& v) : name (n), value (v) {} + NamedValue (const Identifier& n, const var& v) : name (n), value (v) {} NamedValue (const NamedValue& other) : name (other.name), value (other.value) {} #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS @@ -39,7 +39,9 @@ struct NamedValueSet::NamedValue { } - NamedValue (Identifier n, var&& v) : name (n), value (static_cast (v)) + NamedValue (Identifier&& n, var&& v) + : name (static_cast (n)), + value (static_cast (v)) { } @@ -138,7 +140,7 @@ var* NamedValueSet::getVarPointer (const Identifier& name) const noexcept } #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS -bool NamedValueSet::set (Identifier name, var&& newValue) +bool NamedValueSet::set (const Identifier& name, var&& newValue) { if (var* const v = getVarPointer (name)) { @@ -154,7 +156,7 @@ bool NamedValueSet::set (Identifier name, var&& newValue) } #endif -bool NamedValueSet::set (Identifier name, const var& newValue) +bool NamedValueSet::set (const Identifier& name, const var& newValue) { if (var* const v = getVarPointer (name)) { diff --git a/modules/juce_core/containers/juce_NamedValueSet.h b/modules/juce_core/containers/juce_NamedValueSet.h index e4a98edc67..09ad68ee7c 100644 --- a/modules/juce_core/containers/juce_NamedValueSet.h +++ b/modules/juce_core/containers/juce_NamedValueSet.h @@ -78,14 +78,14 @@ public: @returns true if a value was changed or added; false if the value was already set the value passed-in. */ - bool set (Identifier name, const var& newValue); + bool set (const Identifier& name, const var& newValue); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS /** Changes or adds a named value. @returns true if a value was changed or added; false if the value was already set the value passed-in. */ - bool set (Identifier name, var&& newValue); + bool set (const Identifier& name, var&& newValue); #endif /** Returns true if the set contains an item with the specified name. */ diff --git a/modules/juce_core/containers/juce_Variant.cpp b/modules/juce_core/containers/juce_Variant.cpp index 833d7927a8..0cad685920 100644 --- a/modules/juce_core/containers/juce_Variant.cpp +++ b/modules/juce_core/containers/juce_Variant.cpp @@ -576,7 +576,7 @@ var var::clone() const noexcept } //============================================================================== -const var& var::operator[] (Identifier propertyName) const +const var& var::operator[] (const Identifier& propertyName) const { if (DynamicObject* const o = getDynamicObject()) return o->getProperty (propertyName); @@ -589,7 +589,7 @@ const var& var::operator[] (const char* const propertyName) const return operator[] (Identifier (propertyName)); } -var var::getProperty (const Identifier propertyName, const var& defaultReturnValue) const +var var::getProperty (const Identifier& propertyName, const var& defaultReturnValue) const { if (DynamicObject* const o = getDynamicObject()) return o->getProperties().getWithDefault (propertyName, defaultReturnValue); @@ -602,7 +602,7 @@ var::NativeFunction var::getNativeFunction() const return isMethod() ? value.methodValue : nullptr; } -var var::invoke (Identifier method, const var* arguments, int numArguments) const +var var::invoke (const Identifier& method, const var* arguments, int numArguments) const { if (DynamicObject* const o = getDynamicObject()) return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments)); @@ -610,35 +610,35 @@ var var::invoke (Identifier method, const var* arguments, int numArguments) cons return var(); } -var var::call (const Identifier method) const +var var::call (const Identifier& method) const { return invoke (method, nullptr, 0); } -var var::call (const Identifier method, const var& arg1) const +var var::call (const Identifier& method, const var& arg1) const { return invoke (method, &arg1, 1); } -var var::call (const Identifier method, const var& arg1, const var& arg2) const +var var::call (const Identifier& method, const var& arg1, const var& arg2) const { var args[] = { arg1, arg2 }; return invoke (method, args, 2); } -var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3) +var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3) { var args[] = { arg1, arg2, arg3 }; return invoke (method, args, 3); } -var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const +var var::call (const 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 var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const +var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const { var args[] = { arg1, arg2, arg3, arg4, arg5 }; return invoke (method, args, 5); diff --git a/modules/juce_core/containers/juce_Variant.h b/modules/juce_core/containers/juce_Variant.h index 1e0f03cf56..ed624f4d95 100644 --- a/modules/juce_core/containers/juce_Variant.h +++ b/modules/juce_core/containers/juce_Variant.h @@ -62,7 +62,6 @@ public: }; typedef var (*NativeFunction) (const NativeFunctionArgs&); - typedef Identifier identifier; //============================================================================== /** Creates a void variant. */ @@ -242,27 +241,27 @@ public: //============================================================================== /** If this variant is an object, this returns one of its properties. */ - const var& operator[] (Identifier propertyName) const; + const var& operator[] (const Identifier& propertyName) const; /** If this variant is an object, this returns one of its properties. */ const var& operator[] (const char* propertyName) const; /** If this variant is an object, this returns one of its properties, or a default fallback value if the property is not set. */ - var getProperty (Identifier propertyName, const var& defaultReturnValue) const; + var getProperty (const Identifier& propertyName, const var& defaultReturnValue) const; /** Invokes a named method call with no arguments. */ - var call (Identifier method) const; + var call (const Identifier& method) const; /** Invokes a named method call with one argument. */ - var call (Identifier method, const var& arg1) const; + var call (const Identifier& method, const var& arg1) const; /** Invokes a named method call with 2 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2) const; + var call (const Identifier& method, const var& arg1, const var& arg2) const; /** Invokes a named method call with 3 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3); + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3); /** Invokes a named method call with 4 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; /** Invokes a named method call with 5 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; /** Invokes a named method call with a list of arguments. */ - var invoke (Identifier method, const var* arguments, int numArguments) const; + var invoke (const Identifier& method, const var* arguments, int numArguments) const; /** If this object is a method, this returns the function pointer. */ NativeFunction getNativeFunction() const; diff --git a/modules/juce_core/javascript/juce_Javascript.cpp b/modules/juce_core/javascript/juce_Javascript.cpp index 1d7fcf45dc..9e5fe3d9d0 100644 --- a/modules/juce_core/javascript/juce_Javascript.cpp +++ b/modules/juce_core/javascript/juce_Javascript.cpp @@ -102,7 +102,7 @@ struct JavascriptEngine::RootObject : public DynamicObject static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); } static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); } static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; } - static var* getPropertyPointer (DynamicObject* o, Identifier i) { return o->getProperties().getVarPointer (i); } + static var* getPropertyPointer (DynamicObject* o, const Identifier& i) { return o->getProperties().getVarPointer (i); } //============================================================================== struct CodeLocation @@ -136,7 +136,7 @@ struct JavascriptEngine::RootObject : public DynamicObject ReferenceCountedObjectPtr root; DynamicObject::Ptr scope; - var findFunctionCall (const CodeLocation& location, const var& targetObject, Identifier functionName) const + var findFunctionCall (const CodeLocation& location, const var& targetObject, const Identifier& functionName) const { if (DynamicObject* o = targetObject.getDynamicObject()) { @@ -170,7 +170,7 @@ struct JavascriptEngine::RootObject : public DynamicObject return var(); } - var* findRootClassProperty (Identifier className, Identifier propName) const + var* findRootClassProperty (const Identifier& className, const Identifier& propName) const { if (DynamicObject* cls = root->getProperty (className).getDynamicObject()) return getPropertyPointer (cls, propName); @@ -178,7 +178,7 @@ struct JavascriptEngine::RootObject : public DynamicObject return nullptr; } - var findSymbolInParentScopes (Identifier name) const + var findSymbolInParentScopes (const Identifier& name) const { if (const var* v = getPropertyPointer (scope, name)) return *v; @@ -187,7 +187,7 @@ struct JavascriptEngine::RootObject : public DynamicObject : var::undefined(); } - bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const + bool findAndInvokeMethod (const Identifier& function, const var::NativeFunctionArgs& args, var& result) const { DynamicObject* target = args.thisObject.getDynamicObject(); @@ -352,7 +352,7 @@ struct JavascriptEngine::RootObject : public DynamicObject struct UnqualifiedName : public Expression { - UnqualifiedName (const CodeLocation& l, Identifier n) noexcept : Expression (l), name (n) {} + UnqualifiedName (const CodeLocation& l, const Identifier& n) noexcept : Expression (l), name (n) {} var getResult (const Scope& s) const override { return s.findSymbolInParentScopes (name); } @@ -369,7 +369,7 @@ struct JavascriptEngine::RootObject : public DynamicObject struct DotOperator : public Expression { - DotOperator (const CodeLocation& l, ExpPtr& p, Identifier c) noexcept : Expression (l), parent (p), child (c) {} + DotOperator (const CodeLocation& l, ExpPtr& p, const Identifier& c) noexcept : Expression (l), parent (p), child (c) {} var getResult (const Scope& s) const override { @@ -1670,7 +1670,7 @@ JavascriptEngine::~JavascriptEngine() {} void JavascriptEngine::prepareTimeout() const noexcept { root->timeout = Time::getCurrentTime() + maximumExecutionTime; } -void JavascriptEngine::registerNativeObject (Identifier name, DynamicObject* object) +void JavascriptEngine::registerNativeObject (const Identifier& name, DynamicObject* object) { root->setProperty (name, object); } @@ -1706,7 +1706,7 @@ var JavascriptEngine::evaluate (const String& code, Result* result) return var::undefined(); } -var JavascriptEngine::callFunction (Identifier function, const var::NativeFunctionArgs& args, Result* result) +var JavascriptEngine::callFunction (const Identifier& function, const var::NativeFunctionArgs& args, Result* result) { var returnVal (var::undefined()); diff --git a/modules/juce_core/javascript/juce_Javascript.h b/modules/juce_core/javascript/juce_Javascript.h index eafc3cdb60..62eadbb116 100644 --- a/modules/juce_core/javascript/juce_Javascript.h +++ b/modules/juce_core/javascript/juce_Javascript.h @@ -78,7 +78,7 @@ public: The function arguments are passed in the same format as used by native methods in the var class. */ - var callFunction (Identifier function, + var callFunction (const Identifier& function, const var::NativeFunctionArgs& args, Result* errorMessage = nullptr); @@ -87,7 +87,7 @@ public: engine until the engine is deleted. The name must be a simple JS identifier, without any dots. */ - void registerNativeObject (Identifier objectName, DynamicObject* object); + void registerNativeObject (const Identifier& objectName, DynamicObject* object); /** This value indicates how long a call to one of the evaluate methods is permitted to run before timing-out and failing. diff --git a/modules/juce_core/network/juce_URL.h b/modules/juce_core/network/juce_URL.h index d3a87c1344..c02bf96188 100644 --- a/modules/juce_core/network/juce_URL.h +++ b/modules/juce_core/network/juce_URL.h @@ -248,6 +248,9 @@ public: /** Attempts to open a stream that can read from this URL. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand if true, it will try to do use a http 'POST' to pass the parameters, otherwise it'll encode them into the URL and do a 'GET'. @@ -287,6 +290,9 @@ public: If it succeeds, this will return true and append the data it read onto the end of the memory block. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param destData the memory block to append the new data to @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) @@ -302,6 +308,9 @@ public: operation that fails and one that returns an empty string, you'll need to use a different method, such as readEntireBinaryStream(). + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) @see readEntireBinaryStream, readEntireXmlStream @@ -316,6 +325,9 @@ public: When it returns a valid XmlElement object, the caller is responsibile for deleting this object when no longer needed. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) diff --git a/modules/juce_core/text/juce_Identifier.cpp b/modules/juce_core/text/juce_Identifier.cpp index 4d9d3ea55f..04cfd13d1c 100644 --- a/modules/juce_core/text/juce_Identifier.cpp +++ b/modules/juce_core/text/juce_Identifier.cpp @@ -31,7 +31,17 @@ Identifier::~Identifier() noexcept {} Identifier::Identifier (const Identifier& other) noexcept : name (other.name) {} -Identifier& Identifier::operator= (const Identifier other) noexcept +#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS +Identifier::Identifier (Identifier&& other) noexcept : name (static_cast (other.name)) {} + +Identifier& Identifier::operator= (Identifier&& other) noexcept +{ + name = static_cast (other.name); + return *this; +} +#endif + +Identifier& Identifier::operator= (const Identifier& other) noexcept { name = other.name; return *this; diff --git a/modules/juce_core/text/juce_Identifier.h b/modules/juce_core/text/juce_Identifier.h index f60eec8d45..0abc1ae4ac 100644 --- a/modules/juce_core/text/juce_Identifier.h +++ b/modules/juce_core/text/juce_Identifier.h @@ -68,16 +68,24 @@ public: Identifier (const Identifier& other) noexcept; /** Creates a copy of another identifier. */ - Identifier& operator= (const Identifier other) noexcept; + Identifier& operator= (const Identifier& other) noexcept; + + #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS + /** Creates a copy of another identifier. */ + Identifier (Identifier&& other) noexcept; + + /** Creates a copy of another identifier. */ + Identifier& operator= (Identifier&& other) noexcept; + #endif /** Destructor */ ~Identifier() noexcept; /** Compares two identifiers. This is a very fast operation. */ - inline bool operator== (Identifier other) const noexcept { return name.getCharPointer() == other.name.getCharPointer(); } + inline bool operator== (const Identifier& other) const noexcept { return name.getCharPointer() == other.name.getCharPointer(); } /** Compares two identifiers. This is a very fast operation. */ - inline bool operator!= (Identifier other) const noexcept { return name.getCharPointer() != other.name.getCharPointer(); } + inline bool operator!= (const Identifier& other) const noexcept { return name.getCharPointer() != other.name.getCharPointer(); } /** Compares the identifier with a string. */ inline bool operator== (StringRef other) const noexcept { return name == other; } diff --git a/modules/juce_data_structures/values/juce_ValueTree.cpp b/modules/juce_data_structures/values/juce_ValueTree.cpp index 43cfc564c7..1efcb0b099 100644 --- a/modules/juce_data_structures/values/juce_ValueTree.cpp +++ b/modules/juce_data_structures/values/juce_ValueTree.cpp @@ -27,7 +27,7 @@ class ValueTree::SharedObject : public ReferenceCountedObject public: typedef ReferenceCountedObjectPtr Ptr; - explicit SharedObject (Identifier t) noexcept + explicit SharedObject (const Identifier& t) noexcept : type (t), parent (nullptr) { } @@ -126,7 +126,7 @@ public: } } - void sendPropertyChangeMessage (const Identifier property) + void sendPropertyChangeMessage (const Identifier& property) { ValueTree tree (this); @@ -169,7 +169,7 @@ public: callListeners (&ValueTree::Listener::valueTreeParentChanged, tree); } - void setProperty (const Identifier name, const var& newValue, UndoManager* const undoManager) + void setProperty (const Identifier& name, const var& newValue, UndoManager* const undoManager) { if (undoManager == nullptr) { @@ -190,12 +190,12 @@ public: } } - bool hasProperty (const Identifier name) const noexcept + bool hasProperty (const Identifier& name) const noexcept { return properties.contains (name); } - void removeProperty (const Identifier name, UndoManager* const undoManager) + void removeProperty (const Identifier& name, UndoManager* const undoManager) { if (undoManager == nullptr) { @@ -238,7 +238,7 @@ public: setProperty (source.properties.getName(i), source.properties.getValueAt(i), undoManager); } - ValueTree getChildWithName (const Identifier typeToMatch) const + ValueTree getChildWithName (const Identifier& typeToMatch) const { for (int i = 0; i < children.size(); ++i) { @@ -250,7 +250,7 @@ public: return ValueTree(); } - ValueTree getOrCreateChildWithName (const Identifier typeToMatch, UndoManager* undoManager) + ValueTree getOrCreateChildWithName (const Identifier& typeToMatch, UndoManager* undoManager) { for (int i = 0; i < children.size(); ++i) { @@ -265,7 +265,7 @@ public: } - ValueTree getChildWithProperty (const Identifier propertyName, const var& propertyValue) const + ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const { for (int i = 0; i < children.size(); ++i) { @@ -458,7 +458,7 @@ public: class SetPropertyAction : public UndoableAction { public: - SetPropertyAction (SharedObject* const so, const Identifier propertyName, + SetPropertyAction (SharedObject* const so, const Identifier& propertyName, const var& newVal, const var& oldVal, bool isAdding, bool isDeleting) : target (so), name (propertyName), newValue (newVal), oldValue (oldVal), isAddingNewProperty (isAdding), isDeletingProperty (isDeleting) @@ -629,7 +629,7 @@ ValueTree::ValueTree() noexcept const ValueTree ValueTree::invalid; -ValueTree::ValueTree (Identifier type) : object (new ValueTree::SharedObject (type)) +ValueTree::ValueTree (const Identifier& type) : object (new ValueTree::SharedObject (type)) { jassert (type.toString().isNotEmpty()); // All objects must be given a sensible type name! } @@ -702,7 +702,7 @@ ValueTree ValueTree::createCopy() const return ValueTree (createCopyIfNotNull (object.get())); } -bool ValueTree::hasType (const Identifier typeName) const +bool ValueTree::hasType (const Identifier& typeName) const { return object != nullptr && object->type == typeName; } @@ -727,24 +727,23 @@ ValueTree ValueTree::getSibling (const int delta) const return ValueTree (object->parent->children.getObjectPointer (index)); } -const var& ValueTree::operator[] (const Identifier name) const +const var& ValueTree::operator[] (const Identifier& name) const { return object == nullptr ? var::null : object->properties[name]; } -const var& ValueTree::getProperty (const Identifier name) const +const var& ValueTree::getProperty (const Identifier& name) const { return object == nullptr ? var::null : object->properties[name]; } -var ValueTree::getProperty (const Identifier name, const var& defaultReturnValue) const +var ValueTree::getProperty (const Identifier& name, const var& defaultReturnValue) const { return object == nullptr ? defaultReturnValue : object->properties.getWithDefault (name, defaultReturnValue); } -ValueTree& ValueTree::setProperty (const Identifier name, const var& newValue, - UndoManager* const undoManager) +ValueTree& ValueTree::setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager) { jassert (name.toString().isNotEmpty()); // Must have a valid property name! jassert (object != nullptr); // Trying to add a property to a null ValueTree will fail! @@ -755,12 +754,12 @@ ValueTree& ValueTree::setProperty (const Identifier name, const var& newValue, return *this; } -bool ValueTree::hasProperty (const Identifier name) const +bool ValueTree::hasProperty (const Identifier& name) const { return object != nullptr && object->hasProperty (name); } -void ValueTree::removeProperty (const Identifier name, UndoManager* const undoManager) +void ValueTree::removeProperty (const Identifier& name, UndoManager* const undoManager) { if (object != nullptr) object->removeProperty (name, undoManager); @@ -803,7 +802,7 @@ class ValueTreePropertyValueSource : public Value::ValueSource, private ValueTree::Listener { public: - ValueTreePropertyValueSource (const ValueTree& vt, const Identifier prop, UndoManager* um) + ValueTreePropertyValueSource (const ValueTree& vt, const Identifier& prop, UndoManager* um) : tree (vt), property (prop), undoManager (um) { tree.addListener (this); @@ -836,7 +835,7 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreePropertyValueSource) }; -Value ValueTree::getPropertyAsValue (const Identifier name, UndoManager* const undoManager) +Value ValueTree::getPropertyAsValue (const Identifier& name, UndoManager* const undoManager) { return Value (new ValueTreePropertyValueSource (*this, name, undoManager)); } @@ -853,17 +852,17 @@ ValueTree ValueTree::getChild (int index) const : static_cast (nullptr)); } -ValueTree ValueTree::getChildWithName (const Identifier type) const +ValueTree ValueTree::getChildWithName (const Identifier& type) const { return object != nullptr ? object->getChildWithName (type) : ValueTree(); } -ValueTree ValueTree::getOrCreateChildWithName (const Identifier type, UndoManager* undoManager) +ValueTree ValueTree::getOrCreateChildWithName (const Identifier& type, UndoManager* undoManager) { return object != nullptr ? object->getOrCreateChildWithName (type, undoManager) : ValueTree(); } -ValueTree ValueTree::getChildWithProperty (const Identifier propertyName, const var& propertyValue) const +ValueTree ValueTree::getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const { return object != nullptr ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree(); } @@ -945,7 +944,7 @@ void ValueTree::removeListener (Listener* listener) object->valueTreesWithListeners.removeValue (this); } -void ValueTree::sendPropertyChangeMessage (const Identifier property) +void ValueTree::sendPropertyChangeMessage (const Identifier& property) { if (object != nullptr) object->sendPropertyChangeMessage (property); diff --git a/modules/juce_data_structures/values/juce_ValueTree.h b/modules/juce_data_structures/values/juce_ValueTree.h index 9a9ccd16d7..78d870f8ce 100644 --- a/modules/juce_data_structures/values/juce_ValueTree.h +++ b/modules/juce_data_structures/values/juce_ValueTree.h @@ -79,7 +79,7 @@ public: Like an XmlElement, each ValueTree node has a type, which you can access with getType() and hasType(). */ - explicit ValueTree (Identifier type); + explicit ValueTree (const Identifier& type); /** Creates a reference to another ValueTree. */ ValueTree (const ValueTree&); @@ -134,7 +134,7 @@ public: /** Returns true if the node has this type. The comparison is case-sensitive. */ - bool hasType (const Identifier typeName) const; + bool hasType (const Identifier& typeName) const; //============================================================================== /** Returns the value of a named property. @@ -142,21 +142,21 @@ public: You can also use operator[] to get a property. @see var, setProperty, hasProperty */ - const var& getProperty (const Identifier name) const; + const var& getProperty (const Identifier& name) const; /** Returns the value of a named property, or a user-specified default if the property doesn't exist. If no such property has been set, this will return the value of defaultReturnValue. You can also use operator[] and getProperty to get a property. @see var, getProperty, setProperty, hasProperty */ - var getProperty (const Identifier name, const var& defaultReturnValue) const; + var getProperty (const Identifier& name, const var& defaultReturnValue) const; /** Returns the value of a named property. If no such property has been set, this will return a void variant. This is the same as calling getProperty(). @see getProperty */ - const var& operator[] (const Identifier name) const; + const var& operator[] (const Identifier& name) const; /** Changes a named property of the node. The name identifier must not be an empty string. @@ -165,16 +165,16 @@ public: @see var, getProperty, removeProperty @returns a reference to the value tree, so that you can daisy-chain calls to this method. */ - ValueTree& setProperty (const Identifier name, const var& newValue, UndoManager* undoManager); + ValueTree& setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager); /** Returns true if the node contains a named property. */ - bool hasProperty (const Identifier name) const; + bool hasProperty (const Identifier& name) const; /** Removes a property from the node. If the undoManager parameter is non-null, its UndoManager::perform() method will be used, so that this change can be undone. */ - void removeProperty (const Identifier name, UndoManager* undoManager); + void removeProperty (const Identifier& name, UndoManager* undoManager); /** Removes all properties from the node. If the undoManager parameter is non-null, its UndoManager::perform() method will be used, @@ -198,7 +198,7 @@ public: it needs to change the value. Attaching a Value::Listener to the value object will provide callbacks whenever the property changes. */ - Value getPropertyAsValue (const Identifier name, UndoManager* undoManager); + Value getPropertyAsValue (const Identifier& name, UndoManager* undoManager); /** Overwrites all the properties in this tree with the properties of the source tree. Any properties that already exist will be updated; and new ones will be added, and @@ -223,7 +223,7 @@ public: whether a node is valid). @see getOrCreateChildWithName */ - ValueTree getChildWithName (const Identifier type) const; + ValueTree getChildWithName (const Identifier& type) const; /** Returns the first child node with the speficied type name, creating and adding a child with this name if there wasn't already one there. @@ -232,7 +232,7 @@ public: the method on is itself invalid. @see getChildWithName */ - ValueTree getOrCreateChildWithName (const Identifier type, UndoManager* undoManager); + ValueTree getOrCreateChildWithName (const Identifier& type, UndoManager* undoManager); /** Looks for the first child node that has the speficied property value. @@ -242,7 +242,7 @@ public: If no such node is found, it'll return an invalid node. (See isValid() to find out whether a node is valid). */ - ValueTree getChildWithProperty (const Identifier propertyName, const var& propertyValue) const; + ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const; /** Adds a child to this node. @@ -453,7 +453,7 @@ public: /** Causes a property-change callback to be triggered for the specified property, calling any listeners that are registered. */ - void sendPropertyChangeMessage (const Identifier property); + void sendPropertyChangeMessage (const Identifier& property); //============================================================================== /** This method uses a comparator object to sort the tree's children into order. diff --git a/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp b/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp old mode 100644 new mode 100755 index 8f41549072..2dc3364fb1 --- a/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp +++ b/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp @@ -387,7 +387,7 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) { setRoot (f); - if ((flags & canSelectDirectories) != 0) + if ((flags & canSelectDirectories) != 0 && (flags & doNotClearFileNameOnRootChange) == 0) filenameBox.setText (String::empty); } else @@ -432,7 +432,9 @@ void FileBrowserComponent::textEditorReturnKeyPressed (TextEditor&) { setRoot (f); chosenFiles.clear(); - filenameBox.setText (String::empty); + + if ((flags & doNotClearFileNameOnRootChange) == 0) + filenameBox.setText (String()); } else { diff --git a/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h b/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h old mode 100644 new mode 100755 index a1151ef02f..62d28742da --- a/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h +++ b/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h @@ -51,18 +51,19 @@ public: */ enum FileChooserFlags { - openMode = 1, /**< specifies that the component should allow the user to - choose an existing file with the intention of opening it. */ - saveMode = 2, /**< specifies that the component should allow the user to specify - the name of a file that will be used to save something. */ - canSelectFiles = 4, /**< specifies that the user can select files (can be used in - conjunction with canSelectDirectories). */ - canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in - conjuction with canSelectFiles). */ - canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ - useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ - filenameBoxIsReadOnly = 64, /**< specifies that the user can't type directly into the filename box. */ - warnAboutOverwriting = 128 /**< specifies that the dialog should warn about overwriting existing files (if possible). */ + openMode = 1, /**< specifies that the component should allow the user to + choose an existing file with the intention of opening it. */ + saveMode = 2, /**< specifies that the component should allow the user to specify + the name of a file that will be used to save something. */ + canSelectFiles = 4, /**< specifies that the user can select files (can be used in + conjunction with canSelectDirectories). */ + canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in + conjuction with canSelectFiles). */ + canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ + useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ + filenameBoxIsReadOnly = 64, /**< specifies that the user can't type directly into the filename box. */ + warnAboutOverwriting = 128, /**< specifies that the dialog should warn about overwriting existing files (if possible). */ + doNotClearFileNameOnRootChange = 256 /**< specifies that the file name should not be cleared upon root change. */ }; //============================================================================== diff --git a/modules/juce_gui_basics/layout/juce_Viewport.cpp b/modules/juce_gui_basics/layout/juce_Viewport.cpp index 21360a0419..edab5284da 100644 --- a/modules/juce_gui_basics/layout/juce_Viewport.cpp +++ b/modules/juce_gui_basics/layout/juce_Viewport.cpp @@ -24,13 +24,13 @@ Viewport::Viewport (const String& name) : Component (name), - customScrollBarThickness(false), scrollBarThickness (0), singleStepX (16), singleStepY (16), showHScrollbar (true), showVScrollbar (true), deleteContent (true), + customScrollBarThickness (false), allowScrollingWithoutScrollbarV (false), allowScrollingWithoutScrollbarH (false), verticalScrollBar (true), @@ -55,7 +55,6 @@ Viewport::Viewport (const String& name) Viewport::~Viewport() { deleteContentComp(); - mouseWheelTimer = nullptr; } //============================================================================== @@ -382,30 +381,6 @@ static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexce : jmax (distance, 1.0f)); } -// This puts a temporary component overlay over the content component, to prevent -// wheel events from reaching components inside it, so that while spinning a wheel -// with momentum, it won't accidentally scroll any subcomponents of the viewport. -struct Viewport::MouseWheelTimer : public Timer -{ - MouseWheelTimer (Viewport& v) : viewport (v) - { - viewport.contentHolder.addAndMakeVisible (dummyOverlay); - dummyOverlay.setAlwaysOnTop (true); - dummyOverlay.setPaintingIsUnclipped (true); - dummyOverlay.setBounds (viewport.contentHolder.getLocalBounds()); - } - - void timerCallback() override - { - viewport.mouseWheelTimer = nullptr; - } - - Component dummyOverlay; - Viewport& viewport; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MouseWheelTimer) -}; - bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel) { if (! (e.mods.isAltDown() || e.mods.isCtrlDown() || e.mods.isCommandDown())) @@ -436,11 +411,6 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD if (pos != getViewPosition()) { - if (mouseWheelTimer == nullptr) - mouseWheelTimer = new MouseWheelTimer (*this); - - mouseWheelTimer->startTimer (300); - setViewPosition (pos); return true; } diff --git a/modules/juce_gui_basics/layout/juce_Viewport.h b/modules/juce_gui_basics/layout/juce_Viewport.h index 78aa4fa01f..0fa4aaf505 100644 --- a/modules/juce_gui_basics/layout/juce_Viewport.h +++ b/modules/juce_gui_basics/layout/juce_Viewport.h @@ -263,15 +263,13 @@ private: //============================================================================== WeakReference contentComp; Rectangle lastVisibleArea; - bool customScrollBarThickness; int scrollBarThickness; int singleStepX, singleStepY; bool showHScrollbar, showVScrollbar, deleteContent; + bool customScrollBarThickness; bool allowScrollingWithoutScrollbarV, allowScrollingWithoutScrollbarH; Component contentHolder; ScrollBar verticalScrollBar, horizontalScrollBar; - struct MouseWheelTimer; - ScopedPointer mouseWheelTimer; Point viewportPosToCompPos (Point) const; diff --git a/modules/juce_gui_basics/mouse/juce_MouseEvent.h b/modules/juce_gui_basics/mouse/juce_MouseEvent.h index 92ac754ed0..210dd009e0 100644 --- a/modules/juce_gui_basics/mouse/juce_MouseEvent.h +++ b/modules/juce_gui_basics/mouse/juce_MouseEvent.h @@ -354,6 +354,10 @@ struct MouseWheelDetails /** If true, then the wheel has continuous, un-stepped motion. */ bool isSmooth; + + /** If true, then this event is part of the intertial momentum phase that follows + the wheel being released. */ + bool isInertial; }; diff --git a/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp b/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp index 7df09b4b8f..45c8eba956 100644 --- a/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp +++ b/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp @@ -331,10 +331,17 @@ public: Time time, const MouseWheelDetails& wheel) { Desktop::getInstance().incrementMouseWheelCounter(); - Point screenPos; - if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos)) - sendMouseWheel (*current, screenPos, time, wheel); + + // This will make sure that when the wheel spins in its inertial phase, any events + // continue to be sent to the last component that the mouse was over when it was being + // actively controlled by the user. This avoids confusion when scrolling through nested + // scrollable components. + if (lastNonInertialWheelTarget == nullptr || ! wheel.isInertial) + lastNonInertialWheelTarget = getTargetForGesture (peer, positionWithinPeer, time, screenPos); + + if (Component* target = lastNonInertialWheelTarget) + sendMouseWheel (*target, screenPos, time, wheel); } void handleMagnifyGesture (ComponentPeer& peer, Point positionWithinPeer, @@ -467,7 +474,7 @@ public: bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; private: - WeakReference componentUnderMouse; + WeakReference componentUnderMouse, lastNonInertialWheelTarget; ComponentPeer* lastPeer; void* currentCursorHandle; @@ -512,6 +519,7 @@ private: mouseDowns[0].peerID = 0; mouseMovedSignificantlySincePressed = false; + lastNonInertialWheelTarget = nullptr; } void registerMouseDrag (Point screenPos) noexcept diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index 7dc6b382f6..d13def9262 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -978,9 +978,9 @@ private: //============================================================================== #if JUCE_USE_XRANDR - friend class ContainerDeletePolicy; - friend class ContainerDeletePolicy; - friend class ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; class XRandrWrapper { @@ -1062,9 +1062,9 @@ private: private: //============================================================================== - friend class ContainerDeletePolicy; - friend class ContainerDeletePolicy; - friend class ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; void freeScreenResources (XRRScreenResources* ptr) { @@ -2209,6 +2209,7 @@ public: wheel.deltaY = amount; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; handleMouseWheel (0, getMousePos (buttonPressEvent), getEventTime (buttonPressEvent), wheel); } diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index cb0cf5efd7..98c1b74925 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -497,10 +497,7 @@ public: void toBehind (ComponentPeer* other) override { - NSViewComponentPeer* const otherPeer = dynamic_cast (other); - jassert (otherPeer != nullptr); // wrong type of window? - - if (otherPeer != nullptr) + if (NSViewComponentPeer* const otherPeer = dynamic_cast (other)) { if (isSharedWindow) { @@ -514,6 +511,10 @@ public: relativeTo: [otherPeer->window windowNumber]]; } } + else + { + jassertfalse; // wrong type of window? + } } void setIcon (const Image&) override @@ -620,6 +621,7 @@ public: wheel.deltaY = 0; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; #if ! JUCE_PPC @try @@ -628,6 +630,8 @@ public: if ([ev respondsToSelector: @selector (isDirectionInvertedFromDevice)]) wheel.isReversed = [ev isDirectionInvertedFromDevice]; + wheel.isInertial = ([ev momentumPhase] != NSEventPhaseNone); + if ([ev respondsToSelector: @selector (hasPreciseScrollingDeltas)]) { if ([ev hasPreciseScrollingDeltas]) diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 0b55b2ece3..2d8f92d90a 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -1820,6 +1820,7 @@ private: wheel.deltaY = isVertical ? amount / 256.0f : 0.0f; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; Point localPos; if (ComponentPeer* const peer = findPeerUnderMouse (localPos)) diff --git a/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp b/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp index a091587625..3c85254bb2 100644 --- a/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp +++ b/modules/juce_gui_extra/misc/juce_LiveConstantEditor.cpp @@ -32,13 +32,10 @@ class AllComponentRepainter : private Timer, private DeletedAtShutdown { public: - AllComponentRepainter() {} + AllComponentRepainter() {} + ~AllComponentRepainter() { clearSingletonInstance(); } - static AllComponentRepainter& getInstance() - { - static AllComponentRepainter* instance = new AllComponentRepainter(); - return *instance; - } + juce_DeclareSingleton (AllComponentRepainter, false) void trigger() { @@ -57,8 +54,10 @@ private: if (Component* c = TopLevelWindow::getTopLevelWindow(i)) repaintAndResizeAllComps (c, alreadyDone); - for (int i = Desktop::getInstance().getNumComponents(); --i >= 0;) - if (Component* c = Desktop::getInstance().getComponent(i)) + Desktop& desktop = Desktop::getInstance(); + + for (int i = desktop.getNumComponents(); --i >= 0;) + if (Component* c = desktop.getComponent(i)) repaintAndResizeAllComps (c, alreadyDone); } @@ -85,6 +84,9 @@ private: } }; +juce_ImplementSingleton (AllComponentRepainter) +juce_ImplementSingleton (ValueList) + //============================================================================== int64 parseInt (String s) { @@ -189,7 +191,7 @@ void LivePropertyEditorBase::applyNewValue (const String& s) selectOriginalValue(); valueEditor.setText (s, dontSendNotification); - AllComponentRepainter::getInstance().trigger(); + AllComponentRepainter::getInstance()->trigger(); } void LivePropertyEditorBase::selectOriginalValue() @@ -347,14 +349,8 @@ public: }; //============================================================================== -ValueList::ValueList() {} -ValueList::~ValueList() {} - -ValueList& ValueList::getInstance() -{ - static ValueList* i = new ValueList(); - return *i; -} +ValueList::ValueList() {} +ValueList::~ValueList() { clearSingletonInstance(); } void ValueList::addValue (LiveValueBase* v) { diff --git a/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h b/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h index 44c312cd19..5801ba2fdf 100644 --- a/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h +++ b/modules/juce_gui_extra/misc/juce_LiveConstantEditor.h @@ -194,7 +194,7 @@ namespace LiveConstantEditor ValueList(); ~ValueList(); - static ValueList& getInstance(); + juce_DeclareSingleton (ValueList, false) template LiveValue& getValue (const char* file, int line, const Type& initialValue) @@ -233,7 +233,7 @@ namespace LiveConstantEditor template inline LiveValue& getValue (const char* file, int line, const Type& initialValue) { - return ValueList::getInstance().getValue (file, line, initialValue); + return ValueList::getInstance()->getValue (file, line, initialValue); } inline LiveValue& getValue (const char* file, int line, const char* initialValue)