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