HaikuDepot: notify work status from main window
[haiku.git] / src / apps / switcher / LaunchButton.cpp
blob11905a56961190e55bdc41687763e11bd8453ad8
1 /*
2 * Copyright 2006-2009, Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
7 #include "LaunchButton.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #include <AppDefs.h>
14 #include <AppFileInfo.h>
15 #include <Application.h>
16 #include <Bitmap.h>
17 #include <Catalog.h>
18 #include <File.h>
19 #include <Node.h>
20 #include <NodeInfo.h>
21 #include <Region.h>
22 #include <Roster.h>
23 #include <Window.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),
44 fRef(NULL),
45 fAppSig(NULL),
46 fDescription(""),
47 fAnticipatingDrop(false),
48 fLastClickTime(0),
49 fIconSize(DEFAULT_ICON_SIZE)
51 if (sClickSpeed == 0 || get_click_speed(&sClickSpeed) != B_OK)
52 sClickSpeed = 500000;
56 LaunchButton::~LaunchButton()
58 delete fRef;
59 free(fAppSig);
63 void
64 LaunchButton::AttachedToWindow()
66 BIconButton::AttachedToWindow();
67 _UpdateToolTip();
71 void
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 };
77 SetHighColor(color);
78 // limit clipping region to exclude the blue rect we just drew
79 BRect r(Bounds());
80 StrokeRect(r);
81 r.InsetBy(1.0, 1.0);
82 BRegion region(r);
83 ConstrainClippingRegion(&region);
85 if (IsValid()) {
86 BIconButton::Draw(updateRect);
87 } else {
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);
93 BRect r(Bounds());
94 _DrawFrame(r, shadow, light, lightShadow, lightShadow);
95 r.InsetBy(2.0, 2.0);
96 SetHighColor(lightShadow);
97 FillRect(r);
102 void
103 LaunchButton::MessageReceived(BMessage* message)
105 switch (message->what) {
106 case B_SIMPLE_DATA:
107 case B_REFS_RECEIVED: {
108 entry_ref ref;
109 if (message->FindRef("refs", &ref) == B_OK) {
110 if (fRef) {
111 if (ref != *fRef) {
112 BEntry entry(fRef, true);
113 if (entry.IsDirectory()) {
114 message->PrintToStream();
115 // copy stuff into the directory
116 } else {
117 message->what = B_REFS_RECEIVED;
118 team_id team;
119 if (fAppSig)
120 team = be_roster->TeamFor(fAppSig);
121 else
122 team = be_roster->TeamFor(fRef);
123 if (team < 0) {
124 if (fAppSig)
125 be_roster->Launch(fAppSig, message, &team);
126 else
127 be_roster->Launch(fRef, message, &team);
128 } else {
129 app_info appInfo;
130 if (team >= 0
131 && be_roster->GetRunningAppInfo(team,
132 &appInfo) == B_OK) {
133 BMessenger messenger(appInfo.signature,
134 team);
135 if (messenger.IsValid())
136 messenger.SendMessage(message);
141 } else {
142 SetTo(&ref);
145 break;
147 case B_PASTE:
148 case B_MODIFIERS_CHANGED:
149 default:
150 BIconButton::MessageReceived(message);
151 break;
156 void
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()) {
165 uint32 buttons;
166 message->FindInt32("buttons", (int32*)&buttons);
167 if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0 && IsInside()) {
168 // context menu?
169 } else
170 fDragStart = where;
172 if (callInherited)
173 BIconButton::MouseDown(where);
177 void
178 LaunchButton::MouseUp(BPoint where)
180 if (fAnticipatingDrop) {
181 fAnticipatingDrop = false;
182 Invalidate();
184 BIconButton::MouseUp(where);
188 void
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;
197 Invalidate();
200 if (!dragMessage || (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)) {
201 if (fAnticipatingDrop) {
202 fAnticipatingDrop = false;
203 Invalidate();
207 BIconButton::MouseMoved(where, transit, dragMessage);
211 BSize
212 LaunchButton::MinSize()
214 return PreferredSize();
218 BSize
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') {
228 font_height fh;
229 GetFontHeight(&fh);
230 minHeight += ceilf(fh.ascent + fh.descent) + vPadding;
231 minWidth += StringWidth(Label()) + vPadding;
234 return BSize(minWidth + hPadding, minHeight + vPadding);
238 BSize
239 LaunchButton::MaxSize()
241 return PreferredSize();
245 // #pragma mark -
248 void
249 LaunchButton::SetTo(const entry_ref* ref)
251 free(fAppSig);
252 fAppSig = NULL;
254 delete fRef;
255 if (ref) {
256 fRef = new entry_ref(*ref);
257 // follow links
258 BEntry entry(fRef, true);
259 entry.GetRef(fRef);
261 _UpdateIcon(fRef);
262 // see if this is an application
263 BFile file(ref, B_READ_ONLY);
264 BAppFileInfo info;
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);
269 } else {
270 fprintf(stderr, "no MIME signature for '%s'\n", fRef->name);
272 } else {
273 fprintf(stderr, "no BAppFileInfo for '%s'\n", fRef->name);
275 } else {
276 fRef = NULL;
277 ClearIcon();
279 _UpdateToolTip();
283 entry_ref*
284 LaunchButton::Ref() const
286 return fRef;
290 void
291 LaunchButton::SetTo(const char* appSig, bool updateIcon)
293 if (appSig) {
294 free(fAppSig);
295 fAppSig = strdup(appSig);
296 if (updateIcon) {
297 entry_ref ref;
298 if (be_roster->FindApp(fAppSig, &ref) == B_OK)
299 SetTo(&ref);
302 _UpdateToolTip();
306 void
307 LaunchButton::SetDescription(const char* text)
309 fDescription.SetTo(text);
310 _UpdateToolTip();
314 void
315 LaunchButton::SetIconSize(uint32 size)
317 if (fIconSize == size)
318 return;
320 fIconSize = size;
321 _UpdateIcon(fRef);
323 InvalidateLayout();
324 Invalidate();
328 void
329 LaunchButton::SetIgnoreDoubleClick(bool refuse)
331 sIgnoreDoubleClick = refuse;
335 // #pragma mark -
338 void
339 LaunchButton::_UpdateToolTip()
341 // TODO: This works around a bug in the tool tip management.
342 // Remove when fixed (although no harm done...)
343 HideToolTip();
344 SetToolTip(static_cast<BToolTip*>(NULL));
346 if (fRef) {
347 BString helper(fRef->name);
348 if (fDescription.CountChars() > 0) {
349 if (fDescription != helper)
350 helper << "\n\n" << fDescription.String();
351 } else {
352 BFile file(fRef, B_READ_ONLY);
353 BAppFileInfo appFileInfo;
354 version_info info;
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());
368 void
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)
376 SetIcon(icon);
378 delete icon;
382 void
383 LaunchButton::_DrawFrame(BRect r, rgb_color col1, rgb_color col2,
384 rgb_color col3, rgb_color col4)
386 BeginLineArray(8);
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);
391 r.InsetBy(1.0, 1.0);
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);
396 EndLineArray();