Recreate the navit git/gerrit project that vanished
[profile/ivi/navit.git] / navit / gui / win32 / gui_win32.c
1 #include <stdlib.h>
2 #include <process.h>
3 #include <windows.h>
4 #include <glib.h>
5 #include "config.h"
6 #include "plugin.h"
7 #include "gui.h"
8 #include "graphics_win32.h"
9 #include "point.h"
10 #include "menu.h"
11 #include "item.h"
12 #include "attr.h"
13 #include "callback.h"
14 #include <commctrl.h>
15 #include "debug.h"
16 #include "util.h"
17 #include "navit.h"
18 #include "navit_nls.h"
19 #ifdef __CEGCC__
20 #include <sipapi.h>
21 #include <aygshell.h>
22 #include "ceglue.h"
23
24 static int ce_backlight = 1;
25 static int ce_fullscreen;
26 #endif
27
28 #ifdef HAVE_GLIB
29 //static GHashTable *popup_callback_hash = NULL;
30 static GArray *popup_menu_array;
31 #endif
32
33 const TCHAR g_szClassName[] = TEXT("navit_gui_class");
34
35
36 static UINT_PTR menu_id = 0;
37
38 #if 0
39 static gboolean message_pump( gpointer data )
40 {
41     MSG messages;
42
43         Sleep( 1 );
44
45     if (GetMessage (&messages, NULL, 0, 0))
46     {
47         TranslateMessage(&messages);
48         DispatchMessage(&messages);
49     }
50     else{
51         exit( 0 );
52     }
53         return TRUE;
54 }
55
56 static BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
57 {
58     LPRECT rcParent;
59     int idChild;
60
61     idChild = GetWindowLong(hwndChild, GWL_ID);
62
63         if ( idChild == ID_CHILD_GFX )
64         {
65                 rcParent = (LPRECT) lParam;
66
67                 MoveWindow( hwndChild,  0, 0, rcParent->right, rcParent->bottom, TRUE );
68                 PostMessage( hwndChild, WM_USER+1, 0, 0 );
69         }
70
71     return TRUE;
72 }
73 #endif
74
75 #ifndef GET_WHEEL_DELTA_WPARAM
76         #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
77 #endif
78
79 static void CreateToolBar(HWND hwnd)
80 {
81         // Create Toolbar
82         HWND hTool;
83         TBBUTTON tbb[8];
84         TBADDBITMAP tbab;
85 #if 0 /* def _WIN32_WCE */
86         /* Have to initialize common controls under CE */
87         INITCOMMONCONTROLSEX iccex;
88         iccex.dwSize = sizeof (INITCOMMONCONTROLSEX);
89         iccex.dwICC = ICC_BAR_CLASSES;
90         InitCommonControlsEx (&iccex);
91 #else
92         InitCommonControls();
93 #endif
94
95         hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
96                 hwnd, (HMENU)ID_CHILD_TOOLBAR, GetModuleHandle(NULL), NULL);
97
98         if(hTool == NULL)
99                 MessageBox(hwnd, TEXT("Could not create tool bar."), TEXT("Error"), MB_OK | MB_ICONERROR);
100
101         SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
102
103         tbab.hInst = GetModuleHandle(NULL);
104         tbab.nID = IDB_NAVITTOOLBAR;
105         int iImageOffset = SendMessage(hTool, TB_ADDBITMAP, 10, (LPARAM) &tbab);
106
107         int iStr;
108
109         ZeroMemory(tbb, sizeof(tbb));
110
111         tbb[0].iBitmap = iImageOffset;
112         tbb[0].fsState = TBSTATE_ENABLED;
113         tbb[0].fsStyle = TBSTYLE_BUTTON;
114         tbb[0].idCommand = ID_DISPLAY_ZOOMIN;
115         iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"ZoomIn" );
116         tbb[0].iString = iStr;
117
118         tbb[1].iBitmap = iImageOffset+1;
119         tbb[1].fsState = TBSTATE_ENABLED;
120         tbb[1].fsStyle = TBSTYLE_BUTTON;
121         tbb[1].idCommand = ID_DISPLAY_ZOOMOUT;
122         iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"ZoomOut" );
123         tbb[1].iString = iStr;
124
125         tbb[2].iBitmap = iImageOffset+4;
126         tbb[2].fsState = TBSTATE_ENABLED;
127         tbb[2].fsStyle = TBSTYLE_BUTTON;
128         tbb[2].idCommand = ID_DISPLAY_REFRESH;
129         iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"Refresh" );
130         tbb[2].iString = iStr;
131
132         tbb[3].iBitmap = iImageOffset+2;
133         tbb[3].fsState = TBSTATE_ENABLED;
134         tbb[3].fsStyle = TBSTYLE_BUTTON;
135         tbb[3].idCommand = ID_DISPLAY_ZOOMIN;
136         iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"Cursor" );
137         tbb[3].iString = iStr;
138
139         tbb[4].iBitmap = iImageOffset+5;
140         tbb[4].fsState = TBSTATE_ENABLED;
141         tbb[4].fsStyle = TBSTYLE_BUTTON;
142         tbb[4].idCommand = ID_DISPLAY_ORIENT;
143         iStr = SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"Orientation" );
144         tbb[4].iString = iStr;
145
146         tbb[5].iBitmap = iImageOffset+8;
147         tbb[5].fsState = TBSTATE_ENABLED;
148         tbb[5].fsStyle = TBSTYLE_BUTTON;
149         tbb[5].idCommand = ID_DISPLAY_ZOOMIN;
150         iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"Destination" );
151         tbb[5].iString = iStr;
152
153         tbb[6].iBitmap = iImageOffset+3;
154         tbb[6].fsState = TBSTATE_ENABLED;
155         tbb[6].fsStyle = TBSTYLE_BUTTON;
156         tbb[6].idCommand = ID_DISPLAY_ZOOMIN;
157         iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"Roadbook" );
158         tbb[6].iString = iStr;
159
160         tbb[7].iBitmap = iImageOffset+9;
161         tbb[7].fsState = TBSTATE_ENABLED;
162         tbb[7].fsStyle = TBSTYLE_BUTTON;
163         tbb[7].idCommand = ID_FILE_EXIT;
164         iStr= SendMessage(hTool, TB_ADDSTRINGW, 0, (LPARAM)  L"_Quit" );
165         tbb[7].iString = iStr;
166
167         SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb);
168 }
169
170 static void window_layout( HWND hwnd )
171 {
172 #ifndef HAVE_API_WIN32_CE
173         RECT rcClient;
174         RECT rcTool;
175         int iToolHeight;
176
177         HWND hChild = GetDlgItem(hwnd, ID_CHILD_TOOLBAR);
178         SendMessage(hChild, TB_AUTOSIZE, 0, 0);
179
180         GetWindowRect(hChild, &rcTool);
181         iToolHeight = rcTool.bottom - rcTool.top;
182
183         GetClientRect(hwnd, &rcClient);
184         //printf( "BEFORE resize gui to: %d %d %d %d \n", rcClient.left, rcClient.right, rcClient.top, rcClient.bottom );
185
186         rcClient.top += iToolHeight;
187
188         dbg(0, "resize gui to: %d %d %d %d \n", rcClient.left, rcClient.right, rcClient.top, rcClient.bottom );
189
190
191         hChild = GetDlgItem(hwnd, ID_CHILD_GFX);
192         if ( hChild )
193         {
194                 MoveWindow( hChild,  rcClient.left, rcClient.top, rcClient.right- rcClient.left, rcClient.bottom - rcClient.top, TRUE );
195                 PostMessage( hChild, WM_USER+1, 0, 0 );
196         }
197 #endif
198 }
199 #ifdef __CEGCC__
200 static void toggle_fullscreen(HWND mWnd)
201 {
202         if (SHFullScreenPtr) {
203                 if (!ce_fullscreen) {
204                         (*SHFullScreenPtr)(mWnd, SHFS_HIDETASKBAR |
205                         SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON);
206                 } else {
207                         (*SHFullScreenPtr)(mWnd, SHFS_HIDESIPBUTTON);
208                 }
209                 ce_fullscreen = !ce_fullscreen;
210         }
211 }
212
213 static void toggle_backlight(void)
214 {
215         if (ce_backlight)
216                 if (CeEnableBacklight(FALSE))
217                         ce_backlight = 0;
218         else
219                 if (CeEnableBacklight(TRUE))
220                         ce_backlight = 1;
221 }
222 #endif
223
224 static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
225 {
226     RECT rcClient;
227
228 //      printf( "PARENT %d %d %d \n", Message, wParam, lParam );
229
230         switch(Message)
231         {
232                 case WM_CREATE:
233                 {
234                         HMENU hMenu, hSubMenu;
235
236                         CreateToolBar( hwnd );
237
238                         hMenu = CreateMenu();
239                         // g_this_->hwnd = hwnd;
240
241                         hSubMenu = CreatePopupMenu();
242
243                         AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_ZOOMIN, L"ZoomIn" );
244                         AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_ZOOMOUT, L"ZoomOut" );
245                         AppendMenuW(hSubMenu, MF_STRING, ID_DISPLAY_REFRESH, L"Refresh" );
246                         AppendMenuW(hSubMenu, MF_SEPARATOR, 0, NULL );
247                         AppendMenuW(hSubMenu, MF_STRING, ID_FILE_EXIT, L"_Quit" );
248
249                         AppendMenuW(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, L"Display" );
250                         hSubMenu = CreatePopupMenu();
251                         AppendMenu(hSubMenu, MF_STRING, ID_STUFF_GO, TEXT("&Go"));
252                         AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, TEXT("&Stuff"));
253
254 #ifndef HAVE_API_WIN32_CE
255                         SetMenu(hwnd, hMenu);
256 #endif
257
258                         window_layout( hwnd );
259
260                 }
261                 break;
262                 case WM_COMMAND:
263                 {
264                         printf( "WM_COMMAND %d\n", LOWORD(wParam) );
265                         struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
266
267
268                         switch(LOWORD(wParam))
269                         {
270                                 case ID_DISPLAY_ZOOMIN:
271                                         navit_zoom_in(gui->nav, 2, NULL);
272                                         return 0;
273                                 break;
274                                 case ID_DISPLAY_ZOOMOUT:
275                                         navit_zoom_out(gui->nav, 2, NULL);
276                                         return 0;
277                                 break;
278                                 case ID_DISPLAY_REFRESH:
279                                         navit_draw(gui->nav);
280                                         return 0;
281                                 break;
282                                 case ID_DISPLAY_CURSOR:
283                                 {
284                                         struct attr attr;
285                                         attr.type=attr_cursor;
286                                         // TODO attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
287                                         if(!navit_set_attr(gui->nav, &attr)) {
288                                                 dbg(0, "Failed to set attr_cursor\n");
289                                         }
290                                         return 0;
291                                 }
292                                 break;
293                                 case ID_DISPLAY_ORIENT:
294                                 {
295                                         struct attr attr;
296
297                                         attr.type=attr_orientation;
298                                         // attr.u.num=gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(w));
299                                         attr.u.num = 0; // TODO
300                                         if(!navit_set_attr(gui->nav, &attr)) {
301                                                 dbg(0, "Failed to set attr_orientation\n");
302                                         }
303                                         return 0;
304                                 }
305
306                                 case ID_FILE_EXIT:
307                                         PostMessage(hwnd, WM_CLOSE, 0, 0);
308                                         return 0;
309                                 break;
310                         }
311 #if HAVE_GLIB
312                         if ( popup_menu_array )
313                         {
314                                 struct menu_priv* priv = (struct menu_priv*)g_array_index( popup_menu_array, gint, LOWORD(wParam) - POPUP_MENU_OFFSET );
315
316                                 if ( priv )
317                                 {
318                                         struct callback* cb = priv->cb;
319                                         if ( priv->cb )
320                                         {
321                                                 callback_call_0( priv->cb );
322                                                 return 0;
323                                         }
324                                 }
325                         }
326 #endif
327                 }
328                 break;
329                 case WM_USER+ 1:
330             GetClientRect(hwnd, &rcClient);
331                         printf( "resize gui to: %d %d \n", rcClient.right, rcClient.bottom );
332
333                         window_layout( hwnd );
334             //EnumChildWindows(hwnd, EnumChildProc, (LPARAM) &rcClient);
335             return 0;
336                 break;
337                 case WM_CLOSE:
338                         DestroyWindow(hwnd);
339                 break;
340                 case WM_SIZE:
341                         window_layout( hwnd );
342             return 0;
343                 break;
344                 case WM_DESTROY:
345                         PostQuitMessage(0);
346                 break;
347
348
349                 case WM_MOUSEWHEEL:
350                 {
351                         struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
352
353                         short delta = GET_WHEEL_DELTA_WPARAM( wParam );
354                         if ( delta > 0 )
355                         {
356                                 navit_zoom_in(gui->nav, 2, NULL);
357                         }
358                         else{
359                                 navit_zoom_out(gui->nav, 2, NULL);
360                         }
361                 }
362                 break;
363 #ifdef HAVE_API_WIN32_CE
364                 case WM_KEYDOWN:
365                         {
366                         struct point p;
367                         int w,h;
368                         struct gui_priv* gui = (struct gui_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
369                         transform_get_size(navit_get_trans(gui->nav), &w, &h);
370                         
371                         if (wParam == VK_LEFT || wParam == '4') {
372                                 p.x=0;
373                                 p.y=h/2;
374                                 navit_set_center_screen(gui->nav, &p, 1);
375                         } else if (wParam == VK_RIGHT || wParam == '6') {
376                                 p.x=w;
377                                 p.y=h/2;
378                                 navit_set_center_screen(gui->nav, &p, 1);
379                         } else if (wParam == VK_UP || wParam == '2') {
380                                 p.x=w/2;
381                                 p.y=0;
382                                 navit_set_center_screen(gui->nav, &p, 1);
383                         } else if (wParam == VK_DOWN || wParam == '8') {
384                                 p.x=w/2;
385                                 p.y=h;
386                                 navit_set_center_screen(gui->nav, &p, 1);
387                         } else if (wParam == '1') {
388                                 navit_zoom_in(gui->nav, 2, NULL);
389                         } else if (wParam == '3') {
390                                 navit_zoom_out(gui->nav, 2, NULL);
391                         } else if (wParam == '7') {
392 #if 0
393                                 toggle_backlight();
394 #endif
395                         } else if (wParam == '9') {
396 #if 0
397                                 toggle_fullscreen(hwnd);
398 #endif
399                         }
400                         }
401                 break;
402 #endif
403                 default:
404                         return DefWindowProc(hwnd, Message, wParam, lParam);
405         }
406         return 0;
407 }
408
409 static HANDLE CreateWin32Window( void )
410 {
411 #ifdef HAVE_API_WIN32_CE
412         WNDCLASS wc;
413 #else
414         WNDCLASSEX wc;
415         wc.cbSize                = sizeof(WNDCLASSEX);
416         wc.hIconSm               = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_NAVIT));
417 #endif
418         HWND hwnd;
419 //      MSG Msg;
420
421         wc.style                 = 0;
422         wc.lpfnWndProc   = WndProc;
423         wc.cbClsExtra    = 0;
424         wc.cbWndExtra    = 32;
425         wc.hInstance     = NULL;
426         wc.hCursor               = LoadCursor(NULL, IDC_ARROW);
427         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
428         wc.lpszMenuName  = NULL;
429         wc.lpszClassName = g_szClassName;
430         wc.hIcon                 = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_NAVIT));
431
432 #ifdef HAVE_API_WIN32_CE
433         if(!RegisterClass(&wc))
434 #else
435         if(!RegisterClassEx(&wc))
436 #endif
437
438         {
439                 MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
440                 return 0;
441         }
442
443         hwnd = CreateWindowEx(
444                 WS_EX_CLIENTEDGE,
445                 g_szClassName,
446                 TEXT( "Navit" ),
447 #ifdef HAVE_API_WIN32_CE
448                 WS_SYSMENU | WS_CLIPCHILDREN,
449                 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
450 #else
451
452                 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
453                 CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
454 #endif
455                 NULL, NULL, NULL, NULL);
456
457         if(hwnd == NULL)
458         {
459                 MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
460                 return 0;
461         }
462
463         ShowWindow(hwnd, TRUE);
464         UpdateWindow(hwnd);
465
466 #if 0
467         g_idle_add (message_pump, NULL);
468 #endif
469
470         return hwnd;
471 }
472
473
474 static int win32_gui_set_graphics(struct gui_priv *this_, struct graphics *gra)
475 {
476         HANDLE* wndHandle_ptr = graphics_get_data(gra, "wnd_parent_handle_ptr");
477         *wndHandle_ptr = this_->hwnd;
478         graphics_get_data(gra, "START_CLIENT");
479         return 0;
480 }
481
482
483 static void win32_gui_add_bookmark_do(struct gui_priv *gui)
484 {
485 //      navit_add_bookmark(gui->nav, &gui->dialog_coord, gtk_entry_get_text(GTK_ENTRY(gui->dialog_entry)));
486 //      gtk_widget_destroy(gui->dialog_win);
487 }
488
489 static int win32_gui_add_bookmark(struct gui_priv *gui, struct pcoord *c, char *description)
490 {
491         return 1;
492 }
493
494
495 static struct menu_methods menu_methods;
496
497
498 static struct menu_priv *add_menu(      struct menu_priv *menu,
499                                                                         struct menu_methods *meth,
500                                                                         char *name,
501                                                                         enum menu_type type,
502                                                                         struct callback *cb)
503 {
504         struct menu_priv* ret = NULL;
505
506         ret = g_new0(struct menu_priv, 1);
507
508         *ret = *menu;
509         *meth = menu_methods;
510
511         TCHAR *menuname = newSysString(name);
512
513         if ( type == menu_type_submenu )
514         {
515                 HMENU hSubMenu = NULL;
516                 hSubMenu = CreatePopupMenu();
517                 AppendMenu(menu->hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, menuname );
518                 ret->hMenu = hSubMenu;
519         }
520         else
521         {
522                 AppendMenu( menu->hMenu, MF_STRING, menu_id, name );
523         }
524
525         // g_hash_table_insert( popup_callback_hash, GINT_TO_POINTER( menu_id ),  (gpointer)cb );
526 #if HAVE_GLIB
527         g_array_append_val( popup_menu_array, ret );
528 #endif
529
530         ret->cb = cb;
531
532         menu_id++;
533
534         return ret;
535
536 }
537
538 static void set_toggle(struct menu_priv *menu, int active)
539 {
540         // gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(menu->action), active);
541 }
542
543 static int get_toggle(struct menu_priv *menu)
544 {
545         // return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(menu->action));
546         return 0;
547 }
548
549 static struct menu_methods menu_methods = {
550         add_menu,
551         set_toggle,
552         get_toggle,
553 };
554
555 static void popup_activate(struct menu_priv *menu)
556 {
557         POINT pnt;
558         GetCursorPos( &pnt );
559
560         if (menu->hMenu)
561         {
562                 TrackPopupMenu( menu->hMenu, 0, pnt.x, pnt.y, 0, menu->wnd_handle, NULL );
563                 DestroyMenu( menu->hMenu );
564         }
565 }
566
567
568 static void popup_deactivate( struct menu_priv *menu )
569 {
570         DestroyMenu( menu->hMenu );
571 }
572
573 static struct menu_priv* win32_gui_popup_new(struct gui_priv *this_, struct menu_methods *meth)
574 {
575         struct menu_priv* ret = NULL;
576
577         ret = g_new0(struct menu_priv, 1);
578         *meth = menu_methods;
579
580         menu_id = POPUP_MENU_OFFSET;
581
582 #if HAVE_GLIB
583         if ( popup_menu_array )
584         {
585                 g_array_free (popup_menu_array, TRUE);
586                 popup_menu_array = NULL;
587         }
588
589         popup_menu_array = g_array_new (FALSE, FALSE, sizeof (gint));
590 #endif
591
592         ret->cb = NULL;
593         ret->hMenu = CreatePopupMenu();
594         ret->wnd_handle = this_->hwnd;
595         meth->popup=popup_activate;
596
597 printf( "create popup menu %d \n", ret->hMenu );
598
599         return ret;
600 }
601
602 struct gui_methods win32_gui_methods = {
603         NULL, // win32_gui_menubar_new,
604         win32_gui_popup_new,
605         win32_gui_set_graphics,
606         NULL,
607         NULL, // win32_gui_datawindow_new,
608         win32_gui_add_bookmark,
609 };
610
611
612
613 static struct gui_priv *win32_gui_new( struct navit *nav, struct gui_methods *meth, struct attr **attrs)
614 {
615         struct gui_priv *this_;
616 #ifdef HAVE_API_WIN32_CE
617         /* Do not run multiple instances under CE */
618         HWND prev;
619         prev = FindWindow(g_szClassName, NULL);
620         if (prev) {
621                 ShowWindow(prev, SW_RESTORE);
622                 SetForegroundWindow(prev);
623                 InvalidateRect (prev, NULL, FALSE);
624                 exit(0);
625         }
626         InitCeGlue();
627 #endif
628
629         *meth=win32_gui_methods;
630
631         this_=g_new0(struct gui_priv, 1);
632         this_->nav=nav;
633
634         this_->hwnd = CreateWin32Window();
635         SetWindowLongPtr( this_->hwnd , DWLP_USER, (LONG_PTR)this_ );
636
637         return this_;
638 }
639
640 void plugin_init(void)
641 {
642         plugin_register_gui_type("win32", win32_gui_new);
643 }