2 * Copyright 2001-2015 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 // erase the is control flag before drawing the label so that the label
117 // will get drawn using B_PANEL_TEXT_COLOR
118 flags
&= ~BControlLook::B_IS_CONTROL
;
120 BRect
labelRect(Bounds());
121 labelRect
.left
= checkBoxRect
.right
+ 1
122 + be_control_look
->DefaultLabelSpacing();
124 const BBitmap
* icon
= IconBitmap(
125 B_INACTIVE_ICON_BITMAP
| (IsEnabled() ? 0 : B_DISABLED_ICON_BITMAP
));
127 be_control_look
->DrawLabel(this, Label(), icon
, labelRect
, updateRect
,
133 BCheckBox::AttachedToWindow()
135 BControl::AttachedToWindow();
140 BCheckBox::DetachedFromWindow()
142 BControl::DetachedFromWindow();
147 BCheckBox::AllAttached()
149 BControl::AllAttached();
154 BCheckBox::AllDetached()
156 BControl::AllDetached();
161 BCheckBox::FrameMoved(BPoint newPosition
)
163 BControl::FrameMoved(newPosition
);
168 BCheckBox::FrameResized(float newWidth
, float newHeight
)
170 BControl::FrameResized(newWidth
, newHeight
);
175 BCheckBox::WindowActivated(bool active
)
177 BControl::WindowActivated(active
);
182 BCheckBox::MessageReceived(BMessage
* message
)
184 BControl::MessageReceived(message
);
189 BCheckBox::KeyDown(const char* bytes
, int32 numBytes
)
191 if (*bytes
== B_ENTER
|| *bytes
== B_SPACE
) {
195 SetValue(_NextState());
198 // skip the BControl implementation
199 BView::KeyDown(bytes
, numBytes
);
205 BCheckBox::MouseDown(BPoint where
)
212 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS
) {
215 SetMouseEventMask(B_POINTER_EVENTS
, B_LOCK_WINDOW_FOCUS
);
217 BRect bounds
= Bounds();
221 Window()->UpdateIfNeeded();
226 GetMouse(&where
, &buttons
, true);
228 bool inside
= bounds
.Contains(where
);
229 if (fOutlined
!= inside
) {
232 Window()->UpdateIfNeeded();
234 } while (buttons
!= 0);
238 SetValue(_NextState());
242 Window()->UpdateIfNeeded();
249 BCheckBox::MouseUp(BPoint where
)
254 bool inside
= Bounds().Contains(where
);
256 if (fOutlined
!= inside
) {
263 SetValue(_NextState());
274 BCheckBox::MouseMoved(BPoint where
, uint32 code
,
275 const BMessage
* dragMessage
)
280 bool inside
= Bounds().Contains(where
);
282 if (fOutlined
!= inside
) {
293 BCheckBox::GetPreferredSize(float* _width
, float* _height
)
295 _ValidatePreferredSize();
298 *_width
= fPreferredSize
.width
;
301 *_height
= fPreferredSize
.height
;
306 BCheckBox::ResizeToPreferred()
308 BControl::ResizeToPreferred();
315 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
316 _ValidatePreferredSize());
323 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
324 _ValidatePreferredSize());
329 BCheckBox::PreferredSize()
331 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
332 _ValidatePreferredSize());
337 BCheckBox::LayoutAlignment()
339 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
340 BAlignment(B_ALIGN_LEFT
, B_ALIGN_VERTICAL_CENTER
));
348 BCheckBox::MakeFocus(bool focused
)
350 BControl::MakeFocus(focused
);
355 BCheckBox::SetValue(int32 value
)
357 // We only accept three possible values.
361 case B_CONTROL_PARTIALLY_ON
:
364 value
= B_CONTROL_ON
;
368 if (value
!= Value()) {
369 BControl::SetValueNoUpdate(value
);
370 Invalidate(_CheckBoxFrame());
376 BCheckBox::Invoke(BMessage
* message
)
378 return BControl::Invoke(message
);
383 BCheckBox::ResolveSpecifier(BMessage
* message
, int32 index
,
384 BMessage
* specifier
, int32 what
, const char* property
)
386 return BControl::ResolveSpecifier(message
, index
, specifier
, what
,
392 BCheckBox::GetSupportedSuites(BMessage
* message
)
394 return BControl::GetSupportedSuites(message
);
399 BCheckBox::Perform(perform_code code
, void* _data
)
402 case PERFORM_CODE_MIN_SIZE
:
403 ((perform_data_min_size
*)_data
)->return_value
404 = BCheckBox::MinSize();
406 case PERFORM_CODE_MAX_SIZE
:
407 ((perform_data_max_size
*)_data
)->return_value
408 = BCheckBox::MaxSize();
410 case PERFORM_CODE_PREFERRED_SIZE
:
411 ((perform_data_preferred_size
*)_data
)->return_value
412 = BCheckBox::PreferredSize();
414 case PERFORM_CODE_LAYOUT_ALIGNMENT
:
415 ((perform_data_layout_alignment
*)_data
)->return_value
416 = BCheckBox::LayoutAlignment();
418 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
:
419 ((perform_data_has_height_for_width
*)_data
)->return_value
420 = BCheckBox::HasHeightForWidth();
422 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH
:
424 perform_data_get_height_for_width
* data
425 = (perform_data_get_height_for_width
*)_data
;
426 BCheckBox::GetHeightForWidth(data
->width
, &data
->min
, &data
->max
,
430 case PERFORM_CODE_SET_LAYOUT
:
432 perform_data_set_layout
* data
= (perform_data_set_layout
*)_data
;
433 BCheckBox::SetLayout(data
->layout
);
436 case PERFORM_CODE_LAYOUT_INVALIDATED
:
438 perform_data_layout_invalidated
* data
439 = (perform_data_layout_invalidated
*)_data
;
440 BCheckBox::LayoutInvalidated(data
->descendants
);
443 case PERFORM_CODE_DO_LAYOUT
:
445 BCheckBox::DoLayout();
448 case PERFORM_CODE_SET_ICON
:
450 perform_data_set_icon
* data
= (perform_data_set_icon
*)_data
;
451 return BCheckBox::SetIcon(data
->icon
, data
->flags
);
455 return BControl::Perform(code
, _data
);
460 BCheckBox::SetIcon(const BBitmap
* icon
, uint32 flags
)
462 return BControl::SetIcon(icon
, flags
| B_CREATE_DISABLED_ICON_BITMAPS
);
467 BCheckBox::LayoutInvalidated(bool descendants
)
469 // invalidate cached preferred size
470 fPreferredSize
.Set(B_SIZE_UNSET
, B_SIZE_UNSET
);
475 BCheckBox::IsPartialStateToOff() const
477 return fPartialToOff
;
482 BCheckBox::SetPartialStateToOff(bool partialToOff
)
484 fPartialToOff
= partialToOff
;
488 // #pragma mark - FBC padding
491 void BCheckBox::_ReservedCheckBox1() {}
492 void BCheckBox::_ReservedCheckBox2() {}
493 void BCheckBox::_ReservedCheckBox3() {}
497 BCheckBox::_CheckBoxFrame(const font_height
& fontHeight
) const
499 return BRect(0.0f
, 2.0f
, ceilf(3.0f
+ fontHeight
.ascent
),
500 ceilf(5.0f
+ fontHeight
.ascent
));
505 BCheckBox::_CheckBoxFrame() const
507 font_height fontHeight
;
508 GetFontHeight(&fontHeight
);
509 return _CheckBoxFrame(fontHeight
);
514 BCheckBox::_ValidatePreferredSize()
516 if (!fPreferredSize
.IsWidthSet()) {
517 font_height fontHeight
;
518 GetFontHeight(&fontHeight
);
520 BRect
rect(_CheckBoxFrame(fontHeight
));
521 float width
= rect
.right
+ rect
.left
;
522 float height
= rect
.bottom
+ rect
.top
;
524 const BBitmap
* icon
= IconBitmap(B_INACTIVE_ICON_BITMAP
);
526 width
+= be_control_look
->DefaultLabelSpacing()
527 + icon
->Bounds().Width() + 1;
528 height
= std::max(height
, icon
->Bounds().Height());
531 if (const char* label
= Label()) {
532 width
+= be_control_look
->DefaultLabelSpacing()
533 + ceilf(StringWidth(label
));
534 height
= std::max(height
,
535 ceilf(6.0f
+ fontHeight
.ascent
+ fontHeight
.descent
));
538 fPreferredSize
.Set(width
, height
);
540 ResetLayoutInvalidation();
543 return fPreferredSize
;
548 BCheckBox::_NextState() const
553 case B_CONTROL_PARTIALLY_ON
:
554 return fPartialToOff
? B_CONTROL_OFF
: B_CONTROL_ON
;
557 return B_CONTROL_OFF
;
563 BCheckBox::operator=(const BCheckBox
&)
570 B_IF_GCC_2(InvalidateLayout__9BCheckBoxb
, _ZN9BCheckBox16InvalidateLayoutEb
)(
571 BCheckBox
* box
, bool descendants
)
573 perform_data_layout_invalidated data
;
574 data
.descendants
= descendants
;
576 box
->Perform(PERFORM_CODE_LAYOUT_INVALIDATED
, &data
);