]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/frame.cpp
fixed KeySym handling ((keysym & 0xF000) != 0 instead of keysym < 0xFF to determine...
[wxWidgets.git] / src / gtk1 / frame.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: frame.cpp
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
01111366 6// Copyright: (c) 1998 Robert Roebling
19717c50 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
7c0ea335
VZ
10// ============================================================================
11// declarations
12// ============================================================================
13
14// ----------------------------------------------------------------------------
15// headers
16// ----------------------------------------------------------------------------
17
c801d85f 18#ifdef __GNUG__
fe4e9e6c 19 #pragma implementation "frame.h"
c801d85f
KB
20#endif
21
22#include "wx/frame.h"
23#include "wx/dialog.h"
24#include "wx/control.h"
25#include "wx/app.h"
cf4219e7 26#include "wx/menu.h"
dcf924a3 27#if wxUSE_TOOLBAR
7c0ea335 28 #include "wx/toolbar.h"
dcf924a3
RR
29#endif
30#if wxUSE_STATUSBAR
7c0ea335 31 #include "wx/statusbr.h"
dcf924a3 32#endif
362c6693 33#include "wx/dcclient.h"
83624f79 34
55703c91
RR
35#include <glib.h>
36#include <gdk/gdk.h>
37#include <gtk/gtk.h>
38#include <gdk/gdkkeysyms.h>
39#include <gdk/gdkx.h>
40
c801d85f
KB
41#include "wx/gtk/win_gtk.h"
42
7c0ea335 43// ----------------------------------------------------------------------------
2f2aa628 44// constants
7c0ea335 45// ----------------------------------------------------------------------------
2f2aa628 46
907789a0 47const int wxMENU_HEIGHT = 27;
c67daf87 48const int wxSTATUS_HEIGHT = 25;
41ca191f 49const int wxPLACE_HOLDER = 0;
c801d85f 50
7c0ea335 51// ----------------------------------------------------------------------------
acfd422a 52// idle system
7c0ea335 53// ----------------------------------------------------------------------------
acfd422a
RR
54
55extern void wxapp_install_idle_handler();
56extern bool g_isIdle;
2d68e1b4 57extern int g_openDialogs;
acfd422a 58
7c0ea335
VZ
59// ----------------------------------------------------------------------------
60// event tables
61// ----------------------------------------------------------------------------
62
63IMPLEMENT_DYNAMIC_CLASS(wxFrame,wxWindow)
64
65// ----------------------------------------------------------------------------
2f2aa628 66// data
7c0ea335 67// ----------------------------------------------------------------------------
2f2aa628 68
c801d85f
KB
69extern wxList wxPendingDelete;
70
7c0ea335 71// ----------------------------------------------------------------------------
2e563988 72// debug
7c0ea335 73// ----------------------------------------------------------------------------
2e563988
RR
74
75#ifdef __WXDEBUG__
76
77extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window );
78
79#endif
80
7c0ea335
VZ
81// ============================================================================
82// implementation
83// ============================================================================
84
85// ----------------------------------------------------------------------------
86// GTK callbacks
87// ----------------------------------------------------------------------------
88
69ffe1d2
RR
89//-----------------------------------------------------------------------------
90// "focus" from m_window
91//-----------------------------------------------------------------------------
92
93static gint gtk_frame_focus_callback( GtkWidget *widget, GtkDirectionType WXUNUSED(d), wxWindow *WXUNUSED(win) )
94{
95 if (g_isIdle)
96 wxapp_install_idle_handler();
97
98 // This disables GTK's tab traversal
99 gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus" );
100 return TRUE;
101}
102
c801d85f 103//-----------------------------------------------------------------------------
2f2aa628 104// "size_allocate"
c801d85f 105//-----------------------------------------------------------------------------
c801d85f 106
2f2aa628 107static void gtk_frame_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxFrame *win )
ed7a557b 108{
88ac883a 109 if (g_isIdle)
121a3581 110 wxapp_install_idle_handler();
acfd422a 111
54517652
RR
112 if (!win->m_hasVMT)
113 return;
8bbe427f 114
121a3581
RR
115 if ((win->m_width != alloc->width) || (win->m_height != alloc->height))
116 {
54517652
RR
117/*
118 wxPrintf( "OnSize from " );
119 if (win->GetClassInfo() && win->GetClassInfo()->GetClassName())
120 wxPrintf( win->GetClassInfo()->GetClassName() );
121 wxPrintf( " %d %d %d %d\n", (int)alloc->x,
122 (int)alloc->y,
123 (int)alloc->width,
124 (int)alloc->height );
125*/
7beba2fc 126
121a3581
RR
127 win->m_width = alloc->width;
128 win->m_height = alloc->height;
8cb9f0d0 129 win->m_queuedFullRedraw = TRUE;
5b8a521e 130 win->GtkUpdateSize();
121a3581 131 }
362c6693 132}
c801d85f
KB
133
134//-----------------------------------------------------------------------------
2f2aa628
RR
135// "delete_event"
136//-----------------------------------------------------------------------------
c801d85f 137
2f2aa628 138static gint gtk_frame_delete_callback( GtkWidget *WXUNUSED(widget), GdkEvent *WXUNUSED(event), wxFrame *win )
ed7a557b 139{
88ac883a 140 if (g_isIdle)
121a3581 141 wxapp_install_idle_handler();
ed7a557b 142
a56fcaaf 143 if ((g_openDialogs == 0) && (win->IsEnabled()))
2d68e1b4 144 win->Close();
c801d85f 145
fb1585ae 146 return TRUE;
362c6693 147}
c801d85f 148
16bcc879
RR
149//-----------------------------------------------------------------------------
150// "child_attached" of menu bar
151//-----------------------------------------------------------------------------
152
153static void gtk_menu_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
154{
a2053b27 155 if (!win->m_hasVMT) return;
88ac883a 156
16bcc879 157 win->m_menuBarDetached = FALSE;
5b8a521e 158 win->GtkUpdateSize();
16bcc879
RR
159}
160
161//-----------------------------------------------------------------------------
162// "child_detached" of menu bar
163//-----------------------------------------------------------------------------
164
165static void gtk_menu_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
166{
a2053b27 167 if (!win->m_hasVMT) return;
88ac883a 168
16bcc879 169 win->m_menuBarDetached = TRUE;
5b8a521e 170 win->GtkUpdateSize();
16bcc879
RR
171}
172
88ac883a 173#if wxUSE_TOOLBAR
16bcc879
RR
174//-----------------------------------------------------------------------------
175// "child_attached" of tool bar
176//-----------------------------------------------------------------------------
177
178static void gtk_toolbar_attached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
179{
a2053b27 180 if (!win->m_hasVMT) return;
88ac883a 181
16bcc879 182 win->m_toolBarDetached = FALSE;
88ac883a 183
5b8a521e 184 win->GtkUpdateSize();
16bcc879
RR
185}
186
187//-----------------------------------------------------------------------------
188// "child_detached" of tool bar
189//-----------------------------------------------------------------------------
190
5e0201ea 191static void gtk_toolbar_detached_callback( GtkWidget *WXUNUSED(widget), GtkWidget *WXUNUSED(child), wxFrame *win )
16bcc879 192{
88ac883a 193 if (g_isIdle)
801aa178 194 wxapp_install_idle_handler();
acfd422a 195
a2053b27 196 if (!win->m_hasVMT) return;
88ac883a 197
16bcc879 198 win->m_toolBarDetached = TRUE;
5b8a521e 199 win->GtkUpdateSize();
16bcc879 200}
88ac883a 201#endif // wxUSE_TOOLBAR
16bcc879 202
47908e25 203//-----------------------------------------------------------------------------
2f2aa628
RR
204// "configure_event"
205//-----------------------------------------------------------------------------
47908e25 206
7beba2fc 207static gint
2d68e1b4 208#if (GTK_MINOR_VERSION > 0)
c693edf3
RR
209gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxFrame *win )
210#else
211gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *event, wxFrame *win )
212#endif
47908e25 213{
7beba2fc 214 if (g_isIdle)
121a3581 215 wxapp_install_idle_handler();
acfd422a 216
7c0ea335 217 if (!win->m_hasVMT)
2d68e1b4 218 return FALSE;
81855216 219
2d68e1b4 220#if (GTK_MINOR_VERSION > 0)
dfc3d7e0
RR
221 int x = 0;
222 int y = 0;
223 gdk_window_get_root_origin( win->m_widget->window, &x, &y );
dfc3d7e0
RR
224 win->m_x = x;
225 win->m_y = y;
c693edf3
RR
226#else
227 win->m_x = event->x;
228 win->m_y = event->y;
229#endif
8bbe427f 230
a2053b27 231 wxMoveEvent mevent( wxPoint(win->m_x,win->m_y), win->GetId() );
36b3b54a
RR
232 mevent.SetEventObject( win );
233 win->GetEventHandler()->ProcessEvent( mevent );
234
fb1585ae 235 return FALSE;
362c6693 236}
47908e25 237
2b07d713
RR
238//-----------------------------------------------------------------------------
239// "realize" from m_widget
240//-----------------------------------------------------------------------------
241
88ac883a 242/* we cannot MWM hints and icons before the widget has been realized,
2b07d713
RR
243 so we do this directly after realization */
244
88ac883a 245static gint
2e5c594e 246gtk_frame_realized_callback( GtkWidget *widget, wxFrame *win )
2b07d713 247{
88ac883a 248 if (g_isIdle)
121a3581 249 wxapp_install_idle_handler();
acfd422a 250
2e5c594e
RR
251 /* I haven't been able to set the position of
252 the dialog before it is shown, so I set the
253 position in "realize" */
8487f887 254 gtk_widget_set_uposition( widget, win->m_x, win->m_y );
2e5c594e 255
80629c8b 256 if ((win->m_miniEdge > 0) || (win->HasFlag(wxSIMPLE_BORDER)))
15b24b14 257 {
80629c8b 258 /* This is a mini-frame or a borderless frame. */
81855216
RR
259 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)0 );
260 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)0 );
15b24b14 261 }
81855216 262 else
aa64626e 263 {
81855216
RR
264 /* All this is for Motif Window Manager "hints" and is supposed to be
265 recognized by other WM as well. Not tested. */
266 long decor = (long) GDK_DECOR_BORDER;
267 long func = (long) GDK_FUNC_MOVE;
268
269 if ((win->GetWindowStyle() & wxCAPTION) != 0)
270 decor |= GDK_DECOR_TITLE;
271 if ((win->GetWindowStyle() & wxSYSTEM_MENU) != 0)
272 {
273 decor |= GDK_DECOR_MENU;
274 func |= GDK_FUNC_CLOSE;
275 }
276 if ((win->GetWindowStyle() & wxMINIMIZE_BOX) != 0)
277 {
278 func |= GDK_FUNC_MINIMIZE;
279 decor |= GDK_DECOR_MINIMIZE;
280 }
281 if ((win->GetWindowStyle() & wxMAXIMIZE_BOX) != 0)
282 {
283 func |= GDK_FUNC_MAXIMIZE;
284 decor |= GDK_DECOR_MAXIMIZE;
285 }
286 if ((win->GetWindowStyle() & wxRESIZE_BORDER) != 0)
287 {
288 func |= GDK_FUNC_RESIZE;
289 decor |= GDK_DECOR_RESIZEH;
290 }
291
292 gdk_window_set_decorations( win->m_widget->window, (GdkWMDecoration)decor);
293 gdk_window_set_functions( win->m_widget->window, (GdkWMFunction)func);
aa64626e
KB
294 }
295
2b07d713 296 /* GTK's shrinking/growing policy */
f03fc89f 297 if ((win->GetWindowStyle() & wxRESIZE_BORDER) == 0)
a2053b27 298 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 0, 0, 1);
2b07d713 299 else
a2053b27 300 gtk_window_set_policy(GTK_WINDOW(win->m_widget), 1, 1, 1);
88ac883a 301
738f9e5a 302 /* set size hints */
8487f887 303 gint flag = 0; // GDK_HINT_POS;
738f9e5a
RR
304 if ((win->GetMinWidth() != -1) || (win->GetMinHeight() != -1)) flag |= GDK_HINT_MIN_SIZE;
305 if ((win->GetMaxWidth() != -1) || (win->GetMaxHeight() != -1)) flag |= GDK_HINT_MAX_SIZE;
306 if (flag)
307 {
7beba2fc
VZ
308 gdk_window_set_hints( win->m_widget->window,
309 win->m_x, win->m_y,
310 win->GetMinWidth(), win->GetMinHeight(),
311 win->GetMaxWidth(), win->GetMaxHeight(),
312 flag );
738f9e5a 313 }
7beba2fc 314
58dea4b0 315 /* reset the icon */
7c0ea335
VZ
316 wxIcon iconOld = win->GetIcon();
317 if ( iconOld != wxNullIcon )
58dea4b0 318 {
7c0ea335
VZ
319 wxIcon icon( iconOld );
320 win->SetIcon( wxNullIcon );
f03fc89f 321 win->SetIcon( icon );
58dea4b0 322 }
88ac883a 323
2e563988
RR
324 /* we set the focus to the child that accepts the focus. this
325 doesn't really have to be done in "realize" but why not? */
f03fc89f 326 wxWindowList::Node *node = win->GetChildren().GetFirst();
2e563988
RR
327 while (node)
328 {
f03fc89f
VZ
329 wxWindow *child = node->GetData();
330 if (child->AcceptsFocus())
331 {
332 child->SetFocus();
333 break;
334 }
88ac883a 335
f03fc89f 336 node = node->GetNext();
2e563988 337 }
88ac883a 338
227e5e99
RR
339 return FALSE;
340}
88ac883a 341
7c0ea335
VZ
342// ----------------------------------------------------------------------------
343// wxFrame itself
344// ----------------------------------------------------------------------------
345
f362b96d
RR
346//-----------------------------------------------------------------------------
347// InsertChild for wxFrame
348//-----------------------------------------------------------------------------
349
350/* Callback for wxFrame. This very strange beast has to be used because
351 * C++ has no virtual methods in a constructor. We have to emulate a
352 * virtual function here as wxWindows requires different ways to insert
353 * a child in container classes. */
354
6bc8a1c8 355static void wxInsertChildInFrame( wxFrame* parent, wxWindow* child )
f362b96d 356{
5fd11f09 357 wxASSERT( GTK_IS_WIDGET(child->m_widget) );
7beba2fc 358
6bc8a1c8 359 if (!parent->m_insertInClientArea)
f362b96d
RR
360 {
361 /* these are outside the client area */
f03fc89f 362 wxFrame* frame = (wxFrame*) parent;
da048e3d 363 gtk_pizza_put( GTK_PIZZA(frame->m_mainWidget),
a2053b27
RR
364 GTK_WIDGET(child->m_widget),
365 child->m_x,
366 child->m_y,
367 child->m_width,
368 child->m_height );
88ac883a 369
caf51f95 370#if wxUSE_TOOLBAR_NATIVE
f03fc89f
VZ
371 /* we connect to these events for recalculating the client area
372 space when the toolbar is floating */
373 if (wxIS_KIND_OF(child,wxToolBar))
374 {
375 wxToolBar *toolBar = (wxToolBar*) child;
376 if (toolBar->GetWindowStyle() & wxTB_DOCKABLE)
377 {
a2053b27 378 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_attached",
41ca191f 379 GTK_SIGNAL_FUNC(gtk_toolbar_attached_callback), (gpointer)parent );
88ac883a 380
a2053b27 381 gtk_signal_connect( GTK_OBJECT(toolBar->m_widget), "child_detached",
41ca191f 382 GTK_SIGNAL_FUNC(gtk_toolbar_detached_callback), (gpointer)parent );
f03fc89f
VZ
383 }
384 }
88ac883a 385#endif // wxUSE_TOOLBAR
f362b96d
RR
386 }
387 else
388 {
389 /* these are inside the client area */
da048e3d 390 gtk_pizza_put( GTK_PIZZA(parent->m_wxwindow),
a2053b27
RR
391 GTK_WIDGET(child->m_widget),
392 child->m_x,
393 child->m_y,
394 child->m_width,
395 child->m_height );
f362b96d
RR
396 }
397
f362b96d 398 /* resize on OnInternalIdle */
5b8a521e 399 parent->GtkUpdateSize();
f362b96d
RR
400}
401
7c0ea335
VZ
402// ----------------------------------------------------------------------------
403// wxFrame creation
404// ----------------------------------------------------------------------------
c801d85f 405
ddb6bc71 406void wxFrame::Init()
c801d85f 407{
fb1585ae 408 m_sizeSet = FALSE;
b2b3ccc5
RR
409 m_miniEdge = 0;
410 m_miniTitle = 0;
ab2b3dd4 411 m_mainWidget = (GtkWidget*) NULL;
16bcc879
RR
412 m_menuBarDetached = FALSE;
413 m_toolBarDetached = FALSE;
6bc8a1c8 414 m_insertInClientArea = TRUE;
8cb9f0d0 415 m_isFrame = FALSE;
362c6693 416}
c801d85f 417
7c0ea335
VZ
418bool wxFrame::Create( wxWindow *parent,
419 wxWindowID id,
420 const wxString &title,
421 const wxPoint &pos,
422 const wxSize &size,
423 long style,
424 const wxString &name )
c801d85f 425{
a802c3a1 426 wxTopLevelWindows.Append( this );
8bbe427f 427
fb1585ae 428 m_needParent = FALSE;
8cb9f0d0 429 m_isFrame = TRUE;
ed7a557b 430
4dcaf11a
RR
431 if (!PreCreation( parent, pos, size ) ||
432 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ))
433 {
223d09f6 434 wxFAIL_MSG( wxT("wxFrame creation failed") );
7beba2fc 435 return FALSE;
4dcaf11a 436 }
c801d85f 437
fb1585ae 438 m_title = title;
88ac883a 439
6bc8a1c8 440 m_insertCallback = (wxInsertChildFunction) wxInsertChildInFrame;
ed7a557b 441
faecf4cb 442 GtkWindowType win_type = GTK_WINDOW_TOPLEVEL;
8bbe427f 443
fb1585ae 444 m_widget = gtk_window_new( win_type );
88ac883a 445
80629c8b
RR
446 if ((m_parent) && (HasFlag(wxFRAME_FLOAT_ON_PARENT)) && (GTK_IS_WINDOW(m_parent->m_widget)))
447 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
448
de1c750f
RR
449 if (!name.IsEmpty())
450 gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() );
8bbe427f 451
2e563988 452#ifdef __WXDEBUG__
223d09f6 453 debug_focus_in( m_widget, wxT("wxFrame::m_widget"), name );
2e563988
RR
454#endif
455
ed9b9841 456 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
fb1585ae 457 GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS );
ed7a557b 458
fb1585ae
RR
459 gtk_signal_connect( GTK_OBJECT(m_widget), "delete_event",
460 GTK_SIGNAL_FUNC(gtk_frame_delete_callback), (gpointer)this );
ed7a557b 461
f362b96d 462 /* m_mainWidget holds the toolbar, the menubar and the client area */
da048e3d 463 m_mainWidget = gtk_pizza_new();
f362b96d
RR
464 gtk_widget_show( m_mainWidget );
465 GTK_WIDGET_UNSET_FLAGS( m_mainWidget, GTK_CAN_FOCUS );
466 gtk_container_add( GTK_CONTAINER(m_widget), m_mainWidget );
88ac883a 467
2e563988 468#ifdef __WXDEBUG__
223d09f6 469 debug_focus_in( m_mainWidget, wxT("wxFrame::m_mainWidget"), name );
2e563988
RR
470#endif
471
f362b96d 472 /* m_wxwindow only represents the client area without toolbar and menubar */
da048e3d 473 m_wxwindow = gtk_pizza_new();
fb1585ae 474 gtk_widget_show( m_wxwindow );
f362b96d 475 gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow );
88ac883a 476
2e563988 477#ifdef __WXDEBUG__
223d09f6 478 debug_focus_in( m_wxwindow, wxT("wxFrame::m_wxwindow"), name );
2e563988
RR
479#endif
480
481 /* we donm't allow the frame to get the focus as otherwise
482 the frame will grabit at arbitrary fcous changes. */
483 GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS );
ed7a557b 484
de8113d9
RR
485 if (m_parent) m_parent->AddChild( this );
486
54517652
RR
487 /* the user resized the frame by dragging etc. */
488 gtk_signal_connect( GTK_OBJECT(m_widget), "size_allocate",
489 GTK_SIGNAL_FUNC(gtk_frame_size_callback), (gpointer)this );
490
de8113d9
RR
491 PostCreation();
492
58dea4b0 493 /* we cannot set MWM hints and icons before the widget has
2b07d713
RR
494 been realized, so we do this directly after realization */
495 gtk_signal_connect( GTK_OBJECT(m_widget), "realize",
f03fc89f 496 GTK_SIGNAL_FUNC(gtk_frame_realized_callback), (gpointer) this );
88ac883a 497
ab2b3dd4 498 /* the only way to get the window size is to connect to this event */
fb1585ae
RR
499 gtk_signal_connect( GTK_OBJECT(m_widget), "configure_event",
500 GTK_SIGNAL_FUNC(gtk_frame_configure_callback), (gpointer)this );
8bbe427f 501
69ffe1d2
RR
502 /* disable native tab traversal */
503 gtk_signal_connect( GTK_OBJECT(m_widget), "focus",
504 GTK_SIGNAL_FUNC(gtk_frame_focus_callback), (gpointer)this );
505
fb1585ae 506 return TRUE;
362c6693 507}
c801d85f 508
19717c50 509wxFrame::~wxFrame()
c801d85f 510{
31c6b4fc 511 m_isBeingDeleted = TRUE;
88ac883a 512
7c0ea335 513 DeleteAllBars();
ed7a557b 514
fb1585ae 515 wxTopLevelWindows.DeleteObject( this );
2b854a32 516
0d2a2b60 517 if (wxTheApp->GetTopWindow() == this)
0d2a2b60 518 wxTheApp->SetTopWindow( (wxWindow*) NULL );
2b854a32 519
f59d80ca
RR
520 if ((wxTopLevelWindows.Number() == 0) &&
521 (wxTheApp->GetExitOnFrameDelete()))
522 {
0d2a2b60 523 wxTheApp->ExitMainLoop();
f59d80ca 524 }
362c6693 525}
ed7a557b 526
7c0ea335
VZ
527// ----------------------------------------------------------------------------
528// overridden wxWindow methods
529// ----------------------------------------------------------------------------
530
debe6624 531bool wxFrame::Show( bool show )
c801d85f 532{
223d09f6 533 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 534
35178437 535 if (show && !m_sizeSet)
fb1585ae 536 {
e27ce4e9
RR
537 /* by calling GtkOnSize here, we don't have to call
538 either after showing the frame, which would entail
f362b96d 539 much ugly flicker or from within the size_allocate
e27ce4e9 540 handler, because GTK 1.1.X forbids that. */
8bbe427f 541
35178437 542 GtkOnSize( m_x, m_y, m_width, m_height );
fb1585ae 543 }
8bbe427f 544
fb1585ae 545 return wxWindow::Show( show );
362c6693 546}
c801d85f 547
23efdd02
RR
548void wxFrame::DoMoveWindow(int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
549{
550 wxFAIL_MSG( wxT("DoMoveWindow called for wxFrame") );
551}
552
bfc6fde4 553void wxFrame::DoSetSize( int x, int y, int width, int height, int sizeFlags )
903f689b 554{
223d09f6 555 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 556
ab2b3dd4 557 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 558 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 559
ab2b3dd4 560 /* avoid recursions */
7c0ea335
VZ
561 if (m_resizing)
562 return;
fb1585ae
RR
563 m_resizing = TRUE;
564
565 int old_x = m_x;
566 int old_y = m_y;
7beba2fc 567
fb1585ae
RR
568 int old_width = m_width;
569 int old_height = m_height;
8bbe427f 570
85ad5eb5 571 if ((sizeFlags & wxSIZE_ALLOW_MINUS_ONE) == 0)
fb1585ae
RR
572 {
573 if (x != -1) m_x = x;
574 if (y != -1) m_y = y;
575 if (width != -1) m_width = width;
576 if (height != -1) m_height = height;
577 }
578 else
579 {
580 m_x = x;
581 m_y = y;
582 m_width = width;
583 m_height = height;
584 }
585
11e1c70d 586/*
fb1585ae
RR
587 if ((sizeFlags & wxSIZE_AUTO_WIDTH) == wxSIZE_AUTO_WIDTH)
588 {
589 if (width == -1) m_width = 80;
590 }
591
592 if ((sizeFlags & wxSIZE_AUTO_HEIGHT) == wxSIZE_AUTO_HEIGHT)
593 {
594 if (height == -1) m_height = 26;
595 }
11e1c70d 596*/
8bbe427f 597
fb1585ae
RR
598 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
599 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
0c77152e
RR
600 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
601 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
fb1585ae
RR
602
603 if ((m_x != -1) || (m_y != -1))
604 {
8bbe427f 605 if ((m_x != old_x) || (m_y != old_y))
0138c2de 606 {
8487f887 607 gtk_widget_set_uposition( m_widget, m_x, m_y );
0138c2de 608 }
fb1585ae 609 }
8bbe427f 610
fb1585ae
RR
611 if ((m_width != old_width) || (m_height != old_height))
612 {
ab2b3dd4 613 /* we set the size in GtkOnSize, i.e. mostly the actual resizing is
f03fc89f
VZ
614 done either directly before the frame is shown or in idle time
615 so that different calls to SetSize() don't lead to flicker. */
de8113d9 616 m_sizeSet = FALSE;
fb1585ae 617 }
8bbe427f 618
fb1585ae 619 m_resizing = FALSE;
903f689b
RR
620}
621
f9241296 622void wxFrame::DoGetClientSize( int *width, int *height ) const
c801d85f 623{
223d09f6 624 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 625
f9241296 626 wxWindow::DoGetClientSize( width, height );
fb1585ae 627 if (height)
46dc76ba 628 {
41ca191f
RR
629 /* menu bar */
630 if (m_frameMenuBar)
f03fc89f 631 {
88ac883a 632 if (!m_menuBarDetached)
f03fc89f
VZ
633 (*height) -= wxMENU_HEIGHT;
634 else
635 (*height) -= wxPLACE_HOLDER;
636 }
88ac883a 637
dcf924a3 638#if wxUSE_STATUSBAR
f03fc89f 639 /* status bar */
fb1585ae 640 if (m_frameStatusBar) (*height) -= wxSTATUS_HEIGHT;
93fa69f8 641#endif // wxUSE_STATUSBAR
88ac883a 642
dcf924a3 643#if wxUSE_TOOLBAR
f03fc89f 644 /* tool bar */
fb1585ae
RR
645 if (m_frameToolBar)
646 {
93fa69f8 647 if (m_toolBarDetached)
f03fc89f 648 {
93fa69f8 649 *height -= wxPLACE_HOLDER;
f03fc89f
VZ
650 }
651 else
93fa69f8
VZ
652 {
653 int x, y;
654 m_frameToolBar->GetSize( &x, &y );
655 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
656 {
657 *width -= x;
658 }
659 else
660 {
661 *height -= y;
662 }
663 }
fb1585ae 664 }
93fa69f8 665#endif // wxUSE_TOOLBAR
88ac883a 666
f03fc89f 667 /* mini edge */
93fa69f8 668 *height -= m_miniEdge*2 + m_miniTitle;
b2b3ccc5
RR
669 }
670 if (width)
671 {
93fa69f8 672 *width -= m_miniEdge*2;
46dc76ba 673 }
362c6693 674}
c801d85f 675
bfc6fde4 676void wxFrame::DoSetClientSize( int width, int height )
b593568e 677{
223d09f6 678 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 679
41ca191f
RR
680 /* menu bar */
681 if (m_frameMenuBar)
f03fc89f 682 {
88ac883a 683 if (!m_menuBarDetached)
f03fc89f
VZ
684 height += wxMENU_HEIGHT;
685 else
686 height += wxPLACE_HOLDER;
687 }
88ac883a 688
dcf924a3 689#if wxUSE_STATUSBAR
f03fc89f 690 /* status bar */
41ca191f 691 if (m_frameStatusBar) height += wxSTATUS_HEIGHT;
dcf924a3 692#endif
88ac883a 693
dcf924a3 694#if wxUSE_TOOLBAR
f03fc89f 695 /* tool bar */
41ca191f
RR
696 if (m_frameToolBar)
697 {
93fa69f8 698 if (m_toolBarDetached)
f03fc89f 699 {
93fa69f8 700 height += wxPLACE_HOLDER;
f03fc89f
VZ
701 }
702 else
93fa69f8
VZ
703 {
704 int x, y;
705 m_frameToolBar->GetSize( &x, &y );
706 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
707 {
708 width += x;
709 }
710 else
711 {
712 height += y;
713 }
714 }
41ca191f 715 }
dcf924a3 716#endif
88ac883a 717
3017f78d 718 DoSetSize( -1, -1, width + m_miniEdge*2, height + m_miniEdge*2 + m_miniTitle, 0 );
362c6693 719}
b593568e 720
7c0ea335
VZ
721void wxFrame::GtkOnSize( int WXUNUSED(x), int WXUNUSED(y),
722 int width, int height )
c801d85f 723{
f5368809
RR
724 // due to a bug in gtk, x,y are always 0
725 // m_x = x;
726 // m_y = y;
727
ab2b3dd4 728 /* avoid recursions */
e52f60e6
RR
729 if (m_resizing) return;
730 m_resizing = TRUE;
8bbe427f 731
ab2b3dd4 732 /* this shouldn't happen: wxFrame, wxMDIParentFrame and wxMDIChildFrame have m_wxwindow */
223d09f6 733 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
88ac883a 734
f5368809
RR
735 m_width = width;
736 m_height = height;
7beba2fc 737
ab2b3dd4 738 /* space occupied by m_frameToolBar and m_frameMenuBar */
93fa69f8
VZ
739 int client_area_x_offset = 0,
740 client_area_y_offset = 0;
8bbe427f 741
ab2b3dd4
RR
742 /* wxMDIChildFrame derives from wxFrame but it _is_ a wxWindow as it uses
743 wxWindow::Create to create it's GTK equivalent. m_mainWidget is only
744 set in wxFrame::Create so it is used to check what kind of frame we
745 have here. if m_mainWidget is NULL it is a wxMDIChildFrame and so we
746 skip the part which handles m_frameMenuBar, m_frameToolBar and (most
747 importantly) m_mainWidget */
88ac883a 748
ab2b3dd4 749 if (m_mainWidget)
f5368809 750 {
ab2b3dd4
RR
751 /* check if size is in legal range */
752 if ((m_minWidth != -1) && (m_width < m_minWidth)) m_width = m_minWidth;
753 if ((m_minHeight != -1) && (m_height < m_minHeight)) m_height = m_minHeight;
754 if ((m_maxWidth != -1) && (m_width > m_maxWidth)) m_width = m_maxWidth;
755 if ((m_maxHeight != -1) && (m_height > m_maxHeight)) m_height = m_maxHeight;
756
757 /* I revert back to wxGTK's original behaviour. m_mainWidget holds the
758 * menubar, the toolbar and the client area, which is represented by
759 * m_wxwindow.
760 * this hurts in the eye, but I don't want to call SetSize()
761 * because I don't want to call any non-native functions here. */
88ac883a 762
ab2b3dd4
RR
763 if (m_frameMenuBar)
764 {
765 int xx = m_miniEdge;
766 int yy = m_miniEdge + m_miniTitle;
767 int ww = m_width - 2*m_miniEdge;
41ca191f 768 int hh = wxMENU_HEIGHT;
f03fc89f 769 if (m_menuBarDetached) hh = wxPLACE_HOLDER;
121a3581
RR
770 m_frameMenuBar->m_x = xx;
771 m_frameMenuBar->m_y = yy;
772 m_frameMenuBar->m_width = ww;
773 m_frameMenuBar->m_height = hh;
da048e3d 774 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 775 m_frameMenuBar->m_widget,
f03fc89f
VZ
776 xx, yy, ww, hh );
777 client_area_y_offset += hh;
ab2b3dd4 778 }
88ac883a 779
dcf924a3 780#if wxUSE_TOOLBAR
11e1c70d 781 if ((m_frameToolBar) &&
7beba2fc 782 (m_frameToolBar->m_widget->parent == m_mainWidget))
ab2b3dd4
RR
783 {
784 int xx = m_miniEdge;
785 int yy = m_miniEdge + m_miniTitle;
41ca191f 786 if (m_frameMenuBar)
f03fc89f 787 {
88ac883a
VZ
788 if (!m_menuBarDetached)
789 yy += wxMENU_HEIGHT;
790 else
f03fc89f
VZ
791 yy += wxPLACE_HOLDER;
792 }
93fa69f8 793
121a3581
RR
794 m_frameToolBar->m_x = xx;
795 m_frameToolBar->m_y = yy;
93fa69f8
VZ
796
797 /* don't change the toolbar's reported height/width */
798 int ww, hh;
799 if ( m_frameToolBar->GetWindowStyle() & wxTB_VERTICAL )
800 {
801 ww = m_toolBarDetached ? wxPLACE_HOLDER
802 : m_frameToolBar->m_width;
803 hh = m_height - 2*m_miniEdge;
804
805 client_area_x_offset += ww;
806 }
807 else
808 {
809 ww = m_width - 2*m_miniEdge;
810 hh = m_toolBarDetached ? wxPLACE_HOLDER
811 : m_frameToolBar->m_height;
812
813 client_area_y_offset += hh;
814 }
815
da048e3d 816 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 817 m_frameToolBar->m_widget,
f03fc89f 818 xx, yy, ww, hh );
ab2b3dd4 819 }
93fa69f8 820#endif // wxUSE_TOOLBAR
88ac883a 821
93fa69f8 822 int client_x = client_area_x_offset + m_miniEdge;
f03fc89f 823 int client_y = client_area_y_offset + m_miniEdge + m_miniTitle;
93fa69f8 824 int client_w = m_width - client_area_x_offset - 2*m_miniEdge;
f03fc89f 825 int client_h = m_height - client_area_y_offset- 2*m_miniEdge - m_miniTitle;
da048e3d 826 gtk_pizza_set_size( GTK_PIZZA(m_mainWidget),
88ac883a 827 m_wxwindow,
f03fc89f 828 client_x, client_y, client_w, client_h );
32a95f9f
RR
829 }
830 else
831 {
832 /* if there is no m_mainWidget between m_widget and m_wxwindow there
f03fc89f 833 is no need to set the size or position of m_wxwindow. */
f5368809 834 }
88ac883a 835
dcf924a3 836#if wxUSE_STATUSBAR
f5368809
RR
837 if (m_frameStatusBar)
838 {
b2b3ccc5 839 int xx = 0 + m_miniEdge;
f362b96d 840 int yy = m_height - wxSTATUS_HEIGHT - m_miniEdge - client_area_y_offset;
ac57418f
RR
841 int ww = m_width - 2*m_miniEdge;
842 int hh = wxSTATUS_HEIGHT;
121a3581
RR
843 m_frameStatusBar->m_x = xx;
844 m_frameStatusBar->m_y = yy;
845 m_frameStatusBar->m_width = ww;
846 m_frameStatusBar->m_height = hh;
da048e3d 847 gtk_pizza_set_size( GTK_PIZZA(m_wxwindow),
7c0ea335
VZ
848 m_frameStatusBar->m_widget,
849 xx, yy, ww, hh );
b6fa52db 850 gtk_widget_draw( m_frameStatusBar->m_widget, (GdkRectangle*) NULL );
f5368809 851 }
dcf924a3 852#endif
8bbe427f 853
de8113d9
RR
854 /* we actually set the size of a frame here and no-where else */
855 gtk_widget_set_usize( m_widget, m_width, m_height );
88ac883a 856
54517652 857 m_sizeSet = TRUE;
7beba2fc 858
54517652 859 // send size event to frame
43a18898
RR
860 wxSizeEvent event( wxSize(m_width,m_height), GetId() );
861 event.SetEventObject( this );
e52f60e6 862 GetEventHandler()->ProcessEvent( event );
8bbe427f 863
54517652 864 // send size event to status bar
5aa5e35a
RR
865 if (m_frameStatusBar)
866 {
a2053b27 867 wxSizeEvent event2( wxSize(m_frameStatusBar->m_width,m_frameStatusBar->m_height), m_frameStatusBar->GetId() );
5aa5e35a
RR
868 event2.SetEventObject( m_frameStatusBar );
869 m_frameStatusBar->GetEventHandler()->ProcessEvent( event2 );
870 }
884470b1 871
e52f60e6
RR
872 m_resizing = FALSE;
873}
874
ca26177c
RR
875void wxFrame::MakeModal( bool modal )
876{
877 if (modal)
ca26177c 878 gtk_grab_add( m_widget );
ca26177c 879 else
c25ccf85 880 gtk_grab_remove( m_widget );
ca26177c
RR
881}
882
9390a202 883void wxFrame::OnInternalIdle()
e52f60e6 884{
1b3667ab 885 if (!m_sizeSet && GTK_WIDGET_REALIZED(m_wxwindow))
54517652 886 {
e52f60e6 887 GtkOnSize( m_x, m_y, m_width, m_height );
7beba2fc
VZ
888
889 // we'll come back later
54517652
RR
890 if (g_isIdle)
891 wxapp_install_idle_handler();
7beba2fc 892 return;
54517652 893 }
88ac883a 894
082b2798 895 if (m_frameMenuBar) m_frameMenuBar->OnInternalIdle();
dcf924a3 896#if wxUSE_TOOLBAR
082b2798 897 if (m_frameToolBar) m_frameToolBar->OnInternalIdle();
dcf924a3
RR
898#endif
899#if wxUSE_STATUSBAR
082b2798 900 if (m_frameStatusBar) m_frameStatusBar->OnInternalIdle();
dcf924a3 901#endif
5e014a0c
RR
902
903 wxWindow::OnInternalIdle();
362c6693 904}
c801d85f 905
7c0ea335
VZ
906// ----------------------------------------------------------------------------
907// menu/tool/status bar stuff
908// ----------------------------------------------------------------------------
c801d85f 909
c801d85f
KB
910void wxFrame::SetMenuBar( wxMenuBar *menuBar )
911{
223d09f6
KB
912 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
913 wxASSERT_MSG( (m_wxwindow != NULL), wxT("invalid frame") );
8bbe427f 914
186baeb2
RR
915 if (menuBar == m_frameMenuBar)
916 return;
917
918 if (m_frameMenuBar)
919 {
920 m_frameMenuBar->UnsetInvokingWindow( this );
921
922 if (m_frameMenuBar->GetWindowStyle() & wxMB_DOCKABLE)
923 {
924 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
925 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
926
927 gtk_signal_disconnect_by_func( GTK_OBJECT(m_frameMenuBar->m_widget),
928 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
929 }
930
931 gtk_container_remove( GTK_CONTAINER(m_mainWidget), m_frameMenuBar->m_widget );
932 gtk_widget_ref( m_frameMenuBar->m_widget );
933 gtk_widget_unparent( m_frameMenuBar->m_widget );
934 }
935
f5368809 936 m_frameMenuBar = menuBar;
8bbe427f 937
f5368809 938 if (m_frameMenuBar)
30dea054 939 {
5bd9e519 940 m_frameMenuBar->SetInvokingWindow( this );
8bbe427f 941
186baeb2
RR
942 m_frameMenuBar->SetParent(this);
943 gtk_pizza_put( GTK_PIZZA(m_mainWidget),
88ac883a
VZ
944 m_frameMenuBar->m_widget,
945 m_frameMenuBar->m_x,
a2053b27
RR
946 m_frameMenuBar->m_y,
947 m_frameMenuBar->m_width,
948 m_frameMenuBar->m_height );
88ac883a 949
186baeb2
RR
950 if (menuBar->GetWindowStyle() & wxMB_DOCKABLE)
951 {
952 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_attached",
953 GTK_SIGNAL_FUNC(gtk_menu_attached_callback), (gpointer)this );
7beba2fc 954
186baeb2
RR
955 gtk_signal_connect( GTK_OBJECT(menuBar->m_widget), "child_detached",
956 GTK_SIGNAL_FUNC(gtk_menu_detached_callback), (gpointer)this );
f5368809 957 }
186baeb2
RR
958
959 m_frameMenuBar->Show( TRUE );
716b7364 960 }
8bbe427f 961
1e133b7d 962 /* resize window in OnInternalIdle */
5b077d48 963 m_sizeSet = FALSE;
362c6693 964}
c801d85f 965
88ac883a 966#if wxUSE_TOOLBAR
6bc8a1c8 967wxToolBar* wxFrame::CreateToolBar( long style, wxWindowID id, const wxString& name )
46dc76ba 968{
223d09f6 969 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 970
6bc8a1c8 971 m_insertInClientArea = FALSE;
88ac883a 972
7c0ea335 973 m_frameToolBar = wxFrameBase::CreateToolBar( style, id, name );
8bbe427f 974
7c0ea335
VZ
975 if (m_frameToolBar)
976 GetChildren().DeleteObject( m_frameToolBar );
88ac883a 977
6bc8a1c8 978 m_insertInClientArea = TRUE;
8bbe427f 979
5b077d48 980 m_sizeSet = FALSE;
8bbe427f 981
f5368809 982 return m_frameToolBar;
362c6693 983}
46dc76ba 984
7beba2fc
VZ
985void wxFrame::SetToolBar(wxToolBar *toolbar)
986{
7c0ea335
VZ
987 wxFrameBase::SetToolBar(toolbar);
988
307f16e8
RR
989 if (m_frameToolBar)
990 {
991 /* insert into toolbar area if not already there */
3017f78d
RR
992 if ((m_frameToolBar->m_widget->parent) &&
993 (m_frameToolBar->m_widget->parent != m_mainWidget))
307f16e8 994 {
3017f78d 995 GetChildren().DeleteObject( m_frameToolBar );
7beba2fc
VZ
996
997 gtk_widget_reparent( m_frameToolBar->m_widget, m_mainWidget );
5b8a521e 998 GtkUpdateSize();
7beba2fc 999 }
307f16e8
RR
1000 }
1001}
1002
88ac883a 1003#endif // wxUSE_TOOLBAR
46dc76ba 1004
88ac883a 1005#if wxUSE_STATUSBAR
8bbe427f 1006
7c0ea335
VZ
1007wxStatusBar* wxFrame::CreateStatusBar(int number,
1008 long style,
1009 wxWindowID id,
1010 const wxString& name)
c801d85f 1011{
223d09f6 1012 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1013
7c0ea335
VZ
1014 // because it will change when toolbar is added
1015 m_sizeSet = FALSE;
c801d85f 1016
7c0ea335 1017 return wxFrameBase::CreateStatusBar( number, style, id, name );
362c6693
RR
1018}
1019
8febdd39
RR
1020void wxFrame::PositionStatusBar()
1021{
1022 if ( !m_frameStatusBar )
1023 return;
1024
1025 m_sizeSet = FALSE;
1026}
88ac883a 1027#endif // wxUSE_STATUSBAR
c801d85f 1028
7c0ea335
VZ
1029// ----------------------------------------------------------------------------
1030// frame title/icon
1031// ----------------------------------------------------------------------------
c801d85f 1032
c801d85f
KB
1033void wxFrame::SetTitle( const wxString &title )
1034{
223d09f6 1035 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1036
f5368809 1037 m_title = title;
ed9b9841 1038 gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() );
362c6693 1039}
c801d85f 1040
d355d3fe
RR
1041void wxFrame::SetIcon( const wxIcon &icon )
1042{
223d09f6 1043 wxASSERT_MSG( (m_widget != NULL), wxT("invalid frame") );
8bbe427f 1044
7c0ea335 1045 wxFrameBase::SetIcon(icon);
8bbe427f 1046
7c0ea335
VZ
1047 if ( !m_icon.Ok() )
1048 return;
1049
1050 if (!m_widget->window)
1051 return;
58dea4b0 1052
f5368809
RR
1053 wxMask *mask = icon.GetMask();
1054 GdkBitmap *bm = (GdkBitmap *) NULL;
1055 if (mask) bm = mask->GetBitmap();
8bbe427f 1056
f5368809 1057 gdk_window_set_icon( m_widget->window, (GdkWindow *) NULL, icon.GetPixmap(), bm );
d355d3fe 1058}
b2b3ccc5 1059
7c0ea335
VZ
1060// ----------------------------------------------------------------------------
1061// frame state: maximized/iconized/normal (TODO)
1062// ----------------------------------------------------------------------------
1063
7beba2fc 1064void wxFrame::Maximize(bool WXUNUSED(maximize))
cd25b18c
RR
1065{
1066}
1067
7c0ea335
VZ
1068bool wxFrame::IsMaximized() const
1069{
1070 return FALSE;
1071}
1072
7beba2fc 1073void wxFrame::Restore()
cd25b18c
RR
1074{
1075}
1076
7beba2fc
VZ
1077void wxFrame::Iconize( bool iconize )
1078{
cd25b18c
RR
1079 if (iconize)
1080 {
1081 XIconifyWindow( GDK_WINDOW_XDISPLAY( m_widget->window ),
7beba2fc
VZ
1082 GDK_WINDOW_XWINDOW( m_widget->window ),
1083 DefaultScreen( GDK_DISPLAY() ) );
cd25b18c
RR
1084 }
1085}
1086
7beba2fc
VZ
1087bool wxFrame::IsIconized() const
1088{
1089 return FALSE;
cd25b18c 1090}