1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Added a new struct DialogWindow::LaunchOptions, to provide a better mechanism than the existing static methods for launching dialog boxes. I've left the old static methods in there but will probably deprecate them at some point in the future. Also added a couple of methods to OptionalOwnedPointer.

This commit is contained in:
jules 2012-08-29 11:01:47 +01:00
parent a4e87ef28a
commit d7cea05104
11 changed files with 253 additions and 125 deletions

View file

@ -76,33 +76,18 @@ JuceUpdater::~JuceUpdater()
filenameComp.removeListener (this);
}
//==============================================================================
class UpdateDialogWindow : public DialogWindow
{
public:
UpdateDialogWindow (JuceUpdater* updater, Component* componentToCentreAround)
: DialogWindow ("JUCE Module Updater",
Colours::lightgrey, true, true)
{
setUsingNativeTitleBar (true);
setContentOwned (updater, true);
centreAroundComponent (componentToCentreAround, getWidth(), getHeight());
setResizable (true, true);
}
void closeButtonPressed()
{
setVisible (false);
}
private:
JUCE_DECLARE_NON_COPYABLE (UpdateDialogWindow);
};
void JuceUpdater::show (ModuleList& moduleList, Component* mainWindow, const String& message)
{
UpdateDialogWindow w (new JuceUpdater (moduleList, message), mainWindow);
w.runModalLoop();
DialogWindow::LaunchOptions o;
o.content.setOwned (new JuceUpdater (moduleList, message));
o.dialogTitle = "JUCE Module Updater";
o.dialogBackgroundColour = Colours::lightgrey;
o.componentToCentreAround = mainWindow;
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = true;
o.resizable = true;
o.runModal();
}
void JuceUpdater::resized()

View file

@ -127,13 +127,13 @@ namespace FileHelpers
String appendPath (const String& path, const String& subpath)
{
if (isAbsolutePath (subpath))
return subpath.replaceCharacter ('\\', '/');
return unixStylePath (subpath);
String path1 (path.replaceCharacter ('\\', '/'));
String path1 (unixStylePath (path));
if (! path1.endsWithChar ('/'))
path1 << '/';
return path1 + subpath.replaceCharacter ('\\', '/');
return path1 + unixStylePath (subpath);
}
bool shouldPathsBeRelative (String path1, String path2)

View file

@ -48,12 +48,12 @@ public:
{}
RelativePath (const String& path_, const RootFolder root_)
: path (path_.replaceCharacter ('\\', '/')), root (root_)
: path (FileHelpers::unixStylePath (path_)), root (root_)
{
}
RelativePath (const File& file, const File& rootFolder, const RootFolder root_)
: path (FileHelpers::getRelativePathFrom (file, rootFolder).replaceCharacter ('\\', '/')), root (root_)
: path (FileHelpers::unixStylePath (FileHelpers::getRelativePathFrom (file, rootFolder))), root (root_)
{
}

View file

