1 /* 2 * Copyright 2003-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jonas Sundström, jonas@kirilla.com 7 */ 8 9 10 #include "ZipOMaticActivity.h" 11 12 #include <ControlLook.h> 13 14 #include <stdio.h> 15 16 17 Activity::Activity(const char* name) 18 : 19 BView(name, B_WILL_DRAW | B_FRAME_EVENTS), 20 fIsRunning(false), 21 fBitmap(NULL), 22 fSpinSpeed(0.15), 23 fColors(NULL), 24 fNumColors(0), 25 fScrollOffset(0.0), 26 fStripeWidth(0.0), 27 fNumStripes(0) 28 { 29 _InactiveColors(); 30 SetExplicitMinSize(BSize(17, 17)); 31 SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 17)); 32 }; 33 34 35 Activity::~Activity() 36 { 37 delete fBitmap; 38 delete[] fColors; 39 } 40 41 42 void 43 Activity::AllAttached() 44 { 45 _CreateBitmap(); 46 FrameResized(Bounds().Width(), Bounds().Height()); 47 } 48 49 50 void 51 Activity::Start() 52 { 53 fIsRunning = true; 54 _ActiveColors(); 55 Window()->SetPulseRate(100000); 56 SetFlags(Flags() | B_PULSE_NEEDED); 57 Invalidate(); 58 } 59 60 61 void 62 Activity::Pause() 63 { 64 Window()->SetPulseRate(500000); 65 SetFlags(Flags() & (~B_PULSE_NEEDED)); 66 Invalidate(); 67 } 68 69 70 void 71 Activity::Stop() 72 { 73 fIsRunning = false; 74 _InactiveColors(); 75 Window()->SetPulseRate(500000); 76 SetFlags(Flags() & (~B_PULSE_NEEDED)); 77 Invalidate(); 78 } 79 80 81 bool 82 Activity::IsRunning() 83 { 84 return fIsRunning; 85 } 86 87 88 void 89 Activity::Pulse() 90 { 91 fScrollOffset += fStripeWidth / (1.0f / fSpinSpeed); 92 if (fScrollOffset >= fStripeWidth * fNumColors) { 93 // Cycle completed, jump back to where we started 94 fScrollOffset = 0; 95 } 96 Invalidate(); 97 } 98 99 100 void 101 Activity::SetColors(const rgb_color* colors, uint32 numColors) 102 { 103 delete[] fColors; 104 rgb_color* colorsCopy = new rgb_color[numColors]; 105 for (uint32 i = 0; i < numColors; i++) 106 colorsCopy[i] = colors[i]; 107 108 fColors = colorsCopy; 109 fNumColors = numColors; 110 } 111 112 113 void 114 Activity::Draw(BRect rect) 115 { 116 BRect viewRect = Bounds(); 117 BRect bitmapRect = fBitmap->Bounds(); 118 119 if (bitmapRect != viewRect) { 120 delete fBitmap; 121 _CreateBitmap(); 122 } 123 124 _DrawOnBitmap(IsRunning()); 125 SetDrawingMode(B_OP_COPY); 126 DrawBitmap(fBitmap); 127 } 128 129 130 void 131 Activity::_DrawOnBitmap(bool running) 132 { 133 if (fBitmap->Lock()) 134 { 135 BRect bounds = fBitmap->Bounds(); 136 137 fBitmapView->SetDrawingMode(B_OP_COPY); 138 139 // Draw color stripes 140 float position = -fStripeWidth * (fNumColors + 0.5) + fScrollOffset; 141 // Starting position: beginning of the second color cycle 142 // The + 0.5 is so we start out without a partially visible stripe 143 // on the left side (makes it simpler to loop) 144 BRect innerFrame = bounds; 145 innerFrame.InsetBy(-2, -2); 146 147 be_control_look->DrawStatusBar(fBitmapView, innerFrame, innerFrame, 148 ui_color(B_PANEL_BACKGROUND_COLOR), 149 running ? ui_color(B_STATUS_BAR_COLOR) 150 : ui_color(B_PANEL_BACKGROUND_COLOR), 151 bounds.Width()); 152 fBitmapView->SetDrawingMode(B_OP_ALPHA); 153 uint32 colorIndex = 0; 154 for (uint32 i = 0; i < fNumStripes; i++) { 155 fBitmapView->SetHighColor(fColors[colorIndex]); 156 colorIndex++; 157 if (colorIndex >= fNumColors) 158 colorIndex = 0; 159 160 BRect stripeFrame = fStripe.Frame(); 161 fStripe.MapTo(stripeFrame, 162 stripeFrame.OffsetToCopy(position, 0.0)); 163 fBitmapView->FillPolygon(&fStripe); 164 165 position += fStripeWidth; 166 } 167 168 fBitmapView->SetDrawingMode(B_OP_COPY); 169 // Draw box around it 170 be_control_look->DrawTextControlBorder(fBitmapView, bounds, bounds, 171 ui_color(B_PANEL_BACKGROUND_COLOR), B_PLAIN_BORDER); 172 173 fBitmapView->Sync(); 174 fBitmap->Unlock(); 175 } 176 } 177 178 179 void 180 Activity::_CreateBitmap(void) 181 { 182 BRect rect = Bounds(); 183 fBitmap = new BBitmap(rect, B_RGBA32, true); 184 fBitmapView = new BView(Bounds(), "buffer", B_FOLLOW_NONE, 0); 185 fBitmap->AddChild(fBitmapView); 186 } 187 188 189 void 190 Activity::FrameResized(float width, float height) 191 { 192 delete fBitmap; 193 _CreateBitmap(); 194 // Choose stripe width so that at least 2 full stripes fit into the view, 195 // but with a minimum of 5px. Larger views get wider stripes, but they 196 // grow slower than the view and are capped to a maximum of 200px. 197 fStripeWidth = (width / (fIsRunning ? 4 : 6)) + 5; 198 if (fStripeWidth > 200) 199 fStripeWidth = 200; 200 201 BPoint stripePoints[4]; 202 stripePoints[0].Set(fStripeWidth * 0.5, 0.0); // top left 203 stripePoints[1].Set(fStripeWidth * 1.5, 0.0); // top right 204 stripePoints[2].Set(fStripeWidth, height); // bottom right 205 stripePoints[3].Set(0.0, height); // bottom left 206 207 fStripe = BPolygon(stripePoints, 4); 208 209 fNumStripes = (int32)ceilf((width) / fStripeWidth) + 1 + fNumColors; 210 // Number of color stripes drawn in total for the barber pole, the 211 // user-visible part is a "window" onto the complete pole. We need 212 // as many stripes as are visible, an extra one on the right side 213 // (will be partially visible, that's the + 1); and then a whole color 214 // cycle of strips extra which we scroll into until we loop. 215 // 216 // Example with 3 colors and a visible area of 2*fStripeWidth (which means 217 // that 2 will be fully visible, and a third one partially): 218 // ........ 219 // X___________v______v___ 220 // / 1 / 2 / 3 / 1 / 2 / 3 / 221 // ````````````````````````` 222 // Pole is scrolled to the right into the visible region, which is marked 223 // between the two 'v'. Once the left edge of the visible area reaches 224 // point X, we can jump back to the initial region position. 225 Invalidate(); 226 } 227 228 void 229 Activity::_ActiveColors() 230 { 231 // Default colors, chosen from system color scheme 232 rgb_color defaultColors[2]; 233 rgb_color otherColor = tint_color(ui_color(B_STATUS_BAR_COLOR), 1.3); 234 otherColor.alpha = 50; 235 defaultColors[0] = otherColor; 236 defaultColors[1] = B_TRANSPARENT_COLOR; 237 SetColors(defaultColors, 2); 238 239 } 240 241 242 void 243 Activity::_InactiveColors() 244 { 245 // Default colors, chosen from system color scheme 246 rgb_color defaultColors[2]; 247 rgb_color otherColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.7); 248 otherColor.alpha = 50; 249 defaultColors[0] = otherColor; 250 defaultColors[1] = B_TRANSPARENT_COLOR; 251 SetColors(defaultColors, 2); 252 } 253