void ActivityView::_UpdateOffscreenBitmap() { BRect frame = _HistoryFrame(); frame.OffsetTo(B_ORIGIN); if (fOffscreen != NULL && frame == fOffscreen->Bounds()) return; delete fOffscreen; // create offscreen bitmap fOffscreen = new(std::nothrow) BBitmap(frame, B_BITMAP_ACCEPTS_VIEWS, B_RGB32); if (fOffscreen == NULL || fOffscreen->InitCheck() != B_OK) { delete fOffscreen; fOffscreen = NULL; return; } BView* view = new BView(frame, NULL, B_FOLLOW_NONE, B_SUBPIXEL_PRECISE); view->SetViewColor(fHistoryBackgroundColor); view->SetLowColor(view->ViewColor()); fOffscreen->AddChild(view); }
float ActivityView::_PositionForValue(DataSource* source, DataHistory* values, int64 value) { int64 min = source->Minimum(); int64 max = source->Maximum(); if (source->AdaptiveScale()) { int64 adaptiveMax = int64(values->MaximumValue() * 1.2); if (adaptiveMax < max) max = adaptiveMax; } if (value > max) value = max; if (value < min) value = min; float height = _HistoryFrame().Height(); return height - (value - min) * height / (max - min); }
void ActivityView::_DrawHistory(bool drawBackground) { _UpdateOffscreenBitmap(); BView* view = this; if (fOffscreen != NULL) { fOffscreen->Lock(); view = _OffscreenView(); } BRect frame = _HistoryFrame(); BRect outerFrame = frame.InsetByCopy(-2, -2); // draw the outer frame uint32 flags = 0; if (!drawBackground) flags |= BControlLook::B_BLEND_FRAME; be_control_look->DrawTextControlBorder(this, outerFrame, outerFrame, fLegendBackgroundColor, flags); // convert to offscreen view if necessary if (view != this) frame.OffsetTo(B_ORIGIN); view->SetLowColor(fHistoryBackgroundColor); view->FillRect(frame, B_SOLID_LOW); uint32 step = 2; uint32 resolution = fDrawResolution; if (fDrawResolution > 1) { step = 1; resolution--; } // We would get a negative number of steps which isn't a good idea. if (frame.IntegerWidth() <= 10) return; uint32 width = frame.IntegerWidth() - 10; uint32 steps = width / step; bigtime_t timeStep = RefreshInterval() * resolution; bigtime_t now = system_time(); // Draw scale // TODO: add second markers? view->SetPenSize(1); rgb_color scaleColor = view->LowColor(); uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3; if (average < 96) scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT); else scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT); view->SetHighColor(scaleColor); view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2), BPoint(frame.right, frame.top + frame.Height() / 2)); // Draw values view->SetPenSize(1.5); BAutolock _(fSourcesLock); for (uint32 i = fSources.CountItems(); i-- > 0;) { ViewHistory* viewValues = fViewValues.ItemAt(i); DataSource* source = fSources.ItemAt(i); DataHistory* values = fValues.ItemAt(i); viewValues->Update(values, steps, fDrawResolution, now, timeStep, RefreshInterval()); if (viewValues->Start() >= (int32)steps - 1) continue; uint32 x = viewValues->Start() * step; bool first = true; view->SetHighColor(source->Color()); view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN); view->MovePenTo(B_ORIGIN); try { view->BeginLineArray(steps - viewValues->Start() - 1); BPoint prev; for (uint32 j = viewValues->Start(); j < steps; x += step, j++) { float y = _PositionForValue(source, values, viewValues->ValueAt(j)); if (first) { first = false; } else view->AddLine(prev, BPoint(x, y), source->Color()); prev.Set(x, y); } } catch (std::bad_alloc) { // Not enough memory to allocate the line array. // TODO we could try to draw using the slower but less memory // consuming solution using StrokeLine. } view->EndLineArray(); } // TODO: add marks when an app started or quit view->Sync(); if (fOffscreen != NULL) { fOffscreen->Unlock(); DrawBitmap(fOffscreen, outerFrame.LeftTop()); } }
void ActivityView::MessageReceived(BMessage* message) { // if a color is dropped, use it as background if (message->WasDropped()) { rgb_color* color; ssize_t size; if (message->FindData("RGBColor", B_RGB_COLOR_TYPE, 0, (const void**)&color, &size) == B_OK && size == sizeof(rgb_color)) { BPoint dropPoint = message->DropPoint(); ConvertFromScreen(&dropPoint); if (_HistoryFrame().Contains(dropPoint)) { fHistoryBackgroundColor = *color; Invalidate(_HistoryFrame()); } else { // check each legend color box BAutolock _(fSourcesLock); BRect legendFrame = _LegendFrame(); for (int32 i = 0; i < fSources.CountItems(); i++) { BRect frame = _LegendColorFrameAt(legendFrame, i); if (frame.Contains(dropPoint)) { fSources.ItemAt(i)->SetColor(*color); Invalidate(_HistoryFrame()); Invalidate(frame); return; } } if (dynamic_cast<ActivityMonitor*>(be_app) == NULL) { // allow background color change in the replicant only fLegendBackgroundColor = *color; SetLowColor(fLegendBackgroundColor); Invalidate(legendFrame); } } return; } } switch (message->what) { case B_ABOUT_REQUESTED: { BAboutWindow* window = new BAboutWindow(kAppName, kSignature); const char* authors[] = { "Axel Dörfler", NULL }; window->AddCopyright(2008, "Haiku, Inc."); window->AddAuthors(authors); window->Show(); break; } case kMsgUpdateResolution: { int32 resolution; if (message->FindInt32("resolution", &resolution) != B_OK) break; _UpdateResolution(resolution, false); break; } case kMsgTimeIntervalUpdated: bigtime_t interval; if (message->FindInt64("interval", &interval) != B_OK) break; if (interval < 10000) interval = 10000; atomic_set64(&fRefreshInterval, interval); break; case kMsgToggleDataSource: { int32 index; if (message->FindInt32("index", &index) != B_OK) break; const DataSource* baseSource = DataSource::SourceAt(index); if (baseSource == NULL) break; DataSource* source = FindDataSource(baseSource); if (source == NULL) AddDataSource(baseSource); else RemoveDataSource(baseSource); Invalidate(); break; } case kMsgToggleLegend: fShowLegend = !fShowLegend; Invalidate(); break; case B_MOUSE_WHEEL_CHANGED: { float deltaY = 0.0f; if (message->FindFloat("be:wheel_delta_y", &deltaY) != B_OK || deltaY == 0.0f) break; int32 resolution = fDrawResolution; if (deltaY > 0) resolution *= 2; else resolution /= 2; _UpdateResolution(resolution); break; } default: BView::MessageReceived(message); break; } }
void ActivityView::_DrawHistory(bool drawBackground) { _UpdateOffscreenBitmap(); BView* view = this; if (fOffscreen != NULL) { fOffscreen->Lock(); view = _OffscreenView(); } BRect frame = _HistoryFrame(); BRect outerFrame = frame.InsetByCopy(-2, -2); // draw the outer frame uint32 flags = 0; if (!drawBackground) flags |= BControlLook::B_BLEND_FRAME; be_control_look->DrawTextControlBorder(this, outerFrame, outerFrame, fLegendBackgroundColor, flags); // convert to offscreen view if necessary if (view != this) frame.OffsetTo(B_ORIGIN); view->SetLowColor(fHistoryBackgroundColor); view->FillRect(frame, B_SOLID_LOW); uint32 step = 2; uint32 resolution = fDrawResolution; if (fDrawResolution > 1) { step = 1; resolution--; } uint32 width = frame.IntegerWidth() - 10; uint32 steps = width / step; bigtime_t timeStep = RefreshInterval() * resolution; bigtime_t now = system_time(); // Draw scale // TODO: add second markers? view->SetPenSize(1); rgb_color scaleColor = view->LowColor(); uint32 average = (scaleColor.red + scaleColor.green + scaleColor.blue) / 3; if (average < 96) scaleColor = tint_color(scaleColor, B_LIGHTEN_2_TINT); else scaleColor = tint_color(scaleColor, B_DARKEN_2_TINT); view->SetHighColor(scaleColor); view->StrokeLine(BPoint(frame.left, frame.top + frame.Height() / 2), BPoint(frame.right, frame.top + frame.Height() / 2)); // Draw values view->SetPenSize(1.5); BAutolock _(fSourcesLock); for (uint32 i = fSources.CountItems(); i-- > 0;) { ViewHistory* viewValues = fViewValues.ItemAt(i); DataSource* source = fSources.ItemAt(i); DataHistory* values = fValues.ItemAt(i); viewValues->Update(values, steps, fDrawResolution, now, timeStep, RefreshInterval()); uint32 x = viewValues->Start() * step; BShape shape; bool first = true; for (uint32 i = viewValues->Start(); i < steps; x += step, i++) { float y = _PositionForValue(source, values, viewValues->ValueAt(i)); if (first) { shape.MoveTo(BPoint(x, y)); first = false; } else shape.LineTo(BPoint(x, y)); } view->SetHighColor(source->Color()); view->SetLineMode(B_BUTT_CAP, B_ROUND_JOIN); view->MovePenTo(B_ORIGIN); view->StrokeShape(&shape); } // TODO: add marks when an app started or quit view->Sync(); if (fOffscreen != NULL) { fOffscreen->Unlock(); DrawBitmap(fOffscreen, outerFrame.LeftTop()); } }