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