LibreOffice Module reportdesign (master)  1
xmlTable.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 #include "xmlTable.hxx"
20 #include "xmlfilter.hxx"
21 #include <o3tl/safeint.hxx>
22 #include <xmloff/xmltoken.hxx>
23 #include <xmloff/xmlnamespace.hxx>
24 #include <xmloff/xmlstyle.hxx>
25 #include <xmloff/prstylei.hxx>
26 #include <xmloff/xmluconv.hxx>
28 #include <RptDef.hxx>
29 #include "xmlHelper.hxx"
30 #include "xmlEnums.hxx"
31 #include "xmlColumn.hxx"
32 #include <com/sun/star/report/ForceNewPage.hpp>
33 #include "xmlCondPrtExpr.hxx"
34 #include <strings.hxx>
35 #include <com/sun/star/report/XShape.hpp>
36 #include <com/sun/star/report/XFixedLine.hpp>
37 #include <osl/diagnose.h>
38 #include <tools/diagnose_ex.h>
39 
40 #include <numeric>
41 
42 #define MIN_WIDTH 80
43 #define MIN_HEIGHT 20
44 
45 namespace rptxml
46 {
47  using namespace ::xmloff;
48  using namespace ::com::sun::star;
49  using ::com::sun::star::uno::Reference;
50  using namespace ::com::sun::star::xml::sax;
51 
52  static sal_Int16 lcl_getForceNewPageOption(std::string_view _sValue)
53  {
54  sal_Int16 nRet = report::ForceNewPage::NONE;
56  (void)SvXMLUnitConverter::convertEnum( nRet,_sValue,aXML_EnumMap );
57  return nRet;
58  }
59 
60 OXMLTable::OXMLTable( ORptFilter& rImport
61  ,const Reference< XFastAttributeList > & _xAttrList
62  ,const uno::Reference< report::XSection >& _xSection
63  )
64 :SvXMLImportContext( rImport )
65 ,m_xSection(_xSection)
66 ,m_nColSpan(1)
67 ,m_nRowSpan(0)
68 ,m_nRowIndex(0)
69 ,m_nColumnIndex(0)
70 {
71 
72  if (!m_xSection.is())
73  return;
74  try
75  {
76  for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
77  {
78  switch( aIter.getToken() )
79  {
80  case XML_ELEMENT(REPORT, XML_VISIBLE):
81  m_xSection->setVisible(IsXMLToken(aIter, XML_TRUE));
82  break;
83  case XML_ELEMENT(REPORT, XML_FORCE_NEW_PAGE):
84  m_xSection->setForceNewPage(lcl_getForceNewPageOption(aIter.toView()));
85  break;
86  case XML_ELEMENT(REPORT, XML_FORCE_NEW_COLUMN):
87  m_xSection->setNewRowOrCol(lcl_getForceNewPageOption(aIter.toView()));
88  break;
89  case XML_ELEMENT(REPORT, XML_KEEP_TOGETHER):
90  m_xSection->setKeepTogether(IsXMLToken(aIter, XML_TRUE));
91  break;
92  case XML_ELEMENT(TABLE, XML_NAME):
93  m_xSection->setName(aIter.toString());
94  break;
95  case XML_ELEMENT(TABLE, XML_STYLE_NAME):
96  m_sStyleName = aIter.toString();
97  break;
98  default:
99  XMLOFF_WARN_UNKNOWN("reportdesign", aIter);
100  break;
101  }
102  }
103  }
104  catch(Exception&)
105  {
106  TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while filling the section props");
107  }
108 }
109 
110 OXMLTable::~OXMLTable()
111 {
112 }
113 
114 css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLTable::createFastChildContext(
115  sal_Int32 nElement,
116  const Reference< XFastAttributeList > & xAttrList )
117 {
118  css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
119  ORptFilter& rImport = GetOwnImport();
120 
121  switch( nElement )
122  {
123  case XML_ELEMENT(TABLE, XML_TABLE_COLUMNS):
125  xContext = new OXMLRowColumn( rImport,xAttrList ,this);
126  break;
127  case XML_ELEMENT(TABLE, XML_TABLE_ROW):
128  incrementRowIndex();
130  xContext = new OXMLRowColumn( rImport,xAttrList,this);
131  break;
132  case XML_ELEMENT(TABLE, XML_TABLE_COLUMN):
133  rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
134  xContext = new OXMLRowColumn( rImport,xAttrList,this);
135  break;
136  case XML_ELEMENT(REPORT, XML_CONDITIONAL_PRINT_EXPRESSION):
137  xContext = new OXMLCondPrtExpr( rImport,xAttrList,m_xSection);
138  break;
139  default:
140  break;
141  }
142 
143  return xContext;
144 }
145 
146 ORptFilter& OXMLTable::GetOwnImport()
147 {
148  return static_cast<ORptFilter&>(GetImport());
149 }
150 
151 void OXMLTable::endFastElement(sal_Int32 )
152 {
153  try
154  {
155  if ( m_xSection.is() )
156  {
157  if ( !m_sStyleName.isEmpty() )
158  {
159  const SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
160  if ( pAutoStyles )
161  {
162  XMLPropStyleContext* pAutoStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext *>(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_TABLE,m_sStyleName)));
163  if ( pAutoStyle )
164  {
165  pAutoStyle->FillPropertySet(m_xSection);
166  }
167  }
168  }
169  // set height
170  sal_Int32 nHeight = std::accumulate(m_aHeight.begin(), m_aHeight.end(), sal_Int32(0),
171  [](const sal_Int32& rSum, const sal_Int32& rHeight) { return rSum + rHeight; });
172  m_xSection->setHeight( nHeight );
173  // set positions, widths, and heights
174  sal_Int32 nLeftMargin = rptui::getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
175  sal_Int32 nPosY = 0;
176  ::std::vector< ::std::vector<TCell> >::iterator aRowIter = m_aGrid.begin();
177  ::std::vector< ::std::vector<TCell> >::const_iterator aRowEnd = m_aGrid.end();
178  for (sal_Int32 i = 0; aRowIter != aRowEnd; ++aRowIter,++i)
179  {
180  sal_Int32 nPosX = nLeftMargin;
181  ::std::vector<TCell>::iterator aColIter = (*aRowIter).begin();
182  ::std::vector<TCell>::const_iterator aColEnd = (*aRowIter).end();
183  for (sal_Int32 j = 0; aColIter != aColEnd; ++aColIter,++j)
184  {
185  TCell& rCell = *aColIter;
186  for (const auto& rxElement : rCell.xElements)
187  {
188  uno::Reference<report::XShape> xShape(rxElement,uno::UNO_QUERY);
189  if ( xShape.is() )
190  {
191  xShape->setPositionX(xShape->getPositionX() + nLeftMargin);
192  }
193  else
194  {
195  sal_Int32 nWidth = rCell.nWidth;
196  sal_Int32 nColSpan = rCell.nColSpan;
197  if ( nColSpan > 1 )
198  {
199  ::std::vector<TCell>::const_iterator aWidthIter = aColIter + 1;
200  while ( nColSpan > 1 )
201  {
202  nWidth += (aWidthIter++)->nWidth;
203  --nColSpan;
204  }
205  }
206  nHeight = rCell.nHeight;
207  sal_Int32 nRowSpan = rCell.nRowSpan;
208  if ( nRowSpan > 1 )
209  {
210  ::std::vector< ::std::vector<TCell> >::const_iterator aHeightIter = aRowIter + 1;
211  while( nRowSpan > 1)
212  {
213  nHeight += (*aHeightIter)[j].nHeight;
214  ++aHeightIter;
215  --nRowSpan;
216  }
217  }
218  Reference<XFixedLine> xFixedLine(rxElement,uno::UNO_QUERY);
219  if ( xFixedLine.is() )
220  {
221  if ( xFixedLine->getOrientation() == 1 ) // vertical
222  {
223  OSL_ENSURE(o3tl::make_unsigned(j+1) < m_aWidth.size(),"Illegal pos of col iter. There should be an empty cell for the next line part.");
224  nWidth += m_aWidth[j+1];
225  if ( nWidth < MIN_WIDTH )
226  nWidth = MIN_WIDTH;
227  }
228  else if ( nHeight < MIN_HEIGHT )
229  nHeight = MIN_HEIGHT;
230  }
231  try
232  {
233  rxElement->setSize(awt::Size(nWidth,nHeight));
234  rxElement->setPosition(awt::Point(nPosX,nPosY));
235  rxElement->setAutoGrow(rCell.bAutoHeight);
236  }
237  catch(const beans::PropertyVetoException &)
238  {
239  OSL_FAIL("Could not set the correct position or size!");
240  }
241  }
242  }
243  nPosX += m_aWidth[j];
244  }
245  nPosY += m_aHeight[i];
246  }
247  }
248  }
249  catch(Exception&)
250  {
251  TOOLS_WARN_EXCEPTION( "reportdesign", "OXMLTable::EndElement");
252  }
253 }
254 
255 void OXMLTable::addCell(const Reference<XReportComponent>& _xElement)
256 {
257  uno::Reference<report::XShape> xShape(_xElement,uno::UNO_QUERY);
258  OSL_ENSURE(o3tl::make_unsigned(m_nRowIndex-1 ) < m_aGrid.size() && o3tl::make_unsigned( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size(),
259  "OXMLTable::addCell: Invalid column and row index");
260  if ( o3tl::make_unsigned(m_nRowIndex-1 ) < m_aGrid.size() && o3tl::make_unsigned( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size() )
261  {
262  TCell& rCell = m_aGrid[m_nRowIndex-1][m_nColumnIndex-1];
263  if ( _xElement.is() )
264  rCell.xElements.push_back( _xElement );
265  if ( !xShape.is() )
266  {
267  rCell.nWidth = m_aWidth[m_nColumnIndex-1];
268  rCell.nHeight = m_aHeight[m_nRowIndex-1];
269  rCell.bAutoHeight = m_aAutoHeight[m_nRowIndex-1];
270  rCell.nColSpan = m_nColSpan;
271  rCell.nRowSpan = m_nRowSpan;
272  }
273  }
274 
275  if ( !xShape.is() )
276  m_nColSpan = m_nRowSpan = 1;
277 }
278 
279 void OXMLTable::incrementRowIndex()
280 {
281  ++m_nRowIndex;
282  m_nColumnIndex = 0;
283  m_aGrid.push_back(::std::vector<TCell>(m_aWidth.size()));
284 }
285 
286 } // namespace rptxml
287 
288 
289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MIN_HEIGHT
Definition: xmlTable.cxx:43
#define MIN_WIDTH
Definition: xmlTable.cxx:42
tools::Long const nLeftMargin
css::uno::Reference< css::style::XAutoStyleFamily > GetAutoStyles(XmlStyleFamily nFamily) const
static const SvXMLEnumMapEntry< sal_Int16 > * GetForceNewPageOptions()
Definition: xmlHelper.cxx:197
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
#define PROPERTY_LEFTMARGIN
Definition: strings.hxx:102
XML_TABLE_ROWS
#define XMLOFF_WARN_UNKNOWN(area, rIter)
void Increment(sal_Int32 nInc=1)
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
ProgressBarHelper * GetProgressBarHelper()
static sal_Int16 lcl_getForceNewPageOption(std::string_view _sValue)
Definition: xmlTable.cxx:52
::std::vector< css::uno::Reference< css::report::XReportComponent > > xElements
Definition: xmlTable.hxx:39
XML_TRUE
#define XML_ELEMENT(prefix, name)
static bool convertEnum(EnumT &rEnum, std::u16string_view rValue, const SvXMLEnumMapEntry< EnumT > *pMap)
#define PROGRESS_BAR_STEP
Definition: xmlEnums.hxx:22
TABLE
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
OXMLTable(const OXMLTable &)=delete
OUString toString(OptionInfo const *info)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo