275 lines
6.5 KiB
C++
275 lines
6.5 KiB
C++
/*
|
|
* Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
|
|
* Copyright 2010 Adam Smith <adamd.smith@utoronto.ca>
|
|
* 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 <stdlib.h>
|
|
// for srand() and rand()
|
|
|
|
#include <Application.h>
|
|
#include <Bitmap.h>
|
|
#include <Button.h>
|
|
#include <ControlLook.h>
|
|
#include <Catalog.h>
|
|
#include <IconUtils.h>
|
|
#include <InterfaceDefs.h>
|
|
#include <Window.h>
|
|
|
|
#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<PairsButton>(fButtonsCount)),
|
|
fSmallBitmapsList(new BObjectList<BBitmap>(fCardsCount)),
|
|
fMediumBitmapsList(new BObjectList<BBitmap>(fCardsCount)),
|
|
fLargeBitmapsList(new BObjectList<BBitmap>(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<BBitmap>* 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<Pairs*>(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;
|
|
}
|
|
}
|