@ -995,28 +995,6 @@ public:
}
};
//==============================================================================
/** A DialogWindow containing a ColourSelector component */
class ColourSelectorDialogWindow : public DialogWindow
{
public:
ColourSelectorDialogWindow()
: DialogWindow ("Colour selector demo", Colours::lightgrey, true)
{
setContentOwned (new ColourSelector(), false);
centreWithSize (400, 400);
setResizable (true, true);
}
void closeButtonPressed()
{
// we expect this component to be run within a modal loop, so when the close
// button is clicked, we can make it invisible to cause the loop to exit and the
// calling code will delete this object.
setVisible (false);
}
};
#if JUCE_MAC
//==============================================================================
@ -1287,13 +1265,18 @@ public:
}
else if (result == 120)
{
#if JUCE_MODAL_LOOPS_PERMITTED
ColourSelectorDialogWindow colourDialog;
DialogWindow::LaunchOptions o;
// this will run an event loop until the dialog's closeButtonPressed()
// method causes the loop to exit.
colourDialog.runModalLoop();
#endif
o.content.setOwned (new ColourSelector());
o.content->setSize (400, 400);
o.dialogTitle = "Colour Selector Demo";
o.dialogBackgroundColour = Colours::grey;
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = true;
o.resizable = true;
o.launchAsync();
}
else if (result == 140)
{

View file

@ -411,11 +411,16 @@ void MainHostWindow::showAudioSettings()
audioSettingsComp.setSize (500, 450);
DialogWindow::showModalDialog ("Audio Settings",
&audioSettingsComp,
this,
Colours::azure,
true);
DialogWindow::LaunchOptions o;
o.content.setNonOwned (&audioSettingsComp);
o.dialogTitle = "Audio Settings";
o.componentToCentreAround = this;
o.dialogBackgroundColour = Colours::azure;
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = false;
o.resizable = false;
o.runModal();
ScopedPointer<XmlElement> audioState (deviceManager.createStateXml());

View file

@ -173,12 +173,13 @@ void TestComponent::resized()
//==============================================================================
void TestComponent::showInDialogBox (JucerDocument& document)
{
TooltipWindow tooltipWindow (0, 400);
DialogWindow::LaunchOptions o;
o.content.setOwned (new TestComponent (nullptr, document.createCopy(), true));
o.dialogTitle = "Testing: " + document.getClassName();
o.dialogBackgroundColour = Colours::azure;
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = false;
o.resizable = true;
TestComponent testComp (0, document.createCopy(), true);
DialogWindow::showModalDialog ("Testing: " + document.getClassName(),
&testComp, 0,
Colours::azure,
true, true);
o.launchAsync();
}

View file

@ -223,17 +223,22 @@ public:
/** Shows the audio properties dialog box modally. */
virtual void showAudioSettingsDialog()
{
AudioDeviceSelectorComponent selectorComp (*deviceManager,
filter->getNumInputChannels(),
filter->getNumInputChannels(),
filter->getNumOutputChannels(),
filter->getNumOutputChannels(),
true, false, true, false);
DialogWindow::LaunchOptions o;
o.content.setOwned (new AudioDeviceSelectorComponent (*deviceManager,
filter->getNumInputChannels(),
filter->getNumInputChannels(),
filter->getNumOutputChannels(),
filter->getNumOutputChannels(),
true, false, true, false));
o.content->setSize (500, 450);
selectorComp.setSize (500, 450);
o.dialogTitle = TRANS("Audio Settings");
o.dialogBackgroundColour = Colours::lightgrey;
o.escapeKeyTriggersCloseButton = true;
o.useNativeTitleBar = true;
o.resizable = false;
DialogWindow::showModalDialog (TRANS("Audio Settings"), &selectorComp, this,
Colours::lightgrey, true, false, false);
o.launchAsync();
}
//==============================================================================

View file

@ -148,6 +148,18 @@ public:
shouldDelete = takeOwnership;
}
/** Makes this OptionalScopedPointer point at a new object, and take ownership of that object. */
void setOwned (ObjectType* newObject)
{
set (newObject, true);
}
/** Makes this OptionalScopedPointer point at a new object, but will not take ownership of that object. */
void setNonOwned (ObjectType* newObject)
{
set (newObject, false);
}
/** Returns true if the target object will be deleted when this pointer
object is deleted.
*/

View file

