2 * Copyright 2006-2009, Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
7 #include "LaunchButton.h"
14 #include <AppFileInfo.h>
15 #include <Application.h>
26 #include "MainWindow.h"
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "LaunchBox"
33 static const float kDragStartDist
= 10.0;
34 static const float kDragBitmapAlphaScale
= 0.6;
35 static const char* kEmptyHelpString
= B_TRANSLATE("You can drag an icon here.");
38 bigtime_t
LaunchButton::sClickSpeed
= 0;
39 bool LaunchButton::sIgnoreDoubleClick
= true;
42 LaunchButton::LaunchButton(const char* name
, const char* label
,
43 BMessage
* message
, BHandler
* target
)
45 BIconButton(name
, label
, message
, target
),
49 fAnticipatingDrop(false),
51 fIconSize(DEFAULT_ICON_SIZE
)
53 if (sClickSpeed
== 0 || get_click_speed(&sClickSpeed
) != B_OK
)
58 LaunchButton::~LaunchButton()
66 LaunchButton::AttachedToWindow()
68 BIconButton::AttachedToWindow();
74 LaunchButton::Draw(BRect updateRect
)
76 if (fAnticipatingDrop
) {
77 rgb_color color
= fRef
? ui_color(B_KEYBOARD_NAVIGATION_COLOR
)
78 : (rgb_color
){ 0, 130, 60, 255 };
80 // limit clipping region to exclude the blue rect we just drew
85 ConstrainClippingRegion(®ion
);
88 BIconButton::Draw(updateRect
);
90 rgb_color background
= LowColor();
91 rgb_color lightShadow
= tint_color(background
,
92 (B_NO_TINT
+ B_DARKEN_1_TINT
) / 2.0);
93 rgb_color shadow
= tint_color(background
, B_DARKEN_1_TINT
);
94 rgb_color light
= tint_color(background
, B_LIGHTEN_1_TINT
);
96 _DrawFrame(r
, shadow
, light
, lightShadow
, lightShadow
);
98 SetHighColor(lightShadow
);
105 LaunchButton::MessageReceived(BMessage
* message
)
107 switch (message
->what
) {
109 case B_REFS_RECEIVED
: {
111 if (message
->FindRef("refs", &ref
) == B_OK
) {
114 BEntry
entry(fRef
, true);
115 if (entry
.IsDirectory()) {
116 message
->PrintToStream();
117 // copy stuff into the directory
119 message
->what
= B_REFS_RECEIVED
;
122 team
= be_roster
->TeamFor(fAppSig
);
124 team
= be_roster
->TeamFor(fRef
);
127 be_roster
->Launch(fAppSig
, message
, &team
);
129 be_roster
->Launch(fRef
, message
, &team
);
133 && be_roster
->GetRunningAppInfo(team
,
135 BMessenger
messenger(appInfo
.signature
,
137 if (messenger
.IsValid())
138 messenger
.SendMessage(message
);
150 case B_MODIFIERS_CHANGED
:
152 BIconButton::MessageReceived(message
);
159 LaunchButton::MouseDown(BPoint where
)
161 bigtime_t now
= system_time();
162 bool callInherited
= true;
163 if (sIgnoreDoubleClick
&& now
- fLastClickTime
< sClickSpeed
)
164 callInherited
= false;
165 fLastClickTime
= now
;
166 if (BMessage
* message
= Window()->CurrentMessage()) {
168 message
->FindInt32("buttons", (int32
*)&buttons
);
169 if ((buttons
& B_SECONDARY_MOUSE_BUTTON
) != 0 && IsInside()) {
170 if (PadView
* parent
= dynamic_cast<PadView
*>(Parent())) {
171 parent
->DisplayMenu(ConvertToParent(where
), this);
173 callInherited
= false;
180 BIconButton::MouseDown(where
);
185 LaunchButton::MouseUp(BPoint where
)
187 if (fAnticipatingDrop
) {
188 fAnticipatingDrop
= false;
191 BIconButton::MouseUp(where
);
196 LaunchButton::MouseMoved(BPoint where
, uint32 transit
,
197 const BMessage
* dragMessage
)
199 if ((dragMessage
&& (transit
== B_ENTERED_VIEW
|| transit
== B_INSIDE_VIEW
))
200 && ((dragMessage
->what
== B_SIMPLE_DATA
201 || dragMessage
->what
== B_REFS_RECEIVED
) || fRef
)) {
202 if (!fAnticipatingDrop
) {
203 fAnticipatingDrop
= true;
207 if (!dragMessage
|| (transit
== B_EXITED_VIEW
|| transit
== B_OUTSIDE_VIEW
)) {
208 if (fAnticipatingDrop
) {
209 fAnticipatingDrop
= false;
213 // see if we should create a drag message
214 if (IsTracking() && fRef
!= NULL
) {
215 BPoint diff
= where
- fDragStart
;
216 float dist
= sqrtf(diff
.x
* diff
.x
+ diff
.y
* diff
.y
);
217 if (dist
>= kDragStartDist
) {
223 // create drag bitmap and message
224 if (BBitmap
* bitmap
= Bitmap()) {
225 if (bitmap
->ColorSpace() == B_RGB32
) {
226 // make semitransparent
227 uint8
* bits
= (uint8
*)bitmap
->Bits();
228 uint32 width
= bitmap
->Bounds().IntegerWidth() + 1;
229 uint32 height
= bitmap
->Bounds().IntegerHeight() + 1;
230 uint32 bpr
= bitmap
->BytesPerRow();
231 for (uint32 y
= 0; y
< height
; y
++) {
232 uint8
* bitsHandle
= bits
;
233 for (uint32 x
= 0; x
< width
; x
++) {
234 bitsHandle
[3] = uint8(bitsHandle
[3]
235 * kDragBitmapAlphaScale
);
241 BMessage
message(B_SIMPLE_DATA
);
242 message
.AddPointer("button", this);
243 message
.AddRef("refs", fRef
);
244 // DragMessage takes ownership of the bitmap.
245 DragMessage(&message
, bitmap
, B_OP_ALPHA
, fDragStart
);
249 BIconButton::MouseMoved(where
, transit
, dragMessage
);
254 LaunchButton::MinSize()
256 return PreferredSize();
261 LaunchButton::PreferredSize()
263 float minWidth
= fIconSize
;
264 float minHeight
= fIconSize
;
266 float hPadding
= max_c(6.0, ceilf(minHeight
/ 3.0));
267 float vPadding
= max_c(6.0, ceilf(minWidth
/ 3.0));
269 if (Label() != NULL
&& Label()[0] != '\0') {
272 minHeight
+= ceilf(fh
.ascent
+ fh
.descent
) + vPadding
;
273 minWidth
+= StringWidth(Label()) + vPadding
;
276 return BSize(minWidth
+ hPadding
, minHeight
+ vPadding
);
281 LaunchButton::MaxSize()
283 return PreferredSize();
291 LaunchButton::SetTo(const entry_ref
* ref
)
298 fRef
= new entry_ref(*ref
);
300 BEntry
entry(fRef
, true);
304 // see if this is an application
305 BFile
file(ref
, B_READ_ONLY
);
307 if (info
.SetTo(&file
) == B_OK
) {
308 char mimeSig
[B_MIME_TYPE_LENGTH
];
309 if (info
.GetSignature(mimeSig
) == B_OK
) {
310 SetTo(mimeSig
, false);
312 fprintf(stderr
, "no MIME signature for '%s'\n", fRef
->name
);
315 fprintf(stderr
, "no BAppFileInfo for '%s'\n", fRef
->name
);
322 _NotifySettingsChanged();
327 LaunchButton::Ref() const
334 LaunchButton::SetTo(const char* appSig
, bool updateIcon
)
338 fAppSig
= strdup(appSig
);
341 if (be_roster
->FindApp(fAppSig
, &ref
) == B_OK
)
346 _NotifySettingsChanged();
351 LaunchButton::SetDescription(const char* text
)
353 fDescription
.SetTo(text
);
355 _NotifySettingsChanged();
360 LaunchButton::SetIconSize(uint32 size
)
362 if (fIconSize
== size
)
374 LaunchButton::SetIgnoreDoubleClick(bool refuse
)
376 sIgnoreDoubleClick
= refuse
;
384 LaunchButton::_UpdateToolTip()
386 // TODO: This works around a bug in the tool tip management.
387 // Remove when fixed (although no harm done...)
389 SetToolTip(static_cast<BToolTip
*>(NULL
));
392 BString
helper(fRef
->name
);
393 if (fDescription
.CountChars() > 0) {
394 if (fDescription
!= helper
)
395 helper
<< "\n\n" << fDescription
.String();
397 BFile
file(fRef
, B_READ_ONLY
);
398 BAppFileInfo appFileInfo
;
400 if (appFileInfo
.SetTo(&file
) == B_OK
401 && appFileInfo
.GetVersionInfo(&info
,
402 B_APP_VERSION_KIND
) == B_OK
403 && strlen(info
.short_info
) > 0
404 && helper
.Compare(info
.short_info
) != 0) {
405 helper
<< "\n\n" << info
.short_info
;
408 SetToolTip(helper
.String());
410 SetToolTip(kEmptyHelpString
);
416 LaunchButton::_UpdateIcon(const entry_ref
* ref
)
418 BBitmap
* icon
= new BBitmap(BRect(0.0, 0.0, fIconSize
- 1,
419 fIconSize
- 1), B_RGBA32
);
420 // NOTE: passing an invalid/unknown icon_size argument will cause
421 // the BNodeInfo to ignore it and just use the bitmap bounds.
422 if (BNodeInfo::GetTrackerIcon(ref
, icon
, (icon_size
)fIconSize
) == B_OK
)
430 LaunchButton::_NotifySettingsChanged()
432 be_app
->PostMessage(MSG_SETTINGS_CHANGED
);
437 LaunchButton::_DrawFrame(BRect r
, rgb_color col1
, rgb_color col2
,
438 rgb_color col3
, rgb_color col4
)
441 AddLine(BPoint(r
.left
, r
.bottom
), BPoint(r
.left
, r
.top
), col1
);
442 AddLine(BPoint(r
.left
+ 1.0, r
.top
), BPoint(r
.right
, r
.top
), col1
);
443 AddLine(BPoint(r
.right
, r
.top
+ 1.0), BPoint(r
.right
, r
.bottom
), col2
);
444 AddLine(BPoint(r
.right
- 1.0, r
.bottom
), BPoint(r
.left
+ 1.0, r
.bottom
), col2
);
446 AddLine(BPoint(r
.left
, r
.bottom
), BPoint(r
.left
, r
.top
), col3
);
447 AddLine(BPoint(r
.left
+ 1.0, r
.top
), BPoint(r
.right
, r
.top
), col3
);
448 AddLine(BPoint(r
.right
, r
.top
+ 1.0), BPoint(r
.right
, r
.bottom
), col4
);
449 AddLine(BPoint(r
.right
- 1.0, r
.bottom
), BPoint(r
.left
+ 1.0, r
.bottom
), col4
);