xref: /haiku/src/preferences/network/InterfaceListItem.cpp (revision ca8ed5ea660fb6275799a3b7f138b201c41a667b)
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