1/*
2 * Copyright 2003-2007, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		J��r��me Duval
7 *		Jonas Sundstr��m
8 */
9
10
11#include "DeskButton.h"
12
13#include <Alert.h>
14#include <Bitmap.h>
15#include <Catalog.h>
16#include <ControlLook.h>
17#include <Dragger.h>
18#include <MenuItem.h>
19#include <Message.h>
20#include <NodeInfo.h>
21#include <PopUpMenu.h>
22#include <Roster.h>
23#include <String.h>
24
25#include <stdlib.h>
26
27#define OPEN_REF	'opre'
28#define DO_ACTION	'doac'
29
30
31#undef B_TRANSLATION_CONTEXT
32#define B_TRANSLATION_CONTEXT "DeskButton"
33
34
35extern const char *kAppSignature;
36	// from desklink.cpp
37
38
39DeskButton::DeskButton(BRect frame, entry_ref* ref, const char* name,
40		BList& titles, BList& actions, uint32 resizeMask, uint32 flags)
41	: BView(frame, name, resizeMask, flags),
42	fRef(*ref),
43	fActionList(actions),
44	fTitleList(titles)
45{
46	fSegments = new BBitmap(frame, B_RGBA32);
47	BNodeInfo::GetTrackerIcon(&fRef, fSegments, (icon_size)-1);
48}
49
50
51DeskButton::DeskButton(BMessage *message)
52	: BView(message)
53{
54	message->FindRef("ref", &fRef);
55
56	BString title, action;
57	int32 index = 0;
58	while(message->FindString("title", index, &title)==B_OK
59		&& message->FindString("action", index, &action)==B_OK) {
60		fTitleList.AddItem(new BString(title));
61		fActionList.AddItem(new BString(action));
62		index++;
63	}
64
65	BRect bounds;
66	message->FindRect("bounds", &bounds);
67
68	fSegments = new BBitmap(bounds, B_RGBA32);
69	BNodeInfo::GetTrackerIcon(&fRef, fSegments, (icon_size)-1);
70}
71
72
73DeskButton::~DeskButton()
74{
75	delete fSegments;
76}
77
78
79// archiving overrides
80DeskButton *
81DeskButton::Instantiate(BMessage *data)
82{
83	if (!validate_instantiation(data, "DeskButton"))
84		return NULL;
85
86	return new DeskButton(data);
87}
88
89
90status_t
91DeskButton::Archive(BMessage *data, bool deep) const
92{
93	BView::Archive(data, deep);
94
95	data->AddRef("ref", &fRef);
96
97	for (int32 i = 0; i < fTitleList.CountItems()
98			&& i < fActionList.CountItems(); i++) {
99		data->AddString("title", *(BString*)fTitleList.ItemAt(i));
100		data->AddString("action", *(BString*)fActionList.ItemAt(i));
101	}
102
103	data->AddRect("bounds", fSegments->Bounds());
104
105	data->AddString("add_on", kAppSignature);
106	return B_NO_ERROR;
107}
108
109
110void
111DeskButton::MessageReceived(BMessage *message)
112{
113	switch (message->what) {
114		case OPEN_REF:
115			be_roster->Launch(&fRef);
116			break;
117
118		case DO_ACTION:
119		{
120			BString action;
121			if (message->FindString("action", &action) == B_OK) {
122				action += " &";
123				system(action.String());
124			}
125			break;
126		}
127
128		default:
129			BView::MessageReceived(message);
130			break;
131	}
132}
133
134
135void
136DeskButton::AttachedToWindow()
137{
138	BView *parent = Parent();
139	if (parent)
140		SetViewColor(parent->ViewColor());
141
142	BView::AttachedToWindow();
143}
144
145
146void
147DeskButton::Draw(BRect rect)
148{
149	BView::Draw(rect);
150
151#ifdef __HAIKU__
152	SetDrawingMode(B_OP_ALPHA);
153	SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
154#else
155	SetDrawingMode(B_OP_OVER);
156#endif
157	DrawBitmap(fSegments);
158}
159
160
161void
162DeskButton::MouseDown(BPoint point)
163{
164	uint32 mouseButtons = 0;
165	if (Window()->CurrentMessage() != NULL)
166		mouseButtons = Window()->CurrentMessage()->FindInt32("buttons");
167
168	BPoint where = ConvertToScreen(point);
169
170	if (mouseButtons & B_SECONDARY_MOUSE_BUTTON) {
171		BString label = B_TRANSLATE_COMMENT("Open %name", "Don't translate "
172			"variable %name");
173		label.ReplaceFirst("%name", fRef.name);
174		BPopUpMenu *menu = new BPopUpMenu("", false, false);
175		menu->SetFont(be_plain_font);
176		menu->AddItem(new BMenuItem(label.String(), new BMessage(OPEN_REF)));
177		if (fTitleList.CountItems() > 0 && fActionList.CountItems() > 0) {
178			menu->AddSeparatorItem();
179			for (int32 i = 0; i < fTitleList.CountItems()
180					&& i < fActionList.CountItems(); i++) {
181				BMessage *message = new BMessage(DO_ACTION);
182				message->AddString("action", *(BString*)fActionList.ItemAt(i));
183				menu->AddItem(new BMenuItem(((BString*)fTitleList.ItemAt(i))->String(), message));
184			}
185		}
186
187		menu->SetTargetForItems(this);
188		menu->Go(where, true, true, BRect(where - BPoint(4, 4),
189			where + BPoint(4, 4)));
190	} else if (mouseButtons & B_PRIMARY_MOUSE_BUTTON) {
191		be_roster->Launch(&fRef);
192	}
193}
194