~ubuntu-branches/ubuntu/quantal/mysql-workbench/quantal

« back to all changes in this revision

Viewing changes to library/forms/gtk/src/lf_popup.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitry Smirnov
  • Date: 2012-03-01 21:57:30 UTC
  • Revision ID: package-import@ubuntu.com-20120301215730-o7y8av8y38n162ro
Tags: upstream-5.2.38+dfsg
ImportĀ upstreamĀ versionĀ 5.2.38+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 
3
 *
 
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
 
7
 * License.
 
8
 *
 
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.
 
13
 *
 
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
 
17
 * 02110-1301  USA
 
18
 */
 
19
 
 
20
#include "../lf_mforms.h"
 
21
#include "../lf_popup.h"
 
22
#include "mforms.h"
 
23
#include "gtk_helpers.h"
 
24
#include <typeinfo>
 
25
 
 
26
//#define d(...) {fprintf(stderr, "%s:%i: ", __PRETTY_FUNCTION__, __LINE__); fprintf(stderr,__VA_ARGS__);}
 
27
#define d(...)
 
28
 
 
29
namespace mforms {
 
30
namespace gtk {
 
31
 
 
32
//------------------------------------------------------------------------------
 
33
PopupImpl::PopupImpl(::mforms::Popup *self, mforms::PopupStyle style)
 
34
  : ObjectImpl(self)
 
35
  , _width(-1)
 
36
  , _height(-1)
 
37
  , _have_rgba(false)
 
38
  , _inside(false)
 
39
  , _result(-1)
 
40
{
 
41
  d("\n");
 
42
  mforms::Popup* selfc = dynamic_cast<mforms::Popup*>(owner);
 
43
  _wnd.set_app_paintable(true);
 
44
 
 
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));
 
53
 
 
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);
 
58
 
 
59
  _wnd.property_skip_taskbar_hint() = true;
 
60
  _wnd.property_skip_pager_hint() = true;
 
61
  _wnd.property_decorated() = false;
 
62
 
 
63
  on_screen_changed(_wnd.get_screen());
 
64
  set_size(self, 825, 351);
 
65
  _wnd.set_transient_for(*get_mainwindow());
 
66
  _wnd.set_modal(true);
 
67
#if GTK_VERSION_GE(2,12)
 
68
  _wnd.set_opacity(0.92);
 
69
#endif
 
70
}
 
71
 
 
72
//------------------------------------------------------------------------------
 
73
void PopupImpl::on_screen_changed(const Glib::RefPtr<Gdk::Screen>& screen)
 
74
{
 
75
  d("\n");
 
76
  Glib::RefPtr<Gdk::Colormap> colormap = screen->get_rgba_colormap();
 
77
  _have_rgba = colormap;
 
78
 
 
79
  if (!_have_rgba)
 
80
    colormap = screen->get_rgb_colormap();
 
81
 
 
82
  _wnd.set_colormap(colormap);
 
83
}
 
84
 
 
85
//------------------------------------------------------------------------------
 
86
bool PopupImpl::handle_expose_event(GdkEventExpose *event)
 
87
{
 
88
  d("\n");
 
89
  mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
 
90
  if (self)
 
91
  {
 
92
    Gtk::Requisition size = _wnd.size_request();
 
93
 
 
94
    int w = size.width;
 
95
    int h = size.height;
 
96
 
 
97
    Cairo::RefPtr<Cairo::Context> context(_wnd.get_window()->create_cairo_context());
 
98
    cairo_t *cr = context->cobj();
 
99
 
 
100
    if (cr)
 
101
    {
 
102
      // Draw round corners
 
103
      if (_width > 0 && _height > 0)
 
104
      {
 
105
        //cairo_save(cr);
 
106
 
 
107
        const int W = _width;
 
108
        const int H = _height;
 
109
 
 
110
        if (_have_rgba)
 
111
          cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0);
 
112
        else
 
113
          cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
 
114
 
 
115
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
 
116
        cairo_paint(cr);
 
117
 
 
118
        cairo_new_path(cr);
 
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);
 
129
 
 
130
        cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.92);
 
131
        cairo_fill_preserve(cr);
 
132
 
 
133
        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
 
134
        self->repaint(cr, R, R, _width-R, _height-R);
 
135
      }
 
136
      else
 
137
      {
 
138
        self->repaint(cr, event->area.x, event->area.y, event->area.width, event->area.height);
 
139
      }
 
140
    }
 
141
  }
 
142
  return true;
 
143
}
 
144
 
 
145
//------------------------------------------------------------------------------
 
146
bool PopupImpl::key_press_event(GdkEventKey *event)
 
147
{
 
148
  if (event->keyval == GDK_Escape)
 
149
  {
 
150
    set_modal_result(dynamic_cast<mforms::Popup*>(owner), 0);
 
151
  }
 
152
  return true;
 
153
}
 
154
 
 
155
//------------------------------------------------------------------------------
 
156
bool PopupImpl::mouse_cross_event(GdkEventCrossing *event)
 
