]> git.saurik.com Git - wxWidgets.git/commitdiff
wxLayoutStyleInfo ctor reverted back to the original, selection works better
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 9 Jun 1999 16:22:24 +0000 (16:22 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 9 Jun 1999 16:22:24 +0000 (16:22 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2730 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

samples/richedit/wxllist.cpp
samples/richedit/wxllist.h
samples/richedit/wxlwindow.cpp
samples/richedit/wxlwindow.h

index 8d469dc967e0939db7d0d2cc993b69b2c01243a3..600b7d60ffb7e17eb816656f3cbbe55af9a8a222 100644 (file)
@@ -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;
index bf784d0db54050f33986b9eaeadc6145cfded526..cef46fddabf03653c48addc70f07a3ba05cbee43 100644 (file)
@@ -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
index 98239d518464e10a6ba38d567b3a8857e7c86527..7b00168c449cbb8b86868ea8f82fc270a6855d37 100644 (file)
@@ -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();
+      }
+   }
+
+   // <Shift>+<arrow> 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;
+   }
+}
index 6344296e965d7f9daf3ba6d9a0f3feeab89f2b6e..3bbaf90d4369c16981166a781b27b65668549af6 100644 (file)
@@ -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) ; }