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