xref: /haiku/src/apps/activitymonitor/ActivityView.cpp (revision e45d83a9c8efa0981998ca091d7930858d3cb99f)
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__
15065e8de0SAxel Dörfler #	include <AbstractLayoutItem.h>
16ed1b2753SStephan Aßmus #	include <ControlLook.h>
17dc1ffc79SFrançois Revol #endif
1818d3e65eSAxel Dörfler #include <Application.h>
19d4216445SAxel Dörfler #include <Autolock.h>
2018d3e65eSAxel Dörfler #include <Bitmap.h>
2118d3e65eSAxel Dörfler #include <Dragger.h>
22bb7cffd0SPhilippe Saint-Pierre #include <fs_attr.h>
2318d3e65eSAxel Dörfler #include <MenuItem.h>
2418d3e65eSAxel Dörfler #include <MessageRunner.h>
2518d3e65eSAxel Dörfler #include <PopUpMenu.h>
268e26f387SAxel Dörfler #include <Shape.h>
27bb7cffd0SPhilippe Saint-Pierre #include <StorageKit.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 
3618d3e65eSAxel Dörfler 
378e26f387SAxel Dörfler template<typename ObjectType>
388e26f387SAxel Dörfler class ListAddDeleter {
398e26f387SAxel Dörfler public:
408e26f387SAxel Dörfler 	ListAddDeleter(BObjectList<ObjectType>& list, ObjectType* object,
418e26f387SAxel Dörfler 			int32 spot)
428e26f387SAxel Dörfler 		:
438e26f387SAxel Dörfler 		fList(list),
448e26f387SAxel Dörfler 		fObject(object)
458e26f387SAxel Dörfler 	{
468e26f387SAxel Dörfler 		if (fObject != NULL && !fList.AddItem(fObject, spot)) {
478e26f387SAxel Dörfler 			delete fObject;
488e26f387SAxel Dörfler 			fObject = NULL;
498e26f387SAxel Dörfler 		}
508e26f387SAxel Dörfler 	}
518e26f387SAxel Dörfler 
528e26f387SAxel Dörfler 	~ListAddDeleter()
538e26f387SAxel Dörfler 	{
548e26f387SAxel Dörfler 		if (fObject != NULL) {
558e26f387SAxel Dörfler 			fList.RemoveItem(fObject);
568e26f387SAxel Dörfler 			delete fObject;
578e26f387SAxel Dörfler 		}
588e26f387SAxel Dörfler 	}
598e26f387SAxel Dörfler 
608e26f387SAxel Dörfler 	bool Failed() const
618e26f387SAxel Dörfler 	{
628e26f387SAxel Dörfler 		return fObject == NULL;
638e26f387SAxel Dörfler 	}
648e26f387SAxel Dörfler 
658e26f387SAxel Dörfler 	void Detach()
668e26f387SAxel Dörfler 	{
678e26f387SAxel Dörfler 		fObject = NULL;
688e26f387SAxel Dörfler 	}
698e26f387SAxel Dörfler 
708e26f387SAxel Dörfler private:
718e26f387SAxel Dörfler 	BObjectList<ObjectType>&	fList;
728e26f387SAxel Dörfler 	ObjectType*					fObject;
738e26f387SAxel Dörfler };
748e26f387SAxel Dörfler 
758e26f387SAxel Dörfler 
768e26f387SAxel Dörfler /*!	This class manages the scale of a history with a dynamic scale.
778e26f387SAxel Dörfler 	Every history value will be input via Update(), and the minimum/maximum
788e26f387SAxel Dörfler 	is computed from that.
798e26f387SAxel Dörfler */
8051591198SAxel Dörfler class Scale {
8151591198SAxel Dörfler public:
8251591198SAxel Dörfler 								Scale(scale_type type);
8351591198SAxel Dörfler 
8451591198SAxel Dörfler 			int64				MinimumValue() const { return fMinimumValue; }
8551591198SAxel Dörfler 			int64				MaximumValue() const { return fMaximumValue; }
8651591198SAxel Dörfler 
8751591198SAxel Dörfler 			void				Update(int64 value);
8851591198SAxel Dörfler 
8951591198SAxel Dörfler private:
9051591198SAxel Dörfler 			scale_type			fType;
9151591198SAxel Dörfler 			int64				fMinimumValue;
9251591198SAxel Dörfler 			int64				fMaximumValue;
9351591198SAxel Dörfler 			bool				fInitialized;
9451591198SAxel Dörfler };
9551591198SAxel Dörfler 
968e26f387SAxel Dörfler /*!	Stores the interpolated on screen view values. This is done so that the
978e26f387SAxel Dörfler 	interpolation is fixed, and does not change when being scrolled.
988e26f387SAxel Dörfler 
998e26f387SAxel Dörfler 	We could also just do this by making sure we always ask for the same
1008e26f387SAxel Dörfler 	interval only, but this way we also save the interpolation.
1018e26f387SAxel Dörfler */
1028e26f387SAxel Dörfler class ViewHistory {
1038e26f387SAxel Dörfler public:
1048e26f387SAxel Dörfler 								ViewHistory();
1058e26f387SAxel Dörfler 
1068e26f387SAxel Dörfler 			int64				ValueAt(int32 x);
1078e26f387SAxel Dörfler 
1088e26f387SAxel Dörfler 			int32				Start() const
1098e26f387SAxel Dörfler 									{ return fValues.Size()
1108e26f387SAxel Dörfler 										- fValues.CountItems(); }
1118e26f387SAxel Dörfler 
1128e26f387SAxel Dörfler 			void				Update(DataHistory* history, int32 width,
1138e26f387SAxel Dörfler 									int32 resolution, bigtime_t toTime,
1148e26f387SAxel Dörfler 									bigtime_t step, bigtime_t refresh);
1158e26f387SAxel Dörfler 
1168e26f387SAxel Dörfler private:
1178e26f387SAxel Dörfler 			CircularBuffer<int64> fValues;
1188e26f387SAxel Dörfler 			int32				fResolution;
1198e26f387SAxel Dörfler 			bigtime_t			fRefresh;
1208e26f387SAxel Dörfler 			bigtime_t			fLastTime;
1218e26f387SAxel Dörfler };
1228e26f387SAxel Dörfler 
12318d3e65eSAxel Dörfler struct data_item {
12418d3e65eSAxel Dörfler 	bigtime_t	time;
12518d3e65eSAxel Dörfler 	int64		value;
12618d3e65eSAxel Dörfler };
12718d3e65eSAxel Dörfler 
128dc1ffc79SFrançois Revol #ifdef __HAIKU__
129065e8de0SAxel Dörfler class ActivityView::HistoryLayoutItem : public BAbstractLayoutItem {
130065e8de0SAxel Dörfler public:
131065e8de0SAxel Dörfler 							HistoryLayoutItem(ActivityView* parent);
132065e8de0SAxel Dörfler 
133065e8de0SAxel Dörfler 	virtual	bool			IsVisible();
134065e8de0SAxel Dörfler 	virtual	void			SetVisible(bool visible);
135065e8de0SAxel Dörfler 
136065e8de0SAxel Dörfler 	virtual	BRect			Frame();
137065e8de0SAxel Dörfler 	virtual	void			SetFrame(BRect frame);
138065e8de0SAxel Dörfler 
139065e8de0SAxel Dörfler 	virtual	BView*			View();
140065e8de0SAxel Dörfler 
141065e8de0SAxel Dörfler 	virtual	BSize			BasePreferredSize();
142065e8de0SAxel Dörfler 
143065e8de0SAxel Dörfler private:
144065e8de0SAxel Dörfler 	ActivityView*			fParent;
145065e8de0SAxel Dörfler 	BRect					fFrame;
146065e8de0SAxel Dörfler };
147065e8de0SAxel Dörfler 
148065e8de0SAxel Dörfler class ActivityView::LegendLayoutItem : public BAbstractLayoutItem {
149065e8de0SAxel Dörfler public:
150065e8de0SAxel Dörfler 							LegendLayoutItem(ActivityView* parent);
151065e8de0SAxel Dörfler 
152065e8de0SAxel Dörfler 	virtual	bool			IsVisible();
153065e8de0SAxel Dörfler 	virtual	void			SetVisible(bool visible);
154065e8de0SAxel Dörfler 
155065e8de0SAxel Dörfler 	virtual	BRect			Frame();
156065e8de0SAxel Dörfler 	virtual	void			SetFrame(BRect frame);
157065e8de0SAxel Dörfler 
158065e8de0SAxel Dörfler 	virtual	BView*			View();
159065e8de0SAxel Dörfler 
160065e8de0SAxel Dörfler 	virtual	BSize			BaseMinSize();
161065e8de0SAxel Dörfler 	virtual	BSize			BaseMaxSize();
162065e8de0SAxel Dörfler 	virtual	BSize			BasePreferredSize();
163065e8de0SAxel Dörfler 	virtual	BAlignment		BaseAlignment();
164065e8de0SAxel Dörfler 
165065e8de0SAxel Dörfler private:
166065e8de0SAxel Dörfler 	ActivityView*			fParent;
167065e8de0SAxel Dörfler 	BRect					fFrame;
168065e8de0SAxel Dörfler };
169dc1ffc79SFrançois Revol #endif
170065e8de0SAxel Dörfler 
1711bb87bd0SAxel Dörfler const bigtime_t kInitialRefreshInterval = 250000LL;
17218d3e65eSAxel Dörfler 
17318d3e65eSAxel Dörfler const uint32 kMsgToggleDataSource = 'tgds';
1743a4a2141SAxel Dörfler const uint32 kMsgToggleLegend = 'tglg';
1751bb87bd0SAxel Dörfler const uint32 kMsgUpdateResolution = 'ures';
17618d3e65eSAxel Dörfler 
17718d3e65eSAxel Dörfler extern const char* kSignature;
17818d3e65eSAxel Dörfler 
179bb7cffd0SPhilippe Saint-Pierre const char* kDesktopAttrName = "be:bgndimginfo";
18018d3e65eSAxel Dörfler 
18151591198SAxel Dörfler Scale::Scale(scale_type type)
18251591198SAxel Dörfler 	:
18351591198SAxel Dörfler 	fType(type),
18451591198SAxel Dörfler 	fMinimumValue(0),
18551591198SAxel Dörfler 	fMaximumValue(0),
18651591198SAxel Dörfler 	fInitialized(false)
18751591198SAxel Dörfler {
18851591198SAxel Dörfler }
18951591198SAxel Dörfler 
19051591198SAxel Dörfler 
19151591198SAxel Dörfler void
19251591198SAxel Dörfler Scale::Update(int64 value)
19351591198SAxel Dörfler {
19451591198SAxel Dörfler 	if (!fInitialized || fMinimumValue > value)
19551591198SAxel Dörfler 		fMinimumValue = value;
196230e3259SAxel Dörfler 	if (!fInitialized || fMaximumValue < value)
19751591198SAxel Dörfler 		fMaximumValue = value;
19851591198SAxel Dörfler 
19951591198SAxel Dörfler 	fInitialized = true;
20051591198SAxel Dörfler }
20151591198SAxel Dörfler 
20251591198SAxel Dörfler 
20351591198SAxel Dörfler //	#pragma mark -
20451591198SAxel Dörfler 
20551591198SAxel Dörfler 
2068e26f387SAxel Dörfler ViewHistory::ViewHistory()
2078e26f387SAxel Dörfler 	:
2088e26f387SAxel Dörfler 	fValues(1),
2098e26f387SAxel Dörfler 	fResolution(-1),
2108e26f387SAxel Dörfler 	fRefresh(-1),
2118e26f387SAxel Dörfler 	fLastTime(0)
2128e26f387SAxel Dörfler {
2138e26f387SAxel Dörfler }
2148e26f387SAxel Dörfler 
2158e26f387SAxel Dörfler 
2168e26f387SAxel Dörfler int64
2178e26f387SAxel Dörfler ViewHistory::ValueAt(int32 x)
2188e26f387SAxel Dörfler {
2198e26f387SAxel Dörfler 	int64* value = fValues.ItemAt(x - Start());
2208e26f387SAxel Dörfler 	if (value != NULL)
2218e26f387SAxel Dörfler 		return *value;
2228e26f387SAxel Dörfler 
2238e26f387SAxel Dörfler 	return 0;
2248e26f387SAxel Dörfler }
2258e26f387SAxel Dörfler 
2268e26f387SAxel Dörfler 
2278e26f387SAxel Dörfler void
2288e26f387SAxel Dörfler ViewHistory::Update(DataHistory* history, int32 width, int32 resolution,
2298e26f387SAxel Dörfler 	bigtime_t toTime, bigtime_t step, bigtime_t refresh)
2308e26f387SAxel Dörfler {
2312c604c0dSAxel Dörfler 	if (width > 16384) {
2322c604c0dSAxel Dörfler 		// ignore this - it seems the view hasn't been layouted yet
2332c604c0dSAxel Dörfler 		return;
2342c604c0dSAxel Dörfler 	}
2352c604c0dSAxel Dörfler 
2368e26f387SAxel Dörfler 	// Check if we need to invalidate the existing values
2378e26f387SAxel Dörfler 	if ((int32)fValues.Size() != width
2388e26f387SAxel Dörfler 		|| fResolution != resolution
2398e26f387SAxel Dörfler 		|| fRefresh != refresh) {
2408e26f387SAxel Dörfler 		fValues.SetSize(width);
2418e26f387SAxel Dörfler 		fResolution = resolution;
2428e26f387SAxel Dörfler 		fRefresh = refresh;
2437d33b63dSAxel Dörfler 		fLastTime = 0;
2448e26f387SAxel Dörfler 	}
2458e26f387SAxel Dörfler 
2468e26f387SAxel Dörfler 	// Compute how many new values we need to retrieve
2478e26f387SAxel Dörfler 	if (fLastTime < history->Start())
2488e26f387SAxel Dörfler 		fLastTime = history->Start();
2497d33b63dSAxel Dörfler 	if (fLastTime > history->End())
2507d33b63dSAxel Dörfler 		return;
2518e26f387SAxel Dörfler 
2528e26f387SAxel Dörfler 	int32 updateWidth = int32((toTime - fLastTime) / step);
2538e26f387SAxel Dörfler 	if (updateWidth < 1)
2548e26f387SAxel Dörfler 		return;
2558e26f387SAxel Dörfler 
2568e26f387SAxel Dörfler 	if (updateWidth > (int32)fValues.Size()) {
2578e26f387SAxel Dörfler 		updateWidth = fValues.Size();
2588e26f387SAxel Dörfler 		fLastTime = toTime - updateWidth * step;
2598e26f387SAxel Dörfler 	}
2608e26f387SAxel Dörfler 
2618e26f387SAxel Dörfler 	for (int32 i = 0; i < updateWidth; i++) {
2628e26f387SAxel Dörfler 		int64 value = history->ValueAt(fLastTime += step);
2638e26f387SAxel Dörfler 
2648e26f387SAxel Dörfler 		if (step > refresh) {
2658e26f387SAxel Dörfler 			uint32 count = 1;
2668e26f387SAxel Dörfler 			for (bigtime_t offset = refresh; offset < step; offset += refresh) {
2678e26f387SAxel Dörfler 				// TODO: handle int64 overflow correctly!
2688e26f387SAxel Dörfler 				value += history->ValueAt(fLastTime + offset);
2698e26f387SAxel Dörfler 				count++;
2708e26f387SAxel Dörfler 			}
2718e26f387SAxel Dörfler 			value /= count;
2728e26f387SAxel Dörfler 		}
2738e26f387SAxel Dörfler 
2748e26f387SAxel Dörfler 		fValues.AddItem(value);
2758e26f387SAxel Dörfler 	}
2768e26f387SAxel Dörfler }
2778e26f387SAxel Dörfler 
2788e26f387SAxel Dörfler 
2798e26f387SAxel Dörfler //	#pragma mark -
2808e26f387SAxel Dörfler 
2818e26f387SAxel Dörfler 
28218d3e65eSAxel Dörfler DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval)
28318d3e65eSAxel Dörfler 	:
28418d3e65eSAxel Dörfler 	fBuffer(10000),
28518d3e65eSAxel Dörfler 	fMinimumValue(0),
28618d3e65eSAxel Dörfler 	fMaximumValue(0),
28718d3e65eSAxel Dörfler 	fRefreshInterval(interval),
28851591198SAxel Dörfler 	fLastIndex(-1),
28951591198SAxel Dörfler 	fScale(NULL)
29018d3e65eSAxel Dörfler {
29118d3e65eSAxel Dörfler }
29218d3e65eSAxel Dörfler 
29318d3e65eSAxel Dörfler 
29418d3e65eSAxel Dörfler DataHistory::~DataHistory()
29518d3e65eSAxel Dörfler {
29618d3e65eSAxel Dörfler }
29718d3e65eSAxel Dörfler 
29818d3e65eSAxel Dörfler 
29918d3e65eSAxel Dörfler void
30018d3e65eSAxel Dörfler DataHistory::AddValue(bigtime_t time, int64 value)
30118d3e65eSAxel Dörfler {
30218d3e65eSAxel Dörfler 	if (fBuffer.IsEmpty() || fMaximumValue < value)
30318d3e65eSAxel Dörfler 		fMaximumValue = value;
30418d3e65eSAxel Dörfler 	if (fBuffer.IsEmpty() || fMinimumValue > value)
30518d3e65eSAxel Dörfler 		fMinimumValue = value;
30651591198SAxel Dörfler 	if (fScale != NULL)
30751591198SAxel Dörfler 		fScale->Update(value);
30818d3e65eSAxel Dörfler 
30918d3e65eSAxel Dörfler 	data_item item = {time, value};
31018d3e65eSAxel Dörfler 	fBuffer.AddItem(item);
31118d3e65eSAxel Dörfler }
31218d3e65eSAxel Dörfler 
31318d3e65eSAxel Dörfler 
31418d3e65eSAxel Dörfler int64
31518d3e65eSAxel Dörfler DataHistory::ValueAt(bigtime_t time)
31618d3e65eSAxel Dörfler {
31751591198SAxel Dörfler 	int32 left = 0;
31851591198SAxel Dörfler 	int32 right = fBuffer.CountItems() - 1;
31951591198SAxel Dörfler 	data_item* item = NULL;
32051591198SAxel Dörfler 
32151591198SAxel Dörfler 	while (left <= right) {
32251591198SAxel Dörfler 		int32 index = (left + right) / 2;
32351591198SAxel Dörfler 		item = fBuffer.ItemAt(index);
32451591198SAxel Dörfler 
32551591198SAxel Dörfler 		if (item->time > time) {
32651591198SAxel Dörfler 			// search in left part
32751591198SAxel Dörfler 			right = index - 1;
32851591198SAxel Dörfler 		} else {
32984e23a5dSAxel Dörfler 			data_item* nextItem = fBuffer.ItemAt(index + 1);
33084e23a5dSAxel Dörfler 			if (nextItem == NULL)
33184e23a5dSAxel Dörfler 				return item->value;
33284e23a5dSAxel Dörfler 			if (nextItem->time > time) {
33351591198SAxel Dörfler 				// found item
33484e23a5dSAxel Dörfler 				int64 value = item->value;
33584e23a5dSAxel Dörfler 				value += int64(double(nextItem->value - value)
33684e23a5dSAxel Dörfler 					/ (nextItem->time - item->time) * (time - item->time));
3378e26f387SAxel Dörfler 				return value;
33851591198SAxel Dörfler 			}
33951591198SAxel Dörfler 
34051591198SAxel Dörfler 			// search in right part
34151591198SAxel Dörfler 			left = index + 1;
34251591198SAxel Dörfler 		}
34351591198SAxel Dörfler 	}
34418d3e65eSAxel Dörfler 
34518d3e65eSAxel Dörfler 	return 0;
34618d3e65eSAxel Dörfler }
34718d3e65eSAxel Dörfler 
34818d3e65eSAxel Dörfler 
34918d3e65eSAxel Dörfler int64
35018d3e65eSAxel Dörfler DataHistory::MaximumValue() const
35118d3e65eSAxel Dörfler {
35251591198SAxel Dörfler 	if (fScale != NULL)
35351591198SAxel Dörfler 		return fScale->MaximumValue();
35451591198SAxel Dörfler 
35518d3e65eSAxel Dörfler 	return fMaximumValue;
35618d3e65eSAxel Dörfler }
35718d3e65eSAxel Dörfler 
35818d3e65eSAxel Dörfler 
35918d3e65eSAxel Dörfler int64
36018d3e65eSAxel Dörfler DataHistory::MinimumValue() const
36118d3e65eSAxel Dörfler {
36251591198SAxel Dörfler 	if (fScale != NULL)
36351591198SAxel Dörfler 		return fScale->MinimumValue();
36451591198SAxel Dörfler 
36518d3e65eSAxel Dörfler 	return fMinimumValue;
36618d3e65eSAxel Dörfler }
36718d3e65eSAxel Dörfler 
36818d3e65eSAxel Dörfler 
36918d3e65eSAxel Dörfler bigtime_t
37018d3e65eSAxel Dörfler DataHistory::Start() const
37118d3e65eSAxel Dörfler {
37218d3e65eSAxel Dörfler 	if (fBuffer.CountItems() == 0)
37318d3e65eSAxel Dörfler 		return 0;
37418d3e65eSAxel Dörfler 
37518d3e65eSAxel Dörfler 	return fBuffer.ItemAt(0)->time;
37618d3e65eSAxel Dörfler }
37718d3e65eSAxel Dörfler 
37818d3e65eSAxel Dörfler 
37918d3e65eSAxel Dörfler bigtime_t
38018d3e65eSAxel Dörfler DataHistory::End() const
38118d3e65eSAxel Dörfler {
38218d3e65eSAxel Dörfler 	if (fBuffer.CountItems() == 0)
38318d3e65eSAxel Dörfler 		return 0;
38418d3e65eSAxel Dörfler 
38518d3e65eSAxel Dörfler 	return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time;
38618d3e65eSAxel Dörfler }
38718d3e65eSAxel Dörfler 
38818d3e65eSAxel Dörfler 
38918d3e65eSAxel Dörfler void
39018d3e65eSAxel Dörfler DataHistory::SetRefreshInterval(bigtime_t interval)
39118d3e65eSAxel Dörfler {
39218d3e65eSAxel Dörfler 	// TODO: adjust buffer size
39318d3e65eSAxel Dörfler }
39418d3e65eSAxel Dörfler 
39518d3e65eSAxel Dörfler 
39651591198SAxel Dörfler void
39751591198SAxel Dörfler DataHistory::SetScale(Scale* scale)
39851591198SAxel Dörfler {
39951591198SAxel Dörfler 	fScale = scale;
40051591198SAxel Dörfler }
40151591198SAxel Dörfler 
40251591198SAxel Dörfler 
40318d3e65eSAxel Dörfler //	#pragma mark -
40418d3e65eSAxel Dörfler 
40518d3e65eSAxel Dörfler 
406dc1ffc79SFrançois Revol #ifdef __HAIKU__
407065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::HistoryLayoutItem(ActivityView* parent)
408065e8de0SAxel Dörfler 	:
409065e8de0SAxel Dörfler 	fParent(parent),
410065e8de0SAxel Dörfler 	fFrame()
411065e8de0SAxel Dörfler {
412065e8de0SAxel Dörfler }
413065e8de0SAxel Dörfler 
414065e8de0SAxel Dörfler 
415065e8de0SAxel Dörfler bool
416065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::IsVisible()
417065e8de0SAxel Dörfler {
418065e8de0SAxel Dörfler 	return !fParent->IsHidden(fParent);
419065e8de0SAxel Dörfler }
420065e8de0SAxel Dörfler 
421065e8de0SAxel Dörfler 
422065e8de0SAxel Dörfler void
423065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetVisible(bool visible)
424065e8de0SAxel Dörfler {
425065e8de0SAxel Dörfler 	// not allowed
426065e8de0SAxel Dörfler }
427065e8de0SAxel Dörfler 
428065e8de0SAxel Dörfler 
429065e8de0SAxel Dörfler BRect
430065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::Frame()
431065e8de0SAxel Dörfler {
432065e8de0SAxel Dörfler 	return fFrame;
433065e8de0SAxel Dörfler }
434065e8de0SAxel Dörfler 
435065e8de0SAxel Dörfler 
436065e8de0SAxel Dörfler void
437065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetFrame(BRect frame)
438065e8de0SAxel Dörfler {
439065e8de0SAxel Dörfler 	fFrame = frame;
440065e8de0SAxel Dörfler 	fParent->_UpdateFrame();
441065e8de0SAxel Dörfler }
442065e8de0SAxel Dörfler 
443065e8de0SAxel Dörfler 
444065e8de0SAxel Dörfler BView*
445065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::View()
446065e8de0SAxel Dörfler {
447065e8de0SAxel Dörfler 	return fParent;
448065e8de0SAxel Dörfler }
449065e8de0SAxel Dörfler 
450065e8de0SAxel Dörfler 
451065e8de0SAxel Dörfler BSize
452065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::BasePreferredSize()
453065e8de0SAxel Dörfler {
454065e8de0SAxel Dörfler 	BSize size(BaseMaxSize());
455065e8de0SAxel Dörfler 	return size;
456065e8de0SAxel Dörfler }
457065e8de0SAxel Dörfler 
458065e8de0SAxel Dörfler 
459065e8de0SAxel Dörfler //	#pragma mark -
460065e8de0SAxel Dörfler 
461065e8de0SAxel Dörfler 
462065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::LegendLayoutItem(ActivityView* parent)
463065e8de0SAxel Dörfler 	:
464065e8de0SAxel Dörfler 	fParent(parent),
465065e8de0SAxel Dörfler 	fFrame()
466065e8de0SAxel Dörfler {
467065e8de0SAxel Dörfler }
468065e8de0SAxel Dörfler 
469065e8de0SAxel Dörfler 
470065e8de0SAxel Dörfler bool
471065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::IsVisible()
472065e8de0SAxel Dörfler {
473065e8de0SAxel Dörfler 	return !fParent->IsHidden(fParent);
474065e8de0SAxel Dörfler }
475065e8de0SAxel Dörfler 
476065e8de0SAxel Dörfler 
477065e8de0SAxel Dörfler void
478065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetVisible(bool visible)
479065e8de0SAxel Dörfler {
480065e8de0SAxel Dörfler 	// not allowed
481065e8de0SAxel Dörfler }
482065e8de0SAxel Dörfler 
483065e8de0SAxel Dörfler 
484065e8de0SAxel Dörfler BRect
485065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::Frame()
486065e8de0SAxel Dörfler {
487065e8de0SAxel Dörfler 	return fFrame;
488065e8de0SAxel Dörfler }
489065e8de0SAxel Dörfler 
490065e8de0SAxel Dörfler 
491065e8de0SAxel Dörfler void
492065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetFrame(BRect frame)
493065e8de0SAxel Dörfler {
494065e8de0SAxel Dörfler 	fFrame = frame;
495065e8de0SAxel Dörfler 	fParent->_UpdateFrame();
496065e8de0SAxel Dörfler }
497065e8de0SAxel Dörfler 
498065e8de0SAxel Dörfler 
499065e8de0SAxel Dörfler BView*
500065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::View()
501065e8de0SAxel Dörfler {
502065e8de0SAxel Dörfler 	return fParent;
503065e8de0SAxel Dörfler }
504065e8de0SAxel Dörfler 
505065e8de0SAxel Dörfler 
506065e8de0SAxel Dörfler BSize
507065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMinSize()
508065e8de0SAxel Dörfler {
509065e8de0SAxel Dörfler 	// TODO: Cache the info. Might be too expensive for this call.
510065e8de0SAxel Dörfler 	BSize size;
511065e8de0SAxel Dörfler 	size.width = 80;
512065e8de0SAxel Dörfler 	size.height = fParent->_LegendHeight();
513065e8de0SAxel Dörfler 
514065e8de0SAxel Dörfler 	return size;
515065e8de0SAxel Dörfler }
516065e8de0SAxel Dörfler 
517065e8de0SAxel Dörfler 
518065e8de0SAxel Dörfler BSize
519065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMaxSize()
520065e8de0SAxel Dörfler {
521065e8de0SAxel Dörfler 	BSize size(BaseMinSize());
522065e8de0SAxel Dörfler 	size.width = B_SIZE_UNLIMITED;
523065e8de0SAxel Dörfler 	return size;
524065e8de0SAxel Dörfler }
525065e8de0SAxel Dörfler 
526065e8de0SAxel Dörfler 
527065e8de0SAxel Dörfler BSize
528065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BasePreferredSize()
529065e8de0SAxel Dörfler {
530065e8de0SAxel Dörfler 	BSize size(BaseMinSize());
531065e8de0SAxel Dörfler 	return size;
532065e8de0SAxel Dörfler }
533065e8de0SAxel Dörfler 
534065e8de0SAxel Dörfler 
535065e8de0SAxel Dörfler BAlignment
536065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseAlignment()
537065e8de0SAxel Dörfler {
538065e8de0SAxel Dörfler 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
539065e8de0SAxel Dörfler }
540dc1ffc79SFrançois Revol #endif
541065e8de0SAxel Dörfler 
542065e8de0SAxel Dörfler 
543065e8de0SAxel Dörfler //	#pragma mark -
544065e8de0SAxel Dörfler 
545065e8de0SAxel Dörfler 
546bb7cffd0SPhilippe Saint-Pierre const rgb_color kWhite = (rgb_color){255, 255, 255, 255};
547bb7cffd0SPhilippe Saint-Pierre const rgb_color kBlack = (rgb_color){0, 0, 0, 255};
548bb7cffd0SPhilippe Saint-Pierre 
549bb7cffd0SPhilippe Saint-Pierre 
55018d3e65eSAxel Dörfler ActivityView::ActivityView(BRect frame, const char* name,
5513a4a2141SAxel Dörfler 		const BMessage* settings, uint32 resizingMode)
55218d3e65eSAxel Dörfler 	: BView(frame, name, resizingMode,
553d4216445SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
554d4216445SAxel Dörfler 	fSourcesLock("data sources")
55518d3e65eSAxel Dörfler {
5563a4a2141SAxel Dörfler 	_Init(settings);
5573a4a2141SAxel Dörfler 
5583a4a2141SAxel Dörfler 	BRect rect(Bounds());
5593a4a2141SAxel Dörfler 	rect.top = rect.bottom - 7;
5603a4a2141SAxel Dörfler 	rect.left = rect.right - 7;
5613a4a2141SAxel Dörfler 	BDragger* dragger = new BDragger(rect, this,
5623a4a2141SAxel Dörfler 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
5633a4a2141SAxel Dörfler 	AddChild(dragger);
5643a4a2141SAxel Dörfler }
5653a4a2141SAxel Dörfler 
5663a4a2141SAxel Dörfler 
5673a4a2141SAxel Dörfler ActivityView::ActivityView(const char* name, const BMessage* settings)
568cbd4bc95SFrançois Revol #ifdef __HAIKU__
569d4216445SAxel Dörfler 	: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
570cbd4bc95SFrançois Revol #else
571d4216445SAxel Dörfler 	: BView(BRect(0, 0, 300, 200), name, B_FOLLOW_NONE,
572d4216445SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
573cbd4bc95SFrançois Revol #endif
574d4216445SAxel Dörfler 	fSourcesLock("data sources")
5753a4a2141SAxel Dörfler {
57679cbd226SFrançois Revol 	SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
5779c89c450SAxel Dörfler 
5783a4a2141SAxel Dörfler 	_Init(settings);
57918d3e65eSAxel Dörfler 
58018d3e65eSAxel Dörfler 	BRect rect(Bounds());
58118d3e65eSAxel Dörfler 	rect.top = rect.bottom - 7;
58218d3e65eSAxel Dörfler 	rect.left = rect.right - 7;
58318d3e65eSAxel Dörfler 	BDragger* dragger = new BDragger(rect, this,
58418d3e65eSAxel Dörfler 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
58518d3e65eSAxel Dörfler 	AddChild(dragger);
58618d3e65eSAxel Dörfler }
58718d3e65eSAxel Dörfler 
58818d3e65eSAxel Dörfler 
58918d3e65eSAxel Dörfler ActivityView::ActivityView(BMessage* archive)
59018d3e65eSAxel Dörfler 	: BView(archive)
59118d3e65eSAxel Dörfler {
59218d3e65eSAxel Dörfler 	_Init(archive);
59318d3e65eSAxel Dörfler }
59418d3e65eSAxel Dörfler 
59518d3e65eSAxel Dörfler 
59618d3e65eSAxel Dörfler ActivityView::~ActivityView()
59718d3e65eSAxel Dörfler {
598bb7cffd0SPhilippe Saint-Pierre 	stop_watching(this);
5993a4a2141SAxel Dörfler 	delete fOffscreen;
60074158bb4SFrançois Revol 	delete fSystemInfoHandler;
60118d3e65eSAxel Dörfler }
60218d3e65eSAxel Dörfler 
60318d3e65eSAxel Dörfler 
60418d3e65eSAxel Dörfler void
60518d3e65eSAxel Dörfler ActivityView::_Init(const BMessage* settings)
60618d3e65eSAxel Dörfler {
6079c89c450SAxel Dörfler 	fHistoryBackgroundColor = (rgb_color){255, 255, 240};
6089c89c450SAxel Dörfler 	fLegendBackgroundColor = LowColor();
6099c89c450SAxel Dörfler 		// the low color is restored by the BView unarchiving
6103a4a2141SAxel Dörfler 	fOffscreen = NULL;
611dc1ffc79SFrançois Revol #ifdef __HAIKU__
612065e8de0SAxel Dörfler 	fHistoryLayoutItem = NULL;
613065e8de0SAxel Dörfler 	fLegendLayoutItem = NULL;
614dc1ffc79SFrançois Revol #endif
6153a4a2141SAxel Dörfler 	SetViewColor(B_TRANSPARENT_COLOR);
61618d3e65eSAxel Dörfler 
61718d3e65eSAxel Dörfler 	fLastRefresh = 0;
61818d3e65eSAxel Dörfler 	fDrawResolution = 1;
61951591198SAxel Dörfler 	fZooming = false;
62018d3e65eSAxel Dörfler 
62174158bb4SFrançois Revol 	fSystemInfoHandler = new SystemInfoHandler;
62274158bb4SFrançois Revol 
6233a4a2141SAxel Dörfler 	if (settings == NULL
624eee6f40bSAlexandre Deckner 		|| settings->FindInt64("refresh interval", &fRefreshInterval) != B_OK)
625eee6f40bSAlexandre Deckner 		fRefreshInterval = kInitialRefreshInterval;
626eee6f40bSAlexandre Deckner 
627eee6f40bSAlexandre Deckner 	if (settings == NULL
6283a4a2141SAxel Dörfler 		|| settings->FindBool("show legend", &fShowLegend) != B_OK)
6293a4a2141SAxel Dörfler 		fShowLegend = true;
6303a4a2141SAxel Dörfler 
63151591198SAxel Dörfler 	if (settings == NULL)
6323a4a2141SAxel Dörfler 		return;
6333a4a2141SAxel Dörfler 
6349c89c450SAxel Dörfler 	ssize_t colorLength;
63579cbd226SFrançois Revol 	rgb_color *color;
6369c89c450SAxel Dörfler 	if (settings->FindData("history background color", B_RGB_COLOR_TYPE,
6379c89c450SAxel Dörfler 			(const void **)&color, &colorLength) == B_OK
6389c89c450SAxel Dörfler 		&& colorLength == sizeof(rgb_color))
6399c89c450SAxel Dörfler 		fHistoryBackgroundColor = *color;
64079cbd226SFrançois Revol 
6413a4a2141SAxel Dörfler 	const char* name;
6423a4a2141SAxel Dörfler 	for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++) {
6431201d52eSAxel Dörfler 		AddDataSource(DataSource::FindSource(name), settings);
6443a4a2141SAxel Dörfler 	}
64518d3e65eSAxel Dörfler }
64618d3e65eSAxel Dörfler 
64718d3e65eSAxel Dörfler 
64818d3e65eSAxel Dörfler status_t
64918d3e65eSAxel Dörfler ActivityView::Archive(BMessage* into, bool deep) const
65018d3e65eSAxel Dörfler {
65118d3e65eSAxel Dörfler 	status_t status;
65218d3e65eSAxel Dörfler 
65318d3e65eSAxel Dörfler 	status = BView::Archive(into, deep);
65418d3e65eSAxel Dörfler 	if (status < B_OK)
65518d3e65eSAxel Dörfler 		return status;
65618d3e65eSAxel Dörfler 
65718d3e65eSAxel Dörfler 	status = into->AddString("add_on", kSignature);
65818d3e65eSAxel Dörfler 	if (status < B_OK)
65918d3e65eSAxel Dörfler 		return status;
66018d3e65eSAxel Dörfler 
66118d3e65eSAxel Dörfler 	status = SaveState(*into);
66218d3e65eSAxel Dörfler 	if (status < B_OK)
66318d3e65eSAxel Dörfler 		return status;
66418d3e65eSAxel Dörfler 
66518d3e65eSAxel Dörfler 	return B_OK;
66618d3e65eSAxel Dörfler }
66718d3e65eSAxel Dörfler 
66818d3e65eSAxel Dörfler 
66918d3e65eSAxel Dörfler BArchivable*
67018d3e65eSAxel Dörfler ActivityView::Instantiate(BMessage* archive)
67118d3e65eSAxel Dörfler {
67218d3e65eSAxel Dörfler 	if (!validate_instantiation(archive, "ActivityView"))
67318d3e65eSAxel Dörfler 		return NULL;
67418d3e65eSAxel Dörfler 
67518d3e65eSAxel Dörfler 	return new ActivityView(archive);
67618d3e65eSAxel Dörfler }
67718d3e65eSAxel Dörfler 
67818d3e65eSAxel Dörfler 
67918d3e65eSAxel Dörfler status_t
68018d3e65eSAxel Dörfler ActivityView::SaveState(BMessage& state) const
68118d3e65eSAxel Dörfler {
6823a4a2141SAxel Dörfler 	status_t status = state.AddBool("show legend", fShowLegend);
6833a4a2141SAxel Dörfler 	if (status != B_OK)
6843a4a2141SAxel Dörfler 		return status;
6853a4a2141SAxel Dörfler 
686eee6f40bSAlexandre Deckner 	status = state.AddInt64("refresh interval", fRefreshInterval);
687eee6f40bSAlexandre Deckner 	if (status != B_OK)
688eee6f40bSAlexandre Deckner 		return status;
689eee6f40bSAlexandre Deckner 
6909c89c450SAxel Dörfler 	status = state.AddData("history background color", B_RGB_COLOR_TYPE,
6919c89c450SAxel Dörfler 		&fHistoryBackgroundColor, sizeof(rgb_color));
69279cbd226SFrançois Revol 	if (status != B_OK)
69379cbd226SFrançois Revol 		return status;
69479cbd226SFrançois Revol 
6953a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems(); i++) {
6963a4a2141SAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
6973a4a2141SAxel Dörfler 
6983a4a2141SAxel Dörfler 		if (!source->PerCPU() || source->CPU() == 0)
6993a4a2141SAxel Dörfler 			status = state.AddString("source", source->Name());
7003a4a2141SAxel Dörfler 		if (status != B_OK)
7013a4a2141SAxel Dörfler 			return status;
7023a4a2141SAxel Dörfler 
7039c89c450SAxel Dörfler 		BString name = source->Name();
7049c89c450SAxel Dörfler 		name << " color";
7059c89c450SAxel Dörfler 		rgb_color color = source->Color();
7069c89c450SAxel Dörfler 		state.AddData(name.String(), B_RGB_COLOR_TYPE, &color,
7079c89c450SAxel Dörfler 			sizeof(rgb_color));
7083a4a2141SAxel Dörfler 	}
7093a4a2141SAxel Dörfler 	return B_OK;
71018d3e65eSAxel Dörfler }
71118d3e65eSAxel Dörfler 
71218d3e65eSAxel Dörfler 
71351591198SAxel Dörfler Scale*
71451591198SAxel Dörfler ActivityView::_ScaleFor(scale_type type)
71551591198SAxel Dörfler {
71651591198SAxel Dörfler 	if (type == kNoScale)
71751591198SAxel Dörfler 		return NULL;
71851591198SAxel Dörfler 
71951591198SAxel Dörfler 	std::map<scale_type, ::Scale*>::iterator iterator = fScales.find(type);
72051591198SAxel Dörfler 	if (iterator != fScales.end())
72151591198SAxel Dörfler 		return iterator->second;
72251591198SAxel Dörfler 
72351591198SAxel Dörfler 	// add new scale
72451591198SAxel Dörfler 	::Scale* scale = new ::Scale(type);
72551591198SAxel Dörfler 	fScales[type] = scale;
72651591198SAxel Dörfler 
72751591198SAxel Dörfler 	return scale;
72851591198SAxel Dörfler }
72951591198SAxel Dörfler 
73051591198SAxel Dörfler 
731dc1ffc79SFrançois Revol #ifdef __HAIKU__
732065e8de0SAxel Dörfler BLayoutItem*
733065e8de0SAxel Dörfler ActivityView::CreateHistoryLayoutItem()
734065e8de0SAxel Dörfler {
735065e8de0SAxel Dörfler 	if (fHistoryLayoutItem == NULL)
736065e8de0SAxel Dörfler 		fHistoryLayoutItem = new HistoryLayoutItem(this);
737065e8de0SAxel Dörfler 
738065e8de0SAxel Dörfler 	return fHistoryLayoutItem;
739065e8de0SAxel Dörfler }
740065e8de0SAxel Dörfler 
741065e8de0SAxel Dörfler 
742065e8de0SAxel Dörfler BLayoutItem*
743065e8de0SAxel Dörfler ActivityView::CreateLegendLayoutItem()
744065e8de0SAxel Dörfler {
745065e8de0SAxel Dörfler 	if (fLegendLayoutItem == NULL)
746065e8de0SAxel Dörfler 		fLegendLayoutItem = new LegendLayoutItem(this);
747065e8de0SAxel Dörfler 
748065e8de0SAxel Dörfler 	return fLegendLayoutItem;
749065e8de0SAxel Dörfler }
750dc1ffc79SFrançois Revol #endif
751065e8de0SAxel Dörfler 
7529c89c450SAxel Dörfler 
75318d3e65eSAxel Dörfler DataSource*
7543a4a2141SAxel Dörfler ActivityView::FindDataSource(const DataSource* search)
75518d3e65eSAxel Dörfler {
756d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
757d4216445SAxel Dörfler 
75818d3e65eSAxel Dörfler 	for (int32 i = fSources.CountItems(); i-- > 0;) {
75918d3e65eSAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
7603a4a2141SAxel Dörfler 		if (!strcmp(source->Name(), search->Name()))
76118d3e65eSAxel Dörfler 			return source;
76218d3e65eSAxel Dörfler 	}
76318d3e65eSAxel Dörfler 
76418d3e65eSAxel Dörfler 	return NULL;
76518d3e65eSAxel Dörfler }
76618d3e65eSAxel Dörfler 
76718d3e65eSAxel Dörfler 
76818d3e65eSAxel Dörfler status_t
7699c89c450SAxel Dörfler ActivityView::AddDataSource(const DataSource* source, const BMessage* state)
77018d3e65eSAxel Dörfler {
7713a4a2141SAxel Dörfler 	if (source == NULL)
7723a4a2141SAxel Dörfler 		return B_BAD_VALUE;
7733a4a2141SAxel Dörfler 
774d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
775d4216445SAxel Dörfler 
7768e26f387SAxel Dörfler 	// Search for the correct insert spot to maintain the order of the sources
7773a4a2141SAxel Dörfler 	int32 insert = DataSource::IndexOf(source);
7783a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) {
7793a4a2141SAxel Dörfler 		DataSource* before = fSources.ItemAt(i);
7803a4a2141SAxel Dörfler 		if (DataSource::IndexOf(before) > insert) {
7813a4a2141SAxel Dörfler 			insert = i;
7823a4a2141SAxel Dörfler 			break;
7833a4a2141SAxel Dörfler 		}
7843a4a2141SAxel Dörfler 	}
7853a4a2141SAxel Dörfler 	if (insert > fSources.CountItems())
7863a4a2141SAxel Dörfler 		insert = fSources.CountItems();
7873a4a2141SAxel Dörfler 
7888e26f387SAxel Dörfler 	// Generate DataHistory and ViewHistory objects for the source
7898e26f387SAxel Dörfler 	// (one might need one history per CPU)
7908e26f387SAxel Dörfler 
7913a4a2141SAxel Dörfler 	uint32 count = 1;
7923a4a2141SAxel Dörfler 	if (source->PerCPU()) {
7933a4a2141SAxel Dörfler 		SystemInfo info;
7943a4a2141SAxel Dörfler 		count = info.CPUCount();
7953a4a2141SAxel Dörfler 	}
7963a4a2141SAxel Dörfler 
7973a4a2141SAxel Dörfler 	for (uint32 i = 0; i < count; i++) {
79818d3e65eSAxel Dörfler 		DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
7991bb87bd0SAxel Dörfler 			RefreshInterval());
8008e26f387SAxel Dörfler 		ListAddDeleter<DataHistory> valuesDeleter(fValues, values, insert);
8013a4a2141SAxel Dörfler 
8028e26f387SAxel Dörfler 		ViewHistory* viewValues = new(std::nothrow) ViewHistory;
8038e26f387SAxel Dörfler 		ListAddDeleter<ViewHistory> viewValuesDeleter(fViewValues, viewValues,
8048e26f387SAxel Dörfler 			insert);
8058e26f387SAxel Dörfler 
8068e26f387SAxel Dörfler 		if (valuesDeleter.Failed() || viewValuesDeleter.Failed())
80718d3e65eSAxel Dörfler 			return B_NO_MEMORY;
80818d3e65eSAxel Dörfler 
80951591198SAxel Dörfler 		values->SetScale(_ScaleFor(source->ScaleType()));
81051591198SAxel Dörfler 
8113a4a2141SAxel Dörfler 		DataSource* copy;
8123a4a2141SAxel Dörfler 		if (source->PerCPU())
8133a4a2141SAxel Dörfler 			copy = source->CopyForCPU(i);
8143a4a2141SAxel Dörfler 		else
8153a4a2141SAxel Dörfler 			copy = source->Copy();
8163a4a2141SAxel Dörfler 
8178e26f387SAxel Dörfler 		ListAddDeleter<DataSource> sourceDeleter(fSources, copy, insert);
8188e26f387SAxel Dörfler 		if (sourceDeleter.Failed())
8198e26f387SAxel Dörfler 			return B_NO_MEMORY;
8208e26f387SAxel Dörfler 
8219c89c450SAxel Dörfler 		BString colorName = source->Name();
8229c89c450SAxel Dörfler 		colorName << " color";
8239c89c450SAxel Dörfler 		if (state != NULL) {
8249c89c450SAxel Dörfler 			const rgb_color* color = NULL;
8259c89c450SAxel Dörfler 			ssize_t colorLength;
8269c89c450SAxel Dörfler 			if (state->FindData(colorName.String(), B_RGB_COLOR_TYPE, i,
8279c89c450SAxel Dörfler 					(const void**)&color, &colorLength) == B_OK
8289c89c450SAxel Dörfler 				&& colorLength == sizeof(rgb_color))
8299c89c450SAxel Dörfler 				copy->SetColor(*color);
8309c89c450SAxel Dörfler 		}
8319c89c450SAxel Dörfler 
8328e26f387SAxel Dörfler 		valuesDeleter.Detach();
8338e26f387SAxel Dörfler 		viewValuesDeleter.Detach();
8348e26f387SAxel Dörfler 		sourceDeleter.Detach();
8353a4a2141SAxel Dörfler 	}
83618d3e65eSAxel Dörfler 
837dc1ffc79SFrançois Revol #ifdef __HAIKU__
838065e8de0SAxel Dörfler 	InvalidateLayout();
839dc1ffc79SFrançois Revol #endif
84018d3e65eSAxel Dörfler 	return B_OK;
84118d3e65eSAxel Dörfler }
84218d3e65eSAxel Dörfler 
84318d3e65eSAxel Dörfler 
84418d3e65eSAxel Dörfler status_t
8453a4a2141SAxel Dörfler ActivityView::RemoveDataSource(const DataSource* remove)
84618d3e65eSAxel Dörfler {
847065e8de0SAxel Dörfler 	bool removed = false;
848065e8de0SAxel Dörfler 
849d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
850d4216445SAxel Dörfler 
8513a4a2141SAxel Dörfler 	while (true) {
8523a4a2141SAxel Dörfler 		DataSource* source = FindDataSource(remove);
853065e8de0SAxel Dörfler 		if (source == NULL) {
854065e8de0SAxel Dörfler 			if (removed)
855065e8de0SAxel Dörfler 				break;
856065e8de0SAxel Dörfler 			return B_ENTRY_NOT_FOUND;
857065e8de0SAxel Dörfler 		}
8583a4a2141SAxel Dörfler 
85918d3e65eSAxel Dörfler 		int32 index = fSources.IndexOf(source);
86018d3e65eSAxel Dörfler 		if (index < 0)
86118d3e65eSAxel Dörfler 			return B_ENTRY_NOT_FOUND;
86218d3e65eSAxel Dörfler 
86318d3e65eSAxel Dörfler 		fSources.RemoveItemAt(index);
86418d3e65eSAxel Dörfler 		delete source;
86518d3e65eSAxel Dörfler 		DataHistory* values = fValues.RemoveItemAt(index);
86618d3e65eSAxel Dörfler 		delete values;
867065e8de0SAxel Dörfler 		removed = true;
8683a4a2141SAxel Dörfler 	}
86918d3e65eSAxel Dörfler 
870dc1ffc79SFrançois Revol #ifdef __HAIKU__
871065e8de0SAxel Dörfler 	InvalidateLayout();
872dc1ffc79SFrançois Revol #endif
87318d3e65eSAxel Dörfler 	return B_OK;
87418d3e65eSAxel Dörfler }
87518d3e65eSAxel Dörfler 
87618d3e65eSAxel Dörfler 
87718d3e65eSAxel Dörfler void
87818d3e65eSAxel Dörfler ActivityView::RemoveAllDataSources()
87918d3e65eSAxel Dörfler {
880d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
881d4216445SAxel Dörfler 
88218d3e65eSAxel Dörfler 	fSources.MakeEmpty();
88318d3e65eSAxel Dörfler 	fValues.MakeEmpty();
88418d3e65eSAxel Dörfler }
88518d3e65eSAxel Dörfler 
88618d3e65eSAxel Dörfler 
88718d3e65eSAxel Dörfler void
88818d3e65eSAxel Dörfler ActivityView::AttachedToWindow()
88918d3e65eSAxel Dörfler {
890bb7cffd0SPhilippe Saint-Pierre 	if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0)
891bb7cffd0SPhilippe Saint-Pierre 		_LoadBackgroundInfo(true);
892bb7cffd0SPhilippe Saint-Pierre 
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
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
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
93018d3e65eSAxel Dörfler ActivityView::FrameResized(float /*width*/, float /*height*/)
93118d3e65eSAxel Dörfler {
9323a4a2141SAxel Dörfler 	_UpdateOffscreenBitmap();
9333a4a2141SAxel Dörfler }
9343a4a2141SAxel Dörfler 
9353a4a2141SAxel Dörfler 
9363a4a2141SAxel Dörfler void
9379c89c450SAxel Dörfler ActivityView::_UpdateOffscreenBitmap()
9383a4a2141SAxel Dörfler {
9393a4a2141SAxel Dörfler 	BRect frame = _HistoryFrame();
940ed1b2753SStephan Aßmus 	frame.OffsetTo(B_ORIGIN);
941ed1b2753SStephan Aßmus 
9429c89c450SAxel Dörfler 	if (fOffscreen != NULL && frame == fOffscreen->Bounds())
9433a4a2141SAxel Dörfler 		return;
9443a4a2141SAxel Dörfler 
9453a4a2141SAxel Dörfler 	delete fOffscreen;
9463a4a2141SAxel Dörfler 
9473a4a2141SAxel Dörfler 	// create offscreen bitmap
9483a4a2141SAxel Dörfler 
9493a4a2141SAxel Dörfler 	fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS,
9503a4a2141SAxel Dörfler 		B_RGB32);
9513a4a2141SAxel Dörfler 	if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) {
9523a4a2141SAxel Dörfler 		delete fOffscreen;
9533a4a2141SAxel Dörfler 		fOffscreen = NULL;
9543a4a2141SAxel Dörfler 		return;
9553a4a2141SAxel Dörfler 	}
9563a4a2141SAxel Dörfler 
9573a4a2141SAxel Dörfler 	BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE);
9589c89c450SAxel Dörfler 	view->SetViewColor(fHistoryBackgroundColor);
9593a4a2141SAxel Dörfler 	view->SetLowColor(view->ViewColor());
9603a4a2141SAxel Dörfler 	fOffscreen->AddChild(view);
96118d3e65eSAxel Dörfler }
96218d3e65eSAxel Dörfler 
96318d3e65eSAxel Dörfler 
9649c89c450SAxel Dörfler BView*
9659c89c450SAxel Dörfler ActivityView::_OffscreenView()
9669c89c450SAxel Dörfler {
9679c89c450SAxel Dörfler 	if (fOffscreen == NULL)
9689c89c450SAxel Dörfler 		return NULL;
9699c89c450SAxel Dörfler 
9709c89c450SAxel Dörfler 	return fOffscreen->ChildAt(0);
9719c89c450SAxel Dörfler }
9729c89c450SAxel Dörfler 
9739c89c450SAxel Dörfler 
97418d3e65eSAxel Dörfler void
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 
9927974d3dcSStephan Aßmus 	BMenu* additionalMenu = new BMenu("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();
10197974d3dcSStephan Aßmus 	menu->AddItem(new BMenuItem(fShowLegend ? "Hide legend" : "Show legend",
10203a4a2141SAxel Dörfler 		new BMessage(kMsgToggleLegend)));
10213a4a2141SAxel Dörfler 
102218d3e65eSAxel Dörfler 	menu->SetTargetForItems(this);
1023dc1ffc79SFrançois Revol 	additionalMenu->SetTargetForItems(this);
102418d3e65eSAxel Dörfler 
10253f315b26SAxel Dörfler 	ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
10263f315b26SAxel Dörfler 	if (window != NULL && window->ActivityViewCount() > 1) {
10273f315b26SAxel Dörfler 		menu->AddSeparatorItem();
10283f315b26SAxel Dörfler 		BMessage* message = new BMessage(kMsgRemoveView);
10293f315b26SAxel Dörfler 		message->AddPointer("view", this);
10307974d3dcSStephan Aßmus 		menu->AddItem(item = new BMenuItem("Remove graph", message));
10313f315b26SAxel Dörfler 		item->SetTarget(window);
10323f315b26SAxel Dörfler 	}
10333f315b26SAxel Dörfler 
103418d3e65eSAxel Dörfler 	ConvertToScreen(&where);
103518d3e65eSAxel Dörfler 	menu->Go(where, true, false, true);
103618d3e65eSAxel Dörfler }
103718d3e65eSAxel Dörfler 
103818d3e65eSAxel Dörfler 
103918d3e65eSAxel Dörfler void
104051591198SAxel Dörfler ActivityView::MouseUp(BPoint where)
104151591198SAxel Dörfler {
104251591198SAxel Dörfler 	fZooming = false;
104351591198SAxel Dörfler }
104451591198SAxel Dörfler 
104551591198SAxel Dörfler 
104651591198SAxel Dörfler void
104718d3e65eSAxel Dörfler ActivityView::MouseMoved(BPoint where, uint32 transit,
104818d3e65eSAxel Dörfler 	const BMessage* dragMessage)
104918d3e65eSAxel Dörfler {
105051591198SAxel Dörfler 	if (!fZooming)
105151591198SAxel Dörfler 		return;
105251591198SAxel Dörfler 
105351591198SAxel Dörfler 	int32 shift = int32(where.x - fZoomPoint.x) / 25;
10541bb87bd0SAxel Dörfler 	int32 resolution;
105551591198SAxel Dörfler 	if (shift > 0)
10561bb87bd0SAxel Dörfler 		resolution = fOriginalResolution << shift;
105751591198SAxel Dörfler 	else
10581bb87bd0SAxel Dörfler 		resolution = fOriginalResolution >> -shift;
105951591198SAxel Dörfler 
10601bb87bd0SAxel Dörfler 	_UpdateResolution(resolution);
106118d3e65eSAxel Dörfler }
106218d3e65eSAxel Dörfler 
106318d3e65eSAxel Dörfler 
106418d3e65eSAxel Dörfler void
106518d3e65eSAxel Dörfler ActivityView::MessageReceived(BMessage* message)
106618d3e65eSAxel Dörfler {
1067c28f8ea3SFrançois Revol 	// if a color is dropped, use it as background
1068c28f8ea3SFrançois Revol 	if (message->WasDropped()) {
1069c28f8ea3SFrançois Revol 		rgb_color* color;
1070c28f8ea3SFrançois Revol 		ssize_t size;
10711201d52eSAxel Dörfler 		if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0,
10721201d52eSAxel Dörfler 				(const void**)&color, &size) == B_OK
10739c89c450SAxel Dörfler 			&& size == sizeof(rgb_color)) {
10749c89c450SAxel Dörfler 			BPoint dropPoint = message->DropPoint();
1075c28f8ea3SFrançois Revol 			ConvertFromScreen(&dropPoint);
10769c89c450SAxel Dörfler 
1077c28f8ea3SFrançois Revol 			if (_HistoryFrame().Contains(dropPoint)) {
10789c89c450SAxel Dörfler 				fHistoryBackgroundColor = *color;
10799c89c450SAxel Dörfler 				Invalidate(_HistoryFrame());
1080c28f8ea3SFrançois Revol 			} else {
10815f2f72a2SFrançois Revol 				// check each legend color box
1082d4216445SAxel Dörfler 				BAutolock _(fSourcesLock);
1083d4216445SAxel Dörfler 
10845f2f72a2SFrançois Revol 				BRect legendFrame = _LegendFrame();
10859c89c450SAxel Dörfler 				for (int32 i = 0; i < fSources.CountItems(); i++) {
10861201d52eSAxel Dörfler 					BRect frame = _LegendColorFrameAt(legendFrame, i);
10879c89c450SAxel Dörfler 					if (frame.Contains(dropPoint)) {
10885f2f72a2SFrançois Revol 						fSources.ItemAt(i)->SetColor(*color);
10899c89c450SAxel Dörfler 						Invalidate(_HistoryFrame());
10901201d52eSAxel Dörfler 						Invalidate(frame);
10915f2f72a2SFrançois Revol 						return;
10925f2f72a2SFrançois Revol 					}
10935f2f72a2SFrançois Revol 				}
10949c89c450SAxel Dörfler 
10959c89c450SAxel Dörfler 				if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) {
10969c89c450SAxel Dörfler 					// allow background color change in the replicant only
10979c89c450SAxel Dörfler 					fLegendBackgroundColor = *color;
10981201d52eSAxel Dörfler 					SetLowColor(fLegendBackgroundColor);
10999c89c450SAxel Dörfler 					Invalidate(legendFrame);
11009c89c450SAxel Dörfler 				}
1101c28f8ea3SFrançois Revol 			}
1102c28f8ea3SFrançois Revol 			return;
1103c28f8ea3SFrançois Revol 		}
11049c89c450SAxel Dörfler 	}
11059c89c450SAxel Dörfler 
110618d3e65eSAxel Dörfler 	switch (message->what) {
110718d3e65eSAxel Dörfler 		case B_ABOUT_REQUESTED:
110818d3e65eSAxel Dörfler 			ActivityMonitor::ShowAbout();
110918d3e65eSAxel Dörfler 			break;
111018d3e65eSAxel Dörfler 
1111bb7cffd0SPhilippe Saint-Pierre 		case B_NODE_MONITOR:
1112bb7cffd0SPhilippe Saint-Pierre 		{
1113bb7cffd0SPhilippe Saint-Pierre 			BString attrName;
1114bb7cffd0SPhilippe Saint-Pierre 			if (message->FindString("attr", &attrName) == B_OK) {
1115bb7cffd0SPhilippe Saint-Pierre 				if (attrName == kDesktopAttrName)
1116bb7cffd0SPhilippe Saint-Pierre 					_LoadBackgroundInfo(false);
1117bb7cffd0SPhilippe Saint-Pierre 			} else
1118bb7cffd0SPhilippe Saint-Pierre 				_LoadBackgroundInfo(false);
1119bb7cffd0SPhilippe Saint-Pierre 			break;
1120bb7cffd0SPhilippe Saint-Pierre 		}
1121bb7cffd0SPhilippe Saint-Pierre 
11221bb87bd0SAxel Dörfler 		case kMsgUpdateResolution:
11231bb87bd0SAxel Dörfler 		{
11241bb87bd0SAxel Dörfler 			int32 resolution;
11251bb87bd0SAxel Dörfler 			if (message->FindInt32("resolution", &resolution) != B_OK)
11261bb87bd0SAxel Dörfler 				break;
11271bb87bd0SAxel Dörfler 
11281bb87bd0SAxel Dörfler 			_UpdateResolution(resolution, false);
11291bb87bd0SAxel Dörfler 			break;
11301bb87bd0SAxel Dörfler 		}
11311bb87bd0SAxel Dörfler 
11321bb87bd0SAxel Dörfler 		case kMsgTimeIntervalUpdated:
11331bb87bd0SAxel Dörfler 			bigtime_t interval;
11341bb87bd0SAxel Dörfler 			if (message->FindInt64("interval", &interval) != B_OK)
11351bb87bd0SAxel Dörfler 				break;
11361bb87bd0SAxel Dörfler 
11371bb87bd0SAxel Dörfler 			if (interval < 10000)
11381bb87bd0SAxel Dörfler 				interval = 10000;
11391bb87bd0SAxel Dörfler 
11401bb87bd0SAxel Dörfler 			atomic_set64(&fRefreshInterval, interval);
11411bb87bd0SAxel Dörfler 			break;
11421bb87bd0SAxel Dörfler 
114318d3e65eSAxel Dörfler 		case kMsgToggleDataSource:
114418d3e65eSAxel Dörfler 		{
114518d3e65eSAxel Dörfler 			int32 index;
114618d3e65eSAxel Dörfler 			if (message->FindInt32("index", &index) != B_OK)
114718d3e65eSAxel Dörfler 				break;
114818d3e65eSAxel Dörfler 
114918d3e65eSAxel Dörfler 			const DataSource* baseSource = DataSource::SourceAt(index);
115018d3e65eSAxel Dörfler 			if (baseSource == NULL)
115118d3e65eSAxel Dörfler 				break;
115218d3e65eSAxel Dörfler 
11533a4a2141SAxel Dörfler 			DataSource* source = FindDataSource(baseSource);
115418d3e65eSAxel Dörfler 			if (source == NULL)
11553a4a2141SAxel Dörfler 				AddDataSource(baseSource);
115618d3e65eSAxel Dörfler 			else
11577d33b63dSAxel Dörfler 				RemoveDataSource(baseSource);
115818d3e65eSAxel Dörfler 
115918d3e65eSAxel Dörfler 			Invalidate();
116018d3e65eSAxel Dörfler 			break;
116118d3e65eSAxel Dörfler 		}
116218d3e65eSAxel Dörfler 
11633a4a2141SAxel Dörfler 		case kMsgToggleLegend:
11643a4a2141SAxel Dörfler 			fShowLegend = !fShowLegend;
11653a4a2141SAxel Dörfler 			Invalidate();
11663a4a2141SAxel Dörfler 			break;
11673a4a2141SAxel Dörfler 
116818d3e65eSAxel Dörfler 		case B_MOUSE_WHEEL_CHANGED:
116918d3e65eSAxel Dörfler 		{
117018d3e65eSAxel Dörfler 			float deltaY = 0.0f;
117118d3e65eSAxel Dörfler 			if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK
117218d3e65eSAxel Dörfler 				|| deltaY == 0.0f)
117318d3e65eSAxel Dörfler 				break;
117418d3e65eSAxel Dörfler 
11751bb87bd0SAxel Dörfler 			int32 resolution = fDrawResolution;
117618d3e65eSAxel Dörfler 			if (deltaY > 0)
11771bb87bd0SAxel Dörfler 				resolution *= 2;
117818d3e65eSAxel Dörfler 			else
11791bb87bd0SAxel Dörfler 				resolution /= 2;
118018d3e65eSAxel Dörfler 
11811bb87bd0SAxel Dörfler 			_UpdateResolution(resolution);
118218d3e65eSAxel Dörfler 			break;
118318d3e65eSAxel Dörfler 		}
118418d3e65eSAxel Dörfler 
118518d3e65eSAxel Dörfler 		default:
118618d3e65eSAxel Dörfler 			BView::MessageReceived(message);
118718d3e65eSAxel Dörfler 			break;
118818d3e65eSAxel Dörfler 	}
118918d3e65eSAxel Dörfler }
119018d3e65eSAxel Dörfler 
119118d3e65eSAxel Dörfler 
1192065e8de0SAxel Dörfler void
1193065e8de0SAxel Dörfler ActivityView::_UpdateFrame()
1194065e8de0SAxel Dörfler {
1195dc1ffc79SFrançois Revol #ifdef __HAIKU__
1196065e8de0SAxel Dörfler 	if (fLegendLayoutItem == NULL || fHistoryLayoutItem == NULL)
1197065e8de0SAxel Dörfler 		return;
1198065e8de0SAxel Dörfler 
1199065e8de0SAxel Dörfler 	BRect historyFrame = fHistoryLayoutItem->Frame();
1200065e8de0SAxel Dörfler 	BRect legendFrame = fLegendLayoutItem->Frame();
1201dc1ffc79SFrançois Revol #else
1202dc1ffc79SFrançois Revol 	BRect historyFrame = Bounds();
1203dc1ffc79SFrançois Revol 	BRect legendFrame = Bounds();
1204dc1ffc79SFrançois Revol 	historyFrame.bottom -= 2 * Bounds().Height() / 3;
1205dc1ffc79SFrançois Revol 	legendFrame.top += Bounds().Height() / 3;
1206dc1ffc79SFrançois Revol #endif
1207065e8de0SAxel Dörfler 	MoveTo(historyFrame.left, historyFrame.top);
1208065e8de0SAxel Dörfler 	ResizeTo(legendFrame.left + legendFrame.Width() - historyFrame.left,
1209065e8de0SAxel Dörfler 		legendFrame.top + legendFrame.Height() - historyFrame.top);
1210065e8de0SAxel Dörfler }
1211065e8de0SAxel Dörfler 
1212065e8de0SAxel Dörfler 
12133a4a2141SAxel Dörfler BRect
12143a4a2141SAxel Dörfler ActivityView::_HistoryFrame() const
12153a4a2141SAxel Dörfler {
12163a4a2141SAxel Dörfler 	BRect frame = Bounds();
12173a4a2141SAxel Dörfler 
1218ed1b2753SStephan Aßmus 	if (fShowLegend) {
1219ed1b2753SStephan Aßmus 		BRect legendFrame = _LegendFrame();
12203a4a2141SAxel Dörfler 		frame.bottom = legendFrame.top - 1;
1221ed1b2753SStephan Aßmus 	}
1222ed1b2753SStephan Aßmus 
1223ed1b2753SStephan Aßmus 	frame.InsetBy(2, 2);
12243a4a2141SAxel Dörfler 
12253a4a2141SAxel Dörfler 	return frame;
12263a4a2141SAxel Dörfler }
12273a4a2141SAxel Dörfler 
12283a4a2141SAxel Dörfler 
1229065e8de0SAxel Dörfler float
1230065e8de0SAxel Dörfler ActivityView::_LegendHeight() const
12313a4a2141SAxel Dörfler {
12323a4a2141SAxel Dörfler 	font_height fontHeight;
12333a4a2141SAxel Dörfler 	GetFontHeight(&fontHeight);
12343a4a2141SAxel Dörfler 
1235d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
1236d4216445SAxel Dörfler 
12373a4a2141SAxel Dörfler 	int32 rows = (fSources.CountItems() + 1) / 2;
1238fbb82a62SPhilippe Saint-Pierre 
1239*e45d83a9SPhilippe Saint-Pierre 	int32 boldMargin = Parent()
1240*e45d83a9SPhilippe Saint-Pierre 		&& (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0 ? 2 : 0;
1241fbb82a62SPhilippe Saint-Pierre 
1242065e8de0SAxel Dörfler 	return rows * (4 + ceilf(fontHeight.ascent)
1243fbb82a62SPhilippe Saint-Pierre 		+ ceilf(fontHeight.descent) + ceilf(fontHeight.leading)) + boldMargin;
1244065e8de0SAxel Dörfler }
1245065e8de0SAxel Dörfler 
1246065e8de0SAxel Dörfler 
1247065e8de0SAxel Dörfler BRect
1248065e8de0SAxel Dörfler ActivityView::_LegendFrame() const
1249065e8de0SAxel Dörfler {
1250065e8de0SAxel Dörfler 	float height;
1251dc1ffc79SFrançois Revol #ifdef __HAIKU__
1252065e8de0SAxel Dörfler 	if (fLegendLayoutItem != NULL)
1253065e8de0SAxel Dörfler 		height = fLegendLayoutItem->Frame().Height();
1254065e8de0SAxel Dörfler 	else
1255dc1ffc79SFrançois Revol #endif
1256065e8de0SAxel Dörfler 		height = _LegendHeight();
1257065e8de0SAxel Dörfler 
1258065e8de0SAxel Dörfler 	BRect frame = Bounds();
1259065e8de0SAxel Dörfler 	frame.top = frame.bottom - height;
12603a4a2141SAxel Dörfler 
12613a4a2141SAxel Dörfler 	return frame;
12623a4a2141SAxel Dörfler }
12633a4a2141SAxel Dörfler 
12643a4a2141SAxel Dörfler 
12653a4a2141SAxel Dörfler BRect
12663a4a2141SAxel Dörfler ActivityView::_LegendFrameAt(BRect frame, int32 index) const
12673a4a2141SAxel Dörfler {
12683a4a2141SAxel Dörfler 	int32 column = index & 1;
12693a4a2141SAxel Dörfler 	int32 row = index / 2;
12703a4a2141SAxel Dörfler 	if (column == 0)
12713a4a2141SAxel Dörfler 		frame.right = frame.left + floorf(frame.Width() / 2) - 5;
12723a4a2141SAxel Dörfler 	else
12733a4a2141SAxel Dörfler 		frame.left = frame.right - floorf(frame.Width() / 2) + 5;
12743a4a2141SAxel Dörfler 
1275d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
1276d4216445SAxel Dörfler 
12773a4a2141SAxel Dörfler 	int32 rows = (fSources.CountItems() + 1) / 2;
12783a4a2141SAxel Dörfler 	float height = floorf((frame.Height() - 5) / rows);
12793a4a2141SAxel Dörfler 
12803a4a2141SAxel Dörfler 	frame.top = frame.top + 5 + row * height;
12813a4a2141SAxel Dörfler 	frame.bottom = frame.top + height - 1;
12823a4a2141SAxel Dörfler 
12833a4a2141SAxel Dörfler 	return frame;
12843a4a2141SAxel Dörfler }
12853a4a2141SAxel Dörfler 
12863a4a2141SAxel Dörfler 
12871201d52eSAxel Dörfler BRect
12881201d52eSAxel Dörfler ActivityView::_LegendColorFrameAt(BRect frame, int32 index) const
12891201d52eSAxel Dörfler {
12901201d52eSAxel Dörfler 	frame = _LegendFrameAt(frame, index);
12911201d52eSAxel Dörfler 	frame.InsetBy(1, 1);
12921201d52eSAxel Dörfler 	frame.right = frame.left + frame.Height();
12931201d52eSAxel Dörfler 
12941201d52eSAxel Dörfler 	return frame;
12951201d52eSAxel Dörfler }
12961201d52eSAxel Dörfler 
12971201d52eSAxel Dörfler 
129818d3e65eSAxel Dörfler float
129918d3e65eSAxel Dörfler ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
130018d3e65eSAxel Dörfler 	int64 value)
130118d3e65eSAxel Dörfler {
130218d3e65eSAxel Dörfler 	int64 min = source->Minimum();
130318d3e65eSAxel Dörfler 	int64 max = source->Maximum();
130418d3e65eSAxel Dörfler 	if (source->AdaptiveScale()) {
130518d3e65eSAxel Dörfler 		int64 adaptiveMax = int64(values->MaximumValue() * 1.2);
130618d3e65eSAxel Dörfler 		if (adaptiveMax < max)
130718d3e65eSAxel Dörfler 			max = adaptiveMax;
130818d3e65eSAxel Dörfler 	}
130918d3e65eSAxel Dörfler 
131018d3e65eSAxel Dörfler 	if (value > max)
131118d3e65eSAxel Dörfler 		value = max;
131218d3e65eSAxel Dörfler 	if (value < min)
131318d3e65eSAxel Dörfler 		value = min;
131418d3e65eSAxel Dörfler 
13153a4a2141SAxel Dörfler 	float height = _HistoryFrame().Height();
131618d3e65eSAxel Dörfler 	return height - (value - min) * height / (max - min);
131718d3e65eSAxel Dörfler }
131818d3e65eSAxel Dörfler 
131918d3e65eSAxel Dörfler 
132018d3e65eSAxel Dörfler void
1321ed1b2753SStephan Aßmus ActivityView::_DrawHistory(bool drawBackground)
132218d3e65eSAxel Dörfler {
13233a4a2141SAxel Dörfler 	_UpdateOffscreenBitmap();
13243a4a2141SAxel Dörfler 
13253a4a2141SAxel Dörfler 	BView* view = this;
13263a4a2141SAxel Dörfler 	if (fOffscreen != NULL) {
13273a4a2141SAxel Dörfler 		fOffscreen->Lock();
13289c89c450SAxel Dörfler 		view = _OffscreenView();
13293a4a2141SAxel Dörfler 	}
13303a4a2141SAxel Dörfler 
13313a4a2141SAxel Dörfler 	BRect frame = _HistoryFrame();
1332ed1b2753SStephan Aßmus 	BRect outerFrame = frame.InsetByCopy(-2, -2);
1333ed1b2753SStephan Aßmus 
1334ed1b2753SStephan Aßmus 	// draw the outer frame
1335ed1b2753SStephan Aßmus 	uint32 flags = 0;
1336ed1b2753SStephan Aßmus 	if (!drawBackground)
1337ed1b2753SStephan Aßmus 		flags |= BControlLook::B_BLEND_FRAME;
1338ed1b2753SStephan Aßmus 	be_control_look->DrawTextControlBorder(this, outerFrame,
1339ed1b2753SStephan Aßmus 		outerFrame, fLegendBackgroundColor, flags);
1340ed1b2753SStephan Aßmus 
1341ed1b2753SStephan Aßmus 	// convert to offscreen view if necessary
1342ed1b2753SStephan Aßmus 	if (view != this)
1343ed1b2753SStephan Aßmus 		frame.OffsetTo(B_ORIGIN);
1344ed1b2753SStephan Aßmus 
13451201d52eSAxel Dörfler 	view->SetLowColor(fHistoryBackgroundColor);
13463a4a2141SAxel Dörfler 	view->FillRect(frame, B_SOLID_LOW);
13473a4a2141SAxel Dörfler 
134818d3e65eSAxel Dörfler 	uint32 step = 2;
134918d3e65eSAxel Dörfler 	uint32 resolution = fDrawResolution;
135018d3e65eSAxel Dörfler 	if (fDrawResolution > 1) {
135118d3e65eSAxel Dörfler 		step = 1;
135218d3e65eSAxel Dörfler 		resolution--;
135318d3e65eSAxel Dörfler 	}
135418d3e65eSAxel Dörfler 
13553a4a2141SAxel Dörfler 	uint32 width = frame.IntegerWidth() - 10;
135618d3e65eSAxel Dörfler 	uint32 steps = width / step;
13571bb87bd0SAxel Dörfler 	bigtime_t timeStep = RefreshInterval() * resolution;
135818d3e65eSAxel Dörfler 	bigtime_t now = system_time();
135918d3e65eSAxel Dörfler 
13601201d52eSAxel Dörfler 	// Draw scale
13611201d52eSAxel Dörfler 	// TODO: add second markers?
13621201d52eSAxel Dörfler 
13633a4a2141SAxel Dörfler 	view->SetPenSize(1);
13643a4a2141SAxel Dörfler 
13651201d52eSAxel Dörfler 	rgb_color scaleColor = view->LowColor();
13661201d52eSAxel Dörfler 	uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3;
13671201d52eSAxel Dörfler 	if (average < 96)
13681201d52eSAxel Dörfler 		scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT);
13691201d52eSAxel Dörfler 	else
13701201d52eSAxel Dörfler 		scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT);
13711201d52eSAxel Dörfler 
13721201d52eSAxel Dörfler 	view->SetHighColor(scaleColor);
13733a4a2141SAxel Dörfler 	view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2),
13743a4a2141SAxel Dörfler 		BPoint(frame.right, frame.top + frame.Height() / 2));
13753a4a2141SAxel Dörfler 
13761201d52eSAxel Dörfler 	// Draw values
13771201d52eSAxel Dörfler 
13781bb87bd0SAxel Dörfler 	view->SetPenSize(1.5);
1379d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
138018d3e65eSAxel Dörfler 
138118d3e65eSAxel Dörfler 	for (uint32 i = fSources.CountItems(); i-- > 0;) {
13828e26f387SAxel Dörfler 		ViewHistory* viewValues = fViewValues.ItemAt(i);
138318d3e65eSAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
138418d3e65eSAxel Dörfler 		DataHistory* values = fValues.ItemAt(i);
138518d3e65eSAxel Dörfler 
13868e26f387SAxel Dörfler 		viewValues->Update(values, steps, fDrawResolution, now, timeStep,
13878e26f387SAxel Dörfler 			RefreshInterval());
13888e26f387SAxel Dörfler 
13898e26f387SAxel Dörfler 		uint32 x = viewValues->Start() * step;
13908e26f387SAxel Dörfler 		BShape shape;
13918e26f387SAxel Dörfler 		bool first = true;
13928e26f387SAxel Dörfler 
13938e26f387SAxel Dörfler 		for (uint32 i = viewValues->Start(); i < steps; x += step, i++) {
13948e26f387SAxel Dörfler 			float y = _PositionForValue(source, values,
13958e26f387SAxel Dörfler 				viewValues->ValueAt(i));
13968e26f387SAxel Dörfler 
13978e26f387SAxel Dörfler 			if (first) {
13988e26f387SAxel Dörfler 				shape.MoveTo(BPoint(x, y));
13998e26f387SAxel Dörfler 				first = false;
14008e26f387SAxel Dörfler 			} else
14018e26f387SAxel Dörfler 				shape.LineTo(BPoint(x, y));
14028e26f387SAxel Dörfler 		}
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);
14078e26f387SAxel Dörfler 		view->StrokeShape(&shape);
140818d3e65eSAxel Dörfler 	}
140918d3e65eSAxel Dörfler 
141018d3e65eSAxel Dörfler 	// TODO: add marks when an app started or quit
14113a4a2141SAxel Dörfler 	view->Sync();
14123a4a2141SAxel Dörfler 	if (fOffscreen != NULL) {
14133a4a2141SAxel Dörfler 		fOffscreen->Unlock();
1414ed1b2753SStephan Aßmus 		DrawBitmap(fOffscreen, outerFrame.LeftTop());
14153a4a2141SAxel Dörfler 	}
14163a4a2141SAxel Dörfler }
14173a4a2141SAxel Dörfler 
14183a4a2141SAxel Dörfler 
14193a4a2141SAxel Dörfler void
14201bb87bd0SAxel Dörfler ActivityView::_UpdateResolution(int32 resolution, bool broadcast)
14211bb87bd0SAxel Dörfler {
14221bb87bd0SAxel Dörfler 	if (resolution < 1)
14231bb87bd0SAxel Dörfler 		resolution = 1;
14241bb87bd0SAxel Dörfler 	if (resolution > 128)
14251bb87bd0SAxel Dörfler 		resolution = 128;
14261bb87bd0SAxel Dörfler 
14271bb87bd0SAxel Dörfler 	if (resolution == fDrawResolution)
14281bb87bd0SAxel Dörfler 		return;
14291bb87bd0SAxel Dörfler 
14301bb87bd0SAxel Dörfler 	ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
14311bb87bd0SAxel Dörfler 	if (broadcast && window != NULL) {
14321bb87bd0SAxel Dörfler 		BMessage update(kMsgUpdateResolution);
14331bb87bd0SAxel Dörfler 		update.AddInt32("resolution", resolution);
14341bb87bd0SAxel Dörfler 		window->BroadcastToActivityViews(&update, this);
14351bb87bd0SAxel Dörfler 	}
14361bb87bd0SAxel Dörfler 
14371bb87bd0SAxel Dörfler 	fDrawResolution = resolution;
14381bb87bd0SAxel Dörfler 	Invalidate();
14391bb87bd0SAxel Dörfler }
14401bb87bd0SAxel Dörfler 
14411bb87bd0SAxel Dörfler 
14421bb87bd0SAxel Dörfler void
1443bb7cffd0SPhilippe Saint-Pierre ActivityView::_LoadBackgroundInfo(bool watch)
1444bb7cffd0SPhilippe Saint-Pierre {
1445bb7cffd0SPhilippe Saint-Pierre 	fCachedOutline = false;
1446bb7cffd0SPhilippe Saint-Pierre 	fCachedWorkspace = -1;
1447bb7cffd0SPhilippe Saint-Pierre 	BPath path;
1448bb7cffd0SPhilippe Saint-Pierre 	if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) {
1449bb7cffd0SPhilippe Saint-Pierre 		BNode desktopNode = BNode(path.Path());
1450bb7cffd0SPhilippe Saint-Pierre 
1451bb7cffd0SPhilippe Saint-Pierre 		attr_info info;
1452bb7cffd0SPhilippe Saint-Pierre 		if (desktopNode.GetAttrInfo(kDesktopAttrName, &info) != B_OK)
1453bb7cffd0SPhilippe Saint-Pierre 			return;
1454bb7cffd0SPhilippe Saint-Pierre 
1455bb7cffd0SPhilippe Saint-Pierre 		char* buffer = new char[info.size];
1456bb7cffd0SPhilippe Saint-Pierre 		if (desktopNode.ReadAttr(kDesktopAttrName, B_MESSAGE_TYPE, 0,
1457bb7cffd0SPhilippe Saint-Pierre 			buffer, (size_t)info.size) == info.size) {
1458bb7cffd0SPhilippe Saint-Pierre 				BMessage message;
1459bb7cffd0SPhilippe Saint-Pierre 				if (message.Unflatten(buffer) == B_OK)
1460bb7cffd0SPhilippe Saint-Pierre 					fBackgroundInfo = message;
1461bb7cffd0SPhilippe Saint-Pierre 		}
1462bb7cffd0SPhilippe Saint-Pierre 		delete[] buffer;
1463bb7cffd0SPhilippe Saint-Pierre 
1464bb7cffd0SPhilippe Saint-Pierre 		if (watch) {
1465bb7cffd0SPhilippe Saint-Pierre 			node_ref nref;
1466bb7cffd0SPhilippe Saint-Pierre 			desktopNode.GetNodeRef(&nref);
1467bb7cffd0SPhilippe Saint-Pierre 			watch_node(&nref, B_WATCH_ATTR, this);
1468bb7cffd0SPhilippe Saint-Pierre 		}
1469bb7cffd0SPhilippe Saint-Pierre 	}
1470bb7cffd0SPhilippe Saint-Pierre }
1471bb7cffd0SPhilippe Saint-Pierre 
1472bb7cffd0SPhilippe Saint-Pierre 
1473bb7cffd0SPhilippe Saint-Pierre void
1474ed1b2753SStephan Aßmus ActivityView::Draw(BRect updateRect)
14753a4a2141SAxel Dörfler {
1476ed1b2753SStephan Aßmus 	bool drawBackground = true;
1477ed1b2753SStephan Aßmus 	if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0)
1478ed1b2753SStephan Aßmus 		drawBackground = false;
1479ed1b2753SStephan Aßmus 
1480ed1b2753SStephan Aßmus 	_DrawHistory(drawBackground);
14813a4a2141SAxel Dörfler 
14823a4a2141SAxel Dörfler 	if (!fShowLegend)
14833a4a2141SAxel Dörfler 		return;
14843a4a2141SAxel Dörfler 
14853a4a2141SAxel Dörfler 	// draw legend
1486ed1b2753SStephan Aßmus 	BRect legendFrame = _LegendFrame();
1487ed1b2753SStephan Aßmus 	SetLowColor(fLegendBackgroundColor);
1488ed1b2753SStephan Aßmus 	if (drawBackground)
1489ed1b2753SStephan Aßmus 		FillRect(legendFrame, B_SOLID_LOW);
14903a4a2141SAxel Dörfler 
1491d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
14923a4a2141SAxel Dörfler 
14933a4a2141SAxel Dörfler 	font_height fontHeight;
14943a4a2141SAxel Dörfler 	GetFontHeight(&fontHeight);
14953a4a2141SAxel Dörfler 
14963a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems(); i++) {
14973a4a2141SAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
14983a4a2141SAxel Dörfler 		DataHistory* values = fValues.ItemAt(i);
14993a4a2141SAxel Dörfler 		BRect frame = _LegendFrameAt(legendFrame, i);
15003a4a2141SAxel Dörfler 
15013a4a2141SAxel Dörfler 		// draw color box
15021201d52eSAxel Dörfler 		BRect colorBox = _LegendColorFrameAt(legendFrame, i);
1503ed1b2753SStephan Aßmus 		BRect rect = colorBox;
1504ed1b2753SStephan Aßmus 		uint32 flags = BControlLook::B_BLEND_FRAME;
1505ed1b2753SStephan Aßmus 		be_control_look->DrawTextControlBorder(this, rect,
1506ed1b2753SStephan Aßmus 			rect, fLegendBackgroundColor, flags);
15073a4a2141SAxel Dörfler 		SetHighColor(source->Color());
1508ed1b2753SStephan Aßmus 		FillRect(rect);
15093a4a2141SAxel Dörfler 
15103a4a2141SAxel Dörfler 		// show current value and label
15113a4a2141SAxel Dörfler 		float y = frame.top + ceilf(fontHeight.ascent);
15123a4a2141SAxel Dörfler 		int64 value = values->ValueAt(values->End());
15133a4a2141SAxel Dörfler 		BString text;
15143a4a2141SAxel Dörfler 		source->Print(text, value);
15153a4a2141SAxel Dörfler 		float width = StringWidth(text.String());
15163a4a2141SAxel Dörfler 
15173a4a2141SAxel Dörfler 		BString label = source->Label();
1518ed1b2753SStephan Aßmus 		float possibleLabelWidth = frame.right - colorBox.right - 12 - width;
1519ed1b2753SStephan Aßmus 		// TODO: TruncateString() is broken... remove + 5 when fixed!
1520ed1b2753SStephan Aßmus 		if (ceilf(StringWidth(label.String()) + 5) > possibleLabelWidth)
1521ed1b2753SStephan Aßmus 			label = source->ShortLabel();
1522ed1b2753SStephan Aßmus 		TruncateString(&label, B_TRUNCATE_MIDDLE, possibleLabelWidth);
15233a4a2141SAxel Dörfler 
1524ed1b2753SStephan Aßmus 		if (drawBackground)
15253a4a2141SAxel Dörfler 			SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
1526ed1b2753SStephan Aßmus 		else {
1527bb7cffd0SPhilippe Saint-Pierre 			rgb_color c = Parent()->ViewColor();
1528bb7cffd0SPhilippe Saint-Pierre 			rgb_color textColor = c.red + c.green * 1.5f + c.blue * 0.50f
1529bb7cffd0SPhilippe Saint-Pierre 				>= 300 ? kBlack : kWhite;
1530bb7cffd0SPhilippe Saint-Pierre 
1531bb7cffd0SPhilippe Saint-Pierre 			int32 mask;
1532bb7cffd0SPhilippe Saint-Pierre 			bool tmpOutline = false;
1533bb7cffd0SPhilippe Saint-Pierre 			bool outline = fCachedOutline;
1534bb7cffd0SPhilippe Saint-Pierre 			int8 indice = 0;
1535bb7cffd0SPhilippe Saint-Pierre 
1536bb7cffd0SPhilippe Saint-Pierre 			if (fCachedWorkspace != current_workspace()) {
1537bb7cffd0SPhilippe Saint-Pierre 				while (fBackgroundInfo.FindInt32("be:bgndimginfoworkspaces",
1538bb7cffd0SPhilippe Saint-Pierre 						indice, &mask) == B_OK
1539bb7cffd0SPhilippe Saint-Pierre 					&& fBackgroundInfo.FindBool("be:bgndimginfoerasetext",
1540bb7cffd0SPhilippe Saint-Pierre 						indice, &tmpOutline) == B_OK) {
1541bb7cffd0SPhilippe Saint-Pierre 					if (((1 << current_workspace()) & mask) != 0) {
1542bb7cffd0SPhilippe Saint-Pierre 						outline = tmpOutline;
1543bb7cffd0SPhilippe Saint-Pierre 						fCachedWorkspace = current_workspace();
1544bb7cffd0SPhilippe Saint-Pierre 						fCachedOutline = outline;
1545bb7cffd0SPhilippe Saint-Pierre 						break;
1546bb7cffd0SPhilippe Saint-Pierre 					}
1547bb7cffd0SPhilippe Saint-Pierre 					indice++;
1548bb7cffd0SPhilippe Saint-Pierre 				}
1549bb7cffd0SPhilippe Saint-Pierre 			}
1550bb7cffd0SPhilippe Saint-Pierre 
1551bb7cffd0SPhilippe Saint-Pierre 			if (outline) {
1552bb7cffd0SPhilippe Saint-Pierre 				SetDrawingMode(B_OP_ALPHA);
1553bb7cffd0SPhilippe Saint-Pierre 				SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
1554bb7cffd0SPhilippe Saint-Pierre 
1555bb7cffd0SPhilippe Saint-Pierre 				BFont font;
1556bb7cffd0SPhilippe Saint-Pierre 				GetFont(&font);
1557bb7cffd0SPhilippe Saint-Pierre 				if (textColor == kBlack) {
1558bb7cffd0SPhilippe Saint-Pierre 					// Black text with white halo/glow
1559bb7cffd0SPhilippe Saint-Pierre 					rgb_color glowColor = kWhite;
1560bb7cffd0SPhilippe Saint-Pierre 
1561bb7cffd0SPhilippe Saint-Pierre 					font.SetFalseBoldWidth(2.0);
1562bb7cffd0SPhilippe Saint-Pierre 					SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1563bb7cffd0SPhilippe Saint-Pierre 
1564bb7cffd0SPhilippe Saint-Pierre 					glowColor.alpha = 30;
1565bb7cffd0SPhilippe Saint-Pierre 					SetHighColor(glowColor);
1566bb7cffd0SPhilippe Saint-Pierre 					DrawString(label.String(), BPoint(6 + colorBox.right, y));
1567bb7cffd0SPhilippe Saint-Pierre 					DrawString(text.String(), BPoint(frame.right - width, y));
1568bb7cffd0SPhilippe Saint-Pierre 
1569bb7cffd0SPhilippe Saint-Pierre 					font.SetFalseBoldWidth(1.0);
1570bb7cffd0SPhilippe Saint-Pierre 					SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1571bb7cffd0SPhilippe Saint-Pierre 
1572bb7cffd0SPhilippe Saint-Pierre 					glowColor.alpha = 65;
1573bb7cffd0SPhilippe Saint-Pierre 					SetHighColor(glowColor);
1574bb7cffd0SPhilippe Saint-Pierre 					DrawString(label.String(), BPoint(6 + colorBox.right, y));
1575bb7cffd0SPhilippe Saint-Pierre 					DrawString(text.String(), BPoint(frame.right - width, y));
1576bb7cffd0SPhilippe Saint-Pierre 
1577bb7cffd0SPhilippe Saint-Pierre 					font.SetFalseBoldWidth(0.0);
1578bb7cffd0SPhilippe Saint-Pierre 					SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1579bb7cffd0SPhilippe Saint-Pierre 				} else {
1580bb7cffd0SPhilippe Saint-Pierre 					// white text with black outline
1581bb7cffd0SPhilippe Saint-Pierre 					rgb_color outlineColor = kBlack;
1582bb7cffd0SPhilippe Saint-Pierre 
1583bb7cffd0SPhilippe Saint-Pierre 					font.SetFalseBoldWidth(1.0);
1584bb7cffd0SPhilippe Saint-Pierre 					SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1585bb7cffd0SPhilippe Saint-Pierre 
1586bb7cffd0SPhilippe Saint-Pierre 					outlineColor.alpha = 30;
1587bb7cffd0SPhilippe Saint-Pierre 					SetHighColor(outlineColor);
1588bb7cffd0SPhilippe Saint-Pierre 					DrawString(label.String(), BPoint(6 + colorBox.right, y));
1589bb7cffd0SPhilippe Saint-Pierre 					DrawString(text.String(), BPoint(frame.right - width, y));
1590bb7cffd0SPhilippe Saint-Pierre 
1591bb7cffd0SPhilippe Saint-Pierre 					font.SetFalseBoldWidth(0.0);
1592bb7cffd0SPhilippe Saint-Pierre 					SetFont(&font, B_FONT_FALSE_BOLD_WIDTH);
1593bb7cffd0SPhilippe Saint-Pierre 
1594bb7cffd0SPhilippe Saint-Pierre 					outlineColor.alpha = 200;
1595bb7cffd0SPhilippe Saint-Pierre 					SetHighColor(outlineColor);
1596bb7cffd0SPhilippe Saint-Pierre 					DrawString(label.String(), BPoint(6 + colorBox.right + 1,
1597bb7cffd0SPhilippe Saint-Pierre 						y + 1));
1598bb7cffd0SPhilippe Saint-Pierre 					DrawString(text.String(), BPoint(frame.right - width + 1,
1599bb7cffd0SPhilippe Saint-Pierre 						y + 1));
1600bb7cffd0SPhilippe Saint-Pierre 				}
1601bb7cffd0SPhilippe Saint-Pierre 			}
1602ed1b2753SStephan Aßmus 			SetDrawingMode(B_OP_OVER);
1603bb7cffd0SPhilippe Saint-Pierre 			SetHighColor(textColor);
1604ed1b2753SStephan Aßmus 		}
16053a4a2141SAxel Dörfler 		DrawString(label.String(), BPoint(6 + colorBox.right, y));
16063a4a2141SAxel Dörfler 		DrawString(text.String(), BPoint(frame.right - width, y));
16073a4a2141SAxel Dörfler 	}
160818d3e65eSAxel Dörfler }
160918d3e65eSAxel Dörfler 
161018d3e65eSAxel Dörfler 
161118d3e65eSAxel Dörfler void
161218d3e65eSAxel Dörfler ActivityView::_Refresh()
161318d3e65eSAxel Dörfler {
16141bb87bd0SAxel Dörfler 	bigtime_t lastTimeout = system_time() - RefreshInterval();
16154ce1e1d2SAxel Dörfler 	BMessenger target(this);
161618d3e65eSAxel Dörfler 
1617d4216445SAxel Dörfler 	while (true) {
1618d4216445SAxel Dörfler 		status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT,
16191bb87bd0SAxel Dörfler 			lastTimeout + RefreshInterval());
1620d4216445SAxel Dörfler 		if (status == B_OK || status == B_BAD_SEM_ID)
1621d4216445SAxel Dörfler 			break;
1622d4216445SAxel Dörfler 		if (status == B_INTERRUPTED)
1623d4216445SAxel Dörfler 			continue;
1624d4216445SAxel Dörfler 
1625d4216445SAxel Dörfler 		SystemInfo info(fSystemInfoHandler);
16261bb87bd0SAxel Dörfler 		lastTimeout += RefreshInterval();
1627d4216445SAxel Dörfler 
1628d4216445SAxel Dörfler 		fSourcesLock.Lock();
162918d3e65eSAxel Dörfler 
163018d3e65eSAxel Dörfler 		for (uint32 i = fSources.CountItems(); i-- > 0;) {
163118d3e65eSAxel Dörfler 			DataSource* source = fSources.ItemAt(i);
163218d3e65eSAxel Dörfler 			DataHistory* values = fValues.ItemAt(i);
163318d3e65eSAxel Dörfler 
163418d3e65eSAxel Dörfler 			int64 value = source->NextValue(info);
163518d3e65eSAxel Dörfler 			values->AddValue(info.Time(), value);
163618d3e65eSAxel Dörfler 		}
163718d3e65eSAxel Dörfler 
1638d4216445SAxel Dörfler 		fSourcesLock.Unlock();
1639d4216445SAxel Dörfler 
16404ce1e1d2SAxel Dörfler 		target.SendMessage(B_INVALIDATE);
164118d3e65eSAxel Dörfler 	}
1642d4216445SAxel Dörfler }
164318d3e65eSAxel Dörfler 
1644d4216445SAxel Dörfler 
1645d4216445SAxel Dörfler /*static*/ status_t
1646d4216445SAxel Dörfler ActivityView::_RefreshThread(void* self)
1647d4216445SAxel Dörfler {
1648d4216445SAxel Dörfler 	((ActivityView*)self)->_Refresh();
1649d4216445SAxel Dörfler 	return B_OK;
1650d4216445SAxel Dörfler }
1651