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