From a9b301871d06c0ebe42d22b31c685abed5107acd Mon Sep 17 00:00:00 2001 From: John Scipione Date: Mon, 20 Jul 2020 11:00:41 -0400 Subject: [PATCH] IK: align BTextView text rect/fix alignment Preserve passed in text rect in fTextRext (unless in layout) and create an internal version fAlignedTextRect which is used in place of fTextRect. fAlignedTextRext is aligned to fit the text rect bounds and grows to fit. fAlignedTextRect always grows vertically but only grows horizontally if wrap is off. Left-aligned text view's grow right, right-aligned ones grow left, and center center aligned ones grow out. Set fTextRect to bounds in _DoLayout(). Reduce left and right padding inside text views from full label spacing to half label spacing. Unify padding between BTextControl and BTextView. Fixing padding also fixes right and center-aligned BTextViews. Undo extra scrolling for non-left text views from hrev24130 fixing a scrolling left and right with mouse bug when it shouldn't. Replace max_c and min_c with std::max and std::min respectively. Remove scrolling from one instance of BTextView::SetText as it produced undesired results while editing a scrolled text view. Set text rect in BTextControl::DoLayout() and ScreenSaver PreviewView::AddPreview(). Don't add padding if BTextView::SetInsets() is called. Set insets to 0 in Tracker "Edit name" setting which prevents default padding from being added. This is so that when you rename a file in Tracker the TextView appears on top of the file name text with no padding. 80 char limit fixes. Fixes #1651 #12608 #13796 #15189 #15688 Change-Id: I8c6106effc612f49aff374f29742471628b5df86 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3054 Reviewed-by: Adrien Destugues --- 3rdparty/mmu_man/irc/Haiku/plugin.py | 2 +- headers/os/interface/TextView.h | 5 +- src/kits/interface/TextControl.cpp | 7 +- src/kits/interface/TextInput.cpp | 42 +-- src/kits/interface/TextInput.h | 4 +- src/kits/interface/TextView.cpp | 362 +++++++++++++------- src/kits/tracker/TextWidget.cpp | 1 + src/kits/tracker/infowindow/HeaderView.cpp | 2 - src/preferences/screensaver/PreviewView.cpp | 1 + 9 files changed, 251 insertions(+), 175 deletions(-) diff --git a/3rdparty/mmu_man/irc/Haiku/plugin.py b/3rdparty/mmu_man/irc/Haiku/plugin.py index 1bdb6cb276..246d2157a3 100644 --- a/3rdparty/mmu_man/irc/Haiku/plugin.py +++ b/3rdparty/mmu_man/irc/Haiku/plugin.py @@ -136,7 +136,7 @@ class Haiku(callbacks.Plugin): to = None if len(args) > 0: to = args[0] - t = "Current release: http://www.haiku-os.org/get-haiku - Nightly builds: http://haiku-files.org/haiku/development/" + t = "Current release: http://www.haiku-os.org/get-haiku - Nightly builds: http://download.haiku-os.org" irc.reply(t, to = to) def dl(self, irc, msg, args): diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index b4a684afce..6fa7874d31 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -1,5 +1,5 @@ /* - * Copyright 2007-2009, Haiku, Inc. All rights reserved. + * Copyright 2007-2020 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _TEXTVIEW_H @@ -416,6 +416,7 @@ private: LineBuffer* fLines; StyleBuffer* fStyles; BRect fTextRect; + BRect fAlignedTextRect; int32 fSelStart; int32 fSelEnd; bool fCaretVisible; @@ -463,7 +464,7 @@ private: bool fInstalledRemoveCommandWordwiseShortcuts : 1; bool fInstalledRemoveOptionWordwiseShortcuts : 1; - uint32 _reserved[6]; + uint32 _reserved[2]; }; #endif // _TEXTVIEW_H diff --git a/src/kits/interface/TextControl.cpp b/src/kits/interface/TextControl.cpp index a6a88049a2..0eb7c60e72 100644 --- a/src/kits/interface/TextControl.cpp +++ b/src/kits/interface/TextControl.cpp @@ -1,11 +1,12 @@ /* - * Copyright 2001-2015, Haiku Inc. + * Copyright 2001-2020 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Frans van Nispen (xlr8@tref.nl) * Stephan Aßmus * Ingo Weinhold + * John Scipione */ @@ -637,7 +638,6 @@ void BTextControl::SetAlignment(alignment labelAlignment, alignment textAlignment) { fText->SetAlignment(textAlignment); - fText->AlignTextRect(); if (fLabelAlign != labelAlignment) { fLabelAlign = labelAlignment; @@ -911,6 +911,7 @@ BTextControl::DoLayout() // place the text view and set the divider textFrame.InsetBy(kFrameMargin, kFrameMargin); BLayoutUtils::AlignInFrame(fText, textFrame); + fText->SetTextRect(textFrame.OffsetToCopy(B_ORIGIN)); fDivider = divider; @@ -1115,7 +1116,6 @@ BTextControl::_InitText(const char* initialText, const BMessage* archive) SetText(initialText); fText->SetAlignment(B_ALIGN_LEFT); - fText->AlignTextRect(); } // Although this is not strictly initializing the text view, @@ -1171,7 +1171,6 @@ BTextControl::_LayoutTextView() frame.InsetBy(kFrameMargin, kFrameMargin); fText->MoveTo(frame.left, frame.top); fText->ResizeTo(frame.Width(), frame.Height()); - fText->AlignTextRect(); TRACE("width: %.2f, height: %.2f\n", Frame().Width(), Frame().Height()); TRACE("fDivider: %.2f\n", fDivider); diff --git a/src/kits/interface/TextInput.cpp b/src/kits/interface/TextInput.cpp index d589bf9437..dc7380ba60 100644 --- a/src/kits/interface/TextInput.cpp +++ b/src/kits/interface/TextInput.cpp @@ -1,10 +1,11 @@ /* - * Copyright 2001-2015, Haiku Inc. All rights reserved. + * Copyright 2001-2020 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Frans van Nispen (xlr8@tref.nl) * Marc Flerackers (mflerackers@androme.be) + * John Scipione (jscipione@gmail.com) */ @@ -14,7 +15,6 @@ #include #include -#include #include #include #include @@ -84,8 +84,6 @@ void _BTextInput_::FrameResized(float width, float height) { BTextView::FrameResized(width, height); - - AlignTextRect(); } @@ -162,42 +160,6 @@ _BTextInput_::MinSize() } -void -_BTextInput_::AlignTextRect() -{ - // the label font could require the control to be higher than - // necessary for the text view, we compensate this by layouting - // the text rect to be in the middle, normally this means there - // is one pixel spacing on each side - BRect textRect(Bounds()); - float vInset = max_c(1, - floorf((textRect.Height() - LineHeight(0)) / 2.0)); - float hInset = 2; - float textFontWidth = TextRect().right; - - switch (Alignment()) { - case B_ALIGN_LEFT: - hInset = be_control_look->DefaultLabelSpacing(); - break; - - case B_ALIGN_RIGHT: - hInset = textRect.right - textFontWidth; - hInset -= be_control_look->DefaultLabelSpacing(); - break; - - case B_ALIGN_CENTER: - hInset = (textRect.right - textFontWidth) / 2.0; - break; - - default: - break; - } - - textRect.InsetBy(hInset, vInset); - SetTextRect(textRect); -} - - void _BTextInput_::SetInitialText() { diff --git a/src/kits/interface/TextInput.h b/src/kits/interface/TextInput.h index 6b1c9a66c3..a90d712646 100644 --- a/src/kits/interface/TextInput.h +++ b/src/kits/interface/TextInput.h @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008, Haiku Inc. All rights reserved. + * Copyright 2001-2020 Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -11,6 +11,7 @@ #ifndef _TEXT_CONTROLI_H #define _TEXT_CONTROLI_H + #include @@ -36,7 +37,6 @@ virtual void MakeFocus(bool focusState = true); virtual BSize MinSize(); - void AlignTextRect(); void SetInitialText(); virtual void Paste(BClipboard *clipboard); diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index 5b0b201668..8528af9aa9 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2015 Haiku, Inc. All rights reserved. + * Copyright 2001-2020 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -25,6 +25,7 @@ #include +#include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -155,12 +157,17 @@ struct BTextView::LayoutData { topInset(0), rightInset(0), bottomInset(0), - valid(false) + valid(false), + overridden(false) { } void UpdateInsets(const BRect& bounds, const BRect& textRect) { + // do not update insets if SetInsets() was called + if (overridden) + return; + // we disallow negative insets, as they would cause parts of the // text to be hidden leftInset = textRect.left >= bounds.left @@ -184,7 +191,8 @@ struct BTextView::LayoutData { BSize min; BSize preferred; - bool valid; + bool valid : 1; + bool overridden : 1; }; @@ -260,7 +268,15 @@ BTextView::BTextView(BRect frame, const char* name, BRect textRect, uint32 resizeMask, uint32 flags) : BView(frame, name, resizeMask, - flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE) + flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE), + fText(NULL), + fLines(NULL), + fStyles(NULL), + fDisallowedChars(NULL), + fUndo(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + fLayoutData(NULL) { _InitObject(textRect, NULL, NULL); SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); @@ -272,7 +288,15 @@ BTextView::BTextView(BRect frame, const char* name, BRect textRect, uint32 resizeMask, uint32 flags) : BView(frame, name, resizeMask, - flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE) + flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE), + fText(NULL), + fLines(NULL), + fStyles(NULL), + fDisallowedChars(NULL), + fUndo(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + fLayoutData(NULL) { _InitObject(textRect, initialFont, initialColor); SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); @@ -282,7 +306,15 @@ BTextView::BTextView(BRect frame, const char* name, BRect textRect, BTextView::BTextView(const char* name, uint32 flags) : BView(name, - flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE) + flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE), + fText(NULL), + fLines(NULL), + fStyles(NULL), + fDisallowedChars(NULL), + fUndo(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + fLayoutData(NULL) { _InitObject(Bounds(), NULL, NULL); SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); @@ -293,7 +325,15 @@ BTextView::BTextView(const char* name, const BFont* initialFont, const rgb_color* initialColor, uint32 flags) : BView(name, - flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE) + flags | B_FRAME_EVENTS | B_PULSE_NEEDED | B_INPUT_METHOD_AWARE), + fText(NULL), + fLines(NULL), + fStyles(NULL), + fDisallowedChars(NULL), + fUndo(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + fLayoutData(NULL) { _InitObject(Bounds(), initialFont, initialColor); SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); @@ -302,7 +342,15 @@ BTextView::BTextView(const char* name, const BFont* initialFont, BTextView::BTextView(BMessage* archive) : - BView(archive) + BView(archive), + fText(NULL), + fLines(NULL), + fStyles(NULL), + fDisallowedChars(NULL), + fUndo(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + fLayoutData(NULL) { CALLED(); BRect rect; @@ -394,8 +442,8 @@ BTextView::~BTextView() delete fStyles; delete fDisallowedChars; delete fUndo; - delete fClickRunner; delete fDragRunner; + delete fClickRunner; delete fLayoutData; } @@ -1106,7 +1154,6 @@ BTextView::SetText(const char* text, int32 length, const text_run_array* runs) // recalculate line breaks and draw the text _Refresh(0, length, false); fCaretOffset = fSelStart = fSelEnd = 0; - ScrollTo(B_ORIGIN); // draw the caret _ShowCaret(); @@ -1681,6 +1728,7 @@ BTextView::LineAt(int32 offset) const int32 lineNum = _LineAt(offset); if (_IsOnEmptyLastLine(offset)) lineNum++; + return lineNum; } @@ -1689,7 +1737,7 @@ int32 BTextView::LineAt(BPoint point) const { int32 lineNum = _LineAt(point); - if ((*fLines)[lineNum + 1]->origin <= point.y - fTextRect.top) + if ((*fLines)[lineNum + 1]->origin <= point.y - fAlignedTextRect.top) lineNum++; return lineNum; @@ -1712,7 +1760,7 @@ BTextView::PointAt(int32 offset, float* _height) const BPoint result; result.x = 0.0; - result.y = line->origin + fTextRect.top; + result.y = line->origin + fAlignedTextRect.top; bool onEmptyLastLine = _IsOnEmptyLastLine(offset); @@ -1738,14 +1786,14 @@ BTextView::PointAt(int32 offset, float* _height) const if (fAlignment != B_ALIGN_LEFT) { float lineWidth = onEmptyLastLine ? 0.0 : LineWidth(lineNum); - float alignmentOffset = fTextRect.Width() - lineWidth; + float alignmentOffset = fAlignedTextRect.Width() - lineWidth; if (fAlignment == B_ALIGN_CENTER) - alignmentOffset /= 2; + alignmentOffset = floorf(alignmentOffset / 2); result.x += alignmentOffset; } // convert from text rect coordinates - result.x += fTextRect.left; + result.x += fAlignedTextRect.left; // round up result.x = lroundf(result.x); @@ -1763,9 +1811,9 @@ BTextView::OffsetAt(BPoint point) const const int32 textLength = fText->Length(); // should we even bother? - if (point.y >= fTextRect.bottom) + if (point.y >= fAlignedTextRect.bottom) return textLength; - else if (point.y < fTextRect.top) + else if (point.y < fAlignedTextRect.top) return 0; int32 lineNum = _LineAt(point); @@ -1779,21 +1827,22 @@ BTextView::OffsetAt(BPoint point) const // lower than the bottom of the last line, return the last offset // (can happen for newlines) if (lineNum == (fLines->NumLines() - 1)) { - if (point.y >= ((line + 1)->origin + fTextRect.top)) + if (point.y >= ((line + 1)->origin + fAlignedTextRect.top)) return textLength; } #endif // convert to text rect coordinates if (fAlignment != B_ALIGN_LEFT) { - float alignmentOffset = fTextRect.Width() - LineWidth(lineNum); + float alignmentOffset = fAlignedTextRect.Width() + - LineWidth(lineNum); if (fAlignment == B_ALIGN_CENTER) - alignmentOffset /= 2; + alignmentOffset = floorf(alignmentOffset / 2); point.x -= alignmentOffset; } - point.x -= fTextRect.left; - point.x = max_c(point.x, 0.0); + point.x -= fAlignedTextRect.left; + point.x = std::max(point.x, 0.0f); // ToDo: The following code isn't very efficient, because it always starts // from the left end, so when the point is near the right end it's very @@ -2020,6 +2069,7 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset, startOffset = 0; else if (startOffset > fText->Length()) startOffset = fText->Length(); + if (endOffset < 0) endOffset = 0; else if (endOffset > fText->Length()) @@ -2041,29 +2091,29 @@ BTextView::GetTextRegion(int32 startOffset, int32 endOffset, if (startPt.y == endPt.y) { // this is a one-line region - selRect.left = max_c(startPt.x, fTextRect.left); + selRect.left = std::max(startPt.x, fAlignedTextRect.left); selRect.top = startPt.y; selRect.right = endPt.x - 1.0; selRect.bottom = endPt.y + endLineHeight - 1.0; outRegion->Include(selRect); } else { // more than one line in the specified offset range - selRect.left = max_c(startPt.x, fTextRect.left); + selRect.left = std::max(startPt.x, fAlignedTextRect.left); selRect.top = startPt.y; - selRect.right = fTextRect.right; + selRect.right = fAlignedTextRect.right; selRect.bottom = startPt.y + startLineHeight - 1.0; outRegion->Include(selRect); if (startPt.y + startLineHeight < endPt.y) { // more than two lines in the range - selRect.left = fTextRect.left; + selRect.left = fAlignedTextRect.left; selRect.top = startPt.y + startLineHeight; - selRect.right = fTextRect.right; + selRect.right = fAlignedTextRect.right; selRect.bottom = endPt.y - 1.0; outRegion->Include(selRect); } - selRect.left = fTextRect.left; + selRect.left = fAlignedTextRect.left; selRect.top = endPt.y; selRect.right = endPt.x - 1.0; selRect.bottom = endPt.y + endLineHeight - 1.0; @@ -2082,13 +2132,10 @@ BTextView::ScrollToOffset(int32 offset) BPoint point = PointAt(offset, &lineHeight); // horizontal - float extraSpace = fAlignment == B_ALIGN_LEFT ? - ceilf(bounds.IntegerWidth() / 2) : 0.0; - if (point.x < bounds.left) - xDiff = point.x - bounds.left - extraSpace; + xDiff = point.x - bounds.right; else if (point.x > bounds.right) - xDiff = point.x - bounds.right + extraSpace; + xDiff = point.x - bounds.left; // vertical if (point.y < bounds.top) @@ -2156,6 +2203,9 @@ BTextView::SetTextRect(BRect rect) fLayoutData->UpdateInsets(Bounds().OffsetToCopy(B_ORIGIN), rect); + fTextRect = rect; + fAlignedTextRect = fTextRect; + _ResetTextRect(); } @@ -2170,21 +2220,21 @@ BTextView::TextRect() const void BTextView::_ResetTextRect() { - BRect oldTextRect(fTextRect); - // reset text rect to bounds minus insets ... - fTextRect = Bounds().OffsetToCopy(B_ORIGIN); - fTextRect.left += fLayoutData->leftInset; - fTextRect.top += fLayoutData->topInset; - fTextRect.right -= fLayoutData->rightInset; - fTextRect.bottom -= fLayoutData->bottomInset; + BRect oldTextRect(fAlignedTextRect); + // reset text rect to old text bounds minus insets + fAlignedTextRect = fTextRect; + fAlignedTextRect.left += fLayoutData->leftInset; + fAlignedTextRect.top += fLayoutData->topInset; + fAlignedTextRect.right -= fLayoutData->rightInset; + fAlignedTextRect.bottom -= fLayoutData->bottomInset; // and rewrap (potentially adjusting the right and the bottom of the text // rect) _Refresh(0, TextLength(), false); // Make sure that the dirty area outside the text is redrawn too. - BRegion invalid(oldTextRect | fTextRect); - invalid.Exclude(fTextRect); + BRegion invalid(oldTextRect | fAlignedTextRect); + invalid.Exclude(fAlignedTextRect); Invalidate(&invalid); } @@ -2203,6 +2253,8 @@ BTextView::SetInsets(float left, float top, float right, float bottom) fLayoutData->rightInset = right; fLayoutData->bottomInset = bottom; + fLayoutData->overridden = true; + InvalidateLayout(); Invalidate(); } @@ -2324,8 +2376,9 @@ BTextView::SetWordWrap(bool wrap) fWrap = wrap; if (wrap) - _ResetTextRect(); - _Refresh(0, fText->Length(), false); + _ResetTextRect(); // calls _Refresh + else + _Refresh(0, fText->Length(), false); if (updateOnScreen) { // show the caret, hilite the selection @@ -2613,15 +2666,15 @@ BTextView::GetHeightForWidth(float width, float* min, float* max, } // TODO: don't change the actual text rect! - fTextRect.right = fTextRect.left + width; + fAlignedTextRect.right = fAlignedTextRect.left + width; _Refresh(0, TextLength(), false); if (min != NULL) - *min = fTextRect.Height(); + *min = fAlignedTextRect.Height(); if (max != NULL) *max = B_SIZE_UNLIMITED; if (preferred != NULL) - *preferred = fTextRect.Height(); + *preferred = fAlignedTextRect.Height(); } @@ -2662,6 +2715,12 @@ BTextView::DoLayout() if (size.height < fLayoutData->min.height) size.height = fLayoutData->min.height; + // reset insets to 0 unless SetInsets() was called + BRect bounds(Bounds()); + fLayoutData->UpdateInsets(Bounds().OffsetToCopy(B_ORIGIN), bounds); + // reset text rect to Bounds() + fTextRect = bounds; + fAlignedTextRect = fTextRect; _ResetTextRect(); } @@ -2685,7 +2744,7 @@ BTextView::_ValidateLayoutData() fLayoutData->min = min; // compute our preferred size - fLayoutData->preferred.height = fTextRect.Height() + fLayoutData->preferred.height = fAlignedTextRect.Height() + fLayoutData->topInset + fLayoutData->bottomInset; if (fWrap) @@ -3094,6 +3153,7 @@ BTextView::_InitObject(BRect textRect, const BFont* initialFont, // to have less code duplication, and a single place where to do changes // if needed. fTextRect = textRect; + fAlignedTextRect = textRect; // NOTE: The only places where text rect is changed: // * width is possibly adjusted in _AutoResize(), // * height is adjusted in _RecalculateLineBreaks(). @@ -3130,7 +3190,7 @@ BTextView::_InitObject(BRect textRect, const BFont* initialFont, fTrackingMouse = NULL; fLayoutData = new LayoutData; - fLayoutData->UpdateInsets(Bounds().OffsetToCopy(B_ORIGIN), fTextRect); + fLayoutData->UpdateInsets(Bounds().OffsetToCopy(B_ORIGIN), textRect); fLastClickOffset = -1; @@ -3319,7 +3379,8 @@ BTextView::_HandleArrowKey(uint32 arrowKey, int32 modifiers) if (optionKeyDown && !commandKeyDown && !controlKeyDown) fCaretOffset = _NextLineEnd(fCaretOffset); else if (commandKeyDown && !optionKeyDown && !controlKeyDown) { - _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); + _ScrollTo(0, fAlignedTextRect.bottom + + fLayoutData->bottomInset); fCaretOffset = fText->Length(); } else { float height; @@ -3382,8 +3443,7 @@ BTextView::_HandleDelete(int32 modifiers) } if (fUndo) { - TypingUndoBuffer* undoBuffer = dynamic_cast( - fUndo); + TypingUndoBuffer* undoBuffer = dynamic_cast(fUndo); if (!undoBuffer) { delete fUndo; fUndo = undoBuffer = new TypingUndoBuffer(this); @@ -3465,11 +3525,13 @@ BTextView::_HandlePageKey(uint32 pageKey, int32 modifiers) case B_END: if (!fEditable) { fCaretOffset = fText->Length(); - _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); + _ScrollTo(0, fAlignedTextRect.bottom + + fLayoutData->bottomInset); break; } else { if (commandKeyDown && !optionKeyDown && !controlKeyDown) { - _ScrollTo(0, fTextRect.bottom + fLayoutData->bottomInset); + _ScrollTo(0, fAlignedTextRect.bottom + + fLayoutData->bottomInset); fCaretOffset = fText->Length(); } else { // If we are on the last line, just go to the last @@ -3622,7 +3684,6 @@ BTextView::_HandleAlphaKey(const char* bytes, int32 numBytes) _DoInsertText(bytes, numBytes, fSelStart, NULL); fCaretOffset = fSelEnd; - ScrollToOffset(fCaretOffset); } @@ -3638,8 +3699,8 @@ void BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool scroll) { // TODO: Cleanup - float saveHeight = fTextRect.Height(); - float saveWidth = fTextRect.Width(); + float saveHeight = fAlignedTextRect.Height(); + float saveWidth = fAlignedTextRect.Width(); int32 fromLine = _LineAt(fromOffset); int32 toLine = _LineAt(toOffset); int32 saveFromLine = fromLine; @@ -3652,7 +3713,7 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool scroll) return; BRect bounds = Bounds(); - float newHeight = fTextRect.Height(); + float newHeight = fAlignedTextRect.Height(); // if the line breaks have changed, force an erase if (fromLine != saveFromLine || toLine != saveToLine @@ -3662,17 +3723,20 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool scroll) if (newHeight != saveHeight) { // the text area has changed - if (newHeight < saveHeight) - toLine = _LineAt(BPoint(0.0f, saveHeight + fTextRect.top)); - else - toLine = _LineAt(BPoint(0.0f, newHeight + fTextRect.top)); + if (newHeight < saveHeight) { + toLine = _LineAt(BPoint(0.0f, + saveHeight + fAlignedTextRect.top)); + } else { + toLine = _LineAt(BPoint(0.0f, + newHeight + fAlignedTextRect.top)); + } } // draw only those lines that are visible int32 fromVisible = _LineAt(BPoint(0.0f, bounds.top)); int32 toVisible = _LineAt(BPoint(0.0f, bounds.bottom)); - fromLine = max_c(fromVisible, fromLine); - toLine = min_c(toLine, toVisible); + fromLine = std::max(fromVisible, fromLine); + toLine = std::min(toLine, toVisible); _AutoResize(false); @@ -3680,8 +3744,9 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool scroll) // erase the area below the text BRect eraseRect = bounds; - eraseRect.top = fTextRect.top + (*fLines)[fLines->NumLines()]->origin; - eraseRect.bottom = fTextRect.top + saveHeight; + eraseRect.top = fAlignedTextRect.top + + (*fLines)[fLines->NumLines()]->origin; + eraseRect.bottom = fAlignedTextRect.top + saveHeight; if (eraseRect.bottom > eraseRect.top && eraseRect.Intersects(bounds)) { SetLowColor(ViewColor()); FillRect(eraseRect, B_SOLID_LOW); @@ -3708,7 +3773,7 @@ BTextView::_RecalculateLineBreaks(int32* startLine, int32* endLine) { CALLED(); - float width = fTextRect.Width(); + float width = fAlignedTextRect.Width(); // Don't try to compute anything if the text rect is not set if (width <= 0) @@ -3780,16 +3845,61 @@ BTextView::_RecalculateLineBreaks(int32* startLine, int32* endLine) // has always a width of 0 (*fLines)[fLines->NumLines()]->width = 0; - // update the text rect + // update fAlignedTextRect, leave fTextRect alone + fAlignedTextRect = fTextRect; + + // adjust insets + fAlignedTextRect.left += fLayoutData->leftInset; + fAlignedTextRect.top += fLayoutData->topInset; + fAlignedTextRect.right -= fLayoutData->rightInset; + fAlignedTextRect.bottom -= fLayoutData->bottomInset; + + // Set new bottom based on text height unless bottom is below + // the bottom of text height already. float newHeight = TextHeight(0, fLines->NumLines() - 1); - fTextRect.bottom = fTextRect.top + newHeight; + fAlignedTextRect.bottom = std::max(fAlignedTextRect.bottom, + fAlignedTextRect.top + newHeight); + + bool doPadding = !fLayoutData->overridden && (fEditable || fSelectable); + float hPadding = doPadding ? be_control_look->DefaultLabelSpacing() : 0; + + // new min width if (!fWrap) { fMinTextRectWidth = fLines->MaxWidth(); - fTextRect.right = ceilf(fTextRect.left + fMinTextRectWidth); + + // expand width if needed (including padding) + switch (fAlignment) { + default: + case B_ALIGN_LEFT: + // grow right + fAlignedTextRect.right = std::max(fAlignedTextRect.right, + fAlignedTextRect.left + hPadding + fMinTextRectWidth); + break; + + case B_ALIGN_RIGHT: + // grow left + fAlignedTextRect.left = std::min(fAlignedTextRect.left, + fAlignedTextRect.right - hPadding - fMinTextRectWidth); + break; + + case B_ALIGN_CENTER: + // grow out + if (fMinTextRectWidth + hPadding > fAlignedTextRect.Width()) { + fAlignedTextRect.InsetBy(ceilf((fAlignedTextRect.Width() + - hPadding - fMinTextRectWidth) / 2.0f), 0); + } + break; + } + } + + if (doPadding) { + float hInset = floorf(hPadding / 2.0f); + float vInset = 1; + fAlignedTextRect.InsetBy(hInset, vInset); } *endLine = lineIndex - 1; - *startLine = min_c(*startLine, *endLine); + *startLine = std::min(*startLine, *endLine); } @@ -3880,7 +3990,7 @@ BTextView::_FindLineBreak(int32 fromOffset, float* _ascent, float* _descent, } } - delta = max_c(delta, 1); + delta = std::max(delta, (int32)1); // do not include B_ENTER-terminator into width & height calculations deltaWidth = _TabExpandedStyledWidth(offset, @@ -3911,8 +4021,8 @@ BTextView::_FindLineBreak(int32 fromOffset, float* _ascent, float* _descent, } } - *_ascent = max_c(ascent, *_ascent); - *_descent = max_c(descent, *_descent); + *_ascent = std::max(ascent, *_ascent); + *_descent = std::max(descent, *_descent); offset += delta; delta = 0; @@ -3935,12 +4045,12 @@ BTextView::_FindLineBreak(int32 fromOffset, float* _ascent, float* _descent, break; } - *_ascent = max_c(ascent, *_ascent); - *_descent = max_c(descent, *_descent); + *_ascent = std::max(ascent, *_ascent); + *_descent = std::max(descent, *_descent); } } - return min_c(offset, limit); + return std::min(offset, limit); } @@ -4137,8 +4247,8 @@ BTextView::_StyledWidth(int32 fromOffset, int32 length, float* _ascent, int32 numBytes; while ((numBytes = fStyles->Iterate(fromOffset, length, fInline, &font, NULL, &ascent, &descent)) != 0) { - maxAscent = max_c(ascent, maxAscent); - maxDescent = max_c(descent, maxDescent); + maxAscent = std::max(ascent, maxAscent); + maxDescent = std::max(descent, maxDescent); #if USE_WIDTHBUFFER // Use _BWidthBuffer_ if possible @@ -4216,19 +4326,20 @@ BTextView::_DrawLine(BView* view, const int32 &lineNum, BRegion &inputRegion) { STELine* line = (*fLines)[lineNum]; - float startLeft = fTextRect.left; + float startLeft = fAlignedTextRect.left; + if (startOffset != -1) { if (ByteAt(startOffset) == B_ENTER) { // StartOffset is a newline startLeft = PointAt(line->offset).x; } else startLeft = PointAt(startOffset).x; - } - else if (fAlignment != B_ALIGN_LEFT) { - float alignmentOffset = fTextRect.Width() - LineWidth(lineNum); + } else if (fAlignment != B_ALIGN_LEFT) { + float alignmentOffset = fAlignedTextRect.Width() + - LineWidth(lineNum); if (fAlignment == B_ALIGN_CENTER) - alignmentOffset /= 2; - startLeft = fTextRect.left + alignmentOffset; + alignmentOffset = floorf(alignmentOffset / 2); + startLeft = fAlignedTextRect.left + alignmentOffset; } int32 length = (line + 1)->offset; @@ -4241,11 +4352,12 @@ BTextView::_DrawLine(BView* view, const int32 &lineNum, if (ByteAt((line + 1)->offset - 1) == B_ENTER) length--; - view->MovePenTo(startLeft, line->origin + line->ascent + fTextRect.top + 1); + view->MovePenTo(startLeft, + line->origin + line->ascent + fAlignedTextRect.top + 1); if (erase) { - eraseRect.top = line->origin + fTextRect.top; - eraseRect.bottom = (line + 1)->origin + fTextRect.top; + eraseRect.top = line->origin + fAlignedTextRect.top; + eraseRect.bottom = (line + 1)->origin + fAlignedTextRect.top; view->FillRect(eraseRect, B_SOLID_LOW); } @@ -4267,7 +4379,7 @@ BTextView::_DrawLine(BView* view, const int32 &lineNum, view->SetFont(font); view->SetHighColor(*color); - tabChars = min_c(numBytes, length); + tabChars = std::min(numBytes, length); do { foundTab = fText->FindChar(B_TAB, offset, &tabChars); if (foundTab) { @@ -4316,11 +4428,12 @@ BTextView::_DrawLine(BView* view, const int32 &lineNum, } int32 returnedBytes = tabChars; - const char* stringToDraw = fText->GetString(offset, &returnedBytes); + const char* stringToDraw + = fText->GetString(offset, &returnedBytes); view->SetDrawingMode(textRenderingMode); view->DrawString(stringToDraw, returnedBytes); if (foundTab) { - float penPos = PenLocation().x - fTextRect.left; + float penPos = PenLocation().x - fAlignedTextRect.left; float tabWidth = _ActualTabWidth(penPos); if (numTabs > 1) tabWidth += ((numTabs - 1) * fTabWidth); @@ -4332,7 +4445,7 @@ BTextView::_DrawLine(BView* view, const int32 &lineNum, offset += tabChars; length -= tabChars; numBytes -= tabChars; - tabChars = min_c(numBytes, length); + tabChars = std::min(numBytes, length); numTabs = 0; } while (foundTab && tabChars > 0); } @@ -4347,9 +4460,9 @@ BTextView::_DrawLines(int32 startLine, int32 endLine, int32 startOffset, return; // clip the text - BRect textRect(fTextRect); - float minWidth - = Bounds().Width() - fLayoutData->leftInset - fLayoutData->rightInset; + BRect textRect(fAlignedTextRect); + float minWidth = Bounds().Width() - fLayoutData->leftInset + - fLayoutData->rightInset; if (textRect.Width() < minWidth) textRect.right = textRect.left + minWidth; BRect clipRect = Bounds() & textRect; @@ -4395,7 +4508,7 @@ BTextView::_DrawLines(int32 startLine, int32 endLine, int32 startOffset, BPoint erasePoint = PointAt(startErase); eraseRect.left = erasePoint.x; eraseRect.top = erasePoint.y; - eraseRect.bottom = (line + 1)->origin + fTextRect.top; + eraseRect.bottom = (line + 1)->origin + fAlignedTextRect.top; view->FillRect(eraseRect, B_SOLID_LOW); @@ -4450,9 +4563,10 @@ BTextView::_RequestDrawLines(int32 startLine, int32 endLine) STELine* from = (*fLines)[startLine]; STELine* to = endLine == maxLine ? NULL : (*fLines)[endLine + 1]; - BRect invalidRect(Bounds().left, from->origin + fTextRect.top, + BRect invalidRect(Bounds().left, from->origin + fAlignedTextRect.top, Bounds().right, - to != NULL ? to->origin + fTextRect.top : fTextRect.bottom); + to != NULL ? to->origin + fAlignedTextRect.top + : fAlignedTextRect.bottom); Invalidate(invalidRect); Window()->UpdateIfNeeded(); } @@ -4463,7 +4577,7 @@ BTextView::_DrawCaret(int32 offset, bool visible) { float lineHeight; BPoint caretPoint = PointAt(offset, &lineHeight); - caretPoint.x = min_c(caretPoint.x, fTextRect.right); + caretPoint.x = std::min(caretPoint.x, fAlignedTextRect.right); BRect caretRect; caretRect.left = caretRect.right = caretPoint.x; @@ -4794,15 +4908,15 @@ BTextView::_PerformAutoScrolling() // R5 does a pretty soft auto-scroll, we try to do the same by // simply scrolling the distance between cursor and border - if (fWhere.x > bounds.right) { + if (fWhere.x > bounds.right) scrollBy.x = fWhere.x - bounds.right; - } else if (fWhere.x < bounds.left) { + else if (fWhere.x < bounds.left) scrollBy.x = fWhere.x - bounds.left; // negative value - } // prevent from scrolling out of view if (scrollBy.x != 0.0) { - float rightMax = floorf(fTextRect.right + fLayoutData->rightInset); + float rightMax = floorf(fAlignedTextRect.right + + fLayoutData->rightInset); if (bounds.right + scrollBy.x > rightMax) scrollBy.x = rightMax - bounds.right; if (bounds.left + scrollBy.x < 0) @@ -4811,15 +4925,14 @@ BTextView::_PerformAutoScrolling() if (CountLines() > 1) { // scroll in Y only if multiple lines! - if (fWhere.y > bounds.bottom) { + if (fWhere.y > bounds.bottom) scrollBy.y = fWhere.y - bounds.bottom; - } else if (fWhere.y < bounds.top) { + else if (fWhere.y < bounds.top) scrollBy.y = fWhere.y - bounds.top; // negative value - } // prevent from scrolling out of view if (scrollBy.y != 0.0) { - float bottomMax = floorf(fTextRect.bottom + float bottomMax = floorf(fAlignedTextRect.bottom + fLayoutData->bottomInset); if (bounds.bottom + scrollBy.y > bottomMax) scrollBy.y = bottomMax - bounds.bottom; @@ -4844,11 +4957,11 @@ BTextView::_UpdateScrollbars() // do we have a horizontal scroll bar? if (horizontalScrollBar != NULL) { long viewWidth = bounds.IntegerWidth(); - long dataWidth = (long)ceilf(fTextRect.IntegerWidth() + long dataWidth = (long)ceilf(fAlignedTextRect.IntegerWidth() + fLayoutData->leftInset + fLayoutData->rightInset); long maxRange = dataWidth - viewWidth; - maxRange = max_c(maxRange, 0); + maxRange = std::max(maxRange, 0l); horizontalScrollBar->SetRange(0, (float)maxRange); horizontalScrollBar->SetProportion((float)viewWidth / (float)dataWidth); @@ -4858,11 +4971,11 @@ BTextView::_UpdateScrollbars() // how about a vertical scroll bar? if (verticalScrollBar != NULL) { long viewHeight = bounds.IntegerHeight(); - long dataHeight = (long)ceilf(fTextRect.IntegerHeight() - + fLayoutData->topInset + fLayoutData->bottomInset); + long dataHeight = (long)ceilf(fLayoutData->topInset + + fAlignedTextRect.IntegerHeight() + fLayoutData->bottomInset); long maxRange = dataHeight - viewHeight; - maxRange = max_c(maxRange, 0); + maxRange = std::max(maxRange, 0L); verticalScrollBar->SetRange(0, maxRange); verticalScrollBar->SetProportion((float)viewHeight / (float)dataHeight); @@ -4888,13 +5001,13 @@ BTextView::_ScrollTo(float x, float y) long viewWidth = bounds.IntegerWidth(); long viewHeight = bounds.IntegerHeight(); - if (x > fTextRect.right - viewWidth) - x = fTextRect.right - viewWidth; + if (x > fAlignedTextRect.right - viewWidth) + x = fAlignedTextRect.right - viewWidth; if (x < 0.0) x = 0.0; - if (y > fTextRect.bottom + fLayoutData->bottomInset - viewHeight) - y = fTextRect.bottom + fLayoutData->bottomInset - viewHeight; + if (y > fAlignedTextRect.bottom + fLayoutData->bottomInset - viewHeight) + y = fAlignedTextRect.bottom + fLayoutData->bottomInset - viewHeight; if (y < 0.0) y = 0.0; @@ -4910,13 +5023,13 @@ BTextView::_AutoResize(bool redraw) return; BRect bounds = Bounds(); - float oldWidth = bounds.Width(); - float newWidth = ceilf(fLayoutData->leftInset + fTextRect.Width() - + fLayoutData->rightInset); if (fContainerView != NULL) { // NOTE: This container view thing is only used by Tracker. // move container view if not left aligned + float oldWidth = bounds.Width(); + float newWidth = ceilf(fLayoutData->leftInset + + fAlignedTextRect.Width() + fLayoutData->rightInset); if (fAlignment == B_ALIGN_CENTER) { if (fmod(ceilf(newWidth - oldWidth), 2.0) != 0.0) newWidth += 1; @@ -4934,8 +5047,8 @@ BTextView::_AutoResize(bool redraw) // erase any potential left over outside the text rect // (can only be on right hand side) - BRect dirty(fTextRect.right + 1, fTextRect.top, bounds.right, - fTextRect.bottom); + BRect dirty(fAlignedTextRect.right + 1, fAlignedTextRect.top, + bounds.right, fAlignedTextRect.bottom); if (dirty.IsValid()) { SetLowColor(ViewColor()); FillRect(dirty, B_SOLID_LOW); @@ -4951,8 +5064,9 @@ BTextView::_NewOffscreen(float padding) _DeleteOffscreen(); #if USE_DOUBLEBUFFERING - BRect bitmapRect(0, 0, fTextRect.Width() + padding, fTextRect.Height()); - fOffscreen = new BBitmap(bitmapRect, fColorSpace, true, false); + BRect bitmapRect(0, 0, fAlignedTextRect.Width() + padding, + fAlignedTextRect.Height()); + fOffscreen = new BBitmap(bitm->Rect, fColorSpace, true, false); if (fOffscreen != NULL && fOffscreen->Lock()) { BView* bufferView = new BView(bitmapRect, "drawing view", 0, 0); fOffscreen->AddChild(bufferView); @@ -5666,7 +5780,7 @@ BTextView::_LineAt(int32 offset) const int32 BTextView::_LineAt(const BPoint& point) const { - return fLines->PixelToLine(point.y - fTextRect.top); + return fLines->PixelToLine(point.y - fAlignedTextRect.top); } diff --git a/src/kits/tracker/TextWidget.cpp b/src/kits/tracker/TextWidget.cpp index 14b61556be..8b8ab24045 100644 --- a/src/kits/tracker/TextWidget.cpp +++ b/src/kits/tracker/TextWidget.cpp @@ -379,6 +379,7 @@ BTextWidget::StartEdit(BRect bounds, BPoseView* view, BPose* pose) textView->SetWordWrap(false); DisallowMetaKeys(textView); + textView->SetInsets(0, 0, 0, 0); fText->SetUpEditing(textView); textView->AddFilter(new BMessageFilter(B_KEY_DOWN, TextViewFilter)); diff --git a/src/kits/tracker/infowindow/HeaderView.cpp b/src/kits/tracker/infowindow/HeaderView.cpp index 02b4522bac..6bb4d226a5 100644 --- a/src/kits/tracker/infowindow/HeaderView.cpp +++ b/src/kits/tracker/infowindow/HeaderView.cpp @@ -302,7 +302,6 @@ HeaderView::Draw(BRect) // Font information font_height fontMetrics; BFont currentFont; - float lineHeight = 0; float lineBase = 0; // Draw the main title if the user is not currently editing it @@ -311,7 +310,6 @@ HeaderView::Draw(BRect) SetFontSize(be_bold_font->Size()); GetFont(¤tFont); currentFont.GetHeight(&fontMetrics); - lineHeight = CurrentFontHeight() + 5; lineBase = fTitleRect.bottom - fontMetrics.descent; SetHighColor(labelColor); MovePenTo(BPoint(fIconRect.right + 6, lineBase)); diff --git a/src/preferences/screensaver/PreviewView.cpp b/src/preferences/screensaver/PreviewView.cpp index 8301089a0e..e6cea52440 100644 --- a/src/preferences/screensaver/PreviewView.cpp +++ b/src/preferences/screensaver/PreviewView.cpp @@ -146,6 +146,7 @@ PreviewView::AddPreview() fNoPreview->SetExplicitSize(BSize(previewWidth, previewHeight)); fNoPreview->ResizeTo(previewWidth, previewHeight); + fNoPreview->SetTextRect(BRect(0, 0, previewWidth, previewHeight)); fNoPreview->SetInsets(0, previewHeight / 3, 0 , 0); return fSaverView;