]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/app.cpp
image update
[wxWidgets.git] / src / gtk1 / app.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: app.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "app.h"
12 #endif
13
14 #include "wx/app.h"
15 #include "wx/gdicmn.h"
16 #include "wx/utils.h"
17 #include "wx/intl.h"
18 #include "wx/log.h"
19 #include "wx/memory.h"
20 #include "wx/font.h"
21 #include "wx/settings.h"
22 #if wxUSE_WX_RESOURCES
23 #include "wx/resource.h"
24 #endif
25 #include "wx/module.h"
26 #include "wx/image.h"
27 #if wxUSE_THREADS
28 #include "wx/thread.h"
29 #endif
30 #include "unistd.h"
31
32 #include "glib.h"
33 #include "gdk/gdk.h"
34 #include "gtk/gtk.h"
35 #include "wx/gtk/win_gtk.h"
36
37 //-----------------------------------------------------------------------------
38 // global data
39 //-----------------------------------------------------------------------------
40
41 wxApp *wxTheApp = (wxApp *) NULL;
42 wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL;
43
44 extern wxList wxPendingDelete;
45 extern wxResourceCache *wxTheResourceCache;
46
47 unsigned char g_palette[64*3] =
48 {
49 0x0, 0x0, 0x0,
50 0xff, 0xff, 0xff,
51 0xff, 0x0, 0x0,
52 0xff, 0xff, 0x0,
53 0x0, 0xff, 0x0,
54 0x0, 0x0, 0xff,
55 0x0, 0xff, 0xff,
56 0x99, 0x99, 0x99,
57 0xff, 0x88, 0x0,
58 0x88, 0x0, 0x0,
59 0x0, 0x88, 0x88,
60 0x88, 0x88, 0x0,
61 0xff, 0xcc, 0x97,
62 0xbb, 0xbb, 0xbb,
63 0x9f, 0x6b, 0x42,
64 0x55, 0x55, 0x55,
65 0xdd, 0xdd, 0xdd,
66 0x77, 0x77, 0x77,
67 0x33, 0x33, 0x33,
68 0xcc, 0x0, 0x0,
69 0xff, 0x44, 0x0,
70 0xff, 0xcc, 0x0,
71 0xcc, 0xcc, 0x0,
72 0x60, 0x60, 0x0,
73 0x0, 0x43, 0x0,
74 0x0, 0x7f, 0x0,
75 0x0, 0xcc, 0x0,
76 0x0, 0x44, 0x44,
77 0x0, 0x0, 0x44,
78 0x0, 0x0, 0x88,
79 0xef, 0xb1, 0x7b,
80 0xdf, 0x98, 0x5f,
81 0xbf, 0x87, 0x56,
82 0x7f, 0x57, 0x26,
83 0x5f, 0x39, 0xc,
84 0x3f, 0x1c, 0x0,
85 0x21, 0x0, 0x0,
86 0x0, 0x43, 0x87,
87 0x2d, 0x70, 0xaf,
88 0x5a, 0x9e, 0xd7,
89 0x87, 0xcc, 0xff,
90 0xff, 0xe0, 0xba,
91 0x21, 0x43, 0xf,
92 0x3d, 0x5d, 0x25,
93 0x59, 0x78, 0x3a,
94 0x75, 0x93, 0x4f,
95 0x91, 0xae, 0x64,
96 0xad, 0xc8, 0x7a,
97 0xf0, 0xa8, 0xef,
98 0xd0, 0x88, 0xd0,
99 0xaf, 0x66, 0xaf,
100 0x8e, 0x44, 0x8e,
101 0x6d, 0x22, 0x6d,
102 0x4b, 0x0, 0x4b,
103 0xff, 0xc0, 0xbc,
104 0xff, 0x93, 0x91,
105 0xff, 0x66, 0x67,
106 0xd8, 0xf2, 0xbf,
107 0xff, 0xc9, 0x68,
108 0xff, 0x96, 0x67,
109 0xa5, 0x60, 0xff,
110 0x51, 0xff, 0x99,
111 0x3f, 0xa5, 0x63,
112 0x98, 0x90, 0x67
113 };
114
115 //-----------------------------------------------------------------------------
116 // local functions
117 //-----------------------------------------------------------------------------
118
119 extern void wxFlushResources(void);
120
121 //-----------------------------------------------------------------------------
122 // global functions
123 //-----------------------------------------------------------------------------
124
125 void wxExit(void)
126 {
127 gtk_main_quit();
128 }
129
130 bool wxYield(void)
131 {
132 while (gtk_events_pending() > 0) gtk_main_iteration();
133 return TRUE;
134 }
135
136 //-----------------------------------------------------------------------------
137 // wxApp
138 //-----------------------------------------------------------------------------
139
140 IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler)
141
142 BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
143 EVT_IDLE(wxApp::OnIdle)
144 END_EVENT_TABLE()
145
146 gint wxapp_idle_callback( gpointer WXUNUSED(data) )
147 {
148 if (wxTheApp) while (wxTheApp->ProcessIdle()) {}
149 #if wxUSE_THREADS
150 wxMutexGuiLeave();
151 #endif
152 usleep(10000);
153 #if wxUSE_THREADS
154 wxMutexGuiEnter();
155 #endif
156 return TRUE;
157 }
158
159 wxApp::wxApp()
160 {
161 m_idleTag = 0;
162 m_topWindow = (wxWindow *) NULL;
163 m_exitOnFrameDelete = TRUE;
164 m_colorCube = (unsigned char*) NULL;
165 wxTheApp = this;
166 }
167
168 wxApp::~wxApp(void)
169 {
170 gtk_idle_remove( m_idleTag );
171
172 if (m_colorCube) free(m_colorCube);
173 }
174
175 bool wxApp::InitVisual()
176 {
177 /* Nothing to do for 15, 16, 24, 32 bit displays */
178
179 GdkVisual *visual = gdk_visual_get_system();
180 if (visual->depth > 8) return TRUE;
181
182 /* this initiates the standard palette as defined by GdkImlib
183 in the GNOME libraries. it ensures that all GNOME applications
184 use the same 64 colormap entries on 8-bit displays so you
185 can use several rather graphics-heavy applications at the
186 same time */
187
188 /*
189 GdkColormap *cmap = gdk_colormap_new( gdk_visual_get_system(), TRUE );
190
191 for (int i = 0; i < 64; i++)
192 {
193 GdkColor col;
194 col.red = g_palette[i*3 + 0] << 8;
195 col.green = g_palette[i*3 + 1] << 8;
196 col.blue = g_palette[i*3 + 2] << 8;
197 col.pixel = 0;
198
199 gdk_color_alloc( cmap, &col );
200 }
201
202 gtk_widget_set_default_colormap( cmap );
203 */
204
205 /* initialize color cube for 8-bit color reduction dithering */
206
207 GdkColormap *cmap = gtk_widget_get_default_colormap();
208
209 m_colorCube = (unsigned char*)malloc(32 * 32 * 32);
210
211 for (int r = 0; r < 32; r++)
212 {
213 for (int g = 0; g < 32; g++)
214 {
215 for (int b = 0; b < 32; b++)
216 {
217 int rr = (r << 3) | (r >> 2);
218 int gg = (g << 3) | (g >> 2);
219 int bb = (b << 3) | (b >> 2);
220
221 GdkColor *colors = cmap->colors;
222 int max = 3 * (65536);
223 int index = -1;
224
225 for (int i = 0; i < cmap->size; i++)
226 {
227 int rdiff = ((rr << 8) - colors[i].red);
228 int gdiff = ((gg << 8)- colors[i].green);
229 int bdiff = ((bb << 8)- colors[i].blue);
230 int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
231 if (sum < max) { index = i; max = sum; }
232 }
233
234 m_colorCube[ (r*1024) + (g*32) + b ] = index;
235 }
236 }
237 }
238
239 return TRUE;
240 }
241
242 bool wxApp::OnInitGui(void)
243 {
244 m_idleTag = gtk_idle_add( wxapp_idle_callback, NULL );
245
246 return TRUE;
247 }
248
249 bool wxApp::OnInit(void)
250 {
251 return TRUE;
252 }
253
254 int wxApp::OnRun(void)
255 {
256 return MainLoop();
257 }
258
259 bool wxApp::ProcessIdle(void)
260 {
261 wxIdleEvent event;
262 event.SetEventObject( this );
263 ProcessEvent( event );
264
265 return event.MoreRequested();
266 }
267
268 void wxApp::OnIdle( wxIdleEvent &event )
269 {
270 static bool inOnIdle = FALSE;
271
272 /* Avoid recursion (via ProcessEvent default case) */
273 if (inOnIdle)
274 return;
275
276 inOnIdle = TRUE;
277
278 /* 'Garbage' collection of windows deleted with Close(). */
279 DeletePendingObjects();
280
281 /* flush the logged messages if any */
282 wxLog *log = wxLog::GetActiveTarget();
283 if (log != NULL && log->HasPendingMessages())
284 log->Flush();
285
286 /* Send OnIdle events to all windows */
287 bool needMore = SendIdleEvents();
288
289 if (needMore)
290 event.RequestMore(TRUE);
291
292 inOnIdle = FALSE;
293 }
294
295 bool wxApp::SendIdleEvents(void)
296 {
297 bool needMore = FALSE;
298
299 wxNode* node = wxTopLevelWindows.First();
300 while (node)
301 {
302 wxWindow* win = (wxWindow*) node->Data();
303 if (SendIdleEvents(win))
304 needMore = TRUE;
305 node = node->Next();
306 }
307 return needMore;
308 }
309
310 bool wxApp::SendIdleEvents( wxWindow* win )
311 {
312 bool needMore = FALSE;
313
314 wxIdleEvent event;
315 event.SetEventObject(win);
316 win->ProcessEvent(event);
317
318 if (event.MoreRequested())
319 needMore = TRUE;
320
321 wxNode* node = win->GetChildren().First();
322 while (node)
323 {
324 wxWindow* win = (wxWindow*) node->Data();
325 if (SendIdleEvents(win))
326 needMore = TRUE;
327
328 node = node->Next();
329 }
330 return needMore ;
331 }
332
333 int wxApp::OnExit(void)
334 {
335 return 0;
336 }
337
338 int wxApp::MainLoop(void)
339 {
340 gtk_main();
341 return 0;
342 }
343
344 void wxApp::ExitMainLoop(void)
345 {
346 gtk_main_quit();
347 }
348
349 bool wxApp::Initialized(void)
350 {
351 return m_initialized;
352 }
353
354 bool wxApp::Pending(void)
355 {
356 return FALSE;
357 }
358
359 void wxApp::Dispatch(void)
360 {
361 }
362
363 void wxApp::DeletePendingObjects(void)
364 {
365 wxNode *node = wxPendingDelete.First();
366 while (node)
367 {
368 wxObject *obj = (wxObject *)node->Data();
369
370 delete obj;
371
372 if (wxPendingDelete.Member(obj))
373 delete node;
374
375 node = wxPendingDelete.First();
376 }
377 }
378
379 wxWindow *wxApp::GetTopWindow(void)
380 {
381 if (m_topWindow) return m_topWindow;
382 wxNode *node = wxTopLevelWindows.First();
383 if (!node) return (wxWindow *) NULL;
384 return (wxWindow*)node->Data();
385 }
386
387 void wxApp::SetTopWindow( wxWindow *win )
388 {
389 m_topWindow = win;
390 }
391
392 void wxApp::CommonInit(void)
393 {
394 wxSystemSettings::Init();
395
396 wxTheFontNameDirectory = new wxFontNameDirectory;
397 wxTheFontNameDirectory->Initialize();
398
399 wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
400 wxTheColourDatabase->Initialize();
401
402 wxInitializeStockLists();
403 wxInitializeStockObjects();
404
405 #if wxUSE_WX_RESOURCES
406 wxTheResourceCache = new wxResourceCache(wxKEY_STRING);
407
408 wxInitializeResourceSystem();
409 #endif
410
411 wxImage::InitStandardHandlers();
412
413 // g_globalCursor = new wxCursor;
414 }
415
416 void wxApp::CommonCleanUp(void)
417 {
418 if (wxTheColourDatabase) delete wxTheColourDatabase;
419 wxTheColourDatabase = (wxColourDatabase*) NULL;
420
421 if (wxTheFontNameDirectory) delete wxTheFontNameDirectory;
422 wxTheFontNameDirectory = (wxFontNameDirectory*) NULL;
423
424 wxDeleteStockObjects();
425
426 #if wxUSE_WX_RESOURCES
427 wxFlushResources();
428
429 if (wxTheResourceCache) delete wxTheResourceCache;
430 wxTheResourceCache = (wxResourceCache*) NULL;
431
432 wxCleanUpResourceSystem();
433 #endif
434
435 wxDeleteStockLists();
436
437 wxImage::CleanUpHandlers();
438
439 wxSystemSettings::Done();
440 }
441
442 wxLog *wxApp::CreateLogTarget()
443 {
444 return new wxLogGui;
445 }
446
447 //-----------------------------------------------------------------------------
448 // wxEntry
449 //-----------------------------------------------------------------------------
450
451 int wxEntry( int argc, char *argv[] )
452 {
453 wxBuffer = new char[BUFSIZ + 512];
454
455 wxClassInfo::InitializeClasses();
456
457
458 if (!wxTheApp)
459 {
460 if (!wxApp::GetInitializerFunction())
461 {
462 printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" );
463 return 0;
464 }
465
466 wxAppInitializerFunction app_ini = wxApp::GetInitializerFunction();
467
468 wxObject *test_app = app_ini();
469
470 wxTheApp = (wxApp*) test_app;
471 }
472
473 if (!wxTheApp)
474 {
475 printf( "wxWindows error: wxTheApp == NULL\n" );
476 return 0;
477 }
478
479 wxTheApp->argc = argc;
480 wxTheApp->argv = argv;
481
482 char name[200];
483 strcpy( name, argv[0] );
484 strcpy( name, wxFileNameFromPath(name) );
485 wxStripExtension( name );
486 wxTheApp->SetAppName( name );
487
488 gtk_set_locale();
489
490 gtk_init( &argc, &argv );
491
492 if (!wxTheApp->InitVisual()) return 0;
493
494 wxApp::CommonInit();
495
496 if (!wxTheApp->OnInitGui()) return 0;
497
498 wxModule::RegisterModules();
499 if (!wxModule::InitializeModules()) return FALSE;
500
501 // Here frames insert themselves automatically
502 // into wxTopLevelWindows by getting created
503 // in OnInit().
504
505 if (!wxTheApp->OnInit()) return 0;
506
507 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
508
509 int retValue = 0;
510
511 if (wxTheApp->Initialized()) retValue = wxTheApp->OnRun();
512
513 wxTheApp->DeletePendingObjects();
514
515 wxTheApp->OnExit();
516
517 wxModule::CleanUpModules();
518
519 wxApp::CommonCleanUp();
520
521 delete wxTheApp;
522 wxTheApp = (wxApp*) NULL;
523
524 wxClassInfo::CleanUpClasses();
525
526 delete[] wxBuffer;
527
528 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
529
530 if (wxDebugContext::CountObjectsLeft() > 0)
531 {
532 wxLogDebug("There were memory leaks.\n");
533 wxDebugContext::Dump();
534 wxDebugContext::PrintStatistics();
535 }
536
537 #endif
538
539 wxLog *oldLog = wxLog::SetActiveTarget( (wxLog*) NULL );
540 if (oldLog) delete oldLog;
541
542 return retValue;
543 }
544