diff --git a/headers/os/interface/TextControl.h b/headers/os/interface/TextControl.h index 6f4af72c73..dcf1ed9455 100644 --- a/headers/os/interface/TextControl.h +++ b/headers/os/interface/TextControl.h @@ -10,8 +10,9 @@ #include class BLayoutItem; +namespace BPrivate { class _BTextInput_; - +} class BTextControl : public BControl { public: @@ -105,7 +106,7 @@ class BTextControl : public BControl { void _UpdateFrame(); private: - _BTextInput_* fText; + BPrivate::_BTextInput_* fText; char* fLabel; BMessage* fModificationMessage; alignment fLabelAlign; diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index 994c217a58..de356b4be7 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -315,6 +315,8 @@ class BTextView : public BView { _BLineBuffer_* fLines; _BStyleBuffer_* fStyles; BRect fTextRect; + float fLeftInset; + float fRightInset; int32 fSelStart; int32 fSelEnd; bool fCaretVisible; @@ -345,7 +347,7 @@ class BTextView : public BView { BPoint fWhere; _BTextTrackState_* fTrackingMouse; _BTextChangeResult_* fTextChange; - uint32 _reserved[9]; + uint32 _reserved[7]; static _BWidthBuffer_* sWidths; static sem_id sWidthSem; diff --git a/src/kits/interface/TextControl.cpp b/src/kits/interface/TextControl.cpp index 962b0f15c7..bc11c80e35 100644 --- a/src/kits/interface/TextControl.cpp +++ b/src/kits/interface/TextControl.cpp @@ -333,24 +333,26 @@ BTextControl::Draw(BRect updateRect) // label if (Label()) { - font_height fontHeight; - GetFontHeight(&fontHeight); + font_height fh; + GetFontHeight(&fh); - float y = fontHeight.ascent + fText->Frame().top + 1; + float y = Bounds().top + + (Bounds().Height() + 1 - fh.ascent - fh.descent) / 2 + + fh.ascent; float x; float labelWidth = StringWidth(Label()); switch (fLabelAlign) { case B_ALIGN_RIGHT: - x = fDivider - labelWidth - 3.0f; + x = fDivider - labelWidth - 3.0; break; case B_ALIGN_CENTER: - x = fDivider - labelWidth / 2.0f; + x = fDivider - labelWidth / 2.0; break; default: - x = 3.0f; + x = 0.0; break; } @@ -373,7 +375,6 @@ BTextControl::MouseDown(BPoint where) { if (!fText->IsFocus()) { fText->MakeFocus(true); - fText->SelectAll(); } } @@ -428,7 +429,7 @@ BTextControl::GetPreferredSize(float *_width, float *_height) GetFontHeight(&fontHeight); float labelHeight = ceil(fontHeight.ascent + fontHeight.descent + fontHeight.leading); - float textHeight = ceilf(fText->LineHeight(0)) + 4.0; + float textHeight = ceilf(fText->LineHeight(0) + 1.0) + 4.0; *_height = max_c(labelHeight, textHeight); } @@ -730,7 +731,7 @@ BTextControl::_InitData(const char* label, const char* initialText, } if (archive) - fText = static_cast<_BTextInput_ *>(FindView("_input_")); + fText = static_cast(FindView("_input_")); else { BRect frame(fDivider, bounds.top, bounds.right, bounds.bottom); @@ -739,7 +740,7 @@ BTextControl::_InitData(const char* label, const char* initialText, frame.InsetBy(2.0, 3.0); BRect textRect(frame.OffsetToCopy(B_ORIGIN)); - fText = new _BTextInput_(frame, textRect, + fText = new BPrivate::_BTextInput_(frame, textRect, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS | navigableFlags); AddChild(fText); @@ -775,16 +776,7 @@ BTextControl::_LayoutTextView() frame.InsetBy(2.0, 2.0); fText->MoveTo(frame.left, frame.top); fText->ResizeTo(frame.Width(), frame.Height()); - - BRect textRect(frame.OffsetToCopy(B_ORIGIN)); - - // 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 - float lineHeight = ceilf(fText->LineHeight(0)); - textRect.InsetBy(1, floorf((frame.Height() - lineHeight) / 2)); - fText->SetTextRect(textRect); + fText->AlignTextRect(); } diff --git a/src/kits/interface/TextInput.cpp b/src/kits/interface/TextInput.cpp index 109393124b..784945feec 100644 --- a/src/kits/interface/TextInput.cpp +++ b/src/kits/interface/TextInput.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2007, Haiku Inc. + * Copyright 2001-2008, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -20,20 +20,21 @@ #include "TextInput.h" +namespace BPrivate { + + _BTextInput_::_BTextInput_(BRect frame, BRect textRect, uint32 resizeMask, - uint32 flags) - : BTextView(frame, "_input_", textRect, resizeMask, flags), - fPreviousText(NULL), - fBool(false) + uint32 flags) + : BTextView(frame, "_input_", textRect, resizeMask, flags) + , fPreviousText(NULL) { MakeResizable(true); } -_BTextInput_::_BTextInput_(BMessage *archive) - : BTextView(archive), - fPreviousText(NULL), - fBool(false) +_BTextInput_::_BTextInput_(BMessage* archive) + : BTextView(archive) + , fPreviousText(NULL) { MakeResizable(true); } @@ -62,6 +63,19 @@ _BTextInput_::Archive(BMessage *data, bool deep) const } +void +_BTextInput_::MouseDown(BPoint where) +{ + if (!IsFocus()) { + MakeFocus(true); + return; + } + + // only pass through to base class if we already have focus + BTextView::MouseDown(where); +} + + void _BTextInput_::FrameResized(float width, float height) { @@ -116,50 +130,39 @@ _BTextInput_::MakeFocus(bool state) if (state) { SetInitialText(); - - fBool = true; - - if (Window()) { - BMessage *message = Window()->CurrentMessage(); - - if (message && message->what == B_KEY_DOWN) - SelectAll(); - } + SelectAll(); } else { if (strcmp(Text(), fPreviousText) != 0) TextControl()->Invoke(); free(fPreviousText); fPreviousText = NULL; - fBool = false; - - if (Window()) { - BMessage *message = Window()->CurrentMessage(); - - if (message && message->what == B_MOUSE_DOWN) - Select(0, 0); - } } - if (Window()) { +// if (Window()) { // TODO: why do we have to invalidate here? // I'm leaving this in, but it looks suspicious... :-) - Invalidate(Bounds()); +// Invalidate(Bounds()); if (BTextControl* parent = dynamic_cast(Parent())) { BRect frame = Frame(); frame.InsetBy(-1.0, -1.0); parent->Invalidate(frame); } - } +// } } void _BTextInput_::AlignTextRect() { - // TODO: just to get something working, it wouldn't be correct for - // scrolled views + // 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()); + textRect.left = 0.0; + float vInset = max_c(1, floorf((textRect.Height() - LineHeight(0)) / 2.0)); + textRect.InsetBy(2, vInset); SetTextRect(textRect); } @@ -167,10 +170,8 @@ _BTextInput_::AlignTextRect() void _BTextInput_::SetInitialText() { - if (fPreviousText) { - free(fPreviousText); - fPreviousText = NULL; - } + free(fPreviousText); + fPreviousText = NULL; if (Text()) fPreviousText = strdup(Text()); @@ -237,3 +238,7 @@ _BTextInput_::TextControl() return textControl; } + + +} // namespace BPrivate + diff --git a/src/kits/interface/TextInput.h b/src/kits/interface/TextInput.h index 26f6ebbfba..2fd3122286 100644 --- a/src/kits/interface/TextInput.h +++ b/src/kits/interface/TextInput.h @@ -1,60 +1,35 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, OpenBeOS -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// File Name: TextInput.h -// Author: Frans van Nispen (xlr8@tref.nl) -// Description: The BTextView derivative owned by an instance of -// BTextControl. -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Frans van Nispen (xlr8@tref.nl) + */ + +//! The BTextView derivative owned by an instance of BTextControl. #ifndef _TEXT_CONTROLI_H #define _TEXT_CONTROLI_H -// Standard Includes ----------------------------------------------------------- - -// System Includes ------------------------------------------------------------- #include -// Project Includes ------------------------------------------------------------ - -// Local Includes -------------------------------------------------------------- - -// Local Defines --------------------------------------------------------------- - -// Globals --------------------------------------------------------------------- class BTextControl; -// _BTextInput_ class ---------------------------------------------------------- +namespace BPrivate { + class _BTextInput_ : public BTextView { public: _BTextInput_(BRect frame, BRect textRect, uint32 resizeMask, uint32 flags = B_WILL_DRAW | B_PULSE_NEEDED); _BTextInput_(BMessage *data); - ~_BTextInput_(); +virtual ~_BTextInput_(); static BArchivable* Instantiate(BMessage *data); virtual status_t Archive(BMessage *data, bool deep = true) const; +virtual void MouseDown(BPoint where); virtual void FrameResized(float width, float height); virtual void KeyDown(const char *bytes, int32 numBytes); virtual void MakeFocus(bool focusState = true); @@ -78,14 +53,11 @@ private: char *fPreviousText; bool fBool; }; -//------------------------------------------------------------------------------ + +} // namespace BPrivate + +using namespace BPrivate; + #endif // _TEXT_CONTROLI_H -/* - * $Log $ - * - * $Id $ - * - */ - diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index 36e71058e8..dac8188d04 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -400,8 +400,7 @@ BTextView::AttachedToWindow() fDragOffset = -1; fActive = false; - if (fResizable) - _AutoResize(true); + _AutoResize(true); _UpdateScrollbars(); @@ -995,7 +994,7 @@ BTextView::SetText(const char *inText, int32 inLength, const text_run_array *inR // recalc line breaks and draw the text _Refresh(0, inLength, true, false); fClickOffset = fSelStart = fSelEnd = 0; - ScrollToOffset(fSelStart); + ScrollTo(B_ORIGIN); // draw the caret if (fActive) @@ -1917,13 +1916,16 @@ BTextView::_ScrollToOffset(int32 inOffset, bool useHorizontal, bool useVertical) float lineHeight = 0.0; float xDiff = 0.0; float yDiff = 0.0; - BPoint point = PointAt(inOffset, &lineHeight); + BPoint point = PointAt(inOffset, &lineHeight); if (useHorizontal) { if (point.x < bounds.left) xDiff = point.x - bounds.left - bounds.IntegerWidth() / 2; else if (point.x >= bounds.right) xDiff = point.x - bounds.right + bounds.IntegerWidth() / 2; + // prevent negative scroll offset + if (bounds.left + xDiff < 0.0) + xDiff = -bounds.left; } if (useVertical) { @@ -1931,6 +1933,9 @@ BTextView::_ScrollToOffset(int32 inOffset, bool useHorizontal, bool useVertical) yDiff = point.y - bounds.top - bounds.IntegerHeight() / 2; else if (point.y >= bounds.bottom) yDiff = point.y - bounds.bottom + bounds.IntegerHeight() / 2; + // prevent negative scroll offset + if (bounds.top + yDiff < 0.0) + yDiff = -bounds.top; } ScrollBy(xDiff, yDiff); @@ -1978,6 +1983,8 @@ BTextView::SetTextRect(BRect rect) return; fTextRect = rect; + fLeftInset = fTextRect.left; + fRightInset = Bounds().right - fTextRect.right; if (Window() != NULL) { Invalidate(); @@ -2708,6 +2715,8 @@ BTextView::_InitObject(BRect textRect, const BFont *initialFont, // to have less code duplication, and a single place where to do changes // if needed., fTextRect = textRect; + fLeftInset = fTextRect.left; + fRightInset = Bounds().right - fTextRect.right; fSelStart = fSelEnd = 0; fCaretVisible = false; fCaretTime = 0; @@ -3117,8 +3126,7 @@ BTextView::_Refresh(int32 fromOffset, int32 toOffset, bool erase, bool scroll) || fAlignment != B_ALIGN_LEFT) drawOffset = (*fLines)[fromLine]->offset; - if (fResizable) - _AutoResize(false); + _AutoResize(false); _DrawLines(fromLine, toLine, drawOffset, erase); @@ -3541,7 +3549,7 @@ BTextView::_DrawLine(BView *view, const int32 &lineNum, const int32 &startOffset startLeft /= 2; startLeft += fTextRect.left; } - + view->MovePenTo(startLeft, line->origin + line->ascent + fTextRect.top + 1); if (erase) { @@ -3671,10 +3679,6 @@ BTextView::_DrawLines(int32 startLine, int32 endLine, int32 startOffset, if (fAlignment != B_ALIGN_LEFT) erase = true; - // Actually hide the caret - if (fCaretVisible) - _DrawCaret(fSelStart); - BRect eraseRect = clipRect; int32 startEraseLine = startLine; STELine* line = (*fLines)[startLine]; @@ -4097,32 +4101,31 @@ BTextView::_UpdateScrollbars() void BTextView::_AutoResize(bool redraw) { - if (fResizable) { - float oldWidth = Bounds().Width() + 1; - float newWidth = 3; - for (int32 i = 0; i < CountLines(); i++) - newWidth += LineWidth(i); - - BRect newRect(0, 0, ceilf(newWidth), ceilf(LineHeight(0)) + 2); - - if (fContainerView != NULL) { - fContainerView->ResizeTo(newRect.Width() + 1, newRect.Height()); - if (fAlignment == B_ALIGN_CENTER) - fContainerView->MoveBy(ceilf((oldWidth - (newRect.Width() + 1)) / 2), 0); - else if (fAlignment == B_ALIGN_RIGHT) - fContainerView->MoveBy(oldWidth - (newRect.Width() + 1), 0); - fContainerView->Invalidate(); - } - - fTextRect = newRect.InsetBySelf(0, 1); - - if (redraw) - _DrawLines(0, 0); - - // Erase the old text (TODO: Might not work for alignments different than B_ALIGN_LEFT) - SetLowColor(ViewColor()); - FillRect(BRect(fTextRect.right, fTextRect.top, Bounds().right, fTextRect.bottom), B_SOLID_LOW); + if (!fResizable) + return; + + BRect bounds = Bounds(); + float oldWidth = fTextRect.Width(); + float newWidth = max_c(bounds.Width() - (fLeftInset + fRightInset), + ceilf(LineWidth(0))); + + if (fContainerView != NULL) { + fContainerView->ResizeBy(ceilf(newWidth - oldWidth), 0); + if (fAlignment == B_ALIGN_CENTER) + fContainerView->MoveBy(ceilf((oldWidth - newWidth) / 2), 0); + else if (fAlignment == B_ALIGN_RIGHT) + fContainerView->MoveBy(ceilf(oldWidth - newWidth), 0); +// fContainerView->Invalidate(); } + + fTextRect.right = fTextRect.left + newWidth; + + if (redraw) + _DrawLines(0, 0); + + // Erase the old text (TODO: Might not work for alignments different than B_ALIGN_LEFT) + SetLowColor(ViewColor()); + FillRect(BRect(fTextRect.right, fTextRect.top, Bounds().right, fTextRect.bottom), B_SOLID_LOW); }