xref: /haiku/src/apps/pairs/PairsView.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
1 /*
2  * Copyright 2008, Ralf Schülke, teammaui@web.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "PairsView.h"
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 
11 #include <Alert.h>
12 #include <Application.h>
13 #include <Bitmap.h>
14 #include <Button.h>
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <FindDirectory.h>
18 #include <IconUtils.h>
19 #include <List.h>
20 #include <Node.h>
21 #include <NodeInfo.h>
22 #include <Path.h>
23 
24 #include "Pairs.h"
25 #include "PairsGlobal.h"
26 #include "PairsTopButton.h"
27 
28 // TODO: support custom board sizes
29 
30 PairsView::PairsView(BRect frame, const char* name, uint32 resizingMode)
31 	: BView(frame, name, resizingMode, B_WILL_DRAW)
32 {
33 	// init bitmap pointers
34 	for (int i = 0; i < 8; i++)
35 		fCard[i] = NULL;
36 
37 	CreateGameBoard();
38 	_SetPairsBoard();
39 }
40 
41 
42 void
43 PairsView::CreateGameBoard()
44 {
45 	// Show hidden buttons
46 	for (int32 i = 0; i < CountChildren(); i++) {
47 		BView* child = ChildAt(i);
48 		if (child->IsHidden())
49 			child->Show();
50 	}
51 	_GenerateCardPos();
52 }
53 
54 
55 PairsView::~PairsView()
56 {
57 	for (int i = 0; i < 8; i++)
58 		delete fCard[i];
59 
60 	for (int i = 0; i < 16; i++)
61 		delete fDeckCard[i];
62 }
63 
64 
65 void
66 PairsView::AttachedToWindow()
67 {
68 	MakeFocus(true);
69 }
70 
71 
72 void
73 PairsView::_ReadRandomIcons()
74 {
75 	// TODO: maybe read the icons only once at startup
76 
77 	// clean out any previous icons
78 	for (int i = 0; i < 8; i++) {
79 		delete fCard[i];
80 		fCard[i] = NULL;
81 	}
82 
83 	BDirectory appsDirectory;
84 	BDirectory prefsDirectory;
85 
86 	BPath path;
87 	if (find_directory(B_BEOS_APPS_DIRECTORY, &path) == B_OK)
88 		appsDirectory.SetTo(path.Path());
89 	if (find_directory(B_BEOS_PREFERENCES_DIRECTORY, &path) == B_OK)
90 		prefsDirectory.SetTo(path.Path());
91 
92 	// read vector icons from apps and prefs folder and put them
93 	// into a BList as BBitmaps
94 	BList bitmaps;
95 
96 	BEntry entry;
97 	while (appsDirectory.GetNextEntry(&entry) == B_OK
98 		|| prefsDirectory.GetNextEntry(&entry) == B_OK) {
99 
100 		BNode node(&entry);
101 		BNodeInfo nodeInfo(&node);
102 
103 		if (nodeInfo.InitCheck() < B_OK)
104 			continue;
105 
106 		uint8* data;
107 		size_t size;
108 		type_code type;
109 
110 		if (nodeInfo.GetIcon(&data, &size, &type) < B_OK)
111 			continue;
112 
113 		if (type != B_VECTOR_ICON_TYPE) {
114 			delete[] data;
115 			continue;
116 		}
117 
118 		BBitmap* bitmap = new BBitmap(
119 			BRect(0, 0, kBitmapSize - 1, kBitmapSize - 1), 0, B_RGBA32);
120 		if (BIconUtils::GetVectorIcon(data, size, bitmap) < B_OK) {
121 			delete[] data;
122 			delete bitmap;
123 			continue;
124 		}
125 
126 		delete[] data;
127 
128 		if (!bitmaps.AddItem(bitmap))
129 			delete bitmap;
130 
131 		if (bitmaps.CountItems() >= 128) {
132 			// this is enough to choose from, stop eating memory...
133 			break;
134 		}
135 	}
136 
137 	// pick eight random bitmaps from the ones we got in the list
138 	srand((unsigned)time(0));
139 
140 	for (int i = 0; i < 8; i++) {
141 		int32 index = rand() % bitmaps.CountItems();
142 		fCard[i] = (BBitmap*)bitmaps.RemoveItem(index);
143 		if (fCard[i] == NULL) {
144 			BAlert* alert = new BAlert("fatal", "Pairs did not find enough "
145 				"vector icons in the system, it needs at least eight.",
146 				"Oh!", NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT);
147 			alert->Go();
148 			exit(1);
149 		}
150 	}
151 
152 	// delete the remaining bitmaps from the list
153 	while (BBitmap* bitmap = (BBitmap*)bitmaps.RemoveItem(0L))
154 		delete bitmap;
155 }
156 
157 
158 void
159 PairsView::_SetPairsBoard()
160 {
161 	for (int i = 0; i < 16; i++) {
162 		fButtonMessage = new BMessage(kMsgCardButton);
163 		fButtonMessage->AddInt32("ButtonNum", i);
164 
165 		int x =  i % 4 * (kBitmapSize + 10) + 10;
166 		int y =  i / 4 * (kBitmapSize + 10) + 10;
167 
168 		fDeckCard[i] = new TopButton(x, y, fButtonMessage);
169 		AddChild(fDeckCard[i]);
170 	}
171 }
172 
173 
174 void
175 PairsView::_GenerateCardPos()
176 {
177 	_ReadRandomIcons();
178 
179 	srand((unsigned)time(0));
180 
181 	int positions[16];
182 	for (int i = 0; i < 16; i++)
183 		positions[i] = i;
184 
185 	for (int i = 16; i >= 1; i--) {
186 		int index = rand() % i;
187 
188 		fRandPos[16-i] = positions[index];
189 
190 		for (int j = index; j < i - 1; j++)
191 			positions[j] = positions[j + 1];
192 	}
193 
194 	for (int i = 0; i < 16; i++) {
195 		fPosX[i] = (fRandPos[i]) % 4 * (kBitmapSize + 10) + 10;
196 		fPosY[i] = (fRandPos[i]) / 4 * (kBitmapSize + 10) + 10;
197 	}
198 }
199 
200 
201 void
202 PairsView::Draw(BRect updateRect)
203 {
204 	SetDrawingMode(B_OP_ALPHA);
205 
206 	// draw rand pair 1 & 2
207 	for (int i = 0; i < 16; i++)
208 		DrawBitmap(fCard[i % 8], BPoint(fPosX[i], fPosY[i]));
209 }
210 
211 
212 int
213 PairsView::GetIconFromPos(int pos)
214 {
215 	return fRandPos[pos];
216 }
217