mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Big rewrite to the internals of modal components, with a new class ModalComponentManager. This now lets you use modal components asynchronously, providing an object which will receive a callback when they are dismissed, rather than using a blocking event loop. ComboBoxes and some other components now show their popups asynchronously.
This commit is contained in:
parent
80472c3448
commit
b2e0b43960
34 changed files with 1521 additions and 790 deletions
|
|
@ -127,6 +127,7 @@ OBJECTS := \
|
|||
$(OBJDIR)/juce_Component_49f01dfa.o \
|
||||
$(OBJDIR)/juce_ComponentListener_e0eda7ce.o \
|
||||
$(OBJDIR)/juce_Desktop_e3b47b99.o \
|
||||
$(OBJDIR)/juce_ModalComponentManager_b87bddba.o \
|
||||
$(OBJDIR)/juce_ArrowButton_ebac7066.o \
|
||||
$(OBJDIR)/juce_Button_886d3491.o \
|
||||
$(OBJDIR)/juce_DrawableButton_e03899cf.o \
|
||||
|
|
@ -793,6 +794,11 @@ $(OBJDIR)/juce_Desktop_e3b47b99.o: ../../src/gui/components/juce_Desktop.cpp
|
|||
@echo "Compiling juce_Desktop.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/juce_ModalComponentManager_b87bddba.o: ../../src/gui/components/juce_ModalComponentManager.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo "Compiling juce_ModalComponentManager.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/juce_ArrowButton_ebac7066.o: ../../src/gui/components/buttons/juce_ArrowButton.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo "Compiling juce_ArrowButton.cpp"
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
621B7B0B518E63E69122C13E = { isa = PBXBuildFile; fileRef = D0D9267E200BD462361810F7; };
|
||||
97982824572C18827047D92A = { isa = PBXBuildFile; fileRef = E13F33E386E1A0D5FC546521; };
|
||||
927E7250FCE62E838599DF83 = { isa = PBXBuildFile; fileRef = 621B3A4B154182F69DDE2989; };
|
||||
9AE6891C35CE161CB1707B4B = { isa = PBXBuildFile; fileRef = 2FFF9AFE4BD9437CE096E52B; };
|
||||
06994A713C38F415C4E8A009 = { isa = PBXBuildFile; fileRef = 18EE6576A9ED098632CE5155; };
|
||||
98F737B7459895BFCDC7965E = { isa = PBXBuildFile; fileRef = 8B1C747E63EEF036AD9AF3D8; };
|
||||
7033A0968B1C81A821CCC296 = { isa = PBXBuildFile; fileRef = 1C3D15546065C1A9AA5AA0C6; };
|
||||
|
|
@ -550,6 +551,8 @@
|
|||
A0D6308567AAA50D1163D9D3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentListener.h; path = ../../src/gui/components/juce_ComponentListener.h; sourceTree = SOURCE_ROOT; };
|
||||
621B3A4B154182F69DDE2989 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Desktop.cpp; path = ../../src/gui/components/juce_Desktop.cpp; sourceTree = SOURCE_ROOT; };
|
||||
A1F58C1A972425C2B43DD1B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Desktop.h; path = ../../src/gui/components/juce_Desktop.h; sourceTree = SOURCE_ROOT; };
|
||||
2FFF9AFE4BD9437CE096E52B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModalComponentManager.cpp; path = ../../src/gui/components/juce_ModalComponentManager.cpp; sourceTree = SOURCE_ROOT; };
|
||||
41C8C324F13ADA3423FC3B0F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModalComponentManager.h; path = ../../src/gui/components/juce_ModalComponentManager.h; sourceTree = SOURCE_ROOT; };
|
||||
18EE6576A9ED098632CE5155 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ArrowButton.cpp; path = ../../src/gui/components/buttons/juce_ArrowButton.cpp; sourceTree = SOURCE_ROOT; };
|
||||
EB182DC4124FEFFFC87D12C4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ArrowButton.h; path = ../../src/gui/components/buttons/juce_ArrowButton.h; sourceTree = SOURCE_ROOT; };
|
||||
8B1C747E63EEF036AD9AF3D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Button.cpp; path = ../../src/gui/components/buttons/juce_Button.cpp; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1455,6 +1458,8 @@
|
|||
A0D6308567AAA50D1163D9D3,
|
||||
621B3A4B154182F69DDE2989,
|
||||
A1F58C1A972425C2B43DD1B3,
|
||||
2FFF9AFE4BD9437CE096E52B,
|
||||
41C8C324F13ADA3423FC3B0F,
|
||||
2DB55F83F4310F0C4E4E03AA,
|
||||
17B11D96CDB313ED60D8CFE0,
|
||||
BCB2FFE7C2A4084A267F57F2,
|
||||
|
|
@ -1930,6 +1935,7 @@
|
|||
621B7B0B518E63E69122C13E,
|
||||
97982824572C18827047D92A,
|
||||
927E7250FCE62E838599DF83,
|
||||
9AE6891C35CE161CB1707B4B,
|
||||
06994A713C38F415C4E8A009,
|
||||
98F737B7459895BFCDC7965E,
|
||||
7033A0968B1C81A821CCC296,
|
||||
|
|
|
|||
|
|
@ -349,6 +349,8 @@
|
|||
<File RelativePath="..\..\src\gui\components\juce_ComponentListener.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.h"/>
|
||||
<Filter Name="buttons">
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.h"/>
|
||||
|
|
|
|||
|
|
@ -349,6 +349,8 @@
|
|||
<File RelativePath="..\..\src\gui\components\juce_ComponentListener.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.h"/>
|
||||
<Filter Name="buttons">
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.h"/>
|
||||
|
|
|
|||
|
|
@ -351,6 +351,8 @@
|
|||
<File RelativePath="..\..\src\gui\components\juce_ComponentListener.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_Desktop.h"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\juce_ModalComponentManager.h"/>
|
||||
<Filter Name="buttons">
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.cpp"/>
|
||||
<File RelativePath="..\..\src\gui\components\buttons\juce_ArrowButton.h"/>
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@
|
|||
<ClCompile Include="..\..\src\gui\components\juce_Component.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\juce_ComponentListener.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\juce_Desktop.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\juce_ModalComponentManager.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\buttons\juce_ArrowButton.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\buttons\juce_Button.cpp"/>
|
||||
<ClCompile Include="..\..\src\gui\components\buttons\juce_DrawableButton.cpp"/>
|
||||
|
|
@ -549,6 +550,7 @@
|
|||
<ClInclude Include="..\..\src\gui\components\juce_Component.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\juce_ComponentListener.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\juce_Desktop.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\juce_ModalComponentManager.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\buttons\juce_ArrowButton.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\buttons\juce_Button.h"/>
|
||||
<ClInclude Include="..\..\src\gui\components\buttons\juce_DrawableButton.h"/>
|
||||
|
|
|
|||
|
|
@ -430,6 +430,9 @@
|
|||
<ClCompile Include="..\..\src\gui\components\juce_Desktop.cpp">
|
||||
<Filter>Juce\Source\gui\components</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gui\components\juce_ModalComponentManager.cpp">
|
||||
<Filter>Juce\Source\gui\components</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\gui\components\buttons\juce_ArrowButton.cpp">
|
||||
<Filter>Juce\Source\gui\components\buttons</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -1521,6 +1524,9 @@
|
|||
<ClInclude Include="..\..\src\gui\components\juce_Desktop.h">
|
||||
<Filter>Juce\Source\gui\components</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gui\components\juce_ModalComponentManager.h">
|
||||
<Filter>Juce\Source\gui\components</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\gui\components\buttons\juce_ArrowButton.h">
|
||||
<Filter>Juce\Source\gui\components\buttons</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@
|
|||
621B7B0B518E63E69122C13E = { isa = PBXBuildFile; fileRef = D0D9267E200BD462361810F7; };
|
||||
97982824572C18827047D92A = { isa = PBXBuildFile; fileRef = E13F33E386E1A0D5FC546521; };
|
||||
927E7250FCE62E838599DF83 = { isa = PBXBuildFile; fileRef = 621B3A4B154182F69DDE2989; };
|
||||
9AE6891C35CE161CB1707B4B = { isa = PBXBuildFile; fileRef = 2FFF9AFE4BD9437CE096E52B; };
|
||||
06994A713C38F415C4E8A009 = { isa = PBXBuildFile; fileRef = 18EE6576A9ED098632CE5155; };
|
||||
98F737B7459895BFCDC7965E = { isa = PBXBuildFile; fileRef = 8B1C747E63EEF036AD9AF3D8; };
|
||||
7033A0968B1C81A821CCC296 = { isa = PBXBuildFile; fileRef = 1C3D15546065C1A9AA5AA0C6; };
|
||||
|
|
@ -550,6 +551,8 @@
|
|||
A0D6308567AAA50D1163D9D3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentListener.h; path = ../../src/gui/components/juce_ComponentListener.h; sourceTree = SOURCE_ROOT; };
|
||||
621B3A4B154182F69DDE2989 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Desktop.cpp; path = ../../src/gui/components/juce_Desktop.cpp; sourceTree = SOURCE_ROOT; };
|
||||
A1F58C1A972425C2B43DD1B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Desktop.h; path = ../../src/gui/components/juce_Desktop.h; sourceTree = SOURCE_ROOT; };
|
||||
2FFF9AFE4BD9437CE096E52B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ModalComponentManager.cpp; path = ../../src/gui/components/juce_ModalComponentManager.cpp; sourceTree = SOURCE_ROOT; };
|
||||
41C8C324F13ADA3423FC3B0F = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ModalComponentManager.h; path = ../../src/gui/components/juce_ModalComponentManager.h; sourceTree = SOURCE_ROOT; };
|
||||
18EE6576A9ED098632CE5155 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ArrowButton.cpp; path = ../../src/gui/components/buttons/juce_ArrowButton.cpp; sourceTree = SOURCE_ROOT; };
|
||||
EB182DC4124FEFFFC87D12C4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ArrowButton.h; path = ../../src/gui/components/buttons/juce_ArrowButton.h; sourceTree = SOURCE_ROOT; };
|
||||
8B1C747E63EEF036AD9AF3D8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Button.cpp; path = ../../src/gui/components/buttons/juce_Button.cpp; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1455,6 +1458,8 @@
|
|||
A0D6308567AAA50D1163D9D3,
|
||||
621B3A4B154182F69DDE2989,
|
||||
A1F58C1A972425C2B43DD1B3,
|
||||
2FFF9AFE4BD9437CE096E52B,
|
||||
41C8C324F13ADA3423FC3B0F,
|
||||
2DB55F83F4310F0C4E4E03AA,
|
||||
17B11D96CDB313ED60D8CFE0,
|
||||
BCB2FFE7C2A4084A267F57F2,
|
||||
|
|
@ -1930,6 +1935,7 @@
|
|||
621B7B0B518E63E69122C13E,
|
||||
97982824572C18827047D92A,
|
||||
927E7250FCE62E838599DF83,
|
||||
9AE6891C35CE161CB1707B4B,
|
||||
06994A713C38F415C4E8A009,
|
||||
98F737B7459895BFCDC7965E,
|
||||
7033A0968B1C81A821CCC296,
|
||||
|
|
|
|||
|
|
@ -495,6 +495,10 @@
|
|||
file="src/gui/components/juce_Desktop.cpp"/>
|
||||
<FILE id="kteq7JUyy" name="juce_Desktop.h" compile="0" resource="0"
|
||||
file="src/gui/components/juce_Desktop.h"/>
|
||||
<FILE id="OSpcyIq" name="juce_ModalComponentManager.cpp" compile="1"
|
||||
resource="0" file="src/gui/components/juce_ModalComponentManager.cpp"/>
|
||||
<FILE id="hHLSn88" name="juce_ModalComponentManager.h" compile="0"
|
||||
resource="0" file="src/gui/components/juce_ModalComponentManager.h"/>
|
||||
<GROUP id="bZKiEBSYn" name="buttons">
|
||||
<FILE id="XWJvOnuh3" name="juce_ArrowButton.cpp" compile="1" resource="0"
|
||||
file="src/gui/components/buttons/juce_ArrowButton.cpp"/>
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@
|
|||
#include "../src/gui/components/juce_Component.cpp"
|
||||
#include "../src/gui/components/juce_ComponentListener.cpp"
|
||||
#include "../src/gui/components/juce_Desktop.cpp"
|
||||
#include "../src/gui/components/juce_ModalComponentManager.cpp"
|
||||
#include "../src/gui/components/buttons/juce_ArrowButton.cpp"
|
||||
#include "../src/gui/components/buttons/juce_Button.cpp"
|
||||
#include "../src/gui/components/buttons/juce_DrawableButton.cpp"
|
||||
|
|
|
|||
|
|
@ -1184,7 +1184,7 @@ protected:
|
|||
|
||||
const String getProjectType() const
|
||||
{
|
||||
if (project.isGUIApplication())
|
||||
if (project.isGUIApplication() || project.isCommandLineApp())
|
||||
return "Application";
|
||||
else if (project.isAudioPlugin() || project.isBrowserPlugin())
|
||||
return "DynamicLibrary";
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
jucerVersion="3.0.0">
|
||||
<EXPORTFORMATS>
|
||||
<XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
|
||||
juceFolder="../../../juce"/>
|
||||
juceFolder="../.."/>
|
||||
<VS2005 targetFolder="Builds/VisualStudio2005" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../.." libraryType="1"/>
|
||||
<VS2008 targetFolder="Builds/VisualStudio2008" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../juce"/>
|
||||
<LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../.." libraryType="1"/>
|
||||
<LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="../.."/>
|
||||
</EXPORTFORMATS>
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="Plugin Host"
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
bundleIdentifier="com.rawmaterialsoftware.JuceDemoPlugin" jucerVersion="3.0.0">
|
||||
<EXPORTFORMATS>
|
||||
<XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
|
||||
juceFolder="../../../../juce" objCExtraSuffix="JuceDemo"/>
|
||||
juceFolder="../../.." objCExtraSuffix="JuceDemo"/>
|
||||
<VS2005 targetFolder="Builds/VisualStudio2005" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../.." libraryType="1"/>
|
||||
<VS2008 targetFolder="Builds/VisualStudio2008" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../.." libraryType="1"/>
|
||||
</EXPORTFORMATS>
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemoPlugin"
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@
|
|||
pluginAUViewClass="HelloWorldAU_V1" pluginRTASCategory="" bundleIdentifier="com.rawmaterialsoftware.jucehelloworld">
|
||||
<EXPORTFORMATS>
|
||||
<XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
|
||||
juceFolder="../../../juce"/>
|
||||
juceFolder="../.."/>
|
||||
<XCODE_IPHONE targetFolder="Builds/iPhone" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
|
||||
juceFolder="../../../juce"/>
|
||||
juceFolder="../.."/>
|
||||
<VS2005 targetFolder="Builds/VisualStudio2005" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../.." libraryType="1"/>
|
||||
<VS2008 targetFolder="Builds/VisualStudio2008" vstFolder="c:\SDKs\vstsdk2.4"
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../../../juce"/>
|
||||
<LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="../../../juce"/>
|
||||
rtasFolder="c:\SDKs\PT_80_SDK" juceFolder="../.." libraryType="1"/>
|
||||
<LINUX_MAKE targetFolder="Builds/Linux" vstFolder="~/SDKs/vstsdk2.4" juceFolder="../.."/>
|
||||
</EXPORTFORMATS>
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="HelloWorld"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 19
|
||||
#define JUCE_BUILDNUMBER 20
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -14254,7 +14254,7 @@ private:
|
|||
static classname* _singletonInstance; \
|
||||
static JUCE_NAMESPACE::CriticalSection _singletonLock; \
|
||||
\
|
||||
static classname* getInstance() \
|
||||
static classname* JUCE_CALLTYPE getInstance() \
|
||||
{ \
|
||||
if (_singletonInstance == 0) \
|
||||
{\
|
||||
|
|
@ -14282,12 +14282,12 @@ private:
|
|||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static inline classname* getInstanceWithoutCreating() throw() \
|
||||
static inline classname* JUCE_CALLTYPE getInstanceWithoutCreating() throw() \
|
||||
{ \
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static void deleteInstance() \
|
||||
static void JUCE_CALLTYPE deleteInstance() \
|
||||
{ \
|
||||
const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \
|
||||
if (_singletonInstance != 0) \
|
||||
|
|
@ -24927,6 +24927,167 @@ private:
|
|||
#endif // __JUCE_BORDERSIZE_JUCEHEADER__
|
||||
/*** End of inlined file: juce_BorderSize.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_ModalComponentManager.h ***/
|
||||
#ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
#define __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_DeletedAtShutdown.h ***/
|
||||
#ifndef __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
#define __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Classes derived from this will be automatically deleted when the application exits.
|
||||
|
||||
After JUCEApplication::shutdown() has been called, any objects derived from
|
||||
DeletedAtShutdown which are still in existence will be deleted in the reverse
|
||||
order to that in which they were created.
|
||||
|
||||
So if you've got a singleton and don't want to have to explicitly delete it, just
|
||||
inherit from this and it'll be taken care of.
|
||||
*/
|
||||
class JUCE_API DeletedAtShutdown
|
||||
{
|
||||
protected:
|
||||
/** Creates a DeletedAtShutdown object. */
|
||||
DeletedAtShutdown();
|
||||
|
||||
/** Destructor.
|
||||
|
||||
It's ok to delete these objects explicitly - it's only the ones left
|
||||
dangling at the end that will be deleted automatically.
|
||||
*/
|
||||
virtual ~DeletedAtShutdown();
|
||||
|
||||
public:
|
||||
/** Deletes all extant objects.
|
||||
|
||||
This shouldn't be used by applications, as it's called automatically
|
||||
in the shutdown code of the JUCEApplication class.
|
||||
*/
|
||||
static void deleteAll();
|
||||
|
||||
private:
|
||||
DeletedAtShutdown (const DeletedAtShutdown&);
|
||||
DeletedAtShutdown& operator= (const DeletedAtShutdown&);
|
||||
|
||||
static CriticalSection& getLock();
|
||||
static Array <DeletedAtShutdown*>& getObjects();
|
||||
};
|
||||
|
||||
#endif // __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
/*** End of inlined file: juce_DeletedAtShutdown.h ***/
|
||||
|
||||
/**
|
||||
Manages the system's stack of modal components.
|
||||
|
||||
Normally you'll just use the Component methods to invoke modal states in components,
|
||||
and won't have to deal with this class directly, but this is the singleton object that's
|
||||
used internally to manage the stack.
|
||||
|
||||
@see Component::enterModalState, Component::exitModalState, Component::isCurrentlyModal,
|
||||
Component::getCurrentlyModalComponent, Component::isCurrentlyBlockedByAnotherModalComponent
|
||||
*/
|
||||
class JUCE_API ModalComponentManager : public AsyncUpdater,
|
||||
public DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
|
||||
/** Receives callbacks when a modal component is dismissed.
|
||||
|
||||
You can register a callback using Component::enterModalState() or
|
||||
ModalComponentManager::attachCallback().
|
||||
*/
|
||||
class Callback
|
||||
{
|
||||
public:
|
||||
/** */
|
||||
Callback() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~Callback() {}
|
||||
|
||||
/** Called to indicate that a modal component has been dismissed.
|
||||
|
||||
You can register a callback using Component::enterModalState() or
|
||||
ModalComponentManager::attachCallback().
|
||||
|
||||
The returnValue parameter is the value that was passed to Component::exitModalState()
|
||||
when the component was dismissed.
|
||||
|
||||
The callback object will be deleted shortly after this method is called.
|
||||
*/
|
||||
virtual void modalStateFinished (int returnValue) = 0;
|
||||
};
|
||||
|
||||
/** Returns the number of components currently being shown modally.
|
||||
@see getModalComponent
|
||||
*/
|
||||
int getNumModalComponents() const;
|
||||
|
||||
/** Returns one of the components being shown modally.
|
||||
An index of 0 is the most recently-shown, topmost component.
|
||||
*/
|
||||
Component* getModalComponent (int index) const;
|
||||
|
||||
/** Returns true if the specified component is in a modal state. */
|
||||
bool isModal (Component* component) const;
|
||||
|
||||
/** Returns true if the specified component is currently the topmost modal component. */
|
||||
bool isFrontModalComponent (Component* component) const;
|
||||
|
||||
/** Adds a new callback that will be called when the specified modal component is dismissed.
|
||||
|
||||
If the component is modal, then when it is dismissed, either by being hidden, or by calling
|
||||
Component::exitModalState(), then the Callback::modalStateFinished() method will be
|
||||
called.
|
||||
|
||||
Each component can have any number of callbacks associated with it, and this one is added
|
||||
to that list.
|
||||
|
||||
The object that is passed in will be deleted by the manager when it's no longer needed. If
|
||||
the given component is not currently modal, the callback object is deleted immediately and
|
||||
no action is taken.
|
||||
*/
|
||||
void attachCallback (Component* component, Callback* callback);
|
||||
|
||||
/** Runs the event loop until the currently topmost modal component is dismissed, and
|
||||
returns the exit code for that component.
|
||||
*/
|
||||
int runEventLoopForCurrentComponent();
|
||||
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager);
|
||||
|
||||
protected:
|
||||
/** Creates a ModalComponentManager.
|
||||
You shouldn't ever call the constructor - it's a singleton, so use ModalComponentManager::getInstance()
|
||||
*/
|
||||
ModalComponentManager();
|
||||
|
||||
/** Destructor. */
|
||||
~ModalComponentManager();
|
||||
|
||||
/** @internal */
|
||||
void handleAsyncUpdate();
|
||||
|
||||
private:
|
||||
class ModalItem;
|
||||
class ReturnValueRetriever;
|
||||
|
||||
friend class Component;
|
||||
friend class OwnedArray <ModalItem>;
|
||||
OwnedArray <ModalItem> stack;
|
||||
|
||||
void startModal (Component* component, Callback* callback);
|
||||
void endModal (Component* component, int returnValue);
|
||||
void endModal (Component* component);
|
||||
|
||||
};
|
||||
|
||||
#endif // __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
/*** End of inlined file: juce_ModalComponentManager.h ***/
|
||||
|
||||
class LookAndFeel;
|
||||
class MouseInputSource;
|
||||
class MouseInputSourceInternal;
|
||||
|
|
@ -26576,7 +26737,7 @@ public:
|
|||
passed into exitModalState().
|
||||
|
||||
@see enterModalState, exitModalState, isCurrentlyModal, getCurrentlyModalComponent,
|
||||
isCurrentlyBlockedByAnotherModalComponent, MessageManager::dispatchNextMessage
|
||||
isCurrentlyBlockedByAnotherModalComponent, ModalComponentManager
|
||||
*/
|
||||
int runModalLoop();
|
||||
|
||||
|
|
@ -26590,9 +26751,15 @@ public:
|
|||
get the focus, which is usually what you'll want it to do. If not, it will leave
|
||||
the focus unchanged.
|
||||
|
||||
@see exitModalState, runModalLoop
|
||||
The callback is an optional object which will receive a callback when the modal
|
||||
component loses its modal status, either by being hidden or when exitModalState()
|
||||
is called. If you pass an object in here, the system will take care of deleting it
|
||||
later, after making the callback
|
||||
|
||||
@see exitModalState, runModalLoop, ModalComponentManager::attachCallback
|
||||
*/
|
||||
void enterModalState (bool takeKeyboardFocus = true);
|
||||
void enterModalState (bool takeKeyboardFocus = true,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Ends a component's modal state.
|
||||
|
||||
|
|
@ -27717,53 +27884,6 @@ public:
|
|||
#define __JUCE_DESKTOP_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_DeletedAtShutdown.h ***/
|
||||
#ifndef __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
#define __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
|
||||
/**
|
||||
Classes derived from this will be automatically deleted when the application exits.
|
||||
|
||||
After JUCEApplication::shutdown() has been called, any objects derived from
|
||||
DeletedAtShutdown which are still in existence will be deleted in the reverse
|
||||
order to that in which they were created.
|
||||
|
||||
So if you've got a singleton and don't want to have to explicitly delete it, just
|
||||
inherit from this and it'll be taken care of.
|
||||
*/
|
||||
class JUCE_API DeletedAtShutdown
|
||||
{
|
||||
protected:
|
||||
/** Creates a DeletedAtShutdown object. */
|
||||
DeletedAtShutdown();
|
||||
|
||||
/** Destructor.
|
||||
|
||||
It's ok to delete these objects explicitly - it's only the ones left
|
||||
dangling at the end that will be deleted automatically.
|
||||
*/
|
||||
virtual ~DeletedAtShutdown();
|
||||
|
||||
public:
|
||||
/** Deletes all extant objects.
|
||||
|
||||
This shouldn't be used by applications, as it's called automatically
|
||||
in the shutdown code of the JUCEApplication class.
|
||||
*/
|
||||
static void deleteAll();
|
||||
|
||||
private:
|
||||
DeletedAtShutdown (const DeletedAtShutdown&);
|
||||
DeletedAtShutdown& operator= (const DeletedAtShutdown&);
|
||||
|
||||
static CriticalSection& getLock();
|
||||
static Array <DeletedAtShutdown*>& getObjects();
|
||||
};
|
||||
|
||||
#endif // __JUCE_DELETEDATSHUTDOWN_JUCEHEADER__
|
||||
/*** End of inlined file: juce_DeletedAtShutdown.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_Timer.h ***/
|
||||
#ifndef __JUCE_TIMER_JUCEHEADER__
|
||||
#define __JUCE_TIMER_JUCEHEADER__
|
||||
|
|
@ -34964,12 +35084,19 @@ public:
|
|||
in zero.
|
||||
@param standardItemHeight if this is non-zero, it will be used as the standard
|
||||
height for menu items (apart from custom items)
|
||||
@param callback if this is non-zero, the menu will be launched asynchronously,
|
||||
returning immediately, and the callback will receive a
|
||||
call when the menu is either dismissed or has an item
|
||||
selected. This object will be owned and deleted by the
|
||||
system, so make sure that it works safely and that any
|
||||
pointers that it uses are safely within scope.
|
||||
@see showAt
|
||||
*/
|
||||
int show (int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Displays the menu at a specific location.
|
||||
|
||||
|
|
@ -34987,7 +35114,8 @@ public:
|
|||
int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Displays the menu as if it's attached to a component such as a button.
|
||||
|
||||
|
|
@ -34999,7 +35127,8 @@ public:
|
|||
int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Closes any menus that are currently open.
|
||||
|
||||
|
|
@ -35098,6 +35227,7 @@ private:
|
|||
friend class ItemComponent;
|
||||
friend class Window;
|
||||
friend class PopupMenuCustomComponent;
|
||||
friend class MenuBarComponent;
|
||||
friend class OwnedArray <Item>;
|
||||
friend class ScopedPointer <Window>;
|
||||
|
||||
|
|
@ -35107,16 +35237,16 @@ private:
|
|||
|
||||
void addSeparatorIfPending();
|
||||
|
||||
int showMenu (int x, int y, int w, int h,
|
||||
int showMenu (const Rectangle<int>& target,
|
||||
int itemIdThatMustBeVisible,
|
||||
int minimumWidth,
|
||||
int maximumNumColumns,
|
||||
int standardItemHeight,
|
||||
bool alignToRectangle,
|
||||
Component* componentAttachedTo);
|
||||
Component* componentAttachedTo,
|
||||
ModalComponentManager::Callback* callback);
|
||||
|
||||
friend class MenuBarComponent;
|
||||
Component* createMenuComponent (int x, int y, int w, int h,
|
||||
Component* createMenuComponent (const Rectangle<int>& target,
|
||||
int itemIdThatMustBeVisible,
|
||||
int minimumWidth,
|
||||
int maximumNumColumns,
|
||||
|
|
@ -35660,10 +35790,6 @@ public:
|
|||
/** @internal */
|
||||
bool isTextInputActive() const;
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
|
||||
/** This adds the items to the popup menu.
|
||||
|
||||
By default it adds the cut/copy/paste items, but you can override this if
|
||||
|
|
@ -35701,6 +35827,10 @@ protected:
|
|||
*/
|
||||
virtual void performPopupMenuAction (int menuItemID);
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
|
||||
/** Scrolls the minimum distance needed to get the caret into view. */
|
||||
void scrollToMakeSureCursorIsVisible();
|
||||
|
||||
|
|
@ -36462,6 +36592,9 @@ private:
|
|||
bool isRealItem() const throw();
|
||||
};
|
||||
|
||||
class Callback;
|
||||
friend class Callback;
|
||||
|
||||
OwnedArray <ItemInfo> items;
|
||||
Value currentId;
|
||||
int lastCurrentId;
|
||||
|
|
@ -50012,7 +50145,16 @@ public:
|
|||
|
||||
Leave the width or height as 0 to use the default size
|
||||
*/
|
||||
bool show (int width = 0,int height = 0);
|
||||
bool show (int width = 0, int height = 0);
|
||||
|
||||
/** Displays and runs the dialog box modally.
|
||||
|
||||
This will show the box with the specified size at the specified location,
|
||||
returning true if the user pressed 'ok', or false if they cancelled.
|
||||
|
||||
Leave the width or height as 0 to use the default size.
|
||||
*/
|
||||
bool showAt (int x, int y, int width, int height);
|
||||
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the box.
|
||||
|
||||
|
|
@ -50628,6 +50770,9 @@ private:
|
|||
#endif
|
||||
#ifndef __JUCE_DESKTOP_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_KEYBOARDFOCUSTRAVERSER_JUCEHEADER__
|
||||
|
||||
|
|
@ -51809,6 +51954,10 @@ public:
|
|||
*/
|
||||
void setModel (MenuBarModel* newModel);
|
||||
|
||||
/** Returns the current menu bar model being used.
|
||||
*/
|
||||
MenuBarModel* getModel() const throw();
|
||||
|
||||
/** Pops up one of the menu items.
|
||||
|
||||
This lets you manually open one of the menus - it could be triggered by a
|
||||
|
|
@ -51833,8 +51982,6 @@ public:
|
|||
/** @internal */
|
||||
void mouseMove (const MouseEvent& e);
|
||||
/** @internal */
|
||||
void inputAttemptWhenModal();
|
||||
/** @internal */
|
||||
void handleCommandMessage (int commandId);
|
||||
/** @internal */
|
||||
bool keyPressed (const KeyPress& key);
|
||||
|
|
@ -51847,20 +51994,22 @@ public:
|
|||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
class AsyncCallback;
|
||||
friend class AsyncCallback;
|
||||
MenuBarModel* model;
|
||||
|
||||
StringArray menuNames;
|
||||
Array <int> xPositions;
|
||||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked, indexToShowAgain;
|
||||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked;
|
||||
int lastMouseX, lastMouseY;
|
||||
bool inModalState;
|
||||
ScopedPointer <Component> currentPopup;
|
||||
|
||||
int getItemAt (int x, int y);
|
||||
void setItemUnderMouse (int index);
|
||||
void setOpenItem (int index);
|
||||
void updateItemUnderMouse (int x, int y);
|
||||
void hideCurrentMenu();
|
||||
void timerCallback();
|
||||
void repaintMenuItem (int index);
|
||||
void menuDismissed (int topLevelIndex, int itemId);
|
||||
|
||||
MenuBarComponent (const MenuBarComponent&);
|
||||
MenuBarComponent& operator= (const MenuBarComponent&);
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
static classname* _singletonInstance; \
|
||||
static JUCE_NAMESPACE::CriticalSection _singletonLock; \
|
||||
\
|
||||
static classname* getInstance() \
|
||||
static classname* JUCE_CALLTYPE getInstance() \
|
||||
{ \
|
||||
if (_singletonInstance == 0) \
|
||||
{\
|
||||
|
|
@ -121,12 +121,12 @@
|
|||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static inline classname* getInstanceWithoutCreating() throw() \
|
||||
static inline classname* JUCE_CALLTYPE getInstanceWithoutCreating() throw() \
|
||||
{ \
|
||||
return _singletonInstance; \
|
||||
} \
|
||||
\
|
||||
static void deleteInstance() \
|
||||
static void JUCE_CALLTYPE deleteInstance() \
|
||||
{ \
|
||||
const JUCE_NAMESPACE::ScopedLock sl (_singletonLock); \
|
||||
if (_singletonInstance != 0) \
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 19
|
||||
#define JUCE_BUILDNUMBER 20
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -525,15 +525,40 @@ void ComboBox::labelTextChanged (Label*)
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class ComboBox::Callback : public ModalComponentManager::Callback
|
||||
{
|
||||
public:
|
||||
Callback (ComboBox* const box_)
|
||||
: box (box_)
|
||||
{
|
||||
}
|
||||
|
||||
void modalStateFinished (int returnValue)
|
||||
{
|
||||
if (box != 0)
|
||||
{
|
||||
box->menuActive = false;
|
||||
|
||||
if (returnValue != 0)
|
||||
box->setSelectedId (returnValue);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Component::SafePointer<ComboBox> box;
|
||||
|
||||
Callback (const Callback&);
|
||||
Callback& operator= (const Callback&);
|
||||
};
|
||||
|
||||
|
||||
void ComboBox::showPopup()
|
||||
{
|
||||
if (! menuActive)
|
||||
{
|
||||
const int selectedId = getSelectedId();
|
||||
Component::SafePointer<Component> deletionWatcher (this);
|
||||
|
||||
PopupMenu menu;
|
||||
|
||||
menu.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
|
|
@ -552,19 +577,9 @@ void ComboBox::showPopup()
|
|||
if (items.size() == 0)
|
||||
menu.addItem (1, noChoicesMessage, false);
|
||||
|
||||
const int itemHeight = jlimit (12, 24, getHeight());
|
||||
|
||||
menuActive = true;
|
||||
const int resultId = menu.showAt (this, selectedId,
|
||||
getWidth(), 1, itemHeight);
|
||||
|
||||
if (deletionWatcher == 0)
|
||||
return;
|
||||
|
||||
menuActive = false;
|
||||
|
||||
if (resultId != 0)
|
||||
setSelectedId (resultId);
|
||||
menu.showAt (this, selectedId, getWidth(), 1, jlimit (12, 24, getHeight()),
|
||||
new Callback (this));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -388,6 +388,9 @@ private:
|
|||
bool isRealItem() const throw();
|
||||
};
|
||||
|
||||
class Callback;
|
||||
friend class Callback;
|
||||
|
||||
OwnedArray <ItemInfo> items;
|
||||
Value currentId;
|
||||
int lastCurrentId;
|
||||
|
|
|
|||
|
|
@ -1773,6 +1773,28 @@ void TextEditor::paintOverChildren (Graphics& g)
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
class TextEditorMenuPerformer : public ModalComponentManager::Callback
|
||||
{
|
||||
public:
|
||||
TextEditorMenuPerformer (TextEditor* const editor_)
|
||||
: editor (editor_)
|
||||
{
|
||||
}
|
||||
|
||||
void modalStateFinished (int returnValue)
|
||||
{
|
||||
if (editor != 0 && returnValue != 0)
|
||||
editor->performPopupMenuAction (returnValue);
|
||||
}
|
||||
|
||||
private:
|
||||
Component::SafePointer<TextEditor> editor;
|
||||
|
||||
TextEditorMenuPerformer (const TextEditorMenuPerformer&);
|
||||
TextEditorMenuPerformer& operator= (const TextEditorMenuPerformer&);
|
||||
};
|
||||
|
||||
|
||||
void TextEditor::mouseDown (const MouseEvent& e)
|
||||
{
|
||||
beginDragAutoRepeat (100);
|
||||
|
|
@ -1791,12 +1813,7 @@ void TextEditor::mouseDown (const MouseEvent& e)
|
|||
m.setLookAndFeel (&getLookAndFeel());
|
||||
addPopupMenuItems (m, &e);
|
||||
|
||||
menuActive = true;
|
||||
const int result = m.show();
|
||||
menuActive = false;
|
||||
|
||||
if (result != 0)
|
||||
performPopupMenuAction (result);
|
||||
m.show (0, 0, 0, 0, new TextEditorMenuPerformer (this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2221,7 +2238,7 @@ void TextEditor::enablementChanged()
|
|||
//==============================================================================
|
||||
UndoManager* TextEditor::getUndoManager() throw()
|
||||
{
|
||||
return isReadOnly() ? &undoManager : 0;
|
||||
return isReadOnly() ? 0 : &undoManager;
|
||||
}
|
||||
|
||||
void TextEditor::clearInternal (UndoManager* const um)
|
||||
|
|
|
|||
|
|
@ -538,9 +538,6 @@ public:
|
|||
/** @internal */
|
||||
bool isTextInputActive() const;
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** This adds the items to the popup menu.
|
||||
|
||||
|
|
@ -579,6 +576,10 @@ protected:
|
|||
*/
|
||||
virtual void performPopupMenuAction (int menuItemID);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Scrolls the minimum distance needed to get the caret into view. */
|
||||
void scrollToMakeSureCursorIsVisible();
|
||||
|
|
|
|||
|
|
@ -75,6 +75,11 @@ FileChooserDialogBox::~FileChooserDialogBox()
|
|||
|
||||
//==============================================================================
|
||||
bool FileChooserDialogBox::show (int w, int h)
|
||||
{
|
||||
return showAt (-1, -1, w, h);
|
||||
}
|
||||
|
||||
bool FileChooserDialogBox::showAt (int x, int y, int w, int h)
|
||||
{
|
||||
if (w <= 0)
|
||||
{
|
||||
|
|
@ -88,7 +93,10 @@ bool FileChooserDialogBox::show (int w, int h)
|
|||
if (h <= 0)
|
||||
h = 500;
|
||||
|
||||
centreWithSize (w, h);
|
||||
if (x < 0 || y < 0)
|
||||
centreWithSize (w, h);
|
||||
else
|
||||
setBounds (x, y, w, h);
|
||||
|
||||
const bool ok = (runModalLoop() != 0);
|
||||
setVisible (false);
|
||||
|
|
|
|||
|
|
@ -103,8 +103,16 @@ public:
|
|||
|
||||
Leave the width or height as 0 to use the default size
|
||||
*/
|
||||
bool show (int width = 0,int height = 0);
|
||||
bool show (int width = 0, int height = 0);
|
||||
|
||||
/** Displays and runs the dialog box modally.
|
||||
|
||||
This will show the box with the specified size at the specified location,
|
||||
returning true if the user pressed 'ok', or false if they cancelled.
|
||||
|
||||
Leave the width or height as 0 to use the default size.
|
||||
*/
|
||||
bool showAt (int x, int y, int width, int height);
|
||||
|
||||
//==============================================================================
|
||||
/** A set of colour IDs to use to change the colour of various aspects of the box.
|
||||
|
|
|
|||
|
|
@ -39,15 +39,12 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../../events/juce_MessageManager.h"
|
||||
#include "../../events/juce_Timer.h"
|
||||
#include "../../core/juce_Time.h"
|
||||
#include "../../core/juce_Singleton.h"
|
||||
#include "../../core/juce_PlatformUtilities.h"
|
||||
#include "mouse/juce_MouseInputSource.h"
|
||||
|
||||
//==============================================================================
|
||||
Component* Component::currentlyFocusedComponent = 0;
|
||||
|
||||
static Array <Component*> modalComponentStack, modalComponentReturnValueKeys;
|
||||
static Array <int> modalReturnValues;
|
||||
//==============================================================================
|
||||
#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager());
|
||||
|
||||
enum ComponentMessageNumbers
|
||||
{
|
||||
|
|
@ -55,10 +52,8 @@ enum ComponentMessageNumbers
|
|||
exitModalStateMessage = 0x7fff0002
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#define checkMessageManagerIsLocked jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager());
|
||||
|
||||
static uint32 nextComponentUID = 0;
|
||||
Component* Component::currentlyFocusedComponent = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -106,8 +101,6 @@ Component::~Component()
|
|||
if (flags.hasHeavyweightPeerFlag)
|
||||
removeFromDesktop();
|
||||
|
||||
modalComponentStack.removeValue (this);
|
||||
|
||||
for (int i = childComponentList_.size(); --i >= 0;)
|
||||
childComponentList_.getUnchecked(i)->parentComponent_ = 0;
|
||||
|
||||
|
|
@ -1330,59 +1323,17 @@ int Component::runModalLoop()
|
|||
if (! MessageManager::getInstance()->isThisTheMessageThread())
|
||||
{
|
||||
// use a callback so this can be called from non-gui threads
|
||||
return (int) (pointer_sized_int)
|
||||
MessageManager::getInstance()
|
||||
->callFunctionOnMessageThread (&runModalLoopCallback, this);
|
||||
return (int) (pointer_sized_int) MessageManager::getInstance()
|
||||
->callFunctionOnMessageThread (&runModalLoopCallback, this);
|
||||
}
|
||||
|
||||
SafePointer<Component> prevFocused (getCurrentlyFocusedComponent());
|
||||
|
||||
if (! isCurrentlyModal())
|
||||
enterModalState();
|
||||
enterModalState (true);
|
||||
|
||||
JUCE_TRY
|
||||
{
|
||||
while (flags.currentlyModalFlag && flags.visibleFlag)
|
||||
{
|
||||
if (! MessageManager::getInstance()->runDispatchLoopUntil (20))
|
||||
break;
|
||||
|
||||
// check whether this component was deleted during the last message
|
||||
if (! isValidMessageListener())
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
JUCEApplication::sendUnhandledException (&e, __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
JUCEApplication::sendUnhandledException (0, __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int modalIndex = modalComponentReturnValueKeys.indexOf (this);
|
||||
int returnValue = 0;
|
||||
|
||||
if (modalIndex >= 0)
|
||||
{
|
||||
modalComponentReturnValueKeys.remove (modalIndex);
|
||||
returnValue = modalReturnValues.remove (modalIndex);
|
||||
}
|
||||
|
||||
modalComponentStack.removeValue (this);
|
||||
|
||||
if (prevFocused != 0)
|
||||
prevFocused->grabKeyboardFocus();
|
||||
|
||||
return returnValue;
|
||||
return ModalComponentManager::getInstance()->runEventLoopForCurrentComponent();
|
||||
}
|
||||
|
||||
void Component::enterModalState (const bool takeKeyboardFocus_)
|
||||
void Component::enterModalState (const bool takeKeyboardFocus_, ModalComponentManager::Callback* const callback)
|
||||
{
|
||||
// if component methods are being called from threads other than the message
|
||||
// thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
|
||||
|
|
@ -1394,10 +1345,7 @@ void Component::enterModalState (const bool takeKeyboardFocus_)
|
|||
|
||||
if (! isCurrentlyModal())
|
||||
{
|
||||
modalComponentStack.add (this);
|
||||
modalComponentReturnValueKeys.add (this);
|
||||
modalReturnValues.add (0);
|
||||
|
||||
ModalComponentManager::getInstance()->startModal (this, callback);
|
||||
flags.currentlyModalFlag = true;
|
||||
setVisible (true);
|
||||
|
||||
|
|
@ -1412,20 +1360,7 @@ void Component::exitModalState (const int returnValue)
|
|||
{
|
||||
if (MessageManager::getInstance()->isThisTheMessageThread())
|
||||
{
|
||||
const int modalIndex = modalComponentReturnValueKeys.indexOf (this);
|
||||
|
||||
if (modalIndex >= 0)
|
||||
{
|
||||
modalReturnValues.set (modalIndex, returnValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
modalComponentReturnValueKeys.add (this);
|
||||
modalReturnValues.add (returnValue);
|
||||
}
|
||||
|
||||
modalComponentStack.removeValue (this);
|
||||
|
||||
ModalComponentManager::getInstance()->endModal (this, returnValue);
|
||||
flags.currentlyModalFlag = false;
|
||||
|
||||
bringModalComponentToFront();
|
||||
|
|
@ -1455,14 +1390,12 @@ bool Component::isCurrentlyBlockedByAnotherModalComponent() const
|
|||
|
||||
int JUCE_CALLTYPE Component::getNumCurrentlyModalComponents() throw()
|
||||
{
|
||||
return modalComponentStack.size();
|
||||
return ModalComponentManager::getInstance()->getNumModalComponents();
|
||||
}
|
||||
|
||||
Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw()
|
||||
{
|
||||
Component* const c = static_cast <Component*> (modalComponentStack [modalComponentStack.size() - index - 1]);
|
||||
|
||||
return c->isValidComponent() ? c : 0;
|
||||
return ModalComponentManager::getInstance()->getModalComponent (index);
|
||||
}
|
||||
|
||||
void Component::bringModalComponentToFront()
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include "../../text/juce_StringArray.h"
|
||||
#include "../../containers/juce_Array.h"
|
||||
#include "../../containers/juce_NamedValueSet.h"
|
||||
#include "juce_ModalComponentManager.h"
|
||||
|
||||
class LookAndFeel;
|
||||
class MouseInputSource;
|
||||
class MouseInputSourceInternal;
|
||||
|
|
@ -1728,7 +1730,7 @@ public:
|
|||
passed into exitModalState().
|
||||
|
||||
@see enterModalState, exitModalState, isCurrentlyModal, getCurrentlyModalComponent,
|
||||
isCurrentlyBlockedByAnotherModalComponent, MessageManager::dispatchNextMessage
|
||||
isCurrentlyBlockedByAnotherModalComponent, ModalComponentManager
|
||||
*/
|
||||
int runModalLoop();
|
||||
|
||||
|
|
@ -1742,9 +1744,15 @@ public:
|
|||
get the focus, which is usually what you'll want it to do. If not, it will leave
|
||||
the focus unchanged.
|
||||
|
||||
@see exitModalState, runModalLoop
|
||||
The callback is an optional object which will receive a callback when the modal
|
||||
component loses its modal status, either by being hidden or when exitModalState()
|
||||
is called. If you pass an object in here, the system will take care of deleting it
|
||||
later, after making the callback
|
||||
|
||||
@see exitModalState, runModalLoop, ModalComponentManager::attachCallback
|
||||
*/
|
||||
void enterModalState (bool takeKeyboardFocus = true);
|
||||
void enterModalState (bool takeKeyboardFocus = true,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Ends a component's modal state.
|
||||
|
||||
|
|
|
|||
267
src/gui/components/juce_ModalComponentManager.cpp
Normal file
267
src/gui/components/juce_ModalComponentManager.cpp
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_Component.h"
|
||||
#include "juce_ModalComponentManager.h"
|
||||
#include "../../events/juce_MessageManager.h"
|
||||
#include "../../application/juce_Application.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class ModalComponentManager::ModalItem : public ComponentListener
|
||||
{
|
||||
public:
|
||||
ModalItem (Component* const comp, Callback* const callback)
|
||||
: component (comp), returnValue (0), isActive (true), isDeleted (false)
|
||||
{
|
||||
if (callback != 0)
|
||||
callbacks.add (callback);
|
||||
|
||||
jassert (comp != 0);
|
||||
component->addComponentListener (this);
|
||||
}
|
||||
|
||||
~ModalItem()
|
||||
{
|
||||
if (! isDeleted)
|
||||
component->removeComponentListener (this);
|
||||
}
|
||||
|
||||
void componentBeingDeleted (Component&)
|
||||
{
|
||||
isDeleted = true;
|
||||
cancel();
|
||||
}
|
||||
|
||||
void componentVisibilityChanged (Component&)
|
||||
{
|
||||
if (! component->isShowing())
|
||||
cancel();
|
||||
}
|
||||
|
||||
void componentParentHierarchyChanged (Component&)
|
||||
{
|
||||
if (! component->isShowing())
|
||||
cancel();
|
||||
}
|
||||
|
||||
void cancel()
|
||||
{
|
||||
if (isActive)
|
||||
{
|
||||
isActive = false;
|
||||
ModalComponentManager::getInstance()->triggerAsyncUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
Component* component;
|
||||
OwnedArray<Callback> callbacks;
|
||||
int returnValue;
|
||||
bool isActive, isDeleted;
|
||||
|
||||
private:
|
||||
ModalItem (const ModalItem&);
|
||||
ModalItem& operator= (const ModalItem&);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
ModalComponentManager::ModalComponentManager()
|
||||
{
|
||||
}
|
||||
|
||||
ModalComponentManager::~ModalComponentManager()
|
||||
{
|
||||
clearSingletonInstance();
|
||||
}
|
||||
|
||||
juce_ImplementSingleton_SingleThreaded (ModalComponentManager);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void ModalComponentManager::startModal (Component* component, Callback* callback)
|
||||
{
|
||||
if (component != 0)
|
||||
stack.add (new ModalItem (component, callback));
|
||||
}
|
||||
|
||||
void ModalComponentManager::attachCallback (Component* component, Callback* callback)
|
||||
{
|
||||
if (callback != 0)
|
||||
{
|
||||
ScopedPointer<Callback> callbackDeleter (callback);
|
||||
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
ModalItem* const item = stack.getUnchecked(i);
|
||||
|
||||
if (item->component == component)
|
||||
{
|
||||
item->callbacks.add (callback);
|
||||
callbackDeleter.release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModalComponentManager::endModal (Component* component)
|
||||
{
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
ModalItem* const item = stack.getUnchecked(i);
|
||||
|
||||
if (item->component == component)
|
||||
item->cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void ModalComponentManager::endModal (Component* component, int returnValue)
|
||||
{
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
ModalItem* const item = stack.getUnchecked(i);
|
||||
|
||||
if (item->component == component)
|
||||
{
|
||||
item->returnValue = returnValue;
|
||||
item->cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ModalComponentManager::getNumModalComponents() const
|
||||
{
|
||||
int n = 0;
|
||||
for (int i = 0; i < stack.size(); ++i)
|
||||
if (stack.getUnchecked(i)->isActive)
|
||||
++n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
Component* ModalComponentManager::getModalComponent (const int index) const
|
||||
{
|
||||
int n = 0;
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
const ModalItem* const item = stack.getUnchecked(i);
|
||||
if (item->isActive)
|
||||
if (n++ == index)
|
||||
return item->component;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ModalComponentManager::isModal (Component* const comp) const
|
||||
{
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
const ModalItem* const item = stack.getUnchecked(i);
|
||||
if (item->isActive && item->component == comp)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ModalComponentManager::isFrontModalComponent (Component* const comp) const
|
||||
{
|
||||
return comp == getModalComponent (0);
|
||||
}
|
||||
|
||||
void ModalComponentManager::handleAsyncUpdate()
|
||||
{
|
||||
for (int i = stack.size(); --i >= 0;)
|
||||
{
|
||||
const ModalItem* const item = stack.getUnchecked(i);
|
||||
if (! item->isActive)
|
||||
{
|
||||
for (int j = item->callbacks.size(); --j >= 0;)
|
||||
item->callbacks.getUnchecked(j)->modalStateFinished (item->returnValue);
|
||||
|
||||
stack.remove (i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ModalComponentManager::ReturnValueRetriever : public ModalComponentManager::Callback
|
||||
{
|
||||
public:
|
||||
ReturnValueRetriever (int& value_, bool& finished_) : value (value_), finished (finished_) {}
|
||||
~ReturnValueRetriever() {}
|
||||
|
||||
void modalStateFinished (int returnValue)
|
||||
{
|
||||
finished = true;
|
||||
value = returnValue;
|
||||
}
|
||||
|
||||
private:
|
||||
int& value;
|
||||
bool& finished;
|
||||
|
||||
ReturnValueRetriever (const ReturnValueRetriever&);
|
||||
ReturnValueRetriever& operator= (const ReturnValueRetriever&);
|
||||
};
|
||||
|
||||
int ModalComponentManager::runEventLoopForCurrentComponent()
|
||||
{
|
||||
// This can only be run from the message thread!
|
||||
jassert (MessageManager::getInstance()->isThisTheMessageThread());
|
||||
|
||||
Component* currentlyModal = getModalComponent (0);
|
||||
|
||||
if (currentlyModal == 0)
|
||||
return 0;
|
||||
|
||||
Component::SafePointer<Component> prevFocused (Component::getCurrentlyFocusedComponent());
|
||||
|
||||
int returnValue = 0;
|
||||
bool finished = false;
|
||||
attachCallback (currentlyModal, new ReturnValueRetriever (returnValue, finished));
|
||||
|
||||
JUCE_TRY
|
||||
{
|
||||
while (! finished)
|
||||
{
|
||||
if (! MessageManager::getInstance()->runDispatchLoopUntil (20))
|
||||
break;
|
||||
}
|
||||
}
|
||||
JUCE_CATCH_EXCEPTION
|
||||
|
||||
if (prevFocused != 0)
|
||||
prevFocused->grabKeyboardFocus();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
144
src/gui/components/juce_ModalComponentManager.h
Normal file
144
src/gui/components/juce_ModalComponentManager.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
#define __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
|
||||
#include "../../core/juce_Singleton.h"
|
||||
#include "../../events/juce_AsyncUpdater.h"
|
||||
#include "../../utilities/juce_DeletedAtShutdown.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Manages the system's stack of modal components.
|
||||
|
||||
Normally you'll just use the Component methods to invoke modal states in components,
|
||||
and won't have to deal with this class directly, but this is the singleton object that's
|
||||
used internally to manage the stack.
|
||||
|
||||
@see Component::enterModalState, Component::exitModalState, Component::isCurrentlyModal,
|
||||
Component::getCurrentlyModalComponent, Component::isCurrentlyBlockedByAnotherModalComponent
|
||||
*/
|
||||
class JUCE_API ModalComponentManager : public AsyncUpdater,
|
||||
public DeletedAtShutdown
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Receives callbacks when a modal component is dismissed.
|
||||
|
||||
You can register a callback using Component::enterModalState() or
|
||||
ModalComponentManager::attachCallback().
|
||||
*/
|
||||
class Callback
|
||||
{
|
||||
public:
|
||||
/** */
|
||||
Callback() {}
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~Callback() {}
|
||||
|
||||
/** Called to indicate that a modal component has been dismissed.
|
||||
|
||||
You can register a callback using Component::enterModalState() or
|
||||
ModalComponentManager::attachCallback().
|
||||
|
||||
The returnValue parameter is the value that was passed to Component::exitModalState()
|
||||
when the component was dismissed.
|
||||
|
||||
The callback object will be deleted shortly after this method is called.
|
||||
*/
|
||||
virtual void modalStateFinished (int returnValue) = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of components currently being shown modally.
|
||||
@see getModalComponent
|
||||
*/
|
||||
int getNumModalComponents() const;
|
||||
|
||||
/** Returns one of the components being shown modally.
|
||||
An index of 0 is the most recently-shown, topmost component.
|
||||
*/
|
||||
Component* getModalComponent (int index) const;
|
||||
|
||||
/** Returns true if the specified component is in a modal state. */
|
||||
bool isModal (Component* component) const;
|
||||
|
||||
/** Returns true if the specified component is currently the topmost modal component. */
|
||||
bool isFrontModalComponent (Component* component) const;
|
||||
|
||||
/** Adds a new callback that will be called when the specified modal component is dismissed.
|
||||
|
||||
If the component is modal, then when it is dismissed, either by being hidden, or by calling
|
||||
Component::exitModalState(), then the Callback::modalStateFinished() method will be
|
||||
called.
|
||||
|
||||
Each component can have any number of callbacks associated with it, and this one is added
|
||||
to that list.
|
||||
|
||||
The object that is passed in will be deleted by the manager when it's no longer needed. If
|
||||
the given component is not currently modal, the callback object is deleted immediately and
|
||||
no action is taken.
|
||||
*/
|
||||
void attachCallback (Component* component, Callback* callback);
|
||||
|
||||
/** Runs the event loop until the currently topmost modal component is dismissed, and
|
||||
returns the exit code for that component.
|
||||
*/
|
||||
int runEventLoopForCurrentComponent();
|
||||
|
||||
//==============================================================================
|
||||
juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager);
|
||||
|
||||
protected:
|
||||
/** Creates a ModalComponentManager.
|
||||
You shouldn't ever call the constructor - it's a singleton, so use ModalComponentManager::getInstance()
|
||||
*/
|
||||
ModalComponentManager();
|
||||
|
||||
/** Destructor. */
|
||||
~ModalComponentManager();
|
||||
|
||||
/** @internal */
|
||||
void handleAsyncUpdate();
|
||||
|
||||
private:
|
||||
class ModalItem;
|
||||
class ReturnValueRetriever;
|
||||
|
||||
friend class Component;
|
||||
friend class OwnedArray <ModalItem>;
|
||||
OwnedArray <ModalItem> stack;
|
||||
|
||||
void startModal (Component* component, Callback* callback);
|
||||
void endModal (Component* component, int returnValue);
|
||||
void endModal (Component* component);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
|
|
@ -32,31 +32,14 @@ BEGIN_JUCE_NAMESPACE
|
|||
#include "../lookandfeel/juce_LookAndFeel.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class DummyMenuComponent : public Component
|
||||
{
|
||||
DummyMenuComponent (const DummyMenuComponent&);
|
||||
DummyMenuComponent& operator= (const DummyMenuComponent&);
|
||||
|
||||
public:
|
||||
DummyMenuComponent() {}
|
||||
~DummyMenuComponent() {}
|
||||
|
||||
void inputAttemptWhenModal()
|
||||
{
|
||||
exitModalState (0);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
MenuBarComponent::MenuBarComponent (MenuBarModel* model_)
|
||||
: model (0),
|
||||
itemUnderMouse (-1),
|
||||
currentPopupIndex (-1),
|
||||
indexToShowAgain (-1),
|
||||
topLevelIndexClicked (0),
|
||||
lastMouseX (0),
|
||||
lastMouseY (0),
|
||||
inModalState (false)
|
||||
lastMouseY (0)
|
||||
{
|
||||
setRepaintsOnMouseActivity (true);
|
||||
setWantsKeyboardFocus (false);
|
||||
|
|
@ -68,9 +51,12 @@ MenuBarComponent::MenuBarComponent (MenuBarModel* model_)
|
|||
MenuBarComponent::~MenuBarComponent()
|
||||
{
|
||||
setModel (0);
|
||||
|
||||
Desktop::getInstance().removeGlobalMouseListener (this);
|
||||
currentPopup = 0;
|
||||
}
|
||||
|
||||
MenuBarModel* MenuBarComponent::getModel() const throw()
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
void MenuBarComponent::setModel (MenuBarModel* const newModel)
|
||||
|
|
@ -158,144 +144,102 @@ void MenuBarComponent::repaintMenuItem (int index)
|
|||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::updateItemUnderMouse (int x, int y)
|
||||
void MenuBarComponent::setItemUnderMouse (const int index)
|
||||
{
|
||||
const int newItem = getItemAt (x, y);
|
||||
|
||||
if (itemUnderMouse != newItem)
|
||||
if (itemUnderMouse != index)
|
||||
{
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
itemUnderMouse = newItem;
|
||||
itemUnderMouse = index;
|
||||
repaintMenuItem (itemUnderMouse);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::hideCurrentMenu()
|
||||
void MenuBarComponent::setOpenItem (int index)
|
||||
{
|
||||
currentPopup = 0;
|
||||
repaint();
|
||||
if (currentPopupIndex != index)
|
||||
{
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
currentPopupIndex = index;
|
||||
repaintMenuItem (currentPopupIndex);
|
||||
|
||||
if (index >= 0)
|
||||
Desktop::getInstance().addGlobalMouseListener (this);
|
||||
else
|
||||
Desktop::getInstance().removeGlobalMouseListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::updateItemUnderMouse (int x, int y)
|
||||
{
|
||||
setItemUnderMouse (getItemAt (x, y));
|
||||
}
|
||||
|
||||
class MenuBarComponent::AsyncCallback : public ModalComponentManager::Callback
|
||||
{
|
||||
public:
|
||||
AsyncCallback (MenuBarComponent* const bar_, const int topLevelIndex_)
|
||||
: bar (bar_), topLevelIndex (topLevelIndex_)
|
||||
{
|
||||
}
|
||||
|
||||
~AsyncCallback() {}
|
||||
|
||||
void modalStateFinished (int returnValue)
|
||||
{
|
||||
if (bar != 0)
|
||||
bar->menuDismissed (topLevelIndex, returnValue);
|
||||
}
|
||||
|
||||
private:
|
||||
Component::SafePointer<MenuBarComponent> bar;
|
||||
const int topLevelIndex;
|
||||
|
||||
AsyncCallback (const AsyncCallback&);
|
||||
AsyncCallback& operator= (const AsyncCallback&);
|
||||
};
|
||||
|
||||
void MenuBarComponent::showMenu (int index)
|
||||
{
|
||||
if (index != currentPopupIndex)
|
||||
{
|
||||
if (inModalState)
|
||||
{
|
||||
hideCurrentMenu();
|
||||
indexToShowAgain = index;
|
||||
return;
|
||||
}
|
||||
|
||||
indexToShowAgain = -1;
|
||||
currentPopupIndex = -1;
|
||||
itemUnderMouse = index;
|
||||
currentPopup = 0;
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
menuBarItemsChanged (0);
|
||||
|
||||
Component::SafePointer<Component> prevFocused (getCurrentlyFocusedComponent());
|
||||
Component::SafePointer<Component> deletionChecker (this);
|
||||
setOpenItem (index);
|
||||
setItemUnderMouse (index);
|
||||
|
||||
enterModalState (false);
|
||||
inModalState = true;
|
||||
int result = 0;
|
||||
ApplicationCommandManager* managerOfChosenCommand = 0;
|
||||
|
||||
Desktop::getInstance().addGlobalMouseListener (this);
|
||||
|
||||
for (;;)
|
||||
if (index >= 0)
|
||||
{
|
||||
const int x = getScreenX() + xPositions [itemUnderMouse];
|
||||
const int w = xPositions [itemUnderMouse + 1] - xPositions [itemUnderMouse];
|
||||
PopupMenu m (model->getMenuForIndex (itemUnderMouse,
|
||||
menuNames [itemUnderMouse]));
|
||||
|
||||
currentPopupIndex = itemUnderMouse;
|
||||
indexToShowAgain = -1;
|
||||
repaint();
|
||||
if (m.lookAndFeel == 0)
|
||||
m.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
if (((unsigned int) itemUnderMouse) < (unsigned int) menuNames.size())
|
||||
{
|
||||
PopupMenu m (model->getMenuForIndex (itemUnderMouse,
|
||||
menuNames [itemUnderMouse]));
|
||||
const Rectangle<int> itemPos (xPositions [index], 0, xPositions [index + 1] - xPositions [index], getHeight());
|
||||
|
||||
if (m.lookAndFeel == 0)
|
||||
m.setLookAndFeel (&getLookAndFeel());
|
||||
|
||||
currentPopup = m.createMenuComponent (x, getScreenY(),
|
||||
w, getHeight(),
|
||||
0, w, 0, 0,
|
||||
true, this,
|
||||
&managerOfChosenCommand,
|
||||
this);
|
||||
}
|
||||
|
||||
if (currentPopup == 0)
|
||||
{
|
||||
currentPopup = new DummyMenuComponent();
|
||||
addAndMakeVisible (currentPopup);
|
||||
}
|
||||
|
||||
currentPopup->enterModalState (false);
|
||||
currentPopup->toFront (false); // need to do this after making it modal, or it could
|
||||
// be stuck behind other comps that are already modal..
|
||||
result = currentPopup->runModalLoop();
|
||||
|
||||
if (deletionChecker == 0)
|
||||
return;
|
||||
|
||||
const int lastPopupIndex = currentPopupIndex;
|
||||
currentPopup = 0;
|
||||
currentPopupIndex = -1;
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
topLevelIndexClicked = lastPopupIndex;
|
||||
break;
|
||||
}
|
||||
else if (indexToShowAgain >= 0)
|
||||
{
|
||||
menuBarItemsChanged (0);
|
||||
repaint();
|
||||
itemUnderMouse = indexToShowAgain;
|
||||
|
||||
if (((unsigned int) itemUnderMouse) >= (unsigned int) menuNames.size())
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Desktop::getInstance().removeGlobalMouseListener (this);
|
||||
|
||||
inModalState = false;
|
||||
exitModalState (0);
|
||||
|
||||
if (prevFocused != 0)
|
||||
prevFocused->grabKeyboardFocus();
|
||||
|
||||
const Point<int> mousePos (getMouseXYRelative());
|
||||
updateItemUnderMouse (mousePos.getX(), mousePos.getY());
|
||||
repaint();
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
if (managerOfChosenCommand != 0)
|
||||
{
|
||||
ApplicationCommandTarget::InvocationInfo info (result);
|
||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu;
|
||||
|
||||
managerOfChosenCommand->invoke (info, true);
|
||||
}
|
||||
|
||||
postCommandMessage (result);
|
||||
m.showMenu (itemPos + getScreenPosition(),
|
||||
0, itemPos.getWidth(), 0, 0, true, this,
|
||||
new AsyncCallback (this, index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuDismissed (int topLevelIndex, int itemId)
|
||||
{
|
||||
topLevelIndexClicked = topLevelIndex;
|
||||
postCommandMessage (itemId);
|
||||
}
|
||||
|
||||
void MenuBarComponent::handleCommandMessage (int commandId)
|
||||
{
|
||||
if (model != 0)
|
||||
const Point<int> mousePos (getMouseXYRelative());
|
||||
updateItemUnderMouse (mousePos.getX(), mousePos.getY());
|
||||
|
||||
if (! isCurrentlyBlockedByAnotherModalComponent())
|
||||
setOpenItem (-1);
|
||||
|
||||
if (commandId != 0 && model != 0)
|
||||
model->menuItemSelected (commandId, topLevelIndexClicked);
|
||||
}
|
||||
|
||||
|
|
@ -327,7 +271,6 @@ void MenuBarComponent::mouseDown (const MouseEvent& e)
|
|||
void MenuBarComponent::mouseDrag (const MouseEvent& e)
|
||||
{
|
||||
const MouseEvent e2 (e.getEventRelativeTo (this));
|
||||
|
||||
const int item = getItemAt (e2.x, e2.y);
|
||||
|
||||
if (item >= 0)
|
||||
|
|
@ -340,8 +283,11 @@ void MenuBarComponent::mouseUp (const MouseEvent& e)
|
|||
|
||||
updateItemUnderMouse (e2.x, e2.y);
|
||||
|
||||
if (itemUnderMouse < 0 && dynamic_cast <DummyMenuComponent*> (static_cast <Component*> (currentPopup)) != 0)
|
||||
hideCurrentMenu();
|
||||
if (itemUnderMouse < 0 && getLocalBounds().contains (e2.x, e2.y))
|
||||
{
|
||||
setOpenItem (-1);
|
||||
PopupMenu::dismissAllActiveMenus();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBarComponent::mouseMove (const MouseEvent& e)
|
||||
|
|
@ -387,11 +333,6 @@ bool MenuBarComponent::keyPressed (const KeyPress& key)
|
|||
return used;
|
||||
}
|
||||
|
||||
void MenuBarComponent::inputAttemptWhenModal()
|
||||
{
|
||||
hideCurrentMenu();
|
||||
}
|
||||
|
||||
void MenuBarComponent::menuBarItemsChanged (MenuBarModel* /*menuBarModel*/)
|
||||
{
|
||||
StringArray newNames;
|
||||
|
|
@ -410,8 +351,7 @@ void MenuBarComponent::menuBarItemsChanged (MenuBarModel* /*menuBarModel*/)
|
|||
void MenuBarComponent::menuCommandInvoked (MenuBarModel* /*menuBarModel*/,
|
||||
const ApplicationCommandTarget::InvocationInfo& info)
|
||||
{
|
||||
if (model == 0
|
||||
|| (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0)
|
||||
if (model == 0 || (info.commandFlags & ApplicationCommandInfo::dontTriggerVisualFeedback) != 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < menuNames.size(); ++i)
|
||||
|
|
@ -420,10 +360,8 @@ void MenuBarComponent::menuCommandInvoked (MenuBarModel* /*menuBarModel*/,
|
|||
|
||||
if (menu.containsCommandItem (info.commandID))
|
||||
{
|
||||
itemUnderMouse = i;
|
||||
repaintMenuItem (i);
|
||||
setItemUnderMouse (i);
|
||||
startTimer (200);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ public:
|
|||
*/
|
||||
void setModel (MenuBarModel* newModel);
|
||||
|
||||
/** Returns the current menu bar model being used.
|
||||
*/
|
||||
MenuBarModel* getModel() const throw();
|
||||
|
||||
//==============================================================================
|
||||
/** Pops up one of the menu items.
|
||||
|
||||
|
|
@ -86,8 +90,6 @@ public:
|
|||
/** @internal */
|
||||
void mouseMove (const MouseEvent& e);
|
||||
/** @internal */
|
||||
void inputAttemptWhenModal();
|
||||
/** @internal */
|
||||
void handleCommandMessage (int commandId);
|
||||
/** @internal */
|
||||
bool keyPressed (const KeyPress& key);
|
||||
|
|
@ -102,20 +104,22 @@ public:
|
|||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
class AsyncCallback;
|
||||
friend class AsyncCallback;
|
||||
MenuBarModel* model;
|
||||
|
||||
StringArray menuNames;
|
||||
Array <int> xPositions;
|
||||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked, indexToShowAgain;
|
||||
int itemUnderMouse, currentPopupIndex, topLevelIndexClicked;
|
||||
int lastMouseX, lastMouseY;
|
||||
bool inModalState;
|
||||
ScopedPointer <Component> currentPopup;
|
||||
|
||||
int getItemAt (int x, int y);
|
||||
void setItemUnderMouse (int index);
|
||||
void setOpenItem (int index);
|
||||
void updateItemUnderMouse (int x, int y);
|
||||
void hideCurrentMenu();
|
||||
void timerCallback();
|
||||
void repaintMenuItem (int index);
|
||||
void menuDismissed (int topLevelIndex, int itemId);
|
||||
|
||||
MenuBarComponent (const MenuBarComponent&);
|
||||
MenuBarComponent& operator= (const MenuBarComponent&);
|
||||
|
|
|
|||
|
|
@ -309,8 +309,7 @@ public:
|
|||
static Window* create (const PopupMenu& menu,
|
||||
const bool dismissOnMouseUp,
|
||||
Window* const owner_,
|
||||
const int minX, const int maxX,
|
||||
const int minY, const int maxY,
|
||||
const Rectangle<int>& target,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
const int standardItemHeight,
|
||||
|
|
@ -348,14 +347,14 @@ public:
|
|||
mw->componentAttachedTo = componentAttachedTo;
|
||||
mw->componentAttachedToOriginal = componentAttachedTo;
|
||||
|
||||
mw->calculateWindowPos (minX, maxX, minY, maxY, alignToRectangle);
|
||||
mw->calculateWindowPos (target, alignToRectangle);
|
||||
mw->setTopLeftPosition (mw->windowPos.getX(),
|
||||
mw->windowPos.getY());
|
||||
mw->updateYPositions();
|
||||
|
||||
if (itemIdThatMustBeVisible != 0)
|
||||
{
|
||||
const int y = minY - mw->windowPos.getY();
|
||||
const int y = target.getY() - mw->windowPos.getY();
|
||||
mw->ensureItemIsVisible (itemIdThatMustBeVisible,
|
||||
(((unsigned int) y) < (unsigned int) mw->windowPos.getHeight()) ? y : -1);
|
||||
}
|
||||
|
|
@ -804,13 +803,10 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void calculateWindowPos (const int minX, const int maxX,
|
||||
const int minY, const int maxY,
|
||||
const bool alignToRectangle)
|
||||
void calculateWindowPos (const Rectangle<int>& target, const bool alignToRectangle)
|
||||
{
|
||||
const Rectangle<int> mon (Desktop::getInstance()
|
||||
.getMonitorAreaContaining (Point<int> ((minX + maxX) / 2,
|
||||
(minY + maxY) / 2),
|
||||
.getMonitorAreaContaining (target.getCentre(),
|
||||
#if JUCE_MAC
|
||||
true));
|
||||
#else
|
||||
|
|
@ -822,19 +818,19 @@ private:
|
|||
|
||||
if (alignToRectangle)
|
||||
{
|
||||
x = minX;
|
||||
x = target.getX();
|
||||
|
||||
const int spaceUnder = mon.getHeight() - (maxY - mon.getY());
|
||||
const int spaceOver = minY - mon.getY();
|
||||
const int spaceUnder = mon.getHeight() - (target.getBottom() - mon.getY());
|
||||
const int spaceOver = target.getY() - mon.getY();
|
||||
|
||||
if (heightToUse < spaceUnder - 30 || spaceUnder >= spaceOver)
|
||||
y = maxY;
|
||||
y = target.getBottom();
|
||||
else
|
||||
y = minY - heightToUse;
|
||||
y = target.getY() - heightToUse;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool tendTowardsRight = (minX + maxX) / 2 < mon.getCentreX();
|
||||
bool tendTowardsRight = target.getCentreX() < mon.getCentreX();
|
||||
|
||||
if (owner != 0)
|
||||
{
|
||||
|
|
@ -843,38 +839,38 @@ private:
|
|||
const bool ownerGoingRight = (owner->getX() + owner->getWidth() / 2
|
||||
> owner->owner->getX() + owner->owner->getWidth() / 2);
|
||||
|
||||
if (ownerGoingRight && maxX + widthToUse < mon.getRight() - 4)
|
||||
if (ownerGoingRight && target.getRight() + widthToUse < mon.getRight() - 4)
|
||||
tendTowardsRight = true;
|
||||
else if ((! ownerGoingRight) && minX > widthToUse + 4)
|
||||
else if ((! ownerGoingRight) && target.getX() > widthToUse + 4)
|
||||
tendTowardsRight = false;
|
||||
}
|
||||
else if (maxX + widthToUse < mon.getRight() - 32)
|
||||
else if (target.getRight() + widthToUse < mon.getRight() - 32)
|
||||
{
|
||||
tendTowardsRight = true;
|
||||
}
|
||||
}
|
||||
|
||||
const int biggestSpace = jmax (mon.getRight() - maxX,
|
||||
minX - mon.getX()) - 32;
|
||||
const int biggestSpace = jmax (mon.getRight() - target.getRight(),
|
||||
target.getX() - mon.getX()) - 32;
|
||||
|
||||
if (biggestSpace < widthToUse)
|
||||
{
|
||||
layoutMenuItems (biggestSpace + (maxX - minX) / 3, widthToUse, heightToUse);
|
||||
layoutMenuItems (biggestSpace + target.getWidth() / 3, widthToUse, heightToUse);
|
||||
|
||||
if (numColumns > 1)
|
||||
layoutMenuItems (biggestSpace - 4, widthToUse, heightToUse);
|
||||
|
||||
tendTowardsRight = (mon.getRight() - maxX) >= (minX - mon.getX());
|
||||
tendTowardsRight = (mon.getRight() - target.getRight()) >= (target.getX() - mon.getX());
|
||||
}
|
||||
|
||||
if (tendTowardsRight)
|
||||
x = jmin (mon.getRight() - widthToUse - 4, maxX);
|
||||
x = jmin (mon.getRight() - widthToUse - 4, target.getRight());
|
||||
else
|
||||
x = jmax (mon.getX() + 4, minX - widthToUse);
|
||||
x = jmax (mon.getX() + 4, target.getX() - widthToUse);
|
||||
|
||||
y = minY;
|
||||
if ((minY + maxY) / 2 > mon.getCentreY())
|
||||
y = jmax (mon.getY(), maxY - heightToUse);
|
||||
y = target.getY();
|
||||
if (target.getCentreY() > mon.getCentreY())
|
||||
y = jmax (mon.getY(), target.getBottom() - heightToUse);
|
||||
}
|
||||
|
||||
x = jmax (mon.getX() + 1, jmin (mon.getRight() - (widthToUse + 6), x));
|
||||
|
|
@ -1107,13 +1103,10 @@ private:
|
|||
|
||||
if (childComp->isValidComponent() && childComp->itemInfo.hasActiveSubMenu())
|
||||
{
|
||||
const Point<int> topLeft (childComp->relativePositionToGlobal (Point<int>()));
|
||||
const Point<int> bottomRight (childComp->relativePositionToGlobal (Point<int> (childComp->getWidth(), childComp->getHeight())));
|
||||
|
||||
activeSubMenu = Window::create (*(childComp->itemInfo.subMenu),
|
||||
dismissOnMouseUp,
|
||||
this,
|
||||
topLeft.getX(), bottomRight.getX(), topLeft.getY(), bottomRight.getY(),
|
||||
childComp->getScreenBounds(),
|
||||
0, maximumNumColumns,
|
||||
standardItemHeight,
|
||||
false, 0, menuBarComponent,
|
||||
|
|
@ -1494,7 +1487,7 @@ void PopupMenu::addSectionHeader (const String& title)
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
Component* PopupMenu::createMenuComponent (const int x, const int y, const int w, const int h,
|
||||
Component* PopupMenu::createMenuComponent (const Rectangle<int>& target,
|
||||
const int itemIdThatMustBeVisible,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
|
|
@ -1504,20 +1497,10 @@ Component* PopupMenu::createMenuComponent (const int x, const int y, const int w
|
|||
ApplicationCommandManager** managerOfChosenCommand,
|
||||
Component* const componentAttachedTo)
|
||||
{
|
||||
Window* const pw
|
||||
= Window::create (*this,
|
||||
ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(),
|
||||
0,
|
||||
x, x + w,
|
||||
y, y + h,
|
||||
minimumWidth,
|
||||
maximumNumColumns,
|
||||
standardItemHeight,
|
||||
alignToRectangle,
|
||||
itemIdThatMustBeVisible,
|
||||
menuBarComponent,
|
||||
managerOfChosenCommand,
|
||||
componentAttachedTo);
|
||||
Window* const pw = Window::create (*this, ModifierKeys::getCurrentModifiers().isAnyMouseButtonDown(),
|
||||
0, target, minimumWidth, maximumNumColumns, standardItemHeight,
|
||||
alignToRectangle, itemIdThatMustBeVisible, menuBarComponent,
|
||||
managerOfChosenCommand, componentAttachedTo);
|
||||
|
||||
if (pw != 0)
|
||||
pw->setVisible (true);
|
||||
|
|
@ -1525,56 +1508,87 @@ Component* PopupMenu::createMenuComponent (const int x, const int y, const int w
|
|||
return pw;
|
||||
}
|
||||
|
||||
int PopupMenu::showMenu (const int x, const int y, const int w, const int h,
|
||||
// This invokes any command manager commands and deletes the menu window when it is dismissed
|
||||
class PopupMenuCompletionCallback : public ModalComponentManager::Callback
|
||||
{
|
||||
public:
|
||||
PopupMenuCompletionCallback()
|
||||
: managerOfChosenCommand (0)
|
||||
{
|
||||
}
|
||||
|
||||
~PopupMenuCompletionCallback() {}
|
||||
|
||||
void modalStateFinished (int result)
|
||||
{
|
||||
if (managerOfChosenCommand != 0 && result != 0)
|
||||
{
|
||||
ApplicationCommandTarget::InvocationInfo info (result);
|
||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu;
|
||||
|
||||
managerOfChosenCommand->invoke (info, true);
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationCommandManager* managerOfChosenCommand;
|
||||
ScopedPointer<Component> component;
|
||||
|
||||
private:
|
||||
PopupMenuCompletionCallback (const PopupMenuCompletionCallback&);
|
||||
PopupMenuCompletionCallback& operator= (const PopupMenuCompletionCallback&);
|
||||
};
|
||||
|
||||
|
||||
int PopupMenu::showMenu (const Rectangle<int>& target,
|
||||
const int itemIdThatMustBeVisible,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
const int standardItemHeight,
|
||||
const bool alignToRectangle,
|
||||
Component* const componentAttachedTo)
|
||||
Component* const componentAttachedTo,
|
||||
ModalComponentManager::Callback* userCallback)
|
||||
{
|
||||
ScopedPointer<ModalComponentManager::Callback> userCallbackDeleter (userCallback);
|
||||
|
||||
Component::SafePointer<Component> prevFocused (Component::getCurrentlyFocusedComponent());
|
||||
Component::SafePointer<Component> prevTopLevel ((prevFocused != 0) ? prevFocused->getTopLevelComponent() : 0);
|
||||
|
||||
Window::wasHiddenBecauseOfAppChange() = false;
|
||||
|
||||
int result = 0;
|
||||
ApplicationCommandManager* managerOfChosenCommand = 0;
|
||||
PopupMenuCompletionCallback* callback = new PopupMenuCompletionCallback();
|
||||
ScopedPointer<PopupMenuCompletionCallback> callbackDeleter (callback);
|
||||
|
||||
ScopedPointer <Component> popupComp (createMenuComponent (x, y, w, h,
|
||||
itemIdThatMustBeVisible,
|
||||
minimumWidth,
|
||||
maximumNumColumns > 0 ? maximumNumColumns : 7,
|
||||
standardItemHeight,
|
||||
alignToRectangle, 0,
|
||||
&managerOfChosenCommand,
|
||||
componentAttachedTo));
|
||||
callback->component = createMenuComponent (target,
|
||||
itemIdThatMustBeVisible,
|
||||
minimumWidth,
|
||||
maximumNumColumns > 0 ? maximumNumColumns : 7,
|
||||
standardItemHeight,
|
||||
alignToRectangle, 0,
|
||||
&callback->managerOfChosenCommand,
|
||||
componentAttachedTo);
|
||||
|
||||
if (popupComp != 0)
|
||||
if (callback->component == 0)
|
||||
return 0;
|
||||
|
||||
callbackDeleter.release();
|
||||
|
||||
callback->component->enterModalState (false, userCallbackDeleter.release());
|
||||
callback->component->toFront (false); // need to do this after making it modal, or it could
|
||||
// be stuck behind other comps that are already modal..
|
||||
|
||||
ModalComponentManager::getInstance()->attachCallback (callback->component, callback);
|
||||
|
||||
if (userCallback != 0)
|
||||
return 0;
|
||||
|
||||
const int result = callback->component->runModalLoop();
|
||||
|
||||
if (! Window::wasHiddenBecauseOfAppChange())
|
||||
{
|
||||
popupComp->enterModalState (false);
|
||||
popupComp->toFront (false); // need to do this after making it modal, or it could
|
||||
// be stuck behind other comps that are already modal..
|
||||
if (prevTopLevel != 0)
|
||||
prevTopLevel->toFront (true);
|
||||
|
||||
result = popupComp->runModalLoop();
|
||||
popupComp = 0;
|
||||
|
||||
if (! Window::wasHiddenBecauseOfAppChange())
|
||||
{
|
||||
if (prevTopLevel != 0)
|
||||
prevTopLevel->toFront (true);
|
||||
|
||||
if (prevFocused != 0)
|
||||
prevFocused->grabKeyboardFocus();
|
||||
}
|
||||
}
|
||||
|
||||
if (managerOfChosenCommand != 0 && result != 0)
|
||||
{
|
||||
ApplicationCommandTarget::InvocationInfo info (result);
|
||||
info.invocationMethod = ApplicationCommandTarget::InvocationInfo::fromMenu;
|
||||
|
||||
managerOfChosenCommand->invoke (info, true);
|
||||
if (prevFocused != 0)
|
||||
prevFocused->grabKeyboardFocus();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
@ -1583,7 +1597,8 @@ int PopupMenu::showMenu (const int x, const int y, const int w, const int h,
|
|||
int PopupMenu::show (const int itemIdThatMustBeVisible,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
const int standardItemHeight)
|
||||
const int standardItemHeight,
|
||||
ModalComponentManager::Callback* callback)
|
||||
{
|
||||
const Point<int> mousePos (Desktop::getMousePosition());
|
||||
|
||||
|
|
@ -1591,7 +1606,8 @@ int PopupMenu::show (const int itemIdThatMustBeVisible,
|
|||
itemIdThatMustBeVisible,
|
||||
minimumWidth,
|
||||
maximumNumColumns,
|
||||
standardItemHeight);
|
||||
standardItemHeight,
|
||||
callback);
|
||||
}
|
||||
|
||||
int PopupMenu::showAt (const int screenX,
|
||||
|
|
@ -1599,39 +1615,39 @@ int PopupMenu::showAt (const int screenX,
|
|||
const int itemIdThatMustBeVisible,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
const int standardItemHeight)
|
||||
const int standardItemHeight,
|
||||
ModalComponentManager::Callback* callback)
|
||||
{
|
||||
return showMenu (screenX, screenY, 1, 1,
|
||||
return showMenu (Rectangle<int> (screenX, screenY, 1, 1),
|
||||
itemIdThatMustBeVisible,
|
||||
minimumWidth, maximumNumColumns,
|
||||
standardItemHeight,
|
||||
false, 0);
|
||||
false, 0, callback);
|
||||
}
|
||||
|
||||
int PopupMenu::showAt (Component* componentToAttachTo,
|
||||
const int itemIdThatMustBeVisible,
|
||||
const int minimumWidth,
|
||||
const int maximumNumColumns,
|
||||
const int standardItemHeight)
|
||||
const int standardItemHeight,
|
||||
ModalComponentManager::Callback* callback)
|
||||
{
|
||||
if (componentToAttachTo != 0)
|
||||
{
|
||||
return showMenu (componentToAttachTo->getScreenX(),
|
||||
componentToAttachTo->getScreenY(),
|
||||
componentToAttachTo->getWidth(),
|
||||
componentToAttachTo->getHeight(),
|
||||
return showMenu (componentToAttachTo->getScreenBounds(),
|
||||
itemIdThatMustBeVisible,
|
||||
minimumWidth,
|
||||
maximumNumColumns,
|
||||
standardItemHeight,
|
||||
true, componentToAttachTo);
|
||||
true, componentToAttachTo, callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
return show (itemIdThatMustBeVisible,
|
||||
minimumWidth,
|
||||
maximumNumColumns,
|
||||
standardItemHeight);
|
||||
standardItemHeight,
|
||||
callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -240,12 +240,19 @@ public:
|
|||
in zero.
|
||||
@param standardItemHeight if this is non-zero, it will be used as the standard
|
||||
height for menu items (apart from custom items)
|
||||
@param callback if this is non-zero, the menu will be launched asynchronously,
|
||||
returning immediately, and the callback will receive a
|
||||
call when the menu is either dismissed or has an item
|
||||
selected. This object will be owned and deleted by the
|
||||
system, so make sure that it works safely and that any
|
||||
pointers that it uses are safely within scope.
|
||||
@see showAt
|
||||
*/
|
||||
int show (int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
|
||||
/** Displays the menu at a specific location.
|
||||
|
|
@ -264,7 +271,8 @@ public:
|
|||
int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
/** Displays the menu as if it's attached to a component such as a button.
|
||||
|
||||
|
|
@ -276,7 +284,8 @@ public:
|
|||
int itemIdThatMustBeVisible = 0,
|
||||
int minimumWidth = 0,
|
||||
int maximumNumColumns = 0,
|
||||
int standardItemHeight = 0);
|
||||
int standardItemHeight = 0,
|
||||
ModalComponentManager::Callback* callback = 0);
|
||||
|
||||
//==============================================================================
|
||||
/** Closes any menus that are currently open.
|
||||
|
|
@ -383,6 +392,7 @@ private:
|
|||
friend class ItemComponent;
|
||||
friend class Window;
|
||||
friend class PopupMenuCustomComponent;
|
||||
friend class MenuBarComponent;
|
||||
friend class OwnedArray <Item>;
|
||||
friend class ScopedPointer <Window>;
|
||||
|
||||
|
|
@ -392,16 +402,16 @@ private:
|
|||
|
||||
void addSeparatorIfPending();
|
||||
|
||||
int showMenu (int x, int y, int w, int h,
|
||||
int showMenu (const Rectangle<int>& target,
|
||||
int itemIdThatMustBeVisible,
|
||||
int minimumWidth,
|
||||
int maximumNumColumns,
|
||||
int standardItemHeight,
|
||||
bool alignToRectangle,
|
||||
Component* componentAttachedTo);
|
||||
Component* componentAttachedTo,
|
||||
ModalComponentManager::Callback* callback);
|
||||
|
||||
friend class MenuBarComponent;
|
||||
Component* createMenuComponent (int x, int y, int w, int h,
|
||||
Component* createMenuComponent (const Rectangle<int>& target,
|
||||
int itemIdThatMustBeVisible,
|
||||
int minimumWidth,
|
||||
int maximumNumColumns,
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ void Path::addArrow (const Line<float>& line, float lineThickness,
|
|||
|
||||
startNewSubPath (line.getPointAlongLine (0, lineThickness));
|
||||
lineTo (line.getPointAlongLine (0, -lineThickness));
|
||||
lineTo (reversed.getPointAlongLine (0, lineThickness));
|
||||
lineTo (reversed.getPointAlongLine (arrowheadLength, lineThickness));
|
||||
lineTo (reversed.getPointAlongLine (arrowheadLength, arrowheadWidth));
|
||||
lineTo (line.getEnd());
|
||||
lineTo (reversed.getPointAlongLine (arrowheadLength, -arrowheadWidth));
|
||||
|
|
|
|||
|
|
@ -404,6 +404,9 @@
|
|||
#ifndef __JUCE_DESKTOP_JUCEHEADER__
|
||||
#include "gui/components/juce_Desktop.h"
|
||||
#endif
|
||||
#ifndef __JUCE_MODALCOMPONENTMANAGER_JUCEHEADER__
|
||||
#include "gui/components/juce_ModalComponentManager.h"
|
||||
#endif
|
||||
#ifndef __JUCE_KEYBOARDFOCUSTRAVERSER_JUCEHEADER__
|
||||
#include "gui/components/keyboard/juce_KeyboardFocusTraverser.h"
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue