1//
2// StickIt
3// File: JoystickWindow.cpp
4// Joystick window.
5// Sampel code used in "Getting a Grip on BJoystick" by Eric Shepherd
6//
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <OS.h>
12
13#include <Application.h>
14#include <Joystick.h>
15#include <String.h>
16#include <StringView.h>
17
18#include "JoystickWindow.h"
19
20rgb_color rgb_black = {0, 0, 0, 255};
21rgb_color rgb_red = {255, 0, 0, 255};
22rgb_color rgb_grey = {216, 216, 216};
23
24int32 hatX[9] = {10, 10, 20, 20, 20, 10, 0, 0, 0};
25int32 hatY[9] = {10, 0, 0, 10, 20, 20, 20, 10, 0};
26
27JoystickWindow::JoystickWindow(const char *deviceName, BJoystick *stick,
28	BRect rect)
29	: BWindow(rect, deviceName, B_TITLED_WINDOW,
30	B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
31{
32	fView = new JoystickView(Bounds(), stick);
33	fView->SetViewColor(rgb_grey);
34	fView->SetLowColor(rgb_grey);
35	ResizeTo(fView->Bounds().Width(), fView->Bounds().Height());
36	AddChild(fView);
37	SetPulseRate(100000.0);
38}
39
40
41bool
42JoystickWindow::QuitRequested(void) {
43	return true;
44}
45
46
47JoystickView::JoystickView(BRect frame, BJoystick *stick)
48	:BView(frame, "jview", B_FOLLOW_ALL_SIDES, B_WILL_DRAW|B_PULSE_NEEDED),
49	fStick(stick)
50{
51	// Set up the controls
52	BString name;
53	fStick->GetControllerName(&name);
54	BRect rect(5, 5, 350, 25);
55	BStringView *stickName = new BStringView(rect, "stickname", name.String());
56	stickName->SetFontSize(18);
57	AddChild(stickName);
58
59	rect = _BuildButtons(stick);
60	rect.top += 15;
61	rect.bottom += 15;
62	rect = _BuildHats(stick, rect);
63	_BuildAxes(stick, rect);
64}
65
66
67JoystickView::~JoystickView() {
68	delete fStick;
69}
70
71
72void
73JoystickView::Pulse(void) {
74	Window()->Lock();
75	Draw(Bounds());
76	Window()->Unlock();
77}
78
79
80void
81JoystickView::Draw(BRect updateRect)
82{
83	int32 numButtons = fStick->CountButtons();
84	int32 numHats = fStick->CountHats();
85	int32 numAxes = fStick->CountAxes();
86	bool *buttons = (bool *) malloc(sizeof(bool) * numButtons);
87	int16 *axes = (int16 *) malloc(sizeof(int16) * numAxes);
88	uint8 *hats = (uint8 *) malloc(numHats);
89	fStick->Update();
90
91	// Buttons first
92	BRect r(105, 50, 115, 60);
93	fStick->GetButtonValues(buttons);
94	for (int32 i = 0; i < numButtons; i++) {
95		if (buttons[i]) {
96			FillRect(r, B_SOLID_HIGH);
97		} else {
98			r.InsetBy(1, 1);
99			FillRect(r, B_SOLID_LOW);
100			r.InsetBy(-1, -1);
101			StrokeRect(r, B_SOLID_HIGH);
102		}
103		r.top += 18;
104		r.bottom += 18;
105	}
106
107	// Now hats
108	fStick->GetHatValues(hats);
109	r.top += 15;
110	r.bottom = r.top + 30;
111	r.left = 105;
112	r.right = r.left + 30;
113	BRect curHatRect;
114	for (int32 i = 0; i < numHats; i++) {
115		BeginLineArray(8);
116		AddLine(r.LeftTop(), r.RightTop(), rgb_black);
117		AddLine(r.LeftTop(), r.LeftBottom(), rgb_black);
118		AddLine(r.RightTop(), r.RightBottom(), rgb_black);
119		AddLine(r.LeftBottom(), r.RightBottom(), rgb_black);
120		AddLine(BPoint(r.left+10, r.top), BPoint(r.left+10, r.bottom),
121			rgb_black);
122		AddLine(BPoint(r.left+20, r.top), BPoint(r.left+20, r.bottom),
123			rgb_black);
124		AddLine(BPoint(r.left, r.top+10), BPoint(r.right, r.top+10),
125			rgb_black);
126		AddLine(BPoint(r.left, r.top+20), BPoint(r.right, r.top+20),
127			rgb_black);
128		EndLineArray();
129		curHatRect.Set(r.left, r.top, r.left+10, r.top+10);
130		curHatRect.OffsetBy(hatX[hats[i]], hatY[hats[i]]);
131		fLastHatRect.InsetBy(1, 1);
132		FillRect(fLastHatRect, B_SOLID_LOW);
133		fLastHatRect = curHatRect;
134		fLastHatRect.InsetBy(1, 1);
135		FillRect(fLastHatRect, B_SOLID_HIGH);
136		fLastHatRect.InsetBy(-1, -1);
137		r.top += 20;
138		r.bottom += 20;
139	}
140
141	// Now the joystick
142	r.Set(200, 50, 350, 200);
143	FillRect(r, B_SOLID_HIGH);
144	fStick->GetAxisValues(axes);
145	float x = axes[0];
146	float y = axes[1];
147	SetHighColor(rgb_red);
148	x += 32768;
149	y -= 32768;
150	x *= 0.0021362304;
151	y *= 0.0021362304;
152	x += 205;
153	y += 195;
154	FillEllipse(BPoint(x,y), 5, 5);
155	SetHighColor(rgb_black);
156
157	// Finally, other axes
158	r.Set(200, 220, 350, 234);
159	for (int32 i = 2; i < numAxes; i++) {
160		FillRect(r, B_SOLID_HIGH);
161		x = axes[i];
162		x += 32768;
163		x *= 0.0021362304;
164		x += 205;
165		BRect thumbRect(x - 3, r.top, x + 3, r.bottom);
166		SetHighColor(rgb_red);
167		FillRoundRect(thumbRect, 3, 3);
168		SetHighColor(rgb_black);
169		r.top += 20;
170		r.bottom += 20;
171	}
172	free(buttons);
173	free(axes);
174	free(hats);
175}
176
177//----------------------- Pragma mark ------------------------------------//
178
179BRect
180JoystickView::_BuildButtons(BJoystick *stick)
181{
182	BString name;
183	int32 numButtons = stick->CountButtons();
184	BRect rect(5, 50, 100, 64);
185	for (int32 i = 0; i < numButtons; i++) {
186		stick->GetButtonNameAt(i, &name);
187		rect = _BuildString(name, "buttonlabel", 18, rect);
188	}
189	return rect;
190}
191
192
193BRect
194JoystickView::_BuildHats(BJoystick *stick, BRect rect)
195{
196	BString name;
197	int32 numHats = stick->CountHats();
198	for (int32 i = 0; i < numHats; i++) {
199		stick->GetHatNameAt(i, &name);
200		rect = _BuildString(name, "hatlabel", 40, rect);
201	}
202	return rect;
203}
204
205
206BRect
207JoystickView::_BuildString(BString name, const char* strName, int number,
208	BRect rect)
209{
210	name.Append(":");
211	BStringView *sview = new BStringView(rect, strName, name.String());
212	sview->SetAlignment(B_ALIGN_RIGHT);
213	sview->SetFont(be_bold_font);
214	AddChild(sview);
215	rect.top += number;
216	rect.bottom += number;
217	return rect;
218}
219
220
221void
222JoystickView::_BuildAxes(BJoystick *stick, BRect rect)
223{
224	float col1bot = rect.bottom - 30;
225	int32 numAxes = stick->CountAxes();
226	// We assume that the first two axes are the x and y axes.
227	rect.Set(130, 50, 195, 64);
228	BStringView *sview = new BStringView(rect, "sticklabel", "Stick:");
229	sview->SetFont(be_bold_font);
230	sview->SetAlignment(B_ALIGN_RIGHT);
231	AddChild(sview);
232
233	BString name;
234	int32 i;
235	// Now make labels for all the solitary axes
236	rect.Set(130, 200, 195, 234);
237	for (i = 2; i < numAxes; i++) {
238		stick->GetAxisNameAt(i, &name);
239		rect = _BuildString(name, "hatlabel", 20, rect);
240	}
241
242	fLastHatRect.Set(0, 0, 0, 0);
243	if (rect.bottom-10 > col1bot) {
244		if (i == 2) {
245			col1bot = 205;
246		} else {
247			col1bot = rect.bottom - 10;
248		}
249	}
250	ResizeTo(355, col1bot);
251}
252