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 BRect bounds = fBitmap->Bounds(); 135 136 fBitmapView->SetDrawingMode(B_OP_COPY); 137 138 // Draw color stripes 139 float position = -fStripeWidth * (fNumColors + 0.5) + fScrollOffset; 140 // Starting position: beginning of the second color cycle 141 // The + 0.5 is so we start out without a partially visible stripe 142 // on the left side (makes it simpler to loop) 143 BRect innerFrame = bounds; 144 innerFrame.InsetBy(-2, -2); 145 146 be_control_look->DrawStatusBar(fBitmapView, innerFrame, innerFrame, 147 ui_color(B_PANEL_BACKGROUND_COLOR), 148 running ? ui_color(B_STATUS_BAR_COLOR) 149 : ui_color(B_PANEL_BACKGROUND_COLOR), 150 bounds.Width()); 151 fBitmapView->SetDrawingMode(B_OP_ALPHA); 152 uint32 colorIndex = 0; 153 for (uint32 i = 0; i < fNumStripes; i++) { 154 fBitmapView->SetHighColor(fColors[colorIndex]); 155 colorIndex++; 156 if (colorIndex >= fNumColors) 157 colorIndex = 0; 158 159 BRect stripeFrame = fStripe.Frame(); 160 fStripe.MapTo(stripeFrame, 161 stripeFrame.OffsetToCopy(position, 0.0)); 162 fBitmapView->FillPolygon(&fStripe); 163 164 position += fStripeWidth; 165 } 166 167 fBitmapView->SetDrawingMode(B_OP_COPY); 168 // Draw box around it 169 be_control_look->DrawTextControlBorder(fBitmapView, bounds, bounds, 170 ui_color(B_PANEL_BACKGROUND_COLOR), B_PLAIN_BORDER); 171 172 fBitmapView->Sync(); 173 fBitmap->Unlock(); 174 } 175 } 176 177 178 void 179 Activity::_CreateBitmap(void) 180 { 181 BRect rect = Bounds(); 182 fBitmap = new BBitmap(rect, B_RGBA32, true); 183 fBitmapView = new BView(Bounds(), "buffer", B_FOLLOW_NONE, 0); 184 fBitmap->AddChild(fBitmapView); 185 } 186 187 188 void 189 Activity::FrameResized(float width, float height) 190 { 191 delete fBitmap; 192 _CreateBitmap(); 193 // Choose stripe width so that at least 2 full stripes fit into the view, 194 // but with a minimum of 5px. Larger views get wider stripes, but they 195 // grow slower than the view and are capped to a maximum of 200px. 196 fStripeWidth = (width / (fIsRunning ? 4 : 6)) + 5; 197 if (fStripeWidth > 200) 198 fStripeWidth = 200; 199 200 BPoint stripePoints[4]; 201 stripePoints[0].Set(fStripeWidth * 0.5, 0.0); // top left 202 stripePoints[1].Set(fStripeWidth * 1.5, 0.0); // top right 203 stripePoints[2].Set(fStripeWidth, height); // bottom right 204 stripePoints[3].Set(0.0, height); // bottom left 205 206 fStripe = BPolygon(stripePoints, 4); 207 208 fNumStripes = (int32)ceilf((width) / fStripeWidth) + 1 + fNumColors; 209 // Number of color stripes drawn in total for the barber pole, the 210 // user-visible part is a "window" onto the complete pole. We need 211 // as many stripes as are visible, an extra one on the right side 212 // (will be partially visible, that's the + 1); and then a whole color 213 // cycle of strips extra which we scroll into until we loop. 214 // 215 // Example with 3 colors and a visible area of 2*fStripeWidth (which means 216 // that 2 will be fully visible, and a third one partially): 217 // ........ 218 // X___________v______v___ 219 // / 1 / 2 / 3 / 1 / 2 / 3 / 220 // ````````````````````````` 221 // Pole is scrolled to the right into the visible region, which is marked 222 // between the two 'v'. Once the left edge of the visible area reaches 223 // point X, we can jump back to the initial region position. 224 Invalidate(); 225 } 226 227 void 228 Activity::_ActiveColors() 229 { 230 // Default colors, chosen from system color scheme 231 rgb_color defaultColors[2]; 232 rgb_color otherColor = tint_color(ui_color(B_STATUS_BAR_COLOR), 1.3); 233 otherColor.alpha = 50; 234 defaultColors[0] = otherColor; 235 defaultColors[1] = B_TRANSPARENT_COLOR; 236 SetColors(defaultColors, 2); 237 238 } 239 240 241 void 242 Activity::_InactiveColors() 243 { 244 // Default colors, chosen from system color scheme 245 rgb_color defaultColors[2]; 246 rgb_color otherColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.7); 247 otherColor.alpha = 50; 248 defaultColors[0] = otherColor; 249 defaultColors[1] = B_TRANSPARENT_COLOR; 250 SetColors(defaultColors, 2); 251 } 252