2
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; version 2 of the
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
#include "../lf_mforms.h"
21
#include "../lf_popup.h"
23
#include "gtk_helpers.h"
26
//#define d(...) {fprintf(stderr, "%s:%i: ", __PRETTY_FUNCTION__, __LINE__); fprintf(stderr,__VA_ARGS__);}
32
//------------------------------------------------------------------------------
33
PopupImpl::PopupImpl(::mforms::Popup *self, mforms::PopupStyle style)
42
mforms::Popup* selfc = dynamic_cast<mforms::Popup*>(owner);
43
_wnd.set_app_paintable(true);
45
_wnd.signal_expose_event().connect(sigc::mem_fun(this, &PopupImpl::handle_expose_event));
46
_wnd.signal_screen_changed().connect(sigc::mem_fun(this, &PopupImpl::on_screen_changed));
47
_wnd.signal_key_press_event().connect(sigc::mem_fun(this, &PopupImpl::key_press_event));
48
_wnd.signal_button_press_event().connect(sigc::mem_fun(this, &PopupImpl::mouse_button_event));
49
_wnd.signal_button_release_event().connect(sigc::mem_fun(this, &PopupImpl::mouse_button_event));
50
_wnd.signal_enter_notify_event().connect(sigc::mem_fun(this, &PopupImpl::mouse_cross_event));
51
_wnd.signal_leave_notify_event().connect(sigc::mem_fun(this, &PopupImpl::mouse_cross_event));
52
_wnd.signal_motion_notify_event().connect(sigc::mem_fun(this, &PopupImpl::mouse_move_event));
54
// request mouse moved events
55
_wnd.add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK
56
| Gdk::KEY_PRESS_MASK);
57
_wnd.set_gravity(Gdk::GRAVITY_NORTH_WEST);
59
_wnd.property_skip_taskbar_hint() = true;
60
_wnd.property_skip_pager_hint() = true;
61
_wnd.property_decorated() = false;
63
on_screen_changed(_wnd.get_screen());
64
set_size(self, 825, 351);
65
_wnd.set_transient_for(*get_mainwindow());
67
#if GTK_VERSION_GE(2,12)
68
_wnd.set_opacity(0.92);
72
//------------------------------------------------------------------------------
73
void PopupImpl::on_screen_changed(const Glib::RefPtr<Gdk::Screen>& screen)
76
Glib::RefPtr<Gdk::Colormap> colormap = screen->get_rgba_colormap();
77
_have_rgba = colormap;
80
colormap = screen->get_rgb_colormap();
82
_wnd.set_colormap(colormap);
85
//------------------------------------------------------------------------------
86
bool PopupImpl::handle_expose_event(GdkEventExpose *event)
89
mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
92
Gtk::Requisition size = _wnd.size_request();
97
Cairo::RefPtr<Cairo::Context> context(_wnd.get_window()->create_cairo_context());
98
cairo_t *cr = context->cobj();
102
// Draw round corners
103
if (_width > 0 && _height > 0)
107
const int W = _width;
108
const int H = _height;
111
cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
113
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
115
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
119
cairo_move_to(cr, R,0); // 1
120
cairo_line_to(cr, W-R, 0); // 2
121
cairo_curve_to(cr, W, 0, W, 0, W, R); // 3
122
cairo_line_to(cr, W, H-R); // 4
123
cairo_curve_to(cr, W, H, W, H, W-R, H); // 5
124
cairo_line_to(cr, R, H); // 6
125
cairo_curve_to(cr, 0, H, 0, H, 0, H-R); // 7
126
cairo_line_to(cr, 0, R); // 8
127
cairo_curve_to(cr, 0, 0, 0, 0, R, 0); // 9
128
cairo_close_path(cr);
130
cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.92);
131
cairo_fill_preserve(cr);
133
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
134
self->repaint(cr, R, R, _width-R, _height-R);
138
self->repaint(cr, event->area.x, event->area.y, event->area.width, event->area.height);
145
//------------------------------------------------------------------------------
146
bool PopupImpl::key_press_event(GdkEventKey *event)
148
if (event->keyval == GDK_Escape)
150
set_modal_result(dynamic_cast<mforms::Popup*>(owner), 0);
155
//------------------------------------------------------------------------------
156
bool PopupImpl::mouse_cross_event(GdkEventCrossing *event)
158
mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
159
if (self && _wnd.get_window()->gobj() == event->window)
162
if (event->type == GDK_ENTER_NOTIFY)
176
//------------------------------------------------------------------------------
177
bool PopupImpl::mouse_button_event(GdkEventButton *event)
179
mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
181
if (self && _wnd.get_window()->gobj() == event->window)
185
set_modal_result(self, 0);
190
if (event->type == GDK_BUTTON_PRESS)
192
self->mouse_down(event->button-1, (int)event->x, (int)event->y);
194
else if (event->type == GDK_BUTTON_RELEASE)
196
self->mouse_up(event->button-1, (int)event->x, (int)event->y);
197
self->mouse_click(event->button-1, (int)event->x, (int)event->y); // Click must be called after mouse was up!
199
else if (event->type == GDK_2BUTTON_PRESS)
200
self->mouse_double_click(event->button-1, (int)event->x, (int)event->y);
203
set_modal_result(self, 0);
208
//------------------------------------------------------------------------------
209
bool PopupImpl::mouse_move_event(GdkEventMotion *event)
212
mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
213
if (_inside && self && _wnd.get_window()->gobj() == event->window)
214
self->mouse_move((int)event->x, (int)event->y);
218
//------------------------------------------------------------------------------
219
bool PopupImpl::create(::mforms::Popup *self, ::mforms::PopupStyle style)
222
return new PopupImpl(self, style) != 0;
225
//------------------------------------------------------------------------------
226
void PopupImpl::set_needs_repaint(::mforms::Popup *self)
229
// request a repaint so that this can be called from any thread
230
PopupImpl *impl = self->get_data<PopupImpl>();
231
impl->_wnd.queue_draw();
234
//------------------------------------------------------------------------------
235
void PopupImpl::set_size(::mforms::Popup *self, int w, int h)
237
PopupImpl *impl = self->get_data<PopupImpl>();
240
impl->_width = w + 2*R;
241
impl->_height = h + 2*R;
242
impl->_wnd.set_size_request(impl->_width, impl->_height);}
244
//------------------------------------------------------------------------------
245
int PopupImpl::show(::mforms::Popup *self, int x, int y)
247
PopupImpl *impl = self->get_data<PopupImpl>();
249
d("x=%i, y=%i\n", x, y);
250
if (impl->_wnd.is_visible())
254
Gtk::Window* main_window = get_mainwindow();
256
const Gtk::Requisition req = impl->_wnd.size_request();
257
const int x1 = x - req.width;
260
impl->_wnd.move(x1,y-16);
262
impl->_wnd.get_window()->pointer_grab(true, Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK, 0);
265
impl->_wnd.set_modal(false);
269
return impl->_result;
272
//------------------------------------------------------------------------------
273
MySQL::Geometry::Rect PopupImpl::get_content_rect(::mforms::Popup *self)
276
PopupImpl *impl = self->get_data<PopupImpl>();
277
return MySQL::Geometry::Rect(R, R, impl->_width-R, impl->_height-R);
280
//------------------------------------------------------------------------------
281
void PopupImpl::set_modal_result(Popup *self, int result)
284
PopupImpl *impl = self->get_data<PopupImpl>();
285
impl->_result = result;
290
//------------------------------------------------------------------------------
291
void PopupImpl::init()
293
::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
295
f->_popup_impl.create = &PopupImpl::create;
296
f->_popup_impl.set_needs_repaint = &PopupImpl::set_needs_repaint;
297
f->_popup_impl.set_size = &PopupImpl::set_size;
298
f->_popup_impl.show = &PopupImpl::show;
299
f->_popup_impl.get_content_rect = &PopupImpl::get_content_rect;
300
f->_popup_impl.set_modal_result = &PopupImpl::set_modal_result;