use -Wunused-parameter with gcc for consistency with MSVC and other compilers which...
[wxWidgets.git] / src / gtk / minifram.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/minifram.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12
13 #if wxUSE_MINIFRAME
14
15 #include "wx/minifram.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/settings.h"
19 #include "wx/dcclient.h"
20 #include "wx/image.h"
21 #endif
22
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
25
26 //-----------------------------------------------------------------------------
27 // data
28 //-----------------------------------------------------------------------------
29
30 extern bool g_blockEventsOnDrag;
31 extern bool g_blockEventsOnScroll;
32 extern GtkWidget *wxGetRootWindow();
33
34 //-----------------------------------------------------------------------------
35 // "expose_event" of m_mainWidget
36 //-----------------------------------------------------------------------------
37
38 // StepColour() it a utility function that simply darkens
39 // or lightens a color, based on the specified percentage
40 static 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
48 static 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
60 extern "C" {
61 static gboolean gtk_window_own_expose_callback(GtkWidget* widget, GdkEventExpose* gdk_event, wxMiniFrame* win)
62 {
63 if (!win->m_hasVMT || gdk_event->count > 0)
64 return false;
65
66 GtkPizza *pizza = GTK_PIZZA(widget);
67
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);
75
76 int style = win->GetWindowStyle();
77
78 wxClientDC dc(win);
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
86 // Hack alert
87 dc.m_window = pizza->bin_window;
88 #endif
89
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
97 if (!win->GetTitle().empty() &&
98 ((style & wxCAPTION) ||
99 (style & wxTINY_CAPTION_HORIZ) ||
100 (style & wxTINY_CAPTION_VERT)))
101 {
102 dc.SetFont( *wxSMALL_FONT );
103 int height = dc.GetCharHeight();
104
105 wxBrush brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) ) );
106 dc.SetBrush( brush );
107 dc.SetPen( *wxTRANSPARENT_PEN );
108 dc.DrawRectangle( 3, 3, win->m_width - 7, height );
109
110 dc.SetTextForeground( *wxWHITE );
111 dc.DrawText( win->GetTitle(), 6, 3 );
112
113 if (style & wxCLOSE_BOX)
114 dc.DrawBitmap( win->m_closeButton, win->m_width-19, 2, true );
115 }
116 return false;
117 }
118 }
119
120 //-----------------------------------------------------------------------------
121 // "button_press_event" of m_mainWidget
122 //-----------------------------------------------------------------------------
123
124 extern "C" {
125 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
126 {
127 if (!win->m_hasVMT) return FALSE;
128 if (g_blockEventsOnDrag) return TRUE;
129 if (g_blockEventsOnScroll) return TRUE;
130
131 if (win->m_isDragging) return TRUE;
132
133 GtkPizza *pizza = GTK_PIZZA(widget);
134 if (gdk_event->window != pizza->bin_window) return TRUE;
135
136 int style = win->GetWindowStyle();
137
138 int y = (int)gdk_event->y;
139 int x = (int)gdk_event->x;
140
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);
158
159 return TRUE;
160 }
161
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 }
171
172 wxClientDC dc(win);
173 dc.SetFont( *wxSMALL_FONT );
174 int height = dc.GetCharHeight() + 1;
175
176
177 if (y > height) return TRUE;
178
179 gdk_window_raise( win->m_widget->window );
180
181 gdk_pointer_grab( widget->window, FALSE,
182 (GdkEventMask)
183 (GDK_BUTTON_PRESS_MASK |
184 GDK_BUTTON_RELEASE_MASK |
185 GDK_POINTER_MOTION_MASK |
186 GDK_POINTER_MOTION_HINT_MASK |
187 GDK_BUTTON_MOTION_MASK |
188 GDK_BUTTON1_MOTION_MASK),
189 (GdkWindow *) NULL,
190 (GdkCursor *) NULL,
191 (unsigned int) GDK_CURRENT_TIME );
192
193 win->m_diffX = x;
194 win->m_diffY = y;
195 win->m_oldX = 0;
196 win->m_oldY = 0;
197
198 win->m_isDragging = true;
199
200 return TRUE;
201 }
202 }
203
204 //-----------------------------------------------------------------------------
205 // "button_release_event" of m_mainWidget
206 //-----------------------------------------------------------------------------
207
208 extern "C" {
209 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
210 {
211 if (!win->m_hasVMT) return FALSE;
212 if (g_blockEventsOnDrag) return TRUE;
213 if (g_blockEventsOnScroll) return TRUE;
214
215 if (!win->m_isDragging) return TRUE;
216
217 win->m_isDragging = false;
218
219 int x = (int)gdk_event->x;
220 int y = (int)gdk_event->y;
221
222 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
223 int org_x = 0;
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;
228 win->m_x = x;
229 win->m_y = y;
230 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
231
232 return TRUE;
233 }
234 }
235
236 //-----------------------------------------------------------------------------
237 // "leave_notify_event" of m_mainWidget
238 //-----------------------------------------------------------------------------
239
240 extern "C" {
241 static gboolean
242 gtk_window_leave_callback(GtkWidget *widget,
243 GdkEventCrossing * WXUNUSED(gdk_event),
244 wxMiniFrame *win)
245 {
246 if (!win->m_hasVMT) return FALSE;
247 if (g_blockEventsOnDrag) return FALSE;
248
249 gdk_window_set_cursor( widget->window, NULL );
250
251 return FALSE;
252 }
253 }
254
255 //-----------------------------------------------------------------------------
256 // "motion_notify_event" of m_mainWidget
257 //-----------------------------------------------------------------------------
258
259 extern "C" {
260 static gint
261 gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
262 {
263 if (!win->m_hasVMT) return FALSE;
264 if (g_blockEventsOnDrag) return TRUE;
265 if (g_blockEventsOnScroll) return TRUE;
266
267 if (gdk_event->is_hint)
268 {
269 int x = 0;
270 int y = 0;
271 GdkModifierType state;
272 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
273 gdk_event->x = x;
274 gdk_event->y = y;
275 gdk_event->state = state;
276 }
277
278 int style = win->GetWindowStyle();
279
280 int x = (int)gdk_event->x;
281 int y = (int)gdk_event->y;
282
283 if (!win->m_isDragging)
284 {
285 if (style & wxRESIZE_BORDER)
286 {
287 if ((x > win->m_width-14) && (y > win->m_height-14))
288 gdk_window_set_cursor( widget->window, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER ) );
289 else
290 gdk_window_set_cursor( widget->window, NULL );
291 }
292 return TRUE;
293 }
294
295 win->m_oldX = x - win->m_diffX;
296 win->m_oldY = y - win->m_diffY;
297
298 int org_x = 0;
299 int org_y = 0;
300 gdk_window_get_origin( widget->window, &org_x, &org_y );
301 x += org_x - win->m_diffX;
302 y += org_y - win->m_diffY;
303 win->m_x = x;
304 win->m_y = y;
305 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
306
307
308 return TRUE;
309 }
310 }
311
312 //-----------------------------------------------------------------------------
313 // wxMiniFrame
314 //-----------------------------------------------------------------------------
315
316 static unsigned char close_bits[]={
317 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
318 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
319 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
320
321
322 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
323
324 bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
325 const wxPoint &pos, const wxSize &size,
326 long style, const wxString &name )
327 {
328 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
329 m_miniTitle = 16;
330
331 if (style & wxRESIZE_BORDER)
332 m_miniEdge = 4;
333 else
334 m_miniEdge = 3;
335 m_isDragging = false;
336 m_oldX = -1;
337 m_oldY = -1;
338 m_diffX = 0;
339 m_diffY = 0;
340
341 wxFrame::Create( parent, id, title, pos, size, style, name );
342
343 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)))
344 {
345 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
346 }
347
348 if ((style & wxCLOSE_BOX) &&
349 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
350 {
351 wxImage img = wxBitmap((const char*)close_bits, 16, 16).ConvertToImage();
352 img.Replace(0,0,0,123,123,123);
353 img.SetMaskColour(123,123,123);
354 m_closeButton = wxBitmap( img );
355 }
356
357 /* these are called when the borders are drawn */
358 g_signal_connect (m_mainWidget, "expose_event",
359 G_CALLBACK (gtk_window_own_expose_callback), this );
360
361 /* these are required for dragging the mini frame around */
362 g_signal_connect (m_mainWidget, "button_press_event",
363 G_CALLBACK (gtk_window_button_press_callback), this);
364 g_signal_connect (m_mainWidget, "button_release_event",
365 G_CALLBACK (gtk_window_button_release_callback), this);
366 g_signal_connect (m_mainWidget, "motion_notify_event",
367 G_CALLBACK (gtk_window_motion_notify_callback), this);
368 g_signal_connect (m_mainWidget, "leave_notify_event",
369 G_CALLBACK (gtk_window_leave_callback), this);
370 return true;
371 }
372
373 void wxMiniFrame::SetTitle( const wxString &title )
374 {
375 wxFrame::SetTitle( title );
376
377 if (GTK_PIZZA(m_mainWidget)->bin_window)
378 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget)->bin_window, NULL, true );
379 }
380
381 #endif // wxUSE_MINIFRAME