1 /* 2 * Copyright 2004-2015 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexander von Gluck IV, kallisti5@unixzen.com 7 * Philippe Houdoin 8 * Fredrik Modéen 9 * John Scipione, jscipione@gmail.com 10 */ 11 12 13 #include "InterfaceListItem.h" 14 15 #include <algorithm> 16 17 #include <Application.h> 18 #include <Bitmap.h> 19 #include <Catalog.h> 20 #include <ControlLook.h> 21 #include <IconUtils.h> 22 #include <OutlineListView.h> 23 #include <Resources.h> 24 #include <String.h> 25 26 27 #undef B_TRANSLATION_CONTEXT 28 #define B_TRANSLATION_CONTEXT "InterfaceListItem" 29 30 31 InterfaceListItem::InterfaceListItem(const char* name, 32 BNetworkInterfaceType type) 33 : 34 BListItem(0, false), 35 fType(type), 36 fIcon(NULL), 37 fIconOffline(NULL), 38 fIconPending(NULL), 39 fIconOnline(NULL), 40 fFirstLineOffset(0), 41 fLineOffset(0), 42 fDisabled(false), 43 fHasLink(false), 44 fConnecting(false) 45 { 46 fInterface.SetTo(name); 47 _Init(); 48 } 49 50 51 InterfaceListItem::~InterfaceListItem() 52 { 53 delete fIcon; 54 delete fIconOffline; 55 delete fIconPending; 56 delete fIconOnline; 57 } 58 59 60 // #pragma mark - InterfaceListItem public methods 61 62 63 void 64 InterfaceListItem::DrawItem(BView* owner, BRect bounds, bool complete) 65 { 66 owner->PushState(); 67 68 rgb_color lowColor = owner->LowColor(); 69 70 if (IsSelected() || complete) { 71 if (IsSelected()) { 72 owner->SetHighColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR)); 73 owner->SetLowColor(owner->HighColor()); 74 } else 75 owner->SetHighColor(lowColor); 76 77 owner->FillRect(bounds); 78 } 79 80 BBitmap* stateIcon = _StateIcon(); 81 const int32 stateIconWidth = stateIcon->Bounds().IntegerWidth() + 1; 82 const char* stateText = _StateText(); 83 84 // Set the initial bounds of item contents 85 BPoint iconPoint = bounds.LeftTop() 86 + BPoint(be_control_look->DefaultLabelSpacing(), 2); 87 BPoint statePoint = bounds.RightTop() + BPoint(0, fFirstLineOffset) 88 - BPoint(be_plain_font->StringWidth(stateText) 89 + be_control_look->DefaultLabelSpacing(), 0); 90 BPoint namePoint = bounds.LeftTop() 91 + BPoint(stateIconWidth + (be_control_look->DefaultLabelSpacing() * 2), 92 fFirstLineOffset); 93 94 if (fDisabled) { 95 owner->SetDrawingMode(B_OP_ALPHA); 96 owner->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); 97 owner->SetHighColor(0, 0, 0, 32); 98 } else 99 owner->SetDrawingMode(B_OP_OVER); 100 101 owner->DrawBitmapAsync(fIcon, iconPoint); 102 owner->DrawBitmapAsync(stateIcon, iconPoint); 103 104 if (fDisabled) { 105 rgb_color textColor; 106 if (IsSelected()) 107 textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR); 108 else 109 textColor = ui_color(B_LIST_ITEM_TEXT_COLOR); 110 111 if (textColor.red + textColor.green + textColor.blue > 128 * 3) 112 owner->SetHighColor(tint_color(textColor, B_DARKEN_1_TINT)); 113 else 114 owner->SetHighColor(tint_color(textColor, B_LIGHTEN_1_TINT)); 115 } else { 116 if (IsSelected()) 117 owner->SetHighColor(ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR)); 118 else 119 owner->SetHighColor(ui_color(B_LIST_ITEM_TEXT_COLOR)); 120 } 121 122 owner->SetFont(be_bold_font); 123 124 owner->DrawString(fDeviceName, namePoint); 125 owner->SetFont(be_plain_font); 126 owner->DrawString(stateText, statePoint); 127 128 BPoint linePoint = bounds.LeftTop() 129 + BPoint(stateIconWidth + (be_control_look->DefaultLabelSpacing() * 2), 130 fFirstLineOffset + fLineOffset); 131 owner->DrawString(fSubtitle, linePoint); 132 133 owner->PopState(); 134 } 135 136 137 void 138 InterfaceListItem::Update(BView* owner, const BFont* font) 139 { 140 BListItem::Update(owner, font); 141 font_height height; 142 font->GetHeight(&height); 143 144 float lineHeight = ceilf(height.ascent) + ceilf(height.descent) 145 + ceilf(height.leading); 146 147 fFirstLineOffset = 2 + ceilf(height.ascent + height.leading / 2); 148 fLineOffset = lineHeight; 149 150 _UpdateState(); 151 152 SetWidth(fIcon->Bounds().Width() + 36 153 + be_control_look->DefaultLabelSpacing() 154 + be_bold_font->StringWidth(fDeviceName.String()) 155 + owner->StringWidth(_StateText())); 156 SetHeight(std::max(2 * lineHeight + 4, fIcon->Bounds().Height() + 4)); 157 // either to the text height or icon height, whichever is taller 158 } 159 160 161 void 162 InterfaceListItem::ConfigurationUpdated(const BMessage& message) 163 { 164 _UpdateState(); 165 } 166 167 168 // #pragma mark - InterfaceListItem private methods 169 170 171 void 172 InterfaceListItem::_Init() 173 { 174 switch (fType) { 175 case B_NETWORK_INTERFACE_TYPE_WIFI: 176 _PopulateBitmaps("wifi"); 177 break; 178 case B_NETWORK_INTERFACE_TYPE_ETHERNET: 179 _PopulateBitmaps("ether"); 180 break; 181 case B_NETWORK_INTERFACE_TYPE_VPN: 182 _PopulateBitmaps("vpn"); 183 break; 184 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 185 _PopulateBitmaps("dialup"); 186 break; 187 default: 188 _PopulateBitmaps(NULL); 189 break; 190 } 191 } 192 193 194 void 195 InterfaceListItem::_PopulateBitmaps(const char* mediaType) 196 { 197 const uint8* interfaceHVIF; 198 const uint8* offlineHVIF; 199 const uint8* pendingHVIF; 200 const uint8* onlineHVIF; 201 202 BBitmap* interfaceBitmap = NULL; 203 BBitmap* offlineBitmap = NULL; 204 BBitmap* pendingBitmap = NULL; 205 BBitmap* onlineBitmap = NULL; 206 207 BResources* resources = BApplication::AppResources(); 208 209 size_t iconDataSize; 210 211 // Try specific interface icon? 212 interfaceHVIF = (const uint8*)resources->LoadResource( 213 B_VECTOR_ICON_TYPE, Name(), &iconDataSize); 214 215 if (interfaceHVIF == NULL && mediaType != NULL) 216 // Not found, try interface media type? 217 interfaceHVIF = (const uint8*)resources->LoadResource( 218 B_VECTOR_ICON_TYPE, mediaType, &iconDataSize); 219 if (interfaceHVIF == NULL) 220 // Not found, try default interface icon? 221 interfaceHVIF = (const uint8*)resources->LoadResource( 222 B_VECTOR_ICON_TYPE, "ether", &iconDataSize); 223 224 const BSize iconSize = be_control_look->ComposeIconSize(B_LARGE_ICON); 225 if (interfaceHVIF != NULL) { 226 // Now build the bitmap 227 interfaceBitmap = new(std::nothrow) BBitmap( 228 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 229 if (BIconUtils::GetVectorIcon(interfaceHVIF, 230 iconDataSize, interfaceBitmap) == B_OK) 231 fIcon = interfaceBitmap; 232 else 233 delete interfaceBitmap; 234 } 235 236 // Load possible state icons 237 offlineHVIF = (const uint8*)resources->LoadResource( 238 B_VECTOR_ICON_TYPE, "offline", &iconDataSize); 239 240 if (offlineHVIF != NULL) { 241 offlineBitmap = new(std::nothrow) BBitmap( 242 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 243 if (BIconUtils::GetVectorIcon(offlineHVIF, 244 iconDataSize, offlineBitmap) == B_OK) 245 fIconOffline = offlineBitmap; 246 else 247 delete offlineBitmap; 248 } 249 250 pendingHVIF = (const uint8*)resources->LoadResource( 251 B_VECTOR_ICON_TYPE, "pending", &iconDataSize); 252 253 if (pendingHVIF != NULL) { 254 pendingBitmap = new(std::nothrow) BBitmap( 255 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 256 if (BIconUtils::GetVectorIcon(pendingHVIF, 257 iconDataSize, pendingBitmap) == B_OK) 258 fIconPending = pendingBitmap; 259 else 260 delete pendingBitmap; 261 } 262 263 onlineHVIF = (const uint8*)resources->LoadResource( 264 B_VECTOR_ICON_TYPE, "online", &iconDataSize); 265 266 if (onlineHVIF != NULL) { 267 onlineBitmap = new(std::nothrow) BBitmap( 268 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 269 if (BIconUtils::GetVectorIcon(onlineHVIF, 270 iconDataSize, onlineBitmap) == B_OK) 271 fIconOnline = onlineBitmap; 272 else 273 delete onlineBitmap; 274 } 275 } 276 277 278 void 279 InterfaceListItem::_UpdateState() 280 { 281 fDeviceName = Name(); 282 fDeviceName.RemoveFirst("/dev/net/"); 283 284 fDisabled = (fInterface.Flags() & IFF_UP) == 0; 285 fHasLink = fInterface.HasLink(); 286 fConnecting = (fInterface.Flags() & IFF_CONFIGURING) != 0; 287 288 switch (fType) { 289 case B_NETWORK_INTERFACE_TYPE_WIFI: 290 fSubtitle = B_TRANSLATE("Wireless device"); 291 break; 292 case B_NETWORK_INTERFACE_TYPE_ETHERNET: 293 fSubtitle = B_TRANSLATE("Ethernet device"); 294 break; 295 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 296 fSubtitle = B_TRANSLATE("Dial-up connection"); 297 fDisabled = false; 298 break; 299 case B_NETWORK_INTERFACE_TYPE_VPN: 300 fSubtitle = B_TRANSLATE("VPN connection"); 301 fDisabled = false; 302 break; 303 default: 304 fSubtitle = ""; 305 } 306 } 307 308 309 BBitmap* 310 InterfaceListItem::_StateIcon() const 311 { 312 if (fDisabled) 313 return fIconOffline; 314 if (!fHasLink) 315 return fIconOffline; 316 // TODO! 317 // } else if ((fSettings->IPAddr(AF_INET).IsEmpty() 318 // && fSettings->IPAddr(AF_INET6).IsEmpty()) 319 // && (fSettings->AutoConfigure(AF_INET) 320 // || fSettings->AutoConfigure(AF_INET6))) { 321 // interfaceState = "connecting" B_UTF8_ELLIPSIS; 322 // stateIcon = fIconPending; 323 324 return fIconOnline; 325 } 326 327 328 const char* 329 InterfaceListItem::_StateText() const 330 { 331 if (fDisabled) 332 return B_TRANSLATE("disabled"); 333 334 if (!fInterface.HasLink()) { 335 switch (fType) { 336 case B_NETWORK_INTERFACE_TYPE_VPN: 337 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 338 return B_TRANSLATE("disconnected"); 339 default: 340 return B_TRANSLATE("no link"); 341 } 342 } 343 344 // TODO! 345 // } else if ((fSettings->IPAddr(AF_INET).IsEmpty() 346 // && fSettings->IPAddr(AF_INET6).IsEmpty()) 347 // && (fSettings->AutoConfigure(AF_INET) 348 // || fSettings->AutoConfigure(AF_INET6))) { 349 // interfaceState = "connecting" B_UTF8_ELLIPSIS; 350 // stateIcon = fIconPending; 351 352 return B_TRANSLATE("connected"); 353 } 354