From f287ca7dc8ff31c2baa2a65178ca7348e4c8214e Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Wed, 13 May 2009 22:09:15 +0000 Subject: [PATCH] fixed behaviour of non-editable textviews: * non-editable textviews no longer draw the caret * the cursor keys scroll immediately, not only when the (invisible) caret reaches the views bounds * HOME/END work more reliably * any selection stays active throughout keyboard navigation Tested with AboutSystem, Mail, StyledEdit and Beam - seems to work ok git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30756 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/TextView.h | 4 + src/kits/interface/TextView.cpp | 125 +++++++++++++++++++++++++------- 2 files changed, 101 insertions(+), 28 deletions(-) diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index 426d5859c6..0034e06d8e 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -394,6 +394,10 @@ private: float _NullStyleHeight() const; + void _ScrollBy(float horizontalStep, + float verticalStep); + void _ScrollTo(float x, float y); + BPrivate::TextGapBuffer* fText; LineBuffer* fLines; StyleBuffer* fStyles; diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index b450107194..96f1c4f26c 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -157,9 +157,12 @@ struct BTextView::LayoutData { }; -const static rgb_color kBlackColor = { 0, 0, 0, 255 }; -const static rgb_color kBlueInputColor = { 152, 203, 255, 255 }; -const static rgb_color kRedInputColor = { 255, 152, 152, 255 }; +static const rgb_color kBlackColor = { 0, 0, 0, 255 }; +static const rgb_color kBlueInputColor = { 152, 203, 255, 255 }; +static const rgb_color kRedInputColor = { 255, 152, 152, 255 }; + +static const float kHorizontalScrollBarStep = 10.0; +static const float kVerticalScrollBarStep = 12.0; static property_info sPropertyList[] = { @@ -3243,7 +3246,9 @@ BTextView::_HandleArrowKey(uint32 inArrowKey) int32 lastClickOffset = fClickOffset; switch (inArrowKey) { case B_LEFT_ARROW: - if (fSelStart != fSelEnd && !shiftDown) + if (!fEditable) + _ScrollBy(-1 * kHorizontalScrollBarStep, 0); + else if (fSelStart != fSelEnd && !shiftDown) fClickOffset = fSelStart; else { fClickOffset @@ -3267,7 +3272,9 @@ BTextView::_HandleArrowKey(uint32 inArrowKey) break; case B_RIGHT_ARROW: - if (fSelStart != fSelEnd && !shiftDown) + if (!fEditable) + _ScrollBy(kHorizontalScrollBarStep, 0); + else if (fSelStart != fSelEnd && !shiftDown) fClickOffset = fSelEnd; else { fClickOffset @@ -3292,7 +3299,9 @@ BTextView::_HandleArrowKey(uint32 inArrowKey) case B_UP_ARROW: { - if (fSelStart != fSelEnd && !shiftDown) + if (!fEditable) + _ScrollBy(0, -1 * kVerticalScrollBarStep); + else if (fSelStart != fSelEnd && !shiftDown) fClickOffset = fSelStart; else { float height; @@ -3318,7 +3327,9 @@ BTextView::_HandleArrowKey(uint32 inArrowKey) case B_DOWN_ARROW: { - if (fSelStart != fSelEnd && !shiftDown) + if (!fEditable) + _ScrollBy(0, kVerticalScrollBarStep); + else if (fSelStart != fSelEnd && !shiftDown) fClickOffset = fSelEnd; else { float height; @@ -3346,13 +3357,15 @@ BTextView::_HandleArrowKey(uint32 inArrowKey) // invalidate the null style fStyles->InvalidateNullStyle(); - if (shiftDown) - Select(selStart, selEnd); - else - Select(fClickOffset, fClickOffset); + if (fEditable) { + if (shiftDown) + Select(selStart, selEnd); + else + Select(fClickOffset, fClickOffset); - // scroll if needed - ScrollToOffset(fClickOffset); + // scroll if needed + ScrollToOffset(fClickOffset); + } } @@ -3406,9 +3419,15 @@ BTextView::_HandlePageKey(uint32 inPageKey) int32 lastClickOffset = fClickOffset; switch (inPageKey) { case B_HOME: - if (ctrlDown) + if (!fEditable) { + _ScrollTo(0, 0); + break; + } + + if (ctrlDown) { + _ScrollTo(0, 0); fClickOffset = 0; - else { + } else { // get the start of the last line if caret is on it line = (*fLines)[_LineAt(lastClickOffset)]; fClickOffset = line->offset; @@ -3433,7 +3452,13 @@ BTextView::_HandlePageKey(uint32 inPageKey) break; case B_END: + if (!fEditable) { + _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); + break; + } + if (ctrlDown) { + _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); fClickOffset = fText->Length(); } else { // If we are on the last line, just go to the last @@ -3479,7 +3504,10 @@ BTextView::_HandlePageKey(uint32 inPageKey) currentPos.y -= Bounds().Height(); fClickOffset = OffsetAt(LineAt(currentPos)); - ScrollBy(0, -1 * Bounds().Height()); + _ScrollBy(0, -1 * Bounds().Height()); + + if (!fEditable) + break; if (!shiftDown) selStart = selEnd = fClickOffset; @@ -3506,7 +3534,10 @@ BTextView::_HandlePageKey(uint32 inPageKey) currentPos.y += Bounds().Height(); fClickOffset = OffsetAt(LineAt(currentPos)); - ScrollBy(0, Bounds().Height()); + _ScrollBy(0, Bounds().Height()); + + if (!fEditable) + break; if (!shiftDown) selStart = selEnd = fClickOffset; @@ -3528,12 +3559,14 @@ BTextView::_HandlePageKey(uint32 inPageKey) } } - if (shiftDown) - Select(selStart, selEnd); - else - Select(fClickOffset, fClickOffset); + if (fEditable) { + if (shiftDown) + Select(selStart, selEnd); + else + Select(fClickOffset, fClickOffset); - ScrollToOffset(fClickOffset); + ScrollToOffset(fClickOffset); + } } @@ -3580,7 +3613,8 @@ BTextView::_HandleAlphaKey(const char *bytes, int32 numBytes) fClickOffset = fSelEnd; - ScrollToOffset(fClickOffset); + if (fEditable) + ScrollToOffset(fClickOffset); } @@ -4368,7 +4402,7 @@ BTextView::_DrawCaret(int32 offset) inline void BTextView::_ShowCaret() { - if (!fCaretVisible) + if (!fCaretVisible && fEditable) _InvertCaret(); } @@ -4719,8 +4753,8 @@ void BTextView::_UpdateScrollbars() { BRect bounds(Bounds()); - BScrollBar *horizontalScrollBar = ScrollBar(B_HORIZONTAL); - BScrollBar *verticalScrollBar = ScrollBar(B_VERTICAL); + BScrollBar* horizontalScrollBar = ScrollBar(B_HORIZONTAL); + BScrollBar* verticalScrollBar = ScrollBar(B_VERTICAL); // do we have a horizontal scroll bar? if (horizontalScrollBar != NULL) { @@ -4733,7 +4767,7 @@ BTextView::_UpdateScrollbars() horizontalScrollBar->SetRange(0, (float)maxRange); horizontalScrollBar->SetProportion((float)viewWidth / (float)dataWidth); - horizontalScrollBar->SetSteps(10, dataWidth / 10); + horizontalScrollBar->SetSteps(kHorizontalScrollBarStep, dataWidth / 10); } // how about a vertical scroll bar? @@ -4747,11 +4781,45 @@ BTextView::_UpdateScrollbars() verticalScrollBar->SetRange(0, maxRange); verticalScrollBar->SetProportion((float)viewHeight / (float)dataHeight); - verticalScrollBar->SetSteps(12, viewHeight); + verticalScrollBar->SetSteps(kVerticalScrollBarStep, viewHeight); } } +/*! \brief Scrolls by the given offsets +*/ +void +BTextView::_ScrollBy(float horizontal, float vertical) +{ + BRect bounds = Bounds(); + _ScrollTo(bounds.left + horizontal, bounds.top + vertical); +} + + +/*! \brief Scrolls to the given position, making sure not to scroll out of + bounds +*/ +void +BTextView::_ScrollTo(float x, float y) +{ + BRect bounds = Bounds(); + long viewWidth = bounds.IntegerWidth(); + long viewHeight = bounds.IntegerHeight(); + + if (x > fTextRect.right - viewWidth) + x = fTextRect.right - viewWidth; + if (x < 0.0) + x = 0.0; + + if (y > fTextRect.bottom + fLayoutData->bottomInset - viewHeight) + y = fTextRect.bottom + fLayoutData->bottomInset - viewHeight; + if (y < 0.0) + y = 0.0; + + ScrollTo(x, y); +} + + /*! \brief Autoresizes the view to fit the contained text. */ void @@ -5185,6 +5253,7 @@ BTextView::_HandleInputMethodChanged(BMessage *message) fInline->SetSelectionOffset(selectionStart); fInline->SetSelectionLength(selectionEnd - selectionStart); +printf("string=%s\n", string); const int32 inlineOffset = fInline->Offset(); InsertText(string, stringLen, fSelStart, NULL); fSelStart += stringLen;