Fraxinus  16.5.0-fx-rc3
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxLayoutData.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxLayoutData.h"
34 #include <iostream>
35 #include <QDomElement>
36 #include "cxTypeConversions.h"
37 #include "cxLogger.h"
38 #include "cxDefinitionStrings.h"
39 #include "cxView.h"
40 
41 namespace cx
42 {
43 
45 {
46  if (a.pos.col<0 || a.pos.row<0)
47  return b;
48  if (b.pos.col<0 || b.pos.row<0)
49  return a;
50 
51  int r1 = std::min(a.pos.row, b.pos.row);
52  int c1 = std::min(a.pos.col, b.pos.col);
53  int r2 = std::max(a.pos.row + a.span.row - 1, b.pos.row + b.span.row - 1);
54  int c2 = std::max(a.pos.col + a.span.col - 1, b.pos.col + b.span.col - 1);
55  return LayoutRegion(r1, c1, r2 - r1 + 1, c2 - c1 + 1);
56 }
57 
58 void LayoutViewData::addXml(QDomNode node) const
59 {
60  QDomElement elem = node.toElement();
61  elem.setAttribute("group", qstring_cast(mGroup));
62  elem.setAttribute("type", qstring_cast(mPlane));
63  elem.setAttribute("view", qstring_cast(mType));
64  elem.setAttribute("row", qstring_cast(mRegion.pos.row));
65  elem.setAttribute("col", qstring_cast(mRegion.pos.col));
66  elem.setAttribute("rowSpan", qstring_cast(mRegion.span.row));
67  elem.setAttribute("colSpan", qstring_cast(mRegion.span.col));
68 }
69 
70 void LayoutViewData::parseXml(QDomNode node)
71 {
72  QDomElement elem = node.toElement();
73  mGroup = elem.attribute("group").toInt();
74  mPlane = string2enum<PLANE_TYPE> (elem.attribute("type"));
75  // mType = string2enum<View::Type>(elem.attribute("view"));
76  mType = static_cast<View::Type> (elem.attribute("view").toInt());
77  mRegion.pos.row = elem.attribute("row").toInt();
78  mRegion.pos.col = elem.attribute("col").toInt();
79  mRegion.span.row = elem.attribute("rowSpan").toInt();
80  mRegion.span.col = elem.attribute("colSpan").toInt();
81 }
82 
83 LayoutData LayoutData::createHeader(QString uid, QString name)
84 {
85  return create(uid, name, 0, 0);
86 }
87 
88 LayoutData LayoutData::create(QString uid, QString name, int rows, int cols)
89 {
90  LayoutData retval;
91  retval.resetUid(uid);
92  retval.setName(name);
93  retval.resize(rows, cols);
94  return retval;
95 }
96 
98  mName("unnamed")
99 {
100  mSize = LayoutPosition(0, 0);
101  this->resize(0, 0);
102 }
103 
104 void LayoutData::resetUid(const QString& uid)
105 {
106  mUid = uid;
107  mName = mName + " " + uid;
108 }
109 
113 void LayoutData::setView(int group, PLANE_TYPE type, LayoutRegion region)
114 {
115  if (!this->merge(region))
116  return;
117  LayoutViewData& view = get(region.pos);
118  view.mGroup = group;
119  view.mPlane = type;
120  view.mType = View::VIEW_2D;
121 }
122 
123 void LayoutData::setView(int group, View::Type type, LayoutRegion region)
124 {
125  if (!this->merge(region))
126  return;
127  LayoutViewData& view = get(region.pos);
128  view.mGroup = group;
129  view.mPlane = ptNOPLANE;
130  view.mType = type;
131 }
132 
139 {
140  if (region.pos.row + region.span.row > mSize.row || region.pos.col + region.span.col > mSize.col)
141  {
142  reportError("Attempted to merge a region outside allocated space in LayoutData.");
143  return false;
144  }
145 
146  //std::cout << "merge views " << std::endl;
147  this->split(region); // split all existing merges in order to keep consistency
148 
149  // create new merged view based on the ul corner view.
150  LayoutViewData current = this->get(region.pos);
151  current.mRegion = region;
152 
153  // erase all views within region (all should now be 1x1)
154  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
155  {
156  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
157  {
158  iterator iter = this->find(LayoutPosition(r, c));
159  if (iter != this->end())
160  mView.erase(iter);
161  }
162  }
163 
164  // add merged view.
165  mView.push_back(current);
166  return true;
167 }
168 
173 {
174  // reset all primitives in region
175  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
176  {
177  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
178  {
179  iterator iter = this->find(LayoutPosition(r, c));
180  this->split(iter);
181  }
182  }
183 }
184 
189 {
190  if (iter == this->end())
191  return;
192  if (iter->mRegion.span.row == 1 && iter->mRegion.span.col == 1)
193  return; // nothing to split
194 
195  LayoutViewData newView = *iter;
196  LayoutRegion region = iter->mRegion;
197 
198  // erase old region
199  mView.erase(iter);
200 
201  // insert new 1x1 views in the erased region.
202  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
203  {
204  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
205  {
206  newView.mRegion = LayoutRegion(r, c, 1, 1);
207  mView.push_back(newView);
208  }
209  }
210 }
211 
215 void LayoutData::resize(int rows, int cols)
216 {
217  mSize = LayoutPosition(rows, cols);
218 
219  if (mSize.row == 0 || mSize.col == 0)
220  {
221  mView.clear();
222  return;
223  }
224 
225  // erase all views outside region
226  // TODO: also consider nontrivial regions.
227  for (iterator iter = this->begin(); iter != this->end();)
228  {
229  if (iter->mRegion.pos.row >= rows || iter->mRegion.pos.col >= cols)
230  {
231  iter = mView.erase(iter);
232  }
233  else
234  {
235  ++iter;
236  }
237  }
238 
239  // add new views (brute force: optimize if needed)
240  for (int r = 0; r < rows; ++r)
241  {
242  for (int c = 0; c < cols; ++c)
243  {
244  if (this->find(LayoutPosition(r, c)) == this->end())
245  {
246  mView.push_back(LayoutViewData(r, c, 1, 1));
247  }
248  }
249  }
250 }
251 
252 //const LayoutData::ViewData& LayoutData::get(LayoutPosition pos) const
253 //{
254 // return *(this->find(pos));
255 //}
256 
258 {
259  return *(this->find(pos));
260 }
261 
263 {
264  for (iterator iter = this->begin(); iter != this->end(); ++iter)
265  {
266  if (iter->mRegion.contains(pos))
267  return iter;
268  }
269 
270  return this->end();
271 }
272 
273 void LayoutData::addXml(QDomNode node) const
274 {
275  QDomDocument doc = node.ownerDocument();
276  QDomElement elem = node.toElement();
277 
278  elem.setAttribute("uid", mUid);
279  elem.setAttribute("name", mName);
280 
281  QDomElement size = doc.createElement("size");
282  size.setAttribute("row", mSize.row);
283  size.setAttribute("col", mSize.col);
284  elem.appendChild(size);
285 
286  for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
287  {
288  QDomElement view = doc.createElement("view");
289  iter->addXml(view);
290  elem.appendChild(view);
291  }
292 }
293 
294 void LayoutData::parseXml(QDomNode node)
295 {
296  if (node.isNull())
297  return;
298 
299  QDomElement elem = node.toElement();
300  mUid = elem.attribute("uid");
301  mName = elem.attribute("name");
302 
303  QDomElement size = elem.namedItem("size").toElement();
304  mSize.row = size.attribute("row").toInt();
305  mSize.col = size.attribute("col").toInt();
306 
307  mView.clear();
308  // iterate over all views
309  QDomElement currentElem = elem.firstChildElement("view");
310  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("view"))
311  {
312  LayoutViewData viewData;
313  viewData.parseXml(currentElem);
314  mView.push_back(viewData);
315  }
316 }
317 
318 } // namespace cx
QString qstring_cast(const T &val)
int mGroup
what group to connect to. -1 means not set.
Definition: cxLayoutData.h:84
void reportError(QString msg)
Definition: cxLogger.cpp:92
static LayoutData createHeader(QString uid, QString name)
ViewDataContainer::iterator iterator
Definition: cxLayoutData.h:101
LayoutPosition span
size of region
Definition: cxLayoutData.h:67
bool merge(LayoutRegion region)
iterator begin()
Definition: cxLayoutData.h:115
void setName(const QString &name)
Definition: cxLayoutData.h:110
void parseXml(QDomNode node)
load state from xml
PLANE_TYPE mPlane
ptNOPLANE means 3D
Definition: cxLayoutData.h:85
LayoutRegion mRegion
Definition: cxLayoutData.h:87
LayoutViewData & get(LayoutPosition pos)
iterator find(LayoutPosition pos)
void split(iterator iter)
void resize(int rows, int cols)
void setView(int group, PLANE_TYPE type, LayoutRegion region)
void parseXml(QDomNode node)
load state from xml
LayoutPosition size() const
Definition: cxLayoutData.h:126
ptNOPLANE
a initial plane, if no yet set
Definition: cxDefinitions.h:56
LayoutPosition pos
start position of region
Definition: cxLayoutData.h:66
void resetUid(const QString &uid)
ViewDataContainer::const_iterator const_iterator
Definition: cxLayoutData.h:102
void addXml(QDomNode node) const
save state to xml
iterator end()
Definition: cxLayoutData.h:116
View::Type mType
Definition: cxLayoutData.h:86
void addXml(QDomNode node) const
save state to xml
LayoutRegion merge(LayoutRegion a, LayoutRegion b)
static LayoutData create(QString uid, QString name, int rows, int cols)