xref: /haiku/src/add-ons/tracker/zipomatic/ZipOMaticActivity.cpp (revision c42868a015daa160e093679b2637b1cf9f0b26ba)
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