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