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