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 delete menu; 189 } 190 191 192 void 193 DeskbarReplicant::_QuitBluetoothServer() 194 { 195 if (!be_roster->IsRunning(BLUETOOTH_SIGNATURE)) { 196 // The server isn't running, so remove ourself 197 BDeskbar deskbar; 198 deskbar.RemoveItem(kDeskbarItemName); 199 200 return; 201 } 202 status_t status = BMessenger(BLUETOOTH_SIGNATURE).SendMessage( 203 B_QUIT_REQUESTED); 204 if (status < B_OK) { 205 _ShowErrorAlert(B_TRANSLATE("Stopping the Bluetooth server failed."), 206 status); 207 } 208 } 209 210 211 void 212 DeskbarReplicant::_ShowErrorAlert(BString msg, status_t status) 213 { 214 BString error = B_TRANSLATE("Error: %status%"); 215 error.ReplaceFirst("%status%", strerror(status)); 216 msg << "\n\n" << error; 217 BAlert* alert = new BAlert(B_TRANSLATE("Bluetooth error"), msg.String(), 218 B_TRANSLATE("OK")); 219 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 220 alert->Go(NULL); 221 } 222 223 // #pragma mark - 224 225 226 extern "C" _EXPORT BView * 227 instantiate_deskbar_item(void) 228 { 229 return new DeskbarReplicant(BRect(0, 0, 15, 15), 230 B_FOLLOW_LEFT | B_FOLLOW_TOP); 231 } 232 233 // #pragma mark - 234 235 236 status_t 237 our_image(image_info& image) 238 { 239 int32 cookie = 0; 240 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &image) == B_OK) { 241 if ((char *)our_image >= (char *)image.text 242 && (char *)our_image <= (char *)image.text + image.text_size) 243 return B_OK; 244 } 245 246 return B_ERROR; 247 } 248