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