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