From a79c45596318ae510a53e98ede23d3510665f7a3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 8 Nov 2000 19:08:46 +0000 Subject: [PATCH] 1. wxCommand compilation fixes for Unix 2. added wxTextCtrl sample textctrl 3. fixed handling of wxTE_READONLY and wxTE_PASSWORD flags in wxTextCtrl git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8705 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- TODO | 1 + include/wx/cmdproc.h | 3 + include/wx/univ/textctrl.h | 12 +- samples/textctrl/Makefile.in | 21 ++ samples/textctrl/texttest.cpp | 606 ++++++++++++++++++++++++++++++++++ src/univ/files.lst | 3 + src/univ/textctrl.cpp | 78 ++++- 7 files changed, 711 insertions(+), 13 deletions(-) create mode 100644 samples/textctrl/Makefile.in create mode 100644 samples/textctrl/texttest.cpp diff --git a/TODO b/TODO index 2194eeaf0b..1104a55590 100644 --- a/TODO +++ b/TODO @@ -15,6 +15,7 @@ samples: wxTextCtrl *! display corrupted when typing text in quickly (caret problem?) +* caret leaves traces under wxGTK * scrollbars don't disappear after deleting long line ? text ctrl display pb when text is truncated * too much is refreshed when double clicking (word select) diff --git a/include/wx/cmdproc.h b/include/wx/cmdproc.h index 556585ef4d..faa053dc89 100644 --- a/include/wx/cmdproc.h +++ b/include/wx/cmdproc.h @@ -16,6 +16,9 @@ #pragma interface "cmdproc.h" #endif +#include "wx/object.h" +#include "wx/list.h" + // ---------------------------------------------------------------------------- // wxCommand: a single command capable of performing itself // ---------------------------------------------------------------------------- diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index ba6ef56cff..0df0e061e7 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -320,7 +320,14 @@ protected: // get the width of the longest line in pixels wxCoord GetMaxWidth() const; - // update the max width if the width of this line is greater than it + // force recalculation of the max line width + void RecalcMaxWidth() + { + m_widthMax = -1; + (void)GetMaxWidth(); + } + + // update the max width after the given line was modified void UpdateMaxWidth(long line); // event handlers @@ -405,6 +412,9 @@ private: // the max line length in pixels wxCoord m_widthMax; + // the index of the line which has the length of m_widthMax + long m_lineLongest; + // the object to which we delegate our undo/redo implementation wxTextCtrlCommandProcessor *m_cmdProcessor; diff --git a/samples/textctrl/Makefile.in b/samples/textctrl/Makefile.in new file mode 100644 index 0000000000..0704394ea6 --- /dev/null +++ b/samples/textctrl/Makefile.in @@ -0,0 +1,21 @@ +# +# File: makefile.unx +# Author: Julian Smart +# Created: 1998 +# Updated: +# Copyright: (c) 1998 Julian Smart +# +# "%W% %G%" +# +# Makefile for minimal example (UNIX). + +top_srcdir = @top_srcdir@/.. +top_builddir = ../.. +program_dir = samples/textctrl + +PROGRAM=texttest + +OBJECTS=$(PROGRAM).o + +include ../../src/makeprog.env + diff --git a/samples/textctrl/texttest.cpp b/samples/textctrl/texttest.cpp new file mode 100644 index 0000000000..f7b5195d1a --- /dev/null +++ b/samples/textctrl/texttest.cpp @@ -0,0 +1,606 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: texttest.cpp +// Purpose: wxTextCtrl sample +// Author: Vadim Zeitlin +// Id: $Id$ +// Copyright: (c) 2000 Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +/* + Current bugs: + + */ + +// ============================================================================ +// declarations +// ============================================================================ + +#ifdef __GNUG__ + #pragma implementation "texttest.cpp" + #pragma interface "texttest.cpp" +#endif + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx/wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers +#ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/frame.h" + #include "wx/dcclient.h" + + #include "wx/button.h" + #include "wx/checkbox.h" + #include "wx/checklst.h" + #include "wx/radiobox.h" + #include "wx/radiobut.h" + #include "wx/statbox.h" + #include "wx/stattext.h" + #include "wx/textctrl.h" +#endif + +#include "wx/sizer.h" + +#ifdef __WXUNIVERSAL__ + #include "wx/univ/theme.h" +#endif // __WXUNIVERSAL__ + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// control ids +enum +{ + TextTest_Reset = 100, + TextTest_Add, + TextTest_AddText, + TextTest_AddSeveral, + TextTest_AddMany, + TextTest_Clear, + TextTest_ClearLog, + TextTest_Change, + TextTest_ChangeText, + TextTest_Delete, + TextTest_DeleteText, + TextTest_DeleteSel, + TextTest_Password, + TextTest_Textctrl, + TextTest_Quit +}; + +// textctrl line number radiobox values +enum +{ + TextLines_Single, + TextLines_Multi +}; + +// ---------------------------------------------------------------------------- +// our classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp +class TextTestApp : public wxApp +{ +public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); +}; + +// Define a new frame type: this is going to be our main frame +class TextTestFrame : public wxFrame +{ +public: + // ctor(s) and dtor + TextTestFrame(const wxString& title); + virtual ~TextTestFrame(); + +protected: + // event handlers + void OnButtonReset(wxCommandEvent& event); + void OnButtonChange(wxCommandEvent& event); + void OnButtonDelete(wxCommandEvent& event); + void OnButtonDeleteSel(wxCommandEvent& event); + void OnButtonClear(wxCommandEvent& event); + void OnButtonClearLog(wxCommandEvent& event); + void OnButtonAdd(wxCommandEvent& event); + void OnButtonAddSeveral(wxCommandEvent& event); + void OnButtonAddMany(wxCommandEvent& event); + void OnButtonQuit(wxCommandEvent& event); + + void OnText(wxCommandEvent& event); + void OnTextEnter(wxCommandEvent& event); + + void OnCheckOrRadioBox(wxCommandEvent& event); + + void OnUpdateUIAddSeveral(wxUpdateUIEvent& event); + void OnUpdateUIClearButton(wxUpdateUIEvent& event); + void OnUpdateUIDeleteButton(wxUpdateUIEvent& event); + void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event); + + void OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event); + + void OnUpdateUIResetButton(wxUpdateUIEvent& event); + + // reset the textctrl parameters + void Reset(); + + // (re)create the textctrl + void CreateText(); + + // textctrl parameters + // ------------------ + + // single or multi line? + bool m_isSingleLine; + + // readonly or can be modified? + bool m_isReadOnly; + + // in password or normal mode? + bool m_isPassword; + + // the controls + // ------------ + + // the one to contain them all + wxPanel *m_panel; + + // the radiobox to choose between single and multi line + wxRadioBox *m_radioTextLines; + + // the checkboxes + wxCheckBox *m_chkPassword, + *m_chkReadonly; + + // the textctrl itself and the sizer it is in + wxTextCtrl *m_text; + wxSizer *m_sizerText; + + // the textctrl for logging messages + wxTextCtrl *m_textLog; + +private: + // the old log target which we replaced + wxLog *m_logTargetOld; + + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() +}; + +// ---------------------------------------------------------------------------- +// misc macros +// ---------------------------------------------------------------------------- + +IMPLEMENT_APP(TextTestApp) + +#ifdef __WXUNIVERSAL__ + WX_USE_THEME(win32); + WX_USE_THEME(gtk); +#endif // __WXUNIVERSAL__ + +// ---------------------------------------------------------------------------- +// event tables +// ---------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(TextTestFrame, wxFrame) + EVT_BUTTON(TextTest_Reset, TextTestFrame::OnButtonReset) + EVT_BUTTON(TextTest_ClearLog, TextTestFrame::OnButtonClearLog) + EVT_BUTTON(TextTest_Quit, TextTestFrame::OnButtonQuit) +#if 0 + EVT_BUTTON(TextTest_Change, TextTestFrame::OnButtonChange) + EVT_BUTTON(TextTest_Delete, TextTestFrame::OnButtonDelete) + EVT_BUTTON(TextTest_DeleteSel, TextTestFrame::OnButtonDeleteSel) + EVT_BUTTON(TextTest_Clear, TextTestFrame::OnButtonClear) + EVT_BUTTON(TextTest_Add, TextTestFrame::OnButtonAdd) + EVT_BUTTON(TextTest_AddSeveral, TextTestFrame::OnButtonAddSeveral) + EVT_BUTTON(TextTest_AddMany, TextTestFrame::OnButtonAddMany) + + EVT_TEXT_ENTER(TextTest_AddText, TextTestFrame::OnButtonAdd) + EVT_TEXT_ENTER(TextTest_DeleteText, TextTestFrame::OnButtonDelete) + + EVT_UPDATE_UI(TextTest_AddSeveral, TextTestFrame::OnUpdateUIAddSeveral) + EVT_UPDATE_UI(TextTest_Clear, TextTestFrame::OnUpdateUIClearButton) + EVT_UPDATE_UI(TextTest_DeleteText, TextTestFrame::OnUpdateUIClearButton) + EVT_UPDATE_UI(TextTest_Delete, TextTestFrame::OnUpdateUIDeleteButton) + EVT_UPDATE_UI(TextTest_Change, TextTestFrame::OnUpdateUIDeleteSelButton) + EVT_UPDATE_UI(TextTest_ChangeText, TextTestFrame::OnUpdateUIDeleteSelButton) + EVT_UPDATE_UI(TextTest_DeleteSel, TextTestFrame::OnUpdateUIDeleteSelButton) +#endif // 0 + EVT_UPDATE_UI(TextTest_Password, TextTestFrame::OnUpdateUIPasswordCheckbox) + + EVT_UPDATE_UI(TextTest_Reset, TextTestFrame::OnUpdateUIResetButton) + + EVT_TEXT(TextTest_Textctrl, TextTestFrame::OnText) + EVT_TEXT_ENTER(TextTest_Textctrl, TextTestFrame::OnTextEnter) + + EVT_CHECKBOX(-1, TextTestFrame::OnCheckOrRadioBox) + EVT_RADIOBOX(-1, TextTestFrame::OnCheckOrRadioBox) +END_EVENT_TABLE() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// app class +// ---------------------------------------------------------------------------- + +bool TextTestApp::OnInit() +{ + wxFrame *frame = new TextTestFrame(_T("wxTextCtrl sample")); + frame->Show(); + + //wxLog::AddTraceMask(_T("textctrl")); + //wxLog::AddTraceMask(_T("scrollbar")); + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// top level frame class +// ---------------------------------------------------------------------------- + +TextTestFrame::TextTestFrame(const wxString& title) + : wxFrame(NULL, -1, title, wxPoint(100, 100)) +{ + // init everything + m_radioTextLines = (wxRadioBox *)NULL; + + m_chkPassword = + m_chkReadonly = (wxCheckBox *)NULL; + + m_text = + m_textLog = (wxTextCtrl *)NULL; + m_sizerText = (wxSizer *)NULL; + + m_logTargetOld = (wxLog *)NULL; + + m_panel = new wxPanel(this, -1); + + /* + What we create here is a frame having 3 panes: the explanatory pane to + the left allowing to set the textctrl styles and recreate the control, + the pane containing the textctrl itself and the lower pane containing + the buttons which allow to add/change/delete strings to/from it. + */ + wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL), + *sizerUp = new wxBoxSizer(wxHORIZONTAL), + *sizerLeft; + + // upper left pane + static const wxString modes[] = + { + _T("single line"), + _T("multi line"), + }; + + wxStaticBox *box = new wxStaticBox(m_panel, -1, _T("&Set textctrl parameters")); + m_radioTextLines = new wxRadioBox(m_panel, -1, _T("&Number of lines:"), + wxDefaultPosition, wxDefaultSize, + WXSIZEOF(modes), modes, + 1, wxRA_SPECIFY_COLS); + + m_chkPassword = new wxCheckBox(m_panel, TextTest_Password, _T("&Password control")); + m_chkReadonly = new wxCheckBox(m_panel, -1, _T("&Read-only mode")); + + sizerLeft = new wxStaticBoxSizer(box, wxVERTICAL); + + sizerLeft->Add(m_radioTextLines, 0, wxGROW | wxALL, 5); + sizerLeft->Add(5, 5, 0, wxGROW | wxALL, 5); // spacer + sizerLeft->Add(m_chkPassword, 0, wxLEFT | wxRIGHT, 5); + sizerLeft->Add(m_chkReadonly, 0, wxLEFT | wxRIGHT, 5); + + wxButton *btn = new wxButton(m_panel, TextTest_Reset, _T("&Reset")); + sizerLeft->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 15); + + // middle pane + wxStaticBox *box2 = new wxStaticBox(m_panel, -1, _T("&Change contents")); + wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL); +#if 0 + wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(m_panel, TextTest_Add, _T("&Add this string")); + m_textAdd = new wxTextCtrl(m_panel, TextTest_AddText, _T("test item 0")); + sizerRow->Add(btn, 0, wxRIGHT, 5); + sizerRow->Add(m_textAdd, 1, wxLEFT, 5); + sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + + btn = new wxButton(m_panel, TextTest_AddSeveral, _T("&Insert a few strings")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + btn = new wxButton(m_panel, TextTest_AddMany, _T("Add &many strings")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + sizerRow = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(m_panel, TextTest_Change, _T("C&hange current")); + m_textChange = new wxTextCtrl(m_panel, TextTest_ChangeText, _T("")); + sizerRow->Add(btn, 0, wxRIGHT, 5); + sizerRow->Add(m_textChange, 1, wxLEFT, 5); + sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + + sizerRow = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(m_panel, TextTest_Delete, _T("&Delete this item")); + m_textDelete = new wxTextCtrl(m_panel, TextTest_DeleteText, _T("")); + sizerRow->Add(btn, 0, wxRIGHT, 5); + sizerRow->Add(m_textDelete, 1, wxLEFT, 5); + sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5); + + btn = new wxButton(m_panel, TextTest_DeleteSel, _T("Delete &selection")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); + + btn = new wxButton(m_panel, TextTest_Clear, _T("&Clear")); + sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5); +#endif // 0 + + // right pane + wxStaticBox *box3 = new wxStaticBox(m_panel, -1, _T("&Text:")); + m_sizerText = new wxStaticBoxSizer(box3, wxHORIZONTAL); + m_text = new wxTextCtrl(m_panel, TextTest_Textctrl, _T("Hello, world!")); + m_sizerText->Add(m_text, 1, wxALL | wxALIGN_CENTRE_VERTICAL, 5); + m_sizerText->SetMinSize(250, 0); + + // the 3 panes panes compose the upper part of the window + sizerUp->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10); + sizerUp->Add(sizerMiddle, 1, wxGROW | wxALL, 10); + sizerUp->Add(m_sizerText, 1, wxGROW | (wxALL & ~wxRIGHT), 10); + + // the lower one only has the log textctrl and a button to clear it + wxSizer *sizerDown = new wxStaticBoxSizer + ( + new wxStaticBox(m_panel, -1, _T("&Log window")), + wxVERTICAL + ); + m_textLog = new wxTextCtrl(m_panel, -1, _T(""), + wxDefaultPosition, + // wxGTK bug: creating control with default size break layout +#ifdef __WXGTK__ + wxSize(-1, 100), +#else + wxDefaultSize, +#endif + wxTE_MULTILINE); + sizerDown->Add(m_textLog, 1, wxGROW | wxALL, 5); + wxBoxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL); + btn = new wxButton(m_panel, TextTest_ClearLog, _T("Clear &log")); + sizerBtns->Add(btn); + sizerBtns->Add(10, 0); // spacer + btn = new wxButton(m_panel, TextTest_Quit, _T("E&xit")); + sizerBtns->Add(btn); + sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5); + + // put everything together + sizerTop->Add(sizerUp, 1, wxGROW | (wxALL & ~(wxTOP | wxBOTTOM)), 10); + sizerTop->Add(0, 5, 0, wxGROW); // spacer in between + sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10); + + // final initialization + Reset(); + + m_panel->SetAutoLayout(TRUE); + m_panel->SetSizer(sizerTop); + + sizerTop->Fit(this); + sizerTop->SetSizeHints(this); + + // now that everything is created we can redirect the log messages to the + // textctrl + m_logTargetOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_textLog)); +} + +TextTestFrame::~TextTestFrame() +{ + delete wxLog::SetActiveTarget(m_logTargetOld); +} + +// ---------------------------------------------------------------------------- +// operations +// ---------------------------------------------------------------------------- + +void TextTestFrame::Reset() +{ + m_radioTextLines->SetSelection(TextLines_Single); + m_chkPassword->SetValue(FALSE); + m_chkReadonly->SetValue(FALSE); +} + +void TextTestFrame::CreateText() +{ + int flags = 0; + switch ( m_radioTextLines->GetSelection() ) + { + default: + wxFAIL_MSG( _T("unexpected radio box selection") ); + + case TextLines_Single: + break; + + case TextLines_Multi: + flags |= wxTE_MULTILINE; + m_chkPassword->SetValue(FALSE); + break; + } + + if ( m_chkPassword->GetValue() ) + flags |= wxTE_PASSWORD; + if ( m_chkReadonly->GetValue() ) + flags |= wxTE_READONLY; + + wxString valueOld; + if ( m_text ) + { + valueOld = m_text->GetValue(); + + m_sizerText->Remove(m_text); + delete m_text; + } + + m_text = new wxTextCtrl(m_panel, TextTest_Textctrl, + valueOld, + wxDefaultPosition, wxDefaultSize, + flags); + m_sizerText->Add(m_text, 1, wxALL | + (flags & wxTE_MULTILINE ? wxGROW + : wxALIGN_CENTRE_VERTICAL), 5); + m_sizerText->Layout(); +} + +// ---------------------------------------------------------------------------- +// event handlers +// ---------------------------------------------------------------------------- + +void TextTestFrame::OnButtonQuit(wxCommandEvent& WXUNUSED(event)) +{ + Close(); +} + +void TextTestFrame::OnButtonReset(wxCommandEvent& WXUNUSED(event)) +{ + Reset(); + + CreateText(); +} + +void TextTestFrame::OnButtonClearLog(wxCommandEvent& event) +{ + m_textLog->Clear(); +} + +#if 0 +void TextTestFrame::OnButtonChange(wxCommandEvent& WXUNUSED(event)) +{ + wxArrayInt selections; + int count = m_text->GetSelections(selections); + wxString s = m_textChange->GetValue(); + for ( int n = 0; n < count; n++ ) + { + m_text->SetString(selections[n], s); + } +} + +void TextTestFrame::OnButtonDelete(wxCommandEvent& WXUNUSED(event)) +{ + unsigned long n; + if ( !m_textDelete->GetValue().ToULong(&n) || + (n >= (unsigned)m_text->GetCount()) ) + { + return; + } + + m_text->Delete(n); +} + +void TextTestFrame::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event)) +{ + wxArrayInt selections; + int n = m_text->GetSelections(selections); + while ( n > 0 ) + { + m_text->Delete(selections[--n]); + } +} + +void TextTestFrame::OnButtonClear(wxCommandEvent& event) +{ + m_text->Clear(); +} + +void TextTestFrame::OnButtonAdd(wxCommandEvent& event) +{ + static size_t s_item = 0; + + wxString s = m_textAdd->GetValue(); + if ( !m_textAdd->IsModified() ) + { + // update the default string + m_textAdd->SetValue(wxString::Format(_T("test item %u"), ++s_item)); + } + + m_text->Append(s); +} + +void TextTestFrame::OnButtonAddMany(wxCommandEvent& WXUNUSED(event)) +{ + // "many" means 1000 here + for ( size_t n = 0; n < 1000; n++ ) + { + m_text->Append(wxString::Format(_T("item #%u"), n)); + } +} + +void TextTestFrame::OnButtonAddSeveral(wxCommandEvent& event) +{ + wxArrayString items; + items.Add(_T("First")); + items.Add(_T("another one")); + items.Add(_T("and the last (very very very very very very very very very very long) one")); + m_text->InsertItems(items, 0); +} + +void TextTestFrame::OnUpdateUIDeleteButton(wxUpdateUIEvent& event) +{ + unsigned long n; + event.Enable(m_textDelete->GetValue().ToULong(&n) && + (n < (unsigned)m_text->GetCount())); +} + +void TextTestFrame::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event) +{ + wxArrayInt selections; + event.Enable(m_text->GetSelections(selections) != 0); +} + +void TextTestFrame::OnUpdateUIClearButton(wxUpdateUIEvent& event) +{ + event.Enable(m_text->GetCount() != 0); +} + +void TextTestFrame::OnUpdateUIAddSeveral(wxUpdateUIEvent& event) +{ + event.Enable(!(m_text->GetWindowStyle() & wxLB_SORT)); +} + +#endif // 0 + +void TextTestFrame::OnUpdateUIPasswordCheckbox(wxUpdateUIEvent& event) +{ + // can't put multiline control in password mode + event.Enable( m_radioTextLines->GetSelection() == TextLines_Single ); +} + +void TextTestFrame::OnUpdateUIResetButton(wxUpdateUIEvent& event) +{ + event.Enable( (m_radioTextLines->GetSelection() != TextLines_Single) || + m_chkReadonly->GetValue() || + m_chkPassword->GetValue() ); +} + +void TextTestFrame::OnText(wxCommandEvent& event) +{ + wxLogMessage(_T("Text ctrl value changed")); +} + +void TextTestFrame::OnTextEnter(wxCommandEvent& event) +{ + wxLogMessage(_T("Text entered: '%s'"), event.GetString().c_str()); +} + +void TextTestFrame::OnCheckOrRadioBox(wxCommandEvent& event) +{ + CreateText(); +} + diff --git a/src/univ/files.lst b/src/univ/files.lst index 387605dd02..604d46cfe4 100644 --- a/src/univ/files.lst +++ b/src/univ/files.lst @@ -3,6 +3,7 @@ UNIVOBJS = \ button.o \ checkbox.o \ checklst.o \ + cmdproc.o \ colschem.o \ control.o \ inphand.o \ @@ -15,6 +16,7 @@ UNIVOBJS = \ statbox.o \ statline.o \ stattext.o \ + textctrl.o \ theme.o \ gtk.o \ winuniv.o \ @@ -27,6 +29,7 @@ UNIVDEPS = \ button.d \ checkbox.d \ checklst.d \ + cmdproc.d \ colschem.d \ control.d \ inphand.d \ diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 3f3148b5ba..b1eaa272bf 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -259,6 +259,7 @@ void wxTextCtrl::Init() m_updateScrollbarY = FALSE; m_widthMax = -1; + m_lineLongest = 0; // init wxScrollHelper SetWindow(this); @@ -308,6 +309,8 @@ bool wxTextCtrl::Create(wxWindow *parent, SetValue(value); SetBestSize(size); + m_isEditable = !(style & wxTE_READONLY); + CreateCaret(); InitInsertionPoint(); @@ -748,11 +751,23 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text) { // (4b) delete all extra lines (note that we need to delete // them backwards because indices shift while we do it) + bool deletedLongestLine = FALSE; for ( long lineDel = lineEnd; lineDel >= line; lineDel-- ) { + if ( lineDel == m_lineLongest ) + { + // we will need to recalc the max line width + deletedLongestLine = TRUE; + } + m_lines.RemoveAt(lineDel); } + if ( deletedLongestLine ) + { + RecalcMaxWidth(); + } + // update line to exit the loop line = lineEnd + 1; } @@ -1133,6 +1148,9 @@ void wxTextCtrl::SetEditable(bool editable) { m_isEditable = editable; + // the caret (dis)appears + CreateCaret(); + // the appearance of the control might have changed Refresh(); } @@ -2146,16 +2164,36 @@ void wxTextCtrl::DoPrepareDC(wxDC& dc) void wxTextCtrl::UpdateMaxWidth(long line) { - wxCoord width; + // check if the max width changes after this line was modified + wxCoord widthMaxOld = m_widthMax, + width; GetTextExtent(GetLineText(line), &width, NULL); - // GetMaxWidth() and not m_widthMax as it might be not calculated yet - if ( width > GetMaxWidth() ) + if ( line == m_lineLongest ) { - m_widthMax = width; - - m_updateScrollbarX = TRUE; + // this line was the longest one, is it still? + if ( width > m_widthMax ) + { + m_widthMax = width; + } + else if ( width < m_widthMax ) + { + // we need to find the new longest line + RecalcMaxWidth(); + } + //else: its length didn't change, nothing to do } + else // it wasn't the longest line, but maybe it became it? + { + // GetMaxWidth() and not m_widthMax as it might be not calculated yet + if ( width > GetMaxWidth() ) + { + m_widthMax = width; + m_lineLongest = line; + } + } + + m_updateScrollbarX = m_widthMax != widthMaxOld; } wxCoord wxTextCtrl::GetMaxWidth() const @@ -2170,6 +2208,8 @@ wxCoord wxTextCtrl::GetMaxWidth() const wxClientDC dc(self); dc.SetFont(GetFont()); + self->m_widthMax = 0; + size_t count = m_lines.GetCount(); for ( size_t n = 0; n < count; n++ ) { @@ -2177,11 +2217,15 @@ wxCoord wxTextCtrl::GetMaxWidth() const dc.GetTextExtent(m_lines[n], &width, NULL); if ( width > m_widthMax ) { + // remember the width and the line which has it self->m_widthMax = width; + self->m_lineLongest = n; } } } + wxASSERT_MSG( m_widthMax != -1, _T("should have at least 1 line") ); + return m_widthMax; } @@ -2537,7 +2581,7 @@ void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate) } // extract the part of line we need to redraw - wxString textLine = GetLineText(line); + wxString textLine = GetTextToShow(GetLineText(line)); wxString text = textLine.Mid(colStart, colEnd - colStart + 1); // now deal with the selection @@ -2617,7 +2661,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer) } // show caret first time only - if ( !m_hasCaret ) + if ( !m_hasCaret && GetCaret() ) { GetCaret()->Show(); @@ -2641,7 +2685,7 @@ bool wxTextCtrl::SetFont(const wxFont& font) InitInsertionPoint(); ClearSelection(); - m_widthMax = -1; + RecalcMaxWidth(); Refresh(); @@ -2660,11 +2704,21 @@ bool wxTextCtrl::Enable(bool enable) void wxTextCtrl::CreateCaret() { - // FIXME use renderer - wxCaret *caret = new wxCaret(this, 1, GetCharHeight()); + wxCaret *caret; + + if ( IsEditable() ) + { + // FIXME use renderer + caret = new wxCaret(this, 1, GetCharHeight()); #ifndef __WXMSW__ - caret->SetBlinkTime(0); + caret->SetBlinkTime(0); #endif // __WXMSW__ + } + else + { + // read only controls don't have the caret + caret = (wxCaret *)NULL; + } // SetCaret() will delete the old caret if any SetCaret(caret);