/* * 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 "PairsWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "Pairs.h" #include "PairsButton.h" #include "PairsView.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "PairsWindow" const uint32 MENU_NEW = 'MGnw'; const uint32 MENU_DIFFICULTY = 'MGdf'; const uint32 MENU_QUIT = 'MGqu'; const uint32 MENU_ICON_SIZE = 'MSIs'; const uint32 kMsgPairComparing = 'pcom'; // #pragma mark - PairsWindow PairsWindow::PairsWindow() : BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Pairs"), B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE), fPairComparing(NULL), fIsFirstClick(true), fIsPairsActive(true), fPairCardPosition(0), fPairCardTmpPosition(0), fButtonTmpPosition(0), fButtonPosition(0), fButtonClicks(0), fFinishPairs(0), fIconSizeMenu(NULL) { _MakeMenuBar(); _MakeGameView(4, 4); CenterOnScreen(); } PairsWindow::~PairsWindow() { delete fPairComparing; } void PairsWindow::_MakeMenuBar() { fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar"); AddChild(fMenuBar); BMenu* gameMenu = new BMenu(B_TRANSLATE("Game")); fMenuBar->AddItem(gameMenu); BMenuItem* menuItem; BMenu* newMenu = new BMenu(B_TRANSLATE("New")); newMenu->SetRadioMode(true); BMessage* difficultyMessage = new BMessage(MENU_DIFFICULTY); difficultyMessage->AddInt32("rows", 4); difficultyMessage->AddInt32("cols", 4); newMenu->AddItem(menuItem = new BMenuItem(B_TRANSLATE("Beginner (4x4)"), difficultyMessage)); menuItem->SetMarked(true); difficultyMessage = new BMessage(MENU_DIFFICULTY); difficultyMessage->AddInt32("rows", 6); difficultyMessage->AddInt32("cols", 6); newMenu->AddItem(new BMenuItem(B_TRANSLATE("Intermediate (6x6)"), difficultyMessage)); difficultyMessage = new BMessage(MENU_DIFFICULTY); difficultyMessage->AddInt32("rows", 8); difficultyMessage->AddInt32("cols", 8); newMenu->AddItem(new BMenuItem(B_TRANSLATE("Expert (8x8)"), difficultyMessage)); menuItem = new BMenuItem(newMenu, new BMessage(MENU_NEW)); menuItem->SetShortcut('N', B_COMMAND_KEY); gameMenu->AddItem(menuItem); gameMenu->AddSeparatorItem(); gameMenu->AddItem(new BMenuItem(B_TRANSLATE("Quit"), new BMessage(MENU_QUIT), 'Q')); fIconSizeMenu = new BMenu(B_TRANSLATE("Size")); fIconSizeMenu->SetRadioMode(true); fMenuBar->AddItem(fIconSizeMenu); BMessage* iconSizeMessage = new BMessage(MENU_ICON_SIZE); iconSizeMessage->AddInt32("size", kSmallIconSize); fIconSizeMenu->AddItem(new BMenuItem( B_TRANSLATE("Small"), iconSizeMessage), 0); iconSizeMessage = new BMessage(MENU_ICON_SIZE); iconSizeMessage->AddInt32("size", kMediumIconSize); fIconSizeMenu->AddItem(menuItem = new BMenuItem( B_TRANSLATE("Medium"), iconSizeMessage), 1); menuItem->SetMarked(true); iconSizeMessage = new BMessage(MENU_ICON_SIZE); iconSizeMessage->AddInt32("size", kLargeIconSize); fIconSizeMenu->AddItem(new BMenuItem( B_TRANSLATE("Large"), iconSizeMessage), 2); } void PairsWindow::_MakeGameView(uint8 rows, uint8 cols) { BRect viewBounds = Bounds(); viewBounds.top = fMenuBar->Bounds().Height() + 1; uint8 iconSize; BMenuItem* marked = fIconSizeMenu->FindMarked(); if (marked != NULL) { switch (fIconSizeMenu->IndexOf(marked)) { case 0: iconSize = kSmallIconSize; break; case 2: iconSize = kLargeIconSize; break; case 1: default: iconSize = kMediumIconSize; } } else { iconSize = kMediumIconSize; fIconSizeMenu->ItemAt(1)->SetMarked(true); } fPairsView = new PairsView(viewBounds, "PairsView", rows, cols, iconSize); AddChild(fPairsView); _ResizeWindow(rows, cols); } void PairsWindow::NewGame() { fButtonClicks = 0; fFinishPairs = 0; fIsFirstClick = true; fPairsView->CreateGameBoard(); } void PairsWindow::SetGameSize(uint8 rows, uint8 cols) { RemoveChild(fPairsView); delete fPairsView; _MakeGameView(rows, cols); NewGame(); } void PairsWindow::MessageReceived(BMessage* message) { switch (message->what) { case MENU_NEW: NewGame(); break; case MENU_DIFFICULTY: { int32 rows; int32 cols; if (message->FindInt32("rows", &rows) == B_OK && message->FindInt32("cols", &cols) == B_OK) { SetGameSize(rows, cols); } break; } case MENU_ICON_SIZE: { int32 size; if (message->FindInt32("size", &size) == B_OK) { fPairsView->SetIconSize(size); _ResizeWindow(fPairsView->Rows(), fPairsView->Cols()); } break; } case MENU_QUIT: be_app->PostMessage(B_QUIT_REQUESTED); break; case kMsgCardButton: { if (!fIsPairsActive) break; int32 buttonNumber; if (message->FindInt32("button number", &buttonNumber) != B_OK) break; BObjectList* pairsButtonList = fPairsView->PairsButtonList(); if (pairsButtonList == NULL) break; // look at what icon is behind a button int32 buttonCount = pairsButtonList->CountItems(); for (int32 i = 0; i < buttonCount; i++) { int32 iconPosition = fPairsView->GetIconPosition(i); if (iconPosition == buttonNumber) { fPairCardPosition = i % (buttonCount / 2); fButtonPosition = iconPosition; break; } } // gameplay fButtonClicks++; pairsButtonList->ItemAt(fButtonPosition)->Hide(); if (fIsFirstClick) { fPairCardTmpPosition = fPairCardPosition; fButtonTmpPosition = fButtonPosition; } else { delete fPairComparing; // message of message runner might not have arrived // yet, so it is deleted here to prevent any leaking // just in case BMessage message(kMsgPairComparing); fPairComparing = new BMessageRunner(BMessenger(this), &message, 5 * 100000L, 1); fIsPairsActive = false; } fIsFirstClick = !fIsFirstClick; break; } case kMsgPairComparing: { BObjectList* pairsButtonList = fPairsView->PairsButtonList(); if (pairsButtonList == NULL) break; delete fPairComparing; fPairComparing = NULL; fIsPairsActive = true; if (fPairCardPosition == fPairCardTmpPosition) fFinishPairs++; else { pairsButtonList->ItemAt(fButtonPosition)->Show(); pairsButtonList->ItemAt(fButtonTmpPosition)->Show(); } // game end and results if (fFinishPairs == pairsButtonList->CountItems() / 2) { BString strAbout = B_TRANSLATE("%app%\n" "\twritten by Ralf Schülke\n" "\tCopyright 2008-2010, Haiku Inc.\n" "\n"); strAbout.ReplaceFirst("%app%", B_TRANSLATE_SYSTEM_NAME("Pairs")); // Note: in english the singular form is never used, but other // languages behave differently. static BStringFormat format(B_TRANSLATE( "You completed the game in " "{0, plural, one{# click} other{# clicks}}.\n")); format.Format(strAbout, fButtonClicks); BAlert* alert = new BAlert("about", strAbout.String(), B_TRANSLATE("New game"), B_TRANSLATE("Quit game")); BTextView* view = alert->TextView(); BFont font; view->SetStylable(true); view->GetFont(&font); font.SetSize(18); font.SetFace(B_BOLD_FACE); view->SetFontAndColor(0, strlen(B_TRANSLATE_SYSTEM_NAME("Pairs")), &font); view->ResizeToPreferred(); alert->SetShortcut(0, B_ESCAPE); if (alert->Go() == 0) NewGame(); else be_app->PostMessage(B_QUIT_REQUESTED); } break; } default: BWindow::MessageReceived(message); } } // #pragma mark - PairsWindow private methods void PairsWindow::_ResizeWindow(uint8 rows, uint8 cols) { int32 iconSize = fPairsView->IconSize(); int32 spacing = fPairsView->Spacing(); ResizeTo((iconSize + spacing) * rows + spacing, (iconSize + spacing) * cols + spacing + fMenuBar->Bounds().Height()); }