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
Activity(const char * name)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
~Activity()35 Activity::~Activity()
36 {
37 delete fBitmap;
38 delete[] fColors;
39 }
40
41
42 void
AllAttached()43 Activity::AllAttached()
44 {
45 _CreateBitmap();
46 FrameResized(Bounds().Width(), Bounds().Height());
47 }
48
49
50 void
Start()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
Pause()62 Activity::Pause()
63 {
64 Window()->SetPulseRate(500000);
65 SetFlags(Flags() & (~B_PULSE_NEEDED));
66 Invalidate();
67 }
68
69
70 void
Stop()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
IsRunning()82 Activity::IsRunning()
83 {
84 return fIsRunning;
85 }
86
87
88 void
Pulse()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
SetColors(const rgb_color * colors,uint32 numColors)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
Draw(BRect rect)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
_DrawOnBitmap(bool running)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
_CreateBitmap(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
FrameResized(float width,float height)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
_ActiveColors()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
_InactiveColors()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