tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / CheckBox.cpp
blobc8fb055160e8de3aba94ac420329ac10861ac1e1
1 /*
2 * Copyright 2001-2014 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 * Stephan Aßmus <superstippi@gmx.de>
8 */
11 // BCheckBox displays an on/off control.
14 #include <CheckBox.h>
16 #include <algorithm>
17 #include <new>
19 #include <Bitmap.h>
20 #include <ControlLook.h>
21 #include <LayoutUtils.h>
22 #include <Window.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),
31 fPreferredSize(),
32 fOutlined(false),
33 fPartialToOff(false)
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,
46 uint32 flags)
48 BControl(name, label, message, flags | B_WILL_DRAW | B_NAVIGABLE),
49 fPreferredSize(),
50 fOutlined(false),
51 fPartialToOff(false)
56 BCheckBox::BCheckBox(const char* label, BMessage* message)
58 BControl(NULL, label, message, B_WILL_DRAW | B_NAVIGABLE),
59 fPreferredSize(),
60 fOutlined(false),
61 fPartialToOff(false)
66 BCheckBox::BCheckBox(BMessage* data)
68 BControl(data),
69 fOutlined(false),
70 fPartialToOff(false)
75 BCheckBox::~BCheckBox()
80 // #pragma mark - Archiving methods
83 BArchivable*
84 BCheckBox::Instantiate(BMessage* data)
86 if (validate_instantiation(data, "BCheckBox"))
87 return new(std::nothrow) BCheckBox(data);
89 return NULL;
93 status_t
94 BCheckBox::Archive(BMessage* data, bool deep) const
96 return BControl::Archive(data, deep);
100 // #pragma mark - Hook methods
103 void
104 BCheckBox::Draw(BRect updateRect)
106 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
108 uint32 flags = be_control_look->Flags(this);
109 if (fOutlined)
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,
124 base, flags);
128 void
129 BCheckBox::AttachedToWindow()
131 BControl::AttachedToWindow();
135 void
136 BCheckBox::DetachedFromWindow()
138 BControl::DetachedFromWindow();
142 void
143 BCheckBox::AllAttached()
145 BControl::AllAttached();
149 void
150 BCheckBox::AllDetached()
152 BControl::AllDetached();
156 void
157 BCheckBox::FrameMoved(BPoint newPosition)
159 BControl::FrameMoved(newPosition);
163 void
164 BCheckBox::FrameResized(float newWidth, float newHeight)
166 BControl::FrameResized(newWidth, newHeight);
170 void
171 BCheckBox::WindowActivated(bool active)
173 BControl::WindowActivated(active);
177 void
178 BCheckBox::MessageReceived(BMessage* message)
180 BControl::MessageReceived(message);
184 void
185 BCheckBox::KeyDown(const char* bytes, int32 numBytes)
187 if (*bytes == B_ENTER || *bytes == B_SPACE) {
188 if (!IsEnabled())
189 return;
191 SetValue(_NextState());
192 Invoke();
193 } else {
194 // skip the BControl implementation
195 BView::KeyDown(bytes, numBytes);
200 void
201 BCheckBox::MouseDown(BPoint where)
203 if (!IsEnabled())
204 return;
206 fOutlined = true;
208 if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
209 Invalidate();
210 SetTracking(true);
211 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
212 } else {
213 BRect bounds = Bounds();
214 uint32 buttons;
216 Invalidate();
217 Window()->UpdateIfNeeded();
219 do {
220 snooze(40000);
222 GetMouse(&where, &buttons, true);
224 bool inside = bounds.Contains(where);
225 if (fOutlined != inside) {
226 fOutlined = inside;
227 Invalidate();
228 Window()->UpdateIfNeeded();
230 } while (buttons != 0);
232 if (fOutlined) {
233 fOutlined = false;
234 SetValue(_NextState());
235 Invoke();
236 } else {
237 Invalidate();
238 Window()->UpdateIfNeeded();
244 void
245 BCheckBox::MouseUp(BPoint where)
247 if (!IsTracking())
248 return;
250 bool inside = Bounds().Contains(where);
252 if (fOutlined != inside) {
253 fOutlined = inside;
254 Invalidate();
257 if (fOutlined) {
258 fOutlined = false;
259 SetValue(_NextState());
260 Invoke();
261 } else {
262 Invalidate();
265 SetTracking(false);
269 void
270 BCheckBox::MouseMoved(BPoint where, uint32 code,
271 const BMessage* dragMessage)
273 if (!IsTracking())
274 return;
276 bool inside = Bounds().Contains(where);
278 if (fOutlined != inside) {
279 fOutlined = inside;
280 Invalidate();
285 // #pragma mark -
288 void
289 BCheckBox::GetPreferredSize(float* _width, float* _height)
291 _ValidatePreferredSize();
293 if (_width)
294 *_width = fPreferredSize.width;
296 if (_height)
297 *_height = fPreferredSize.height;
301 void
302 BCheckBox::ResizeToPreferred()
304 BControl::ResizeToPreferred();
308 BSize
309 BCheckBox::MinSize()
311 return BLayoutUtils::ComposeSize(ExplicitMinSize(),
312 _ValidatePreferredSize());
316 BSize
317 BCheckBox::MaxSize()
319 return BLayoutUtils::ComposeSize(ExplicitMaxSize(),
320 _ValidatePreferredSize());
324 BSize
325 BCheckBox::PreferredSize()
327 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
328 _ValidatePreferredSize());
332 BAlignment
333 BCheckBox::LayoutAlignment()
335 return BLayoutUtils::ComposeAlignment(ExplicitAlignment(),
336 BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER));
340 // #pragma mark -
343 void
344 BCheckBox::MakeFocus(bool focused)
346 BControl::MakeFocus(focused);
350 void
351 BCheckBox::SetValue(int32 value)
353 // We only accept three possible values.
354 switch (value) {
355 case B_CONTROL_OFF:
356 case B_CONTROL_ON:
357 case B_CONTROL_PARTIALLY_ON:
358 break;
359 default:
360 value = B_CONTROL_ON;
361 break;
364 if (value != Value()) {
365 BControl::SetValueNoUpdate(value);
366 Invalidate(_CheckBoxFrame());
371 status_t
372 BCheckBox::Invoke(BMessage* message)
374 return BControl::Invoke(message);
378 BHandler*
379 BCheckBox::ResolveSpecifier(BMessage* message, int32 index,
380 BMessage* specifier, int32 what, const char* property)
382 return BControl::ResolveSpecifier(message, index, specifier, what,
383 property);
387 status_t
388 BCheckBox::GetSupportedSuites(BMessage* message)
390 return BControl::GetSupportedSuites(message);
394 status_t
395 BCheckBox::Perform(perform_code code, void* _data)
397 switch (code) {
398 case PERFORM_CODE_MIN_SIZE:
399 ((perform_data_min_size*)_data)->return_value
400 = BCheckBox::MinSize();
401 return B_OK;
402 case PERFORM_CODE_MAX_SIZE:
403 ((perform_data_max_size*)_data)->return_value
404 = BCheckBox::MaxSize();
405 return B_OK;
406 case PERFORM_CODE_PREFERRED_SIZE:
407 ((perform_data_preferred_size*)_data)->return_value
408 = BCheckBox::PreferredSize();
409 return B_OK;
410 case PERFORM_CODE_LAYOUT_ALIGNMENT:
411 ((perform_data_layout_alignment*)_data)->return_value
412 = BCheckBox::LayoutAlignment();
413 return B_OK;
414 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
415 ((perform_data_has_height_for_width*)_data)->return_value
416 = BCheckBox::HasHeightForWidth();
417 return B_OK;
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,
423 &data->preferred);
424 return B_OK;
426 case PERFORM_CODE_SET_LAYOUT:
428 perform_data_set_layout* data = (perform_data_set_layout*)_data;
429 BCheckBox::SetLayout(data->layout);
430 return B_OK;
432 case PERFORM_CODE_LAYOUT_INVALIDATED:
434 perform_data_layout_invalidated* data
435 = (perform_data_layout_invalidated*)_data;
436 BCheckBox::LayoutInvalidated(data->descendants);
437 return B_OK;
439 case PERFORM_CODE_DO_LAYOUT:
441 BCheckBox::DoLayout();
442 return B_OK;
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);
455 status_t
456 BCheckBox::SetIcon(const BBitmap* icon, uint32 flags)
458 return BControl::SetIcon(icon, flags | B_CREATE_DISABLED_ICON_BITMAPS);
462 void
463 BCheckBox::LayoutInvalidated(bool descendants)
465 // invalidate cached preferred size
466 fPreferredSize.Set(B_SIZE_UNSET, B_SIZE_UNSET);
470 bool
471 BCheckBox::IsPartialStateToOff() const
473 return fPartialToOff;
477 void
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() {}
492 BRect
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));
500 BRect
501 BCheckBox::_CheckBoxFrame() const
503 font_height fontHeight;
504 GetFontHeight(&fontHeight);
505 return _CheckBoxFrame(fontHeight);
509 BSize
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);
521 if (icon != NULL) {
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;
543 int32
544 BCheckBox::_NextState() const
546 switch (Value()) {
547 case B_CONTROL_OFF:
548 return B_CONTROL_ON;
549 case B_CONTROL_PARTIALLY_ON:
550 return fPartialToOff ? B_CONTROL_OFF : B_CONTROL_ON;
551 case B_CONTROL_ON:
552 default:
553 return B_CONTROL_OFF;
558 BCheckBox &
559 BCheckBox::operator=(const BCheckBox &)
561 return *this;
565 extern "C" void
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);