From 4bc1afd502a0f6f31bddb349a63f41a828f54ded Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 May 2001 03:28:28 +0000 Subject: [PATCH] added text style support to wxTextCtrl for MSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10345 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/msw/textctrl.h | 6 ++ include/wx/textctrl.h | 47 ++++++++++++- samples/menu/menu.cpp | 3 - samples/text/text.cpp | 9 +++ src/common/textcmn.cpp | 25 +++++++ src/msw/menu.cpp | 4 +- src/msw/textctrl.cpp | 143 ++++++++++++++++++++++++++++++++++---- 7 files changed, 216 insertions(+), 21 deletions(-) diff --git a/include/wx/msw/textctrl.h b/include/wx/msw/textctrl.h index f233ee08f6..1f85ae5ca3 100644 --- a/include/wx/msw/textctrl.h +++ b/include/wx/msw/textctrl.h @@ -77,6 +77,12 @@ public: virtual void WriteText(const wxString& text); virtual void AppendText(const wxString& text); +#if wxUSE_RICHEDIT + // apply text attribute to the range of text (only works with richedit + // controls) + virtual bool SetStyle(long start, long end, const wxTextAttr& style); +#endif // wxUSE_RICHEDIT + // translate between the position (which is just an index in the text ctrl // considering all its contents as a single strings) and (x, y) coordinates // which represent column and line. diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index 02434c3377..eb02d1d6ef 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -15,9 +15,10 @@ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- + #ifdef __GNUG__ #pragma interface "textctrlbase.h" -#endif +#endif #include "wx/defs.h" #include "wx/control.h" // the base class @@ -48,6 +49,40 @@ class WXDLLEXPORT wxTextCtrl; WXDLLEXPORT_DATA(extern const wxChar*) wxTextCtrlNameStr; WXDLLEXPORT_DATA(extern const wxChar*) wxEmptyString; +// ---------------------------------------------------------------------------- +// wxTextAttr: a structure containing the visual attributes of a text +// ---------------------------------------------------------------------------- + +class WXDLLEXPORT wxTextAttr +{ +public: + // ctors + wxTextAttr() { } + wxTextAttr(const wxColour& colText, + const wxColour& colBack = wxNullColour, + const wxFont& font = wxNullFont) + : m_colText(colText), m_colBack(colBack), m_font(font) { } + + // setters + void SetTextColour(const wxColour& colText) { m_colText = colText; } + void SetBackgroundColour(const wxColour& colBack) { m_colBack = colBack; } + void SetFont(const wxFont& font) { m_font = font; } + + // accessors + bool HasTextColour() const { return m_colText.Ok(); } + bool HasBackgroundColour() const { return m_colBack.Ok(); } + bool HasFont() const { return m_font.Ok(); } + + const wxColour& GetTextColour() const { return m_colText; } + const wxColour& GetBackgroundColour() const { return m_colBack; } + const wxFont& GetFont() const { return m_font; } + +private: + wxColour m_colText, + m_colBack; + wxFont m_font; +}; + // ---------------------------------------------------------------------------- // wxTextCtrl: a single or multiple line text zone where user can enter and // edit text @@ -102,6 +137,13 @@ public: virtual void WriteText(const wxString& text) = 0; virtual void AppendText(const wxString& text) = 0; + // text control under some platforms supports the text styles: these + // methods allow to apply the given text style to the given selection or to + // set/get the style which will be used for all appended text + virtual bool SetStyle(long start, long end, const wxTextAttr& style); + virtual bool SetDefaultStyle(const wxTextAttr& style); + virtual const wxTextAttr& GetDefaultStyle() const; + // translate between the position (which is just an index in the text ctrl // considering all its contents as a single strings) and (x, y) coordinates // which represent column and line. @@ -161,6 +203,9 @@ protected: // SaveFile() by default wxString m_filename; + // the text style which will be used for any new text added to the control + wxTextAttr m_defaultStyle; + private: #ifndef NO_TEXT_WINDOW_STREAM #if !wxUSE_IOSTREAMH diff --git a/samples/menu/menu.cpp b/samples/menu/menu.cpp index 3bfdbc8e77..365e990140 100644 --- a/samples/menu/menu.cpp +++ b/samples/menu/menu.cpp @@ -253,13 +253,10 @@ MyFrame::MyFrame() wxMenu *fileMenu = new wxMenu; fileMenu->Append(Menu_File_Quit, "E&xit\tAlt-X", "Quit toolbar sample"); - // not supported just yet -#ifndef __WXUNIVERSAL__ wxMenuItem *itemBitmap = new wxMenuItem(fileMenu, Menu_File_Quit, "Quit with &bitmap\tAlt-Q"); itemBitmap->SetBitmap(wxBitmap(copy_xpm)); fileMenu->Append(itemBitmap); -#endif // __WXUNIVERSAL__ wxMenu *menubarMenu = new wxMenu; menubarMenu->Append(Menu_MenuBar_Append, "&Append menu\tCtrl-A", diff --git a/samples/text/text.cpp b/samples/text/text.cpp index a0472525f5..f90776ee1c 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -645,8 +645,17 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h ) "wxHSCROLL style", wxPoint(450, 10), wxSize(200, 230), wxTE_RICH | wxTE_MULTILINE | wxHSCROLL); +#ifdef __WXMSW__ + m_textrich->SetStyle(0, 10, *wxRED); + m_textrich->SetStyle(10, 20, *wxBLUE); + m_textrich->SetStyle(30, 40, + wxTextAttr(*wxGREEN, wxNullColour, *wxITALIC_FONT)); + m_textrich->SetDefaultStyle(*wxBLUE); + m_textrich->AppendText(_T("\nIs this text really in blue?")); +#else m_textrich->SetForegroundColour(wxColour(0, 255, 255)); m_textrich->SetBackgroundColour(*wxBLUE); +#endif } void MyPanel::OnSize( wxSizeEvent &event ) diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp index 0ce243a141..1686e5c91e 100644 --- a/src/common/textcmn.cpp +++ b/src/common/textcmn.cpp @@ -69,6 +69,31 @@ wxTextCtrlBase::~wxTextCtrlBase() #endif } +// ---------------------------------------------------------------------------- +// style functions - not implemented here +// ---------------------------------------------------------------------------- + +// apply styling to text range +bool wxTextCtrlBase::SetStyle(long WXUNUSED(start), long WXUNUSED(end), + const wxTextAttr& WXUNUSED(style)) +{ + // to be implemented in derived TextCtrl classes + return FALSE; +} + +// change default text attributes +bool wxTextCtrlBase::SetDefaultStyle(const wxTextAttr &style) +{ + m_defaultStyle = style; + return TRUE; +} + +// get default text attributes +const wxTextAttr& wxTextCtrlBase::GetDefaultStyle() const +{ + return m_defaultStyle; +} + // ---------------------------------------------------------------------------- // file IO functions // ---------------------------------------------------------------------------- diff --git a/src/msw/menu.cpp b/src/msw/menu.cpp index 48b0b30706..b35727d9a8 100644 --- a/src/msw/menu.cpp +++ b/src/msw/menu.cpp @@ -273,7 +273,7 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos) #endif // __WIN32__ // if we're already attached to the menubar, we must update it - if ( IsAttached() ) + if ( IsAttached() && m_menuBar->IsAttached() ) { m_menuBar->Refresh(); } @@ -326,7 +326,7 @@ wxMenuItem *wxMenu::DoRemove(wxMenuItem *item) wxLogLastError(wxT("RemoveMenu")); } - if ( IsAttached() ) + if ( IsAttached() && m_menuBar->IsAttached() ) { // otherwise, the chane won't be visible m_menuBar->Refresh(); diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index ec254dfb85..ff6b6c1c97 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -126,7 +126,6 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) #endif END_EVENT_TABLE() - // ============================================================================ // implementation // ============================================================================ @@ -450,6 +449,17 @@ void wxTextCtrl::WriteText(const wxString& value) { wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Dos); +#if wxUSE_RICHEDIT + // ensure that the new text will be in the default style + if ( IsRich() && + (m_defaultStyle.HasFont() || m_defaultStyle.HasTextColour()) ) + { + long start, end; + GetSelection(&start, &end); + SetStyle(start, end, m_defaultStyle ); + } +#endif // wxUSE_RICHEDIT + SendMessage(GetHwnd(), EM_REPLACESEL, 0, (LPARAM)valueDos.c_str()); AdjustSpaceLimit(); @@ -625,18 +635,19 @@ void wxTextCtrl::GetSelection(long* from, long* to) const *from = charRange.cpMin; *to = charRange.cpMax; - - return; } -#endif - DWORD dwStart, dwEnd; - WPARAM wParam = (WPARAM) (DWORD*) & dwStart; // receives starting position - LPARAM lParam = (LPARAM) (DWORD*) & dwEnd; // receives ending position + else +#endif // rich/!rich + { + DWORD dwStart, dwEnd; + WPARAM wParam = (WPARAM) &dwStart; // receives starting position + LPARAM lParam = (LPARAM) &dwEnd; // receives ending position - ::SendMessage(GetHwnd(), EM_GETSEL, wParam, lParam); + ::SendMessage(GetHwnd(), EM_GETSEL, wParam, lParam); - *from = dwStart; - *to = dwEnd; + *from = dwStart; + *to = dwEnd; + } } bool wxTextCtrl::IsEditable() const @@ -1151,12 +1162,13 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) event.Enable( CanRedo() ); } +// the rest of the file only deals with the rich edit controls +#if wxUSE_RICHEDIT + // ---------------------------------------------------------------------------- // colour setting for the rich edit controls // ---------------------------------------------------------------------------- -#if wxUSE_RICHEDIT - // Watcom C++ doesn't define this #ifndef SCF_ALL #define SCF_ALL 0x0004 @@ -1202,14 +1214,115 @@ bool wxTextCtrl::SetForegroundColour(const wxColour& colour) return TRUE; } -#endif // wxUSE_RICHEDIT +// ---------------------------------------------------------------------------- +// styling support for rich edit controls +// ---------------------------------------------------------------------------- + +bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) +{ + if ( !IsRich() ) + { + // can't do it with normal text control + return FALSE; + } + + // the rich text control doesn't handle setting background colour, so don't + // even try if it's the only thing we want to change + if ( !style.HasFont() && !style.HasTextColour() ) + { + // nothing to do: return TRUE if there was really nothing to doand + // FALSE fi we failed to set bg colour + return !style.HasBackgroundColour(); + } + + // order the range if needed + if ( start > end ) + { + long tmp = start; + start = end; + end = tmp; + } + + // we can only change the format of the selection, so select the range we + // want and restore the old selection later + long startOld, endOld; + GetSelection(&startOld, &endOld); + + // but do we really have to change the selection? + bool changeSel = start != startOld || end != endOld; + + if ( changeSel ) + SendMessage(GetHwnd(), EM_SETSEL, (WPARAM) start, (LPARAM) end); + + // initialize CHARFORMAT struct + CHARFORMAT cf; + wxZeroMemory(cf); + cf.cbSize = sizeof(cf); + + if ( style.HasFont() ) + { + cf.dwMask |= CFM_FACE | CFM_SIZE | CFM_CHARSET; + + // fill in data from LOGFONT but recalculate lfHeight because we need + // the real height in twips and not the negative number which + // wxFillLogFont() returns (this is correct in general and works with + // the Windows font mapper, but not here) + LOGFONT lf; + wxFillLogFont(&lf, &style.GetFont()); + cf.yHeight = 20*style.GetFont().GetPointSize(); // 1 pt = 20 twips + cf.bCharSet = lf.lfCharSet; + cf.bPitchAndFamily = lf.lfPitchAndFamily; + wxStrncpy( cf.szFaceName, lf.lfFaceName, WXSIZEOF(cf.szFaceName) ); + + // also deal with underline/italic/bold attributes + if ( lf.lfItalic ) + { + cf.dwMask |= CFM_ITALIC; + cf.dwEffects |= CFE_ITALIC; + } + + if ( lf.lfWeight == FW_BOLD ) + { + cf.dwMask |= CFM_BOLD; + cf.dwEffects |= CFE_BOLD; + } + + if ( lf.lfUnderline ) + { + cf.dwMask |= CFM_UNDERLINE; + cf.dwEffects |= CFE_UNDERLINE; + } + + // strikeout fonts are not supported by wxWindows + } + + if ( style.HasTextColour() ) + { + cf.dwMask |= CFM_COLOR; + cf.crTextColor = wxColourToRGB(style.GetTextColour()); + } + + // do format the selection + bool ok = ::SendMessage(GetHwnd(), EM_SETCHARFORMAT, + SCF_SELECTION, (LPARAM)&cf) != 0; + if ( !ok ) + { + wxLogDebug(_T("SendMessage(EM_SETCHARFORMAT, SCF_SELECTION) failed")); + } + + if ( changeSel ) + { + // restore the original selection + SendMessage(GetHwnd(), EM_SETSEL, (WPARAM)startOld, (LPARAM)endOld); + } + + return ok; +} // ---------------------------------------------------------------------------- // wxRichEditModule // ---------------------------------------------------------------------------- -#if wxUSE_RICHEDIT - bool wxRichEditModule::OnInit() { // don't do anything - we will load it when needed -- 2.45.2