diff --git a/src/apps/activitymonitor/ActivityView.cpp b/src/apps/activitymonitor/ActivityView.cpp index 531120757d..080bd39294 100644 --- a/src/apps/activitymonitor/ActivityView.cpp +++ b/src/apps/activitymonitor/ActivityView.cpp @@ -11,7 +11,7 @@ #include #ifdef __HAIKU__ -#include +# include #endif #include #include @@ -23,11 +23,26 @@ #include "ActivityMonitor.h" #include "ActivityWindow.h" -#include "DataSource.h" #include "SystemInfo.h" #include "SystemInfoHandler.h" +class Scale { +public: + Scale(scale_type type); + + int64 MinimumValue() const { return fMinimumValue; } + int64 MaximumValue() const { return fMaximumValue; } + + void Update(int64 value); + +private: + scale_type fType; + int64 fMinimumValue; + int64 fMaximumValue; + bool fInitialized; +}; + struct data_item { bigtime_t time; int64 value; @@ -85,13 +100,39 @@ const uint32 kMsgToggleLegend = 'tglg'; extern const char* kSignature; +Scale::Scale(scale_type type) + : + fType(type), + fMinimumValue(0), + fMaximumValue(0), + fInitialized(false) +{ +} + + +void +Scale::Update(int64 value) +{ + if (!fInitialized || fMinimumValue > value) + fMinimumValue = value; + if (!fInitialized || fMaximumValue > value) + fMaximumValue = value; + + fInitialized = true; +} + + +// #pragma mark - + + DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval) : fBuffer(10000), fMinimumValue(0), fMaximumValue(0), fRefreshInterval(interval), - fLastIndex(-1) + fLastIndex(-1), + fScale(NULL) { } @@ -108,6 +149,8 @@ DataHistory::AddValue(bigtime_t time, int64 value) fMaximumValue = value; if (fBuffer.IsEmpty() || fMinimumValue > value) fMinimumValue = value; + if (fScale != NULL) + fScale->Update(value); data_item item = {time, value}; fBuffer.AddItem(item); @@ -117,11 +160,28 @@ DataHistory::AddValue(bigtime_t time, int64 value) int64 DataHistory::ValueAt(bigtime_t time) { - // TODO: if the refresh rate changes, this computation won't work anymore! - int32 index = (time - Start()) / fRefreshInterval; - data_item* item = fBuffer.ItemAt(index); - if (item != NULL) - return item->value; + int32 left = 0; + int32 right = fBuffer.CountItems() - 1; + data_item* item = NULL; + + while (left <= right) { + int32 index = (left + right) / 2; + item = fBuffer.ItemAt(index); + + if (item->time > time) { + // search in left part + right = index - 1; + } else { + if (index + 1 >= fBuffer.CountItems() + || fBuffer.ItemAt(index + 1)->time > time) { + // found item + return item->value; + } + + // search in right part + left = index + 1; + } + } return 0; } @@ -130,6 +190,9 @@ DataHistory::ValueAt(bigtime_t time) int64 DataHistory::MaximumValue() const { + if (fScale != NULL) + return fScale->MaximumValue(); + return fMaximumValue; } @@ -137,6 +200,9 @@ DataHistory::MaximumValue() const int64 DataHistory::MinimumValue() const { + if (fScale != NULL) + return fScale->MinimumValue(); + return fMinimumValue; } @@ -168,6 +234,13 @@ DataHistory::SetRefreshInterval(bigtime_t interval) } +void +DataHistory::SetScale(Scale* scale) +{ + fScale = scale; +} + + // #pragma mark - @@ -378,6 +451,7 @@ ActivityView::_Init(const BMessage* settings) fDrawInterval = kInitialRefreshInterval * 2; fLastRefresh = 0; fDrawResolution = 1; + fZooming = false; fSystemInfoHandler = new SystemInfoHandler; @@ -385,11 +459,8 @@ ActivityView::_Init(const BMessage* settings) || settings->FindBool("show legend", &fShowLegend) != B_OK) fShowLegend = true; - if (settings == NULL) { - AddDataSource(new UsedMemoryDataSource()); - AddDataSource(new CachedMemoryDataSource()); + if (settings == NULL) return; - } ssize_t colorLength; rgb_color *color; @@ -466,6 +537,24 @@ ActivityView::SaveState(BMessage& state) const } +Scale* +ActivityView::_ScaleFor(scale_type type) +{ + if (type == kNoScale) + return NULL; + + std::map::iterator iterator = fScales.find(type); + if (iterator != fScales.end()) + return iterator->second; + + // add new scale + ::Scale* scale = new ::Scale(type); + fScales[type] = scale; + + return scale; +} + + #ifdef __HAIKU__ BLayoutItem* ActivityView::CreateHistoryLayoutItem() @@ -535,6 +624,8 @@ ActivityView::AddDataSource(const DataSource* source, const BMessage* state) return B_NO_MEMORY; } + values->SetScale(_ScaleFor(source->ScaleType())); + DataSource* copy; if (source->PerCPU()) copy = source->CopyForCPU(i); @@ -688,14 +779,16 @@ ActivityView::_OffscreenView() void ActivityView::MouseDown(BPoint where) { -#if 0 - int32 buttons = B_PRIMARY_MOUSE_BUTTON; - int32 clicks = 1; - if (Looper() != NULL && Looper()->CurrentMessage() != NULL) { + int32 buttons = B_SECONDARY_MOUSE_BUTTON; + if (Looper() != NULL && Looper()->CurrentMessage() != NULL) Looper()->CurrentMessage()->FindInt32("buttons", &buttons); - Looper()->CurrentMessage()->FindInt32("clicks", &clicks); + + if (buttons == B_PRIMARY_MOUSE_BUTTON) { + fZoomPoint = where; + fOriginalResolution = fDrawResolution; + fZooming = true; + return; } -#endif BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); menu->SetFont(be_plain_font); @@ -748,10 +841,35 @@ ActivityView::MouseDown(BPoint where) } +void +ActivityView::MouseUp(BPoint where) +{ + fZooming = false; +} + + void ActivityView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) { + if (!fZooming) + return; + + int32 previousResolution = fDrawResolution; + + int32 shift = int32(where.x - fZoomPoint.x) / 25; + if (shift > 0) + fDrawResolution = fOriginalResolution << shift; + else + fDrawResolution = fOriginalResolution >> -shift; + + if (fDrawResolution < 1) + fDrawResolution = 1; + if (fDrawResolution > 128) + fDrawResolution = 128; + + if (previousResolution != fDrawResolution) + Invalidate(); } diff --git a/src/apps/activitymonitor/ActivityView.h b/src/apps/activitymonitor/ActivityView.h index c18e42cc28..2774da49ca 100644 --- a/src/apps/activitymonitor/ActivityView.h +++ b/src/apps/activitymonitor/ActivityView.h @@ -6,14 +6,18 @@ #define ACTIVITY_VIEW_H +#include + #include #include #include "CircularBuffer.h" +#include "DataSource.h" class BBitmap; class BMessageRunner; class DataSource; +class Scale; class SystemInfoHandler; struct data_item; @@ -32,6 +36,7 @@ public: bigtime_t End() const; void SetRefreshInterval(bigtime_t interval); + void SetScale(Scale* scale); private: CircularBuffer fBuffer; @@ -39,6 +44,7 @@ private: int64 fMaximumValue; bigtime_t fRefreshInterval; int32 fLastIndex; + Scale* fScale; }; @@ -77,6 +83,7 @@ protected: virtual void FrameResized(float width, float height); virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); virtual void MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage); @@ -86,6 +93,7 @@ protected: private: void _Init(const BMessage* settings); + ::Scale* _ScaleFor(scale_type type); void _Refresh(); void _UpdateOffscreenBitmap(); BView* _OffscreenView(); @@ -99,6 +107,7 @@ private: DataHistory* values, int64 value); void _DrawHistory(); +private: class HistoryLayoutItem; class LegendLayoutItem; @@ -120,7 +129,11 @@ private: bigtime_t fDrawInterval; int32 fDrawResolution; bool fShowLegend; + bool fZooming; + BPoint fZoomPoint; + int32 fOriginalResolution; SystemInfoHandler* fSystemInfoHandler; + std::map fScales; }; #endif // ACTIVITY_VIEW_H diff --git a/src/apps/activitymonitor/ActivityWindow.cpp b/src/apps/activitymonitor/ActivityWindow.cpp index 207d57e14c..435be9428a 100644 --- a/src/apps/activitymonitor/ActivityWindow.cpp +++ b/src/apps/activitymonitor/ActivityWindow.cpp @@ -22,13 +22,14 @@ #include "ActivityMonitor.h" #include "ActivityView.h" +#include "DataSource.h" static const uint32 kMsgAddView = 'advw'; ActivityWindow::ActivityWindow() - : BWindow(BRect(100, 100, 500, 250), "ActivityMonitor", B_TITLED_WINDOW, + : BWindow(BRect(100, 100, 500, 350), "ActivityMonitor", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE) { BMessage settings; @@ -68,12 +69,11 @@ ActivityWindow::ActivityWindow() count++; } if (count == 0) { - ActivityView* view = new ActivityView("ActivityMonitor", NULL); - fLayout->AddItem(view->CreateHistoryLayoutItem()); - fLayout->AddItem(view->CreateLegendLayoutItem()); + // Add default views (memory & CPU usage) + _AddDefaultView(); + _AddDefaultView(); } - -#else +#else // !__HAIKU__ BView *layout = new BView(Bounds(), "topmost", B_FOLLOW_NONE, 0); AddChild(layout); @@ -221,6 +221,34 @@ ActivityWindow::_MessageDropped(BMessage* message) } +void +ActivityWindow::_AddDefaultView() +{ + ActivityView* view = new ActivityView("ActivityMonitor", NULL); + + switch (ActivityViewCount()) { + case 0: + // The first view defaults to memory usage + view->AddDataSource(new UsedMemoryDataSource()); + view->AddDataSource(new CachedMemoryDataSource()); + break; + case 2: + // The third view defaults to network in/out + view->AddDataSource(new NetworkUsageDataSource(true)); + view->AddDataSource(new NetworkUsageDataSource(false)); + break; + case 1: + default: + // Everything beyond that defaults to a CPU usage view + view->AddDataSource(new CPUUsageDataSource()); + break; + } + + fLayout->AddItem(view->CreateHistoryLayoutItem()); + fLayout->AddItem(view->CreateLegendLayoutItem()); +} + + void ActivityWindow::MessageReceived(BMessage* message) { @@ -240,9 +268,7 @@ ActivityWindow::MessageReceived(BMessage* message) #ifdef __HAIKU__ BView* firstView = fLayout->View()->ChildAt(0); - ActivityView* view = new ActivityView("ActivityMonitor", NULL); - fLayout->AddItem(view->CreateHistoryLayoutItem()); - fLayout->AddItem(view->CreateLegendLayoutItem()); + _AddDefaultView(); if (firstView != NULL) ResizeBy(0, firstView->Bounds().Height() + fLayout->Spacing()); diff --git a/src/apps/activitymonitor/ActivityWindow.h b/src/apps/activitymonitor/ActivityWindow.h index 425c2c8dab..cccd7ac2c3 100644 --- a/src/apps/activitymonitor/ActivityWindow.h +++ b/src/apps/activitymonitor/ActivityWindow.h @@ -29,6 +29,7 @@ private: status_t _LoadSettings(BMessage& settings); status_t _SaveSettings(); + void _AddDefaultView(); void _UpdateRemoveItem(); void _MessageDropped(BMessage *message); diff --git a/src/apps/activitymonitor/DataSource.cpp b/src/apps/activitymonitor/DataSource.cpp index f693747be4..8e9b660d03 100644 --- a/src/apps/activitymonitor/DataSource.cpp +++ b/src/apps/activitymonitor/DataSource.cpp @@ -176,6 +176,13 @@ DataSource::AdaptiveScale() const } +scale_type +DataSource::ScaleType() const +{ + return kNoScale; +} + + int32 DataSource::CPU() const { diff --git a/src/apps/activitymonitor/DataSource.h b/src/apps/activitymonitor/DataSource.h index 39e4435d66..777032f131 100644 --- a/src/apps/activitymonitor/DataSource.h +++ b/src/apps/activitymonitor/DataSource.h @@ -12,6 +12,11 @@ class SystemInfo; +enum scale_type { + kNoScale, + kBytePerSecondScale, +}; + class DataSource { public: DataSource(int64 initialMin, int64 initialMax); @@ -38,6 +43,7 @@ public: virtual const char* Unit() const; virtual rgb_color Color() const; virtual bool AdaptiveScale() const; + virtual scale_type ScaleType() const; virtual int32 CPU() const; virtual bool PerCPU() const; virtual bool MultiCPUOnly() const;