/* * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com. * Copyright 2010 Adam Smith * Copyright 2014 Haiku, Inc. All rights reserved. * * Distributed under the terms of the MIT License. * * Authors: * Ralf Schülke, ralf.schuelke@googlemail.com * John Scipione, jscipione@gmail.com * Adam Smith, adamd.smith@utoronto.ca */ #include "PairsView.h" #include // for srand() and rand() #include #include #include #include #include #include #include #include #include "Pairs.h" #include "PairsButton.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "PairsView" // #pragma mark - PairsView PairsView::PairsView(BRect frame, const char* name, uint8 rows, uint8 cols, uint8 iconSize) : BView(frame, name, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS), fRows(rows), fCols(cols), fIconSize(iconSize), fButtonsCount(rows * cols), fCardsCount(fButtonsCount / 2), fPairsButtonList(new BObjectList(fButtonsCount)), fSmallBitmapsList(new BObjectList(fCardsCount)), fMediumBitmapsList(new BObjectList(fCardsCount)), fLargeBitmapsList(new BObjectList(fCardsCount)), fRandomPosition(new int32[fButtonsCount]), fPositionX(new int32[fButtonsCount]), fPositionY(new int32[fButtonsCount]) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); CreateGameBoard(); _SetPairsBoard(); } void PairsView::CreateGameBoard() { // Show hidden buttons int32 childrenCount = CountChildren(); for (int32 i = 0; i < childrenCount; i++) { BView* child = ChildAt(i); if (child->IsHidden()) child->Show(); } _GenerateCardPositions(); } PairsView::~PairsView() { delete fSmallBitmapsList; delete fMediumBitmapsList; delete fLargeBitmapsList; delete fPairsButtonList; delete[] fRandomPosition; delete[] fPositionX; delete[] fPositionY; } void PairsView::AttachedToWindow() { for (int32 i = 0; i < fButtonsCount; i++) { PairsButton* button = fPairsButtonList->ItemAt(i); if (button != NULL) button->SetTarget(Window()); } MakeFocus(true); BView::AttachedToWindow(); } void PairsView::Draw(BRect updateRect) { BObjectList* bitmapsList; switch (fIconSize) { case kSmallIconSize: bitmapsList = fSmallBitmapsList; break; case kLargeIconSize: bitmapsList = fLargeBitmapsList; break; case kMediumIconSize: default: bitmapsList = fMediumBitmapsList; } for (int32 i = 0; i < fButtonsCount; i++) { SetDrawingMode(B_OP_ALPHA); DrawBitmap(bitmapsList->ItemAt(i % (fButtonsCount / 2)), BPoint(fPositionX[i], fPositionY[i])); SetDrawingMode(B_OP_COPY); } } void PairsView::FrameResized(float newWidth, float newHeight) { int32 spacing = Spacing(); for (int32 i = 0; i < fButtonsCount; i++) { PairsButton* button = fPairsButtonList->ItemAt(i); if (button != NULL) { button->ResizeTo(fIconSize, fIconSize); int32 x = i % fRows * (fIconSize + spacing) + spacing; int32 y = i / fCols * (fIconSize + spacing) + spacing; button->MoveTo(x, y); button->SetFontSize(fIconSize - 15); } } _SetPositions(); Invalidate(BRect(0, 0, newWidth, newHeight)); BView::FrameResized(newWidth, newHeight); } int32 PairsView::GetIconPosition(int32 index) { return fRandomPosition[index]; } // #pragma mark - PairsView private methods void PairsView::_GenerateCardPositions() { // seed the random number generator based on the current timestamp srand((unsigned)time(0)); _ReadRandomIcons(); int32* positions = new int32[fButtonsCount]; for (int32 i = 0; i < fButtonsCount; i++) positions[i] = i; for (int32 i = fButtonsCount; i > 0; i--) { int32 index = rand() % i; fRandomPosition[fButtonsCount - i] = positions[index]; for (int32 j = index; j < i - 1; j++) positions[j] = positions[j + 1]; } delete[] positions; _SetPositions(); } void PairsView::_ReadRandomIcons() { Pairs* app = dynamic_cast(be_app); if (app == NULL) // check if NULL to make Coverity happy return; // Create a copy of the icon map so we can erase elements from it as we // add them to the list eliminating repeated icons without altering the // orginal IconMap. IconMap tmpIconMap(app->GetIconMap()); size_t mapSize = tmpIconMap.size(); if (mapSize < (size_t)fCardsCount) { // not enough icons, we're screwed return; } // clean out any previous icons fSmallBitmapsList->MakeEmpty(); fMediumBitmapsList->MakeEmpty(); fLargeBitmapsList->MakeEmpty(); // pick bitmaps at random from the icon map for (int32 i = 0; i < fCardsCount; i++) { IconMap::iterator iter = tmpIconMap.begin(); if (mapSize < (size_t)fCardsCount) { // not enough valid icons, we're really screwed return; } std::advance(iter, rand() % mapSize); size_t key = iter->first; vector_icon* icon = iter->second; BBitmap* smallBitmap = new BBitmap( BRect(0, 0, kSmallIconSize - 1, kSmallIconSize - 1), B_RGBA32); status_t smallResult = BIconUtils::GetVectorIcon(icon->data, icon->size, smallBitmap); BBitmap* mediumBitmap = new BBitmap( BRect(0, 0, kMediumIconSize - 1, kMediumIconSize - 1), B_RGBA32); status_t mediumResult = BIconUtils::GetVectorIcon(icon->data, icon->size, mediumBitmap); BBitmap* largeBitmap = new BBitmap( BRect(0, 0, kLargeIconSize - 1, kLargeIconSize - 1), B_RGBA32); status_t largeResult = BIconUtils::GetVectorIcon(icon->data, icon->size, largeBitmap); if (smallResult + mediumResult + largeResult == B_OK) { fSmallBitmapsList->AddItem(smallBitmap); fMediumBitmapsList->AddItem(mediumBitmap); fLargeBitmapsList->AddItem(largeBitmap); } else { delete smallBitmap; delete mediumBitmap; delete largeBitmap; i--; } mapSize -= tmpIconMap.erase(key); // remove the element from the map so we don't read it again } } void PairsView::_SetPairsBoard() { int32 spacing = Spacing(); for (int32 i = 0; i < fButtonsCount; i++) { BMessage* buttonMessage = new BMessage(kMsgCardButton); buttonMessage->AddInt32("button number", i); int32 x = i % fRows * (fIconSize + spacing) + spacing; int32 y = i / fCols * (fIconSize + spacing) + spacing; PairsButton* button = new PairsButton(x, y, fIconSize, buttonMessage); fPairsButtonList->AddItem(button); AddChild(button); } } void PairsView::_SetPositions() { int32 spacing = Spacing(); for (int32 i = 0; i < fButtonsCount; i++) { fPositionX[i] = fRandomPosition[i] % fRows * (fIconSize + spacing) + spacing; fPositionY[i] = fRandomPosition[i] / fCols * (fIconSize + spacing) + spacing; } }