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

« back to all changes in this revision

Viewing changes to backend/wbpublic/wbcanvas/layer_figure.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) 2007, 2011, 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
#include "stdafx.h"
 
20
 
 
21
#include "layer_figure.h"
 
22
#include "figure_common.h"
 
23
#include <grts/structs.model.h>
 
24
 
 
25
using namespace std;
 
26
using namespace wbfig;
 
27
using namespace MySQL::Geometry;
 
28
using namespace MySQL::Drawing;
 
29
 
 
30
#define MIN_LAYER_TITLE_WIDTH 120.0
 
31
#define MIN_LAYER_SIZE 10.0
 
32
 
 
33
//--------------------------------------------------------------------------------------------------
 
34
 
 
35
LayerAreaGroup::LayerAreaGroup(mdc::Layer *layer, FigureEventHub *hub, model_Object *represented_object)
 
36
: mdc::AreaGroup(layer), _hub(hub), _represented_object(represented_object)
 
37
{
 
38
  set_cache_toplevel_contents(false);
 
39
 
 
40
  set_auto_sizing(false);
 
41
//  set_background(_layer_back);
 
42
  set_draggable(true);
 
43
 
 
44
  _extents_invalid= true;
 
45
 
 
46
  _font= layer->get_view()->get_default_font();
 
47
  _font.weight= mdc::WBold;
 
48
 
 
49
  _title_fore= Color::Black();
 
50
  _title_back= Color(0.85, 0.85, 0.85);
 
51
 
 
52
  _min_size.width= MIN_LAYER_SIZE;
 
53
  _min_size.height= MIN_LAYER_SIZE;
 
54
 
 
55
  _drag_selects_contents= true;
 
56
  
 
57
  _resizing= false;
 
58
 
 
59
  _text_texture= 0;
 
60
  _display_list= 0;
 
61
}
 
62
 
 
63
//--------------------------------------------------------------------------------------------------
 
64
 
 
65
LayerAreaGroup::~LayerAreaGroup()
 
66
{
 
67
  if (_display_list != 0)
 
68
    glDeleteLists(_display_list, 1);
 
69
 
 
70
  if (_text_texture != 0)
 
71
    glDeleteTextures(1, &_text_texture);
 
72
}
 
73
 
 
74
//--------------------------------------------------------------------------------------------------
 
75
 
 
76
void LayerAreaGroup::set_title(const std::string &title)
 
77
{
 
78
  _title= title;
 
79
  _extents_invalid= true;
 
80
  set_needs_repaint();
 
81
}
 
82
 
 
83
 
 
84
void LayerAreaGroup::set_font(const mdc::FontSpec &font)
 
85
{
 
86
  _font= font;
 
87
  _extents_invalid= true;
 
88
  set_needs_repaint();
 
89
}
 
90
 
 
91
 
 
92
static void get_bounding_area(mdc::CanvasItem *item, Point *maxpos)
 
93
{
 
94
  Rect bounds= item->get_bounds();
 
95
 
 
96
  maxpos->x= max(maxpos->x, bounds.right());
 
97
  maxpos->y= max(maxpos->y, bounds.bottom());
 
98
}
 
99
 
 
100
 
 
101
void LayerAreaGroup::move_item(mdc::CanvasItem *item, const Point &pos)
 
102
{
 
103
  item->move_to(pos);
 
104
}
 
105
 
 
106
 
 
107
bool LayerAreaGroup::on_drag_handle(mdc::ItemHandle *handle, const Point &pos, bool dragging)
 
108
{
 
109
  //Point offset= pos - get_view()->snap_to_grid(handle->get_position());
 
110
  Point npos= get_position();
 
111
  Size nsize= get_size();
 
112
 
 
113
  if (!_resizing)
 
114
  {
 
115
    Point maxpos;
 
116
 
 
117
    _initial_bounds= get_root_bounds();
 
118
    _resizing= true;
 
119
 
 
120
    foreach(boost::bind(get_bounding_area, _1, &maxpos));
 
121
 
 
122
    _min_size.width= max(maxpos.x, MIN_LAYER_SIZE);
 
123
    _min_size.height= max(maxpos.y, MIN_LAYER_SIZE);
 
124
    _min_size_invalid= false;
 
125
  }
 
126
 
 
127
  bool flag= mdc::AreaGroup::on_drag_handle(handle, get_view()->snap_to_grid(pos), dragging);
 
128
 
 
129
  if (!dragging)
 
130
  {
 
131
    _resizing= false;
 
132
    _min_size.width= MIN_LAYER_SIZE;
 
133
    _min_size.height= MIN_LAYER_SIZE;
 
134
    _min_size_invalid= false;
 
135
 
 
136
    _resize_signal(_initial_bounds);
 
137
  }
 
138
 
 
139
  return flag;
 
140
}
 
