From e6ef9ea4ed13bee3ea5d830270986eab571876e6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 18 Nov 2007 19:33:34 +0000 Subject: [PATCH] preserve custom colours between calls to wxGetColourFromUser(), also allow passing a custom wxColourData to it (modified patch 1832582) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@50056 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/function.tex | 6 ++- include/wx/cmndata.h | 20 +++++++--- include/wx/colordlg.h | 6 ++- samples/dialogs/dialogs.cpp | 41 ++++++++++++++------- samples/dialogs/dialogs.h | 2 + src/common/cmndata.cpp | 73 ++++++++++++++++++++++++++++++++++--- src/common/utilscmn.cpp | 46 +++++++++++++++++++---- 7 files changed, 162 insertions(+), 32 deletions(-) diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex index ec4bbee62b..f3e5b28410 100644 --- a/docs/latex/wx/function.tex +++ b/docs/latex/wx/function.tex @@ -2109,7 +2109,7 @@ customization. \membersection{::wxGetColourFromUser}\label{wxgetcolourfromuser} -\func{wxColour}{wxGetColourFromUser}{\param{wxWindow *}{parent}, \param{const wxColour\& }{colInit}, \param{const wxString\& }{caption = wxEmptyString}} +\func{wxColour}{wxGetColourFromUser}{\param{wxWindow *}{parent}, \param{const wxColour\& }{colInit}, \param{const wxString\& }{caption = wxEmptyString}, \param{wxColourData *}{data = \NULL}} Shows the colour selection dialog and returns the colour selected by user or invalid colour (use \helpref{wxColour:IsOk}{wxcolourisok} to test whether a colour @@ -2123,6 +2123,10 @@ is valid) if the dialog was cancelled. \docparam{caption}{If given, this will be used for the dialog caption.} +\docparam{data}{Optional object storing additional colour dialog settings, such +as custom colours. If none is provided the same settings as the last time are +used.} + \wxheading{Include files} diff --git a/include/wx/cmndata.h b/include/wx/cmndata.h index 5aa5f102f7..3ecfc402a8 100644 --- a/include/wx/cmndata.h +++ b/include/wx/cmndata.h @@ -26,11 +26,18 @@ class WXDLLIMPEXP_FWD_CORE wxPrintNativeDataBase; -class WXDLLEXPORT wxColourData: public wxObject +class WXDLLEXPORT wxColourData : public wxObject { public: + // number of custom colours we store + enum + { + NUM_CUSTOM = 16 + }; + wxColourData(); wxColourData(const wxColourData& data); + void operator=(const wxColourData&); virtual ~wxColourData(); void SetChooseFull(bool flag) { m_chooseFull = flag; } @@ -39,15 +46,18 @@ public: const wxColour& GetColour() const { return m_dataColour; } wxColour& GetColour() { return m_dataColour; } - // Array of 16 custom colours + // These functions modify colours in an internal array of NUM_CUSTOM custom + // colours void SetCustomColour(int i, const wxColour& colour); wxColour GetCustomColour(int i); - void operator=(const wxColourData& data); + // Serialize the object to a string and restore it from it + wxString ToString() const; + bool FromString(const wxString& str); -public: +public: // TODO: make these fields private wxColour m_dataColour; - wxColour m_custColours[16]; + wxColour m_custColours[NUM_CUSTOM]; bool m_chooseFull; private: diff --git a/include/wx/colordlg.h b/include/wx/colordlg.h index 8fb0ff6af2..6bff18a13b 100644 --- a/include/wx/colordlg.h +++ b/include/wx/colordlg.h @@ -30,10 +30,14 @@ #define wxColourDialog wxGenericColourDialog #endif +class WXDLLIMPEXP_FWD_CORE wxColourData; + // get the colour from user and return it wxColour WXDLLEXPORT wxGetColourFromUser(wxWindow *parent = (wxWindow *)NULL, - const wxColour& colInit = wxNullColour, const wxString& caption = wxEmptyString); + const wxColour& colInit = wxNullColour, + const wxString& caption = wxEmptyString, + wxColourData *data = NULL); #endif // wxUSE_COLOURDLG diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 18b12f67b8..6b837a6dfe 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -119,6 +119,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) #if wxUSE_COLOURDLG EVT_MENU(DIALOGS_CHOOSE_COLOUR, MyFrame::ChooseColour) + EVT_MENU(DIALOGS_GET_COLOUR, MyFrame::GetColour) #endif // wxUSE_COLOURDLG #if wxUSE_FONTDLG @@ -271,7 +272,8 @@ bool MyApp::OnInit() wxMenu *choices_menu = new wxMenu; #if wxUSE_COLOURDLG - choices_menu->Append(DIALOGS_CHOOSE_COLOUR, _T("&Choose colour")); + choices_menu->Append(DIALOGS_CHOOSE_COLOUR, _T("&Choose bg colour")); + choices_menu->Append(DIALOGS_GET_COLOUR, _T("&Choose fg colour")); #endif // wxUSE_COLOURDLG #if wxUSE_FONTDLG @@ -463,16 +465,10 @@ MyFrame::MyFrame(wxWindow *parent, #if wxUSE_COLOURDLG m_clrData.SetChooseFull(true); - for (int i = 0; i < 16; i++) + for (int i = 0; i < wxColourData::NUM_CUSTOM; i++) { - m_clrData.SetCustomColour( - i, - wxColour( - (unsigned char)(i*16), - (unsigned char)(i*16), - (unsigned char)(i*16) - ) - ); + unsigned char n = i*16; + m_clrData.SetCustomColour(i, wxColour(n, n, n)); } #endif // wxUSE_COLOURDLG @@ -482,13 +478,14 @@ MyFrame::MyFrame(wxWindow *parent, } #if wxUSE_COLOURDLG -void MyFrame::ChooseColour(wxCommandEvent& WXUNUSED(event) ) + +void MyFrame::ChooseColour(wxCommandEvent& WXUNUSED(event)) { m_clrData.SetColour(myCanvas->GetBackgroundColour()); wxColourDialog dialog(this, &m_clrData); - dialog.SetTitle(_T("Choose the background colour")); - if (dialog.ShowModal() == wxID_OK) + dialog.SetTitle(_("Please choose the background colour")); + if ( dialog.ShowModal() == wxID_OK ) { m_clrData = dialog.GetColourData(); myCanvas->SetBackgroundColour(m_clrData.GetColour()); @@ -496,8 +493,26 @@ void MyFrame::ChooseColour(wxCommandEvent& WXUNUSED(event) ) myCanvas->Refresh(); } } + +void MyFrame::GetColour(wxCommandEvent& WXUNUSED(event)) +{ + wxColour clr = wxGetColourFromUser + ( + this, + wxGetApp().m_canvasTextColour, + "Please choose the foreground colour" + ); + if ( clr.IsOk() ) + { + wxGetApp().m_canvasTextColour = clr; + myCanvas->Refresh(); + } + //else: dialog cancelled by user +} + #endif // wxUSE_COLOURDLG + #if USE_COLOURDLG_GENERIC void MyFrame::ChooseColourGeneric(wxCommandEvent& WXUNUSED(event)) { diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h index 62ff683de9..b371fbd106 100644 --- a/samples/dialogs/dialogs.h +++ b/samples/dialogs/dialogs.h @@ -211,6 +211,7 @@ public: #if wxUSE_COLOURDLG void ChooseColour(wxCommandEvent& event); + void GetColour(wxCommandEvent& event); #endif // wxUSE_COLOURDLG #if wxUSE_FONTDLG @@ -341,6 +342,7 @@ public: enum { DIALOGS_CHOOSE_COLOUR = wxID_HIGHEST, + DIALOGS_GET_COLOUR, DIALOGS_CHOOSE_COLOUR_GENERIC, DIALOGS_CHOOSE_FONT, DIALOGS_CHOOSE_FONT_GENERIC, diff --git a/src/common/cmndata.cpp b/src/common/cmndata.cpp index f50447a3f5..40e6073529 100644 --- a/src/common/cmndata.cpp +++ b/src/common/cmndata.cpp @@ -89,14 +89,14 @@ wxColourData::~wxColourData() void wxColourData::SetCustomColour(int i, const wxColour& colour) { - wxCHECK_RET( (i >= 0 && i < 16), _T("custom colour index out of range") ); + wxCHECK_RET( (i >= 0 && i < WXSIZEOF(m_custColours)), _T("custom colour index out of range") ); m_custColours[i] = colour; } wxColour wxColourData::GetCustomColour(int i) { - wxCHECK_MSG( (i >= 0 && i < 16), wxColour(0,0,0), + wxCHECK_MSG( (i >= 0 && i < WXSIZEOF(m_custColours)), wxColour(0,0,0), _T("custom colour index out of range") ); return m_custColours[i]; @@ -104,14 +104,77 @@ wxColour wxColourData::GetCustomColour(int i) void wxColourData::operator=(const wxColourData& data) { - int i; - for (i = 0; i < 16; i++) + for (int i = 0; i < WXSIZEOF(m_custColours); i++) m_custColours[i] = data.m_custColours[i]; - m_dataColour = (wxColour&)data.m_dataColour; + m_dataColour = data.m_dataColour; m_chooseFull = data.m_chooseFull; } +// ---------------------------------------------------------------------------- +// [de]serialization +// ---------------------------------------------------------------------------- + +// separator used between different fields +static const char wxCOL_DATA_SEP = ','; + +wxString wxColourData::ToString() const +{ + wxString str(m_chooseFull ? '1' : '0'); + + for ( int i = 0; i < WXSIZEOF(m_custColours); i++ ) + { + str += wxCOL_DATA_SEP; + + const wxColour& clr = m_custColours[i]; + if ( clr.IsOk() ) + str += clr.GetAsString(wxC2S_HTML_SYNTAX); + } + + return str; +} + +bool wxColourData::FromString(const wxString& str) +{ + wxString token; + int n = -1; // index of the field, -1 corresponds to m_chooseFull + for ( wxString::const_iterator i = str.begin(); i != str.end(); ++i ) + { + if ( *i == wxCOL_DATA_SEP ) + { + if ( n == -1 ) + { + if ( token == '0' ) + m_chooseFull = false; + else if ( token == '1' ) + m_chooseFull = true; + else // only '0' and '1' are used in ToString() + return false; + } + else // custom colour + { + if ( n == WXSIZEOF(m_custColours) ) + return false; // too many custom colours + + // empty strings are used by ToString() for colours not used + if ( token.empty() ) + m_custColours[n] = wxNullColour; + else if ( !m_custColours[n].Set(token) ) + return false; // invalid colour string + } + + token.clear(); + n++; + } + else // continuation of the current field + { + token += *i; + } + } + + return true; +} + // ---------------------------------------------------------------------------- // Font data // ---------------------------------------------------------------------------- diff --git a/src/common/utilscmn.cpp b/src/common/utilscmn.cpp index 00436e7679..4ba9c856e1 100644 --- a/src/common/utilscmn.cpp +++ b/src/common/utilscmn.cpp @@ -1419,24 +1419,56 @@ wxString wxGetPasswordFromUser(const wxString& message, #if wxUSE_COLOURDLG -wxColour wxGetColourFromUser(wxWindow *parent, const wxColour& colInit, const wxString& caption) +wxColour wxGetColourFromUser(wxWindow *parent, + const wxColour& colInit, + const wxString& caption, + wxColourData *ptrData) { + // contains serialized representation of wxColourData used the last time + // the dialog was shown: we want to reuse it the next time in order to show + // the same custom colours to the user (and we can't just have static + // wxColourData itself because it's a GUI object and so should be destroyed + // before GUI shutdown and doing it during static cleanup is too late) + static wxString s_strColourData; + wxColourData data; - data.SetChooseFull(true); - if ( colInit.Ok() ) + if ( !ptrData ) { - data.SetColour((wxColour &)colInit); // const_cast + ptrData = &data; + if ( !s_strColourData.empty() ) + { + if ( !data.FromString(s_strColourData) ) + { + wxFAIL_MSG( "bug in wxColourData::FromString()?" ); + } + +#ifdef __WXMSW__ + // we don't get back the "choose full" flag value from the native + // dialog and so we can't preserve it between runs, so we decide to + // always use it as it seems better than not using it (user can + // just ignore the extra controls in the dialog but having to click + // a button each time to show them would be very annoying + data.SetChooseFull(true); +#endif // __WXMSW__ + } + } + + if ( colInit.IsOk() ) + { + ptrData->SetColour(colInit); } wxColour colRet; - wxColourDialog dialog(parent, &data); + wxColourDialog dialog(parent, ptrData); if (!caption.empty()) dialog.SetTitle(caption); if ( dialog.ShowModal() == wxID_OK ) { - colRet = dialog.GetColourData().GetColour(); + *ptrData = dialog.GetColourData(); + colRet = ptrData->GetColour(); + s_strColourData = ptrData->ToString(); } - //else: leave it invalid + //else: leave colRet invalid return colRet; } -- 2.45.2