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