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 bool 73 PairsView::_HasBitmap(BList& bitmaps, BBitmap* bitmap) 74 { 75 // TODO: if this takes too long, we could build a hash value for each 76 // bitmap in a separate list 77 for (int32 i = bitmaps.CountItems(); i-- > 0;) { 78 BBitmap* item = (BBitmap*)bitmaps.ItemAtFast(i); 79 if (!memcmp(item->Bits(), bitmap->Bits(), item->BitsLength())) 80 return true; 81 } 82 83 return false; 84 } 85 86 87 void 88 PairsView::_ReadRandomIcons() 89 { 90 // TODO: maybe read the icons only once at startup 91 92 // clean out any previous icons 93 for (int i = 0; i < 8; i++) { 94 delete fCard[i]; 95 fCard[i] = NULL; 96 } 97 98 BDirectory appsDirectory; 99 BDirectory prefsDirectory; 100 101 BPath path; 102 if (find_directory(B_BEOS_APPS_DIRECTORY, &path) == B_OK) 103 appsDirectory.SetTo(path.Path()); 104 if (find_directory(B_BEOS_PREFERENCES_DIRECTORY, &path) == B_OK) 105 prefsDirectory.SetTo(path.Path()); 106 107 // read vector icons from apps and prefs folder and put them 108 // into a BList as BBitmaps 109 BList bitmaps; 110 111 BEntry entry; 112 while (appsDirectory.GetNextEntry(&entry) == B_OK 113 || prefsDirectory.GetNextEntry(&entry) == B_OK) { 114 115 BNode node(&entry); 116 BNodeInfo nodeInfo(&node); 117 118 if (nodeInfo.InitCheck() < B_OK) 119 continue; 120 121 uint8* data; 122 size_t size; 123 type_code type; 124 125 if (nodeInfo.GetIcon(&data, &size, &type) < B_OK) 126 continue; 127 128 if (type != B_VECTOR_ICON_TYPE) { 129 delete[] data; 130 continue; 131 } 132 133 BBitmap* bitmap = new BBitmap( 134 BRect(0, 0, kBitmapSize - 1, kBitmapSize - 1), 0, B_RGBA32); 135 if (BIconUtils::GetVectorIcon(data, size, bitmap) < B_OK) { 136 delete[] data; 137 delete bitmap; 138 continue; 139 } 140 141 delete[] data; 142 143 if (_HasBitmap(bitmaps, bitmap) || !bitmaps.AddItem(bitmap)) 144 delete bitmap; 145 else if (bitmaps.CountItems() >= 128) { 146 // this is enough to choose from, stop eating memory... 147 break; 148 } 149 } 150 151 // pick eight random bitmaps from the ones we got in the list 152 srand((unsigned)time(0)); 153 154 for (int i = 0; i < 8; i++) { 155 int32 index = rand() % bitmaps.CountItems(); 156 fCard[i] = (BBitmap*)bitmaps.RemoveItem(index); 157 if (fCard[i] == NULL) { 158 BAlert* alert = new BAlert("fatal", "Pairs did not find enough " 159 "vector icons in the system, it needs at least eight.", 160 "Oh!", NULL, NULL, B_WIDTH_FROM_WIDEST, B_STOP_ALERT); 161 alert->Go(); 162 exit(1); 163 } 164 } 165 166 // delete the remaining bitmaps from the list 167 while (BBitmap* bitmap = (BBitmap*)bitmaps.RemoveItem(0L)) 168 delete bitmap; 169 } 170 171 172 void 173 PairsView::_SetPairsBoard() 174 { 175 for (int i = 0; i < 16; i++) { 176 fButtonMessage = new BMessage(kMsgCardButton); 177 fButtonMessage->AddInt32("ButtonNum", i); 178 179 int x = i % 4 * (kBitmapSize + 10) + 10; 180 int y = i / 4 * (kBitmapSize + 10) + 10; 181 182 fDeckCard[i] = new TopButton(x, y, fButtonMessage); 183 AddChild(fDeckCard[i]); 184 } 185 } 186 187 188 void 189 PairsView::_GenerateCardPos() 190 { 191 _ReadRandomIcons(); 192 193 srand((unsigned)time(0)); 194 195 int positions[16]; 196 for (int i = 0; i < 16; i++) 197 positions[i] = i; 198 199 for (int i = 16; i >= 1; i--) { 200 int index = rand() % i; 201 202 fRandPos[16-i] = positions[index]; 203 204 for (int j = index; j < i - 1; j++) 205 positions[j] = positions[j + 1]; 206 } 207 208 for (int i = 0; i < 16; i++) { 209 fPosX[i] = (fRandPos[i]) % 4 * (kBitmapSize + 10) + 10; 210 fPosY[i] = (fRandPos[i]) / 4 * (kBitmapSize + 10) + 10; 211 } 212 } 213 214 215 void 216 PairsView::Draw(BRect updateRect) 217 { 218 SetDrawingMode(B_OP_ALPHA); 219 220 // draw rand pair 1 & 2 221 for (int i = 0; i < 16; i++) 222 DrawBitmap(fCard[i % 8], BPoint(fPosX[i], fPosY[i])); 223 } 224 225 226 int 227 PairsView::GetIconFromPos(int pos) 228 { 229 return fRandPos[pos]; 230 } 231