source: trunk/OpenYahtzee/src/MainFrame.cpp @ 87

Last change on this file since 87 was 87, checked in by guyru, 6 years ago

added new horizontal layout.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.4 KB
Line 
1// $Header$
2/***************************************************************************
3 *   Copyright (C) 2006 by Guy Rutenberg   *
4 *   guyrutenberg@gmail.com   *
5 *                                                                         *
6 *   This program is free software; you can redistribute it and/or modify  *
7 *   it under the terms of the GNU General Public License as published by  *
8 *   the Free Software Foundation; either version 2 of the License, or     *
9 *   (at your option) any later version.                                   *
10 *                                                                         *
11 *   This program is distributed in the hope that it will be useful,       *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14 *   GNU General Public License for more details.                          *
15 *                                                                         *
16 *   You should have received a copy of the GNU General Public License     *
17 *   along with this program; if not, write to the                         *
18 *   Free Software Foundation, Inc.,                                       *
19 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
20 ***************************************************************************/
21
22 /***********************************************
23 *      This File contains the definitions      *
24 *      of MainFrame's functions                *
25 ***********************************************/
26
27// #define DEBUG
28
29#include <wx/wx.h>
30
31#include "MainFrame.h"
32#include "wxDynamicBitmap.h"
33#include "ObjectsID.h"
34#include "HighScoreDialog.h"
35#include "SettingsDialog.h"
36#include "About.h"
37#include "UtilityFunctions.h"
38#include <iostream>
39#include <sstream>
40#include <cstdlib>
41#include <wx/version.h>
42
43//include the images for the dice
44#include "one.xpm"
45#include "two.xpm"
46#include "three.xpm"
47#include "four.xpm"
48#include "five.xpm"
49#include "six.xpm"
50
51//include the icon file
52#include "Icon.h"
53
54//default values
55#define SPACE_SIZE 1
56#define DEF_HIGHSCORESIZE 20
57#define OY_VERSION "1.7.0"
58
59DEFINE_EVENT_TYPE(wxEVT_ENABLE_ROLL)
60
61
62MainFrame::MainFrame(const wxString& title, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE)
63        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, size, style)
64{
65        //give the frame an icon
66        SetIcon(wxIcon(ICON));
67
68
69        std::ostringstream sstr;
70
71        m_settingsdb = new SettingsDB(); //Get the settings database connection
72        m_highscoredb = new HighScoreTableDB();
73       
74        InitializeDatabase();//this must come _after_ m_settingsdb and m_highscoredb are created
75
76        bitmap_dices[0] = new wxBitmap(one_xpm);
77        bitmap_dices[1] = new wxBitmap(two_xpm);
78        bitmap_dices[2] = new wxBitmap(three_xpm);
79        bitmap_dices[3] = new wxBitmap(four_xpm);
80        bitmap_dices[4] = new wxBitmap(five_xpm);
81        bitmap_dices[5] = new wxBitmap(six_xpm);
82       
83        //randomize the random-number generator based on the time
84        srand( (unsigned)time( NULL ) );
85
86
87        /*****Create and initialize the menu bar******/
88
89        /*Create the menus*/
90        wxMenu *gameMenu = new wxMenu;  //create File menu
91        wxMenu *helpMenu = new wxMenu;  //create Help menu
92       
93       
94        //insert menu items into menu Help
95        helpMenu->Append(ID_CHECK_FOR_UPDATES, wxT("&Check for Updates"),
96                        wxT("Check for new version of the game via the web"));
97        helpMenu->AppendSeparator();
98        helpMenu->Append(ID_SENDCOMMENT, wxT("&Send a Comment to Developers"),
99                        wxT("Send a comment to the developers of the game"));
100        helpMenu->AppendSeparator();
101        helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
102                        wxT("Show about dialog"));
103
104        //insert menu items into menu File
105        gameMenu->Append(ID_NEWGAME,wxT("&New Game\tF2"),wxT("Start a new game"));
106        //create the undo button and make it disabled
107        gameMenu->Append(ID_UNDO,wxT("&Undo\tCTRL+Z"),wxT("Undo the last move"));
108        gameMenu->Append(ID_SHOWHIGHSCORE,wxT("High &Scores"),wxT("Show high-scores table"));
109        gameMenu->Append(ID_SETTINGS,wxT("Settings"),wxT("Show settings dialog"));
110        gameMenu->Append(wxID_EXIT, wxT("E&xit\tAlt-X"),
111                        wxT("Quit this program"));
112       
113        // Declare the menu-bar and append the freshly created menus to the menu bar...
114        wxMenuBar *menuBar = new wxMenuBar();
115        menuBar->Append(gameMenu, wxT("&Game"));
116        menuBar->Append(helpMenu, wxT("&Help"));
117       
118        // ... and attach this menu bar to the frame
119        SetMenuBar(menuBar);
120       
121        /***End menu-bar ***/
122        wxPanel* panel = new wxPanel(this, ID_PANEL,
123                wxDefaultPosition, wxDefaultSize);
124        m_horizontallayout = 0; //TODO remove this line
125        wxBoxSizer *topSizer;
126        wxBoxSizer *sectionsSizer;
127        wxFlexGridSizer *diceSizer;
128        if (m_horizontallayout) {
129                topSizer = new wxBoxSizer( wxVERTICAL );
130                sectionsSizer = new wxBoxSizer( wxHORIZONTAL );
131                diceSizer = new wxFlexGridSizer(2, 0, 0, 0);
132        } else {
133                topSizer = new wxBoxSizer( wxHORIZONTAL );
134                sectionsSizer = new wxBoxSizer( wxVERTICAL );
135                diceSizer = new wxFlexGridSizer(1, 0, 0);;
136        }
137
138        wxSizer *uppersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Upper Section") ), wxVERTICAL);
139        wxSizer *lowersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Lower Section") ), wxVERTICAL);
140       
141        wxFlexGridSizer* uppergrid = new wxFlexGridSizer(2, 0, 10);
142        wxFlexGridSizer* lowergrid = new wxFlexGridSizer(2, 0, 10);
143
144        //BEGIN layout for the upper section of the score board
145        uppergrid->Add(new wxButton(panel,ID_ACES,wxT("Aces")),0,wxALL,SPACE_SIZE);
146        uppergrid->Add(new wxTextCtrl(panel, ID_ACESTEXT),1,wxALL,SPACE_SIZE);
147        uppergrid->Add(new wxButton(panel,ID_TWOS,wxT("Twos")),0,wxALL,SPACE_SIZE);
148        uppergrid->Add(new wxTextCtrl(panel, ID_TWOSTEXT),1,wxALL,SPACE_SIZE);
149        uppergrid->Add(new wxButton(panel,ID_THREES,wxT("Threes")),0,wxALL,SPACE_SIZE);
150        uppergrid->Add(new wxTextCtrl(panel, ID_THREESTEXT),1,wxALL,SPACE_SIZE);
151        uppergrid->Add(new wxButton(panel,ID_FOURS,wxT("Fours")),0,wxALL,SPACE_SIZE);
152        uppergrid->Add(new wxTextCtrl(panel, ID_FOURSTEXT),1,wxALL,SPACE_SIZE);
153        uppergrid->Add(new wxButton(panel,ID_FIVES,wxT("Fives")),0,wxALL,SPACE_SIZE);
154        uppergrid->Add(new wxTextCtrl(panel, ID_FIVESTEXT),1,wxALL,SPACE_SIZE);
155        uppergrid->Add(new wxButton(panel,ID_SIXES,wxT("Sixes")),0,wxALL,SPACE_SIZE);
156        uppergrid->Add(new wxTextCtrl(panel, ID_SIXESTEXT),1,wxALL,SPACE_SIZE);
157        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total score:")),0,wxALL,SPACE_SIZE);
158        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERSECTIONTOTAL),1,wxALL,SPACE_SIZE);
159        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Bonus:")),0,wxALL,SPACE_SIZE);
160        uppergrid->Add(new wxTextCtrl(panel, ID_BONUS),1,wxALL,SPACE_SIZE);
161        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of upper section:")),0,wxALL,SPACE_SIZE);
162        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERTOTAL),1,wxALL,SPACE_SIZE);
163        //END layout for the upper section of the score board
164
165        //BEGIN layout for the lower section of the score board
166        lowergrid->Add(new wxButton(panel,ID_THREEOFAKIND,wxT("3 of a kind")),0,wxALL,SPACE_SIZE);
167        lowergrid->Add(new wxTextCtrl(panel, ID_THREEOFAKINDTEXT),1,wxALL,SPACE_SIZE);
168        lowergrid->Add(new wxButton(panel,ID_FOUROFAKIND,wxT("4 of a kind")),0,wxALL,SPACE_SIZE);
169        lowergrid->Add(new wxTextCtrl(panel, ID_FOUROFAKINDTEXT),1,wxALL,SPACE_SIZE);
170        lowergrid->Add(new wxButton(panel,ID_FULLHOUSE,wxT("Full House")),0,wxALL,SPACE_SIZE);
171        lowergrid->Add(new wxTextCtrl(panel, ID_FULLHOUSETEXT),1,wxALL,SPACE_SIZE);
172        lowergrid->Add(new wxButton(panel,ID_SMALLSEQUENCE,wxT("Sequence of 4")),0,wxALL,SPACE_SIZE);
173        lowergrid->Add(new wxTextCtrl(panel, ID_SMALLSEQUENCETEXT),1,wxALL,SPACE_SIZE);
174        lowergrid->Add(new wxButton(panel,ID_LARGESEQUENCE,wxT("Sequence of 5")),0,wxALL,SPACE_SIZE);
175        lowergrid->Add(new wxTextCtrl(panel, ID_LARGESEQUENCETEXT),1,wxALL,SPACE_SIZE);
176        lowergrid->Add(new wxButton(panel,ID_YAHTZEE,wxT("Yahtzee")),0,wxALL,SPACE_SIZE);
177        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEETEXT),1,wxALL,SPACE_SIZE);
178        lowergrid->Add(new wxButton(panel,ID_CHANCE,wxT("Chance")),0,wxALL,SPACE_SIZE);
179        lowergrid->Add(new wxTextCtrl(panel, ID_CHANCETEXT),1,wxALL,SPACE_SIZE);
180        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Yahtzee Bonus")),0,wxALL,SPACE_SIZE);
181        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEEBONUSTEXT),1,wxALL,SPACE_SIZE);
182        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of lower section:")),0,wxALL,SPACE_SIZE);
183        lowergrid->Add(new wxTextCtrl(panel, ID_LOWERTOTAL),1,wxALL,SPACE_SIZE);
184        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Grand Total:")),0,wxALL,SPACE_SIZE);
185        lowergrid->Add(new wxTextCtrl(panel, ID_GRANDTOTAL),1,wxALL,SPACE_SIZE);
186        //END layout for the lower section of the score board
187
188        uppersection->Add(uppergrid);
189        lowersection->Add(lowergrid);
190        sectionsSizer->Add(uppersection,0,wxALL,5);
191        sectionsSizer->Add(lowersection,0,wxALL,5);
192
193        //BEGIN layout for the dice section of the score board
194        if (m_horizontallayout) {
195                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE1,*bitmap_dices[0]),0,wxALL,3);
196                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE2,*bitmap_dices[1]),0,wxALL,3);
197                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE3,*bitmap_dices[2]),0,wxALL,3);
198                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE4,*bitmap_dices[3]),0,wxALL,3);
199                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE5,*bitmap_dices[4]),0,wxALL,3);
200                diceSizer->Add(new wxButton(panel, ID_ROLL, wxT("Roll!"),wxDefaultPosition,wxSize(64,64)),0,wxALL,3);
201                diceSizer->Add(new wxCheckBox(panel, ID_DICE1KEEP, wxT("Keep")),0,wxBOTTOM,10);
202                diceSizer->Add(new wxCheckBox(panel, ID_DICE2KEEP, wxT("Keep")),0,wxBOTTOM,10);
203                diceSizer->Add(new wxCheckBox(panel, ID_DICE3KEEP, wxT("Keep")),0,wxBOTTOM,10);
204                diceSizer->Add(new wxCheckBox(panel, ID_DICE4KEEP, wxT("Keep")),0,wxBOTTOM,10);
205                diceSizer->Add(new wxCheckBox(panel, ID_DICE5KEEP, wxT("Keep")),0,wxBOTTOM,10);
206        } else {
207                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE1,*bitmap_dices[0]),0,wxALL,3);
208                diceSizer->Add(new wxCheckBox(panel, ID_DICE1KEEP, wxT("Keep")),0,wxBOTTOM,10);
209                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE2,*bitmap_dices[1]),0,wxALL,3);
210                diceSizer->Add(new wxCheckBox(panel, ID_DICE2KEEP, wxT("Keep")),0,wxBOTTOM,10);
211                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE3,*bitmap_dices[2]),0,wxALL,3);
212                diceSizer->Add(new wxCheckBox(panel, ID_DICE3KEEP, wxT("Keep")),0,wxBOTTOM,10);
213                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE4,*bitmap_dices[3]),0,wxALL,3);
214                diceSizer->Add(new wxCheckBox(panel, ID_DICE4KEEP, wxT("Keep")),0,wxBOTTOM,10);
215                diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE5,*bitmap_dices[4]),0,wxALL,3);
216                diceSizer->Add(new wxCheckBox(panel, ID_DICE5KEEP, wxT("Keep")),0,wxBOTTOM,10);
217                diceSizer->Add(new wxButton(panel, ID_ROLL, wxT("Roll!"),wxDefaultPosition,wxSize(64,64)),0,wxALL,3);
218        }
219        //END layout for the dice section of the score board *******/
220
221       
222        topSizer->Add(sectionsSizer);
223        topSizer->Add(diceSizer);       
224
225        panel->SetSizer(topSizer);
226       
227        topSizer->Fit(this);
228        topSizer->SetSizeHints(this);
229       
230        //make the text boxes uneditable to the user   
231        wxTextCtrl *textctrl;
232        for(int i = ID_ACESTEXT;i<=ID_GRANDTOTAL;i++) {
233                textctrl = (wxTextCtrl*) FindWindow(i);
234                textctrl->SetEditable(false);
235        }
236       
237        //disable the undo button
238        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
239
240
241       
242
243        /***************************************/
244        /********* Declare Event Table *********/
245        /***************************************/
246       
247        //BEGIN connecting the menu items' events
248        Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnQuit));
249        Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAbout));
250        Connect(ID_CHECK_FOR_UPDATES, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnCheckForUpdates));
251        Connect(ID_SENDCOMMENT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSendComment));
252        Connect(ID_NEWGAME, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnNewGame));
253        Connect(ID_UNDO, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnUndo));
254        Connect(ID_SHOWHIGHSCORE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnShowHighscore));
255        Connect(ID_SETTINGS, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSettings));
256        //END connecting the menu items' events
257
258        Connect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
259        Connect(ID_ROLL, wxEVT_ENABLE_ROLL, wxCommandEventHandler (MainFrame::OnRollButton));
260
261        //BEGIN connecting the scoreboard buttons to the events
262        Connect(ID_ACES,ID_SIXES, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnUpperButtons));
263        Connect(ID_THREEOFAKIND, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::On3ofakindButton));
264        Connect(ID_FOUROFAKIND, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::On4ofakindButton));
265        Connect(ID_FULLHOUSE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnFullHouseButton));
266        Connect(ID_SMALLSEQUENCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnSmallSequenceButton));
267        Connect(ID_LARGESEQUENCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnLargeSequenceButton));
268        Connect(ID_YAHTZEE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnYahtzeeButton));
269        Connect(ID_CHANCE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnChanceButton));
270        Connect(ID_DICE1,ID_DICE5, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnDiceClick));
271        Connect(ID_DICE1KEEP,ID_DICE5KEEP, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (MainFrame::OnKeepClick));
272        //END connecting the scoreboard buttons to the event
273
274        /*** End of Event Table ***/
275
276        ResetRolls();
277        ClearDiceHash();
278        m_yahtzee = false;
279        m_yahtzeebonus = false;
280        m_numofplaysleft = 13;
281
282 }
283
284/*********EVENT PROCCESSING FUNCTIONS********/
285
286
287void MainFrame::OnAbout(wxCommandEvent& event)
288{
289        AboutDialog *about = new AboutDialog(this,wxID_ANY,wxT("About Open Yahtzee"));
290        about->ShowModal();
291}
292
293/**
294 * Connects to the Open Yahtzee website on sourceforge.net and checks for
295 * updates to the game.
296 * \param event
297 */
298void MainFrame::OnCheckForUpdates (wxCommandEvent& event)
299{
300       
301        wxString link = wxT("http://openyahtzee.sourceforge.net/update.php?version=");
302       
303        link += wxT(OY_VERSION);
304
305        LaunchBrowser(link);
306}
307
308
309/**
310 * Starts up the user browser and connects to the Open Yahtzee website's
311 * feedback page.
312 * \param event
313 */
314void MainFrame::OnSendComment (wxCommandEvent& event)
315{
316        wxString link = wxT("http://openyahtzee.sourceforge.net/feedback.php");
317       
318        LaunchBrowser(link);
319}
320
321void MainFrame::OnQuit(wxCommandEvent& event)
322{
323        // Destroy the frame
324        Close();
325}
326
327/**
328 * This is the event handler of the New Game menu item. It starts a new
329 * game and clears the board from the last game.
330 * \param event
331 */
332void MainFrame::OnNewGame(wxCommandEvent& event)
333{
334        //disable the undo button so it won't be enabled when a new game is started.
335        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
336       
337        ResetRolls();
338        ClearDiceHash();
339        m_yahtzee = false;
340        m_numofplaysleft = 13;
341       
342        for (int i = ID_ACESTEXT; i<= ID_GRANDTOTAL; i++)
343                ((wxTextCtrl*) FindWindow(i))->Clear();
344        for (int i = ID_ACES; i<= ID_CHANCE; i++)
345                ((wxButton*) FindWindow(i))->Enable(true);
346}
347
348/**
349 * This function handles the undo events. It's connected to the Undo menu item.
350 *
351 * Note that the function only allows undoing of scoring actions and not dice
352 * rolls. Also it won't allow the undoing of the last move of the game because
353 * of a technical problem relating to the case an high-score was made and then
354 * the user undo the last move and rescore another high-score and so on.
355 * \param event
356 */
357void MainFrame::OnUndo(wxCommandEvent& event)
358{
359        m_rolls = m_rollsundo;
360
361        //after the user scored the button was enabled, check if it should be disabled
362        if (m_rolls <= 0) //we don't have remaining rolls
363                ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
364
365        //restore the 'keep' checkboxes
366        for (int i=0; i<5; i++)
367                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(true);
368       
369        //reset the users last choice
370        FindWindow(m_lastmove)->Enable(true);
371
372        //clear the score;
373        ((wxTextCtrl*)FindWindow(ID_ACESTEXT + (m_lastmove - ID_ACES)))->SetValue(wxT(""));
374
375        //undo also the yahtzee bonus if needed
376        if (m_yahtzeebonus) {
377                long temp;
378                wxString tempstr;
379       
380                tempstr = ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> GetValue();
381                tempstr.ToLong(&temp,10);
382                temp -= 100; //this line reduces the points given for the yahtzee bonus
383                tempstr.Printf(wxT("%i"),temp);
384                ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> SetValue(tempstr);
385        }
386
387        //recalculate the subtotals
388        CalculateSubTotal();
389
390        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
391        //cancel the counting for the choice that was canceled
392        m_numofplaysleft++;
393}
394
395/**
396 * This function enables the undo button and stores the last move
397 * \param id
398 */
399inline void MainFrame::EnableUndo(int id)
400{
401        if (m_numofplaysleft) {
402                (GetMenuBar()->FindItem(ID_UNDO))->Enable(true);
403                m_lastmove = id;
404        }
405}
406
407/**
408 * Shows the high-score dialog. Connected to the Game->"Show High Score" menu item.
409 * \param event
410 */
411void MainFrame::OnShowHighscore(wxCommandEvent& event)
412{
413        HighScoreDialog *dialog = new HighScoreDialog(this,wxID_ANY,m_highscoredb);
414        dialog->ShowModal();
415}
416
417/**
418 * Shows the settings dialog. This event-handler is connected to Game->Settings
419 * menu item.
420 * \param event
421 */
422void MainFrame::OnSettings( wxCommandEvent& event)
423{
424        SettingsDialog *dialog = new SettingsDialog(this,wxID_ANY);
425        SettingsDialogData data;
426        std::ostringstream sstr;
427       
428        data.highscoresize = m_highscoredb->GetSize();
429
430        data.animate = (m_settingsdb->GetKey("animate")=="Yes")?true:false;
431        data.subtotal = (m_settingsdb->GetKey("calculatesubtotal")=="Yes")?true:false;
432       
433        dialog->SetData(data);
434        if(dialog->ShowModal()==wxID_OK) { //user saved Changes
435                data = dialog->GetData();
436
437                if(data.reset)
438                        m_highscoredb->SetSize(0);
439               
440                sstr<<data.highscoresize<<std::flush;
441                m_settingsdb->SetKey("highscoresize",sstr.str());
442                               
443                m_highscoredb->SetSize(data.highscoresize);
444               
445                if (data.animate){
446                        m_settingsdb->SetKey("animate","Yes");
447                        m_animate = true;
448                       
449                } else {
450                        m_settingsdb->SetKey("animate","No");
451                        m_animate = false;
452                }
453                if (data.subtotal){
454                        m_settingsdb->SetKey("calculatesubtotal","Yes");
455                        m_calculatesubtotal = true;
456                       
457                } else {
458                        m_settingsdb->SetKey("calculatesubtotal","No");
459                        m_calculatesubtotal = false;
460                }
461
462        }
463}
464
465/**
466 * Event handler for the Roll button. It checks the settings if it should
467 * animate the dice and then rolls them accordingly. It also checks for the
468 * status of the "keep" checkboxes.
469 * \param event
470 */
471void MainFrame::OnRollButton (wxCommandEvent& event)
472{
473        if (event.GetEventType() == wxEVT_ENABLE_ROLL) {
474                //here we reconnect the event handler. We should recieve this event only after
475                //the dice stopped rolling and all other click events where skipped.
476                Connect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
477                return;
478        }
479        //Disconnect the button so we won't recieve new events untill we finish rolling the dice.
480        Disconnect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (MainFrame::OnRollButton));
481
482        //roll the dice...
483        if (m_animate) {
484                int dice_throws[5] = {0,0,0,0,0};
485                for (int i=0; i<5; i++) { //set the number of rolls for each dice
486                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
487                                dice_throws[i] = (rand()%15)+3; //ensures the number is at least one.
488                        }
489                }
490                while (dice_throws[0] || dice_throws[1] || dice_throws[2] || dice_throws[3] || dice_throws[4]) {
491                        for (int i=0 ; i<5; i++){
492                                if(dice_throws[i]){
493                                        dice_throws[i]--;
494                                        dice[i] = rand()%6;
495                                        ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
496                                }
497                        }
498                        ::wxMilliSleep(100);
499                }
500        } else {
501                for (int i=0; i<5; i++) {
502                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
503                                dice[i] = rand()%6;
504                                ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
505                        }
506                }
507        }
508       
509        //Clear old dice-hash and create a new one
510        ClearDiceHash();
511        for (int i=0; i<5; i++)
512                dicehash[dice[i]] += 1;
513
514        //if out of rolls disable the roll butoon
515        m_rolls -= 1;
516        #ifndef DEBUG
517        if (m_rolls <= 0)
518                ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
519        #endif
520       
521        //enable the keep checkboxes
522        for (int i=0; i<5; i++)
523                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(true);
524       
525        //we rolled the dices so undoing isn't allowed
526        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
527        m_yahtzeebonus = false; //if we scored yahtzee bonus before we don't care anymore.
528       
529        //queue the event which will cause the event-handler for clicks to be reconnected.
530        event.SetEventType(wxEVT_ENABLE_ROLL);
531        wxEvtHandler::AddPendingEvent(event);
532}
533
534/**
535 * This is the event-handler for all of the scoring buttons of the upper section.
536 *
537 * It gets the id of the button that called the event handler by comparing it
538 * to the id of the aces button it figures what button was pressed, And updates
539 * the suiting score textbox (again by comparing the id to the one of the aces
540 * checbox).
541 * \param event
542 */
543void MainFrame::OnUpperButtons (wxCommandEvent& event)
544{
545        wxString out;
546        int temp;
547        if(m_rolls < 3){
548                YahtzeeBonus();
549                temp = dicehash[(event.GetId() - ID_ACES)] * (event.GetId() - ID_ACES + 1);
550       
551                out.Printf(wxT("%i"),temp);
552                ((wxTextCtrl*) FindWindow(event.GetId() - ID_ACES + ID_ACESTEXT))->SetValue(out);
553               
554                PostScore(event.GetId());
555        }
556        else
557                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
558}
559
560/**
561 * Event handler for the "3 of a kind" score button.
562 * \param event
563 */
564void MainFrame::On3ofakindButton(wxCommandEvent& event)
565{
566        if(m_rolls>=3) {
567                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
568                return;
569        }
570        YahtzeeBonus();
571        bool three = false;
572        wxString out;
573        int temp = 0;   
574
575        //check for the conditions of scoring
576        for (int i=0; i<6; i++)
577                if (dicehash[i] >= 3)
578                        three = true;
579        if (three){
580                for(int i = 0; i<5; i++)
581                        temp += dice[i]+1;
582       
583                out.Printf(wxT("%i"),temp);
584                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(out);
585        } else
586                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(wxT("0"));
587       
588        PostScore(event.GetId());
589}
590
591/**
592 * Event handler for the "4 of a kind" score button.
593 * \param event
594 */
595void MainFrame::On4ofakindButton(wxCommandEvent& event)
596{
597        if(m_rolls>=3) {
598                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
599                return;
600        }
601        YahtzeeBonus();
602        bool four = false;
603        wxString out;
604        int temp = 0;   
605
606        //check for the conditions of scoring
607        for (int i=0; i<6; i++)
608                if (dicehash[i] >= 4)
609                        four = true;
610        if (four){
611                for(int i = 0; i<5; i++)
612                        temp += dice[i]+1;
613       
614                out.Printf(wxT("%i"),temp);
615                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(out);
616        } else
617                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(wxT("0"));
618       
619        PostScore(event.GetId());
620}
621
622/**
623 * Event handler for the full-house score button.
624 * \param event
625 */
626void MainFrame::OnFullHouseButton(wxCommandEvent& event)
627{
628        if(m_rolls>=3) {
629                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
630                return;
631        }
632        YahtzeeBonus();
633        bool two = false;
634        bool three = false;
635
636        //check for the conditions of scoring
637        for (int i=0; i<6; i++)
638                if (dicehash[i] == 2)
639                        two = true;
640        for (int i=0; i<6; i++)
641                if (dicehash[i] == 3)
642                        three = true;
643        if ((two && three) || YahtzeeJoker())
644                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("25"));
645        else
646                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("0"));
647       
648        PostScore(event.GetId());
649}
650
651/**
652 * Event handler for the small-sequence score button.
653 * \param event
654 */
655void MainFrame::OnSmallSequenceButton(wxCommandEvent& event)
656{
657        if(m_rolls>=3) {
658                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
659                return;
660        }
661
662        YahtzeeBonus();
663        bool sequence = false;
664        //check for the conditions of scoring
665        if ( (dicehash[0]>=1 && dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1) ||
666                (dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1) ||
667                (dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1 && dicehash[5]>=1))
668                        sequence = true;
669        if (sequence || YahtzeeJoker())
670                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("30"));
671        else
672                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("0"));
673       
674        PostScore(event.GetId());
675}
676
677/**
678 * Event handler for the large-sequence score button.
679 * \param event
680 */
681void MainFrame::OnLargeSequenceButton(wxCommandEvent& event)
682{
683        if(m_rolls>=3) {
684                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
685                return;
686        }
687
688        YahtzeeBonus();
689        bool sequence = false;
690        //check for the conditions of scoring
691        if ( (dicehash[0]==1 && dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1) ||
692                (dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1 && dicehash[5]==1))
693                        sequence = true;
694        if (sequence || YahtzeeJoker())
695                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("40"));
696        else
697                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("0"));
698       
699        PostScore(event.GetId());
700}
701
702/**
703 * Event handler for the yahtzee score button.
704 * \param event
705 */
706void MainFrame::OnYahtzeeButton(wxCommandEvent& event)
707{
708        if(m_rolls>=3) {
709                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
710                return;
711        }
712        //give the score
713        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])){
714                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("50"));
715                m_yahtzee=true;
716        } else
717                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("0"));
718
719        PostScore(event.GetId());
720}
721
722/**
723 * Evnet handler for the chance score button.
724 * \param event
725 */
726void MainFrame::OnChanceButton (wxCommandEvent& event)
727{
728        wxString out;
729        int temp = 0;
730        if(m_rolls < 3){
731                YahtzeeBonus();
732                for(int i = 0; i<5; i++)
733                        temp += dice[i]+1;
734       
735                out.Printf(wxT("%i"),temp);
736                ((wxTextCtrl*) FindWindow(ID_CHANCETEXT))->SetValue(out);
737               
738                PostScore(event.GetId());
739        }
740        else
741                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
742
743}
744
745/**
746 * Event handler for mouse clicks on the dice.
747 *
748 * When clicking on the dice this event-handler ticks the appropriate "keep" checkbox.
749 * \param event
750 */
751void MainFrame::OnDiceClick (wxCommandEvent& event)
752{
753        //tick the checkbox
754        if (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->IsEnabled()){
755                bool newvalue = (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->GetValue())?false:true;
756                ((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP)) -> SetValue(newvalue);
757        }
758
759        //dispatch a click event on the checkbox
760        wxCommandEvent clickevent((event.GetId()-ID_DICE1 + ID_DICE1KEEP),wxEVT_COMMAND_CHECKBOX_CLICKED);
761        clickevent.SetEventObject( this );
762        clickevent.SetId(event.GetId()-ID_DICE1 + ID_DICE1KEEP);
763        this->OnKeepClick(clickevent); ///\todo find a better way to call the event handler.
764}
765
766void MainFrame::OnKeepClick (wxCommandEvent& event)
767{
768        wxCheckBox *temp = (wxCheckBox*) FindWindow(event.GetId());
769        ((wxDynamicBitmap*) FindWindow(event.GetId()-ID_DICE1KEEP + ID_DICE1))->SetGrayScale(temp->GetValue());
770}
771
772//********************************************
773//******        General Functions       ******
774//********************************************
775
776/**
777 * This function clears the dice hash.
778 *
779 * The dice hash is just an array that holds how many dices have each value.
780 */
781void MainFrame::ClearDiceHash()
782{
783        for (int i=0; i<6; i++)
784                dicehash[i] = 0;
785}
786
787/**
788 * This function handles everything related to reseting the dice rolls after scoring.
789 */
790void MainFrame::ResetRolls()
791{
792        m_rollsundo = m_rolls;
793        m_rolls = 3;
794        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(true);
795        for (int i=0; i<5; i++){
796                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> SetValue(false);
797                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(false);
798                ((wxDynamicBitmap*) FindWindow(i+ID_DICE1)) -> SetGrayScale(false);
799        }
800}
801
802/**
803 * This function checks for a Yahtzee Bonus situation and if one exists it scores accordingly.
804 */
805void MainFrame::YahtzeeBonus()
806{
807        long temp;
808        wxString tempstr;
809       
810        //if the player didn't have any yathzees yet he can't have the bonus;
811        if (!m_yahtzee)
812                return;
813        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])) {
814                tempstr = ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> GetValue();
815                tempstr.ToLong(&temp,10);
816                temp += 100;
817                tempstr.Printf(wxT("%i"),temp);
818                ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> SetValue(tempstr);
819                m_yahtzeebonus = true;
820        }       
821}
822
823/**
824 * This function checks whether we have a Yahtzee Joker situation.
825 * \return true if there is Yahtzee Joker, false otherwise.
826 */
827bool MainFrame::YahtzeeJoker()
828{
829        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4]) && !(FindWindow(ID_ACES+dice[0])->IsEnabled()) && !(FindWindow(ID_YAHTZEE)->IsEnabled())) {
830                return true;
831        }
832        return false;
833}
834
835/**
836 * This function handles the end of game.
837 *
838 * When a game ends it calculates the total score and submit it to the high
839 * score list.
840 */
841void MainFrame::EndofGame()
842{
843        if(m_numofplaysleft>0)
844                return;
845       
846        wxString tempstr;
847        long temp;
848        long upperscore = 0;
849        long lowerscore = 0;
850
851        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
852                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
853                tempstr.ToLong(&temp,10);
854                upperscore +=temp;
855        }
856       
857        tempstr.Printf(wxT("%i"),upperscore);
858        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
859       
860        //check for bonus
861        if(upperscore>=63) {
862                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("35"));
863                upperscore +=35;
864        } else
865                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("0"));
866       
867        tempstr.Printf(wxT("%i"),upperscore);
868        ((wxTextCtrl*) FindWindow(ID_UPPERTOTAL)) -> SetValue(tempstr);
869       
870        //calculate total on lower section
871        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
872                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
873                tempstr.ToLong(&temp,10);
874                lowerscore +=temp;
875        }
876       
877        tempstr.Printf(wxT("%i"),lowerscore);
878        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
879        tempstr.Printf(wxT("%i"),upperscore + lowerscore);
880        ((wxTextCtrl*) FindWindow(ID_GRANDTOTAL)) -> SetValue(tempstr);
881
882        //disable the roll button;
883        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
884
885        tempstr.Printf(wxT("Your final score is %i points!"),lowerscore+upperscore);
886        wxMessageBox(tempstr, wxT("Game Ended"), wxOK | wxICON_INFORMATION, this);
887
888        //submit to high score
889        HighScoreHandler(lowerscore+upperscore);
890       
891}
892
893/**
894 * This function checks if a given score qualifies for the high score list and
895 * adds it to the list if it does.
896 * @param score The score submitted to the high score list.
897 */
898void MainFrame::HighScoreHandler(int score)
899{
900        int place;
901        std::string name,date;
902        wxCommandEvent newevent;
903
904
905        place = m_highscoredb->IsHighScore(score);
906       
907        if(!place)  //if the score didn't make it to the highscore table do nothing
908                return;
909       
910        wxString msg;
911        msg.Printf(wxT("Your score made it to the high score table. Your place is number %i.\nPlease enter your name below:"),place);
912
913        wxTextEntryDialog infodialog(this,msg,wxT("Please enter your name"),wxT(""),wxOK | wxCENTRE);
914        infodialog.ShowModal();
915
916        name = infodialog.GetValue().mb_str();
917
918        //get the date
919        wxDateTime now = wxDateTime::Now();
920        date = now.FormatISOTime().mb_str();
921        date +=" ";
922        date += now.FormatDate().mb_str();
923
924        m_highscoredb->SendHighScore(name,date,score);
925
926        //now show the high score table
927        newevent.SetId(ID_SHOWHIGHSCORE);
928        newevent.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
929        ProcessEvent(newevent);
930
931}
932
933///this function handles all the post scoring stuff such as disabling the right button.
934/**
935 * This function is always called after scoring and it handles all the post-score
936 * stuff such as reseting the dice rolls, enabling the undo button, calculating
937 * the sub-total scores and ending the game if necessary.
938 * \param id
939 */
940void MainFrame::PostScore(int id)
941{
942        //now after the scoring reset the rolls
943        ResetRolls();
944
945        CalculateSubTotal();
946
947        //and disable the button
948        FindWindow(id)->Enable(false);
949        m_numofplaysleft--;
950        EnableUndo(id);
951        EndofGame();
952}
953
954/**
955 * This function calculates the sub-total scores and should be called after
956 * every score. It does so only if this feature is requested in the settings
957 * dialog.
958 */
959void MainFrame::CalculateSubTotal()
960{
961        if (!m_calculatesubtotal)
962                return;
963        long upperscore = 0;
964        long lowerscore = 0;
965        wxString tempstr;
966        long temp;
967
968
969        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
970                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
971                tempstr.ToLong(&temp,10);
972                upperscore +=temp;
973        }
974       
975        tempstr.Printf(wxT("%i"),upperscore);
976        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
977
978        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
979                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
980                tempstr.ToLong(&temp,10);
981                lowerscore +=temp;
982        }
983       
984        tempstr.Printf(wxT("%i"),lowerscore);
985        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
986}
987
988
989/**
990 * Initializes the database and stores default settings if needed.
991 * @return 0 if some error
992 */
993int MainFrame::InitializeDatabase()
994{
995        std::ostringstream sstr;
996
997
998        if (m_settingsdb->GetKey("highscoresize") == "") { //check if we need to create a new high score table
999                m_highscoredb->SetSize(DEF_HIGHSCORESIZE);
1000                sstr<<DEF_HIGHSCORESIZE<<std::flush;
1001                m_settingsdb->SetKey("highscoresize", sstr.str());
1002        } else {
1003                int highscoresize = atoi((m_settingsdb->GetKey("highscoresize")).c_str());
1004                //m_highscoredb->SetSize((highscoresize>0)?highscoresize:DEF_HIGHSCORESIZE);
1005                m_highscoredb->SetSize(highscoresize);
1006        }
1007       
1008        if (m_settingsdb->GetKey("animate") == "Yes") {
1009                m_animate = true;
1010        } else if (m_settingsdb->GetKey("animate") == "No") {
1011                m_animate = false;
1012        } else {
1013                m_settingsdb->SetKey("animate", "Yes");
1014                m_animate = true;
1015        }
1016        if (m_settingsdb->GetKey("calculatesubtotal") == "Yes") {
1017                m_calculatesubtotal = true;
1018        } else if (m_settingsdb->GetKey("calculatesubtotal") == "No") {
1019                m_calculatesubtotal = false;
1020        } else {
1021                m_settingsdb->SetKey("calculatesubtotal", "Yes");
1022                m_calculatesubtotal = true;
1023        }
1024       
1025        if (m_settingsdb->GetKey("openyahtzeehomepage") == "") {
1026                m_settingsdb->SetKey("openyahtzeehomepage", "http://openyahtzee.sourceforge.net/");
1027        }
1028
1029        if (m_settingsdb->GetKey("updateurl") == "") {
1030                /*the version string will be appended in the end of the
1031                  given url */
1032                m_settingsdb->SetKey("updateurl", "http://openyahtzee.sourceforge.net/update.php?version=");
1033        }
1034       
1035        return 1;
1036}
Note: See TracBrowser for help on using the repository browser.