]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/minifram.cpp
Fix various minor PS issues
[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, GdkEventCrossing *gdk_event, wxMiniFrame *win )
243 {
244 if (!win->m_hasVMT) return FALSE;
245 if (g_blockEventsOnDrag) return FALSE;
246
247 gdk_window_set_cursor( widget->window, NULL );
248
249 return FALSE;
250 }
251 }
252
253 //-----------------------------------------------------------------------------
254 // "motion_notify_event" of m_mainWidget
255 //-----------------------------------------------------------------------------
256
257 extern "C" {
258 static gint
259 gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
260 {
261 if (!win->m_hasVMT) return FALSE;
262 if (g_blockEventsOnDrag) return TRUE;
263 if (g_blockEventsOnScroll) return TRUE;
264
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
276 int style = win->GetWindowStyle();
277
278 int x = (int)gdk_event->x;
279 int y = (int)gdk_event->y;
280
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 }
292
293 win->m_oldX = x - win->m_diffX;
294 win->m_oldY = y - win->m_diffY;
295
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
305
306 return TRUE;
307 }
308 }
309
310 //-----------------------------------------------------------------------------
311 // wxMiniFrame
312 //-----------------------------------------------------------------------------
313
314 static 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
319
320 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
321
322 bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
323 const wxPoint &pos, const wxSize &size,
324 long style, const wxString &name )
325 {
326 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
327 m_miniTitle = 16;
328
329 if (style & wxRESIZE_BORDER)
330 m_miniEdge = 4;
331 else
332 m_miniEdge = 3;
333 m_isDragging = false;
334 m_oldX = -1;
335 m_oldY = -1;
336 m_diffX = 0;
337 m_diffY = 0;
338
339 wxFrame::Create( parent, id, title, pos, size, style, name );
340
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 }
345
346 if ((style & wxCLOSE_BOX) &&
347 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
348 {
349 wxImage img = wxBitmap((const char*)close_bits, 16, 16).ConvertToImage();
350 img.Replace(0,0,0,123,123,123);
351 img.SetMaskColour(123,123,123);
352 m_closeButton = wxBitmap( img );
353 }
354
355 /* these are called when the borders are drawn */
356 g_signal_connect (m_mainWidget, "expose_event",
357 G_CALLBACK (gtk_window_own_expose_callback), this );
358
359 /* these are required for dragging the mini frame around */
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);
366 g_signal_connect (m_mainWidget, "leave_notify_event",
367 G_CALLBACK (gtk_window_leave_callback), this);
368 return true;
369 }
370
371 void wxMiniFrame::SetTitle( const wxString &title )
372 {
373 wxFrame::SetTitle( title );
374
375 if (GTK_PIZZA(m_mainWidget)->bin_window)
376 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget)->bin_window, NULL, true );
377 }
378
379 #endif // wxUSE_MINIFRAME