Fraxinus  17.12
An IGT application
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  mOffScreenRendering(false)
100 {
101  mSize = LayoutPosition(0, 0);
102  this->resize(0, 0);
103 }
104 
105 void LayoutData::resetUid(const QString& uid)
106 {
107  mUid = uid;
108  mName = mName + " " + uid;
109 }
110 
114 void LayoutData::setView(int group, PLANE_TYPE type, LayoutRegion region)
115 {
116  if (!this->merge(region))
117  return;
118  LayoutViewData& view = get(region.pos);
119  view.mGroup = group;
120  view.mPlane = type;
121  view.mType = View::VIEW_2D;
122 }
123 
124 void LayoutData::setView(int group, View::Type type, LayoutRegion region)
125 {
126  if (!this->merge(region))
127  return;
128  LayoutViewData& view = get(region.pos);
129  view.mGroup = group;
130  view.mPlane = ptNOPLANE;
131  view.mType = type;
132 }
133 
140 {
141  if (region.pos.row + region.span.row > mSize.row || region.pos.col + region.span.col > mSize.col)
142  {
143  reportError("Attempted to merge a region outside allocated space in LayoutData.");
144  return false;
145  }
146 
147  //std::cout << "merge views " << std::endl;
148  this->split(region); // split all existing merges in order to keep consistency
149 
150  // create new merged view based on the ul corner view.
151  LayoutViewData current = this->get(region.pos);
152  current.mRegion = region;
153 
154  // erase all views within region (all should now be 1x1)
155  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
156  {
157  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
158  {
159  iterator iter = this->find(LayoutPosition(r, c));
160  if (iter != this->end())
161  mView.erase(iter);
162  }
163  }
164 
165  // add merged view.
166  mView.push_back(current);
167  return true;
168 }
169 
174 {
175  // reset all primitives in region
176  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
177  {
178  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
179  {
180  iterator iter = this->find(LayoutPosition(r, c));
181  this->split(iter);
182  }
183  }
184 }
185 
190 {
191  if (iter == this->end())
192  return;
193  if (iter->mRegion.span.row == 1 && iter->mRegion.span.col == 1)
194  return; // nothing to split
195 
196  LayoutViewData newView = *iter;
197  LayoutRegion region = iter->mRegion;
198 
199  // erase old region
200  mView.erase(iter);
201 
202  // insert new 1x1 views in the erased region.
203  for (int r = region.pos.row; r < region.pos.row + region.span.row; ++r)
204  {
205  for (int c = region.pos.col; c < region.pos.col + region.span.col; ++c)
206  {
207  newView.mRegion = LayoutRegion(r, c, 1, 1);
208  mView.push_back(newView);
209  }
210  }
211 }
212 
216 void LayoutData::resize(int rows, int cols)
217 {
218  mSize = LayoutPosition(rows, cols);
219 
220  if (mSize.row == 0 || mSize.col == 0)
221  {
222  mView.clear();
223  return;
224  }
225 
226  // erase all views outside region
227  // TODO: also consider nontrivial regions.
228  for (iterator iter = this->begin(); iter != this->end();)
229  {
230  if (iter->mRegion.pos.row >= rows || iter->mRegion.pos.col >= cols)
231  {
232  iter = mView.erase(iter);
233  }
234  else
235  {
236  ++iter;
237  }
238  }
239 
240  // add new views (brute force: optimize if needed)
241  for (int r = 0; r < rows; ++r)
242  {
243  for (int c = 0; c < cols; ++c)
244  {
245  if (this->find(LayoutPosition(r, c)) == this->end())
246  {
247  mView.push_back(LayoutViewData(r, c, 1, 1));
248  }
249  }
250  }
251 }
252 
253 //const LayoutData::ViewData& LayoutData::get(LayoutPosition pos) const
254 //{
255 // return *(this->find(pos));
256 //}
257 
259 {
260  return *(this->find(pos));
261 }
262 
264 {
265  for (iterator iter = this->begin(); iter != this->end(); ++iter)
266  {
267  if (iter->mRegion.contains(pos))
268  return iter;
269  }
270 
271  return this->end();
272 }
273 
274 void LayoutData::addXml(QDomNode node) const
275 {
276  QDomDocument doc = node.ownerDocument();
277  QDomElement elem = node.toElement();
278 
279  elem.setAttribute("uid", mUid);
280  elem.setAttribute("name", mName);
281  elem.setAttribute("offScreenRendering", mOffScreenRendering);
282 
283  QDomElement size = doc.createElement("size");
284  size.setAttribute("row", mSize.row);
285  size.setAttribute("col", mSize.col);
286  elem.appendChild(size);
287 
288  for (const_iterator iter = this->begin(); iter != this->end(); ++iter)
289  {
290  QDomElement view = doc.createElement("view");
291  iter->addXml(view);
292  elem.appendChild(view);
293  }
294 }
295 
296 void LayoutData::parseXml(QDomNode node)
297 {
298  if (node.isNull())
299  return;
300 
301  QDomElement elem = node.toElement();
302  mUid = elem.attribute("uid");
303  mName = elem.attribute("name");
304  mOffScreenRendering = elem.attribute("offScreenRendering").toInt();
305 
306  QDomElement size = elem.namedItem("size").toElement();
307  mSize.row = size.attribute("row").toInt();
308  mSize.col = size.attribute("col").toInt();
309 
310  mView.clear();
311  // iterate over all views
312  QDomElement currentElem = elem.firstChildElement("view");
313  for (; !currentElem.isNull(); currentElem = currentElem.nextSiblingElement("view"))
314  {
315  LayoutViewData viewData;
316  viewData.parseXml(currentElem);
317  mView.push_back(viewData);
318  }
319 }
320 
321 } // 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:118
void setName(const QString &name)
Definition: cxLayoutData.h:113
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:129
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:119
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)
Namespace for all CustusX production code.