/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ package com.sun.star.wizards.reportbuilder.layout; import com.sun.star.awt.FontDescriptor; import com.sun.star.awt.Rectangle; import com.sun.star.awt.Size; import com.sun.star.awt.XControl; import com.sun.star.awt.XControlModel; import com.sun.star.awt.XLayoutConstrains; import com.sun.star.awt.XUnitConversion; import com.sun.star.awt.XWindow; import com.sun.star.awt.XWindowPeer; import com.sun.star.beans.Property; import com.sun.star.beans.PropertyAttribute; import com.sun.star.beans.XPropertySet; import com.sun.star.beans.XPropertySetInfo; import com.sun.star.container.XEnumeration; import com.sun.star.container.XNameAccess; import com.sun.star.lang.XComponent; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.report.XFixedLine; import com.sun.star.report.XFixedText; import com.sun.star.report.XFormattedField; import com.sun.star.report.XGroup; import com.sun.star.report.XGroups; import com.sun.star.report.XImageControl; import com.sun.star.report.XReportComponent; import com.sun.star.report.XReportControlModel; import com.sun.star.report.XReportDefinition; import com.sun.star.report.XSection; import com.sun.star.drawing.XShape; import com.sun.star.sdbc.DataType; import com.sun.star.style.XStyle; import com.sun.star.uno.UnoRuntime; import com.sun.star.util.XNumberFormatTypes; import com.sun.star.util.XNumberFormats; import com.sun.star.util.XNumberFormatsSupplier; import com.sun.star.wizards.common.Configuration; import com.sun.star.wizards.common.FileAccess; import com.sun.star.wizards.common.Helper; import com.sun.star.wizards.common.PropertyNames; import com.sun.star.wizards.common.PropertySetHelper; import com.sun.star.wizards.common.Resource; import com.sun.star.wizards.report.IReportBuilderLayouter; import com.sun.star.wizards.report.IReportDefinitionReadAccess; import com.sun.star.wizards.ui.UIConsts; import java.util.HashMap; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; /** * This class is abstract and more like a helper for create different layouts for Report Builder Wizard. * @author ll93751 */// TODO: let a little bit place between 2 formatted fields // TODO: move all sectionobjects which have a connect to the right max page width to left if there is a orientation change. abstract public class ReportBuilderLayouter implements IReportBuilderLayouter { private IReportDefinitionReadAccess m_xReportDefinitionReadAccess; private Resource m_aResource; private String[][] m_aSortNames; /** * dispose the ReportBuilderLayouter */ public void dispose() { closeDesignTemplate(); m_xReportDefinitionReadAccess = null; // m_xReportBuilderLayouter = null; } /** * The Constructor is protected, this is a abstract class, use Tabular or other to create an instance. * @param _xDefinitionAccess * @param _aResource */ protected ReportBuilderLayouter(IReportDefinitionReadAccess _xDefinitionAccess, Resource _aResource) { m_xReportDefinitionReadAccess = _xDefinitionAccess; m_aResource = _aResource; } /** * Access to the current ReportDefinition * @return the ReportDefinition */ public XReportDefinition getReportDefinition() { // we have to ask our parent for this value return m_xReportDefinitionReadAccess.getReportDefinition(); } /** * Access to the global MultiServiceFactory * @return the global Service Factory */ private XMultiServiceFactory getGlobalMSF() { return m_xReportDefinitionReadAccess.getGlobalMSF(); } /** * Layout the complete report new, by all information we know until this time. * * If there are some information less, it is no problem for this function, they will be leaved out. * It is possible to call this function after every change, but be careful, could take a little bit longer. */ public synchronized void layout() { try { // we bring the clear and insert methods together, this should be a little bit smoother clearReportHeader(); insertReportHeader(); clearReportFooter(); insertReportFooter(); clearPageHeader(); insertPageHeader(); clearPageFooter(); insertPageFooter(); clearGroups(); int lastGroupPostion = insertGroups(); clearDetails(); // clearFieldTitles(); insertDetailFieldTitles(lastGroupPostion); insertDetailFields(); } catch (java.lang.ArrayIndexOutOfBoundsException e) { // could happen, if you change the count of values } catch (java.lang.RuntimeException e) { throw e; } catch (Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } // ------------------------------------------------------------------------- /** * Remove all Groups */ protected void clearGroups() { final XGroups xGroups = getReportDefinition().getGroups(); // int nCount = xGroups.getCount(); while (xGroups.hasElements()) { try { xGroups.removeByIndex(0); } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } } // ------------------------------------------------------------------------- /** * Remove all fields * @param _xSectionToClear */ private void emptySection(XSection _xSectionToClear) { if (_xSectionToClear == null) { return; } // int nCount = _xSectionToClear.getCount(); while (_xSectionToClear.hasElements()) { try { final Object aObj = _xSectionToClear.getByIndex(0); final XShape aShape = UnoRuntime.queryInterface(XShape.class, aObj); _xSectionToClear.remove(aShape); } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } } private void clearDetails() { final XSection xSection = getReportDefinition().getDetail(); emptySection(xSection); } // public void clearFieldTitles() // { // } /** * * @param _nGroupCount * @return the left indent in 1/100mm */ protected int getLeftGroupIndent(int _nGroupCount) { // TODO: Fix values for group indent (1/2cm) only the first 2 groups int nIndent = 0; final int MAX_INDENT = 2; if (_nGroupCount <= MAX_INDENT) { nIndent = _nGroupCount * LayoutConstants.IndentFactorWidth; } else { nIndent = MAX_INDENT * LayoutConstants.IndentFactorWidth; } return nIndent; } /** * Get left page indent. * The left indent is the area on the left side which will no be printed. * The default is 2000 1/100mm what is 2cm of DIN A4. * @return the left indent in 1/100mm */ int m_nLeftIndent = -1; protected int getLeftPageIndent() { if (m_nLeftIndent < 0) { m_nLeftIndent = getFromPageStyles("LeftMargin", 2000); } return m_nLeftIndent; } /** * Get right page indent. * The right indent is the area on the right side which will no be printed. * The default is 2000 1/100mm what is 2cm of DIN A4. * @return the right indent in 1/100mm */ int m_nRightIndent = -1; protected int getRightPageIndent() { if (m_nRightIndent < 0) { m_nRightIndent = getFromPageStyles("RightMargin", 2000); } return m_nRightIndent; } private XStyle getUsedStyle(String _sStyleName) { XStyle aUsedStyle = null; final XNameAccess xNameAccess = getReportDefinition().getStyleFamilies(); try { // // String[] aNames = xNameAccess.getElementNames(); // // get all Page Styles final Object aPageStylesObj = xNameAccess.getByName(_sStyleName); final XNameAccess xContainer = UnoRuntime.queryInterface(XNameAccess.class, aPageStylesObj); // step over all Page Styles, search the one which is in use final String[] aElementNames = xContainer.getElementNames(); for (int i = 0; i < aElementNames.length; i++) { final String sName = aElementNames[i]; final Object aObj = xContainer.getByName(sName); final XStyle xStyle = UnoRuntime.queryInterface(XStyle.class, aObj); if (xStyle.isInUse()) { aUsedStyle = xStyle; break; } } } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } return aUsedStyle; } protected int getFromPageStyles(String _sStyleName, int _nDefault) { int nValue = _nDefault; final XStyle xStyle = getUsedStyle("PageStyles"); if (xStyle != null) { // we found the page style which is in use final PropertySetHelper aHelper = new PropertySetHelper(xStyle); nValue = aHelper.getPropertyValueAsInteger(_sStyleName, nValue); } return nValue; } protected void setToPageStyles(String _sStyleName, Object _aObj) { final XStyle xStyle = getUsedStyle("PageStyles"); if (xStyle != null) { final PropertySetHelper aHelper = new PropertySetHelper(xStyle); aHelper.setPropertyValueDontThrow(_sStyleName, _aObj); } } /** * Get page width. The default is 21000 1/100mm what is 21cm of DIN A4. * @return the Width of the page in 1/100mm */ int m_nPageWidth = -1; protected int getPageWidth() { if (m_nPageWidth < 0) { m_nPageWidth = getFromPageStyles(PropertyNames.PROPERTY_WIDTH, 21000); } return m_nPageWidth; } // ------------------------------------------------------------------------- /** * Stores the Group names. To insert/create a report with such group names, call layout() * @param _aGroupNames */ public void insertGroupNames(String[] _aGroupNames) { m_aGroupNames = _aGroupNames; } public void insertSortingNames(String[][] _aSortFieldNames) { m_aSortNames = _aSortFieldNames; } protected void copyGroupProperties(int _nGroup) { if (getDesignTemplate() != null) { try { final XGroups xForeignGroups = getDesignTemplate().getGroups(); if (_nGroup < xForeignGroups.getCount()) { XGroup xForeignGroup = UnoRuntime.queryInterface(XGroup.class, xForeignGroups.getByIndex(_nGroup)); XSection xForeignGroupSection = xForeignGroup.getHeader(); if (xForeignGroupSection != null) { final XGroups xGroups = getReportDefinition().getGroups(); Object aGroup = xGroups.getByIndex(_nGroup); XGroup xGroup = UnoRuntime.queryInterface(XGroup.class, aGroup); XSection xGroupSection = xGroup.getHeader(); // copy Properties copyProperties(xForeignGroupSection, xGroupSection); } } } catch (Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } } // ------------------------------------------------------------------------- protected int insertGroups() { final XGroups xGroups = getReportDefinition().getGroups(); int lastGroupPosition = -1; if (m_aGroupNames != null) { final int nLeftPageIndent = getLeftPageIndent(); final int nLabelWidth = getMaxLabelWidth(); // 3000; final int nUsablePageWidth = getPageWidth() - getLeftPageIndent() - getRightPageIndent() - getLeftGroupIndent(getCountOfGroups()); final int nFieldWidth = nUsablePageWidth - nLabelWidth; XGroup aLastGroup = null; // after done with all groups, we need access to the last group, for set property 'KeepTogether' so we remember it. for (int i = 0; i < m_aGroupNames.length; i++) { lastGroupPosition = i; final XGroup xGroup = xGroups.createGroup(); aLastGroup = xGroup; xGroup.setExpression(m_aGroupNames[i]); xGroup.setHeaderOn(true); try { int nCount = xGroups.getCount(); xGroups.insertByIndex(nCount, xGroup); final XSection xGroupSection = xGroup.getHeader(); copyGroupProperties(nCount); Rectangle aRect = new Rectangle(); aRect.X = nLeftPageIndent + getLeftGroupIndent(i); SectionObject aSO = getDesignTemplate().getGroupLabel(i); aRect = insertLabel(xGroupSection, getTitleFromFieldName(m_aGroupNames[i]), aRect, nLabelWidth, aSO); final String sGroupName = convertToFieldName(m_aGroupNames[i]); aSO = getDesignTemplate().getGroupTextField(i); aRect = insertFormattedField(xGroupSection, sGroupName, aRect, nFieldWidth, aSO); int height = aRect.Height; // draw a line under the label/formattedfield aRect.X = nLeftPageIndent + getLeftGroupIndent(i); aRect.Y = aRect.Height; final int nLineWidth = getPageWidth() - getRightPageIndent() - aRect.X; final int nLineHeight = LayoutConstants.LineHeight; insertHorizontalLine(xGroupSection, aRect, nLineWidth, nLineHeight); xGroupSection.setHeight(height + nLineHeight); } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } // hold the inner group together if (aLastGroup != null) { doNotBreakInTable(aLastGroup); } } if (m_aSortNames != null) { for (String[] sortFieldName : m_aSortNames) { try { final XGroup xGroup = xGroups.createGroup(); xGroup.setExpression(sortFieldName[0]); xGroup.setSortAscending(PropertyNames.ASC.equals(sortFieldName[1])); xGroup.setHeaderOn(false); int nCount = xGroups.getCount(); xGroups.insertByIndex(nCount, xGroup); } catch (java.lang.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } } return lastGroupPosition; } // ------------------------------------------------------------------------- /** * Give a list off all field title names to insert the field title names, call layout() * @param _aFieldTitleNames */ public void insertFieldTitles(String[] _aFieldTitleNames) { m_aFieldTitleNames = _aFieldTitleNames; } // ------------------------------------------------------------------------- protected String getTitleFromFieldName(String _sField) { for (int i = 0; i < m_aFieldNames.length; i++) { if (m_aFieldNames[i].equals(_sField)) { return m_aFieldTitleNames[i]; } } return PropertyNames.EMPTY_STRING; } protected int getTypeFromFieldName(String _sField) { for (int i = 0; i < m_aFieldNames.length; i++) { if (m_aFieldNames[i].equals(_sField)) { return m_aFieldTypes[i]; } } return 0; } protected boolean listContains(String[] _aList, String _aValue) { for (int i = 0; i < _aList.length; i++) { if (_aList[i].equals(_aValue)) { return true; } } return false; } // ------------------------------------------------------------------------- /** * Helper to get all field names without the names which are already in the group names * @param _aList * @param _aGetResultFrom * @return */ protected String[] getNamesWithoutGroupNames(String[] _aList, String[] _aGetResultFrom) { if (_aList == null /* || _aGetResultsFrom == null */) { return new String[] { }; /* empty list */ } if (getCountOfGroups() == 0) { if (_aGetResultFrom != null) { return _aGetResultFrom; } return _aList; } final int nNewLength = _aList.length - getCountOfGroups(); String[] aNewList = new String[nNewLength]; int j = 0; for (int i = 0; i < _aList.length; i++) { final String sField = _aList[i]; if (listContains(m_aGroupNames, sField)) { continue; } if (_aGetResultFrom != null) { aNewList[j++] = _aGetResultFrom[i]; } else { aNewList[j++] = sField; } if (j == nNewLength) { break; // Emergency break, we leave the result list. } } return aNewList; } // ------------------------------------------------------------------------- protected int calculateFieldWidth(int _nLeftIndent, int _nFieldCount) { int nWidth = 3000; if (_nFieldCount > 0) { nWidth = (getPageWidth() - getLeftPageIndent() - getRightPageIndent() - _nLeftIndent) / _nFieldCount; } return nWidth; } protected String[] getFieldTitleNames() { return getNamesWithoutGroupNames(m_aFieldNames, m_aFieldTitleNames); } // ------------------------------------------------------------------------- abstract protected void insertDetailFieldTitles(int lastGroupPostion); // ------------------------------------------------------------------------- /** * Give a list off all field names to insert the field names, call layout() * @param _aFieldNames */ public void insertFieldNames(String[] _aFieldNames) { m_aFieldNames = _aFieldNames; } public void insertFieldTypes(int[] _aFieldTypes) { m_aFieldTypes = _aFieldTypes; } public void insertFieldWidths(int[] _aFieldWidths) { m_aFieldWidths = _aFieldWidths; } protected int getCountOfGroups() { return ((m_aGroupNames == null) ? 0 : m_aGroupNames.length); } // ------------------------------------------------------------------------- protected String[] getFieldNames() { return getNamesWithoutGroupNames(m_aFieldNames, null); } abstract protected void insertDetailFields(); protected void copyDetailProperties() { if (getDesignTemplate() != null) { try { XSection xForeignSection = getDesignTemplate().getDetail(); if (xForeignSection != null) { XSection xSection = getReportDefinition().getDetail(); // copy Properties copyProperties(xForeignSection, xSection); } } catch (Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } } // ------------------------------------------------------------------------- protected Rectangle insertLabel(XSection _xSection, String _sLabel, Rectangle _aRect, int _nWidth, SectionObject _aSO) { if (_xSection != null) { try { final Object aFixedText = getMSFofReportDefinition().createInstance("com.sun.star.report.FixedText"); final XFixedText xFixedText = UnoRuntime.queryInterface(XFixedText.class, aFixedText); int nHeight = LayoutConstants.LabelHeight; // default height of label is fixed. if (_aSO != null) { if (_aSO instanceof SectionEmptyObject) { float fCharWeight = _aSO.getCharWeight(com.sun.star.awt.FontWeight.NORMAL); if (fCharWeight > 0.1f) { xFixedText.setCharWeight(fCharWeight); } } else { // TODO: there seems to be some problems with copy all properties from the design template to the current design final FontDescriptor aFD = _aSO.getFontDescriptor(); if (aFD != null) { xFixedText.setFontDescriptor(aFD); copyProperties(_aSO.getParent(), xFixedText); } nHeight = _aSO.getHeight(LayoutConstants.LabelHeight); } } xFixedText.setLabel(_sLabel); xFixedText.setPositionX(_aRect.X); xFixedText.setPositionY(_aRect.Y); // Width will calculate from outside. // We have to set, because there exist no right default (0) xFixedText.setWidth(_nWidth); _aRect.X += _nWidth; xFixedText.setHeight(nHeight); _xSection.add(xFixedText); } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } return _aRect; } // ------------------------------------------------------------------------- protected String convertToFieldName(String _sElementName) { final StringBuffer aDataField = new StringBuffer(32); aDataField.append("field:[").append(_sElementName).append(']'); return aDataField.toString(); } protected String convertFromFieldName(String _sName) { if (_sName.startsWith("field:[")) { int nCloseBrace = _sName.lastIndexOf("]"); return _sName.substring(7, nCloseBrace).trim(); } return _sName; } // ------------------------------------------------------------------------- /** * Insert a already formatted field name into a given section * * Use 'convertToFieldName(dbfield)' to convert a dbfield name in the right. * * @param _xSection in which section the formatted field will store * @param _sFormattedfield as String a dbfield or an other function * @param _aRect .X, .Y are the absolute position (1/100mm) where the formatted field will set * @param _nWidth the width of the field in 1/100mm * @param _aSO * @return a new Rectangle with the new Rect.X position, Rect.Y will not change. */ protected Rectangle insertFormattedField(XSection _xSection, String _sFormattedfield, Rectangle _aRect, int _nWidth, SectionObject _aSO) { return insertFormattedField(_xSection, _sFormattedfield, _aRect, _nWidth, _aSO, (short) com.sun.star.awt.TextAlign.LEFT); } protected Rectangle insertFormattedField(XSection _xSection, String _sFormattedfield, Rectangle _aRect, int _nWidth, SectionObject _aSO, short _nAlignment) { if (_xSection != null) { try { Object aField; int nHeight = LayoutConstants.FormattedFieldHeight; int nType = getTypeFromFieldName(convertFromFieldName(_sFormattedfield)); if (nType == DataType.BINARY || nType == DataType.VARBINARY || nType == DataType.LONGVARBINARY) { aField = getMSFofReportDefinition().createInstance("com.sun.star.report.ImageControl"); nHeight = LayoutConstants.BinaryHeight; } else { aField = getMSFofReportDefinition().createInstance("com.sun.star.report.FormattedField"); nHeight = LayoutConstants.FormattedFieldHeight; if (nType == DataType.LONGVARCHAR) /* memo */ { nHeight = LayoutConstants.MemoFieldHeight; // special case for memo } } _aRect.Height = nHeight; final XReportControlModel xReportControlModel = UnoRuntime.queryInterface(XReportControlModel.class, aField); if (xReportControlModel != null) { // #i86907# not documented right in idl description. xReportControlModel.setDataField(_sFormattedfield); if (_aSO != null) { // TODO: there seems to be some problems with copy all properties from the design template to the current design final FontDescriptor aFD = _aSO.getFontDescriptor(); if (aFD != null) { xReportControlModel.setFontDescriptor(aFD); copyProperties(_aSO.getParent(), xReportControlModel); } nHeight = _aSO.getHeight(nHeight); } xReportControlModel.setPositionX(_aRect.X); xReportControlModel.setPositionY(_aRect.Y); xReportControlModel.setWidth(_nWidth); _aRect.X += _nWidth; xReportControlModel.setHeight(nHeight); if (nType == DataType.BINARY || nType == DataType.VARBINARY || nType == DataType.LONGVARBINARY) { // aField = getMSFofReportDefinition().createInstance("com.sun.star.report.ImageControl"); final XImageControl xImageControl = UnoRuntime.queryInterface(XImageControl.class, xReportControlModel); if (xImageControl != null) { // xImageControl.setScaleImage(true); xImageControl.setScaleMode(com.sun.star.awt.ImageScaleMode.ISOTROPIC); } } else { try { xReportControlModel.setParaAdjust(_nAlignment); // if (nType == DataType.LONGVARCHAR) // { // xReportControlModel.??? // } } catch (com.sun.star.beans.UnknownPropertyException ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } // spezial case rpt:now() (default date format) if (_sFormattedfield.equals("rpt:now()")) { final XFormattedField xFormattedField = UnoRuntime.queryInterface(XFormattedField.class, xReportControlModel); XNumberFormatsSupplier x = xFormattedField.getFormatsSupplier(); XNumberFormats xFormats = x.getNumberFormats(); XNumberFormatTypes x3 = UnoRuntime.queryInterface(XNumberFormatTypes.class, xFormats); Locale.getDefault(); com.sun.star.lang.Locale aLocale = new com.sun.star.lang.Locale(); aLocale.Country = Locale.getDefault().getCountry(); aLocale.Language = Locale.getDefault().getLanguage(); int nFormat = x3.getStandardFormat(com.sun.star.util.NumberFormat.DATE, aLocale); xFormattedField.setFormatKey(nFormat); } _xSection.add(xReportControlModel); } } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } return _aRect; } // ------------------------------------------------------------------------- // TODO: check with Query, this code will not work with Queries public void setTableName(int _aType, String _sTableName) { m_aCommandType = _aType; m_sTableName = _sTableName; // getReportDefinition().setCommandType(com.sun.star.sdb.CommandType.TABLE); getReportDefinition().setCommandType(_aType); getReportDefinition().setCommand(_sTableName); } // ------------------------------------------------------------------------- protected XMultiServiceFactory m_xMSF; protected XMultiServiceFactory getMSFofReportDefinition() { if (m_xMSF == null) { m_xMSF = UnoRuntime.queryInterface(XMultiServiceFactory.class, getReportDefinition()); } return m_xMSF; } // ------------------------------------------------------------------------- protected Rectangle insertVerticalLine(XSection _xSection, Rectangle _aRect, int _nWidth, int _nHeight) { return insertLine(_xSection, _aRect, _nWidth, _nHeight, 1); } protected Rectangle insertHorizontalLine(XSection _xSection, Rectangle _aRect, int _nWidth, int _nHeight) { return insertLine(_xSection, _aRect, _nWidth, _nHeight, 0); } protected Rectangle insertLine(XSection _xSection, Rectangle _aRect, int _nWidth, int _nHeight, int _nOrientation) { if (_xSection != null) { try { final Object aFixedLine = getMSFofReportDefinition().createInstance("com.sun.star.report.FixedLine"); final XFixedLine xFixedLine = UnoRuntime.queryInterface(XFixedLine.class, aFixedLine); xFixedLine.setOrientation(_nOrientation); // TODO: line width is fixed xFixedLine.setLineWidth(8); xFixedLine.setPositionX(_aRect.X); xFixedLine.setPositionY(_aRect.Y); xFixedLine.setWidth(_nWidth); _aRect.X += _nWidth; xFixedLine.setHeight(_nHeight); _xSection.add(xFixedLine); } catch (com.sun.star.uno.Exception ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } return _aRect; } // ------------------------------------------------------------------------- protected void clearReportHeader() { XSection xSection; try { if (getReportDefinition().getReportHeaderOn()) { xSection = getReportDefinition().getReportHeader(); emptySection(xSection); } } catch (com.sun.star.container.NoSuchElementException ex) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, ex); } } protected void insertReportHeader() { if (getDesignTemplate() != null) { if (getDesignTemplate().getReportHeaderOn()) { // copy all Section information from Page Header to our Header try { XSection xForeignSection = getDesignTemplate().getReportHeader(); if (xForeignSection != null) { getReportDefinition().setReportHeaderOn(true); XSection xSection = getReportDefinition().getReportHeader(); // copy Sections copySection(xForeignSection, xSection); } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } else { // we won't a page header getReportDefinition().setReportHeaderOn(false); } } } protected void clearReportFooter() { XSection xSection; try { if (getReportDefinition().getReportFooterOn()) { xSection = getReportDefinition().getReportFooter(); emptySection(xSection); } } catch (com.sun.star.container.NoSuchElementException e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } protected void insertReportFooter() { if (getDesignTemplate() != null) { if (getDesignTemplate().getReportFooterOn()) { // copy all Section information from Page Header to our Header try { XSection xForeignSection = getDesignTemplate().getReportFooter(); if (xForeignSection != null) { getReportDefinition().setReportFooterOn(true); XSection xSection = getReportDefinition().getReportFooter(); // copy Sections copySection(xForeignSection, xSection); } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } else { // we won't a page header getReportDefinition().setReportFooterOn(false); } } } // ------------------------------------------------------------------------- protected void clearPageHeader() { XSection xSection; try { if (getReportDefinition().getPageHeaderOn()) { xSection = getReportDefinition().getPageHeader(); emptySection(xSection); } } catch (com.sun.star.container.NoSuchElementException e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } // protected static String getDateString(String _sFormat) // { // GregorianCalendar aCalendar = new GregorianCalendar(); // StringBuffer aBuf = new StringBuffer(); // // Locale aLocale = new Locale("en","US"); // SimpleDateFormat aFormat = new SimpleDateFormat(_sFormat, aLocale); // aBuf = aFormat.format(aCalendar.getTime(), aBuf, new FieldPosition(0) ); // // DebugHelper.writeInfo("Date: " + aBuf.toString()); // return aBuf.toString(); // } // protected String getCurrentDate() // { // Calendar aCalendar = Calendar.getInstance(); //// aCalendar.setTimeInMillis(1202382900000L); //// aCalendar. // Date aDate = new Date(); // String sDate = DateFormat.getDateInstance().format(aDate); // // String aCalStr = aCalendar.toString(); // return sDate; // // //// Date aDate = new Date(); //// aDate.setSeconds(0); //// aDate.setMinutes(15); //// aDate.setHours(12); //// // aDate.setMonth(2); //// // aDate.setYear(2008); //// // aDate.setDay(7); //// long nTime = aDate.getTime(); //// Long aLong = new Long(nTime); //// String aStr = aLong.toString(); //// //// Date aNewDate = new Date(1202382900000L); ////// aNewDate. //// String aDateStr = aNewDate.toString(); ////// Datetime aNewTime = new Time(1202382900); ////// String aTimeStr = aNewTime.toString(); //// // // } protected void clearPageFooter() { XSection xSection; try { if (getReportDefinition().getPageFooterOn()) { xSection = getReportDefinition().getPageFooter(); emptySection(xSection); } } catch (com.sun.star.container.NoSuchElementException e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } public void setPageOrientation(int _nOrientation) { final int nWidth = getFromPageStyles(PropertyNames.PROPERTY_WIDTH, 0); final int nHeight = getFromPageStyles(PropertyNames.PROPERTY_HEIGHT, 0); if (com.sun.star.wizards.report.ReportLayouter.SOOPTLANDSCAPE == _nOrientation) { setToPageStyles("IsLandscape", Boolean.TRUE); if (nWidth < nHeight) { setToPageStyles(PropertyNames.PROPERTY_WIDTH, new Integer(nHeight)); setToPageStyles(PropertyNames.PROPERTY_HEIGHT, new Integer(nWidth)); } } else { setToPageStyles("IsLandscape", Boolean.FALSE); if (nHeight < nWidth) { setToPageStyles(PropertyNames.PROPERTY_WIDTH, new Integer(nHeight)); setToPageStyles(PropertyNames.PROPERTY_HEIGHT, new Integer(nWidth)); } } // dirty the PageWidth m_nPageWidth = -1; } /** * Returns the width and height of a given string (_sText) in 1/100mm drawn in the given font descriptor. * TODO: This function is a performance leak, we could store already calculated values in a map, to build a cache. Access should be much faster then. * * @param _sText * @param _aFont * @return width of given text in 1/100mm */ Size getPreferredSize(String _sText, FontDescriptor _aFont) { Size aSizeMM_100TH = new Size(0, 0); try { // Object aControlContainer = getGlobalMSF().createInstance("com.sun.star.awt.UnoControlContainer"); // XControlContainer xControlContainer = (XControlContainer)UnoRuntime.queryInterface(XControlContainer.class, aControlContainer); final Object aFixedTextModel = getGlobalMSF().createInstance("com.sun.star.awt.UnoControlFixedTextModel"); final XControlModel xFixedTextModel = UnoRuntime.queryInterface(XControlModel.class, aFixedTextModel); final PropertySetHelper aPropertySetHelper = new PropertySetHelper(xFixedTextModel); // aPropertySetHelper.showProperties(); aPropertySetHelper.setPropertyValueDontThrow(PropertyNames.FONT_DESCRIPTOR, _aFont); final Object aUnoCtrlFixedText = getGlobalMSF().createInstance("com.sun.star.awt.UnoControlFixedText"); // XServiceInfo xServiceInfo2 = (XServiceInfo)UnoRuntime.queryInterface(XServiceInfo.class, aUnoCtrlFixedText); // String[] sServices2 = xServiceInfo2.getSupportedServiceNames(); final XWindow xWindow = UnoRuntime.queryInterface(XWindow.class, aUnoCtrlFixedText); xWindow.setVisible(false); final XControl xControl = UnoRuntime.queryInterface(XControl.class, aUnoCtrlFixedText); xControl.setModel(xFixedTextModel); final com.sun.star.awt.XFixedText xFixedText = UnoRuntime.queryInterface(com.sun.star.awt.XFixedText.class, aUnoCtrlFixedText); xFixedText.setText(_sText); final XLayoutConstrains xLayoutConstraints = UnoRuntime.queryInterface(XLayoutConstrains.class, aUnoCtrlFixedText); final Size aSizeInPixel = xLayoutConstraints.getPreferredSize(); final XWindowPeer xPeerOfReportDefinition = UnoRuntime.queryInterface(XWindowPeer.class, getReportDefinition().getCurrentController().getFrame().getComponentWindow()); xControl.createPeer(null, xPeerOfReportDefinition); final XWindowPeer x = xControl.getPeer(); final XUnitConversion xConversion = UnoRuntime.queryInterface(XUnitConversion.class, x); aSizeMM_100TH = xConversion.convertSizeToLogic(aSizeInPixel, com.sun.star.util.MeasureUnit.MM_100TH); // xToolkit.createScreenCompatibleDevice(_nWidth, _nWidth). // XWindow x = getReportDefinition().getCurrentController().getFrame().getContainerWindow(); // Object aObj = _xSection.getParent(); // we don't need the created objects any longer final XComponent xFixedTextDeleter = UnoRuntime.queryInterface(XComponent.class, xFixedText); xFixedTextDeleter.dispose(); final XComponent xFixedTextModelDeleter = UnoRuntime.queryInterface(XComponent.class, aFixedTextModel); xFixedTextModelDeleter.dispose(); } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } return aSizeMM_100TH; } protected String getTableName() { if (m_sTableName != null) { return m_sTableName; } return PropertyNames.EMPTY_STRING; } protected String getUserNameFromConfiguration() { String sFirstName = PropertyNames.EMPTY_STRING; String sLastName = PropertyNames.EMPTY_STRING; try { Object oProdNameAccess = Configuration.getConfigurationRoot(getGlobalMSF(), "org.openoffice.UserProfile/Data", false); sFirstName = (String) Helper.getUnoObjectbyName(oProdNameAccess, "givenname"); sLastName = (String) Helper.getUnoObjectbyName(oProdNameAccess, "sn"); } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } return sFirstName + PropertyNames.SPACE + sLastName; } /** * Helper function, to copy all not read only properties of _xFromSection to _xToSection * @param _xFromSection * @param _xToSection */ private void copyProperties(Object _aFrom, Object _aTo) { XPropertySet xFrom = UnoRuntime.queryInterface(XPropertySet.class, _aFrom); XPropertySet xTo = UnoRuntime.queryInterface(XPropertySet.class, _aTo); XPropertySetInfo xForeignPropInfo = xFrom.getPropertySetInfo(); XPropertySetInfo xSectionPropInfo = xTo.getPropertySetInfo(); Property[] aAllProperties = xForeignPropInfo.getProperties(); for (int i = 0; i < aAllProperties.length; i++) { String sPropertyName = aAllProperties[i].Name; if (xSectionPropInfo.hasPropertyByName(sPropertyName)) { try { Property aDestProp = xForeignPropInfo.getPropertyByName(sPropertyName); if ((aDestProp.Attributes & PropertyAttribute.READONLY) == 0) { xTo.setPropertyValue(sPropertyName, xFrom.getPropertyValue(sPropertyName)); } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } } } /** * Helper Funktion to copy the whole content of _xFromSection to the _xToSection * @param _xFromSection * @param _xToSection */ private void copySection(XSection _xFromSection, XSection _xToSection) { copyProperties(_xFromSection, _xToSection); try { XEnumeration xEnum = _xFromSection.createEnumeration(); while (xEnum.hasMoreElements()) { Object aEnumObj = xEnum.nextElement(); XReportComponent aComponent = UnoRuntime.queryInterface(XReportComponent.class, aEnumObj); // XCloneable aClone = (XCloneable)UnoRuntime.queryInterface(XCloneable.class, aEnumObj); if (aComponent != null) { Object aClone = aComponent.createClone(); if (aClone != null) { XShape aShape = UnoRuntime.queryInterface(XShape.class, aClone); // normally 'createClone' will create a real clone of the component, // but there seems some problems, we have to control. copyProperties(aComponent, aClone); // aShape.setPosition(aComponent.getPosition()); // aShape.setSize(aComponent.getSize()); _xToSection.add(aShape); } } } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } // String sName = xForeignSection.getName(); // int dummy = 0; } protected void insertPageHeader() { if (getDesignTemplate() != null) { if (getDesignTemplate().getPageHeaderOn()) { // copy all Section information from Page Header to our Header try { XSection xForeignSection = getDesignTemplate().getPageHeader(); if (xForeignSection != null) { getReportDefinition().setPageHeaderOn(true); XSection xSection = getReportDefinition().getPageHeader(); // copy Sections copySection(xForeignSection, xSection); } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } else { // we won't a page header // getReportDefinition().setPageHeaderOn(true); getReportDefinition().setPageHeaderOn(false); } } else { if (getReportDefinition() == null) { return; } // there is no foreign report definition // TODO: #i86902# rpt:Title() out of the document // TODO: #i86902# rpt:Author() can't set with something like rpt:author() // TODO: #i86902# more fieldnames need. final String sTitleTitle = getResource().getResText(UIConsts.RID_REPORT + 86); // "Title:" final String sTitle = getTableName(); // "Default title, this is a first draft report generated by the new report wizard."; final String sAuthorTitle = getResource().getResText(UIConsts.RID_REPORT + 87); // "Author:" final String sAuthor = getUserNameFromConfiguration(); // "You"; // rpt:fieldvalue(); final String sDateTitle = getResource().getResText(UIConsts.RID_REPORT + 88); // "Date:" // TODO: #i86911# Date: we need to set the style of the date. final String sDate = "rpt:now()"; // getDateString("EEE, d MMM yyyy HH:mm:ss zzzz"); try { getReportDefinition().setPageHeaderOn(true); XSection xSection = null; xSection = getReportDefinition().getPageHeader(); Rectangle aRect = new Rectangle(); aRect.X = getLeftPageIndent(); SectionObject aSOLabel = SectionEmptyObject.create(); aSOLabel.setFontToBold(); aRect.Y = aSOLabel.getHeight(LayoutConstants.LabelHeight); final int nWidth = 3000; aRect = insertLabel(xSection, sTitleTitle, aRect, nWidth, aSOLabel); final int nTitleWidth = getPageWidth() - getLeftPageIndent() - getRightPageIndent() - 3000; // aRect = insertFormattedField(xSection, "rpt:Title()", aRect, nTitleWidth); aRect = insertLabel(xSection, sTitle, aRect, nTitleWidth, aSOLabel); aRect.Y += aSOLabel.getHeight(LayoutConstants.LabelHeight) + LayoutConstants.LineHeight; aRect.X = getLeftPageIndent(); aRect = insertLabel(xSection, sAuthorTitle, aRect, nWidth, aSOLabel); // aRect = insertFormattedField(xSection, "rpt:Author()", aRect, nWidth); aRect = insertLabel(xSection, sAuthor, aRect, nTitleWidth, aSOLabel); aRect.Y += aSOLabel.getHeight(LayoutConstants.LabelHeight); aRect.X = getLeftPageIndent(); aRect = insertLabel(xSection, sDateTitle, aRect, nWidth, aSOLabel); // aRect = insertFormattedField(xSection, "rpt:Date()", aRect, nWidth); aRect = insertFormattedField(xSection, sDate, aRect, nTitleWidth, aSOLabel); aRect.Y += aSOLabel.getHeight(LayoutConstants.FormattedFieldHeight) + LayoutConstants.LineHeight; // draw a line under the label/formattedfield aRect.X = getLeftPageIndent(); final int nLineWidth = getPageWidth() - getRightPageIndent() - aRect.X; final int nLineHeight = LayoutConstants.LineHeight; insertHorizontalLine(xSection, aRect, nLineWidth, nLineHeight); aRect.Y += nLineHeight; xSection.setHeight(aRect.Y); } catch (com.sun.star.uno.Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } } protected void insertPageFooter() { if (getDesignTemplate() != null) { if (getDesignTemplate().getPageFooterOn()) { try { XSection xForeignSection = getDesignTemplate().getPageFooter(); if (xForeignSection != null) { getReportDefinition().setPageFooterOn(true); XSection xSection = getReportDefinition().getPageFooter(); // copy Sections copySection(xForeignSection, xSection); } } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } else { // getReportDefinition().setPageFooterOn(true); getReportDefinition().setPageFooterOn(false); } } else { if (getReportDefinition() == null) { return; } // TODO: how should we arrive this code (set page and pagecount in the middle of the page footer) // If there exists a design template, don't use it. // we don't have a default report definition final String sPageOf = getResource().getResText(UIConsts.RID_REPORT + 89); // 'Page #page# of #count#' // Convert // 'Page #page# of #count#' // to something like // '\"Page \" & PageNumber() & \" of \" & PageCount()' // due to the fact that is is not fixed, where #page# or #count# occurs, we make it // a little bit trickier. // we first surround the string with double quotes, // second, replace the #...# // last, we remove double 'double quotes'. final String sSurroundDoubleQuotes = "\"" + sPageOf + "\""; final String sPageNumber = sSurroundDoubleQuotes.replaceAll("#page#", "\" & PageNumber() & \""); final String sPageCount = sPageNumber.replaceAll("#count#", "\" & PageCount() & \""); final String sNoLastUnusedQuotes = sPageCount.replaceAll(" & \\\"\\\"", PropertyNames.EMPTY_STRING); final String sNoFirstUnusedQuotes = sNoLastUnusedQuotes.replaceAll("\\\"\\\" & ", PropertyNames.EMPTY_STRING); final int nUsablePageWidth = getPageWidth() - getLeftPageIndent() - getRightPageIndent(); try { getReportDefinition().setPageFooterOn(true); XSection xSection = null; xSection = getReportDefinition().getPageFooter(); Rectangle aRect = new Rectangle(); aRect.X = getLeftPageIndent(); // draw a line over the label/formattedfield final int nLineWidth = getPageWidth() - getRightPageIndent() - aRect.X; final int nLineHeight = LayoutConstants.LineHeight; insertHorizontalLine(xSection, aRect, nLineWidth, nLineHeight); aRect.Y += nLineHeight; aRect.Y += LayoutConstants.LabelHeight; aRect.X = getLeftPageIndent(); aRect = insertFormattedField(xSection, "rpt:" + sNoFirstUnusedQuotes, aRect, nUsablePageWidth, null, (short) com.sun.star.awt.TextAlign.CENTER); aRect.Y += LayoutConstants.FormattedFieldHeight + LayoutConstants.LineHeight; xSection.setHeight(aRect.Y); } catch (Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } } protected Resource getResource() { return m_aResource; } protected int m_aCommandType; // Table or Query protected String m_sTableName; protected String[] m_aGroupNames; protected String[] m_aFieldNames; protected String[] m_aFieldTitleNames; protected int[] m_aFieldWidths; protected int[] m_aFieldTypes; // protected int[] m_nLeftIndent; private DesignTemplate m_xDesignTemplate = null; public void initializeData(IReportBuilderLayouter _aOther) { if (_aOther instanceof ReportBuilderLayouter) { final ReportBuilderLayouter aOther = (ReportBuilderLayouter) _aOther; m_aCommandType = aOther.m_aCommandType; m_sTableName = aOther.m_sTableName; m_aGroupNames = aOther.m_aGroupNames; m_aFieldNames = aOther.m_aFieldNames; m_aFieldTitleNames = aOther.m_aFieldTitleNames; m_aFieldWidths = aOther.m_aFieldWidths; m_aFieldTypes = aOther.m_aFieldTypes; // m_nLeftIndent = aOther.m_nLeftIndent; m_xDesignTemplate = aOther.m_xDesignTemplate; // dirty PageWidth m_nPageWidth = -1; } } /** * Get the maximal label width of all labels * @return the width in 1/100mm */ protected int getMaxLabelWidth() { int nWidth = 0; final String[] aFieldTitles = m_aFieldTitleNames; // we want all Field Titles here // getFieldTitleNames(); for (int i = 0; i < aFieldTitles.length; i++) { final String sLabel = aFieldTitles[i]; nWidth = Math.max(nWidth, getLabelWidth(sLabel)); } for (int i = 0; i < m_aGroupNames.length; i++) { final String sGroupName = m_aGroupNames[i]; final SectionObject a = getDesignTemplate().getGroupLabel(i); final FontDescriptor aFD = a.getFontDescriptor(); nWidth = Math.max(nWidth, getLabelWidth(sGroupName, aFD)); } if (nWidth == 0) { nWidth = 3000; } else { nWidth += 500; } return nWidth; } /** * Get width of a given string (Label) in 1/100mm * @param _sLabel * @return the width in 1/100mm */ protected int getLabelWidth(String _sLabel) { return getLabelWidth(_sLabel, 0.0f, 0.0f); } XFixedText m_aFixedTextHelper = null; HashMap m_aLabelWidthMap; protected int getLabelWidth(String _sLabel, FontDescriptor _aFD) { float fCharWeight = 0.0f; float fCharHeight = 0.0f; if (_aFD != null) { fCharWeight = _aFD.Weight; fCharHeight = _aFD.Height; } return getLabelWidth(_sLabel, fCharWeight, fCharHeight); } protected int getLabelWidth(String _sLabel, float _nCharWeight, float _nCharHeight) { int nWidth = 0; if (m_aLabelWidthMap == null) { m_aLabelWidthMap = new HashMap(); } // At first, try to get the Width out of a HashMap (Cache) StringBuffer aKey = new StringBuffer(40); final String sKey = aKey.append(_sLabel).append(_nCharWeight).append(_nCharHeight).toString(); if (m_aLabelWidthMap.containsKey(sKey)) { final Object aWidth = m_aLabelWidthMap.get(sKey); final Integer aIntegerWidth = (Integer) aWidth; nWidth = aIntegerWidth.intValue(); } else { try { if (m_aFixedTextHelper == null) { final Object aFixedText = getMSFofReportDefinition().createInstance("com.sun.star.report.FixedText"); m_aFixedTextHelper = UnoRuntime.queryInterface(XFixedText.class, aFixedText); } m_aFixedTextHelper.setLabel(_sLabel); if (_nCharWeight > 0.1f) { m_aFixedTextHelper.setCharWeight(_nCharWeight); } if (_nCharHeight > 0.1f) { m_aFixedTextHelper.setCharHeight(_nCharHeight); } final FontDescriptor xFont = m_aFixedTextHelper.getFontDescriptor(); final Size aSize = getPreferredSize(_sLabel, xFont); nWidth = aSize.Width; // cache the found width m_aLabelWidthMap.put(sKey, new Integer(nWidth)); } catch (com.sun.star.uno.Exception e) { Logger.getLogger(ReportBuilderLayouter.class.getName()).log(Level.SEVERE, null, e); } } return nWidth; } protected void doNotBreakInTable(Object _xSectionOrGroup) { // try // { // _xSection.setKeepTogether(true); final PropertySetHelper aHelper = new PropertySetHelper(_xSectionOrGroup); aHelper.setPropertyValueDontThrow("KeepTogether", Boolean.TRUE); // } // catch (com.sun.star.uno.Exception e) // { // // Exception not set, but not really from interest. // } } protected DesignTemplate getDesignTemplate() { if (m_xDesignTemplate == null) { // initialise the report definition. String sDefaultHeaderLayout = m_xReportDefinitionReadAccess.getDefaultHeaderLayout(); loadAndSetBackgroundTemplate(sDefaultHeaderLayout); // copy all functions from the design template to the current report definition // XFunctions xOtherFunctions = m_xDesignTemplate.getReportDefinition().getFunctions(); // final int nFunctionCount = xOtherFunctions.getCount(); // for (int i=0;i