9 #include <glib/gi18n.h>
11 #ifdef WITH_MAEMOFULLSCREEN
12 #include <hildon-widgets/hildon-program.h>
16 #include "GtkDasherControl.h"
17 #include "dasher_lock_dialogue.h"
19 #include "dasher_maemo_helper.h"
21 #include "dasher_main.h"
23 #include "dasher_editor.h"
24 #include "dasher_editor_internal.h"
25 #include "dasher_editor_external.h"
28 struct _DasherMainPrivate
{
32 // Child objects owned here
33 DasherAppSettings
*pAppSettings
;
34 DasherPreferencesDialogue
*pPreferencesDialogue
;
35 DasherEditor
*pEditor
;
37 CKeyboardHelper
*pKeyboardHelper
;
39 // Various widgets which need to be cached:
40 // GtkWidget *pBufferView;
42 GtkWindow
*pMainWindow
;
44 GtkSpinButton
*pSpeedBox
;
45 GtkWidget
*pAlphabetCombo
;
46 GtkWidget
*pStatusControl
;
47 GtkWidget
*pDasherWidget
;
49 GtkListStore
*pAlphabetList
;
50 GtkAccelGroup
*pAccel
;
52 // Widgets used for maemo
54 DasherMaemoHelper
*pMaemoHelper
;
55 #ifdef WITH_MAEMOFULLSCREEN
56 HildonProgram
*pProgram
;
57 HildonWindow
*pHWindow
;
61 // Properties of the main window
64 bool bWidgetsInitialised
;
67 typedef struct _DasherMainPrivate DasherMainPrivate
;
69 // TODO: Make sure this is actually used
70 #define DASHER_MAIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), DASHER_TYPE_MAIN, DasherMainPrivate))
77 static guint dasher_main_signals
[SIGNAL_NUM
] = { 0 };
79 G_DEFINE_TYPE(DasherMain
, dasher_main
, G_TYPE_OBJECT
);
81 static void dasher_main_finalize(GObject
*pObject
);
83 /* Private member functions */
84 static void dasher_main_setup_window_state(DasherMain
*pSelf
);
85 static void dasher_main_setup_window_style(DasherMain
*pSelf
);
86 static void dasher_main_setup_internal_layout(DasherMain
*pSelf
);
87 static void dasher_main_set_window_title(DasherMain
*pSelf
);
89 /* ... Table based menu/toolbar commands */
90 static void dasher_main_command_import(DasherMain
*pSelf
);
91 static void dasher_main_command_quit(DasherMain
*pSelf
);
92 static void dasher_main_command_preferences(DasherMain
*pSelf
);
93 static void dasher_main_command_preferences_alphabet(DasherMain
*pSelf
);
94 static void dasher_main_command_help(DasherMain
*pSelf
);
95 static void dasher_main_command_about(DasherMain
*pSelf
);
96 static void dasher_main_command_toggle_game_mode(DasherMain
*);
98 /* c.f. WRAP_CPP_CB below */
99 extern "C" void dasher_main_cb_import(GtkAction
*, DasherMain
*);
100 extern "C" void dasher_main_cb_quit(GtkAction
*, DasherMain
*);
101 extern "C" void dasher_main_cb_preferences(GtkAction
*, DasherMain
*);
102 extern "C" void dasher_main_cb_help(GtkAction
*, DasherMain
*);
103 extern "C" void dasher_main_cb_about(GtkAction
*, DasherMain
*);
104 extern "C" void dasher_main_cb_toggle_game_mode(GtkAction
*, DasherMain
*);
106 static gboolean
dasher_main_speed_changed(DasherMain
*pSelf
);
107 static void dasher_main_alphabet_combo_changed(DasherMain
*pSelf
);
108 // TODO: populate speed slider
109 static void dasher_main_populate_alphabet_combo(DasherMain
*pSelf
);
111 /* TODO: order these in file */
112 static GtkBuilder
*dasher_main_open_gui_xml(DasherMain
*, const char *);
113 static void dasher_main_load_interface(DasherMain
*pSelf
);
114 static void dasher_main_create_preferences(DasherMain
*pSelf
);
115 static void dasher_main_handle_parameter_change(DasherMain
*pSelf
, int iParameter
);
116 static void dasher_main_load_state(DasherMain
*pSelf
);
117 static void dasher_main_save_state(DasherMain
*pSelf
);
118 static void dasher_main_setup_window(DasherMain
*pSelf
);
119 static void dasher_main_populate_controls(DasherMain
*pSelf
);
120 static gint
dasher_main_lookup_key(DasherMain
*pSelf
, guint iKeyVal
);
122 /* TODO: Various functions which haven't yet been rationalised */
123 gboolean
grab_focus();
125 /* ... Message handling from main window widgets */
126 extern "C" void speed_changed(GtkWidget
*pWidget
, gpointer user_data
);
127 extern "C" void alphabet_combo_changed(GtkWidget
*pWidget
, gpointer pUserData
);
128 extern "C" void dasher_main_cb_filename_changed(DasherEditor
*pEditor
, gpointer pUserData
);
129 extern "C" void dasher_main_cb_buffer_changed(DasherEditor
*pEditor
, gpointer pUserData
);
130 extern "C" void dasher_main_cb_context_changed(DasherEditor
*pEditor
, gpointer pUserData
);
131 extern "C" gboolean
dasher_main_cb_window_close(GtkWidget
*pWidget
, gpointer pUserData
);
132 extern "C" void parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer data
);
134 /* ... Focus management and event forwarding */
135 extern "C" bool focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
);
136 extern "C" bool edit_focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
);
137 extern "C" gboolean
take_real_focus(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
);
139 extern "C" gboolean
edit_key_press(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
140 extern "C" gboolean
edit_key_release(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
142 /* ... Temporary test/debug functions */
143 extern "C" gboolean
test_focus_handler(GtkWidget
*pWidget
, GtkDirectionType iDirection
, gpointer
*pUserData
);
145 extern "C" void handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
);
146 extern "C" gint
dasher_main_key_snooper(GtkWidget
*pWidget
, GdkEventKey
*pEvent
, gpointer pUserData
);
148 /* Boilerplate code */
150 dasher_main_class_init(DasherMainClass
*pClass
) {
151 g_type_class_add_private(pClass
, sizeof(DasherMainPrivate
));
153 dasher_main_signals
[REALIZED
] =
154 g_signal_new("realized", G_TYPE_FROM_CLASS(pClass
),
155 (GSignalFlags
)(G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
),
156 G_STRUCT_OFFSET(DasherMainClass
, realized
),
157 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
,
160 GObjectClass
*pObjectClass
= (GObjectClass
*)pClass
;
161 pObjectClass
->finalize
= dasher_main_finalize
;
165 dasher_main_init(DasherMain
*pDasherMain
) {
166 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
168 pPrivate
->pAppSettings
= NULL
;
169 pPrivate
->pEditor
= NULL
;
170 pPrivate
->pPreferencesDialogue
= NULL
;
172 pPrivate
->pKeyboardHelper
= new CKeyboardHelper(NULL
);
174 pPrivate
->bWidgetsInitialised
= false;
178 dasher_main_finalize(GObject
*pObject
) {
180 DasherMain
*pDasherMain
= DASHER_MAIN(pObject
);
181 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
183 dasher_main_save_state(pDasherMain
);
185 /* TODO: Does unref really do the right thing - check the whole ref counting situation */
186 // if(pPrivate->pEditor)
187 // g_object_unref(pPrivate->pEditor);
189 if(pPrivate
->pPreferencesDialogue
)
190 g_object_unref(pPrivate
->pPreferencesDialogue
);
192 if(pPrivate
->pAppSettings
)
193 g_object_unref(pPrivate
->pAppSettings
);
195 gtk_widget_destroy(GTK_WIDGET(pPrivate
->pMainWindow
));
197 /* TODO: Do we need to take down anything else? */
202 dasher_main_new(int *argc
, char ***argv
, SCommandLine
*pCommandLine
) {
203 DasherMain
*pDasherMain
= (DasherMain
*)(g_object_new(dasher_main_get_type(), NULL
));
204 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
206 /* Create the app settings object */
207 pPrivate
->pAppSettings
= dasher_app_settings_new(pDasherMain
, *argc
, *argv
);
209 /* Load the user interface from the GUI file */
210 if(pCommandLine
&& pCommandLine
->szAppStyle
) {
211 if(!strcmp(pCommandLine
->szAppStyle
, "traditional")) {
212 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_TRAD
);
214 else if(!strcmp(pCommandLine
->szAppStyle
, "compose")) {
215 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_COMPOSE
);
217 else if(!strcmp(pCommandLine
->szAppStyle
, "direct")) {
218 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_DIRECT
);
220 else if(!strcmp(pCommandLine
->szAppStyle
, "fullscreen")) {
221 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_FULLSCREEN
);
224 g_critical("Application style %s is not supported", pCommandLine
->szAppStyle
);
229 // By default use traditional mode
230 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_TRAD
);
233 dasher_main_load_interface(pDasherMain
);
235 dasher_app_settings_set_widget(pPrivate
->pAppSettings
, GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
));
238 /* TODO: This parsing code should really be tidied up */
239 if(pCommandLine
&& pCommandLine
->szOptions
) {
240 gchar
**pszOptionTerms
;
241 pszOptionTerms
= g_strsplit(pCommandLine
->szOptions
, ",", 0);
243 gchar
**pszCurrent
= pszOptionTerms
;
246 gchar
*szJoin
= g_strrstr(*pszCurrent
, "=");
247 // Note to translators: This message will be output for command line errors when the "=" in --options=foo is missing.
248 const gchar
*errorMessage
= _("option setting is missing \"=\".");
251 int iLength
= szJoin
- *pszCurrent
;
253 gchar
*szKey
= g_new(gchar
, iLength
+ 1);
254 memcpy(szKey
, *pszCurrent
, iLength
);
255 szKey
[iLength
] = '\0';
257 errorMessage
= dasher_app_settings_cl_set(pPrivate
->pAppSettings
, szKey
, szJoin
+ 1);
263 // Note to translators: This string will be output when --options= specifies an unknown option.
264 g_critical("%s: '%s', %s", _("Invalid option string specified"), *pszCurrent
, errorMessage
);
271 g_strfreev(pszOptionTerms
);
276 dasher_editor_initialise(pPrivate
->pEditor
, pPrivate
->pAppSettings
, GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), pPrivate
->pXML
, NULL
);
279 dasher_main_setup_window(pDasherMain
);
281 /* Create the editor */
282 gchar
*szFullPath
= NULL
;
285 if(pCommandLine
->szFilename
) {
286 if(!g_path_is_absolute(pCommandLine
->szFilename
)) {
288 cwd
= (char *)malloc(1024 * sizeof(char));
290 szFullPath
= g_build_path("/", cwd
, pCommandLine
->szFilename
, NULL
);
293 szFullPath
= g_strdup(pCommandLine
->szFilename
);
299 // pPrivate->pEditor = GTK_EDITOR(
302 // dasher_editor_initialise(pPrivate->pAppSettings, pDasherMain, pPrivate->pXML, szFullPath);
306 /* Create the preferences window */
307 dasher_main_create_preferences(pDasherMain
);
309 /* Create the lock dialogue (to be removed in future versions) */
311 dasher_lock_dialogue_new(pPrivate
->pXML
, pPrivate
->pMainWindow
);
313 dasher_lock_dialogue_new(pPrivate
->pXML
, 0);
316 g_object_unref(pPrivate
->pXML
);
319 g_object_unref(pPrivate
->pPrefXML
);
320 pPrivate
->pPrefXML
= 0;
322 /* Set up various bits and pieces */
323 dasher_main_set_window_title(pDasherMain
);
324 dasher_main_populate_controls(pDasherMain
);
326 gtk_key_snooper_install(dasher_main_key_snooper
, pDasherMain
);
332 dasher_main_open_gui_xml(DasherMain
*pSelf
, const char *szGUIFilename
) {
334 GtkBuilder
*xml
= gtk_builder_new();
336 g_message("Opening GUI file: %s", szGUIFilename
);
338 if (!gtk_builder_add_from_file(xml
, szGUIFilename
, &e
)) {
339 g_message("Can't find GUI file: %s. Dasher is unlikely to be correctly "
340 "installed. (%s)", szGUIFilename
, e
->message
);
344 gtk_builder_connect_signals(xml
, pSelf
);
350 #define WRAP_CPP_CB(item) \
352 dasher_main_cb_##item(GtkAction *obj, DasherMain *p)\
354 dasher_main_command_##item(p);\
358 * Editor passes on the action strings to dasher_editor_command which
359 * land in dasher_editor_internal.
363 WRAP_CPP_CB(preferences
)
366 WRAP_CPP_CB(toggle_game_mode
)
369 dasher_main_cb_editor(GtkAction
*obj
, DasherMain
*pSelf
)
371 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
372 DASHER_ASSERT(pPrivate
->pEditor
!= NULL
);
373 const gchar
*action
= gtk_action_get_name(obj
);
374 dasher_editor_command(pPrivate
->pEditor
, action
);
378 dasher_main_load_interface(DasherMain
*pSelf
) {
379 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
380 const char *szGUIFilename
= NULL
;
381 const char *szPrefGUIFilename
= NULL
;
384 #ifdef WITH_MAEMOFULLSCREEN
385 szGUIFilename
= PROGDATA
"/dashermaemofullscreen.ui";
387 szGUIFilename
= PROGDATA
"/dashermaemo.ui";
389 szPrefGUIFilename
= PROGDATA
"/dashermaemo.preferences.ui";
391 szGUIFilename
= PROGDATA
"/dasher.traditional.ui";
392 szPrefGUIFilename
= PROGDATA
"/dasher.preferences.ui";
396 g_error("Failure to determine GUI filename");
399 pPrivate
->pXML
= dasher_main_open_gui_xml(pSelf
, szGUIFilename
);
400 pPrivate
->pPrefXML
= dasher_main_open_gui_xml(pSelf
, szPrefGUIFilename
);
402 #ifndef HAVE_GTK_SHOW_URI
404 GTK_ACTION(gtk_builder_get_object(pPrivate
->pXML
, "action_help"));
405 gtk_action_set_sensitive(helpact
, false);
406 gtk_action_set_visible(helpact
, false);
409 // Save the details of some of the widgets for later
410 // pPrivate->pActionPane = gtk_builder_get_object(pPrivate->pXML, "vbox39");
411 // pPrivate->pBufferView = gtk_builder_get_object(pPrivate->pXML, "the_text_view");
412 pPrivate
->pDivider
= GTK_PANED(gtk_builder_get_object(pPrivate
->pXML
, "main_divider"));
413 // pPrivate->pEditPane = gtk_builder_get_object(pPrivate->pXML, "vbox40");
414 pPrivate
->pMainWindow
= GTK_WINDOW(gtk_builder_get_object(pPrivate
->pXML
, "window"));
415 pPrivate
->pToolbar
= GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "dasher_tool_bar"));
416 // pPrivate->pMenuBar = gtk_builder_get_object(pPrivate->pXML, "dasher_menu_bar");
417 pPrivate
->pDasherWidget
= GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "DasherControl"));
418 pPrivate
->pEditor
= DASHER_EDITOR(gtk_builder_get_object(pPrivate
->pXML
, "DasherEditor"));
419 gtk_dasher_control_set_editor(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), pPrivate
->pEditor
);
422 pPrivate
->pSpeedBox
= GTK_SPIN_BUTTON(gtk_builder_get_object(pPrivate
->pXML
, "spinbutton1"));
423 pPrivate
->pAlphabetCombo
= GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "combobox1"));
424 pPrivate
->pStatusControl
= GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "hbox8"));
426 pPrivate
->pAlphabetList
= gtk_list_store_new(1, G_TYPE_STRING
);
427 gtk_combo_box_set_model(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
),
428 GTK_TREE_MODEL(pPrivate
->pAlphabetList
));
430 GtkCellRenderer
*pRenderer
;
431 pRenderer
= gtk_cell_renderer_text_new();
432 g_object_set(G_OBJECT(pRenderer
), "ellipsize", PANGO_ELLIPSIZE_END
, NULL
);
433 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(pPrivate
->pAlphabetCombo
), pRenderer
, true);
434 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(pPrivate
->pAlphabetCombo
), pRenderer
, "text", 0, NULL
);
437 // gtk_widget_add_events(pPrivate->pDragHandle, GDK_POINTER_MOTION_MASK);
440 #ifdef WITH_MAEMOFULLSCREEN
441 // TODO: This is horrible - no need to get it from the glade file if we're not going to use it
443 pPrivate
->pProgram
= HILDON_PROGRAM(hildon_program_get_instance());
444 // hildon_app_set_title(pPrivate->pApp, "Dasher");
446 pPrivate
->pHWindow
= HILDON_WINDOW(hildon_window_new());
447 hildon_program_add_window(pPrivate
->pProgram
, pPrivate
->pHWindow
);
449 gtk_widget_reparent(pPrivate
->pInnerFrame
, GTK_WIDGET(pPrivate
->pHWindow
));
450 // gtk_paned_set_position(GTK_PANED(window), 100);
454 GtkWidget
*file_menu
;
455 GtkWidget
*file_menu_item
;
456 GtkWidget
*options_menu
;
457 GtkWidget
*options_menu_item
;
458 GtkWidget
*help_menu
;
459 GtkWidget
*help_menu_item
;
462 // main_menu = hildon_appview_get_menu(appview);
464 main_menu
= GTK_MENU(gtk_menu_new());
465 file_menu
= gtk_builder_get_object(pPrivate
->pXML
, "file_menu");
466 options_menu
= gtk_builder_get_object(pPrivate
->pXML
, "options1_menu");
467 help_menu
= gtk_builder_get_object(pPrivate
->pXML
, "help_menu");
468 file_menu_item
= gtk_menu_item_new_with_label ("File");
469 options_menu_item
= gtk_menu_item_new_with_label ("Options");
470 help_menu_item
= gtk_menu_item_new_with_label ("Help");
472 g_object_ref(file_menu
);
473 g_object_ref(options_menu
);
474 g_object_ref(help_menu
);
476 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk_builder_get_object(pPrivate
->pXML
, "file_menu")), NULL
);
477 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk_builder_get_object(pPrivate
->pXML
, "options1")), NULL
);
478 gtk_menu_item_set_submenu(GTK_MENU_ITEM(gtk_builder_get_object(pPrivate
->pXML
, "help_menu")), NULL
);
480 gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu_item
),file_menu
);
481 gtk_menu_item_set_submenu(GTK_MENU_ITEM(options_menu_item
),options_menu
);
482 gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_menu_item
),help_menu
);
483 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, file_menu_item
);
484 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, options_menu_item
);
485 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, help_menu_item
);
487 g_object_unref(file_menu
);
488 g_object_unref(options_menu
);
489 g_object_unref(help_menu
);
491 hildon_program_set_common_menu(pPrivate
->pProgram
, main_menu
);
493 gtk_widget_show_all( GTK_WIDGET( main_menu
) );
496 // GtkWidget *toolbar;
497 // toolbar = gtk_builder_get_object(pPrivate->pXML, "toolbar");
498 // g_print("Got %p\n",toolbar);
499 // gtk_widget_reparent (toolbar, appview->vbox);
501 gtk_widget_show_all(GTK_WIDGET(pPrivate
->pHWindow
));
503 gtk_widget_destroy(GTK_WIDGET(pPrivate
->pMainWindow
));
504 pPrivate
->pMainWindow
= pPrivate
->pHWindow
;
506 g_signal_connect(G_OBJECT(pPrivate
->pHWindow
), "delete_event", G_CALLBACK(ask_save_before_exit
), NULL
);
508 #endif // Maemo fullscreen
511 // pPrivate->bHidden = false;
512 // pPrivate->bGrabbed = false;
514 // pPrivate->iPosition = 100; // FIXME - make this persistant
516 // TODO: Specify callbacks in glade file
517 // TODO: Rationalise focus
518 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "button-release-event", G_CALLBACK(take_real_focus), NULL);
519 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-press-event", G_CALLBACK(edit_key_press), NULL);
520 //g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-release-event", G_CALLBACK(edit_key_release), NULL);
522 // dasher_main_build_context_menu(pSelf);
524 // Create a Maemo helper if necessary
525 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
526 pPrivate
->pMaemoHelper
= dasher_maemo_helper_new(pPrivate
->pMainWindow
);
529 // Set up any non-registry-dependent options
531 gtk_window_set_decorated(pPrivate
->pMainWindow
, false);
534 // Hide any widgets which aren't appropriate for this mode
535 // XXX PRLW: chances are these aren't defined in direct.ui anyway => we are
536 // hiding non-existent widgets.
538 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) == APP_STYLE_DIRECT
) {
539 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "dasher_menu_bar")));
541 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_new")));
542 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_open")));
543 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_save")));
544 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_saveas")));
545 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "separatortoolitem1")));
546 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_cut")));
547 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_copy")));
548 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "tb_command_paste")));
549 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "separatortoolitem2")));
550 gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(pPrivate
->pXML
, "DasherEditor")));
554 pPrivate
->bWidgetsInitialised
= true;
558 dasher_main_create_preferences(DasherMain
*pSelf
) {
559 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
560 pPrivate
->pPreferencesDialogue
= dasher_preferences_dialogue_new(pPrivate
->pPrefXML
, pPrivate
->pEditor
, pPrivate
->pAppSettings
, pPrivate
->pMainWindow
);
564 * Start game mode: prompt user for the text to play with, put this in SP_GAME_TEXT_FILE;
565 * clear out any text in the dasher editor; call CDasherControl::EnterGameMode().
569 * Event handler which displays a standard GTK file dialog. The dialog allows the user
570 * to specify a text file to play game mode with.
572 * @param pButton the button that fired the event
573 * @param pWidget reference needed by GTK for callback signature
574 * @param pData pointer to a an std::pair<GtkWindow*, DasherMain*> containing references
575 * to the dialog's parent window and an instance of DasherMain
577 void show_game_file_dialog(GtkWidget
*pButton
, GtkWidget
*pWidget
, gpointer pData
) {
579 std::pair
<GtkWindow
*, DasherMain
*> *objRefs
= (std::pair
<GtkWindow
*, DasherMain
*>*)pData
;
581 DasherMain
*pSelf
= objRefs
->second
;
582 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
584 GtkWidget
*pFileDialog
= gtk_file_chooser_dialog_new("Choose a Game Text",
585 GTK_WINDOW(objRefs
->first
),
586 GTK_FILE_CHOOSER_ACTION_OPEN
,
587 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
588 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
591 gtk_window_set_destroy_with_parent(GTK_WINDOW(pFileDialog
), true);
593 if (gtk_dialog_run(GTK_DIALOG(pFileDialog
)) == GTK_RESPONSE_ACCEPT
) {
595 char *filename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileDialog
));
597 dasher_app_settings_set_string(pPrivate
->pAppSettings
,
600 gtk_dasher_control_set_game_mode(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), true);
602 gtk_widget_destroy(GTK_WIDGET(objRefs
->first
));
606 * Toggle game mode on and off. Toggling on causes a dialog box to be displayed
607 * welcoming the user to game mode and prompting them to specify a file to play with.
608 * Toggling off just calls LeaveGameMode().
610 * @param pSelf a reference to an instance of DasherMain
612 void dasher_main_command_toggle_game_mode(DasherMain
*pSelf
) {
614 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
616 if(!gtk_dasher_control_get_game_mode(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
))) {
618 GtkWidget
*pDialog
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
619 GTK_MESSAGE_OTHER
, GTK_BUTTONS_NONE
,
620 _("Welcome to Dasher Game Mode! Game Mode is a fun way to practice entering text in Dasher. Please select a training text to play with:"));
622 GtkWidget
*pDefaultButton
= gtk_dialog_add_button(GTK_DIALOG(pDialog
), _("Use Default"), GTK_RESPONSE_ACCEPT
);
623 GtkWidget
*pFileButton
= gtk_dialog_add_button(GTK_DIALOG(pDialog
), _("Choose File..."), 2);
624 gtk_dialog_add_button(GTK_DIALOG(pDialog
), _("Cancel"), GTK_RESPONSE_REJECT
);
626 //make a pair with references to the the DasherMain and parent window instances that
627 //handler will need - kind of disgusting, but looks like only way to pass multiple
628 //parameters in g_signal_connect
629 std::pair
<GtkWindow
*, DasherMain
*> objRefs
= std::make_pair(GTK_WINDOW(pDialog
), pSelf
);
630 //ACL surprisingly this works: the signal handler (show_game_file_dialog) is called
631 // before gtk_dialog_run returns, and the pair is in this, calling, method's stack frame,
632 // so exists until _this_ method finishes...
634 g_signal_connect(pFileButton
, "button-press-event", G_CALLBACK(show_game_file_dialog
),
637 if (gtk_dialog_run(GTK_DIALOG(pDialog
))==GTK_RESPONSE_ACCEPT
) {
638 gtk_dasher_control_set_game_mode(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), true);
641 //have to do this check because we might have destroyed the dialog already in show_game_file_dialog
642 if(GTK_IS_WIDGET(pDialog
))
643 gtk_widget_destroy(pDialog
);
645 GtkWidget
*pDialog
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
646 GTK_MESSAGE_OTHER
, GTK_BUTTONS_NONE
,
647 _("Are you sure you wish to turn off game mode? All unsaved changes will be lost."));
649 GtkWidget
*pNoButton
= gtk_dialog_add_button(GTK_DIALOG(pDialog
), GTK_STOCK_NO
, GTK_RESPONSE_REJECT
);
650 GtkWidget
*pYesButton
= gtk_dialog_add_button(GTK_DIALOG(pDialog
), GTK_STOCK_YES
, GTK_RESPONSE_ACCEPT
);
652 if(gtk_dialog_run(GTK_DIALOG(pDialog
))==GTK_RESPONSE_ACCEPT
) {
653 gtk_dasher_control_set_game_mode(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), false);
655 DASHER_ASSERT(GTK_IS_WIDGET(pDialog
));
656 gtk_widget_destroy(GTK_WIDGET(pDialog
));
662 dasher_main_handle_parameter_change(DasherMain
*pSelf
, int iParameter
) {
663 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
665 switch( iParameter
) {
666 case APP_BP_SHOW_TOOLBAR
:
667 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, APP_BP_SHOW_TOOLBAR
))
668 gtk_widget_show(pPrivate
->pToolbar
);
670 gtk_widget_hide(pPrivate
->pToolbar
);
672 case BP_SHOW_SLIDER
: // TODO: Shouldn't be a core parmeter
673 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, BP_SHOW_SLIDER
))
674 gtk_widget_show(pPrivate
->pStatusControl
);
676 gtk_widget_hide(pPrivate
->pStatusControl
);
680 gtk_spin_button_set_value(pPrivate
->pSpeedBox
, dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) / 100.0);
684 dasher_main_populate_alphabet_combo(pSelf
);
686 case BP_GLOBAL_KEYBOARD
:
687 dasher_main_setup_window(pSelf
);
689 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
690 case APP_LP_MAEMO_SIZE
: {
691 g_message("Maemo size");
693 bool bVisible
= GTK_WIDGET_VISIBLE(pPrivate
->pMainWindow
);
694 gtk_widget_hide(pPrivate
->pMainWindow
);
695 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_MAEMO_SIZE
) == 0) {
697 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWidth
, NULL
);
698 gtk_widget_set_size_request(pPrivate
->pMainWindow
, -1, 150);
699 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWidth
, 150);
700 gtk_widget_set_size_request(pPrivate
->pDasherWidget
, 175, -1);
704 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWidth
, NULL
);
705 gtk_widget_set_size_request(pPrivate
->pMainWindow
, -1, 250);
706 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWidth
, 250);
707 gtk_widget_set_size_request(pPrivate
->pDasherWidget
, 280, -1);
710 gtk_widget_show(pPrivate
->pMainWindow
);
716 if(pPrivate
->pPreferencesDialogue
)
717 dasher_preferences_dialogue_handle_parameter_change(pPrivate
->pPreferencesDialogue
, iParameter
);
719 if(pPrivate
->pEditor
)
720 dasher_editor_handle_parameter_change(pPrivate
->pEditor
, iParameter
);
724 dasher_main_load_state(DasherMain
*pSelf
) {
725 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
731 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_COMPOSE
) {
732 iEditHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_EDIT_HEIGHT
);
733 iWindowWidth
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH
);
734 iWindowHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT
);
737 iEditHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_EDIT_WIDTH
);
738 iWindowWidth
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH_H
);
739 iWindowHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT_H
);
743 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWindowWidth
, iWindowHeight
);
746 gtk_paned_set_position(pPrivate
->pDivider
, iEditHeight
);
748 pPrivate
->iWidth
= iWindowWidth
;
749 pPrivate
->iHeight
= iWindowHeight
;
755 iWindowX
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_X
);
756 iWindowY
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_Y
);
758 gtk_window_move(GTK_WINDOW(pPrivate
->pMainWindow
), iWindowX
, iWindowY
);
762 dasher_main_save_state(DasherMain
*pSelf
) {
763 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
765 if(!pPrivate
->bWidgetsInitialised
)
772 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWindowWidth
, &iWindowHeight
);
773 iEditHeight
= gtk_paned_get_position(pPrivate
->pDivider
);
775 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_COMPOSE
) {
776 // APP_STYLE_DIRECT doesn't have an edit window.
777 if (dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_DIRECT
)
778 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_EDIT_HEIGHT
, iEditHeight
);
779 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH
, iWindowWidth
);
780 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT
, iWindowHeight
);
783 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_EDIT_WIDTH
, iEditHeight
);
784 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH_H
, iWindowWidth
);
785 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT_H
, iWindowHeight
);
790 gtk_window_get_position(GTK_WINDOW(pPrivate
->pMainWindow
), &iWindowX
, &iWindowY
);
792 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_X
, iWindowX
);
793 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_Y
, iWindowY
);
797 dasher_main_show(DasherMain
*pSelf
) {
798 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
799 gtk_widget_show(GTK_WIDGET(pPrivate
->pMainWindow
));
803 dasher_main_setup_window(DasherMain
*pSelf
) {
804 dasher_main_setup_window_style(pSelf
);
805 dasher_main_setup_window_state(pSelf
);
806 dasher_main_setup_internal_layout(pSelf
);
808 // DasherMainPrivate *pPrivate = (DasherMainPrivate *)(pSelf->private_data);
810 // if(dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_GLOBAL_KEYBOARD))
811 // gdk_window_add_filter(0, keyboard_filter_cb, 0);
813 // gdk_window_remove_filter(0, keyboard_filter_cb, 0);
817 dasher_main_populate_controls(DasherMain
*pSelf
) {
818 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
820 // Populate the alphabet chooser
821 dasher_main_populate_alphabet_combo(pSelf
);
823 // Set the value of the speed spinner
824 gtk_spin_button_set_value(pPrivate
->pSpeedBox
,
825 dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) / 100.0);
828 /* Private methods */
830 /* Window state is basically size and position */
832 dasher_main_setup_window_state(DasherMain
*pSelf
) {
833 dasher_main_load_state(pSelf
);
835 // TODO: Setup positioning here - need to think up a policy on this
839 /* Setup the window style - this is defined to be window manager hints and the like */
841 dasher_main_setup_window_style(DasherMain
*pSelf
) {
842 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
844 switch(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
)) {
848 case APP_STYLE_COMPOSE
:
851 case APP_STYLE_DIRECT
:
852 // Direct mode - set always on top
853 gtk_window_set_keep_above(GTK_WINDOW(pPrivate
->pMainWindow
), true);
856 gtk_window_set_accept_focus(GTK_WINDOW(pPrivate
->pMainWindow
), false);
858 // Stick on all desktops
859 gtk_window_stick(GTK_WINDOW(pPrivate
->pMainWindow
));
861 case APP_STYLE_FULLSCREEN
:
862 // Fullscreen mode - set fullscreen
863 gtk_window_fullscreen(GTK_WINDOW(pPrivate
->pMainWindow
));
866 g_error("Inconsistent application style specified.");
870 /* Internal layout is the visibility of various widgets */
872 dasher_main_setup_internal_layout(DasherMain
*pSelf
) {
873 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
875 if(pPrivate
->pToolbar
) {
876 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, APP_BP_SHOW_TOOLBAR
))
877 gtk_widget_show(pPrivate
->pToolbar
);
879 gtk_widget_hide(pPrivate
->pToolbar
);
882 if(pPrivate
->pStatusControl
) {
883 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, BP_SHOW_SLIDER
))
884 gtk_widget_show(pPrivate
->pStatusControl
);
886 gtk_widget_hide(pPrivate
->pStatusControl
);
890 // TODO: Fold into setup controls?
892 dasher_main_set_window_title(DasherMain
*pSelf
) {
893 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
895 const gchar
*szFilename
= dasher_editor_get_filename(pPrivate
->pEditor
);
897 // Note to translators: This is the name of the dasher program as it appears
898 // in a window title.
899 gchar
* dasher
= _("Dasher");
900 if(szFilename
== 0) {
901 gtk_window_set_title(GTK_WINDOW(pPrivate
->pMainWindow
), dasher
);
904 gchar
*title
= g_strdup_printf("%s - %s", dasher
, szFilename
);
905 gtk_window_set_title(GTK_WINDOW(pPrivate
->pMainWindow
), title
);
911 dasher_main_command_import(DasherMain
*pSelf
) {
912 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
914 GtkWidget
*pFileSel
= gtk_file_chooser_dialog_new(_("Select File"),
915 GTK_WINDOW(pPrivate
->pMainWindow
),
916 GTK_FILE_CHOOSER_ACTION_OPEN
,
917 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
918 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
921 #ifdef TEACH_TRAINING_HELPER_LOAD_FILE_ABOUT_URI
922 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(pFileSel
), FALSE
);
925 if(gtk_dialog_run(GTK_DIALOG(pFileSel
)) == GTK_RESPONSE_ACCEPT
) {
927 #ifdef TEACH_TRAINING_HELPER_LOAD_FILE_ABOUT_URI
928 gchar
*szFilename
= gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(pFileSel
));
930 gchar
*szFilename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSel
));
933 gtk_dasher_control_train(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), szFilename
);
938 gtk_widget_destroy(pFileSel
);
941 static void dasher_main_command_quit(DasherMain
*pSelf
) {
942 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
944 GtkWidget
*pDialogue
= NULL
;
946 if(dasher_editor_file_changed(pPrivate
->pEditor
)) {
947 // XXX PRLW: Just open the save dialogue box.
949 const gchar
*szFilename
= dasher_editor_get_filename(pPrivate
->pEditor
);
952 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
953 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
954 _("Do you want to save your changes to %s?\n\nYour changes will be lost if you don't save them."),
959 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
960 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
961 _("Do you want to save your changes?\n\nYour changes will be lost if you don't save them."));
966 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue
),
967 _("Don't save"), GTK_RESPONSE_REJECT
,
968 _("Don't quit"), GTK_RESPONSE_CANCEL
,
969 _("Save and quit"), GTK_RESPONSE_ACCEPT
,
972 switch (gtk_dialog_run(GTK_DIALOG(pDialogue
))) {
973 case GTK_RESPONSE_REJECT
:
976 case GTK_RESPONSE_CANCEL
:
977 gtk_widget_destroy(GTK_WIDGET(pDialogue
));
979 case GTK_RESPONSE_ACCEPT
:
980 dasher_editor_command(pPrivate
->pEditor
, "action_save");
986 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
987 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
988 _("Are you sure you wish to quit?"));
990 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue
),
991 _("Don't quit"), GTK_RESPONSE_REJECT
,
992 _("Quit"), GTK_RESPONSE_ACCEPT
,
995 switch (gtk_dialog_run(GTK_DIALOG(pDialogue
))) {
996 case GTK_RESPONSE_REJECT
:
997 gtk_widget_destroy(GTK_WIDGET(pDialogue
));
999 case GTK_RESPONSE_ACCEPT
:
1006 dasher_main_command_preferences(DasherMain
*pSelf
) {
1007 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1008 dasher_preferences_dialogue_show(pPrivate
->pPreferencesDialogue
, 0);
1012 dasher_main_command_preferences_alphabet(DasherMain
*pSelf
) {
1013 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1014 dasher_preferences_dialogue_show(pPrivate
->pPreferencesDialogue
, 1);
1018 dasher_main_command_help(DasherMain
*pSelf
) {
1019 #ifdef HAVE_GTK_SHOW_URI
1020 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1024 scr
= gtk_widget_get_screen(GTK_WIDGET(pPrivate
->pMainWindow
));
1025 if (!gtk_show_uri(scr
, "ghelp:dasher", gtk_get_current_event_time(), &err
)) {
1027 d
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
),
1029 GTK_MESSAGE_ERROR
, GTK_BUTTONS_CLOSE
,
1030 "%s", _("Unable to open help file"));
1031 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(d
),
1032 "%s", err
->message
);
1033 g_signal_connect(d
, "response", G_CALLBACK(gtk_widget_destroy
), NULL
);
1034 gtk_window_present(GTK_WINDOW(d
));
1042 dasher_main_command_about(DasherMain
*pSelf
) {
1043 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1045 // In alphabetical order - please keep this in sync with the AUTHORS
1046 // file at root of the package tree
1047 const gchar
*authors
[] = {
1072 // Yeah, should really do some Gnome documentation for it...
1073 const gchar
*documenters
[] = {
1080 gtk_show_about_dialog(GTK_WINDOW(pPrivate
->pMainWindow
),
1082 "comments", _("Dasher is a predictive text entry application"),
1083 "copyright", "Copyright \xC2\xA9 1998-2011 The Dasher Project",
1084 "documenters", documenters
,
1085 "license", "GPL 2+",
1086 "logo-icon-name", "dasher",
1087 "translator-credits", _("translator-credits"),
1088 "version", PACKAGE_VERSION
,
1089 "website", PACKAGE_URL
,
1090 "wrap-license", true,
1095 dasher_main_speed_changed(DasherMain
*pSelf
) {
1096 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1098 int iNewValue( static_cast<int>(round(gtk_spin_button_get_value(pPrivate
->pSpeedBox
) * 100)));
1100 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) != iNewValue
)
1101 dasher_app_settings_set_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
, iNewValue
);
1107 dasher_main_alphabet_combo_changed(DasherMain
*pSelf
) {
1108 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1112 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), &sIter
)) {
1114 gtk_tree_model_get(GTK_TREE_MODEL(pPrivate
->pAlphabetList
), &sIter
, 0, &szSelected
, -1);
1116 if(!strcmp("More Alphabets...", szSelected
)) {
1117 gtk_combo_box_set_active(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), 0);
1118 // dasher_preferences_dialogue_show(pPrivate->pPreferencesDialogue);
1119 dasher_main_command_preferences_alphabet(pSelf
);
1122 dasher_app_settings_set_string(pPrivate
->pAppSettings
, SP_ALPHABET_ID
, szSelected
);
1129 dasher_main_populate_alphabet_combo(DasherMain
*pSelf
) {
1131 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1133 // Disconnect the event handler temporarily, otherwise this will
1134 // trigger alphabet changes
1136 g_signal_handlers_block_by_func(pPrivate
->pAlphabetCombo
, (gpointer
)alphabet_combo_changed
, pSelf
);
1138 gtk_list_store_clear(pPrivate
->pAlphabetList
);
1142 const char *szValue
;
1144 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_ID
);
1146 if(strlen(szValue
) > 0) {
1147 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1148 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1149 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), &sIter
);
1152 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_1
);
1153 if(strlen(szValue
) > 0) {
1154 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1155 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1158 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_2
);
1159 if(strlen(szValue
) > 0) {
1160 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1161 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1164 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_3
);
1165 if(strlen(szValue
) > 0) {
1166 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1167 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1170 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_4
);
1171 if(strlen(szValue
) > 0) {
1172 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1173 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1176 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1177 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, "More Alphabets...", -1);
1179 g_signal_handlers_unblock_by_func(pPrivate
->pAlphabetCombo
, (gpointer
)alphabet_combo_changed
, pSelf
);
1185 dasher_main_lookup_key(DasherMain
*pSelf
, guint iKeyVal
) {
1186 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1188 if(pPrivate
->pKeyboardHelper
)
1189 return pPrivate
->pKeyboardHelper
->ConvertKeycode(iKeyVal
);
1198 // TODO: reimplement (text view member of class)
1199 // gtk_widget_grab_focus(the_text_view);
1200 // g_bForwardKeyboard = true;
1207 speed_changed(GtkWidget
*pWidget
, gpointer pUserData
) {
1208 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1209 dasher_main_speed_changed(pDasherMain
);
1213 alphabet_combo_changed(GtkWidget
*pWidget
, gpointer pUserData
) {
1214 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1215 dasher_main_alphabet_combo_changed(pDasherMain
);
1219 dasher_main_cb_filename_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1220 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1221 dasher_main_set_window_title(pDasherMain
);
1225 dasher_main_cb_buffer_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1226 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pUserData
);
1228 gtk_dasher_control_set_buffer(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), dasher_editor_get_offset(pPrivate
->pEditor
));
1232 dasher_main_cb_context_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1233 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1234 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
1236 gtk_dasher_control_set_offset(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), dasher_editor_get_offset(pPrivate
->pEditor
));
1240 dasher_main_cb_window_close(GtkWidget
*pWidget
, gpointer pUserData
) {
1241 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1242 dasher_main_command_quit(pDasherMain
);
1244 /* Returning true stops further propagation */
1249 parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer pUserData
) {
1250 DasherMain
*pDasherMain
= DASHER_MAIN(pUserData
);
1251 dasher_main_handle_parameter_change(pDasherMain
, iParameter
);
1254 // TODO: Not really sure what happens here - need to sort out focus behaviour in general
1256 focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
) {
1257 return grab_focus();
1261 edit_focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
) {
1266 take_real_focus(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
) {
1267 // g_bForwardKeyboard = false;
1272 edit_key_press(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
) {
1273 // TODO: Reimplement
1275 // if(g_bForwardKeyboard) {
1276 // gboolean *returnType;
1277 // g_signal_emit_by_name(GTK_WIDGET(pPrivate->pDasherWidget), "key_press_event", event, &returnType);
1284 // TODO: Check callback return functions
1289 edit_key_release(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
) {
1290 // TODO: reimplement
1292 // if(g_bForwardKeyboard) {
1293 // gboolean *returnType;
1294 // g_signal_emit_by_name(GTK_WIDGET(pPrivate->pDasherWidget), "key_release_event", event, &returnType);
1301 // TODO: Check callback return functions
1306 test_focus_handler(GtkWidget
*pWidget
, GtkDirectionType iDirection
, gpointer
*pUserData
) {
1311 handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1312 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(data
);
1314 dasher_editor_grab_focus(pPrivate
->pEditor
);
1318 // TODO: Make this only work for children of the main window
1320 dasher_main_key_snooper(GtkWidget
*pWidget
, GdkEventKey
*pEvent
,
1321 gpointer pUserData
) {
1322 DasherMain
*pSelf
= DASHER_MAIN(pUserData
);
1324 gint iButton
= dasher_main_lookup_key(pSelf
, pEvent
->keyval
);
1327 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1329 if (pWidget
== GTK_WIDGET(pPrivate
->pMainWindow
) ||
1330 gtk_widget_is_ancestor(pWidget
, GTK_WIDGET(pPrivate
->pMainWindow
))) {
1331 if(pPrivate
->pDasherWidget
) {
1332 if(pEvent
->type
== GDK_KEY_PRESS
)
1333 gtk_dasher_control_external_key_down(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), iButton
);
1335 gtk_dasher_control_external_key_up(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), iButton
);
1349 // Callbacks from the Dasher widget
1352 handle_stop_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1353 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(data
);
1355 if(pPrivate
->pEditor
)
1356 dasher_editor_handle_stop(pPrivate
->pEditor
);
1359 // TODO: The following two should probably be made the same
1361 handle_request_settings(GtkDasherControl
* pDasherControl
, gpointer data
) {
1362 // TODO: reimplement
1363 // dasher_preferences_dialogue_show(g_pPreferencesDialogue);
1367 gtk2_edit_delete_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, int iOffset
, gpointer user_data
) {
1368 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(user_data
);
1370 if(pPrivate
->pEditor
) {
1371 gint displaylength
= g_utf8_strlen(szText
, -1);
1372 dasher_editor_delete(pPrivate
->pEditor
, displaylength
, iOffset
);
1377 gtk2_edit_output_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, int iOffset
, gpointer user_data
) {
1378 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(user_data
);
1380 if(pPrivate
->pEditor
) {
1381 dasher_editor_output(pPrivate
->pEditor
, szText
, iOffset
);
1386 convert_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1387 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pUserData
);
1389 if(pPrivate
->pEditor
) {
1390 dasher_editor_edit_convert(pPrivate
->pEditor
);
1395 protect_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1396 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pUserData
);
1398 if(pPrivate
->pEditor
) {
1399 dasher_editor_edit_protect(pPrivate
->pEditor
);