Network: integrated former hardware view from add-on.

* The interfaces logic is within the main application, so is the
  new interface view.
* Disabling/renegotiating does not work yet.
* Reveals a bug in some interface code; when you click on an ethernet
  device first, there is no place for the wireless menu. When you then
  press on a wireless device, it crashes in BMenuField code.
  In the other direction, there is then an empty space.
* Fixed list item width reporting.
This commit is contained in:
Axel Dörfler 2015-02-05 09:02:26 +01:00
parent d5dd8637bb
commit f6c7cf44b5
8 changed files with 314 additions and 187 deletions

View File

@ -41,8 +41,9 @@ public:
const BNetworkProfile*
Profile() const;
virtual status_t Save() = 0;
virtual status_t Apply() = 0;
virtual status_t Revert() = 0;
virtual bool IsRevertable() = 0;
private:
const BNetworkProfile*

View File

@ -28,7 +28,7 @@
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "InterfacesListView"
#define B_TRANSLATION_CONTEXT "InterfaceListItem"
InterfaceListItem::InterfaceListItem(const char* name)
@ -74,57 +74,38 @@ InterfaceListItem::DrawItem(BView* owner, BRect /*bounds*/, bool complete)
list->FillRect(bounds);
}
BString interfaceState;
BBitmap* stateIcon(NULL);
// TODO: only update periodically
bool disabled = (fInterface.Flags() & IFF_UP) == 0;
_UpdateState();
if (disabled) {
interfaceState = "disabled";
stateIcon = fIconOffline;
} else if (!fInterface.HasLink()) {
interfaceState = "no link";
stateIcon = fIconOffline;
// TODO!
// } else if ((fSettings->IPAddr(AF_INET).IsEmpty()
// && fSettings->IPAddr(AF_INET6).IsEmpty())
// && (fSettings->AutoConfigure(AF_INET)
// || fSettings->AutoConfigure(AF_INET6))) {
// interfaceState = "connecting" B_UTF8_ELLIPSIS;
// stateIcon = fIconPending;
} else {
interfaceState = "connected";
stateIcon = fIconOnline;
}
BBitmap* stateIcon = _StateIcon();
const char* stateText = _StateText();
// Set the initial bounds of item contents
BPoint iconPt = bounds.LeftTop();
BPoint namePt = bounds.LeftTop();
BPoint line2Pt = bounds.LeftTop();
BPoint line3Pt = bounds.LeftTop();
BPoint statePt = bounds.RightTop();
BPoint iconPoint = bounds.LeftTop();
BPoint namePoint = bounds.LeftTop();
BPoint line2Point = bounds.LeftTop();
BPoint line3Point = bounds.LeftTop();
BPoint statePoint = bounds.RightTop();
iconPt += BPoint(4, 4);
statePt += BPoint(0, fFirstlineOffset);
namePt += BPoint(ICON_SIZE + 12, fFirstlineOffset);
line2Pt += BPoint(ICON_SIZE + 12, fSecondlineOffset);
line3Pt += BPoint(ICON_SIZE + 12, fThirdlineOffset);
iconPoint += BPoint(4, 4);
statePoint += BPoint(0, fFirstlineOffset);
namePoint += BPoint(ICON_SIZE + 12, fFirstlineOffset);
line2Point += BPoint(ICON_SIZE + 12, fSecondlineOffset);
line3Point += BPoint(ICON_SIZE + 12, fThirdlineOffset);
statePt -= BPoint(
be_plain_font->StringWidth(interfaceState.String()) + 4.0f, 0);
statePoint -= BPoint(be_plain_font->StringWidth(stateText) + 4.0f, 0);
if (disabled) {
if (fDisabled) {
list->SetDrawingMode(B_OP_ALPHA);
list->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
list->SetHighColor(0, 0, 0, 32);
} else
list->SetDrawingMode(B_OP_OVER);
list->DrawBitmapAsync(fIcon, iconPt);
list->DrawBitmapAsync(stateIcon, iconPt);
list->DrawBitmapAsync(fIcon, iconPoint);
list->DrawBitmapAsync(stateIcon, iconPoint);
if (disabled) {
if (fDisabled) {
rgb_color textColor;
if (IsSelected())
textColor = ui_color(B_LIST_SELECTED_ITEM_TEXT_COLOR);
@ -144,12 +125,9 @@ InterfaceListItem::DrawItem(BView* owner, BRect /*bounds*/, bool complete)
list->SetFont(be_bold_font);
BString name = Name();
name.RemoveFirst("/dev/net/");
list->DrawString(name, namePt);
list->DrawString(fDeviceName, namePoint);
list->SetFont(be_plain_font);
list->DrawString(interfaceState, statePt);
list->DrawString(stateText, statePoint);
// TODO!
/* if (!disabled) {
@ -160,7 +138,7 @@ InterfaceListItem::DrawItem(BView* owner, BRect /*bounds*/, bool complete)
else
ipv4Str << " " << BString(fSettings->IP(AF_INET));
list->DrawString(ipv4Str, line2Pt);
list->DrawString(ipv4Str, line2Point);
}
// Render IPv6 Address (if present)
@ -168,7 +146,7 @@ InterfaceListItem::DrawItem(BView* owner, BRect /*bounds*/, bool complete)
BString ipv6Str(B_TRANSLATE_COMMENT("IPv6:", "IPv6 address label"));
ipv6Str << " " << BString(fSettings->IP(AF_INET6));
list->DrawString(ipv6Str, line3Pt);
list->DrawString(ipv6Str, line3Point);
}
*/
owner->PopState();
@ -189,6 +167,11 @@ InterfaceListItem::Update(BView* owner, const BFont* font)
fSecondlineOffset = fFirstlineOffset + lineHeight;
fThirdlineOffset = fFirstlineOffset + (lineHeight * 2);
_UpdateState();
SetWidth(fIcon->Bounds().Width() + 24
+ be_bold_font->StringWidth(fDeviceName.String())
+ owner->StringWidth(_StateText()));
SetHeight(std::max(3 * lineHeight + 4, fIcon->Bounds().Height() + 8));
// either to the text height or icon height, whichever is taller
}
@ -279,3 +262,65 @@ InterfaceListItem::_PopulateBitmaps(const char* mediaType)
BIconUtils::GetVectorIcon(onlineHVIF, iconSize, fIconOnline);
}
}
void
InterfaceListItem::_UpdateState()
{
fDeviceName = Name();
fDeviceName.RemoveFirst("/dev/net/");
fDisabled = (fInterface.Flags() & IFF_UP) == 0;
fHasLink = fInterface.HasLink();
fConnecting = (fInterface.Flags() & IFF_CONFIGURING) != 0;
int32 count = fInterface.CountAddresses();
size_t addressIndex = 0;
for (int32 index = 0; index < count; index++) {
if (addressIndex >= sizeof(fAddress) / sizeof(fAddress[0]))
break;
BNetworkInterfaceAddress address;
if (fInterface.GetAddressAt(index, address) == B_OK)
fAddress[addressIndex++] = address.Address().ToString();
}
}
BBitmap*
InterfaceListItem::_StateIcon() const
{
if (fDisabled)
return fIconOffline;
if (!fHasLink)
return fIconOffline;
// TODO!
// } else if ((fSettings->IPAddr(AF_INET).IsEmpty()
// && fSettings->IPAddr(AF_INET6).IsEmpty())
// && (fSettings->AutoConfigure(AF_INET)
// || fSettings->AutoConfigure(AF_INET6))) {
// interfaceState = "connecting" B_UTF8_ELLIPSIS;
// stateIcon = fIconPending;
return fIconOnline;
}
const char*
InterfaceListItem::_StateText() const
{
if (fDisabled)
return B_TRANSLATE("disabled");
if (!fInterface.HasLink())
return B_TRANSLATE("no link");
// TODO!
// } else if ((fSettings->IPAddr(AF_INET).IsEmpty()
// && fSettings->IPAddr(AF_INET6).IsEmpty())
// && (fSettings->AutoConfigure(AF_INET)
// || fSettings->AutoConfigure(AF_INET6))) {
// interfaceState = "connecting" B_UTF8_ELLIPSIS;
// stateIcon = fIconPending;
return B_TRANSLATE("connected");
}

