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 #define DEFAULT_ICON_SIZE 64
28 #undef B_TRANSLATION_CONTEXT
29 #define B_TRANSLATION_CONTEXT "LaunchBox"
32 static const float kDragStartDist
= 10.0;
33 static const float kDragBitmapAlphaScale
= 0.6;
36 bigtime_t
LaunchButton::sClickSpeed
= 0;
37 bool LaunchButton::sIgnoreDoubleClick
= true;
40 LaunchButton::LaunchButton(const char* name
, const char* label
,
41 BMessage
* message
, BHandler
* target
)
43 BIconButton(name
, label
, message
, target
),
47 fAnticipatingDrop(false),
49 fIconSize(DEFAULT_ICON_SIZE
)
51 if (sClickSpeed
== 0 || get_click_speed(&sClickSpeed
) != B_OK
)
56 LaunchButton::~LaunchButton()
64 LaunchButton::AttachedToWindow()
66 BIconButton::AttachedToWindow();
72 LaunchButton::Draw(BRect updateRect
)
74 if (fAnticipatingDrop
) {
75 rgb_color color
= fRef
? ui_color(B_KEYBOARD_NAVIGATION_COLOR
)
76 : (rgb_color
){ 0, 130, 60, 255 };
78 // limit clipping region to exclude the blue rect we just drew
83 ConstrainClippingRegion(®ion
);
86 BIconButton::Draw(updateRect
);
88 rgb_color background
= LowColor();
89 rgb_color lightShadow
= tint_color(background
,
90 (B_NO_TINT
+ B_DARKEN_1_TINT
) / 2.0);
91 rgb_color shadow
= tint_color(background
, B_DARKEN_1_TINT
);
92 rgb_color light
= tint_color(background
, B_LIGHTEN_1_TINT
);
94 _DrawFrame(r
, shadow
, light
, lightShadow
, lightShadow
);
96 SetHighColor(lightShadow
);
103 LaunchButton::MessageReceived(BMessage
* message
)
105 switch (message
->what
) {
107 case B_REFS_RECEIVED
: {
109 if (message
->FindRef("refs", &ref
) == B_OK
) {
112 BEntry
entry(fRef
, true);
113 if (entry
.IsDirectory()) {
114 message
->PrintToStream();
115 // copy stuff into the directory
117 message
->what
= B_REFS_RECEIVED
;
120 team
= be_roster
->TeamFor(fAppSig
);
122 team
= be_roster
->TeamFor(fRef
);
125 be_roster
->Launch(fAppSig
, message
, &team
);
127 be_roster
->Launch(fRef
, message
, &team
);
131 && be_roster
->GetRunningAppInfo(team
,
133 BMessenger
messenger(appInfo
.signature
,
135 if (messenger
.IsValid())
136 messenger
.SendMessage(message
);
148 case B_MODIFIERS_CHANGED
:
150 BIconButton::MessageReceived(message
);
157 LaunchButton::MouseDown(BPoint where
)
159 bigtime_t now
= system_time();
160 bool callInherited
= true;
161 if (sIgnoreDoubleClick
&& now
- fLastClickTime
< sClickSpeed
)
162 callInherited
= false;
163 fLastClickTime
= now
;
164 if (BMessage
* message
= Window()->CurrentMessage()) {
166 message
->FindInt32("buttons", (int32
*)&buttons
);
167 if ((buttons
& B_SECONDARY_MOUSE_BUTTON
) != 0 && IsInside()) {
173 BIconButton::MouseDown(where
);
178 LaunchButton::MouseUp(BPoint where
)
180 if (fAnticipatingDrop
) {
181 fAnticipatingDrop
= false;
184 BIconButton::MouseUp(where
);
189 LaunchButton::MouseMoved(BPoint where
, uint32 transit
,
190 const BMessage
* dragMessage
)
192 if ((dragMessage
&& (transit
== B_ENTERED_VIEW
|| transit
== B_INSIDE_VIEW
))
193 && ((dragMessage
->what
== B_SIMPLE_DATA
194 || dragMessage
->what
== B_REFS_RECEIVED
) || fRef
)) {
195 if (!fAnticipatingDrop
) {
196 fAnticipatingDrop
= true;
200 if (!dragMessage
|| (transit
== B_EXITED_VIEW
|| transit
== B_OUTSIDE_VIEW
)) {
201 if (fAnticipatingDrop
) {
202 fAnticipatingDrop
= false;
207 BIconButton::MouseMoved(where
, transit
, dragMessage
);
212 LaunchButton::MinSize()
214 return PreferredSize();
219 LaunchButton::PreferredSize()
221 float minWidth
= fIconSize
;
222 float minHeight
= fIconSize
;
224 float hPadding
= max_c(6.0, ceilf(minHeight
/ 3.0));
225 float vPadding
= max_c(6.0, ceilf(minWidth
/ 3.0));
227 if (Label() != NULL
&& Label()[0] != '\0') {
230 minHeight
+= ceilf(fh
.ascent
+ fh
.descent
) + vPadding
;
231 minWidth
+= StringWidth(Label()) + vPadding
;
234 return BSize(minWidth
+ hPadding
, minHeight
+ vPadding
);
239 LaunchButton::MaxSize()
241 return PreferredSize();
249 LaunchButton::SetTo(const entry_ref
* ref
)
256 fRef
= new entry_ref(*ref
);
258 BEntry
entry(fRef
, true);
262 // see if this is an application
263 BFile
file(ref
, B_READ_ONLY
);
265 if (info
.SetTo(&file
) == B_OK
) {
266 char mimeSig
[B_MIME_TYPE_LENGTH
];
267 if (info
.GetSignature(mimeSig
) == B_OK
) {
268 SetTo(mimeSig
, false);
270 fprintf(stderr
, "no MIME signature for '%s'\n", fRef
->name
);
273 fprintf(stderr
, "no BAppFileInfo for '%s'\n", fRef
->name
);
284 LaunchButton::Ref() const
291 LaunchButton::SetTo(const char* appSig
, bool updateIcon
)
295 fAppSig
= strdup(appSig
);
298 if (be_roster
->FindApp(fAppSig
, &ref
) == B_OK
)
307 LaunchButton::SetDescription(const char* text
)
309 fDescription
.SetTo(text
);
315 LaunchButton::SetIconSize(uint32 size
)
317 if (fIconSize
== size
)
329 LaunchButton::SetIgnoreDoubleClick(bool refuse
)
331 sIgnoreDoubleClick
= refuse
;
339 LaunchButton::_UpdateToolTip()
341 // TODO: This works around a bug in the tool tip management.
342 // Remove when fixed (although no harm done...)
344 SetToolTip(static_cast<BToolTip
*>(NULL
));
347 BString
helper(fRef
->name
);
348 if (fDescription
.CountChars() > 0) {
349 if (fDescription
!= helper
)
350 helper
<< "\n\n" << fDescription
.String();
352 BFile
file(fRef
, B_READ_ONLY
);
353 BAppFileInfo appFileInfo
;
355 if (appFileInfo
.SetTo(&file
) == B_OK
356 && appFileInfo
.GetVersionInfo(&info
,
357 B_APP_VERSION_KIND
) == B_OK
358 && strlen(info
.short_info
) > 0
359 && helper
.Compare(info
.short_info
) != 0) {
360 helper
<< "\n\n" << info
.short_info
;
363 SetToolTip(helper
.String());
369 LaunchButton::_UpdateIcon(const entry_ref
* ref
)
371 BBitmap
* icon
= new BBitmap(BRect(0.0, 0.0, fIconSize
- 1,
372 fIconSize
- 1), B_RGBA32
);
373 // NOTE: passing an invalid/unknown icon_size argument will cause
374 // the BNodeInfo to ignore it and just use the bitmap bounds.
375 if (BNodeInfo::GetTrackerIcon(ref
, icon
, (icon_size
)fIconSize
) == B_OK
)
383 LaunchButton::_DrawFrame(BRect r
, rgb_color col1
, rgb_color col2
,
384 rgb_color col3
, rgb_color col4
)
387 AddLine(BPoint(r
.left
, r
.bottom
), BPoint(r
.left
, r
.top
), col1
);
388 AddLine(BPoint(r
.left
+ 1.0, r
.top
), BPoint(r
.right
, r
.top
), col1
);
389 AddLine(BPoint(r
.right
, r
.top
+ 1.0), BPoint(r
.right
, r
.bottom
), col2
);
390 AddLine(BPoint(r
.right
- 1.0, r
.bottom
), BPoint(r
.left
+ 1.0, r
.bottom
), col2
);
392 AddLine(BPoint(r
.left
, r
.bottom
), BPoint(r
.left
, r
.top
), col3
);
393 AddLine(BPoint(r
.left
+ 1.0, r
.top
), BPoint(r
.right
, r
.top
), col3
);
394 AddLine(BPoint(r
.right
, r
.top
+ 1.0), BPoint(r
.right
, r
.bottom
), col4
);
395 AddLine(BPoint(r
.right
- 1.0, r
.bottom
), BPoint(r
.left
+ 1.0, r
.bottom
), col4
);