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
+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.
*
* Authors:
@@ -8,12 +8,14 @@
* Ingo Weinhold <[email protected]>
*/
/*! BTextControl displays text that can act like a control. */
#include <string.h>
#include <TextControl.h>
#include <string.h>
#include <AbstractLayoutItem.h>
#include <ControlLook.h>
#include <LayoutUtils.h>
@@ -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
{