xref: /haiku/src/servers/bluetooth/DeskbarReplicant.cpp (revision 95c9effd68127df2dce202d5e254a7c86560010a)
1 /*
2  * Copyright 2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Weirauch, dev@m-phasis.de
7  */
8 
9 
10 #include "DeskbarReplicant.h"
11 
12 #include <Alert.h>
13 #include <Application.h>
14 #include <Bitmap.h>
15 #include <Deskbar.h>
16 #include <IconUtils.h>
17 #include <MenuItem.h>
18 #include <Message.h>
19 #include <PopUpMenu.h>
20 #include <Resources.h>
21 #include <Roster.h>
22 #include <String.h>
23 
24 #include <bluetoothserver_p.h>
25 
26 extern "C" _EXPORT BView *instantiate_deskbar_item(void);
27 status_t our_image(image_info& image);
28 
29 const uint32 kMsgOpenBluetoothPreferences = 'obtp';
30 const uint32 kMsgQuitBluetoothServer = 'qbts';
31 
32 const char* kDeskbarItemName = "BluetoothServerReplicant";
33 const char* kClassName = "DeskbarReplicant";
34 
35 //	#pragma mark -
36 
37 
38 DeskbarReplicant::DeskbarReplicant(BRect frame, int32 resizingMode)
39 	: BView(frame, kDeskbarItemName, resizingMode,
40 		B_WILL_DRAW | B_FRAME_EVENTS)
41 {
42 	_Init();
43 }
44 
45 
46 DeskbarReplicant::DeskbarReplicant(BMessage* archive)
47 	: BView(archive)
48 {
49 	_Init();
50 }
51 
52 
53 DeskbarReplicant::~DeskbarReplicant()
54 {
55 }
56 
57 
58 void
59 DeskbarReplicant::_Init()
60 {
61 	fIcon = NULL;
62 
63 	image_info info;
64 	if (our_image(info) != B_OK)
65 		return;
66 
67 	BFile file(info.name, B_READ_ONLY);
68 	if (file.InitCheck() < B_OK)
69 		return;
70 
71 	BResources resources(&file);
72 #ifdef HAIKU_TARGET_PLATFORM_HAIKU
73 	if (resources.InitCheck() < B_OK)
74 		return;
75 #endif
76 
77 	size_t size;
78 	const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE,
79 		"tray_icon", &size);
80 	if (data != NULL) {
81 		BBitmap* icon = new BBitmap(Bounds(), B_RGBA32);
82 		if (icon->InitCheck() == B_OK
83 			&& BIconUtils::GetVectorIcon((const uint8 *)data,
84 				size, icon) == B_OK) {
85 			fIcon = icon;
86 		} else
87 			delete icon;
88 	}
89 }
90 
91 
92 DeskbarReplicant *
93 DeskbarReplicant::Instantiate(BMessage* archive)
94 {
95 	if (!validate_instantiation(archive, kClassName))
96 		return NULL;
97 
98 	return new DeskbarReplicant(archive);
99 }
100 
101 
102 status_t
103 DeskbarReplicant::Archive(BMessage* archive, bool deep) const
104 {
105 	status_t status = BView::Archive(archive, deep);
106 	if (status == B_OK)
107 		status = archive->AddString("add_on", BLUETOOTH_SIGNATURE);
108 	if (status == B_OK)
109 		status = archive->AddString("class", kClassName);
110 
111 	return status;
112 }
113 
114 
115 void
116 DeskbarReplicant::AttachedToWindow()
117 {
118 	BView::AttachedToWindow();
119 	AdoptParentColors();
120 
121 	SetLowColor(ViewColor());
122 }
123 
124 
125 void
126 DeskbarReplicant::Draw(BRect updateRect)
127 {
128 	if (!fIcon) {
129 		/* At least display something... */
130 		rgb_color lowColor = LowColor();
131 		SetLowColor(0, 113, 187, 255);
132 		FillRoundRect(Bounds().InsetBySelf(3.f, 0.f), 5.f, 7.f, B_SOLID_LOW);
133 		SetLowColor(lowColor);
134 	} else {
135 		SetDrawingMode(B_OP_ALPHA);
136 		DrawBitmap(fIcon);
137 		SetDrawingMode(B_OP_COPY);
138 	}
139 }
140 
141 
142 void
143 DeskbarReplicant::MessageReceived(BMessage* msg)
144 {
145 	switch (msg->what) {
146 		case kMsgOpenBluetoothPreferences:
147 			be_roster->Launch(BLUETOOTH_APP_SIGNATURE);
148 			break;
149 
150 		case kMsgQuitBluetoothServer:
151 			_QuitBluetoothServer();
152 			break;
153 
154 		default:
155 			BView::MessageReceived(msg);
156 	}
157 }
158 
159 
160 void
161 DeskbarReplicant::MouseDown(BPoint where)
162 {
163 	BPoint point;
164 	uint32 buttons;
165 	GetMouse(&point, &buttons);
166 	if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) {
167 		return;
168 	}
169 
170 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
171 
172 	menu->AddItem(new BMenuItem("Settings" B_UTF8_ELLIPSIS,
173 		new BMessage(kMsgOpenBluetoothPreferences)));
174 
175 	// TODO show list of known/paired devices
176 
177 	menu->AddItem(new BMenuItem("Quit",
178 		new BMessage(kMsgQuitBluetoothServer)));
179 
180 	menu->SetTargetForItems(this);
181 	ConvertToScreen(&point);
182 	menu->Go(point, true, true, true);
183 }
184 
185 
186 void
187 DeskbarReplicant::_QuitBluetoothServer()
188 {
189 	if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) {
190 		// The server isn't running, so remove ourself
191 		BDeskbar deskbar;
192 		deskbar.RemoveItem(kDeskbarItemName);
193 
194 		return;
195 	}
196 	status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage(
197 		B_QUIT_REQUESTED);
198 	if (status < B_OK) {
199 		_ShowErrorAlert("Stopping the Bluetooth server failed.", status);
200 	}
201 }
202 
203 
204 void
205 DeskbarReplicant::_ShowErrorAlert(BString msg, status_t status)
206 {
207 	msg << "\n\nError: " << strerror(status);
208 	BAlert* alert = new BAlert("Bluetooth error", msg.String(), "OK");
209 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
210 	alert->Go(NULL);
211 }
212 
213 //	#pragma mark -
214 
215 
216 extern "C" _EXPORT BView *
217 instantiate_deskbar_item(void)
218 {
219 	return new DeskbarReplicant(BRect(0, 0, 15, 15),
220 		B_FOLLOW_LEFT | B_FOLLOW_TOP);
221 }
222 
223 //	#pragma mark -
224 
225 
226 status_t
227 our_image(image_info& image)
228 {
229 	int32 cookie = 0;
230 	while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) {
231 		if ((char *)our_image >= (char *)image.text
232 			&& (char *)our_image <= (char *)image.text + image.text_size)
233 			return B_OK;
234 	}
235 
236 	return B_ERROR;
237 }
238