1 /*
2  * C++ wrapper of DiagramData - just to have something clean to wrap
3  *
4  * Copyright (C) 2007, Hans Breuer, <Hans@Breuer.Org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20 #include "object.h"
21 #include "diagramdata.h"
22 #include <assert.h>
23 
24 #include "dia-object.h"
25 
26 #include "dia-diagramdata.h"
27 
28 //! how many contained
29 int
len() const30 dia::Objects::len () const
31 {
32     if (list)
33         return g_list_length(*list);
34     return 0;
35 }
36 //! \brief return back a single one
37 //! Together with len() getitem() allows list access. The code generator needs some
38 //! extra help to not making it an endless list. At least for Python the NULL return
39 //! was turned into None objects, we want to have only as much list elements
40 //! as there are real objects.
41 dia::Object*
getitem(int n) const42 dia::Objects::getitem (int n) const
43 {
44     if (list && n >= 0 && n < g_list_length(*list))
45         return new dia::Object((::DiaObject*)g_list_nth_data(*list, n));
46     return 0;
47 }
48 
49 //! construct with underlying list of objects
50 //! \todo check ownership/lifetime of that list!
Layer(::Layer * layer)51 dia::Layer::Layer (::Layer* layer) : self(layer), _found(0)
52 {
53     assert (self);
54     // todo: when we allow to change the name this needs to change
55     name = g_strdup (self->name);
56     objects = new dia::Objects(&(layer->objects));
57 }
~Layer()58 dia::Layer::~Layer ()
59 {
60     if (_found)
61         delete _found;
62     if (name)
63         g_free (const_cast<gchar*>(name));
64     if (objects)
65       delete const_cast<dia::Objects*>(objects);
66 }
67 void
add_object(Object * o)68 dia::Layer::add_object (Object* o)
69 {
70     g_return_if_fail (self != NULL);
71     layer_add_object (self, o->Self());
72 }
73 void
update_extents()74 dia::Layer::update_extents ()
75 {
76     g_return_if_fail (self != NULL);
77     layer_update_extents(self);
78 }
79 //! the object next to given point but within maxdist
80 dia::Object*
find_closest_object(::Point * pos,double maxdist) const81 dia::Layer::find_closest_object (::Point* pos, double maxdist) const
82 {
83     g_return_val_if_fail (self != NULL, 0);
84     ::DiaObject* o = layer_find_closest_object (self, pos, maxdist);
85     if (o)
86       return new dia::Object (o);
87     return 0;
88 }
89 //! a list of Object in the given rectangle
90 dia::Objects&
find_objects_in_rectangle(::Rectangle * rect) const91 dia::Layer::find_objects_in_rectangle (::Rectangle* rect) const
92 {
93     static GList* list = layer_find_objects_in_rectangle (self, rect);
94     if (_found)
95         delete _found;
96     const_cast<Layer*>(this)->_found = new dia::Objects (&list);
97     return *_found;
98 }
99  //! objects are kept in an ordered list, this is the index of the given object
100 int
object_index(Object * o) const101 dia::Layer::object_index (Object* o) const
102 {
103     g_return_val_if_fail (self != NULL, -1);
104     return layer_object_index (self, o->Self());
105 }
106 
107 int
len() const108 dia::Layers::len () const
109 {
110     if (list)
111         return (*list)->len;
112     return 0;
113 }
114 dia::Layer*
getitem(int n) const115 dia::Layers::getitem (int n) const
116 {
117   if (list && n >= 0 && n < (*list)->len)
118     return new dia::Layer(static_cast< ::Layer* >(g_ptr_array_index (*list, n)));
119   return 0;
120 }
121 
122 /*!
123  * DiagramData is the low level Diagram, i.e. everything without an UI
124  */
DiagramData()125 dia::DiagramData::DiagramData () : self(0), active_layer(0), _selected(0)
126 {
127     // the usual GObjetc cast DIA_DIAGRAM_DATA does not work when playing games with namespaces ;)
128     self = static_cast< ::DiagramData* > (g_object_new (DIA_TYPE_DIAGRAM_DATA, NULL));
129     //FIXME: grumpf
130     if (self->active_layer)
131       active_layer = new Layer(self->active_layer);
132     else if (self->layers->len > 0)
133       active_layer = new Layer((::Layer*)g_ptr_array_index(self->layers, 0));
134     layers = new Layers(&self->layers);
135 }
~DiagramData()136 dia::DiagramData::~DiagramData ()
137 {
138     g_object_unref (self);
139     if (_selected)
140         delete _selected;
141     if (layers)
142       delete const_cast< dia::Layers* >(layers);
143 }
144 
145 dia::Layer*
add_layer(const char * name)146 dia::DiagramData::add_layer (const char* name)
147 {
148     int pos = -1; //TODO: make this a parameter
149     g_return_val_if_fail (self != NULL, 0);
150     ::Layer* layer = new_layer(g_strdup(name),self);
151     if (pos != -1)
152 	data_add_layer_at(self, layer, pos);
153     else
154 	data_add_layer(self, layer);
155 
156     dia::Layer* dl = new dia::Layer (layer);
157     return dl;
158 }
159 void
update_extents()160 dia::DiagramData::update_extents ()
161 {
162     g_return_if_fail(self != NULL);
163     data_update_extents(self);
164     // conceptionally const, i.e. read-only
165     *const_cast< ::Rectangle* >(&extents) = self->extents;
166 }
167 dia::Objects&
get_sorted_selected() const168 dia::DiagramData::get_sorted_selected () const
169 {
170     if (_selected)
171         delete _selected;
172 
173     static GList* list = data_get_sorted_selected(self);
174     const_cast< DiagramData* >(this)->_selected = new dia::Objects (&list);
175     return *_selected;
176 }
177 
178