From: Vadim Zeitlin Date: Wed, 9 Jun 1999 16:22:24 +0000 (+0000) Subject: wxLayoutStyleInfo ctor reverted back to the original, selection works better X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/93a740f1d6fe181fe280af1787f858b97c1b97e6 wxLayoutStyleInfo ctor reverted back to the original, selection works better git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/samples/richedit/wxllist.cpp b/samples/richedit/wxllist.cpp index 8d469dc967..600b7d60ff 100644 --- a/samples/richedit/wxllist.cpp +++ b/samples/richedit/wxllist.cpp @@ -642,6 +642,8 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist) m_Next->MoveLines(+1); m_Next->RecalculatePositions(1,llist); } + + m_StyleInfo = llist->GetDefaultStyleInfo(); } wxLayoutLine::~wxLayoutLine() @@ -1131,12 +1133,18 @@ wxLayoutLine::Layout(wxDC &dc, else str = WXLO_CURSORCHAR; dc.GetTextExtent(str, &width, &height, &descent); - wxASSERT(cursorSize); - // Just in case some joker inserted an empty string object: - if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH; - if(height == 0) height = sizeObj.y; - cursorSize->x = width; - cursorSize->y = height; + + if ( cursorSize ) + { + // Just in case some joker inserted an empty string object: + if(width == 0) + width = WXLO_MINIMUM_CURSOR_WIDTH; + if(height == 0) + height = sizeObj.y; + cursorSize->x = width; + cursorSize->y = height; + } + cursorFound = true; // no more checks } else @@ -1206,7 +1214,7 @@ wxLayoutLine::Layout(wxDC &dc, } // We need to check whether we found a valid cursor size: - if(cursorPos) + if(cursorPos && cursorSize) { // this might be the case if the cursor is at the end of the // line or on a command object: @@ -1755,7 +1763,7 @@ wxLayoutList::MoveCursorHorizontally(int n) } bool -wxLayoutList::MoveCursorWord(int n) +wxLayoutList::MoveCursorWord(int n, bool untilNext) { wxCHECK_MSG( m_CursorLine, false, "no current line" ); wxCHECK_MSG( n == -1 || n == +1, false, "not implemented yet" ); @@ -1805,25 +1813,41 @@ wxLayoutList::MoveCursorWord(int n) if ( canAdvance ) { - const char *start = tobj->GetText().c_str(); + const wxString& text = tobj->GetText(); + const char *start = text.c_str(); + const char *end = start + text.length(); const char *p = start + offset; + if ( n < 0 ) + { + if ( offset > 0 ) + p--; + } + // to the beginning/end of the next/prev word - while ( isspace(*p) ) + while ( p >= start && p < end && isspace(*p) ) { n > 0 ? p++ : p--; } // go to the end/beginning of the word (in a broad sense...) - while ( p >= start && !isspace(*p) ) + while ( p >= start && p < end && !isspace(*p) ) { n > 0 ? p++ : p--; } if ( n > 0 ) { - // now advance to the beginning of the next word - while ( isspace(*p) ) + if ( untilNext ) + { + // now advance to the beginning of the next word + while ( isspace(*p) && p < end ) + p++; + } + } + else // backwards + { + if ( isspace(*p) ) p++; } @@ -2185,6 +2209,23 @@ wxLayoutList::Draw(wxDC &dc, { wxLayoutLine *line = m_FirstLine; + if ( m_Selection.m_discarded ) + { + // calculate them if we don't have them already + if ( !m_Selection.HasValidScreenCoords() ) + { + m_Selection.m_ScreenA = GetScreenPos(dc, m_Selection.m_CursorA); + m_Selection.m_ScreenB = GetScreenPos(dc, m_Selection.m_CursorB); + } + + // invalidate the area which was previousle selected - and which is not + // selected any more + SetUpdateRect(m_Selection.m_ScreenA); + SetUpdateRect(m_Selection.m_ScreenB); + + m_Selection.m_discarded = false; + } + /* We need to re-layout all dirty lines to update styleinfos etc. However, somehow we don't find all dirty lines... */ Layout(dc); //,-1,true); //FIXME @@ -2438,28 +2479,17 @@ wxLayoutList::DiscardSelection() m_Selection.m_valid = m_Selection.m_selecting = false; - - // invalidate the area which was previousle selected - and which is not - // selected any more - if ( m_Selection.HasValidScreenCoords() ) - { - SetUpdateRect(m_Selection.m_ScreenA); - SetUpdateRect(m_Selection.m_ScreenB); - } - else - { - // TODO - } + m_Selection.m_discarded = true; } bool -wxLayoutList::IsSelecting(void) +wxLayoutList::IsSelecting(void) const { return m_Selection.m_selecting; } bool -wxLayoutList::IsSelected(const wxPoint &cursor) +wxLayoutList::IsSelected(const wxPoint &cursor) const { if ( !HasSelection() ) return false; diff --git a/samples/richedit/wxllist.h b/samples/richedit/wxllist.h index bf784d0db5..cef46fddab 100644 --- a/samples/richedit/wxllist.h +++ b/samples/richedit/wxllist.h @@ -324,11 +324,11 @@ private: */ struct wxLayoutStyleInfo { - wxLayoutStyleInfo(int ifamily = wxDEFAULT, - int isize = WXLO_DEFAULTFONTSIZE, - int istyle = wxNORMAL, - int iweight = wxNORMAL, - int iul = FALSE, + wxLayoutStyleInfo(int ifamily = -1, + int isize = -1, + int istyle = -1, + int iweight = -1, + int iul = -1, wxColour *fg = NULL, wxColour *bg = NULL); wxLayoutStyleInfo & operator=(const wxLayoutStyleInfo &right); @@ -783,9 +783,11 @@ public: bool MoveCursorHorizontally(int n); /** Move cursor to the left or right counting in words @param n = number of positions in words + @param untilNext: puts the cursor at the start of the next word if true, + leaves it at the end of the current one otherwise @return bool if it could be moved */ - bool MoveCursorWord(int n); + bool MoveCursorWord(int n, bool untilNext = true); /// Move cursor to end of line. void MoveCursorToEndOfLine(void) @@ -1070,9 +1072,9 @@ public: /// Discard the current selection void DiscardSelection(); /// Are we still selecting text? - bool IsSelecting(void); + bool IsSelecting(void) const; /// Is the given point (text coords) selected? - bool IsSelected(const wxPoint &cursor); + bool IsSelected(const wxPoint &cursor) const; /// Do we have a non null selection? bool HasSelection() const { return m_Selection.m_valid || m_Selection.m_selecting; } @@ -1140,9 +1142,11 @@ private: /// selection.state and begin/end coordinates struct Selection { - Selection() { m_valid = false; m_selecting = false; } + Selection() { m_valid = m_selecting = m_discarded = false; } + bool m_valid; bool m_selecting; + bool m_discarded; // may be TRUE only until the next redraw // returns true if we already have the screen coordinates of the // selection start and end diff --git a/samples/richedit/wxlwindow.cpp b/samples/richedit/wxlwindow.cpp index 98239d5184..7b00168c44 100644 --- a/samples/richedit/wxlwindow.cpp +++ b/samples/richedit/wxlwindow.cpp @@ -6,9 +6,9 @@ * $Id$ *******************************************************************/ -// =========================================================================== +// ============================================================================ // declarations -// =========================================================================== +// ============================================================================ // ---------------------------------------------------------------------------- // headers @@ -89,7 +89,8 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow) EVT_CHAR (wxLayoutWindow::OnChar) EVT_KEY_UP (wxLayoutWindow::OnKeyUp) - EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick) + EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseDown) + EVT_LEFT_UP(wxLayoutWindow::OnLeftMouseUp) EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick) EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick) EVT_MOTION (wxLayoutWindow::OnMouseMove) @@ -103,9 +104,16 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow) EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus) END_EVENT_TABLE() -// =========================================================================== +// ---------------------------------------------------------------------------- +// function prototypes +// ---------------------------------------------------------------------------- + +/// returns TRUE if keyCode is one of arrows/home/end/page{up|down} keys +static bool IsDirectionKey(long keyCode); + +// ============================================================================ // implementation -// =========================================================================== +// ============================================================================ /* LEAVE IT HERE UNTIL WXGTK WORKS AGAIN!!! */ #ifdef __WXGTK__ @@ -212,8 +220,10 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) findPos.x -= WXLO_XOFFSET; findPos.y -= WXLO_YOFFSET; - if(findPos.x < 0) findPos.x = 0; - if(findPos.y < 0) findPos.y = 0; + if(findPos.x < 0) + findPos.x = 0; + if(findPos.y < 0) + findPos.y = 0; m_ClickPosition = wxPoint(event.GetX(), event.GetY()); @@ -223,98 +233,116 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) &cursorPos, &found); wxLayoutObject::UserData *u = obj ? obj->GetUserData() : NULL; - //has the mouse only been moved? - if(eventId == WXLOWIN_MENU_MOUSEMOVE) + // has the mouse only been moved? + switch ( eventId ) { - // 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) + case WXLOWIN_MENU_MOUSEMOVE: + // 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); + } } - } - else - { - if(m_HandCursor) - SetCursor(wxCURSOR_IBEAM); - m_HandCursor = FALSE; - if(m_StatusBar && m_StatusFieldLabel != -1) - m_StatusBar->SetStatusText("", m_StatusFieldLabel); - } - if(event.LeftIsDown()) - { - if(! m_Selecting) + else { - m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition); - m_Selecting = true; - DoPaint(); // TODO: we don't have to redraw everything! + if(m_HandCursor) + SetCursor(wxCURSOR_IBEAM); + m_HandCursor = FALSE; + if(m_StatusBar && m_StatusFieldLabel != -1) + m_StatusBar->SetStatusText("", m_StatusFieldLabel); } - else + + // 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! } - } - if(m_Selecting && ! event.LeftIsDown()) - { - m_llist->EndSelection(cursorPos, m_ClickPosition); - m_Selecting = false; - DoPaint(); // TODO: we don't have to redraw everything! - } - if ( u ) - { - u->DecRef(); - u = NULL; - } - } - else if(eventId == WXLOWIN_MENU_LCLICK) - { - // always move cursor to mouse click: - m_llist->MoveCursorTo(cursorPos); + if ( u ) + { + u->DecRef(); + u = NULL; + } + break; - // clicking a mouse removes the selection - if ( m_llist->HasSelection() ) - { - m_llist->DiscardSelection(); - DoPaint(); // TODO: we don't have to redraw everything! - } + case WXLOWIN_MENU_LDOWN: + { + // always move cursor to mouse click: + m_llist->MoveCursorTo(cursorPos); + + // clicking a mouse removes the selection + if ( m_llist->HasSelection() ) + { + m_llist->DiscardSelection(); + DoPaint(); // TODO: we don't have to redraw everything! + } + + // Calculate where the top of the visible area is: + int x0, y0; + ViewStart(&x0,&y0); + int dx, dy; + GetScrollPixelsPerUnit(&dx, &dy); + x0 *= dx; y0 *= dy; + + wxPoint offset(-x0+WXLO_XOFFSET, -y0+WXLO_YOFFSET); + + if(m_CursorVisibility == -1) + m_CursorVisibility = 1; + + if(m_CursorVisibility != 0) + { + // 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 - // Calculate where the top of the visible area is: - int x0, y0; - ViewStart(&x0,&y0); - int dx, dy; - GetScrollPixelsPerUnit(&dx, &dy); - x0 *= dx; y0 *= dy; +#ifdef __WXGTK__ + DoPaint(); // DoPaint suppresses flicker under GTK +#endif // wxGTK - wxPoint offset(-x0+WXLO_XOFFSET, -y0+WXLO_YOFFSET); + // start selection + m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition); + m_Selecting = true; + } + break; - if(m_CursorVisibility == -1) - m_CursorVisibility = 1; + case WXLOWIN_MENU_LUP: + if ( m_Selecting ) + { + m_llist->EndSelection(); + m_Selecting = false; - if(m_CursorVisibility != 0) - { - // draw a thick cursor for editable windows with focus - m_llist->DrawCursor(dc, m_HaveFocus && IsEditable(), offset); - } + DoPaint(); // TODO: we don't have to redraw everything! + } + break; - // VZ: this should be unnecessary because mouse can only click on a - // visible part of the canvas -#if 0 - ScrollToCursor(); -#endif // 0 + case WXLOWIN_MENU_DBLCLICK: + // select a word under cursor + m_llist->MoveCursorTo(cursorPos); + m_llist->MoveCursorWord(-1); + m_llist->StartSelection(); + m_llist->MoveCursorWord(1, false); + m_llist->EndSelection(); -#ifdef __WXGTK__ - DoPaint(); // DoPaint suppresses flicker under GTK -#endif // wxGTK + DoPaint(); // TODO: we don't have to redraw everything! + break; } // notify about mouse events? @@ -344,9 +372,10 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) u->DecRef(); } -/* - * Some simple keyboard handling. - */ +// ---------------------------------------------------------------------------- +// keyboard handling. +// ---------------------------------------------------------------------------- + void wxLayoutWindow::OnChar(wxKeyEvent& event) { @@ -360,24 +389,32 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) } #endif - if(! m_Selecting && event.ShiftDown()) + wxASSERT_MSG( !m_Selecting || event.ShiftDown(), + "m_Selecting is normally reset in OnKeyUp() when Shift " + "goes up!" ); + + if ( !m_Selecting && m_llist->HasSelection() ) { - switch(keyCode) + // pressing any non-arrow key replaces the selection + if ( !IsDirectionKey(keyCode) ) + { + m_llist->DeleteSelection(); + } + else if ( !event.ShiftDown() ) + { + m_llist->DiscardSelection(); + } + } + + // + starts selection + if ( event.ShiftDown() && IsDirectionKey(keyCode) ) + { + if ( !m_Selecting ) { - case WXK_UP: - case WXK_DOWN: - case WXK_RIGHT: - case WXK_LEFT: - case WXK_PRIOR: - case WXK_NEXT: - case WXK_HOME: - case WXK_END: m_Selecting = true; m_llist->StartSelection(); - break; - default: - ; } + //else: just continue the old selection } // If needed, make cursor visible: @@ -505,7 +542,8 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) m_llist->Delete(1); break; case WXK_BACK: // backspace - if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); + if(m_llist->MoveCursorHorizontally(-1)) + m_llist->Delete(1); break; case WXK_RETURN: if(m_WrapMargin > 0) @@ -528,15 +566,11 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) SetModified(); }// if(IsEditable()) }// first switch() - if(m_Selecting) + + if ( m_Selecting ) { - if(event.ShiftDown()) - m_llist->ContinueSelection(); - else - { - m_llist->EndSelection(); - m_Selecting = false; - } + // continue selection to the current (new) cursor position + m_llist->ContinueSelection(); } // we must call ResizeScrollbars() before ScrollToCursor(), otherwise the @@ -551,11 +585,12 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) void wxLayoutWindow::OnKeyUp(wxKeyEvent& event) { - if(event.KeyCode() == WXK_SHIFT && m_llist->IsSelecting()) + if ( event.KeyCode() == WXK_SHIFT && m_Selecting ) { m_llist->EndSelection(); m_Selecting = false; } + event.Skip(); } @@ -822,6 +857,10 @@ wxLayoutWindow::ResizeScrollbars(bool exact) } } +// ---------------------------------------------------------------------------- +// clipboard operations +// ---------------------------------------------------------------------------- + void wxLayoutWindow::Paste(void) { @@ -926,6 +965,11 @@ wxLayoutWindow::Cut(void) else return FALSE; } + +// ---------------------------------------------------------------------------- +// searching +// ---------------------------------------------------------------------------- + bool wxLayoutWindow::Find(const wxString &needle, wxPoint * fromWhere) @@ -950,6 +994,10 @@ wxLayoutWindow::Find(const wxString &needle, return false; } +// ---------------------------------------------------------------------------- +// popup menu stuff +// ---------------------------------------------------------------------------- + wxMenu * wxLayoutWindow::MakeFormatMenu() { @@ -1014,6 +1062,10 @@ void wxLayoutWindow::OnMenu(wxCommandEvent& event) } } +// ---------------------------------------------------------------------------- +// focus +// ---------------------------------------------------------------------------- + void wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) { @@ -1027,3 +1079,26 @@ wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) m_HaveFocus = false; ev.Skip(); } + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +static bool IsDirectionKey(long keyCode) +{ + switch(keyCode) + { + case WXK_UP: + case WXK_DOWN: + case WXK_RIGHT: + case WXK_LEFT: + case WXK_PRIOR: + case WXK_NEXT: + case WXK_HOME: + case WXK_END: + return true; + + default: + return false; + } +} diff --git a/samples/richedit/wxlwindow.h b/samples/richedit/wxlwindow.h index 6344296e96..3bbaf90d43 100644 --- a/samples/richedit/wxlwindow.h +++ b/samples/richedit/wxlwindow.h @@ -36,8 +36,9 @@ enum WXLOWIN_MENU_TYPEWRITER, WXLOWIN_MENU_SANSSERIF, WXLOWIN_MENU_RCLICK, - WXLOWIN_MENU_LCLICK, WXLOWIN_MENU_DBLCLICK, + WXLOWIN_MENU_LDOWN, + WXLOWIN_MENU_LUP, WXLOWIN_MENU_MOUSEMOVE, WXLOWIN_MENU_LAST = WXLOWIN_MENU_MOUSEMOVE }; @@ -133,7 +134,8 @@ public: void OnUpdateMenuBold(wxUpdateUIEvent& event); void OnUpdateMenuItalic(wxUpdateUIEvent& event); void OnMenu(wxCommandEvent& event); - void OnLeftMouseClick(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_LCLICK, event); } + void OnLeftMouseDown(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_LDOWN, event); } + void OnLeftMouseUp(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_LUP, event); } void OnRightMouseClick(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_RCLICK, event); } void OnMouseDblClick(wxMouseEvent& event) { OnMouse(WXLOWIN_MENU_DBLCLICK, event); } void OnMouseMove(wxMouseEvent &event) { OnMouse(WXLOWIN_MENU_MOUSEMOVE, event) ; }