Some more work on the ActivityMonitor:
* Added legend. * Added network receiving/sending DataSource. * Now uses the new layout engine. * Added support for per CPU DataSources, and added a per CPU CPU usage DataSource. * The DataSources can now be turned on and off via popup menu. * You can now add more than one view to the window. * The DataSources of the ActivityViews are now remembered. * Now uses an offscreen bitmap to reduce flicker (it should now no longer flicker with accelerated graphics). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24955 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -32,6 +32,7 @@ const bigtime_t kInitialRefreshInterval = 500000LL;
|
|||||||
|
|
||||||
const uint32 kMsgRefresh = 'refr';
|
const uint32 kMsgRefresh = 'refr';
|
||||||
const uint32 kMsgToggleDataSource = 'tgds';
|
const uint32 kMsgToggleDataSource = 'tgds';
|
||||||
|
const uint32 kMsgToggleLegend = 'tglg';
|
||||||
|
|
||||||
extern const char* kSignature;
|
extern const char* kSignature;
|
||||||
|
|
||||||
@@ -123,12 +124,25 @@ DataHistory::SetRefreshInterval(bigtime_t interval)
|
|||||||
|
|
||||||
|
|
||||||
ActivityView::ActivityView(BRect frame, const char* name,
|
ActivityView::ActivityView(BRect frame, const char* name,
|
||||||
const BMessage& settings, uint32 resizingMode)
|
const BMessage* settings, uint32 resizingMode)
|
||||||
: BView(frame, name, resizingMode,
|
: BView(frame, name, resizingMode,
|
||||||
B_WILL_DRAW | B_SUBPIXEL_PRECISE | B_FULL_UPDATE_ON_RESIZE
|
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
|
||||||
| B_FRAME_EVENTS)
|
|
||||||
{
|
{
|
||||||
_Init(&settings);
|
_Init(settings);
|
||||||
|
|
||||||
|
BRect rect(Bounds());
|
||||||
|
rect.top = rect.bottom - 7;
|
||||||
|
rect.left = rect.right - 7;
|
||||||
|
BDragger* dragger = new BDragger(rect, this,
|
||||||
|
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
||||||
|
AddChild(dragger);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ActivityView::ActivityView(const char* name, const BMessage* settings)
|
||||||
|
: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS)
|
||||||
|
{
|
||||||
|
_Init(settings);
|
||||||
|
|
||||||
BRect rect(Bounds());
|
BRect rect(Bounds());
|
||||||
rect.top = rect.bottom - 7;
|
rect.top = rect.bottom - 7;
|
||||||
@@ -148,6 +162,7 @@ ActivityView::ActivityView(BMessage* archive)
|
|||||||
|
|
||||||
ActivityView::~ActivityView()
|
ActivityView::~ActivityView()
|
||||||
{
|
{
|
||||||
|
delete fOffscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -155,17 +170,29 @@ void
|
|||||||
ActivityView::_Init(const BMessage* settings)
|
ActivityView::_Init(const BMessage* settings)
|
||||||
{
|
{
|
||||||
fBackgroundColor = (rgb_color){255, 255, 240};
|
fBackgroundColor = (rgb_color){255, 255, 240};
|
||||||
SetLowColor(fBackgroundColor);
|
fOffscreen = NULL;
|
||||||
|
SetViewColor(B_TRANSPARENT_COLOR);
|
||||||
|
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
|
|
||||||
fRefreshInterval = kInitialRefreshInterval;
|
fRefreshInterval = kInitialRefreshInterval;
|
||||||
fDrawInterval = kInitialRefreshInterval * 2;
|
fDrawInterval = kInitialRefreshInterval * 2;
|
||||||
fLastRefresh = 0;
|
fLastRefresh = 0;
|
||||||
fDrawResolution = 1;
|
fDrawResolution = 1;
|
||||||
|
|
||||||
|
if (settings == NULL
|
||||||
|
|| settings->FindBool("show legend", &fShowLegend) != B_OK)
|
||||||
|
fShowLegend = true;
|
||||||
|
|
||||||
|
if (settings == NULL) {
|
||||||
AddDataSource(new UsedMemoryDataSource());
|
AddDataSource(new UsedMemoryDataSource());
|
||||||
AddDataSource(new CachedMemoryDataSource());
|
AddDataSource(new CachedMemoryDataSource());
|
||||||
AddDataSource(new ThreadsDataSource());
|
return;
|
||||||
AddDataSource(new CpuUsageDataSource());
|
}
|
||||||
|
|
||||||
|
const char* name;
|
||||||
|
for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++) {
|
||||||
|
AddDataSource(DataSource::FindSource(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -203,16 +230,30 @@ ActivityView::Instantiate(BMessage* archive)
|
|||||||
status_t
|
status_t
|
||||||
ActivityView::SaveState(BMessage& state) const
|
ActivityView::SaveState(BMessage& state) const
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
status_t status = state.AddBool("show legend", fShowLegend);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fSources.CountItems(); i++) {
|
||||||
|
DataSource* source = fSources.ItemAt(i);
|
||||||
|
|
||||||
|
if (!source->PerCPU() || source->CPU() == 0)
|
||||||
|
status = state.AddString("source", source->Name());
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// TODO: save and restore color as well
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DataSource*
|
DataSource*
|
||||||
ActivityView::FindDataSource(const char* name)
|
ActivityView::FindDataSource(const DataSource* search)
|
||||||
{
|
{
|
||||||
for (int32 i = fSources.CountItems(); i-- > 0;) {
|
for (int32 i = fSources.CountItems(); i-- > 0;) {
|
||||||
DataSource* source = fSources.ItemAt(i);
|
DataSource* source = fSources.ItemAt(i);
|
||||||
if (!strcmp(source->Label(), name))
|
if (!strcmp(source->Name(), search->Name()))
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,30 +262,64 @@ ActivityView::FindDataSource(const char* name)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ActivityView::AddDataSource(DataSource* source)
|
ActivityView::AddDataSource(const DataSource* source)
|
||||||
{
|
{
|
||||||
|
if (source == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
int32 insert = DataSource::IndexOf(source);
|
||||||
|
for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) {
|
||||||
|
DataSource* before = fSources.ItemAt(i);
|
||||||
|
if (DataSource::IndexOf(before) > insert) {
|
||||||
|
insert = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (insert > fSources.CountItems())
|
||||||
|
insert = fSources.CountItems();
|
||||||
|
|
||||||
|
uint32 count = 1;
|
||||||
|
if (source->PerCPU()) {
|
||||||
|
SystemInfo info;
|
||||||
|
count = info.CPUCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < count; i++) {
|
||||||
DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
|
DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
|
||||||
fRefreshInterval);
|
fRefreshInterval);
|
||||||
if (values == NULL)
|
if (values == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
if (!fValues.AddItem(values)) {
|
|
||||||
|
if (!fValues.AddItem(values, insert + i)) {
|
||||||
delete values;
|
delete values;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fSources.AddItem(source)) {
|
DataSource* copy;
|
||||||
|
if (source->PerCPU())
|
||||||
|
copy = source->CopyForCPU(i);
|
||||||
|
else
|
||||||
|
copy = source->Copy();
|
||||||
|
|
||||||
|
if (!fSources.AddItem(copy, insert + i)) {
|
||||||
fValues.RemoveItem(values);
|
fValues.RemoveItem(values);
|
||||||
delete values;
|
delete values;
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ActivityView::RemoveDataSource(DataSource* source)
|
ActivityView::RemoveDataSource(const DataSource* remove)
|
||||||
{
|
{
|
||||||
|
while (true) {
|
||||||
|
DataSource* source = FindDataSource(remove);
|
||||||
|
if (source == NULL)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
int32 index = fSources.IndexOf(source);
|
int32 index = fSources.IndexOf(source);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return B_ENTRY_NOT_FOUND;
|
return B_ENTRY_NOT_FOUND;
|
||||||
@@ -253,6 +328,7 @@ ActivityView::RemoveDataSource(DataSource* source)
|
|||||||
delete source;
|
delete source;
|
||||||
DataHistory* values = fValues.RemoveItemAt(index);
|
DataHistory* values = fValues.RemoveItemAt(index);
|
||||||
delete values;
|
delete values;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -271,6 +347,8 @@ ActivityView::AttachedToWindow()
|
|||||||
{
|
{
|
||||||
BMessage refresh(kMsgRefresh);
|
BMessage refresh(kMsgRefresh);
|
||||||
fRunner = new BMessageRunner(this, &refresh, fRefreshInterval);
|
fRunner = new BMessageRunner(this, &refresh, fRefreshInterval);
|
||||||
|
|
||||||
|
FrameResized(Bounds().Width(), Bounds().Height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -281,9 +359,47 @@ ActivityView::DetachedFromWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
ActivityView::MinSize()
|
||||||
|
{
|
||||||
|
BSize size(32, 32);
|
||||||
|
if (fShowLegend)
|
||||||
|
size.height = _LegendFrame().Height();
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ActivityView::FrameResized(float /*width*/, float /*height*/)
|
ActivityView::FrameResized(float /*width*/, float /*height*/)
|
||||||
{
|
{
|
||||||
|
_UpdateOffscreenBitmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::_UpdateOffscreenBitmap()
|
||||||
|
{
|
||||||
|
BRect frame = _HistoryFrame();
|
||||||
|
if (fOffscreen != NULL && frame == fOffscreen->Bounds())
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete fOffscreen;
|
||||||
|
|
||||||
|
// create offscreen bitmap
|
||||||
|
|
||||||
|
fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS,
|
||||||
|
B_RGB32);
|
||||||
|
if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) {
|
||||||
|
delete fOffscreen;
|
||||||
|
fOffscreen = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE);
|
||||||
|
view->SetViewColor(fBackgroundColor);
|
||||||
|
view->SetLowColor(view->ViewColor());
|
||||||
|
fOffscreen->AddChild(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -301,21 +417,30 @@ ActivityView::MouseDown(BPoint where)
|
|||||||
|
|
||||||
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
|
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
|
||||||
menu->SetFont(be_plain_font);
|
menu->SetFont(be_plain_font);
|
||||||
|
|
||||||
|
SystemInfo info;
|
||||||
BMenuItem* item;
|
BMenuItem* item;
|
||||||
|
|
||||||
for (int32 i = 0; i < DataSource::CountSources(); i++) {
|
for (int32 i = 0; i < DataSource::CountSources(); i++) {
|
||||||
const DataSource* source = DataSource::SourceAt(i);
|
const DataSource* source = DataSource::SourceAt(i);
|
||||||
|
|
||||||
|
if (source->MultiCPUOnly() && info.CPUCount() == 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
BMessage* message = new BMessage(kMsgToggleDataSource);
|
BMessage* message = new BMessage(kMsgToggleDataSource);
|
||||||
message->AddInt32("index", i);
|
message->AddInt32("index", i);
|
||||||
|
|
||||||
item = new BMenuItem(source->Label(), message);
|
item = new BMenuItem(source->Name(), message);
|
||||||
if (FindDataSource(source->Label()))
|
if (FindDataSource(source))
|
||||||
item->SetMarked(true);
|
item->SetMarked(true);
|
||||||
|
|
||||||
menu->AddItem(item);
|
menu->AddItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
menu->AddItem(new BMenuItem(fShowLegend ? "Hide Legend" : "Show Legend",
|
||||||
|
new BMessage(kMsgToggleLegend)));
|
||||||
|
|
||||||
menu->SetTargetForItems(this);
|
menu->SetTargetForItems(this);
|
||||||
|
|
||||||
ConvertToScreen(&where);
|
ConvertToScreen(&where);
|
||||||
@@ -353,9 +478,9 @@ ActivityView::MessageReceived(BMessage* message)
|
|||||||
if (baseSource == NULL)
|
if (baseSource == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
DataSource* source = FindDataSource(baseSource->Label());
|
DataSource* source = FindDataSource(baseSource);
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
AddDataSource(baseSource->Copy());
|
AddDataSource(baseSource);
|
||||||
else
|
else
|
||||||
RemoveDataSource(source);
|
RemoveDataSource(source);
|
||||||
|
|
||||||
@@ -363,6 +488,11 @@ ActivityView::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case kMsgToggleLegend:
|
||||||
|
fShowLegend = !fShowLegend;
|
||||||
|
Invalidate();
|
||||||
|
break;
|
||||||
|
|
||||||
case B_MOUSE_WHEEL_CHANGED:
|
case B_MOUSE_WHEEL_CHANGED:
|
||||||
{
|
{
|
||||||
float deltaY = 0.0f;
|
float deltaY = 0.0f;
|
||||||
@@ -391,6 +521,56 @@ ActivityView::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect
|
||||||
|
ActivityView::_HistoryFrame() const
|
||||||
|
{
|
||||||
|
if (!fShowLegend)
|
||||||
|
return Bounds();
|
||||||
|
|
||||||
|
BRect frame = Bounds();
|
||||||
|
BRect legendFrame = _LegendFrame();
|
||||||
|
|
||||||
|
frame.bottom = legendFrame.top - 1;
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect
|
||||||
|
ActivityView::_LegendFrame() const
|
||||||
|
{
|
||||||
|
BRect frame = Bounds();
|
||||||
|
font_height fontHeight;
|
||||||
|
GetFontHeight(&fontHeight);
|
||||||
|
|
||||||
|
int32 rows = (fSources.CountItems() + 1) / 2;
|
||||||
|
frame.top = frame.bottom - rows * (4 + ceilf(fontHeight.ascent)
|
||||||
|
+ ceilf(fontHeight.descent) + ceilf(fontHeight.leading));
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BRect
|
||||||
|
ActivityView::_LegendFrameAt(BRect frame, int32 index) const
|
||||||
|
{
|
||||||
|
int32 column = index & 1;
|
||||||
|
int32 row = index / 2;
|
||||||
|
if (column == 0)
|
||||||
|
frame.right = frame.left + floorf(frame.Width() / 2) - 5;
|
||||||
|
else
|
||||||
|
frame.left = frame.right - floorf(frame.Width() / 2) + 5;
|
||||||
|
|
||||||
|
int32 rows = (fSources.CountItems() + 1) / 2;
|
||||||
|
float height = floorf((frame.Height() - 5) / rows);
|
||||||
|
|
||||||
|
frame.top = frame.top + 5 + row * height;
|
||||||
|
frame.bottom = frame.top + height - 1;
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
float
|
float
|
||||||
ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
|
ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
|
||||||
int64 value)
|
int64 value)
|
||||||
@@ -408,14 +588,25 @@ ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
|
|||||||
if (value < min)
|
if (value < min)
|
||||||
value = min;
|
value = min;
|
||||||
|
|
||||||
float height = Bounds().Height();
|
float height = _HistoryFrame().Height();
|
||||||
return height - (value - min) * height / (max - min);
|
return height - (value - min) * height / (max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ActivityView::Draw(BRect /*updateRect*/)
|
ActivityView::_DrawHistory()
|
||||||
{
|
{
|
||||||
|
_UpdateOffscreenBitmap();
|
||||||
|
|
||||||
|
BView* view = this;
|
||||||
|
if (fOffscreen != NULL) {
|
||||||
|
fOffscreen->Lock();
|
||||||
|
view = fOffscreen->ChildAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BRect frame = _HistoryFrame();
|
||||||
|
view->FillRect(frame, B_SOLID_LOW);
|
||||||
|
|
||||||
uint32 step = 2;
|
uint32 step = 2;
|
||||||
uint32 resolution = fDrawResolution;
|
uint32 resolution = fDrawResolution;
|
||||||
if (fDrawResolution > 1) {
|
if (fDrawResolution > 1) {
|
||||||
@@ -423,12 +614,19 @@ ActivityView::Draw(BRect /*updateRect*/)
|
|||||||
resolution--;
|
resolution--;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 width = Bounds().IntegerWidth() - 10;
|
uint32 width = frame.IntegerWidth() - 10;
|
||||||
uint32 steps = width / step;
|
uint32 steps = width / step;
|
||||||
bigtime_t timeStep = fRefreshInterval * resolution;
|
bigtime_t timeStep = fRefreshInterval * resolution;
|
||||||
bigtime_t now = system_time();
|
bigtime_t now = system_time();
|
||||||
|
|
||||||
SetPenSize(2);
|
view->SetPenSize(1);
|
||||||
|
|
||||||
|
view->SetHighColor(tint_color(view->ViewColor(), B_DARKEN_2_TINT));
|
||||||
|
view->StrokeRect(frame);
|
||||||
|
view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2),
|
||||||
|
BPoint(frame.right, frame.top + frame.Height() / 2));
|
||||||
|
|
||||||
|
view->SetPenSize(2);
|
||||||
|
|
||||||
for (uint32 i = fSources.CountItems(); i-- > 0;) {
|
for (uint32 i = fSources.CountItems(); i-- > 0;) {
|
||||||
DataSource* source = fSources.ItemAt(i);
|
DataSource* source = fSources.ItemAt(i);
|
||||||
@@ -436,8 +634,8 @@ ActivityView::Draw(BRect /*updateRect*/)
|
|||||||
bigtime_t time = now - steps * timeStep;
|
bigtime_t time = now - steps * timeStep;
|
||||||
// for now steps pixels per second
|
// for now steps pixels per second
|
||||||
|
|
||||||
BeginLineArray(steps);
|
view->BeginLineArray(steps);
|
||||||
SetHighColor(source->Color());
|
view->SetHighColor(source->Color());
|
||||||
|
|
||||||
float lastY = FLT_MIN;
|
float lastY = FLT_MIN;
|
||||||
uint32 lastX = 0;
|
uint32 lastX = 0;
|
||||||
@@ -462,17 +660,72 @@ ActivityView::Draw(BRect /*updateRect*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
float y = _PositionForValue(source, values, value);
|
float y = _PositionForValue(source, values, value);
|
||||||
if (lastY != FLT_MIN)
|
if (lastY != FLT_MIN) {
|
||||||
AddLine(BPoint(lastX, lastY), BPoint(x, y), source->Color());
|
view->AddLine(BPoint(lastX, lastY), BPoint(x, y),
|
||||||
|
source->Color());
|
||||||
|
}
|
||||||
|
|
||||||
lastX = x;
|
lastX = x;
|
||||||
lastY = y;
|
lastY = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndLineArray();
|
view->EndLineArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add marks when an app started or quit
|
// TODO: add marks when an app started or quit
|
||||||
|
view->Sync();
|
||||||
|
if (fOffscreen != NULL) {
|
||||||
|
fOffscreen->Unlock();
|
||||||
|
DrawBitmap(fOffscreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityView::Draw(BRect /*updateRect*/)
|
||||||
|
{
|
||||||
|
_DrawHistory();
|
||||||
|
|
||||||
|
if (!fShowLegend)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// draw legend
|
||||||
|
|
||||||
|
BRect legendFrame = _LegendFrame();
|
||||||
|
FillRect(legendFrame, B_SOLID_LOW);
|
||||||
|
|
||||||
|
font_height fontHeight;
|
||||||
|
GetFontHeight(&fontHeight);
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fSources.CountItems(); i++) {
|
||||||
|
DataSource* source = fSources.ItemAt(i);
|
||||||
|
DataHistory* values = fValues.ItemAt(i);
|
||||||
|
BRect frame = _LegendFrameAt(legendFrame, i);
|
||||||
|
|
||||||
|
// draw color box
|
||||||
|
BRect colorBox = frame.InsetByCopy(2, 2);
|
||||||
|
colorBox.right = colorBox.left + colorBox.Height();
|
||||||
|
SetHighColor(tint_color(source->Color(), B_DARKEN_1_TINT));
|
||||||
|
StrokeRect(colorBox);
|
||||||
|
SetHighColor(source->Color());
|
||||||
|
colorBox.InsetBy(1, 1);
|
||||||
|
FillRect(colorBox);
|
||||||
|
|
||||||
|
// show current value and label
|
||||||
|
float y = frame.top + ceilf(fontHeight.ascent);
|
||||||
|
int64 value = values->ValueAt(values->End());
|
||||||
|
BString text;
|
||||||
|
source->Print(text, value);
|
||||||
|
float width = StringWidth(text.String());
|
||||||
|
|
||||||
|
BString label = source->Label();
|
||||||
|
TruncateString(&label, B_TRUNCATE_MIDDLE,
|
||||||
|
frame.right - colorBox.right - 12 - width);
|
||||||
|
|
||||||
|
SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
||||||
|
DrawString(label.String(), BPoint(6 + colorBox.right, y));
|
||||||
|
DrawString(text.String(), BPoint(frame.right - width, y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "CircularBuffer.h"
|
#include "CircularBuffer.h"
|
||||||
|
|
||||||
|
class BBitmap;
|
||||||
class BMessageRunner;
|
class BMessageRunner;
|
||||||
class DataSource;
|
class DataSource;
|
||||||
struct data_item;
|
struct data_item;
|
||||||
@@ -43,7 +44,9 @@ private:
|
|||||||
class ActivityView : public BView {
|
class ActivityView : public BView {
|
||||||
public:
|
public:
|
||||||
ActivityView(BRect frame, const char* name,
|
ActivityView(BRect frame, const char* name,
|
||||||
const BMessage& settings, uint32 resizingMode);
|
const BMessage* settings, uint32 resizingMode);
|
||||||
|
ActivityView(const char* name,
|
||||||
|
const BMessage* settings);
|
||||||
ActivityView(BMessage* archive);
|
ActivityView(BMessage* archive);
|
||||||
virtual ~ActivityView();
|
virtual ~ActivityView();
|
||||||
|
|
||||||
@@ -52,15 +55,17 @@ public:
|
|||||||
|
|
||||||
status_t SaveState(BMessage& state) const;
|
status_t SaveState(BMessage& state) const;
|
||||||
|
|
||||||
DataSource* FindDataSource(const char* name);
|
DataSource* FindDataSource(const DataSource* source);
|
||||||
status_t AddDataSource(DataSource* source);
|
status_t AddDataSource(const DataSource* source);
|
||||||
status_t RemoveDataSource(DataSource* source);
|
status_t RemoveDataSource(const DataSource* source);
|
||||||
void RemoveAllDataSources();
|
void RemoveAllDataSources();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void DetachedFromWindow();
|
virtual void DetachedFromWindow();
|
||||||
|
|
||||||
|
virtual BSize MinSize();
|
||||||
|
|
||||||
virtual void FrameResized(float width, float height);
|
virtual void FrameResized(float width, float height);
|
||||||
virtual void MouseDown(BPoint where);
|
virtual void MouseDown(BPoint where);
|
||||||
virtual void MouseMoved(BPoint where, uint32 transit,
|
virtual void MouseMoved(BPoint where, uint32 transit,
|
||||||
@@ -73,10 +78,16 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void _Init(const BMessage* settings);
|
void _Init(const BMessage* settings);
|
||||||
void _Refresh();
|
void _Refresh();
|
||||||
|
void _UpdateOffscreenBitmap();
|
||||||
|
BRect _HistoryFrame() const;
|
||||||
|
BRect _LegendFrame() const;
|
||||||
|
BRect _LegendFrameAt(BRect frame, int32 index) const;
|
||||||
float _PositionForValue(DataSource* source,
|
float _PositionForValue(DataSource* source,
|
||||||
DataHistory* values, int64 value);
|
DataHistory* values, int64 value);
|
||||||
|
void _DrawHistory();
|
||||||
|
|
||||||
rgb_color fBackgroundColor;
|
rgb_color fBackgroundColor;
|
||||||
|
BBitmap* fOffscreen;
|
||||||
BObjectList<DataSource> fSources;
|
BObjectList<DataSource> fSources;
|
||||||
BObjectList<DataHistory> fValues;
|
BObjectList<DataHistory> fValues;
|
||||||
BMessageRunner* fRunner;
|
BMessageRunner* fRunner;
|
||||||
@@ -84,6 +95,7 @@ private:
|
|||||||
bigtime_t fLastRefresh;
|
bigtime_t fLastRefresh;
|
||||||
bigtime_t fDrawInterval;
|
bigtime_t fDrawInterval;
|
||||||
int32 fDrawResolution;
|
int32 fDrawResolution;
|
||||||
|
bool fShowLegend;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ACTIVITY_VIEW_H
|
#endif // ACTIVITY_VIEW_H
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
|
#include <GroupLayout.h>
|
||||||
#include <Menu.h>
|
#include <Menu.h>
|
||||||
#include <MenuBar.h>
|
#include <MenuBar.h>
|
||||||
#include <MenuItem.h>
|
#include <MenuItem.h>
|
||||||
@@ -21,6 +22,10 @@
|
|||||||
#include "ActivityView.h"
|
#include "ActivityView.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint32 kMsgAddView = 'advw';
|
||||||
|
const uint32 kMsgRemoveView = 'rmvw';
|
||||||
|
|
||||||
|
|
||||||
ActivityWindow::ActivityWindow()
|
ActivityWindow::ActivityWindow()
|
||||||
: BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW,
|
: BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW,
|
||||||
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
|
B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE)
|
||||||
@@ -32,24 +37,34 @@ ActivityWindow::ActivityWindow()
|
|||||||
if (settings.FindRect("window frame", &frame) == B_OK) {
|
if (settings.FindRect("window frame", &frame) == B_OK) {
|
||||||
MoveTo(frame.LeftTop());
|
MoveTo(frame.LeftTop());
|
||||||
ResizeTo(frame.Width(), frame.Height());
|
ResizeTo(frame.Width(), frame.Height());
|
||||||
frame.OffsetTo(B_ORIGIN);
|
}
|
||||||
} else
|
|
||||||
frame = Bounds();
|
BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
|
||||||
|
SetLayout(layout);
|
||||||
|
|
||||||
// create GUI
|
// create GUI
|
||||||
|
|
||||||
BMenuBar* menuBar = new BMenuBar(Bounds(), "menu");
|
BMenuBar* menuBar = new BMenuBar("menu");
|
||||||
AddChild(menuBar);
|
layout->AddView(menuBar);
|
||||||
|
|
||||||
frame.top = menuBar->Frame().bottom;
|
fLayout = new BGroupLayout(B_VERTICAL);
|
||||||
|
float inset = ceilf(be_plain_font->Size() * 0.7);
|
||||||
|
fLayout->SetInsets(inset, inset, inset, inset);
|
||||||
|
fLayout->SetSpacing(inset);
|
||||||
|
|
||||||
BView* top = new BView(frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
|
BView* top = new BView("top", 0, fLayout);
|
||||||
top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
top->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
AddChild(top);
|
layout->AddView(top);
|
||||||
|
|
||||||
fActivityView = new ActivityView(top->Bounds().InsetByCopy(10, 10),
|
BMessage viewState;
|
||||||
"ActivityMonitor", settings, B_FOLLOW_ALL);
|
int32 count = 0;
|
||||||
top->AddChild(fActivityView);
|
for (int32 i = 0; settings.FindMessage("activity view", i, &viewState)
|
||||||
|
== B_OK; i++) {
|
||||||
|
fLayout->AddView(new ActivityView("ActivityMonitor", &viewState));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count == 0)
|
||||||
|
fLayout->AddView(new ActivityView("ActivityMonitor", NULL));
|
||||||
|
|
||||||
// add menu
|
// add menu
|
||||||
|
|
||||||
@@ -57,6 +72,11 @@ ActivityWindow::ActivityWindow()
|
|||||||
BMenu* menu = new BMenu("File");
|
BMenu* menu = new BMenu("File");
|
||||||
BMenuItem* item;
|
BMenuItem* item;
|
||||||
|
|
||||||
|
menu->AddItem(new BMenuItem("Add View", new BMessage(kMsgAddView)));
|
||||||
|
menu->AddItem(fRemoveItem = new BMenuItem("Remove View",
|
||||||
|
new BMessage(kMsgRemoveView)));
|
||||||
|
menu->AddSeparatorItem();
|
||||||
|
|
||||||
menu->AddItem(item = new BMenuItem("About ActivityMonitor" B_UTF8_ELLIPSIS,
|
menu->AddItem(item = new BMenuItem("About ActivityMonitor" B_UTF8_ELLIPSIS,
|
||||||
new BMessage(B_ABOUT_REQUESTED)));
|
new BMessage(B_ABOUT_REQUESTED)));
|
||||||
menu->AddSeparatorItem();
|
menu->AddSeparatorItem();
|
||||||
@@ -65,6 +85,8 @@ ActivityWindow::ActivityWindow()
|
|||||||
menu->SetTargetForItems(this);
|
menu->SetTargetForItems(this);
|
||||||
item->SetTarget(be_app);
|
item->SetTarget(be_app);
|
||||||
menuBar->AddItem(menu);
|
menuBar->AddItem(menu);
|
||||||
|
|
||||||
|
_UpdateRemoveItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -109,6 +131,26 @@ ActivityWindow::_SaveSettings()
|
|||||||
|
|
||||||
BMessage settings('actm');
|
BMessage settings('actm');
|
||||||
status = settings.AddRect("window frame", Frame());
|
status = settings.AddRect("window frame", Frame());
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
BView* top = GetLayout()->View();
|
||||||
|
int32 count = top->CountChildren();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
ActivityView* view = dynamic_cast<ActivityView*>(top->ChildAt(i));
|
||||||
|
if (view == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BMessage* viewState = new BMessage;
|
||||||
|
status = view->SaveState(*viewState);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = settings.AddMessage("activity view", viewState);
|
||||||
|
if (status != B_OK) {
|
||||||
|
delete viewState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = settings.Flatten(&file);
|
status = settings.Flatten(&file);
|
||||||
|
|
||||||
@@ -116,6 +158,16 @@ ActivityWindow::_SaveSettings()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ActivityWindow::_UpdateRemoveItem()
|
||||||
|
{
|
||||||
|
BView* view = fLayout->View();
|
||||||
|
int32 count = view->CountChildren();
|
||||||
|
|
||||||
|
fRemoveItem->SetEnabled(count >= 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ActivityWindow::_MessageDropped(BMessage* message)
|
ActivityWindow::_MessageDropped(BMessage* message)
|
||||||
{
|
{
|
||||||
@@ -140,6 +192,32 @@ ActivityWindow::MessageReceived(BMessage* message)
|
|||||||
_MessageDropped(message);
|
_MessageDropped(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kMsgAddView:
|
||||||
|
{
|
||||||
|
BView* view = fLayout->View()->ChildAt(0);
|
||||||
|
fLayout->AddView(new ActivityView("ActivityMonitor", NULL));
|
||||||
|
if (view != NULL)
|
||||||
|
ResizeBy(0, view->Bounds().Height() + fLayout->Spacing());
|
||||||
|
_UpdateRemoveItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kMsgRemoveView:
|
||||||
|
{
|
||||||
|
BView* view = fLayout->View();
|
||||||
|
int32 count = view->CountChildren();
|
||||||
|
if (count == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BView* last = view->ChildAt(count - 1);
|
||||||
|
fLayout->RemoveView(last);
|
||||||
|
ResizeBy(0, -last->Bounds().Height() - fLayout->Spacing());
|
||||||
|
delete last;
|
||||||
|
|
||||||
|
_UpdateRemoveItem();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BWindow::MessageReceived(message);
|
BWindow::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
class BFile;
|
class BFile;
|
||||||
|
class BGroupLayout;
|
||||||
|
class BMenuItem;
|
||||||
class ActivityView;
|
class ActivityView;
|
||||||
|
|
||||||
|
|
||||||
@@ -25,9 +27,11 @@ private:
|
|||||||
status_t _LoadSettings(BMessage& settings);
|
status_t _LoadSettings(BMessage& settings);
|
||||||
status_t _SaveSettings();
|
status_t _SaveSettings();
|
||||||
|
|
||||||
|
void _UpdateRemoveItem();
|
||||||
void _MessageDropped(BMessage *message);
|
void _MessageDropped(BMessage *message);
|
||||||
|
|
||||||
ActivityView* fActivityView;
|
BGroupLayout* fLayout;
|
||||||
|
BMenuItem* fRemoveItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ACTIVITY_WINDOW_H
|
#endif // ACTIVITY_WINDOW_H
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ const DataSource* kSources[] = {
|
|||||||
new UsedMemoryDataSource(),
|
new UsedMemoryDataSource(),
|
||||||
new CachedMemoryDataSource(),
|
new CachedMemoryDataSource(),
|
||||||
new ThreadsDataSource(),
|
new ThreadsDataSource(),
|
||||||
new CpuUsageDataSource(),
|
new CPUUsageDataSource(),
|
||||||
|
new CPUCombinedUsageDataSource(),
|
||||||
|
new NetworkUsageDataSource(true),
|
||||||
|
new NetworkUsageDataSource(false)
|
||||||
};
|
};
|
||||||
const size_t kSourcesCount = sizeof(kSources) / sizeof(kSources[0]);
|
const size_t kSourcesCount = sizeof(kSources) / sizeof(kSources[0]);
|
||||||
|
|
||||||
@@ -65,6 +68,13 @@ DataSource::Copy() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
DataSource::CopyForCPU(int32 cpu) const
|
||||||
|
{
|
||||||
|
return Copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int64
|
int64
|
||||||
DataSource::Minimum() const
|
DataSource::Minimum() const
|
||||||
{
|
{
|
||||||
@@ -123,6 +133,13 @@ DataSource::Print(BString& text, int64 value) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
DataSource::Name() const
|
||||||
|
{
|
||||||
|
return Label();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
DataSource::Label() const
|
DataSource::Label() const
|
||||||
{
|
{
|
||||||
@@ -151,6 +168,27 @@ DataSource::AdaptiveScale() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
DataSource::CPU() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DataSource::PerCPU() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
DataSource::MultiCPUOnly() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int32
|
/*static*/ int32
|
||||||
DataSource::CountSources()
|
DataSource::CountSources()
|
||||||
{
|
{
|
||||||
@@ -168,6 +206,33 @@ DataSource::SourceAt(int32 index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ const DataSource*
|
||||||
|
DataSource::FindSource(const char* name)
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < kSourcesCount; i++) {
|
||||||
|
const DataSource* source = kSources[i];
|
||||||
|
if (!strcmp(source->Name(), name))
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ int32
|
||||||
|
DataSource::IndexOf(const DataSource* source)
|
||||||
|
{
|
||||||
|
const char* name = source->Name();
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < kSourcesCount; i++) {
|
||||||
|
if (!strcmp(kSources[i]->Name(), name))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -189,7 +254,7 @@ void
|
|||||||
MemoryDataSource::Print(BString& text, int64 value) const
|
MemoryDataSource::Print(BString& text, int64 value) const
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
snprintf(buffer, sizeof(buffer), "%.1g MB", value / 1048576.0);
|
snprintf(buffer, sizeof(buffer), "%.1f MB", value / 1048576.0);
|
||||||
|
|
||||||
text = buffer;
|
text = buffer;
|
||||||
}
|
}
|
||||||
@@ -232,7 +297,7 @@ UsedMemoryDataSource::NextValue(SystemInfo& info)
|
|||||||
const char*
|
const char*
|
||||||
UsedMemoryDataSource::Label() const
|
UsedMemoryDataSource::Label() const
|
||||||
{
|
{
|
||||||
return "Available Memory";
|
return "Used Memory";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -321,7 +386,134 @@ ThreadsDataSource::AdaptiveScale() const
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
CpuUsageDataSource::CpuUsageDataSource()
|
CPUUsageDataSource::CPUUsageDataSource(int32 cpu)
|
||||||
|
:
|
||||||
|
fPreviousActive(0),
|
||||||
|
fPreviousTime(0)
|
||||||
|
{
|
||||||
|
fMinimum = 0;
|
||||||
|
fMaximum = 1000;
|
||||||
|
|
||||||
|
_SetCPU(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CPUUsageDataSource::CPUUsageDataSource(const CPUUsageDataSource& other)
|
||||||
|
: DataSource(other)
|
||||||
|
{
|
||||||
|
fPreviousActive = other.fPreviousActive;
|
||||||
|
fPreviousTime = other.fPreviousTime;
|
||||||
|
fCPU = other.fCPU;
|
||||||
|
fLabel = other.fLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CPUUsageDataSource::~CPUUsageDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
CPUUsageDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new CPUUsageDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
CPUUsageDataSource::CopyForCPU(int32 cpu) const
|
||||||
|
{
|
||||||
|
CPUUsageDataSource* copy = new CPUUsageDataSource(*this);
|
||||||
|
copy->_SetCPU(cpu);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CPUUsageDataSource::Print(BString& text, int64 value) const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%.1f%%", value / 10.0);
|
||||||
|
|
||||||
|
text = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
CPUUsageDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
bigtime_t active = info.Info().cpu_infos[fCPU].active_time;
|
||||||
|
|
||||||
|
int64 percent = int64(1000.0 * (active - fPreviousActive)
|
||||||
|
/ (info.Time() - fPreviousTime));
|
||||||
|
if (percent < 0)
|
||||||
|
percent = 0;
|
||||||
|
if (percent > 1000)
|
||||||
|
percent = 1000;
|
||||||
|
|
||||||
|
fPreviousActive = active;
|
||||||
|
fPreviousTime = info.Time();
|
||||||
|
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CPUUsageDataSource::Label() const
|
||||||
|
{
|
||||||
|
return fLabel.String();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CPUUsageDataSource::Name() const
|
||||||
|
{
|
||||||
|
return "CPU Usage";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
CPUUsageDataSource::CPU() const
|
||||||
|
{
|
||||||
|
return fCPU;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPUUsageDataSource::PerCPU() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CPUUsageDataSource::_SetCPU(int32 cpu)
|
||||||
|
{
|
||||||
|
fCPU = cpu;
|
||||||
|
fLabel = "CPU";
|
||||||
|
if (SystemInfo().CPUCount() > 1)
|
||||||
|
fLabel << " " << cpu;
|
||||||
|
|
||||||
|
fLabel << " Usage";
|
||||||
|
|
||||||
|
const rgb_color kColors[] = {
|
||||||
|
// TODO: find some better defaults...
|
||||||
|
{200, 0, 200},
|
||||||
|
{0, 200, 200},
|
||||||
|
{80, 80, 80},
|
||||||
|
{230, 150, 50},
|
||||||
|
};
|
||||||
|
const uint32 kNumColors = sizeof(kColors) / sizeof(kColors[0]);
|
||||||
|
|
||||||
|
fColor = kColors[cpu % kNumColors];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
CPUCombinedUsageDataSource::CPUCombinedUsageDataSource()
|
||||||
:
|
:
|
||||||
fPreviousActive(0),
|
fPreviousActive(0),
|
||||||
fPreviousTime(0)
|
fPreviousTime(0)
|
||||||
@@ -333,37 +525,39 @@ CpuUsageDataSource::CpuUsageDataSource()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CpuUsageDataSource::CpuUsageDataSource(const CpuUsageDataSource& other)
|
CPUCombinedUsageDataSource::CPUCombinedUsageDataSource(
|
||||||
|
const CPUCombinedUsageDataSource& other)
|
||||||
|
: DataSource(other)
|
||||||
{
|
{
|
||||||
fPreviousActive = other.fPreviousActive;
|
fPreviousActive = other.fPreviousActive;
|
||||||
fPreviousTime = other.fPreviousTime;
|
fPreviousTime = other.fPreviousTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CpuUsageDataSource::~CpuUsageDataSource()
|
CPUCombinedUsageDataSource::~CPUCombinedUsageDataSource()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DataSource*
|
DataSource*
|
||||||
CpuUsageDataSource::Copy() const
|
CPUCombinedUsageDataSource::Copy() const
|
||||||
{
|
{
|
||||||
return new CpuUsageDataSource(*this);
|
return new CPUCombinedUsageDataSource(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CpuUsageDataSource::Print(BString& text, int64 value) const
|
CPUCombinedUsageDataSource::Print(BString& text, int64 value) const
|
||||||
{
|
{
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
snprintf(buffer, sizeof(buffer), "%.1g%%", value / 10.0);
|
snprintf(buffer, sizeof(buffer), "%.1f%%", value / 10.0);
|
||||||
|
|
||||||
text = buffer;
|
text = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64
|
int64
|
||||||
CpuUsageDataSource::NextValue(SystemInfo& info)
|
CPUCombinedUsageDataSource::NextValue(SystemInfo& info)
|
||||||
{
|
{
|
||||||
int32 running = 0;
|
int32 running = 0;
|
||||||
bigtime_t active = 0;
|
bigtime_t active = 0;
|
||||||
@@ -389,7 +583,108 @@ CpuUsageDataSource::NextValue(SystemInfo& info)
|
|||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
CpuUsageDataSource::Label() const
|
CPUCombinedUsageDataSource::Label() const
|
||||||
{
|
{
|
||||||
return "CPU Usage";
|
return "CPU Usage";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
CPUCombinedUsageDataSource::Name() const
|
||||||
|
{
|
||||||
|
return "CPU Usage (combined)";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CPUCombinedUsageDataSource::MultiCPUOnly() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
NetworkUsageDataSource::NetworkUsageDataSource(bool in)
|
||||||
|
:
|
||||||
|
fIn(in),
|
||||||
|
fPreviousBytes(0),
|
||||||
|
fPreviousTime(0)
|
||||||
|
{
|
||||||
|
SystemInfo info;
|
||||||
|
NextValue(info);
|
||||||
|
|
||||||
|
fMinimum = 0;
|
||||||
|
fMaximum = 1000000000LL;
|
||||||
|
|
||||||
|
fColor = fIn ? (rgb_color){200, 150, 0} : (rgb_color){200, 220, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetworkUsageDataSource::NetworkUsageDataSource(
|
||||||
|
const NetworkUsageDataSource& other)
|
||||||
|
: DataSource(other)
|
||||||
|
{
|
||||||
|
fIn = other.fIn;
|
||||||
|
fPreviousBytes = other.fPreviousBytes;
|
||||||
|
fPreviousTime = other.fPreviousTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NetworkUsageDataSource::~NetworkUsageDataSource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DataSource*
|
||||||
|
NetworkUsageDataSource::Copy() const
|
||||||
|
{
|
||||||
|
return new NetworkUsageDataSource(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
NetworkUsageDataSource::Print(BString& text, int64 value) const
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%.1f KB/s", value / 1024.0);
|
||||||
|
|
||||||
|
text = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int64
|
||||||
|
NetworkUsageDataSource::NextValue(SystemInfo& info)
|
||||||
|
{
|
||||||
|
uint64 transferred = fIn ? info.NetworkReceived() : info.NetworkSent();
|
||||||
|
|
||||||
|
int64 bytesPerSecond = uint64((transferred - fPreviousBytes)
|
||||||
|
/ ((info.Time() - fPreviousTime) / 1000000.0));
|
||||||
|
|
||||||
|
fPreviousBytes = transferred;
|
||||||
|
fPreviousTime = info.Time();
|
||||||
|
|
||||||
|
return bytesPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
NetworkUsageDataSource::Label() const
|
||||||
|
{
|
||||||
|
return fIn ? "Receiving" : "Sending";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
NetworkUsageDataSource::Name() const
|
||||||
|
{
|
||||||
|
return fIn ? "Network Receive" : "Network Send";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
NetworkUsageDataSource::AdaptiveScale() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <InterfaceDefs.h>
|
#include <InterfaceDefs.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
class BString;
|
|
||||||
class SystemInfo;
|
class SystemInfo;
|
||||||
|
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@ public:
|
|||||||
virtual ~DataSource();
|
virtual ~DataSource();
|
||||||
|
|
||||||
virtual DataSource* Copy() const;
|
virtual DataSource* Copy() const;
|
||||||
|
virtual DataSource* CopyForCPU(int32 cpu) const;
|
||||||
|
|
||||||
int64 Minimum() const;
|
int64 Minimum() const;
|
||||||
int64 Maximum() const;
|
int64 Maximum() const;
|
||||||
@@ -32,13 +33,19 @@ public:
|
|||||||
virtual int64 NextValue(SystemInfo& info);
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
virtual void Print(BString& text, int64 value) const;
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
|
||||||
|
virtual const char* Name() const;
|
||||||
virtual const char* Label() const;
|
virtual const char* Label() const;
|
||||||
virtual const char* Unit() const;
|
virtual const char* Unit() const;
|
||||||
virtual rgb_color Color() const;
|
virtual rgb_color Color() const;
|
||||||
virtual bool AdaptiveScale() const;
|
virtual bool AdaptiveScale() const;
|
||||||
|
virtual int32 CPU() const;
|
||||||
|
virtual bool PerCPU() const;
|
||||||
|
virtual bool MultiCPUOnly() const;
|
||||||
|
|
||||||
static int32 CountSources();
|
static int32 CountSources();
|
||||||
static const DataSource* SourceAt(int32 index);
|
static const DataSource* SourceAt(int32 index);
|
||||||
|
static const DataSource* FindSource(const char* name);
|
||||||
|
static int32 IndexOf(const DataSource* source);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int64 fMinimum;
|
int64 fMinimum;
|
||||||
@@ -95,21 +102,77 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CpuUsageDataSource : public DataSource {
|
class CPUUsageDataSource : public DataSource {
|
||||||
public:
|
public:
|
||||||
CpuUsageDataSource();
|
CPUUsageDataSource(int32 cpu = 0);
|
||||||
CpuUsageDataSource(const CpuUsageDataSource& other);
|
CPUUsageDataSource(const CPUUsageDataSource& other);
|
||||||
virtual ~CpuUsageDataSource();
|
virtual ~CPUUsageDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
virtual DataSource* CopyForCPU(int32 cpu) const;
|
||||||
|
|
||||||
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
|
||||||
|
virtual const char* Name() const;
|
||||||
|
virtual const char* Label() const;
|
||||||
|
|
||||||
|
virtual int32 CPU() const;
|
||||||
|
virtual bool PerCPU() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void _SetCPU(int32 cpu);
|
||||||
|
|
||||||
|
bigtime_t fPreviousActive;
|
||||||
|
bigtime_t fPreviousTime;
|
||||||
|
int32 fCPU;
|
||||||
|
BString fLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CPUCombinedUsageDataSource : public DataSource {
|
||||||
|
public:
|
||||||
|
CPUCombinedUsageDataSource();
|
||||||
|
CPUCombinedUsageDataSource(
|
||||||
|
const CPUCombinedUsageDataSource& other);
|
||||||
|
virtual ~CPUCombinedUsageDataSource();
|
||||||
|
|
||||||
virtual DataSource* Copy() const;
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
virtual void Print(BString& text, int64 value) const;
|
virtual void Print(BString& text, int64 value) const;
|
||||||
virtual int64 NextValue(SystemInfo& info);
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
|
||||||
|
virtual const char* Name() const;
|
||||||
virtual const char* Label() const;
|
virtual const char* Label() const;
|
||||||
|
|
||||||
|
virtual bool MultiCPUOnly() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bigtime_t fPreviousActive;
|
bigtime_t fPreviousActive;
|
||||||
bigtime_t fPreviousTime;
|
bigtime_t fPreviousTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkUsageDataSource : public DataSource {
|
||||||
|
public:
|
||||||
|
NetworkUsageDataSource(bool in);
|
||||||
|
NetworkUsageDataSource(
|
||||||
|
const NetworkUsageDataSource& other);
|
||||||
|
virtual ~NetworkUsageDataSource();
|
||||||
|
|
||||||
|
virtual DataSource* Copy() const;
|
||||||
|
|
||||||
|
virtual void Print(BString& text, int64 value) const;
|
||||||
|
virtual int64 NextValue(SystemInfo& info);
|
||||||
|
|
||||||
|
virtual const char* Name() const;
|
||||||
|
virtual const char* Label() const;
|
||||||
|
virtual bool AdaptiveScale() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool fIn;
|
||||||
|
uint64 fPreviousBytes;
|
||||||
|
bigtime_t fPreviousTime;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // DATA_SOURCE_H
|
#endif // DATA_SOURCE_H
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
SubDir HAIKU_TOP src apps activitymonitor ;
|
SubDir HAIKU_TOP src apps activitymonitor ;
|
||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
|
||||||
|
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
Application ActivityMonitor :
|
Application ActivityMonitor :
|
||||||
@@ -11,6 +9,6 @@ Application ActivityMonitor :
|
|||||||
DataSource.cpp
|
DataSource.cpp
|
||||||
SystemInfo.cpp
|
SystemInfo.cpp
|
||||||
|
|
||||||
: be tracker $(TARGET_LIBSTDC++)
|
: be tracker $(TARGET_LIBSTDC++) libnetwork.so
|
||||||
: ActivityMonitor.rdef
|
: ActivityMonitor.rdef
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -6,10 +6,17 @@
|
|||||||
|
|
||||||
#include "SystemInfo.h"
|
#include "SystemInfo.h"
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sockio.h>
|
||||||
|
|
||||||
|
|
||||||
SystemInfo::SystemInfo()
|
SystemInfo::SystemInfo()
|
||||||
:
|
:
|
||||||
fTime(system_time())
|
fTime(system_time()),
|
||||||
|
fRetrievedNetwork(false)
|
||||||
{
|
{
|
||||||
get_system_info(&fSystemInfo);
|
get_system_info(&fSystemInfo);
|
||||||
}
|
}
|
||||||
@@ -67,3 +74,79 @@ SystemInfo::MaxTeams() const
|
|||||||
{
|
{
|
||||||
return fSystemInfo.max_teams;
|
return fSystemInfo.max_teams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SystemInfo::_RetrieveNetwork()
|
||||||
|
{
|
||||||
|
if (fRetrievedNetwork)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fBytesReceived = 0;
|
||||||
|
fBytesSent = 0;
|
||||||
|
fRetrievedNetwork = true;
|
||||||
|
|
||||||
|
// we need a socket to talk to the networking stack
|
||||||
|
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (socket < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get a list of all interfaces
|
||||||
|
|
||||||
|
ifconf config;
|
||||||
|
config.ifc_len = sizeof(config.ifc_value);
|
||||||
|
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0
|
||||||
|
|| config.ifc_value == 0) {
|
||||||
|
close(socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 count = (uint32)config.ifc_value;
|
||||||
|
|
||||||
|
void *buffer = malloc(count * sizeof(struct ifreq));
|
||||||
|
if (buffer == NULL) {
|
||||||
|
close(socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.ifc_len = count * sizeof(struct ifreq);
|
||||||
|
config.ifc_buf = buffer;
|
||||||
|
if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0) {
|
||||||
|
close(socket);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifreq *interface = (ifreq *)buffer;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < count; i++) {
|
||||||
|
ifreq request;
|
||||||
|
strlcpy(request.ifr_name, interface->ifr_name, IF_NAMESIZE);
|
||||||
|
|
||||||
|
if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) == 0) {
|
||||||
|
fBytesReceived += request.ifr_stats.receive.bytes;
|
||||||
|
fBytesSent += request.ifr_stats.send.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
||||||
|
+ interface->ifr_addr.sa_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
SystemInfo::NetworkReceived()
|
||||||
|
{
|
||||||
|
_RetrieveNetwork();
|
||||||
|
return fBytesReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64
|
||||||
|
SystemInfo::NetworkSent()
|
||||||
|
{
|
||||||
|
_RetrieveNetwork();
|
||||||
|
return fBytesSent;
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,11 +25,20 @@ public:
|
|||||||
uint32 MaxTeams() const;
|
uint32 MaxTeams() const;
|
||||||
|
|
||||||
bigtime_t Time() const { return fTime; }
|
bigtime_t Time() const { return fTime; }
|
||||||
|
uint32 CPUCount() const { return fSystemInfo.cpu_count; }
|
||||||
const system_info& Info() const { return fSystemInfo; }
|
const system_info& Info() const { return fSystemInfo; }
|
||||||
|
|
||||||
|
uint64 NetworkReceived();
|
||||||
|
uint64 NetworkSent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void _RetrieveNetwork();
|
||||||
|
|
||||||
system_info fSystemInfo;
|
system_info fSystemInfo;
|
||||||
bigtime_t fTime;
|
bigtime_t fTime;
|
||||||
|
bool fRetrievedNetwork;
|
||||||
|
uint64 fBytesReceived;
|
||||||
|
uint64 fBytesSent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SYSTEM_INFO_H
|
#endif // SYSTEM_INFO_H
|
||||||
|
|||||||
Reference in New Issue
Block a user