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

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

Make the dice look grayscale when the "keep" checkbox is ticked.
-Added SetGrayScale?() to wxDynamicBitmap
-Added event-handler for clicking on the "keep" checkboxes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.2 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 <iostream>
38#include <sstream>
39#include <cstdlib>
40#include <wx/version.h>
41
42//include the images for the dice
43#include "one.xpm"
44#include "two.xpm"
45#include "three.xpm"
46#include "four.xpm"
47#include "five.xpm"
48#include "six.xpm"
49
50//include the icon file
51#include "Icon.h"
52
53//default values
54#define SPACE_SIZE 1
55#define DEF_HIGHSCORESIZE 20
56#define OY_VERSION "1.7.0"
57
58MainFrame::MainFrame(const wxString& title, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE)
59        : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition, size, style)
60{
61        //give the frame an icon
62        SetIcon(wxIcon(ICON));
63
64
65        std::ostringstream sstr;
66
67        m_settingsdb = new SettingsDB(); //Get the settings database connection
68        m_highscoredb = new HighScoreTableDB();
69
70        //DATABASE initialization
71        if (m_settingsdb->GetKey("highscoresize") == "") { //check if we need to create a new high score table
72                m_highscoredb->SetSize(DEF_HIGHSCORESIZE);
73                sstr<<DEF_HIGHSCORESIZE<<std::flush;
74                m_settingsdb->SetKey("highscoresize", sstr.str());
75        } else {
76                int highscoresize = atoi((m_settingsdb->GetKey("highscoresize")).c_str());
77                //m_highscoredb->SetSize((highscoresize>0)?highscoresize:DEF_HIGHSCORESIZE);
78                m_highscoredb->SetSize(highscoresize);
79        }
80       
81        if (m_settingsdb->GetKey("animate") == "Yes") {
82                m_animate = true;
83        } else if (m_settingsdb->GetKey("animate") == "No") {
84                m_animate = false;
85        } else {
86                m_settingsdb->SetKey("animate", "Yes");
87                m_animate = true;
88        }
89        if (m_settingsdb->GetKey("calculatesubtotal") == "Yes") {
90                m_calculatesubtotal = true;
91        } else if (m_settingsdb->GetKey("calculatesubtotal") == "No") {
92                m_calculatesubtotal = false;
93        } else {
94                m_settingsdb->SetKey("calculatesubtotal", "Yes");
95                m_calculatesubtotal = true;
96        }
97
98        // END Database initialization
99
100        bitmap_dices[0] = new wxBitmap(one_xpm);
101        bitmap_dices[1] = new wxBitmap(two_xpm);
102        bitmap_dices[2] = new wxBitmap(three_xpm);
103        bitmap_dices[3] = new wxBitmap(four_xpm);
104        bitmap_dices[4] = new wxBitmap(five_xpm);
105        bitmap_dices[5] = new wxBitmap(six_xpm);
106       
107        //randomize the random-number generator based on the time
108        srand( (unsigned)time( NULL ) );
109
110
111        /*****Create and initialize the menu bar******/
112
113        /*Create the menus*/
114        wxMenu *gameMenu = new wxMenu;  //create File menu
115        wxMenu *helpMenu = new wxMenu;  //create Help menu
116       
117       
118        //insert menu items into menu Help
119        helpMenu->Append(ID_CHECK_FOR_UPDATES, wxT("&Check for Updates"),
120                        wxT("Check for new version of the game via the web"));
121        helpMenu->AppendSeparator();
122        helpMenu->Append(ID_SENDCOMMENT, wxT("&Send a Comment to Developers"),
123                        wxT("Send a comment to the developers of the game"));
124        helpMenu->AppendSeparator();
125        helpMenu->Append(wxID_ABOUT, wxT("&About...\tF1"),
126                        wxT("Show about dialog"));
127
128        //insert menu items into menu File
129        gameMenu->Append(ID_NEWGAME,wxT("&New Game\tF2"),wxT("Start a new game"));
130        //create the undo button and make it disabled
131        gameMenu->Append(ID_UNDO,wxT("&Undo\tCTRL+Z"),wxT("Undo the last move"));
132        gameMenu->Append(ID_SHOWHIGHSCORE,wxT("High &Scores"),wxT("Show high-scores table"));
133        gameMenu->Append(ID_SETTINGS,wxT("Settings"),wxT("Show settings dialog"));
134        gameMenu->Append(wxID_EXIT, wxT("E&xit\tAlt-X"),
135                        wxT("Quit this program"));
136       
137        // Declare the menu-bar and append the freshly created menus to the menu bar...
138        wxMenuBar *menuBar = new wxMenuBar();
139        menuBar->Append(gameMenu, wxT("&Game"));
140        menuBar->Append(helpMenu, wxT("&Help"));
141       
142        // ... and attach this menu bar to the frame
143        SetMenuBar(menuBar);
144       
145        /***End menu-bar ***/
146        wxPanel* panel = new wxPanel(this, ID_PANEL,
147                wxDefaultPosition, wxDefaultSize);
148
149        wxBoxSizer *topSizer = new wxBoxSizer( wxHORIZONTAL );
150        wxBoxSizer *sectionsSizer = new wxBoxSizer( wxVERTICAL );
151        wxBoxSizer *diceSizer = new wxBoxSizer( wxVERTICAL );
152
153        wxSizer *uppersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Upper Section") ), wxVERTICAL);
154        wxSizer *lowersection = new wxStaticBoxSizer( new wxStaticBox( panel, wxID_ANY, wxT("Lower Section") ), wxVERTICAL);
155       
156        wxFlexGridSizer* uppergrid = new wxFlexGridSizer(2, 0, 10);
157        wxFlexGridSizer* lowergrid = new wxFlexGridSizer(2, 0, 10);
158
159        //BEGIN layout for the upper section of the score board
160        uppergrid->Add(new wxButton(panel,ID_ACES,wxT("Aces")),0,wxALL,SPACE_SIZE);
161        uppergrid->Add(new wxTextCtrl(panel, ID_ACESTEXT),1,wxALL,SPACE_SIZE);
162        uppergrid->Add(new wxButton(panel,ID_TWOS,wxT("Twos")),0,wxALL,SPACE_SIZE);
163        uppergrid->Add(new wxTextCtrl(panel, ID_TWOSTEXT),1,wxALL,SPACE_SIZE);
164        uppergrid->Add(new wxButton(panel,ID_THREES,wxT("Threes")),0,wxALL,SPACE_SIZE);
165        uppergrid->Add(new wxTextCtrl(panel, ID_THREESTEXT),1,wxALL,SPACE_SIZE);
166        uppergrid->Add(new wxButton(panel,ID_FOURS,wxT("Fours")),0,wxALL,SPACE_SIZE);
167        uppergrid->Add(new wxTextCtrl(panel, ID_FOURSTEXT),1,wxALL,SPACE_SIZE);
168        uppergrid->Add(new wxButton(panel,ID_FIVES,wxT("Fives")),0,wxALL,SPACE_SIZE);
169        uppergrid->Add(new wxTextCtrl(panel, ID_FIVESTEXT),1,wxALL,SPACE_SIZE);
170        uppergrid->Add(new wxButton(panel,ID_SIXES,wxT("Sixes")),0,wxALL,SPACE_SIZE);
171        uppergrid->Add(new wxTextCtrl(panel, ID_SIXESTEXT),1,wxALL,SPACE_SIZE);
172        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total score:")),0,wxALL,SPACE_SIZE);
173        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERSECTIONTOTAL),1,wxALL,SPACE_SIZE);
174        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Bonus:")),0,wxALL,SPACE_SIZE);
175        uppergrid->Add(new wxTextCtrl(panel, ID_BONUS),1,wxALL,SPACE_SIZE);
176        uppergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of upper section:")),0,wxALL,SPACE_SIZE);
177        uppergrid->Add(new wxTextCtrl(panel, ID_UPPERTOTAL),1,wxALL,SPACE_SIZE);
178        //END layout for the upper section of the score board
179
180        //BEGIN layout for the lower section of the score board
181        lowergrid->Add(new wxButton(panel,ID_THREEOFAKIND,wxT("3 of a kind")),0,wxALL,SPACE_SIZE);
182        lowergrid->Add(new wxTextCtrl(panel, ID_THREEOFAKINDTEXT),1,wxALL,SPACE_SIZE);
183        lowergrid->Add(new wxButton(panel,ID_FOUROFAKIND,wxT("4 of a kind")),0,wxALL,SPACE_SIZE);
184        lowergrid->Add(new wxTextCtrl(panel, ID_FOUROFAKINDTEXT),1,wxALL,SPACE_SIZE);
185        lowergrid->Add(new wxButton(panel,ID_FULLHOUSE,wxT("Full House")),0,wxALL,SPACE_SIZE);
186        lowergrid->Add(new wxTextCtrl(panel, ID_FULLHOUSETEXT),1,wxALL,SPACE_SIZE);
187        lowergrid->Add(new wxButton(panel,ID_SMALLSEQUENCE,wxT("Sequence of 4")),0,wxALL,SPACE_SIZE);
188        lowergrid->Add(new wxTextCtrl(panel, ID_SMALLSEQUENCETEXT),1,wxALL,SPACE_SIZE);
189        lowergrid->Add(new wxButton(panel,ID_LARGESEQUENCE,wxT("Sequence of 5")),0,wxALL,SPACE_SIZE);
190        lowergrid->Add(new wxTextCtrl(panel, ID_LARGESEQUENCETEXT),1,wxALL,SPACE_SIZE);
191        lowergrid->Add(new wxButton(panel,ID_YAHTZEE,wxT("Yahtzee")),0,wxALL,SPACE_SIZE);
192        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEETEXT),1,wxALL,SPACE_SIZE);
193        lowergrid->Add(new wxButton(panel,ID_CHANCE,wxT("Chance")),0,wxALL,SPACE_SIZE);
194        lowergrid->Add(new wxTextCtrl(panel, ID_CHANCETEXT),1,wxALL,SPACE_SIZE);
195        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Yahtzee Bonus")),0,wxALL,SPACE_SIZE);
196        lowergrid->Add(new wxTextCtrl(panel, ID_YAHTZEEBONUSTEXT),1,wxALL,SPACE_SIZE);
197        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Total of lower section:")),0,wxALL,SPACE_SIZE);
198        lowergrid->Add(new wxTextCtrl(panel, ID_LOWERTOTAL),1,wxALL,SPACE_SIZE);
199        lowergrid->Add(new wxStaticText(panel, wxID_ANY, wxT("Grand Total:")),0,wxALL,SPACE_SIZE);
200        lowergrid->Add(new wxTextCtrl(panel, ID_GRANDTOTAL),1,wxALL,SPACE_SIZE);
201        //END layout for the lower section of the score board
202
203        uppersection->Add(uppergrid);
204        lowersection->Add(lowergrid);
205        sectionsSizer->Add(uppersection,0,wxALL,5);
206        sectionsSizer->Add(lowersection,0,wxALL,5);
207
208        //BEGIN layout for the dice section of the score board
209        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE1,*bitmap_dices[0]),0,wxALL,3);
210        diceSizer->Add(new wxCheckBox(panel, ID_DICE1KEEP, wxT("Keep")),0,wxBOTTOM,10);
211        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE2,*bitmap_dices[1]),0,wxALL,3);
212        diceSizer->Add(new wxCheckBox(panel, ID_DICE2KEEP, wxT("Keep")),0,wxBOTTOM,10);
213        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE3,*bitmap_dices[2]),0,wxALL,3);
214        diceSizer->Add(new wxCheckBox(panel, ID_DICE3KEEP, wxT("Keep")),0,wxBOTTOM,10);
215        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE4,*bitmap_dices[3]),0,wxALL,3);
216        diceSizer->Add(new wxCheckBox(panel, ID_DICE4KEEP, wxT("Keep")),0,wxBOTTOM,10);
217        diceSizer->Add(new wxDynamicBitmap(panel,ID_DICE5,*bitmap_dices[4]),0,wxALL,3);
218        diceSizer->Add(new wxCheckBox(panel, ID_DICE5KEEP, wxT("Keep")),0,wxBOTTOM,10);
219        diceSizer->Add(new wxButton(panel, ID_ROLL, wxT("Roll")),0,wxALL,3);
220        /*===> END layout for the dice section of the score board *******/
221
222       
223        topSizer->Add(sectionsSizer);
224        topSizer->Add(diceSizer);       
225
226        panel->SetSizer(topSizer);
227       
228        topSizer->Fit(this);
229        topSizer->SetSizeHints(this);
230       
231        //make the text boxes uneditable to the user   
232        wxTextCtrl *textctrl;
233        for(int i = ID_ACESTEXT;i<=ID_GRANDTOTAL;i++) {
234                textctrl = (wxTextCtrl*) FindWindow(i);
235                textctrl->SetEditable(false);
236        }
237       
238        //disable the undo button
239        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
240
241
242       
243
244        /***************************************/
245        /********* Declare Event Table *********/
246        /***************************************/
247       
248        //BEGIN connecting the menu items' events
249        Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnQuit));
250        Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAbout));
251        Connect(ID_CHECK_FOR_UPDATES, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnCheckForUpdates));
252        Connect(ID_SENDCOMMENT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSendComment));
253        Connect(ID_NEWGAME, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnNewGame));
254        Connect(ID_UNDO, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnUndo));
255        Connect(ID_SHOWHIGHSCORE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnShowHighscore));
256        Connect(ID_SETTINGS, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSettings));
257        //END connecting the menu items' events
258
259        Connect(ID_ROLL, wxEVT_COMMAND_BUTTON_CLICKED, 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        //roll the dice...
474        if (m_animate) {
475                int dice_throws[5] = {0,0,0,0,0};
476                for (int i=0; i<5; i++) { //set the number of rolls for each dice
477                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
478                                dice_throws[i] = (rand()%15)+3; //ensures the number is at least one.
479                        }
480                }
481                while (dice_throws[0] || dice_throws[1] || dice_throws[2] || dice_throws[3] || dice_throws[4]) {
482                        for (int i=0 ; i<5; i++){
483                                if(dice_throws[i]){
484                                        dice_throws[i]--;
485                                        dice[i] = rand()%6;
486                                        ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
487                                }
488                        }
489                        ::wxMilliSleep(100);
490                }
491        } else {
492                for (int i=0; i<5; i++) {
493                        if (!((wxCheckBox*) FindWindow(i + ID_DICE1KEEP))->IsChecked()) {
494                                dice[i] = rand()%6;
495                                ((wxDynamicBitmap*) FindWindow(i + ID_DICE1)) -> SetBitmap(*bitmap_dices[dice[i]]);
496                        }
497                }
498        }
499       
500        //Clear old dice-hash and create a new one
501        ClearDiceHash();
502        for (int i=0; i<5; i++)
503                dicehash[dice[i]] += 1;
504
505        //if out of rolls disable the roll butoon
506        m_rolls -= 1;
507        #ifndef DEBUG
508        if (m_rolls <= 0)
509                ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
510        #endif
511       
512        //enable the keep checkboxes
513        for (int i=0; i<5; i++)
514                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(true);
515       
516        //we rolled the dices so undoing isn't allowed
517        (GetMenuBar()->FindItem(ID_UNDO))->Enable(false);
518        m_yahtzeebonus = false; //if we scored yahtzee bonus before we don't care anymore.
519
520}
521
522/**
523 * This is the event-handler for all of the scoring buttons of the upper section.
524 *
525 * It gets the id of the button that called the event handler by comparing it
526 * to the id of the aces button it figures what button was pressed, And updates
527 * the suiting score textbox (again by comparing the id to the one of the aces
528 * checbox).
529 * \param event
530 */
531void MainFrame::OnUpperButtons (wxCommandEvent& event)
532{
533        wxString out;
534        int temp;
535        if(m_rolls < 3){
536                YahtzeeBonus();
537                temp = dicehash[(event.GetId() - ID_ACES)] * (event.GetId() - ID_ACES + 1);
538       
539                out.Printf(wxT("%i"),temp);
540                ((wxTextCtrl*) FindWindow(event.GetId() - ID_ACES + ID_ACESTEXT))->SetValue(out);
541               
542                PostScore(event.GetId());
543        }
544        else
545                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
546}
547
548/**
549 * Event handler for the "3 of a kind" score button.
550 * \param event
551 */
552void MainFrame::On3ofakindButton(wxCommandEvent& event)
553{
554        if(m_rolls>=3) {
555                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
556                return;
557        }
558        YahtzeeBonus();
559        bool three = false;
560        wxString out;
561        int temp = 0;   
562
563        //check for the conditions of scoring
564        for (int i=0; i<6; i++)
565                if (dicehash[i] >= 3)
566                        three = true;
567        if (three){
568                for(int i = 0; i<5; i++)
569                        temp += dice[i]+1;
570       
571                out.Printf(wxT("%i"),temp);
572                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(out);
573        } else
574                ((wxTextCtrl*) FindWindow(ID_THREEOFAKINDTEXT))->SetValue(wxT("0"));
575       
576        PostScore(event.GetId());
577}
578
579/**
580 * Event handler for the "4 of a kind" score button.
581 * \param event
582 */
583void MainFrame::On4ofakindButton(wxCommandEvent& event)
584{
585        if(m_rolls>=3) {
586                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
587                return;
588        }
589        YahtzeeBonus();
590        bool four = false;
591        wxString out;
592        int temp = 0;   
593
594        //check for the conditions of scoring
595        for (int i=0; i<6; i++)
596                if (dicehash[i] >= 4)
597                        four = true;
598        if (four){
599                for(int i = 0; i<5; i++)
600                        temp += dice[i]+1;
601       
602                out.Printf(wxT("%i"),temp);
603                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(out);
604        } else
605                ((wxTextCtrl*) FindWindow(ID_FOUROFAKINDTEXT))->SetValue(wxT("0"));
606       
607        PostScore(event.GetId());
608}
609
610/**
611 * Event handler for the full-house score button.
612 * \param event
613 */
614void MainFrame::OnFullHouseButton(wxCommandEvent& event)
615{
616        if(m_rolls>=3) {
617                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
618                return;
619        }
620        YahtzeeBonus();
621        bool two = false;
622        bool three = false;
623
624        //check for the conditions of scoring
625        for (int i=0; i<6; i++)
626                if (dicehash[i] == 2)
627                        two = true;
628        for (int i=0; i<6; i++)
629                if (dicehash[i] == 3)
630                        three = true;
631        if ((two && three) || YahtzeeJoker())
632                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("25"));
633        else
634                ((wxTextCtrl*) FindWindow(ID_FULLHOUSETEXT))->SetValue(wxT("0"));
635       
636        PostScore(event.GetId());
637}
638
639/**
640 * Event handler for the small-sequence score button.
641 * \param event
642 */
643void MainFrame::OnSmallSequenceButton(wxCommandEvent& event)
644{
645        if(m_rolls>=3) {
646                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
647                return;
648        }
649
650        YahtzeeBonus();
651        bool sequence = false;
652        //check for the conditions of scoring
653        if ( (dicehash[0]>=1 && dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1) ||
654                (dicehash[1]>=1 && dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1) ||
655                (dicehash[2]>=1 && dicehash[3]>=1 && dicehash[4]>=1 && dicehash[5]>=1))
656                        sequence = true;
657        if (sequence || YahtzeeJoker())
658                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("30"));
659        else
660                ((wxTextCtrl*) FindWindow(ID_SMALLSEQUENCETEXT))->SetValue(wxT("0"));
661       
662        PostScore(event.GetId());
663}
664
665/**
666 * Event handler for the large-sequence score button.
667 * \param event
668 */
669void MainFrame::OnLargeSequenceButton(wxCommandEvent& event)
670{
671        if(m_rolls>=3) {
672                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
673                return;
674        }
675
676        YahtzeeBonus();
677        bool sequence = false;
678        //check for the conditions of scoring
679        if ( (dicehash[0]==1 && dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1) ||
680                (dicehash[1]==1 && dicehash[2]==1 && dicehash[3]==1 && dicehash[4]==1 && dicehash[5]==1))
681                        sequence = true;
682        if (sequence || YahtzeeJoker())
683                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("40"));
684        else
685                ((wxTextCtrl*) FindWindow(ID_LARGESEQUENCETEXT))->SetValue(wxT("0"));
686       
687        PostScore(event.GetId());
688}
689
690/**
691 * Event handler for the yahtzee score button.
692 * \param event
693 */
694void MainFrame::OnYahtzeeButton(wxCommandEvent& event)
695{
696        if(m_rolls>=3) {
697                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
698                return;
699        }
700        //give the score
701        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])){
702                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("50"));
703                m_yahtzee=true;
704        } else
705                ((wxTextCtrl*) FindWindow(ID_YAHTZEETEXT))->SetValue(wxT("0"));
706
707        PostScore(event.GetId());
708}
709
710/**
711 * Evnet handler for the chance score button.
712 * \param event
713 */
714void MainFrame::OnChanceButton (wxCommandEvent& event)
715{
716        wxString out;
717        int temp = 0;
718        if(m_rolls < 3){
719                YahtzeeBonus();
720                for(int i = 0; i<5; i++)
721                        temp += dice[i]+1;
722       
723                out.Printf(wxT("%i"),temp);
724                ((wxTextCtrl*) FindWindow(ID_CHANCETEXT))->SetValue(out);
725               
726                PostScore(event.GetId());
727        }
728        else
729                wxMessageBox(wxT("First you need to roll, and after you roll you may score"), wxT("OpenYahtzee"), wxOK | wxICON_INFORMATION, this);
730
731}
732
733/**
734 * Event handler for mouse clicks on the dice.
735 *
736 * When clicking on the dice this event-handler ticks the appropriate "keep" checkbox.
737 * \param event
738 */
739void MainFrame::OnDiceClick (wxCommandEvent& event)
740{
741        //tick the checkbox
742        if (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->IsEnabled()){
743                bool newvalue = (((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP))->GetValue())?false:true;
744                ((wxCheckBox*) FindWindow(event.GetId()-ID_DICE1 + ID_DICE1KEEP)) -> SetValue(newvalue);
745        }
746
747        //dispatch a click event on the checkbox
748        wxCommandEvent clickevent((event.GetId()-ID_DICE1 + ID_DICE1KEEP),wxEVT_COMMAND_CHECKBOX_CLICKED);
749        clickevent.SetEventObject( this );
750        clickevent.SetId(event.GetId()-ID_DICE1 + ID_DICE1KEEP);
751        this->OnKeepClick(clickevent); ///\todo find a better way to call the event handler.
752}
753
754void MainFrame::OnKeepClick (wxCommandEvent& event)
755{
756        wxCheckBox *temp = (wxCheckBox*) FindWindow(event.GetId());
757        ((wxDynamicBitmap*) FindWindow(event.GetId()-ID_DICE1KEEP + ID_DICE1))->SetGrayScale(temp->GetValue());
758}
759
760//********************************************
761//******        General Functions       ******
762//********************************************
763
764/**
765 * This function clears the dice hash.
766 *
767 * The dice hash is just an array that holds how many dices have each value.
768 */
769void MainFrame::ClearDiceHash()
770{
771        for (int i=0; i<6; i++)
772                dicehash[i] = 0;
773}
774
775/**
776 * This function handles everything related to reseting the dice rolls after scoring.
777 */
778void MainFrame::ResetRolls()
779{
780        m_rollsundo = m_rolls;
781        m_rolls = 3;
782        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(true);
783        for (int i=0; i<5; i++){
784                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> SetValue(false);
785                ((wxCheckBox*) FindWindow(i + ID_DICE1KEEP)) -> Enable(false);
786                ((wxDynamicBitmap*) FindWindow(i+ID_DICE1)) -> SetGrayScale(false);
787        }
788}
789
790/**
791 * This function checks for a Yahtzee Bonus situation and if one exists it scores accordingly.
792 */
793void MainFrame::YahtzeeBonus()
794{
795        long temp;
796        wxString tempstr;
797       
798        //if the player didn't have any yathzees yet he can't have the bonus;
799        if (!m_yahtzee)
800                return;
801        if ((dice[0]==dice[1]) && (dice[1]==dice[2]) && (dice[1]==dice[3]) && (dice[1]==dice[4])) {
802                tempstr = ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> GetValue();
803                tempstr.ToLong(&temp,10);
804                temp += 100;
805                tempstr.Printf(wxT("%i"),temp);
806                ((wxTextCtrl*) FindWindow(ID_YAHTZEEBONUSTEXT)) -> SetValue(tempstr);
807                m_yahtzeebonus = true;
808        }       
809}
810
811/**
812 * This function checks whether we have a Yahtzee Joker situation.
813 * \return true if there is Yahtzee Joker, false otherwise.
814 */
815bool MainFrame::YahtzeeJoker()
816{
817        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())) {
818                return true;
819        }
820        return false;
821}
822
823/**
824 * This function handles the end of game.
825 *
826 * When a game ends it calculates the total score and submit it to the high
827 * score list.
828 */
829void MainFrame::EndofGame()
830{
831        if(m_numofplaysleft>0)
832                return;
833       
834        wxString tempstr;
835        long temp;
836        long upperscore = 0;
837        long lowerscore = 0;
838
839        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
840                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
841                tempstr.ToLong(&temp,10);
842                upperscore +=temp;
843        }
844       
845        tempstr.Printf(wxT("%i"),upperscore);
846        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
847       
848        //check for bonus
849        if(upperscore>=63) {
850                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("35"));
851                upperscore +=35;
852        } else
853                ((wxTextCtrl*) FindWindow(ID_BONUS)) -> SetValue(wxT("0"));
854       
855        tempstr.Printf(wxT("%i"),upperscore);
856        ((wxTextCtrl*) FindWindow(ID_UPPERTOTAL)) -> SetValue(tempstr);
857       
858        //calculate total on lower section
859        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
860                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
861                tempstr.ToLong(&temp,10);
862                lowerscore +=temp;
863        }
864       
865        tempstr.Printf(wxT("%i"),lowerscore);
866        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
867        tempstr.Printf(wxT("%i"),upperscore + lowerscore);
868        ((wxTextCtrl*) FindWindow(ID_GRANDTOTAL)) -> SetValue(tempstr);
869
870        //disable the roll button;
871        ((wxButton*) FindWindow(ID_ROLL)) -> Enable(false);
872
873        tempstr.Printf(wxT("Your final score is %i points!"),lowerscore+upperscore);
874        wxMessageBox(tempstr, wxT("Game Ended"), wxOK | wxICON_INFORMATION, this);
875
876        //submit to high score
877        HighScoreHandler(lowerscore+upperscore);
878       
879}
880
881/**
882 * This function checks if a given score qualifies for the high score list and
883 * adds it to the list if it does.
884 * @param score The score submitted to the high score list.
885 */
886void MainFrame::HighScoreHandler(int score)
887{
888        int place;
889        std::string name,date;
890        wxCommandEvent newevent;
891
892
893        place = m_highscoredb->IsHighScore(score);
894       
895        if(!place)  //if the score didn't make it to the highscore table do nothing
896                return;
897        HighScoreInfo *infodialog = new HighScoreInfo(this,place);
898        infodialog->ShowModal();
899
900        name = infodialog->GetName().mb_str();
901
902        //get the date
903        wxDateTime now = wxDateTime::Now();
904        date = now.FormatISOTime().mb_str();
905        date +=" ";
906        date += now.FormatDate().mb_str();
907
908        m_highscoredb->SendHighScore(name,date,score);
909
910        //now show the high score table
911        newevent.SetId(ID_SHOWHIGHSCORE);
912        newevent.SetEventType(wxEVT_COMMAND_MENU_SELECTED);
913        ProcessEvent(newevent);
914
915}
916
917///this function handles all the post scoring stuff such as disabling the right button.
918/**
919 * This function is always called after scoring and it handles all the post-score
920 * stuff such as reseting the dice rolls, enabling the undo button, calculating
921 * the sub-total scores and ending the game if necessary.
922 * \param id
923 */
924void MainFrame::PostScore(int id)
925{
926        //now after the scoring reset the rolls
927        ResetRolls();
928
929        CalculateSubTotal();
930
931        //and disable the button
932        FindWindow(id)->Enable(false);
933        m_numofplaysleft--;
934        EnableUndo(id);
935        EndofGame();
936}
937
938/**
939 * This function calculates the sub-total scores and should be called after
940 * every score. It does so only if this feature is requested in the settings
941 * dialog.
942 */
943void MainFrame::CalculateSubTotal()
944{
945        if (!m_calculatesubtotal)
946                return;
947        long upperscore = 0;
948        long lowerscore = 0;
949        wxString tempstr;
950        long temp;
951
952
953        for (int i = ID_ACESTEXT; i<=ID_SIXESTEXT; i++){
954                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
955                tempstr.ToLong(&temp,10);
956                upperscore +=temp;
957        }
958       
959        tempstr.Printf(wxT("%i"),upperscore);
960        ((wxTextCtrl*) FindWindow(ID_UPPERSECTIONTOTAL)) -> SetValue(tempstr);
961
962        for (int i = ID_THREEOFAKINDTEXT; i<=ID_YAHTZEEBONUSTEXT; i++) {
963                tempstr = ((wxTextCtrl*) FindWindow(i)) -> GetValue();
964                tempstr.ToLong(&temp,10);
965                lowerscore +=temp;
966        }
967       
968        tempstr.Printf(wxT("%i"),lowerscore);
969        ((wxTextCtrl*) FindWindow(ID_LOWERTOTAL)) -> SetValue(tempstr);
970}
971
972/**
973 * This function launches the default browser and directs it to a given url.
974 *
975 * This function extends the wxWidgets default function for this job by checking manually for
976 * different browsers if the wxWidgets' function doesn't find one. This is usually necessary
977 * under linux when epiphany isn't installed for some unknown reason.
978 * @param link The url that the browser will go to when it stats.
979 */
980void MainFrame::LaunchBrowser (wxString link){
981        if (!wxLaunchDefaultBrowser(link)){
982                 //if builtin function doesn't work search for couple of browsers manually. see
983                 //http://linux-consulting.buanzo.com.ar/2006/05/wxwidgets-code-to-launch-browser.html
984
985                // variable declarations
986                wxArrayString browsers;
987                wxPathList path_list;
988                bool BrowserWasFound = false;
989                unsigned int i = 0;
990                wxString path;
991
992                // Add directories to wxPathList's search path from PATH environment variable
993                path_list.AddEnvList(wxT("PATH"));
994               
995                // Add browsers filenames. First item = most priority
996                browsers.Add(wxT("firefox"));
997                browsers.Add(wxT("firefox-bin"));
998                browsers.Add(wxT("mozilla"));
999                browsers.Add(wxT("mozilla-bin"));
1000                browsers.Add(wxT("opera"));
1001                browsers.Add(wxT("konqueror"));
1002                browsers.Add(wxT("epiphany"));
1003               
1004                for (i = 0; i < browsers.GetCount(); i++) {
1005                        path = path_list.FindAbsoluteValidPath(browsers[i]);
1006                        if (path.IsEmpty()) {
1007                                continue;
1008                        } else {
1009                                BrowserWasFound = true;
1010                                break;
1011                        }
1012                }
1013               
1014                browsers.Clear();
1015               
1016                if (BrowserWasFound) {
1017                        path += wxT(" ");
1018                        path += link;
1019                        ::wxExecute(path);
1020                } else {
1021                        wxMessageBox(wxT("No browser has been found."),wxT("OpenYahtzee"));
1022                }
1023        }
1024}
Note: See TracBrowser for help on using the repository browser.