@ -23,12 +23,10 @@
==============================================================================
*/
DialogWindow::DialogWindow (const String& name,
const Colour& backgroundColour_,
const bool escapeKeyTriggersCloseButton_,
const bool addToDesktop_)
: DocumentWindow (name, backgroundColour_, DocumentWindow::closeButton, addToDesktop_),
escapeKeyTriggersCloseButton (escapeKeyTriggersCloseButton_)
DialogWindow::DialogWindow (const String& name, const Colour& colour,
const bool escapeCloses, const bool onDesktop)
: DocumentWindow (name, colour, DocumentWindow::closeButton, onDesktop),
escapeKeyTriggersCloseButton (escapeCloses)
{
}
@ -36,40 +34,53 @@ DialogWindow::~DialogWindow()
{
}
//==============================================================================
bool DialogWindow::keyPressed (const KeyPress& key)
{
if (escapeKeyTriggersCloseButton && key == KeyPress::escapeKey)
{
setVisible (false);
return true;
}
return DocumentWindow::keyPressed (key);
}
void DialogWindow::resized()
{
DocumentWindow::resized();
const KeyPress esc (KeyPress::escapeKey, 0, 0);
if (escapeKeyTriggersCloseButton
&& getCloseButton() != nullptr
&& ! getCloseButton()->isRegisteredForShortcut (esc))
if (escapeKeyTriggersCloseButton)
{
getCloseButton()->addShortcut (esc);
if (Button* const close = getCloseButton())
{
const KeyPress esc (KeyPress::escapeKey, 0, 0);
if (! close->isRegisteredForShortcut (esc))
close->addShortcut (esc);
}
}
}
//==============================================================================
class TempDialogWindow : public DialogWindow
class DefaultDialogWindow : public DialogWindow
{
public:
TempDialogWindow (const String& title,
Component* contentComponent_,
Component* componentToCentreAround,
const Colour& colour,
const bool escapeKeyTriggersCloseButton_,
const bool shouldBeResizable,
const bool useBottomRightCornerResizer)
: DialogWindow (title, colour, escapeKeyTriggersCloseButton_, true)
DefaultDialogWindow (LaunchOptions& options)
: DialogWindow (options.dialogTitle, options.dialogBackgroundColour,
options.escapeKeyTriggersCloseButton, true)
{
setUsingNativeTitleBar (options.useNativeTitleBar);
if (! JUCEApplication::isStandaloneApp())
setAlwaysOnTop (true); // for a plugin, make it always-on-top because the host windows are often top-level
setContentNonOwned (contentComponent_, true);
centreAroundComponent (componentToCentreAround, getWidth(), getHeight());
setResizable (shouldBeResizable, useBottomRightCornerResizer);
if (options.content.willDeleteObject())
setContentOwned (options.content.release(), true);
else
setContentNonOwned (options.content.release(), true);
centreAroundComponent (options.componentToCentreAround, getWidth(), getHeight());
setResizable (options.resizable, options.useBottomRightCornerResizer);
}
void closeButtonPressed()
@ -78,9 +89,34 @@ public:
}
private:
JUCE_DECLARE_NON_COPYABLE (TempDialogWindow);
JUCE_DECLARE_NON_COPYABLE (DefaultDialogWindow);
};
DialogWindow::LaunchOptions::LaunchOptions() noexcept
: dialogBackgroundColour (Colours::lightgrey),
componentToCentreAround (nullptr),
escapeKeyTriggersCloseButton (true),
useNativeTitleBar (true),
resizable (true),
useBottomRightCornerResizer (false)
{
}
DialogWindow* DialogWindow::LaunchOptions::launchAsync()
{
jassert (content != nullptr); // You need to provide some kind of content for the dialog!
DefaultDialogWindow* const d = new DefaultDialogWindow (*this);
d->enterModalState (true, nullptr, true);
return d;
}
#if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN
int DialogWindow::LaunchOptions::runModal()
{
return launchAsync()->runModalLoop();
}
#endif
//==============================================================================
void DialogWindow::showDialog (const String& dialogTitle,
@ -88,14 +124,20 @@ void DialogWindow::showDialog (const String& dialogTitle,
Component* const componentToCentreAround,
const Colour& backgroundColour,
const bool escapeKeyTriggersCloseButton,
const bool shouldBeResizable,
const bool resizable,
const bool useBottomRightCornerResizer)
{
TempDialogWindow* dw = new TempDialogWindow (dialogTitle, contentComponent, componentToCentreAround,
backgroundColour, escapeKeyTriggersCloseButton,
shouldBeResizable, useBottomRightCornerResizer);
LaunchOptions o;
o.dialogTitle = dialogTitle;
o.content.setNonOwned (contentComponent);
o.componentToCentreAround = componentToCentreAround;
o.dialogBackgroundColour = backgroundColour;
o.escapeKeyTriggersCloseButton = escapeKeyTriggersCloseButton;
o.useNativeTitleBar = false;
o.resizable = resizable;
o.useBottomRightCornerResizer = useBottomRightCornerResizer;
dw->enterModalState (true, 0, true);
o.launchAsync();
}
#if JUCE_MODAL_LOOPS_PERMITTED
@ -104,13 +146,19 @@ int DialogWindow::showModalDialog (const String& dialogTitle,
Component* const componentToCentreAround,
const Colour& backgroundColour,
const bool escapeKeyTriggersCloseButton,
const bool shouldBeResizable,
const bool resizable,
const bool useBottomRightCornerResizer)
{
TempDialogWindow dw (dialogTitle, contentComponent, componentToCentreAround,
backgroundColour, escapeKeyTriggersCloseButton,
shouldBeResizable, useBottomRightCornerResizer);
LaunchOptions o;
o.dialogTitle = dialogTitle;
o.content.setNonOwned (contentComponent);
o.componentToCentreAround = componentToCentreAround;
o.dialogBackgroundColour = backgroundColour;
o.escapeKeyTriggersCloseButton = escapeKeyTriggersCloseButton;
o.useNativeTitleBar = false;
o.resizable = resizable;
o.useBottomRightCornerResizer = useBottomRightCornerResizer;
return dw.runModalLoop();
return o.runModal();
}
#endif

View file

@ -27,7 +27,6 @@
#define __JUCE_DIALOGWINDOW_JUCEHEADER__
#include "juce_DocumentWindow.h"
#include "../buttons/juce_Button.h"
//==============================================================================
@ -40,13 +39,13 @@
Any of the methods available to a DocumentWindow or ResizableWindow are also
available to this, so it can be made resizable, have a menu bar, etc.
To add items to the box, see the ResizableWindow::setContentOwned() or
ResizableWindow::setContentNonOwned() methods. Don't add components directly to this
class - always put them in a content component!
You can either override or use an instance of the DialogWindow class directly,
or you can use a DialogWindow::LaunchOptions structure to quickly set up and
launch a box containing a content component.
You'll need to override the DocumentWindow::closeButtonPressed() method to handle
the user clicking the close button - for more info, see the DocumentWindow
help.
If you use the class directly, you'll need to override the
DocumentWindow::closeButtonPressed() method to handle the user clicking the close
button - for more info, see the DocumentWindow help.
@see DocumentWindow, ResizableWindow
*/
@ -75,9 +74,83 @@ public:
*/
~DialogWindow();
//==============================================================================
/** This class defines a collection of settings to be used to open a DialogWindow.
The easiest way to open a DialogWindow is to create yourself a LaunchOptions structure,
initialise its fields with the appropriate details, and then call its launchAsync()
method to launch the dialog.
*/
struct LaunchOptions
{
LaunchOptions() noexcept;
/** The title to give the window. */
String dialogTitle;
/** The background colour for the window. */
Colour dialogBackgroundColour;
/** The content component to show in the window. This must not be null!
Using an OptionalScopedPointer to hold this pointer lets you indicate whether
you'd like the dialog to automatically delete the component when the dialog
has terminated.
*/
OptionalScopedPointer <Component> content;
/** If this is not a nullptr, it indicates a component that you'd like to position this
dialog box in front of. See the DocumentWindow::centreAroundComponent() method for
more info about this parameter.
*/
Component* componentToCentreAround;
/** If true, then the escape key will trigger the dialog's close button. */
bool escapeKeyTriggersCloseButton;
/** If true, the dialog will use a native title bar. See TopLevelWindow::setUsingNativeTitleBar() */
bool useNativeTitleBar;
/** If true, the window will be resizable. See ResizableWindow::setResizable() */
bool resizable;
/** Indicates whether to use a border or corner resizer component. See ResizableWindow::setResizable() */
bool useBottomRightCornerResizer;
/** Launches a new modal dialog window.
This will create a dialog based on the settings in this structure,
launch it modally, and return immediately. The window that is returned
will be automatically deleted when the modal state is terminated.
When the dialog's close button is clicked, it'll automatically terminate its
modal state, but you can also do this programatically by calling
exitModalState (returnValue) on the DialogWindow.
If your content component needs to find the dialog window that it is
contained in, a quick trick is to do this:
@code
Dialogwindow* dw = contentComponent->findParentComponentOfClass<DialogWindow>();
if (dw != nullptr)
dw->exitModalState (1234);
@endcode
*/
DialogWindow* launchAsync();
#if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN
/** Launches and runs the dialog modally, returning the status code that was
used to terminate the modal loop.
Note that running modal loops inline is a BAD technique. If possible, always
use launchAsync() instead of this method.
*/
int runModal();
#endif
};
//==============================================================================
/** Easy way of quickly showing a dialog box containing a given component.
Note: this method has been superceded by the DialogWindow::LaunchOptions structure,
which does the same job with some extra flexibility. The showDialog method is here
for backwards compatibility, but please use DialogWindow::LaunchOptions in new code.
This will open and display a DialogWindow containing a given component, making it
modal, but returning immediately to allow the dialog to finish in its own time. If
you want to block and run a modal loop until the dialog is dismissed, use showModalDialog()
@ -119,8 +192,13 @@ public:
bool shouldBeResizable = false,
bool useBottomRightCornerResizer = false);
#if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN
/** Easy way of quickly showing a dialog box containing a given component.
Note: this method has been superceded by the DialogWindow::LaunchOptions structure,
which does the same job with some extra flexibility. The showDialog method is here
for backwards compatibility, but please use DialogWindow::LaunchOptions in new code.
This will open and display a DialogWindow containing a given component, returning
when the user clicks its close button.
@ -154,7 +232,6 @@ public:
@param useBottomRightCornerResizer if shouldBeResizable is true, this indicates whether
to use a border or corner resizer component. See ResizableWindow::setResizable()
*/
#if JUCE_MODAL_LOOPS_PERMITTED || DOXYGEN
static int showModalDialog (const String& dialogTitle,
Component* contentComponent,
Component* componentToCentreAround,
@ -164,12 +241,15 @@ public:
bool useBottomRightCornerResizer = false);
#endif
protected:
//==============================================================================
/** @internal */
void resized();
/** @internal */
bool keyPressed (const KeyPress&);
private:
//==============================================================================
bool escapeKeyTriggersCloseButton;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DialogWindow);

View file

@ -83,7 +83,16 @@ void PreferencesPanel::addSettingsPage (const String& title, const void* imageDa
void PreferencesPanel::showInDialogBox (const String& dialogTitle, int dialogWidth, int dialogHeight, const Colour& backgroundColour)
{
setSize (dialogWidth, dialogHeight);
DialogWindow::showDialog (dialogTitle, this, 0, backgroundColour, false);
DialogWindow::LaunchOptions o;
o.content.setNonOwned (this);
o.dialogTitle = dialogTitle;
o.dialogBackgroundColour = backgroundColour;
o.escapeKeyTriggersCloseButton = false;
o.useNativeTitleBar = false;
o.resizable = false;
o.launchAsync();
}
//==============================================================================