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 default: 176 case B_NETWORK_INTERFACE_TYPE_WIFI: 177 _PopulateBitmaps("wifi"); 178 break; 179 case B_NETWORK_INTERFACE_TYPE_ETHERNET: 180 _PopulateBitmaps("ether"); 181 break; 182 case B_NETWORK_INTERFACE_TYPE_VPN: 183 _PopulateBitmaps("vpn"); 184 break; 185 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 186 _PopulateBitmaps("dialup"); 187 break; 188 } 189 } 190 191 192 void 193 InterfaceListItem::_PopulateBitmaps(const char* mediaType) 194 { 195 const uint8* interfaceHVIF; 196 const uint8* offlineHVIF; 197 const uint8* pendingHVIF; 198 const uint8* onlineHVIF; 199 200 BBitmap* interfaceBitmap = NULL; 201 BBitmap* offlineBitmap = NULL; 202 BBitmap* pendingBitmap = NULL; 203 BBitmap* onlineBitmap = NULL; 204 205 BResources* resources = BApplication::AppResources(); 206 207 size_t iconDataSize; 208 209 // Try specific interface icon? 210 interfaceHVIF = (const uint8*)resources->LoadResource( 211 B_VECTOR_ICON_TYPE, Name(), &iconDataSize); 212 213 if (interfaceHVIF == NULL && mediaType != NULL) 214 // Not found, try interface media type? 215 interfaceHVIF = (const uint8*)resources->LoadResource( 216 B_VECTOR_ICON_TYPE, mediaType, &iconDataSize); 217 if (interfaceHVIF == NULL) 218 // Not found, try default interface icon? 219 interfaceHVIF = (const uint8*)resources->LoadResource( 220 B_VECTOR_ICON_TYPE, "ether", &iconDataSize); 221 222 const BSize iconSize = be_control_look->ComposeIconSize(B_LARGE_ICON); 223 if (interfaceHVIF != NULL) { 224 // Now build the bitmap 225 interfaceBitmap = new(std::nothrow) BBitmap( 226 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 227 if (BIconUtils::GetVectorIcon(interfaceHVIF, 228 iconDataSize, interfaceBitmap) == B_OK) 229 fIcon = interfaceBitmap; 230 else 231 delete interfaceBitmap; 232 } 233 234 // Load possible state icons 235 offlineHVIF = (const uint8*)resources->LoadResource( 236 B_VECTOR_ICON_TYPE, "offline", &iconDataSize); 237 238 if (offlineHVIF != NULL) { 239 offlineBitmap = new(std::nothrow) BBitmap( 240 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 241 if (BIconUtils::GetVectorIcon(offlineHVIF, 242 iconDataSize, offlineBitmap) == B_OK) 243 fIconOffline = offlineBitmap; 244 else 245 delete offlineBitmap; 246 } 247 248 pendingHVIF = (const uint8*)resources->LoadResource( 249 B_VECTOR_ICON_TYPE, "pending", &iconDataSize); 250 251 if (pendingHVIF != NULL) { 252 pendingBitmap = new(std::nothrow) BBitmap( 253 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 254 if (BIconUtils::GetVectorIcon(pendingHVIF, 255 iconDataSize, pendingBitmap) == B_OK) 256 fIconPending = pendingBitmap; 257 else 258 delete pendingBitmap; 259 } 260 261 onlineHVIF = (const uint8*)resources->LoadResource( 262 B_VECTOR_ICON_TYPE, "online", &iconDataSize); 263 264 if (onlineHVIF != NULL) { 265 onlineBitmap = new(std::nothrow) BBitmap( 266 BRect(BPoint(0, 0), iconSize), 0, B_RGBA32); 267 if (BIconUtils::GetVectorIcon(onlineHVIF, 268 iconDataSize, onlineBitmap) == B_OK) 269 fIconOnline = onlineBitmap; 270 else 271 delete onlineBitmap; 272 } 273 } 274 275 276 void 277 InterfaceListItem::_UpdateState() 278 { 279 fDeviceName = Name(); 280 fDeviceName.RemoveFirst("/dev/net/"); 281 282 fDisabled = (fInterface.Flags() & IFF_UP) == 0; 283 fHasLink = fInterface.HasLink(); 284 fConnecting = (fInterface.Flags() & IFF_CONFIGURING) != 0; 285 286 switch (fType) { 287 case B_NETWORK_INTERFACE_TYPE_WIFI: 288 fSubtitle = B_TRANSLATE("Wireless device"); 289 break; 290 case B_NETWORK_INTERFACE_TYPE_ETHERNET: 291 fSubtitle = B_TRANSLATE("Ethernet device"); 292 break; 293 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 294 fSubtitle = B_TRANSLATE("Dial-up connection"); 295 fDisabled = false; 296 break; 297 case B_NETWORK_INTERFACE_TYPE_VPN: 298 fSubtitle = B_TRANSLATE("VPN connection"); 299 fDisabled = false; 300 break; 301 default: 302 fSubtitle = ""; 303 } 304 } 305 306 307 BBitmap* 308 InterfaceListItem::_StateIcon() const 309 { 310 if (fDisabled) 311 return fIconOffline; 312 if (!fHasLink) 313 return fIconOffline; 314 // TODO! 315 // } else if ((fSettings->IPAddr(AF_INET).IsEmpty() 316 // && fSettings->IPAddr(AF_INET6).IsEmpty()) 317 // && (fSettings->AutoConfigure(AF_INET) 318 // || fSettings->AutoConfigure(AF_INET6))) { 319 // interfaceState = "connecting" B_UTF8_ELLIPSIS; 320 // stateIcon = fIconPending; 321 322 return fIconOnline; 323 } 324 325 326 const char* 327 InterfaceListItem::_StateText() const 328 { 329 if (fDisabled) 330 return B_TRANSLATE("disabled"); 331 332 if (!fInterface.HasLink()) { 333 switch (fType) { 334 case B_NETWORK_INTERFACE_TYPE_VPN: 335 case B_NETWORK_INTERFACE_TYPE_DIAL_UP: 336 return B_TRANSLATE("disconnected"); 337 default: 338 return B_TRANSLATE("no link"); 339 } 340 } 341 342 // TODO! 343 // } else if ((fSettings->IPAddr(AF_INET).IsEmpty() 344 // && fSettings->IPAddr(AF_INET6).IsEmpty()) 345 // && (fSettings->AutoConfigure(AF_INET) 346 // || fSettings->AutoConfigure(AF_INET6))) { 347 // interfaceState = "connecting" B_UTF8_ELLIPSIS; 348 // stateIcon = fIconPending; 349 350 return B_TRANSLATE("connected"); 351 } 352