~ubuntu-branches/ubuntu/quantal/glom/quantal

« back to all changes in this revision

Viewing changes to glom/mode_design/print_layouts/canvas_layout_item.cc

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2009-01-11 17:12:01 UTC
  • mfrom: (1.1.39 upstream)
  • Revision ID: james.westby@ubuntu.com-20090111171201-0ov9zh1fxfueshxc
Tags: 1.8.5-0ubuntu1
* New upstream release (LP: #256701), fixes LP bugs: 
  + Clear the text in property dialogs for text items (LP: #309147)
  + Don't crash when showing and then hiding the grid (LP: #303453)
  + Temporarily remember the sort order so it is the same when navigating 
    away and back (LP: #303422)
  + Use the list's sort order for the top-level records in the report 
    (LP: #303425)
  + Users/Groups: Disable drag-and-drop for the treeview, because it is
    useless and confusing (LP: #299573)
  + Import: Sort the fields list alphabetically (LP: #306593)
  + delete primary key make unusuable the database (LP: #299549)
  + Spanish translate incomplete (LP: #299556)
  + import date format error (LP: #299591)
  + can't delete data from table list view (LP: #299853)
  + Field definition: default value not saved (LP: #299896)
  + reports crashing (LP: #300054)
  + Year error with date fields (LP: #300057)
  + list view: 2 records added instead of 1 (LP: #300819)
* debian/control: Refreshed dependencies for libglom-dev.
* debian/control: Updated build-deps to match configure checks. goocavnasmm
  build-dep bumped to version without .la files.
* debian/rules: Don't delete the directory containing the templates.
* debian/control, debian/rules, debian/glom-doc.*: Split out
  arch-independent manual and examples into separate package glom-doc, which
  is now recommended by glom (glom will still work if they're not available)
* debian/copyright: Rewritten to new machine-readable format. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Glom
 
2
 *
 
3
 * Copyright (C) 2001-2004 Murray Cumming
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License as
 
7
 * published by the Free Software Foundation; either version 2 of the
 
8
 * License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public
 
16
 * License along with this program; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include "canvas_layout_item.h"
 
22
#include <glom/utility_widgets/canvas/canvas_rect_movable.h>
 
23
#include <glom/utility_widgets/canvas/canvas_text_movable.h>
 
24
#include <glom/utility_widgets/canvas/canvas_image_movable.h>
 
25
#include <glom/utility_widgets/canvas/canvas_line_movable.h>
 
26
#include <glom/utility_widgets/canvas/canvas_group_movable.h>
 
27
#include <glom/utility_widgets/canvas/canvas_table_movable.h>
 
28
#include <glom/libglom/data_structure/layout/layoutitem_button.h>
 
29
#include <glom/libglom/data_structure/layout/layoutitem_text.h>
 
30
#include <glom/libglom/data_structure/layout/layoutitem_image.h>
 
31
#include <glom/libglom/data_structure/layout/layoutitem_field.h>
 
32
#include <glom/libglom/data_structure/layout/layoutitem_line.h>
 
33
#include <glom/libglom/data_structure/layout/layoutitem_portal.h>
 
34
#include <glom/libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
 
35
#include <glom/libglom/data_structure/glomconversions.h>
 
36
#include <glibmm/i18n.h>
 
37
#include <math.h>
 
38
#include <algorithm> //For std::max().
 
39
 
 
40
namespace Glom
 
41
{
 
42
 
 
43
CanvasLayoutItem::CanvasLayoutItem()
 
44
{
 
45
  //Rescale images when the canvas item is resized:
 
46
  signal_resized().connect( sigc::mem_fun(*this, &CanvasLayoutItem::on_resized) );
 
47
}
 
48
 
 
49
CanvasLayoutItem::CanvasLayoutItem(const sharedptr<LayoutItem>& layout_item)
 
50
{
 
51
  set_layout_item(layout_item);
 
52
 
 
53
  //Rescale images when the canvas item is resized:
 
54
  signal_resized().connect( sigc::mem_fun(*this, &CanvasLayoutItem::on_resized) );
 
55
}
 
56
 
 
57
CanvasLayoutItem::~CanvasLayoutItem()
 
58
{
 
59
}
 
60
 
 
61
Glib::RefPtr<CanvasLayoutItem> CanvasLayoutItem::create()
 
62
{
 
63
  return Glib::RefPtr<CanvasLayoutItem>(new CanvasLayoutItem());
 
64
}
 
65
 
 
66
Glib::RefPtr<CanvasLayoutItem> CanvasLayoutItem::create(const sharedptr<LayoutItem>& layout_item)
 
67
{
 
68
  return Glib::RefPtr<CanvasLayoutItem>(new CanvasLayoutItem(layout_item));
 
69
}
 
70
 
 
71
sharedptr<LayoutItem> CanvasLayoutItem::get_layout_item()
 
72
{
 
73
  return m_layout_item;
 
74
}
 
75
 
 
76
void CanvasLayoutItem::check_and_apply_formatting(const Glib::RefPtr<CanvasTextMovable>& canvas_item, FieldFormatting& formatting)
 
77
{
 
78
  if(!canvas_item)
 
79
    return;
 
80
 
 
81
  Glib::ustring font = formatting.get_text_format_font();
 
82
  if(font.empty())
 
83
  {
 
84
    font = "Serif 9";
 
85
 
 
86
    //Set it in the input parameter,
 
87
    //so that this is the default:
 
88
    formatting.set_text_format_font(font);    
 
89
  }
 
90
 
 
91
  canvas_item->set_font_points(font);
 
92
 
 
93
  //TODO: Are these sensible properties? Maybe we need to use markup:
 
94
  const Glib::ustring fg = formatting.get_text_format_color_foreground();
 
95
  if(!fg.empty())
 
96
    canvas_item->property_stroke_color() = fg;
 
97
 
 
98
  const Glib::ustring bg = formatting.get_text_format_color_background();
 
99
  if(!bg.empty())
 
100
    canvas_item->property_fill_color() = bg;
 
101
}
 
102
 
 
103
void CanvasLayoutItem::on_resized()
 
104
{
 
105
  Glib::RefPtr<CanvasImageMovable> canvas_image = Glib::RefPtr<CanvasImageMovable>::cast_dynamic(get_child());
 
106
  if(canvas_image)
 
107
    canvas_image->scale_to_size();
 
108
}
 
109
 
 
110
void CanvasLayoutItem::set_layout_item(const sharedptr<LayoutItem>& layout_item)
 
111
{
 
112
  //Add the new child:
 
113
  m_layout_item = layout_item;
 
114
 
 
115
  if(!m_layout_item)
 
116
    std::cerr << "CanvasLayoutItem::set_layout_item(): item was NULL." << std::endl;
 
117
 
 
118
  Glib::RefPtr<CanvasItemMovable> child_item = create_canvas_item_for_layout_item(m_layout_item);
 
119
 
 
120
  if(child_item)
 
121
  {
 
122
    //child_item->property_pointer_events() = 
 
123
    //  (Goocanvas::PointerEvents)(Goocanvas::EVENTS_VISIBLE_FILL & GOO_CANVAS_EVENTS_VISIBLE_STROKE);
 
124
      
 
125
    //Set the position and dimensions of this group to match the child:
 
126
    double x = 0;
 
127
    double y = 0;
 
128
    double width = 0;
 
129
    double height = 0;
 
130
    m_layout_item->get_print_layout_position(x, y, width, height);
 
131
 
 
132
    set_xy(x, y);
 
133
    set_width_height(width, height);
 
134
    //std::cout << "CanvasLayoutItem::set_layout_item(): item x=" << x << std::endl;
 
135
 
 
136
    set_child(child_item);
 
137
  }
 
138
 
 
139
  //Scale images.
 
140
  //This can only be done after setting the size:
 
141
  Glib::RefPtr<CanvasImageMovable> canvas_image = Glib::RefPtr<CanvasImageMovable>::cast_dynamic(child_item);
 
142
  if(canvas_image)
 
143
  {
 
144
    canvas_image->scale_to_size();
 
145
  }
 
146
}
 
147
 
 
148
int CanvasLayoutItem::get_rows_count_for_portal(const sharedptr<const LayoutItem_Portal>& portal, double& row_height)
 
149
{
 
150
  if(!portal)
 
151
  {
 
152
    row_height = 0;
 
153
    return 0;
 
154
  }
 
155
 
 
156
  row_height = std::max(portal->get_print_layout_row_height(), (double)1); //Avoid 0, because that makes the whole thing zero sized.
 
157
 
 
158
  double ignore_x = 0;
 
159
  double ignore_y = 0;
 
160
  double total_width = 0;
 
161
  double total_height = 0;
 
162
  portal->get_print_layout_position(ignore_x, ignore_y, total_width, total_height);
 
163
 
 
164
  const double max_rows_fraction = total_height / row_height;
 
165
  double max_rows = 0;
 
166
  modf(max_rows_fraction, &max_rows);
 
167
 
 
168
  return max_rows;
 
169
}
 
170
 
 
171
Glib::RefPtr<CanvasItemMovable> CanvasLayoutItem::create_canvas_item_for_layout_item(const sharedptr<LayoutItem>& layout_item)
 
172
{
 
173
  sharedptr<LayoutItem_Line> line;
 
174
 
 
175
  Glib::RefPtr<CanvasItemMovable> child;
 
176
  Glib::RefPtr<Goocanvas::Item> child_item;
 
177
  sharedptr<LayoutItem_Text> text = sharedptr<LayoutItem_Text>::cast_dynamic(layout_item);
 
178
  if(text)
 
179
  {
 
180
    Glib::RefPtr<CanvasTextMovable> canvas_item = CanvasTextMovable::create();
 
181
    canvas_item->property_line_width() = 0;
 
182
 
 
183
    FieldFormatting& formatting = text->m_formatting;
 
184
    check_and_apply_formatting(canvas_item, formatting);
 
185
 
 
186
    canvas_item->set_text(text->get_text());
 
187
    child = canvas_item;
 
188
    child_item = canvas_item;
 
189
  }
 
190
  else
 
191
  {
 
192
    sharedptr<LayoutItem_Image> image = sharedptr<LayoutItem_Image>::cast_dynamic(layout_item);
 
193
    if(image)
 
194
    {
 
195
      Glib::RefPtr<CanvasImageMovable> canvas_item = CanvasImageMovable::create();
 
196
      Glib::RefPtr<Gdk::Pixbuf> pixbuf = image->get_image_as_pixbuf();
 
197
      if(pixbuf)
 
198
        canvas_item->set_image(pixbuf);
 
199
      else
 
200
        canvas_item->set_image_empty(); //show a no-image picture.
 
201
 
 
202
      canvas_item->property_fill_color() = "white"; //This makes the whole area clickable, not just the outline stroke.
 
203
      child = canvas_item;
 
204
      child_item = canvas_item;
 
205
    }
 
206
    else
 
207
    {
 
208
      sharedptr<LayoutItem_Line> line = sharedptr<LayoutItem_Line>::cast_dynamic(layout_item);
 
209
      if(line)
 
210
      {
 
211
        double start_x = 0;
 
212
        double start_y = 0;
 
213
        double end_x  = 0;
 
214
        double end_y = 0;
 
215
        line->get_coordinates(start_x, start_y, end_x, end_y);
 
216
        
 
217
        Glib::RefPtr<CanvasLineMovable> canvas_item = CanvasLineMovable::create();
 
218
        canvas_item->property_line_width() = 1;
 
219
        canvas_item->property_stroke_color() = "black";
 
220
 
 
221
        Goocanvas::Points points(2);
 
222
        points.set_coordinate(0, start_x, start_y);
 
223
        points.set_coordinate(0, end_x, end_y);
 
224
        canvas_item->property_points() = points;
 
225
        child = canvas_item;
 
226
        child_item = canvas_item;
 
227
      }
 
228
      else
 
229
      {
 
230
        sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(layout_item);
 
231
        if(field)
 
232
        {
 
233
          //Create an appropriate canvas item for the field type:
 
234
          if(field->get_glom_type() == Field::TYPE_IMAGE)
 
235
          {
 
236
            Glib::RefPtr<CanvasImageMovable> canvas_item = CanvasImageMovable::create();
 
237
            canvas_item->set_image_empty();
 
238
 
 
239
            child = canvas_item;
 
240
            child_item = canvas_item;
 
241
          }
 
242
          else //text, numbers, date, time, boolean:
 
243
          {
 
244
            Glib::RefPtr<CanvasTextMovable> canvas_item = CanvasTextMovable::create();
 
245
            canvas_item->property_line_width() = 0;
 
246
         
 
247
            FieldFormatting& formatting = field->m_formatting;
 
248
            check_and_apply_formatting(canvas_item, formatting);
 
249
 
 
250
            Glib::ustring name = field->get_name();
 
251
            if(name.empty())
 
252
              name = _("Choose Field");
 
253
          
 
254
            canvas_item->set_text(name);
 
255
 
 
256
            child = canvas_item;
 
257
            child_item = canvas_item;
 
258
          }
 
259
        }
 
260
        else
 
261
        {
 
262
          sharedptr<LayoutItem_Portal> portal = sharedptr<LayoutItem_Portal>::cast_dynamic(layout_item);
 
263
          if(portal)
 
264
          {
 
265
            Glib::RefPtr<CanvasTableMovable> canvas_item = CanvasTableMovable::create();
 
266
            canvas_item->property_vert_grid_line_width() = 1;
 
267
            canvas_item->property_horz_grid_line_width() = 1;
 
268
            canvas_item->property_stroke_color() = "black";
 
269
 
 
270
            //Show as many rows as can fit in the height.
 
271
            double row_height = 0;
 
272
            const int max_rows = get_rows_count_for_portal(portal, row_height);
 
273
 
 
274
            const LayoutGroup::type_list_items child_items = portal->get_items();
 
275
 
 
276
            for(guint row = 0; row < (guint)max_rows; ++row)
 
277
            {
 
278
              guint col = 0;
 
279
              for(LayoutGroup::type_list_items::const_iterator iter = child_items.begin(); iter != child_items.end(); ++iter)
 
280
              {
 
281
                sharedptr<LayoutItem> layout_item = *iter;
 
282
 
 
283
                //We use create_canvas_item_for_layout_item() instead of just 
 
284
                //creating another CanvasLayoutItem, because that would be a group,
 
285
                //but goocanvas cannot yet support Groups inside Tables. murrayc.
 
286
                //TODO: Bug number.
 
287
                Glib::RefPtr<CanvasItemMovable> cell = create_canvas_item_for_layout_item(layout_item);
 
288
                if(cell)
 
289
                {
 
290
                  //Make sure that the width is sensible:
 
291
                  guint width = 0;
 
292
                  layout_item->get_display_width(width);
 
293
                  width = std::max(width, (guint)10);
 
294
                  cell->set_width_height(width, row_height);
 
295
                  std::cout << "DEBUG: width=" << width << std::endl;
 
296
 
 
297
                  //TODO: Add/Remove rows when resizing, instead of resizing the rows:
 
298
                  Glib::RefPtr<Goocanvas::Item> cell_as_item = CanvasItemMovable::cast_to_item(cell);
 
299
                  if(cell_as_item)
 
300
                  {
 
301
                    canvas_item->attach(cell_as_item, 
 
302
                      col /* left_attach */, col+1 /* right_attach */, 
 
303
                      row /* top_attach */, row + 1 /* right_attach */, 
 
304
                      Gtk::FILL, (Gtk::AttachOptions)Gtk::FILL | Gtk::EXPAND);
 
305
                  }
 
306
                }
 
307
 
 
308
                ++col;
 
309
              }
 
310
            }
 
311
 
 
312
            child = canvas_item;
 
313
            child_item = canvas_item;
 
314
          }
 
315
          else if(layout_item)
 
316
          {
 
317
            std::cerr << "CanvasLayoutItem::set_layout_item(): Unhandled LayoutItem type. part type=" << layout_item->get_part_type_name() << std::endl;
 
318
          }
 
319
          else
 
320
          {
 
321
            std::cerr << "CanvasLayoutItem::set_layout_item(): NULL LayoutItem type." << std::endl;
 
322
          }
 
323
        }
 
324
      }
 
325
    }
 
326
  }
 
327
 
 
328
  return child;
 
329
 
 
330
  if(child && child_item)
 
331
  {
 
332
    //child_item->property_pointer_events() = 
 
333
    //  (Goocanvas::PointerEvents)(Goocanvas::EVENTS_VISIBLE_FILL & GOO_CANVAS_EVENTS_VISIBLE_STROKE);
 
334
      
 
335
    //Set the position and dimensions of this group to match the child:
 
336
    double x = 0;
 
337
    double y = 0;
 
338
    double width = 0;
 
339
    double height = 0;
 
340
    layout_item->get_print_layout_position(x, y, width, height);
 
341
    child->set_width_height(width, height);
 
342
    //std::cout << "CanvasLayoutItem::set_layout_item(): item x=" << x << std::endl;
 
343
  }
 
344
 
 
345
  //Scale images.
 
346
  //This can only be done after setting the size:
 
347
  Glib::RefPtr<CanvasImageMovable> canvas_image = Glib::RefPtr<CanvasImageMovable>::cast_dynamic(child);
 
348
  if(canvas_image)
 
349
  {
 
350
    canvas_image->scale_to_size();
 
351
 
 
352
    //It will also be rescaled when this canvas item is resized - see on_resized().
 
353
  }
 
354
 
 
355
  return child;
 
356
}
 
357
 
 
358
void CanvasLayoutItem::set_db_data(const Gnome::Gda::Value& value)
 
359
{
 
360
  sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(m_layout_item);
 
361
  if(!field)
 
362
    return;
 
363
    
 
364
  Glib::RefPtr<CanvasItemMovable> child = get_child();
 
365
  if(!child)
 
366
    return;
 
367
  
 
368
  const Field::glom_field_type field_type = field->get_glom_type();
 
369
  switch(field->get_glom_type())
 
370
  {
 
371
    case(Field::TYPE_TEXT):
 
372
    case(Field::TYPE_NUMERIC):
 
373
    case(Field::TYPE_BOOLEAN):
 
374
    case(Field::TYPE_TIME):
 
375
    case(Field::TYPE_DATE):
 
376
    {
 
377
      Glib::RefPtr<CanvasTextMovable> canvas_item = Glib::RefPtr<CanvasTextMovable>::cast_dynamic(child);
 
378
      if(!canvas_item)
 
379
        return;
 
380
        
 
381
      Glib::ustring text_value = Conversions::get_text_for_gda_value(field_type, value, field->get_formatting_used().m_numeric_format);
 
382
 
 
383
      //The Postgres summary functions return NULL when summarising NULL records, but 0 is more sensible:
 
384
      if(text_value.empty() && sharedptr<const LayoutItem_FieldSummary>::cast_dynamic(field) && (field_type == Field::TYPE_NUMERIC))
 
385
      {
 
386
        //Use get_text_for_gda_value() instead of "0" so we get the correct numerical formatting:
 
387
        Gnome::Gda::Value value = Conversions::parse_value(0);
 
388
        text_value = Conversions::get_text_for_gda_value(field_type, value, field->get_formatting_used().m_numeric_format);
 
389
      }
 
390
    
 
391
      canvas_item->set_text(text_value);
 
392
      break;
 
393
    }
 
394
    case(Field::TYPE_IMAGE):
 
395
    {
 
396
      Glib::RefPtr<CanvasImageMovable> canvas_item = Glib::RefPtr<CanvasImageMovable>::cast_dynamic(child);
 
397
      if(!canvas_item)
 
398
        return;
 
399
        
 
400
      //Get the height of the item (not of the pixbuf),
 
401
      //so we can scale the pixbuf:
 
402
      double width = 0;
 
403
      double height = 0;
 
404
      canvas_item->get_width_height(width, height);
 
405
      
 
406
      Glib::RefPtr<Gdk::Pixbuf> pixbuf = Conversions::get_pixbuf_for_gda_value(value);
 
407
      if(pixbuf) //TODO: Remove this if() check when goocanvas has my patch to avoid crashes when this is NULL.
 
408
        canvas_item->set_image(pixbuf);
 
409
     
 
410
      break;
 
411
    }
 
412
    default:
 
413
      std::cerr << "CanvasLayoutItem::set_db_data(): unhandled field type." << std::endl;
 
414
  }
 
415
        
 
416
}
 
417
 
 
418
void CanvasLayoutItem::remove_empty_indicators()
 
419
{
 
420
  Glib::RefPtr<CanvasItemMovable> child = get_child();
 
421
  Glib::RefPtr<CanvasImageMovable> canvas_image = Glib::RefPtr<CanvasImageMovable>::cast_dynamic(child);
 
422
  if(canvas_image)
 
423
  {
 
424
    //Clear the no-image pixbuf from images:
 
425
    if(canvas_image->get_image_empty())
 
426
    {
 
427
      Glib::RefPtr<Gdk::Pixbuf> really_empty;
 
428
      canvas_image->property_pixbuf() = really_empty;
 
429
    }
 
430
  }
 
431
}
 
432
 
 
433
} //namespace Glom
 
434