118d3e65eSAxel Dörfler /* 21bb87bd0SAxel Dörfler * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de. 318d3e65eSAxel Dörfler * Distributed under the terms of the MIT License. 418d3e65eSAxel Dörfler */ 518d3e65eSAxel Dörfler 618d3e65eSAxel Dörfler 718d3e65eSAxel Dörfler #include "ActivityView.h" 818d3e65eSAxel Dörfler 918d3e65eSAxel Dörfler #include <new> 1018d3e65eSAxel Dörfler #include <stdio.h> 1118d3e65eSAxel Dörfler #include <stdlib.h> 12cce423c2SRene Gollent #include <vector> 1318d3e65eSAxel Dörfler 14dc1ffc79SFrançois Revol #ifdef __HAIKU__ 155b0cd987SJohn Scipione # include <AboutWindow.h> 16065e8de0SAxel Dörfler # include <AbstractLayoutItem.h> 17ed1b2753SStephan Aßmus # include <ControlLook.h> 18dc1ffc79SFrançois Revol #endif 1918d3e65eSAxel Dörfler #include <Application.h> 20d4216445SAxel Dörfler #include <Autolock.h> 2118d3e65eSAxel Dörfler #include <Bitmap.h> 224840a72fSPhilippe Houdoin #include <Catalog.h> 2318d3e65eSAxel Dörfler #include <Dragger.h> 2418d3e65eSAxel Dörfler #include <MenuItem.h> 2518d3e65eSAxel Dörfler #include <MessageRunner.h> 2618d3e65eSAxel Dörfler #include <PopUpMenu.h> 278e26f387SAxel Dörfler #include <Shape.h> 2818d3e65eSAxel Dörfler #include <String.h> 2918d3e65eSAxel Dörfler 3018d3e65eSAxel Dörfler #include "ActivityMonitor.h" 313f315b26SAxel Dörfler #include "ActivityWindow.h" 321bb87bd0SAxel Dörfler #include "SettingsWindow.h" 3318d3e65eSAxel Dörfler #include "SystemInfo.h" 3474158bb4SFrançois Revol #include "SystemInfoHandler.h" 3518d3e65eSAxel Dörfler 36546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT 37546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "ActivityView" 3818d3e65eSAxel Dörfler 398e26f387SAxel Dörfler template<typename ObjectType> 408e26f387SAxel Dörfler class ListAddDeleter { 418e26f387SAxel Dörfler public: 428e26f387SAxel Dörfler ListAddDeleter(BObjectList<ObjectType>& list, ObjectType* object, 438e26f387SAxel Dörfler int32 spot) 448e26f387SAxel Dörfler : 458e26f387SAxel Dörfler fList(list), 468e26f387SAxel Dörfler fObject(object) 478e26f387SAxel Dörfler { 488e26f387SAxel Dörfler if (fObject != NULL && !fList.AddItem(fObject, spot)) { 498e26f387SAxel Dörfler delete fObject; 508e26f387SAxel Dörfler fObject = NULL; 518e26f387SAxel Dörfler } 528e26f387SAxel Dörfler } 538e26f387SAxel Dörfler 548e26f387SAxel Dörfler ~ListAddDeleter() 558e26f387SAxel Dörfler { 568e26f387SAxel Dörfler if (fObject != NULL) { 578e26f387SAxel Dörfler fList.RemoveItem(fObject); 588e26f387SAxel Dörfler delete fObject; 598e26f387SAxel Dörfler } 608e26f387SAxel Dörfler } 618e26f387SAxel Dörfler 628e26f387SAxel Dörfler bool Failed() const 638e26f387SAxel Dörfler { 648e26f387SAxel Dörfler return fObject == NULL; 658e26f387SAxel Dörfler } 668e26f387SAxel Dörfler 678e26f387SAxel Dörfler void Detach() 688e26f387SAxel Dörfler { 698e26f387SAxel Dörfler fObject = NULL; 708e26f387SAxel Dörfler } 718e26f387SAxel Dörfler 728e26f387SAxel Dörfler private: 738e26f387SAxel Dörfler BObjectList<ObjectType>& fList; 748e26f387SAxel Dörfler ObjectType* fObject; 758e26f387SAxel Dörfler }; 768e26f387SAxel Dörfler 778e26f387SAxel Dörfler 788e26f387SAxel Dörfler /*! This class manages the scale of a history with a dynamic scale. 798e26f387SAxel Dörfler Every history value will be input via Update(), and the minimum/maximum 808e26f387SAxel Dörfler is computed from that. 818e26f387SAxel Dörfler */ 8251591198SAxel Dörfler class Scale { 8351591198SAxel Dörfler public: 8451591198SAxel Dörfler Scale(scale_type type); 8551591198SAxel Dörfler 8651591198SAxel Dörfler int64 MinimumValue() const { return fMinimumValue; } 8751591198SAxel Dörfler int64 MaximumValue() const { return fMaximumValue; } 8851591198SAxel Dörfler 8951591198SAxel Dörfler void Update(int64 value); 9051591198SAxel Dörfler 9151591198SAxel Dörfler private: 9251591198SAxel Dörfler scale_type fType; 9351591198SAxel Dörfler int64 fMinimumValue; 9451591198SAxel Dörfler int64 fMaximumValue; 9551591198SAxel Dörfler bool fInitialized; 9651591198SAxel Dörfler }; 9751591198SAxel Dörfler 988e26f387SAxel Dörfler /*! Stores the interpolated on screen view values. This is done so that the 998e26f387SAxel Dörfler interpolation is fixed, and does not change when being scrolled. 1008e26f387SAxel Dörfler 1018e26f387SAxel Dörfler We could also just do this by making sure we always ask for the same 1028e26f387SAxel Dörfler interval only, but this way we also save the interpolation. 1038e26f387SAxel Dörfler */ 1048e26f387SAxel Dörfler class ViewHistory { 1058e26f387SAxel Dörfler public: 1068e26f387SAxel Dörfler ViewHistory(); 1078e26f387SAxel Dörfler 1088e26f387SAxel Dörfler int64 ValueAt(int32 x); 1098e26f387SAxel Dörfler 1108e26f387SAxel Dörfler int32 Start() const 1118e26f387SAxel Dörfler { return fValues.Size() 1128e26f387SAxel Dörfler - fValues.CountItems(); } 1138e26f387SAxel Dörfler 1148e26f387SAxel Dörfler void Update(DataHistory* history, int32 width, 1158e26f387SAxel Dörfler int32 resolution, bigtime_t toTime, 1168e26f387SAxel Dörfler bigtime_t step, bigtime_t refresh); 1178e26f387SAxel Dörfler 1188e26f387SAxel Dörfler private: 1198e26f387SAxel Dörfler CircularBuffer<int64> fValues; 1208e26f387SAxel Dörfler int32 fResolution; 1218e26f387SAxel Dörfler bigtime_t fRefresh; 1228e26f387SAxel Dörfler bigtime_t fLastTime; 1238e26f387SAxel Dörfler }; 1248e26f387SAxel Dörfler 12518d3e65eSAxel Dörfler struct data_item { 12618d3e65eSAxel Dörfler bigtime_t time; 12718d3e65eSAxel Dörfler int64 value; 12818d3e65eSAxel Dörfler }; 12918d3e65eSAxel Dörfler 130dc1ffc79SFrançois Revol #ifdef __HAIKU__ 131065e8de0SAxel Dörfler class ActivityView::HistoryLayoutItem : public BAbstractLayoutItem { 132065e8de0SAxel Dörfler public: 133065e8de0SAxel Dörfler HistoryLayoutItem(ActivityView* parent); 134065e8de0SAxel Dörfler 135065e8de0SAxel Dörfler virtual bool IsVisible(); 136065e8de0SAxel Dörfler virtual void SetVisible(bool visible); 137065e8de0SAxel Dörfler 138065e8de0SAxel Dörfler virtual BRect Frame(); 139065e8de0SAxel Dörfler virtual void SetFrame(BRect frame); 140065e8de0SAxel Dörfler 141065e8de0SAxel Dörfler virtual BView* View(); 142065e8de0SAxel Dörfler 143065e8de0SAxel Dörfler virtual BSize BasePreferredSize(); 144065e8de0SAxel Dörfler 145065e8de0SAxel Dörfler private: 146065e8de0SAxel Dörfler ActivityView* fParent; 147065e8de0SAxel Dörfler BRect fFrame; 148065e8de0SAxel Dörfler }; 149065e8de0SAxel Dörfler 150065e8de0SAxel Dörfler class ActivityView::LegendLayoutItem : public BAbstractLayoutItem { 151065e8de0SAxel Dörfler public: 152065e8de0SAxel Dörfler LegendLayoutItem(ActivityView* parent); 153065e8de0SAxel Dörfler 154065e8de0SAxel Dörfler virtual bool IsVisible(); 155065e8de0SAxel Dörfler virtual void SetVisible(bool visible); 156065e8de0SAxel Dörfler 157065e8de0SAxel Dörfler virtual BRect Frame(); 158065e8de0SAxel Dörfler virtual void SetFrame(BRect frame); 159065e8de0SAxel Dörfler 160065e8de0SAxel Dörfler virtual BView* View(); 161065e8de0SAxel Dörfler 162065e8de0SAxel Dörfler virtual BSize BaseMinSize(); 163065e8de0SAxel Dörfler virtual BSize BaseMaxSize(); 164065e8de0SAxel Dörfler virtual BSize BasePreferredSize(); 165065e8de0SAxel Dörfler virtual BAlignment BaseAlignment(); 166065e8de0SAxel Dörfler 167065e8de0SAxel Dörfler private: 168065e8de0SAxel Dörfler ActivityView* fParent; 169065e8de0SAxel Dörfler BRect fFrame; 170065e8de0SAxel Dörfler }; 171dc1ffc79SFrançois Revol #endif 172065e8de0SAxel Dörfler 1731bb87bd0SAxel Dörfler const bigtime_t kInitialRefreshInterval = 250000LL; 17418d3e65eSAxel Dörfler 17518d3e65eSAxel Dörfler const uint32 kMsgToggleDataSource = 'tgds'; 1763a4a2141SAxel Dörfler const uint32 kMsgToggleLegend = 'tglg'; 1771bb87bd0SAxel Dörfler const uint32 kMsgUpdateResolution = 'ures'; 17818d3e65eSAxel Dörfler 1795b0cd987SJohn Scipione extern const char* kAppName; 18018d3e65eSAxel Dörfler extern const char* kSignature; 18118d3e65eSAxel Dörfler 18218d3e65eSAxel Dörfler 18351591198SAxel Dörfler Scale::Scale(scale_type type) 18451591198SAxel Dörfler : 18551591198SAxel Dörfler fType(type), 18651591198SAxel Dörfler fMinimumValue(0), 18751591198SAxel Dörfler fMaximumValue(0), 18851591198SAxel Dörfler fInitialized(false) 18951591198SAxel Dörfler { 19051591198SAxel Dörfler } 19151591198SAxel Dörfler 19251591198SAxel Dörfler 19351591198SAxel Dörfler void 19451591198SAxel Dörfler Scale::Update(int64 value) 19551591198SAxel Dörfler { 19651591198SAxel Dörfler if (!fInitialized || fMinimumValue > value) 19751591198SAxel Dörfler fMinimumValue = value; 198230e3259SAxel Dörfler if (!fInitialized || fMaximumValue < value) 19951591198SAxel Dörfler fMaximumValue = value; 20051591198SAxel Dörfler 20151591198SAxel Dörfler fInitialized = true; 20251591198SAxel Dörfler } 20351591198SAxel Dörfler 20451591198SAxel Dörfler 20551591198SAxel Dörfler // #pragma mark - 20651591198SAxel Dörfler 20751591198SAxel Dörfler 2088e26f387SAxel Dörfler ViewHistory::ViewHistory() 2098e26f387SAxel Dörfler : 2108e26f387SAxel Dörfler fValues(1), 2118e26f387SAxel Dörfler fResolution(-1), 2128e26f387SAxel Dörfler fRefresh(-1), 2138e26f387SAxel Dörfler fLastTime(0) 2148e26f387SAxel Dörfler { 2158e26f387SAxel Dörfler } 2168e26f387SAxel Dörfler 2178e26f387SAxel Dörfler 2188e26f387SAxel Dörfler int64 2198e26f387SAxel Dörfler ViewHistory::ValueAt(int32 x) 2208e26f387SAxel Dörfler { 2218e26f387SAxel Dörfler int64* value = fValues.ItemAt(x - Start()); 2228e26f387SAxel Dörfler if (value != NULL) 2238e26f387SAxel Dörfler return *value; 2248e26f387SAxel Dörfler 2258e26f387SAxel Dörfler return 0; 2268e26f387SAxel Dörfler } 2278e26f387SAxel Dörfler 2288e26f387SAxel Dörfler 2298e26f387SAxel Dörfler void 2308e26f387SAxel Dörfler ViewHistory::Update(DataHistory* history, int32 width, int32 resolution, 2318e26f387SAxel Dörfler bigtime_t toTime, bigtime_t step, bigtime_t refresh) 2328e26f387SAxel Dörfler { 2332c604c0dSAxel Dörfler if (width > 16384) { 2342c604c0dSAxel Dörfler // ignore this - it seems the view hasn't been layouted yet 2352c604c0dSAxel Dörfler return; 2362c604c0dSAxel Dörfler } 2372c604c0dSAxel Dörfler 2388e26f387SAxel Dörfler // Check if we need to invalidate the existing values 2398e26f387SAxel Dörfler if ((int32)fValues.Size() != width 2408e26f387SAxel Dörfler || fResolution != resolution 2418e26f387SAxel Dörfler || fRefresh != refresh) { 2428e26f387SAxel Dörfler fValues.SetSize(width); 2438e26f387SAxel Dörfler fResolution = resolution; 2448e26f387SAxel Dörfler fRefresh = refresh; 2457d33b63dSAxel Dörfler fLastTime = 0; 2468e26f387SAxel Dörfler } 2478e26f387SAxel Dörfler 2488e26f387SAxel Dörfler // Compute how many new values we need to retrieve 2498e26f387SAxel Dörfler if (fLastTime < history->Start()) 2508e26f387SAxel Dörfler fLastTime = history->Start(); 2517d33b63dSAxel Dörfler if (fLastTime > history->End()) 2527d33b63dSAxel Dörfler return; 2538e26f387SAxel Dörfler 2548e26f387SAxel Dörfler int32 updateWidth = int32((toTime - fLastTime) / step); 2558e26f387SAxel Dörfler if (updateWidth < 1) 2568e26f387SAxel Dörfler return; 2578e26f387SAxel Dörfler 2588e26f387SAxel Dörfler if (updateWidth > (int32)fValues.Size()) { 2598e26f387SAxel Dörfler updateWidth = fValues.Size(); 2608e26f387SAxel Dörfler fLastTime = toTime - updateWidth * step; 2618e26f387SAxel Dörfler } 2628e26f387SAxel Dörfler 2638e26f387SAxel Dörfler for (int32 i = 0; i < updateWidth; i++) { 2648e26f387SAxel Dörfler int64 value = history->ValueAt(fLastTime += step); 2658e26f387SAxel Dörfler 2668e26f387SAxel Dörfler if (step > refresh) { 2678e26f387SAxel Dörfler uint32 count = 1; 2688e26f387SAxel Dörfler for (bigtime_t offset = refresh; offset < step; offset += refresh) { 2698e26f387SAxel Dörfler // TODO: handle int64 overflow correctly! 2708e26f387SAxel Dörfler value += history->ValueAt(fLastTime + offset); 2718e26f387SAxel Dörfler count++; 2728e26f387SAxel Dörfler } 2738e26f387SAxel Dörfler value /= count; 2748e26f387SAxel Dörfler } 2758e26f387SAxel Dörfler 2768e26f387SAxel Dörfler fValues.AddItem(value); 2778e26f387SAxel Dörfler } 2788e26f387SAxel Dörfler } 2798e26f387SAxel Dörfler 2808e26f387SAxel Dörfler 2818e26f387SAxel Dörfler // #pragma mark - 2828e26f387SAxel Dörfler 2838e26f387SAxel Dörfler 28418d3e65eSAxel Dörfler DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval) 28518d3e65eSAxel Dörfler : 28618d3e65eSAxel Dörfler fBuffer(10000), 28718d3e65eSAxel Dörfler fMinimumValue(0), 28818d3e65eSAxel Dörfler fMaximumValue(0), 28918d3e65eSAxel Dörfler fRefreshInterval(interval), 29051591198SAxel Dörfler fLastIndex(-1), 29151591198SAxel Dörfler fScale(NULL) 29218d3e65eSAxel Dörfler { 29318d3e65eSAxel Dörfler } 29418d3e65eSAxel Dörfler 29518d3e65eSAxel Dörfler 29618d3e65eSAxel Dörfler DataHistory::~DataHistory() 29718d3e65eSAxel Dörfler { 29818d3e65eSAxel Dörfler } 29918d3e65eSAxel Dörfler 30018d3e65eSAxel Dörfler 30118d3e65eSAxel Dörfler void 30218d3e65eSAxel Dörfler DataHistory::AddValue(bigtime_t time, int64 value) 30318d3e65eSAxel Dörfler { 30418d3e65eSAxel Dörfler if (fBuffer.IsEmpty() || fMaximumValue < value) 30518d3e65eSAxel Dörfler fMaximumValue = value; 30618d3e65eSAxel Dörfler if (fBuffer.IsEmpty() || fMinimumValue > value) 30718d3e65eSAxel Dörfler fMinimumValue = value; 30851591198SAxel Dörfler if (fScale != NULL) 30951591198SAxel Dörfler fScale->Update(value); 31018d3e65eSAxel Dörfler 31118d3e65eSAxel Dörfler data_item item = {time, value}; 31218d3e65eSAxel Dörfler fBuffer.AddItem(item); 31318d3e65eSAxel Dörfler } 31418d3e65eSAxel Dörfler 31518d3e65eSAxel Dörfler 31618d3e65eSAxel Dörfler int64 31718d3e65eSAxel Dörfler DataHistory::ValueAt(bigtime_t time) 31818d3e65eSAxel Dörfler { 31951591198SAxel Dörfler int32 left = 0; 32051591198SAxel Dörfler int32 right = fBuffer.CountItems() - 1; 32151591198SAxel Dörfler data_item* item = NULL; 32251591198SAxel Dörfler 32351591198SAxel Dörfler while (left <= right) { 32451591198SAxel Dörfler int32 index = (left + right) / 2; 32551591198SAxel Dörfler item = fBuffer.ItemAt(index); 32651591198SAxel Dörfler 32751591198SAxel Dörfler if (item->time > time) { 32851591198SAxel Dörfler // search in left part 32951591198SAxel Dörfler right = index - 1; 33051591198SAxel Dörfler } else { 33184e23a5dSAxel Dörfler data_item* nextItem = fBuffer.ItemAt(index + 1); 33284e23a5dSAxel Dörfler if (nextItem == NULL) 33384e23a5dSAxel Dörfler return item->value; 33484e23a5dSAxel Dörfler if (nextItem->time > time) { 33551591198SAxel Dörfler // found item 33684e23a5dSAxel Dörfler int64 value = item->value; 33784e23a5dSAxel Dörfler value += int64(double(nextItem->value - value) 33884e23a5dSAxel Dörfler / (nextItem->time - item->time) * (time - item->time)); 3398e26f387SAxel Dörfler return value; 34051591198SAxel Dörfler } 34151591198SAxel Dörfler 34251591198SAxel Dörfler // search in right part 34351591198SAxel Dörfler left = index + 1; 34451591198SAxel Dörfler } 34551591198SAxel Dörfler } 34618d3e65eSAxel Dörfler 34718d3e65eSAxel Dörfler return 0; 34818d3e65eSAxel Dörfler } 34918d3e65eSAxel Dörfler 35018d3e65eSAxel Dörfler 35118d3e65eSAxel Dörfler int64 35218d3e65eSAxel Dörfler DataHistory::MaximumValue() const 35318d3e65eSAxel Dörfler { 35451591198SAxel Dörfler if (fScale != NULL) 35551591198SAxel Dörfler return fScale->MaximumValue(); 35651591198SAxel Dörfler 35718d3e65eSAxel Dörfler return fMaximumValue; 35818d3e65eSAxel Dörfler } 35918d3e65eSAxel Dörfler 36018d3e65eSAxel Dörfler 36118d3e65eSAxel Dörfler int64 36218d3e65eSAxel Dörfler DataHistory::MinimumValue() const 36318d3e65eSAxel Dörfler { 36451591198SAxel Dörfler if (fScale != NULL) 36551591198SAxel Dörfler return fScale->MinimumValue(); 36651591198SAxel Dörfler 36718d3e65eSAxel Dörfler return fMinimumValue; 36818d3e65eSAxel Dörfler } 36918d3e65eSAxel Dörfler 37018d3e65eSAxel Dörfler 37118d3e65eSAxel Dörfler bigtime_t 37218d3e65eSAxel Dörfler DataHistory::Start() const 37318d3e65eSAxel Dörfler { 37418d3e65eSAxel Dörfler if (fBuffer.CountItems() == 0) 37518d3e65eSAxel Dörfler return 0; 37618d3e65eSAxel Dörfler 37718d3e65eSAxel Dörfler return fBuffer.ItemAt(0)->time; 37818d3e65eSAxel Dörfler } 37918d3e65eSAxel Dörfler 38018d3e65eSAxel Dörfler 38118d3e65eSAxel Dörfler bigtime_t 38218d3e65eSAxel Dörfler DataHistory::End() const 38318d3e65eSAxel Dörfler { 38418d3e65eSAxel Dörfler if (fBuffer.CountItems() == 0) 38518d3e65eSAxel Dörfler return 0; 38618d3e65eSAxel Dörfler 38718d3e65eSAxel Dörfler return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time; 38818d3e65eSAxel Dörfler } 38918d3e65eSAxel Dörfler 39018d3e65eSAxel Dörfler 39118d3e65eSAxel Dörfler void 39218d3e65eSAxel Dörfler DataHistory::SetRefreshInterval(bigtime_t interval) 39318d3e65eSAxel Dörfler { 39418d3e65eSAxel Dörfler // TODO: adjust buffer size 39518d3e65eSAxel Dörfler } 39618d3e65eSAxel Dörfler 39718d3e65eSAxel Dörfler 39851591198SAxel Dörfler void 39951591198SAxel Dörfler DataHistory::SetScale(Scale* scale) 40051591198SAxel Dörfler { 40151591198SAxel Dörfler fScale = scale; 40251591198SAxel Dörfler } 40351591198SAxel Dörfler 40451591198SAxel Dörfler 40518d3e65eSAxel Dörfler // #pragma mark - 40618d3e65eSAxel Dörfler 40718d3e65eSAxel Dörfler 408dc1ffc79SFrançois Revol #ifdef __HAIKU__ 409065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::HistoryLayoutItem(ActivityView* parent) 410065e8de0SAxel Dörfler : 411065e8de0SAxel Dörfler fParent(parent), 412065e8de0SAxel Dörfler fFrame() 413065e8de0SAxel Dörfler { 414065e8de0SAxel Dörfler } 415065e8de0SAxel Dörfler 416065e8de0SAxel Dörfler 417065e8de0SAxel Dörfler bool 418065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::IsVisible() 419065e8de0SAxel Dörfler { 420065e8de0SAxel Dörfler return !fParent->IsHidden(fParent); 421065e8de0SAxel Dörfler } 422065e8de0SAxel Dörfler 423065e8de0SAxel Dörfler 424065e8de0SAxel Dörfler void 425065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetVisible(bool visible) 426065e8de0SAxel Dörfler { 427065e8de0SAxel Dörfler // not allowed 428065e8de0SAxel Dörfler } 429065e8de0SAxel Dörfler 430065e8de0SAxel Dörfler 431065e8de0SAxel Dörfler BRect 432065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::Frame() 433065e8de0SAxel Dörfler { 434065e8de0SAxel Dörfler return fFrame; 435065e8de0SAxel Dörfler } 436065e8de0SAxel Dörfler 437065e8de0SAxel Dörfler 438065e8de0SAxel Dörfler void 439065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetFrame(BRect frame) 440065e8de0SAxel Dörfler { 441065e8de0SAxel Dörfler fFrame = frame; 442065e8de0SAxel Dörfler fParent->_UpdateFrame(); 443065e8de0SAxel Dörfler } 444065e8de0SAxel Dörfler 445065e8de0SAxel Dörfler 446065e8de0SAxel Dörfler BView* 447065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::View() 448065e8de0SAxel Dörfler { 449065e8de0SAxel Dörfler return fParent; 450065e8de0SAxel Dörfler } 451065e8de0SAxel Dörfler 452065e8de0SAxel Dörfler 453065e8de0SAxel Dörfler BSize 454065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::BasePreferredSize() 455065e8de0SAxel Dörfler { 456065e8de0SAxel Dörfler BSize size(BaseMaxSize()); 457065e8de0SAxel Dörfler return size; 458065e8de0SAxel Dörfler } 459065e8de0SAxel Dörfler 460065e8de0SAxel Dörfler 461065e8de0SAxel Dörfler // #pragma mark - 462065e8de0SAxel Dörfler 463065e8de0SAxel Dörfler 464065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::LegendLayoutItem(ActivityView* parent) 465065e8de0SAxel Dörfler : 466065e8de0SAxel Dörfler fParent(parent), 467065e8de0SAxel Dörfler fFrame() 468065e8de0SAxel Dörfler { 469065e8de0SAxel Dörfler } 470065e8de0SAxel Dörfler 471065e8de0SAxel Dörfler 472065e8de0SAxel Dörfler bool 473065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::IsVisible() 474065e8de0SAxel Dörfler { 475065e8de0SAxel Dörfler return !fParent->IsHidden(fParent); 476065e8de0SAxel Dörfler } 477065e8de0SAxel Dörfler 478065e8de0SAxel Dörfler 479065e8de0SAxel Dörfler void 480065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetVisible(bool visible) 481065e8de0SAxel Dörfler { 482065e8de0SAxel Dörfler // not allowed 483065e8de0SAxel Dörfler } 484065e8de0SAxel Dörfler 485065e8de0SAxel Dörfler 486065e8de0SAxel Dörfler BRect 487065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::Frame() 488065e8de0SAxel Dörfler { 489065e8de0SAxel Dörfler return fFrame; 490065e8de0SAxel Dörfler } 491065e8de0SAxel Dörfler 492065e8de0SAxel Dörfler 493065e8de0SAxel Dörfler void 494065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetFrame(BRect frame) 495065e8de0SAxel Dörfler { 496065e8de0SAxel Dörfler fFrame = frame; 497065e8de0SAxel Dörfler fParent->_UpdateFrame(); 498065e8de0SAxel Dörfler } 499065e8de0SAxel Dörfler 500065e8de0SAxel Dörfler 501065e8de0SAxel Dörfler BView* 502065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::View() 503065e8de0SAxel Dörfler { 504065e8de0SAxel Dörfler return fParent; 505065e8de0SAxel Dörfler } 506065e8de0SAxel Dörfler 507065e8de0SAxel Dörfler 508065e8de0SAxel Dörfler BSize 509065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMinSize() 510065e8de0SAxel Dörfler { 511065e8de0SAxel Dörfler // TODO: Cache the info. Might be too expensive for this call. 512065e8de0SAxel Dörfler BSize size; 513065e8de0SAxel Dörfler size.width = 80; 514065e8de0SAxel Dörfler size.height = fParent->_LegendHeight(); 515065e8de0SAxel Dörfler 516065e8de0SAxel Dörfler return size; 517065e8de0SAxel Dörfler } 518065e8de0SAxel Dörfler 519065e8de0SAxel Dörfler 520065e8de0SAxel Dörfler BSize 521065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMaxSize() 522065e8de0SAxel Dörfler { 523065e8de0SAxel Dörfler BSize size(BaseMinSize()); 524065e8de0SAxel Dörfler size.width = B_SIZE_UNLIMITED; 525065e8de0SAxel Dörfler return size; 526065e8de0SAxel Dörfler } 527065e8de0SAxel Dörfler 528065e8de0SAxel Dörfler 529065e8de0SAxel Dörfler BSize 530065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BasePreferredSize() 531065e8de0SAxel Dörfler { 532065e8de0SAxel Dörfler BSize size(BaseMinSize()); 533065e8de0SAxel Dörfler return size; 534065e8de0SAxel Dörfler } 535065e8de0SAxel Dörfler 536065e8de0SAxel Dörfler 537065e8de0SAxel Dörfler BAlignment 538065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseAlignment() 539065e8de0SAxel Dörfler { 540065e8de0SAxel Dörfler return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 541065e8de0SAxel Dörfler } 542dc1ffc79SFrançois Revol #endif 543065e8de0SAxel Dörfler 544065e8de0SAxel Dörfler 545065e8de0SAxel Dörfler // #pragma mark - 546065e8de0SAxel Dörfler 547065e8de0SAxel Dörfler 548bb7cffd0SPhilippe Saint-Pierre const rgb_color kWhite = (rgb_color){255, 255, 255, 255}; 549bb7cffd0SPhilippe Saint-Pierre const rgb_color kBlack = (rgb_color){0, 0, 0, 255}; 5509bd81dbeSStephan Aßmus const float kDraggerSize = 7; 551bb7cffd0SPhilippe Saint-Pierre 552bb7cffd0SPhilippe Saint-Pierre 55318d3e65eSAxel Dörfler ActivityView::ActivityView(BRect frame, const char* name, 5543a4a2141SAxel Dörfler const BMessage* settings, uint32 resizingMode) 55518d3e65eSAxel Dörfler : BView(frame, name, resizingMode, 556d4216445SAxel Dörfler B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 557d4216445SAxel Dörfler fSourcesLock("data sources") 55818d3e65eSAxel Dörfler { 5593a4a2141SAxel Dörfler _Init(settings); 5603a4a2141SAxel Dörfler 5613a4a2141SAxel Dörfler BRect rect(Bounds()); 5629bd81dbeSStephan Aßmus rect.top = rect.bottom - kDraggerSize; 5639bd81dbeSStephan Aßmus rect.left = rect.right - kDraggerSize; 5643a4a2141SAxel Dörfler BDragger* dragger = new BDragger(rect, this, 5653a4a2141SAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 5663a4a2141SAxel Dörfler AddChild(dragger); 5673a4a2141SAxel Dörfler } 5683a4a2141SAxel Dörfler 5693a4a2141SAxel Dörfler 5703a4a2141SAxel Dörfler ActivityView::ActivityView(const char* name, const BMessage* settings) 571cbd4bc95SFrançois Revol #ifdef __HAIKU__ 572d4216445SAxel Dörfler : BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 573cbd4bc95SFrançois Revol #else 574d4216445SAxel Dörfler : BView(BRect(0, 0, 300, 200), name, B_FOLLOW_NONE, 575d4216445SAxel Dörfler B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 576cbd4bc95SFrançois Revol #endif 577d4216445SAxel Dörfler fSourcesLock("data sources") 5783a4a2141SAxel Dörfler { 57979cbd226SFrançois Revol SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 5809c89c450SAxel Dörfler 5813a4a2141SAxel Dörfler _Init(settings); 58218d3e65eSAxel Dörfler 58318d3e65eSAxel Dörfler BRect rect(Bounds()); 5849bd81dbeSStephan Aßmus rect.top = rect.bottom - kDraggerSize; 5859bd81dbeSStephan Aßmus rect.left = rect.right - kDraggerSize; 58618d3e65eSAxel Dörfler BDragger* dragger = new BDragger(rect, this, 58718d3e65eSAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 58818d3e65eSAxel Dörfler AddChild(dragger); 58918d3e65eSAxel Dörfler } 59018d3e65eSAxel Dörfler 59118d3e65eSAxel Dörfler 59218d3e65eSAxel Dörfler ActivityView::ActivityView(BMessage* archive) 59318d3e65eSAxel Dörfler : BView(archive) 59418d3e65eSAxel Dörfler { 59518d3e65eSAxel Dörfler _Init(archive); 59618d3e65eSAxel Dörfler } 59718d3e65eSAxel Dörfler 59818d3e65eSAxel Dörfler 59918d3e65eSAxel Dörfler ActivityView::~ActivityView() 60018d3e65eSAxel Dörfler { 6013a4a2141SAxel Dörfler delete fOffscreen; 60274158bb4SFrançois Revol delete fSystemInfoHandler; 6035b0cd987SJohn Scipione 604*3fdab584SJohn Scipione // replicant deleted, destroy the about window 605*3fdab584SJohn Scipione if (fAboutWindow != NULL) 6065b0cd987SJohn Scipione fAboutWindow->Quit(); 60718d3e65eSAxel Dörfler } 60818d3e65eSAxel Dörfler 60918d3e65eSAxel Dörfler 61018d3e65eSAxel Dörfler void 61118d3e65eSAxel Dörfler ActivityView::_Init(const BMessage* settings) 61218d3e65eSAxel Dörfler { 6139c89c450SAxel Dörfler fHistoryBackgroundColor = (rgb_color){255, 255, 240}; 6149c89c450SAxel Dörfler fLegendBackgroundColor = LowColor(); 6159c89c450SAxel Dörfler // the low color is restored by the BView unarchiving 6163a4a2141SAxel Dörfler fOffscreen = NULL; 617dc1ffc79SFrançois Revol #ifdef __HAIKU__ 618065e8de0SAxel Dörfler fHistoryLayoutItem = NULL; 619065e8de0SAxel Dörfler fLegendLayoutItem = NULL; 620dc1ffc79SFrançois Revol #endif 6213a4a2141SAxel Dörfler SetViewColor(B_TRANSPARENT_COLOR); 62218d3e65eSAxel Dörfler 62318d3e65eSAxel Dörfler fLastRefresh = 0; 62418d3e65eSAxel Dörfler fDrawResolution = 1; 62551591198SAxel Dörfler fZooming = false; 62618d3e65eSAxel Dörfler 62774158bb4SFrançois Revol fSystemInfoHandler = new SystemInfoHandler; 62874158bb4SFrançois Revol 6293a4a2141SAxel Dörfler if (settings == NULL 630eee6f40bSAlexandre Deckner || settings->FindInt64("refresh interval", &fRefreshInterval) != B_OK) 631eee6f40bSAlexandre Deckner fRefreshInterval = kInitialRefreshInterval; 632eee6f40bSAlexandre Deckner 633eee6f40bSAlexandre Deckner if (settings == NULL 6343a4a2141SAxel Dörfler || settings->FindBool("show legend", &fShowLegend) != B_OK) 6353a4a2141SAxel Dörfler fShowLegend = true; 6363a4a2141SAxel Dörfler 63751591198SAxel Dörfler if (settings == NULL) 6383a4a2141SAxel Dörfler return; 6393a4a2141SAxel Dörfler 6409c89c450SAxel Dörfler ssize_t colorLength; 64179cbd226SFrançois Revol rgb_color *color; 6429c89c450SAxel Dörfler if (settings->FindData("history background color", B_RGB_COLOR_TYPE, 6439c89c450SAxel Dörfler (const void **)&color, &colorLength) == B_OK 6449c89c450SAxel Dörfler && colorLength == sizeof(rgb_color)) 6459c89c450SAxel Dörfler fHistoryBackgroundColor = *color; 64679cbd226SFrançois Revol 6473a4a2141SAxel Dörfler const char* name; 648d1901581SStephan Aßmus for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++) 6491201d52eSAxel Dörfler AddDataSource(DataSource::FindSource(name), settings); 650*3fdab584SJohn Scipione 651*3fdab584SJohn Scipione fAboutWindow = NULL; 6523a4a2141SAxel Dörfler } 65318d3e65eSAxel Dörfler 65418d3e65eSAxel Dörfler 65518d3e65eSAxel Dörfler status_t 65618d3e65eSAxel Dörfler ActivityView::Archive(BMessage* into, bool deep) const 65718d3e65eSAxel Dörfler { 65818d3e65eSAxel Dörfler status_t status; 65918d3e65eSAxel Dörfler 66018d3e65eSAxel Dörfler status = BView::Archive(into, deep); 66118d3e65eSAxel Dörfler if (status < B_OK) 66218d3e65eSAxel Dörfler return status; 66318d3e65eSAxel Dörfler 66418d3e65eSAxel Dörfler status = into->AddString("add_on", kSignature); 66518d3e65eSAxel Dörfler if (status < B_OK) 66618d3e65eSAxel Dörfler return status; 66718d3e65eSAxel Dörfler 66818d3e65eSAxel Dörfler status = SaveState(*into); 66918d3e65eSAxel Dörfler if (status < B_OK) 67018d3e65eSAxel Dörfler return status; 67118d3e65eSAxel Dörfler 67218d3e65eSAxel Dörfler return B_OK; 67318d3e65eSAxel Dörfler } 67418d3e65eSAxel Dörfler 67518d3e65eSAxel Dörfler 67618d3e65eSAxel Dörfler BArchivable* 67718d3e65eSAxel Dörfler ActivityView::Instantiate(BMessage* archive) 67818d3e65eSAxel Dörfler { 67918d3e65eSAxel Dörfler if (!validate_instantiation(archive, "ActivityView")) 68018d3e65eSAxel Dörfler return NULL; 68118d3e65eSAxel Dörfler 68218d3e65eSAxel Dörfler return new ActivityView(archive); 68318d3e65eSAxel Dörfler } 68418d3e65eSAxel Dörfler 68518d3e65eSAxel Dörfler 68618d3e65eSAxel Dörfler status_t 68718d3e65eSAxel Dörfler ActivityView::SaveState(BMessage& state) const 68818d3e65eSAxel Dörfler { 6893a4a2141SAxel Dörfler status_t status = state.AddBool("show legend", fShowLegend); 6903a4a2141SAxel Dörfler if (status != B_OK) 6913a4a2141SAxel Dörfler return status; 6923a4a2141SAxel Dörfler 693eee6f40bSAlexandre Deckner status = state.AddInt64("refresh interval", fRefreshInterval); 694eee6f40bSAlexandre Deckner if (status != B_OK) 695eee6f40bSAlexandre Deckner return status; 696eee6f40bSAlexandre Deckner 6979c89c450SAxel Dörfler status = state.AddData("history background color", B_RGB_COLOR_TYPE, 6989c89c450SAxel Dörfler &fHistoryBackgroundColor, sizeof(rgb_color)); 69979cbd226SFrançois Revol if (status != B_OK) 70079cbd226SFrançois Revol return status; 70179cbd226SFrançois Revol 7023a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 7033a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i); 7043a4a2141SAxel Dörfler 7053a4a2141SAxel Dörfler if (!source->PerCPU() || source->CPU() == 0) 706d1901581SStephan Aßmus status = state.AddString("source", source->InternalName()); 7073a4a2141SAxel Dörfler if (status != B_OK) 7083a4a2141SAxel Dörfler return status; 7093a4a2141SAxel Dörfler 7109c89c450SAxel Dörfler BString name = source->Name(); 7119c89c450SAxel Dörfler name << " color"; 7129c89c450SAxel Dörfler rgb_color color = source->Color(); 7139c89c450SAxel Dörfler state.AddData(name.String(), B_RGB_COLOR_TYPE, &color, 7149c89c450SAxel Dörfler sizeof(rgb_color)); 7153a4a2141SAxel Dörfler } 7163a4a2141SAxel Dörfler return B_OK; 71718d3e65eSAxel Dörfler } 71818d3e65eSAxel Dörfler 71918d3e65eSAxel Dörfler 72051591198SAxel Dörfler Scale* 72151591198SAxel Dörfler ActivityView::_ScaleFor(scale_type type) 72251591198SAxel Dörfler { 72351591198SAxel Dörfler if (type == kNoScale) 72451591198SAxel Dörfler return NULL; 72551591198SAxel Dörfler 72651591198SAxel Dörfler std::map<scale_type, ::Scale*>::iterator iterator = fScales.find(type); 72751591198SAxel Dörfler if (iterator != fScales.end()) 72851591198SAxel Dörfler return iterator->second; 72951591198SAxel Dörfler 73051591198SAxel Dörfler // add new scale 73151591198SAxel Dörfler ::Scale* scale = new ::Scale(type); 73251591198SAxel Dörfler fScales[type] = scale; 73351591198SAxel Dörfler 73451591198SAxel Dörfler return scale; 73551591198SAxel Dörfler } 73651591198SAxel Dörfler 73751591198SAxel Dörfler 738dc1ffc79SFrançois Revol #ifdef __HAIKU__ 739065e8de0SAxel Dörfler BLayoutItem* 740065e8de0SAxel Dörfler ActivityView::CreateHistoryLayoutItem() 741065e8de0SAxel Dörfler { 742065e8de0SAxel Dörfler if (fHistoryLayoutItem == NULL) 743065e8de0SAxel Dörfler fHistoryLayoutItem = new HistoryLayoutItem(this); 744065e8de0SAxel Dörfler 745065e8de0SAxel Dörfler return fHistoryLayoutItem; 746065e8de0SAxel Dörfler } 747065e8de0SAxel Dörfler 748065e8de0SAxel Dörfler 749065e8de0SAxel Dörfler BLayoutItem* 750065e8de0SAxel Dörfler ActivityView::CreateLegendLayoutItem() 751065e8de0SAxel Dörfler { 752065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL) 753065e8de0SAxel Dörfler fLegendLayoutItem = new LegendLayoutItem(this); 754065e8de0SAxel Dörfler 755065e8de0SAxel Dörfler return fLegendLayoutItem; 756065e8de0SAxel Dörfler } 757dc1ffc79SFrançois Revol #endif 758065e8de0SAxel Dörfler 7599c89c450SAxel Dörfler 76018d3e65eSAxel Dörfler DataSource* 7613a4a2141SAxel Dörfler ActivityView::FindDataSource(const DataSource* search) 76218d3e65eSAxel Dörfler { 763d4216445SAxel Dörfler BAutolock _(fSourcesLock); 764d4216445SAxel Dörfler 76518d3e65eSAxel Dörfler for (int32 i = fSources.CountItems(); i-- > 0;) { 76618d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 7673a4a2141SAxel Dörfler if (!strcmp(source->Name(), search->Name())) 76818d3e65eSAxel Dörfler return source; 76918d3e65eSAxel Dörfler } 77018d3e65eSAxel Dörfler 77118d3e65eSAxel Dörfler return NULL; 77218d3e65eSAxel Dörfler } 77318d3e65eSAxel Dörfler 77418d3e65eSAxel Dörfler 77518d3e65eSAxel Dörfler status_t 7769c89c450SAxel Dörfler ActivityView::AddDataSource(const DataSource* source, const BMessage* state) 77718d3e65eSAxel Dörfler { 7783a4a2141SAxel Dörfler if (source == NULL) 7793a4a2141SAxel Dörfler return B_BAD_VALUE; 7803a4a2141SAxel Dörfler 781d4216445SAxel Dörfler BAutolock _(fSourcesLock); 782d4216445SAxel Dörfler 7838e26f387SAxel Dörfler // Search for the correct insert spot to maintain the order of the sources 7843a4a2141SAxel Dörfler int32 insert = DataSource::IndexOf(source); 7853a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) { 7863a4a2141SAxel Dörfler DataSource* before = fSources.ItemAt(i); 7873a4a2141SAxel Dörfler if (DataSource::IndexOf(before) > insert) { 7883a4a2141SAxel Dörfler insert = i; 7893a4a2141SAxel Dörfler break; 7903a4a2141SAxel Dörfler } 7913a4a2141SAxel Dörfler } 7923a4a2141SAxel Dörfler if (insert > fSources.CountItems()) 7933a4a2141SAxel Dörfler insert = fSources.CountItems(); 7943a4a2141SAxel Dörfler 7958e26f387SAxel Dörfler // Generate DataHistory and ViewHistory objects for the source 7968e26f387SAxel Dörfler // (one might need one history per CPU) 7978e26f387SAxel Dörfler 7983a4a2141SAxel Dörfler uint32 count = 1; 7993a4a2141SAxel Dörfler if (source->PerCPU()) { 8003a4a2141SAxel Dörfler SystemInfo info; 8013a4a2141SAxel Dörfler count = info.CPUCount(); 8023a4a2141SAxel Dörfler } 8033a4a2141SAxel Dörfler 8043a4a2141SAxel Dörfler for (uint32 i = 0; i < count; i++) { 80518d3e65eSAxel Dörfler DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL, 8061bb87bd0SAxel Dörfler RefreshInterval()); 8078e26f387SAxel Dörfler ListAddDeleter<DataHistory> valuesDeleter(fValues, values, insert); 8083a4a2141SAxel Dörfler 8098e26f387SAxel Dörfler ViewHistory* viewValues = new(std::nothrow) ViewHistory; 8108e26f387SAxel Dörfler ListAddDeleter<ViewHistory> viewValuesDeleter(fViewValues, viewValues, 8118e26f387SAxel Dörfler insert); 8128e26f387SAxel Dörfler 8138e26f387SAxel Dörfler if (valuesDeleter.Failed() || viewValuesDeleter.Failed()) 81418d3e65eSAxel Dörfler return B_NO_MEMORY; 81518d3e65eSAxel Dörfler 81651591198SAxel Dörfler values->SetScale(_ScaleFor(source->ScaleType())); 81751591198SAxel Dörfler 8183a4a2141SAxel Dörfler DataSource* copy; 8193a4a2141SAxel Dörfler if (source->PerCPU()) 8203a4a2141SAxel Dörfler copy = source->CopyForCPU(i); 8213a4a2141SAxel Dörfler else 8223a4a2141SAxel Dörfler copy = source->Copy(); 8233a4a2141SAxel Dörfler 8248e26f387SAxel Dörfler ListAddDeleter<DataSource> sourceDeleter(fSources, copy, insert); 8258e26f387SAxel Dörfler if (sourceDeleter.Failed()) 8268e26f387SAxel Dörfler return B_NO_MEMORY; 8278e26f387SAxel Dörfler 8289c89c450SAxel Dörfler BString colorName = source->Name(); 8299c89c450SAxel Dörfler colorName << " color"; 8309c89c450SAxel Dörfler if (state != NULL) { 8319c89c450SAxel Dörfler const rgb_color* color = NULL; 8329c89c450SAxel Dörfler ssize_t colorLength; 8339c89c450SAxel Dörfler if (state->FindData(colorName.String(), B_RGB_COLOR_TYPE, i, 8349c89c450SAxel Dörfler (const void**)&color, &colorLength) == B_OK 8359c89c450SAxel Dörfler && colorLength == sizeof(rgb_color)) 8369c89c450SAxel Dörfler copy->SetColor(*color); 8379c89c450SAxel Dörfler } 8389c89c450SAxel Dörfler 8398e26f387SAxel Dörfler valuesDeleter.Detach(); 8408e26f387SAxel Dörfler viewValuesDeleter.Detach(); 8418e26f387SAxel Dörfler sourceDeleter.Detach(); 842be3f9645SAxel Dörfler insert++; 8433a4a2141SAxel Dörfler } 84418d3e65eSAxel Dörfler 845dc1ffc79SFrançois Revol #ifdef __HAIKU__ 846065e8de0SAxel Dörfler InvalidateLayout(); 847dc1ffc79SFrançois Revol #endif 84818d3e65eSAxel Dörfler return B_OK; 84918d3e65eSAxel Dörfler } 85018d3e65eSAxel Dörfler 85118d3e65eSAxel Dörfler 85218d3e65eSAxel Dörfler status_t 8533a4a2141SAxel Dörfler ActivityView::RemoveDataSource(const DataSource* remove) 85418d3e65eSAxel Dörfler { 855065e8de0SAxel Dörfler bool removed = false; 856065e8de0SAxel Dörfler 857d4216445SAxel Dörfler BAutolock _(fSourcesLock); 858d4216445SAxel Dörfler 8593a4a2141SAxel Dörfler while (true) { 8603a4a2141SAxel Dörfler DataSource* source = FindDataSource(remove); 861065e8de0SAxel Dörfler if (source == NULL) { 862065e8de0SAxel Dörfler if (removed) 863065e8de0SAxel Dörfler break; 864065e8de0SAxel Dörfler return B_ENTRY_NOT_FOUND; 865065e8de0SAxel Dörfler } 8663a4a2141SAxel Dörfler 86718d3e65eSAxel Dörfler int32 index = fSources.IndexOf(source); 86818d3e65eSAxel Dörfler if (index < 0) 86918d3e65eSAxel Dörfler return B_ENTRY_NOT_FOUND; 87018d3e65eSAxel Dörfler 87118d3e65eSAxel Dörfler fSources.RemoveItemAt(index); 87218d3e65eSAxel Dörfler delete source; 87318d3e65eSAxel Dörfler DataHistory* values = fValues.RemoveItemAt(index); 87418d3e65eSAxel Dörfler delete values; 875065e8de0SAxel Dörfler removed = true; 8763a4a2141SAxel Dörfler } 87718d3e65eSAxel Dörfler 878dc1ffc79SFrançois Revol #ifdef __HAIKU__ 879065e8de0SAxel Dörfler InvalidateLayout(); 880dc1ffc79SFrançois Revol #endif 88118d3e65eSAxel Dörfler return B_OK; 88218d3e65eSAxel Dörfler } 88318d3e65eSAxel Dörfler 88418d3e65eSAxel Dörfler 88518d3e65eSAxel Dörfler void 88618d3e65eSAxel Dörfler ActivityView::RemoveAllDataSources() 88718d3e65eSAxel Dörfler { 888d4216445SAxel Dörfler BAutolock _(fSourcesLock); 889d4216445SAxel Dörfler 89018d3e65eSAxel Dörfler fSources.MakeEmpty(); 89118d3e65eSAxel Dörfler fValues.MakeEmpty(); 89218d3e65eSAxel Dörfler } 89318d3e65eSAxel Dörfler 89418d3e65eSAxel Dörfler 89518d3e65eSAxel Dörfler void 89618d3e65eSAxel Dörfler ActivityView::AttachedToWindow() 89718d3e65eSAxel Dörfler { 89874158bb4SFrançois Revol Looper()->AddHandler(fSystemInfoHandler); 8996f6ba875SAxel Dörfler fSystemInfoHandler->StartWatching(); 9006f6ba875SAxel Dörfler 901d4216445SAxel Dörfler fRefreshSem = create_sem(0, "refresh sem"); 902d4216445SAxel Dörfler fRefreshThread = spawn_thread(&_RefreshThread, "source refresh", 9038e26f387SAxel Dörfler B_URGENT_DISPLAY_PRIORITY, this); 904d4216445SAxel Dörfler resume_thread(fRefreshThread); 9053a4a2141SAxel Dörfler 9063a4a2141SAxel Dörfler FrameResized(Bounds().Width(), Bounds().Height()); 90718d3e65eSAxel Dörfler } 90818d3e65eSAxel Dörfler 90918d3e65eSAxel Dörfler 91018d3e65eSAxel Dörfler void 91118d3e65eSAxel Dörfler ActivityView::DetachedFromWindow() 91218d3e65eSAxel Dörfler { 9136f6ba875SAxel Dörfler fSystemInfoHandler->StopWatching(); 91474158bb4SFrançois Revol Looper()->RemoveHandler(fSystemInfoHandler); 9156f6ba875SAxel Dörfler 916d4216445SAxel Dörfler delete_sem(fRefreshSem); 917d4216445SAxel Dörfler wait_for_thread(fRefreshThread, NULL); 91818d3e65eSAxel Dörfler } 91918d3e65eSAxel Dörfler 92018d3e65eSAxel Dörfler 921cbd4bc95SFrançois Revol #ifdef __HAIKU__ 9223a4a2141SAxel Dörfler BSize 9233a4a2141SAxel Dörfler ActivityView::MinSize() 9243a4a2141SAxel Dörfler { 9253a4a2141SAxel Dörfler BSize size(32, 32); 9263a4a2141SAxel Dörfler if (fShowLegend) 9279c89c450SAxel Dörfler size.height = _LegendHeight(); 9283a4a2141SAxel Dörfler 9293a4a2141SAxel Dörfler return size; 9303a4a2141SAxel Dörfler } 931cbd4bc95SFrançois Revol #endif 9323a4a2141SAxel Dörfler 9333a4a2141SAxel Dörfler 93418d3e65eSAxel Dörfler void 93518d3e65eSAxel Dörfler ActivityView::FrameResized(float /*width*/, float /*height*/) 93618d3e65eSAxel Dörfler { 9373a4a2141SAxel Dörfler _UpdateOffscreenBitmap(); 9383a4a2141SAxel Dörfler } 9393a4a2141SAxel Dörfler 9403a4a2141SAxel Dörfler 9413a4a2141SAxel Dörfler void 9429c89c450SAxel Dörfler ActivityView::_UpdateOffscreenBitmap() 9433a4a2141SAxel Dörfler { 9443a4a2141SAxel Dörfler BRect frame = _HistoryFrame(); 945ed1b2753SStephan Aßmus frame.OffsetTo(B_ORIGIN); 946ed1b2753SStephan Aßmus 9479c89c450SAxel Dörfler if (fOffscreen != NULL && frame == fOffscreen->Bounds()) 9483a4a2141SAxel Dörfler return; 9493a4a2141SAxel Dörfler 9503a4a2141SAxel Dörfler delete fOffscreen; 9513a4a2141SAxel Dörfler 9523a4a2141SAxel Dörfler // create offscreen bitmap 9533a4a2141SAxel Dörfler 9543a4a2141SAxel Dörfler fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS, 9553a4a2141SAxel Dörfler B_RGB32); 9563a4a2141SAxel Dörfler if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) { 9573a4a2141SAxel Dörfler delete fOffscreen; 9583a4a2141SAxel Dörfler fOffscreen = NULL; 9593a4a2141SAxel Dörfler return; 9603a4a2141SAxel Dörfler } 9613a4a2141SAxel Dörfler 9623a4a2141SAxel Dörfler BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE); 9639c89c450SAxel Dörfler view->SetViewColor(fHistoryBackgroundColor); 9643a4a2141SAxel Dörfler view->SetLowColor(view->ViewColor()); 9653a4a2141SAxel Dörfler fOffscreen->AddChild(view); 96618d3e65eSAxel Dörfler } 96718d3e65eSAxel Dörfler 96818d3e65eSAxel Dörfler 9699c89c450SAxel Dörfler BView* 9709c89c450SAxel Dörfler ActivityView::_OffscreenView() 9719c89c450SAxel Dörfler { 9729c89c450SAxel Dörfler if (fOffscreen == NULL) 9739c89c450SAxel Dörfler return NULL; 9749c89c450SAxel Dörfler 9759c89c450SAxel Dörfler return fOffscreen->ChildAt(0); 9769c89c450SAxel Dörfler } 9779c89c450SAxel Dörfler 9789c89c450SAxel Dörfler 97918d3e65eSAxel Dörfler void 98018d3e65eSAxel Dörfler ActivityView::MouseDown(BPoint where) 98118d3e65eSAxel Dörfler { 98251591198SAxel Dörfler int32 buttons = B_SECONDARY_MOUSE_BUTTON; 98351591198SAxel Dörfler if (Looper() != NULL && Looper()->CurrentMessage() != NULL) 98418d3e65eSAxel Dörfler Looper()->CurrentMessage()->FindInt32("buttons", &buttons); 98551591198SAxel Dörfler 98651591198SAxel Dörfler if (buttons == B_PRIMARY_MOUSE_BUTTON) { 98751591198SAxel Dörfler fZoomPoint = where; 98851591198SAxel Dörfler fOriginalResolution = fDrawResolution; 98951591198SAxel Dörfler fZooming = true; 9908e26f387SAxel Dörfler SetMouseEventMask(B_POINTER_EVENTS); 99151591198SAxel Dörfler return; 99218d3e65eSAxel Dörfler } 99318d3e65eSAxel Dörfler 99418d3e65eSAxel Dörfler BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 99518d3e65eSAxel Dörfler menu->SetFont(be_plain_font); 9963a4a2141SAxel Dörfler 9974840a72fSPhilippe Houdoin BMenu* additionalMenu = new BMenu(B_TRANSLATE("Additional items")); 998dc1ffc79SFrançois Revol additionalMenu->SetFont(be_plain_font); 999dc1ffc79SFrançois Revol 10003a4a2141SAxel Dörfler SystemInfo info; 100118d3e65eSAxel Dörfler BMenuItem* item; 100218d3e65eSAxel Dörfler 100318d3e65eSAxel Dörfler for (int32 i = 0; i < DataSource::CountSources(); i++) { 100418d3e65eSAxel Dörfler const DataSource* source = DataSource::SourceAt(i); 100518d3e65eSAxel Dörfler 10063a4a2141SAxel Dörfler if (source->MultiCPUOnly() && info.CPUCount() == 1) 10073a4a2141SAxel Dörfler continue; 10083a4a2141SAxel Dörfler 100918d3e65eSAxel Dörfler BMessage* message = new BMessage(kMsgToggleDataSource); 101018d3e65eSAxel Dörfler message->AddInt32("index", i); 101118d3e65eSAxel Dörfler 10123a4a2141SAxel Dörfler item = new BMenuItem(source->Name(), message); 10133a4a2141SAxel Dörfler if (FindDataSource(source)) 101418d3e65eSAxel Dörfler item->SetMarked(true); 101518d3e65eSAxel Dörfler 101643eda1cdSAxel Dörfler if (source->Primary()) 101718d3e65eSAxel Dörfler menu->AddItem(item); 101843eda1cdSAxel Dörfler else 101943eda1cdSAxel Dörfler additionalMenu->AddItem(item); 102018d3e65eSAxel Dörfler } 102118d3e65eSAxel Dörfler 102243eda1cdSAxel Dörfler menu->AddItem(new BMenuItem(additionalMenu)); 10233a4a2141SAxel Dörfler menu->AddSeparatorItem(); 10244840a72fSPhilippe Houdoin menu->AddItem(new BMenuItem(fShowLegend ? 10254840a72fSPhilippe Houdoin B_TRANSLATE("Hide legend") : B_TRANSLATE("Show legend"), 10263a4a2141SAxel Dörfler new BMessage(kMsgToggleLegend))); 10273a4a2141SAxel Dörfler 102818d3e65eSAxel Dörfler menu->SetTargetForItems(this); 1029dc1ffc79SFrançois Revol additionalMenu->SetTargetForItems(this); 103018d3e65eSAxel Dörfler 10313f315b26SAxel Dörfler ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window()); 10323f315b26SAxel Dörfler if (window != NULL && window->ActivityViewCount() > 1) { 10333f315b26SAxel Dörfler menu->AddSeparatorItem(); 10343f315b26SAxel Dörfler BMessage* message = new BMessage(kMsgRemoveView); 10353f315b26SAxel Dörfler message->AddPointer("view", this); 10364840a72fSPhilippe Houdoin menu->AddItem(item = new BMenuItem(B_TRANSLATE("Remove graph"), 10374840a72fSPhilippe Houdoin message)); 10383f315b26SAxel Dörfler item->SetTarget(window); 10393f315b26SAxel Dörfler } 10403f315b26SAxel Dörfler 104118d3e65eSAxel Dörfler ConvertToScreen(&where); 104218d3e65eSAxel Dörfler menu->Go(where, true, false, true); 104318d3e65eSAxel Dörfler } 104418d3e65eSAxel Dörfler 104518d3e65eSAxel Dörfler 104618d3e65eSAxel Dörfler void 104751591198SAxel Dörfler ActivityView::MouseUp(BPoint where) 104851591198SAxel Dörfler { 104951591198SAxel Dörfler fZooming = false; 105051591198SAxel Dörfler } 105151591198SAxel Dörfler 105251591198SAxel Dörfler 105351591198SAxel Dörfler void 105418d3e65eSAxel Dörfler ActivityView::MouseMoved(BPoint where, uint32 transit, 105518d3e65eSAxel Dörfler const BMessage* dragMessage) 105618d3e65eSAxel Dörfler { 105751591198SAxel Dörfler if (!fZooming) 105851591198SAxel Dörfler return; 105951591198SAxel Dörfler 106051591198SAxel Dörfler int32 shift = int32(where.x - fZoomPoint.x) / 25; 10611bb87bd0SAxel Dörfler int32 resolution; 106251591198SAxel Dörfler if (shift > 0) 10631bb87bd0SAxel Dörfler resolution = fOriginalResolution << shift; 106451591198SAxel Dörfler else 10651bb87bd0SAxel Dörfler resolution = fOriginalResolution >> -shift; 106651591198SAxel Dörfler 10671bb87bd0SAxel Dörfler _UpdateResolution(resolution); 106818d3e65eSAxel Dörfler } 106918d3e65eSAxel Dörfler 107018d3e65eSAxel Dörfler 107118d3e65eSAxel Dörfler void 107218d3e65eSAxel Dörfler ActivityView::MessageReceived(BMessage* message) 107318d3e65eSAxel Dörfler { 1074c28f8ea3SFrançois Revol // if a color is dropped, use it as background 1075c28f8ea3SFrançois Revol if (message->WasDropped()) { 1076c28f8ea3SFrançois Revol rgb_color* color; 1077c28f8ea3SFrançois Revol ssize_t size; 10781201d52eSAxel Dörfler if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0, 10791201d52eSAxel Dörfler (const void**)&color, &size) == B_OK 10809c89c450SAxel Dörfler && size == sizeof(rgb_color)) { 10819c89c450SAxel Dörfler BPoint dropPoint = message->DropPoint(); 1082c28f8ea3SFrançois Revol ConvertFromScreen(&dropPoint); 10839c89c450SAxel Dörfler 1084c28f8ea3SFrançois Revol if (_HistoryFrame().Contains(dropPoint)) { 10859c89c450SAxel Dörfler fHistoryBackgroundColor = *color; 10869c89c450SAxel Dörfler Invalidate(_HistoryFrame()); 1087c28f8ea3SFrançois Revol } else { 10885f2f72a2SFrançois Revol // check each legend color box 1089d4216445SAxel Dörfler BAutolock _(fSourcesLock); 1090d4216445SAxel Dörfler 10915f2f72a2SFrançois Revol BRect legendFrame = _LegendFrame(); 10929c89c450SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 10931201d52eSAxel Dörfler BRect frame = _LegendColorFrameAt(legendFrame, i); 10949c89c450SAxel Dörfler if (frame.Contains(dropPoint)) { 10955f2f72a2SFrançois Revol fSources.ItemAt(i)->SetColor(*color); 10969c89c450SAxel Dörfler Invalidate(_HistoryFrame()); 10971201d52eSAxel Dörfler Invalidate(frame); 10985f2f72a2SFrançois Revol return; 10995f2f72a2SFrançois Revol } 11005f2f72a2SFrançois Revol } 11019c89c450SAxel Dörfler 11029c89c450SAxel Dörfler if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) { 11039c89c450SAxel Dörfler // allow background color change in the replicant only 11049c89c450SAxel Dörfler fLegendBackgroundColor = *color; 11051201d52eSAxel Dörfler SetLowColor(fLegendBackgroundColor); 11069c89c450SAxel Dörfler Invalidate(legendFrame); 11079c89c450SAxel Dörfler } 1108c28f8ea3SFrançois Revol } 1109c28f8ea3SFrançois Revol return; 1110c28f8ea3SFrançois Revol } 11119c89c450SAxel Dörfler } 11129c89c450SAxel Dörfler 111318d3e65eSAxel Dörfler switch (message->what) { 111418d3e65eSAxel Dörfler case B_ABOUT_REQUESTED: 1115*3fdab584SJohn Scipione if (fAboutWindow == NULL) { 1116*3fdab584SJohn Scipione fAboutWindow = new BAboutWindow(this, kAppName, kSignature); 1117*3fdab584SJohn Scipione fAboutWindow->AddCopyright(2008, "Haiku, Inc."); 11185b0cd987SJohn Scipione fAboutWindow->Show(); 1119*3fdab584SJohn Scipione } else 1120*3fdab584SJohn Scipione fAboutWindow->Activate(); 1121*3fdab584SJohn Scipione 1122*3fdab584SJohn Scipione break; 1123*3fdab584SJohn Scipione 1124*3fdab584SJohn Scipione case kAboutWindowClosed: 1125*3fdab584SJohn Scipione fAboutWindow = NULL; 112618d3e65eSAxel Dörfler break; 112718d3e65eSAxel Dörfler 11281bb87bd0SAxel Dörfler case kMsgUpdateResolution: 11291bb87bd0SAxel Dörfler { 11301bb87bd0SAxel Dörfler int32 resolution; 11311bb87bd0SAxel Dörfler if (message->FindInt32("resolution", &resolution) != B_OK) 11321bb87bd0SAxel Dörfler break; 11331bb87bd0SAxel Dörfler 11341bb87bd0SAxel Dörfler _UpdateResolution(resolution, false); 11351bb87bd0SAxel Dörfler break; 11361bb87bd0SAxel Dörfler } 11371bb87bd0SAxel Dörfler 11381bb87bd0SAxel Dörfler case kMsgTimeIntervalUpdated: 11391bb87bd0SAxel Dörfler bigtime_t interval; 11401bb87bd0SAxel Dörfler if (message->FindInt64("interval", &interval) != B_OK) 11411bb87bd0SAxel Dörfler break; 11421bb87bd0SAxel Dörfler 11431bb87bd0SAxel Dörfler if (interval < 10000) 11441bb87bd0SAxel Dörfler interval = 10000; 11451bb87bd0SAxel Dörfler 11461bb87bd0SAxel Dörfler atomic_set64(&fRefreshInterval, interval); 11471bb87bd0SAxel Dörfler break; 11481bb87bd0SAxel Dörfler 114918d3e65eSAxel Dörfler case kMsgToggleDataSource: 115018d3e65eSAxel Dörfler { 115118d3e65eSAxel Dörfler int32 index; 115218d3e65eSAxel Dörfler if (message->FindInt32("index", &index) != B_OK) 115318d3e65eSAxel Dörfler break; 115418d3e65eSAxel Dörfler 115518d3e65eSAxel Dörfler const DataSource* baseSource = DataSource::SourceAt(index); 115618d3e65eSAxel Dörfler if (baseSource == NULL) 115718d3e65eSAxel Dörfler break; 115818d3e65eSAxel Dörfler 11593a4a2141SAxel Dörfler DataSource* source = FindDataSource(baseSource); 116018d3e65eSAxel Dörfler if (source == NULL) 11613a4a2141SAxel Dörfler AddDataSource(baseSource); 116218d3e65eSAxel Dörfler else 11637d33b63dSAxel Dörfler RemoveDataSource(baseSource); 116418d3e65eSAxel Dörfler 116518d3e65eSAxel Dörfler Invalidate(); 116618d3e65eSAxel Dörfler break; 116718d3e65eSAxel Dörfler } 116818d3e65eSAxel Dörfler 11693a4a2141SAxel Dörfler case kMsgToggleLegend: 11703a4a2141SAxel Dörfler fShowLegend = !fShowLegend; 11713a4a2141SAxel Dörfler Invalidate(); 11723a4a2141SAxel Dörfler break; 11733a4a2141SAxel Dörfler 117418d3e65eSAxel Dörfler case B_MOUSE_WHEEL_CHANGED: 117518d3e65eSAxel Dörfler { 117618d3e65eSAxel Dörfler float deltaY = 0.0f; 117718d3e65eSAxel Dörfler if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK 117818d3e65eSAxel Dörfler || deltaY == 0.0f) 117918d3e65eSAxel Dörfler break; 118018d3e65eSAxel Dörfler 11811bb87bd0SAxel Dörfler int32 resolution = fDrawResolution; 118218d3e65eSAxel Dörfler if (deltaY > 0) 11831bb87bd0SAxel Dörfler resolution *= 2; 118418d3e65eSAxel Dörfler else 11851bb87bd0SAxel Dörfler resolution /= 2; 118618d3e65eSAxel Dörfler 11871bb87bd0SAxel Dörfler _UpdateResolution(resolution); 118818d3e65eSAxel Dörfler break; 118918d3e65eSAxel Dörfler } 119018d3e65eSAxel Dörfler 119118d3e65eSAxel Dörfler default: 119218d3e65eSAxel Dörfler BView::MessageReceived(message); 119318d3e65eSAxel Dörfler break; 119418d3e65eSAxel Dörfler } 119518d3e65eSAxel Dörfler } 119618d3e65eSAxel Dörfler 119718d3e65eSAxel Dörfler 1198065e8de0SAxel Dörfler void 1199065e8de0SAxel Dörfler ActivityView::_UpdateFrame() 1200065e8de0SAxel Dörfler { 1201dc1ffc79SFrançois Revol #ifdef __HAIKU__ 1202065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL || fHistoryLayoutItem == NULL) 1203065e8de0SAxel Dörfler return; 1204065e8de0SAxel Dörfler 1205065e8de0SAxel Dörfler BRect historyFrame = fHistoryLayoutItem->Frame(); 1206065e8de0SAxel Dörfler BRect legendFrame = fLegendLayoutItem->Frame(); 1207dc1ffc79SFrançois Revol #else 1208dc1ffc79SFrançois Revol BRect historyFrame = Bounds(); 1209dc1ffc79SFrançois Revol BRect legendFrame = Bounds(); 1210dc1ffc79SFrançois Revol historyFrame.bottom -= 2 * Bounds().Height() / 3; 1211dc1ffc79SFrançois Revol legendFrame.top += Bounds().Height() / 3; 1212dc1ffc79SFrançois Revol #endif 1213065e8de0SAxel Dörfler MoveTo(historyFrame.left, historyFrame.top); 1214065e8de0SAxel Dörfler ResizeTo(legendFrame.left + legendFrame.Width() - historyFrame.left, 1215065e8de0SAxel Dörfler legendFrame.top + legendFrame.Height() - historyFrame.top); 1216065e8de0SAxel Dörfler } 1217065e8de0SAxel Dörfler 1218065e8de0SAxel Dörfler 12193a4a2141SAxel Dörfler BRect 12203a4a2141SAxel Dörfler ActivityView::_HistoryFrame() const 12213a4a2141SAxel Dörfler { 12223a4a2141SAxel Dörfler BRect frame = Bounds(); 12233a4a2141SAxel Dörfler 1224ed1b2753SStephan Aßmus if (fShowLegend) { 1225ed1b2753SStephan Aßmus BRect legendFrame = _LegendFrame(); 12263a4a2141SAxel Dörfler frame.bottom = legendFrame.top - 1; 1227ed1b2753SStephan Aßmus } 1228ed1b2753SStephan Aßmus 1229ed1b2753SStephan Aßmus frame.InsetBy(2, 2); 12303a4a2141SAxel Dörfler 12313a4a2141SAxel Dörfler return frame; 12323a4a2141SAxel Dörfler } 12333a4a2141SAxel Dörfler 12343a4a2141SAxel Dörfler 1235065e8de0SAxel Dörfler float 1236065e8de0SAxel Dörfler ActivityView::_LegendHeight() const 12373a4a2141SAxel Dörfler { 12383a4a2141SAxel Dörfler font_height fontHeight; 12393a4a2141SAxel Dörfler GetFontHeight(&fontHeight); 12403a4a2141SAxel Dörfler 1241d4216445SAxel Dörfler BAutolock _(fSourcesLock); 1242d4216445SAxel Dörfler 12433a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2; 1244fbb82a62SPhilippe Saint-Pierre 1245e45d83a9SPhilippe Saint-Pierre int32 boldMargin = Parent() 1246e45d83a9SPhilippe Saint-Pierre && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0 ? 2 : 0; 1247fbb82a62SPhilippe Saint-Pierre 1248065e8de0SAxel Dörfler return rows * (4 + ceilf(fontHeight.ascent) 12499bd81dbeSStephan Aßmus + ceilf(fontHeight.descent) + ceilf(fontHeight.leading)) + boldMargin; 1250065e8de0SAxel Dörfler } 1251065e8de0SAxel Dörfler 1252065e8de0SAxel Dörfler 1253065e8de0SAxel Dörfler BRect 1254065e8de0SAxel Dörfler ActivityView::_LegendFrame() const 1255065e8de0SAxel Dörfler { 1256065e8de0SAxel Dörfler float height; 1257dc1ffc79SFrançois Revol #ifdef __HAIKU__ 1258065e8de0SAxel Dörfler if (fLegendLayoutItem != NULL) 1259065e8de0SAxel Dörfler height = fLegendLayoutItem->Frame().Height(); 1260065e8de0SAxel Dörfler else 1261dc1ffc79SFrançois Revol #endif 1262065e8de0SAxel Dörfler height = _LegendHeight(); 1263065e8de0SAxel Dörfler 1264065e8de0SAxel Dörfler BRect frame = Bounds(); 12659bd81dbeSStephan Aßmus frame.bottom -= kDraggerSize; 1266065e8de0SAxel Dörfler frame.top = frame.bottom - height; 12673a4a2141SAxel Dörfler 12683a4a2141SAxel Dörfler return frame; 12693a4a2141SAxel Dörfler } 12703a4a2141SAxel Dörfler 12713a4a2141SAxel Dörfler 12723a4a2141SAxel Dörfler BRect 12733a4a2141SAxel Dörfler ActivityView::_LegendFrameAt(BRect frame, int32 index) const 12743a4a2141SAxel Dörfler { 12753a4a2141SAxel Dörfler int32 column = index & 1; 12763a4a2141SAxel Dörfler int32 row = index / 2; 12773a4a2141SAxel Dörfler if (column == 0) 12783a4a2141SAxel Dörfler frame.right = frame.left + floorf(frame.Width() / 2) - 5; 12793a4a2141SAxel Dörfler else 12803a4a2141SAxel Dörfler frame.left = frame.right - floorf(frame.Width() / 2) + 5; 12813a4a2141SAxel Dörfler 1282d4216445SAxel Dörfler BAutolock _(fSourcesLock); 1283d4216445SAxel Dörfler 12843a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2; 12853a4a2141SAxel Dörfler float height = floorf((frame.Height() - 5) / rows); 12863a4a2141SAxel Dörfler 12873a4a2141SAxel Dörfler frame.top = frame.top + 5 + row * height; 12883a4a2141SAxel Dörfler frame.bottom = frame.top + height - 1; 12893a4a2141SAxel Dörfler 12903a4a2141SAxel Dörfler return frame; 12913a4a2141SAxel Dörfler } 12923a4a2141SAxel Dörfler 12933a4a2141SAxel Dörfler 12941201d52eSAxel Dörfler BRect 12951201d52eSAxel Dörfler ActivityView::_LegendColorFrameAt(BRect frame, int32 index) const 12961201d52eSAxel Dörfler { 12971201d52eSAxel Dörfler frame = _LegendFrameAt(frame, index); 12981201d52eSAxel Dörfler frame.InsetBy(1, 1); 12991201d52eSAxel Dörfler frame.right = frame.left + frame.Height(); 13001201d52eSAxel Dörfler 13011201d52eSAxel Dörfler return frame; 13021201d52eSAxel Dörfler } 13031201d52eSAxel Dörfler 13041201d52eSAxel Dörfler 130518d3e65eSAxel Dörfler float 130618d3e65eSAxel Dörfler ActivityView::_PositionForValue(DataSource* source, DataHistory* values, 130718d3e65eSAxel Dörfler int64 value) 130818d3e65eSAxel Dörfler { 130918d3e65eSAxel Dörfler int64 min = source->Minimum(); 131018d3e65eSAxel Dörfler int64 max = source->Maximum(); 131118d3e65eSAxel Dörfler if (source->AdaptiveScale()) { 131218d3e65eSAxel Dörfler int64 adaptiveMax = int64(values->MaximumValue() * 1.2); 131318d3e65eSAxel Dörfler if (adaptiveMax < max) 131418d3e65eSAxel Dörfler max = adaptiveMax; 131518d3e65eSAxel Dörfler } 131618d3e65eSAxel Dörfler 131718d3e65eSAxel Dörfler if (value > max) 131818d3e65eSAxel Dörfler value = max; 131918d3e65eSAxel Dörfler if (value < min) 132018d3e65eSAxel Dörfler value = min; 132118d3e65eSAxel Dörfler 13223a4a2141SAxel Dörfler float height = _HistoryFrame().Height(); 132318d3e65eSAxel Dörfler return height - (value - min) * height / (max - min); 132418d3e65eSAxel Dörfler } 132518d3e65eSAxel Dörfler 132618d3e65eSAxel Dörfler 132718d3e65eSAxel Dörfler void 1328ed1b2753SStephan Aßmus ActivityView::_DrawHistory(bool drawBackground) 132918d3e65eSAxel Dörfler { 13303a4a2141SAxel Dörfler _UpdateOffscreenBitmap(); 13313a4a2141SAxel Dörfler 13323a4a2141SAxel Dörfler BView* view = this; 13333a4a2141SAxel Dörfler if (fOffscreen != NULL) { 13343a4a2141SAxel Dörfler fOffscreen->Lock(); 13359c89c450SAxel Dörfler view = _OffscreenView(); 13363a4a2141SAxel Dörfler } 13373a4a2141SAxel Dörfler 13383a4a2141SAxel Dörfler BRect frame = _HistoryFrame(); 1339ed1b2753SStephan Aßmus BRect outerFrame = frame.InsetByCopy(-2, -2); 1340ed1b2753SStephan Aßmus 1341ed1b2753SStephan Aßmus // draw the outer frame 1342ed1b2753SStephan Aßmus uint32 flags = 0; 1343ed1b2753SStephan Aßmus if (!drawBackground) 1344ed1b2753SStephan Aßmus flags |= BControlLook::B_BLEND_FRAME; 1345ed1b2753SStephan Aßmus be_control_look->DrawTextControlBorder(this, outerFrame, 1346ed1b2753SStephan Aßmus outerFrame, fLegendBackgroundColor, flags); 1347ed1b2753SStephan Aßmus 1348ed1b2753SStephan Aßmus // convert to offscreen view if necessary 1349ed1b2753SStephan Aßmus if (view != this) 1350ed1b2753SStephan Aßmus frame.OffsetTo(B_ORIGIN); 1351ed1b2753SStephan Aßmus 13521201d52eSAxel Dörfler view->SetLowColor(fHistoryBackgroundColor); 13533a4a2141SAxel Dörfler view->FillRect(frame, B_SOLID_LOW); 13543a4a2141SAxel Dörfler 135518d3e65eSAxel Dörfler uint32 step = 2; 135618d3e65eSAxel Dörfler uint32 resolution = fDrawResolution; 135718d3e65eSAxel Dörfler if (fDrawResolution > 1) { 135818d3e65eSAxel Dörfler step = 1; 135918d3e65eSAxel Dörfler resolution--; 136018d3e65eSAxel Dörfler } 136118d3e65eSAxel Dörfler 13623a4a2141SAxel Dörfler uint32 width = frame.IntegerWidth() - 10; 136318d3e65eSAxel Dörfler uint32 steps = width / step; 13641bb87bd0SAxel Dörfler bigtime_t timeStep = RefreshInterval() * resolution; 136518d3e65eSAxel Dörfler bigtime_t now = system_time(); 136618d3e65eSAxel Dörfler 13671201d52eSAxel Dörfler // Draw scale 13681201d52eSAxel Dörfler // TODO: add second markers? 13691201d52eSAxel Dörfler 13703a4a2141SAxel Dörfler view->SetPenSize(1); 13713a4a2141SAxel Dörfler 13721201d52eSAxel Dörfler rgb_color scaleColor = view->LowColor(); 13731201d52eSAxel Dörfler uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3; 13741201d52eSAxel Dörfler if (average < 96) 13751201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT); 13761201d52eSAxel Dörfler else 13771201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT); 13781201d52eSAxel Dörfler 13791201d52eSAxel Dörfler view->SetHighColor(scaleColor); 13803a4a2141SAxel Dörfler view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2), 13813a4a2141SAxel Dörfler BPoint(frame.right, frame.top + frame.Height() / 2)); 13823a4a2141SAxel Dörfler 13831201d52eSAxel Dörfler // Draw values 13841201d52eSAxel Dörfler 13851bb87bd0SAxel Dörfler view->SetPenSize(1.5); 1386d4216445SAxel Dörfler BAutolock _(fSourcesLock); 138718d3e65eSAxel Dörfler 138818d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) { 13898e26f387SAxel Dörfler ViewHistory* viewValues = fViewValues.ItemAt(i); 139018d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 139118d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i); 139218d3e65eSAxel Dörfler 13938e26f387SAxel Dörfler viewValues->Update(values, steps, fDrawResolution, now, timeStep, 13948e26f387SAxel Dörfler RefreshInterval()); 13958e26f387SAxel Dörfler 13968e26f387SAxel Dörfler uint32 x = viewValues->Start() * step; 13978e26f387SAxel Dörfler BShape shape; 13988e26f387SAxel Dörfler bool first = true; 13998e26f387SAxel Dörfler 14008e26f387SAxel Dörfler for (uint32 i = viewValues->Start(); i < steps; x += step, i++) { 14018e26f387SAxel Dörfler float y = _PositionForValue(source, values, 14028e26f387SAxel Dörfler viewValues->ValueAt(i)); 14038e26f387SAxel Dörfler 14048e26f387SAxel Dörfler if (first) { 14058e26f387SAxel Dörfler shape.MoveTo(BPoint(x, y)); 14068e26f387SAxel Dörfler first = false; 14078e26f387SAxel Dörfler } else 14088e26f387SAxel Dörfler shape.LineTo(BPoint(x, y)); 14098e26f387SAxel Dörfler } 14108e26f387SAxel Dörfler 14113a4a2141SAxel Dörfler view->SetHighColor(source->Color()); 14128e26f387SAxel Dörfler view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN); 14138e26f387SAxel Dörfler view->MovePenTo(B_ORIGIN); 14148e26f387SAxel Dörfler view->StrokeShape(&shape); 141518d3e65eSAxel Dörfler } 141618d3e65eSAxel Dörfler 141718d3e65eSAxel Dörfler // TODO: add marks when an app started or quit 14183a4a2141SAxel Dörfler view->Sync(); 14193a4a2141SAxel Dörfler if (fOffscreen != NULL) { 14203a4a2141SAxel Dörfler fOffscreen->Unlock(); 1421ed1b2753SStephan Aßmus DrawBitmap(fOffscreen, outerFrame.LeftTop()); 14223a4a2141SAxel Dörfler } 14233a4a2141SAxel Dörfler } 14243a4a2141SAxel Dörfler 14253a4a2141SAxel Dörfler 14263a4a2141SAxel Dörfler void 14271bb87bd0SAxel Dörfler ActivityView::_UpdateResolution(int32 resolution, bool broadcast) 14281bb87bd0SAxel Dörfler { 14291bb87bd0SAxel Dörfler if (resolution < 1) 14301bb87bd0SAxel Dörfler resolution = 1; 14311bb87bd0SAxel Dörfler if (resolution > 128) 14321bb87bd0SAxel Dörfler resolution = 128; 14331bb87bd0SAxel Dörfler 14341bb87bd0SAxel Dörfler if (resolution == fDrawResolution) 14351bb87bd0SAxel Dörfler return; 14361bb87bd0SAxel Dörfler 14371bb87bd0SAxel Dörfler ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window()); 14381bb87bd0SAxel Dörfler if (broadcast && window != NULL) { 14391bb87bd0SAxel Dörfler BMessage update(kMsgUpdateResolution); 14401bb87bd0SAxel Dörfler update.AddInt32("resolution", resolution); 14411bb87bd0SAxel Dörfler window->BroadcastToActivityViews(&update, this); 14421bb87bd0SAxel Dörfler } 14431bb87bd0SAxel Dörfler 14441bb87bd0SAxel Dörfler fDrawResolution = resolution; 14451bb87bd0SAxel Dörfler Invalidate(); 14461bb87bd0SAxel Dörfler } 14471bb87bd0SAxel Dörfler 14481bb87bd0SAxel Dörfler 14491bb87bd0SAxel Dörfler void 1450ed1b2753SStephan Aßmus ActivityView::Draw(BRect updateRect) 14513a4a2141SAxel Dörfler { 1452ed1b2753SStephan Aßmus bool drawBackground = true; 1453ed1b2753SStephan Aßmus if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0) 1454ed1b2753SStephan Aßmus drawBackground = false; 1455ed1b2753SStephan Aßmus 1456ed1b2753SStephan Aßmus _DrawHistory(drawBackground); 14573a4a2141SAxel Dörfler 14583a4a2141SAxel Dörfler if (!fShowLegend) 14593a4a2141SAxel Dörfler return; 14603a4a2141SAxel Dörfler 14613a4a2141SAxel Dörfler // draw legend 1462ed1b2753SStephan Aßmus BRect legendFrame = _LegendFrame(); 1463ed1b2753SStephan Aßmus SetLowColor(fLegendBackgroundColor); 14649bd81dbeSStephan Aßmus if (drawBackground) { 14659bd81dbeSStephan Aßmus BRect backgroundFrame(legendFrame); 14669bd81dbeSStephan Aßmus backgroundFrame.bottom += kDraggerSize; 14679bd81dbeSStephan Aßmus FillRect(backgroundFrame, B_SOLID_LOW); 14689bd81dbeSStephan Aßmus } 14693a4a2141SAxel Dörfler 1470d4216445SAxel Dörfler BAutolock _(fSourcesLock); 14713a4a2141SAxel Dörfler 14723a4a2141SAxel Dörfler font_height fontHeight; 14733a4a2141SAxel Dörfler GetFontHeight(&fontHeight); 14743a4a2141SAxel Dörfler 14753a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 14763a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i); 14773a4a2141SAxel Dörfler DataHistory* values = fValues.ItemAt(i); 14783a4a2141SAxel Dörfler BRect frame = _LegendFrameAt(legendFrame, i); 14793a4a2141SAxel Dörfler 14803a4a2141SAxel Dörfler // draw color box 14811201d52eSAxel Dörfler BRect colorBox = _LegendColorFrameAt(legendFrame, i); 1482ed1b2753SStephan Aßmus BRect rect = colorBox; 1483ed1b2753SStephan Aßmus uint32 flags = BControlLook::B_BLEND_FRAME; 1484ed1b2753SStephan Aßmus be_control_look->DrawTextControlBorder(this, rect, 1485ed1b2753SStephan Aßmus rect, fLegendBackgroundColor, flags); 14863a4a2141SAxel Dörfler SetHighColor(source->Color()); 1487ed1b2753SStephan Aßmus FillRect(rect); 14883a4a2141SAxel Dörfler 14893a4a2141SAxel Dörfler // show current value and label 14903a4a2141SAxel Dörfler float y = frame.top + ceilf(fontHeight.ascent); 14913a4a2141SAxel Dörfler int64 value = values->ValueAt(values->End()); 14923a4a2141SAxel Dörfler BString text; 14933a4a2141SAxel Dörfler source->Print(text, value); 14943a4a2141SAxel Dörfler float width = StringWidth(text.String()); 14953a4a2141SAxel Dörfler 14963a4a2141SAxel Dörfler BString label = source->Label(); 1497ed1b2753SStephan Aßmus float possibleLabelWidth = frame.right - colorBox.right - 12 - width; 1498ed1b2753SStephan Aßmus // TODO: TruncateString() is broken... remove + 5 when fixed! 1499ed1b2753SStephan Aßmus if (ceilf(StringWidth(label.String()) + 5) > possibleLabelWidth) 1500ed1b2753SStephan Aßmus label = source->ShortLabel(); 1501ed1b2753SStephan Aßmus TruncateString(&label, B_TRUNCATE_MIDDLE, possibleLabelWidth); 15023a4a2141SAxel Dörfler 1503ed1b2753SStephan Aßmus if (drawBackground) 15043a4a2141SAxel Dörfler SetHighColor(ui_color(B_CONTROL_TEXT_COLOR)); 1505bb7cffd0SPhilippe Saint-Pierre 1506d63b75faSPhilippe Saint-Pierre if (be_control_look == NULL) { 1507bb7cffd0SPhilippe Saint-Pierre DrawString(label.String(), BPoint(6 + colorBox.right, y)); 1508bb7cffd0SPhilippe Saint-Pierre DrawString(text.String(), BPoint(frame.right - width, y)); 1509bb7cffd0SPhilippe Saint-Pierre } else { 1510d63b75faSPhilippe Saint-Pierre be_control_look->DrawLabel(this, label.String(), 1511d63b75faSPhilippe Saint-Pierre Parent()->ViewColor(), 0, BPoint(6 + colorBox.right, y)); 1512d63b75faSPhilippe Saint-Pierre be_control_look->DrawLabel(this, text.String(), 1513d63b75faSPhilippe Saint-Pierre Parent()->ViewColor(), 0, BPoint(frame.right - width, y)); 1514bb7cffd0SPhilippe Saint-Pierre } 1515bb7cffd0SPhilippe Saint-Pierre } 151618d3e65eSAxel Dörfler } 151718d3e65eSAxel Dörfler 151818d3e65eSAxel Dörfler 151918d3e65eSAxel Dörfler void 152018d3e65eSAxel Dörfler ActivityView::_Refresh() 152118d3e65eSAxel Dörfler { 15221bb87bd0SAxel Dörfler bigtime_t lastTimeout = system_time() - RefreshInterval(); 15234ce1e1d2SAxel Dörfler BMessenger target(this); 152418d3e65eSAxel Dörfler 1525d4216445SAxel Dörfler while (true) { 1526d4216445SAxel Dörfler status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT, 15271bb87bd0SAxel Dörfler lastTimeout + RefreshInterval()); 1528d4216445SAxel Dörfler if (status == B_OK || status == B_BAD_SEM_ID) 1529d4216445SAxel Dörfler break; 1530d4216445SAxel Dörfler if (status == B_INTERRUPTED) 1531d4216445SAxel Dörfler continue; 1532d4216445SAxel Dörfler 1533d4216445SAxel Dörfler SystemInfo info(fSystemInfoHandler); 15341bb87bd0SAxel Dörfler lastTimeout += RefreshInterval(); 1535d4216445SAxel Dörfler 1536d4216445SAxel Dörfler fSourcesLock.Lock(); 153718d3e65eSAxel Dörfler 153818d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) { 153918d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 154018d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i); 154118d3e65eSAxel Dörfler 154218d3e65eSAxel Dörfler int64 value = source->NextValue(info); 154318d3e65eSAxel Dörfler values->AddValue(info.Time(), value); 154418d3e65eSAxel Dörfler } 154518d3e65eSAxel Dörfler 1546d4216445SAxel Dörfler fSourcesLock.Unlock(); 1547d4216445SAxel Dörfler 15484ce1e1d2SAxel Dörfler target.SendMessage(B_INVALIDATE); 154918d3e65eSAxel Dörfler } 1550d4216445SAxel Dörfler } 155118d3e65eSAxel Dörfler 1552d4216445SAxel Dörfler 1553d4216445SAxel Dörfler /*static*/ status_t 1554d4216445SAxel Dörfler ActivityView::_RefreshThread(void* self) 1555d4216445SAxel Dörfler { 1556d4216445SAxel Dörfler ((ActivityView*)self)->_Refresh(); 1557d4216445SAxel Dörfler return B_OK; 1558d4216445SAxel Dörfler } 1559