118d3e65eSAxel Dörfler /*
227231d80SAxel Dörfler * Copyright 2008-2015, 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:
ListAddDeleter(BObjectList<ObjectType> & list,ObjectType * object,int32 spot)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
~ListAddDeleter()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
Failed() const628e26f387SAxel Dörfler bool Failed() const
638e26f387SAxel Dörfler {
648e26f387SAxel Dörfler return fObject == NULL;
658e26f387SAxel Dörfler }
668e26f387SAxel Dörfler
Detach()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
MinimumValue() const8651591198SAxel Dörfler int64 MinimumValue() const { return fMinimumValue; }
MaximumValue() const8751591198SAxel 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
Start() const1108e26f387SAxel 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
Scale(scale_type type)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
Update(int64 value)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
ViewHistory()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
ValueAt(int32 x)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
Update(DataHistory * history,int32 width,int32 resolution,bigtime_t toTime,bigtime_t step,bigtime_t refresh)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
DataHistory(bigtime_t memorize,bigtime_t interval)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
~DataHistory()29618d3e65eSAxel Dörfler DataHistory::~DataHistory()
29718d3e65eSAxel Dörfler {
29818d3e65eSAxel Dörfler }
29918d3e65eSAxel Dörfler
30018d3e65eSAxel Dörfler
30118d3e65eSAxel Dörfler void
AddValue(bigtime_t time,int64 value)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
ValueAt(bigtime_t time)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
MaximumValue() const35218d3e65eSAxel 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
MinimumValue() const36218d3e65eSAxel 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
Start() const37218d3e65eSAxel 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
End() const38218d3e65eSAxel 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
SetRefreshInterval(bigtime_t interval)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
SetScale(Scale * scale)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__
HistoryLayoutItem(ActivityView * parent)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
IsVisible()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
SetVisible(bool visible)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
Frame()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
SetFrame(BRect frame)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*
View()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
BasePreferredSize()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
LegendLayoutItem(ActivityView * parent)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
IsVisible()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
SetVisible(bool visible)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
Frame()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
SetFrame(BRect frame)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*
View()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
BaseMinSize()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
BaseMaxSize()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
BasePreferredSize()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
BaseAlignment()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
ActivityView(BRect frame,const char * name,const BMessage * settings,uint32 resizingMode)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,
556*0f2661ccSAdrien Destugues 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
ActivityView(const char * name,const BMessage * settings)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 {
579fa19dd44Slooncraz SetLowUIColor(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
ActivityView(BMessage * archive)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
~ActivityView()59918d3e65eSAxel Dörfler ActivityView::~ActivityView()
60018d3e65eSAxel Dörfler {
601*0f2661ccSAdrien Destugues delete fOffscreen;
60274158bb4SFrançois Revol delete fSystemInfoHandler;
60318d3e65eSAxel Dörfler }
60418d3e65eSAxel Dörfler
60518d3e65eSAxel Dörfler
60618d3e65eSAxel Dörfler void
_Init(const BMessage * settings)60718d3e65eSAxel Dörfler ActivityView::_Init(const BMessage* settings)
60818d3e65eSAxel Dörfler {
6099c89c450SAxel Dörfler fHistoryBackgroundColor = (rgb_color){255, 255, 240};
6109c89c450SAxel Dörfler fLegendBackgroundColor = LowColor();
6119c89c450SAxel Dörfler // the low color is restored by the BView unarchiving
612*0f2661ccSAdrien Destugues fOffscreen = NULL;
613dc1ffc79SFrançois Revol #ifdef __HAIKU__
614065e8de0SAxel Dörfler fHistoryLayoutItem = NULL;
615065e8de0SAxel Dörfler fLegendLayoutItem = NULL;
616dc1ffc79SFrançois Revol #endif
6173a4a2141SAxel Dörfler SetViewColor(B_TRANSPARENT_COLOR);
61847102c07SX512 SetFlags(Flags() | B_TRANSPARENT_BACKGROUND);
61918d3e65eSAxel Dörfler
62018d3e65eSAxel Dörfler fLastRefresh = 0;
62118d3e65eSAxel Dörfler fDrawResolution = 1;
62251591198SAxel Dörfler fZooming = false;
62318d3e65eSAxel Dörfler
62474158bb4SFrançois Revol fSystemInfoHandler = new SystemInfoHandler;
62574158bb4SFrançois Revol
6263a4a2141SAxel Dörfler if (settings == NULL
627eee6f40bSAlexandre Deckner || settings->FindInt64("refresh interval", &fRefreshInterval) != B_OK)
628eee6f40bSAlexandre Deckner fRefreshInterval = kInitialRefreshInterval;
629eee6f40bSAlexandre Deckner
630eee6f40bSAlexandre Deckner if (settings == NULL
6313a4a2141SAxel Dörfler || settings->FindBool("show legend", &fShowLegend) != B_OK)
6323a4a2141SAxel Dörfler fShowLegend = true;
6333a4a2141SAxel Dörfler
63451591198SAxel Dörfler if (settings == NULL)
6353a4a2141SAxel Dörfler return;
6363a4a2141SAxel Dörfler
6379c89c450SAxel Dörfler ssize_t colorLength;
63879cbd226SFrançois Revol rgb_color *color;
6399c89c450SAxel Dörfler if (settings->FindData("history background color", B_RGB_COLOR_TYPE,
6409c89c450SAxel Dörfler (const void **)&color, &colorLength) == B_OK
6419c89c450SAxel Dörfler && colorLength == sizeof(rgb_color))
6429c89c450SAxel Dörfler fHistoryBackgroundColor = *color;
64379cbd226SFrançois Revol
6443a4a2141SAxel Dörfler const char* name;
645d1901581SStephan Aßmus for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++)
6461201d52eSAxel Dörfler AddDataSource(DataSource::FindSource(name), settings);
6473a4a2141SAxel Dörfler }
64818d3e65eSAxel Dörfler
64918d3e65eSAxel Dörfler
65018d3e65eSAxel Dörfler status_t
Archive(BMessage * into,bool deep) const65118d3e65eSAxel Dörfler ActivityView::Archive(BMessage* into, bool deep) const
65218d3e65eSAxel Dörfler {
65318d3e65eSAxel Dörfler status_t status;
65418d3e65eSAxel Dörfler
65518d3e65eSAxel Dörfler status = BView::Archive(into, deep);
65618d3e65eSAxel Dörfler if (status < B_OK)
65718d3e65eSAxel Dörfler return status;
65818d3e65eSAxel Dörfler
65918d3e65eSAxel Dörfler status = into->AddString("add_on", kSignature);
66018d3e65eSAxel Dörfler if (status < B_OK)
66118d3e65eSAxel Dörfler return status;
66218d3e65eSAxel Dörfler
66318d3e65eSAxel Dörfler status = SaveState(*into);
66418d3e65eSAxel Dörfler if (status < B_OK)
66518d3e65eSAxel Dörfler return status;
66618d3e65eSAxel Dörfler
66718d3e65eSAxel Dörfler return B_OK;
66818d3e65eSAxel Dörfler }
66918d3e65eSAxel Dörfler
67018d3e65eSAxel Dörfler
67118d3e65eSAxel Dörfler BArchivable*
Instantiate(BMessage * archive)67218d3e65eSAxel Dörfler ActivityView::Instantiate(BMessage* archive)
67318d3e65eSAxel Dörfler {
67418d3e65eSAxel Dörfler if (!validate_instantiation(archive, "ActivityView"))
67518d3e65eSAxel Dörfler return NULL;
67618d3e65eSAxel Dörfler
67718d3e65eSAxel Dörfler return new ActivityView(archive);
67818d3e65eSAxel Dörfler }
67918d3e65eSAxel Dörfler
68018d3e65eSAxel Dörfler
68118d3e65eSAxel Dörfler status_t
SaveState(BMessage & state) const68218d3e65eSAxel Dörfler ActivityView::SaveState(BMessage& state) const
68318d3e65eSAxel Dörfler {
6843a4a2141SAxel Dörfler status_t status = state.AddBool("show legend", fShowLegend);
6853a4a2141SAxel Dörfler if (status != B_OK)
6863a4a2141SAxel Dörfler return status;
6873a4a2141SAxel Dörfler
688eee6f40bSAlexandre Deckner status = state.AddInt64("refresh interval", fRefreshInterval);
689eee6f40bSAlexandre Deckner if (status != B_OK)
690eee6f40bSAlexandre Deckner return status;
691eee6f40bSAlexandre Deckner
6929c89c450SAxel Dörfler status = state.AddData("history background color", B_RGB_COLOR_TYPE,
6939c89c450SAxel Dörfler &fHistoryBackgroundColor, sizeof(rgb_color));
69479cbd226SFrançois Revol if (status != B_OK)
69579cbd226SFrançois Revol return status;
69679cbd226SFrançois Revol
6973a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) {
6983a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i);
6993a4a2141SAxel Dörfler
7003a4a2141SAxel Dörfler if (!source->PerCPU() || source->CPU() == 0)
701d1901581SStephan Aßmus status = state.AddString("source", source->InternalName());
7023a4a2141SAxel Dörfler if (status != B_OK)
7033a4a2141SAxel Dörfler return status;
7043a4a2141SAxel Dörfler
7059c89c450SAxel Dörfler BString name = source->Name();
7069c89c450SAxel Dörfler name << " color";
7079c89c450SAxel Dörfler rgb_color color = source->Color();
7089c89c450SAxel Dörfler state.AddData(name.String(), B_RGB_COLOR_TYPE, &color,
7099c89c450SAxel Dörfler sizeof(rgb_color));
7103a4a2141SAxel Dörfler }
7113a4a2141SAxel Dörfler return B_OK;
71218d3e65eSAxel Dörfler }
71318d3e65eSAxel Dörfler
71418d3e65eSAxel Dörfler
71551591198SAxel Dörfler Scale*
_ScaleFor(scale_type type)71651591198SAxel Dörfler ActivityView::_ScaleFor(scale_type type)
71751591198SAxel Dörfler {
71851591198SAxel Dörfler if (type == kNoScale)
71951591198SAxel Dörfler return NULL;
72051591198SAxel Dörfler
72151591198SAxel Dörfler std::map<scale_type, ::Scale*>::iterator iterator = fScales.find(type);
72251591198SAxel Dörfler if (iterator != fScales.end())
72351591198SAxel Dörfler return iterator->second;
72451591198SAxel Dörfler
72551591198SAxel Dörfler // add new scale
72651591198SAxel Dörfler ::Scale* scale = new ::Scale(type);
72751591198SAxel Dörfler fScales[type] = scale;
72851591198SAxel Dörfler
72951591198SAxel Dörfler return scale;
73051591198SAxel Dörfler }
73151591198SAxel Dörfler
73251591198SAxel Dörfler
733dc1ffc79SFrançois Revol #ifdef __HAIKU__
734065e8de0SAxel Dörfler BLayoutItem*
CreateHistoryLayoutItem()735065e8de0SAxel Dörfler ActivityView::CreateHistoryLayoutItem()
736065e8de0SAxel Dörfler {
737065e8de0SAxel Dörfler if (fHistoryLayoutItem == NULL)
738065e8de0SAxel Dörfler fHistoryLayoutItem = new HistoryLayoutItem(this);
739065e8de0SAxel Dörfler
740065e8de0SAxel Dörfler return fHistoryLayoutItem;
741065e8de0SAxel Dörfler }
742065e8de0SAxel Dörfler
743065e8de0SAxel Dörfler
744065e8de0SAxel Dörfler BLayoutItem*
CreateLegendLayoutItem()745065e8de0SAxel Dörfler ActivityView::CreateLegendLayoutItem()
746065e8de0SAxel Dörfler {
747065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL)
748065e8de0SAxel Dörfler fLegendLayoutItem = new LegendLayoutItem(this);
749065e8de0SAxel Dörfler
750065e8de0SAxel Dörfler return fLegendLayoutItem;
751065e8de0SAxel Dörfler }
752dc1ffc79SFrançois Revol #endif
753065e8de0SAxel Dörfler
7549c89c450SAxel Dörfler
75518d3e65eSAxel Dörfler DataSource*
FindDataSource(const DataSource * search)7563a4a2141SAxel Dörfler ActivityView::FindDataSource(const DataSource* search)
75718d3e65eSAxel Dörfler {
758d4216445SAxel Dörfler BAutolock _(fSourcesLock);
759d4216445SAxel Dörfler
76018d3e65eSAxel Dörfler for (int32 i = fSources.CountItems(); i-- > 0;) {
76118d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i);
7623a4a2141SAxel Dörfler if (!strcmp(source->Name(), search->Name()))
76318d3e65eSAxel Dörfler return source;
76418d3e65eSAxel Dörfler }
76518d3e65eSAxel Dörfler
76618d3e65eSAxel Dörfler return NULL;
76718d3e65eSAxel Dörfler }
76818d3e65eSAxel Dörfler
76918d3e65eSAxel Dörfler
77018d3e65eSAxel Dörfler status_t
AddDataSource(const DataSource * source,const BMessage * state)7719c89c450SAxel Dörfler ActivityView::AddDataSource(const DataSource* source, const BMessage* state)
77218d3e65eSAxel Dörfler {
7733a4a2141SAxel Dörfler if (source == NULL)
7743a4a2141SAxel Dörfler return B_BAD_VALUE;
7753a4a2141SAxel Dörfler
776d4216445SAxel Dörfler BAutolock _(fSourcesLock);
777d4216445SAxel Dörfler
7788e26f387SAxel Dörfler // Search for the correct insert spot to maintain the order of the sources
7793a4a2141SAxel Dörfler int32 insert = DataSource::IndexOf(source);
7803a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) {
7813a4a2141SAxel Dörfler DataSource* before = fSources.ItemAt(i);
7823a4a2141SAxel Dörfler if (DataSource::IndexOf(before) > insert) {
7833a4a2141SAxel Dörfler insert = i;
7843a4a2141SAxel Dörfler break;
7853a4a2141SAxel Dörfler }
7863a4a2141SAxel Dörfler }
7873a4a2141SAxel Dörfler if (insert > fSources.CountItems())
7883a4a2141SAxel Dörfler insert = fSources.CountItems();
7893a4a2141SAxel Dörfler
7908e26f387SAxel Dörfler // Generate DataHistory and ViewHistory objects for the source
7918e26f387SAxel Dörfler // (one might need one history per CPU)
7928e26f387SAxel Dörfler
7933a4a2141SAxel Dörfler uint32 count = 1;
7943a4a2141SAxel Dörfler if (source->PerCPU()) {
7953a4a2141SAxel Dörfler SystemInfo info;
7963a4a2141SAxel Dörfler count = info.CPUCount();
7973a4a2141SAxel Dörfler }
7983a4a2141SAxel Dörfler
7993a4a2141SAxel Dörfler for (uint32 i = 0; i < count; i++) {
80018d3e65eSAxel Dörfler DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
8011bb87bd0SAxel Dörfler RefreshInterval());
8028e26f387SAxel Dörfler ListAddDeleter<DataHistory> valuesDeleter(fValues, values, insert);
8033a4a2141SAxel Dörfler
8048e26f387SAxel Dörfler ViewHistory* viewValues = new(std::nothrow) ViewHistory;
8058e26f387SAxel Dörfler ListAddDeleter<ViewHistory> viewValuesDeleter(fViewValues, viewValues,
8068e26f387SAxel Dörfler insert);
8078e26f387SAxel Dörfler
8088e26f387SAxel Dörfler if (valuesDeleter.Failed() || viewValuesDeleter.Failed())
80918d3e65eSAxel Dörfler return B_NO_MEMORY;
81018d3e65eSAxel Dörfler
81151591198SAxel Dörfler values->SetScale(_ScaleFor(source->ScaleType()));
81251591198SAxel Dörfler
8133a4a2141SAxel Dörfler DataSource* copy;
8143a4a2141SAxel Dörfler if (source->PerCPU())
8153a4a2141SAxel Dörfler copy = source->CopyForCPU(i);
8163a4a2141SAxel Dörfler else
8173a4a2141SAxel Dörfler copy = source->Copy();
8183a4a2141SAxel Dörfler
8198e26f387SAxel Dörfler ListAddDeleter<DataSource> sourceDeleter(fSources, copy, insert);
8208e26f387SAxel Dörfler if (sourceDeleter.Failed())
8218e26f387SAxel Dörfler return B_NO_MEMORY;
8228e26f387SAxel Dörfler
8239c89c450SAxel Dörfler BString colorName = source->Name();
8249c89c450SAxel Dörfler colorName << " color";
8259c89c450SAxel Dörfler if (state != NULL) {
8269c89c450SAxel Dörfler const rgb_color* color = NULL;
8279c89c450SAxel Dörfler ssize_t colorLength;
8289c89c450SAxel Dörfler if (state->FindData(colorName.String(), B_RGB_COLOR_TYPE, i,
8299c89c450SAxel Dörfler (const void**)&color, &colorLength) == B_OK
8309c89c450SAxel Dörfler && colorLength == sizeof(rgb_color))
8319c89c450SAxel Dörfler copy->SetColor(*color);
8329c89c450SAxel Dörfler }
8339c89c450SAxel Dörfler
8348e26f387SAxel Dörfler valuesDeleter.Detach();
8358e26f387SAxel Dörfler viewValuesDeleter.Detach();
8368e26f387SAxel Dörfler sourceDeleter.Detach();
837be3f9645SAxel Dörfler insert++;
8383a4a2141SAxel Dörfler }
83918d3e65eSAxel Dörfler
840dc1ffc79SFrançois Revol #ifdef __HAIKU__
841065e8de0SAxel Dörfler InvalidateLayout();
842dc1ffc79SFrançois Revol #endif
84318d3e65eSAxel Dörfler return B_OK;
84418d3e65eSAxel Dörfler }
84518d3e65eSAxel Dörfler
84618d3e65eSAxel Dörfler
84718d3e65eSAxel Dörfler status_t
RemoveDataSource(const DataSource * remove)8483a4a2141SAxel Dörfler ActivityView::RemoveDataSource(const DataSource* remove)
84918d3e65eSAxel Dörfler {
850065e8de0SAxel Dörfler bool removed = false;
851065e8de0SAxel Dörfler
852d4216445SAxel Dörfler BAutolock _(fSourcesLock);
853d4216445SAxel Dörfler
8543a4a2141SAxel Dörfler while (true) {
8553a4a2141SAxel Dörfler DataSource* source = FindDataSource(remove);
856065e8de0SAxel Dörfler if (source == NULL) {
857065e8de0SAxel Dörfler if (removed)
858065e8de0SAxel Dörfler break;
859065e8de0SAxel Dörfler return B_ENTRY_NOT_FOUND;
860065e8de0SAxel Dörfler }
8613a4a2141SAxel Dörfler
86218d3e65eSAxel Dörfler int32 index = fSources.IndexOf(source);
86318d3e65eSAxel Dörfler if (index < 0)
86418d3e65eSAxel Dörfler return B_ENTRY_NOT_FOUND;
86518d3e65eSAxel Dörfler
86618d3e65eSAxel Dörfler fSources.RemoveItemAt(index);
86718d3e65eSAxel Dörfler delete source;
86818d3e65eSAxel Dörfler DataHistory* values = fValues.RemoveItemAt(index);
86918d3e65eSAxel Dörfler delete values;
870065e8de0SAxel Dörfler removed = true;
8713a4a2141SAxel Dörfler }
87218d3e65eSAxel Dörfler
873dc1ffc79SFrançois Revol #ifdef __HAIKU__
874065e8de0SAxel Dörfler InvalidateLayout();
875dc1ffc79SFrançois Revol #endif
87618d3e65eSAxel Dörfler return B_OK;
87718d3e65eSAxel Dörfler }
87818d3e65eSAxel Dörfler
87918d3e65eSAxel Dörfler
88018d3e65eSAxel Dörfler void
RemoveAllDataSources()88118d3e65eSAxel Dörfler ActivityView::RemoveAllDataSources()
88218d3e65eSAxel Dörfler {
883d4216445SAxel Dörfler BAutolock _(fSourcesLock);
884d4216445SAxel Dörfler
88518d3e65eSAxel Dörfler fSources.MakeEmpty();
88618d3e65eSAxel Dörfler fValues.MakeEmpty();
88718d3e65eSAxel Dörfler }
88818d3e65eSAxel Dörfler
88918d3e65eSAxel Dörfler
89018d3e65eSAxel Dörfler void
AttachedToWindow()89118d3e65eSAxel Dörfler ActivityView::AttachedToWindow()
89218d3e65eSAxel Dörfler {
89374158bb4SFrançois Revol Looper()->AddHandler(fSystemInfoHandler);
8946f6ba875SAxel Dörfler fSystemInfoHandler->StartWatching();
8956f6ba875SAxel Dörfler
896d4216445SAxel Dörfler fRefreshSem = create_sem(0, "refresh sem");
897d4216445SAxel Dörfler fRefreshThread = spawn_thread(&_RefreshThread, "source refresh",
8988e26f387SAxel Dörfler B_URGENT_DISPLAY_PRIORITY, this);
899d4216445SAxel Dörfler resume_thread(fRefreshThread);
9003a4a2141SAxel Dörfler
9013a4a2141SAxel Dörfler FrameResized(Bounds().Width(), Bounds().Height());
90218d3e65eSAxel Dörfler }
90318d3e65eSAxel Dörfler
90418d3e65eSAxel Dörfler
90518d3e65eSAxel Dörfler void
DetachedFromWindow()90618d3e65eSAxel Dörfler ActivityView::DetachedFromWindow()
90718d3e65eSAxel Dörfler {
9086f6ba875SAxel Dörfler fSystemInfoHandler->StopWatching();
90974158bb4SFrançois Revol Looper()->RemoveHandler(fSystemInfoHandler);
9106f6ba875SAxel Dörfler
911d4216445SAxel Dörfler delete_sem(fRefreshSem);
912d4216445SAxel Dörfler wait_for_thread(fRefreshThread, NULL);
91318d3e65eSAxel Dörfler }
91418d3e65eSAxel Dörfler
91518d3e65eSAxel Dörfler
916cbd4bc95SFrançois Revol #ifdef __HAIKU__
9173a4a2141SAxel Dörfler BSize
MinSize()9183a4a2141SAxel Dörfler ActivityView::MinSize()
9193a4a2141SAxel Dörfler {
9203a4a2141SAxel Dörfler BSize size(32, 32);
9213a4a2141SAxel Dörfler if (fShowLegend)
9229c89c450SAxel Dörfler size.height = _LegendHeight();
9233a4a2141SAxel Dörfler
9243a4a2141SAxel Dörfler return size;
9253a4a2141SAxel Dörfler }
926cbd4bc95SFrançois Revol #endif
9273a4a2141SAxel Dörfler
9283a4a2141SAxel Dörfler
92918d3e65eSAxel Dörfler void
FrameResized(float,float)930*0f2661ccSAdrien Destugues ActivityView::FrameResized(float /*width*/, float /*height*/)
931*0f2661ccSAdrien Destugues {
932*0f2661ccSAdrien Destugues _UpdateOffscreenBitmap();
933*0f2661ccSAdrien Destugues }
934*0f2661ccSAdrien Destugues
935*0f2661ccSAdrien Destugues
936*0f2661ccSAdrien Destugues void
_UpdateOffscreenBitmap()937*0f2661ccSAdrien Destugues ActivityView::_UpdateOffscreenBitmap()
938*0f2661ccSAdrien Destugues {
939*0f2661ccSAdrien Destugues BRect frame = _HistoryFrame();
940*0f2661ccSAdrien Destugues frame.OffsetTo(B_ORIGIN);
941*0f2661ccSAdrien Destugues
942*0f2661ccSAdrien Destugues if (fOffscreen != NULL && frame == fOffscreen->Bounds())
943*0f2661ccSAdrien Destugues return;
944*0f2661ccSAdrien Destugues
945*0f2661ccSAdrien Destugues delete fOffscreen;
946*0f2661ccSAdrien Destugues
947*0f2661ccSAdrien Destugues // create offscreen bitmap
948*0f2661ccSAdrien Destugues
949*0f2661ccSAdrien Destugues fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS,
950*0f2661ccSAdrien Destugues B_RGB32);
951*0f2661ccSAdrien Destugues if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) {
952*0f2661ccSAdrien Destugues delete fOffscreen;
953*0f2661ccSAdrien Destugues fOffscreen = NULL;
954*0f2661ccSAdrien Destugues return;
955*0f2661ccSAdrien Destugues }
956*0f2661ccSAdrien Destugues
957*0f2661ccSAdrien Destugues BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE);
958*0f2661ccSAdrien Destugues view->SetViewColor(fHistoryBackgroundColor);
959*0f2661ccSAdrien Destugues view->SetLowColor(view->ViewColor());
960*0f2661ccSAdrien Destugues fOffscreen->AddChild(view);
961*0f2661ccSAdrien Destugues }
962*0f2661ccSAdrien Destugues
963*0f2661ccSAdrien Destugues
964*0f2661ccSAdrien Destugues BView*
_OffscreenView()965*0f2661ccSAdrien Destugues ActivityView::_OffscreenView()
966*0f2661ccSAdrien Destugues {
967*0f2661ccSAdrien Destugues if (fOffscreen == NULL)
968*0f2661ccSAdrien Destugues return NULL;
969*0f2661ccSAdrien Destugues
970*0f2661ccSAdrien Destugues return fOffscreen->ChildAt(0);
971*0f2661ccSAdrien Destugues }
972*0f2661ccSAdrien Destugues
973*0f2661ccSAdrien Destugues
974*0f2661ccSAdrien Destugues void
MouseDown(BPoint where)97518d3e65eSAxel Dörfler ActivityView::MouseDown(BPoint where)
97618d3e65eSAxel Dörfler {
97751591198SAxel Dörfler int32 buttons = B_SECONDARY_MOUSE_BUTTON;
97851591198SAxel Dörfler if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
97918d3e65eSAxel Dörfler Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
98051591198SAxel Dörfler
98151591198SAxel Dörfler if (buttons == B_PRIMARY_MOUSE_BUTTON) {
98251591198SAxel Dörfler fZoomPoint = where;
98351591198SAxel Dörfler fOriginalResolution = fDrawResolution;
98451591198SAxel Dörfler fZooming = true;
9858e26f387SAxel Dörfler SetMouseEventMask(B_POINTER_EVENTS);
98651591198SAxel Dörfler return;
98718d3e65eSAxel Dörfler }
98818d3e65eSAxel Dörfler
98918d3e65eSAxel Dörfler BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
99018d3e65eSAxel Dörfler menu->SetFont(be_plain_font);
9913a4a2141SAxel Dörfler
9924840a72fSPhilippe Houdoin BMenu* additionalMenu = new BMenu(B_TRANSLATE("Additional items"));
993dc1ffc79SFrançois Revol additionalMenu->SetFont(be_plain_font);
994dc1ffc79SFrançois Revol
9953a4a2141SAxel Dörfler SystemInfo info;
99618d3e65eSAxel Dörfler BMenuItem* item;
99718d3e65eSAxel Dörfler
99818d3e65eSAxel Dörfler for (int32 i = 0; i < DataSource::CountSources(); i++) {
99918d3e65eSAxel Dörfler const DataSource* source = DataSource::SourceAt(i);
100018d3e65eSAxel Dörfler
10013a4a2141SAxel Dörfler if (source->MultiCPUOnly() && info.CPUCount() == 1)
10023a4a2141SAxel Dörfler continue;
10033a4a2141SAxel Dörfler
100418d3e65eSAxel Dörfler BMessage* message = new BMessage(kMsgToggleDataSource);
100518d3e65eSAxel Dörfler message->AddInt32("index", i);
100618d3e65eSAxel Dörfler
10073a4a2141SAxel Dörfler item = new BMenuItem(source->Name(), message);
10083a4a2141SAxel Dörfler if (FindDataSource(source))
100918d3e65eSAxel Dörfler item->SetMarked(true);
101018d3e65eSAxel Dörfler
101143eda1cdSAxel Dörfler if (source->Primary())
101218d3e65eSAxel Dörfler menu->AddItem(item);
101343eda1cdSAxel Dörfler else
101443eda1cdSAxel Dörfler additionalMenu->AddItem(item);
101518d3e65eSAxel Dörfler }
101618d3e65eSAxel Dörfler
101743eda1cdSAxel Dörfler menu->AddItem(new BMenuItem(additionalMenu));
10183a4a2141SAxel Dörfler menu->AddSeparatorItem();
10197f07c303SJanus menu->AddItem(item = new BMenuItem(B_TRANSLATE("Show legend"),
10203a4a2141SAxel Dörfler new BMessage(kMsgToggleLegend)));
10217f07c303SJanus item->SetMarked(fShowLegend);
10223a4a2141SAxel Dörfler
102318d3e65eSAxel Dörfler menu->SetTargetForItems(this);
1024dc1ffc79SFrançois Revol additionalMenu->SetTargetForItems(this);
102518d3e65eSAxel Dörfler
10263f315b26SAxel Dörfler ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
10273f315b26SAxel Dörfler if (window != NULL && window->ActivityViewCount() > 1) {
10283f315b26SAxel Dörfler menu->AddSeparatorItem();
10293f315b26SAxel Dörfler BMessage* message = new BMessage(kMsgRemoveView);
10303f315b26SAxel Dörfler message->AddPointer("view", this);
10314840a72fSPhilippe Houdoin menu->AddItem(item = new BMenuItem(B_TRANSLATE("Remove graph"),
10324840a72fSPhilippe Houdoin message));
10333f315b26SAxel Dörfler item->SetTarget(window);
10343f315b26SAxel Dörfler }
10353f315b26SAxel Dörfler
103618d3e65eSAxel Dörfler ConvertToScreen(&where);
103718d3e65eSAxel Dörfler menu->Go(where, true, false, true);
103818d3e65eSAxel Dörfler }
103918d3e65eSAxel Dörfler
104018d3e65eSAxel Dörfler
104118d3e65eSAxel Dörfler void
MouseUp(BPoint where)104251591198SAxel Dörfler ActivityView::MouseUp(BPoint where)
104351591198SAxel Dörfler {
104451591198SAxel Dörfler fZooming = false;
104551591198SAxel Dörfler }
104651591198SAxel Dörfler
104751591198SAxel Dörfler
104851591198SAxel Dörfler void
MouseMoved(BPoint where,uint32 transit,const BMessage * dragMessage)104918d3e65eSAxel Dörfler ActivityView::MouseMoved(BPoint where, uint32 transit,
105018d3e65eSAxel Dörfler const BMessage* dragMessage)
105118d3e65eSAxel Dörfler {
105251591198SAxel Dörfler if (!fZooming)
105351591198SAxel Dörfler return;
105451591198SAxel Dörfler
105551591198SAxel Dörfler int32 shift = int32(where.x - fZoomPoint.x) / 25;
10561bb87bd0SAxel Dörfler int32 resolution;
105751591198SAxel Dörfler if (shift > 0)
10581bb87bd0SAxel Dörfler resolution = fOriginalResolution << shift;
105951591198SAxel Dörfler else
10601bb87bd0SAxel Dörfler resolution = fOriginalResolution >> -shift;
106151591198SAxel Dörfler
10621bb87bd0SAxel Dörfler _UpdateResolution(resolution);
106318d3e65eSAxel Dörfler }
106418d3e65eSAxel Dörfler
106518d3e65eSAxel Dörfler
106618d3e65eSAxel Dörfler void
MessageReceived(BMessage * message)106718d3e65eSAxel Dörfler ActivityView::MessageReceived(BMessage* message)
106818d3e65eSAxel Dörfler {
1069c28f8ea3SFrançois Revol // if a color is dropped, use it as background
1070c28f8ea3SFrançois Revol if (message->WasDropped()) {
1071c28f8ea3SFrançois Revol rgb_color* color;
1072c28f8ea3SFrançois Revol ssize_t size;
10731201d52eSAxel Dörfler if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0,
10741201d52eSAxel Dörfler (const void**)&color, &size) == B_OK
10759c89c450SAxel Dörfler && size == sizeof(rgb_color)) {
10769c89c450SAxel Dörfler BPoint dropPoint = message->DropPoint();
1077c28f8ea3SFrançois Revol ConvertFromScreen(&dropPoint);
10789c89c450SAxel Dörfler
1079c28f8ea3SFrançois Revol if (_HistoryFrame().Contains(dropPoint)) {
10809c89c450SAxel Dörfler fHistoryBackgroundColor = *color;
10819c89c450SAxel Dörfler Invalidate(_HistoryFrame());
1082c28f8ea3SFrançois Revol } else {
10835f2f72a2SFrançois Revol // check each legend color box
1084d4216445SAxel Dörfler BAutolock _(fSourcesLock);
1085d4216445SAxel Dörfler
10865f2f72a2SFrançois Revol BRect legendFrame = _LegendFrame();
10879c89c450SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) {
10881201d52eSAxel Dörfler BRect frame = _LegendColorFrameAt(legendFrame, i);
10899c89c450SAxel Dörfler if (frame.Contains(dropPoint)) {
10905f2f72a2SFrançois Revol fSources.ItemAt(i)->SetColor(*color);
10919c89c450SAxel Dörfler Invalidate(_HistoryFrame());
10921201d52eSAxel Dörfler Invalidate(frame);
10935f2f72a2SFrançois Revol return;
10945f2f72a2SFrançois Revol }
10955f2f72a2SFrançois Revol }
10969c89c450SAxel Dörfler
10979c89c450SAxel Dörfler if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) {
10989c89c450SAxel Dörfler // allow background color change in the replicant only
10999c89c450SAxel Dörfler fLegendBackgroundColor = *color;
11001201d52eSAxel Dörfler SetLowColor(fLegendBackgroundColor);
11019c89c450SAxel Dörfler Invalidate(legendFrame);
11029c89c450SAxel Dörfler }
1103c28f8ea3SFrançois Revol }
1104c28f8ea3SFrançois Revol return;
1105c28f8ea3SFrançois Revol }
11069c89c450SAxel Dörfler }
11079c89c450SAxel Dörfler
110818d3e65eSAxel Dörfler switch (message->what) {
110918d3e65eSAxel Dörfler case B_ABOUT_REQUESTED:
1110fd19c736SAdrien Destugues {
1111df2257deSAdrien Destugues BAboutWindow* window = new BAboutWindow(kAppName, kSignature);
1112df2257deSAdrien Destugues
111380d7bf83SJohn Scipione const char* authors[] = {
111480d7bf83SJohn Scipione "Axel Dörfler",
111580d7bf83SJohn Scipione NULL
111680d7bf83SJohn Scipione };
111780d7bf83SJohn Scipione
1118fd19c736SAdrien Destugues window->AddCopyright(2008, "Haiku, Inc.");
1119fd19c736SAdrien Destugues window->AddAuthors(authors);
1120fd19c736SAdrien Destugues
1121fd19c736SAdrien Destugues window->Show();
11223fdab584SJohn Scipione
11233fdab584SJohn Scipione break;
1124fd19c736SAdrien Destugues }
11251bb87bd0SAxel Dörfler case kMsgUpdateResolution:
11261bb87bd0SAxel Dörfler {
11271bb87bd0SAxel Dörfler int32 resolution;
11281bb87bd0SAxel Dörfler if (message->FindInt32("resolution", &resolution) != B_OK)
11291bb87bd0SAxel Dörfler break;
11301bb87bd0SAxel Dörfler
11311bb87bd0SAxel Dörfler _UpdateResolution(resolution, false);
11321bb87bd0SAxel Dörfler break;
11331bb87bd0SAxel Dörfler }
11341bb87bd0SAxel Dörfler
11351bb87bd0SAxel Dörfler case kMsgTimeIntervalUpdated:
11361bb87bd0SAxel Dörfler bigtime_t interval;
11371bb87bd0SAxel Dörfler if (message->FindInt64("interval", &interval) != B_OK)
11381bb87bd0SAxel Dörfler break;
11391bb87bd0SAxel Dörfler
11401bb87bd0SAxel Dörfler if (interval < 10000)
11411bb87bd0SAxel Dörfler interval = 10000;
11421bb87bd0SAxel Dörfler
11431bb87bd0SAxel Dörfler atomic_set64(&fRefreshInterval, interval);
11441bb87bd0SAxel Dörfler break;
11451bb87bd0SAxel Dörfler
114618d3e65eSAxel Dörfler case kMsgToggleDataSource:
114718d3e65eSAxel Dörfler {
114818d3e65eSAxel Dörfler int32 index;
114918d3e65eSAxel Dörfler if (message->FindInt32("index", &index) != B_OK)
115018d3e65eSAxel Dörfler break;
115118d3e65eSAxel Dörfler
115218d3e65eSAxel Dörfler const DataSource* baseSource = DataSource::SourceAt(index);
115318d3e65eSAxel Dörfler if (baseSource == NULL)
115418d3e65eSAxel Dörfler break;
115518d3e65eSAxel Dörfler
11563a4a2141SAxel Dörfler DataSource* source = FindDataSource(baseSource);
115718d3e65eSAxel Dörfler if (source == NULL)
11583a4a2141SAxel Dörfler AddDataSource(baseSource);
115918d3e65eSAxel Dörfler else
11607d33b63dSAxel Dörfler RemoveDataSource(baseSource);
116118d3e65eSAxel Dörfler
116218d3e65eSAxel Dörfler Invalidate();
116318d3e65eSAxel Dörfler break;
116418d3e65eSAxel Dörfler }
116518d3e65eSAxel Dörfler
11663a4a2141SAxel Dörfler case kMsgToggleLegend:
11673a4a2141SAxel Dörfler fShowLegend = !fShowLegend;
11683a4a2141SAxel Dörfler Invalidate();
11693a4a2141SAxel Dörfler break;
11703a4a2141SAxel Dörfler
117118d3e65eSAxel Dörfler case B_MOUSE_WHEEL_CHANGED:
117218d3e65eSAxel Dörfler {
117318d3e65eSAxel Dörfler float deltaY = 0.0f;
117418d3e65eSAxel Dörfler if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK
117518d3e65eSAxel Dörfler || deltaY == 0.0f)
117618d3e65eSAxel Dörfler break;
117718d3e65eSAxel Dörfler
11781bb87bd0SAxel Dörfler int32 resolution = fDrawResolution;
117918d3e65eSAxel Dörfler if (deltaY > 0)
11801bb87bd0SAxel Dörfler resolution *= 2;
118118d3e65eSAxel Dörfler else
11821bb87bd0SAxel Dörfler resolution /= 2;
118318d3e65eSAxel Dörfler
11841bb87bd0SAxel Dörfler _UpdateResolution(resolution);
118518d3e65eSAxel Dörfler break;
118618d3e65eSAxel Dörfler }
118718d3e65eSAxel Dörfler
118818d3e65eSAxel Dörfler default:
118918d3e65eSAxel Dörfler BView::MessageReceived(message);
119018d3e65eSAxel Dörfler break;
119118d3e65eSAxel Dörfler }
119218d3e65eSAxel Dörfler }
119318d3e65eSAxel Dörfler
119418d3e65eSAxel Dörfler
1195065e8de0SAxel Dörfler void
_UpdateFrame()1196065e8de0SAxel Dörfler ActivityView::_UpdateFrame()
1197065e8de0SAxel Dörfler {
1198dc1ffc79SFrançois Revol #ifdef __HAIKU__
1199065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL || fHistoryLayoutItem == NULL)
1200065e8de0SAxel Dörfler return;
1201065e8de0SAxel Dörfler
1202065e8de0SAxel Dörfler BRect historyFrame = fHistoryLayoutItem->Frame();
1203065e8de0SAxel Dörfler BRect legendFrame = fLegendLayoutItem->Frame();
1204dc1ffc79SFrançois Revol #else
1205dc1ffc79SFrançois Revol BRect historyFrame = Bounds();
1206dc1ffc79SFrançois Revol BRect legendFrame = Bounds();
1207dc1ffc79SFrançois Revol historyFrame.bottom -= 2 * Bounds().Height() / 3;
1208dc1ffc79SFrançois Revol legendFrame.top += Bounds().Height() / 3;
1209dc1ffc79SFrançois Revol #endif
1210065e8de0SAxel Dörfler MoveTo(historyFrame.left, historyFrame.top);
1211065e8de0SAxel Dörfler ResizeTo(legendFrame.left + legendFrame.Width() - historyFrame.left,
1212065e8de0SAxel Dörfler legendFrame.top + legendFrame.Height() - historyFrame.top);
1213065e8de0SAxel Dörfler }
1214065e8de0SAxel Dörfler
1215065e8de0SAxel Dörfler
12163a4a2141SAxel Dörfler BRect
_HistoryFrame() const12173a4a2141SAxel Dörfler ActivityView::_HistoryFrame() const
12183a4a2141SAxel Dörfler {
12193a4a2141SAxel Dörfler BRect frame = Bounds();
12203a4a2141SAxel Dörfler
1221ed1b2753SStephan Aßmus if (fShowLegend) {
1222ed1b2753SStephan Aßmus BRect legendFrame = _LegendFrame();
12233a4a2141SAxel Dörfler frame.bottom = legendFrame.top - 1;
1224ed1b2753SStephan Aßmus }
1225ed1b2753SStephan Aßmus
1226ed1b2753SStephan Aßmus frame.InsetBy(2, 2);
12273a4a2141SAxel Dörfler
12283a4a2141SAxel Dörfler return frame;
12293a4a2141SAxel Dörfler }
12303a4a2141SAxel Dörfler
12313a4a2141SAxel Dörfler
1232065e8de0SAxel Dörfler float
_LegendHeight() const1233065e8de0SAxel Dörfler ActivityView::_LegendHeight() const
12343a4a2141SAxel Dörfler {
12353a4a2141SAxel Dörfler font_height fontHeight;
12363a4a2141SAxel Dörfler GetFontHeight(&fontHeight);
12373a4a2141SAxel Dörfler
1238d4216445SAxel Dörfler BAutolock _(fSourcesLock);
1239d4216445SAxel Dörfler
12403a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2;
1241fbb82a62SPhilippe Saint-Pierre
1242e45d83a9SPhilippe Saint-Pierre int32 boldMargin = Parent()
1243e45d83a9SPhilippe Saint-Pierre && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0 ? 2 : 0;
1244fbb82a62SPhilippe Saint-Pierre
1245065e8de0SAxel Dörfler return rows * (4 + ceilf(fontHeight.ascent)
12469bd81dbeSStephan Aßmus + ceilf(fontHeight.descent) + ceilf(fontHeight.leading)) + boldMargin;
1247065e8de0SAxel Dörfler }
1248065e8de0SAxel Dörfler
1249065e8de0SAxel Dörfler
1250065e8de0SAxel Dörfler BRect
_LegendFrame() const1251065e8de0SAxel Dörfler ActivityView::_LegendFrame() const
1252065e8de0SAxel Dörfler {
1253065e8de0SAxel Dörfler float height;
1254dc1ffc79SFrançois Revol #ifdef __HAIKU__
1255065e8de0SAxel Dörfler if (fLegendLayoutItem != NULL)
1256065e8de0SAxel Dörfler height = fLegendLayoutItem->Frame().Height();
1257065e8de0SAxel Dörfler else
1258dc1ffc79SFrançois Revol #endif
1259065e8de0SAxel Dörfler height = _LegendHeight();
1260065e8de0SAxel Dörfler
1261065e8de0SAxel Dörfler BRect frame = Bounds();
12629bd81dbeSStephan Aßmus frame.bottom -= kDraggerSize;
1263065e8de0SAxel Dörfler frame.top = frame.bottom - height;
12643a4a2141SAxel Dörfler
12653a4a2141SAxel Dörfler return frame;
12663a4a2141SAxel Dörfler }
12673a4a2141SAxel Dörfler
12683a4a2141SAxel Dörfler
12693a4a2141SAxel Dörfler BRect
_LegendFrameAt(BRect frame,int32 index) const12703a4a2141SAxel Dörfler ActivityView::_LegendFrameAt(BRect frame, int32 index) const
12713a4a2141SAxel Dörfler {
12723a4a2141SAxel Dörfler int32 column = index & 1;
12733a4a2141SAxel Dörfler int32 row = index / 2;
12746df2c16cSAdrien Destugues if (column == 0) {
127527231d80SAxel Dörfler // Use the full width if there is only one item
127627231d80SAxel Dörfler if (fSources.CountItems() != 1)
12773a4a2141SAxel Dörfler frame.right = frame.left + floorf(frame.Width() / 2) - 5;
12786df2c16cSAdrien Destugues } else
12793a4a2141SAxel Dörfler frame.left = frame.right - floorf(frame.Width() / 2) + 5;
12803a4a2141SAxel Dörfler
1281d4216445SAxel Dörfler BAutolock _(fSourcesLock);
1282d4216445SAxel Dörfler
12833a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2;
12843a4a2141SAxel Dörfler float height = floorf((frame.Height() - 5) / rows);
12853a4a2141SAxel Dörfler
12863a4a2141SAxel Dörfler frame.top = frame.top + 5 + row * height;
12873a4a2141SAxel Dörfler frame.bottom = frame.top + height - 1;
12883a4a2141SAxel Dörfler
12893a4a2141SAxel Dörfler return frame;
12903a4a2141SAxel Dörfler }
12913a4a2141SAxel Dörfler
12923a4a2141SAxel Dörfler
12931201d52eSAxel Dörfler BRect
_LegendColorFrameAt(BRect frame,int32 index) const12941201d52eSAxel Dörfler ActivityView::_LegendColorFrameAt(BRect frame, int32 index) const
12951201d52eSAxel Dörfler {
12961201d52eSAxel Dörfler frame = _LegendFrameAt(frame, index);
12971201d52eSAxel Dörfler frame.InsetBy(1, 1);
12981201d52eSAxel Dörfler frame.right = frame.left + frame.Height();
12991201d52eSAxel Dörfler
13001201d52eSAxel Dörfler return frame;
13011201d52eSAxel Dörfler }
13021201d52eSAxel Dörfler
13031201d52eSAxel Dörfler
130418d3e65eSAxel Dörfler float
_PositionForValue(DataSource * source,DataHistory * values,int64 value)130518d3e65eSAxel Dörfler ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
130618d3e65eSAxel Dörfler int64 value)
130718d3e65eSAxel Dörfler {
130818d3e65eSAxel Dörfler int64 min = source->Minimum();
130918d3e65eSAxel Dörfler int64 max = source->Maximum();
131018d3e65eSAxel Dörfler if (source->AdaptiveScale()) {
131118d3e65eSAxel Dörfler int64 adaptiveMax = int64(values->MaximumValue() * 1.2);
131218d3e65eSAxel Dörfler if (adaptiveMax < max)
131318d3e65eSAxel Dörfler max = adaptiveMax;
131418d3e65eSAxel Dörfler }
131518d3e65eSAxel Dörfler
131618d3e65eSAxel Dörfler if (value > max)
131718d3e65eSAxel Dörfler value = max;
131818d3e65eSAxel Dörfler if (value < min)
131918d3e65eSAxel Dörfler value = min;
132018d3e65eSAxel Dörfler
13213a4a2141SAxel Dörfler float height = _HistoryFrame().Height();
132218d3e65eSAxel Dörfler return height - (value - min) * height / (max - min);
132318d3e65eSAxel Dörfler }
132418d3e65eSAxel Dörfler
132518d3e65eSAxel Dörfler
132618d3e65eSAxel Dörfler void
_DrawHistory()1327cc0226faSX512 ActivityView::_DrawHistory()
132818d3e65eSAxel Dörfler {
1329*0f2661ccSAdrien Destugues _UpdateOffscreenBitmap();
1330*0f2661ccSAdrien Destugues
13313a4a2141SAxel Dörfler BView* view = this;
1332*0f2661ccSAdrien Destugues if (fOffscreen != NULL) {
1333*0f2661ccSAdrien Destugues fOffscreen->Lock();
1334*0f2661ccSAdrien Destugues view = _OffscreenView();
1335*0f2661ccSAdrien Destugues }
13363a4a2141SAxel Dörfler
13373a4a2141SAxel Dörfler BRect frame = _HistoryFrame();
1338ed1b2753SStephan Aßmus BRect outerFrame = frame.InsetByCopy(-2, -2);
1339ed1b2753SStephan Aßmus
1340ed1b2753SStephan Aßmus // draw the outer frame
1341cc0226faSX512 uint32 flags = BControlLook::B_BLEND_FRAME;
1342ed1b2753SStephan Aßmus be_control_look->DrawTextControlBorder(this, outerFrame,
1343ed1b2753SStephan Aßmus outerFrame, fLegendBackgroundColor, flags);
1344ed1b2753SStephan Aßmus
1345ed1b2753SStephan Aßmus // convert to offscreen view if necessary
1346ed1b2753SStephan Aßmus if (view != this)
1347ed1b2753SStephan Aßmus frame.OffsetTo(B_ORIGIN);
1348ed1b2753SStephan Aßmus
13491201d52eSAxel Dörfler view->SetLowColor(fHistoryBackgroundColor);
13503a4a2141SAxel Dörfler view->FillRect(frame, B_SOLID_LOW);
13513a4a2141SAxel Dörfler
135218d3e65eSAxel Dörfler uint32 step = 2;
135318d3e65eSAxel Dörfler uint32 resolution = fDrawResolution;
135418d3e65eSAxel Dörfler if (fDrawResolution > 1) {
135518d3e65eSAxel Dörfler step = 1;
135618d3e65eSAxel Dörfler resolution--;
135718d3e65eSAxel Dörfler }
135818d3e65eSAxel Dörfler
13593f57b135SAdrien Destugues // We would get a negative number of steps which isn't a good idea.
13603f57b135SAdrien Destugues if (frame.IntegerWidth() <= 10)
13613f57b135SAdrien Destugues return;
13623f57b135SAdrien Destugues
13633a4a2141SAxel Dörfler uint32 width = frame.IntegerWidth() - 10;
136418d3e65eSAxel Dörfler uint32 steps = width / step;
13651bb87bd0SAxel Dörfler bigtime_t timeStep = RefreshInterval() * resolution;
136618d3e65eSAxel Dörfler bigtime_t now = system_time();
136718d3e65eSAxel Dörfler
13681201d52eSAxel Dörfler // Draw scale
13691201d52eSAxel Dörfler // TODO: add second markers?
13701201d52eSAxel Dörfler
13713a4a2141SAxel Dörfler view->SetPenSize(1);
13723a4a2141SAxel Dörfler
13731201d52eSAxel Dörfler rgb_color scaleColor = view->LowColor();
13741201d52eSAxel Dörfler uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3;
13751201d52eSAxel Dörfler if (average < 96)
13761201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT);
13771201d52eSAxel Dörfler else
13781201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT);
13791201d52eSAxel Dörfler
13801201d52eSAxel Dörfler view->SetHighColor(scaleColor);
13813a4a2141SAxel Dörfler view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2),
13823a4a2141SAxel Dörfler BPoint(frame.right, frame.top + frame.Height() / 2));
13833a4a2141SAxel Dörfler
13841201d52eSAxel Dörfler // Draw values
13851201d52eSAxel Dörfler
13861bb87bd0SAxel Dörfler view->SetPenSize(1.5);
1387d4216445SAxel Dörfler BAutolock _(fSourcesLock);
138818d3e65eSAxel Dörfler
138918d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) {
13908e26f387SAxel Dörfler ViewHistory* viewValues = fViewValues.ItemAt(i);
139118d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i);
139218d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i);
139318d3e65eSAxel Dörfler
13948e26f387SAxel Dörfler viewValues->Update(values, steps, fDrawResolution, now, timeStep,
13958e26f387SAxel Dörfler RefreshInterval());
13968e26f387SAxel Dörfler
13973f57b135SAdrien Destugues if (viewValues->Start() >= (int32)steps - 1)
13983f57b135SAdrien Destugues continue;
13993f57b135SAdrien Destugues
14008e26f387SAxel Dörfler uint32 x = viewValues->Start() * step;
14013f57b135SAdrien Destugues
14028e26f387SAxel Dörfler bool first = true;
14038e26f387SAxel Dörfler
14043a4a2141SAxel Dörfler view->SetHighColor(source->Color());
14058e26f387SAxel Dörfler view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN);
14068e26f387SAxel Dörfler view->MovePenTo(B_ORIGIN);
14073f57b135SAdrien Destugues
140852051a08SAdrien Destugues try {
14093f57b135SAdrien Destugues view->BeginLineArray(steps - viewValues->Start() - 1);
14103f57b135SAdrien Destugues
14113f57b135SAdrien Destugues BPoint prev;
14123f57b135SAdrien Destugues
14133f57b135SAdrien Destugues for (uint32 j = viewValues->Start(); j < steps; x += step, j++) {
14143f57b135SAdrien Destugues float y = _PositionForValue(source, values,
14153f57b135SAdrien Destugues viewValues->ValueAt(j));
14163f57b135SAdrien Destugues
14173f57b135SAdrien Destugues if (first) {
14183f57b135SAdrien Destugues first = false;
14193f57b135SAdrien Destugues } else
14203f57b135SAdrien Destugues view->AddLine(prev, BPoint(x, y), source->Color());
14213f57b135SAdrien Destugues
14223f57b135SAdrien Destugues prev.Set(x, y);
14233f57b135SAdrien Destugues }
14243f57b135SAdrien Destugues
1425b08627f3SMurai Takashi } catch (std::bad_alloc&) {
142652051a08SAdrien Destugues // Not enough memory to allocate the line array.
142752051a08SAdrien Destugues // TODO we could try to draw using the slower but less memory
142852051a08SAdrien Destugues // consuming solution using StrokeLine.
142952051a08SAdrien Destugues }
143052051a08SAdrien Destugues
14313f57b135SAdrien Destugues view->EndLineArray();
143218d3e65eSAxel Dörfler }
143318d3e65eSAxel Dörfler
143418d3e65eSAxel Dörfler // TODO: add marks when an app started or quit
1435*0f2661ccSAdrien Destugues view->Sync();
1436*0f2661ccSAdrien Destugues if (fOffscreen != NULL) {
1437*0f2661ccSAdrien Destugues fOffscreen->Unlock();
1438*0f2661ccSAdrien Destugues DrawBitmap(fOffscreen, outerFrame.LeftTop());
1439*0f2661ccSAdrien Destugues }
14403a4a2141SAxel Dörfler }
14413a4a2141SAxel Dörfler
14423a4a2141SAxel Dörfler
14433a4a2141SAxel Dörfler void
_UpdateResolution(int32 resolution,bool broadcast)14441bb87bd0SAxel Dörfler ActivityView::_UpdateResolution(int32 resolution, bool broadcast)
14451bb87bd0SAxel Dörfler {
14461bb87bd0SAxel Dörfler if (resolution < 1)
14471bb87bd0SAxel Dörfler resolution = 1;
14481bb87bd0SAxel Dörfler if (resolution > 128)
14491bb87bd0SAxel Dörfler resolution = 128;
14501bb87bd0SAxel Dörfler
14511bb87bd0SAxel Dörfler if (resolution == fDrawResolution)
14521bb87bd0SAxel Dörfler return;
14531bb87bd0SAxel Dörfler
14541bb87bd0SAxel Dörfler ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
14551bb87bd0SAxel Dörfler if (broadcast && window != NULL) {
14561bb87bd0SAxel Dörfler BMessage update(kMsgUpdateResolution);
14571bb87bd0SAxel Dörfler update.AddInt32("resolution", resolution);
14581bb87bd0SAxel Dörfler window->BroadcastToActivityViews(&update, this);
14591bb87bd0SAxel Dörfler }
14601bb87bd0SAxel Dörfler
14611bb87bd0SAxel Dörfler fDrawResolution = resolution;
14621bb87bd0SAxel Dörfler Invalidate();
14631bb87bd0SAxel Dörfler }
14641bb87bd0SAxel Dörfler
14651bb87bd0SAxel Dörfler
14661bb87bd0SAxel Dörfler void
Draw(BRect updateRect)1467ed1b2753SStephan Aßmus ActivityView::Draw(BRect updateRect)
14683a4a2141SAxel Dörfler {
1469cc0226faSX512 _DrawHistory();
14703a4a2141SAxel Dörfler
14713a4a2141SAxel Dörfler if (!fShowLegend)
14723a4a2141SAxel Dörfler return;
14733a4a2141SAxel Dörfler
14743a4a2141SAxel Dörfler // draw legend
1475ed1b2753SStephan Aßmus BRect legendFrame = _LegendFrame();
1476fa19dd44Slooncraz if (LowUIColor() == B_NO_COLOR)
1477ed1b2753SStephan Aßmus SetLowColor(fLegendBackgroundColor);
1478fa19dd44Slooncraz
1479d4216445SAxel Dörfler BAutolock _(fSourcesLock);
14803a4a2141SAxel Dörfler
14813a4a2141SAxel Dörfler font_height fontHeight;
14823a4a2141SAxel Dörfler GetFontHeight(&fontHeight);
14833a4a2141SAxel Dörfler
14843a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) {
14853a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i);
14863a4a2141SAxel Dörfler DataHistory* values = fValues.ItemAt(i);
14873a4a2141SAxel Dörfler BRect frame = _LegendFrameAt(legendFrame, i);
14883a4a2141SAxel Dörfler
14893a4a2141SAxel Dörfler // draw color box
14901201d52eSAxel Dörfler BRect colorBox = _LegendColorFrameAt(legendFrame, i);
1491ed1b2753SStephan Aßmus BRect rect = colorBox;
1492ed1b2753SStephan Aßmus uint32 flags = BControlLook::B_BLEND_FRAME;
1493ed1b2753SStephan Aßmus be_control_look->DrawTextControlBorder(this, rect,
1494ed1b2753SStephan Aßmus rect, fLegendBackgroundColor, flags);
14953a4a2141SAxel Dörfler SetHighColor(source->Color());
1496ed1b2753SStephan Aßmus FillRect(rect);
14973a4a2141SAxel Dörfler
14983a4a2141SAxel Dörfler // show current value and label
14993a4a2141SAxel Dörfler float y = frame.top + ceilf(fontHeight.ascent);
15003a4a2141SAxel Dörfler int64 value = values->ValueAt(values->End());
15013a4a2141SAxel Dörfler BString text;
15023a4a2141SAxel Dörfler source->Print(text, value);
15033a4a2141SAxel Dörfler float width = StringWidth(text.String());
15043a4a2141SAxel Dörfler
15053a4a2141SAxel Dörfler BString label = source->Label();
1506ed1b2753SStephan Aßmus float possibleLabelWidth = frame.right - colorBox.right - 12 - width;
1507a22fff48SAdrien Destugues if (ceilf(StringWidth(label.String())) > possibleLabelWidth)
1508ed1b2753SStephan Aßmus label = source->ShortLabel();
1509ed1b2753SStephan Aßmus TruncateString(&label, B_TRUNCATE_MIDDLE, possibleLabelWidth);
15103a4a2141SAxel Dörfler
1511d63b75faSPhilippe Saint-Pierre if (be_control_look == NULL) {
1512bb7cffd0SPhilippe Saint-Pierre DrawString(label.String(), BPoint(6 + colorBox.right, y));
1513bb7cffd0SPhilippe Saint-Pierre DrawString(text.String(), BPoint(frame.right - width, y));
1514bb7cffd0SPhilippe Saint-Pierre } else {
1515d63b75faSPhilippe Saint-Pierre be_control_look->DrawLabel(this, label.String(),
1516d63b75faSPhilippe Saint-Pierre Parent()->ViewColor(), 0, BPoint(6 + colorBox.right, y));
1517d63b75faSPhilippe Saint-Pierre be_control_look->DrawLabel(this, text.String(),
1518d63b75faSPhilippe Saint-Pierre Parent()->ViewColor(), 0, BPoint(frame.right - width, y));
1519bb7cffd0SPhilippe Saint-Pierre }
1520bb7cffd0SPhilippe Saint-Pierre }
152118d3e65eSAxel Dörfler }
152218d3e65eSAxel Dörfler
152318d3e65eSAxel Dörfler
152418d3e65eSAxel Dörfler void
_Refresh()152518d3e65eSAxel Dörfler ActivityView::_Refresh()
152618d3e65eSAxel Dörfler {
15271bb87bd0SAxel Dörfler bigtime_t lastTimeout = system_time() - RefreshInterval();
15284ce1e1d2SAxel Dörfler BMessenger target(this);
152918d3e65eSAxel Dörfler
1530d4216445SAxel Dörfler while (true) {
1531d4216445SAxel Dörfler status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT,
15321bb87bd0SAxel Dörfler lastTimeout + RefreshInterval());
1533d4216445SAxel Dörfler if (status == B_OK || status == B_BAD_SEM_ID)
1534d4216445SAxel Dörfler break;
1535d4216445SAxel Dörfler if (status == B_INTERRUPTED)
1536d4216445SAxel Dörfler continue;
1537d4216445SAxel Dörfler
1538d4216445SAxel Dörfler SystemInfo info(fSystemInfoHandler);
15391bb87bd0SAxel Dörfler lastTimeout += RefreshInterval();
1540d4216445SAxel Dörfler
1541d4216445SAxel Dörfler fSourcesLock.Lock();
154218d3e65eSAxel Dörfler
154318d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) {
154418d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i);
154518d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i);
154618d3e65eSAxel Dörfler
154718d3e65eSAxel Dörfler int64 value = source->NextValue(info);
154818d3e65eSAxel Dörfler values->AddValue(info.Time(), value);
154918d3e65eSAxel Dörfler }
155018d3e65eSAxel Dörfler
1551d4216445SAxel Dörfler fSourcesLock.Unlock();
1552d4216445SAxel Dörfler
15534ce1e1d2SAxel Dörfler target.SendMessage(B_INVALIDATE);
155418d3e65eSAxel Dörfler }
1555d4216445SAxel Dörfler }
155618d3e65eSAxel Dörfler
1557d4216445SAxel Dörfler
1558d4216445SAxel Dörfler /*static*/ status_t
_RefreshThread(void * self)1559d4216445SAxel Dörfler ActivityView::_RefreshThread(void* self)
1560d4216445SAxel Dörfler {
1561d4216445SAxel Dörfler ((ActivityView*)self)->_Refresh();
1562d4216445SAxel Dörfler return B_OK;
1563d4216445SAxel Dörfler }
1564