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.
This commit is contained in:
Axel Dörfler
2012-11-05 12:50:02 +01:00
parent 6643ead593
commit 09d87d9151
2 changed files with 85 additions and 38 deletions
+5 -4
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
#ifndef _TEXT_CONTROL_H #ifndef _TEXT_CONTROL_H
@@ -9,6 +9,7 @@
#include <Control.h> #include <Control.h>
#include <TextView.h> #include <TextView.h>
class BLayoutItem; class BLayoutItem;
namespace BPrivate { namespace BPrivate {
class _BTextInput_; class _BTextInput_;
@@ -22,14 +23,14 @@ public:
BMessage* message, BMessage* message,
uint32 resizeMode uint32 resizeMode
= B_FOLLOW_LEFT | B_FOLLOW_TOP, = B_FOLLOW_LEFT | B_FOLLOW_TOP,
uint32 flags = B_WILL_DRAW | B_NAVIGABLE); uint32 flags = B_WILL_DRAW | B_NAVIGABLE);
BTextControl(const char* name, BTextControl(const char* name,
const char* label, const char* initialText, const char* label, const char* initialText,
BMessage* message, BMessage* message,
uint32 flags = B_WILL_DRAW | B_NAVIGABLE); uint32 flags = B_WILL_DRAW | B_NAVIGABLE);
BTextControl(const char* label, BTextControl(const char* label,
const char* initialText, const char* initialText,
BMessage* message); BMessage* message);
virtual ~BTextControl(); virtual ~BTextControl();
BTextControl(BMessage* archive); BTextControl(BMessage* archive);
+80 -34
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2001-2008, Haiku Inc. * Copyright 2001-2012, Haiku Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -8,12 +8,14 @@
* Ingo Weinhold <[email protected]> * Ingo Weinhold <[email protected]>
*/ */
/*! BTextControl displays text that can act like a control. */ /*! BTextControl displays text that can act like a control. */
#include <string.h>
#include <TextControl.h> #include <TextControl.h>
#include <string.h>
#include <AbstractLayoutItem.h> #include <AbstractLayoutItem.h>
#include <ControlLook.h> #include <ControlLook.h>
#include <LayoutUtils.h> #include <LayoutUtils.h>
@@ -82,8 +84,11 @@ public:
virtual BSize BasePreferredSize(); virtual BSize BasePreferredSize();
virtual BAlignment BaseAlignment(); virtual BAlignment BaseAlignment();
BRect FrameInParent() const;
virtual status_t Archive(BMessage* into, bool deep = true) const; virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* from); static BArchivable* Instantiate(BMessage* from);
private: private:
BTextControl* fParent; BTextControl* fParent;
BRect fFrame; BRect fFrame;
@@ -109,6 +114,8 @@ public:
virtual BSize BasePreferredSize(); virtual BSize BasePreferredSize();
virtual BAlignment BaseAlignment(); virtual BAlignment BaseAlignment();
BRect FrameInParent() const;
virtual status_t Archive(BMessage* into, bool deep = true) const; virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* from); static BArchivable* Instantiate(BMessage* from);
private: private:
@@ -425,13 +432,17 @@ BTextControl::Draw(BRect updateRect)
be_control_look->DrawTextControlBorder(this, rect, updateRect, base, be_control_look->DrawTextControlBorder(this, rect, updateRect, base,
flags); flags);
rect = Bounds(); if (Label() != NULL) {
rect.right = fDivider - kLabelInputSpacing; if (fLayoutData->label_layout_item != NULL) {
// rect.right = fText->Frame().left - 2; rect = fLayoutData->label_layout_item->FrameInParent();
// rect.right -= 3;//be_control_look->DefaultLabelSpacing(); } else {
be_control_look->DrawLabel(this, Label(), rect, updateRect, rect = Bounds();
base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE)); rect.right = fDivider - kLabelInputSpacing;
}
be_control_look->DrawLabel(this, Label(), rect, updateRect,
base, flags, BAlignment(fLabelAlign, B_ALIGN_MIDDLE));
}
return; return;
} }
@@ -524,9 +535,8 @@ BTextControl::Draw(BRect updateRect)
void void
BTextControl::MouseDown(BPoint where) BTextControl::MouseDown(BPoint where)
{ {
if (!fText->IsFocus()) { if (!fText->IsFocus())
fText->MakeFocus(true); fText->MakeFocus(true);
}
} }
@@ -892,23 +902,28 @@ BTextControl::DoLayout()
if (size.height < fLayoutData->min.height) if (size.height < fLayoutData->min.height)
size.height = fLayoutData->min.height; size.height = fLayoutData->min.height;
BRect dirty(fText->Frame());
BRect textFrame;
// divider // divider
float divider = 0; float divider = 0;
if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { if (fLayoutData->text_view_layout_item != NULL) {
// We have layout items. They define the divider location. if (fLayoutData->label_layout_item != NULL) {
divider = fLayoutData->text_view_layout_item->Frame().left // We have layout items. They define the divider location.
- fLayoutData->label_layout_item->Frame().left; divider = fabs(fLayoutData->text_view_layout_item->Frame().left
- fLayoutData->label_layout_item->Frame().left);
}
textFrame = fLayoutData->text_view_layout_item->FrameInParent();
} else { } else {
if (fLayoutData->label_width > 0) if (fLayoutData->label_width > 0) {
divider = fLayoutData->label_width + 5; 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 // place the text view and set the divider
textFrame.InsetBy(kFrameMargin, kFrameMargin);
BLayoutUtils::AlignInFrame(fText, textFrame); BLayoutUtils::AlignInFrame(fText, textFrame);
fDivider = divider; fDivider = divider;
@@ -1071,7 +1086,6 @@ BTextControl::_InitData(const char* label, const BMessage* archive)
if (label) if (label)
fDivider = floorf(bounds.Width() / 2.0f); fDivider = floorf(bounds.Width() / 2.0f);
} }
@@ -1139,8 +1153,14 @@ BTextControl::_LayoutTextView()
{ {
CALLED(); CALLED();
BRect frame = Bounds(); BRect frame;
frame.left = fDivider; 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 // we are stroking the frame around the text view, which
// is 2 pixels wide // is 2 pixels wide
frame.InsetBy(kFrameMargin, kFrameMargin); frame.InsetBy(kFrameMargin, kFrameMargin);
@@ -1160,17 +1180,26 @@ BTextControl::_UpdateFrame()
{ {
CALLED(); CALLED();
if (fLayoutData->label_layout_item && fLayoutData->text_view_layout_item) { if (fLayoutData->text_view_layout_item != NULL) {
BRect labelFrame = fLayoutData->label_layout_item->Frame();
BRect textFrame = fLayoutData->text_view_layout_item->Frame(); BRect textFrame = fLayoutData->text_view_layout_item->Frame();
BRect labelFrame;
if (fLayoutData->label_layout_item != NULL)
labelFrame = fLayoutData->label_layout_item->Frame();
// update divider BRect frame;
fDivider = textFrame.left - labelFrame.left; 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(); BSize oldSize = Bounds().Size();
ResizeTo(textFrame.left + textFrame.Width() - labelFrame.left, ResizeTo(frame.Width(), frame.Height());
textFrame.top + textFrame.Height() - labelFrame.top);
BSize newSize = Bounds().Size(); BSize newSize = Bounds().Size();
// If the size changes, ResizeTo() will trigger a relayout, otherwise // If the size changes, ResizeTo() will trigger a relayout, otherwise
@@ -1203,8 +1232,10 @@ BTextControl::_ValidateLayoutData()
// compute the minimal divider // compute the minimal divider
float divider = 0; float divider = 0;
if (fLayoutData->label_width > 0) if (fLayoutData->label_width > 0) {
divider = fLayoutData->label_width + 5; divider = fLayoutData->label_width
+ be_control_look->DefaultLabelSpacing();
}
// If we shan't do real layout, we let the current divider take influence. // If we shan't do real layout, we let the current divider take influence.
if (!(Flags() & B_SUPPORTS_LAYOUT)) if (!(Flags() & B_SUPPORTS_LAYOUT))
@@ -1306,7 +1337,8 @@ BTextControl::LabelLayoutItem::BaseMinSize()
if (!fParent->Label()) if (!fParent->Label())
return BSize(-1, -1); 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); 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 status_t
BTextControl::LabelLayoutItem::Archive(BMessage* into, bool deep) const 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 status_t
BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const BTextControl::TextViewLayoutItem::Archive(BMessage* into, bool deep) const
{ {