2
* Copyright (c) 2007, 2011, 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
21
#include "layer_figure.h"
22
#include "figure_common.h"
23
#include <grts/structs.model.h>
26
using namespace wbfig;
27
using namespace MySQL::Geometry;
28
using namespace MySQL::Drawing;
30
#define MIN_LAYER_TITLE_WIDTH 120.0
31
#define MIN_LAYER_SIZE 10.0
33
//--------------------------------------------------------------------------------------------------
35
LayerAreaGroup::LayerAreaGroup(mdc::Layer *layer, FigureEventHub *hub, model_Object *represented_object)
36
: mdc::AreaGroup(layer), _hub(hub), _represented_object(represented_object)
38
set_cache_toplevel_contents(false);
40
set_auto_sizing(false);
41
// set_background(_layer_back);
44
_extents_invalid= true;
46
_font= layer->get_view()->get_default_font();
47
_font.weight= mdc::WBold;
49
_title_fore= Color::Black();
50
_title_back= Color(0.85, 0.85, 0.85);
52
_min_size.width= MIN_LAYER_SIZE;
53
_min_size.height= MIN_LAYER_SIZE;
55
_drag_selects_contents= true;
63
//--------------------------------------------------------------------------------------------------
65
LayerAreaGroup::~LayerAreaGroup()
67
if (_display_list != 0)
68
glDeleteLists(_display_list, 1);
70
if (_text_texture != 0)
71
glDeleteTextures(1, &_text_texture);
74
//--------------------------------------------------------------------------------------------------
76
void LayerAreaGroup::set_title(const std::string &title)
79
_extents_invalid= true;
84
void LayerAreaGroup::set_font(const mdc::FontSpec &font)
87
_extents_invalid= true;
92
static void get_bounding_area(mdc::CanvasItem *item, Point *maxpos)
94
Rect bounds= item->get_bounds();
96
maxpos->x= max(maxpos->x, bounds.right());
97
maxpos->y= max(maxpos->y, bounds.bottom());
101
void LayerAreaGroup::move_item(mdc::CanvasItem *item, const Point &pos)
107
bool LayerAreaGroup::on_drag_handle(mdc::ItemHandle *handle, const Point &pos, bool dragging)
109
//Point offset= pos - get_view()->snap_to_grid(handle->get_position());
110
Point npos= get_position();
111
Size nsize= get_size();
117
_initial_bounds= get_root_bounds();
120
foreach(boost::bind(get_bounding_area, _1, &maxpos));
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;
127
bool flag= mdc::AreaGroup::on_drag_handle(handle, get_view()->snap_to_grid(pos), dragging);
132
_min_size.width= MIN_LAYER_SIZE;
133
_min_size.height= MIN_LAYER_SIZE;
134
_min_size_invalid= false;
136
_resize_signal(_initial_bounds);
143
bool LayerAreaGroup::on_button_press(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
145
if (mdc::bounds_contain_point(get_title_bounds(), point.x, point.y))
147
_drag_selects_contents= false;
150
if (!_hub || !_hub->figure_button_release(_represented_object, target, point, button, state))
151
return super::on_button_press(target, point, button, state);
157
bool LayerAreaGroup::on_button_release(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
161
if (!_hub || !_hub->figure_button_release(_represented_object, target, point, button, state))
162
ret= super::on_button_release(target, point, button, state);
164
_drag_selects_contents= true;
169
//--------------------------------------------------------------------------------------------------
171
bool LayerAreaGroup::on_click(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
173
if (!_hub || !_hub->figure_click(_represented_object, target, point, button, state))
174
return mdc::AreaGroup::on_click(target, point, button, state);
179
//--------------------------------------------------------------------------------------------------
181
bool LayerAreaGroup::on_double_click(mdc::CanvasItem *target, const Point &point, mdc::MouseButton button, mdc::EventState state)
183
if (!_hub || !_hub->figure_double_click(_represented_object, target, point, button, state))
184
return mdc::AreaGroup::on_double_click(target, point, button, state);
189
//--------------------------------------------------------------------------------------------------
191
bool LayerAreaGroup::on_enter(mdc::CanvasItem *target, const Point &point)
193
if (!_hub || !_hub->figure_enter(_represented_object, target, point))
194
return super::on_enter(target, point);
199
bool LayerAreaGroup::on_leave(mdc::CanvasItem *target, const Point &point)
201
if (!_hub || !_hub->figure_leave(_represented_object, target, point))
202
return super::on_leave(target, point);
206
#define TEXT_PADDING 5
208
void LayerAreaGroup::render(mdc::CairoCtx *cr)
210
mdc::AreaGroup::render(cr);
212
if (_extents_invalid)
214
cr->get_text_extents(_font, _title, _extents);
215
_extents_invalid= false;
218
Size size= get_title_bounds().size;
221
cr->translate(get_position());
222
cr->set_color(_title_back);
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));
232
cr->set_color(_title_fore);
233
cr->move_to(Point(TEXT_PADDING + _extents.x_bearing, TEXT_PADDING - _extents.y_bearing));
235
cr->show_text(_title);
240
//--------------------------------------------------------------------------------------------------
242
void LayerAreaGroup::render_gl(mdc::CairoCtx *cr)
244
mdc::AreaGroup::render_gl(cr);
246
if (_extents_invalid)
248
cr->get_text_extents(_font, _title, _extents);
249
_extents_invalid= false;
252
Size size= get_title_bounds().size;
253
Point text_position= Point(_extents.x_bearing, -_extents.y_bearing);
255
// Render caption for the layer figure. This is done via Cairo and a texture.
256
bool generate_display_list= _display_list == 0;
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)
262
generate_display_list= true;
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));
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;
278
if (_text_texture == 0)
279
glGenTextures(1, &_text_texture);
282
glBindTexture(GL_TEXTURE_2D, _text_texture);
284
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
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);
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));
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);
301
glMatrixMode(GL_MODELVIEW);
303
glTranslated(get_position().x, get_position().y, 0);
305
if (generate_display_list)
307
if (_display_list == 0)
308
_display_list= glGenLists(1);
310
glNewList(_display_list, GL_COMPILE);
312
mdc::gl_setcolor(_title_back);
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);
322
glEnable(GL_TEXTURE_2D);
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);
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);
333
double max_x_coordinate= size.width / texture_size.width;
334
double max_y_coordinate= size.height / texture_size.height;
339
glTexCoord2d(max_x_coordinate, 0);
340
glVertex2d(size.width, 0);
342
glTexCoord2d(max_x_coordinate, max_y_coordinate);
343
glVertex2d(size.width, size.height);
345
glTexCoord2d(0, max_y_coordinate);
346
glVertex2d(0, size.height);
349
glDisable(GL_TEXTURE_2D);
354
glCallList(_display_list);
359
Rect LayerAreaGroup::get_title_bounds() const
363
double width= _extents.width + 10;
364
if (width < MIN_LAYER_TITLE_WIDTH)
365
width= MIN_LAYER_TITLE_WIDTH;
367
Size size= get_size();
369
if (width > size.width - _extents.height - 2 * TEXT_PADDING)
370
width= size.width - _extents.height - 2 * TEXT_PADDING;
372
rect.size.width= width + 2 * TEXT_PADDING;
373
rect.size.height= _extents.height + 2 * TEXT_PADDING;