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 <sal/log.hxx>
39 #include <tools/diagnose_ex.h>
40 
41 #include <numeric>
42 
43 #define MIN_WIDTH 80
44 #define MIN_HEIGHT 20
45 
46 namespace rptxml
47 {
48  using namespace ::xmloff;
49  using namespace ::com::sun::star;
50  using ::com::sun::star::uno::Reference;
51  using namespace ::com::sun::star::xml::sax;
52 
53  static sal_Int16 lcl_getForceNewPageOption(std::string_view _sValue)
54  {
55  sal_Int16 nRet = report::ForceNewPage::NONE;
57  (void)SvXMLUnitConverter::convertEnum( nRet,_sValue,aXML_EnumMap );
58  return nRet;
59  }
60 
61 OXMLTable::OXMLTable( ORptFilter& rImport
62  ,const Reference< XFastAttributeList > & _xAttrList
63  ,const uno::Reference< report::XSection >& _xSection
64  )
65 :SvXMLImportContext( rImport )
66 ,m_xSection(_xSection)
67 ,m_nColSpan(1)
68 ,m_nRowSpan(0)
69 ,m_nRowIndex(0)
70 ,m_nColumnIndex(0)
71 {
72 
73  if (!m_xSection.is())
74  return;
75  try
76  {
77  for (auto &aIter : sax_fastparser::castToFastAttributeList( _xAttrList ))
78  {
79  switch( aIter.getToken() )
80  {
81  case XML_ELEMENT(REPORT, XML_VISIBLE):
82  m_xSection->setVisible(IsXMLToken(aIter, XML_TRUE));
83  break;
84  case XML_ELEMENT(REPORT, XML_FORCE_NEW_PAGE):
85  m_xSection->setForceNewPage(lcl_getForceNewPageOption(aIter.toView()));
86  break;
87  case XML_ELEMENT(REPORT, XML_FORCE_NEW_COLUMN):
88  m_xSection->setNewRowOrCol(lcl_getForceNewPageOption(aIter.toView()));
89  break;
90  case XML_ELEMENT(REPORT, XML_KEEP_TOGETHER):
91  m_xSection->setKeepTogether(IsXMLToken(aIter, XML_TRUE));
92  break;
93  case XML_ELEMENT(TABLE, XML_NAME):
94  m_xSection->setName(aIter.toString());
95  break;
96  case XML_ELEMENT(TABLE, XML_STYLE_NAME):
97  m_sStyleName = aIter.toString();
98  break;
99  default:
100  XMLOFF_WARN_UNKNOWN("reportdesign", aIter);
101  break;
102  }
103  }
104  }
105  catch(Exception&)
106  {
107  TOOLS_WARN_EXCEPTION( "reportdesign", "Exception caught while filling the section props");
108  }
109 }
110 
111 OXMLTable::~OXMLTable()
112 {
113 }
114 
115 css::uno::Reference< css::xml::sax::XFastContextHandler > OXMLTable::createFastChildContext(
116  sal_Int32 nElement,
117  const Reference< XFastAttributeList > & xAttrList )
118 {
119  css::uno::Reference< css::xml::sax::XFastContextHandler > xContext;
120  ORptFilter& rImport = GetOwnImport();
121 
122  switch( nElement )
123  {
124  case XML_ELEMENT(TABLE, XML_TABLE_COLUMNS):
126  xContext = new OXMLRowColumn( rImport,xAttrList ,this);
127  break;
128  case XML_ELEMENT(TABLE, XML_TABLE_ROW):
129  incrementRowIndex();
131  xContext = new OXMLRowColumn( rImport,xAttrList,this);
132  break;
133  case XML_ELEMENT(TABLE, XML_TABLE_COLUMN):
134  rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
135  xContext = new OXMLRowColumn( rImport,xAttrList,this);
136  break;
137  case XML_ELEMENT(REPORT, XML_CONDITIONAL_PRINT_EXPRESSION):
138  xContext = new OXMLCondPrtExpr( rImport,xAttrList,m_xSection);
139  break;
140  default:
141  break;
142  }
143 
144  return xContext;
145 }
146 
147 ORptFilter& OXMLTable::GetOwnImport()
148 {
149  return static_cast<ORptFilter&>(GetImport());
150 }
151 
152 void OXMLTable::endFastElement(sal_Int32 )
153 {
154  try
155  {
156  if ( m_xSection.is() )
157  {
158  if ( !m_sStyleName.isEmpty() )
159  {
160  const SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
161  if ( pAutoStyles )
162  {
163  XMLPropStyleContext* pAutoStyle = const_cast<XMLPropStyleContext*>(dynamic_cast< const XMLPropStyleContext *>(pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_TABLE,m_sStyleName)));
164  if ( pAutoStyle )
165  {
166  pAutoStyle->FillPropertySet(m_xSection);
167  }
168  }
169  }
170  // set height
171  sal_Int32 nHeight = std::accumulate(m_aHeight.begin(), m_aHeight.end(), sal_Int32(0),
172  [](const sal_Int32& rSum, const sal_Int32& rHeight) { return rSum + rHeight; });
173  m_xSection->setHeight( nHeight );
174  // set positions, widths, and heights
175  sal_Int32 nLeftMargin = rptui::getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
176  sal_Int32 nPosY = 0;
177  ::std::vector< ::std::vector<TCell> >::iterator aRowIter = m_aGrid.begin();
178  ::std::vector< ::std::vector<TCell> >::const_iterator aRowEnd = m_aGrid.end();
179  for (sal_Int32 i = 0; aRowIter != aRowEnd; ++aRowIter,++i)
180  {
181  sal_Int32 nPosX = nLeftMargin;
182  ::std::vector<TCell>::iterator aColIter = (*aRowIter).begin();
183  ::std::vector<TCell>::const_iterator aColEnd = (*aRowIter).end();
184  for (sal_Int32 j = 0; aColIter != aColEnd; ++aColIter,++j)
185  {
186  TCell& rCell = *aColIter;
187  for (const auto& rxElement : rCell.xElements)
188  {
189  uno::Reference<report::XShape> xShape(rxElement,uno::UNO_QUERY);
190  if ( xShape.is() )
191  {
192  xShape->setPositionX(xShape->getPositionX() + nLeftMargin);
193  }
194  else
195  {
196  sal_Int32 nWidth = rCell.nWidth;
197  sal_Int32 nColSpan = rCell.nColSpan;
198  if ( nColSpan > 1 )
199  {
200  ::std::vector<TCell>::const_iterator aWidthIter = aColIter + 1;
201  while ( nColSpan > 1 )
202  {
203  nWidth += (aWidthIter++)->nWidth;
204  --nColSpan;
205  }
206  }
207  nHeight = rCell.nHeight;
208  sal_Int32 nRowSpan = rCell.nRowSpan;
209  if ( nRowSpan > 1 )
210  {
211  ::std::vector< ::std::vector<TCell> >::const_iterator aHeightIter = aRowIter + 1;
212  while( nRowSpan > 1)
213  {
214  nHeight += (*aHeightIter)[j].nHeight;
215  ++aHeightIter;
216  --nRowSpan;
217  }
218  }
219  Reference<XFixedLine> xFixedLine(rxElement,uno::UNO_QUERY);
220  if ( xFixedLine.is() )
221  {
222  if ( xFixedLine->getOrientation() == 1 ) // vertical
223  {
224  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.");
225  nWidth += m_aWidth[j+1];
226  if ( nWidth < MIN_WIDTH )
227  nWidth = MIN_WIDTH;
228  }
229  else if ( nHeight < MIN_HEIGHT )
230  nHeight = MIN_HEIGHT;
231  }
232  try
233  {
234  rxElement->setSize(awt::Size(nWidth,nHeight));
235  rxElement->setPosition(awt::Point(nPosX,nPosY));
236  rxElement->setAutoGrow(rCell.bAutoHeight);
237  }
238  catch(const beans::PropertyVetoException &)
239  {
240  OSL_FAIL("Could not set the correct position or size!");
241  }
242  }
243  }
244  nPosX += m_aWidth[j];
245  }
246  nPosY += m_aHeight[i];
247  }
248  }
249  }
250  catch(Exception&)
251  {
252  TOOLS_WARN_EXCEPTION( "reportdesign", "OXMLTable::EndElement");
253  }
254 }
255 
256 void OXMLTable::addCell(const Reference<XReportComponent>& _xElement)
257 {
258  uno::Reference<report::XShape> xShape(_xElement,uno::UNO_QUERY);
259  OSL_ENSURE(o3tl::make_unsigned(m_nRowIndex-1 ) < m_aGrid.size() && o3tl::make_unsigned( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size(),
260  "OXMLTable::addCell: Invalid column and row index");
261  if ( o3tl::make_unsigned(m_nRowIndex-1 ) < m_aGrid.size() && o3tl::make_unsigned( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size() )
262  {
263  TCell& rCell = m_aGrid[m_nRowIndex-1][m_nColumnIndex-1];
264  if ( _xElement.is() )
265  rCell.xElements.push_back( _xElement );
266  if ( !xShape.is() )
267  {
268  rCell.nWidth = m_aWidth[m_nColumnIndex-1];
269  rCell.nHeight = m_aHeight[m_nRowIndex-1];
270  rCell.bAutoHeight = m_aAutoHeight[m_nRowIndex-1];
271  rCell.nColSpan = m_nColSpan;
272  rCell.nRowSpan = m_nRowSpan;
273  }
274  }
275 
276  if ( !xShape.is() )
277  m_nColSpan = m_nRowSpan = 1;
278 }
279 
280 void OXMLTable::incrementRowIndex()
281 {
282  ++m_nRowIndex;
283  m_nColumnIndex = 0;
284  m_aGrid.push_back(::std::vector<TCell>(m_aWidth.size()));
285 }
286 
287 } // namespace rptxml
288 
289 
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MIN_HEIGHT
Definition: xmlTable.cxx:44
#define MIN_WIDTH
Definition: xmlTable.cxx:43
tools::Long const nLeftMargin
css::uno::Reference< css::style::XAutoStyleFamily > GetAutoStyles(XmlStyleFamily nFamily) const
static const SvXMLEnumMapEntry< sal_Int16 > * GetForceNewPageOptions()
Definition: xmlHelper.cxx:198
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:104
#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:53
::std::vector< css::uno::Reference< css::report::XReportComponent > > xElements
Definition: xmlTable.hxx:39
#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
XML_TRUE
const SvXMLStyleContext * FindStyleChildContext(XmlStyleFamily nFamily, const OUString &rName, bool bCreateIndex=false) const
XML_TABLE_ROWS
OXMLTable(const OXMLTable &)=delete
OUString toString(OptionInfo const *info)
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo