xref: /haiku/src/kits/interface/Button.cpp (revision 14e3d1b5768e7110b3d5c0855833267409b71dbb)
1 /*
2  *	Copyright 2001-2005, Haiku.
3  *  Distributed under the terms of the MIT License.
4  *
5  *	Authors:
6  *		Marc Flerackers (mflerackers@androme.be)
7  *		Mike Wilber
8  *		Stefano Ceccherini (burton666@libero.it)
9  *		Ivan Tonizza
10  *		Stephan Aßmus, <superstippi@gmx.de>
11  */
12 
13 
14 #include <Button.h>
15 
16 #include <Font.h>
17 #include <LayoutUtils.h>
18 #include <String.h>
19 #include <Window.h>
20 
21 
22 BButton::BButton(BRect frame, const char *name, const char *label, BMessage *message,
23 				  uint32 resizingMode, uint32 flags)
24 	:	BControl(frame, name, label, message, resizingMode,
25 			flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
26 		fDrawAsDefault(false)
27 {
28 	// Resize to minimum height if needed
29 	font_height fh;
30 	GetFontHeight(&fh);
31 	float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent);
32 	if (Bounds().Height() < minHeight)
33 		ResizeTo(Bounds().Width(), minHeight);
34 }
35 
36 
37 BButton::BButton(const char* name, const char* label, BMessage *message,
38 				 uint32 flags)
39 	:	BControl(BRect(0, 0, -1, -1), name, label, message, B_FOLLOW_NONE,
40 			flags | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_SUPPORTS_LAYOUT),
41 		fDrawAsDefault(false)
42 {
43 	// Resize to minimum height if needed
44 	font_height fh;
45 	GetFontHeight(&fh);
46 	float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent);
47 	if (Bounds().Height() < minHeight)
48 		ResizeTo(Bounds().Width(), minHeight);
49 }
50 
51 
52 BButton::BButton(const char* label, BMessage *message)
53 	:	BControl(BRect(0, 0, -1, -1), NULL, label, message, B_FOLLOW_NONE,
54 			B_WILL_DRAW | B_NAVIGABLE | B_FULL_UPDATE_ON_RESIZE
55 			| B_SUPPORTS_LAYOUT),
56 		fDrawAsDefault(false)
57 {
58 	// Resize to minimum height if needed
59 	font_height fh;
60 	GetFontHeight(&fh);
61 	float minHeight = 12.0f + (float)ceil(fh.ascent + fh.descent);
62 	if (Bounds().Height() < minHeight)
63 		ResizeTo(Bounds().Width(), minHeight);
64 }
65 
66 
67 BButton::~BButton()
68 {
69 }
70 
71 
72 BButton::BButton(BMessage *archive)
73 	:	BControl (archive)
74 {
75 	if (archive->FindBool("_default", &fDrawAsDefault) != B_OK)
76 		fDrawAsDefault = false;
77 }
78 
79 
80 BArchivable *
81 BButton::Instantiate(BMessage *archive)
82 {
83 	if (validate_instantiation(archive, "BButton"))
84 		return new BButton(archive);
85 
86 	return NULL;
87 }
88 
89 
90 status_t
91 BButton::Archive(BMessage* archive, bool deep) const
92 {
93 	status_t err = BControl::Archive(archive, deep);
94 
95 	if (err != B_OK)
96 		return err;
97 
98 	if (IsDefault())
99 		err = archive->AddBool("_default", true);
100 
101 	return err;
102 }
103 
104 
105 void
106 BButton::Draw(BRect updateRect)
107 {
108 	font_height fh;
109 	GetFontHeight(&fh);
110 
111 	const BRect bounds = Bounds();
112 	BRect rect = bounds;
113 
114 	const bool enabled = IsEnabled();
115 	const bool pushed = Value() == B_CONTROL_ON;
116 #if 0
117 	// Default indicator
118 	if (IsDefault())
119 		rect = DrawDefault(rect, enabled);
120 	else
121 		rect.InsetBy(1.0f, 1.0f);
122 
123 	BRect fillArea = rect;
124 	fillArea.InsetBy(3.0f, 3.0f);
125 
126 	BString text = Label();
127 
128 #if 1
129 	// Label truncation
130 	BFont font;
131 	GetFont(&font);
132 	font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width());
133 #endif
134 
135 	// Label position
136 	const float stringWidth = StringWidth(text.String());
137 	const float x = (bounds.right - stringWidth) / 2.0f;
138 	const float labelY = bounds.top
139 		+ ((bounds.Height() - fh.ascent - fh.descent) / 2.0f)
140 		+ fh.ascent +  1.0f;
141 	const float focusLineY = labelY + fh.descent;
142 
143 	/* speed trick:
144 	   if the focus changes but the button is not pressed then we can
145 	   redraw only the focus line,
146 	   if the focus changes and the button is pressed invert the internal rect
147 	   this block takes care of all the focus changes
148 	*/
149 	if (IsFocusChanging()) {
150 		if (pushed) {
151 			rect.InsetBy(2.0, 2.0);
152 			InvertRect(rect);
153 		} else
154 			DrawFocusLine(x, focusLineY, stringWidth, IsFocus() && Window()->IsActive());
155 
156 		return;
157 	}
158 
159 	// Colors
160 	const rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
161 	const rgb_color buttonBgColor=tint_color(panelBgColor, B_LIGHTEN_1_TINT);
162 	const rgb_color maxLightColor=tint_color(panelBgColor, B_LIGHTEN_MAX_TINT);
163 	const rgb_color maxShadowColor=tint_color(panelBgColor, B_DARKEN_MAX_TINT);
164 	const rgb_color darkBorderColor = tint_color(panelBgColor,
165 		enabled ? B_DARKEN_4_TINT : B_DARKEN_2_TINT);
166 	const rgb_color firstBevelColor = enabled ? tint_color(panelBgColor, B_DARKEN_2_TINT)
167 		: panelBgColor;
168 	const rgb_color cornerColor = IsDefault() ? firstBevelColor : panelBgColor;
169 
170 	// Fill the button area
171 	SetHighColor(buttonBgColor);
172 	FillRect(fillArea);
173 
174 	// external border
175 	SetHighColor(darkBorderColor);
176 	StrokeRect(rect);
177 
178 	BeginLineArray(14);
179 
180 	// Corners
181 	AddLine(rect.LeftTop(), rect.LeftTop(), cornerColor);
182 	AddLine(rect.LeftBottom(), rect.LeftBottom(), cornerColor);
183 	AddLine(rect.RightTop(), rect.RightTop(), cornerColor);
184 	AddLine(rect.RightBottom(), rect.RightBottom(), cornerColor);
185 
186 	rect.InsetBy(1.0f,1.0f);
187 
188 	// Shadow
189 	AddLine(rect.LeftBottom(), rect.RightBottom(), firstBevelColor);
190 	AddLine(rect.RightBottom(), rect.RightTop(), firstBevelColor);
191 	// Light
192 	AddLine(rect.LeftTop(), rect.LeftBottom(),buttonBgColor);
193 	AddLine(rect.LeftTop(), rect.RightTop(), buttonBgColor);
194 
195 	rect.InsetBy(1.0f, 1.0f);
196 
197 	// Shadow
198 	AddLine(rect.LeftBottom(), rect.RightBottom(), panelBgColor);
199 	AddLine(rect.RightBottom(), rect.RightTop(), panelBgColor);
200 	// Light
201 	AddLine(rect.LeftTop(), rect.LeftBottom(),maxLightColor);
202 	AddLine(rect.LeftTop(), rect.RightTop(), maxLightColor);
203 
204 	rect.InsetBy(1.0f,1.0f);
205 
206 	// Light
207 	AddLine(rect.LeftTop(), rect.LeftBottom(),maxLightColor);
208 	AddLine(rect.LeftTop(), rect.RightTop(), maxLightColor);
209 
210 	EndLineArray();
211 
212 	// Invert if clicked
213 	if (enabled && pushed) {
214 		rect.InsetBy(-2.0f, -2.0f);
215 		InvertRect(rect);
216 	}
217 
218 	// Label color
219 	if (enabled) {
220 		if (pushed) {
221 			SetHighColor(maxLightColor);
222 			SetLowColor(maxShadowColor);
223 		} else {
224 			SetHighColor(maxShadowColor);
225 			SetLowColor(tint_color(panelBgColor, B_LIGHTEN_2_TINT));
226 		}
227 	} else {
228 		SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT));
229 		SetLowColor(tint_color(panelBgColor, B_LIGHTEN_2_TINT));
230 	}
231 
232 	// Draw the label
233 	DrawString(text.String(), BPoint(x, labelY));
234 
235 	// Focus line
236 	if (enabled && IsFocus() && Window()->IsActive() && !pushed)
237 		DrawFocusLine(x,focusLineY,stringWidth,true);
238 #else
239 	// Default indicator
240 	if (IsDefault())
241 		rect = DrawDefault(rect, enabled);
242 
243 	BRect fillArea = rect;
244 	fillArea.InsetBy(3.0, 3.0);
245 
246 	BString text = Label();
247 
248 #if 1
249 	// Label truncation
250 	BFont font;
251 	GetFont(&font);
252 	font.TruncateString(&text, B_TRUNCATE_END, fillArea.Width() - 4);
253 #endif
254 
255 	// Label position
256 	const float stringWidth = StringWidth(text.String());
257 	const float x = (rect.right - stringWidth) / 2.0;
258 	const float labelY = bounds.top
259 		+ ((bounds.Height() - fh.ascent - fh.descent) / 2.0)
260 		+ fh.ascent +  1.0;
261 	const float focusLineY = labelY + fh.descent;
262 
263 	/* speed trick:
264 	   if the focus changes but the button is not pressed then we can
265 	   redraw only the focus line,
266 	   if the focus changes and the button is pressed invert the internal rect
267 	   this block takes care of all the focus changes
268 	*/
269 	if (IsFocusChanging()) {
270 		if (pushed) {
271 			rect.InsetBy(2.0, 2.0);
272 			InvertRect(rect);
273 		} else
274 			DrawFocusLine(x, focusLineY, stringWidth, IsFocus() && Window()->IsActive());
275 
276 		return;
277 	}
278 
279 	// colors
280 	rgb_color panelBgColor = ui_color(B_PANEL_BACKGROUND_COLOR);
281 	rgb_color buttonBgColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
282 	rgb_color lightColor;
283 	rgb_color maxLightColor;
284 	rgb_color maxShadowColor = tint_color(panelBgColor, B_DARKEN_MAX_TINT);
285 
286 	rgb_color dark1BorderColor;
287 	rgb_color dark2BorderColor;
288 
289 	rgb_color bevelColor1;
290 	rgb_color bevelColor2;
291 	rgb_color bevelColorRBCorner;
292 
293 	rgb_color borderBevelShadow;
294 	rgb_color borderBevelLight;
295 
296 	if (enabled) {
297 		lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
298 		maxLightColor = tint_color(panelBgColor, B_LIGHTEN_MAX_TINT);
299 
300 		dark1BorderColor = tint_color(panelBgColor, B_DARKEN_3_TINT);
301 		dark2BorderColor = tint_color(panelBgColor, B_DARKEN_4_TINT);
302 
303 		bevelColor1 = tint_color(panelBgColor, B_DARKEN_2_TINT);
304 		bevelColor2 = panelBgColor;
305 
306 		if (IsDefault()) {
307 			borderBevelShadow = tint_color(dark1BorderColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2);
308 			borderBevelLight = tint_color(dark1BorderColor, B_LIGHTEN_1_TINT);
309 
310 			borderBevelLight.red = (borderBevelLight.red + panelBgColor.red) / 2;
311 			borderBevelLight.green = (borderBevelLight.green + panelBgColor.green) / 2;
312 			borderBevelLight.blue = (borderBevelLight.blue + panelBgColor.blue) / 2;
313 
314 			dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_3_TINT);
315 			dark2BorderColor = tint_color(dark1BorderColor, B_DARKEN_4_TINT);
316 
317 			bevelColorRBCorner = borderBevelShadow;
318 		} else {
319 			borderBevelShadow = tint_color(panelBgColor, (B_NO_TINT + B_DARKEN_1_TINT) / 2);
320 			borderBevelLight = buttonBgColor;
321 
322 			bevelColorRBCorner = dark1BorderColor;
323 		}
324 	} else {
325 		lightColor = tint_color(panelBgColor, B_LIGHTEN_2_TINT);
326 		maxLightColor = tint_color(panelBgColor, B_LIGHTEN_1_TINT);
327 
328 		dark1BorderColor = tint_color(panelBgColor, B_DARKEN_1_TINT);
329 		dark2BorderColor = tint_color(panelBgColor, B_DARKEN_2_TINT);
330 
331 		bevelColor1 = panelBgColor;
332 		bevelColor2 = buttonBgColor;
333 
334 		if (IsDefault()) {
335 			borderBevelShadow = dark1BorderColor;
336 			borderBevelLight = panelBgColor;
337 			dark1BorderColor = tint_color(dark1BorderColor, B_DARKEN_1_TINT);
338 			dark2BorderColor = tint_color(dark1BorderColor, 1.16);
339 
340 		} else {
341 			borderBevelShadow = panelBgColor;
342 			borderBevelLight = panelBgColor;
343 		}
344 
345 		bevelColorRBCorner = tint_color(panelBgColor, 1.08);;
346 	}
347 
348 	// fill the button area
349 	SetHighColor(buttonBgColor);
350 	FillRect(fillArea);
351 
352 	BeginLineArray(22);
353 	// bevel around external border
354 	AddLine(BPoint(rect.left, rect.bottom),
355 			BPoint(rect.left, rect.top), borderBevelShadow);
356 	AddLine(BPoint(rect.left + 1, rect.top),
357 			BPoint(rect.right, rect.top), borderBevelShadow);
358 
359 	AddLine(BPoint(rect.right, rect.top + 1),
360 			BPoint(rect.right, rect.bottom), borderBevelLight);
361 	AddLine(BPoint(rect.left + 1, rect.bottom),
362 			BPoint(rect.right - 1, rect.bottom), borderBevelLight);
363 
364 	rect.InsetBy(1.0, 1.0);
365 
366 	// external border
367 	AddLine(BPoint(rect.left, rect.bottom),
368 			BPoint(rect.left, rect.top), dark1BorderColor);
369 	AddLine(BPoint(rect.left + 1, rect.top),
370 			BPoint(rect.right, rect.top), dark1BorderColor);
371 	AddLine(BPoint(rect.right, rect.top + 1),
372 			BPoint(rect.right, rect.bottom), dark2BorderColor);
373 	AddLine(BPoint(rect.right - 1, rect.bottom),
374 			BPoint(rect.left + 1, rect.bottom), dark2BorderColor);
375 
376 	rect.InsetBy(1.0, 1.0);
377 
378 	// Light
379 	AddLine(BPoint(rect.left, rect.top),
380 			BPoint(rect.left, rect.top), buttonBgColor);
381 	AddLine(BPoint(rect.left, rect.top + 1),
382 			BPoint(rect.left, rect.bottom - 1), lightColor);
383 	AddLine(BPoint(rect.left, rect.bottom),
384 			BPoint(rect.left, rect.bottom), bevelColor2);
385 	AddLine(BPoint(rect.left + 1, rect.top),
386 			BPoint(rect.right - 1, rect.top), lightColor);
387 	AddLine(BPoint(rect.right, rect.top),
388 			BPoint(rect.right, rect.top), bevelColor2);
389 	// Shadow
390 	AddLine(BPoint(rect.left + 1, rect.bottom),
391 			BPoint(rect.right - 1, rect.bottom), bevelColor1);
392 	AddLine(BPoint(rect.right, rect.bottom),
393 			BPoint(rect.right, rect.bottom), bevelColorRBCorner);
394 	AddLine(BPoint(rect.right, rect.bottom - 1),
395 			BPoint(rect.right, rect.top + 1), bevelColor1);
396 
397 	rect.InsetBy(1.0, 1.0);
398 
399 	// Light
400 	AddLine(BPoint(rect.left, rect.top),
401 			BPoint(rect.left, rect.bottom - 1), maxLightColor);
402 	AddLine(BPoint(rect.left, rect.bottom),
403 			BPoint(rect.left, rect.bottom), buttonBgColor);
404 	AddLine(BPoint(rect.left + 1, rect.top),
405 			BPoint(rect.right - 1, rect.top), maxLightColor);
406 	AddLine(BPoint(rect.right, rect.top),
407 			BPoint(rect.right, rect.top), buttonBgColor);
408 	// Shadow
409 	AddLine(BPoint(rect.left + 1, rect.bottom),
410 			BPoint(rect.right, rect.bottom), bevelColor2);
411 	AddLine(BPoint(rect.right, rect.bottom - 1),
412 			BPoint(rect.right, rect.top + 1), bevelColor2);
413 
414 	rect.InsetBy(1.0,1.0);
415 
416 	EndLineArray();
417 
418 	// Invert if clicked
419 	if (enabled && pushed) {
420 		rect.InsetBy(-2.0, -2.0);
421 		InvertRect(rect);
422 	}
423 
424 	// Label color
425 	if (enabled) {
426 		if (pushed) {
427 			SetHighColor(maxLightColor);
428 			SetLowColor(255 - buttonBgColor.red,
429 						255 - buttonBgColor.green,
430 						255 - buttonBgColor.blue);
431 		} else {
432 			SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
433 			SetLowColor(buttonBgColor);
434 		}
435 	} else {
436 		SetHighColor(tint_color(panelBgColor, B_DISABLED_LABEL_TINT));
437 		SetLowColor(buttonBgColor);
438 	}
439 
440 	// Draw the label
441 	DrawString(text.String(), BPoint(x, labelY));
442 
443 	// Focus line
444 	if (enabled && IsFocus() && Window()->IsActive() && !pushed)
445 		DrawFocusLine(x, focusLineY, stringWidth, true);
446 #endif
447 }
448 
449 
450 void
451 BButton::MouseDown(BPoint point)
452 {
453 	if (!IsEnabled())
454 		return;
455 
456 	SetValue(B_CONTROL_ON);
457 
458 	if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
459  		SetTracking(true);
460  		SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
461  	} else {
462 		BRect bounds = Bounds();
463 		uint32 buttons;
464 
465 		do {
466 			Window()->UpdateIfNeeded();
467 			snooze(40000);
468 
469 			GetMouse(&point, &buttons, true);
470 
471  			bool inside = bounds.Contains(point);
472 
473 			if ((Value() == B_CONTROL_ON) != inside)
474 				SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
475 		} while (buttons != 0);
476 
477 		if (Value() == B_CONTROL_ON)
478 			Invoke();
479 	}
480 }
481 
482 
483 void
484 BButton::AttachedToWindow()
485 {
486 	BControl::AttachedToWindow();
487 		// low color will now be the parents view color
488 
489 	if (IsDefault())
490 		Window()->SetDefaultButton(this);
491 
492 	SetViewColor(B_TRANSPARENT_COLOR);
493 }
494 
495 
496 void
497 BButton::KeyDown(const char *bytes, int32 numBytes)
498 {
499 	if (*bytes == B_ENTER || *bytes == B_SPACE) {
500 		if (!IsEnabled())
501 			return;
502 
503 		SetValue(B_CONTROL_ON);
504 
505 		// make sure the user saw that
506 		Window()->UpdateIfNeeded();
507 		snooze(25000);
508 
509 		Invoke();
510 
511 	} else
512 		BControl::KeyDown(bytes, numBytes);
513 }
514 
515 
516 void
517 BButton::MakeDefault(bool flag)
518 {
519 	BButton *oldDefault = NULL;
520 	BWindow *window = Window();
521 
522 	if (window)
523 		oldDefault = window->DefaultButton();
524 
525 	if (flag) {
526 		if (fDrawAsDefault && oldDefault == this)
527 			return;
528 
529 		if (!fDrawAsDefault) {
530 			fDrawAsDefault = true;
531 
532 			ResizeBy(6.0f, 6.0f);
533 			MoveBy(-3.0f, -3.0f);
534 		}
535 
536 		if (window && oldDefault != this)
537 			window->SetDefaultButton(this);
538 	} else {
539 		if (!fDrawAsDefault)
540 			return;
541 
542 		fDrawAsDefault = false;
543 
544 		ResizeBy(-6.0f, -6.0f);
545 		MoveBy(3.0f, 3.0f);
546 
547 		if (window && oldDefault == this)
548 			window->SetDefaultButton(NULL);
549 	}
550 }
551 
552 
553 void
554 BButton::SetLabel(const char *string)
555 {
556 	BControl::SetLabel(string);
557 }
558 
559 
560 bool
561 BButton::IsDefault() const
562 {
563 	return fDrawAsDefault;
564 }
565 
566 
567 void
568 BButton::MessageReceived(BMessage *message)
569 {
570 	BControl::MessageReceived(message);
571 }
572 
573 
574 void
575 BButton::WindowActivated(bool active)
576 {
577 	BControl::WindowActivated(active);
578 }
579 
580 
581 void
582 BButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
583 {
584 	if (!IsTracking())
585 		return;
586 
587 	bool inside = Bounds().Contains(point);
588 
589 	if ((Value() == B_CONTROL_ON) != inside)
590 		SetValue(inside ? B_CONTROL_ON : B_CONTROL_OFF);
591 }
592 
593 
594 void
595 BButton::MouseUp(BPoint point)
596 {
597 	if (!IsTracking())
598 		return;
599 
600 	if (Bounds().Contains(point))
601 		Invoke();
602 
603 	SetTracking(false);
604 }
605 
606 
607 void
608 BButton::DetachedFromWindow()
609 {
610 	BControl::DetachedFromWindow();
611 }
612 
613 
614 void
615 BButton::SetValue(int32 value)
616 {
617 	if (value != Value())
618 		BControl::SetValue(value);
619 }
620 
621 
622 void
623 BButton::GetPreferredSize(float *_width, float *_height)
624 {
625 	if (_height) {
626 		font_height fontHeight;
627 		GetFontHeight(&fontHeight);
628 
629 //		*_height = 12.0f + ceilf(fontHeight.ascent + fontHeight.descent)
630 		*_height = ceilf((fontHeight.ascent + fontHeight.descent) * 1.8)
631 			+ (fDrawAsDefault ? 6.0f : 0);
632 	}
633 
634 	if (_width) {
635 		float width = 20.0f + (float)ceil(StringWidth(Label()));
636 		if (width < 75.0f)
637 			width = 75.0f;
638 
639 		if (fDrawAsDefault)
640 			width += 6.0f;
641 
642 		*_width = width;
643 	}
644 }
645 
646 
647 void
648 BButton::ResizeToPreferred()
649 {
650 	 BControl::ResizeToPreferred();
651 }
652 
653 
654 status_t
655 BButton::Invoke(BMessage *message)
656 {
657 	Sync();
658 	snooze(50000);
659 
660 	status_t err = BControl::Invoke(message);
661 
662 	SetValue(B_CONTROL_OFF);
663 
664 	return err;
665 }
666 
667 
668 void
669 BButton::FrameMoved(BPoint newLocation)
670 {
671 	BControl::FrameMoved(newLocation);
672 }
673 
674 
675 void
676 BButton::FrameResized(float width, float height)
677 {
678 	BControl::FrameResized(width, height);
679 }
680 
681 
682 void
683 BButton::MakeFocus(bool focused)
684 {
685 	BControl::MakeFocus(focused);
686 }
687 
688 
689 void
690 BButton::AllAttached()
691 {
692 	BControl::AllAttached();
693 }
694 
695 
696 void
697 BButton::AllDetached()
698 {
699 	BControl::AllDetached();
700 }
701 
702 
703 BHandler *
704 BButton::ResolveSpecifier(BMessage *message, int32 index,
705 									BMessage *specifier, int32 what,
706 									const char *property)
707 {
708 	return BControl::ResolveSpecifier(message, index, specifier, what, property);
709 }
710 
711 
712 status_t
713 BButton::GetSupportedSuites(BMessage *message)
714 {
715 	return BControl::GetSupportedSuites(message);
716 }
717 
718 
719 status_t
720 BButton::Perform(perform_code d, void *arg)
721 {
722 	return BControl::Perform(d, arg);
723 }
724 
725 
726 BSize
727 BButton::MaxSize()
728 {
729 	float width, height;
730 	GetPreferredSize(&width, &height);
731 
732 	return BLayoutUtils::ComposeSize(ExplicitMaxSize(), BSize(width, height));
733 }
734 
735 
736 void BButton::_ReservedButton1() {}
737 void BButton::_ReservedButton2() {}
738 void BButton::_ReservedButton3() {}
739 
740 
741 BButton &
742 BButton::operator=(const BButton &)
743 {
744 	return *this;
745 }
746 
747 
748 BRect
749 BButton::DrawDefault(BRect bounds, bool enabled)
750 {
751 #if 0
752 	rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR),
753 	lighten1 = tint_color(no_tint, B_LIGHTEN_1_TINT),
754 	darken1 = tint_color(no_tint, B_DARKEN_1_TINT);
755 
756 	rgb_color borderColor;
757 	if (enabled)
758 		borderColor = tint_color(no_tint, B_DARKEN_4_TINT);
759 	else
760 		borderColor = darken1;
761 
762 	// Dark border
763 	BeginLineArray(4);
764 	AddLine(BPoint(bounds.left, bounds.bottom - 1.0f),
765 		BPoint(bounds.left, bounds.top + 1.0f), borderColor);
766 	AddLine(BPoint(bounds.left + 1.0f, bounds.top),
767 		BPoint(bounds.right - 1.0f, bounds.top), borderColor);
768 	AddLine(BPoint(bounds.right, bounds.top + 1.0f),
769 		BPoint(bounds.right, bounds.bottom - 1.0f), borderColor);
770 	AddLine(BPoint(bounds.left + 1.0f, bounds.bottom),
771 		BPoint(bounds.right - 1.0f, bounds.bottom), borderColor);
772 	EndLineArray();
773 
774 	if (enabled) {
775 		// Bevel
776 		bounds.InsetBy(1.0f, 1.0f);
777 		SetHighColor(darken1);
778 		StrokeRect(bounds);
779 	}
780 
781 	bounds.InsetBy(1.0f, 1.0f);
782 
783 	// Filling
784 	float inset = enabled? 2.0f : 3.0f;
785 	SetHighColor(lighten1);
786 
787 	FillRect(BRect(bounds.left, bounds.top,
788 		bounds.right, bounds.top+inset-1.0f));
789 	FillRect(BRect(bounds.left, bounds.bottom-inset+1.0f,
790 		bounds.right, bounds.bottom));
791 	FillRect(BRect(bounds.left, bounds.top+inset-1.0f,
792 		bounds.left+inset-1.0f, bounds.bottom-inset+1.0f));
793 	FillRect(BRect(bounds.right-inset+1.0f, bounds.top+inset-1.0f,
794 		bounds.right, bounds.bottom-inset+1.0f));
795 
796 	bounds.InsetBy(inset,inset);
797 
798 	return bounds;
799 #else
800 	rgb_color low = LowColor();
801 	rgb_color focusColor = tint_color(low, enabled ? (B_DARKEN_1_TINT + B_DARKEN_2_TINT) / 2
802 												   : (B_NO_TINT + B_DARKEN_1_TINT) / 2);
803 
804 	SetHighColor(focusColor);
805 
806 	StrokeRect(bounds, B_SOLID_LOW);
807 	bounds.InsetBy(1.0, 1.0);
808 	StrokeRect(bounds);
809 	bounds.InsetBy(1.0, 1.0);
810 	StrokeRect(bounds);
811 	bounds.InsetBy(1.0, 1.0);
812 
813 	return bounds;
814 #endif
815 }
816 
817 
818 status_t
819 BButton::Execute()
820 {
821 	if (!IsEnabled())
822 		return B_ERROR;
823 
824 	SetValue(B_CONTROL_ON);
825 	return Invoke();
826 }
827 
828 
829 void
830 BButton::DrawFocusLine(float x, float y, float width, bool visible)
831 {
832 	if (visible)
833 		SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
834 	else {
835 		SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
836 			B_LIGHTEN_1_TINT));
837 	}
838 
839 	// Blue Line
840 	StrokeLine(BPoint(x, y), BPoint(x + width, y));
841 
842 	if (visible)
843 		SetHighColor(255, 255, 255);
844 	// White Line
845 	StrokeLine(BPoint(x, y + 1.0f), BPoint(x + width, y + 1.0f));
846 }
847