btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / interface / Control.cpp
blob37aacc05605c2c504950efe7957b51ea49a3fbdc
1 /*
2 * Copyright 2001-2015, 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 }
48 { 0 }
52 BControl::BControl(BRect frame, const char* name, const char* label,
53 BMessage* message, uint32 resizingMode, uint32 flags)
55 BView(frame, name, resizingMode, flags)
57 InitData(NULL);
59 SetLabel(label);
60 SetMessage(message);
64 BControl::BControl(const char* name, const char* label, BMessage* message,
65 uint32 flags)
67 BView(name, flags)
69 InitData(NULL);
71 SetLabel(label);
72 SetMessage(message);
76 BControl::~BControl()
78 free(fLabel);
79 delete fIcon;
80 SetMessage(NULL);
84 BControl::BControl(BMessage* data)
86 BView(data)
88 InitData(data);
90 BMessage message;
91 if (data->FindMessage("_msg", &message) == B_OK)
92 SetMessage(new BMessage(message));
94 const char* label;
95 if (data->FindString("_label", &label) == B_OK)
96 SetLabel(label);
98 int32 value;
99 if (data->FindInt32("_val", &value) == B_OK)
100 SetValue(value);
102 bool toggle;
103 if (data->FindBool("_disable", &toggle) == B_OK)
104 SetEnabled(!toggle);
106 if (data->FindBool("be:wants_nav", &toggle) == B_OK)
107 fWantsNav = toggle;
111 BArchivable*
112 BControl::Instantiate(BMessage* data)
114 if (validate_instantiation(data, "BControl"))
115 return new BControl(data);
117 return NULL;
121 status_t
122 BControl::Archive(BMessage* data, bool deep) const
124 status_t status = BView::Archive(data, deep);
126 if (status == B_OK && Message())
127 status = data->AddMessage("_msg", Message());
129 if (status == B_OK && fLabel)
130 status = data->AddString("_label", fLabel);
132 if (status == B_OK && fValue != B_CONTROL_OFF)
133 status = data->AddInt32("_val", fValue);
135 if (status == B_OK && !fEnabled)
136 status = data->AddBool("_disable", true);
138 return status;
142 void
143 BControl::WindowActivated(bool active)
145 BView::WindowActivated(active);
147 if (IsFocus())
148 Invalidate();
152 void
153 BControl::AttachedToWindow()
155 AdoptParentColors();
157 if (ViewColor() == B_TRANSPARENT_COLOR
158 || Parent() == NULL) {
159 AdoptSystemColors();
162 // Force view color as low color
163 if (Parent() != NULL) {
164 float tint = B_NO_TINT;
165 color_which which = ViewUIColor(&tint);
166 if (which != B_NO_COLOR)
167 SetLowUIColor(which, tint);
168 else
169 SetLowColor(ViewColor());
172 if (!Messenger().IsValid())
173 SetTarget(Window());
175 BView::AttachedToWindow();
179 void
180 BControl::DetachedFromWindow()
182 BView::DetachedFromWindow();
186 void
187 BControl::AllAttached()
189 BView::AllAttached();
193 void
194 BControl::AllDetached()
196 BView::AllDetached();
200 void
201 BControl::MessageReceived(BMessage* message)
203 if (message->what == B_GET_PROPERTY || message->what == B_SET_PROPERTY) {
204 BMessage reply(B_REPLY);
205 bool handled = false;
207 BMessage specifier;
208 int32 index;
209 int32 form;
210 const char* property;
211 if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) {
212 if (strcmp(property, "Label") == 0) {
213 if (message->what == B_GET_PROPERTY) {
214 reply.AddString("result", fLabel);
215 handled = true;
216 } else {
217 // B_SET_PROPERTY
218 const char* label;
219 if (message->FindString("data", &label) == B_OK) {
220 SetLabel(label);
221 reply.AddInt32("error", B_OK);
222 handled = true;
225 } else if (strcmp(property, "Value") == 0) {
226 if (message->what == B_GET_PROPERTY) {
227 reply.AddInt32("result", fValue);
228 handled = true;
229 } else {
230 // B_SET_PROPERTY
231 int32 value;
232 if (message->FindInt32("data", &value) == B_OK) {
233 SetValue(value);
234 reply.AddInt32("error", B_OK);
235 handled = true;
238 } else if (strcmp(property, "Enabled") == 0) {
239 if (message->what == B_GET_PROPERTY) {
240 reply.AddBool("result", fEnabled);
241 handled = true;
242 } else {
243 // B_SET_PROPERTY
244 bool enabled;
245 if (message->FindBool("data", &enabled) == B_OK) {
246 SetEnabled(enabled);
247 reply.AddInt32("error", B_OK);
248 handled = true;
254 if (handled) {
255 message->SendReply(&reply);
256 return;
260 BView::MessageReceived(message);
264 void
265 BControl::MakeFocus(bool focus)
267 if (focus == IsFocus())
268 return;
270 BView::MakeFocus(focus);
272 if (Window() != NULL) {
273 fFocusChanging = true;
274 Invalidate(Bounds());
275 Flush();
276 fFocusChanging = false;
281 void
282 BControl::KeyDown(const char* bytes, int32 numBytes)
284 if (*bytes == B_ENTER || *bytes == B_SPACE) {
285 if (!fEnabled)
286 return;
288 SetValue(Value() ? B_CONTROL_OFF : B_CONTROL_ON);
289 Invoke();
290 } else
291 BView::KeyDown(bytes, numBytes);
295 void
296 BControl::MouseDown(BPoint where)
298 BView::MouseDown(where);
302 void
303 BControl::MouseUp(BPoint where)
305 BView::MouseUp(where);
309 void
310 BControl::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
312 BView::MouseMoved(where, code, dragMessage);
316 void
317 BControl::SetLabel(const char* label)
319 if (label != NULL && !label[0])
320 label = NULL;
322 // Has the label been changed?
323 if ((fLabel && label && !strcmp(fLabel, label))
324 || ((fLabel == NULL || !fLabel[0]) && label == NULL))
325 return;
327 free(fLabel);
328 fLabel = label ? strdup(label) : NULL;
330 InvalidateLayout();
331 Invalidate();
335 const char*
336 BControl::Label() const
338 return fLabel;
342 void
343 BControl::SetValue(int32 value)
345 if (value == fValue)
346 return;
348 fValue = value;
349 Invalidate();
353 void
354 BControl::SetValueNoUpdate(int32 value)
356 fValue = value;
360 int32
361 BControl::Value() const
363 return fValue;
367 void
368 BControl::SetEnabled(bool enabled)
370 if (fEnabled == enabled)
371 return;
373 fEnabled = enabled;
375 if (fEnabled && fWantsNav)
376 SetFlags(Flags() | B_NAVIGABLE);
377 else if (!fEnabled && (Flags() & B_NAVIGABLE)) {
378 fWantsNav = true;
379 SetFlags(Flags() & ~B_NAVIGABLE);
380 } else
381 fWantsNav = false;
383 if (Window()) {
384 Invalidate(Bounds());
385 Flush();
390 bool
391 BControl::IsEnabled() const
393 return fEnabled;
397 void
398 BControl::GetPreferredSize(float* _width, float* _height)
400 BView::GetPreferredSize(_width, _height);
404 void
405 BControl::ResizeToPreferred()
407 BView::ResizeToPreferred();
411 status_t
412 BControl::Invoke(BMessage* message)
414 bool notify = false;
415 uint32 kind = InvokeKind(&notify);
417 if (!message && !notify)
418 message = Message();
420 BMessage clone(kind);
422 if (!message) {
423 if (!IsWatched())
424 return B_BAD_VALUE;
425 } else
426 clone = *message;
428 clone.AddInt64("when", (int64)system_time());
429 clone.AddPointer("source", this);
430 clone.AddInt32("be:value", fValue);
431 clone.AddMessenger("be:sender", BMessenger(this));
433 // ToDo: is this correct? If message == NULL (even if IsWatched()), we always return B_BAD_VALUE
434 status_t err;
435 if (message)
436 err = BInvoker::Invoke(&clone);
437 else
438 err = B_BAD_VALUE;
440 // TODO: asynchronous messaging
441 SendNotices(kind, &clone);
443 return err;
447 BHandler*
448 BControl::ResolveSpecifier(BMessage* message, int32 index,
449 BMessage* specifier, int32 what, const char* property)
451 BPropertyInfo propInfo(sPropertyList);
453 if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK)
454 return this;
456 return BView::ResolveSpecifier(message, index, specifier, what,
457 property);
461 status_t
462 BControl::GetSupportedSuites(BMessage* message)
464 message->AddString("suites", "suite/vnd.Be-control");
466 BPropertyInfo propInfo(sPropertyList);
467 message->AddFlat("messages", &propInfo);
469 return BView::GetSupportedSuites(message);
473 status_t
474 BControl::Perform(perform_code code, void* _data)
476 switch (code) {
477 case PERFORM_CODE_MIN_SIZE:
478 ((perform_data_min_size*)_data)->return_value
479 = BControl::MinSize();
480 return B_OK;
481 case PERFORM_CODE_MAX_SIZE:
482 ((perform_data_max_size*)_data)->return_value
483 = BControl::MaxSize();
484 return B_OK;
485 case PERFORM_CODE_PREFERRED_SIZE:
486 ((perform_data_preferred_size*)_data)->return_value
487 = BControl::PreferredSize();
488 return B_OK;
489 case PERFORM_CODE_LAYOUT_ALIGNMENT:
490 ((perform_data_layout_alignment*)_data)->return_value
491 = BControl::LayoutAlignment();
492 return B_OK;
493 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
494 ((perform_data_has_height_for_width*)_data)->return_value
495 = BControl::HasHeightForWidth();
496 return B_OK;
497 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
499 perform_data_get_height_for_width* data
500 = (perform_data_get_height_for_width*)_data;
501 BControl::GetHeightForWidth(data->width, &data->min, &data->max,
502 &data->preferred);
503 return B_OK;
505 case PERFORM_CODE_SET_LAYOUT:
507 perform_data_set_layout* data = (perform_data_set_layout*)_data;
508 BControl::SetLayout(data->layout);
509 return B_OK;
511 case PERFORM_CODE_LAYOUT_INVALIDATED:
513 perform_data_layout_invalidated* data
514 = (perform_data_layout_invalidated*)_data;
515 BControl::LayoutInvalidated(data->descendants);
516 return B_OK;
518 case PERFORM_CODE_DO_LAYOUT:
520 BControl::DoLayout();
521 return B_OK;
523 case PERFORM_CODE_SET_ICON:
525 perform_data_set_icon* data = (perform_data_set_icon*)_data;
526 return BControl::SetIcon(data->icon, data->flags);
530 return BView::Perform(code, _data);
534 status_t
535 BControl::SetIcon(const BBitmap* bitmap, uint32 flags)
537 status_t error = BIcon::UpdateIcon(bitmap, flags, fIcon);
539 if (error == B_OK) {
540 InvalidateLayout();
541 Invalidate();
544 return error;
548 status_t
549 BControl::SetIconBitmap(const BBitmap* bitmap, uint32 which, uint32 flags)
551 status_t error = BIcon::SetIconBitmap(bitmap, which, flags, fIcon);
553 if (error != B_OK) {
554 InvalidateLayout();
555 Invalidate();
558 return error;
562 const BBitmap*
563 BControl::IconBitmap(uint32 which) const
565 return fIcon != NULL ? fIcon->Bitmap(which) : NULL;
569 bool
570 BControl::IsFocusChanging() const
572 return fFocusChanging;
576 bool
577 BControl::IsTracking() const
579 return fTracking;
583 void
584 BControl::SetTracking(bool state)
586 fTracking = state;
590 extern "C" status_t
591 B_IF_GCC_2(_ReservedControl1__8BControl, _ZN8BControl17_ReservedControl1Ev)(
592 BControl* control, const BBitmap* icon, uint32 flags)
594 // SetIcon()
595 perform_data_set_icon data;
596 data.icon = icon;
597 data.flags = flags;
598 return control->Perform(PERFORM_CODE_SET_ICON, &data);
602 void BControl::_ReservedControl2() {}
603 void BControl::_ReservedControl3() {}
604 void BControl::_ReservedControl4() {}
607 BControl &
608 BControl::operator=(const BControl &)
610 return *this;
614 void
615 BControl::InitData(BMessage* data)
617 SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
618 SetLowUIColor(ViewUIColor());
620 fLabel = NULL;
621 SetLabel(B_EMPTY_STRING);
622 fValue = B_CONTROL_OFF;
623 fEnabled = true;
624 fFocusChanging = false;
625 fTracking = false;
626 fWantsNav = Flags() & B_NAVIGABLE;
627 fIcon = NULL;
629 if (data && data->HasString("_fname"))
630 SetFont(be_plain_font, B_FONT_FAMILY_AND_STYLE);