* Added a settings window - right now, you can only change the time interval,

though.
* Shortened the time interval defaults to 250 ms; the drawing updates are made
  every 500 ms - this still seems to have only little influence on CPU load over
  here (YMMV).
* The resolution/scale change is now applied to all views, not just the current.
* Changed the pen size of the chart to 1.5.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29497 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-03-13 20:19:10 +00:00
parent 51ff40fed0
commit 1bb87bd0b1
7 changed files with 401 additions and 106 deletions
+71 -31
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -24,6 +24,7 @@
#include "ActivityMonitor.h" #include "ActivityMonitor.h"
#include "ActivityWindow.h" #include "ActivityWindow.h"
#include "SettingsWindow.h"
#include "SystemInfo.h" #include "SystemInfo.h"
#include "SystemInfoHandler.h" #include "SystemInfoHandler.h"
@@ -92,10 +93,11 @@ private:
}; };
#endif #endif
const bigtime_t kInitialRefreshInterval = 500000LL; const bigtime_t kInitialRefreshInterval = 250000LL;
const uint32 kMsgToggleDataSource = 'tgds'; const uint32 kMsgToggleDataSource = 'tgds';
const uint32 kMsgToggleLegend = 'tglg'; const uint32 kMsgToggleLegend = 'tglg';
const uint32 kMsgUpdateResolution = 'ures';
extern const char* kSignature; extern const char* kSignature;
@@ -627,7 +629,7 @@ ActivityView::AddDataSource(const DataSource* source, const BMessage* state)
for (uint32 i = 0; i < count; i++) { for (uint32 i = 0; i < count; i++) {
DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL, DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
fRefreshInterval); RefreshInterval());
if (values == NULL) if (values == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -874,21 +876,14 @@ ActivityView::MouseMoved(BPoint where, uint32 transit,
if (!fZooming) if (!fZooming)
return; return;
int32 previousResolution = fDrawResolution;
int32 shift = int32(where.x - fZoomPoint.x) / 25; int32 shift = int32(where.x - fZoomPoint.x) / 25;
int32 resolution;
if (shift > 0) if (shift > 0)
fDrawResolution = fOriginalResolution << shift; resolution = fOriginalResolution << shift;
else else
fDrawResolution = fOriginalResolution >> -shift; resolution = fOriginalResolution >> -shift;
if (fDrawResolution < 1) _UpdateResolution(resolution);
fDrawResolution = 1;
if (fDrawResolution > 128)
fDrawResolution = 128;
if (previousResolution != fDrawResolution)
Invalidate();
} }
@@ -939,6 +934,32 @@ ActivityView::MessageReceived(BMessage* message)
ActivityMonitor::ShowAbout(); ActivityMonitor::ShowAbout();
break; break;
case kMsgUpdateResolution:
{
int32 resolution;
if (message->FindInt32("resolution", &resolution) != B_OK)
break;
_UpdateResolution(resolution, false);
break;
}
case kMsgTimeIntervalUpdated:
bigtime_t interval;
if (message->FindInt64("interval", &interval) != B_OK)
break;
if (interval < 10000)
interval = 10000;
atomic_set64(&fRefreshInterval, interval);
if (interval > 250000)
atomic_set64(&fDrawInterval, interval);
else
atomic_set64(&fDrawInterval, interval * 2);
break;
case kMsgToggleDataSource: case kMsgToggleDataSource:
{ {
int32 index; int32 index;
@@ -971,17 +992,13 @@ ActivityView::MessageReceived(BMessage* message)
|| deltaY == 0.0f) || deltaY == 0.0f)
break; break;
int32 resolution = fDrawResolution;
if (deltaY > 0) if (deltaY > 0)
fDrawResolution *= 2; resolution *= 2;
else else
fDrawResolution /= 2; resolution /= 2;
if (fDrawResolution < 1) _UpdateResolution(resolution);
fDrawResolution = 1;
if (fDrawResolution > 128)
fDrawResolution = 128;
Invalidate();
break; break;
} }
@@ -1139,7 +1156,7 @@ ActivityView::_DrawHistory()
uint32 width = frame.IntegerWidth() - 10; uint32 width = frame.IntegerWidth() - 10;
uint32 steps = width / step; uint32 steps = width / step;
bigtime_t timeStep = fRefreshInterval * resolution; bigtime_t timeStep = RefreshInterval() * resolution;
bigtime_t now = system_time(); bigtime_t now = system_time();
// Draw scale // Draw scale
@@ -1161,7 +1178,7 @@ ActivityView::_DrawHistory()
// Draw values // Draw values
view->SetPenSize(2); view->SetPenSize(1.5);
BAutolock _(fSourcesLock); BAutolock _(fSourcesLock);
for (uint32 i = fSources.CountItems(); i-- > 0;) { for (uint32 i = fSources.CountItems(); i-- > 0;) {
@@ -1182,12 +1199,12 @@ ActivityView::_DrawHistory()
continue; continue;
int64 value = values->ValueAt(time); int64 value = values->ValueAt(time);
if (timeStep > fRefreshInterval) { if (timeStep > RefreshInterval()) {
// TODO: always start with the same index, so that it always // TODO: always start with the same index, so that it always
// uses the same values for computation (currently it jumps) // uses the same values for computation (currently it jumps)
uint32 count = 1; uint32 count = 1;
for (bigtime_t offset = fRefreshInterval; offset < timeStep; for (bigtime_t offset = RefreshInterval(); offset < timeStep;
offset += fRefreshInterval) { offset += RefreshInterval()) {
// TODO: handle int64 overflow correctly! // TODO: handle int64 overflow correctly!
value += values->ValueAt(time + offset); value += values->ValueAt(time + offset);
count++; count++;
@@ -1217,6 +1234,29 @@ ActivityView::_DrawHistory()
} }
void
ActivityView::_UpdateResolution(int32 resolution, bool broadcast)
{
if (resolution < 1)
resolution = 1;
if (resolution > 128)
resolution = 128;
if (resolution == fDrawResolution)
return;
ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
if (broadcast && window != NULL) {
BMessage update(kMsgUpdateResolution);
update.AddInt32("resolution", resolution);
window->BroadcastToActivityViews(&update, this);
}
fDrawResolution = resolution;
Invalidate();
}
void void
ActivityView::Draw(BRect /*updateRect*/) ActivityView::Draw(BRect /*updateRect*/)
{ {
@@ -1270,19 +1310,19 @@ ActivityView::Draw(BRect /*updateRect*/)
void void
ActivityView::_Refresh() ActivityView::_Refresh()
{ {
bigtime_t lastTimeout = system_time() - fRefreshInterval; bigtime_t lastTimeout = system_time() - RefreshInterval();
BMessenger target(this); BMessenger target(this);
while (true) { while (true) {
status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT, status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT,
lastTimeout + fRefreshInterval); lastTimeout + RefreshInterval());
if (status == B_OK || status == B_BAD_SEM_ID) if (status == B_OK || status == B_BAD_SEM_ID)
break; break;
if (status == B_INTERRUPTED) if (status == B_INTERRUPTED)
continue; continue;
SystemInfo info(fSystemInfoHandler); SystemInfo info(fSystemInfoHandler);
lastTimeout += fRefreshInterval; lastTimeout += RefreshInterval();
fSourcesLock.Lock(); fSourcesLock.Lock();
@@ -1297,7 +1337,7 @@ ActivityView::_Refresh()
fSourcesLock.Unlock(); fSourcesLock.Unlock();
bigtime_t now = info.Time(); bigtime_t now = info.Time();
if (fLastRefresh + fDrawInterval <= now) { if (fLastRefresh + DrawInterval() <= now) {
target.SendMessage(B_INVALIDATE); target.SendMessage(B_INVALIDATE);
fLastRefresh = now; fLastRefresh = now;
} }
+7
View File
@@ -74,6 +74,11 @@ public:
status_t RemoveDataSource(const DataSource* source); status_t RemoveDataSource(const DataSource* source);
void RemoveAllDataSources(); void RemoveAllDataSources();
bigtime_t RefreshInterval() const
{ return atomic_get64((vint64*)&fRefreshInterval); }
bigtime_t DrawInterval() const
{ return atomic_get64((vint64*)&fDrawInterval); }
protected: protected:
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void DetachedFromWindow(); virtual void DetachedFromWindow();
@@ -108,6 +113,8 @@ private:
float _PositionForValue(DataSource* source, float _PositionForValue(DataSource* source,
DataHistory* values, int64 value); DataHistory* values, int64 value);
void _DrawHistory(); void _DrawHistory();
void _UpdateResolution(int32 resolution,
bool broadcast = true);
private: private:
class HistoryLayoutItem; class HistoryLayoutItem;
+134 -72
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -23,9 +23,11 @@
#include "ActivityMonitor.h" #include "ActivityMonitor.h"
#include "ActivityView.h" #include "ActivityView.h"
#include "DataSource.h" #include "DataSource.h"
#include "SettingsWindow.h"
static const uint32 kMsgAddView = 'advw'; static const uint32 kMsgAddView = 'advw';
static const uint32 kMsgShowSettings = 'shst';
ActivityWindow::ActivityWindow() ActivityWindow::ActivityWindow()
@@ -125,6 +127,13 @@ ActivityWindow::ActivityWindow()
menu->SetTargetForItems(this); menu->SetTargetForItems(this);
item->SetTarget(be_app); item->SetTarget(be_app);
menuBar->AddItem(menu); menuBar->AddItem(menu);
// "Settings" menu
menu = new BMenu("Settings");
menu->AddItem(new BMenuItem("Settings" B_UTF8_ELLIPSIS,
new BMessage(kMsgShowSettings)));
menu->SetTargetForItems(this);
menuBar->AddItem(menu);
} }
@@ -133,6 +142,126 @@ ActivityWindow::~ActivityWindow()
} }
void
ActivityWindow::MessageReceived(BMessage* message)
{
if (message->WasDropped()) {
_MessageDropped(message);
return;
}
switch (message->what) {
case B_REFS_RECEIVED:
case B_SIMPLE_DATA:
_MessageDropped(message);
break;
case kMsgAddView:
{
#ifdef __HAIKU__
BView* firstView = fLayout->View()->ChildAt(0);
_AddDefaultView();
if (firstView != NULL)
ResizeBy(0, firstView->Bounds().Height() + fLayout->Spacing());
#endif
break;
}
case kMsgRemoveView:
{
#ifdef __HAIKU__
BView* view;
if (message->FindPointer("view", (void**)&view) != B_OK)
break;
view->RemoveSelf();
ResizeBy(0, -view->Bounds().Height() - fLayout->Spacing());
delete view;
#endif
break;
}
case kMsgShowSettings:
{
if (fSettingsWindow.IsValid()) {
// Just bring the window to front (via scripting)
BMessage toFront(B_SET_PROPERTY);
toFront.AddSpecifier("Active");
toFront.AddSpecifier("Window", "Settings");
toFront.AddBool("data", true);
fSettingsWindow.SendMessage(&toFront);
} else {
// Open new settings window
BWindow* window = new SettingsWindow(this);
window->Show();
fSettingsWindow = window;
}
break;
}
case kMsgTimeIntervalUpdated:
BroadcastToActivityViews(message);
break;
default:
BWindow::MessageReceived(message);
break;
}
}
bool
ActivityWindow::QuitRequested()
{
_SaveSettings();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
int32
ActivityWindow::ActivityViewCount() const
{
#ifdef __HAIKU__
return fLayout->View()->CountChildren();
#else
return 1;
#endif
}
ActivityView*
ActivityWindow::ActivityViewAt(int32 index) const
{
return dynamic_cast<ActivityView*>(fLayout->View()->ChildAt(index));
}
void
ActivityWindow::BroadcastToActivityViews(BMessage* message, BView* exceptToView)
{
BView* view;
for (int32 i = 0; (view = ActivityViewAt(i)) != NULL; i++) {
if (view != exceptToView)
PostMessage(message, view);
}
}
bigtime_t
ActivityWindow::RefreshInterval() const
{
ActivityView* view = ActivityViewAt(0);
if (view != 0)
return view->RefreshInterval();
return 100000;
}
status_t status_t
ActivityWindow::_OpenSettings(BFile& file, uint32 mode) ActivityWindow::_OpenSettings(BFile& file, uint32 mode)
{ {
@@ -200,27 +329,6 @@ ActivityWindow::_SaveSettings()
} }
int32
ActivityWindow::ActivityViewCount()
{
#ifdef __HAIKU__
return fLayout->View()->CountChildren();
#else
return 1;
#endif
}
void
ActivityWindow::_MessageDropped(BMessage* message)
{
entry_ref ref;
if (message->FindRef("refs", &ref) != B_OK) {
// TODO: If app, then launch it, and add ActivityView for this one?
}
}
void void
ActivityWindow::_AddDefaultView() ActivityWindow::_AddDefaultView()
{ {
@@ -250,57 +358,11 @@ ActivityWindow::_AddDefaultView()
void void
ActivityWindow::MessageReceived(BMessage* message) ActivityWindow::_MessageDropped(BMessage* message)
{ {
if (message->WasDropped()) { entry_ref ref;
_MessageDropped(message); if (message->FindRef("refs", &ref) != B_OK) {
return; // TODO: If app, then launch it, and add ActivityView for this one?
}
switch (message->what) {
case B_REFS_RECEIVED:
case B_SIMPLE_DATA:
_MessageDropped(message);
break;
case kMsgAddView:
{
#ifdef __HAIKU__
BView* firstView = fLayout->View()->ChildAt(0);
_AddDefaultView();
if (firstView != NULL)
ResizeBy(0, firstView->Bounds().Height() + fLayout->Spacing());
#endif
break;
}
case kMsgRemoveView:
{
#ifdef __HAIKU__
BView* view;
if (message->FindPointer("view", (void**)&view) != B_OK)
break;
view->RemoveSelf();
ResizeBy(0, -view->Bounds().Height() - fLayout->Spacing());
delete view;
#endif
break;
}
default:
BWindow::MessageReceived(message);
break;
} }
} }
bool
ActivityWindow::QuitRequested()
{
_SaveSettings();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
+9 -3
View File
@@ -1,11 +1,12 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef ACTIVITY_WINDOW_H #ifndef ACTIVITY_WINDOW_H
#define ACTIVITY_WINDOW_H #define ACTIVITY_WINDOW_H
#include <Messenger.h>
#include <Window.h> #include <Window.h>
class BFile; class BFile;
@@ -22,7 +23,12 @@ public:
virtual void MessageReceived(BMessage* message); virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested(); virtual bool QuitRequested();
int32 ActivityViewCount(); int32 ActivityViewCount() const;
ActivityView* ActivityViewAt(int32 index) const;
void BroadcastToActivityViews(BMessage* message,
BView* exceptToView = NULL);
bigtime_t RefreshInterval() const;
private: private:
status_t _OpenSettings(BFile& file, uint32 mode); status_t _OpenSettings(BFile& file, uint32 mode);
@@ -30,12 +36,12 @@ private:
status_t _SaveSettings(); status_t _SaveSettings();
void _AddDefaultView(); void _AddDefaultView();
void _UpdateRemoveItem();
void _MessageDropped(BMessage *message); void _MessageDropped(BMessage *message);
#ifdef __HAIKU__ #ifdef __HAIKU__
BGroupLayout* fLayout; BGroupLayout* fLayout;
#endif #endif
BMessenger fSettingsWindow;
}; };
static const uint32 kMsgRemoveView = 'rmvw'; static const uint32 kMsgRemoveView = 'rmvw';
+1
View File
@@ -10,6 +10,7 @@ Application ActivityMonitor :
ActivityView.cpp ActivityView.cpp
ActivityWindow.cpp ActivityWindow.cpp
DataSource.cpp DataSource.cpp
SettingsWindow.cpp
SystemInfo.cpp SystemInfo.cpp
SystemInfoHandler.cpp SystemInfoHandler.cpp
+146
View File
@@ -0,0 +1,146 @@
/*
* Copyright 2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "SettingsWindow.h"
#include <stdio.h>
#include <GridLayoutBuilder.h>
#include <GroupLayoutBuilder.h>
#include <Slider.h>
#include <String.h>
static const uint32 kMsgUpdateTimeInterval = 'upti';
static const bigtime_t kUpdateIntervals[] = { 50, 100, 250, 500, 1000, 2000 };
class IntervalSlider : public BSlider {
public:
IntervalSlider(const char* label, BMessage* message, uint32 levels)
: BSlider("intervalSlider", label, message, 0, levels - 1, B_HORIZONTAL)
{
BString min(_TextFor(0));
BString max(_TextFor(levels - 1));
SetLimitLabels(min.String(), max.String());
SetHashMarks(B_HASH_MARKS_BOTTOM);
SetHashMarkCount(levels);
if (message != NULL)
SetModificationMessage(new BMessage(*message));
}
void SetInterval(bigtime_t interval)
{
interval /= 1000;
// Find closest index
int32 bestDiff = LONG_MAX;
uint32 bestIndex = 0;
for (uint32 i = 0;
i < sizeof(kUpdateIntervals) / sizeof(kUpdateIntervals[0]);
i++) {
int32 diff = abs(kUpdateIntervals[i] - interval);
if (diff < bestDiff) {
bestDiff = diff;
bestIndex = i;
}
}
SetValue(bestIndex);
}
virtual const char* UpdateText() const
{
return _TextFor(Value());
}
private:
const char* _TextFor(uint32 level) const
{
if (level >= sizeof(kUpdateIntervals) / sizeof(kUpdateIntervals[0]))
return NULL;
bigtime_t interval = kUpdateIntervals[level];
if ((interval % 1000) == 0)
snprintf(fText, sizeof(fText), "%lld secs", interval / 1000);
else
snprintf(fText, sizeof(fText), "%lld msecs", interval);
return fText;
}
mutable char fText[64];
};
// #pragma mark -
SettingsWindow::SettingsWindow(ActivityWindow* target)
: BWindow(_RelativeTo(target), "Settings", B_FLOATING_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS),
fTarget(target)
{
SetLayout(new BGroupLayout(B_VERTICAL));
fIntervalSlider = new IntervalSlider("Update time interval:",
new BMessage(kMsgUpdateTimeInterval), 6);
fIntervalSlider->SetInterval(target->RefreshInterval());
// controls pane
AddChild(BGroupLayoutBuilder(B_VERTICAL)
.Add(fIntervalSlider)
.SetInsets(10, 10, 10, 10)
);
}
SettingsWindow::~SettingsWindow()
{
}
void
SettingsWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgUpdateTimeInterval:
{
int32 level = 0;
if (message->FindInt32("be:value", &level) != B_OK)
break;
BMessage update(kMsgTimeIntervalUpdated);
update.AddInt64("interval", kUpdateIntervals[level] * 1000LL);
fTarget.SendMessage(&update);
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
bool
SettingsWindow::QuitRequested()
{
return true;
}
BRect
SettingsWindow::_RelativeTo(BWindow* window)
{
BRect frame = window->Frame();
return BRect(frame.right - 150, frame.top + frame.Height() / 4,
frame.right + 200, frame.top + frame.Height() / 4 + 50);
}
+33
View File
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SETTINGS_WINDOW_H
#define SETTINGS_WINDOW_H
#include <Messenger.h>
#include "ActivityWindow.h"
class IntervalSlider;
class SettingsWindow : public BWindow {
public:
SettingsWindow(ActivityWindow* target);
virtual ~SettingsWindow();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
private:
BRect _RelativeTo(BWindow* window);
BMessenger fTarget;
IntervalSlider* fIntervalSlider;
};
static const uint32 kMsgTimeIntervalUpdated = 'tiup';
#endif // SETTINGS_WINDOW_H