View File

@ -33,7 +33,11 @@ public:
private:
void _Init();
void _PopulateBitmaps(const char* mediaType);
void _UpdateState();
BBitmap* _StateIcon() const;
const char* _StateText() const;
private:
BBitmap* fIcon;
BBitmap* fIconOffline;
BBitmap* fIconPending;
@ -45,6 +49,12 @@ private:
float fFirstlineOffset;
float fSecondlineOffset;
float fThirdlineOffset;
BString fDeviceName;
bool fDisabled;
bool fHasLink;
bool fConnecting;
BString fAddress[2];
};

View File

@ -1,80 +1,81 @@
/*
* Copyright 2004-2013 Haiku, Inc. All rights reserved.
* Copyright 2004-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, <axeld@pinc-software.de>
* Alexander von Gluck, kallisti5@unixzen.com
* John Scipione, jscipione@gmail.com
*/
#include "InterfaceHardwareView.h"
#include "InterfaceView.h"
#include "NetworkSettings.h"
#include "WirelessNetworkMenuItem.h"
#include <set>
#include <net/if_media.h>
#include <Button.h>
#include <Catalog.h>
#include <ControlLook.h>
#include <LayoutBuilder.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <NetworkAddress.h>
#include <Screen.h>
#include <Size.h>
#include <NetworkDevice.h>
#include <StringForSize.h>
#include <StringView.h>
#include <TextControl.h>
#include <set>
#include <stdio.h>
#include "MediaTypes.h"
#include "WirelessNetworkMenuItem.h"
static const uint32 kMsgInterfaceToggle = 'onof';
static const uint32 kMsgInterfaceRenegotiate = 'redo';
static const uint32 kMsgJoinNetwork = 'join';
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "IntefaceHardwareView"
#define B_TRANSLATION_CONTEXT "IntefaceView"
// #pragma mark - InterfaceHardwareView
// #pragma mark - InterfaceView
InterfaceHardwareView::InterfaceHardwareView(NetworkSettings* settings)
InterfaceView::InterfaceView()
:
BGroupView(B_VERTICAL),
fSettings(settings)
BGroupView(B_VERTICAL)
{
SetLayout(new BGroupLayout(B_VERTICAL));
SetFlags(Flags() | B_PULSE_NEEDED);
// TODO : Small graph of throughput?
// TODO: Small graph of throughput?
float minimumWidth = be_control_look->DefaultItemSpacing() * 16;
BStringView* status = new BStringView("status label", B_TRANSLATE("Status:"));
status->SetAlignment(B_ALIGN_RIGHT);
BStringView* statusLabel = new BStringView("status label",
B_TRANSLATE("Status:"));
statusLabel->SetAlignment(B_ALIGN_RIGHT);
fStatusField = new BStringView("status field", "");
fStatusField->SetExplicitMinSize(BSize(minimumWidth, B_SIZE_UNSET));
BStringView* macAddress = new BStringView("mac address label",
BStringView* macAddressLabel = new BStringView("mac address label",
B_TRANSLATE("MAC address:"));
macAddress->SetAlignment(B_ALIGN_RIGHT);
macAddressLabel->SetAlignment(B_ALIGN_RIGHT);
fMacAddressField = new BStringView("mac address field", "");
fMacAddressField->SetExplicitMinSize(BSize(minimumWidth, B_SIZE_UNSET));
BStringView* linkSpeed = new BStringView("link speed label",
BStringView* linkSpeedLabel = new BStringView("link speed label",
B_TRANSLATE("Link speed:"));
linkSpeed->SetAlignment(B_ALIGN_RIGHT);
linkSpeedLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkSpeedField = new BStringView("link speed field", "");
fLinkSpeedField->SetExplicitMinSize(BSize(minimumWidth, B_SIZE_UNSET));
// TODO: These metrics may be better in a BScrollView?
BStringView* linkTx = new BStringView("tx label",
BStringView* linkTxLabel = new BStringView("tx label",
B_TRANSLATE("Sent:"));
linkTx->SetAlignment(B_ALIGN_RIGHT);
linkTxLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkTxField = new BStringView("tx field", "");
fLinkTxField ->SetExplicitMinSize(BSize(minimumWidth, B_SIZE_UNSET));
BStringView* linkRx = new BStringView("rx label",
BStringView* linkRxLabel = new BStringView("rx label",
B_TRANSLATE("Received:"));
linkRx->SetAlignment(B_ALIGN_RIGHT);
linkRxLabel->SetAlignment(B_ALIGN_RIGHT);
fLinkRxField = new BStringView("rx field", "");
fLinkRxField ->SetExplicitMinSize(BSize(minimumWidth, B_SIZE_UNSET));
@ -93,43 +94,44 @@ InterfaceHardwareView::InterfaceHardwareView(NetworkSettings* settings)
BLayoutBuilder::Group<>(this)
.AddGrid()
.Add(status, 0, 0)
.Add(statusLabel, 0, 0)
.Add(fStatusField, 1, 0)
.Add(fNetworkMenuField->CreateLabelLayoutItem(), 0, 1)
.Add(fNetworkMenuField->CreateMenuBarLayoutItem(), 1, 1)
.Add(macAddress, 0, 2)
.Add(macAddressLabel, 0, 2)
.Add(fMacAddressField, 1, 2)
.Add(linkSpeed, 0, 3)
.Add(linkSpeedLabel, 0, 3)
.Add(fLinkSpeedField, 1, 3)
.Add(linkTx, 0, 4)
.Add(linkTxLabel, 0, 4)
.Add(fLinkTxField, 1, 4)
.Add(linkRx, 0, 5)
.Add(linkRxLabel, 0, 5)
.Add(fLinkRxField, 1, 5)
.End()
.AddGlue()
.AddGroup(B_HORIZONTAL)
.Add(fOnOff)
.AddGlue()
.Add(fOnOff)
.Add(fRenegotiate)
.End()
.SetInsets(B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING,
B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING);
.End();
}
InterfaceHardwareView::~InterfaceHardwareView()
InterfaceView::~InterfaceView()
{
}
// #pragma mark - InterfaceHardwareView virtual methods
void
InterfaceHardwareView::AttachedToWindow()
InterfaceView::SetTo(const char* name)
{
Update();
fInterface.SetTo(name);
}
void
InterfaceView::AttachedToWindow()
{
_Update();
// Populate the fields
fOnOff->SetTarget(this);
@ -138,25 +140,35 @@ InterfaceHardwareView::AttachedToWindow()
void
InterfaceHardwareView::MessageReceived(BMessage* message)
InterfaceView::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgNetwork:
case kMsgJoinNetwork:
{
fSettings->SetWirelessNetwork(message->FindString("name"));
const char* name;
BNetworkAddress address;
if (message->FindString("name", &name) == B_OK
&& message->FindFlat("address", &address) == B_OK) {
BNetworkDevice device(fInterface.Name());
status_t status = device.JoinNetwork(address);
if (status != B_OK) {
// This does not really matter, as it's stored this way,
// anyway.
}
// TODO: store value
}
break;
}
case kMsgInterfaceToggle:
{
fSettings->SetDisabled(!fSettings->IsDisabled());
Update();
Window()->FindView("interfaces")->Invalidate();
// TODO: disable/enable interface
_Update();
break;
}
case kMsgInterfaceRenegotiate:
{
fSettings->RenegotiateAddresses();
// TODO: renegotiate addresses
break;
}
@ -167,31 +179,25 @@ InterfaceHardwareView::MessageReceived(BMessage* message)
void
InterfaceHardwareView::Pulse()
InterfaceView::Pulse()
{
// TODO maybe not everything needs to be updated here.
Update();
}
// #pragma mark - InterfaceHardwareView public methods
status_t
InterfaceHardwareView::Revert()
{
Update();
return B_OK;
// Update the wireless network menu every 5 seconds
_Update((fPulseCount++ % 5) == 0);
}
status_t
InterfaceHardwareView::Update()
InterfaceView::_Update(bool updateWirelessNetworks)
{
BNetworkDevice device(fInterface.Name());
bool isWireless = device.IsWireless();
bool disabled = (fInterface.Flags() & IFF_UP) == 0;
// Populate fields with current settings
if (fSettings->HasLink()) {
if (fSettings->IsWireless()) {
BString network = fSettings->WirelessNetwork();
if (fInterface.HasLink()) {
if (isWireless) {
// TODO!
BString network = "---";
network.Prepend(" (");
network.Prepend(B_TRANSLATE("connected"));
network.Append(")");
@ -202,34 +208,39 @@ InterfaceHardwareView::Update()
} else
fStatusField->SetText(B_TRANSLATE("disconnected"));
fMacAddressField->SetText(fSettings->HardwareAddress());
BNetworkAddress hardwareAddress;
if (device.GetHardwareAddress(hardwareAddress) == B_OK)
fMacAddressField->SetText(hardwareAddress.ToString());
else
fMacAddressField->SetText("-");
// TODO : Find how to get link speed
fLinkSpeedField->SetText("100 Mb/s");
int media = fInterface.Media();
if ((media & IFM_ACTIVE) != 0)
fLinkSpeedField->SetText(media_type_to_string(media));
else
fLinkSpeedField->SetText("-");
// Update Link stats
ifreq_stats stats;
char buffer[100];
fSettings->Stats(&stats);
if (fInterface.GetStats(stats) == B_OK) {
char buffer[100];
string_for_size(stats.send.bytes, buffer, sizeof(buffer));
fLinkTxField->SetText(buffer);
string_for_size(stats.send.bytes, buffer, sizeof(buffer));
fLinkTxField->SetText(buffer);
string_for_size(stats.receive.bytes, buffer, sizeof(buffer));
fLinkRxField->SetText(buffer);
// TODO move the wireless info to a separate tab. We should have a
// BListView of available networks, rather than a menu, to make them more
// readable and easier to browse and select.
if (fNetworkMenuField->IsHidden(fNetworkMenuField)
&& fSettings->IsWireless()) {
fNetworkMenuField->Show();
} else if (!fNetworkMenuField->IsHidden(fNetworkMenuField)
&& !fSettings->IsWireless()) {
fNetworkMenuField->Hide();
string_for_size(stats.receive.bytes, buffer, sizeof(buffer));
fLinkRxField->SetText(buffer);
}
if (fSettings->IsWireless()) {
// TODO: move the wireless info to a separate tab. We should have a
// BListView of available networks, rather than a menu, to make them more
// readable and easier to browse and select.
if (fNetworkMenuField->IsHidden(fNetworkMenuField) && isWireless)
fNetworkMenuField->Show();
else if (!fNetworkMenuField->IsHidden(fNetworkMenuField) && !isWireless)
fNetworkMenuField->Hide();
if (isWireless && updateWirelessNetworks) {
// Rebuild network menu
BMenu* menu = fNetworkMenuField->Menu();
menu->RemoveItems(0, menu->CountItems(), true);
@ -237,17 +248,18 @@ InterfaceHardwareView::Update()
std::set<BNetworkAddress> associated;
BNetworkAddress address;
uint32 cookie = 0;
while (fSettings->GetNextAssociatedNetwork(cookie, address) == B_OK)
while (device.GetNextAssociatedNetwork(cookie, address) == B_OK)
associated.insert(address);
wireless_network network;
int32 count = 0;
cookie = 0;
while (fSettings->GetNextNetwork(cookie, network) == B_OK) {
BMessage* message = new BMessage(kMsgNetwork);
while (device.GetNextNetwork(cookie, network) == B_OK) {
BMessage* message = new BMessage(kMsgJoinNetwork);
message->AddString("device", fSettings->Name());
message->AddString("device", fInterface.Name());
message->AddString("name", network.name);
message->AddFlat("address", &network.address);
BMenuItem* item = new WirelessNetworkMenuItem(network.name,
network.signal_strength,
@ -274,15 +286,8 @@ InterfaceHardwareView::Update()
menu->SetTargetForItems(this);
}
fRenegotiate->SetEnabled(!fSettings->IsDisabled());
fOnOff->SetLabel(fSettings->IsDisabled() ? "Enable" : "Disable");
fRenegotiate->SetEnabled(!disabled);
fOnOff->SetLabel(disabled ? "Enable" : "Disable");
return B_OK;
}
status_t
InterfaceHardwareView::Save()
{
return B_OK;
}

View File

@ -1,48 +1,44 @@
/*
* Copyright 2004-2013 Haiku, Inc. All rights reserved.
* Copyright 2004-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, <axeld@pinc-software.de>
* Alexander von Gluck, kallisti5@unixzen.com
* John Scipione, jscipione@gmail.com
*/
#ifndef INTERFACE_HARDWARE_VIEW_H
#define INTERFACE_HARDWARE_VIEW_H
#ifndef INTERFACE_VIEW_H
#define INTERFACE_VIEW_H
#include "NetworkSettings.h"
#include <GroupView.h>
static const uint32 kMsgInterfaceToggle = 'onof';
static const uint32 kMsgInterfaceRenegotiate = 'redo';
#include <NetworkInterface.h>
class BButton;
class BMenuField;
class BMessage;
class BRect;
class BStringView;
class InterfaceHardwareView : public BGroupView {
class InterfaceView : public BGroupView {
public:
InterfaceHardwareView(
NetworkSettings* settings);
virtual ~InterfaceHardwareView();
InterfaceView();
virtual ~InterfaceView();
void SetTo(const char* name);
virtual void MessageReceived(BMessage* message);
virtual void AttachedToWindow();
void Pulse();
status_t Revert();
status_t Save();
virtual void Pulse();
private:
status_t Update();
status_t _Update(bool updateWirelessNetworks = true);
void _EnableFields(bool enabled);
NetworkSettings* fSettings;
private:
BNetworkInterface fInterface;
int fPulseCount;
BStringView* fStatusField;
BStringView* fMacAddressField;

View File

@ -3,7 +3,8 @@ SubDir HAIKU_TOP src preferences network ;
UsePublicHeaders [ FDirName add-ons network_settings ] ;
UsePrivateHeaders net shared ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps networkstatus ] ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps networkstatus ]
[ FDirName $(HAIKU_TOP) src bin network ifconfig ] ;
Preference Network :
Network.cpp
@ -11,12 +12,16 @@ Preference Network :
NetworkProfile.cpp
NetworkSettingsAddOn.cpp
InterfaceListItem.cpp
InterfaceView.cpp
# from NetworkStatus
RadioView.cpp
WirelessNetworkMenuItem.cpp
: be root bnetapi [ TargetLibstdc++ ] localestub
# from ifconfig
MediaTypes.cpp
: be bnetapi libshared.a [ TargetLibstdc++ ] localestub
: Network.rdef InterfaceIcons.rdef
;

View File

@ -40,6 +40,7 @@
#endif
#include "InterfaceListItem.h"
#include "InterfaceView.h"
const char* kNetworkStatusSignature = "application/x-vnd.Haiku-NetworkStatus";
@ -59,7 +60,7 @@ static const uint32 kMsgItemSelected = 'ItSl';
NetworkWindow::NetworkWindow()
:
BWindow(BRect(100, 100, 300, 300), B_TRANSLATE("Network"), B_TITLED_WINDOW,
BWindow(BRect(100, 100, 400, 400), B_TRANSLATE("Network"), B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS)
{
// Profiles section
@ -98,6 +99,12 @@ NetworkWindow::NetworkWindow()
BScrollView* scrollView = new BScrollView("ScrollView", fListView,
0, false, true);
fAddOnShellView = new BView("add-on shell", 0,
new BGroupLayout(B_VERTICAL));
fAddOnShellView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fInterfaceView = new InterfaceView();
// Build the layout
BLayoutBuilder::Group<>(this, B_VERTICAL)
.SetInsets(B_USE_DEFAULT_SPACING)
@ -110,7 +117,7 @@ NetworkWindow::NetworkWindow()
#endif
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
.Add(scrollView)
.AddGlue()
.Add(fAddOnShellView)
.End()
.Add(showReplicantCheckBox)
.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
@ -122,7 +129,11 @@ NetworkWindow::NetworkWindow()
_ScanInterfaces();
_ScanAddOns();
fAddOnView = NULL;
// Set preferred size of the list view from its contents
float width;
float height;
fListView->GetPreferredSize(&width, &height);
fListView->SetExplicitMinSize(BSize(width, std::min(height, 400.f)));
CenterOnScreen();
}
@ -162,19 +173,29 @@ NetworkWindow::MessageReceived(BMessage* message)
}
case kMsgItemSelected:
{
BListItem* listItem = fListView->FullListItemAt(
fListView->FullListCurrentSelection());
if (listItem == NULL)
break;
_SelectItem(listItem);
break;
}
case kMsgRevert:
{
for (int index = 0; index < fItems.CountItems(); index++)
fItems.ItemAt(index)->Revert();
SettingsMap::const_iterator iterator = fSettingsMap.begin();
for (; iterator != fSettingsMap.end(); iterator++)
iterator->second->Revert();
break;
}
case kMsgApply:
{
for (int index = 0; index < fItems.CountItems(); index++)
fItems.ItemAt(index)->Save();
SettingsMap::const_iterator iterator = fSettingsMap.begin();
for (; iterator != fSettingsMap.end(); iterator++)
iterator->second->Apply();
break;
}
@ -328,7 +349,7 @@ NetworkWindow::_ScanAddOns()
if (item == NULL)
break;
fItems.AddItem(item);
fSettingsMap[item->ListItem()] = item;
// TODO: sort
fListView->AddUnder(interfaceItem, item->ListItem());
}
@ -341,17 +362,29 @@ NetworkWindow::_ScanAddOns()
if (item == NULL)
break;
fItems.AddItem(item);
fSettingsMap[item->ListItem()] = item;
// TODO: sort
fListView->AddUnder(_ItemFor(item->Type()), item->ListItem());
fListView->AddUnder(_ListItemFor(item->Type()),
item->ListItem());
}
}
}
}
BNetworkSettingsItem*
NetworkWindow::_SettingsItemFor(BListItem* item)
{
SettingsMap::const_iterator found = fSettingsMap.find(item);
if (found != fSettingsMap.end())
return found->second;
return NULL;
}
BListItem*
NetworkWindow::_ItemFor(BNetworkSettingsType type)
NetworkWindow::_ListItemFor(BNetworkSettingsType type)
{
switch (type) {
case B_NETWORK_SETTINGS_TYPE_SERVICE:
@ -378,6 +411,34 @@ NetworkWindow::_ItemFor(BNetworkSettingsType type)
}
void
NetworkWindow::_SelectItem(BListItem* listItem)
{
if (fAddOnShellView->CountChildren() > 0)
fAddOnShellView->ChildAt(0)->RemoveSelf();
BView* nextView = NULL;
BNetworkSettingsItem* item = _SettingsItemFor(listItem);
if (item != NULL) {
nextView = item->View();
} else {
InterfaceListItem* item = dynamic_cast<InterfaceListItem*>(
listItem);
if (item != NULL) {
fInterfaceView->SetTo(item->Name());
nextView = fInterfaceView;
}
}
if (nextView != NULL)
fAddOnShellView->AddChild(nextView);
fAddOnShellView->Invalidate();
InvalidateLayout();
}
void
NetworkWindow::_ShowReplicant(bool show)
{

View File

@ -20,10 +20,9 @@
using namespace BNetworkKit;
class BTabView;
class BButton;
class BMenu;
class InterfaceView;
class NetworkWindow : public BWindow {
@ -40,7 +39,10 @@ private:
void _BuildProfilesMenu(BMenu* menu, int32 what);
void _ScanInterfaces();
void _ScanAddOns();
BListItem* _ItemFor(BNetworkSettingsType type);
BNetworkSettingsItem*
_SettingsItemFor(BListItem* item);
BListItem* _ListItemFor(BNetworkSettingsType type);
void _SelectItem(BListItem* listItem);
bool _IsReplicantInstalled();
void _ShowReplicant(bool show);
@ -49,6 +51,7 @@ private:
typedef BObjectList<BNetworkSettingsAddOn> AddOnList;
typedef BObjectList<BNetworkSettingsItem> ItemList;
typedef std::map<BString, BListItem*> ItemMap;
typedef std::map<BListItem*, BNetworkSettingsItem*> SettingsMap;
BButton* fRevertButton;
BButton* fApplyButton;
@ -61,9 +64,10 @@ private:
BListItem* fDialUpItem;
BListItem* fOtherItem;
ItemList fItems;
SettingsMap fSettingsMap;
BView* fAddOnView;
InterfaceView* fInterfaceView;
BView* fAddOnShellView;
};