From 1bb87bd0b16cfc690abe9a3a492ff8a755f1eced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 13 Mar 2009 20:19:10 +0000 Subject: [PATCH] * 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 --- src/apps/activitymonitor/ActivityView.cpp | 102 +++++++--- src/apps/activitymonitor/ActivityView.h | 7 + src/apps/activitymonitor/ActivityWindow.cpp | 206 +++++++++++++------- src/apps/activitymonitor/ActivityWindow.h | 12 +- src/apps/activitymonitor/Jamfile | 1 + src/apps/activitymonitor/SettingsWindow.cpp | 146 ++++++++++++++ src/apps/activitymonitor/SettingsWindow.h | 33 ++++ 7 files changed, 401 insertions(+), 106 deletions(-) create mode 100644 src/apps/activitymonitor/SettingsWindow.cpp create mode 100644 src/apps/activitymonitor/SettingsWindow.h diff --git a/src/apps/activitymonitor/ActivityView.cpp b/src/apps/activitymonitor/ActivityView.cpp index df1d7302e8..4dbde33ea0 100644 --- a/src/apps/activitymonitor/ActivityView.cpp +++ b/src/apps/activitymonitor/ActivityView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -24,6 +24,7 @@ #include "ActivityMonitor.h" #include "ActivityWindow.h" +#include "SettingsWindow.h" #include "SystemInfo.h" #include "SystemInfoHandler.h" @@ -92,10 +93,11 @@ private: }; #endif -const bigtime_t kInitialRefreshInterval = 500000LL; +const bigtime_t kInitialRefreshInterval = 250000LL; const uint32 kMsgToggleDataSource = 'tgds'; const uint32 kMsgToggleLegend = 'tglg'; +const uint32 kMsgUpdateResolution = 'ures'; extern const char* kSignature; @@ -627,7 +629,7 @@ ActivityView::AddDataSource(const DataSource* source, const BMessage* state) for (uint32 i = 0; i < count; i++) { DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL, - fRefreshInterval); + RefreshInterval()); if (values == NULL) return B_NO_MEMORY; @@ -874,21 +876,14 @@ ActivityView::MouseMoved(BPoint where, uint32 transit, if (!fZooming) return; - int32 previousResolution = fDrawResolution; - int32 shift = int32(where.x - fZoomPoint.x) / 25; + int32 resolution; if (shift > 0) - fDrawResolution = fOriginalResolution << shift; + resolution = fOriginalResolution << shift; else - fDrawResolution = fOriginalResolution >> -shift; + resolution = fOriginalResolution >> -shift; - if (fDrawResolution < 1) - fDrawResolution = 1; - if (fDrawResolution > 128) - fDrawResolution = 128; - - if (previousResolution != fDrawResolution) - Invalidate(); + _UpdateResolution(resolution); } @@ -939,6 +934,32 @@ ActivityView::MessageReceived(BMessage* message) ActivityMonitor::ShowAbout(); 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: { int32 index; @@ -971,17 +992,13 @@ ActivityView::MessageReceived(BMessage* message) || deltaY == 0.0f) break; + int32 resolution = fDrawResolution; if (deltaY > 0) - fDrawResolution *= 2; + resolution *= 2; else - fDrawResolution /= 2; + resolution /= 2; - if (fDrawResolution < 1) - fDrawResolution = 1; - if (fDrawResolution > 128) - fDrawResolution = 128; - - Invalidate(); + _UpdateResolution(resolution); break; } @@ -1139,7 +1156,7 @@ ActivityView::_DrawHistory() uint32 width = frame.IntegerWidth() - 10; uint32 steps = width / step; - bigtime_t timeStep = fRefreshInterval * resolution; + bigtime_t timeStep = RefreshInterval() * resolution; bigtime_t now = system_time(); // Draw scale @@ -1161,7 +1178,7 @@ ActivityView::_DrawHistory() // Draw values - view->SetPenSize(2); + view->SetPenSize(1.5); BAutolock _(fSourcesLock); for (uint32 i = fSources.CountItems(); i-- > 0;) { @@ -1182,12 +1199,12 @@ ActivityView::_DrawHistory() continue; int64 value = values->ValueAt(time); - if (timeStep > fRefreshInterval) { + if (timeStep > RefreshInterval()) { // TODO: always start with the same index, so that it always // uses the same values for computation (currently it jumps) uint32 count = 1; - for (bigtime_t offset = fRefreshInterval; offset < timeStep; - offset += fRefreshInterval) { + for (bigtime_t offset = RefreshInterval(); offset < timeStep; + offset += RefreshInterval()) { // TODO: handle int64 overflow correctly! value += values->ValueAt(time + offset); 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(Window()); + if (broadcast && window != NULL) { + BMessage update(kMsgUpdateResolution); + update.AddInt32("resolution", resolution); + window->BroadcastToActivityViews(&update, this); + } + + fDrawResolution = resolution; + Invalidate(); +} + + void ActivityView::Draw(BRect /*updateRect*/) { @@ -1270,19 +1310,19 @@ ActivityView::Draw(BRect /*updateRect*/) void ActivityView::_Refresh() { - bigtime_t lastTimeout = system_time() - fRefreshInterval; + bigtime_t lastTimeout = system_time() - RefreshInterval(); BMessenger target(this); while (true) { status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT, - lastTimeout + fRefreshInterval); + lastTimeout + RefreshInterval()); if (status == B_OK || status == B_BAD_SEM_ID) break; if (status == B_INTERRUPTED) continue; SystemInfo info(fSystemInfoHandler); - lastTimeout += fRefreshInterval; + lastTimeout += RefreshInterval(); fSourcesLock.Lock(); @@ -1297,7 +1337,7 @@ ActivityView::_Refresh() fSourcesLock.Unlock(); bigtime_t now = info.Time(); - if (fLastRefresh + fDrawInterval <= now) { + if (fLastRefresh + DrawInterval() <= now) { target.SendMessage(B_INVALIDATE); fLastRefresh = now; } diff --git a/src/apps/activitymonitor/ActivityView.h b/src/apps/activitymonitor/ActivityView.h index 240a9062ca..203d959236 100644 --- a/src/apps/activitymonitor/ActivityView.h +++ b/src/apps/activitymonitor/ActivityView.h @@ -74,6 +74,11 @@ public: status_t RemoveDataSource(const DataSource* source); void RemoveAllDataSources(); + bigtime_t RefreshInterval() const + { return atomic_get64((vint64*)&fRefreshInterval); } + bigtime_t DrawInterval() const + { return atomic_get64((vint64*)&fDrawInterval); } + protected: virtual void AttachedToWindow(); virtual void DetachedFromWindow(); @@ -108,6 +113,8 @@ private: float _PositionForValue(DataSource* source, DataHistory* values, int64 value); void _DrawHistory(); + void _UpdateResolution(int32 resolution, + bool broadcast = true); private: class HistoryLayoutItem; diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index 435be9428a..d7c58b06c7 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -23,9 +23,11 @@ #include "ActivityMonitor.h" #include "ActivityView.h" #include "DataSource.h" +#include "SettingsWindow.h" static const uint32 kMsgAddView = 'advw'; +static const uint32 kMsgShowSettings = 'shst'; ActivityWindow::ActivityWindow() @@ -125,6 +127,13 @@ ActivityWindow::ActivityWindow() menu->SetTargetForItems(this); item->SetTarget(be_app); 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(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 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 ActivityWindow::_AddDefaultView() { @@ -250,57 +358,11 @@ ActivityWindow::_AddDefaultView() void -ActivityWindow::MessageReceived(BMessage* message) +ActivityWindow::_MessageDropped(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; - } - - default: - BWindow::MessageReceived(message); - break; + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) { + // TODO: If app, then launch it, and add ActivityView for this one? } } - -bool -ActivityWindow::QuitRequested() -{ - _SaveSettings(); - be_app->PostMessage(B_QUIT_REQUESTED); - return true; -} diff --git a/src/apps/activitymonitor/ActivityWindow.h b/src/apps/activitymonitor/ActivityWindow.h index cccd7ac2c3..aa218aff50 100644 --- a/src/apps/activitymonitor/ActivityWindow.h +++ b/src/apps/activitymonitor/ActivityWindow.h @@ -1,11 +1,12 @@ /* - * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ #ifndef ACTIVITY_WINDOW_H #define ACTIVITY_WINDOW_H +#include #include class BFile; @@ -22,7 +23,12 @@ public: virtual void MessageReceived(BMessage* message); 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: status_t _OpenSettings(BFile& file, uint32 mode); @@ -30,12 +36,12 @@ private: status_t _SaveSettings(); void _AddDefaultView(); - void _UpdateRemoveItem(); void _MessageDropped(BMessage *message); #ifdef __HAIKU__ BGroupLayout* fLayout; #endif + BMessenger fSettingsWindow; }; static const uint32 kMsgRemoveView = 'rmvw'; diff --git a/src/apps/activitymonitor/Jamfile b/src/apps/activitymonitor/Jamfile index 8ba7fd498a..c9e045e9cb 100644 --- a/src/apps/activitymonitor/Jamfile +++ b/src/apps/activitymonitor/Jamfile @@ -10,6 +10,7 @@ Application ActivityMonitor : ActivityView.cpp ActivityWindow.cpp DataSource.cpp + SettingsWindow.cpp SystemInfo.cpp SystemInfoHandler.cpp diff --git a/src/apps/activitymonitor/SettingsWindow.cpp b/src/apps/activitymonitor/SettingsWindow.cpp new file mode 100644 index 0000000000..816e9f0ff0 --- /dev/null +++ b/src/apps/activitymonitor/SettingsWindow.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include "SettingsWindow.h" + +#include + +#include +#include +#include +#include + + +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); +} + diff --git a/src/apps/activitymonitor/SettingsWindow.h b/src/apps/activitymonitor/SettingsWindow.h new file mode 100644 index 0000000000..a057870ab9 --- /dev/null +++ b/src/apps/activitymonitor/SettingsWindow.h @@ -0,0 +1,33 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SETTINGS_WINDOW_H +#define SETTINGS_WINDOW_H + + +#include + +#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