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