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