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.
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>
21 #include <ObjectList.h>
25 #include <MessageFormat.h>
26 #include <MessageRunner.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
),
59 fPairCardTmpPosition(0),
60 fButtonTmpPosition(0),
73 PairsWindow::~PairsWindow()
75 delete fPairComparing
;
80 PairsWindow::_MakeMenuBar()
82 fMenuBar
= new BMenuBar(BRect(0, 0, 0, 0), "menubar");
85 BMenu
* gameMenu
= new BMenu(B_TRANSLATE("Game"));
86 fMenuBar
->AddItem(gameMenu
);
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)"),
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)"),
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);
144 PairsWindow::_MakeGameView(uint8 rows
, uint8 cols
)
146 BRect viewBounds
= Bounds();
147 viewBounds
.top
= fMenuBar
->Bounds().Height() + 1;
150 BMenuItem
* marked
= fIconSizeMenu
->FindMarked();
151 if (marked
!= NULL
) {
152 switch (fIconSizeMenu
->IndexOf(marked
)) {
154 iconSize
= kSmallIconSize
;
158 iconSize
= kLargeIconSize
;
163 iconSize
= kMediumIconSize
;
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
);
177 PairsWindow::NewGame()
181 fPairsView
->CreateGameBoard();
186 PairsWindow::SetGameSize(uint8 rows
, uint8 cols
)
188 RemoveChild(fPairsView
);
191 _MakeGameView(rows
, cols
);
197 PairsWindow::MessageReceived(BMessage
* message
)
199 switch (message
->what
) {
204 case MENU_DIFFICULTY
:
208 if (message
->FindInt32("rows", &rows
) == B_OK
209 && message
->FindInt32("cols", &cols
) == B_OK
) {
210 SetGameSize(rows
, cols
);
218 if (message
->FindInt32("size", &size
) == B_OK
) {
219 fPairsView
->SetIconSize(size
);
220 _ResizeWindow(fPairsView
->Rows(), fPairsView
->Cols());
227 be_app
->PostMessage(B_QUIT_REQUESTED
);
236 if (message
->FindInt32("button number", &buttonNumber
) != B_OK
)
239 BObjectList
<PairsButton
>* pairsButtonList
240 = fPairsView
->PairsButtonList();
241 if (pairsButtonList
== NULL
)
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
;
257 pairsButtonList
->ItemAt(fButtonPosition
)->Hide();
260 fPairCardTmpPosition
= fPairCardPosition
;
261 fButtonTmpPosition
= fButtonPosition
;
263 delete fPairComparing
;
264 // message of message runner might not have arrived
265 // yet, so it is deleted here to prevent any leaking
267 BMessage
message(kMsgPairComparing
);
268 fPairComparing
= new BMessageRunner(BMessenger(this),
269 &message
, 5 * 100000L, 1);
270 fIsPairsActive
= false;
273 fIsFirstClick
= !fIsFirstClick
;
277 case kMsgPairComparing
:
279 BObjectList
<PairsButton
>* pairsButtonList
280 = fPairsView
->PairsButtonList();
281 if (pairsButtonList
== NULL
)
284 delete fPairComparing
;
285 fPairComparing
= NULL
;
287 fIsPairsActive
= true;
289 if (fPairCardPosition
== fPairCardTmpPosition
)
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"
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",
315 B_TRANSLATE("New game"),
316 B_TRANSLATE("Quit game"));
318 BTextView
* view
= alert
->TextView();
321 view
->SetStylable(true);
323 view
->GetFont(&font
);
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)
334 be_app
->PostMessage(B_QUIT_REQUESTED
);
340 BWindow::MessageReceived(message
);
345 // #pragma mark - PairsWindow private methods
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());