118d3e65eSAxel Dörfler /* 218d3e65eSAxel Dörfler * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 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> 1218d3e65eSAxel Dörfler 13dc1ffc79SFrançois Revol #ifdef __HAIKU__ 14065e8de0SAxel Dörfler # include <AbstractLayoutItem.h> 15dc1ffc79SFrançois Revol #endif 1618d3e65eSAxel Dörfler #include <Application.h> 17d4216445SAxel Dörfler #include <Autolock.h> 1818d3e65eSAxel Dörfler #include <Bitmap.h> 1918d3e65eSAxel Dörfler #include <Dragger.h> 2018d3e65eSAxel Dörfler #include <MenuItem.h> 2118d3e65eSAxel Dörfler #include <MessageRunner.h> 2218d3e65eSAxel Dörfler #include <PopUpMenu.h> 2318d3e65eSAxel Dörfler #include <String.h> 2418d3e65eSAxel Dörfler 2518d3e65eSAxel Dörfler #include "ActivityMonitor.h" 263f315b26SAxel Dörfler #include "ActivityWindow.h" 2718d3e65eSAxel Dörfler #include "SystemInfo.h" 2874158bb4SFrançois Revol #include "SystemInfoHandler.h" 2918d3e65eSAxel Dörfler 3018d3e65eSAxel Dörfler 3151591198SAxel Dörfler class Scale { 3251591198SAxel Dörfler public: 3351591198SAxel Dörfler Scale(scale_type type); 3451591198SAxel Dörfler 3551591198SAxel Dörfler int64 MinimumValue() const { return fMinimumValue; } 3651591198SAxel Dörfler int64 MaximumValue() const { return fMaximumValue; } 3751591198SAxel Dörfler 3851591198SAxel Dörfler void Update(int64 value); 3951591198SAxel Dörfler 4051591198SAxel Dörfler private: 4151591198SAxel Dörfler scale_type fType; 4251591198SAxel Dörfler int64 fMinimumValue; 4351591198SAxel Dörfler int64 fMaximumValue; 4451591198SAxel Dörfler bool fInitialized; 4551591198SAxel Dörfler }; 4651591198SAxel Dörfler 4718d3e65eSAxel Dörfler struct data_item { 4818d3e65eSAxel Dörfler bigtime_t time; 4918d3e65eSAxel Dörfler int64 value; 5018d3e65eSAxel Dörfler }; 5118d3e65eSAxel Dörfler 52dc1ffc79SFrançois Revol #ifdef __HAIKU__ 53065e8de0SAxel Dörfler class ActivityView::HistoryLayoutItem : public BAbstractLayoutItem { 54065e8de0SAxel Dörfler public: 55065e8de0SAxel Dörfler HistoryLayoutItem(ActivityView* parent); 56065e8de0SAxel Dörfler 57065e8de0SAxel Dörfler virtual bool IsVisible(); 58065e8de0SAxel Dörfler virtual void SetVisible(bool visible); 59065e8de0SAxel Dörfler 60065e8de0SAxel Dörfler virtual BRect Frame(); 61065e8de0SAxel Dörfler virtual void SetFrame(BRect frame); 62065e8de0SAxel Dörfler 63065e8de0SAxel Dörfler virtual BView* View(); 64065e8de0SAxel Dörfler 65065e8de0SAxel Dörfler virtual BSize BasePreferredSize(); 66065e8de0SAxel Dörfler 67065e8de0SAxel Dörfler private: 68065e8de0SAxel Dörfler ActivityView* fParent; 69065e8de0SAxel Dörfler BRect fFrame; 70065e8de0SAxel Dörfler }; 71065e8de0SAxel Dörfler 72065e8de0SAxel Dörfler class ActivityView::LegendLayoutItem : public BAbstractLayoutItem { 73065e8de0SAxel Dörfler public: 74065e8de0SAxel Dörfler LegendLayoutItem(ActivityView* parent); 75065e8de0SAxel Dörfler 76065e8de0SAxel Dörfler virtual bool IsVisible(); 77065e8de0SAxel Dörfler virtual void SetVisible(bool visible); 78065e8de0SAxel Dörfler 79065e8de0SAxel Dörfler virtual BRect Frame(); 80065e8de0SAxel Dörfler virtual void SetFrame(BRect frame); 81065e8de0SAxel Dörfler 82065e8de0SAxel Dörfler virtual BView* View(); 83065e8de0SAxel Dörfler 84065e8de0SAxel Dörfler virtual BSize BaseMinSize(); 85065e8de0SAxel Dörfler virtual BSize BaseMaxSize(); 86065e8de0SAxel Dörfler virtual BSize BasePreferredSize(); 87065e8de0SAxel Dörfler virtual BAlignment BaseAlignment(); 88065e8de0SAxel Dörfler 89065e8de0SAxel Dörfler private: 90065e8de0SAxel Dörfler ActivityView* fParent; 91065e8de0SAxel Dörfler BRect fFrame; 92065e8de0SAxel Dörfler }; 93dc1ffc79SFrançois Revol #endif 94065e8de0SAxel Dörfler 9518d3e65eSAxel Dörfler const bigtime_t kInitialRefreshInterval = 500000LL; 9618d3e65eSAxel Dörfler 9718d3e65eSAxel Dörfler const uint32 kMsgToggleDataSource = 'tgds'; 983a4a2141SAxel Dörfler const uint32 kMsgToggleLegend = 'tglg'; 9918d3e65eSAxel Dörfler 10018d3e65eSAxel Dörfler extern const char* kSignature; 10118d3e65eSAxel Dörfler 10218d3e65eSAxel Dörfler 10351591198SAxel Dörfler Scale::Scale(scale_type type) 10451591198SAxel Dörfler : 10551591198SAxel Dörfler fType(type), 10651591198SAxel Dörfler fMinimumValue(0), 10751591198SAxel Dörfler fMaximumValue(0), 10851591198SAxel Dörfler fInitialized(false) 10951591198SAxel Dörfler { 11051591198SAxel Dörfler } 11151591198SAxel Dörfler 11251591198SAxel Dörfler 11351591198SAxel Dörfler void 11451591198SAxel Dörfler Scale::Update(int64 value) 11551591198SAxel Dörfler { 11651591198SAxel Dörfler if (!fInitialized || fMinimumValue > value) 11751591198SAxel Dörfler fMinimumValue = value; 118*230e3259SAxel Dörfler if (!fInitialized || fMaximumValue < value) 11951591198SAxel Dörfler fMaximumValue = value; 12051591198SAxel Dörfler 12151591198SAxel Dörfler fInitialized = true; 12251591198SAxel Dörfler } 12351591198SAxel Dörfler 12451591198SAxel Dörfler 12551591198SAxel Dörfler // #pragma mark - 12651591198SAxel Dörfler 12751591198SAxel Dörfler 12818d3e65eSAxel Dörfler DataHistory::DataHistory(bigtime_t memorize, bigtime_t interval) 12918d3e65eSAxel Dörfler : 13018d3e65eSAxel Dörfler fBuffer(10000), 13118d3e65eSAxel Dörfler fMinimumValue(0), 13218d3e65eSAxel Dörfler fMaximumValue(0), 13318d3e65eSAxel Dörfler fRefreshInterval(interval), 13451591198SAxel Dörfler fLastIndex(-1), 13551591198SAxel Dörfler fScale(NULL) 13618d3e65eSAxel Dörfler { 13718d3e65eSAxel Dörfler } 13818d3e65eSAxel Dörfler 13918d3e65eSAxel Dörfler 14018d3e65eSAxel Dörfler DataHistory::~DataHistory() 14118d3e65eSAxel Dörfler { 14218d3e65eSAxel Dörfler } 14318d3e65eSAxel Dörfler 14418d3e65eSAxel Dörfler 14518d3e65eSAxel Dörfler void 14618d3e65eSAxel Dörfler DataHistory::AddValue(bigtime_t time, int64 value) 14718d3e65eSAxel Dörfler { 14818d3e65eSAxel Dörfler if (fBuffer.IsEmpty() || fMaximumValue < value) 14918d3e65eSAxel Dörfler fMaximumValue = value; 15018d3e65eSAxel Dörfler if (fBuffer.IsEmpty() || fMinimumValue > value) 15118d3e65eSAxel Dörfler fMinimumValue = value; 15251591198SAxel Dörfler if (fScale != NULL) 15351591198SAxel Dörfler fScale->Update(value); 15418d3e65eSAxel Dörfler 15518d3e65eSAxel Dörfler data_item item = {time, value}; 15618d3e65eSAxel Dörfler fBuffer.AddItem(item); 15718d3e65eSAxel Dörfler } 15818d3e65eSAxel Dörfler 15918d3e65eSAxel Dörfler 16018d3e65eSAxel Dörfler int64 16118d3e65eSAxel Dörfler DataHistory::ValueAt(bigtime_t time) 16218d3e65eSAxel Dörfler { 16351591198SAxel Dörfler int32 left = 0; 16451591198SAxel Dörfler int32 right = fBuffer.CountItems() - 1; 16551591198SAxel Dörfler data_item* item = NULL; 16651591198SAxel Dörfler 16751591198SAxel Dörfler while (left <= right) { 16851591198SAxel Dörfler int32 index = (left + right) / 2; 16951591198SAxel Dörfler item = fBuffer.ItemAt(index); 17051591198SAxel Dörfler 17151591198SAxel Dörfler if (item->time > time) { 17251591198SAxel Dörfler // search in left part 17351591198SAxel Dörfler right = index - 1; 17451591198SAxel Dörfler } else { 17584e23a5dSAxel Dörfler data_item* nextItem = fBuffer.ItemAt(index + 1); 17684e23a5dSAxel Dörfler if (nextItem == NULL) 17784e23a5dSAxel Dörfler return item->value; 17884e23a5dSAxel Dörfler if (nextItem->time > time) { 17951591198SAxel Dörfler // found item 18084e23a5dSAxel Dörfler int64 value = item->value; 18184e23a5dSAxel Dörfler value += int64(double(nextItem->value - value) 18284e23a5dSAxel Dörfler / (nextItem->time - item->time) * (time - item->time)); 18318d3e65eSAxel Dörfler return item->value; 18451591198SAxel Dörfler } 18551591198SAxel Dörfler 18651591198SAxel Dörfler // search in right part 18751591198SAxel Dörfler left = index + 1; 18851591198SAxel Dörfler } 18951591198SAxel Dörfler } 19018d3e65eSAxel Dörfler 19118d3e65eSAxel Dörfler return 0; 19218d3e65eSAxel Dörfler } 19318d3e65eSAxel Dörfler 19418d3e65eSAxel Dörfler 19518d3e65eSAxel Dörfler int64 19618d3e65eSAxel Dörfler DataHistory::MaximumValue() const 19718d3e65eSAxel Dörfler { 19851591198SAxel Dörfler if (fScale != NULL) 19951591198SAxel Dörfler return fScale->MaximumValue(); 20051591198SAxel Dörfler 20118d3e65eSAxel Dörfler return fMaximumValue; 20218d3e65eSAxel Dörfler } 20318d3e65eSAxel Dörfler 20418d3e65eSAxel Dörfler 20518d3e65eSAxel Dörfler int64 20618d3e65eSAxel Dörfler DataHistory::MinimumValue() const 20718d3e65eSAxel Dörfler { 20851591198SAxel Dörfler if (fScale != NULL) 20951591198SAxel Dörfler return fScale->MinimumValue(); 21051591198SAxel Dörfler 21118d3e65eSAxel Dörfler return fMinimumValue; 21218d3e65eSAxel Dörfler } 21318d3e65eSAxel Dörfler 21418d3e65eSAxel Dörfler 21518d3e65eSAxel Dörfler bigtime_t 21618d3e65eSAxel Dörfler DataHistory::Start() const 21718d3e65eSAxel Dörfler { 21818d3e65eSAxel Dörfler if (fBuffer.CountItems() == 0) 21918d3e65eSAxel Dörfler return 0; 22018d3e65eSAxel Dörfler 22118d3e65eSAxel Dörfler return fBuffer.ItemAt(0)->time; 22218d3e65eSAxel Dörfler } 22318d3e65eSAxel Dörfler 22418d3e65eSAxel Dörfler 22518d3e65eSAxel Dörfler bigtime_t 22618d3e65eSAxel Dörfler DataHistory::End() const 22718d3e65eSAxel Dörfler { 22818d3e65eSAxel Dörfler if (fBuffer.CountItems() == 0) 22918d3e65eSAxel Dörfler return 0; 23018d3e65eSAxel Dörfler 23118d3e65eSAxel Dörfler return fBuffer.ItemAt(fBuffer.CountItems() - 1)->time; 23218d3e65eSAxel Dörfler } 23318d3e65eSAxel Dörfler 23418d3e65eSAxel Dörfler 23518d3e65eSAxel Dörfler void 23618d3e65eSAxel Dörfler DataHistory::SetRefreshInterval(bigtime_t interval) 23718d3e65eSAxel Dörfler { 23818d3e65eSAxel Dörfler // TODO: adjust buffer size 23918d3e65eSAxel Dörfler } 24018d3e65eSAxel Dörfler 24118d3e65eSAxel Dörfler 24251591198SAxel Dörfler void 24351591198SAxel Dörfler DataHistory::SetScale(Scale* scale) 24451591198SAxel Dörfler { 24551591198SAxel Dörfler fScale = scale; 24651591198SAxel Dörfler } 24751591198SAxel Dörfler 24851591198SAxel Dörfler 24918d3e65eSAxel Dörfler // #pragma mark - 25018d3e65eSAxel Dörfler 25118d3e65eSAxel Dörfler 252dc1ffc79SFrançois Revol #ifdef __HAIKU__ 253065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::HistoryLayoutItem(ActivityView* parent) 254065e8de0SAxel Dörfler : 255065e8de0SAxel Dörfler fParent(parent), 256065e8de0SAxel Dörfler fFrame() 257065e8de0SAxel Dörfler { 258065e8de0SAxel Dörfler } 259065e8de0SAxel Dörfler 260065e8de0SAxel Dörfler 261065e8de0SAxel Dörfler bool 262065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::IsVisible() 263065e8de0SAxel Dörfler { 264065e8de0SAxel Dörfler return !fParent->IsHidden(fParent); 265065e8de0SAxel Dörfler } 266065e8de0SAxel Dörfler 267065e8de0SAxel Dörfler 268065e8de0SAxel Dörfler void 269065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetVisible(bool visible) 270065e8de0SAxel Dörfler { 271065e8de0SAxel Dörfler // not allowed 272065e8de0SAxel Dörfler } 273065e8de0SAxel Dörfler 274065e8de0SAxel Dörfler 275065e8de0SAxel Dörfler BRect 276065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::Frame() 277065e8de0SAxel Dörfler { 278065e8de0SAxel Dörfler return fFrame; 279065e8de0SAxel Dörfler } 280065e8de0SAxel Dörfler 281065e8de0SAxel Dörfler 282065e8de0SAxel Dörfler void 283065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::SetFrame(BRect frame) 284065e8de0SAxel Dörfler { 285065e8de0SAxel Dörfler fFrame = frame; 286065e8de0SAxel Dörfler fParent->_UpdateFrame(); 287065e8de0SAxel Dörfler } 288065e8de0SAxel Dörfler 289065e8de0SAxel Dörfler 290065e8de0SAxel Dörfler BView* 291065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::View() 292065e8de0SAxel Dörfler { 293065e8de0SAxel Dörfler return fParent; 294065e8de0SAxel Dörfler } 295065e8de0SAxel Dörfler 296065e8de0SAxel Dörfler 297065e8de0SAxel Dörfler BSize 298065e8de0SAxel Dörfler ActivityView::HistoryLayoutItem::BasePreferredSize() 299065e8de0SAxel Dörfler { 300065e8de0SAxel Dörfler BSize size(BaseMaxSize()); 301065e8de0SAxel Dörfler return size; 302065e8de0SAxel Dörfler } 303065e8de0SAxel Dörfler 304065e8de0SAxel Dörfler 305065e8de0SAxel Dörfler // #pragma mark - 306065e8de0SAxel Dörfler 307065e8de0SAxel Dörfler 308065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::LegendLayoutItem(ActivityView* parent) 309065e8de0SAxel Dörfler : 310065e8de0SAxel Dörfler fParent(parent), 311065e8de0SAxel Dörfler fFrame() 312065e8de0SAxel Dörfler { 313065e8de0SAxel Dörfler } 314065e8de0SAxel Dörfler 315065e8de0SAxel Dörfler 316065e8de0SAxel Dörfler bool 317065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::IsVisible() 318065e8de0SAxel Dörfler { 319065e8de0SAxel Dörfler return !fParent->IsHidden(fParent); 320065e8de0SAxel Dörfler } 321065e8de0SAxel Dörfler 322065e8de0SAxel Dörfler 323065e8de0SAxel Dörfler void 324065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetVisible(bool visible) 325065e8de0SAxel Dörfler { 326065e8de0SAxel Dörfler // not allowed 327065e8de0SAxel Dörfler } 328065e8de0SAxel Dörfler 329065e8de0SAxel Dörfler 330065e8de0SAxel Dörfler BRect 331065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::Frame() 332065e8de0SAxel Dörfler { 333065e8de0SAxel Dörfler return fFrame; 334065e8de0SAxel Dörfler } 335065e8de0SAxel Dörfler 336065e8de0SAxel Dörfler 337065e8de0SAxel Dörfler void 338065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::SetFrame(BRect frame) 339065e8de0SAxel Dörfler { 340065e8de0SAxel Dörfler fFrame = frame; 341065e8de0SAxel Dörfler fParent->_UpdateFrame(); 342065e8de0SAxel Dörfler } 343065e8de0SAxel Dörfler 344065e8de0SAxel Dörfler 345065e8de0SAxel Dörfler BView* 346065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::View() 347065e8de0SAxel Dörfler { 348065e8de0SAxel Dörfler return fParent; 349065e8de0SAxel Dörfler } 350065e8de0SAxel Dörfler 351065e8de0SAxel Dörfler 352065e8de0SAxel Dörfler BSize 353065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMinSize() 354065e8de0SAxel Dörfler { 355065e8de0SAxel Dörfler // TODO: Cache the info. Might be too expensive for this call. 356065e8de0SAxel Dörfler BSize size; 357065e8de0SAxel Dörfler size.width = 80; 358065e8de0SAxel Dörfler size.height = fParent->_LegendHeight(); 359065e8de0SAxel Dörfler 360065e8de0SAxel Dörfler return size; 361065e8de0SAxel Dörfler } 362065e8de0SAxel Dörfler 363065e8de0SAxel Dörfler 364065e8de0SAxel Dörfler BSize 365065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseMaxSize() 366065e8de0SAxel Dörfler { 367065e8de0SAxel Dörfler BSize size(BaseMinSize()); 368065e8de0SAxel Dörfler size.width = B_SIZE_UNLIMITED; 369065e8de0SAxel Dörfler return size; 370065e8de0SAxel Dörfler } 371065e8de0SAxel Dörfler 372065e8de0SAxel Dörfler 373065e8de0SAxel Dörfler BSize 374065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BasePreferredSize() 375065e8de0SAxel Dörfler { 376065e8de0SAxel Dörfler BSize size(BaseMinSize()); 377065e8de0SAxel Dörfler return size; 378065e8de0SAxel Dörfler } 379065e8de0SAxel Dörfler 380065e8de0SAxel Dörfler 381065e8de0SAxel Dörfler BAlignment 382065e8de0SAxel Dörfler ActivityView::LegendLayoutItem::BaseAlignment() 383065e8de0SAxel Dörfler { 384065e8de0SAxel Dörfler return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 385065e8de0SAxel Dörfler } 386dc1ffc79SFrançois Revol #endif 387065e8de0SAxel Dörfler 388065e8de0SAxel Dörfler 389065e8de0SAxel Dörfler // #pragma mark - 390065e8de0SAxel Dörfler 391065e8de0SAxel Dörfler 39218d3e65eSAxel Dörfler ActivityView::ActivityView(BRect frame, const char* name, 3933a4a2141SAxel Dörfler const BMessage* settings, uint32 resizingMode) 39418d3e65eSAxel Dörfler : BView(frame, name, resizingMode, 395d4216445SAxel Dörfler B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 396d4216445SAxel Dörfler fSourcesLock("data sources") 39718d3e65eSAxel Dörfler { 3983a4a2141SAxel Dörfler _Init(settings); 3993a4a2141SAxel Dörfler 4003a4a2141SAxel Dörfler BRect rect(Bounds()); 4013a4a2141SAxel Dörfler rect.top = rect.bottom - 7; 4023a4a2141SAxel Dörfler rect.left = rect.right - 7; 4033a4a2141SAxel Dörfler BDragger* dragger = new BDragger(rect, this, 4043a4a2141SAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 4053a4a2141SAxel Dörfler AddChild(dragger); 4063a4a2141SAxel Dörfler } 4073a4a2141SAxel Dörfler 4083a4a2141SAxel Dörfler 4093a4a2141SAxel Dörfler ActivityView::ActivityView(const char* name, const BMessage* settings) 410cbd4bc95SFrançois Revol #ifdef __HAIKU__ 411d4216445SAxel Dörfler : BView(name, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 412cbd4bc95SFrançois Revol #else 413d4216445SAxel Dörfler : BView(BRect(0,0,300,200), name, B_FOLLOW_NONE, 414d4216445SAxel Dörfler B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_FRAME_EVENTS), 415cbd4bc95SFrançois Revol #endif 416d4216445SAxel Dörfler fSourcesLock("data sources") 4173a4a2141SAxel Dörfler { 41879cbd226SFrançois Revol SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 4199c89c450SAxel Dörfler 4203a4a2141SAxel Dörfler _Init(settings); 42118d3e65eSAxel Dörfler 42218d3e65eSAxel Dörfler BRect rect(Bounds()); 42318d3e65eSAxel Dörfler rect.top = rect.bottom - 7; 42418d3e65eSAxel Dörfler rect.left = rect.right - 7; 42518d3e65eSAxel Dörfler BDragger* dragger = new BDragger(rect, this, 42618d3e65eSAxel Dörfler B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 42718d3e65eSAxel Dörfler AddChild(dragger); 42818d3e65eSAxel Dörfler } 42918d3e65eSAxel Dörfler 43018d3e65eSAxel Dörfler 43118d3e65eSAxel Dörfler ActivityView::ActivityView(BMessage* archive) 43218d3e65eSAxel Dörfler : BView(archive) 43318d3e65eSAxel Dörfler { 43418d3e65eSAxel Dörfler _Init(archive); 43518d3e65eSAxel Dörfler } 43618d3e65eSAxel Dörfler 43718d3e65eSAxel Dörfler 43818d3e65eSAxel Dörfler ActivityView::~ActivityView() 43918d3e65eSAxel Dörfler { 4403a4a2141SAxel Dörfler delete fOffscreen; 44174158bb4SFrançois Revol delete fSystemInfoHandler; 44218d3e65eSAxel Dörfler } 44318d3e65eSAxel Dörfler 44418d3e65eSAxel Dörfler 44518d3e65eSAxel Dörfler void 44618d3e65eSAxel Dörfler ActivityView::_Init(const BMessage* settings) 44718d3e65eSAxel Dörfler { 4489c89c450SAxel Dörfler fHistoryBackgroundColor = (rgb_color){255, 255, 240}; 4499c89c450SAxel Dörfler fLegendBackgroundColor = LowColor(); 4509c89c450SAxel Dörfler // the low color is restored by the BView unarchiving 4513a4a2141SAxel Dörfler fOffscreen = NULL; 452dc1ffc79SFrançois Revol #ifdef __HAIKU__ 453065e8de0SAxel Dörfler fHistoryLayoutItem = NULL; 454065e8de0SAxel Dörfler fLegendLayoutItem = NULL; 455dc1ffc79SFrançois Revol #endif 4563a4a2141SAxel Dörfler SetViewColor(B_TRANSPARENT_COLOR); 45718d3e65eSAxel Dörfler 45818d3e65eSAxel Dörfler fRefreshInterval = kInitialRefreshInterval; 45918d3e65eSAxel Dörfler fDrawInterval = kInitialRefreshInterval * 2; 46018d3e65eSAxel Dörfler fLastRefresh = 0; 46118d3e65eSAxel Dörfler fDrawResolution = 1; 46251591198SAxel Dörfler fZooming = false; 46318d3e65eSAxel Dörfler 46474158bb4SFrançois Revol fSystemInfoHandler = new SystemInfoHandler; 46574158bb4SFrançois Revol 4663a4a2141SAxel Dörfler if (settings == NULL 4673a4a2141SAxel Dörfler || settings->FindBool("show legend", &fShowLegend) != B_OK) 4683a4a2141SAxel Dörfler fShowLegend = true; 4693a4a2141SAxel Dörfler 47051591198SAxel Dörfler if (settings == NULL) 4713a4a2141SAxel Dörfler return; 4723a4a2141SAxel Dörfler 4739c89c450SAxel Dörfler ssize_t colorLength; 47479cbd226SFrançois Revol rgb_color *color; 4759c89c450SAxel Dörfler if (settings->FindData("history background color", B_RGB_COLOR_TYPE, 4769c89c450SAxel Dörfler (const void **)&color, &colorLength) == B_OK 4779c89c450SAxel Dörfler && colorLength == sizeof(rgb_color)) 4789c89c450SAxel Dörfler fHistoryBackgroundColor = *color; 47979cbd226SFrançois Revol 4803a4a2141SAxel Dörfler const char* name; 4813a4a2141SAxel Dörfler for (int32 i = 0; settings->FindString("source", i, &name) == B_OK; i++) { 4821201d52eSAxel Dörfler AddDataSource(DataSource::FindSource(name), settings); 4833a4a2141SAxel Dörfler } 48418d3e65eSAxel Dörfler } 48518d3e65eSAxel Dörfler 48618d3e65eSAxel Dörfler 48718d3e65eSAxel Dörfler status_t 48818d3e65eSAxel Dörfler ActivityView::Archive(BMessage* into, bool deep) const 48918d3e65eSAxel Dörfler { 49018d3e65eSAxel Dörfler status_t status; 49118d3e65eSAxel Dörfler 49218d3e65eSAxel Dörfler status = BView::Archive(into, deep); 49318d3e65eSAxel Dörfler if (status < B_OK) 49418d3e65eSAxel Dörfler return status; 49518d3e65eSAxel Dörfler 49618d3e65eSAxel Dörfler status = into->AddString("add_on", kSignature); 49718d3e65eSAxel Dörfler if (status < B_OK) 49818d3e65eSAxel Dörfler return status; 49918d3e65eSAxel Dörfler 50018d3e65eSAxel Dörfler status = SaveState(*into); 50118d3e65eSAxel Dörfler if (status < B_OK) 50218d3e65eSAxel Dörfler return status; 50318d3e65eSAxel Dörfler 50418d3e65eSAxel Dörfler return B_OK; 50518d3e65eSAxel Dörfler } 50618d3e65eSAxel Dörfler 50718d3e65eSAxel Dörfler 50818d3e65eSAxel Dörfler BArchivable* 50918d3e65eSAxel Dörfler ActivityView::Instantiate(BMessage* archive) 51018d3e65eSAxel Dörfler { 51118d3e65eSAxel Dörfler if (!validate_instantiation(archive, "ActivityView")) 51218d3e65eSAxel Dörfler return NULL; 51318d3e65eSAxel Dörfler 51418d3e65eSAxel Dörfler return new ActivityView(archive); 51518d3e65eSAxel Dörfler } 51618d3e65eSAxel Dörfler 51718d3e65eSAxel Dörfler 51818d3e65eSAxel Dörfler status_t 51918d3e65eSAxel Dörfler ActivityView::SaveState(BMessage& state) const 52018d3e65eSAxel Dörfler { 5213a4a2141SAxel Dörfler status_t status = state.AddBool("show legend", fShowLegend); 5223a4a2141SAxel Dörfler if (status != B_OK) 5233a4a2141SAxel Dörfler return status; 5243a4a2141SAxel Dörfler 5259c89c450SAxel Dörfler status = state.AddData("history background color", B_RGB_COLOR_TYPE, 5269c89c450SAxel Dörfler &fHistoryBackgroundColor, sizeof(rgb_color)); 52779cbd226SFrançois Revol if (status != B_OK) 52879cbd226SFrançois Revol return status; 52979cbd226SFrançois Revol 5303a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 5313a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i); 5323a4a2141SAxel Dörfler 5333a4a2141SAxel Dörfler if (!source->PerCPU() || source->CPU() == 0) 5343a4a2141SAxel Dörfler status = state.AddString("source", source->Name()); 5353a4a2141SAxel Dörfler if (status != B_OK) 5363a4a2141SAxel Dörfler return status; 5373a4a2141SAxel Dörfler 5389c89c450SAxel Dörfler BString name = source->Name(); 5399c89c450SAxel Dörfler name << " color"; 5409c89c450SAxel Dörfler rgb_color color = source->Color(); 5419c89c450SAxel Dörfler state.AddData(name.String(), B_RGB_COLOR_TYPE, &color, 5429c89c450SAxel Dörfler sizeof(rgb_color)); 5433a4a2141SAxel Dörfler } 5443a4a2141SAxel Dörfler return B_OK; 54518d3e65eSAxel Dörfler } 54618d3e65eSAxel Dörfler 54718d3e65eSAxel Dörfler 54851591198SAxel Dörfler Scale* 54951591198SAxel Dörfler ActivityView::_ScaleFor(scale_type type) 55051591198SAxel Dörfler { 55151591198SAxel Dörfler if (type == kNoScale) 55251591198SAxel Dörfler return NULL; 55351591198SAxel Dörfler 55451591198SAxel Dörfler std::map<scale_type, ::Scale*>::iterator iterator = fScales.find(type); 55551591198SAxel Dörfler if (iterator != fScales.end()) 55651591198SAxel Dörfler return iterator->second; 55751591198SAxel Dörfler 55851591198SAxel Dörfler // add new scale 55951591198SAxel Dörfler ::Scale* scale = new ::Scale(type); 56051591198SAxel Dörfler fScales[type] = scale; 56151591198SAxel Dörfler 56251591198SAxel Dörfler return scale; 56351591198SAxel Dörfler } 56451591198SAxel Dörfler 56551591198SAxel Dörfler 566dc1ffc79SFrançois Revol #ifdef __HAIKU__ 567065e8de0SAxel Dörfler BLayoutItem* 568065e8de0SAxel Dörfler ActivityView::CreateHistoryLayoutItem() 569065e8de0SAxel Dörfler { 570065e8de0SAxel Dörfler if (fHistoryLayoutItem == NULL) 571065e8de0SAxel Dörfler fHistoryLayoutItem = new HistoryLayoutItem(this); 572065e8de0SAxel Dörfler 573065e8de0SAxel Dörfler return fHistoryLayoutItem; 574065e8de0SAxel Dörfler } 575065e8de0SAxel Dörfler 576065e8de0SAxel Dörfler 577065e8de0SAxel Dörfler BLayoutItem* 578065e8de0SAxel Dörfler ActivityView::CreateLegendLayoutItem() 579065e8de0SAxel Dörfler { 580065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL) 581065e8de0SAxel Dörfler fLegendLayoutItem = new LegendLayoutItem(this); 582065e8de0SAxel Dörfler 583065e8de0SAxel Dörfler return fLegendLayoutItem; 584065e8de0SAxel Dörfler } 585dc1ffc79SFrançois Revol #endif 586065e8de0SAxel Dörfler 5879c89c450SAxel Dörfler 58818d3e65eSAxel Dörfler DataSource* 5893a4a2141SAxel Dörfler ActivityView::FindDataSource(const DataSource* search) 59018d3e65eSAxel Dörfler { 591d4216445SAxel Dörfler BAutolock _(fSourcesLock); 592d4216445SAxel Dörfler 59318d3e65eSAxel Dörfler for (int32 i = fSources.CountItems(); i-- > 0;) { 59418d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 5953a4a2141SAxel Dörfler if (!strcmp(source->Name(), search->Name())) 59618d3e65eSAxel Dörfler return source; 59718d3e65eSAxel Dörfler } 59818d3e65eSAxel Dörfler 59918d3e65eSAxel Dörfler return NULL; 60018d3e65eSAxel Dörfler } 60118d3e65eSAxel Dörfler 60218d3e65eSAxel Dörfler 60318d3e65eSAxel Dörfler status_t 6049c89c450SAxel Dörfler ActivityView::AddDataSource(const DataSource* source, const BMessage* state) 60518d3e65eSAxel Dörfler { 6063a4a2141SAxel Dörfler if (source == NULL) 6073a4a2141SAxel Dörfler return B_BAD_VALUE; 6083a4a2141SAxel Dörfler 609d4216445SAxel Dörfler BAutolock _(fSourcesLock); 610d4216445SAxel Dörfler 6113a4a2141SAxel Dörfler int32 insert = DataSource::IndexOf(source); 6123a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems() && i < insert; i++) { 6133a4a2141SAxel Dörfler DataSource* before = fSources.ItemAt(i); 6143a4a2141SAxel Dörfler if (DataSource::IndexOf(before) > insert) { 6153a4a2141SAxel Dörfler insert = i; 6163a4a2141SAxel Dörfler break; 6173a4a2141SAxel Dörfler } 6183a4a2141SAxel Dörfler } 6193a4a2141SAxel Dörfler if (insert > fSources.CountItems()) 6203a4a2141SAxel Dörfler insert = fSources.CountItems(); 6213a4a2141SAxel Dörfler 6223a4a2141SAxel Dörfler uint32 count = 1; 6233a4a2141SAxel Dörfler if (source->PerCPU()) { 6243a4a2141SAxel Dörfler SystemInfo info; 6253a4a2141SAxel Dörfler count = info.CPUCount(); 6263a4a2141SAxel Dörfler } 6273a4a2141SAxel Dörfler 6283a4a2141SAxel Dörfler for (uint32 i = 0; i < count; i++) { 62918d3e65eSAxel Dörfler DataHistory* values = new(std::nothrow) DataHistory(10 * 60000000LL, 63018d3e65eSAxel Dörfler fRefreshInterval); 63118d3e65eSAxel Dörfler if (values == NULL) 63218d3e65eSAxel Dörfler return B_NO_MEMORY; 6333a4a2141SAxel Dörfler 6343a4a2141SAxel Dörfler if (!fValues.AddItem(values, insert + i)) { 63518d3e65eSAxel Dörfler delete values; 63618d3e65eSAxel Dörfler return B_NO_MEMORY; 63718d3e65eSAxel Dörfler } 63818d3e65eSAxel Dörfler 63951591198SAxel Dörfler values->SetScale(_ScaleFor(source->ScaleType())); 64051591198SAxel Dörfler 6413a4a2141SAxel Dörfler DataSource* copy; 6423a4a2141SAxel Dörfler if (source->PerCPU()) 6433a4a2141SAxel Dörfler copy = source->CopyForCPU(i); 6443a4a2141SAxel Dörfler else 6453a4a2141SAxel Dörfler copy = source->Copy(); 6463a4a2141SAxel Dörfler 6479c89c450SAxel Dörfler BString colorName = source->Name(); 6489c89c450SAxel Dörfler colorName << " color"; 6499c89c450SAxel Dörfler if (state != NULL) { 6509c89c450SAxel Dörfler const rgb_color* color = NULL; 6519c89c450SAxel Dörfler ssize_t colorLength; 6529c89c450SAxel Dörfler if (state->FindData(colorName.String(), B_RGB_COLOR_TYPE, i, 6539c89c450SAxel Dörfler (const void**)&color, &colorLength) == B_OK 6549c89c450SAxel Dörfler && colorLength == sizeof(rgb_color)) 6559c89c450SAxel Dörfler copy->SetColor(*color); 6569c89c450SAxel Dörfler } 6579c89c450SAxel Dörfler 6583a4a2141SAxel Dörfler if (!fSources.AddItem(copy, insert + i)) { 65918d3e65eSAxel Dörfler fValues.RemoveItem(values); 66018d3e65eSAxel Dörfler delete values; 66118d3e65eSAxel Dörfler return B_NO_MEMORY; 66218d3e65eSAxel Dörfler } 6633a4a2141SAxel Dörfler } 66418d3e65eSAxel Dörfler 665dc1ffc79SFrançois Revol #ifdef __HAIKU__ 666065e8de0SAxel Dörfler InvalidateLayout(); 667dc1ffc79SFrançois Revol #endif 66818d3e65eSAxel Dörfler return B_OK; 66918d3e65eSAxel Dörfler } 67018d3e65eSAxel Dörfler 67118d3e65eSAxel Dörfler 67218d3e65eSAxel Dörfler status_t 6733a4a2141SAxel Dörfler ActivityView::RemoveDataSource(const DataSource* remove) 67418d3e65eSAxel Dörfler { 675065e8de0SAxel Dörfler bool removed = false; 676065e8de0SAxel Dörfler 677d4216445SAxel Dörfler BAutolock _(fSourcesLock); 678d4216445SAxel Dörfler 6793a4a2141SAxel Dörfler while (true) { 6803a4a2141SAxel Dörfler DataSource* source = FindDataSource(remove); 6819c89c450SAxel Dörfler debug_printf("SEARCH %s, found %p\n", remove->Name(), source); 682065e8de0SAxel Dörfler if (source == NULL) { 683065e8de0SAxel Dörfler if (removed) 684065e8de0SAxel Dörfler break; 685065e8de0SAxel Dörfler return B_ENTRY_NOT_FOUND; 686065e8de0SAxel Dörfler } 6873a4a2141SAxel Dörfler 68818d3e65eSAxel Dörfler int32 index = fSources.IndexOf(source); 68918d3e65eSAxel Dörfler if (index < 0) 69018d3e65eSAxel Dörfler return B_ENTRY_NOT_FOUND; 69118d3e65eSAxel Dörfler 69218d3e65eSAxel Dörfler fSources.RemoveItemAt(index); 69318d3e65eSAxel Dörfler delete source; 69418d3e65eSAxel Dörfler DataHistory* values = fValues.RemoveItemAt(index); 69518d3e65eSAxel Dörfler delete values; 696065e8de0SAxel Dörfler removed = true; 6973a4a2141SAxel Dörfler } 69818d3e65eSAxel Dörfler 699dc1ffc79SFrançois Revol #ifdef __HAIKU__ 700065e8de0SAxel Dörfler InvalidateLayout(); 701dc1ffc79SFrançois Revol #endif 70218d3e65eSAxel Dörfler return B_OK; 70318d3e65eSAxel Dörfler } 70418d3e65eSAxel Dörfler 70518d3e65eSAxel Dörfler 70618d3e65eSAxel Dörfler void 70718d3e65eSAxel Dörfler ActivityView::RemoveAllDataSources() 70818d3e65eSAxel Dörfler { 709d4216445SAxel Dörfler BAutolock _(fSourcesLock); 710d4216445SAxel Dörfler 71118d3e65eSAxel Dörfler fSources.MakeEmpty(); 71218d3e65eSAxel Dörfler fValues.MakeEmpty(); 71318d3e65eSAxel Dörfler } 71418d3e65eSAxel Dörfler 71518d3e65eSAxel Dörfler 71618d3e65eSAxel Dörfler void 71718d3e65eSAxel Dörfler ActivityView::AttachedToWindow() 71818d3e65eSAxel Dörfler { 71974158bb4SFrançois Revol Looper()->AddHandler(fSystemInfoHandler); 7206f6ba875SAxel Dörfler fSystemInfoHandler->StartWatching(); 7216f6ba875SAxel Dörfler 722d4216445SAxel Dörfler fRefreshSem = create_sem(0, "refresh sem"); 723d4216445SAxel Dörfler fRefreshThread = spawn_thread(&_RefreshThread, "source refresh", 724d4216445SAxel Dörfler B_NORMAL_PRIORITY, this); 725d4216445SAxel Dörfler resume_thread(fRefreshThread); 7263a4a2141SAxel Dörfler 7273a4a2141SAxel Dörfler FrameResized(Bounds().Width(), Bounds().Height()); 72818d3e65eSAxel Dörfler } 72918d3e65eSAxel Dörfler 73018d3e65eSAxel Dörfler 73118d3e65eSAxel Dörfler void 73218d3e65eSAxel Dörfler ActivityView::DetachedFromWindow() 73318d3e65eSAxel Dörfler { 7346f6ba875SAxel Dörfler fSystemInfoHandler->StopWatching(); 73574158bb4SFrançois Revol Looper()->RemoveHandler(fSystemInfoHandler); 7366f6ba875SAxel Dörfler 737d4216445SAxel Dörfler delete_sem(fRefreshSem); 738d4216445SAxel Dörfler wait_for_thread(fRefreshThread, NULL); 73918d3e65eSAxel Dörfler } 74018d3e65eSAxel Dörfler 74118d3e65eSAxel Dörfler 742cbd4bc95SFrançois Revol #ifdef __HAIKU__ 7433a4a2141SAxel Dörfler BSize 7443a4a2141SAxel Dörfler ActivityView::MinSize() 7453a4a2141SAxel Dörfler { 7463a4a2141SAxel Dörfler BSize size(32, 32); 7473a4a2141SAxel Dörfler if (fShowLegend) 7489c89c450SAxel Dörfler size.height = _LegendHeight(); 7493a4a2141SAxel Dörfler 7503a4a2141SAxel Dörfler return size; 7513a4a2141SAxel Dörfler } 752cbd4bc95SFrançois Revol #endif 7533a4a2141SAxel Dörfler 7543a4a2141SAxel Dörfler 75518d3e65eSAxel Dörfler void 75618d3e65eSAxel Dörfler ActivityView::FrameResized(float /*width*/, float /*height*/) 75718d3e65eSAxel Dörfler { 7583a4a2141SAxel Dörfler _UpdateOffscreenBitmap(); 7593a4a2141SAxel Dörfler } 7603a4a2141SAxel Dörfler 7613a4a2141SAxel Dörfler 7623a4a2141SAxel Dörfler void 7639c89c450SAxel Dörfler ActivityView::_UpdateOffscreenBitmap() 7643a4a2141SAxel Dörfler { 7653a4a2141SAxel Dörfler BRect frame = _HistoryFrame(); 7669c89c450SAxel Dörfler if (fOffscreen != NULL && frame == fOffscreen->Bounds()) 7673a4a2141SAxel Dörfler return; 7683a4a2141SAxel Dörfler 7693a4a2141SAxel Dörfler delete fOffscreen; 7703a4a2141SAxel Dörfler 7713a4a2141SAxel Dörfler // create offscreen bitmap 7723a4a2141SAxel Dörfler 7733a4a2141SAxel Dörfler fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS, 7743a4a2141SAxel Dörfler B_RGB32); 7753a4a2141SAxel Dörfler if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) { 7763a4a2141SAxel Dörfler delete fOffscreen; 7773a4a2141SAxel Dörfler fOffscreen = NULL; 7783a4a2141SAxel Dörfler return; 7793a4a2141SAxel Dörfler } 7803a4a2141SAxel Dörfler 7813a4a2141SAxel Dörfler BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE); 7829c89c450SAxel Dörfler view->SetViewColor(fHistoryBackgroundColor); 7833a4a2141SAxel Dörfler view->SetLowColor(view->ViewColor()); 7843a4a2141SAxel Dörfler fOffscreen->AddChild(view); 78518d3e65eSAxel Dörfler } 78618d3e65eSAxel Dörfler 78718d3e65eSAxel Dörfler 7889c89c450SAxel Dörfler BView* 7899c89c450SAxel Dörfler ActivityView::_OffscreenView() 7909c89c450SAxel Dörfler { 7919c89c450SAxel Dörfler if (fOffscreen == NULL) 7929c89c450SAxel Dörfler return NULL; 7939c89c450SAxel Dörfler 7949c89c450SAxel Dörfler return fOffscreen->ChildAt(0); 7959c89c450SAxel Dörfler } 7969c89c450SAxel Dörfler 7979c89c450SAxel Dörfler 79818d3e65eSAxel Dörfler void 79918d3e65eSAxel Dörfler ActivityView::MouseDown(BPoint where) 80018d3e65eSAxel Dörfler { 80151591198SAxel Dörfler int32 buttons = B_SECONDARY_MOUSE_BUTTON; 80251591198SAxel Dörfler if (Looper() != NULL && Looper()->CurrentMessage() != NULL) 80318d3e65eSAxel Dörfler Looper()->CurrentMessage()->FindInt32("buttons", &buttons); 80451591198SAxel Dörfler 80551591198SAxel Dörfler if (buttons == B_PRIMARY_MOUSE_BUTTON) { 80651591198SAxel Dörfler fZoomPoint = where; 80751591198SAxel Dörfler fOriginalResolution = fDrawResolution; 80851591198SAxel Dörfler fZooming = true; 80951591198SAxel Dörfler return; 81018d3e65eSAxel Dörfler } 81118d3e65eSAxel Dörfler 81218d3e65eSAxel Dörfler BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING, false, false); 81318d3e65eSAxel Dörfler menu->SetFont(be_plain_font); 8143a4a2141SAxel Dörfler 81543eda1cdSAxel Dörfler BMenu* additionalMenu = new BMenu("Additional Items"); 816dc1ffc79SFrançois Revol additionalMenu->SetFont(be_plain_font); 817dc1ffc79SFrançois Revol 8183a4a2141SAxel Dörfler SystemInfo info; 81918d3e65eSAxel Dörfler BMenuItem* item; 82018d3e65eSAxel Dörfler 82118d3e65eSAxel Dörfler for (int32 i = 0; i < DataSource::CountSources(); i++) { 82218d3e65eSAxel Dörfler const DataSource* source = DataSource::SourceAt(i); 82318d3e65eSAxel Dörfler 8243a4a2141SAxel Dörfler if (source->MultiCPUOnly() && info.CPUCount() == 1) 8253a4a2141SAxel Dörfler continue; 8263a4a2141SAxel Dörfler 82718d3e65eSAxel Dörfler BMessage* message = new BMessage(kMsgToggleDataSource); 82818d3e65eSAxel Dörfler message->AddInt32("index", i); 82918d3e65eSAxel Dörfler 8303a4a2141SAxel Dörfler item = new BMenuItem(source->Name(), message); 8313a4a2141SAxel Dörfler if (FindDataSource(source)) 83218d3e65eSAxel Dörfler item->SetMarked(true); 83318d3e65eSAxel Dörfler 83443eda1cdSAxel Dörfler if (source->Primary()) 83518d3e65eSAxel Dörfler menu->AddItem(item); 83643eda1cdSAxel Dörfler else 83743eda1cdSAxel Dörfler additionalMenu->AddItem(item); 83818d3e65eSAxel Dörfler } 83918d3e65eSAxel Dörfler 84043eda1cdSAxel Dörfler menu->AddItem(new BMenuItem(additionalMenu)); 8413a4a2141SAxel Dörfler menu->AddSeparatorItem(); 8423a4a2141SAxel Dörfler menu->AddItem(new BMenuItem(fShowLegend ? "Hide Legend" : "Show Legend", 8433a4a2141SAxel Dörfler new BMessage(kMsgToggleLegend))); 8443a4a2141SAxel Dörfler 84518d3e65eSAxel Dörfler menu->SetTargetForItems(this); 846dc1ffc79SFrançois Revol additionalMenu->SetTargetForItems(this); 84718d3e65eSAxel Dörfler 8483f315b26SAxel Dörfler ActivityWindow* window = dynamic_cast<ActivityWindow*>(Window()); 8493f315b26SAxel Dörfler if (window != NULL && window->ActivityViewCount() > 1) { 8503f315b26SAxel Dörfler menu->AddSeparatorItem(); 8513f315b26SAxel Dörfler BMessage* message = new BMessage(kMsgRemoveView); 8523f315b26SAxel Dörfler message->AddPointer("view", this); 8533f315b26SAxel Dörfler menu->AddItem(item = new BMenuItem("Remove View", message)); 8543f315b26SAxel Dörfler item->SetTarget(window); 8553f315b26SAxel Dörfler } 8563f315b26SAxel Dörfler 85718d3e65eSAxel Dörfler ConvertToScreen(&where); 85818d3e65eSAxel Dörfler menu->Go(where, true, false, true); 85918d3e65eSAxel Dörfler 86018d3e65eSAxel Dörfler } 86118d3e65eSAxel Dörfler 86218d3e65eSAxel Dörfler 86318d3e65eSAxel Dörfler void 86451591198SAxel Dörfler ActivityView::MouseUp(BPoint where) 86551591198SAxel Dörfler { 86651591198SAxel Dörfler fZooming = false; 86751591198SAxel Dörfler } 86851591198SAxel Dörfler 86951591198SAxel Dörfler 87051591198SAxel Dörfler void 87118d3e65eSAxel Dörfler ActivityView::MouseMoved(BPoint where, uint32 transit, 87218d3e65eSAxel Dörfler const BMessage* dragMessage) 87318d3e65eSAxel Dörfler { 87451591198SAxel Dörfler if (!fZooming) 87551591198SAxel Dörfler return; 87651591198SAxel Dörfler 87751591198SAxel Dörfler int32 previousResolution = fDrawResolution; 87851591198SAxel Dörfler 87951591198SAxel Dörfler int32 shift = int32(where.x - fZoomPoint.x) / 25; 88051591198SAxel Dörfler if (shift > 0) 88151591198SAxel Dörfler fDrawResolution = fOriginalResolution << shift; 88251591198SAxel Dörfler else 88351591198SAxel Dörfler fDrawResolution = fOriginalResolution >> -shift; 88451591198SAxel Dörfler 88551591198SAxel Dörfler if (fDrawResolution < 1) 88651591198SAxel Dörfler fDrawResolution = 1; 88751591198SAxel Dörfler if (fDrawResolution > 128) 88851591198SAxel Dörfler fDrawResolution = 128; 88951591198SAxel Dörfler 89051591198SAxel Dörfler if (previousResolution != fDrawResolution) 89151591198SAxel Dörfler Invalidate(); 89218d3e65eSAxel Dörfler } 89318d3e65eSAxel Dörfler 89418d3e65eSAxel Dörfler 89518d3e65eSAxel Dörfler void 89618d3e65eSAxel Dörfler ActivityView::MessageReceived(BMessage* message) 89718d3e65eSAxel Dörfler { 898c28f8ea3SFrançois Revol // if a color is dropped, use it as background 899c28f8ea3SFrançois Revol if (message->WasDropped()) { 900c28f8ea3SFrançois Revol rgb_color* color; 901c28f8ea3SFrançois Revol ssize_t size; 9021201d52eSAxel Dörfler if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0, 9031201d52eSAxel Dörfler (const void**)&color, &size) == B_OK 9049c89c450SAxel Dörfler && size == sizeof(rgb_color)) { 9059c89c450SAxel Dörfler BPoint dropPoint = message->DropPoint(); 906c28f8ea3SFrançois Revol ConvertFromScreen(&dropPoint); 9079c89c450SAxel Dörfler 908c28f8ea3SFrançois Revol if (_HistoryFrame().Contains(dropPoint)) { 9099c89c450SAxel Dörfler fHistoryBackgroundColor = *color; 9109c89c450SAxel Dörfler Invalidate(_HistoryFrame()); 911c28f8ea3SFrançois Revol } else { 9125f2f72a2SFrançois Revol // check each legend color box 913d4216445SAxel Dörfler BAutolock _(fSourcesLock); 914d4216445SAxel Dörfler 9155f2f72a2SFrançois Revol BRect legendFrame = _LegendFrame(); 9169c89c450SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 9171201d52eSAxel Dörfler BRect frame = _LegendColorFrameAt(legendFrame, i); 9189c89c450SAxel Dörfler if (frame.Contains(dropPoint)) { 9195f2f72a2SFrançois Revol fSources.ItemAt(i)->SetColor(*color); 9209c89c450SAxel Dörfler Invalidate(_HistoryFrame()); 9211201d52eSAxel Dörfler Invalidate(frame); 9225f2f72a2SFrançois Revol return; 9235f2f72a2SFrançois Revol } 9245f2f72a2SFrançois Revol } 9259c89c450SAxel Dörfler 9269c89c450SAxel Dörfler if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) { 9279c89c450SAxel Dörfler // allow background color change in the replicant only 9289c89c450SAxel Dörfler fLegendBackgroundColor = *color; 9291201d52eSAxel Dörfler SetLowColor(fLegendBackgroundColor); 9309c89c450SAxel Dörfler Invalidate(legendFrame); 9319c89c450SAxel Dörfler } 932c28f8ea3SFrançois Revol } 933c28f8ea3SFrançois Revol return; 934c28f8ea3SFrançois Revol } 9359c89c450SAxel Dörfler } 9369c89c450SAxel Dörfler 93718d3e65eSAxel Dörfler switch (message->what) { 93818d3e65eSAxel Dörfler case B_ABOUT_REQUESTED: 93918d3e65eSAxel Dörfler ActivityMonitor::ShowAbout(); 94018d3e65eSAxel Dörfler break; 94118d3e65eSAxel Dörfler 94218d3e65eSAxel Dörfler case kMsgToggleDataSource: 94318d3e65eSAxel Dörfler { 94418d3e65eSAxel Dörfler int32 index; 94518d3e65eSAxel Dörfler if (message->FindInt32("index", &index) != B_OK) 94618d3e65eSAxel Dörfler break; 94718d3e65eSAxel Dörfler 94818d3e65eSAxel Dörfler const DataSource* baseSource = DataSource::SourceAt(index); 94918d3e65eSAxel Dörfler if (baseSource == NULL) 95018d3e65eSAxel Dörfler break; 95118d3e65eSAxel Dörfler 9523a4a2141SAxel Dörfler DataSource* source = FindDataSource(baseSource); 95318d3e65eSAxel Dörfler if (source == NULL) 9543a4a2141SAxel Dörfler AddDataSource(baseSource); 95518d3e65eSAxel Dörfler else 95618d3e65eSAxel Dörfler RemoveDataSource(source); 95718d3e65eSAxel Dörfler 95818d3e65eSAxel Dörfler Invalidate(); 95918d3e65eSAxel Dörfler break; 96018d3e65eSAxel Dörfler } 96118d3e65eSAxel Dörfler 9623a4a2141SAxel Dörfler case kMsgToggleLegend: 9633a4a2141SAxel Dörfler fShowLegend = !fShowLegend; 9643a4a2141SAxel Dörfler Invalidate(); 9653a4a2141SAxel Dörfler break; 9663a4a2141SAxel Dörfler 96718d3e65eSAxel Dörfler case B_MOUSE_WHEEL_CHANGED: 96818d3e65eSAxel Dörfler { 96918d3e65eSAxel Dörfler float deltaY = 0.0f; 97018d3e65eSAxel Dörfler if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK 97118d3e65eSAxel Dörfler || deltaY == 0.0f) 97218d3e65eSAxel Dörfler break; 97318d3e65eSAxel Dörfler 97418d3e65eSAxel Dörfler if (deltaY > 0) 97518d3e65eSAxel Dörfler fDrawResolution *= 2; 97618d3e65eSAxel Dörfler else 97718d3e65eSAxel Dörfler fDrawResolution /= 2; 97818d3e65eSAxel Dörfler 97918d3e65eSAxel Dörfler if (fDrawResolution < 1) 98018d3e65eSAxel Dörfler fDrawResolution = 1; 98118d3e65eSAxel Dörfler if (fDrawResolution > 128) 98218d3e65eSAxel Dörfler fDrawResolution = 128; 98318d3e65eSAxel Dörfler 98418d3e65eSAxel Dörfler Invalidate(); 98518d3e65eSAxel Dörfler break; 98618d3e65eSAxel Dörfler } 98718d3e65eSAxel Dörfler 98818d3e65eSAxel Dörfler default: 98918d3e65eSAxel Dörfler BView::MessageReceived(message); 99018d3e65eSAxel Dörfler break; 99118d3e65eSAxel Dörfler } 99218d3e65eSAxel Dörfler } 99318d3e65eSAxel Dörfler 99418d3e65eSAxel Dörfler 995065e8de0SAxel Dörfler void 996065e8de0SAxel Dörfler ActivityView::_UpdateFrame() 997065e8de0SAxel Dörfler { 998dc1ffc79SFrançois Revol #ifdef __HAIKU__ 999065e8de0SAxel Dörfler if (fLegendLayoutItem == NULL || fHistoryLayoutItem == NULL) 1000065e8de0SAxel Dörfler return; 1001065e8de0SAxel Dörfler 1002065e8de0SAxel Dörfler BRect historyFrame = fHistoryLayoutItem->Frame(); 1003065e8de0SAxel Dörfler BRect legendFrame = fLegendLayoutItem->Frame(); 1004dc1ffc79SFrançois Revol #else 1005dc1ffc79SFrançois Revol BRect historyFrame = Bounds(); 1006dc1ffc79SFrançois Revol BRect legendFrame = Bounds(); 1007dc1ffc79SFrançois Revol historyFrame.bottom -= 2 * Bounds().Height() / 3; 1008dc1ffc79SFrançois Revol legendFrame.top += Bounds().Height() / 3; 1009dc1ffc79SFrançois Revol #endif 1010065e8de0SAxel Dörfler MoveTo(historyFrame.left, historyFrame.top); 1011065e8de0SAxel Dörfler ResizeTo(legendFrame.left + legendFrame.Width() - historyFrame.left, 1012065e8de0SAxel Dörfler legendFrame.top + legendFrame.Height() - historyFrame.top); 1013065e8de0SAxel Dörfler } 1014065e8de0SAxel Dörfler 1015065e8de0SAxel Dörfler 10163a4a2141SAxel Dörfler BRect 10173a4a2141SAxel Dörfler ActivityView::_HistoryFrame() const 10183a4a2141SAxel Dörfler { 10193a4a2141SAxel Dörfler if (!fShowLegend) 10203a4a2141SAxel Dörfler return Bounds(); 10213a4a2141SAxel Dörfler 10223a4a2141SAxel Dörfler BRect frame = Bounds(); 10233a4a2141SAxel Dörfler BRect legendFrame = _LegendFrame(); 10243a4a2141SAxel Dörfler 10253a4a2141SAxel Dörfler frame.bottom = legendFrame.top - 1; 10263a4a2141SAxel Dörfler 10273a4a2141SAxel Dörfler return frame; 10283a4a2141SAxel Dörfler } 10293a4a2141SAxel Dörfler 10303a4a2141SAxel Dörfler 1031065e8de0SAxel Dörfler float 1032065e8de0SAxel Dörfler ActivityView::_LegendHeight() const 10333a4a2141SAxel Dörfler { 10343a4a2141SAxel Dörfler font_height fontHeight; 10353a4a2141SAxel Dörfler GetFontHeight(&fontHeight); 10363a4a2141SAxel Dörfler 1037d4216445SAxel Dörfler BAutolock _(fSourcesLock); 1038d4216445SAxel Dörfler 10393a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2; 1040065e8de0SAxel Dörfler return rows * (4 + ceilf(fontHeight.ascent) 10413a4a2141SAxel Dörfler + ceilf(fontHeight.descent) + ceilf(fontHeight.leading)); 1042065e8de0SAxel Dörfler } 1043065e8de0SAxel Dörfler 1044065e8de0SAxel Dörfler 1045065e8de0SAxel Dörfler BRect 1046065e8de0SAxel Dörfler ActivityView::_LegendFrame() const 1047065e8de0SAxel Dörfler { 1048065e8de0SAxel Dörfler float height; 1049dc1ffc79SFrançois Revol #ifdef __HAIKU__ 1050065e8de0SAxel Dörfler if (fLegendLayoutItem != NULL) 1051065e8de0SAxel Dörfler height = fLegendLayoutItem->Frame().Height(); 1052065e8de0SAxel Dörfler else 1053dc1ffc79SFrançois Revol #endif 1054065e8de0SAxel Dörfler height = _LegendHeight(); 1055065e8de0SAxel Dörfler 1056065e8de0SAxel Dörfler BRect frame = Bounds(); 1057065e8de0SAxel Dörfler frame.top = frame.bottom - height; 10583a4a2141SAxel Dörfler 10593a4a2141SAxel Dörfler return frame; 10603a4a2141SAxel Dörfler } 10613a4a2141SAxel Dörfler 10623a4a2141SAxel Dörfler 10633a4a2141SAxel Dörfler BRect 10643a4a2141SAxel Dörfler ActivityView::_LegendFrameAt(BRect frame, int32 index) const 10653a4a2141SAxel Dörfler { 10663a4a2141SAxel Dörfler int32 column = index & 1; 10673a4a2141SAxel Dörfler int32 row = index / 2; 10683a4a2141SAxel Dörfler if (column == 0) 10693a4a2141SAxel Dörfler frame.right = frame.left + floorf(frame.Width() / 2) - 5; 10703a4a2141SAxel Dörfler else 10713a4a2141SAxel Dörfler frame.left = frame.right - floorf(frame.Width() / 2) + 5; 10723a4a2141SAxel Dörfler 1073d4216445SAxel Dörfler BAutolock _(fSourcesLock); 1074d4216445SAxel Dörfler 10753a4a2141SAxel Dörfler int32 rows = (fSources.CountItems() + 1) / 2; 10763a4a2141SAxel Dörfler float height = floorf((frame.Height() - 5) / rows); 10773a4a2141SAxel Dörfler 10783a4a2141SAxel Dörfler frame.top = frame.top + 5 + row * height; 10793a4a2141SAxel Dörfler frame.bottom = frame.top + height - 1; 10803a4a2141SAxel Dörfler 10813a4a2141SAxel Dörfler return frame; 10823a4a2141SAxel Dörfler } 10833a4a2141SAxel Dörfler 10843a4a2141SAxel Dörfler 10851201d52eSAxel Dörfler BRect 10861201d52eSAxel Dörfler ActivityView::_LegendColorFrameAt(BRect frame, int32 index) const 10871201d52eSAxel Dörfler { 10881201d52eSAxel Dörfler frame = _LegendFrameAt(frame, index); 10891201d52eSAxel Dörfler frame.InsetBy(1, 1); 10901201d52eSAxel Dörfler frame.right = frame.left + frame.Height(); 10911201d52eSAxel Dörfler 10921201d52eSAxel Dörfler return frame; 10931201d52eSAxel Dörfler } 10941201d52eSAxel Dörfler 10951201d52eSAxel Dörfler 109618d3e65eSAxel Dörfler float 109718d3e65eSAxel Dörfler ActivityView::_PositionForValue(DataSource* source, DataHistory* values, 109818d3e65eSAxel Dörfler int64 value) 109918d3e65eSAxel Dörfler { 110018d3e65eSAxel Dörfler int64 min = source->Minimum(); 110118d3e65eSAxel Dörfler int64 max = source->Maximum(); 110218d3e65eSAxel Dörfler if (source->AdaptiveScale()) { 110318d3e65eSAxel Dörfler int64 adaptiveMax = int64(values->MaximumValue() * 1.2); 110418d3e65eSAxel Dörfler if (adaptiveMax < max) 110518d3e65eSAxel Dörfler max = adaptiveMax; 110618d3e65eSAxel Dörfler } 110718d3e65eSAxel Dörfler 110818d3e65eSAxel Dörfler if (value > max) 110918d3e65eSAxel Dörfler value = max; 111018d3e65eSAxel Dörfler if (value < min) 111118d3e65eSAxel Dörfler value = min; 111218d3e65eSAxel Dörfler 11133a4a2141SAxel Dörfler float height = _HistoryFrame().Height(); 111418d3e65eSAxel Dörfler return height - (value - min) * height / (max - min); 111518d3e65eSAxel Dörfler } 111618d3e65eSAxel Dörfler 111718d3e65eSAxel Dörfler 111818d3e65eSAxel Dörfler void 11193a4a2141SAxel Dörfler ActivityView::_DrawHistory() 112018d3e65eSAxel Dörfler { 11213a4a2141SAxel Dörfler _UpdateOffscreenBitmap(); 11223a4a2141SAxel Dörfler 11233a4a2141SAxel Dörfler BView* view = this; 11243a4a2141SAxel Dörfler if (fOffscreen != NULL) { 11253a4a2141SAxel Dörfler fOffscreen->Lock(); 11269c89c450SAxel Dörfler view = _OffscreenView(); 11273a4a2141SAxel Dörfler } 11283a4a2141SAxel Dörfler 11293a4a2141SAxel Dörfler BRect frame = _HistoryFrame(); 11301201d52eSAxel Dörfler view->SetLowColor(fHistoryBackgroundColor); 11313a4a2141SAxel Dörfler view->FillRect(frame, B_SOLID_LOW); 11323a4a2141SAxel Dörfler 113318d3e65eSAxel Dörfler uint32 step = 2; 113418d3e65eSAxel Dörfler uint32 resolution = fDrawResolution; 113518d3e65eSAxel Dörfler if (fDrawResolution > 1) { 113618d3e65eSAxel Dörfler step = 1; 113718d3e65eSAxel Dörfler resolution--; 113818d3e65eSAxel Dörfler } 113918d3e65eSAxel Dörfler 11403a4a2141SAxel Dörfler uint32 width = frame.IntegerWidth() - 10; 114118d3e65eSAxel Dörfler uint32 steps = width / step; 114218d3e65eSAxel Dörfler bigtime_t timeStep = fRefreshInterval * resolution; 114318d3e65eSAxel Dörfler bigtime_t now = system_time(); 114418d3e65eSAxel Dörfler 11451201d52eSAxel Dörfler // Draw scale 11461201d52eSAxel Dörfler // TODO: add second markers? 11471201d52eSAxel Dörfler 11483a4a2141SAxel Dörfler view->SetPenSize(1); 11493a4a2141SAxel Dörfler 11501201d52eSAxel Dörfler rgb_color scaleColor = view->LowColor(); 11511201d52eSAxel Dörfler uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3; 11521201d52eSAxel Dörfler if (average < 96) 11531201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT); 11541201d52eSAxel Dörfler else 11551201d52eSAxel Dörfler scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT); 11561201d52eSAxel Dörfler 11571201d52eSAxel Dörfler view->SetHighColor(scaleColor); 11583a4a2141SAxel Dörfler view->StrokeRect(frame); 11593a4a2141SAxel Dörfler view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2), 11603a4a2141SAxel Dörfler BPoint(frame.right, frame.top + frame.Height() / 2)); 11613a4a2141SAxel Dörfler 11621201d52eSAxel Dörfler // Draw values 11631201d52eSAxel Dörfler 11643a4a2141SAxel Dörfler view->SetPenSize(2); 1165d4216445SAxel Dörfler BAutolock _(fSourcesLock); 116618d3e65eSAxel Dörfler 116718d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) { 116818d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 116918d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i); 117018d3e65eSAxel Dörfler bigtime_t time = now - steps * timeStep; 117118d3e65eSAxel Dörfler // for now steps pixels per second 117218d3e65eSAxel Dörfler 11733a4a2141SAxel Dörfler view->BeginLineArray(steps); 11743a4a2141SAxel Dörfler view->SetHighColor(source->Color()); 117518d3e65eSAxel Dörfler 117618d3e65eSAxel Dörfler float lastY = FLT_MIN; 117718d3e65eSAxel Dörfler uint32 lastX = 0; 117818d3e65eSAxel Dörfler 117918d3e65eSAxel Dörfler for (uint32 x = 0; x < width; x += step, time += timeStep) { 118018d3e65eSAxel Dörfler // TODO: compute starting point instead! 118118d3e65eSAxel Dörfler if (values->Start() > time || values->End() < time) 118218d3e65eSAxel Dörfler continue; 118318d3e65eSAxel Dörfler 118418d3e65eSAxel Dörfler int64 value = values->ValueAt(time); 118518d3e65eSAxel Dörfler if (timeStep > fRefreshInterval) { 118618d3e65eSAxel Dörfler // TODO: always start with the same index, so that it always 118718d3e65eSAxel Dörfler // uses the same values for computation (currently it jumps) 118818d3e65eSAxel Dörfler uint32 count = 1; 118918d3e65eSAxel Dörfler for (bigtime_t offset = fRefreshInterval; offset < timeStep; 119018d3e65eSAxel Dörfler offset += fRefreshInterval) { 119118d3e65eSAxel Dörfler // TODO: handle int64 overflow correctly! 119218d3e65eSAxel Dörfler value += values->ValueAt(time + offset); 119318d3e65eSAxel Dörfler count++; 119418d3e65eSAxel Dörfler } 119518d3e65eSAxel Dörfler value /= count; 119618d3e65eSAxel Dörfler } 119718d3e65eSAxel Dörfler 119818d3e65eSAxel Dörfler float y = _PositionForValue(source, values, value); 11993a4a2141SAxel Dörfler if (lastY != FLT_MIN) { 12003a4a2141SAxel Dörfler view->AddLine(BPoint(lastX, lastY), BPoint(x, y), 12013a4a2141SAxel Dörfler source->Color()); 12023a4a2141SAxel Dörfler } 120318d3e65eSAxel Dörfler 120418d3e65eSAxel Dörfler lastX = x; 120518d3e65eSAxel Dörfler lastY = y; 120618d3e65eSAxel Dörfler } 120718d3e65eSAxel Dörfler 12083a4a2141SAxel Dörfler view->EndLineArray(); 120918d3e65eSAxel Dörfler } 121018d3e65eSAxel Dörfler 121118d3e65eSAxel Dörfler // TODO: add marks when an app started or quit 12123a4a2141SAxel Dörfler view->Sync(); 12133a4a2141SAxel Dörfler if (fOffscreen != NULL) { 12143a4a2141SAxel Dörfler fOffscreen->Unlock(); 12153a4a2141SAxel Dörfler DrawBitmap(fOffscreen); 12163a4a2141SAxel Dörfler } 12173a4a2141SAxel Dörfler } 12183a4a2141SAxel Dörfler 12193a4a2141SAxel Dörfler 12203a4a2141SAxel Dörfler void 12213a4a2141SAxel Dörfler ActivityView::Draw(BRect /*updateRect*/) 12223a4a2141SAxel Dörfler { 12233a4a2141SAxel Dörfler _DrawHistory(); 12243a4a2141SAxel Dörfler 12253a4a2141SAxel Dörfler if (!fShowLegend) 12263a4a2141SAxel Dörfler return; 12273a4a2141SAxel Dörfler 12283a4a2141SAxel Dörfler // draw legend 12293a4a2141SAxel Dörfler 1230d4216445SAxel Dörfler BAutolock _(fSourcesLock); 12313a4a2141SAxel Dörfler BRect legendFrame = _LegendFrame(); 12329c89c450SAxel Dörfler 12339c89c450SAxel Dörfler SetLowColor(fLegendBackgroundColor); 12343a4a2141SAxel Dörfler FillRect(legendFrame, B_SOLID_LOW); 12353a4a2141SAxel Dörfler 12363a4a2141SAxel Dörfler font_height fontHeight; 12373a4a2141SAxel Dörfler GetFontHeight(&fontHeight); 12383a4a2141SAxel Dörfler 12393a4a2141SAxel Dörfler for (int32 i = 0; i < fSources.CountItems(); i++) { 12403a4a2141SAxel Dörfler DataSource* source = fSources.ItemAt(i); 12413a4a2141SAxel Dörfler DataHistory* values = fValues.ItemAt(i); 12423a4a2141SAxel Dörfler BRect frame = _LegendFrameAt(legendFrame, i); 12433a4a2141SAxel Dörfler 12443a4a2141SAxel Dörfler // draw color box 12451201d52eSAxel Dörfler BRect colorBox = _LegendColorFrameAt(legendFrame, i); 12463a4a2141SAxel Dörfler SetHighColor(tint_color(source->Color(), B_DARKEN_1_TINT)); 12473a4a2141SAxel Dörfler StrokeRect(colorBox); 12483a4a2141SAxel Dörfler SetHighColor(source->Color()); 12493a4a2141SAxel Dörfler colorBox.InsetBy(1, 1); 12503a4a2141SAxel Dörfler FillRect(colorBox); 12513a4a2141SAxel Dörfler 12523a4a2141SAxel Dörfler // show current value and label 12533a4a2141SAxel Dörfler float y = frame.top + ceilf(fontHeight.ascent); 12543a4a2141SAxel Dörfler int64 value = values->ValueAt(values->End()); 12553a4a2141SAxel Dörfler BString text; 12563a4a2141SAxel Dörfler source->Print(text, value); 12573a4a2141SAxel Dörfler float width = StringWidth(text.String()); 12583a4a2141SAxel Dörfler 12593a4a2141SAxel Dörfler BString label = source->Label(); 12603a4a2141SAxel Dörfler TruncateString(&label, B_TRUNCATE_MIDDLE, 12613a4a2141SAxel Dörfler frame.right - colorBox.right - 12 - width); 12623a4a2141SAxel Dörfler 12633a4a2141SAxel Dörfler SetHighColor(ui_color(B_CONTROL_TEXT_COLOR)); 12643a4a2141SAxel Dörfler DrawString(label.String(), BPoint(6 + colorBox.right, y)); 12653a4a2141SAxel Dörfler DrawString(text.String(), BPoint(frame.right - width, y)); 12663a4a2141SAxel Dörfler } 126718d3e65eSAxel Dörfler } 126818d3e65eSAxel Dörfler 126918d3e65eSAxel Dörfler 127018d3e65eSAxel Dörfler void 127118d3e65eSAxel Dörfler ActivityView::_Refresh() 127218d3e65eSAxel Dörfler { 1273d4216445SAxel Dörfler bigtime_t lastTimeout = system_time() - fRefreshInterval; 12744ce1e1d2SAxel Dörfler BMessenger target(this); 127518d3e65eSAxel Dörfler 1276d4216445SAxel Dörfler while (true) { 1277d4216445SAxel Dörfler status_t status = acquire_sem_etc(fRefreshSem, 1, B_ABSOLUTE_TIMEOUT, 1278d4216445SAxel Dörfler lastTimeout + fRefreshInterval); 1279d4216445SAxel Dörfler if (status == B_OK || status == B_BAD_SEM_ID) 1280d4216445SAxel Dörfler break; 1281d4216445SAxel Dörfler if (status == B_INTERRUPTED) 1282d4216445SAxel Dörfler continue; 1283d4216445SAxel Dörfler 1284d4216445SAxel Dörfler SystemInfo info(fSystemInfoHandler); 1285d4216445SAxel Dörfler lastTimeout += fRefreshInterval; 1286d4216445SAxel Dörfler 1287d4216445SAxel Dörfler fSourcesLock.Lock(); 128818d3e65eSAxel Dörfler 128918d3e65eSAxel Dörfler for (uint32 i = fSources.CountItems(); i-- > 0;) { 129018d3e65eSAxel Dörfler DataSource* source = fSources.ItemAt(i); 129118d3e65eSAxel Dörfler DataHistory* values = fValues.ItemAt(i); 129218d3e65eSAxel Dörfler 129318d3e65eSAxel Dörfler int64 value = source->NextValue(info); 129418d3e65eSAxel Dörfler values->AddValue(info.Time(), value); 129518d3e65eSAxel Dörfler } 129618d3e65eSAxel Dörfler 1297d4216445SAxel Dörfler fSourcesLock.Unlock(); 1298d4216445SAxel Dörfler 129918d3e65eSAxel Dörfler bigtime_t now = info.Time(); 130018d3e65eSAxel Dörfler if (fLastRefresh + fDrawInterval <= now) { 13014ce1e1d2SAxel Dörfler target.SendMessage(B_INVALIDATE); 130218d3e65eSAxel Dörfler fLastRefresh = now; 130318d3e65eSAxel Dörfler } 130418d3e65eSAxel Dörfler } 1305d4216445SAxel Dörfler } 130618d3e65eSAxel Dörfler 1307d4216445SAxel Dörfler 1308d4216445SAxel Dörfler /*static*/ status_t 1309d4216445SAxel Dörfler ActivityView::_RefreshThread(void* self) 1310d4216445SAxel Dörfler { 1311d4216445SAxel Dörfler ((ActivityView*)self)->_Refresh(); 1312d4216445SAxel Dörfler return B_OK; 1313d4216445SAxel Dörfler } 1314