1/* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Clemens Zeidler, haiku@clemens-zeidler.de 7 */ 8 9#include "ColorStepView.h" 10 11#include <stdio.h> 12 13#include <Catalog.h> 14#include <Locale.h> 15#include <Window.h> 16 17 18#undef B_TRANSLATION_CONTEXT 19#define B_TRANSLATION_CONTEXT "Color Step View" 20 21 22const int32 kColorBarHeight = 15; 23 24const uint32 kMSGSliderChanged = '&slc'; 25 26 27ColorStepView::ColorStepView(BRect frame) 28 : BControl(frame, "ColorStepView", "", new BMessage(kSteppingChanged), 29 B_FOLLOW_ALL, B_WILL_DRAW), 30 fOffScreenView(NULL), 31 fOffScreenBitmap(NULL) 32{ 33 fPerformanceList = new PerformanceList(20, true); 34 35 fSliderPosition = 0; 36 fNSteps = 0; 37 fLowFreqColor.red = 0; 38 fLowFreqColor.blue = 255; 39 fLowFreqColor.green = 0; 40 41 fHighFreqColor.red = 255; 42 fHighFreqColor.blue = 0; 43 fHighFreqColor.green = 0; 44 45 fMinFrequencyLabel = "? MHz"; 46 fMaxFrequencyLabel = "? MHz"; 47 _InitView(); 48} 49 50 51ColorStepView::~ColorStepView() 52{ 53 delete fPerformanceList; 54} 55 56 57void 58ColorStepView::AttachedToWindow() 59{ 60 fSlider->SetTarget(this); 61 62 if (!fOffScreenView) { 63 fOffScreenView = new BView(Bounds(), "", B_FOLLOW_ALL, B_WILL_DRAW); 64 } 65 if (!fOffScreenBitmap) { 66 fOffScreenBitmap = new BBitmap(Bounds(), B_CMAP8, true, false); 67 Window()->Lock(); 68 if (fOffScreenBitmap && fOffScreenView) 69 fOffScreenBitmap->AddChild(fOffScreenView); 70 Window()->Unlock(); 71 } 72} 73 74 75void 76ColorStepView::DetachedFromWindow() 77{ 78 BView::DetachedFromWindow(); 79 80 if (fOffScreenBitmap) { 81 delete fOffScreenBitmap; 82 fOffScreenBitmap = NULL; 83 fOffScreenView = NULL; 84 } 85} 86 87 88void 89ColorStepView::FrameResized(float w,float h) 90{ 91 BView::FrameResized(w, h); 92 93 BRect bounds(Bounds()); 94 95 if (bounds.right <= 0.0f || bounds.bottom <= 0.0f) 96 return; 97 98 if (fOffScreenBitmap) { 99 fOffScreenBitmap->RemoveChild(fOffScreenView); 100 delete fOffScreenBitmap; 101 102 fOffScreenView->ResizeTo(bounds.Width(), bounds.Height()); 103 104 fOffScreenBitmap = new BBitmap(Bounds(), B_RGBA32, true, false); 105 fOffScreenBitmap->AddChild(fOffScreenView); 106 } 107 108 Invalidate(); 109} 110 111 112void 113ColorStepView::GetPreferredSize(float *width, float *height) 114{ 115 *width = Frame().Width(); 116 font_height fontHeight; 117 GetFontHeight(&fontHeight); 118 119 *height = fSlider->Frame().Height(); 120 *height += kColorBarHeight; 121 *height += fontHeight.descent + fontHeight.ascent + 5; 122} 123 124 125void 126ColorStepView::Draw(BRect updateRect) 127{ 128 BView *view = NULL; 129 if(fOffScreenView){ 130 view = fOffScreenView; 131 } 132 else{ 133 view = this; 134 } 135 136 if (!fOffScreenBitmap || !fOffScreenBitmap->Lock()) 137 return; 138 view->SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 139 140 view->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 141 view->FillRect(updateRect); 142 143 BRect colorBarRect = fSlider->BarFrame(); 144 colorBarRect.top = 0; 145 colorBarRect.bottom = kColorBarHeight; 146 colorBarRect.OffsetTo(colorBarRect.left, fSlider->Frame().bottom); 147 148 float pos = 0.0; 149 for (int i = fPerformanceList->CountItems() - 1; i >= 0 ; i--) { 150 performance_step* perfState = fPerformanceList->ItemAt(i); 151 152 float nextPos = perfState->cpu_usage; 153 float width = colorBarRect.Width(); 154 155 BRect subRect(colorBarRect); 156 subRect.left += pos * width; 157 subRect.right = colorBarRect.left + nextPos * width; 158 159 view->SetHighColor(perfState->color); 160 view->FillRect(subRect); 161 162 pos = nextPos; 163 } 164 // draw label 165 if (IsEnabled()) { 166 view->SetHighColor(0, 0, 0); 167 } else { 168 view->SetHighColor(tint_color(LowColor(), B_DISABLED_LABEL_TINT)); 169 } 170 171 font_height fontHeight; 172 GetFontHeight(&fontHeight); 173 float totalFontHeight = fontHeight.descent + fontHeight.ascent; 174 175 view->DrawString(fMinFrequencyLabel.String(), 176 BPoint(0.0, 177 colorBarRect.bottom + totalFontHeight + 5)); 178 179 view->DrawString(fMaxFrequencyLabel.String(), 180 BPoint(Bounds().right 181 - StringWidth(fMaxFrequencyLabel.String()), 182 colorBarRect.bottom + totalFontHeight + 5)); 183 184 // blit bitmap 185 view->Sync(); 186 fOffScreenBitmap->Unlock(); 187 DrawBitmap(fOffScreenBitmap, B_ORIGIN); 188 189 BView::Draw(updateRect); 190} 191 192 193void 194ColorStepView::MessageReceived(BMessage *message) 195{ 196 switch (message->what) { 197 case kMSGSliderChanged: 198 fSliderPosition = fSlider->Position(); 199 _CalculatePerformanceSteps(); 200 Invalidate(); 201 break; 202 case kSteppingChanged: 203 Invoke(); 204 break; 205 default: 206 BView::MessageReceived(message); 207 break; 208 } 209} 210 211 212void 213ColorStepView::SetEnabled(bool enabled) 214{ 215 fSlider->SetEnabled(enabled); 216 BControl::SetEnabled(enabled); 217} 218 219 220void 221ColorStepView::SetFrequencys(StateList *list) 222{ 223 fStateList = list; 224 fNSteps = fStateList->CountItems(); 225 if (fNSteps >= 2) { 226 float minFreq = fStateList->ItemAt(fNSteps - 1)->frequency; 227 float maxFreq = fStateList->ItemAt(0)->frequency; 228 fMinFrequencyLabel = CreateFrequencyString(minFreq); 229 fMaxFrequencyLabel = CreateFrequencyString(maxFreq); 230 } 231 232 // fit size of fPerformanceList 233 int32 perfNumber = fPerformanceList->CountItems(); 234 if (perfNumber < fNSteps) { 235 for (int i = 0; i < fNSteps - perfNumber; i++) 236 fPerformanceList->AddItem(new performance_step); 237 } 238 else { 239 for (int i = 0; i < perfNumber - fNSteps; i++) 240 fPerformanceList->RemoveItemAt(0); 241 } 242 // and fill the list 243 _CalculatePerformanceSteps(); 244 245} 246 247 248PerformanceList* 249ColorStepView::GetPerformanceSteps() 250{ 251 return fPerformanceList; 252} 253 254 255BString 256ColorStepView::CreateFrequencyString(uint16 frequency) 257{ 258 BString string = ""; 259 if (frequency >= 1000) { 260 char buffer [10]; 261 sprintf (buffer, "%.1f", float(frequency) / 1000); 262 string << buffer; 263 string += " GHz"; 264 } 265 else { 266 string << frequency; 267 string += " MHz"; 268 } 269 return string; 270} 271 272 273 274float 275ColorStepView::UsageOfStep(int32 step, int32 nSteps, float base) 276{ 277 float singleWidth = (1 - base) / (nSteps - 1); 278 return base + singleWidth * step; 279} 280 281 282void 283ColorStepView::_InitView() 284{ 285 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 286 287 BRect sliderFrame(Bounds()); 288 289 fSlider = new BSlider(sliderFrame, "StepSlider", 290 B_TRANSLATE("Step up by CPU usage"), 291 new BMessage(kSteppingChanged), 0, 100); 292 fSlider->SetModificationMessage(new BMessage(kMSGSliderChanged)); 293 294 fSliderPosition = 0.25 - fNSteps * 0.05; 295 fSlider->SetPosition(fSliderPosition); 296 fSlider->SetLimitLabels("0%", "100%"); 297 fSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 298 fSlider->SetHashMarkCount(5); 299 AddChild(fSlider); 300} 301 302 303void 304ColorStepView::_CalculatePerformanceSteps() 305{ 306 for (int i = 0; i < fNSteps; i++) { 307 // begin with the lowest frequency 308 performance_step* perfState = fPerformanceList->ItemAt(fNSteps -1 - i); 309 perfState->cpu_usage = _PositonStep(i); 310 _ColorStep(i, perfState->color); 311 } 312} 313 314 315float 316ColorStepView::_PositonStep(int32 step) 317{ 318 if (step >= fNSteps) 319 return 1.0; 320 321 return UsageOfStep(step, fNSteps, fSliderPosition); 322} 323 324 325void 326ColorStepView::_ColorStep(int32 step, rgb_color &color) 327{ 328 color.red = fLowFreqColor.red 329 + (fHighFreqColor.red - fLowFreqColor.red) 330 / (fNSteps - 1) * step; 331 color.green = fLowFreqColor.green 332 + (fHighFreqColor.green - fLowFreqColor.green) 333 / (fNSteps - 1) * step; 334 color.blue = fLowFreqColor.blue 335 + (fHighFreqColor.blue - fLowFreqColor.blue) 336 / (fNSteps - 1) * step; 337} 338 339