9 #include <glade/glade.h>
10 #include <glib/gi18n.h>
12 #ifdef WITH_MAEMOFULLSCREEN
13 #include <hildon-widgets/hildon-program.h>
16 #include <libgnome/libgnome.h>
20 #include "GtkDasherControl.h"
21 #include "KeyboardHelper.h"
22 #include "Preferences.h"
23 #include "dasher_lock_dialogue.h"
25 #include "dasher_maemo_helper.h"
27 #include "dasher_main.h"
29 #include "DasherAppSettings.h"
30 #include "dasher_editor_internal.h"
31 #include "dasher_editor_external.h"
33 /* Static instance of singleton, USE SPARINGLY */
34 static DasherMain
*g_pDasherMain
= NULL
;
36 // TODO: The following global variable makes control mode editing work
37 // - this needs to be sorted out properly.
38 static gboolean g_bSend
= true;
40 struct _DasherMainPrivate
{
44 // Child objects owned here
45 DasherAppSettings
*pAppSettings
;
46 DasherPreferencesDialogue
*pPreferencesDialogue
;
47 DasherEditor
*pEditor
;
49 CKeyboardHelper
*pKeyboardHelper
;
51 // Various widgets which need to be cached:
52 GtkWidget
*pBufferView
;
54 GtkWidget
*pMainWindow
;
57 GtkWidget
*pAlphabetCombo
;
58 GtkWidget
*pStatusControl
;
59 GtkWidget
*pDasherWidget
;
61 GtkListStore
*pAlphabetList
;
62 GtkAccelGroup
*pAccel
;
63 gulong iAlphabetComboHandler
;
65 // Widgets used for maemo
67 DasherMaemoHelper
*pMaemoHelper
;
68 #ifdef WITH_MAEMOFULLSCREEN
69 HildonProgram
*pProgram
;
70 HildonWindow
*pHWindow
;
74 // Properties of the main window
77 bool bWidgetsInitialised
;
80 typedef struct _DasherMainPrivate DasherMainPrivate
;
82 // TODO: Make sure this is actually used
83 #define DASHER_MAIN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), TYPE_DASHER_MAIN, DasherMainPrivate))
90 static guint dasher_main_signals
[SIGNAL_NUM
] = { 0 };
92 /* Automatic command hookups */
94 typedef struct _DasherMenuCommand DasherMenuCommand
;
96 struct _DasherMenuCommand
{
98 const gchar
*szWidgetName
;
99 const gchar
*szCommand
;
102 static DasherMenuCommand MenuCommands
[] = {
104 {NULL
, "menu_command_new", "new"},
105 {NULL
, "menu_command_open", "open"},
106 {NULL
, "menu_command_save", "save"},
107 {NULL
, "menu_command_saveas", "saveas"},
108 {NULL
, "menu_command_append", "append"},
109 {NULL
, "menu_command_import", "import"},
110 {NULL
, "menu_command_quit", "quit"},
111 {NULL
, "menu_command_cut", "cut"},
112 {NULL
, "menu_command_copy", "copy"},
113 {NULL
, "menu_command_copyall", "copyall"},
114 {NULL
, "menu_command_paste", "paste"},
115 {NULL
, "menu_command_preferences", "preferences"},
116 {NULL
, "menu_command_tutorial", "tutorial"},
117 {NULL
, "menu_command_help", "help"},
118 {NULL
, "menu_command_about", "about"},
121 {NULL
, "tb_command_new", "new"},
122 {NULL
, "tb_command_open", "open"},
123 {NULL
, "tb_command_save", "save"},
124 {NULL
, "tb_command_saveas", "saveas"},
125 {NULL
, "tb_command_cut", "cut"},
126 {NULL
, "tb_command_copy", "copy"},
127 {NULL
, "tb_command_paste", "paste"},
128 {NULL
, "tb_command_preferences", "preferences"},
129 {NULL
, "tb_command_help", "help"},
130 {NULL
, "tb_command_quit", "quit"}
133 G_DEFINE_TYPE(DasherMain
, dasher_main
, G_TYPE_OBJECT
);
135 static void dasher_main_finalize(GObject
*pObject
);
137 /* Private member functions */
138 static void dasher_main_setup_window_state(DasherMain
*pSelf
);
139 static void dasher_main_setup_window_style(DasherMain
*pSelf
);
140 static void dasher_main_setup_internal_layout(DasherMain
*pSelf
);
141 //static void dasher_main_refresh_font(DasherMain *pSelf);
142 static void dasher_main_set_window_title(DasherMain
*pSelf
);
144 /* ... Table based menu/toolbar commands */
145 static void dasher_main_connect_menus(DasherMain
*pSelf
);
146 static void dasher_main_menu_command(DasherMain
*pSelf
, GtkWidget
*pWidget
);
148 static void dasher_main_command_import(DasherMain
*pSelf
);
149 static void dasher_main_command_quit(DasherMain
*pSelf
);
150 static void dasher_main_command_preferences(DasherMain
*pSelf
);
151 static void dasher_main_command_preferences_alphabet(DasherMain
*pSelf
);
152 static void dasher_main_command_tutorial(DasherMain
*pSelf
);
153 static void dasher_main_command_help(DasherMain
*pSelf
);
154 static void dasher_main_command_about(DasherMain
*pself
);
156 static gboolean
dasher_main_speed_changed(DasherMain
*pSelf
);
157 static void dasher_main_alphabet_combo_changed(DasherMain
*pSelf
);
158 // TODO: populate speed slider
159 static void dasher_main_populate_alphabet_combo(DasherMain
*pSelf
);
161 /* TODO: order these in file */
162 static GladeXML
*dasher_main_open_glade_xml(const char *szGladeFilename
);
163 static void dasher_main_load_interface(DasherMain
*pSelf
);
164 static void dasher_main_create_preferences(DasherMain
*pSelf
);
165 static void dasher_main_handle_parameter_change(DasherMain
*pSelf
, int iParameter
);
166 static void dasher_main_load_state(DasherMain
*pSelf
);
167 static void dasher_main_save_state(DasherMain
*pSelf
);
168 static void dasher_main_setup_window(DasherMain
*pSelf
);
169 static void dasher_main_populate_controls(DasherMain
*pSelf
);
170 static void dasher_main_connect_control(DasherMain
*pSelf
);
171 static gboolean
dasher_main_command(DasherMain
*pSelf
, const gchar
*szCommand
);
172 static gint
dasher_main_lookup_key(DasherMain
*pSelf
, guint iKeyVal
);
174 /* TODO: Various functions which haven't yet been rationalised */
175 gboolean
grab_focus();
177 // TODO: Sort out callbacks - 1 rename, 2 check return values
179 /* Callback functions */
180 extern "C" GtkWidget
*create_dasher_control(gchar
*szName
, gchar
*szString1
, gchar
*szString2
, gint iInt1
, gint iInt2
);
181 extern "C" GtkWidget
*create_dasher_editor(gchar
*szName
, gchar
*szString1
, gchar
*szString2
, gint iInt1
, gint iInt2
);
183 /* ... Message handling from main window widgets */
184 extern "C" gboolean
dasher_main_cb_menu_command(GtkWidget
*pWidget
, gpointer pUserData
);
185 extern "C" gboolean
speed_changed(GtkWidget
*pWidget
, gpointer user_data
);
186 extern "C" void alphabet_combo_changed(GtkWidget
*pWidget
, gpointer pUserData
);
187 extern "C" void dasher_main_cb_filename_changed(DasherEditor
*pEditor
, gpointer pUserData
);
188 extern "C" void dasher_main_cb_buffer_changed(DasherEditor
*pEditor
, gpointer pUserData
);
189 extern "C" void dasher_main_cb_context_changed(DasherEditor
*pEditor
, gpointer pUserData
);
190 extern "C" gboolean
dasher_main_cb_window_close(GtkWidget
*pWidget
, gpointer pUserData
);
191 extern "C" void parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer data
);
193 /* ... Focus management and event forwarding */
194 extern "C" bool focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
);
195 extern "C" bool edit_focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
);
196 extern "C" gboolean
take_real_focus(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
);
198 extern "C" gboolean
edit_key_press(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
199 extern "C" gboolean
edit_key_release(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
201 /* ... Temporary test/debug functions */
202 extern "C" gboolean
test_focus_handler(GtkWidget
*pWidget
, GtkDirectionType iDirection
, gpointer
*pUserData
);
204 extern "C" void handle_context_request(GtkDasherControl
* pDasherControl
, gint iOffset
, gint iLength
, gpointer data
);
205 extern "C" void handle_control_event(GtkDasherControl
*pDasherControl
, gint iEvent
, gpointer data
);
206 extern "C" void handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
);
207 extern "C" gint
dasher_main_key_snooper(GtkWidget
*pWidget
, GdkEventKey
*pEvent
, gpointer pUserData
);
209 /* Boilerplate code */
211 dasher_main_class_init(DasherMainClass
*pClass
) {
212 g_type_class_add_private(pClass
, sizeof(DasherMainPrivate
));
214 dasher_main_signals
[REALIZED
] = g_signal_new("realized", G_TYPE_FROM_CLASS(pClass
),
215 (GSignalFlags
)(G_SIGNAL_RUN_FIRST
| G_SIGNAL_ACTION
),
216 G_STRUCT_OFFSET(DasherMainClass
, realized
),
217 NULL
, NULL
, g_cclosure_marshal_VOID__VOID
,
220 GObjectClass
*pObjectClass
= (GObjectClass
*)pClass
;
221 pObjectClass
->finalize
= dasher_main_finalize
;
225 dasher_main_init(DasherMain
*pDasherMain
) {
226 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
228 pPrivate
->pAppSettings
= NULL
;
229 pPrivate
->pEditor
= NULL
;
230 pPrivate
->pPreferencesDialogue
= NULL
;
232 pPrivate
->pKeyboardHelper
= new CKeyboardHelper(NULL
);
234 pPrivate
->bWidgetsInitialised
= false;
238 dasher_main_finalize(GObject
*pObject
) {
240 DasherMain
*pDasherMain
= DASHER_MAIN(pObject
);
241 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
243 dasher_main_save_state(pDasherMain
);
245 /* TODO: Does unref really do the right thing - check the whole ref counting situation */
246 // if(pPrivate->pEditor)
247 // g_object_unref(pPrivate->pEditor);
249 if(pPrivate
->pPreferencesDialogue
)
250 g_object_unref(pPrivate
->pPreferencesDialogue
);
252 if(pPrivate
->pAppSettings
)
253 g_object_unref(pPrivate
->pAppSettings
);
255 gtk_widget_destroy(pPrivate
->pMainWindow
);
257 /* TODO: Do we need to take down anything else? */
262 dasher_main_new(int *argc
, char ***argv
, SCommandLine
*pCommandLine
) {
264 return g_pDasherMain
;
266 DasherMain
*pDasherMain
= (DasherMain
*)(g_object_new(dasher_main_get_type(), NULL
));
267 g_pDasherMain
= pDasherMain
;
269 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
271 /* Create the app settings object */
272 pPrivate
->pAppSettings
= dasher_app_settings_new(*argc
, *argv
);
274 /* Load the user interface from the glade file */
275 if(pCommandLine
&& pCommandLine
->szAppStyle
) {
276 if(!strcmp(pCommandLine
->szAppStyle
, "traditional")) {
277 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_TRAD
);
279 else if(!strcmp(pCommandLine
->szAppStyle
, "compose")) {
280 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_COMPOSE
);
282 else if(!strcmp(pCommandLine
->szAppStyle
, "direct")) {
283 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_DIRECT
);
285 else if(!strcmp(pCommandLine
->szAppStyle
, "fullscreen")) {
286 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_FULLSCREEN
);
289 g_critical("Application style %s is not supported", pCommandLine
->szAppStyle
);
294 // By default use traditional mode
295 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_STYLE
, APP_STYLE_TRAD
);
298 dasher_main_load_interface(pDasherMain
);
300 dasher_app_settings_set_widget(pPrivate
->pAppSettings
, GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
));
303 /* TODO: This parsing code should really be tidied up */
304 if(pCommandLine
&& pCommandLine
->szOptions
) {
305 gchar
**pszOptionTerms
;
306 pszOptionTerms
= g_strsplit(pCommandLine
->szOptions
, ",", 0);
308 gchar
**pszCurrent
= pszOptionTerms
;
311 gchar
*szJoin
= g_strrstr(*pszCurrent
, "=");
312 // Note to translators: This message will be output for command line errors when the "=" in --options=foo is missing.
313 const gchar
*errorMessage
= _("option setting is missing \"=\".");
316 int iLength
= szJoin
- *pszCurrent
;
318 gchar
*szKey
= g_new(gchar
, iLength
+ 1);
319 memcpy(szKey
, *pszCurrent
, iLength
);
320 szKey
[iLength
] = '\0';
322 errorMessage
= dasher_app_settings_cl_set(pPrivate
->pAppSettings
, szKey
, szJoin
+ 1);
328 // Note to translators: This string will be output when --options= specifies an unknown option.
329 g_critical("%s: '%s', %s", _("Invalid option string specified"), *pszCurrent
, errorMessage
);
336 g_strfreev(pszOptionTerms
);
342 dasher_editor_initialise(pPrivate
->pEditor
, pPrivate
->pAppSettings
, pDasherMain
, pPrivate
->pGladeXML
, NULL
);
345 dasher_main_setup_window(pDasherMain
);
347 /* Create the editor */
348 gchar
*szFullPath
= NULL
;
351 if(pCommandLine
->szFilename
) {
352 if(!g_path_is_absolute(pCommandLine
->szFilename
)) {
354 cwd
= (char *)malloc(1024 * sizeof(char));
356 szFullPath
= g_build_path("/", cwd
, pCommandLine
->szFilename
, NULL
);
359 szFullPath
= g_strdup(pCommandLine
->szFilename
);
365 // pPrivate->pEditor = GTK_EDITOR(
368 // dasher_editor_initialise(pPrivate->pAppSettings, pDasherMain, pPrivate->pGladeXML, szFullPath);
372 // TODO: Were these really needed?
373 // g_signal_connect(pPrivate->pEditor, "filename_changed", G_CALLBACK(dasher_main_cb_filename_changed), pDasherMain);
374 // g_signal_connect(pPrivate->pEditor, "buffer_changed", G_CALLBACK(dasher_main_cb_buffer_changed), pDasherMain);
375 // g_signal_connect(pPrivate->pEditor, "context_changed", G_CALLBACK(dasher_main_cb_context_changed), pDasherMain);
377 /* Create the preferences window */
378 dasher_main_create_preferences(pDasherMain
);
380 /* Create the lock dialogue (to be removed in future versions) */
382 dasher_lock_dialogue_new(pPrivate
->pGladeXML
, GTK_WINDOW(pPrivate
->pMainWindow
));
384 dasher_lock_dialogue_new(pPrivate
->pGladeXML
, 0);
387 g_object_unref(pPrivate
->pGladeXML
);
388 pPrivate
->pGladeXML
= 0;
390 g_object_unref(pPrivate
->pPrefXML
);
391 pPrivate
->pPrefXML
= 0;
393 /* Set up various bits and pieces */
394 dasher_main_set_window_title(pDasherMain
);
395 dasher_main_populate_controls(pDasherMain
);
396 dasher_main_connect_control(pDasherMain
);
398 gtk_key_snooper_install(dasher_main_key_snooper
, pDasherMain
);
405 dasher_main_open_glade_xml(const char *szGladeFilename
) {
406 g_message("Opening Glade file: %s", szGladeFilename
);
408 GladeXML
*xml
= glade_xml_new(szGladeFilename
, NULL
, NULL
);
411 g_error("Can't find Glade file: %s. Dasher is unlikely to be correctly installed.", szGladeFilename
);
414 glade_xml_signal_autoconnect(xml
);
419 /* Load the window interface from the glade file, and do various initialisation bits and pieces */
421 dasher_main_load_interface(DasherMain
*pSelf
) {
422 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
424 const char *szGladeFilename
= NULL
;
425 const char *szPrefGladeFilename
= NULL
;
428 szGladeFilename
= PROGDATA
"/dashergpe.glade";
430 #ifdef WITH_MAEMOFULLSCREEN
431 // szGladeFilename = "/var/lib/install" PROGDATA "/dashermaemofullscreen.glade";
432 szGladeFilename
= PROGDATA
"/dashermaemofullscreen.glade";
434 //szGladeFilename = "/var/lib/install" PROGDATA "/dashermaemo.glade";
435 szGladeFilename
= PROGDATA
"/dashermaemo.glade";
437 szPrefGladeFilename
= PROGDATA
"/dashermaemo.preferences.glade";
439 switch(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
)) {
441 szGladeFilename
= PROGDATA
"/dasher.traditional.glade";
443 case APP_STYLE_COMPOSE
:
444 szGladeFilename
= PROGDATA
"/dasher.compose.glade";
446 case APP_STYLE_DIRECT
:
447 szGladeFilename
= PROGDATA
"/dasher.direct.glade";
449 case APP_STYLE_FULLSCREEN
:
450 szGladeFilename
= PROGDATA
"/dasher.fullscreen.glade";
453 g_error("Inconsistent application style specified.");
455 szPrefGladeFilename
= PROGDATA
"/dasher.preferences.glade";
458 if(!szGladeFilename
) {
459 g_error("Failure to determine glade filename");
462 pPrivate
->pGladeXML
= dasher_main_open_glade_xml(szGladeFilename
);
464 if (szPrefGladeFilename
) {
465 pPrivate
->pPrefXML
= dasher_main_open_glade_xml(szPrefGladeFilename
);
468 // If no separate preference file, preferences widget is in main glade xml
469 pPrivate
->pPrefXML
= (GladeXML
*) g_object_ref(pPrivate
->pGladeXML
);
472 // XXX PRLW: Hide the Help Contents as there is no handler to display help.
474 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "menu_command_help"));
476 // Save the details of some of the widgets for later
477 // pPrivate->pActionPane = glade_xml_get_widget(pPrivate->pGladeXML, "vbox39");
478 pPrivate
->pBufferView
= glade_xml_get_widget(pPrivate
->pGladeXML
, "the_text_view");
479 pPrivate
->pDivider
= glade_xml_get_widget(pPrivate
->pGladeXML
, "main_divider");
480 // pPrivate->pEditPane = glade_xml_get_widget(pPrivate->pGladeXML, "vbox40");
481 pPrivate
->pMainWindow
= glade_xml_get_widget(pPrivate
->pGladeXML
, "window");
482 pPrivate
->pToolbar
= glade_xml_get_widget(pPrivate
->pGladeXML
, "toolbar");
483 // pPrivate->pMenuBar = glade_xml_get_widget(pPrivate->pGladeXML, "dasher_menu_bar");
484 pPrivate
->pDasherWidget
= glade_xml_get_widget(pPrivate
->pGladeXML
, "DasherControl");
487 pPrivate
->pSpeedBox
= glade_xml_get_widget(pPrivate
->pGladeXML
, "spinbutton1");
488 pPrivate
->pAlphabetCombo
= glade_xml_get_widget(pPrivate
->pGladeXML
, "combobox1");
489 pPrivate
->pStatusControl
= glade_xml_get_widget(pPrivate
->pGladeXML
, "hbox8");
491 pPrivate
->pAlphabetList
= gtk_list_store_new(1, G_TYPE_STRING
);
492 gtk_combo_box_set_model(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
),
493 GTK_TREE_MODEL(pPrivate
->pAlphabetList
));
495 GtkCellRenderer
*pRenderer
;
496 pRenderer
= gtk_cell_renderer_text_new();
497 #if GTK_CHECK_VERSION(2,6,0)
498 g_object_set(G_OBJECT(pRenderer
), "ellipsize", PANGO_ELLIPSIZE_END
, NULL
);
500 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(pPrivate
->pAlphabetCombo
), pRenderer
, true);
501 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(pPrivate
->pAlphabetCombo
), pRenderer
, "text", 0, NULL
);
504 // gtk_widget_add_events(pPrivate->pDragHandle, GDK_POINTER_MOTION_MASK);
507 #ifdef WITH_MAEMOFULLSCREEN
508 // TODO: This is horrible - no need to get it from the glade file if we're not going to use it
510 pPrivate
->pProgram
= HILDON_PROGRAM(hildon_program_get_instance());
511 // hildon_app_set_title(pPrivate->pApp, "Dasher");
513 pPrivate
->pHWindow
= HILDON_WINDOW(hildon_window_new());
514 hildon_program_add_window(pPrivate
->pProgram
, pPrivate
->pHWindow
);
516 gtk_widget_reparent(pPrivate
->pInnerFrame
, GTK_WIDGET(pPrivate
->pHWindow
));
517 // gtk_paned_set_position(GTK_PANED(window), 100);
521 GtkWidget
*file_menu
;
522 GtkWidget
*file_menu_item
;
523 GtkWidget
*options_menu
;
524 GtkWidget
*options_menu_item
;
525 GtkWidget
*help_menu
;
526 GtkWidget
*help_menu_item
;
529 // main_menu = hildon_appview_get_menu(appview);
531 main_menu
= GTK_MENU(gtk_menu_new());
532 file_menu
= glade_xml_get_widget(pPrivate
->pGladeXML
, "menuitem4_menu");
533 options_menu
= glade_xml_get_widget(pPrivate
->pGladeXML
, "options1_menu");
534 help_menu
= glade_xml_get_widget(pPrivate
->pGladeXML
, "menuitem7_menu");
535 file_menu_item
= gtk_menu_item_new_with_label ("File");
536 options_menu_item
= gtk_menu_item_new_with_label ("Options");
537 help_menu_item
= gtk_menu_item_new_with_label ("Help");
539 g_object_ref(file_menu
);
540 g_object_ref(options_menu
);
541 g_object_ref(help_menu
);
543 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate
->pGladeXML
, "menuitem4")), NULL
);
544 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate
->pGladeXML
, "options1")), NULL
);
545 gtk_menu_item_set_submenu(GTK_MENU_ITEM(glade_xml_get_widget(pPrivate
->pGladeXML
, "menuitem7")), NULL
);
547 gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menu_item
),file_menu
);
548 gtk_menu_item_set_submenu(GTK_MENU_ITEM(options_menu_item
),options_menu
);
549 gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_menu_item
),help_menu
);
550 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, file_menu_item
);
551 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, options_menu_item
);
552 gtk_menu_shell_append((GtkMenuShell
*)main_menu
, help_menu_item
);
554 g_object_unref(file_menu
);
555 g_object_unref(options_menu
);
556 g_object_unref(help_menu
);
558 hildon_program_set_common_menu(pPrivate
->pProgram
, main_menu
);
560 gtk_widget_show_all( GTK_WIDGET( main_menu
) );
563 // GtkWidget *toolbar;
564 // toolbar = glade_xml_get_widget(pPrivate->pGladeXML, "toolbar");
565 // g_print("Got %p\n",toolbar);
566 // gtk_widget_reparent (toolbar, appview->vbox);
568 gtk_widget_show_all(GTK_WIDGET(pPrivate
->pHWindow
));
570 gtk_widget_destroy(pPrivate
->pMainWindow
);
571 pPrivate
->pMainWindow
= GTK_WIDGET(pPrivate
->pHWindow
);
573 g_signal_connect(G_OBJECT(pPrivate
->pHWindow
), "delete_event", G_CALLBACK(ask_save_before_exit
), NULL
);
575 #endif // Maemo fullscreen
578 // pPrivate->bHidden = false;
579 // pPrivate->bGrabbed = false;
581 // pPrivate->iPosition = 100; // FIXME - make this persistant
583 // TODO: Specify callbacks in glade file
584 // TODO: Rationalise focus
585 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "button-release-event", G_CALLBACK(take_real_focus), NULL);
586 // g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-press-event", G_CALLBACK(edit_key_press), NULL);
587 //g_signal_connect(G_OBJECT(pPrivate->pBufferView), "key-release-event", G_CALLBACK(edit_key_release), NULL);
589 pPrivate
->iAlphabetComboHandler
= g_signal_connect(G_OBJECT(pPrivate
->pAlphabetCombo
), "changed", G_CALLBACK(alphabet_combo_changed
), NULL
);
591 // dasher_main_build_context_menu(pSelf);
593 // Create a Maemo helper if necessary
594 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
595 pPrivate
->pMaemoHelper
= dasher_maemo_helper_new(GTK_WINDOW(pPrivate
->pMainWindow
));
598 // Set up any non-registry-dependent options
600 gtk_window_set_decorated(GTK_WINDOW(pPrivate
->pMainWindow
), false);
603 // Hide any widgets which aren't appropriate for this mode
605 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) == APP_STYLE_DIRECT
) {
606 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "dasher_menu_bar"));
608 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_new"));
609 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_open"));
610 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_save"));
611 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_saveas"));
612 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "separatortoolitem1"));
613 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_cut"));
614 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_copy"));
615 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "tb_command_paste"));
616 gtk_widget_hide(glade_xml_get_widget(pPrivate
->pGladeXML
, "separatortoolitem2"));
620 dasher_main_connect_menus(pSelf
);
623 pPrivate
->pEditor
= DASHER_EDITOR(glade_xml_get_widget(pPrivate
->pGladeXML
, "DasherEditor"));
625 pPrivate
->bWidgetsInitialised
= true;
629 dasher_main_create_preferences(DasherMain
*pSelf
) {
630 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
631 pPrivate
->pPreferencesDialogue
= dasher_preferences_dialogue_new(pPrivate
->pPrefXML
, pPrivate
->pEditor
, pPrivate
->pAppSettings
, GTK_WINDOW(pPrivate
->pMainWindow
));
635 // dasher_main_get_editor(DasherMain *pSelf) {
636 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
637 // return pPrivate->pEditor;
641 dasher_main_handle_parameter_change(DasherMain
*pSelf
, int iParameter
) {
642 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
644 switch( iParameter
) {
645 case APP_BP_SHOW_TOOLBAR
:
646 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, APP_BP_SHOW_TOOLBAR
))
647 gtk_widget_show(pPrivate
->pToolbar
);
649 gtk_widget_hide(pPrivate
->pToolbar
);
651 case BP_SHOW_SLIDER
: // TODO: Shouldn't be a core parmeter
652 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, BP_SHOW_SLIDER
))
653 gtk_widget_show(pPrivate
->pStatusControl
);
655 gtk_widget_hide(pPrivate
->pStatusControl
);
657 // case APP_SP_EDIT_FONT:
658 // TODO: Editor should handle this directly
659 // dasher_main_refresh_font(pSelf);
663 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pPrivate
->pSpeedBox
), dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) / 100.0);
667 dasher_main_populate_alphabet_combo(pSelf
);
669 case BP_GLOBAL_KEYBOARD
:
670 dasher_main_setup_window(pSelf
);
672 #if defined WITH_MAEMO && !defined WITH_MAEMOFULLSCREEN
673 case APP_LP_MAEMO_SIZE
: {
674 g_message("Maemo size");
676 bool bVisible
= GTK_WIDGET_VISIBLE(pPrivate
->pMainWindow
);
677 gtk_widget_hide(pPrivate
->pMainWindow
);
678 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_MAEMO_SIZE
) == 0) {
680 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWidth
, NULL
);
681 gtk_widget_set_size_request(pPrivate
->pMainWindow
, -1, 150);
682 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWidth
, 150);
683 gtk_widget_set_size_request(pPrivate
->pDasherWidget
, 175, -1);
687 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWidth
, NULL
);
688 gtk_widget_set_size_request(pPrivate
->pMainWindow
, -1, 250);
689 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWidth
, 250);
690 gtk_widget_set_size_request(pPrivate
->pDasherWidget
, 280, -1);
693 gtk_widget_show(pPrivate
->pMainWindow
);
699 if(pPrivate
->pPreferencesDialogue
)
700 dasher_preferences_dialogue_handle_parameter_change(pPrivate
->pPreferencesDialogue
, iParameter
);
702 if(pPrivate
->pEditor
)
703 dasher_editor_handle_parameter_change(pPrivate
->pEditor
, iParameter
);
707 dasher_main_load_state(DasherMain
*pSelf
) {
708 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
714 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_COMPOSE
) {
715 iEditHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_EDIT_HEIGHT
);
716 iWindowWidth
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH
);
717 iWindowHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT
);
720 iEditHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_EDIT_WIDTH
);
721 iWindowWidth
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH_H
);
722 iWindowHeight
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT_H
);
726 gtk_window_resize(GTK_WINDOW(pPrivate
->pMainWindow
), iWindowWidth
, iWindowHeight
);
729 gtk_paned_set_position(GTK_PANED(pPrivate
->pDivider
), iEditHeight
);
731 pPrivate
->iWidth
= iWindowWidth
;
732 pPrivate
->iHeight
= iWindowHeight
;
738 iWindowX
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_X
);
739 iWindowY
= dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_Y
);
741 gtk_window_move(GTK_WINDOW(pPrivate
->pMainWindow
), iWindowX
, iWindowY
);
744 // pPrivate->iPosition = dasher_app_settings_get_long(pPrivate->pAppSettings, APP_LP_DOCK_POSITION);
748 dasher_main_save_state(DasherMain
*pSelf
) {
749 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
751 if(!pPrivate
->bWidgetsInitialised
)
758 gtk_window_get_size(GTK_WINDOW(pPrivate
->pMainWindow
), &iWindowWidth
, &iWindowHeight
);
759 iEditHeight
= gtk_paned_get_position(GTK_PANED(pPrivate
->pDivider
));
761 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_COMPOSE
) {
762 // APP_STYLE_DIRECT doesn't have an edit window.
763 if (dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) != APP_STYLE_DIRECT
)
764 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_EDIT_HEIGHT
, iEditHeight
);
765 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH
, iWindowWidth
);
766 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT
, iWindowHeight
);
769 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_EDIT_WIDTH
, iEditHeight
);
770 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_WIDTH_H
, iWindowWidth
);
771 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_SCREEN_HEIGHT_H
, iWindowHeight
);
776 gtk_window_get_position(GTK_WINDOW(pPrivate
->pMainWindow
), &iWindowX
, &iWindowY
);
778 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_X
, iWindowX
);
779 dasher_app_settings_set_long(pPrivate
->pAppSettings
, APP_LP_Y
, iWindowY
);
781 // dasher_app_settings_set_long(pPrivate->pAppSettings, APP_LP_DOCK_POSITION, pPrivate->iPosition);
785 dasher_main_show(DasherMain
*pSelf
) {
786 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
787 gtk_widget_show(pPrivate
->pMainWindow
);
791 dasher_main_setup_window(DasherMain
*pSelf
) {
792 dasher_main_setup_window_style(pSelf
);
793 dasher_main_setup_window_state(pSelf
);
794 dasher_main_setup_internal_layout(pSelf
);
796 // DasherMainPrivate *pPrivate = (DasherMainPrivate *)(pSelf->private_data);
798 // if(dasher_app_settings_get_bool(pPrivate->pAppSettings, BP_GLOBAL_KEYBOARD))
799 // gdk_window_add_filter(0, keyboard_filter_cb, 0);
801 // gdk_window_remove_filter(0, keyboard_filter_cb, 0);
805 dasher_main_populate_controls(DasherMain
*pSelf
) {
806 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
808 // Populate the alphabet chooser
809 dasher_main_populate_alphabet_combo(pSelf
);
811 // Set the value of the speed spinner
812 gtk_spin_button_set_value(GTK_SPIN_BUTTON(pPrivate
->pSpeedBox
),
813 dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) / 100.0);
817 dasher_main_connect_control(DasherMain
*pSelf
) {
818 /* TODO: This is very much temporary - we need to think of a better
819 way of presenting application commands in a unified way */
821 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
823 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
824 Dasher::CControlManager::CTL_USER
,
827 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
828 Dasher::CControlManager::CTL_USER
,
829 Dasher::CControlManager::CTL_ROOT
, -2);
832 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
833 Dasher::CControlManager::CTL_USER
+ 1,
836 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
837 Dasher::CControlManager::CTL_USER
+ 2,
840 gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
841 Dasher::CControlManager::CTL_USER
+ 3,
844 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
845 Dasher::CControlManager::CTL_USER
+ 1,
846 Dasher::CControlManager::CTL_USER
, -2);
848 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
850 Dasher::CControlManager::CTL_USER
+ 1, -2);
852 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
853 Dasher::CControlManager::CTL_USER
+ 2,
854 Dasher::CControlManager::CTL_USER
, -2);
856 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
858 Dasher::CControlManager::CTL_USER
+ 2, -2);
860 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
861 Dasher::CControlManager::CTL_USER
+ 3,
862 Dasher::CControlManager::CTL_USER
, -2);
864 gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
866 Dasher::CControlManager::CTL_USER
+ 3, -2);
873 dasher_main_command(DasherMain
*pSelf
, const gchar
*szCommand
) {
874 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
876 if(!strcmp(szCommand
, "import")) {
877 dasher_main_command_import(pSelf
);
881 if(!strcmp(szCommand
, "quit")) {
882 dasher_main_command_quit(pSelf
);
886 if(!strcmp(szCommand
, "preferences")) {
887 dasher_main_command_preferences(pSelf
);
891 if(!strcmp(szCommand
, "preferences_alphabet")) {
892 dasher_main_command_preferences_alphabet(pSelf
);
896 if(!strcmp(szCommand
, "tutorial")) {
897 dasher_main_command_tutorial(pSelf
);
901 if(!strcmp(szCommand
, "help")) {
902 dasher_main_command_help(pSelf
);
906 if(!strcmp(szCommand
, "about")) {
907 dasher_main_command_about(pSelf
);
911 if(pPrivate
->pEditor
)
912 return dasher_editor_command(pPrivate
->pEditor
, szCommand
);
917 /* Private methods */
919 /* Window state is basically size and position */
921 dasher_main_setup_window_state(DasherMain
*pSelf
) {
922 dasher_main_load_state(pSelf
);
924 // TODO: Setup positioning here - need to think up a policy on this
928 /* Setup the window style - this is defined to be window manager hints and the like */
930 dasher_main_setup_window_style(DasherMain
*pSelf
) {
931 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
933 switch(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
)) {
937 case APP_STYLE_COMPOSE
:
940 case APP_STYLE_DIRECT
:
941 // Direct mode - set always on top
942 gtk_window_set_keep_above(GTK_WINDOW(pPrivate
->pMainWindow
), true);
945 gtk_window_set_accept_focus(GTK_WINDOW(pPrivate
->pMainWindow
), false);
947 // Stick on all desktops
948 gtk_window_stick(GTK_WINDOW(pPrivate
->pMainWindow
));
950 case APP_STYLE_FULLSCREEN
:
951 // Fullscreen mode - set fullscreen
952 gtk_window_fullscreen(GTK_WINDOW(pPrivate
->pMainWindow
));
955 g_error("Inconsistent application style specified.");
959 /* Internal layout is the visibility of various widgets */
961 dasher_main_setup_internal_layout(DasherMain
*pSelf
) {
962 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
964 if(pPrivate
->pToolbar
) {
965 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, APP_BP_SHOW_TOOLBAR
))
966 gtk_widget_show(pPrivate
->pToolbar
);
968 gtk_widget_hide(pPrivate
->pToolbar
);
971 if(pPrivate
->pStatusControl
) {
972 if( dasher_app_settings_get_bool(pPrivate
->pAppSettings
, BP_SHOW_SLIDER
))
973 gtk_widget_show(pPrivate
->pStatusControl
);
975 gtk_widget_hide(pPrivate
->pStatusControl
);
978 // dasher_main_refresh_font(pSelf);
982 // dasher_main_refresh_font(DasherMain *pSelf) {
983 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(pSelf);
985 // dasher_editor_handle_font(pPrivate->pEditor,
986 // dasher_app_settings_get_string(pPrivate->pAppSettings, APP_SP_EDIT_FONT));
989 // TODO: Fold into setup controls?
991 dasher_main_set_window_title(DasherMain
*pSelf
) {
992 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
994 const gchar
*szFilename
= dasher_editor_get_filename(pPrivate
->pEditor
);
996 // Note to translators: This is the name of the dasher program as it appears
997 // in a window title.
998 gchar
* dasher
= _("Dasher");
999 if(szFilename
== 0) {
1000 gtk_window_set_title(GTK_WINDOW(pPrivate
->pMainWindow
), dasher
);
1003 gchar
*title
= g_strdup_printf("%s - %s", dasher
, szFilename
);
1004 gtk_window_set_title(GTK_WINDOW(pPrivate
->pMainWindow
), title
);
1010 dasher_main_connect_menus(DasherMain
*pSelf
) {
1011 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1013 int iNumItems
= sizeof(MenuCommands
) / sizeof(DasherMenuCommand
);
1015 for(int i(0); i
< iNumItems
; ++i
) {
1018 pWidget
= glade_xml_get_widget(pPrivate
->pGladeXML
, MenuCommands
[i
].szWidgetName
);
1020 MenuCommands
[i
].pWidget
= pWidget
;
1022 // TODO: Check that these are the right signals to connect to
1024 if(GTK_IS_MENU_ITEM(pWidget
))
1025 g_signal_connect(G_OBJECT(pWidget
), "activate", G_CALLBACK(dasher_main_cb_menu_command
), pSelf
);
1027 g_signal_connect(G_OBJECT(pWidget
), "clicked", G_CALLBACK(dasher_main_cb_menu_command
), pSelf
);
1033 dasher_main_menu_command(DasherMain
*pSelf
, GtkWidget
*pWidget
) {
1034 int iNumItems
= sizeof(MenuCommands
) / sizeof(DasherMenuCommand
);
1036 for(int i(0); i
< iNumItems
; ++i
) {
1037 if(MenuCommands
[i
].pWidget
== pWidget
) {
1038 dasher_main_command(pSelf
, MenuCommands
[i
].szCommand
);
1045 dasher_main_command_import(DasherMain
*pSelf
) {
1046 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1048 GtkWidget
*pFileSel
= gtk_file_chooser_dialog_new(_("Select File"),
1049 GTK_WINDOW(pPrivate
->pMainWindow
),
1050 GTK_FILE_CHOOSER_ACTION_OPEN
,
1051 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
1052 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
1056 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(pFileSel
), FALSE
);
1059 if(gtk_dialog_run(GTK_DIALOG(pFileSel
)) == GTK_RESPONSE_ACCEPT
) {
1062 gchar
*szFilename
= gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(pFileSel
));
1064 gchar
*szFilename
= gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(pFileSel
));
1067 gtk_dasher_control_train(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), szFilename
);
1072 gtk_widget_destroy(pFileSel
);
1075 static void dasher_main_command_quit(DasherMain
*pSelf
) {
1076 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1078 GtkWidget
*pDialogue
= NULL
;
1080 if(dasher_editor_file_changed(pPrivate
->pEditor
)) {
1081 // XXX PRLW: Just open the save dialogue box.
1083 const gchar
*szFilename
= dasher_editor_get_filename(pPrivate
->pEditor
);
1086 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
1087 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
1088 _("Do you want to save your changes to %s?\n\nYour changes will be lost if you don't save them."),
1093 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
1094 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
1095 _("Do you want to save your changes?\n\nYour changes will be lost if you don't save them."));
1100 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue
),
1101 _("Don't save"), GTK_RESPONSE_REJECT
,
1102 _("Don't quit"), GTK_RESPONSE_CANCEL
,
1103 _("Save and quit"), GTK_RESPONSE_ACCEPT
,
1106 switch (gtk_dialog_run(GTK_DIALOG(pDialogue
))) {
1107 case GTK_RESPONSE_REJECT
:
1110 case GTK_RESPONSE_CANCEL
:
1111 gtk_widget_destroy(GTK_WIDGET(pDialogue
));
1113 case GTK_RESPONSE_ACCEPT
:
1114 dasher_editor_command(pPrivate
->pEditor
, "save");
1120 pDialogue
= gtk_message_dialog_new(GTK_WINDOW(pPrivate
->pMainWindow
), GTK_DIALOG_MODAL
,
1121 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
,
1122 _("Are you sure you wish to quit?"));
1124 gtk_dialog_add_buttons(GTK_DIALOG(pDialogue
),
1125 _("Don't quit"), GTK_RESPONSE_REJECT
,
1126 _("Quit"), GTK_RESPONSE_ACCEPT
,
1129 switch (gtk_dialog_run(GTK_DIALOG(pDialogue
))) {
1130 case GTK_RESPONSE_REJECT
:
1131 gtk_widget_destroy(GTK_WIDGET(pDialogue
));
1133 case GTK_RESPONSE_ACCEPT
:
1140 dasher_main_command_preferences(DasherMain
*pSelf
) {
1141 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1142 dasher_preferences_dialogue_show(pPrivate
->pPreferencesDialogue
, 0);
1146 dasher_main_command_preferences_alphabet(DasherMain
*pSelf
) {
1147 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1148 dasher_preferences_dialogue_show(pPrivate
->pPreferencesDialogue
, 1);
1152 dasher_main_command_tutorial(DasherMain
*pSelf
) {
1153 // TODO: Implement this
1157 dasher_main_command_help(DasherMain
*pSelf
) {
1158 // TODO: Need to disable the menu if gnome libs aren't present (or get rid of without gnome option)
1160 gnome_help_display_desktop(NULL
, "dasher", "dasher", NULL
, NULL
);
1165 dasher_main_command_about(DasherMain
*pSelf
) {
1166 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1168 #if (defined GNOME_LIBS) || (GTK_CHECK_VERSION(2,6,0))
1170 // In alphabetical order - please keep this in sync with the AUTHORS
1171 // file at root of the package tree
1172 const gchar
*authors
[] = {
1194 // Yeah, should really do some Gnome documentation for it...
1195 const gchar
*documenters
[] = {
1202 #if GTK_CHECK_VERSION(2,6,0)
1203 gtk_show_about_dialog(GTK_WINDOW(pPrivate
->pMainWindow
),
1205 "comments", _("Dasher is a predictive text entry application"),
1206 "copyright", "Copyright \xC2\xA9 1998-2007 The Dasher Project",
1207 "documenters", documenters
,
1208 "license", "GPL 2+",
1209 "logo-icon-name", "dasher",
1210 "translator-credits", _("translator-credits"),
1212 "website", "http://www.dasher.org.uk/",
1213 "wrap-license", true,
1216 gchar
*translator_credits
= _("translator-credits");
1218 GtkWidget
*about
= gnome_about_new (_("Dasher"),
1220 "Copyright The Dasher Project\n",
1221 _("Dasher is a predictive text entry application"),
1222 (const char **)authors
,
1223 (const char **)documenters
,
1224 strcmp (translator_credits
, "translator-credits") != 0 ? (const char *)translator_credits
: NULL
,
1227 gtk_window_set_transient_for (GTK_WINDOW(about
), GTK_WINDOW(pPrivate
->pMainWindow
));
1228 // g_signal_connect (G_OBJECT (about), "destory", G_CALLBACK (gtk_widget_destroyed), &about);
1229 gtk_widget_show(about
);
1234 // EAT UGLY ABOUT BOX, PHILISTINE
1235 GtkWidget
*label
, *button
;
1238 GtkWidget
*about
= gtk_dialog_new();
1240 gtk_dialog_set_has_separator(GTK_DIALOG(about
), FALSE
);
1241 gtk_window_set_title(GTK_WINDOW(about
), "About Dasher");
1243 tmp
= g_strdup_printf("Dasher Version %s ", VERSION
);
1244 label
= gtk_label_new(tmp
);
1245 gtk_widget_show(label
);
1246 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about
)->vbox
), label
, FALSE
, FALSE
, 0);
1248 label
= gtk_label_new("http://www.dasher.org.uk/");
1249 gtk_widget_show(label
);
1250 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about
)->vbox
), label
, FALSE
, FALSE
, 0);
1252 label
= gtk_label_new("Copyright The Dasher Project");
1253 gtk_widget_show(label
);
1254 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about
)->vbox
), label
, TRUE
, TRUE
, 0);
1256 button
= gtk_button_new_from_stock(GTK_STOCK_OK
);
1257 gtk_widget_show(button
);
1258 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(about
)->vbox
), button
, FALSE
, FALSE
, 0);
1259 g_signal_connect_swapped(G_OBJECT(button
), "clicked", G_CALLBACK(gtk_widget_destroy
), G_OBJECT(about
));
1261 gtk_widget_show(about
);
1266 dasher_main_speed_changed(DasherMain
*pSelf
) {
1267 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1269 int iNewValue( static_cast<int>(round(gtk_spin_button_get_value(GTK_SPIN_BUTTON(pPrivate
->pSpeedBox
)) * 100)));
1271 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
) != iNewValue
)
1272 dasher_app_settings_set_long(pPrivate
->pAppSettings
, LP_MAX_BITRATE
, iNewValue
);
1278 dasher_main_alphabet_combo_changed(DasherMain
*pSelf
) {
1279 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1283 if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), &sIter
)) {
1285 gtk_tree_model_get(GTK_TREE_MODEL(pPrivate
->pAlphabetList
), &sIter
, 0, &szSelected
, -1);
1287 if(!strcmp("More Alphabets...", szSelected
)) {
1288 gtk_combo_box_set_active(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), 0);
1289 // dasher_preferences_dialogue_show(pPrivate->pPreferencesDialogue);
1290 dasher_main_command(pSelf
, "preferences_alphabet");
1293 dasher_app_settings_set_string(pPrivate
->pAppSettings
, SP_ALPHABET_ID
, szSelected
);
1300 dasher_main_populate_alphabet_combo(DasherMain
*pSelf
) {
1302 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1304 // Disconnect the event handler temporarily, otherwise this will
1305 // trigger alphabet changes
1307 g_signal_handler_block(pPrivate
->pAlphabetCombo
, pPrivate
->iAlphabetComboHandler
);
1309 gtk_list_store_clear(pPrivate
->pAlphabetList
);
1313 const char *szValue
;
1315 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_ID
);
1317 if(strlen(szValue
) > 0) {
1318 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1319 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1320 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(pPrivate
->pAlphabetCombo
), &sIter
);
1323 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_1
);
1324 if(strlen(szValue
) > 0) {
1325 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1326 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1329 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_2
);
1330 if(strlen(szValue
) > 0) {
1331 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1332 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1335 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_3
);
1336 if(strlen(szValue
) > 0) {
1337 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1338 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1341 szValue
= dasher_app_settings_get_string(pPrivate
->pAppSettings
, SP_ALPHABET_4
);
1342 if(strlen(szValue
) > 0) {
1343 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1344 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, szValue
, -1);
1347 gtk_list_store_append(pPrivate
->pAlphabetList
, &sIter
);
1348 gtk_list_store_set(pPrivate
->pAlphabetList
, &sIter
, 0, "More Alphabets...", -1);
1350 g_signal_handler_unblock(pPrivate
->pAlphabetCombo
, pPrivate
->iAlphabetComboHandler
);
1356 dasher_main_lookup_key(DasherMain
*pSelf
, guint iKeyVal
) {
1357 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1359 if(pPrivate
->pKeyboardHelper
)
1360 return pPrivate
->pKeyboardHelper
->ConvertKeycode(iKeyVal
);
1369 // TODO: reimplement (text view member of class)
1370 // gtk_widget_grab_focus(the_text_view);
1371 // g_bForwardKeyboard = true;
1377 extern "C" GtkWidget
*
1378 create_dasher_control(gchar
*szName
, gchar
*szString1
, gchar
*szString2
, gint iInt1
, gint iInt2
) {
1379 GtkWidget
*pDasherControl
= gtk_dasher_control_new();
1382 // TODO: Do this in glade file?
1383 gtk_widget_set_size_request(pDasherControl
, 175, -1);
1386 return pDasherControl
;
1389 extern "C" GtkWidget
*
1390 create_dasher_editor(gchar
*szName
, gchar
*szString1
, gchar
*szString2
, gint iInt1
, gint iInt2
) {
1391 g_return_val_if_fail(g_pDasherMain
!= NULL
, NULL
);
1393 DasherMain
*pDasherMain
= DASHER_MAIN(g_pDasherMain
);
1394 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
1396 if(dasher_app_settings_get_long(pPrivate
->pAppSettings
, APP_LP_STYLE
) == APP_STYLE_DIRECT
)
1397 return GTK_WIDGET(dasher_editor_external_new());
1399 return GTK_WIDGET(dasher_editor_internal_new());
1403 dasher_main_cb_menu_command(GtkWidget
*pWidget
, gpointer pUserData
) {
1404 dasher_main_menu_command((DasherMain
*)pUserData
, pWidget
);
1406 return FALSE
; // TODO: Scheck semantics of return value
1410 speed_changed(GtkWidget
*pWidget
, gpointer user_data
) {
1412 return dasher_main_speed_changed(g_pDasherMain
);
1414 // TODO: Check callback return functions
1419 alphabet_combo_changed(GtkWidget
*pWidget
, gpointer pUserData
) {
1421 dasher_main_alphabet_combo_changed(g_pDasherMain
);
1425 dasher_main_cb_filename_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1427 dasher_main_set_window_title(g_pDasherMain
);
1431 dasher_main_cb_buffer_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1435 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1437 gtk_dasher_control_set_buffer(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), dasher_editor_get_offset(pPrivate
->pEditor
));
1441 dasher_main_cb_context_changed(DasherEditor
*pEditor
, gpointer pUserData
) {
1448 DasherMain
*pDasherMain
= DASHER_MAIN(g_pDasherMain
);
1449 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pDasherMain
);
1451 gtk_dasher_control_set_offset(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), dasher_editor_get_offset(pPrivate
->pEditor
));
1455 dasher_main_cb_window_close(GtkWidget
*pWidget
, gpointer pUserData
) {
1456 dasher_main_command(g_pDasherMain
, "quit");
1458 /* Returning true stops further propagation */
1463 parameter_notification(GtkDasherControl
*pDasherControl
, gint iParameter
, gpointer data
) {
1465 dasher_main_handle_parameter_change(g_pDasherMain
, iParameter
);
1468 // TODO: Not really sure what happens here - need to sort out focus behaviour in general
1470 focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
) {
1471 return grab_focus();
1475 edit_focus_in_event(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer data
) {
1480 take_real_focus(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
) {
1481 // g_bForwardKeyboard = false;
1486 edit_key_press(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
) {
1487 // TODO: Reimplement
1489 // if(g_bForwardKeyboard) {
1490 // gboolean *returnType;
1491 // g_signal_emit_by_name(GTK_OBJECT(pPrivate->pDasherWidget), "key_press_event", event, &returnType);
1498 // TODO: Check callback return functions
1503 edit_key_release(GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
) {
1504 // TODO: reimplement
1506 // if(g_bForwardKeyboard) {
1507 // gboolean *returnType;
1508 // g_signal_emit_by_name(GTK_OBJECT(pPrivate->pDasherWidget), "key_release_event", event, &returnType);
1515 // TODO: Check callback return functions
1520 test_focus_handler(GtkWidget
*pWidget
, GtkDirectionType iDirection
, gpointer
*pUserData
) {
1525 handle_context_request(GtkDasherControl
* pDasherControl
, gint iOffset
, gint iLength
, gpointer data
) {
1529 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1531 if(!pPrivate
->pEditor
|| !pPrivate
->pDasherWidget
)
1534 gtk_dasher_control_set_context(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), dasher_editor_get_context(pPrivate
->pEditor
, iOffset
, iLength
));
1538 handle_control_event(GtkDasherControl
*pDasherControl
, gint iEvent
, gpointer data
) {
1542 /* TODO: replace this with something a little more sensible */
1545 case Dasher::CControlManager::CTL_USER
+ 1:
1546 dasher_main_command(g_pDasherMain
, "speakall");
1548 case Dasher::CControlManager::CTL_USER
+ 2:
1549 dasher_main_command(g_pDasherMain
, "speaklast");
1551 case Dasher::CControlManager::CTL_USER
+ 3:
1552 dasher_main_command(g_pDasherMain
, "speakrepeat");
1559 // TODO: This is a horrible hack here to make the release work!
1563 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1564 dasher_editor_handle_control(pPrivate
->pEditor
, iEvent
);
1566 gtk_dasher_control_set_control_offset(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
),
1567 dasher_editor_get_offset(pPrivate
->pEditor
));
1575 handle_start_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1579 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1581 dasher_editor_grab_focus(pPrivate
->pEditor
);
1585 // TODO: Make this only work for children of the main window
1587 dasher_main_key_snooper(GtkWidget
*pWidget
, GdkEventKey
*pEvent
, gpointer pUserData
) {
1588 DasherMain
*pSelf
= DASHER_MAIN(pUserData
);
1590 gint iButton
= dasher_main_lookup_key(pSelf
, pEvent
->keyval
);
1593 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(pSelf
);
1595 if(gdk_window_get_toplevel(pEvent
->window
) == pPrivate
->pMainWindow
->window
) {
1596 if(pPrivate
->pDasherWidget
) {
1597 if(pEvent
->type
== GDK_KEY_PRESS
)
1598 gtk_dasher_control_external_key_down(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), iButton
);
1600 gtk_dasher_control_external_key_up(GTK_DASHER_CONTROL(pPrivate
->pDasherWidget
), iButton
);
1614 // Callbacks from the Dasher widget
1617 handle_stop_event(GtkDasherControl
*pDasherControl
, gpointer data
) {
1619 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1621 if(pPrivate
->pEditor
)
1622 dasher_editor_handle_stop(pPrivate
->pEditor
);
1627 on_message(GtkDasherControl
*pDasherControl
, gpointer pMessageInfo
, gpointer pUserData
) {
1628 // TODO: I don't believe that this is widely used, but possibly need to reimplement
1630 // if(g_pDasherMain) {
1631 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1633 // if(pPrivate->pEditor)
1634 // dasher_editor_display_message(pPrivate->pEditor, (DasherMessageInfo *)pMessageInfo);
1639 on_command(GtkDasherControl
*pDasherControl
, gchar
*szCommand
, gpointer pUserData
) {
1641 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1643 if(pPrivate
->pEditor
)
1644 dasher_editor_command(pPrivate
->pEditor
, szCommand
);
1648 // TODO: The following two should probably be made the same
1650 handle_request_settings(GtkDasherControl
* pDasherControl
, gpointer data
) {
1651 // TODO: reimplement
1652 // dasher_preferences_dialogue_show(g_pPreferencesDialogue);
1656 gtk2_edit_delete_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, int iOffset
, gpointer user_data
) {
1658 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1660 if(pPrivate
->pEditor
) {
1661 gint displaylength
= g_utf8_strlen(szText
, -1);
1662 dasher_editor_delete(pPrivate
->pEditor
, displaylength
, iOffset
);
1668 gtk2_edit_output_callback(GtkDasherControl
*pDasherControl
, const gchar
*szText
, int iOffset
, gpointer user_data
) {
1670 DasherMainPrivate
*pPrivate
= DASHER_MAIN_GET_PRIVATE(g_pDasherMain
);
1672 if(pPrivate
->pEditor
) {
1673 dasher_editor_output(pPrivate
->pEditor
, szText
, iOffset
);
1678 // TODO: The following aren't exported from the editor - need to fix this
1681 convert_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1682 // if(g_pDasherMain) {
1683 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1685 // if(pPrivate->pEditor) {
1686 // dasher_editor_convert(pPrivate->pEditor);
1692 protect_cb(GtkDasherControl
*pDasherControl
, gpointer pUserData
) {
1693 // if(g_pDasherMain) {
1694 // DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
1696 // if(pPrivate->pEditor) {
1697 // dasher_editor_protect(pPrivate->pEditor);