From 17665a2b5c3e86e081963f9d40d45149a7aaa83e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 18 Jun 2001 17:41:33 +0000 Subject: [PATCH] implemented text styles for GTK+ git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@10610 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/textctrl.h | 9 +- include/wx/gtk1/textctrl.h | 9 +- include/wx/textctrl.h | 7 ++ samples/text/text.cpp | 20 ++-- src/gtk/textctrl.cpp | 181 ++++++++++++++++++++++++++++++------- src/gtk1/textctrl.cpp | 181 ++++++++++++++++++++++++++++++------- 6 files changed, 325 insertions(+), 82 deletions(-) diff --git a/include/wx/gtk/textctrl.h b/include/wx/gtk/textctrl.h index 727e7741f9..8c3b01786b 100644 --- a/include/wx/gtk/textctrl.h +++ b/include/wx/gtk/textctrl.h @@ -79,6 +79,10 @@ public: virtual void WriteText(const wxString& text); virtual void AppendText(const wxString& text); + // apply text attribute to the range of text (only works with richedit + // controls) + virtual bool SetStyle(long start, long end, const wxTextAttr& style); + // 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. @@ -130,8 +134,9 @@ public: void OnUpdateUndo(wxUpdateUIEvent& event); void OnUpdateRedo(wxUpdateUIEvent& event); - bool SetFont( const wxFont &font ); - bool SetBackgroundColour(const wxColour &colour); + bool SetFont(const wxFont& font); + bool SetForegroundColour(const wxColour& colour); + bool SetBackgroundColour(const wxColour& colour); GtkWidget* GetConnectWidget(); bool IsOwnGtkWindow( GdkWindow *window ); diff --git a/include/wx/gtk1/textctrl.h b/include/wx/gtk1/textctrl.h index 727e7741f9..8c3b01786b 100644 --- a/include/wx/gtk1/textctrl.h +++ b/include/wx/gtk1/textctrl.h @@ -79,6 +79,10 @@ public: virtual void WriteText(const wxString& text); virtual void AppendText(const wxString& text); + // apply text attribute to the range of text (only works with richedit + // controls) + virtual bool SetStyle(long start, long end, const wxTextAttr& style); + // 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. @@ -130,8 +134,9 @@ public: void OnUpdateUndo(wxUpdateUIEvent& event); void OnUpdateRedo(wxUpdateUIEvent& event); - bool SetFont( const wxFont &font ); - bool SetBackgroundColour(const wxColour &colour); + bool SetFont(const wxFont& font); + bool SetForegroundColour(const wxColour& colour); + bool SetBackgroundColour(const wxColour& colour); GtkWidget* GetConnectWidget(); bool IsOwnGtkWindow( GdkWindow *window ); diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index d268922f9a..647a320ce3 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -80,10 +80,17 @@ public: bool HasBackgroundColour() const { return m_colBack.Ok(); } bool HasFont() const { return m_font.Ok(); } + // setters const wxColour& GetTextColour() const { return m_colText; } const wxColour& GetBackgroundColour() const { return m_colBack; } const wxFont& GetFont() const { return m_font; } + // returns false if we have any attributes set, true otherwise + bool IsDefault() const + { + return !HasTextColour() && !HasBackgroundColour() && !HasFont(); + } + private: wxColour m_colText, m_colBack; diff --git a/samples/text/text.cpp b/samples/text/text.cpp index f90776ee1c..5db27ae1a3 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -186,7 +186,7 @@ bool MyApp::OnInit() { // Create the main frame window MyFrame *frame = new MyFrame((wxFrame *) NULL, - "Text wxWindows sample", 50, 50, 660, 420); + "Text wxWindows sample", 50, 50, 700, 420); frame->SetSizeHints( 500, 400 ); wxMenu *file_menu = new wxMenu; @@ -643,19 +643,23 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h ) "and a very very very very very " "very very very long line to test" "wxHSCROLL style", - wxPoint(450, 10), wxSize(200, 230), + wxPoint(450, 10), wxSize(230, 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(wxTextAttr()); + m_textrich->AppendText(_T("\n\nFirst 10 characters should be in red\n")); + m_textrich->AppendText(_T("Next 10 characters should be in blue\n")); + m_textrich->AppendText(_T("Next 10 characters should be normal\n")); + m_textrich->AppendText(_T("And the next 10 characters should be green and italic\n")); + m_textrich->SetDefaultStyle(wxTextAttr(*wxCYAN, *wxBLUE)); + m_textrich->AppendText(_T("This text should be cyan on blue\n")); 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 + m_textrich->AppendText(_T("And this should be in blue and the text you ") + _T("type should be in blue as well")); } void MyPanel::OnSize( wxSizeEvent &event ) diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 9904ed48a2..bde02f7faa 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -396,10 +396,18 @@ bool wxTextCtrl::Create( wxWindow *parent, /* we don't set a valid background colour, because the window manager should use a default one */ m_backgroundColour = wxColour(); - SetForegroundColour( parent->GetForegroundColour() ); + + wxColour colFg = parent->GetForegroundColour(); + SetForegroundColour( colFg ); m_cursor = wxCursor( wxCURSOR_IBEAM ); + // FIXME: is the bg colour correct here? + wxTextAttr attrDef( colFg, + wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW), + parent->GetFont() ); + SetDefaultStyle( attrDef ); + Show( TRUE ); return TRUE; @@ -481,33 +489,53 @@ void wxTextCtrl::WriteText( const wxString &text ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - if (text.IsEmpty()) return; + if ( text.empty() ) + return; - if (m_windowStyle & wxTE_MULTILINE) +#if wxUSE_UNICODE + wxWX2MBbuf buf = text.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = text; + size_t txtlen = text.length(); +#endif + + if ( m_windowStyle & wxTE_MULTILINE ) { /* this moves the cursor pos to behind the inserted text */ gint len = GTK_EDITABLE(m_text)->current_pos; -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + // if we have any special style, use it + if ( !m_defaultStyle.IsDefault() ) + { + GdkFont *font = m_defaultStyle.HasFont() + ? m_defaultStyle.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = m_defaultStyle.HasTextColour() + ? m_defaultStyle.GetTextColour().GetColor() + : NULL; + + GdkColor *colBg = m_defaultStyle.HasBackgroundColour() + ? m_defaultStyle.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); + } + else // no style + { + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); + } /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); } - else + else // single line { /* this moves the cursor pos to behind the inserted text */ gint len = GTK_EDITABLE(m_text)->current_pos; -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos += text.Len(); @@ -521,40 +549,49 @@ void wxTextCtrl::AppendText( const wxString &text ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - if (text.IsEmpty()) return; + if ( text.empty() ) + return; + +#if wxUSE_UNICODE + wxWX2MBbuf buf = text.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = text; + size_t txtlen = text.length(); +#endif if (m_windowStyle & wxTE_MULTILINE) { - bool hasSpecialAttributes = m_font.Ok() || - m_foregroundColour.Ok(); - if ( hasSpecialAttributes ) + if ( !m_defaultStyle.IsDefault() ) { - gtk_text_insert( GTK_TEXT(m_text), - m_font.GetInternalFont(), - m_foregroundColour.GetColor(), - m_backgroundColour.Ok() ? - m_backgroundColour.GetColor(): NULL, - text.mbc_str(), text.length()); + GdkFont *font = m_defaultStyle.HasFont() + ? m_defaultStyle.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = m_defaultStyle.HasTextColour() + ? m_defaultStyle.GetTextColour().GetColor() + : NULL; + GdkColor *colBg = m_defaultStyle.HasBackgroundColour() + ? m_defaultStyle.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); } - else + else // no style { /* we'll insert at the last position */ gint len = gtk_text_get_length( GTK_TEXT(m_text) ); -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); } /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); } - else + else // single line { - gtk_entry_append_text( GTK_ENTRY(m_text), text.mbc_str() ); + gtk_entry_append_text( GTK_ENTRY(m_text), txt ); } } @@ -1072,6 +1109,17 @@ void wxTextCtrl::UpdateFontIfNeeded() ChangeFontGlobally(); } +bool wxTextCtrl::SetForegroundColour(const wxColour& colour) +{ + if ( !wxControl::SetForegroundColour(colour) ) + return FALSE; + + // update default fg colour too + m_defaultStyle.SetTextColour(colour); + + return TRUE; +} + bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) { wxCHECK_MSG( m_text != NULL, FALSE, wxT("invalid text ctrl") ); @@ -1102,9 +1150,72 @@ bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) gdk_window_clear( window ); } + // change active background color too + m_defaultStyle.SetBackgroundColour( colour ); + return TRUE; } +bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr &style ) +{ + /* VERY dirty way to do that - removes the required text and re-adds it + with styling (FIXME) */ + if ( m_windowStyle & wxTE_MULTILINE ) + { + if ( style.IsDefault() ) + { + // nothing to do + return TRUE; + } + + gint l = gtk_text_get_length( GTK_TEXT(m_text) ); + + wxCHECK_MSG( start >= 0 && end <= l, FALSE, + _T("invalid range in wxTextCtrl::SetStyle") ); + + gint old_pos = gtk_editable_get_position( GTK_EDITABLE(m_text) ); + char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), start, end ); + wxString tmp(text,*wxConvCurrent); + g_free( text ); + + gtk_editable_delete_text( GTK_EDITABLE(m_text), start, end ); + gtk_editable_set_position( GTK_EDITABLE(m_text), start ); + +#if wxUSE_UNICODE + wxWX2MBbuf buf = tmp.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = tmp; + size_t txtlen = tmp.length(); +#endif + + GdkFont *font = style.HasFont() + ? style.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = style.HasTextColour() + ? style.GetTextColour().GetColor() + : NULL; + + GdkColor *colBg = style.HasBackgroundColour() + ? style.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); + + /* does not seem to help under GTK+ 1.2 !!! + gtk_editable_set_position( GTK_EDITABLE(m_text), old_pos ); */ + SetInsertionPoint( old_pos ); + return TRUE; + } + else // singe line + { + // cannot do this for GTK+'s Entry widget + return FALSE; + } +} + void wxTextCtrl::ApplyWidgetStyle() { if (m_windowStyle & wxTE_MULTILINE) diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index 9904ed48a2..bde02f7faa 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -396,10 +396,18 @@ bool wxTextCtrl::Create( wxWindow *parent, /* we don't set a valid background colour, because the window manager should use a default one */ m_backgroundColour = wxColour(); - SetForegroundColour( parent->GetForegroundColour() ); + + wxColour colFg = parent->GetForegroundColour(); + SetForegroundColour( colFg ); m_cursor = wxCursor( wxCURSOR_IBEAM ); + // FIXME: is the bg colour correct here? + wxTextAttr attrDef( colFg, + wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW), + parent->GetFont() ); + SetDefaultStyle( attrDef ); + Show( TRUE ); return TRUE; @@ -481,33 +489,53 @@ void wxTextCtrl::WriteText( const wxString &text ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - if (text.IsEmpty()) return; + if ( text.empty() ) + return; - if (m_windowStyle & wxTE_MULTILINE) +#if wxUSE_UNICODE + wxWX2MBbuf buf = text.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = text; + size_t txtlen = text.length(); +#endif + + if ( m_windowStyle & wxTE_MULTILINE ) { /* this moves the cursor pos to behind the inserted text */ gint len = GTK_EDITABLE(m_text)->current_pos; -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + // if we have any special style, use it + if ( !m_defaultStyle.IsDefault() ) + { + GdkFont *font = m_defaultStyle.HasFont() + ? m_defaultStyle.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = m_defaultStyle.HasTextColour() + ? m_defaultStyle.GetTextColour().GetColor() + : NULL; + + GdkColor *colBg = m_defaultStyle.HasBackgroundColour() + ? m_defaultStyle.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); + } + else // no style + { + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); + } /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); } - else + else // single line { /* this moves the cursor pos to behind the inserted text */ gint len = GTK_EDITABLE(m_text)->current_pos; -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos += text.Len(); @@ -521,40 +549,49 @@ void wxTextCtrl::AppendText( const wxString &text ) { wxCHECK_RET( m_text != NULL, wxT("invalid text ctrl") ); - if (text.IsEmpty()) return; + if ( text.empty() ) + return; + +#if wxUSE_UNICODE + wxWX2MBbuf buf = text.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = text; + size_t txtlen = text.length(); +#endif if (m_windowStyle & wxTE_MULTILINE) { - bool hasSpecialAttributes = m_font.Ok() || - m_foregroundColour.Ok(); - if ( hasSpecialAttributes ) + if ( !m_defaultStyle.IsDefault() ) { - gtk_text_insert( GTK_TEXT(m_text), - m_font.GetInternalFont(), - m_foregroundColour.GetColor(), - m_backgroundColour.Ok() ? - m_backgroundColour.GetColor(): NULL, - text.mbc_str(), text.length()); + GdkFont *font = m_defaultStyle.HasFont() + ? m_defaultStyle.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = m_defaultStyle.HasTextColour() + ? m_defaultStyle.GetTextColour().GetColor() + : NULL; + GdkColor *colBg = m_defaultStyle.HasBackgroundColour() + ? m_defaultStyle.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); } - else + else // no style { /* we'll insert at the last position */ gint len = gtk_text_get_length( GTK_TEXT(m_text) ); -#if wxUSE_UNICODE - wxWX2MBbuf buf = text.mbc_str(); - gtk_editable_insert_text( GTK_EDITABLE(m_text), buf, strlen(buf), &len ); -#else - gtk_editable_insert_text( GTK_EDITABLE(m_text), text, text.Length(), &len ); -#endif + gtk_editable_insert_text( GTK_EDITABLE(m_text), txt, txtlen, &len ); } /* bring editable's cursor uptodate. bug in GTK. */ GTK_EDITABLE(m_text)->current_pos = gtk_text_get_point( GTK_TEXT(m_text) ); } - else + else // single line { - gtk_entry_append_text( GTK_ENTRY(m_text), text.mbc_str() ); + gtk_entry_append_text( GTK_ENTRY(m_text), txt ); } } @@ -1072,6 +1109,17 @@ void wxTextCtrl::UpdateFontIfNeeded() ChangeFontGlobally(); } +bool wxTextCtrl::SetForegroundColour(const wxColour& colour) +{ + if ( !wxControl::SetForegroundColour(colour) ) + return FALSE; + + // update default fg colour too + m_defaultStyle.SetTextColour(colour); + + return TRUE; +} + bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) { wxCHECK_MSG( m_text != NULL, FALSE, wxT("invalid text ctrl") ); @@ -1102,9 +1150,72 @@ bool wxTextCtrl::SetBackgroundColour( const wxColour &colour ) gdk_window_clear( window ); } + // change active background color too + m_defaultStyle.SetBackgroundColour( colour ); + return TRUE; } +bool wxTextCtrl::SetStyle( long start, long end, const wxTextAttr &style ) +{ + /* VERY dirty way to do that - removes the required text and re-adds it + with styling (FIXME) */ + if ( m_windowStyle & wxTE_MULTILINE ) + { + if ( style.IsDefault() ) + { + // nothing to do + return TRUE; + } + + gint l = gtk_text_get_length( GTK_TEXT(m_text) ); + + wxCHECK_MSG( start >= 0 && end <= l, FALSE, + _T("invalid range in wxTextCtrl::SetStyle") ); + + gint old_pos = gtk_editable_get_position( GTK_EDITABLE(m_text) ); + char *text = gtk_editable_get_chars( GTK_EDITABLE(m_text), start, end ); + wxString tmp(text,*wxConvCurrent); + g_free( text ); + + gtk_editable_delete_text( GTK_EDITABLE(m_text), start, end ); + gtk_editable_set_position( GTK_EDITABLE(m_text), start ); + +#if wxUSE_UNICODE + wxWX2MBbuf buf = tmp.mbc_str(); + const char *txt = buf; + size_t txtlen = strlen(buf); +#else + const char *txt = tmp; + size_t txtlen = tmp.length(); +#endif + + GdkFont *font = style.HasFont() + ? style.GetFont().GetInternalFont() + : NULL; + + GdkColor *colFg = style.HasTextColour() + ? style.GetTextColour().GetColor() + : NULL; + + GdkColor *colBg = style.HasBackgroundColour() + ? style.GetBackgroundColour().GetColor() + : NULL; + + gtk_text_insert( GTK_TEXT(m_text), font, colFg, colBg, txt, txtlen ); + + /* does not seem to help under GTK+ 1.2 !!! + gtk_editable_set_position( GTK_EDITABLE(m_text), old_pos ); */ + SetInsertionPoint( old_pos ); + return TRUE; + } + else // singe line + { + // cannot do this for GTK+'s Entry widget + return FALSE; + } +} + void wxTextCtrl::ApplyWidgetStyle() { if (m_windowStyle & wxTE_MULTILINE) -- 2.45.2