]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/minifram.cpp
use more natively looking HildonNote instead of GtkMessageDialog under Maemo
[wxWidgets.git] / src / gtk / minifram.cpp
CommitLineData
b2b3ccc5 1/////////////////////////////////////////////////////////////////////////////
340bfb43 2// Name: src/gtk/minifram.cpp
b2b3ccc5
RR
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
b2b3ccc5
RR
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
dcf924a3
RR
13#if wxUSE_MINIFRAME
14
11dbb4bf
WS
15#include "wx/minifram.h"
16
17#ifndef WX_PRECOMP
b41b2a05 18 #include "wx/settings.h"
0416c418
PC
19 #include "wx/dcclient.h"
20 #include "wx/image.h"
11dbb4bf 21#endif
b2b3ccc5 22
cca410b3 23#include <gtk/gtk.h>
83624f79 24
32a95f9f
RR
25//-----------------------------------------------------------------------------
26// data
27//-----------------------------------------------------------------------------
28
8480b297
RR
29extern bool g_blockEventsOnDrag;
30extern bool g_blockEventsOnScroll;
32a95f9f 31
32a95f9f
RR
32//-----------------------------------------------------------------------------
33// "expose_event" of m_mainWidget
34//-----------------------------------------------------------------------------
35
6d976005
RR
36// StepColour() it a utility function that simply darkens
37// or lightens a color, based on the specified percentage
38static wxColor StepColour(const wxColor& c, int percent)
39{
40 int r = c.Red(), g = c.Green(), b = c.Blue();
41 return wxColour((unsigned char)wxMin((r*percent)/100,255),
42 (unsigned char)wxMin((g*percent)/100,255),
43 (unsigned char)wxMin((b*percent)/100,255));
44}
45
46static wxColor LightContrastColour(const wxColour& c)
47{
48 int amount = 120;
49
50 // if the color is especially dark, then
51 // make the contrast even lighter
52 if (c.Red() < 128 && c.Green() < 128 && c.Blue() < 128)
53 amount = 160;
54
55 return StepColour(c, amount);
56}
57
865bb325 58extern "C" {
6d727f6c 59static gboolean gtk_window_own_expose_callback(GtkWidget* widget, GdkEventExpose* gdk_event, wxMiniFrame* win)
32a95f9f 60{
6d727f6c
PC
61 if (!win->m_hasVMT || gdk_event->count > 0)
62 return false;
c2fa61e8 63
67b73b9a 64 gtk_paint_shadow (widget->style,
cca410b3 65 widget->window,
67b73b9a
MR
66 GTK_STATE_NORMAL,
67 GTK_SHADOW_OUT,
68 NULL, NULL, NULL, // FIXME: No clipping?
69 0, 0,
70 win->m_width, win->m_height);
b9a535f5 71
00e4ffbc 72 int style = win->GetWindowStyle();
b41b2a05 73
85a0a12a 74 wxClientDC dc(win);
cca410b3 75
ab171e95
RR
76#if wxUSE_NEW_DC
77 wxImplDC *impl = dc.GetImpl();
78 wxGTKClientImplDC *client_impl = wxDynamicCast( impl, wxGTKClientImplDC );
79 // Hack alert
cca410b3 80 client_impl->m_window = widget->window;
ab171e95 81#else
85a0a12a 82 // Hack alert
cca410b3 83 dc.m_window = widget->window;
ab171e95 84#endif
b41b2a05 85
85a0a12a
RR
86 if (style & wxRESIZE_BORDER)
87 {
88 dc.SetBrush( *wxGREY_BRUSH );
89 dc.SetPen( *wxTRANSPARENT_PEN );
90 dc.DrawRectangle( win->m_width - 14, win->m_height-14, 14, 14 );
91 }
92
340bfb43 93 if (!win->GetTitle().empty() &&
00e4ffbc
RR
94 ((style & wxCAPTION) ||
95 (style & wxTINY_CAPTION_HORIZ) ||
96 (style & wxTINY_CAPTION_VERT)))
b9a535f5 97 {
ba718523 98 dc.SetFont( *wxSMALL_FONT );
340bfb43 99
6d976005
RR
100 wxBrush brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) ) );
101 dc.SetBrush( brush );
102 dc.SetPen( *wxTRANSPARENT_PEN );
39db4477
RR
103 dc.DrawRectangle( win->m_miniEdge-1,
104 win->m_miniEdge-1,
105 win->m_width - (2*(win->m_miniEdge-1)),
106 15 );
ba718523 107
ba718523 108 dc.SetTextForeground( *wxWHITE );
39db4477 109 dc.DrawText( win->GetTitle(), 6, 4 );
00e4ffbc
RR
110
111 if (style & wxCLOSE_BOX)
39db4477 112 dc.DrawBitmap( win->m_closeButton, win->m_width-18, 3, true );
b9a535f5 113 }
39db4477 114
6d727f6c 115 return false;
32a95f9f 116}
865bb325 117}
32a95f9f 118
32a95f9f
RR
119//-----------------------------------------------------------------------------
120// "button_press_event" of m_mainWidget
121//-----------------------------------------------------------------------------
122
865bb325 123extern "C" {
32a95f9f
RR
124static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
125{
a2053b27 126 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
127 if (g_blockEventsOnDrag) return TRUE;
128 if (g_blockEventsOnScroll) return TRUE;
129
130 if (win->m_isDragging) return TRUE;
131
85a0a12a
RR
132 int style = win->GetWindowStyle();
133
00e4ffbc
RR
134 int y = (int)gdk_event->y;
135 int x = (int)gdk_event->x;
b41b2a05 136
85a0a12a
RR
137 if ((style & wxRESIZE_BORDER) &&
138 (x > win->m_width-14) && (y > win->m_height-14))
139 {
140 GtkWidget *ancestor = gtk_widget_get_toplevel( widget );
141
cca410b3 142 GdkWindow *source = widget->window;
85a0a12a
RR
143
144 int org_x = 0;
145 int org_y = 0;
146 gdk_window_get_origin( source, &org_x, &org_y );
147
148 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor),
149 GDK_WINDOW_EDGE_SOUTH_EAST,
150 1,
151 org_x + x,
152 org_y + y,
153 0);
b41b2a05 154
85a0a12a
RR
155 return TRUE;
156 }
00e4ffbc 157
00e4ffbc
RR
158 if ((style & wxCLOSE_BOX) &&
159 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
160 {
161 if ((y > 3) && (y < 19) && (x > win->m_width-19) && (x < win->m_width-3))
162 {
163 win->Close();
164 return TRUE;
165 }
166 }
b41b2a05 167
39db4477 168 if (y > win->m_miniEdge-1 + 15) return TRUE;
340bfb43 169
4dcaf11a 170 gdk_window_raise( win->m_widget->window );
c2fa61e8 171
32a95f9f
RR
172 gdk_pointer_grab( widget->window, FALSE,
173 (GdkEventMask)
174 (GDK_BUTTON_PRESS_MASK |
175 GDK_BUTTON_RELEASE_MASK |
f03fc89f 176 GDK_POINTER_MOTION_MASK |
32a95f9f 177 GDK_POINTER_MOTION_HINT_MASK |
f03fc89f 178 GDK_BUTTON_MOTION_MASK |
32a95f9f
RR
179 GDK_BUTTON1_MOTION_MASK),
180 (GdkWindow *) NULL,
181 (GdkCursor *) NULL,
7941ba11 182 (unsigned int) GDK_CURRENT_TIME );
c2fa61e8 183
00e4ffbc
RR
184 win->m_diffX = x;
185 win->m_diffY = y;
32a95f9f
RR
186 win->m_oldX = 0;
187 win->m_oldY = 0;
c2fa61e8 188
340bfb43 189 win->m_isDragging = true;
32a95f9f
RR
190
191 return TRUE;
192}
865bb325 193}
32a95f9f
RR
194
195//-----------------------------------------------------------------------------
196// "button_release_event" of m_mainWidget
197//-----------------------------------------------------------------------------
198
865bb325 199extern "C" {
32a95f9f
RR
200static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
201{
a2053b27 202 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
203 if (g_blockEventsOnDrag) return TRUE;
204 if (g_blockEventsOnScroll) return TRUE;
205
206 if (!win->m_isDragging) return TRUE;
c2fa61e8 207
11dbb4bf 208 win->m_isDragging = false;
c2fa61e8 209
32a95f9f
RR
210 int x = (int)gdk_event->x;
211 int y = (int)gdk_event->y;
c2fa61e8 212
13111b2a 213 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
c2fa61e8 214 int org_x = 0;
32a95f9f
RR
215 int org_y = 0;
216 gdk_window_get_origin( widget->window, &org_x, &org_y );
217 x += org_x - win->m_diffX;
218 y += org_y - win->m_diffY;
121a3581
RR
219 win->m_x = x;
220 win->m_y = y;
9adb9063 221 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
32a95f9f
RR
222
223 return TRUE;
224}
865bb325 225}
32a95f9f 226
85a0a12a
RR
227//-----------------------------------------------------------------------------
228// "leave_notify_event" of m_mainWidget
229//-----------------------------------------------------------------------------
230
231extern "C" {
232static gboolean
e4161a2a
VZ
233gtk_window_leave_callback(GtkWidget *widget,
234 GdkEventCrossing * WXUNUSED(gdk_event),
235 wxMiniFrame *win)
85a0a12a 236{
85a0a12a
RR
237 if (!win->m_hasVMT) return FALSE;
238 if (g_blockEventsOnDrag) return FALSE;
239
240 gdk_window_set_cursor( widget->window, NULL );
b41b2a05 241
85a0a12a
RR
242 return FALSE;
243}
244}
245
32a95f9f
RR
246//-----------------------------------------------------------------------------
247// "motion_notify_event" of m_mainWidget
248//-----------------------------------------------------------------------------
249
865bb325 250extern "C" {
b41b2a05 251static gint
85a0a12a 252gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
32a95f9f 253{
a2053b27 254 if (!win->m_hasVMT) return FALSE;
32a95f9f
RR
255 if (g_blockEventsOnDrag) return TRUE;
256 if (g_blockEventsOnScroll) return TRUE;
257
32a95f9f
RR
258 if (gdk_event->is_hint)
259 {
260 int x = 0;
261 int y = 0;
262 GdkModifierType state;
263 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
264 gdk_event->x = x;
265 gdk_event->y = y;
266 gdk_event->state = state;
267 }
268
85a0a12a 269 int style = win->GetWindowStyle();
b41b2a05 270
d02d8b4c
RR
271 int x = (int)gdk_event->x;
272 int y = (int)gdk_event->y;
b41b2a05 273
85a0a12a
RR
274 if (!win->m_isDragging)
275 {
276 if (style & wxRESIZE_BORDER)
277 {
278 if ((x > win->m_width-14) && (y > win->m_height-14))
279 gdk_window_set_cursor( widget->window, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER ) );
280 else
281 gdk_window_set_cursor( widget->window, NULL );
282 }
283 return TRUE;
284 }
b41b2a05 285
85a0a12a
RR
286 win->m_oldX = x - win->m_diffX;
287 win->m_oldY = y - win->m_diffY;
288
d02d8b4c
RR
289 int org_x = 0;
290 int org_y = 0;
291 gdk_window_get_origin( widget->window, &org_x, &org_y );
292 x += org_x - win->m_diffX;
293 y += org_y - win->m_diffY;
294 win->m_x = x;
295 win->m_y = y;
296 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
297
32a95f9f
RR
298 return TRUE;
299}
865bb325 300}
32a95f9f 301
cca410b3
PC
302//-----------------------------------------------------------------------------
303// "size_allocate" from GtkFixed, parent of m_mainWidget
304//-----------------------------------------------------------------------------
305
306extern "C" {
307static void size_allocate(GtkWidget*, GtkAllocation* alloc, wxMiniFrame* win)
308{
309 // place m_mainWidget inside of decorations drawn on the GtkFixed
310 GtkAllocation alloc2 = win->m_mainWidget->allocation;
311 alloc2.width = alloc->width - 2 * win->m_miniEdge;
312 alloc2.height = alloc->height - win->m_miniTitle - 2 * win->m_miniEdge;
313 gtk_widget_size_allocate(win->m_mainWidget, &alloc2);
314}
315}
316
b2b3ccc5
RR
317//-----------------------------------------------------------------------------
318// wxMiniFrame
319//-----------------------------------------------------------------------------
320
00e4ffbc
RR
321static unsigned char close_bits[]={
322 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
323 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
324 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
325
5d5b3a40 326
b2b3ccc5
RR
327IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
328
329bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
330 const wxPoint &pos, const wxSize &size,
331 long style, const wxString &name )
332{
b9a535f5 333 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
00e4ffbc 334 m_miniTitle = 16;
c2fa61e8 335
6d976005 336 if (style & wxRESIZE_BORDER)
85a0a12a 337 m_miniEdge = 4;
6d976005
RR
338 else
339 m_miniEdge = 3;
340bfb43 340 m_isDragging = false;
b2b3ccc5
RR
341 m_oldX = -1;
342 m_oldY = -1;
343 m_diffX = 0;
344 m_diffY = 0;
c2fa61e8 345
b2b3ccc5
RR
346 wxFrame::Create( parent, id, title, pos, size, style, name );
347
cca410b3
PC
348 // borders and title are on a GtkFixed between m_widget and m_mainWidget
349 GtkWidget* fixed = gtk_fixed_new();
350 gtk_fixed_set_has_window((GtkFixed*)fixed, true);
351 gtk_widget_add_events(fixed,
352 GDK_POINTER_MOTION_MASK |
353 GDK_POINTER_MOTION_HINT_MASK |
354 GDK_BUTTON_MOTION_MASK |
355 GDK_BUTTON_PRESS_MASK |
356 GDK_BUTTON_RELEASE_MASK |
357 GDK_LEAVE_NOTIFY_MASK);
358 gtk_widget_show(fixed);
359 gtk_widget_reparent(m_mainWidget, fixed);
360 gtk_container_add((GtkContainer*)m_widget, fixed);
361 gtk_fixed_move((GtkFixed*)fixed, m_mainWidget, m_miniEdge, m_miniTitle + m_miniEdge);
362 g_signal_connect(fixed, "size_allocate", G_CALLBACK(size_allocate), this);
363
364 m_gdkDecor = 0;
365 m_gdkFunc = 0;
366 if (style & wxRESIZE_BORDER)
367 m_gdkFunc = GDK_FUNC_RESIZE;
368
2c990ec0
RR
369 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)))
370 {
371 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
372 }
340bfb43 373
00e4ffbc 374 if ((style & wxCLOSE_BOX) &&
b9a535f5
RR
375 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
376 {
00e4ffbc 377 wxImage img = wxBitmap((const char*)close_bits, 16, 16).ConvertToImage();
c4d39711 378 img.Replace(0,0,0,123,123,123);
00e4ffbc
RR
379 img.SetMaskColour(123,123,123);
380 m_closeButton = wxBitmap( img );
b9a535f5 381 }
c2fa61e8 382
32a95f9f 383 /* these are called when the borders are drawn */
cca410b3 384 g_signal_connect_after(fixed, "expose_event",
9fa72bd2 385 G_CALLBACK (gtk_window_own_expose_callback), this );
b2b3ccc5 386
32a95f9f 387 /* these are required for dragging the mini frame around */
cca410b3 388 g_signal_connect (fixed, "button_press_event",
9fa72bd2 389 G_CALLBACK (gtk_window_button_press_callback), this);
cca410b3 390 g_signal_connect (fixed, "button_release_event",
9fa72bd2 391 G_CALLBACK (gtk_window_button_release_callback), this);
cca410b3 392 g_signal_connect (fixed, "motion_notify_event",
9fa72bd2 393 G_CALLBACK (gtk_window_motion_notify_callback), this);
cca410b3 394 g_signal_connect (fixed, "leave_notify_event",
85a0a12a 395 G_CALLBACK (gtk_window_leave_callback), this);
340bfb43 396 return true;
b2b3ccc5 397}
dcf924a3 398
cca410b3
PC
399void wxMiniFrame::DoGetClientSize(int* width, int* height) const
400{
401 wxFrame::DoGetClientSize(width, height);
402 if (width)
403 {
404 *width -= 2 * m_miniEdge;
405 if (*width < 0) *width = 0;
406 }
407 if (height)
408 {
409 *height -= m_miniTitle + 2 * m_miniEdge;
410 if (*height < 0) *height = 0;
411 }
412}
413
400be137
RR
414void wxMiniFrame::SetTitle( const wxString &title )
415{
416 wxFrame::SetTitle( title );
340bfb43 417
cca410b3
PC
418 GtkWidget* fixed = GTK_BIN(m_widget)->child;
419 if (fixed->window)
420 gdk_window_invalidate_rect(fixed->window, NULL, false);
400be137
RR
421}
422
11dbb4bf 423#endif // wxUSE_MINIFRAME