repository_infos: Enable automatic updates on the main Haiku repostiory.
[haiku.git] / src / apps / pairs / PairsWindow.cpp
blobe0379e023ff37337b32163515b89c14dbb74fd90
1 /*
2 * Copyright 2008 Ralf Schülke, ralf.schuelke@googlemail.com.
3 * Copyright 2010 Adam Smith <adamd.smith@utoronto.ca>
4 * Copyright 2014 Haiku, Inc. All rights reserved.
6 * Distributed under the terms of the MIT License.
8 * Authors:
9 * Ralf Schülke, ralf.schuelke@googlemail.com
10 * John Scipione, jscipione@gmail.com
11 * Adam Smith, adamd.smith@utoronto.ca
15 #include "PairsWindow.h"
17 #include <Application.h>
18 #include <Alert.h>
19 #include <Button.h>
20 #include <Catalog.h>
21 #include <ObjectList.h>
22 #include <Menu.h>
23 #include <MenuBar.h>
24 #include <MenuItem.h>
25 #include <MessageFormat.h>
26 #include <MessageRunner.h>
27 #include <String.h>
28 #include <TextView.h>
30 #include "Pairs.h"
31 #include "PairsButton.h"
32 #include "PairsView.h"
35 #undef B_TRANSLATION_CONTEXT
36 #define B_TRANSLATION_CONTEXT "PairsWindow"
39 const uint32 MENU_NEW = 'MGnw';
40 const uint32 MENU_DIFFICULTY = 'MGdf';
41 const uint32 MENU_QUIT = 'MGqu';
42 const uint32 MENU_ICON_SIZE = 'MSIs';
44 const uint32 kMsgPairComparing = 'pcom';
47 // #pragma mark - PairsWindow
50 PairsWindow::PairsWindow()
52 BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_SYSTEM_NAME("Pairs"),
53 B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
54 | B_NOT_RESIZABLE | B_NOT_ZOOMABLE),
55 fPairComparing(NULL),
56 fIsFirstClick(true),
57 fIsPairsActive(true),
58 fPairCardPosition(0),
59 fPairCardTmpPosition(0),
60 fButtonTmpPosition(0),
61 fButtonPosition(0),
62 fButtonClicks(0),
63 fFinishPairs(0),
64 fIconSizeMenu(NULL)
66 _MakeMenuBar();
67 _MakeGameView(4, 4);
69 CenterOnScreen();
73 PairsWindow::~PairsWindow()
75 delete fPairComparing;
79 void
80 PairsWindow::_MakeMenuBar()
82 fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar");
83 AddChild(fMenuBar);
85 BMenu* gameMenu = new BMenu(B_TRANSLATE("Game"));
86 fMenuBar->AddItem(gameMenu);
88 BMenuItem* menuItem;
90 BMenu* newMenu = new BMenu(B_TRANSLATE("New"));
91 newMenu->SetRadioMode(true);
93 BMessage* difficultyMessage = new BMessage(MENU_DIFFICULTY);
94 difficultyMessage->AddInt32("rows", 4);
95 difficultyMessage->AddInt32("cols", 4);
96 newMenu->AddItem(menuItem = new BMenuItem(B_TRANSLATE("Beginner (4x4)"),
97 difficultyMessage));
98 menuItem->SetMarked(true);
100 difficultyMessage = new BMessage(MENU_DIFFICULTY);
101 difficultyMessage->AddInt32("rows", 6);
102 difficultyMessage->AddInt32("cols", 6);
103 newMenu->AddItem(menuItem = new BMenuItem(
104 B_TRANSLATE("Intermediate (6x6)"), difficultyMessage));
106 difficultyMessage = new BMessage(MENU_DIFFICULTY);
107 difficultyMessage->AddInt32("rows", 8);
108 difficultyMessage->AddInt32("cols", 8);
109 newMenu->AddItem(menuItem = new BMenuItem(B_TRANSLATE("Expert (8x8)"),
110 difficultyMessage));
112 menuItem = new BMenuItem(newMenu, new BMessage(MENU_NEW));
113 menuItem->SetShortcut('N', B_COMMAND_KEY);
114 gameMenu->AddItem(menuItem);
116 gameMenu->AddSeparatorItem();
118 gameMenu->AddItem(menuItem = new BMenuItem(B_TRANSLATE("Quit"),
119 new BMessage(MENU_QUIT), 'Q'));
121 fIconSizeMenu = new BMenu(B_TRANSLATE("Size"));
122 fIconSizeMenu->SetRadioMode(true);
123 fMenuBar->AddItem(fIconSizeMenu);
125 BMessage* iconSizeMessage = new BMessage(MENU_ICON_SIZE);
126 iconSizeMessage->AddInt32("size", kSmallIconSize);
127 fIconSizeMenu->AddItem(menuItem = new BMenuItem(
128 B_TRANSLATE("Small"), iconSizeMessage), 0);
130 iconSizeMessage = new BMessage(MENU_ICON_SIZE);
131 iconSizeMessage->AddInt32("size", kMediumIconSize);
132 fIconSizeMenu->AddItem(menuItem = new BMenuItem(
133 B_TRANSLATE("Medium"), iconSizeMessage), 1);
134 menuItem->SetMarked(true);
136 iconSizeMessage = new BMessage(MENU_ICON_SIZE);
137 iconSizeMessage->AddInt32("size", kLargeIconSize);
138 fIconSizeMenu->AddItem(menuItem = new BMenuItem(
139 B_TRANSLATE("Large"), iconSizeMessage), 2);
143 void
144 PairsWindow::_MakeGameView(uint8 rows, uint8 cols)
146 BRect viewBounds = Bounds();
147 viewBounds.top = fMenuBar->Bounds().Height() + 1;
149 uint8 iconSize;
150 BMenuItem* marked = fIconSizeMenu->FindMarked();
151 if (marked != NULL) {
152 switch (fIconSizeMenu->IndexOf(marked)) {
153 case 0:
154 iconSize = kSmallIconSize;
155 break;
157 case 2:
158 iconSize = kLargeIconSize;
159 break;
161 case 1:
162 default:
163 iconSize = kMediumIconSize;
165 } else {
166 iconSize = kMediumIconSize;
167 fIconSizeMenu->ItemAt(1)->SetMarked(true);
170 fPairsView = new PairsView(viewBounds, "PairsView", rows, cols, iconSize);
171 AddChild(fPairsView);
172 _ResizeWindow(rows, cols);
176 void
177 PairsWindow::NewGame()
179 fButtonClicks = 0;
180 fFinishPairs = 0;
181 fPairsView->CreateGameBoard();
185 void
186 PairsWindow::SetGameSize(uint8 rows, uint8 cols)
188 RemoveChild(fPairsView);
189 delete fPairsView;
191 _MakeGameView(rows, cols);
192 NewGame();
196 void
197 PairsWindow::MessageReceived(BMessage* message)
199 switch (message->what) {
200 case MENU_NEW:
201 NewGame();
202 break;
204 case MENU_DIFFICULTY:
206 int32 rows;
207 int32 cols;
208 if (message->FindInt32("rows", &rows) == B_OK
209 && message->FindInt32("cols", &cols) == B_OK) {
210 SetGameSize(rows, cols);
212 break;
215 case MENU_ICON_SIZE:
217 int32 size;
218 if (message->FindInt32("size", &size) == B_OK) {
219 fPairsView->SetIconSize(size);
220 _ResizeWindow(fPairsView->Rows(), fPairsView->Cols());
223 break;
226 case MENU_QUIT:
227 be_app->PostMessage(B_QUIT_REQUESTED);
228 break;
230 case kMsgCardButton:
232 if (!fIsPairsActive)
233 break;
235 int32 buttonNumber;
236 if (message->FindInt32("button number", &buttonNumber) != B_OK)
237 break;
239 BObjectList<PairsButton>* pairsButtonList
240 = fPairsView->PairsButtonList();
241 if (pairsButtonList == NULL)
242 break;
244 // look at what icon is behind a button
245 int32 buttonCount = pairsButtonList->CountItems();
246 for (int32 i = 0; i < buttonCount; i++) {
247 int32 iconPosition = fPairsView->GetIconPosition(i);
248 if (iconPosition == buttonNumber) {
249 fPairCardPosition = i % (buttonCount / 2);
250 fButtonPosition = iconPosition;
251 break;
255 // gameplay
256 fButtonClicks++;
257 pairsButtonList->ItemAt(fButtonPosition)->Hide();
259 if (fIsFirstClick) {
260 fPairCardTmpPosition = fPairCardPosition;
261 fButtonTmpPosition = fButtonPosition;
262 } else {
263 delete fPairComparing;
264 // message of message runner might not have arrived
265 // yet, so it is deleted here to prevent any leaking
266 // just in case
267 BMessage message(kMsgPairComparing);
268 fPairComparing = new BMessageRunner(BMessenger(this),
269 &message, 5 * 100000L, 1);
270 fIsPairsActive = false;
273 fIsFirstClick = !fIsFirstClick;
274 break;
277 case kMsgPairComparing:
279 BObjectList<PairsButton>* pairsButtonList
280 = fPairsView->PairsButtonList();
281 if (pairsButtonList == NULL)
282 break;
284 delete fPairComparing;
285 fPairComparing = NULL;
287 fIsPairsActive = true;
289 if (fPairCardPosition == fPairCardTmpPosition)
290 fFinishPairs++;
291 else {
292 pairsButtonList->ItemAt(fButtonPosition)->Show();
293 pairsButtonList->ItemAt(fButtonTmpPosition)->Show();
296 // game end and results
297 if (fFinishPairs == pairsButtonList->CountItems() / 2) {
298 BString strAbout = B_TRANSLATE("%app%\n"
299 "\twritten by Ralf Schülke\n"
300 "\tCopyright 2008-2010, Haiku Inc.\n"
301 "\n");
303 strAbout.ReplaceFirst("%app%",
304 B_TRANSLATE_SYSTEM_NAME("Pairs"));
306 // Note: in english the singular form is never used, but other
307 // languages behave differently.
308 static BMessageFormat format(B_TRANSLATE(
309 "You completed the game in "
310 "{0, plural, one{# click} other{# clicks}}.\n"));
311 format.Format(strAbout, fButtonClicks);
313 BAlert* alert = new BAlert("about",
314 strAbout.String(),
315 B_TRANSLATE("New game"),
316 B_TRANSLATE("Quit game"));
318 BTextView* view = alert->TextView();
319 BFont font;
321 view->SetStylable(true);
323 view->GetFont(&font);
324 font.SetSize(18);
325 font.SetFace(B_BOLD_FACE);
326 view->SetFontAndColor(0,
327 strlen(B_TRANSLATE_SYSTEM_NAME("Pairs")), &font);
328 view->ResizeToPreferred();
329 alert->SetShortcut(0, B_ESCAPE);
331 if (alert->Go() == 0)
332 NewGame();
333 else
334 be_app->PostMessage(B_QUIT_REQUESTED);
336 break;
339 default:
340 BWindow::MessageReceived(message);
345 // #pragma mark - PairsWindow private methods
348 void
349 PairsWindow::_ResizeWindow(uint8 rows, uint8 cols)
351 int32 iconSize = fPairsView->IconSize();
352 int32 spacing = fPairsView->Spacing();
354 ResizeTo((iconSize + spacing) * rows + spacing,
355 (iconSize + spacing) * cols + spacing + fMenuBar->Bounds().Height());