157
{
 
158
  mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
 
159
  if (self && _wnd.get_window()->gobj() == event->window)
 
160
  {
 
161
    d("\n");
 
162
    if (event->type == GDK_ENTER_NOTIFY)
 
163
    {
 
164
      _inside= true;
 
165
      self->mouse_enter();
 
166
    }
 
167
    else
 
168
    {
 
169
      _inside= false;
 
170
      self->mouse_leave();
 
171
    }
 
172
  }
 
173
  return true;
 
174
}
 
175
 
 
176
//------------------------------------------------------------------------------
 
177
bool PopupImpl::mouse_button_event(GdkEventButton *event)
 
178
{
 
179
  mforms::Popup* self = dynamic_cast<mforms::Popup*>(owner);
 
180
  d("\n");
 
181
  if (self && _wnd.get_window()->gobj() == event->window)
 
182
  {
 
183
    if (!_inside)
 
184
    {
 
185
      set_modal_result(self, 0);
 
186
      
 
187
      return false;
 
188
    }
 
189
 
 
190
    if (event->type == GDK_BUTTON_PRESS)
 
191
    {
 
192
      self->mouse_down(event->button-1, (int)event->x, (int)event->y);
 
193
    }
 
194
    else if (event->type == GDK_BUTTON_RELEASE)
 
195
    {
 
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!
 
198
    }
 
199
    else if (event->type == GDK_2BUTTON_PRESS)
 
200
      self->mouse_double_click(event->button-1, (int)event->x, (int)event->y);
 
201
  }
 
202
  else
 
203
    set_modal_result(self, 0);
 
204
 
 
205
  return false;
 
206
}
 
207
 
 
208
//------------------------------------------------------------------------------
 
209
bool PopupImpl::mouse_move_event(GdkEventMotion *event)
 
210
{
 
211
  d("\n");
 
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);
 
215
  return true;
 
216
}
 
217
 
 
218
//------------------------------------------------------------------------------
 
219
bool PopupImpl::create(::mforms::Popup *self, ::mforms::PopupStyle style)
 
220
{
 
221
  d("\n");
 
222
  return new PopupImpl(self, style) != 0;
 
223
}
 
224
 
 
225
//------------------------------------------------------------------------------
 
226
void PopupImpl::set_needs_repaint(::mforms::Popup *self)
 
227
{
 
228
  d("\n");
 
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();
 
232
}
 
233
 
 
234
//------------------------------------------------------------------------------
 
235
void PopupImpl::set_size(::mforms::Popup *self, int w, int h)
 
236
{
 
237
  PopupImpl *impl = self->get_data<PopupImpl>();
 
238
  d("\n");
 
239
 
 
240
  impl->_width = w + 2*R;
 
241
  impl->_height = h + 2*R;
 
242
  impl->_wnd.set_size_request(impl->_width, impl->_height);}
 
243
 
 
244
//------------------------------------------------------------------------------
 
245
int PopupImpl::show(::mforms::Popup *self, int x, int y)
 
246
{
 
247
  PopupImpl *impl = self->get_data<PopupImpl>();
 
248
 
 
249
  d("x=%i, y=%i\n", x, y);
 
250
  if (impl->_wnd.is_visible())
 
251
    impl->_wnd.hide();
 
252
  else
 
253
  {
 
254
    Gtk::Window* main_window = get_mainwindow();
 
255
 
 
256
    const Gtk::Requisition req = impl->_wnd.size_request();
 
257
    const int x1 = x - req.width;
 
258
 
 
259
    impl->_wnd.show();
 
260
    impl->_wnd.move(x1,y-16);
 
261
    
 
262
    impl->_wnd.get_window()->pointer_grab(true, Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK, 0);
 
263
 
 
264
    Gtk::Main::run();
 
265
    impl->_wnd.set_modal(false);
 
266
    impl->_wnd.hide();
 
267
  }
 
268
 
 
269
  return impl->_result;
 
270
}
 
271
 
 
272
//------------------------------------------------------------------------------
 
273
MySQL::Geometry::Rect PopupImpl::get_content_rect(::mforms::Popup *self)
 
274
{
 
275
  d("\n");
 
276
  PopupImpl *impl = self->get_data<PopupImpl>();
 
277
  return MySQL::Geometry::Rect(R, R, impl->_width-R, impl->_height-R);
 
278
}
 
279
 
 
280
//------------------------------------------------------------------------------
 
281
void PopupImpl::set_modal_result(Popup *self, int result)
 
282
{
 
283
  d("\n");
 
284
  PopupImpl *impl = self->get_data<PopupImpl>();
 
285
  impl->_result = result;
 
286
  if (result > -1)
 
287
    Gtk::Main::quit();
 
288
}
 
289
 
 
290
//------------------------------------------------------------------------------
 
291
void PopupImpl::init()
 
292
{
 
293
  ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
 
294
 
 
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;
 
301
}
 
302
 
 
303
};
 
304
};