1 /* 2 * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. 3 * Copyright 2010 Adam Smith <adamd.smith@utoronto.ca> 4 * All rights reserved. Distributed under the terms of the MIT License. 5 */ 6 7 #include "PairsView.h" 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 13 #include <Alert.h> 14 #include <Application.h> 15 #include <Bitmap.h> 16 #include <Button.h> 17 #include <Catalog.h> 18 #include <Directory.h> 19 #include <Entry.h> 20 #include <FindDirectory.h> 21 #include <IconUtils.h> 22 #include <List.h> 23 #include <Node.h> 24 #include <NodeInfo.h> 25 #include <Path.h> 26 27 #include "Pairs.h" 28 #include "PairsGlobal.h" 29 #include "PairsTopButton.h" 30 31 PairsView::PairsView(BRect frame, const char* name, int width, int height, 32 uint32 resizingMode) 33 : 34 BView(frame, name, resizingMode, B_WILL_DRAW), 35 fWidth(width), 36 fHeight(height), 37 fNumOfCards(width * height), 38 fRandPos(new int[fNumOfCards]), 39 fPosX(new int[fNumOfCards]), 40 fPosY(new int[fNumOfCards]) 41 { 42 CreateGameBoard(); 43 _SetPairsBoard(); 44 } 45 46 47 void 48 PairsView::CreateGameBoard() 49 { 50 // Show hidden buttons 51 for (int32 i = 0; i < CountChildren(); i++) { 52 BView* child = ChildAt(i); 53 if (child->IsHidden()) 54 child->Show(); 55 } 56 _GenerateCardPos(); 57 } 58 59 60 PairsView::~PairsView() 61 { 62 for (int i = 0; i < fCardBitmaps.CountItems(); i++) 63 delete ((BBitmap*)fCardBitmaps.ItemAt(i)); 64 65 for (int i = 0; i < fDeckCard.CountItems(); i++) 66 delete ((TopButton*)fDeckCard.ItemAt(i)); 67 68 delete fRandPos; 69 delete fPosX; 70 delete fPosY; 71 } 72 73 74 void 75 PairsView::AttachedToWindow() 76 { 77 MakeFocus(true); 78 } 79 80 81 bool 82 PairsView::_HasBitmap(BList& bitmaps, BBitmap* bitmap) 83 { 84 // TODO: if this takes too long, we could build a hash value for each 85 // bitmap in a separate list 86 for (int32 i = bitmaps.CountItems(); i-- > 0;) { 87 BBitmap* item = (BBitmap*)bitmaps.ItemAtFast(i); 88 if (!memcmp(item->Bits(), bitmap->Bits(), item->BitsLength())) 89 return true; 90 } 91 92 return false; 93 } 94 95 #undef B_TRANSLATE_CONTEXT 96 #define B_TRANSLATE_CONTEXT "PairsView" 97 98 void 99 PairsView::_ReadRandomIcons() 100 { 101 // TODO: maybe read the icons only once at startup 102 103 // clean out any previous icons 104 for (int i = 0; i < fCardBitmaps.CountItems(); i++) 105 delete ((BBitmap*)fCardBitmaps.ItemAt(i)); 106 107 fCardBitmaps.MakeEmpty(); 108 109 BDirectory appsDirectory; 110 BDirectory prefsDirectory; 111 112 BPath path; 113 if (find_directory(B_BEOS_APPS_DIRECTORY, &path) == B_OK) 114 appsDirectory.SetTo(path.Path()); 115 if (find_directory(B_BEOS_PREFERENCES_DIRECTORY, &path) == B_OK) 116 prefsDirectory.SetTo(path.Path()); 117 118 // read vector icons from apps and prefs folder and put them 119 // into a BList as BBitmaps 120 BList bitmaps; 121 122 BEntry entry; 123 while (appsDirectory.GetNextEntry(&entry) == B_OK 124 || prefsDirectory.GetNextEntry(&entry) == B_OK) { 125 126 BNode node(&entry); 127 BNodeInfo nodeInfo(&node); 128 129 if (nodeInfo.InitCheck() < B_OK) 130 continue; 131 132 uint8* data; 133 size_t size; 134 type_code type; 135 136 if (nodeInfo.GetIcon(&data, &size, &type) < B_OK) 137 continue; 138 139 if (type != B_VECTOR_ICON_TYPE) { 140 delete[] data; 141 continue; 142 } 143 144 BBitmap* bitmap = new BBitmap( 145 BRect(0, 0, kBitmapSize - 1, kBitmapSize - 1), 0, B_RGBA32); 146 if (BIconUtils::GetVectorIcon(data, size, bitmap) < B_OK) { 147 delete[] data; 148 delete bitmap; 149 continue; 150 } 151 152 delete[] data; 153 154 if (_HasBitmap(bitmaps, bitmap) || !bitmaps.AddItem(bitmap)) 155 delete bitmap; 156 else if (bitmaps.CountItems() >= 128) { 157 // this is enough to choose from, stop eating memory... 158 break; 159 } 160 } 161 162 // pick random bitmaps from the ones we got in the list 163 srand((unsigned)time(0)); 164 165 for (int i = 0; i < fNumOfCards / 2; i++) { 166 int32 index = rand() % bitmaps.CountItems(); 167 BBitmap* bitmap = ((BBitmap*)bitmaps.RemoveItem(index)); 168 if (bitmap == NULL) { 169 char buffer[512]; 170 snprintf(buffer, sizeof(buffer), B_TRANSLATE("Pairs did not find " 171 "enough vector icons in the system; it needs at least %d."), 172 fNumOfCards / 2); 173 BString msgStr(buffer); 174 msgStr << "\n"; 175 BAlert* alert = new BAlert("Fatal", msgStr.String(), 176 B_TRANSLATE("OK"), NULL, NULL, B_WIDTH_FROM_WIDEST, 177 B_STOP_ALERT); 178 alert->SetShortcut(0, B_ESCAPE); 179 alert->Go(); 180 exit(1); 181 } 182 fCardBitmaps.AddItem(bitmap); 183 } 184 185 // delete the remaining bitmaps from the list 186 while (BBitmap* bitmap = (BBitmap*)bitmaps.RemoveItem(0L)) 187 delete bitmap; 188 } 189 190 191 void 192 PairsView::_SetPairsBoard() 193 { 194 for (int i = 0; i < fNumOfCards; i++) { 195 fButtonMessage = new BMessage(kMsgCardButton); 196 fButtonMessage->AddInt32("ButtonNum", i); 197 198 int x = i % fWidth * (kBitmapSize + kSpaceSize) + kSpaceSize; 199 int y = i / fHeight * (kBitmapSize + kSpaceSize) + kSpaceSize; 200 201 TopButton* button = new TopButton(x, y, fButtonMessage); 202 fDeckCard.AddItem(button); 203 AddChild(button); 204 } 205 } 206 207 208 void 209 PairsView::_GenerateCardPos() 210 { 211 _ReadRandomIcons(); 212 213 srand((unsigned)time(0)); 214 215 int* positions = new int[fNumOfCards]; 216 for (int i = 0; i < fNumOfCards; i++) 217 positions[i] = i; 218 219 for (int i = fNumOfCards; i >= 1; i--) { 220 int index = rand() % i; 221 222 fRandPos[fNumOfCards - i] = positions[index]; 223 224 for (int j = index; j < i - 1; j++) 225 positions[j] = positions[j + 1]; 226 } 227 228 for (int i = 0; i < fNumOfCards; i++) { 229 fPosX[i] = (fRandPos[i]) % fWidth * (kBitmapSize + kSpaceSize) 230 + kSpaceSize; 231 fPosY[i] = (fRandPos[i]) / fHeight * (kBitmapSize + kSpaceSize) 232 + kSpaceSize; 233 } 234 235 delete [] positions; 236 } 237 238 239 void 240 PairsView::Draw(BRect updateRect) 241 { 242 SetDrawingMode(B_OP_ALPHA); 243 244 // draw rand pair 1 & 2 245 for (int i = 0; i < fNumOfCards; i++) { 246 BBitmap* bitmap = ((BBitmap*)fCardBitmaps.ItemAt(i % fNumOfCards / 2)); 247 DrawBitmap(bitmap, BPoint(fPosX[i], fPosY[i])); 248 } 249 } 250 251 252 int 253 PairsView::GetIconFromPos(int pos) 254 { 255 return fRandPos[pos]; 256 } 257