From 09d87d9151728f731c1d27e8914c5bbd6e72ec5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sun, 4 Nov 2012 15:23:09 +0100 Subject: [PATCH] The text control is now more flexible with its layout items. * Before, you had to have both, the text view layout item, and the label layout item or else nothing would ever be visible. * Now you can only create the text view item, and it will still work. * Also, no matter the order you added the layout items, they would always put the label on the left, and the control to the right. * You can place the label and text view layout items anywhere now, although you should keep in mind that the view spans over their frame unions; IOW they should always adjacent to each other, but not necessarily horizontally and left to right. * No longer uses a fixed label spacing, but utilizes BControlLook::DefaultLabelSpacing() instead. * However, the spacing is always added to the right of the label, no matter how you place it in the layout. Maybe one wants to add a SetLabelTextViewGap() like method. --- headers/os/interface/TextControl.h | 9 ++- src/kits/interface/TextControl.cpp | 114 ++++++++++++++++++++--------- 2 files changed, 85 insertions(+), 38 deletions(-) diff --git a/headers/os/interface/TextControl.h b/headers/os/interface/TextControl.h index 456c6f1dee..aca56a18f9 100644 --- a/headers/os/interface/TextControl.h +++ b/headers/os/interface/TextControl.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2010, Haiku, Inc. All rights reserved. + * Copyright 2006-2012, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _TEXT_CONTROL_H @@ -9,6 +9,7 @@ #include #include + class BLayoutItem; namespace BPrivate { class _BTextInput_; @@ -22,14 +23,14 @@ public: BMessage* message, uint32 resizeMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, - uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); BTextControl(const char* name, const char* label, const char* initialText, BMessage* message, - uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); BTextControl(const char* label, const char* initialText, - BMessage* message); + BMessage* message); virtual ~BTextControl(); BTextControl(BMessage* archive); diff --git a/src/kits/interface/TextControl.cpp b/src/kits/interface/TextControl.cpp index f0f64f4405..90ee19dd13 100644 --- a/src/kits/interface/TextControl.cpp +++ b/src/kits/interface/TextControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2008, Haiku Inc. + * Copyright 2001-2012, Haiku Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -8,12 +8,14 @@ * Ingo Weinhold */ + /*! BTextControl displays text that can act like a control. */ -#include #include +#include + #include #include #include @@ -82,8 +84,11 @@ public: virtual BSize BasePreferredSize(); virtual BAlignment BaseAlignment(); + BRect FrameInParent() const; + virtual status_t Archive(BMessage* into, bool deep = true) const; static BArchivable* Instantiate(BMessage* from); + private: BTextControl* fParent; BRect fFrame; @@ -109,6 +114,8 @@ public: virtual BSize BasePreferredSize(); virtual BAlignment BaseAlignment(); + BRect FrameInParent() const; + virtual status_t Archive(BMessage* into, bool deep = true) const; static BArchivable* Instantiate(BMessage* from); private: @@ -425,13 +432,17 @@ BTextControl::Draw(BRect updateRect) be_control_look->DrawTextControlBorder(this, rect, updateRect, base, flags); - rect = Bounds(); - rect.right = fDivider - kLabelInputSpacing; -// rect.right = fText->Frame().left - 2; -// rect.right -= 3;//be_control_look->DefaultLabelSpacing(); - be_control_look->DrawLabel(this, Label(), rect, updateRect, - base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE)); + if (Label() != NULL) { + if (fLayoutData->label_layout_item != NULL) { + rect = fLayoutData->label_layout_item->FrameInParent(); + } else { + rect = Bounds(); + rect.right = fDivider - kLabelInputSpacing; + } + be_control_look->DrawLabel(this, Label(), rect, updateRect, + base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE)); + } return; } @@ -524,9 +535,8 @@ BTextControl::Draw(BRect updateRect) void BTextControl::MouseDown(BPoint where) { - if (!fText->IsFocus()) { + if (!fText->IsFocus()) fText->MakeFocus(true); - } } @@ -892,23 +902,28 @@ BTextControl::DoLayout() if (size.height < fLayoutData->min.height) size.height = fLayoutData->min.height; + BRect dirty(fText->Frame()); + BRect textFrame; + // divider float divider = 0; - if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { - // We have layout items. They define the divider location. - divider = fLayoutData->text_view_layout_item->Frame().left - - fLayoutData->label_layout_item->Frame().left; + if (fLayoutData->text_view_layout_item != NULL) { + if (fLayoutData->label_layout_item != NULL) { + // We have layout items. They define the divider location. + divider = fabs(fLayoutData->text_view_layout_item->Frame().left + - fLayoutData->label_layout_item->Frame().left); + } + textFrame = fLayoutData->text_view_layout_item->FrameInParent(); } else { - if (fLayoutData->label_width > 0) - divider = fLayoutData->label_width + 5; + if (fLayoutData->label_width > 0) { + divider = fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(); + } + textFrame.Set(divider, 0, size.width, size.height); } - // text view - BRect dirty(fText->Frame()); - BRect textFrame(divider + kFrameMargin, kFrameMargin, - size.width - kFrameMargin, size.height - kFrameMargin); - // place the text view and set the divider + textFrame.InsetBy(kFrameMargin, kFrameMargin); BLayoutUtils::AlignInFrame(fText, textFrame); fDivider = divider; @@ -1071,7 +1086,6 @@ BTextControl::_InitData(const char* label, const BMessage* archive) if (label) fDivider = floorf(bounds.Width() / 2.0f); - } @@ -1139,8 +1153,14 @@ BTextControl::_LayoutTextView() { CALLED(); - BRect frame = Bounds(); - frame.left = fDivider; + BRect frame; + if (fLayoutData->text_view_layout_item != NULL) { + frame = fLayoutData->text_view_layout_item->FrameInParent(); + } else { + frame = Bounds(); + frame.left = fDivider; + } + // we are stroking the frame around the text view, which // is 2 pixels wide frame.InsetBy(kFrameMargin, kFrameMargin); @@ -1160,17 +1180,26 @@ BTextControl::_UpdateFrame() { CALLED(); - if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { - BRect labelFrame = fLayoutData->label_layout_item->Frame(); + if (fLayoutData->text_view_layout_item != NULL) { BRect textFrame = fLayoutData->text_view_layout_item->Frame(); + BRect labelFrame; + if (fLayoutData->label_layout_item != NULL) + labelFrame = fLayoutData->label_layout_item->Frame(); - // update divider - fDivider = textFrame.left - labelFrame.left; + BRect frame; + if (labelFrame.IsValid()) { + frame = textFrame | labelFrame; - MoveTo(labelFrame.left, labelFrame.top); + // update divider + fDivider = fabs(textFrame.left - labelFrame.left); + } else { + frame = textFrame; + fDivider = 0; + } + + MoveTo(frame.left, frame.top); BSize oldSize = Bounds().Size(); - ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left, - textFrame.top + textFrame.Height() - labelFrame.top); + ResizeTo(frame.Width(), frame.Height()); BSize newSize = Bounds().Size(); // If the size changes, ResizeTo() will trigger a relayout, otherwise @@ -1203,8 +1232,10 @@ BTextControl::_ValidateLayoutData() // compute the minimal divider float divider = 0; - if (fLayoutData->label_width > 0) - divider = fLayoutData->label_width + 5; + if (fLayoutData->label_width > 0) { + divider = fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(); + } // If we shan't do real layout, we let the current divider take influence. if (!(Flags() & B_SUPPORTS_LAYOUT)) @@ -1306,7 +1337,8 @@ BTextControl::LabelLayoutItem::BaseMinSize() if (!fParent->Label()) return BSize(-1, -1); - return BSize(fParent->fLayoutData->label_width + 5, + return BSize(fParent->fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(), fParent->fLayoutData->label_height); } @@ -1332,6 +1364,13 @@ BTextControl::LabelLayoutItem::BaseAlignment() } +BRect +BTextControl::LabelLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + status_t BTextControl::LabelLayoutItem::Archive(BMessage* into, bool deep) const { @@ -1459,6 +1498,13 @@ BTextControl::TextViewLayoutItem::BaseAlignment() } +BRect +BTextControl::TextViewLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + status_t BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const {