1 /*
2  * Copyright (C) 2007-2011 Jordi Mas i Hernàndez <jmas@softcatala.org>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 using System;
19 using Gtk;
20 using Mono.Unix;
21 using System.Diagnostics;
22 using Gdk;
23 using System.Reflection;
24 
25 using gbrainy.Core.Main;
26 using gbrainy.Core.Platform;
27 using gbrainy.Core.Services;
28 using gbrainy.Core.Libraries;
29 using gbrainy.Clients.Classical.Dialogs;
30 using gbrainy.Clients.Classical.Widgets;
31 
32 
33 namespace gbrainy.Clients.Classical
34 {
35 	public class GtkClient
36 	{
37 		[Builder.Object("gbrainy")] Gtk.Window app_window;
38 		[Builder.Object] Gtk.CheckMenuItem showtoolbar_menuitem;
39 		[Builder.Object] Box drawing_vbox;
40 		[Builder.Object] Gtk.Box main_hbox;
41 		[Builder.Object] Gtk.Box framework_vbox;
42 		[Builder.Object] Gtk.Entry answer_entry;
43 		[Builder.Object] Gtk.Button answer_button;
44 		[Builder.Object] Gtk.Label answer_label;
45 		[Builder.Object] Gtk.Button tip_button;
46 		[Builder.Object] Gtk.Button next_button;
47 		[Builder.Object] Gtk.Statusbar statusbar;
48 		[Builder.Object] Gtk.MenuBar menubar;
49 		[Builder.Object] Gtk.MenuItem pause_menuitem;
50 		[Builder.Object] Gtk.MenuItem finish_menuitem;
51 		[Builder.Object] Gtk.MenuItem newgame_menuitem;
52 		[Builder.Object] Gtk.MenuItem allgames_menuitem;
53 		[Builder.Object] Gtk.MenuItem logic_menuitem;
54 		[Builder.Object] Gtk.MenuItem calculation_menuitem;
55 		[Builder.Object] Gtk.MenuItem memory_menuitem;
56 		[Builder.Object] Gtk.MenuItem verbal_menuitem;
57 		[Builder.Object] Gtk.MenuItem extensions_menuitem;
58 		[Builder.Object] Gtk.RadioMenuItem vertical_radiomenuitem;
59 		[Builder.Object] Gtk.RadioMenuItem horizontal_radiomenuitem;
60 		[Builder.Object] Gtk.MenuItem toolbar_orientation_menuitem;
61 
62 		Widgets.Toolbar toolbar;
63 
64 		GameDrawingArea drawing_area;
65 		GameSession session;
66 		bool full_screen;
67 		GameSession.Types initial_session;
68 		static bool pluggins_loaded;
69 
70 		public readonly int MIN_TRANSLATION = 80;
71 
GtkClient(ITranslations translations)72 		public GtkClient (ITranslations translations)
73 		{
74 			Translations = translations;
75 			if (Preferences.Get <bool> (Preferences.EnglishKey) == false)
76 			{
77 				translations.Init ("gbrainy", Defines.GNOME_LOCALE_DIR);
78 			}
79 
80 			Unix.FixLocaleInfo ();
81 		}
82 
83 		public GameSession Session {
84 			get { return session; }
85 		}
86 
87 		public GameSession.Types InitialSessionType {
88 			get { return initial_session; }
89 			set { initial_session = value; }
90 		}
91 
92 		ITranslations Translations {get; set;}
93 
Initialize()94 		public void Initialize ()
95 		{
96 			session = new GameSession (Translations);
97 
98 			GameManagerPreload (session.GameManager);
99 			Console.WriteLine (session.GameManager.GetGamesSummary (Translations));
100 
101 			session.PlayList.ColorBlind = Preferences.Get <bool> (Preferences.ColorBlindKey);
102 			session.DrawRequest += SessionDrawRequest;
103 			session.UpdateUIElement += SessionUpdateUIElement;
104 			session.SynchronizingObject = new GtkSynchronize ();
105 			session.Difficulty = (GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey);
106 
107 			BuildUI ();
108 		}
109 
GameManagerPreload(GameManager gm)110 		public static void GameManagerPreload (GameManager gm)
111 		{
112 			gm.LoadAssemblyGames (Defines.GAME_ASSEMBLY);
113 			gm.LoadVerbalAnalogies (System.IO.Path.Combine (Defines.DATA_DIR, Defines.VERBAL_ANALOGIES));
114 			gm.LoadGamesFromXml (System.IO.Path.Combine (Defines.DATA_DIR, Defines.GAMES_FILE));
115 		}
116 
BuildUI()117 		void BuildUI ()
118 		{
119 			bool show_toolbar;
120 
121 			Builder builder = new Builder ("gbrainy.ui");
122 			builder.Autoconnect (this);
123 
124 			show_toolbar = Preferences.Get <bool> (Preferences.ToolbarShowKey) == true;
125 
126 			// Toolbar creation
127 			toolbar = new Widgets.Toolbar (main_hbox, framework_vbox);
128 			toolbar.Attach ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey));
129 			toolbar.AllButton.Clicked += OnAllGames;
130 			toolbar.LogicButton.Clicked += OnLogicOnly;
131 			toolbar.CalculationButton.Clicked += OnMathOnly;
132 			toolbar.MemoryButton.Clicked += OnMemoryOnly;
133 			toolbar.VerbalButton.Clicked += OnVerbalOnly;
134 			toolbar.PauseButton.Clicked += OnPauseGame;
135 			toolbar.FinishButton.Clicked += OnEndGame;
136 
137 			drawing_area = new GameDrawingArea ();
138 			drawing_area.Drawable = session;
139                         drawing_area.Vexpand = true;
140                         drawing_area.SetSizeRequest (drawing_vbox.WidthRequest, drawing_vbox.HeightRequest);
141 			GameSensitiveUI ();
142 
143 			EventBox eb = new EventBox (); // Provides a window for drawing area windowless widget
144 
145 			eb.Events = Gdk.EventMask.PointerMotionMask;
146 			drawing_vbox.Add (eb);
147 
148 			eb.Add (drawing_area);
149 
150 			eb.MotionNotifyEvent += OnMouseMotionEvent;
151 			eb.ButtonPressEvent += OnHandleButtonPress;
152 
153 			show_toolbar = Preferences.Get <bool> (Preferences.ToolbarShowKey) == true;
154 
155 			// We only disable the Arrow if we are going to show the toolbar.
156 			// It has an impact on the total window width size even if we do not show it
157 			if (show_toolbar)
158 				toolbar.ShowArrow = false;
159 
160 			app_window.IconName = "gbrainy";
161 
162 			app_window.ShowAll ();
163 
164 			toolbar_orientation_menuitem.Sensitive = toolbar.Visible;
165 
166 			// Check default radio button
167 			switch (toolbar.Orientation) {
168 			case Gtk.Orientation.Vertical:
169 				vertical_radiomenuitem.Active = true;
170 				break;
171 			case Gtk.Orientation.Horizontal:
172 				horizontal_radiomenuitem.Active = true;
173 				break;
174 			default:
175 				throw new InvalidOperationException ();
176 			}
177 
178 			// The toolbar by default is enabled. By setting this menu entry to false
179 			// triggers the OnActivateToolbar event that hides the toolbar
180 			if (show_toolbar == false)
181 				showtoolbar_menuitem.Active = false;
182 
183 			extensions_menuitem.Visible = false;
184 			ActiveInputControls (false);
185 		}
186 
ProcessDefaults()187 		public void ProcessDefaults ()
188 		{
189 			if (InitialSessionType != GameSession.Types.None)
190 				OnNewGame (InitialSessionType);
191 		}
192 
193 		// Gamesession has requested a question refresh
SessionUpdateUIElement(object o, UpdateUIStateEventArgs args)194 		public void SessionUpdateUIElement (object o, UpdateUIStateEventArgs args)
195 		{
196 			switch (args.EventType) {
197 			case UpdateUIStateEventArgs.EventUIType.QuestionText:
198 				UpdateQuestion ((string) args.Data);
199 				ActiveInputControls (true);
200 				break;
201 			case UpdateUIStateEventArgs.EventUIType.Time:
202 				UpdateStatusBar ();
203 				break;
204 			default:
205 				throw new InvalidOperationException ("Unknown value");
206 			}
207 		}
208 
209 		// Gamesession has requested a redraw of the drawingarea
SessionDrawRequest(object o, EventArgs args)210 		public void SessionDrawRequest (object o, EventArgs args)
211 		{
212 			drawing_area.QueueDraw ();
213 		}
214 
OnMouseMotionEvent(object o, MotionNotifyEventArgs ev_args)215 		void OnMouseMotionEvent (object o, MotionNotifyEventArgs ev_args)
216 		{
217 			SendMouseEvent (ev_args.Event.X, ev_args.Event.Y, MouseEventType.Move);
218 		}
219 
OnHandleButtonPress(object o, ButtonPressEventArgs ev_args)220 		void OnHandleButtonPress (object o, ButtonPressEventArgs ev_args)
221 		{
222 			if (ev_args.Event.Type != EventType.ButtonPress)
223 				return;
224 
225 			SendMouseEvent (ev_args.Event.X, ev_args.Event.Y, MouseEventType.ButtonPress);
226 		}
227 
SendMouseEvent(double ev_x, double ev_y, MouseEventType type)228 		void SendMouseEvent (double ev_x, double ev_y, MouseEventType type)
229 		{
230 			double x, y;
231 			int drawing_square = drawing_area.DrawingSquare;
232 
233 			x = ev_x - drawing_area.OffsetX;
234 			y = ev_y - drawing_area.OffsetY;
235 
236 			if (x < 0 || y < 0 || x > drawing_square || y > drawing_square)
237 				return;
238 
239 			x =  x / drawing_square;
240 			y =  y / drawing_square;
241 
242 			session.MouseEvent (this, new MouseEventArgs (x, y, type));
243 		}
244 
UpdateStatusBar()245 		public void UpdateStatusBar ()
246 		{
247 			statusbar.Push (0, session.StatusText);
248 		}
249 
250 		// These are UI elements dependent of the game status
ActiveInputControls(bool active)251 		public void ActiveInputControls (bool active)
252 		{
253 			bool answer, next, tip, can_pause;
254 
255 			can_pause = answer = next = tip = active;
256 
257 			if (active == true && session.CurrentGame != null && session.CurrentGame.ButtonsActive == true && String.IsNullOrEmpty (session.CurrentGame.Tip ) == false)
258 				tip = true;
259 			else
260 				tip = false;
261 
262 			switch (session.Status) {
263 			case GameSession.SessionStatus.NotPlaying:
264 			case GameSession.SessionStatus.Finished:
265 				answer = false;
266 				next = false;
267 				tip = false;
268 				can_pause = false;
269 				break;
270 			case GameSession.SessionStatus.Playing:
271 				if (session.CurrentGame != null) {
272 					can_pause = session.CurrentGame.ButtonsActive;
273 				}
274 				else {
275 					can_pause = true;
276 				}
277 				break;
278 			case GameSession.SessionStatus.Answered:
279 				answer = false;
280 				tip = false;
281 				can_pause = false;
282 				break;
283 			}
284 
285 			answer_button.Sensitive = answer;
286 			answer_entry.Sensitive = answer;
287 			answer_label.Sensitive = answer;
288 			next_button.Sensitive = next;
289 			tip_button.Sensitive = tip;
290 			pause_menuitem.Sensitive = toolbar.PauseButton.Sensitive = can_pause;
291 
292 			if (answer == true)
293 				answer_entry.GrabFocus ();
294 		}
295 
UpdateQuestion(string question)296 		public void UpdateQuestion (string question)
297 		{
298 			drawing_area.Question = question;
299 		}
300 
QueueDraw()301 		public void QueueDraw ()
302 		{
303 			drawing_area.QueueDraw ();
304 		}
305 
UpdateSolution(string solution, GameDrawingArea.SolutionType solution_type)306 		void UpdateSolution (string solution, GameDrawingArea.SolutionType solution_type)
307 		{
308 			drawing_area.Solution = solution;
309 			drawing_area.SolutionIcon = solution_type;
310 			QueueDraw ();
311 		}
312 
313 		// These are UI elements independent of the game status, set only when the game starts / ends
GameSensitiveUI()314 		void GameSensitiveUI ()
315 		{
316 			//Toolbar buttons and menu items that are sensitive when the user is playing
317 			bool playing;
318 			GameTypes available;
319 
320 			playing = (session.Status == GameSession.SessionStatus.Playing);
321 			toolbar.FinishButton.Sensitive = playing;
322 
323 			available = session.AvailableGames;
324 
325 			if (playing == false && ((available & GameTypes.LogicPuzzle) == GameTypes.LogicPuzzle))
326 				logic_menuitem.Sensitive = toolbar.LogicButton.Sensitive = true;
327 			else
328 				logic_menuitem.Sensitive = toolbar.LogicButton.Sensitive = false;
329 
330 			if (playing == false && ((available & GameTypes.Calculation) == GameTypes.Calculation))
331 				memory_menuitem.Sensitive = toolbar.MemoryButton.Sensitive = true;
332 			else
333 				memory_menuitem.Sensitive = toolbar.MemoryButton.Sensitive = false;
334 
335 			if (playing == false && ((available & GameTypes.Calculation) == GameTypes.Calculation))
336 				calculation_menuitem.Sensitive = toolbar.CalculationButton.Sensitive = true;
337 			else
338 				calculation_menuitem.Sensitive = toolbar.CalculationButton.Sensitive = false;
339 
340 			if (playing == false && ((available & GameTypes.VerbalAnalogy) == GameTypes.VerbalAnalogy))
341 				verbal_menuitem.Sensitive = toolbar.VerbalButton.Sensitive = true;
342 			else
343 				verbal_menuitem.Sensitive = toolbar.VerbalButton.Sensitive = false;
344 
345 			if (playing == false && (available != GameTypes.None))
346 				allgames_menuitem.Sensitive = toolbar.AllButton.Sensitive = true;
347 			else
348 				allgames_menuitem.Sensitive = toolbar.AllButton.Sensitive = false;
349 
350 			finish_menuitem.Sensitive = playing;
351 			newgame_menuitem.Sensitive = !playing;
352 		}
353 
GetNextGame()354 		private void GetNextGame ()
355 		{
356 			UpdateSolution (String.Empty, GameDrawingArea.SolutionType.None);
357 			UpdateQuestion (String.Empty);
358 
359 			if (session.CurrentGame != null) {
360 				session.CurrentGame.AnswerEvent -= OnAnswerFromGame;
361 			}
362 
363 			session.NextGame ();
364 			session.CurrentGame.AnswerEvent += OnAnswerFromGame;
365 
366 			ActiveInputControls (session.CurrentGame.ButtonsActive);
367 			next_button.Sensitive = true;
368 			UpdateQuestion (session.CurrentGame.Question);
369 			answer_entry.Text = string.Empty;
370 			UpdateStatusBar ();
371 			session.CurrentGame.Answer.Draw = false;
372 			drawing_area.QueueDraw ();
373 		}
374 
375 		// The user has clicked with the mouse in an answer and generated this event
OnAnswerFromGame(object obj, GameAnswerEventArgs args)376 		void OnAnswerFromGame (object obj, GameAnswerEventArgs args)
377 		{
378 			answer_entry.Text = args.AnswerText;
379 			OnAnswerButtonClicked (this, EventArgs.Empty);
380 			session.CurrentGame.AnswerEvent -= OnAnswerFromGame; // User can only answer once
381 		}
382 
OnMenuAbout(object sender, EventArgs args)383 		void OnMenuAbout (object sender, EventArgs args)
384 		{
385 			Dialogs.AboutDialog about = new Dialogs.AboutDialog ();
386 			about.Run ();
387 		}
388 
OnMenuHelp(object sender, EventArgs args)389 		void OnMenuHelp (object sender, EventArgs args)
390 		{
391 			Unix.ShowUri (null, "help:gbrainy",
392 				Gdk.EventHelper.GetTime (new Gdk.Event(IntPtr.Zero)));
393 		}
394 
OnAnswerButtonClicked(object sender, EventArgs args)395 		void OnAnswerButtonClicked (object sender, EventArgs args)
396 		{
397 			string answer;
398 			bool correct;
399 
400 			if (session.CurrentGame == null)
401 				return;
402 
403 			correct = session.ScoreGame (answer_entry.Text);
404 			if (correct)
405 			{
406 				answer = Translations.GetString ("Congratulations.");
407 			}
408 			else
409 			{
410 				answer = Translations.GetString ("Incorrect answer.");
411 			}
412 
413 			session.EnableTimer = false;
414 			answer_entry.Text = String.Empty;
415 			UpdateStatusBar ();
416 			UpdateSolution (answer + " " + session.CurrentGame.AnswerText,
417 				correct == true ? GameDrawingArea.SolutionType.CorrectAnswer :
418 			        GameDrawingArea.SolutionType.InvalidAnswer);
419 
420 			session.CurrentGame.Answer.Draw = true;
421 			ActiveInputControls (true);
422 			next_button.GrabFocus ();
423 			drawing_area.QueueDraw ();
424 
425 			if (Preferences.Get <bool> (Preferences.SoundsKey))
426 			{
427 				Unix.PlaySound(app_window.Handle, System.IO.Path.Combine(Defines.DATA_DIR, correct ? "right.oga" : "wrong.oga"));
428 			}
429 		}
430 
OnQuit(object sender, EventArgs args)431 		void OnQuit (object sender, EventArgs args)
432 		{
433 			Gtk.Application.Quit ();
434 		}
435 
OnDeleteWindow(object sender, DeleteEventArgs args)436 		void OnDeleteWindow (object sender, DeleteEventArgs args)
437 		{
438 			Gtk.Application.Quit ();
439 		}
440 
OnNextButtonClicked(object sender, EventArgs args)441 		void OnNextButtonClicked (object sender, EventArgs args)
442 		{
443 			if (answer_entry.Text.Length > 0) {
444 				OnAnswerButtonClicked (sender, args);
445 				return;
446 			}
447 
448 			session.ScoreGame (String.Empty);
449 			GetNextGame ();
450 			session.EnableTimer = true;
451 		}
452 
OnTip(object sender, EventArgs args)453 		void OnTip (object sender, EventArgs args)
454 		{
455 			if (session.CurrentGame == null)
456 				return;
457 
458 			UpdateSolution (session.CurrentGame.TipString, GameDrawingArea.SolutionType.Tip);
459 		}
460 
OnNewGame(GameSession.Types type)461 		void OnNewGame (GameSession.Types type)
462 		{
463 			// If the translation is lower than MIN_TRANSLATION explain that running the English version is an option
464 			if (ShouldShowTranslationWarning ())
465 				ShowTranslationWarning ();
466 
467 			session.Type = type;
468 			session.New ();
469 			GetNextGame ();
470 			GameSensitiveUI ();
471 			UpdateSolution (Translations.GetString ("Once you have an answer type it in the \"Answer:\" entry box and press the \"OK\" button."),
472 				GameDrawingArea.SolutionType.Tip);
473 			UpdateStatusBar ();
474 		}
475 
ShouldShowTranslationWarning()476 		public bool ShouldShowTranslationWarning ()
477 		{
478 			// Notify the user once per version only
479 			if (String.Compare (Preferences.Get <string> (Preferences.EnglishVersionKey), Defines.VERSION, 0) == 0)
480 				return false;
481 
482 			int percentage = Translations.TranslationPercentage;
483 			if (percentage > 0 && percentage < MIN_TRANSLATION)
484 			{
485 				Preferences.Set <string> (Preferences.EnglishVersionKey, Defines.VERSION);
486 				Preferences.Save ();
487 				return true;
488 			}
489 
490 			return false;
491 		}
492 
ShowTranslationWarning()493 		void ShowTranslationWarning ()
494 		{
495 			HigMessageDialog dlg;
496 
497 			dlg = new HigMessageDialog (app_window,
498 				Gtk.DialogFlags.DestroyWithParent,
499 				Gtk.MessageType.Warning,
500 				Gtk.ButtonsType.Ok,
501 				Translations.GetString ("The level of translation of gbrainy for your language is low."),
502 				Translations.GetString ("You may be exposed to partially translated games making it more difficult to play. If you prefer to play in English, there is an option for doing so in gbrainy's Preferences."));
503 
504 			try {
505 	 			dlg.Run ();
506 	 		} finally {
507 	 			dlg.Destroy ();
508 	 		}
509 		}
510 
OnMathOnly(object sender, EventArgs args)511 		void OnMathOnly (object sender, EventArgs args)
512 		{
513 			OnNewGame (GameSession.Types.Calculation);
514 		}
515 
OnVerbalOnly(object sender, EventArgs args)516 		void OnVerbalOnly (object sender, EventArgs args)
517 		{
518 			OnNewGame (GameSession.Types.VerbalAnalogies);
519 		}
520 
OnMemoryOnly(object sender, EventArgs args)521 		void OnMemoryOnly (object sender, EventArgs args)
522 		{
523 			OnNewGame (GameSession.Types.Memory);
524 		}
525 
OnPdfExport(object sender, EventArgs args)526 		void OnPdfExport (object sender, EventArgs args)
527 		{
528 			PdfExportDialog pdf;
529 
530 			pdf = new PdfExportDialog (session.GameManager, Translations);
531 			pdf.Run ();
532 			pdf.Destroy ();
533 		}
534 
OnPreferences(object sender, EventArgs args)535 		void OnPreferences (object sender, EventArgs args)
536 		{
537 			PreferencesDialog dialog;
538 
539 			dialog = new PreferencesDialog (Translations, session.PlayerHistory);
540 			if ((Gtk.ResponseType) dialog.Run () == ResponseType.Ok) {
541 				session.Difficulty = (GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey);
542 				session.PlayList.ColorBlind = Preferences.Get <bool> (Preferences.ColorBlindKey);
543 
544 				if (dialog.NewThemeSet == true)
545 					drawing_area.ReloadBackground ();
546 			}
547 			dialog.Destroy ();
548 		}
549 
OnCustomGame(object sender, EventArgs args)550 		void OnCustomGame (object sender, EventArgs args)
551 		{
552 			CustomGameDialog dialog;
553 
554 			dialog = new CustomGameDialog (Translations, session);
555 			dialog.Run ();
556 			dialog.Destroy ();
557 
558 			if (dialog.SelectionDone == true)
559 				OnNewGame (GameSession.Types.Custom);
560 		}
561 
OnLogicOnly(object sender, EventArgs args)562 		void OnLogicOnly (object sender, EventArgs args)
563 		{
564 			OnNewGame (GameSession.Types.LogicPuzzles);
565 		}
566 
OnAllGames(object sender, EventArgs args)567 		void OnAllGames (object sender, EventArgs args)
568 		{
569 			OnNewGame (GameSession.Types.AllGames);
570 		}
571 
OnAnswerActivate(object sender, EventArgs args)572 		void OnAnswerActivate (object sender, EventArgs args)
573 		{
574 			if (answer_entry.Text.Length > 0) {
575 				OnAnswerButtonClicked (sender, args);
576 				return;
577 			}
578 		}
579 
OnEndGame(object sender, EventArgs args)580 		void OnEndGame (object sender, EventArgs args)
581 		{
582 			session.End ();
583 
584 			UpdateSolution (String.Empty, GameDrawingArea.SolutionType.None);
585 			UpdateQuestion (String.Empty);
586 			UpdateStatusBar ();
587 			GameSensitiveUI ();
588 			drawing_area.QueueDraw ();
589 			ActiveInputControls (false);
590 			SetPauseResumeButtonUI (true);
591 		}
592 
SetPauseResumeButtonUI(bool pause)593 		void SetPauseResumeButtonUI (bool pause)
594 		{
595 			if (pause) {
596 				drawing_area.Paused = false;
597 				toolbar.PauseButton.StockId = "pause";
598 				toolbar.PauseButton.Label = Translations.GetString ("Pause");
599 				ActiveInputControls (true);
600 			} else {
601 				drawing_area.Paused = true;
602 				toolbar.PauseButton.StockId = "resume";
603 				toolbar.PauseButton.Label = Translations.GetString ("Resume");
604 				ActiveInputControls (false);
605 			}
606 			UpdateStatusBar ();
607 		}
608 
SetPauseResumeButton(bool pause)609 		void SetPauseResumeButton (bool pause)
610 		{
611 			if (pause)
612 	 			session.Resume ();
613 			else
614 				session.Pause ();
615 
616 			SetPauseResumeButtonUI (pause);
617 		}
618 
OnPauseGame(object sender, EventArgs args)619 		void OnPauseGame (object sender, EventArgs args)
620 		{
621 			SetPauseResumeButton (session.Paused);
622 		}
623 
OnActivateToolbar(object sender, System.EventArgs args)624 		void OnActivateToolbar (object sender, System.EventArgs args)
625 		{
626 			int width, height;
627 			Requisition minimum_size, natural_size;
628 
629 			toolbar.GetPreferredSize(out minimum_size, out natural_size);
630 			app_window.GetSize (out width, out height);
631 			toolbar.Visible = !toolbar.Visible;
632 
633 			if (toolbar.Visible)
634 				toolbar.ShowArrow = false;
635 
636 			toolbar_orientation_menuitem.Sensitive = toolbar.Visible;
637 
638 			if (Preferences.Get <bool> (Preferences.ToolbarShowKey) != toolbar.Visible)
639 			{
640 				Preferences.Set <bool> (Preferences.ToolbarShowKey, toolbar.Visible);
641 				Preferences.Save ();
642 			}
643 			app_window.Resize (width, height - natural_size.Height);
644 		}
645 
OnVerticalToolbar(object sender, System.EventArgs args)646 		void OnVerticalToolbar (object sender, System.EventArgs args)
647 		{
648 			if (toolbar.InitCompleted  == false)
649 				return;
650 
651 			const Gtk.Orientation orientation = Gtk.Orientation.Vertical;
652 
653 			if ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey) != orientation)
654 			{
655 				Preferences.Set <int> (Preferences.ToolbarOrientationKey, (int) orientation);
656 				Preferences.Save ();
657 			}
658 			toolbar.Attach (orientation);
659 		}
660 
OnHorizontalToolbar(object sender, System.EventArgs args)661 		void OnHorizontalToolbar (object sender, System.EventArgs args)
662 		{
663 			if (toolbar.InitCompleted  == false)
664 				return;
665 
666 			const Gtk.Orientation orientation = Gtk.Orientation.Horizontal;
667 
668 			if ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey) != orientation)
669 			{
670 				Preferences.Set <int>  (Preferences.ToolbarOrientationKey, (int) Gtk.Orientation.Horizontal);
671 				Preferences.Save ();
672 			}
673 			toolbar.Attach (orientation);
674 		}
675 
OnHistory(object sender, EventArgs args)676 		void OnHistory (object sender, EventArgs args)
677 		{
678 			PlayerHistoryDialog dialog;
679 
680 			dialog = new PlayerHistoryDialog (Translations, session.PlayerHistory);
681 			dialog.Run ();
682 			dialog.Destroy ();
683 		}
684 
OnFullscreen(object sender, EventArgs args)685 		void OnFullscreen (object sender, EventArgs args)
686 		{
687 			if (full_screen == false) {
688 				app_window.Fullscreen ();
689 			}
690 			else {
691 				app_window.Unfullscreen ();
692 			}
693 
694 			full_screen = !full_screen;
695 		}
696 
InitCoreLibraries()697 		static void InitCoreLibraries ()
698 		{
699 			new DefaultServices ().RegisterServices ();
700 
701 			// Configuration
702 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.GamesDefinitions, Defines.DATA_DIR);
703 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.GamesGraphics, Defines.DATA_DIR);
704 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.ThemesDir, Defines.DATA_DIR);
705 
706 			string assemblies_dir;
707 			assemblies_dir =  System.IO.Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location);
708 			ServiceLocator.Instance.GetService <IConfiguration> ().Set (ConfigurationKeys.AssembliesDir, assemblies_dir);
709 		}
710 
Main(string [] args)711 		public static void Main (string [] args)
712 		{
713 			try {
714 				Unix.SetProcessName ("gbrainy");
715 			}
716 			catch (Exception e)
717 			{
718 				Console.WriteLine ("gbrainy.Main. Could not set process name. Error {0}", e);
719 			}
720 
721 			DateTime start_time = DateTime.Now;
722 			ITranslations translations = new TranslationsCatalog ();
723 
724 			InitCoreLibraries ();
725 
726 			GtkClient app = new GtkClient (translations);
727 			CommandLine.Version ();
728 
729 			CommandLine line = new CommandLine (translations, args);
730 			line.Parse ();
731 
732 			if (line.Continue == false)
733 				return;
734 
735 			Gtk.Application.Init ();
736 
737 			app.Initialize ();
738 			// Set RandomOrder before setting the custom list then it has effect of custom games
739 			app.Session.PlayList.RandomOrder = line.RandomOrder;
740 			if (line.PlayList.Length > 0) {
741 				app.Session.PlayList.PlayList = line.PlayList;
742 				app.InitialSessionType = GameSession.Types.Custom;
743 			}
744 			app.ProcessDefaults ();
745 			ThemeManager.Load ();
746 
747 			TimeSpan span = DateTime.Now - start_time;
748 			Console.WriteLine (Catalog.GetString ("Startup time {0}"), span);
749 			Gtk.Application.Run ();
750 		}
751 	}
752 }
753