X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/668e4f17be1fdeab2d08fc6d472d585447894aa7..c50f1fb9226d9260454ccb9c8a67d0be23c2827f:/samples/richedit/wxlwindow.cpp diff --git a/samples/richedit/wxlwindow.cpp b/samples/richedit/wxlwindow.cpp index 07e6e01cde..63ce2369cf 100644 --- a/samples/richedit/wxlwindow.cpp +++ b/samples/richedit/wxlwindow.cpp @@ -18,7 +18,7 @@ # pragma implementation "wxlwindow.h" #endif -#include "wx/wxprec.h" +#include #ifdef __BORLANDC__ # pragma hdrstop @@ -118,15 +118,6 @@ static bool IsDirectionKey(long keyCode); // implementation // ============================================================================ -/* LEAVE IT HERE UNTIL WXGTK WORKS AGAIN!!! */ -#ifdef __WXGTK__ -/// allows me to compare to wxPoints -static bool operator != (wxPoint const &p1, wxPoint const &p2) -{ - return p1.x != p2.x || p1.y != p2.y; -} -#endif // __WXGTK__ - #ifndef wxWANTS_CHARS #define wxWANTS_CHARS 0 #endif @@ -153,21 +144,10 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent) m_bitmap = new wxBitmap(4,4); m_bitmapSize = wxPoint(4,4); m_llist = new wxLayoutList(); - m_BGbitmap = NULL; m_ScrollToCursor = false; SetWrapMargin(0); - // initially the list is empty, so why would we need the scrollbars? -#if 0 - wxPoint max = m_llist->GetSize(); - SetScrollbars(X_SCROLL_PAGE, Y_SCROLL_PAGE, - max.x / X_SCROLL_PAGE + 1, max.y / Y_SCROLL_PAGE + 1); - EnableScrolling(true, true); - m_maxx = max.x + X_SCROLL_PAGE; - m_maxy = max.y + Y_SCROLL_PAGE; -#endif // 0 - // no scrollbars initially m_hasHScrollbar = m_hasVScrollbar = false; @@ -179,13 +159,16 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent) wxCaret *caret = new wxCaret(this, 2, 20); SetCaret(caret); m_llist->SetCaret(caret); - caret->Show(); #endif // WXLAYOUT_USE_CARET + m_HaveFocus = FALSE; m_HandCursor = FALSE; m_CursorVisibility = -1; SetCursor(wxCURSOR_IBEAM); SetDirty(); + + // at least under Windows, this should be the default behaviour + m_AutoDeleteSelection = TRUE; } wxLayoutWindow::~wxLayoutWindow() @@ -208,10 +191,19 @@ wxLayoutWindow::Clear(int family, { GetLayoutList()->Clear(family,size,style,weight,underline,fg,bg); SetBackgroundColour(GetLayoutList()->GetDefaultStyleInfo().GetBGColour()); + wxScrolledWindow::Clear(); ResizeScrollbars(true); SetDirty(); SetModified(false); - wxScrolledWindow::Clear(); + + if ( m_Editable ) + m_CursorVisibility = 1; + +#ifdef WXLAYOUT_USE_CARET + if ( m_CursorVisibility == 1 ) + GetCaret()->Show(); +#endif // WXLAYOUT_USE_CARET + DoPaint((wxRect *)NULL); } @@ -220,7 +212,7 @@ void wxLayoutWindow::Refresh(bool eraseBackground, const wxRect *rect) wxScrolledWindow::Refresh(eraseBackground, rect); ResizeScrollbars(); - ScrollToCursor(); +//FIXME is this needed? It causes problems... ScrollToCursor(); } void @@ -228,9 +220,13 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) { wxClientDC dc( this ); PrepareDC( dc ); +#ifdef __WXMSW__ if ( eventId != WXLOWIN_MENU_MOUSEMOVE ) +#endif { - // moving the mouse in a window shouldn't give it the focus! + // moving the mouse in a window shouldn't give it the focus! + // Oh yes! wxGTK's focus handling is so broken, that this is the + // only sensible way to go. SetFocus(); } @@ -258,37 +254,53 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) switch ( eventId ) { case WXLOWIN_MENU_MOUSEMOVE: - // found is only true if we are really over an object, not just - // behind it - if(found && u && ! m_Selecting) { - if(!m_HandCursor) - SetCursor(wxCURSOR_HAND); - m_HandCursor = TRUE; - if(m_StatusBar && m_StatusFieldLabel != -1) + // this variables is used to only erase the message in the status + // bar if we had put it there previously - otherwise empting status + // bar might be undesirable + static bool s_hasPutMessageInStatusBar = false; + + // found is only true if we are really over an object, not just + // behind it + if(found && u && ! m_Selecting) { - const wxString &label = u->GetLabel(); - if(label.Length()) - m_StatusBar->SetStatusText(label, - m_StatusFieldLabel); + if(!m_HandCursor) + SetCursor(wxCURSOR_HAND); + m_HandCursor = TRUE; + if(m_StatusBar && m_StatusFieldLabel != -1) + { + const wxString &label = u->GetLabel(); + if(label.Length()) + { + m_StatusBar->SetStatusText(label, + m_StatusFieldLabel); + s_hasPutMessageInStatusBar = true; + } + } + } + else + { + if(m_HandCursor) + SetCursor(wxCURSOR_IBEAM); + m_HandCursor = FALSE; + if( m_StatusBar && m_StatusFieldLabel != -1 && + s_hasPutMessageInStatusBar ) + { + m_StatusBar->SetStatusText("", m_StatusFieldLabel); + } } - } - else - { - if(m_HandCursor) - SetCursor(wxCURSOR_IBEAM); - m_HandCursor = FALSE; - if(m_StatusBar && m_StatusFieldLabel != -1) - m_StatusBar->SetStatusText("", m_StatusFieldLabel); } // selecting? if ( event.LeftIsDown() ) { - wxASSERT_MSG( m_Selecting, "should be set in OnMouseLeftDown" ); - - m_llist->ContinueSelection(cursorPos, m_ClickPosition); - DoPaint(); // TODO: we don't have to redraw everything! + // m_Selecting might not be set if the button got pressed + // outside this window, so check for it: + if( m_Selecting ) + { + m_llist->ContinueSelection(cursorPos, m_ClickPosition); + DoPaint(); // TODO: we don't have to redraw everything! + } } if ( u ) @@ -301,21 +313,22 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) case WXLOWIN_MENU_LDOWN: { // always move cursor to mouse click: - if ( obj ) +// if ( obj ) { // we have found the real position m_llist->MoveCursorTo(cursorPos); } - else - { - // click beyond the end of the text - m_llist->MoveCursorToEnd(); - } +// else +// { +// // click beyond the end of the text +// m_llist->MoveCursorToEnd(); +// } // clicking a mouse removes the selection if ( m_llist->HasSelection() ) { m_llist->DiscardSelection(); + m_Selecting = false; DoPaint(); // TODO: we don't have to redraw everything! } @@ -330,19 +343,17 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) if(m_CursorVisibility == -1) m_CursorVisibility = 1; +#ifdef WXLAYOUT_USE_CARET + if ( m_CursorVisibility == 1 ) + GetCaret()->Show(); +#endif // WXLAYOUT_USE_CARET - if(m_CursorVisibility != 0) + if(m_CursorVisibility) { - // draw a thick cursor for editable windows with focus + // draw a thick cursor for editable windows with focus m_llist->DrawCursor(dc, m_HaveFocus && IsEditable(), offset); } - // VZ: this should be unnecessary because mouse can only click on a - // visible part of the canvas -#if 0 - ScrollToCursor(); -#endif // 0 - #ifdef __WXGTK__ DoPaint(); // DoPaint suppresses flicker under GTK #endif // wxGTK @@ -374,7 +385,7 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) m_llist->StartSelection(); m_llist->MoveCursorWord(1, false); m_llist->EndSelection(); - + m_Selecting = false; DoPaint(); // TODO: we don't have to redraw everything! break; } @@ -402,8 +413,7 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) } } - if( u ) - u->DecRef(); + if( u ) u->DecRef(); } // ---------------------------------------------------------------------------- @@ -414,6 +424,7 @@ void wxLayoutWindow::OnChar(wxKeyEvent& event) { int keyCode = event.KeyCode(); + bool ctrlDown = event.ControlDown(); #ifdef WXLAYOUT_DEBUG if(keyCode == WXK_F1) @@ -423,34 +434,51 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) } #endif - wxASSERT_MSG( !m_Selecting || event.ShiftDown(), - "m_Selecting is normally reset in OnKeyUp() when Shift " - "goes up!" ); - - if ( !m_Selecting && m_llist->HasSelection() ) + // Force m_Selecting to be false if shift is no longer + // pressed. OnKeyUp() cannot catch all Shift-Up events. + if(m_Selecting && !event.ShiftDown()) { - // pressing any non-arrow key replaces the selection - if ( !IsDirectionKey(keyCode) ) - { - m_llist->DeleteSelection(); - } - else if ( !event.ShiftDown() ) - { - m_llist->DiscardSelection(); - } + m_Selecting = false; + m_llist->EndSelection(); } - + + // If we deleted the selection here, we must not execute the + // deletion in Delete/Backspace handling. + bool deletedSelection = false; + // pressing any non-arrow key optionally replaces the selection: + if(m_AutoDeleteSelection + && !m_Selecting + && m_llist->HasSelection() + && ! IsDirectionKey(keyCode) + && ! (event.AltDown() || ctrlDown) + ) + { + m_llist->DeleteSelection(); + deletedSelection = true; + } + // + starts selection - if ( event.ShiftDown() && IsDirectionKey(keyCode) ) + if ( IsDirectionKey(keyCode) ) { - if ( !m_Selecting ) + if ( m_Selecting ) + { + // just continue the old selection + if( event.ShiftDown() ) + m_llist->ContinueSelection(); + else + { + m_llist->DiscardSelection(); + m_Selecting = false; + } + } + else if( event.ShiftDown() ) { m_Selecting = true; m_llist->StartSelection(); } - //else: just continue the old selection + } - + // If needed, make cursor visible: if(m_CursorVisibility == -1) m_CursorVisibility = 1; @@ -460,7 +488,6 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) cursor, etc. It's default will process all keycodes causing modifications to the buffer, but only if editing is allowed. */ - bool ctrlDown = event.ControlDown(); switch(keyCode) { case WXK_RIGHT: @@ -509,7 +536,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) else if( IsEditable() ) { /* First, handle control keys */ - if(event.ControlDown() && ! event.AltDown()) + if(ctrlDown && ! event.AltDown()) { switch(keyCode) { @@ -517,8 +544,12 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) Copy(); break; case WXK_DELETE : + if(! deletedSelection) + m_llist->DeleteWord(); + break; case 'd': - m_llist->Delete(1); + if(! deletedSelection) // already done + m_llist->Delete(1); break; case 'y': m_llist->DeleteLines(1); @@ -573,11 +604,13 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) if(event.ShiftDown()) Cut(); else - m_llist->Delete(1); + if(! deletedSelection) + m_llist->Delete(1); break; case WXK_BACK: // backspace - if(m_llist->MoveCursorHorizontally(-1)) - m_llist->Delete(1); + if(! deletedSelection) + if(m_llist->MoveCursorHorizontally(-1)) + m_llist->Delete(1); break; case WXK_RETURN: if(m_WrapMargin > 0) @@ -586,6 +619,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) break; case WXK_TAB: + if ( !event.ShiftDown() ) { // TODO should be configurable static const int tabSize = 8; @@ -706,12 +740,13 @@ void wxLayoutWindow::DoPaint(const wxRect *updateRect) { #ifdef __WXGTK__ + // Calling Refresh() causes bad flicker under wxGTK!!! InternalPaint(updateRect); -#else // Causes bad flicker under wxGTK!!! +#else + // shouldn't specify the update rectangle if it doesn't include all the + // changed locations - otherwise, they won't be repainted at all because + // the system clips the display to the update rect Refresh(FALSE); //, updateRect); - - if ( !::UpdateWindow(GetHwnd()) ) - wxLogLastError("UpdateWindow"); #endif } @@ -750,6 +785,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) m_llist->Layout(dc); ResizeScrollbars(); } + /* Check whether the window has grown, if so, we need to reallocate the bitmap to be larger. */ if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y) @@ -765,7 +801,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) } m_memDC->SetDeviceOrigin(0,0); - m_memDC->SetBrush(wxBrush(m_llist->GetDefaultStyleInfo().GetBGColour(),wxSOLID)); + m_memDC->SetBackground(wxBrush(m_llist->GetDefaultStyleInfo().GetBGColour(),wxSOLID)); m_memDC->SetPen(wxPen(m_llist->GetDefaultStyleInfo().GetBGColour(), 0,wxTRANSPARENT)); m_memDC->SetLogicalFunction(wxCOPY); @@ -841,7 +877,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) #ifdef WXLAYOUT_USE_CARET // show the caret back after everything is redrawn - m_caret->Show(); + GetCaret()->Show(); #endif // WXLAYOUT_USE_CARET ResetDirty(); @@ -888,9 +924,9 @@ wxLayoutWindow::ResizeScrollbars(bool exact) // in the absence of scrollbars we should compare with the client size if ( !m_hasHScrollbar ) - m_maxx = size.x - WXLO_ROFFSET; + m_maxx = size.x;// - WXLO_ROFFSET; if ( !m_hasVScrollbar ) - m_maxy = size.y - WXLO_BOFFSET; + m_maxy = size.y;// - WXLO_BOFFSET; // check if the text hasn't become too big // TODO why do we set both at once? they're independent... @@ -917,18 +953,27 @@ wxLayoutWindow::ResizeScrollbars(bool exact) m_maxy = max.y + Y_SCROLL_PAGE; } #if 0 + //FIXME: this code is pretty broken, producing "arithmetic + //exception" crashes (div by 0??) else { // check if the window hasn't become too big, thus making the scrollbars // unnecessary - if ( m_hasHScrollbar && (max.x < size.x) ) + if ( !exact ) + { + // add an extra bit to the sizes to avoid future updates + max.x -= WXLO_ROFFSET; + max.y -= WXLO_BOFFSET; + } + + if ( m_hasHScrollbar && (max.x < m_maxx) ) { // remove the horizontal scrollbar SetScrollbars(0, -1, 0, -1, 0, -1, true); m_hasHScrollbar = false; } - if ( m_hasVScrollbar && (max.y < size.y) ) + if ( m_hasVScrollbar && (max.y < m_maxy) ) { // remove the vertical scrollbar SetScrollbars(-1, 0, -1, 0, -1, 0, true); @@ -960,7 +1005,7 @@ wxLayoutWindow::Paste(bool primary) wxTheClipboard->GetData(&wxldo); { } - //FIXME: missing functionality m_llist->Insert(wxldo.GetList()); + //FIXME: missing functionality m_llist->Insert(wxldo.GetList()); } else #endif @@ -975,17 +1020,6 @@ wxLayoutWindow::Paste(bool primary) } wxTheClipboard->Close(); } - -#if 0 - /* My attempt to get the primary selection, but it does not - work. :-( */ - if(text.Length() == 0) - { - wxTextCtrl tmp_tctrl(this,-1); - tmp_tctrl.Paste(); - text += tmp_tctrl.GetValue(); - } -#endif } bool @@ -1123,21 +1157,21 @@ void wxLayoutWindow::OnMenu(wxCommandEvent& event) switch (event.GetId()) { case WXLOWIN_MENU_LARGER: - m_llist->SetFontLarger(); Refresh(FALSE); break; + m_llist->SetFontLarger(); DoPaint(); break; case WXLOWIN_MENU_SMALLER: - m_llist->SetFontSmaller(); Refresh(FALSE); break; + m_llist->SetFontSmaller(); DoPaint(); break; case WXLOWIN_MENU_UNDERLINE: - m_llist->ToggleFontUnderline(); Refresh(FALSE); break; + m_llist->ToggleFontUnderline(); DoPaint(); break; case WXLOWIN_MENU_BOLD: - m_llist->ToggleFontWeight(); Refresh(FALSE); break; + m_llist->ToggleFontWeight(); DoPaint(); break; case WXLOWIN_MENU_ITALICS: - m_llist->ToggleFontItalics(); Refresh(FALSE); break; + m_llist->ToggleFontItalics(); DoPaint(); break; case WXLOWIN_MENU_ROMAN: - m_llist->SetFontFamily(wxROMAN); Refresh(FALSE); break; + m_llist->SetFontFamily(wxROMAN); DoPaint(); break; case WXLOWIN_MENU_TYPEWRITER: - m_llist->SetFontFamily(wxFIXED); Refresh(FALSE); break; + m_llist->SetFontFamily(wxFIXED); DoPaint(); break; case WXLOWIN_MENU_SANSSERIF: - m_llist->SetFontFamily(wxSWISS); Refresh(FALSE); break; + m_llist->SetFontFamily(wxSWISS); DoPaint(); break; } } @@ -1150,6 +1184,7 @@ wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) { m_HaveFocus = true; ev.Skip(); + DoPaint(); // cursor must change } void @@ -1157,6 +1192,7 @@ wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) { m_HaveFocus = false; ev.Skip(); + DoPaint();// cursor must change } // ----------------------------------------------------------------------------