141
 
 
142
 
 
143
bool LayerAreaGroup::on_button_press(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
 
144
{
 
145
  if (mdc::bounds_contain_point(get_title_bounds(), point.x, point.y))
 
146
  {
 
147
    _drag_selects_contents= false;
 
148
  }
 
149
 
 
150
  if (!_hub || !_hub->figure_button_release(_represented_object, target, point, button, state))
 
151
    return super::on_button_press(target, point, button, state);
 
152
  
 
153
  return false;
 
154
}
 
155
 
 
156
 
 
157
bool LayerAreaGroup::on_button_release(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
 
158
{
 
159
  bool ret= false;
 
160
  
 
161
  if (!_hub || !_hub->figure_button_release(_represented_object, target, point, button, state))
 
162
    ret= super::on_button_release(target, point, button, state);
 
163
 
 
164
  _drag_selects_contents= true;
 
165
  
 
166
  return ret;
 
167
}
 
168
 
 
169
//--------------------------------------------------------------------------------------------------
 
170
 
 
171
bool LayerAreaGroup::on_click(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
 
172
{
 
173
  if (!_hub || !_hub->figure_click(_represented_object, target, point, button, state))
 
174
    return mdc::AreaGroup::on_click(target, point, button, state);
 
175
 
 
176
  return false;
 
177
}
 
178
 
 
179
//--------------------------------------------------------------------------------------------------
 
180
 
 
181
bool LayerAreaGroup::on_double_click(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
 
182
{
 
183
  if (!_hub || !_hub->figure_double_click(_represented_object, target, point, button, state))
 
184
    return mdc::AreaGroup::on_double_click(target, point, button, state);
 
185
 
 
186
  return false;
 
187
}
 
188
 
 
189
//--------------------------------------------------------------------------------------------------
 
190
 
 
191
bool LayerAreaGroup::on_enter(mdc::CanvasItem *target, const Point &point)
 
192
{
 
193
  if (!_hub || !_hub->figure_enter(_represented_object, target, point))
 
194
    return super::on_enter(target, point);
 
195
  return false;
 
196
}
 
197
 
 
198
 
 
199
bool LayerAreaGroup::on_leave(mdc::CanvasItem *target, const Point &point)
 
200
{
 
201
  if (!_hub || !_hub->figure_leave(_represented_object, target, point))
 
202
    return super::on_leave(target, point);
 
203
  return false;
 
204
}
 
205
 
 
206
#define TEXT_PADDING 5
 
207
 
 
208
void LayerAreaGroup::render(mdc::CairoCtx *cr)
 
209
{
 
210
  mdc::AreaGroup::render(cr);
 
211
 
 
212
  if (_extents_invalid)
 
213
  {
 
214
    cr->get_text_extents(_font, _title, _extents);
 
215
    _extents_invalid= false;
 
216
  }
 
217
 
 
218
  Size size= get_title_bounds().size;
 
219
 
 
220
  cr->save();
 
221
  cr->translate(get_position());
 
222
  cr->set_color(_title_back);
 
223
  cr->new_path();
 
224
  cr->move_to(Point(0, 0));
 
225
  cr->line_to(Point(size.width, 0));
 
226
  cr->line_to(Point(size.width, size.height-5));
 
227
  cr->line_to(Point(size.width-5, size.height));
 
228
  cr->line_to(Point(0, size.height));
 
229
  cr->close_path();
 
230
  cr->fill();
 
231
 
 
232
  cr->set_color(_title_fore);
 
233
  cr->move_to(Point(TEXT_PADDING + _extents.x_bearing, TEXT_PADDING - _extents.y_bearing));
 
234
  cr->set_font(_font);
 
235
  cr->show_text(_title);
 
236
  
 
237
  cr->restore();
 
238
}
 
239
 
 
240
//--------------------------------------------------------------------------------------------------
 
241
 
 
242
void LayerAreaGroup::render_gl(mdc::CairoCtx *cr) 
 
243
 
244
  mdc::AreaGroup::render_gl(cr); 
 
245
 
 
246
  if (_extents_invalid) 
 
247
  { 
 
248
    cr->get_text_extents(_font, _title, _extents); 
 
249
    _extents_invalid= false; 
 
250
  } 
 
251
 
 
252
  Size size= get_title_bounds().size; 
 
253
  Point text_position= Point(_extents.x_bearing, -_extents.y_bearing);
 
254
 
 
255
  // Render caption for the layer figure. This is done via Cairo and a texture.
 
256
  bool generate_display_list= _display_list == 0;
 
257
 
 
258
  // Check if we need to regenerate the cache. if so, do it and load it as a texture.
 
259
  Size texture_size= get_texture_size(size);
 
260
  if (_needs_render || _text_texture == 0)
 
261
  {
 
262
    generate_display_list= true;
 
263
 
 
264
    // Create a temporary surface we can render the text into.
 
265
    cairo_surface_t* surface= cairo_image_surface_create(CAIRO_FORMAT_ARGB32, (unsigned int) texture_size.width, (unsigned int) texture_size.height);
 
266
    _layer->get_view()->bookkeep_cache_mem(cairo_image_surface_get_stride(surface) * cairo_image_surface_get_height(surface));
 
267
    memset(cairo_image_surface_get_data(surface), 0,
 
268
           cairo_image_surface_get_stride(surface) * cairo_image_surface_get_height(surface));
 
269
 
 
270
    // Create a context for the temporary surface and render the text.
 
271
    mdc::CairoCtx texture_context(surface);
 
272
    texture_context.set_color(_title_fore); 
 
273
    texture_context.move_to(text_position); 
 
274
    texture_context.set_font(_font); 
 
275
    texture_context.show_text(_title); 
 
276
    _needs_render= false;
 
277
 
 
278
    if (_text_texture == 0)
 
279
      glGenTextures(1, &_text_texture);
 
280
 
 
281
    // setup the texture
 
282
    glBindTexture(GL_TEXTURE_2D, _text_texture);
 
283
    
 
284
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 
285
 
 
286
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
287
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 
288
    // don't tile the image
 
289
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
 
290
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
291
 
 
292
    // load the texture into opengl
 
293
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, (int) texture_size.width,  (int) texture_size.height, 0,
 
294
      GL_BGRA, GL_UNSIGNED_BYTE, cairo_image_surface_get_data(surface));
 
295
 
 
296
    // Once we transferred the pixel data we don't need the cache anymore.
 
297
    _layer->get_view()->bookkeep_cache_mem(-cairo_image_surface_get_stride(surface) * cairo_image_surface_get_height(surface));
 
298
    cairo_surface_destroy(surface);
 
299
  }
 
300
 
 
301
  glMatrixMode(GL_MODELVIEW);
 
302
  glPushMatrix(); 
 
303
  glTranslated(get_position().x, get_position().y, 0); 
 
304
 
 
305
  if (generate_display_list)
 
306
  {
 
307
    if (_display_list == 0)
 
308
      _display_list= glGenLists(1);
 
309
 
 
310
    glNewList(_display_list, GL_COMPILE);
 
311
 
 
312
    mdc::gl_setcolor(_title_back); 
 
313
   
 
314
    glBegin(GL_POLYGON); 
 
315
      glVertex2f(0.0, 0.0); 
 
316
      glVertex2d(size.width, 0); 
 
317
      glVertex2d(size.width, size.height - 5); 
 
318
      glVertex2d(size.width - 5, size.height); 
 
319
      glVertex2d(0, size.height); 
 
320
    glEnd(); 
 
321
   
 
322
    glEnable(GL_TEXTURE_2D);
 
323
    
 
324
    // Render the texture.
 
325
    glBindTexture(GL_TEXTURE_2D, _text_texture);
 
326
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 
327
    glTranslated(TEXT_PADDING, TEXT_PADDING, 0);
 
328
    glBegin(GL_QUADS);
 
329
 
 
330
    // Due to round-up to power of two the actual texture coordinates are usually somewhere within the actual texture.
 
331
    cairo_user_to_device_distance(_layer->get_view()->cairoctx()->get_cr(), &size.width, &size.height);
 
332
 
 
333
    double max_x_coordinate= size.width / texture_size.width;
 
334
    double max_y_coordinate= size.height / texture_size.height;
 
335
 
 
336
    glTexCoord2d(0, 0);
 
337
    glVertex2d(0, 0);
 
338
 
 
339
    glTexCoord2d(max_x_coordinate, 0);
 
340
    glVertex2d(size.width, 0);
 
341
 
 
342
    glTexCoord2d(max_x_coordinate, max_y_coordinate);
 
343
    glVertex2d(size.width, size.height);
 
344
 
 
345
    glTexCoord2d(0, max_y_coordinate);
 
346
    glVertex2d(0, size.height);
 
347
 
 
348
    glEnd();
 
349
    glDisable(GL_TEXTURE_2D);
 
350
 
 
351
    glEndList();
 
352
  }
 
353
 
 
354
  glCallList(_display_list);
 
355
 
 
356
  glPopMatrix();
 
357
 
358
 
 
359
Rect LayerAreaGroup::get_title_bounds() const
 
360
{
 
361
  Rect rect;
 
362
  
 
363
  double width= _extents.width + 10;
 
364
  if (width < MIN_LAYER_TITLE_WIDTH)
 
365
    width= MIN_LAYER_TITLE_WIDTH;
 
366
  
 
367
  Size size= get_size();
 
368
 
 
369
  if (width > size.width - _extents.height - 2 * TEXT_PADDING)
 
370
    width= size.width - _extents.height - 2 * TEXT_PADDING;
 
371
 
 
372
  rect.size.width= width + 2 * TEXT_PADDING;
 
373
  rect.size.height= _extents.height + 2 * TEXT_PADDING;
 
374
 
 
375
  return rect;
 
376
}
 
377
 
 
378