1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 #include "precompiled_rptxml.hxx"
24 #include "xmlTable.hxx"
25 #include "xmlfilter.hxx"
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnmspe.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include <xmloff/xmluconv.hxx>
30 #include "RptDef.hxx"
31 #include "xmlHelper.hxx"
32 #include "xmlEnums.hxx"
33 #ifndef RPT_XMLCOLUMN_HXX
34 #include "xmlColumn.hxx"
35 #endif
36 #include <com/sun/star/report/ForceNewPage.hpp>
37 #include "xmlCondPrtExpr.hxx"
38 #include "xmlStyleImport.hxx"
39 #include "xmlstrings.hrc"
40 #include <connectivity/dbtools.hxx>
41 #include <tools/debug.hxx>
42 #ifndef REPORTDESIGN_SHARED_XMLSTRINGS_HRC
43 #include "xmlstrings.hrc"
44 #endif
45 #include <com/sun/star/report/XShape.hpp>
46 #include <com/sun/star/report/XFixedLine.hpp>
47 
48 #define MIN_WIDTH   80
49 #define MIN_HEIGHT  20
50 
51 namespace rptxml
52 {
53 	using namespace ::xmloff;
54 	using namespace ::com::sun::star;
55 	using ::com::sun::star::uno::Reference;
56 	using namespace ::com::sun::star::xml::sax;
57 	using ::com::sun::star::xml::sax::XAttributeList;
58 
lcl_getForceNewPageOption(const::rtl::OUString & _sValue)59     sal_uInt16 lcl_getForceNewPageOption(const ::rtl::OUString& _sValue)
60 	{
61 		sal_uInt16 nRet = report::ForceNewPage::NONE;
62 		const SvXMLEnumMapEntry* aXML_EnumMap = OXMLHelper::GetForceNewPageOptions();
63 		SvXMLUnitConverter::convertEnum( nRet,_sValue,aXML_EnumMap );
64 		return nRet;
65 	}
DBG_NAME(rpt_OXMLTable)66 DBG_NAME( rpt_OXMLTable )
67 
68 OXMLTable::OXMLTable( ORptFilter& rImport
69 				,sal_uInt16 nPrfx
70                 ,const ::rtl::OUString& _sLocalName
71                 ,const Reference< XAttributeList > & _xAttrList
72 				,const uno::Reference< report::XSection >& _xSection
73                 )
74 :SvXMLImportContext( rImport, nPrfx, _sLocalName )
75 ,m_xSection(_xSection)
76 ,m_nColSpan(1)
77 ,m_nRowSpan(0)
78 ,m_nRowIndex(0)
79 ,m_nColumnIndex(0)
80 {
81     DBG_CTOR( rpt_OXMLTable,NULL);
82     OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!");
83 	const SvXMLNamespaceMap& rMap = rImport.GetNamespaceMap();
84 	const SvXMLTokenMap& rTokenMap = rImport.GetSectionElemTokenMap();
85 
86 	const sal_Int16 nLength = (m_xSection.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0;
87     static const ::rtl::OUString s_sTRUE = ::xmloff::token::GetXMLToken(XML_TRUE);
88     try
89 	{
90 	    for(sal_Int16 i = 0; i < nLength; ++i)
91 	    {
92 		    rtl::OUString sLocalName;
93 		    const rtl::OUString sAttrName = _xAttrList->getNameByIndex( i );
94 		    const sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName,&sLocalName );
95 		    const rtl::OUString sValue = _xAttrList->getValueByIndex( i );
96 
97 		    switch( rTokenMap.Get( nPrefix, sLocalName ) )
98 		    {
99                 case XML_TOK_VISIBLE:
100 				    m_xSection->setVisible(sValue == s_sTRUE);
101 				    break;
102 			    case XML_TOK_FORCE_NEW_PAGE:
103 				    m_xSection->setForceNewPage(lcl_getForceNewPageOption(sValue));
104 				    break;
105                 case XML_TOK_FORCE_NEW_COLUMN:
106 				    m_xSection->setNewRowOrCol(lcl_getForceNewPageOption(sValue));
107 				    break;
108 			    case XML_TOK_KEEP_TOGETHER:
109 				    m_xSection->setKeepTogether(sValue == s_sTRUE);
110 				    break;
111 			    case XML_TOK_SECTION_NAME:
112 				    m_xSection->setName(sValue);
113 				    break;
114                 case XML_TOK_SECT_STYLE_NAME:
115 				    m_sStyleName = sValue;
116 				    break;
117                 default:
118                     break;
119             }
120         }
121     }
122 	catch(Exception&)
123 	{
124 		OSL_ENSURE(0,"Exception catched while filling the section props");
125 	}
126 }
127 // -----------------------------------------------------------------------------
~OXMLTable()128 OXMLTable::~OXMLTable()
129 {
130     DBG_DTOR( rpt_OXMLTable,NULL);
131 }
132 // -----------------------------------------------------------------------------
133 
CreateChildContext(sal_uInt16 _nPrefix,const::rtl::OUString & _rLocalName,const Reference<XAttributeList> & xAttrList)134 SvXMLImportContext* OXMLTable::CreateChildContext(
135 		sal_uInt16 _nPrefix,
136 		const ::rtl::OUString& _rLocalName,
137 		const Reference< XAttributeList > & xAttrList )
138 {
139 	SvXMLImportContext *pContext = 0;
140     ORptFilter& rImport = GetOwnImport();
141 	const SvXMLTokenMap&	rTokenMap	= rImport.GetColumnTokenMap();
142     Reference<XMultiServiceFactory> xFactor = rImport.getServiceFactory();
143 
144 	switch( rTokenMap.Get( _nPrefix, _rLocalName ) )
145 	{
146         case XML_TOK_TABLE_COLUMNS:
147         case XML_TOK_TABLE_ROWS:
148             pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList ,this);
149 			break;
150         case XML_TOK_ROW:
151             incrementRowIndex();
152             rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
153 			pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
154 			break;
155         case XML_TOK_COLUMN:
156             rImport.GetProgressBarHelper()->Increment( PROGRESS_BAR_STEP );
157 			pContext = new OXMLRowColumn( rImport, _nPrefix, _rLocalName,xAttrList,this);
158 			break;
159         case XML_TOK_CONDITIONAL_PRINT_EXPRESSION:
160 			pContext = new OXMLCondPrtExpr( rImport, _nPrefix, _rLocalName,xAttrList,m_xSection.get());
161 			break;
162         default:
163                 break;
164 	}
165 
166 	if( !pContext )
167 		pContext = new SvXMLImportContext( rImport, _nPrefix, _rLocalName );
168 
169 	return pContext;
170 }
171 // -----------------------------------------------------------------------------
GetOwnImport()172 ORptFilter& OXMLTable::GetOwnImport()
173 {
174 	return static_cast<ORptFilter&>(GetImport());
175 }
176 // -----------------------------------------------------------------------------
EndElement()177 void OXMLTable::EndElement()
178 {
179 	try
180 	{
181 		if ( m_xSection.is() )
182 		{
183             if ( m_sStyleName.getLength() )
184 			{
185 				const SvXMLStylesContext* pAutoStyles = GetImport().GetAutoStyles();
186 				if ( pAutoStyles )
187 				{
188 					XMLPropStyleContext* pAutoStyle = PTR_CAST(XMLPropStyleContext,pAutoStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_TABLE,m_sStyleName));
189 					if ( pAutoStyle )
190 					{
191 						pAutoStyle->FillPropertySet(m_xSection.get());
192 					}
193 				}
194 			} // if ( m_sStyleName.getLength() )
195             // set height
196             ::std::vector<sal_Int32>::iterator aIter = m_aHeight.begin();
197             ::std::vector<sal_Int32>::iterator aEnd = m_aHeight.end();
198             sal_Int32 nHeight = 0;
199             for (; aIter != aEnd; ++aIter)
200                 nHeight += *aIter;
201             m_xSection->setHeight( nHeight );
202             // set positions, widths, and heights
203             sal_Int32 nLeftMargin = rptui::getStyleProperty<sal_Int32>(m_xSection->getReportDefinition(),PROPERTY_LEFTMARGIN);
204             sal_Int32 nPosY = 0;
205             ::std::vector< ::std::vector<TCell> >::iterator aRowIter = m_aGrid.begin();
206             ::std::vector< ::std::vector<TCell> >::iterator aRowEnd = m_aGrid.end();
207             for (sal_Int32 i = 0; aRowIter != aRowEnd; ++aRowIter,++i)
208             {
209                 sal_Int32 nPosX = nLeftMargin;
210                 ::std::vector<TCell>::iterator aColIter = (*aRowIter).begin();
211                 ::std::vector<TCell>::iterator aColEnd = (*aRowIter).end();
212                 for (sal_Int32 j = 0; aColIter != aColEnd; ++aColIter,++j)
213                 {
214                     TCell& rCell = *aColIter;
215                     if ( !rCell.xElements.empty())
216                     {
217                         ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellIter = rCell.xElements.begin();
218                         const ::std::vector< uno::Reference< report::XReportComponent> >::iterator aCellEnd = rCell.xElements.end();
219                         for (;aCellIter != aCellEnd ; ++aCellIter)
220                         {
221                             uno::Reference<report::XShape> xShape(*aCellIter,uno::UNO_QUERY);
222                             if ( xShape.is() )
223                             {
224                                 xShape->setPositionX(xShape->getPositionX() + nLeftMargin);
225                             }
226                             else
227                             {
228                                 sal_Int32 nWidth = rCell.nWidth;
229                                 sal_Int32 nColSpan = rCell.nColSpan;
230                                 if ( nColSpan > 1 )
231                                 {
232                                     ::std::vector<TCell>::iterator aWidthIter = aColIter + 1;
233                                     while ( nColSpan > 1 )
234                                     {
235                                         nWidth += (aWidthIter++)->nWidth;
236                                         --nColSpan;
237                                     }
238                                 }
239                                 nHeight = rCell.nHeight;
240                                 sal_Int32 nRowSpan = rCell.nRowSpan;
241                                 if ( nRowSpan > 1 )
242                                 {
243                                     ::std::vector< ::std::vector<TCell> >::iterator aHeightIter = aRowIter + 1;
244                                     while( nRowSpan > 1)
245                                     {
246                                         nHeight += (*aHeightIter)[j].nHeight;
247                                         ++aHeightIter;
248                                         --nRowSpan;
249                                     }
250                                 }
251                                 Reference<XFixedLine> xFixedLine(*aCellIter,uno::UNO_QUERY);
252                                 if ( xFixedLine.is() )
253                                 {
254                                     if ( xFixedLine->getOrientation() == 1 ) // vertical
255                                     {
256                                         OSL_ENSURE(static_cast<sal_uInt32>(j+1) < m_aWidth.size(),"Illegal pos of col iter. There should be an empty cell for the next line part.");
257                                         nWidth += m_aWidth[j+1];
258                                         if ( nWidth < MIN_WIDTH )
259                                             nWidth = MIN_WIDTH;
260                                     }
261                                     else if ( nHeight < MIN_HEIGHT )
262                                         nHeight = MIN_HEIGHT;
263                                 }
264                                 try
265                                 {
266                                     (*aCellIter)->setSize(awt::Size(nWidth,nHeight));
267                                     (*aCellIter)->setPosition(awt::Point(nPosX,nPosY));
268                                 }
269                                 catch(beans::PropertyVetoException)
270                                 {
271                                     OSL_ENSURE(0,"Could not set the correct position or size!");
272                                 }
273                             }
274                         }
275                     }
276                     nPosX += m_aWidth[j];
277                 }
278                 nPosY += m_aHeight[i];
279             }
280 		} // if ( m_xComponent.is() )
281 	}
282 	catch(Exception&)
283 	{
284 		OSL_ENSURE(0,"OXMLTable::EndElement -> exception catched");
285 	}
286 }
287 // -----------------------------------------------------------------------------
addCell(const Reference<XReportComponent> & _xElement)288 void OXMLTable::addCell(const Reference<XReportComponent>& _xElement)
289 {
290     uno::Reference<report::XShape> xShape(_xElement,uno::UNO_QUERY);
291     OSL_ENSURE(static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size(),
292         "OXMLTable::addCell: Invalid column and row index");
293     if ( static_cast<sal_uInt32>(m_nRowIndex-1 ) < m_aGrid.size() && static_cast<sal_uInt32>( m_nColumnIndex-1 ) < m_aGrid[m_nRowIndex-1].size() )
294     {
295         TCell& rCell = m_aGrid[m_nRowIndex-1][m_nColumnIndex-1];
296         if ( _xElement.is() )
297             rCell.xElements.push_back( _xElement );
298         if ( !xShape.is() )
299         {
300             rCell.nWidth   = m_aWidth[m_nColumnIndex-1];
301             rCell.nHeight  = m_aHeight[m_nRowIndex-1];
302             rCell.nColSpan = m_nColSpan;
303             rCell.nRowSpan = m_nRowSpan;
304         }
305     }
306 
307     if ( !xShape.is() )
308         m_nColSpan = m_nRowSpan = 1;
309 }
310 // -----------------------------------------------------------------------------
incrementRowIndex()311 void OXMLTable::incrementRowIndex()
312 {
313     ++m_nRowIndex;
314     m_nColumnIndex = 0;
315     m_aGrid.push_back(::std::vector<TCell>(m_aWidth.size()));
316 }
317 //----------------------------------------------------------------------------
318 } // namespace rptxml
319 // -----------------------------------------------------------------------------
320