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 kMsgShowBluetoothServerConsole = 'sbtc'; 30 const uint32 kMsgOpenBluetoothPreferences = 'obtp'; 31 const uint32 kMsgQuitBluetoothServer = 'qbts'; 32 33 const char* kDeskbarItemName = "BluetoothServerReplicant"; 34 const char* kClassName = "DeskbarReplicant"; 35 36 // #pragma mark - 37 38 39 DeskbarReplicant::DeskbarReplicant(BRect frame, int32 resizingMode) 40 : BView(frame, kDeskbarItemName, resizingMode, 41 B_WILL_DRAW | B_FRAME_EVENTS) 42 { 43 _Init(); 44 } 45 46 47 DeskbarReplicant::DeskbarReplicant(BMessage* archive) 48 : BView(archive) 49 { 50 _Init(); 51 } 52 53 54 DeskbarReplicant::~DeskbarReplicant() 55 { 56 } 57 58 59 void 60 DeskbarReplicant::_Init() 61 { 62 fIcon = NULL; 63 64 image_info info; 65 if (our_image(info) != B_OK) 66 return; 67 68 BFile file(info.name, B_READ_ONLY); 69 if (file.InitCheck() < B_OK) 70 return; 71 72 BResources resources(&file); 73 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 74 if (resources.InitCheck() < B_OK) 75 return; 76 #endif 77 78 size_t size; 79 const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, 80 "BEOS:ICON", &size); 81 if (data != NULL) { 82 BBitmap* icon = new BBitmap(Bounds(), B_RGBA32); 83 if (icon->InitCheck() == B_OK 84 && BIconUtils::GetVectorIcon((const uint8 *)data, 85 size, icon) == B_OK) { 86 fIcon = icon; 87 } else 88 delete icon; 89 } 90 } 91 92 93 DeskbarReplicant * 94 DeskbarReplicant::Instantiate(BMessage* archive) 95 { 96 if (!validate_instantiation(archive, kClassName)) 97 return NULL; 98 99 return new DeskbarReplicant(archive); 100 } 101 102 103 status_t 104 DeskbarReplicant::Archive(BMessage* archive, bool deep) const 105 { 106 status_t status = BView::Archive(archive, deep); 107 if (status == B_OK) 108 status = archive->AddString("add_on", BLUETOOTH_SIGNATURE); 109 if (status == B_OK) 110 status = archive->AddString("class", kClassName); 111 112 return status; 113 } 114 115 116 void 117 DeskbarReplicant::AttachedToWindow() 118 { 119 BView::AttachedToWindow(); 120 AdoptParentColors(); 121 122 SetLowColor(ViewColor()); 123 } 124 125 126 void 127 DeskbarReplicant::Draw(BRect updateRect) 128 { 129 if (!fIcon) { 130 /* At least display something... */ 131 rgb_color lowColor = LowColor(); 132 SetLowColor(0, 113, 187, 255); 133 FillRoundRect(Bounds().InsetBySelf(3.f, 0.f), 5.f, 7.f, B_SOLID_LOW); 134 SetLowColor(lowColor); 135 } else { 136 SetDrawingMode(B_OP_ALPHA); 137 DrawBitmap(fIcon); 138 SetDrawingMode(B_OP_COPY); 139 } 140 } 141 142 143 void 144 DeskbarReplicant::MessageReceived(BMessage* msg) 145 { 146 switch (msg->what) { 147 case kMsgShowBluetoothServerConsole: 148 _ShowBluetoothServerConsole(); 149 break; 150 151 case kMsgOpenBluetoothPreferences: 152 _OpenBluetoothPreferences(); 153 break; 154 155 case kMsgQuitBluetoothServer: 156 _QuitBluetoothServer(); 157 break; 158 159 default: 160 BView::MessageReceived(msg); 161 } 162 } 163 164 165 void 166 DeskbarReplicant::MouseDown(BPoint where) 167 { 168 BPoint point; 169 uint32 buttons; 170 GetMouse(&point, &buttons); 171 if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) { 172 return; 173 } 174 175 BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 176 177 menu->AddItem(new BMenuItem("Settings" B_UTF8_ELLIPSIS, 178 new BMessage(kMsgOpenBluetoothPreferences))); 179 180 // TODO show list of known/paired devices 181 182 /* The code below is for development purposes only, but doesn't 183 * hurt to be enabled as long as in alpha state. 184 */ 185 menu->AddSeparatorItem(); 186 187 menu->AddItem(new BMenuItem("Show server console" B_UTF8_ELLIPSIS, 188 new BMessage(kMsgShowBluetoothServerConsole))); 189 190 menu->AddItem(new BMenuItem("Stop server", 191 new BMessage(kMsgQuitBluetoothServer))); 192 193 menu->SetTargetForItems(this); 194 ConvertToScreen(&point); 195 menu->Go(point, true, true, true); 196 } 197 198 199 void 200 DeskbarReplicant::_OpenBluetoothPreferences() 201 { 202 status_t status = be_roster->Launch(BLUETOOTH_APP_SIGNATURE); 203 if (status < B_OK) { 204 _ShowErrorAlert("Launching the Bluetooth preflet failed.", status); 205 } 206 } 207 208 209 void 210 DeskbarReplicant::_ShowBluetoothServerConsole() 211 { 212 if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) { 213 return; 214 } 215 status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage( 216 BT_MSG_SERVER_SHOW_CONSOLE); 217 if (status < B_OK) { 218 _ShowErrorAlert("Showing the Bluetooth server console failed.", status); 219 } 220 } 221 222 223 void 224 DeskbarReplicant::_QuitBluetoothServer() 225 { 226 if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) { 227 return; 228 } 229 status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage( 230 B_QUIT_REQUESTED); 231 if (status < B_OK) { 232 _ShowErrorAlert("Stopping the Bluetooth server failed.", status); 233 } 234 } 235 236 237 void 238 DeskbarReplicant::_ShowErrorAlert(BString msg, status_t status) 239 { 240 msg << "\n\nError: " << strerror(status); 241 BAlert* alert = new BAlert("Bluetooth error", msg.String(), "OK"); 242 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 243 alert->Go(NULL); 244 } 245 246 // #pragma mark - 247 248 249 extern "C" _EXPORT BView * 250 instantiate_deskbar_item(void) 251 { 252 return new DeskbarReplicant(BRect(0, 0, 15, 15), 253 B_FOLLOW_LEFT | B_FOLLOW_TOP); 254 } 255 256 // #pragma mark - 257 258 259 status_t 260 our_image(image_info& image) 261 { 262 int32 cookie = 0; 263 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { 264 if ((char *)our_image >= (char *)image.text 265 && (char *)our_image <= (char *)image.text + image.text_size) 266 return B_OK; 267 } 268 269 return B_ERROR; 270 } 271