2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stephan Aßmus <superstippi@gmx.de>
11 // BCheckBox displays an on/off control.
20 #include <ControlLook.h>
21 #include <LayoutUtils.h>
24 #include <binary_compatibility/Interface.h>
27 BCheckBox::BCheckBox(BRect frame
, const char* name
, const char* label
,
28 BMessage
* message
, uint32 resizingMode
, uint32 flags
)
30 BControl(frame
, name
, label
, message
, resizingMode
, flags
),
35 // Resize to minimum height if needed
36 font_height fontHeight
;
37 GetFontHeight(&fontHeight
);
38 float minHeight
= (float)ceil(6.0f
+ fontHeight
.ascent
39 + fontHeight
.descent
);
40 if (Bounds().Height() < minHeight
)
41 ResizeTo(Bounds().Width(), minHeight
);
45 BCheckBox::BCheckBox(const char* name
, const char* label
, BMessage
* message
,
48 BControl(name
, label
, message
, flags
| B_WILL_DRAW
| B_NAVIGABLE
),
56 BCheckBox::BCheckBox(const char* label
, BMessage
* message
)
58 BControl(NULL
, label
, message
, B_WILL_DRAW
| B_NAVIGABLE
),
66 BCheckBox::BCheckBox(BMessage
* data
)
75 BCheckBox::~BCheckBox()
80 // #pragma mark - Archiving methods
84 BCheckBox::Instantiate(BMessage
* data
)
86 if (validate_instantiation(data
, "BCheckBox"))
87 return new(std::nothrow
) BCheckBox(data
);
94 BCheckBox::Archive(BMessage
* data
, bool deep
) const
96 return BControl::Archive(data
, deep
);
100 // #pragma mark - Hook methods
104 BCheckBox::Draw(BRect updateRect
)
106 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
108 uint32 flags
= be_control_look
->Flags(this);
110 flags
|= BControlLook::B_CLICKED
;
112 BRect
checkBoxRect(_CheckBoxFrame());
113 BRect
rect(checkBoxRect
);
114 be_control_look
->DrawCheckBox(this, rect
, updateRect
,base
, flags
);
116 BRect
labelRect(Bounds());
117 labelRect
.left
= checkBoxRect
.right
+ 1
118 + be_control_look
->DefaultLabelSpacing();
120 const BBitmap
* icon
= IconBitmap(
121 B_INACTIVE_ICON_BITMAP
| (IsEnabled() ? 0 : B_DISABLED_ICON_BITMAP
));
123 be_control_look
->DrawLabel(this, Label(), icon
, labelRect
, updateRect
,
129 BCheckBox::AttachedToWindow()
131 BControl::AttachedToWindow();
136 BCheckBox::DetachedFromWindow()
138 BControl::DetachedFromWindow();
143 BCheckBox::AllAttached()
145 BControl::AllAttached();
150 BCheckBox::AllDetached()
152 BControl::AllDetached();
157 BCheckBox::FrameMoved(BPoint newPosition
)
159 BControl::FrameMoved(newPosition
);
164 BCheckBox::FrameResized(float newWidth
, float newHeight
)
166 BControl::FrameResized(newWidth
, newHeight
);
171 BCheckBox::WindowActivated(bool active
)
173 BControl::WindowActivated(active
);
178 BCheckBox::MessageReceived(BMessage
* message
)
180 BControl::MessageReceived(message
);
185 BCheckBox::KeyDown(const char* bytes
, int32 numBytes
)
187 if (*bytes
== B_ENTER
|| *bytes
== B_SPACE
) {
191 SetValue(_NextState());
194 // skip the BControl implementation
195 BView::KeyDown(bytes
, numBytes
);
201 BCheckBox::MouseDown(BPoint where
)
208 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS
) {
211 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
213 BRect bounds
= Bounds();
217 Window()->UpdateIfNeeded();
222 GetMouse(&where
, &buttons
, true);
224 bool inside
= bounds
.Contains(where
);
225 if (fOutlined
!= inside
) {
228 Window()->UpdateIfNeeded();
230 } while (buttons
!= 0);
234 SetValue(_NextState());
238 Window()->UpdateIfNeeded();
245 BCheckBox::MouseUp(BPoint where
)
250 bool inside
= Bounds().Contains(where
);
252 if (fOutlined
!= inside
) {
259 SetValue(_NextState());
270 BCheckBox::MouseMoved(BPoint where
, uint32 code
,
271 const BMessage
* dragMessage
)
276 bool inside
= Bounds().Contains(where
);
278 if (fOutlined
!= inside
) {
289 BCheckBox::GetPreferredSize(float* _width
, float* _height
)
291 _ValidatePreferredSize();
294 *_width
= fPreferredSize
.width
;
297 *_height
= fPreferredSize
.height
;
302 BCheckBox::ResizeToPreferred()
304 BControl::ResizeToPreferred();
311 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
312 _ValidatePreferredSize());
319 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
320 _ValidatePreferredSize());
325 BCheckBox::PreferredSize()
327 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
328 _ValidatePreferredSize());
333 BCheckBox::LayoutAlignment()
335 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
336 BAlignment(B_ALIGN_LEFT
, B_ALIGN_VERTICAL_CENTER
));
344 BCheckBox::MakeFocus(bool focused
)
346 BControl::MakeFocus(focused
);
351 BCheckBox::SetValue(int32 value
)
353 // We only accept three possible values.
357 case B_CONTROL_PARTIALLY_ON
:
360 value
= B_CONTROL_ON
;
364 if (value
!= Value()) {
365 BControl::SetValueNoUpdate(value
);
366 Invalidate(_CheckBoxFrame());
372 BCheckBox::Invoke(BMessage
* message
)
374 return BControl::Invoke(message
);
379 BCheckBox::ResolveSpecifier(BMessage
* message
, int32 index
,
380 BMessage
* specifier
, int32 what
, const char* property
)
382 return BControl::ResolveSpecifier(message
, index
, specifier
, what
,
388 BCheckBox::GetSupportedSuites(BMessage
* message
)
390 return BControl::GetSupportedSuites(message
);
395 BCheckBox::Perform(perform_code code
, void* _data
)
398 case PERFORM_CODE_MIN_SIZE
:
399 ((perform_data_min_size
*)_data
)->return_value
400 = BCheckBox::MinSize();
402 case PERFORM_CODE_MAX_SIZE
:
403 ((perform_data_max_size
*)_data
)->return_value
404 = BCheckBox::MaxSize();
406 case PERFORM_CODE_PREFERRED_SIZE
:
407 ((perform_data_preferred_size
*)_data
)->return_value
408 = BCheckBox::PreferredSize();
410 case PERFORM_CODE_LAYOUT_ALIGNMENT
:
411 ((perform_data_layout_alignment
*)_data
)->return_value
412 = BCheckBox::LayoutAlignment();
414 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
:
415 ((perform_data_has_height_for_width
*)_data
)->return_value
416 = BCheckBox::HasHeightForWidth();
418 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH
:
420 perform_data_get_height_for_width
* data
421 = (perform_data_get_height_for_width
*)_data
;
422 BCheckBox::GetHeightForWidth(data
->width
, &data
->min
, &data
->max
,
426 case PERFORM_CODE_SET_LAYOUT
:
428 perform_data_set_layout
* data
= (perform_data_set_layout
*)_data
;
429 BCheckBox::SetLayout(data
->layout
);
432 case PERFORM_CODE_LAYOUT_INVALIDATED
:
434 perform_data_layout_invalidated
* data
435 = (perform_data_layout_invalidated
*)_data
;
436 BCheckBox::LayoutInvalidated(data
->descendants
);
439 case PERFORM_CODE_DO_LAYOUT
:
441 BCheckBox::DoLayout();
444 case PERFORM_CODE_SET_ICON
:
446 perform_data_set_icon
* data
= (perform_data_set_icon
*)_data
;
447 return BCheckBox::SetIcon(data
->icon
, data
->flags
);
451 return BControl::Perform(code
, _data
);
456 BCheckBox::SetIcon(const BBitmap
* icon
, uint32 flags
)
458 return BControl::SetIcon(icon
, flags
| B_CREATE_DISABLED_ICON_BITMAPS
);
463 BCheckBox::LayoutInvalidated(bool descendants
)
465 // invalidate cached preferred size
466 fPreferredSize
.Set(B_SIZE_UNSET
, B_SIZE_UNSET
);
471 BCheckBox::IsPartialStateToOff() const
473 return fPartialToOff
;
478 BCheckBox::SetPartialStateToOff(bool partialToOff
)
480 fPartialToOff
= partialToOff
;
484 // #pragma mark - FBC padding
487 void BCheckBox::_ReservedCheckBox1() {}
488 void BCheckBox::_ReservedCheckBox2() {}
489 void BCheckBox::_ReservedCheckBox3() {}
493 BCheckBox::_CheckBoxFrame(const font_height
& fontHeight
) const
495 return BRect(0.0f
, 2.0f
, ceilf(3.0f
+ fontHeight
.ascent
),
496 ceilf(5.0f
+ fontHeight
.ascent
));
501 BCheckBox::_CheckBoxFrame() const
503 font_height fontHeight
;
504 GetFontHeight(&fontHeight
);
505 return _CheckBoxFrame(fontHeight
);
510 BCheckBox::_ValidatePreferredSize()
512 if (!fPreferredSize
.IsWidthSet()) {
513 font_height fontHeight
;
514 GetFontHeight(&fontHeight
);
516 BRect
rect(_CheckBoxFrame(fontHeight
));
517 float width
= rect
.right
+ rect
.left
;
518 float height
= rect
.bottom
+ rect
.top
;
520 const BBitmap
* icon
= IconBitmap(B_INACTIVE_ICON_BITMAP
);
522 width
+= be_control_look
->DefaultLabelSpacing()
523 + icon
->Bounds().Width() + 1;
524 height
= std::max(height
, icon
->Bounds().Height());
527 if (const char* label
= Label()) {
528 width
+= be_control_look
->DefaultLabelSpacing()
529 + ceilf(StringWidth(label
));
530 height
= std::max(height
,
531 ceilf(6.0f
+ fontHeight
.ascent
+ fontHeight
.descent
));
534 fPreferredSize
.Set(width
, height
);
536 ResetLayoutInvalidation();
539 return fPreferredSize
;
544 BCheckBox::_NextState() const
549 case B_CONTROL_PARTIALLY_ON
:
550 return fPartialToOff
? B_CONTROL_OFF
: B_CONTROL_ON
;
553 return B_CONTROL_OFF
;
559 BCheckBox::operator=(const BCheckBox
&)
566 B_IF_GCC_2(InvalidateLayout__9BCheckBoxb
, _ZN9BCheckBox16InvalidateLayoutEb
)(
567 BCheckBox
* box
, bool descendants
)
569 perform_data_layout_invalidated data
;
570 data
.descendants
= descendants
;
572 box
->Perform(PERFORM_CODE_LAYOUT_INVALIDATED
, &data
);