xref: /haiku/src/apps/activitymonitor/ActivityView.cpp (revision fa19dd4470177c1c769d49a660ea9e20f4ad6561)
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:
428e26f387SAxel Dörfler 	ListAddDeleter(BObjectList<ObjectType>& list, ObjectType* object,
438e26f387SAxel Dörfler 			int32 spot)
448e26f387SAxel Dörfler 		:
458e26f387SAxel Dörfler 		fList(list),
468e26f387SAxel Dörfler 		fObject(object)
478e26f387SAxel Dörfler 	{
488e26f387SAxel Dörfler 		if (fObject != NULL && !fList.AddItem(fObject, spot)) {
498e26f387SAxel Dörfler 			delete fObject;
508e26f387SAxel Dörfler 			fObject = NULL;
518e26f387SAxel Dörfler 		}
528e26f387SAxel Dörfler 	}
538e26f387SAxel Dörfler 
548e26f387SAxel Dörfler 	~ListAddDeleter()
558e26f387SAxel Dörfler 	{
568e26f387SAxel Dörfler 		if (fObject != NULL) {
578e26f387SAxel Dörfler 			fList.RemoveItem(fObject);
588e26f387SAxel Dörfler 			delete fObject;
598e26f387SAxel Dörfler 		}
608e26f387SAxel Dörfler 	}
618e26f387SAxel Dörfler 
628e26f387SAxel Dörfler 	bool Failed() const
638e26f387SAxel Dörfler 	{
648e26f387SAxel Dörfler 		return fObject == NULL;
658e26f387SAxel Dörfler 	}
668e26f387SAxel Dörfler 
678e26f387SAxel Dörfler 	void Detach()
688e26f387SAxel Dörfler 	{
698e26f387SAxel Dörfler 		fObject = NULL;
708e26f387SAxel Dörfler 	}
718e26f387SAxel Dörfler 
728e26f387SAxel Dörfler private:
738e26f387SAxel Dörfler 	BObjectList<ObjectType>&	fList;
748e26f387SAxel Dörfler 	ObjectType*					fObject;
758e26f387SAxel Dörfler };
768e26f387SAxel Dörfler 
778e26f387SAxel Dörfler 
788e26f387SAxel Dörfler /*!	This class manages the scale of a history with a dynamic scale.
798e26f387SAxel Dörfler 	Every history value will be input via Update(), and the minimum/maximum
808e26f387SAxel Dörfler 	is computed from that.
818e26f387SAxel Dörfler */
8251591198SAxel Dörfler class Scale {
8351591198SAxel Dörfler public:
8451591198SAxel Dörfler 								Scale(scale_type type);
8551591198SAxel Dörfler 
8651591198SAxel Dörfler 			int64				MinimumValue() const { return fMinimumValue; }
8751591198SAxel Dörfler 			int64				MaximumValue() const { return fMaximumValue; }
8851591198SAxel Dörfler 
8951591198SAxel Dörfler 			void				Update(int64 value);
9051591198SAxel Dörfler 
9151591198SAxel Dörfler private:
9251591198SAxel Dörfler 			scale_type			fType;
9351591198SAxel Dörfler 			int64				fMinimumValue;
9451591198SAxel Dörfler 			int64				fMaximumValue;
9551591198SAxel Dörfler 			bool				fInitialized;
9651591198SAxel Dörfler };
9751591198SAxel Dörfler 
988e26f387SAxel Dörfler /*!	Stores the interpolated on screen view values. This is done so that the
998e26f387SAxel Dörfler 	interpolation is fixed, and does not change when being scrolled.
1008e26f387SAxel Dörfler 
1018e26f387SAxel Dörfler 	We could also just do this by making sure we always ask for the same
1028e26f387SAxel Dörfler 	interval only, but this way we also save the interpolation.
1038e26f387SAxel Dörfler */
1048e26f387SAxel Dörfler class ViewHistory {
1058e26f387SAxel Dörfler public:
1068e26f387SAxel Dörfler 								ViewHistory();
1078e26f387SAxel Dörfler 
1088e26f387SAxel Dörfler 			int64				ValueAt(int32 x);
1098e26f387SAxel Dörfler 
1108e26f387SAxel Dörfler 			int32				Start() const
1118e26f387SAxel Dörfler 									{ return fValues.Size()
1128e26f387SAxel Dörfler 										- fValues.CountItems(); }
1138e26f387SAxel Dörfler 
1148e26f387SAxel Dörfler 			void				Update(DataHistory* history, int32 width,
1158e26f387SAxel Dörfler 									int32 resolution, bigtime_t toTime,
1168e26f387SAxel Dörfler 									bigtime_t step, bigtime_t refresh);
1178e26f387SAxel Dörfler 
1188e26f387SAxel Dörfler private:
1198e26f387SAxel Dörfler 			CircularBuffer<int64> fValues;
1208e26f387SAxel Dörfler 			int32				fResolution;
1218e26f387SAxel Dörfler 			bigtime_t			fRefresh;
1228e26f387SAxel Dörfler 			bigtime_t			fLastTime;
1238e26f387SAxel Dörfler };
1248e26f387SAxel Dörfler 
12518d3e65eSAxel Dörfler struct data_item {
12618d3e65eSAxel Dörfler 	bigtime_t	time;
12718d3e65eSAxel Dörfler 	int64		value;
12818d3e65eSAxel Dörfler };
12918d3e65eSAxel Dörfler 
130dc1ffc79SFrançois Revol #ifdef __HAIKU__
131065e8de0SAxel Dörfler class ActivityView::HistoryLayoutItem : public BAbstractLayoutItem {
132065e8de0SAxel Dörfler public:
133065e8de0SAxel Dörfler 							HistoryLayoutItem(ActivityView* parent);
134065e8de0SAxel Dörfler 
135065e8de0SAxel Dörfler 	virtual	bool			IsVisible();
136065e8de0SAxel Dörfler 	virtual	void			SetVisible(bool visible);
137065e8de0SAxel Dörfler 
138065e8de0SAxel Dörfler 	virtual	BRect			Frame();
139065e8de0SAxel Dörfler 	virtual	void			SetFrame(BRect frame);
140065e8de0SAxel Dörfler 
141065e8de0SAxel Dörfler 	virtual	BView*			View();
142065e8de0SAxel Dörfler 
143065e8de0SAxel Dörfler 	virtual	BSize			BasePreferredSize();
144065e8de0SAxel Dörfler 
145065e8de0SAxel Dörfler private:
146065e8de0SAxel Dörfler 	ActivityView*			fParent;
147065e8de0SAxel Dörfler 	BRect					fFrame;
148065e8de0SAxel Dörfler };
149065e8de0SAxel Dörfler 
150065e8de0SAxel Dörfler class ActivityView::LegendLayoutItem : public BAbstractLayoutItem {
151065e8de0SAxel Dörfler public:
152065e8de0SAxel Dörfler 							LegendLayoutItem(ActivityView* parent);
153065e8de0SAxel Dörfler 
154065e8de0SAxel Dörfler 	virtual	bool			IsVisible();
155065e8de0SAxel Dörfler 	virtual	void			SetVisible(bool visible);
156065e8de0SAxel Dörfler 
157065e8de0SAxel Dörfler 	virtual	BRect			Frame();
158065e8de0SAxel Dörfler 	virtual	void			SetFrame(BRect frame);
159065e8de0SAxel Dörfler 
160065e8de0SAxel Dörfler 	virtual	BView*			View();
161065e8de0SAxel Dörfler 
162065e8de0SAxel Dörfler 	virtual	BSize			BaseMinSize();
163065e8de0SAxel Dörfler 	virtual	BSize			BaseMaxSize();
164065e8de0SAxel Dörfler 	virtual	BSize			BasePreferredSize();
165065e8de0SAxel Dörfler 	virtual	BAlignment		BaseAlignment();
166065e8de0SAxel Dörfler 
167065e8de0SAxel Dörfler private:
168065e8de0SAxel Dörfler 	ActivityView*			fParent;
169065e8de0SAxel Dörfler 	BRect					fFrame;
170065e8de0SAxel Dörfler };
171dc1ffc79SFrançois Revol #endif
172065e8de0SAxel Dörfler 
1731bb87bd0SAxel Dörfler const bigtime_t kInitialRefreshInterval = 250000LL;
17418d3e65eSAxel Dörfler 
17518d3e65eSAxel Dörfler const uint32 kMsgToggleDataSource = 'tgds';
1763a4a2141SAxel Dörfler const uint32 kMsgToggleLegend = 'tglg';
1771bb87bd0SAxel Dörfler const uint32 kMsgUpdateResolution = 'ures';
17818d3e65eSAxel Dörfler 
1795b0cd987SJohn Scipione extern const char* kAppName;
18018d3e65eSAxel Dörfler extern const char* kSignature;
18118d3e65eSAxel Dörfler 
18218d3e65eSAxel Dörfler 
18351591198SAxel Dörfler Scale::Scale(scale_type type)
18451591198SAxel Dörfler 	:
18551591198SAxel Dörfler 	fType(type),
18651591198SAxel Dörfler 	fMinimumValue(0),
18751591198SAxel Dörfler 	fMaximumValue(0),
18851591198SAxel Dörfler 	fInitialized(false)
18951591198SAxel Dörfler {
19051591198SAxel Dörfler }
19151591198SAxel Dörfler 
19251591198SAxel Dörfler 
19351591198SAxel Dörfler void
19451591198SAxel Dörfler Scale::Update(int64 value)
19551591198SAxel Dörfler {
19651591198SAxel Dörfler 	if (!fInitialized || fMinimumValue > value)
19751591198SAxel Dörfler 		fMinimumValue = value;
198230e3259SAxel Dörfler 	if (!fInitialized || fMaximumValue < value)
19951591198SAxel Dörfler 		fMaximumValue = value;
20051591198SAxel Dörfler 
20151591198SAxel Dörfler 	fInitialized = true;
20251591198SAxel Dörfler }
20351591198SAxel Dörfler 
20451591198SAxel Dörfler 
20551591198SAxel Dörfler //	#pragma mark -
20651591198SAxel Dörfler 
20751591198SAxel Dörfler 
2088e26f387SAxel Dörfler ViewHistory::ViewHistory()
2098e26f387SAxel Dörfler 	:
2108e26f387SAxel Dörfler 	fValues(1),
2118e26f387SAxel Dörfler 	fResolution(-1),
2128e26f387SAxel Dörfler 	fRefresh(-1),
2138e26f387SAxel Dörfler 	fLastTime(0)
2148e26f387SAxel Dörfler {
2158e26f387SAxel Dörfler }
2168e26f387SAxel Dörfler 
2178e26f387SAxel Dörfler 
2188e26f387SAxel Dörfler int64
2198e26f387SAxel Dörfler ViewHistory::ValueAt(int32 x)
2208e26f387SAxel Dörfler {
2218e26f387SAxel Dörfler 	int64* value = fValues.ItemAt(x - Start());
2228e26f387SAxel Dörfler 	if (value != NULL)
2238e26f387SAxel Dörfler 		return *value;
2248e26f387SAxel Dörfler 
2258e26f387SAxel Dörfler 	return 0;
2268e26f387SAxel Dörfler }
2278e26f387SAxel Dörfler 
2288e26f387SAxel Dörfler 
2298e26f387SAxel Dörfler void
2308e26f387SAxel Dörfler ViewHistory::Update(DataHistory* history, int32 width, int32 resolution,
2318e26f387SAxel Dörfler 	bigtime_t toTime, bigtime_t step, bigtime_t refresh)
2328e26f387SAxel Dörfler {
2332c604c0dSAxel Dörfler 	if (width > 16384) {
2342c604c0dSAxel Dörfler 		// ignore this - it seems the view hasn't been layouted yet
2352c604c0dSAxel Dörfler 		return;
2362c604c0dSAxel Dörfler 	}
2372c604c0dSAxel Dörfler 
2388e26f387SAxel Dörfler 	// Check if we need to invalidate the existing values
2398e26f387SAxel Dörfler 	if ((int32)fValues.Size() != width
2408e26f387SAxel Dörfler 		|| fResolution != resolution
2418e26f387SAxel Dörfler 		|| fRefresh != refresh) {
2428e26f387SAxel Dörfler 		fValues.SetSize(width);
2438e26f387SAxel Dörfler 		fResolution = resolution;
2448e26f387SAxel Dörfler 		fRefresh = refresh;
2457d33b63dSAxel Dörfler 		fLastTime = 0;
2468e26f387SAxel Dörfler 	}
2478e26f387SAxel Dörfler 
2488e26f387SAxel Dörfler 	// Compute how many new values we need to retrieve
2498e26f387SAxel Dörfler 	if (fLastTime < history->Start())
2508e26f387SAxel Dörfler 		fLastTime = history->Start();
2517d33b63dSAxel Dörfler 	if (fLastTime > history->End())
2527d33b63dSAxel Dörfler 		return;
2538e26f387SAxel Dörfler 
2548e26f387SAxel Dörfler 	int32 updateWidth = int32((toTime - fLastTime) / step);
2558e26f387SAxel Dörfler 	if (updateWidth < 1)
2568e26f387SAxel Dörfler 		return;
2578e26f387SAxel Dörfler 
2588e26f387SAxel Dörfler 	if (updateWidth > (int32)fValues.Size()) {
2598e26f387SAxel Dörfler 		updateWidth = fValues.Size();
2608e26f387SAxel Dörfler 		fLastTime = toTime - updateWidth * step;
2618e26f387SAxel Dörfler 	}
2628e26f387SAxel Dörfler 
2638e26f387SAxel Dörfler 	for (int32 i = 0; i < updateWidth; i++) {
2648e26f387SAxel Dörfler 		int64 value = history->ValueAt(fLastTime += step);
2658e26f387SAxel Dörfler 
2668e26f387SAxel Dörfler 		if (step > refresh) {
2678e26f387SAxel Dörfler 			uint32 count = 1;
2688e26f387SAxel Dörfler 			for (bigtime_t offset = refresh; offset < step; offset += refresh) {
2698e26f387SAxel Dörfler 				// TODO: handle int64 overflow correctly!
2708e26f387SAxel Dörfler 				value += history->ValueAt(fLastTime + offset);
2718e26f387SAxel Dörfler 				count++;
2728e26f387SAxel Dörfler 			}
2738e26f387SAxel Dörfler 			value /= count;
2748e26f387SAxel Dörfler 		}
2758e26f387SAxel Dörfler 
2768e26f387SAxel Dörfler 		fValues.AddItem(value);
2778e26f387SAxel Dörfler 	}
2788e26f387SAxel Dörfler }
2798e26f387SAxel Dörfler 
2808e26f387SAxel Dörfler 
2818e26f387SAxel Dörfler //	#pragma mark -
2828e26f387SAxel Dörfler 
2838e26f387SAxel Dörfler 
28418d3e65eSAxel Dörfler DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval)
28518d3e65eSAxel Dörfler 	:
28618d3e65eSAxel Dörfler 	fBuffer(10000),
28718d3e65eSAxel Dörfler 	fMinimumValue(0),
28818d3e65eSAxel Dörfler 	fMaximumValue(0),
28918d3e65eSAxel Dörfler 	fRefreshInterval(interval),
29051591198SAxel Dörfler 	fLastIndex(-1),
29151591198SAxel Dörfler 	fScale(NULL)
29218d3e65eSAxel Dörfler {
29318d3e65eSAxel Dörfler }
29418d3e65eSAxel Dörfler 
29518d3e65eSAxel Dörfler 
29618d3e65eSAxel Dörfler DataHistory::~DataHistory()
29718d3e65eSAxel Dörfler {
29818d3e65eSAxel Dörfler }
29918d3e65eSAxel Dörfler 
30018d3e65eSAxel Dörfler 
30118d3e65eSAxel Dörfler void
30218d3e65eSAxel Dörfler DataHistory::AddValue(bigtime_t time, int64 value)
30318d3e65eSAxel Dörfler {
30418d3e65eSAxel Dörfler 	if (fBuffer.IsEmpty() || fMaximumValue < value)
30518d3e65eSAxel Dörfler 		fMaximumValue = value;
30618d3e65eSAxel Dörfler 	if (fBuffer.IsEmpty() || fMinimumValue > value)
30718d3e65eSAxel Dörfler 		fMinimumValue = value;
30851591198SAxel Dörfler 	if (fScale != NULL)
30951591198SAxel Dörfler 		fScale->Update(value);
31018d3e65eSAxel Dörfler 
31118d3e65eSAxel Dörfler 	data_item item = {time, value};
31218d3e65eSAxel Dörfler 	fBuffer.AddItem(item);
31318d3e65eSAxel Dörfler }
31418d3e65eSAxel Dörfler 
31518d3e65eSAxel Dörfler 
31618d3e65eSAxel Dörfler int64
31718d3e65eSAxel Dörfler DataHistory::ValueAt(bigtime_t time)
31818d3e65eSAxel Dörfler {
31951591198SAxel Dörfler 	int32 left = 0;
32051591198SAxel Dörfler 	int32 right = fBuffer.CountItems() - 1;
32151591198SAxel Dörfler 	data_item* item = NULL;
32251591198SAxel Dörfler 
32351591198SAxel Dörfler 	while (left <= right) {
32451591198SAxel Dörfler 		int32 index = (left + right) / 2;
32551591198SAxel Dörfler 		item = fBuffer.ItemAt(index);
32651591198SAxel Dörfler 
32751591198SAxel Dörfler 		if (item->time > time) {
32851591198SAxel Dörfler 			// search in left part
32951591198SAxel Dörfler 			right = index - 1;
33051591198SAxel Dörfler 		} else {
33184e23a5dSAxel Dörfler 			data_item* nextItem = fBuffer.ItemAt(index + 1);
33284e23a5dSAxel Dörfler 			if (nextItem == NULL)
33384e23a5dSAxel Dörfler 				return item->value;
33484e23a5dSAxel Dörfler 			if (nextItem->time > time) {
33551591198SAxel Dörfler 				// found item
33684e23a5dSAxel Dörfler 				int64 value = item->value;
33784e23a5dSAxel Dörfler 				value += int64(double(nextItem->value - value)
33884e23a5dSAxel Dörfler 					/ (nextItem->time - item->time) * (time - item->time));
3398e26f387SAxel Dörfler 				return value;
34051591198SAxel Dörfler 			}
34151591198SAxel Dörfler 
34251591198SAxel Dörfler 			// search in right part
34351591198SAxel Dörfler 			left = index + 1;
34451591198SAxel Dörfler 		}
34551591198SAxel Dörfler 	}
34618d3e65eSAxel Dörfler 
34718d3e65eSAxel Dörfler 	return 0;
34818d3e65eSAxel Dörfler }
34918d3e65eSAxel Dörfler 
35018d3e65eSAxel Dörfler 
35118d3e65eSAxel Dörfler int64
35218d3e65eSAxel Dörfler DataHistory::MaximumValue() const
35318d3e65eSAxel Dörfler {
35451591198SAxel Dörfler 	if (fScale != NULL)
35551591198SAxel Dörfler 		return fScale->MaximumValue();
35651591198SAxel Dörfler 
35718d3e65eSAxel Dörfler 	return fMaximumValue;
35818d3e65eSAxel Dörfler }
35918d3e65eSAxel Dörfler 
36018d3e65eSAxel Dörfler 
36118d3e65eSAxel Dörfler int64
36218d3e65eSAxel Dörfler DataHistory::MinimumValue() const
36318d3e65eSAxel Dörfler {
36451591198SAxel Dörfler 	if (fScale != NULL)
36551591198SAxel Dörfler 		return fScale->MinimumValue();
36651591198SAxel Dörfler 
36718d3e65eSAxel Dörfler 	return fMinimumValue;
36818d3e65eSAxel Dörfler }
36918d3e65eSAxel Dörfler 
37018d3e65eSAxel Dörfler 
37118d3e65eSAxel Dörfler bigtime_t
37218d3e65eSAxel Dörfler DataHistory::Start() const
37318d3e65eSAxel Dörfler {
37418d3e65eSAxel Dörfler 	if (fBuffer.CountItems() == 0)
37518d3e65eSAxel Dörfler 		return 0;
37618d3e65eSAxel Dörfler 
37718d3e65eSAxel Dörfler 	return fBuffer.ItemAt(0)->time;
37818d3e65eSAxel Dörfler }
37918d3e65eSAxel Dörfler 
38018d3e65eSAxel Dörfler 
38118d3e65eSAxel Dörfler bigtime_t
38218d3e65eSAxel Dörfler DataHistory::End() const
38318d3e65eSAxel Dörfler {
38418d3e65eSAxel Dörfler 	if (fBuffer.CountItems() == 0)
38518d3e65eSAxel Dörfler 		return 0;
38618d3e65eSAxel Dörfler 
38718d3e65eSAxel Dörfler 	return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time;
38818d3e65eSAxel Dörfler }
38918d3e65eSAxel Dörfler 
39018d3e65eSAxel Dörfler 
39118d3e65eSAxel Dörfler void
39218d3e65eSAxel Dörfler DataHistory::SetRefreshInterval(bigtime_t interval)
39318d3e65eSAxel Dörfler {
39418d3e65eSAxel Dörfler 	// TODO: adjust buffer size
39518d3e65eSAxel Dörfler }
39618d3e65eSAxel Dörfler 
39718d3e65eSAxel Dörfler 
39851591198SAxel Dörfler void
39951591198SAxel Dörfler DataHistory::SetScale(Scale* scale)
40051591198SAxel Dörfler {
40151591198SAxel Dörfler 	fScale = scale;
40251591198SAxel Dörfler }
40351591198SAxel Dörfler 
40451591198SAxel Dörfler 
40518d3e65eSAxel Dörfler //	#pragma mark -
40618d3e65eSAxel Dörfler 
40718d3e65eSAxel Dörfler 
408dc1ffc79SFrançois Revol #ifdef __HAIKU__
409065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::HistoryLayoutItem(ActivityView* parent)
410065e8de0SAxel Dörfler 	:
411065e8de0SAxel Dörfler 	fParent(parent),
412065e8de0SAxel Dörfler 	fFrame()
413065e8de0SAxel Dörfler {
414065e8de0SAxel Dörfler }
415065e8de0SAxel Dörfler 
416065e8de0SAxel Dörfler 
417065e8de0SAxel Dörfler bool
418065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::IsVisible()
419065e8de0SAxel Dörfler {
420065e8de0SAxel Dörfler 	return !fParent->IsHidden(fParent);
421065e8de0SAxel Dörfler }
422065e8de0SAxel Dörfler 
423065e8de0SAxel Dörfler 
424065e8de0SAxel Dörfler void
425065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetVisible(bool visible)
426065e8de0SAxel Dörfler {
427065e8de0SAxel Dörfler 	// not allowed
428065e8de0SAxel Dörfler }
429065e8de0SAxel Dörfler 
430065e8de0SAxel Dörfler 
431065e8de0SAxel Dörfler BRect
432065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::Frame()
433065e8de0SAxel Dörfler {
434065e8de0SAxel Dörfler 	return fFrame;
435065e8de0SAxel Dörfler }
436065e8de0SAxel Dörfler 
437065e8de0SAxel Dörfler 
438065e8de0SAxel Dörfler void
439065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetFrame(BRect frame)
440065e8de0SAxel Dörfler {
441065e8de0SAxel Dörfler 	fFrame = frame;
442065e8de0SAxel Dörfler 	fParent->_UpdateFrame();
443065e8de0SAxel Dörfler }
444065e8de0SAxel Dörfler 
445065e8de0SAxel Dörfler 
446065e8de0SAxel Dörfler BView*
447065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::View()
448065e8de0SAxel Dörfler {
449065e8de0SAxel Dörfler 	return fParent;
450065e8de0SAxel Dörfler }
451065e8de0SAxel Dörfler 
452065e8de0SAxel Dörfler 
453065e8de0SAxel Dörfler BSize
454065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::BasePreferredSize()
455065e8de0SAxel Dörfler {
456065e8de0SAxel Dörfler 	BSize size(BaseMaxSize());
457065e8de0SAxel Dörfler 	return size;
458065e8de0SAxel Dörfler }
459065e8de0SAxel Dörfler 
460065e8de0SAxel Dörfler 
461065e8de0SAxel Dörfler //	#pragma mark -
462065e8de0SAxel Dörfler 
463065e8de0SAxel Dörfler 
464065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::LegendLayoutItem(ActivityView* parent)
465065e8de0SAxel Dörfler 	:
466065e8de0SAxel Dörfler 	fParent(parent),
467065e8de0SAxel Dörfler 	fFrame()
468065e8de0SAxel Dörfler {
469065e8de0SAxel Dörfler }
470065e8de0SAxel Dörfler 
471065e8de0SAxel Dörfler 
472065e8de0SAxel Dörfler bool
473065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::IsVisible()
474065e8de0SAxel Dörfler {
475065e8de0SAxel Dörfler 	return !fParent->IsHidden(fParent);
476065e8de0SAxel Dörfler }
477065e8de0SAxel Dörfler 
478065e8de0SAxel Dörfler 
479065e8de0SAxel Dörfler void
480065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetVisible(bool visible)
481065e8de0SAxel Dörfler {
482065e8de0SAxel Dörfler 	// not allowed
483065e8de0SAxel Dörfler }
484065e8de0SAxel Dörfler 
485065e8de0SAxel Dörfler 
486065e8de0SAxel Dörfler BRect
487065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::Frame()
488065e8de0SAxel Dörfler {
489065e8de0SAxel Dörfler 	return fFrame;
490065e8de0SAxel Dörfler }
491065e8de0SAxel Dörfler 
492065e8de0SAxel Dörfler 
493065e8de0SAxel Dörfler void
494065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetFrame(BRect frame)
495065e8de0SAxel Dörfler {
496065e8de0SAxel Dörfler 	fFrame = frame;
497065e8de0SAxel Dörfler 	fParent->_UpdateFrame();
498065e8de0SAxel Dörfler }
499065e8de0SAxel Dörfler 
500065e8de0SAxel Dörfler 
501065e8de0SAxel Dörfler BView*
502065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::View()
503065e8de0SAxel Dörfler {
504065e8de0SAxel Dörfler 	return fParent;
505065e8de0SAxel Dörfler }
506065e8de0SAxel Dörfler 
507065e8de0SAxel Dörfler 
508065e8de0SAxel Dörfler BSize
509065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMinSize()
510065e8de0SAxel Dörfler {
511065e8de0SAxel Dörfler 	// TODO: Cache the info. Might be too expensive for this call.
512065e8de0SAxel Dörfler 	BSize size;
513065e8de0SAxel Dörfler 	size.width = 80;
514065e8de0SAxel Dörfler 	size.height = fParent->_LegendHeight();
515065e8de0SAxel Dörfler 
516065e8de0SAxel Dörfler 	return size;
517065e8de0SAxel Dörfler }
518065e8de0SAxel Dörfler 
519065e8de0SAxel Dörfler 
520065e8de0SAxel Dörfler BSize
521065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMaxSize()
522065e8de0SAxel Dörfler {
523065e8de0SAxel Dörfler 	BSize size(BaseMinSize());
524065e8de0SAxel Dörfler 	size.width = B_SIZE_UNLIMITED;
525065e8de0SAxel Dörfler 	return size;
526065e8de0SAxel Dörfler }
527065e8de0SAxel Dörfler 
528065e8de0SAxel Dörfler 
529065e8de0SAxel Dörfler BSize
530065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BasePreferredSize()
531065e8de0SAxel Dörfler {
532065e8de0SAxel Dörfler 	BSize size(BaseMinSize());
533065e8de0SAxel Dörfler 	return size;
534065e8de0SAxel Dörfler }
535065e8de0SAxel Dörfler 
536065e8de0SAxel Dörfler 
537065e8de0SAxel Dörfler BAlignment
538065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseAlignment()
539065e8de0SAxel Dörfler {
540065e8de0SAxel Dörfler 	return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT);
541065e8de0SAxel Dörfler }
542dc1ffc79SFrançois Revol #endif
543065e8de0SAxel Dörfler 
544065e8de0SAxel Dörfler 
545065e8de0SAxel Dörfler //	#pragma mark -
546065e8de0SAxel Dörfler 
547065e8de0SAxel Dörfler 
548bb7cffd0SPhilippe Saint-Pierre const rgb_color kWhite = (rgb_color){255, 255, 255, 255};
549bb7cffd0SPhilippe Saint-Pierre const rgb_color kBlack = (rgb_color){0, 0, 0, 255};
5509bd81dbeSStephan Aßmus const float kDraggerSize = 7;
551bb7cffd0SPhilippe Saint-Pierre 
552bb7cffd0SPhilippe Saint-Pierre 
55318d3e65eSAxel Dörfler ActivityView::ActivityView(BRect frame, const char* name,
5543a4a2141SAxel Dörfler 		const BMessage* settings, uint32 resizingMode)
55518d3e65eSAxel Dörfler 	: BView(frame, name, resizingMode,
556d4216445SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
557d4216445SAxel Dörfler 	fSourcesLock("data sources")
55818d3e65eSAxel Dörfler {
5593a4a2141SAxel Dörfler 	_Init(settings);
5603a4a2141SAxel Dörfler 
5613a4a2141SAxel Dörfler 	BRect rect(Bounds());
5629bd81dbeSStephan Aßmus 	rect.top = rect.bottom - kDraggerSize;
5639bd81dbeSStephan Aßmus 	rect.left = rect.right - kDraggerSize;
5643a4a2141SAxel Dörfler 	BDragger* dragger = new BDragger(rect, this,
5653a4a2141SAxel Dörfler 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
5663a4a2141SAxel Dörfler 	AddChild(dragger);
5673a4a2141SAxel Dörfler }
5683a4a2141SAxel Dörfler 
5693a4a2141SAxel Dörfler 
5703a4a2141SAxel Dörfler ActivityView::ActivityView(const char* name, const BMessage* settings)
571cbd4bc95SFrançois Revol #ifdef __HAIKU__
572d4216445SAxel Dörfler 	: BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
573cbd4bc95SFrançois Revol #else
574d4216445SAxel Dörfler 	: BView(BRect(0, 0, 300, 200), name, B_FOLLOW_NONE,
575d4216445SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS),
576cbd4bc95SFrançois Revol #endif
577d4216445SAxel Dörfler 	fSourcesLock("data sources")
5783a4a2141SAxel Dörfler {
579*fa19dd44Slooncraz 	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 
59218d3e65eSAxel Dörfler ActivityView::ActivityView(BMessage* archive)
59318d3e65eSAxel Dörfler 	: BView(archive)
59418d3e65eSAxel Dörfler {
59518d3e65eSAxel Dörfler 	_Init(archive);
59618d3e65eSAxel Dörfler }
59718d3e65eSAxel Dörfler 
59818d3e65eSAxel Dörfler 
59918d3e65eSAxel Dörfler ActivityView::~ActivityView()
60018d3e65eSAxel Dörfler {
6013a4a2141SAxel Dörfler 	delete fOffscreen;
60274158bb4SFrançois Revol 	delete fSystemInfoHandler;
60318d3e65eSAxel Dörfler }
60418d3e65eSAxel Dörfler 
60518d3e65eSAxel Dörfler 
60618d3e65eSAxel Dörfler void
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
6123a4a2141SAxel Dörfler 	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);
61818d3e65eSAxel Dörfler 
61918d3e65eSAxel Dörfler 	fLastRefresh = 0;
62018d3e65eSAxel Dörfler 	fDrawResolution = 1;
62151591198SAxel Dörfler 	fZooming = false;
62218d3e65eSAxel Dörfler 
62374158bb4SFrançois Revol 	fSystemInfoHandler = new SystemInfoHandler;
62474158bb4SFrançois Revol 
6253a4a2141SAxel Dörfler 	if (settings == NULL
626eee6f40bSAlexandre Deckner 		|| settings->FindInt64("refresh interval", &fRefreshInterval) != B_OK)
627eee6f40bSAlexandre Deckner 		fRefreshInterval = kInitialRefreshInterval;
628eee6f40bSAlexandre Deckner 
629eee6f40bSAlexandre Deckner 	if (settings == NULL
6303a4a2141SAxel Dörfler 		|| settings->FindBool("show legend", &fShowLegend) != B_OK)
6313a4a2141SAxel Dörfler 		fShowLegend = true;
6323a4a2141SAxel Dörfler 
63351591198SAxel Dörfler 	if (settings == NULL)
6343a4a2141SAxel Dörfler 		return;
6353a4a2141SAxel Dörfler 
6369c89c450SAxel Dörfler 	ssize_t colorLength;
63779cbd226SFrançois Revol 	rgb_color *color;
6389c89c450SAxel Dörfler 	if (settings->FindData("history background color", B_RGB_COLOR_TYPE,
6399c89c450SAxel Dörfler 			(const void **)&color, &colorLength) == B_OK
6409c89c450SAxel Dörfler 		&& colorLength == sizeof(rgb_color))
6419c89c450SAxel Dörfler 		fHistoryBackgroundColor = *color;
64279cbd226SFrançois Revol 
6433a4a2141SAxel Dörfler 	const char* name;
644d1901581SStephan Aßmus 	for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++)
6451201d52eSAxel Dörfler 		AddDataSource(DataSource::FindSource(name), settings);
6463a4a2141SAxel Dörfler }
64718d3e65eSAxel Dörfler 
64818d3e65eSAxel Dörfler 
64918d3e65eSAxel Dörfler status_t
65018d3e65eSAxel Dörfler ActivityView::Archive(BMessage* into, bool deep) const
65118d3e65eSAxel Dörfler {
65218d3e65eSAxel Dörfler 	status_t status;
65318d3e65eSAxel Dörfler 
65418d3e65eSAxel Dörfler 	status = BView::Archive(into, deep);
65518d3e65eSAxel Dörfler 	if (status < B_OK)
65618d3e65eSAxel Dörfler 		return status;
65718d3e65eSAxel Dörfler 
65818d3e65eSAxel Dörfler 	status = into->AddString("add_on", kSignature);
65918d3e65eSAxel Dörfler 	if (status < B_OK)
66018d3e65eSAxel Dörfler 		return status;
66118d3e65eSAxel Dörfler 
66218d3e65eSAxel Dörfler 	status = SaveState(*into);
66318d3e65eSAxel Dörfler 	if (status < B_OK)
66418d3e65eSAxel Dörfler 		return status;
66518d3e65eSAxel Dörfler 
66618d3e65eSAxel Dörfler 	return B_OK;
66718d3e65eSAxel Dörfler }
66818d3e65eSAxel Dörfler 
66918d3e65eSAxel Dörfler 
67018d3e65eSAxel Dörfler BArchivable*
67118d3e65eSAxel Dörfler ActivityView::Instantiate(BMessage* archive)
67218d3e65eSAxel Dörfler {
67318d3e65eSAxel Dörfler 	if (!validate_instantiation(archive, "ActivityView"))
67418d3e65eSAxel Dörfler 		return NULL;
67518d3e65eSAxel Dörfler 
67618d3e65eSAxel Dörfler 	return new ActivityView(archive);
67718d3e65eSAxel Dörfler }
67818d3e65eSAxel Dörfler 
67918d3e65eSAxel Dörfler 
68018d3e65eSAxel Dörfler status_t
68118d3e65eSAxel Dörfler ActivityView::SaveState(BMessage& state) const
68218d3e65eSAxel Dörfler {
6833a4a2141SAxel Dörfler 	status_t status = state.AddBool("show legend", fShowLegend);
6843a4a2141SAxel Dörfler 	if (status != B_OK)
6853a4a2141SAxel Dörfler 		return status;
6863a4a2141SAxel Dörfler 
687eee6f40bSAlexandre Deckner 	status = state.AddInt64("refresh interval", fRefreshInterval);
688eee6f40bSAlexandre Deckner 	if (status != B_OK)
689eee6f40bSAlexandre Deckner 		return status;
690eee6f40bSAlexandre Deckner 
6919c89c450SAxel Dörfler 	status = state.AddData("history background color", B_RGB_COLOR_TYPE,
6929c89c450SAxel Dörfler 		&fHistoryBackgroundColor, sizeof(rgb_color));
69379cbd226SFrançois Revol 	if (status != B_OK)
69479cbd226SFrançois Revol 		return status;
69579cbd226SFrançois Revol 
6963a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems(); i++) {
6973a4a2141SAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
6983a4a2141SAxel Dörfler 
6993a4a2141SAxel Dörfler 		if (!source->PerCPU() || source->CPU() == 0)
700d1901581SStephan Aßmus 			status = state.AddString("source", source->InternalName());
7013a4a2141SAxel Dörfler 		if (status != B_OK)
7023a4a2141SAxel Dörfler 			return status;
7033a4a2141SAxel Dörfler 
7049c89c450SAxel Dörfler 		BString name = source->Name();
7059c89c450SAxel Dörfler 		name << " color";
7069c89c450SAxel Dörfler 		rgb_color color = source->Color();
7079c89c450SAxel Dörfler 		state.AddData(name.String(), B_RGB_COLOR_TYPE, &color,
7089c89c450SAxel Dörfler 			sizeof(rgb_color));
7093a4a2141SAxel Dörfler 	}
7103a4a2141SAxel Dörfler 	return B_OK;
71118d3e65eSAxel Dörfler }
71218d3e65eSAxel Dörfler 
71318d3e65eSAxel Dörfler 
71451591198SAxel Dörfler Scale*
71551591198SAxel Dörfler ActivityView::_ScaleFor(scale_type type)
71651591198SAxel Dörfler {
71751591198SAxel Dörfler 	if (type == kNoScale)
71851591198SAxel Dörfler 		return NULL;
71951591198SAxel Dörfler 
72051591198SAxel Dörfler 	std::map<scale_type, ::Scale*>::iterator iterator = fScales.find(type);
72151591198SAxel Dörfler 	if (iterator != fScales.end())
72251591198SAxel Dörfler 		return iterator->second;
72351591198SAxel Dörfler 
72451591198SAxel Dörfler 	// add new scale
72551591198SAxel Dörfler 	::Scale* scale = new ::Scale(type);
72651591198SAxel Dörfler 	fScales[type] = scale;
72751591198SAxel Dörfler 
72851591198SAxel Dörfler 	return scale;
72951591198SAxel Dörfler }
73051591198SAxel Dörfler 
73151591198SAxel Dörfler 
732dc1ffc79SFrançois Revol #ifdef __HAIKU__
733065e8de0SAxel Dörfler BLayoutItem*
734065e8de0SAxel Dörfler ActivityView::CreateHistoryLayoutItem()
735065e8de0SAxel Dörfler {
736065e8de0SAxel Dörfler 	if (fHistoryLayoutItem == NULL)
737065e8de0SAxel Dörfler 		fHistoryLayoutItem = new HistoryLayoutItem(this);
738065e8de0SAxel Dörfler 
739065e8de0SAxel Dörfler 	return fHistoryLayoutItem;
740065e8de0SAxel Dörfler }
741065e8de0SAxel Dörfler 
742065e8de0SAxel Dörfler 
743065e8de0SAxel Dörfler BLayoutItem*
744065e8de0SAxel Dörfler ActivityView::CreateLegendLayoutItem()
745065e8de0SAxel Dörfler {
746065e8de0SAxel Dörfler 	if (fLegendLayoutItem == NULL)
747065e8de0SAxel Dörfler 		fLegendLayoutItem = new LegendLayoutItem(this);
748065e8de0SAxel Dörfler 
749065e8de0SAxel Dörfler 	return fLegendLayoutItem;
750065e8de0SAxel Dörfler }
751dc1ffc79SFrançois Revol #endif
752065e8de0SAxel Dörfler 
7539c89c450SAxel Dörfler 
75418d3e65eSAxel Dörfler DataSource*
7553a4a2141SAxel Dörfler ActivityView::FindDataSource(const DataSource* search)
75618d3e65eSAxel Dörfler {
757d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
758d4216445SAxel Dörfler 
75918d3e65eSAxel Dörfler 	for (int32 i = fSources.CountItems(); i-- > 0;) {
76018d3e65eSAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
7613a4a2141SAxel Dörfler 		if (!strcmp(source->Name(), search->Name()))
76218d3e65eSAxel Dörfler 			return source;
76318d3e65eSAxel Dörfler 	}
76418d3e65eSAxel Dörfler 
76518d3e65eSAxel Dörfler 	return NULL;
76618d3e65eSAxel Dörfler }
76718d3e65eSAxel Dörfler 
76818d3e65eSAxel Dörfler 
76918d3e65eSAxel Dörfler status_t
7709c89c450SAxel Dörfler ActivityView::AddDataSource(const DataSource* source, const BMessage* state)
77118d3e65eSAxel Dörfler {
7723a4a2141SAxel Dörfler 	if (source == NULL)
7733a4a2141SAxel Dörfler 		return B_BAD_VALUE;
7743a4a2141SAxel Dörfler 
775d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
776d4216445SAxel Dörfler 
7778e26f387SAxel Dörfler 	// Search for the correct insert spot to maintain the order of the sources
7783a4a2141SAxel Dörfler 	int32 insert = DataSource::IndexOf(source);
7793a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) {
7803a4a2141SAxel Dörfler 		DataSource* before = fSources.ItemAt(i);
7813a4a2141SAxel Dörfler 		if (DataSource::IndexOf(before) > insert) {
7823a4a2141SAxel Dörfler 			insert = i;
7833a4a2141SAxel Dörfler 			break;
7843a4a2141SAxel Dörfler 		}
7853a4a2141SAxel Dörfler 	}
7863a4a2141SAxel Dörfler 	if (insert > fSources.CountItems())
7873a4a2141SAxel Dörfler 		insert = fSources.CountItems();
7883a4a2141SAxel Dörfler 
7898e26f387SAxel Dörfler 	// Generate DataHistory and ViewHistory objects for the source
7908e26f387SAxel Dörfler 	// (one might need one history per CPU)
7918e26f387SAxel Dörfler 
7923a4a2141SAxel Dörfler 	uint32 count = 1;
7933a4a2141SAxel Dörfler 	if (source->PerCPU()) {
7943a4a2141SAxel Dörfler 		SystemInfo info;
7953a4a2141SAxel Dörfler 		count = info.CPUCount();
7963a4a2141SAxel Dörfler 	}
7973a4a2141SAxel Dörfler 
7983a4a2141SAxel Dörfler 	for (uint32 i = 0; i < count; i++) {
79918d3e65eSAxel Dörfler 		DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL,
8001bb87bd0SAxel Dörfler 			RefreshInterval());
8018e26f387SAxel Dörfler 		ListAddDeleter<DataHistory> valuesDeleter(fValues, values, insert);
8023a4a2141SAxel Dörfler 
8038e26f387SAxel Dörfler 		ViewHistory* viewValues = new(std::nothrow) ViewHistory;
8048e26f387SAxel Dörfler 		ListAddDeleter<ViewHistory> viewValuesDeleter(fViewValues, viewValues,
8058e26f387SAxel Dörfler 			insert);
8068e26f387SAxel Dörfler 
8078e26f387SAxel Dörfler 		if (valuesDeleter.Failed() || viewValuesDeleter.Failed())
80818d3e65eSAxel Dörfler 			return B_NO_MEMORY;
80918d3e65eSAxel Dörfler 
81051591198SAxel Dörfler 		values->SetScale(_ScaleFor(source->ScaleType()));
81151591198SAxel Dörfler 
8123a4a2141SAxel Dörfler 		DataSource* copy;
8133a4a2141SAxel Dörfler 		if (source->PerCPU())
8143a4a2141SAxel Dörfler 			copy = source->CopyForCPU(i);
8153a4a2141SAxel Dörfler 		else
8163a4a2141SAxel Dörfler 			copy = source->Copy();
8173a4a2141SAxel Dörfler 
8188e26f387SAxel Dörfler 		ListAddDeleter<DataSource> sourceDeleter(fSources, copy, insert);
8198e26f387SAxel Dörfler 		if (sourceDeleter.Failed())
8208e26f387SAxel Dörfler 			return B_NO_MEMORY;
8218e26f387SAxel Dörfler 
8229c89c450SAxel Dörfler 		BString colorName = source->Name();
8239c89c450SAxel Dörfler 		colorName << " color";
8249c89c450SAxel Dörfler 		if (state != NULL) {
8259c89c450SAxel Dörfler 			const rgb_color* color = NULL;
8269c89c450SAxel Dörfler 			ssize_t colorLength;
8279c89c450SAxel Dörfler 			if (state->FindData(colorName.String(), B_RGB_COLOR_TYPE, i,
8289c89c450SAxel Dörfler 					(const void**)&color, &colorLength) == B_OK
8299c89c450SAxel Dörfler 				&& colorLength == sizeof(rgb_color))
8309c89c450SAxel Dörfler 				copy->SetColor(*color);
8319c89c450SAxel Dörfler 		}
8329c89c450SAxel Dörfler 
8338e26f387SAxel Dörfler 		valuesDeleter.Detach();
8348e26f387SAxel Dörfler 		viewValuesDeleter.Detach();
8358e26f387SAxel Dörfler 		sourceDeleter.Detach();
836be3f9645SAxel Dörfler 		insert++;
8373a4a2141SAxel Dörfler 	}
83818d3e65eSAxel Dörfler 
839dc1ffc79SFrançois Revol #ifdef __HAIKU__
840065e8de0SAxel Dörfler 	InvalidateLayout();
841dc1ffc79SFrançois Revol #endif
84218d3e65eSAxel Dörfler 	return B_OK;
84318d3e65eSAxel Dörfler }
84418d3e65eSAxel Dörfler 
84518d3e65eSAxel Dörfler 
84618d3e65eSAxel Dörfler status_t
8473a4a2141SAxel Dörfler ActivityView::RemoveDataSource(const DataSource* remove)
84818d3e65eSAxel Dörfler {
849065e8de0SAxel Dörfler 	bool removed = false;
850065e8de0SAxel Dörfler 
851d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
852d4216445SAxel Dörfler 
8533a4a2141SAxel Dörfler 	while (true) {
8543a4a2141SAxel Dörfler 		DataSource* source = FindDataSource(remove);
855065e8de0SAxel Dörfler 		if (source == NULL) {
856065e8de0SAxel Dörfler 			if (removed)
857065e8de0SAxel Dörfler 				break;
858065e8de0SAxel Dörfler 			return B_ENTRY_NOT_FOUND;
859065e8de0SAxel Dörfler 		}
8603a4a2141SAxel Dörfler 
86118d3e65eSAxel Dörfler 		int32 index = fSources.IndexOf(source);
86218d3e65eSAxel Dörfler 		if (index < 0)
86318d3e65eSAxel Dörfler 			return B_ENTRY_NOT_FOUND;
86418d3e65eSAxel Dörfler 
86518d3e65eSAxel Dörfler 		fSources.RemoveItemAt(index);
86618d3e65eSAxel Dörfler 		delete source;
86718d3e65eSAxel Dörfler 		DataHistory* values = fValues.RemoveItemAt(index);
86818d3e65eSAxel Dörfler 		delete values;
869065e8de0SAxel Dörfler 		removed = true;
8703a4a2141SAxel Dörfler 	}
87118d3e65eSAxel Dörfler 
872dc1ffc79SFrançois Revol #ifdef __HAIKU__
873065e8de0SAxel Dörfler 	InvalidateLayout();
874dc1ffc79SFrançois Revol #endif
87518d3e65eSAxel Dörfler 	return B_OK;
87618d3e65eSAxel Dörfler }
87718d3e65eSAxel Dörfler 
87818d3e65eSAxel Dörfler 
87918d3e65eSAxel Dörfler void
88018d3e65eSAxel Dörfler ActivityView::RemoveAllDataSources()
88118d3e65eSAxel Dörfler {
882d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
883d4216445SAxel Dörfler 
88418d3e65eSAxel Dörfler 	fSources.MakeEmpty();
88518d3e65eSAxel Dörfler 	fValues.MakeEmpty();
88618d3e65eSAxel Dörfler }
88718d3e65eSAxel Dörfler 
88818d3e65eSAxel Dörfler 
88918d3e65eSAxel Dörfler void
89018d3e65eSAxel Dörfler ActivityView::AttachedToWindow()
89118d3e65eSAxel Dörfler {
89274158bb4SFrançois Revol 	Looper()->AddHandler(fSystemInfoHandler);
8936f6ba875SAxel Dörfler 	fSystemInfoHandler->StartWatching();
8946f6ba875SAxel Dörfler 
895d4216445SAxel Dörfler 	fRefreshSem = create_sem(0, "refresh sem");
896d4216445SAxel Dörfler 	fRefreshThread = spawn_thread(&_RefreshThread, "source refresh",
8978e26f387SAxel Dörfler 		B_URGENT_DISPLAY_PRIORITY, this);
898d4216445SAxel Dörfler 	resume_thread(fRefreshThread);
8993a4a2141SAxel Dörfler 
9003a4a2141SAxel Dörfler 	FrameResized(Bounds().Width(), Bounds().Height());
90118d3e65eSAxel Dörfler }
90218d3e65eSAxel Dörfler 
90318d3e65eSAxel Dörfler 
90418d3e65eSAxel Dörfler void
90518d3e65eSAxel Dörfler ActivityView::DetachedFromWindow()
90618d3e65eSAxel Dörfler {
9076f6ba875SAxel Dörfler 	fSystemInfoHandler->StopWatching();
90874158bb4SFrançois Revol 	Looper()->RemoveHandler(fSystemInfoHandler);
9096f6ba875SAxel Dörfler 
910d4216445SAxel Dörfler 	delete_sem(fRefreshSem);
911d4216445SAxel Dörfler 	wait_for_thread(fRefreshThread, NULL);
91218d3e65eSAxel Dörfler }
91318d3e65eSAxel Dörfler 
91418d3e65eSAxel Dörfler 
915cbd4bc95SFrançois Revol #ifdef __HAIKU__
9163a4a2141SAxel Dörfler BSize
9173a4a2141SAxel Dörfler ActivityView::MinSize()
9183a4a2141SAxel Dörfler {
9193a4a2141SAxel Dörfler 	BSize size(32, 32);
9203a4a2141SAxel Dörfler 	if (fShowLegend)
9219c89c450SAxel Dörfler 		size.height = _LegendHeight();
9223a4a2141SAxel Dörfler 
9233a4a2141SAxel Dörfler 	return size;
9243a4a2141SAxel Dörfler }
925cbd4bc95SFrançois Revol #endif
9263a4a2141SAxel Dörfler 
9273a4a2141SAxel Dörfler 
92818d3e65eSAxel Dörfler void
92918d3e65eSAxel Dörfler ActivityView::FrameResized(float /*width*/, float /*height*/)
93018d3e65eSAxel Dörfler {
9313a4a2141SAxel Dörfler 	_UpdateOffscreenBitmap();
9323a4a2141SAxel Dörfler }
9333a4a2141SAxel Dörfler 
9343a4a2141SAxel Dörfler 
9353a4a2141SAxel Dörfler void
9369c89c450SAxel Dörfler ActivityView::_UpdateOffscreenBitmap()
9373a4a2141SAxel Dörfler {
9383a4a2141SAxel Dörfler 	BRect frame = _HistoryFrame();
939ed1b2753SStephan Aßmus 	frame.OffsetTo(B_ORIGIN);
940ed1b2753SStephan Aßmus 
9419c89c450SAxel Dörfler 	if (fOffscreen != NULL && frame == fOffscreen->Bounds())
9423a4a2141SAxel Dörfler 		return;
9433a4a2141SAxel Dörfler 
9443a4a2141SAxel Dörfler 	delete fOffscreen;
9453a4a2141SAxel Dörfler 
9463a4a2141SAxel Dörfler 	// create offscreen bitmap
9473a4a2141SAxel Dörfler 
9483a4a2141SAxel Dörfler 	fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS,
9493a4a2141SAxel Dörfler 		B_RGB32);
9503a4a2141SAxel Dörfler 	if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) {
9513a4a2141SAxel Dörfler 		delete fOffscreen;
9523a4a2141SAxel Dörfler 		fOffscreen = NULL;
9533a4a2141SAxel Dörfler 		return;
9543a4a2141SAxel Dörfler 	}
9553a4a2141SAxel Dörfler 
9563a4a2141SAxel Dörfler 	BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE);
9579c89c450SAxel Dörfler 	view->SetViewColor(fHistoryBackgroundColor);
9583a4a2141SAxel Dörfler 	view->SetLowColor(view->ViewColor());
9593a4a2141SAxel Dörfler 	fOffscreen->AddChild(view);
96018d3e65eSAxel Dörfler }
96118d3e65eSAxel Dörfler 
96218d3e65eSAxel Dörfler 
9639c89c450SAxel Dörfler BView*
9649c89c450SAxel Dörfler ActivityView::_OffscreenView()
9659c89c450SAxel Dörfler {
9669c89c450SAxel Dörfler 	if (fOffscreen == NULL)
9679c89c450SAxel Dörfler 		return NULL;
9689c89c450SAxel Dörfler 
9699c89c450SAxel Dörfler 	return fOffscreen->ChildAt(0);
9709c89c450SAxel Dörfler }
9719c89c450SAxel Dörfler 
9729c89c450SAxel Dörfler 
97318d3e65eSAxel Dörfler void
97418d3e65eSAxel Dörfler ActivityView::MouseDown(BPoint where)
97518d3e65eSAxel Dörfler {
97651591198SAxel Dörfler 	int32 buttons = B_SECONDARY_MOUSE_BUTTON;
97751591198SAxel Dörfler 	if (Looper() != NULL && Looper()->CurrentMessage() != NULL)
97818d3e65eSAxel Dörfler 		Looper()->CurrentMessage()->FindInt32("buttons", &buttons);
97951591198SAxel Dörfler 
98051591198SAxel Dörfler 	if (buttons == B_PRIMARY_MOUSE_BUTTON) {
98151591198SAxel Dörfler 		fZoomPoint = where;
98251591198SAxel Dörfler 		fOriginalResolution = fDrawResolution;
98351591198SAxel Dörfler 		fZooming = true;
9848e26f387SAxel Dörfler 		SetMouseEventMask(B_POINTER_EVENTS);
98551591198SAxel Dörfler 		return;
98618d3e65eSAxel Dörfler 	}
98718d3e65eSAxel Dörfler 
98818d3e65eSAxel Dörfler 	BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false);
98918d3e65eSAxel Dörfler 	menu->SetFont(be_plain_font);
9903a4a2141SAxel Dörfler 
9914840a72fSPhilippe Houdoin 	BMenu* additionalMenu = new BMenu(B_TRANSLATE("Additional items"));
992dc1ffc79SFrançois Revol 	additionalMenu->SetFont(be_plain_font);
993dc1ffc79SFrançois Revol 
9943a4a2141SAxel Dörfler 	SystemInfo info;
99518d3e65eSAxel Dörfler 	BMenuItem* item;
99618d3e65eSAxel Dörfler 
99718d3e65eSAxel Dörfler 	for (int32 i = 0; i < DataSource::CountSources(); i++) {
99818d3e65eSAxel Dörfler 		const DataSource* source = DataSource::SourceAt(i);
99918d3e65eSAxel Dörfler 
10003a4a2141SAxel Dörfler 		if (source->MultiCPUOnly() && info.CPUCount() == 1)
10013a4a2141SAxel Dörfler 			continue;
10023a4a2141SAxel Dörfler 
100318d3e65eSAxel Dörfler 		BMessage* message = new BMessage(kMsgToggleDataSource);
100418d3e65eSAxel Dörfler 		message->AddInt32("index", i);
100518d3e65eSAxel Dörfler 
10063a4a2141SAxel Dörfler 		item = new BMenuItem(source->Name(), message);
10073a4a2141SAxel Dörfler 		if (FindDataSource(source))
100818d3e65eSAxel Dörfler 			item->SetMarked(true);
100918d3e65eSAxel Dörfler 
101043eda1cdSAxel Dörfler 		if (source->Primary())
101118d3e65eSAxel Dörfler 			menu->AddItem(item);
101243eda1cdSAxel Dörfler 		else
101343eda1cdSAxel Dörfler 			additionalMenu->AddItem(item);
101418d3e65eSAxel Dörfler 	}
101518d3e65eSAxel Dörfler 
101643eda1cdSAxel Dörfler 	menu->AddItem(new BMenuItem(additionalMenu));
10173a4a2141SAxel Dörfler 	menu->AddSeparatorItem();
10184840a72fSPhilippe Houdoin 	menu->AddItem(new BMenuItem(fShowLegend ?
10194840a72fSPhilippe Houdoin 		B_TRANSLATE("Hide legend") : B_TRANSLATE("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);
10304840a72fSPhilippe Houdoin 		menu->AddItem(item = new BMenuItem(B_TRANSLATE("Remove graph"),
10314840a72fSPhilippe Houdoin 			message));
10323f315b26SAxel Dörfler 		item->SetTarget(window);
10333f315b26SAxel Dörfler 	}
10343f315b26SAxel Dörfler 
103518d3e65eSAxel Dörfler 	ConvertToScreen(&where);
103618d3e65eSAxel Dörfler 	menu->Go(where, true, false, true);
103718d3e65eSAxel Dörfler }
103818d3e65eSAxel Dörfler 
103918d3e65eSAxel Dörfler 
104018d3e65eSAxel Dörfler void
104151591198SAxel Dörfler ActivityView::MouseUp(BPoint where)
104251591198SAxel Dörfler {
104351591198SAxel Dörfler 	fZooming = false;
104451591198SAxel Dörfler }
104551591198SAxel Dörfler 
104651591198SAxel Dörfler 
104751591198SAxel Dörfler void
104818d3e65eSAxel Dörfler ActivityView::MouseMoved(BPoint where, uint32 transit,
104918d3e65eSAxel Dörfler 	const BMessage* dragMessage)
105018d3e65eSAxel Dörfler {
105151591198SAxel Dörfler 	if (!fZooming)
105251591198SAxel Dörfler 		return;
105351591198SAxel Dörfler 
105451591198SAxel Dörfler 	int32 shift = int32(where.x - fZoomPoint.x) / 25;
10551bb87bd0SAxel Dörfler 	int32 resolution;
105651591198SAxel Dörfler 	if (shift > 0)
10571bb87bd0SAxel Dörfler 		resolution = fOriginalResolution << shift;
105851591198SAxel Dörfler 	else
10591bb87bd0SAxel Dörfler 		resolution = fOriginalResolution >> -shift;
106051591198SAxel Dörfler 
10611bb87bd0SAxel Dörfler 	_UpdateResolution(resolution);
106218d3e65eSAxel Dörfler }
106318d3e65eSAxel Dörfler 
106418d3e65eSAxel Dörfler 
106518d3e65eSAxel Dörfler void
106618d3e65eSAxel Dörfler ActivityView::MessageReceived(BMessage* message)
106718d3e65eSAxel Dörfler {
1068c28f8ea3SFrançois Revol 	// if a color is dropped, use it as background
1069c28f8ea3SFrançois Revol 	if (message->WasDropped()) {
1070c28f8ea3SFrançois Revol 		rgb_color* color;
1071c28f8ea3SFrançois Revol 		ssize_t size;
10721201d52eSAxel Dörfler 		if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0,
10731201d52eSAxel Dörfler 				(const void**)&color, &size) == B_OK
10749c89c450SAxel Dörfler 			&& size == sizeof(rgb_color)) {
10759c89c450SAxel Dörfler 			BPoint dropPoint = message->DropPoint();
1076c28f8ea3SFrançois Revol 			ConvertFromScreen(&dropPoint);
10779c89c450SAxel Dörfler 
1078c28f8ea3SFrançois Revol 			if (_HistoryFrame().Contains(dropPoint)) {
10799c89c450SAxel Dörfler 				fHistoryBackgroundColor = *color;
10809c89c450SAxel Dörfler 				Invalidate(_HistoryFrame());
1081c28f8ea3SFrançois Revol 			} else {
10825f2f72a2SFrançois Revol 				// check each legend color box
1083d4216445SAxel Dörfler 				BAutolock _(fSourcesLock);
1084d4216445SAxel Dörfler 
10855f2f72a2SFrançois Revol 				BRect legendFrame = _LegendFrame();
10869c89c450SAxel Dörfler 				for (int32 i = 0; i < fSources.CountItems(); i++) {
10871201d52eSAxel Dörfler 					BRect frame = _LegendColorFrameAt(legendFrame, i);
10889c89c450SAxel Dörfler 					if (frame.Contains(dropPoint)) {
10895f2f72a2SFrançois Revol 						fSources.ItemAt(i)->SetColor(*color);
10909c89c450SAxel Dörfler 						Invalidate(_HistoryFrame());
10911201d52eSAxel Dörfler 						Invalidate(frame);
10925f2f72a2SFrançois Revol 						return;
10935f2f72a2SFrançois Revol 					}
10945f2f72a2SFrançois Revol 				}
10959c89c450SAxel Dörfler 
10969c89c450SAxel Dörfler 				if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) {
10979c89c450SAxel Dörfler 					// allow background color change in the replicant only
10989c89c450SAxel Dörfler 					fLegendBackgroundColor = *color;
10991201d52eSAxel Dörfler 					SetLowColor(fLegendBackgroundColor);
11009c89c450SAxel Dörfler 					Invalidate(legendFrame);
11019c89c450SAxel Dörfler 				}
1102c28f8ea3SFrançois Revol 			}
1103c28f8ea3SFrançois Revol 			return;
1104c28f8ea3SFrançois Revol 		}
11059c89c450SAxel Dörfler 	}
11069c89c450SAxel Dörfler 
110718d3e65eSAxel Dörfler 	switch (message->what) {
110818d3e65eSAxel Dörfler 		case B_ABOUT_REQUESTED:
1109fd19c736SAdrien Destugues 		{
1110df2257deSAdrien Destugues 			BAboutWindow* window = new BAboutWindow(kAppName, kSignature);
1111df2257deSAdrien Destugues 
111280d7bf83SJohn Scipione 			const char* authors[] = {
111380d7bf83SJohn Scipione 				"Axel Dörfler",
111480d7bf83SJohn Scipione 				NULL
111580d7bf83SJohn Scipione 			};
111680d7bf83SJohn Scipione 
1117fd19c736SAdrien Destugues 			window->AddCopyright(2008, "Haiku, Inc.");
1118fd19c736SAdrien Destugues 			window->AddAuthors(authors);
1119fd19c736SAdrien Destugues 
1120fd19c736SAdrien Destugues 			window->Show();
11213fdab584SJohn Scipione 
11223fdab584SJohn Scipione 			break;
1123fd19c736SAdrien Destugues 		}
11241bb87bd0SAxel Dörfler 		case kMsgUpdateResolution:
11251bb87bd0SAxel Dörfler 		{
11261bb87bd0SAxel Dörfler 			int32 resolution;
11271bb87bd0SAxel Dörfler 			if (message->FindInt32("resolution", &resolution) != B_OK)
11281bb87bd0SAxel Dörfler 				break;
11291bb87bd0SAxel Dörfler 
11301bb87bd0SAxel Dörfler 			_UpdateResolution(resolution, false);
11311bb87bd0SAxel Dörfler 			break;
11321bb87bd0SAxel Dörfler 		}
11331bb87bd0SAxel Dörfler 
11341bb87bd0SAxel Dörfler 		case kMsgTimeIntervalUpdated:
11351bb87bd0SAxel Dörfler 			bigtime_t interval;
11361bb87bd0SAxel Dörfler 			if (message->FindInt64("interval", &interval) != B_OK)
11371bb87bd0SAxel Dörfler 				break;
11381bb87bd0SAxel Dörfler 
11391bb87bd0SAxel Dörfler 			if (interval < 10000)
11401bb87bd0SAxel Dörfler 				interval = 10000;
11411bb87bd0SAxel Dörfler 
11421bb87bd0SAxel Dörfler 			atomic_set64(&fRefreshInterval, interval);
11431bb87bd0SAxel Dörfler 			break;
11441bb87bd0SAxel Dörfler 
114518d3e65eSAxel Dörfler 		case kMsgToggleDataSource:
114618d3e65eSAxel Dörfler 		{
114718d3e65eSAxel Dörfler 			int32 index;
114818d3e65eSAxel Dörfler 			if (message->FindInt32("index", &index) != B_OK)
114918d3e65eSAxel Dörfler 				break;
115018d3e65eSAxel Dörfler 
115118d3e65eSAxel Dörfler 			const DataSource* baseSource = DataSource::SourceAt(index);
115218d3e65eSAxel Dörfler 			if (baseSource == NULL)
115318d3e65eSAxel Dörfler 				break;
115418d3e65eSAxel Dörfler 
11553a4a2141SAxel Dörfler 			DataSource* source = FindDataSource(baseSource);
115618d3e65eSAxel Dörfler 			if (source == NULL)
11573a4a2141SAxel Dörfler 				AddDataSource(baseSource);
115818d3e65eSAxel Dörfler 			else
11597d33b63dSAxel Dörfler 				RemoveDataSource(baseSource);
116018d3e65eSAxel Dörfler 
116118d3e65eSAxel Dörfler 			Invalidate();
116218d3e65eSAxel Dörfler 			break;
116318d3e65eSAxel Dörfler 		}
116418d3e65eSAxel Dörfler 
11653a4a2141SAxel Dörfler 		case kMsgToggleLegend:
11663a4a2141SAxel Dörfler 			fShowLegend = !fShowLegend;
11673a4a2141SAxel Dörfler 			Invalidate();
11683a4a2141SAxel Dörfler 			break;
11693a4a2141SAxel Dörfler 
117018d3e65eSAxel Dörfler 		case B_MOUSE_WHEEL_CHANGED:
117118d3e65eSAxel Dörfler 		{
117218d3e65eSAxel Dörfler 			float deltaY = 0.0f;
117318d3e65eSAxel Dörfler 			if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK
117418d3e65eSAxel Dörfler 				|| deltaY == 0.0f)
117518d3e65eSAxel Dörfler 				break;
117618d3e65eSAxel Dörfler 
11771bb87bd0SAxel Dörfler 			int32 resolution = fDrawResolution;
117818d3e65eSAxel Dörfler 			if (deltaY > 0)
11791bb87bd0SAxel Dörfler 				resolution *= 2;
118018d3e65eSAxel Dörfler 			else
11811bb87bd0SAxel Dörfler 				resolution /= 2;
118218d3e65eSAxel Dörfler 
11831bb87bd0SAxel Dörfler 			_UpdateResolution(resolution);
118418d3e65eSAxel Dörfler 			break;
118518d3e65eSAxel Dörfler 		}
118618d3e65eSAxel Dörfler 
118718d3e65eSAxel Dörfler 		default:
118818d3e65eSAxel Dörfler 			BView::MessageReceived(message);
118918d3e65eSAxel Dörfler 			break;
119018d3e65eSAxel Dörfler 	}
119118d3e65eSAxel Dörfler }
119218d3e65eSAxel Dörfler 
119318d3e65eSAxel Dörfler 
1194065e8de0SAxel Dörfler void
1195065e8de0SAxel Dörfler ActivityView::_UpdateFrame()
1196065e8de0SAxel Dörfler {
1197dc1ffc79SFrançois Revol #ifdef __HAIKU__
1198065e8de0SAxel Dörfler 	if (fLegendLayoutItem == NULL || fHistoryLayoutItem == NULL)
1199065e8de0SAxel Dörfler 		return;
1200065e8de0SAxel Dörfler 
1201065e8de0SAxel Dörfler 	BRect historyFrame = fHistoryLayoutItem->Frame();
1202065e8de0SAxel Dörfler 	BRect legendFrame = fLegendLayoutItem->Frame();
1203dc1ffc79SFrançois Revol #else
1204dc1ffc79SFrançois Revol 	BRect historyFrame = Bounds();
1205dc1ffc79SFrançois Revol 	BRect legendFrame = Bounds();
1206dc1ffc79SFrançois Revol 	historyFrame.bottom -= 2 * Bounds().Height() / 3;
1207dc1ffc79SFrançois Revol 	legendFrame.top += Bounds().Height() / 3;
1208dc1ffc79SFrançois Revol #endif
1209065e8de0SAxel Dörfler 	MoveTo(historyFrame.left, historyFrame.top);
1210065e8de0SAxel Dörfler 	ResizeTo(legendFrame.left + legendFrame.Width() - historyFrame.left,
1211065e8de0SAxel Dörfler 		legendFrame.top + legendFrame.Height() - historyFrame.top);
1212065e8de0SAxel Dörfler }
1213065e8de0SAxel Dörfler 
1214065e8de0SAxel Dörfler 
12153a4a2141SAxel Dörfler BRect
12163a4a2141SAxel Dörfler ActivityView::_HistoryFrame() const
12173a4a2141SAxel Dörfler {
12183a4a2141SAxel Dörfler 	BRect frame = Bounds();
12193a4a2141SAxel Dörfler 
1220ed1b2753SStephan Aßmus 	if (fShowLegend) {
1221ed1b2753SStephan Aßmus 		BRect legendFrame = _LegendFrame();
12223a4a2141SAxel Dörfler 		frame.bottom = legendFrame.top - 1;
1223ed1b2753SStephan Aßmus 	}
1224ed1b2753SStephan Aßmus 
1225ed1b2753SStephan Aßmus 	frame.InsetBy(2, 2);
12263a4a2141SAxel Dörfler 
12273a4a2141SAxel Dörfler 	return frame;
12283a4a2141SAxel Dörfler }
12293a4a2141SAxel Dörfler 
12303a4a2141SAxel Dörfler 
1231065e8de0SAxel Dörfler float
1232065e8de0SAxel Dörfler ActivityView::_LegendHeight() const
12333a4a2141SAxel Dörfler {
12343a4a2141SAxel Dörfler 	font_height fontHeight;
12353a4a2141SAxel Dörfler 	GetFontHeight(&fontHeight);
12363a4a2141SAxel Dörfler 
1237d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
1238d4216445SAxel Dörfler 
12393a4a2141SAxel Dörfler 	int32 rows = (fSources.CountItems() + 1) / 2;
1240fbb82a62SPhilippe Saint-Pierre 
1241e45d83a9SPhilippe Saint-Pierre 	int32 boldMargin = Parent()
1242e45d83a9SPhilippe Saint-Pierre 		&& (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0 ? 2 : 0;
1243fbb82a62SPhilippe Saint-Pierre 
1244065e8de0SAxel Dörfler 	return rows * (4 + ceilf(fontHeight.ascent)
12459bd81dbeSStephan Aßmus 		+ ceilf(fontHeight.descent) + ceilf(fontHeight.leading)) + boldMargin;
1246065e8de0SAxel Dörfler }
1247065e8de0SAxel Dörfler 
1248065e8de0SAxel Dörfler 
1249065e8de0SAxel Dörfler BRect
1250065e8de0SAxel Dörfler ActivityView::_LegendFrame() const
1251065e8de0SAxel Dörfler {
1252065e8de0SAxel Dörfler 	float height;
1253dc1ffc79SFrançois Revol #ifdef __HAIKU__
1254065e8de0SAxel Dörfler 	if (fLegendLayoutItem != NULL)
1255065e8de0SAxel Dörfler 		height = fLegendLayoutItem->Frame().Height();
1256065e8de0SAxel Dörfler 	else
1257dc1ffc79SFrançois Revol #endif
1258065e8de0SAxel Dörfler 		height = _LegendHeight();
1259065e8de0SAxel Dörfler 
1260065e8de0SAxel Dörfler 	BRect frame = Bounds();
12619bd81dbeSStephan Aßmus 	frame.bottom -= kDraggerSize;
1262065e8de0SAxel Dörfler 	frame.top = frame.bottom - height;
12633a4a2141SAxel Dörfler 
12643a4a2141SAxel Dörfler 	return frame;
12653a4a2141SAxel Dörfler }
12663a4a2141SAxel Dörfler 
12673a4a2141SAxel Dörfler 
12683a4a2141SAxel Dörfler BRect
12693a4a2141SAxel Dörfler ActivityView::_LegendFrameAt(BRect frame, int32 index) const
12703a4a2141SAxel Dörfler {
12713a4a2141SAxel Dörfler 	int32 column = index & 1;
12723a4a2141SAxel Dörfler 	int32 row = index / 2;
12736df2c16cSAdrien Destugues 	if (column == 0) {
127427231d80SAxel Dörfler 		// Use the full width if there is only one item
127527231d80SAxel Dörfler 		if (fSources.CountItems() != 1)
12763a4a2141SAxel Dörfler 			frame.right = frame.left + floorf(frame.Width() / 2) - 5;
12776df2c16cSAdrien Destugues 	} else
12783a4a2141SAxel Dörfler 		frame.left = frame.right - floorf(frame.Width() / 2) + 5;
12793a4a2141SAxel Dörfler 
1280d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
1281d4216445SAxel Dörfler 
12823a4a2141SAxel Dörfler 	int32 rows = (fSources.CountItems() + 1) / 2;
12833a4a2141SAxel Dörfler 	float height = floorf((frame.Height() - 5) / rows);
12843a4a2141SAxel Dörfler 
12853a4a2141SAxel Dörfler 	frame.top = frame.top + 5 + row * height;
12863a4a2141SAxel Dörfler 	frame.bottom = frame.top + height - 1;
12873a4a2141SAxel Dörfler 
12883a4a2141SAxel Dörfler 	return frame;
12893a4a2141SAxel Dörfler }
12903a4a2141SAxel Dörfler 
12913a4a2141SAxel Dörfler 
12921201d52eSAxel Dörfler BRect
12931201d52eSAxel Dörfler ActivityView::_LegendColorFrameAt(BRect frame, int32 index) const
12941201d52eSAxel Dörfler {
12951201d52eSAxel Dörfler 	frame = _LegendFrameAt(frame, index);
12961201d52eSAxel Dörfler 	frame.InsetBy(1, 1);
12971201d52eSAxel Dörfler 	frame.right = frame.left + frame.Height();
12981201d52eSAxel Dörfler 
12991201d52eSAxel Dörfler 	return frame;
13001201d52eSAxel Dörfler }
13011201d52eSAxel Dörfler 
13021201d52eSAxel Dörfler 
130318d3e65eSAxel Dörfler float
130418d3e65eSAxel Dörfler ActivityView::_PositionForValue(DataSource* source, DataHistory* values,
130518d3e65eSAxel Dörfler 	int64 value)
130618d3e65eSAxel Dörfler {
130718d3e65eSAxel Dörfler 	int64 min = source->Minimum();
130818d3e65eSAxel Dörfler 	int64 max = source->Maximum();
130918d3e65eSAxel Dörfler 	if (source->AdaptiveScale()) {
131018d3e65eSAxel Dörfler 		int64 adaptiveMax = int64(values->MaximumValue() * 1.2);
131118d3e65eSAxel Dörfler 		if (adaptiveMax < max)
131218d3e65eSAxel Dörfler 			max = adaptiveMax;
131318d3e65eSAxel Dörfler 	}
131418d3e65eSAxel Dörfler 
131518d3e65eSAxel Dörfler 	if (value > max)
131618d3e65eSAxel Dörfler 		value = max;
131718d3e65eSAxel Dörfler 	if (value < min)
131818d3e65eSAxel Dörfler 		value = min;
131918d3e65eSAxel Dörfler 
13203a4a2141SAxel Dörfler 	float height = _HistoryFrame().Height();
132118d3e65eSAxel Dörfler 	return height - (value - min) * height / (max - min);
132218d3e65eSAxel Dörfler }
132318d3e65eSAxel Dörfler 
132418d3e65eSAxel Dörfler 
132518d3e65eSAxel Dörfler void
1326ed1b2753SStephan Aßmus ActivityView::_DrawHistory(bool drawBackground)
132718d3e65eSAxel Dörfler {
13283a4a2141SAxel Dörfler 	_UpdateOffscreenBitmap();
13293a4a2141SAxel Dörfler 
13303a4a2141SAxel Dörfler 	BView* view = this;
13313a4a2141SAxel Dörfler 	if (fOffscreen != NULL) {
13323a4a2141SAxel Dörfler 		fOffscreen->Lock();
13339c89c450SAxel Dörfler 		view = _OffscreenView();
13343a4a2141SAxel Dörfler 	}
13353a4a2141SAxel Dörfler 
13363a4a2141SAxel Dörfler 	BRect frame = _HistoryFrame();
1337ed1b2753SStephan Aßmus 	BRect outerFrame = frame.InsetByCopy(-2, -2);
1338ed1b2753SStephan Aßmus 
1339ed1b2753SStephan Aßmus 	// draw the outer frame
1340ed1b2753SStephan Aßmus 	uint32 flags = 0;
1341ed1b2753SStephan Aßmus 	if (!drawBackground)
1342ed1b2753SStephan Aßmus 		flags |= BControlLook::B_BLEND_FRAME;
1343ed1b2753SStephan Aßmus 	be_control_look->DrawTextControlBorder(this, outerFrame,
1344ed1b2753SStephan Aßmus 		outerFrame, fLegendBackgroundColor, flags);
1345ed1b2753SStephan Aßmus 
1346ed1b2753SStephan Aßmus 	// convert to offscreen view if necessary
1347ed1b2753SStephan Aßmus 	if (view != this)
1348ed1b2753SStephan Aßmus 		frame.OffsetTo(B_ORIGIN);
1349ed1b2753SStephan Aßmus 
13501201d52eSAxel Dörfler 	view->SetLowColor(fHistoryBackgroundColor);
13513a4a2141SAxel Dörfler 	view->FillRect(frame, B_SOLID_LOW);
13523a4a2141SAxel Dörfler 
135318d3e65eSAxel Dörfler 	uint32 step = 2;
135418d3e65eSAxel Dörfler 	uint32 resolution = fDrawResolution;
135518d3e65eSAxel Dörfler 	if (fDrawResolution > 1) {
135618d3e65eSAxel Dörfler 		step = 1;
135718d3e65eSAxel Dörfler 		resolution--;
135818d3e65eSAxel Dörfler 	}
135918d3e65eSAxel Dörfler 
13603f57b135SAdrien Destugues 	// We would get a negative number of steps which isn't a good idea.
13613f57b135SAdrien Destugues 	if (frame.IntegerWidth() <= 10)
13623f57b135SAdrien Destugues 		return;
13633f57b135SAdrien Destugues 
13643a4a2141SAxel Dörfler 	uint32 width = frame.IntegerWidth() - 10;
136518d3e65eSAxel Dörfler 	uint32 steps = width / step;
13661bb87bd0SAxel Dörfler 	bigtime_t timeStep = RefreshInterval() * resolution;
136718d3e65eSAxel Dörfler 	bigtime_t now = system_time();
136818d3e65eSAxel Dörfler 
13691201d52eSAxel Dörfler 	// Draw scale
13701201d52eSAxel Dörfler 	// TODO: add second markers?
13711201d52eSAxel Dörfler 
13723a4a2141SAxel Dörfler 	view->SetPenSize(1);
13733a4a2141SAxel Dörfler 
13741201d52eSAxel Dörfler 	rgb_color scaleColor = view->LowColor();
13751201d52eSAxel Dörfler 	uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3;
13761201d52eSAxel Dörfler 	if (average < 96)
13771201d52eSAxel Dörfler 		scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT);
13781201d52eSAxel Dörfler 	else
13791201d52eSAxel Dörfler 		scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT);
13801201d52eSAxel Dörfler 
13811201d52eSAxel Dörfler 	view->SetHighColor(scaleColor);
13823a4a2141SAxel Dörfler 	view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2),
13833a4a2141SAxel Dörfler 		BPoint(frame.right, frame.top + frame.Height() / 2));
13843a4a2141SAxel Dörfler 
13851201d52eSAxel Dörfler 	// Draw values
13861201d52eSAxel Dörfler 
13871bb87bd0SAxel Dörfler 	view->SetPenSize(1.5);
1388d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
138918d3e65eSAxel Dörfler 
139018d3e65eSAxel Dörfler 	for (uint32 i = fSources.CountItems(); i-- > 0;) {
13918e26f387SAxel Dörfler 		ViewHistory* viewValues = fViewValues.ItemAt(i);
139218d3e65eSAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
139318d3e65eSAxel Dörfler 		DataHistory* values = fValues.ItemAt(i);
139418d3e65eSAxel Dörfler 
13958e26f387SAxel Dörfler 		viewValues->Update(values, steps, fDrawResolution, now, timeStep,
13968e26f387SAxel Dörfler 			RefreshInterval());
13978e26f387SAxel Dörfler 
13983f57b135SAdrien Destugues 		if (viewValues->Start() >= (int32)steps - 1)
13993f57b135SAdrien Destugues 			continue;
14003f57b135SAdrien Destugues 
14018e26f387SAxel Dörfler 		uint32 x = viewValues->Start() * step;
14023f57b135SAdrien Destugues 
14038e26f387SAxel Dörfler 		bool first = true;
14048e26f387SAxel Dörfler 
14053a4a2141SAxel Dörfler 		view->SetHighColor(source->Color());
14068e26f387SAxel Dörfler 		view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN);
14078e26f387SAxel Dörfler 		view->MovePenTo(B_ORIGIN);
14083f57b135SAdrien Destugues 
140952051a08SAdrien Destugues 		try {
14103f57b135SAdrien Destugues 			view->BeginLineArray(steps - viewValues->Start() - 1);
14113f57b135SAdrien Destugues 
14123f57b135SAdrien Destugues 			BPoint prev;
14133f57b135SAdrien Destugues 
14143f57b135SAdrien Destugues 			for (uint32 j = viewValues->Start(); j < steps; x += step, j++) {
14153f57b135SAdrien Destugues 				float y = _PositionForValue(source, values,
14163f57b135SAdrien Destugues 					viewValues->ValueAt(j));
14173f57b135SAdrien Destugues 
14183f57b135SAdrien Destugues 				if (first) {
14193f57b135SAdrien Destugues 					first = false;
14203f57b135SAdrien Destugues 				} else
14213f57b135SAdrien Destugues 					view->AddLine(prev, BPoint(x, y), source->Color());
14223f57b135SAdrien Destugues 
14233f57b135SAdrien Destugues 				prev.Set(x, y);
14243f57b135SAdrien Destugues 			}
14253f57b135SAdrien Destugues 
142652051a08SAdrien Destugues 		} catch (std::bad_alloc) {
142752051a08SAdrien Destugues 			// Not enough memory to allocate the line array.
142852051a08SAdrien Destugues 			// TODO we could try to draw using the slower but less memory
142952051a08SAdrien Destugues 			// consuming solution using StrokeLine.
143052051a08SAdrien Destugues 		}
143152051a08SAdrien Destugues 
14323f57b135SAdrien Destugues 		view->EndLineArray();
143318d3e65eSAxel Dörfler 	}
143418d3e65eSAxel Dörfler 
143518d3e65eSAxel Dörfler 	// TODO: add marks when an app started or quit
14363a4a2141SAxel Dörfler 	view->Sync();
14373a4a2141SAxel Dörfler 	if (fOffscreen != NULL) {
14383a4a2141SAxel Dörfler 		fOffscreen->Unlock();
1439ed1b2753SStephan Aßmus 		DrawBitmap(fOffscreen, outerFrame.LeftTop());
14403a4a2141SAxel Dörfler 	}
14413a4a2141SAxel Dörfler }
14423a4a2141SAxel Dörfler 
14433a4a2141SAxel Dörfler 
14443a4a2141SAxel Dörfler void
14451bb87bd0SAxel Dörfler ActivityView::_UpdateResolution(int32 resolution, bool broadcast)
14461bb87bd0SAxel Dörfler {
14471bb87bd0SAxel Dörfler 	if (resolution < 1)
14481bb87bd0SAxel Dörfler 		resolution = 1;
14491bb87bd0SAxel Dörfler 	if (resolution > 128)
14501bb87bd0SAxel Dörfler 		resolution = 128;
14511bb87bd0SAxel Dörfler 
14521bb87bd0SAxel Dörfler 	if (resolution == fDrawResolution)
14531bb87bd0SAxel Dörfler 		return;
14541bb87bd0SAxel Dörfler 
14551bb87bd0SAxel Dörfler 	ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window());
14561bb87bd0SAxel Dörfler 	if (broadcast && window != NULL) {
14571bb87bd0SAxel Dörfler 		BMessage update(kMsgUpdateResolution);
14581bb87bd0SAxel Dörfler 		update.AddInt32("resolution", resolution);
14591bb87bd0SAxel Dörfler 		window->BroadcastToActivityViews(&update, this);
14601bb87bd0SAxel Dörfler 	}
14611bb87bd0SAxel Dörfler 
14621bb87bd0SAxel Dörfler 	fDrawResolution = resolution;
14631bb87bd0SAxel Dörfler 	Invalidate();
14641bb87bd0SAxel Dörfler }
14651bb87bd0SAxel Dörfler 
14661bb87bd0SAxel Dörfler 
14671bb87bd0SAxel Dörfler void
1468ed1b2753SStephan Aßmus ActivityView::Draw(BRect updateRect)
14693a4a2141SAxel Dörfler {
1470ed1b2753SStephan Aßmus 	bool drawBackground = true;
1471ed1b2753SStephan Aßmus 	if (Parent() && (Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0)
1472ed1b2753SStephan Aßmus 		drawBackground = false;
1473ed1b2753SStephan Aßmus 
1474ed1b2753SStephan Aßmus 	_DrawHistory(drawBackground);
14753a4a2141SAxel Dörfler 
14763a4a2141SAxel Dörfler 	if (!fShowLegend)
14773a4a2141SAxel Dörfler 		return;
14783a4a2141SAxel Dörfler 
14793a4a2141SAxel Dörfler 	// draw legend
1480ed1b2753SStephan Aßmus 	BRect legendFrame = _LegendFrame();
1481*fa19dd44Slooncraz 	if (LowUIColor() == B_NO_COLOR)
1482ed1b2753SStephan Aßmus 		SetLowColor(fLegendBackgroundColor);
1483*fa19dd44Slooncraz 
14849bd81dbeSStephan Aßmus 	if (drawBackground) {
14859bd81dbeSStephan Aßmus 		BRect backgroundFrame(legendFrame);
14869bd81dbeSStephan Aßmus 		backgroundFrame.bottom += kDraggerSize;
14879bd81dbeSStephan Aßmus 		FillRect(backgroundFrame, B_SOLID_LOW);
14889bd81dbeSStephan Aßmus 	}
14893a4a2141SAxel Dörfler 
1490d4216445SAxel Dörfler 	BAutolock _(fSourcesLock);
14913a4a2141SAxel Dörfler 
14923a4a2141SAxel Dörfler 	font_height fontHeight;
14933a4a2141SAxel Dörfler 	GetFontHeight(&fontHeight);
14943a4a2141SAxel Dörfler 
14953a4a2141SAxel Dörfler 	for (int32 i = 0; i < fSources.CountItems(); i++) {
14963a4a2141SAxel Dörfler 		DataSource* source = fSources.ItemAt(i);
14973a4a2141SAxel Dörfler 		DataHistory* values = fValues.ItemAt(i);
14983a4a2141SAxel Dörfler 		BRect frame = _LegendFrameAt(legendFrame, i);
14993a4a2141SAxel Dörfler 
15003a4a2141SAxel Dörfler 		// draw color box
15011201d52eSAxel Dörfler 		BRect colorBox = _LegendColorFrameAt(legendFrame, i);
1502ed1b2753SStephan Aßmus 		BRect rect = colorBox;
1503ed1b2753SStephan Aßmus 		uint32 flags = BControlLook::B_BLEND_FRAME;
1504ed1b2753SStephan Aßmus 		be_control_look->DrawTextControlBorder(this, rect,
1505ed1b2753SStephan Aßmus 			rect, fLegendBackgroundColor, flags);
15063a4a2141SAxel Dörfler 		SetHighColor(source->Color());
1507ed1b2753SStephan Aßmus 		FillRect(rect);
15083a4a2141SAxel Dörfler 
15093a4a2141SAxel Dörfler 		// show current value and label
15103a4a2141SAxel Dörfler 		float y = frame.top + ceilf(fontHeight.ascent);
15113a4a2141SAxel Dörfler 		int64 value = values->ValueAt(values->End());
15123a4a2141SAxel Dörfler 		BString text;
15133a4a2141SAxel Dörfler 		source->Print(text, value);
15143a4a2141SAxel Dörfler 		float width = StringWidth(text.String());
15153a4a2141SAxel Dörfler 
15163a4a2141SAxel Dörfler 		BString label = source->Label();
1517ed1b2753SStephan Aßmus 		float possibleLabelWidth = frame.right - colorBox.right - 12 - width;
1518ed1b2753SStephan Aßmus 		// TODO: TruncateString() is broken... remove + 5 when fixed!
1519ed1b2753SStephan Aßmus 		if (ceilf(StringWidth(label.String()) + 5) > possibleLabelWidth)
1520ed1b2753SStephan Aßmus 			label = source->ShortLabel();
1521ed1b2753SStephan Aßmus 		TruncateString(&label, B_TRUNCATE_MIDDLE, possibleLabelWidth);
15223a4a2141SAxel Dörfler 
1523ed1b2753SStephan Aßmus 		if (drawBackground)
1524*fa19dd44Slooncraz 			SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
1525bb7cffd0SPhilippe Saint-Pierre 
1526d63b75faSPhilippe Saint-Pierre 		if (be_control_look == NULL) {
1527bb7cffd0SPhilippe Saint-Pierre 			DrawString(label.String(), BPoint(6 + colorBox.right, y));
1528bb7cffd0SPhilippe Saint-Pierre 			DrawString(text.String(), BPoint(frame.right - width, y));
1529bb7cffd0SPhilippe Saint-Pierre 		} else {
1530d63b75faSPhilippe Saint-Pierre 			be_control_look->DrawLabel(this, label.String(),
1531d63b75faSPhilippe Saint-Pierre 				Parent()->ViewColor(), 0, BPoint(6 + colorBox.right, y));
1532d63b75faSPhilippe Saint-Pierre 			be_control_look->DrawLabel(this, text.String(),
1533d63b75faSPhilippe Saint-Pierre 				Parent()->ViewColor(), 0, BPoint(frame.right - width, y));
1534bb7cffd0SPhilippe Saint-Pierre 		}
1535bb7cffd0SPhilippe Saint-Pierre 	}
153618d3e65eSAxel Dörfler }
153718d3e65eSAxel Dörfler 
153818d3e65eSAxel Dörfler 
153918d3e65eSAxel Dörfler void
154018d3e65eSAxel Dörfler ActivityView::_Refresh()
154118d3e65eSAxel Dörfler {
15421bb87bd0SAxel Dörfler 	bigtime_t lastTimeout = system_time() - RefreshInterval();
15434ce1e1d2SAxel Dörfler 	BMessenger target(this);
154418d3e65eSAxel Dörfler 
1545d4216445SAxel Dörfler 	while (true) {
1546d4216445SAxel Dörfler 		status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT,
15471bb87bd0SAxel Dörfler 			lastTimeout + RefreshInterval());
1548d4216445SAxel Dörfler 		if (status == B_OK || status == B_BAD_SEM_ID)
1549d4216445SAxel Dörfler 			break;
1550d4216445SAxel Dörfler 		if (status == B_INTERRUPTED)
1551d4216445SAxel Dörfler 			continue;
1552d4216445SAxel Dörfler 
1553d4216445SAxel Dörfler 		SystemInfo info(fSystemInfoHandler);
15541bb87bd0SAxel Dörfler 		lastTimeout += RefreshInterval();
1555d4216445SAxel Dörfler 
1556d4216445SAxel Dörfler 		fSourcesLock.Lock();
155718d3e65eSAxel Dörfler 
155818d3e65eSAxel Dörfler 		for (uint32 i = fSources.CountItems(); i-- > 0;) {
155918d3e65eSAxel Dörfler 			DataSource* source = fSources.ItemAt(i);
156018d3e65eSAxel Dörfler 			DataHistory* values = fValues.ItemAt(i);
156118d3e65eSAxel Dörfler 
156218d3e65eSAxel Dörfler 			int64 value = source->NextValue(info);
156318d3e65eSAxel Dörfler 			values->AddValue(info.Time(), value);
156418d3e65eSAxel Dörfler 		}
156518d3e65eSAxel Dörfler 
1566d4216445SAxel Dörfler 		fSourcesLock.Unlock();
1567d4216445SAxel Dörfler 
15684ce1e1d2SAxel Dörfler 		target.SendMessage(B_INVALIDATE);
156918d3e65eSAxel Dörfler 	}
1570d4216445SAxel Dörfler }
157118d3e65eSAxel Dörfler 
1572d4216445SAxel Dörfler 
1573d4216445SAxel Dörfler /*static*/ status_t
1574d4216445SAxel Dörfler ActivityView::_RefreshThread(void* self)
1575d4216445SAxel Dörfler {
1576d4216445SAxel Dörfler 	((ActivityView*)self)->_Refresh();
1577d4216445SAxel Dörfler 	return B_OK;
1578d4216445SAxel Dörfler }
1579