diff --git a/docs/changes.txt b/docs/changes.txt
index 78bdab73ce..5cc7000284 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -56,6 +56,7 @@ Unix:
All (GUI):
- Allow requesting modern (3.x+) OpenGL version in wxGLCanvas (Fabio Arnold).
+- Allow customizing window shown by wxBusyInfo.
- XRC handler for wxAuiToolBar added (Kinaou Hervé, David Hart).
- Add wxFD_NO_FOLLOW style for wxFileDialog (Luca Bacci).
- Add support for embedding bitmaps in generated SVG in wxSVGFileDC (iwbnwif).
diff --git a/include/wx/busyinfo.h b/include/wx/busyinfo.h
index 600c86c634..7de6f22fef 100644
--- a/include/wx/busyinfo.h
+++ b/include/wx/busyinfo.h
@@ -13,6 +13,59 @@
#if wxUSE_BUSYINFO
+// This class is used to pass all the various parameters to wxBusyInfo ctor.
+// According to the usual naming conventions (see wxAboutDialogInfo,
+// wxFontInfo, ...) it would be called wxBusyInfoInfo, but this would have been
+// rather strange, so we call it wxBusyInfoFlags instead.
+//
+// Methods are mostly self-explanatory except for the difference between "Text"
+// and "Label": the former can contain markup, while the latter is just plain
+// string which is not parsed in any way.
+class wxBusyInfoFlags
+{
+public:
+ wxBusyInfoFlags()
+ {
+ m_parent = NULL;
+ m_alpha = wxALPHA_OPAQUE;
+ }
+
+ wxBusyInfoFlags& Parent(wxWindow* parent)
+ { m_parent = parent; return *this; }
+
+ wxBusyInfoFlags& Icon(const wxIcon& icon)
+ { m_icon = icon; return *this; }
+ wxBusyInfoFlags& Title(const wxString& title)
+ { m_title = title; return *this; }
+ wxBusyInfoFlags& Text(const wxString& text)
+ { m_text = text; return *this; }
+ wxBusyInfoFlags& Label(const wxString& label)
+ { m_label = label; return *this; }
+
+ wxBusyInfoFlags& Foreground(const wxColour& foreground)
+ { m_foreground = foreground; return *this; }
+ wxBusyInfoFlags& Background(const wxColour& background)
+ { m_background = background; return *this; }
+
+ wxBusyInfoFlags& Transparency(wxByte alpha)
+ { m_alpha = alpha; return *this; }
+
+private:
+ wxWindow* m_parent;
+
+ wxIcon m_icon;
+ wxString m_title,
+ m_text,
+ m_label;
+
+ wxColour m_foreground,
+ m_background;
+
+ wxByte m_alpha;
+
+ friend class wxBusyInfo;
+};
+
#include "wx/generic/busyinfo.h"
#endif // wxUSE_BUSYINFO
diff --git a/include/wx/generic/busyinfo.h b/include/wx/generic/busyinfo.h
index 7f56edb26d..d910668c86 100644
--- a/include/wx/generic/busyinfo.h
+++ b/include/wx/generic/busyinfo.h
@@ -27,11 +27,21 @@ class WXDLLIMPEXP_FWD_CORE wxWindow;
class WXDLLIMPEXP_CORE wxBusyInfo : public wxObject
{
public:
- wxBusyInfo(const wxString& message, wxWindow *parent = NULL);
+ wxBusyInfo(const wxBusyInfoFlags& flags)
+ {
+ Init(flags);
+ }
+
+ wxBusyInfo(const wxString& message, wxWindow *parent = NULL)
+ {
+ Init(wxBusyInfoFlags().Parent(parent).Label(message));
+ }
virtual ~wxBusyInfo();
private:
+ void Init(const wxBusyInfoFlags& flags);
+
wxFrame *m_InfoFrame;
wxDECLARE_NO_COPY_CLASS(wxBusyInfo);
diff --git a/interface/wx/busyinfo.h b/interface/wx/busyinfo.h
index 0953d49f9d..59cd50d5fc 100644
--- a/interface/wx/busyinfo.h
+++ b/interface/wx/busyinfo.h
@@ -9,8 +9,13 @@
@class wxBusyInfo
This class makes it easy to tell your user that the program is temporarily busy.
- Just create a wxBusyInfo object on the stack, and within the current scope,
- a message window will be shown.
+
+ Normally the main thread should always return to the main loop to continue
+ dispatching events as quickly as possible, hence this class shouldn't be
+ needed. However if the main thread does need to block, this class provides
+ a simple way to at least show this to the user: just create a wxBusyInfo
+ object on the stack, and within the current scope, a message window will be
+ shown.
For example:
@@ -26,6 +31,28 @@
It works by creating a window in the constructor, and deleting it
in the destructor.
+ This window is rather plain by default but can be customized by passing
+ wxBusyInfo constructor an object of wxBusyInfoFlags class instead of a
+ simple message. Here is an example from the @ref page_samples_dialogs:
+ @code
+ wxBusyInfo info
+ (
+ wxBusyInfoFlags()
+ .Parent(this)
+ .Icon(wxArtProvider::GetIcon(wxART_PRINT,
+ wxART_OTHER, wxSize(128, 128)))
+ .Title("Printing your document")
+ .Text("Please wait...")
+ .Foreground(*wxWHITE)
+ .Background(*wxBLACK)
+ .Transparency(4*wxALPHA_OPAQUE/5)
+ );
+ @endcode
+ showing that separate title and text can be set, and that simple markup
+ (@ref wxControl::SetLabelMarkup()) can be used in them, and that it's also
+ possible to add an icon and customize the colours and transparency of the
+ window.
+
You may also want to call wxTheApp->Yield() to refresh the window
periodically (in case it had been obscured by other windows, for
example) like this:
@@ -57,7 +84,25 @@ class wxBusyInfo
{
public:
/**
- Constructs a busy info window as child of @a parent and displays @e msg in it.
+ General constructor.
+
+ This constructor allows to specify all supported attributes by calling
+ the appropriate methods on wxBusyInfoFlags object passed to it as
+ parameter. All of them are optional but usually at least the message
+ should be specified.
+
+ @since 3.1.0
+ */
+ wxBusyInfo(const wxBusyInfoFlags& flags);
+
+ /**
+ Simple constructor specifying only the message and the parent.
+
+ This constructs a busy info window as child of @a parent and displays
+ @a msg in it. It is exactly equivalent to using
+ @code
+ wxBusyInfo(wxBusyInfoFlags().Parent(parent).Label(message))
+ @endcode
@note If @a parent is not @NULL you must ensure that it is not
closed while the busy info is shown.
@@ -70,3 +115,86 @@ public:
virtual ~wxBusyInfo();
};
+/**
+ Parameters for wxBusyInfo.
+
+ This class exists only in order to make passing attributes to wxBusyInfo
+ constructor easier and the code doing it more readable.
+
+ All methods of this class return the reference to the object on which they
+ are called, making it possible to chain them together, e.g. typically you
+ would just create a temporary wxBusyInfoFlags object and then call the
+ methods corresponding to the attributes you want to set, before finally
+ passing the result to wxBusyInfo constructor, e.g.:
+ @code
+ wxBusyInfo info
+ (
+ wxBusyInfoFlags()
+ .Parent(window)
+ .Icon(icon)
+ .Title("Some text")
+ .Text("Some more text")
+ .Foreground(wxColour(...))
+ .Background(wxColour(...))
+ );
+ @endcode
+
+ @since 3.1.0
+ */
+class wxBusyInfoFlags
+{
+public:
+ /**
+ Default constructor initializes all attributes to default values.
+
+ Call the other methods to really fill in the object.
+ */
+ wxBusyInfoFlags();
+
+ /// Sets the parent for wxBusyInfo.
+ wxBusyInfoFlags& Parent(wxWindow* parent);
+
+ /// Sets the icon to show in wxBusyInfo.
+ wxBusyInfoFlags& Icon(const wxIcon& icon);
+
+ /**
+ Sets the title, shown prominently in wxBusyInfo window.
+
+ The @a title string may contain markup as described in
+ wxControl::SetLabelMarkup().
+ */
+ wxBusyInfoFlags& Title(const wxString& title);
+
+ /**
+ Sets the more detailed text, shown under the title, if any.
+
+ The @a text string may contain markup as described in
+ wxControl::SetLabelMarkup().
+ */
+ wxBusyInfoFlags& Text(const wxString& text);
+
+ /**
+ Same as Text() but doesn't interpret the string as containing markup.
+
+ This method should be used if the text shown in wxBusyInfo comes from
+ external source and so may contain characters having special meaning in
+ simple markup, e.g. '<'.
+ */
+ wxBusyInfoFlags& Label(const wxString& label);
+
+ /// Sets the foreground colour of the title and text strings.
+ wxBusyInfoFlags& Foreground(const wxColour& foreground);
+
+ /// Sets the background colour of wxBusyInfo window.
+ wxBusyInfoFlags& Background(const wxColour& background);
+
+ /**
+ Sets the transparency of wxBusyInfo window.
+
+ @param alpha Value in wxALPHA_TRANSPARENT (0) to wxALPHA_OPAQUE (255)
+ range.
+
+ @see wxTopLevelWindow::SetTransparent()
+ */
+ wxBusyInfoFlags& Transparency(wxByte alpha);
+};
diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp
index 7804fc425c..0022327b54 100644
--- a/samples/dialogs/dialogs.cpp
+++ b/samples/dialogs/dialogs.cpp
@@ -233,6 +233,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
#if wxUSE_BUSYINFO
EVT_MENU(DIALOGS_BUSYINFO, MyFrame::ShowBusyInfo)
+ EVT_MENU(DIALOGS_BUSYINFO_RICH, MyFrame::ShowRichBusyInfo)
#endif // wxUSE_BUSYINFO
#if wxUSE_FINDREPLDLG
@@ -474,6 +475,7 @@ bool MyApp::OnInit()
#if wxUSE_BUSYINFO
info_menu->Append(DIALOGS_BUSYINFO, wxT("&Busy info dialog\tCtrl-B"));
+ info_menu->Append(DIALOGS_BUSYINFO_RICH, wxT("&Rich busy info dialog\tShift-Ctrl-B"));
#endif // wxUSE_BUSYINFO
#if wxUSE_LOG_DIALOG
@@ -2422,7 +2424,28 @@ void MyFrame::ShowBusyInfo(wxCommandEvent& WXUNUSED(event))
}
wxSleep(2);
- //wxWakeUpIdle();
+}
+
+void MyFrame::ShowRichBusyInfo(wxCommandEvent& WXUNUSED(event))
+{
+ wxWindowDisabler disableAll;
+
+ // This is just an example and not an encouragement for printing
+ // synchronously from the main thread.
+ wxBusyInfo info
+ (
+ wxBusyInfoFlags()
+ .Parent(this)
+ .Icon(wxArtProvider::GetIcon(wxART_PRINT,
+ wxART_OTHER, wxSize(128, 128)))
+ .Title("Printing your document")
+ .Text("Please wait...")
+ .Foreground(*wxWHITE)
+ .Background(*wxBLACK)
+ .Transparency(4*wxALPHA_OPAQUE/5)
+ );
+
+ wxSleep(5);
}
#endif // wxUSE_BUSYINFO
diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h
index 71f022161d..06d6b46ca2 100644
--- a/samples/dialogs/dialogs.h
+++ b/samples/dialogs/dialogs.h
@@ -441,6 +441,7 @@ public:
#if wxUSE_BUSYINFO
void ShowBusyInfo(wxCommandEvent& event);
+ void ShowRichBusyInfo(wxCommandEvent& event);
#endif // wxUSE_BUSYINFO
#if wxUSE_FINDREPLDLG
@@ -577,6 +578,7 @@ enum
DIALOGS_ABOUTDLG_FULL,
DIALOGS_ABOUTDLG_CUSTOM,
DIALOGS_BUSYINFO,
+ DIALOGS_BUSYINFO_RICH,
DIALOGS_FIND,
DIALOGS_REPLACE,
DIALOGS_REQUEST,
diff --git a/src/generic/busyinfo.cpp b/src/generic/busyinfo.cpp
index 3e9e728875..ec9798cd01 100644
--- a/src/generic/busyinfo.cpp
+++ b/src/generic/busyinfo.cpp
@@ -16,57 +16,106 @@
// for all others, include the necessary headers
#ifndef WX_PRECOMP
- #include "wx/frame.h"
+ #include "wx/m_InfoFrame.h"
#include "wx/stattext.h"
#include "wx/panel.h"
+ #include "wx/sizer.h"
+ #include "wx/statbmp.h"
#include "wx/utils.h"
#endif
#include "wx/busyinfo.h"
-#include "wx/generic/stattextg.h"
-class WXDLLEXPORT wxInfoFrame : public wxFrame
-{
-public:
- wxInfoFrame(wxWindow *parent, const wxString& message);
+// wxStaticText currently supports markup only in wxGTK and wxOSX/Cocoa, so use
+// the generic version for markup support in the other ports.
+#if wxUSE_MARKUP && !(defined(__WXGTK__) || defined(__WXOSX_COCOA__))
+ #include "wx/generic/stattextg.h"
-private:
- wxDECLARE_NO_COPY_CLASS(wxInfoFrame);
-};
-
-
-wxInfoFrame::wxInfoFrame(wxWindow *parent, const wxString& message)
- : wxFrame(parent, wxID_ANY, wxString(),
- wxDefaultPosition, wxDefaultSize,
- wxSIMPLE_BORDER | wxFRAME_TOOL_WINDOW | wxSTAY_ON_TOP)
-{
- wxPanel *panel = new wxPanel( this );
-#ifdef __WXGTK__
- wxGenericStaticText *text = new wxGenericStaticText(panel, wxID_ANY, message);
+ #define wxStaticTextWithMarkupSupport wxGenericStaticText
#else
- wxStaticText *text = new wxStaticText(panel, wxID_ANY, message);
+ #define wxStaticTextWithMarkupSupport wxStaticText
#endif
- panel->SetCursor(*wxHOURGLASS_CURSOR);
- text->SetCursor(*wxHOURGLASS_CURSOR);
-
- // make the frame of at least the standard size (400*80) but big enough
- // for the text we show
- wxSize size = text->GetBestSize();
- size.IncBy(ConvertDialogToPixels(wxPoint(10, 10)));
- size.IncTo(wxSize(400, 80));
- SetClientSize(size);
-
- // need to size the panel correctly first so that text->Centre() works
- panel->SetSize(GetClientSize());
-
- text->Centre(wxBOTH);
- Centre(wxBOTH);
-}
-
-wxBusyInfo::wxBusyInfo(const wxString& message, wxWindow *parent)
+void wxBusyInfo::Init(const wxBusyInfoFlags& flags)
{
- m_InfoFrame = new wxInfoFrame(parent, message);
+ m_InfoFrame = new wxFrame(flags.m_parent, wxID_ANY, wxString(),
+ wxDefaultPosition, wxDefaultSize,
+ wxSIMPLE_BORDER |
+ wxFRAME_TOOL_WINDOW |
+ wxSTAY_ON_TOP);
+
+ wxPanel* const panel = new wxPanel(m_InfoFrame);
+
+ wxBoxSizer* const sizer = new wxBoxSizer(wxVERTICAL);
+
+ const wxSizerFlags sizerFlags = wxSizerFlags().DoubleBorder().Centre();
+
+ if ( flags.m_icon.IsOk() )
+ {
+ sizer->Add(new wxStaticBitmap(panel, wxID_ANY, flags.m_icon), sizerFlags);
+ }
+
+ wxControl* title;
+ if ( !flags.m_title.empty() )
+ {
+ title = new wxStaticTextWithMarkupSupport(panel, wxID_ANY, wxString());
+ title->SetFont(title->GetFont().Scaled(2));
+ title->SetLabelMarkup(flags.m_title);
+
+ sizer->Add(title, sizerFlags);
+ }
+ else
+ {
+ title = NULL;
+ }
+
+ // Vertically center the text in the window.
+ sizer->AddStretchSpacer();
+
+ wxControl* text;
+#if wxUSE_MARKUP
+ if ( !flags.m_text.empty() )
+ {
+ text = new wxStaticTextWithMarkupSupport(panel, wxID_ANY, wxString());
+ text->SetLabelMarkup(flags.m_text);
+ }
+ else
+#endif // wxUSE_MARKUP
+ {
+ text = new wxStaticText(panel, wxID_ANY, wxString());
+ text->SetLabelText(flags.m_label);
+ }
+
+ sizer->Add(text, sizerFlags);
+
+ sizer->AddStretchSpacer();
+
+ panel->SetSizer(sizer);
+
+ if ( flags.m_foreground.IsOk() )
+ {
+ if ( title )
+ title->SetForegroundColour(flags.m_foreground);
+ text->SetForegroundColour(flags.m_foreground);
+ }
+
+ if ( flags.m_background.IsOk() )
+ panel->SetBackgroundColour(flags.m_background);
+
+ if ( flags.m_alpha != wxALPHA_OPAQUE )
+ m_InfoFrame->SetTransparent(flags.m_alpha);
+
+ m_InfoFrame->SetCursor(*wxHOURGLASS_CURSOR);
+
+ // We need to accommodate our contents, but also impose some minimal size
+ // to make the busy info frame more noticeable.
+ wxSize size = panel->GetBestSize();
+ size.IncTo(wxSize(400, 80));
+
+ m_InfoFrame->SetClientSize(size);
+ m_InfoFrame->Layout();
+
+ m_InfoFrame->Centre(wxBOTH);
m_InfoFrame->Show(true);
m_InfoFrame->Refresh();
m_InfoFrame->Update();