Use the same colour for miniframe title bar and
[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 #include "wx/settings.h"
17
18 #ifndef WX_PRECOMP
19 #include "wx/dcscreen.h"
20 #endif
21
22 #include "gtk/gtk.h"
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
25
26 #include <gdk/gdk.h>
27 #include <gdk/gdkprivate.h>
28 #include <gdk/gdkx.h>
29
30 //-----------------------------------------------------------------------------
31 // data
32 //-----------------------------------------------------------------------------
33
34 extern bool g_blockEventsOnDrag;
35 extern bool g_blockEventsOnScroll;
36 extern GtkWidget *wxGetRootWindow();
37
38 //-----------------------------------------------------------------------------
39 // "expose_event" of m_mainWidget
40 //-----------------------------------------------------------------------------
41
42 // StepColour() it a utility function that simply darkens
43 // or lightens a color, based on the specified percentage
44 static wxColor StepColour(const wxColor& c, int percent)
45 {
46 int r = c.Red(), g = c.Green(), b = c.Blue();
47 return wxColour((unsigned char)wxMin((r*percent)/100,255),
48 (unsigned char)wxMin((g*percent)/100,255),
49 (unsigned char)wxMin((b*percent)/100,255));
50 }
51
52 static wxColor LightContrastColour(const wxColour& c)
53 {
54 int amount = 120;
55
56 // if the color is especially dark, then
57 // make the contrast even lighter
58 if (c.Red() < 128 && c.Green() < 128 && c.Blue() < 128)
59 amount = 160;
60
61 return StepColour(c, amount);
62 }
63
64 extern "C" {
65 static void gtk_window_own_expose_callback( GtkWidget *widget, GdkEventExpose *gdk_event, wxMiniFrame *win )
66 {
67 if (g_isIdle) wxapp_install_idle_handler();
68
69 if (!win->m_hasVMT) return;
70 if (gdk_event->count > 0) return;
71
72 GtkPizza *pizza = GTK_PIZZA(widget);
73
74 gtk_paint_shadow (widget->style,
75 pizza->bin_window,
76 GTK_STATE_NORMAL,
77 GTK_SHADOW_OUT,
78 NULL, NULL, NULL, // FIXME: No clipping?
79 0, 0,
80 win->m_width, win->m_height);
81
82 int style = win->GetWindowStyle();
83
84 if (!win->GetTitle().empty() &&
85 ((style & wxCAPTION) ||
86 (style & wxTINY_CAPTION_HORIZ) ||
87 (style & wxTINY_CAPTION_VERT)))
88 {
89 wxClientDC dc(win);
90 // Hack alert
91 dc.m_window = pizza->bin_window;
92
93 dc.SetFont( *wxSMALL_FONT );
94 int height = dc.GetCharHeight();
95
96 wxBrush brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT) ) );
97 dc.SetBrush( brush );
98 dc.SetPen( *wxTRANSPARENT_PEN );
99 dc.DrawRectangle( 3, 3, win->m_width - 7, height-2 );
100
101 dc.SetTextForeground( *wxWHITE );
102 dc.DrawText( win->GetTitle(), 6, 3 );
103
104 if (style & wxCLOSE_BOX)
105 dc.DrawBitmap( win->m_closeButton, win->m_width-19, 3, true );
106 }
107 }
108 }
109
110 //-----------------------------------------------------------------------------
111 // "button_press_event" of m_mainWidget
112 //-----------------------------------------------------------------------------
113
114 extern "C" {
115 static gint gtk_window_button_press_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
116 {
117 if (g_isIdle) wxapp_install_idle_handler();
118
119 if (!win->m_hasVMT) return FALSE;
120 if (g_blockEventsOnDrag) return TRUE;
121 if (g_blockEventsOnScroll) return TRUE;
122
123 if (win->m_isDragging) return TRUE;
124
125 GtkPizza *pizza = GTK_PIZZA(widget);
126 if (gdk_event->window != pizza->bin_window) return TRUE;
127
128 int y = (int)gdk_event->y;
129 int x = (int)gdk_event->x;
130
131 int style = win->GetWindowStyle();
132 if ((style & wxCLOSE_BOX) &&
133 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
134 {
135 if ((y > 3) && (y < 19) && (x > win->m_width-19) && (x < win->m_width-3))
136 {
137 win->Close();
138 return TRUE;
139 }
140 }
141
142 wxClientDC dc(win);
143 dc.SetFont( *wxSMALL_FONT );
144 int height = dc.GetCharHeight() + 1;
145
146
147 if (y > height) return TRUE;
148
149 gdk_window_raise( win->m_widget->window );
150
151 gdk_pointer_grab( widget->window, FALSE,
152 (GdkEventMask)
153 (GDK_BUTTON_PRESS_MASK |
154 GDK_BUTTON_RELEASE_MASK |
155 GDK_POINTER_MOTION_MASK |
156 GDK_POINTER_MOTION_HINT_MASK |
157 GDK_BUTTON_MOTION_MASK |
158 GDK_BUTTON1_MOTION_MASK),
159 (GdkWindow *) NULL,
160 (GdkCursor *) NULL,
161 (unsigned int) GDK_CURRENT_TIME );
162
163 win->m_diffX = x;
164 win->m_diffY = y;
165 win->m_oldX = 0;
166 win->m_oldY = 0;
167
168 win->m_isDragging = true;
169
170 return TRUE;
171 }
172 }
173
174 //-----------------------------------------------------------------------------
175 // "button_release_event" of m_mainWidget
176 //-----------------------------------------------------------------------------
177
178 extern "C" {
179 static gint gtk_window_button_release_callback( GtkWidget *widget, GdkEventButton *gdk_event, wxMiniFrame *win )
180 {
181 if (g_isIdle) wxapp_install_idle_handler();
182
183 if (!win->m_hasVMT) return FALSE;
184 if (g_blockEventsOnDrag) return TRUE;
185 if (g_blockEventsOnScroll) return TRUE;
186
187 if (!win->m_isDragging) return TRUE;
188
189 win->m_isDragging = false;
190
191 int x = (int)gdk_event->x;
192 int y = (int)gdk_event->y;
193
194 gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME );
195 int org_x = 0;
196 int org_y = 0;
197 gdk_window_get_origin( widget->window, &org_x, &org_y );
198 x += org_x - win->m_diffX;
199 y += org_y - win->m_diffY;
200 win->m_x = x;
201 win->m_y = y;
202 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
203
204 return TRUE;
205 }
206 }
207
208 //-----------------------------------------------------------------------------
209 // "motion_notify_event" of m_mainWidget
210 //-----------------------------------------------------------------------------
211
212 extern "C" {
213 static gint gtk_window_motion_notify_callback( GtkWidget *widget, GdkEventMotion *gdk_event, wxMiniFrame *win )
214 {
215 if (g_isIdle) wxapp_install_idle_handler();
216
217 if (!win->m_hasVMT) return FALSE;
218 if (g_blockEventsOnDrag) return TRUE;
219 if (g_blockEventsOnScroll) return TRUE;
220
221 if (!win->m_isDragging) return TRUE;
222
223 if (gdk_event->is_hint)
224 {
225 int x = 0;
226 int y = 0;
227 GdkModifierType state;
228 gdk_window_get_pointer(gdk_event->window, &x, &y, &state);
229 gdk_event->x = x;
230 gdk_event->y = y;
231 gdk_event->state = state;
232 }
233
234 win->m_oldX = (int)gdk_event->x - win->m_diffX;
235 win->m_oldY = (int)gdk_event->y - win->m_diffY;
236
237 int x = (int)gdk_event->x;
238 int y = (int)gdk_event->y;
239
240 int org_x = 0;
241 int org_y = 0;
242 gdk_window_get_origin( widget->window, &org_x, &org_y );
243 x += org_x - win->m_diffX;
244 y += org_y - win->m_diffY;
245 win->m_x = x;
246 win->m_y = y;
247 gtk_window_move( GTK_WINDOW(win->m_widget), x, y );
248
249
250 return TRUE;
251 }
252 }
253
254 //-----------------------------------------------------------------------------
255 // wxMiniFrame
256 //-----------------------------------------------------------------------------
257
258 static unsigned char close_bits[]={
259 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
260 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
261 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
262
263
264 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame,wxFrame)
265
266 bool wxMiniFrame::Create( wxWindow *parent, wxWindowID id, const wxString &title,
267 const wxPoint &pos, const wxSize &size,
268 long style, const wxString &name )
269 {
270 style = style | wxCAPTION;
271
272 if ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT))
273 m_miniTitle = 16;
274
275 if (style & wxRESIZE_BORDER)
276 m_miniEdge = 5;
277 else
278 m_miniEdge = 3;
279 m_isDragging = false;
280 m_oldX = -1;
281 m_oldY = -1;
282 m_diffX = 0;
283 m_diffY = 0;
284
285 wxFrame::Create( parent, id, title, pos, size, style, name );
286
287 if (m_parent && (GTK_IS_WINDOW(m_parent->m_widget)))
288 {
289 gtk_window_set_transient_for( GTK_WINDOW(m_widget), GTK_WINDOW(m_parent->m_widget) );
290 }
291
292 if ((style & wxCLOSE_BOX) &&
293 ((style & wxCAPTION) || (style & wxTINY_CAPTION_HORIZ) || (style & wxTINY_CAPTION_VERT)))
294 {
295 wxImage img = wxBitmap((const char*)close_bits, 16, 16).ConvertToImage();
296 img.Replace(255,255,255,123,123,123);
297 img.Replace(0,0,0,255,255,255);
298 img.SetMaskColour(123,123,123);
299 m_closeButton = wxBitmap( img );
300 }
301
302 /* these are called when the borders are drawn */
303 g_signal_connect (m_mainWidget, "expose_event",
304 G_CALLBACK (gtk_window_own_expose_callback), this );
305
306 /* these are required for dragging the mini frame around */
307 g_signal_connect (m_mainWidget, "button_press_event",
308 G_CALLBACK (gtk_window_button_press_callback), this);
309 g_signal_connect (m_mainWidget, "button_release_event",
310 G_CALLBACK (gtk_window_button_release_callback), this);
311 g_signal_connect (m_mainWidget, "motion_notify_event",
312 G_CALLBACK (gtk_window_motion_notify_callback), this);
313
314 return true;
315 }
316
317 void wxMiniFrame::SetTitle( const wxString &title )
318 {
319 wxFrame::SetTitle( title );
320
321 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget)->bin_window, NULL, true );
322 }
323
324 #endif // wxUSE_MINIFRAME