tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / Control.cpp
blob6cef099db5e5d21459c6bbb3a212c4227ec224f3
1 /*
2 * Copyright 2001-2013, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers, mflerackers@androme.be
7 * Ingo Weinhold, ingo_weinhold@gmx.de
8 */
11 // BControl is the base class for user-event handling objects.
14 #include <stdlib.h>
15 #include <string.h>
17 #include <Control.h>
18 #include <PropertyInfo.h>
19 #include <Window.h>
21 #include <binary_compatibility/Interface.h>
22 #include <Icon.h>
25 static property_info sPropertyList[] = {
27 "Enabled",
28 { B_GET_PROPERTY, B_SET_PROPERTY },
29 { B_DIRECT_SPECIFIER },
30 NULL, 0,
31 { B_BOOL_TYPE }
34 "Label",
35 { B_GET_PROPERTY, B_SET_PROPERTY },
36 { B_DIRECT_SPECIFIER },
37 NULL, 0,
38 { B_STRING_TYPE }
41 "Value",
42 { B_GET_PROPERTY, B_SET_PROPERTY },
43 { B_DIRECT_SPECIFIER },
44 NULL, 0,
45 { B_INT32_TYPE }
51 BControl::BControl(BRect frame, const char* name, const char* label,
52 BMessage* message, uint32 resizingMode, uint32 flags)
54 BView(frame, name, resizingMode, flags)
56 InitData(NULL);
58 SetLabel(label);
59 SetMessage(message);
63 BControl::BControl(const char* name, const char* label, BMessage* message,
64 uint32 flags)
66 BView(name, flags)
68 InitData(NULL);
70 SetLabel(label);
71 SetMessage(message);
75 BControl::~BControl()
77 free(fLabel);
78 delete fIcon;
79 SetMessage(NULL);
83 BControl::BControl(BMessage* data)
85 BView(data)
87 InitData(data);
89 BMessage message;
90 if (data->FindMessage("_msg", &message) == B_OK)
91 SetMessage(new BMessage(message));
93 const char* label;
94 if (data->FindString("_label", &label) == B_OK)
95 SetLabel(label);
97 int32 value;
98 if (data->FindInt32("_val", &value) == B_OK)
99 SetValue(value);
101 bool toggle;
102 if (data->FindBool("_disable", &toggle) == B_OK)
103 SetEnabled(!toggle);
105 if (data->FindBool("be:wants_nav", &toggle) == B_OK)
106 fWantsNav = toggle;
110 BArchivable*
111 BControl::Instantiate(BMessage* data)
113 if (validate_instantiation(data, "BControl"))
114 return new BControl(data);
116 return NULL;
120 status_t
121 BControl::Archive(BMessage* data, bool deep) const
123 status_t status = BView::Archive(data, deep);
125 if (status == B_OK && Message())
126 status = data->AddMessage("_msg", Message());
128 if (status == B_OK && fLabel)
129 status = data->AddString("_label", fLabel);
131 if (status == B_OK && fValue != B_CONTROL_OFF)
132 status = data->AddInt32("_val", fValue);
134 if (status == B_OK && !fEnabled)
135 status = data->AddBool("_disable", true);
137 return status;
141 void
142 BControl::WindowActivated(bool active)
144 BView::WindowActivated(active);
146 if (IsFocus())
147 Invalidate();
151 void
152 BControl::AttachedToWindow()
154 rgb_color color;
156 BView* parent = Parent();
157 if (parent != NULL) {
158 // inherit the color from parent
159 color = parent->ViewColor();
160 if (color == B_TRANSPARENT_COLOR)
161 color = ui_color(B_PANEL_BACKGROUND_COLOR);
162 } else
163 color = ui_color(B_PANEL_BACKGROUND_COLOR);
165 SetViewColor(color);
166 SetLowColor(color);
168 if (!Messenger().IsValid())
169 SetTarget(Window());
171 BView::AttachedToWindow();
175 void
176 BControl::DetachedFromWindow()
178 BView::DetachedFromWindow();
182 void
183 BControl::AllAttached()
185 BView::AllAttached();
189 void
190 BControl::AllDetached()
192 BView::AllDetached();
196 void
197 BControl::MessageReceived(BMessage* message)
199 if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
200 BMessage reply(B_REPLY);
201 bool handled = false;
203 BMessage specifier;
204 int32 index;
205 int32 form;
206 const char* property;
207 if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) {
208 if (strcmp(property, "Label") == 0) {
209 if (message->what == B_GET_PROPERTY) {
210 reply.AddString("result", fLabel);
211 handled = true;
212 } else {
213 // B_SET_PROPERTY
214 const char* label;
215 if (message->FindString("data", &label) == B_OK) {
216 SetLabel(label);
217 reply.AddInt32("error", B_OK);
218 handled = true;
221 } else if (strcmp(property, "Value") == 0) {
222 if (message->what == B_GET_PROPERTY) {
223 reply.AddInt32("result", fValue);
224 handled = true;
225 } else {
226 // B_SET_PROPERTY
227 int32 value;
228 if (message->FindInt32("data", &value) == B_OK) {
229 SetValue(value);
230 reply.AddInt32("error", B_OK);
231 handled = true;
234 } else if (strcmp(property, "Enabled") == 0) {
235 if (message->what == B_GET_PROPERTY) {
236 reply.AddBool("result", fEnabled);
237 handled = true;
238 } else {
239 // B_SET_PROPERTY
240 bool enabled;
241 if (message->FindBool("data", &enabled) == B_OK) {
242 SetEnabled(enabled);
243 reply.AddInt32("error", B_OK);
244 handled = true;
250 if (handled) {
251 message->SendReply(&reply);
252 return;
256 BView::MessageReceived(message);
260 void
261 BControl::MakeFocus(bool focus)
263 if (focus == IsFocus())
264 return;
266 BView::MakeFocus(focus);
268 if (Window() != NULL) {
269 fFocusChanging = true;
270 Invalidate(Bounds());
271 Flush();
272 fFocusChanging = false;
277 void
278 BControl::KeyDown(const char* bytes, int32 numBytes)
280 if (*bytes == B_ENTER || *bytes == B_SPACE) {
281 if (!fEnabled)
282 return;
284 SetValue(Value() ? B_CONTROL_OFF : B_CONTROL_ON);
285 Invoke();
286 } else
287 BView::KeyDown(bytes, numBytes);
291 void
292 BControl::MouseDown(BPoint where)
294 BView::MouseDown(where);
298 void
299 BControl::MouseUp(BPoint where)
301 BView::MouseUp(where);
305 void
306 BControl::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
308 BView::MouseMoved(where, code, dragMessage);
312 void
313 BControl::SetLabel(const char* label)
315 if (label != NULL && !label[0])
316 label = NULL;
318 // Has the label been changed?
319 if ((fLabel && label && !strcmp(fLabel, label))
320 || ((fLabel == NULL || !fLabel[0]) && label == NULL))
321 return;
323 free(fLabel);
324 fLabel = label ? strdup(label) : NULL;
326 InvalidateLayout();
327 Invalidate();
331 const char*
332 BControl::Label() const
334 return fLabel;
338 void
339 BControl::SetValue(int32 value)
341 if (value == fValue)
342 return;
344 fValue = value;
345 Invalidate();
349 void
350 BControl::SetValueNoUpdate(int32 value)
352 fValue = value;
356 int32
357 BControl::Value() const
359 return fValue;
363 void
364 BControl::SetEnabled(bool enabled)
366 if (fEnabled == enabled)
367 return;
369 fEnabled = enabled;
371 if (fEnabled && fWantsNav)
372 SetFlags(Flags() | B_NAVIGABLE);
373 else if (!fEnabled && (Flags() & B_NAVIGABLE)) {
374 fWantsNav = true;
375 SetFlags(Flags() & ~B_NAVIGABLE);
376 } else
377 fWantsNav = false;
379 if (Window()) {
380 Invalidate(Bounds());
381 Flush();
386 bool
387 BControl::IsEnabled() const
389 return fEnabled;
393 void
394 BControl::GetPreferredSize(float* _width, float* _height)
396 BView::GetPreferredSize(_width, _height);
400 void
401 BControl::ResizeToPreferred()
403 BView::ResizeToPreferred();
407 status_t
408 BControl::Invoke(BMessage* message)
410 bool notify = false;
411 uint32 kind = InvokeKind(&notify);
413 if (!message && !notify)
414 message = Message();
416 BMessage clone(kind);
418 if (!message) {
419 if (!IsWatched())
420 return B_BAD_VALUE;
421 } else
422 clone = *message;
424 clone.AddInt64("when", (int64)system_time());
425 clone.AddPointer("source", this);
426 clone.AddInt32("be:value", fValue);
427 clone.AddMessenger("be:sender", BMessenger(this));
429 // ToDo: is this correct? If message == NULL (even if IsWatched()), we always return B_BAD_VALUE
430 status_t err;
431 if (message)
432 err = BInvoker::Invoke(&clone);
433 else
434 err = B_BAD_VALUE;
436 // TODO: asynchronous messaging
437 SendNotices(kind, &clone);
439 return err;
443 BHandler*
444 BControl::ResolveSpecifier(BMessage* message, int32 index,
445 BMessage* specifier, int32 what, const char* property)
447 BPropertyInfo propInfo(sPropertyList);
449 if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK)
450 return this;
452 return BView::ResolveSpecifier(message, index, specifier, what,
453 property);
457 status_t
458 BControl::GetSupportedSuites(BMessage* message)
460 message->AddString("suites", "suite/vnd.Be-control");
462 BPropertyInfo propInfo(sPropertyList);
463 message->AddFlat("messages", &propInfo);
465 return BView::GetSupportedSuites(message);
469 status_t
470 BControl::Perform(perform_code code, void* _data)
472 switch (code) {
473 case PERFORM_CODE_MIN_SIZE:
474 ((perform_data_min_size*)_data)->return_value
475 = BControl::MinSize();
476 return B_OK;
477 case PERFORM_CODE_MAX_SIZE:
478 ((perform_data_max_size*)_data)->return_value
479 = BControl::MaxSize();
480 return B_OK;
481 case PERFORM_CODE_PREFERRED_SIZE:
482 ((perform_data_preferred_size*)_data)->return_value
483 = BControl::PreferredSize();
484 return B_OK;
485 case PERFORM_CODE_LAYOUT_ALIGNMENT:
486 ((perform_data_layout_alignment*)_data)->return_value
487 = BControl::LayoutAlignment();
488 return B_OK;
489 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
490 ((perform_data_has_height_for_width*)_data)->return_value
491 = BControl::HasHeightForWidth();
492 return B_OK;
493 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
495 perform_data_get_height_for_width* data
496 = (perform_data_get_height_for_width*)_data;
497 BControl::GetHeightForWidth(data->width, &data->min, &data->max,
498 &data->preferred);
499 return B_OK;
501 case PERFORM_CODE_SET_LAYOUT:
503 perform_data_set_layout* data = (perform_data_set_layout*)_data;
504 BControl::SetLayout(data->layout);
505 return B_OK;
507 case PERFORM_CODE_LAYOUT_INVALIDATED:
509 perform_data_layout_invalidated* data
510 = (perform_data_layout_invalidated*)_data;
511 BControl::LayoutInvalidated(data->descendants);
512 return B_OK;
514 case PERFORM_CODE_DO_LAYOUT:
516 BControl::DoLayout();
517 return B_OK;
519 case PERFORM_CODE_SET_ICON:
521 perform_data_set_icon* data = (perform_data_set_icon*)_data;
522 return BControl::SetIcon(data->icon, data->flags);
526 return BView::Perform(code, _data);
530 status_t
531 BControl::SetIcon(const BBitmap* bitmap, uint32 flags)
533 status_t error = BIcon::UpdateIcon(bitmap, flags, fIcon);
535 if (error == B_OK) {
536 InvalidateLayout();
537 Invalidate();
540 return error;
544 status_t
545 BControl::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags)
547 status_t error = BIcon::SetIconBitmap(bitmap, which, flags, fIcon);
549 if (error != B_OK) {
550 InvalidateLayout();
551 Invalidate();
554 return error;
558 const BBitmap*
559 BControl::IconBitmap(uint32 which) const
561 return fIcon != NULL ? fIcon->Bitmap(which) : NULL;
565 bool
566 BControl::IsFocusChanging() const
568 return fFocusChanging;
572 bool
573 BControl::IsTracking() const
575 return fTracking;
579 void
580 BControl::SetTracking(bool state)
582 fTracking = state;
586 extern "C" status_t
587 B_IF_GCC_2(_ReservedControl1__8BControl, _ZN8BControl17_ReservedControl1Ev)(
588 BControl* control, const BBitmap* icon, uint32 flags)
590 // SetIcon()
591 perform_data_set_icon data;
592 data.icon = icon;
593 data.flags = flags;
594 return control->Perform(PERFORM_CODE_SET_ICON, &data);
598 void BControl::_ReservedControl2() {}
599 void BControl::_ReservedControl3() {}
600 void BControl::_ReservedControl4() {}
603 BControl &
604 BControl::operator=(const BControl &)
606 return *this;
610 void
611 BControl::InitData(BMessage* data)
613 fLabel = NULL;
614 SetLabel(B_EMPTY_STRING);
615 fValue = B_CONTROL_OFF;
616 fEnabled = true;
617 fFocusChanging = false;
618 fTracking = false;
619 fWantsNav = Flags() & B_NAVIGABLE;
620 fIcon = NULL;
622 if (data && data->HasString("_fname"))
623 SetFont(be_plain_font, B_FONT_FAMILY_AND_STYLE);