mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Had a look at the SplashScreen class, and realised it was total crap, so redesigned it to avoid using any modal loop nastiness, and to encourage initialisation on background threads.
This commit is contained in:
parent
44b4ccc693
commit
a696e907e4
2 changed files with 104 additions and 117 deletions
|
|
@ -22,71 +22,50 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
SplashScreen::SplashScreen()
|
||||
: originalClickCounter (0)
|
||||
SplashScreen::SplashScreen (const String& title, const Image& image, bool useDropShadow)
|
||||
: Component (title),
|
||||
backgroundImage (image),
|
||||
clickCountToDelete (0)
|
||||
{
|
||||
setOpaque (true);
|
||||
// You must supply a valid image here!
|
||||
jassert (backgroundImage.isValid());
|
||||
|
||||
setOpaque (! backgroundImage.hasAlphaChannel());
|
||||
makeVisible (image.getWidth(), image.getHeight(), useDropShadow);
|
||||
}
|
||||
|
||||
SplashScreen::~SplashScreen()
|
||||
SplashScreen::SplashScreen (const String& title, int width, int height, bool useDropShadow)
|
||||
: Component (title),
|
||||
clickCountToDelete (0)
|
||||
{
|
||||
makeVisible (width, height, useDropShadow);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SplashScreen::show (const String& title,
|
||||
const Image& backgroundImage_,
|
||||
const int minimumTimeToDisplayFor,
|
||||
const bool useDropShadow,
|
||||
const bool removeOnMouseClick)
|
||||
void SplashScreen::makeVisible (int w, int h, bool useDropShadow)
|
||||
{
|
||||
backgroundImage = backgroundImage_;
|
||||
clickCountToDelete = Desktop::getInstance().getMouseButtonClickCounter();
|
||||
creationTime = Time::getCurrentTime();
|
||||
|
||||
jassert (backgroundImage_.isValid());
|
||||
|
||||
if (backgroundImage_.isValid())
|
||||
{
|
||||
setOpaque (! backgroundImage_.hasAlphaChannel());
|
||||
|
||||
show (title,
|
||||
backgroundImage_.getWidth(),
|
||||
backgroundImage_.getHeight(),
|
||||
minimumTimeToDisplayFor,
|
||||
useDropShadow,
|
||||
removeOnMouseClick);
|
||||
}
|
||||
}
|
||||
|
||||
void SplashScreen::show (const String& title,
|
||||
const int width,
|
||||
const int height,
|
||||
const int minimumTimeToDisplayFor,
|
||||
const bool useDropShadow,
|
||||
const bool removeOnMouseClick)
|
||||
{
|
||||
setName (title);
|
||||
setAlwaysOnTop (true);
|
||||
setVisible (true);
|
||||
centreWithSize (width, height);
|
||||
|
||||
centreWithSize (w, h);
|
||||
addToDesktop (useDropShadow ? ComponentPeer::windowHasDropShadow : 0);
|
||||
toFront (false);
|
||||
}
|
||||
|
||||
#if JUCE_MODAL_LOOPS_PERMITTED
|
||||
MessageManager::getInstance()->runDispatchLoopUntil (300);
|
||||
#endif
|
||||
SplashScreen::~SplashScreen() {}
|
||||
|
||||
repaint();
|
||||
void SplashScreen::deleteAfterDelay (RelativeTime timeout, bool removeOnMouseClick)
|
||||
{
|
||||
// Note that this method must be safe to call from non-GUI threads
|
||||
if (! removeOnMouseClick)
|
||||
clickCountToDelete = std::numeric_limits<int>::max();
|
||||
|
||||
originalClickCounter = removeOnMouseClick
|
||||
? Desktop::getInstance().getMouseButtonClickCounter()
|
||||
: std::numeric_limits<int>::max();
|
||||
|
||||
earliestTimeToDelete = Time::getCurrentTime() + RelativeTime::milliseconds (minimumTimeToDisplayFor);
|
||||
minimumVisibleTime = timeout;
|
||||
|
||||
startTimer (50);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void SplashScreen::paint (Graphics& g)
|
||||
{
|
||||
g.setOpacity (1.0f);
|
||||
|
|
@ -98,9 +77,7 @@ void SplashScreen::paint (Graphics& g)
|
|||
|
||||
void SplashScreen::timerCallback()
|
||||
{
|
||||
if (Time::getCurrentTime() > earliestTimeToDelete
|
||||
|| Desktop::getInstance().getMouseButtonClickCounter() != originalClickCounter)
|
||||
{
|
||||
if (Time::getCurrentTime() > creationTime + minimumVisibleTime
|
||||
|| Desktop::getInstance().getMouseButtonClickCounter() > clickCountToDelete)
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,24 +29,40 @@
|
|||
//==============================================================================
|
||||
/** A component for showing a splash screen while your app starts up.
|
||||
|
||||
This will automatically position itself, and delete itself when the app has
|
||||
finished initialising (it uses the JUCEApplication::isInitialising() to detect
|
||||
this).
|
||||
This will automatically position itself, and can be told to delete itself after
|
||||
being on-screen for a minimum length of time.
|
||||
|
||||
To use it, just create one of these in your JUCEApplication::initialise() method,
|
||||
call its show() method and let the object delete itself later.
|
||||
and when your initialisation tasks have finished running, call its deleteAfterDelay()
|
||||
method to make it automatically get rid of itself.
|
||||
|
||||
Note that although you could call deleteAfterDelay() as soon as you create the
|
||||
SplashScreen object, if you've got a long initialisation procedure, you probably
|
||||
don't want the splash to time-out and disappear before the initialisation has
|
||||
finished, which is why it makes sense to not call this method until the end of
|
||||
your init tasks.
|
||||
|
||||
E.g. @code
|
||||
|
||||
void MyApp::initialise (const String& commandLine)
|
||||
{
|
||||
SplashScreen* splash = new SplashScreen();
|
||||
splash = new SplashScreen ("Welcome to my app!",
|
||||
ImageFileFormat::loadFrom (File ("/foobar/splash.jpg")),
|
||||
true);
|
||||
|
||||
splash->show ("welcome to my app",
|
||||
ImageCache::getFromFile (File ("/foobar/splash.jpg")),
|
||||
4000, false);
|
||||
// now kick off your initialisation work on some kind of thread or task, and
|
||||
launchBackgroundInitialisationThread();
|
||||
}
|
||||
|
||||
.. no need to delete the splash screen - it'll do that itself.
|
||||
void MyApp::myInitialisationWorkFinished()
|
||||
{
|
||||
// ..assuming this is some kind of callback method that is triggered when
|
||||
// your background initialisation threads have finished, and it's time to open
|
||||
// your main window, etc..
|
||||
|
||||
splash->deleteAfterDelay (RelativeTime::seconds (4), false);
|
||||
|
||||
...etc...
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
|
@ -59,84 +75,78 @@ public:
|
|||
//==============================================================================
|
||||
/** Creates a SplashScreen object.
|
||||
|
||||
After creating one of these (or your subclass of it), call one of the show()
|
||||
methods to display it.
|
||||
*/
|
||||
SplashScreen();
|
||||
When called, the constructor will position the SplashScreen in the centre of the
|
||||
display, and after the time specified, it will automatically delete itself.
|
||||
|
||||
/** Destructor. */
|
||||
~SplashScreen();
|
||||
Bear in mind that if you call this during your JUCEApplication::initialise()
|
||||
method and then block the message thread by performing some kind of task, then
|
||||
obviously neither your splash screen or any other GUI won't appear until you
|
||||
allow the message thread to resume and do its work. So if you have time-consuming
|
||||
tasks to do during startup, use a background thread for them.
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a SplashScreen object that will display an image.
|
||||
After creating one of these (or your subclass of it), you should do your app's
|
||||
initialisation work, and then call the deleteAfterDelay() method to tell this object
|
||||
to delete itself after the user has had chance to get a good look at it.
|
||||
|
||||
As soon as this is called, the SplashScreen will be displayed in the centre of the
|
||||
screen. This method will also dispatch any pending messages to make sure that when
|
||||
it returns, the splash screen has been completely drawn, and your initialisation
|
||||
code can carry on.
|
||||
If you're writing a custom splash screen class, there's another protected constructor
|
||||
that your subclass can call, which doesn't take an image.
|
||||
|
||||
@param title the name to give the component
|
||||
@param backgroundImage an image to draw on the component. The component's size
|
||||
will be set to the size of this image, and if the image is
|
||||
semi-transparent, the component will be made semi-transparent
|
||||
too. This image will be deleted (or released from the ImageCache
|
||||
if that's how it was created) by the splash screen object when
|
||||
it is itself deleted.
|
||||
@param minimumTimeToDisplayFor how long (in milliseconds) the splash screen
|
||||
should stay visible for. If the initialisation takes longer than
|
||||
this time, the splash screen will wait for it to finish before
|
||||
disappearing, but if initialisation is very quick, this lets
|
||||
you make sure that people get a good look at your splash.
|
||||
semi-transparent, the component will be made non-opaque
|
||||
@param useDropShadow if true, the window will have a drop shadow
|
||||
@param removeOnMouseClick if true, the window will go away as soon as the user clicks
|
||||
|
||||
*/
|
||||
SplashScreen (const String& title,
|
||||
const Image& backgroundImage,
|
||||
bool useDropShadow);
|
||||
|
||||
/** Destructor. */
|
||||
~SplashScreen();
|
||||
|
||||
/** Tells the component to auto-delete itself after a timeout period, or when the
|
||||
mouse is clicked.
|
||||
|
||||
You should call this after finishing your app's initialisation work.
|
||||
|
||||
Note that although you could call deleteAfterDelay() as soon as you create the
|
||||
SplashScreen object, if you've got a long initialisation procedure, you probably
|
||||
don't want the splash to time-out and disappear before your initialisation has
|
||||
finished, which is why it makes sense to not call this method and start the
|
||||
self-delete timer until you're ready.
|
||||
|
||||
It's safe to call this method from a non-GUI thread as long as there's no danger that
|
||||
the object may be being deleted at the same time.
|
||||
|
||||
@param minimumTotalTimeToDisplayFor how long the splash screen should stay visible for.
|
||||
Note that this time is measured from the construction-time of this
|
||||
object, not from the time that the deleteAfterDelay() method is
|
||||
called, so if you call this method after a long initialisation
|
||||
period, it may be deleted without any further delay.
|
||||
@param removeOnMouseClick if true, the window will be deleted as soon as the user clicks
|
||||
the mouse (anywhere)
|
||||
*/
|
||||
void show (const String& title,
|
||||
const Image& backgroundImage,
|
||||
int minimumTimeToDisplayFor,
|
||||
bool useDropShadow,
|
||||
bool removeOnMouseClick = true);
|
||||
|
||||
/** Creates a SplashScreen object with a specified size.
|
||||
|
||||
For a custom splash screen, you can use this method to display it at a certain size
|
||||
and then override the paint() method yourself to do whatever's necessary.
|
||||
|
||||
As soon as this is called, the SplashScreen will be displayed in the centre of the
|
||||
screen. This method will also dispatch any pending messages to make sure that when
|
||||
it returns, the splash screen has been completely drawn, and your initialisation
|
||||
code can carry on.
|
||||
|
||||
@param title the name to give the component
|
||||
@param width the width to use
|
||||
@param height the height to use
|
||||
@param minimumTimeToDisplayFor how long (in milliseconds) the splash screen
|
||||
should stay visible for. If the initialisation takes longer than
|
||||
this time, the splash screen will wait for it to finish before
|
||||
disappearing, but if initialisation is very quick, this lets
|
||||
you make sure that people get a good look at your splash.
|
||||
@param useDropShadow if true, the window will have a drop shadow
|
||||
@param removeOnMouseClick if true, the window will go away as soon as the user clicks
|
||||
the mouse (anywhere)
|
||||
*/
|
||||
void show (const String& title,
|
||||
int width,
|
||||
int height,
|
||||
int minimumTimeToDisplayFor,
|
||||
bool useDropShadow,
|
||||
bool removeOnMouseClick = true);
|
||||
void deleteAfterDelay (RelativeTime minimumTotalTimeToDisplayFor,
|
||||
bool removeOnMouseClick);
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** This constructor is for use by custom sub-classes that don't want to provide an image. */
|
||||
SplashScreen (const String& title, int width, int height, bool useDropShadow);
|
||||
|
||||
/** @internal */
|
||||
void paint (Graphics&) override;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
Image backgroundImage;
|
||||
Time earliestTimeToDelete;
|
||||
int originalClickCounter;
|
||||
Time creationTime;
|
||||
RelativeTime minimumVisibleTime;
|
||||
int clickCountToDelete;
|
||||
|
||||
void timerCallback() override;
|
||||
void makeVisible (int w, int h, bool shadow);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SplashScreen)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue