/* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 . */ package com.sun.star.wizards.form; import com.sun.star.awt.Point; import com.sun.star.awt.Size; import com.sun.star.container.XNameContainer; import com.sun.star.lang.XMultiServiceFactory; import com.sun.star.sdbc.ColumnValue; import com.sun.star.sdbc.DataType; import com.sun.star.task.XStatusIndicator; import com.sun.star.uno.AnyConverter; import com.sun.star.uno.Exception; import com.sun.star.wizards.common.Helper; import com.sun.star.wizards.common.Resource; import com.sun.star.wizards.common.PropertyNames; import com.sun.star.wizards.db.*; import com.sun.star.wizards.document.Control; import com.sun.star.wizards.document.DatabaseControl; import com.sun.star.wizards.document.FormHandler; import com.sun.star.wizards.document.Shape; import com.sun.star.wizards.document.TimeStampControl; public class FormControlArranger { private static final String LABELCONTROL = "LabelControl"; protected DatabaseControl[] DBControlList = null; private final XNameContainer xFormName; private final XMultiServiceFactory xMSF; private Control[] LabelControlList = null; private final XStatusIndicator xProgressBar; private final FieldColumn[] FieldColumns; // Control curLabelControl; private int icurArrangement; private boolean bIsFirstRun; private boolean bIsVeryFirstRun; private boolean bControlsareCreated; private int cXOffset; private int cYOffset; private static final int cVertDistance = 200; private static final int cHoriDistance = 300; private static final int cLabelGap = 100; private static final double CMAXREDUCTION = 0.7; private final FormHandler oFormHandler; private int iReduceWidth; private int m_currentLabelPosX; private int m_currentLabelPosY; private int m_currentControlPosX; private int m_currentControlPosY; private int m_LabelHeight; private int m_LabelWidth; private int m_dbControlHeight; private int m_dbControlWidth; private int m_MaxLabelWidth; private int nFormWidth; private int nFormHeight; private int m_currentMaxRowHeight; private int nSecMaxRowY; private int m_maxPositionX; private int a; private int StartA; private int m_controlMaxPosY = 0; //the maximum YPosition of a DBControl in the form private Short NBorderType = Short.valueOf((short) 1); //3-D Border public FormControlArranger(FormHandler _oFormHandler, XNameContainer _xFormName, CommandMetaData oDBMetaData, XStatusIndicator _xProgressBar, Point _StartPoint, Size _FormSize) { FieldColumns = oDBMetaData.FieldColumns; xMSF = oDBMetaData.xMSF; xFormName = _xFormName; xProgressBar = _xProgressBar; LabelControlList = new Control[FieldColumns.length]; DBControlList = new DatabaseControl[FieldColumns.length]; oFormHandler = _oFormHandler; cXOffset = _StartPoint.X; cYOffset = _StartPoint.Y; setFormSize(_FormSize); } // Note: on all Controls except for the checkbox the Label has to be set // a bit under the DBControl because its Height is also smaller private int getLabelDiffHeight(int _index) { final DatabaseControl curDBControl = DBControlList[_index]; if (curDBControl != null && curDBControl.getControlType() == FormHandler.SOCHECKBOX) { return getCheckBoxDiffHeight(_index); } return oFormHandler.getBasicLabelDiffHeight(); } public Control[] getLabelControlList() { return LabelControlList; } private int getCheckBoxDiffHeight(int LastIndex) { if (LastIndex < DBControlList.length && DBControlList[LastIndex].getControlType() == FormHandler.SOCHECKBOX) { return (oFormHandler.getControlReferenceHeight() - DBControlList[LastIndex].getControlHeight()) / 2; } return 0; } private boolean isReducable(int _index, int i_labelWidth, int i_dbControlWidth) { boolean bisreducable = false; int ntype = FieldColumns[_index].getFieldType(); switch (ntype) { case DataType.TINYINT: case DataType.SMALLINT: case DataType.INTEGER: case DataType.FLOAT: case DataType.DATE: case DataType.TIME: case DataType.TIMESTAMP: case DataType.REAL: case DataType.DOUBLE: case DataType.NUMERIC: case DataType.DECIMAL: case DataType.BIT: case DataType.BOOLEAN: bisreducable = false; break; case DataType.VARCHAR: short nTextLen; try { nTextLen = AnyConverter.toShort(DBControlList[_index].xPropertySet.getPropertyValue("MaxTextLen")); if ((nTextLen == 0) || (nTextLen > 20)) { bisreducable = true; } } catch (Exception e) { e.printStackTrace(System.err); } break; case DataType.BIGINT: bisreducable = true; break; default: bisreducable = true; } if (bisreducable && i_labelWidth > 0.9 * CMAXREDUCTION * i_dbControlWidth) { bisreducable = false; } return bisreducable; } private void checkJustifiedPosition(int a) { int nBaseWidth = nFormWidth + cXOffset; int nLeftDist = m_maxPositionX - nBaseWidth; int nRightDist = nBaseWidth - (DBControlList[a].getPosition().X - cHoriDistance); if (nLeftDist < 0.5 * nRightDist) { // Fieldwidths in the line can be made smaller... adjustLineWidth(StartA, a, nLeftDist, -1); m_currentLabelPosY = m_currentMaxRowHeight + cVertDistance; m_currentControlPosY = m_currentLabelPosY + m_LabelHeight; m_currentLabelPosX = cXOffset; m_currentControlPosX = cXOffset; bIsFirstRun = true; StartA = a + 1; } else { // FieldWidths in the line can be made wider... if (m_currentControlPosY + m_dbControlHeight == m_currentMaxRowHeight) { // The last Control was the highest in the row m_currentLabelPosY = nSecMaxRowY; } else { m_currentLabelPosY = m_currentMaxRowHeight; } m_currentLabelPosY += cVertDistance; m_currentControlPosY = m_currentLabelPosY + m_LabelHeight; m_currentControlPosX = cXOffset; m_currentLabelPosX = cXOffset; LabelControlList[a].setPosition(new Point(cXOffset, m_currentLabelPosY)); DBControlList[a].setPosition(new Point(cXOffset, m_currentControlPosY)); bIsFirstRun = true; checkOuterPoints(m_currentControlPosX, m_dbControlWidth > m_LabelWidth ? m_dbControlWidth : m_LabelWidth, m_currentControlPosY, m_dbControlHeight, true); m_currentLabelPosX = m_maxPositionX + cHoriDistance; m_currentControlPosX = m_currentLabelPosX; adjustLineWidth(StartA, a - 1, nRightDist, 1); StartA = a; } } private int getCorrWidth(int StartIndex, int EndIndex, int nDist, int Widthfactor) { int ShapeCount; if (Widthfactor > 0) { // shapes are made wide ShapeCount = EndIndex - StartIndex + 1; } else { // shapes are made more narrow ShapeCount = iReduceWidth; } if(ShapeCount == 0) return 0; else return (nDist) / ShapeCount; } /** * * @param StartIndex * @param EndIndex * @param nDist * @param WidthFactor is either '+1' or '-1' and determines whether the control shapes widths are to be made smaller or larger */ private void adjustLineWidth(final int StartIndex, final int EndIndex, final int nDist, final int WidthFactor) { if(StartIndex <= EndIndex) { int CorrWidth = getCorrWidth(StartIndex, EndIndex, nDist, WidthFactor); int iLocTCPosX = cXOffset; for (int i = StartIndex; i <= EndIndex; i++) { int nControlBaseWidth = 0; DatabaseControl dbControl = DBControlList[i]; Control curLabelControl = LabelControlList[i]; if (i != StartIndex) { curLabelControl.setPosition(new Point(iLocTCPosX, curLabelControl.getPosition().Y)); dbControl.setPosition(new Point(iLocTCPosX, curLabelControl.getPosition().Y + m_LabelHeight)); } final Size labelSize = curLabelControl.getSize(); Size controlSize = dbControl.getSize(); if (((labelSize.Width > controlSize.Width)) && (WidthFactor > 0)) { nControlBaseWidth = labelSize.Width; } else { nControlBaseWidth = controlSize.Width; } if (FieldColumns[i].getFieldType() == DataType.TIMESTAMP) { TimeStampControl oDBTimeStampControl = (TimeStampControl) dbControl; nControlBaseWidth = oDBTimeStampControl.getSize().Width; } if (WidthFactor > 0 || isReducable(i, labelSize.Width, controlSize.Width)) { controlSize.Width = nControlBaseWidth + WidthFactor * CorrWidth; dbControl.setSize(controlSize); controlSize = dbControl.getSize(); } if (labelSize.Width > controlSize.Width) { iLocTCPosX += labelSize.Width; } else { iLocTCPosX += controlSize.Width; } iLocTCPosX += cHoriDistance; } } if (WidthFactor > 0) { iReduceWidth = 1; } else { iReduceWidth = 0; } } private void checkOuterPoints(int i_nXPos, int i_nWidth, int i_nYPos, int i_nHeight, boolean i_bIsDBField) { if (icurArrangement == FormWizard.IN_BLOCK_TOP && i_bIsDBField) { // Only at DBControls you can measure the Value of nMaxRowY if (bIsFirstRun) { m_currentMaxRowHeight = i_nYPos + i_nHeight; nSecMaxRowY = m_currentMaxRowHeight; } else { int nRowY = i_nYPos + i_nHeight; if (nRowY >= m_currentMaxRowHeight) { nSecMaxRowY = m_currentMaxRowHeight; m_currentMaxRowHeight = nRowY; } } } // Find the outer right point if (bIsFirstRun) { m_maxPositionX = i_nXPos + i_nWidth; bIsFirstRun = false; } else { int nColRightX = i_nXPos + i_nWidth; if (nColRightX > m_maxPositionX) { m_maxPositionX = nColRightX; } } } public void positionControls(int _icurArrangement, Point _aStartPoint, short _iAlign, Short _NBorderType) { try { NBorderType = _NBorderType; setStartPoint(_aStartPoint); icurArrangement = _icurArrangement; initializePosSizes(); initializeControlColumn(-1); bIsVeryFirstRun = true; m_currentMaxRowHeight = 0; nSecMaxRowY = 0; m_maxPositionX = 0; xProgressBar.start(PropertyNames.EMPTY_STRING, FieldColumns.length); for (int i = 0; i < FieldColumns.length; i++) { try { insertLabel(i, _iAlign); insertDBControl(i); bIsVeryFirstRun = false; DBControlList[i].setPropertyValue(LABELCONTROL, LabelControlList[i].xPropertySet); resetPosSizes(i); xProgressBar.setValue(i + 1); } catch (RuntimeException e) { } } xProgressBar.end(); bControlsareCreated = true; } catch (Exception e) { e.printStackTrace(System.err); } } public boolean areControlsexisting() { if (DBControlList != null) { if (DBControlList.length > 0) { return (DBControlList[0] != null); } } return false; } private void initializeControlColumn(int LastIndex) { bIsFirstRun = true; StartA = LastIndex + 1; a = 0; } private void resetPosSizes(int LastIndex) { int nYRefPos = m_currentControlPosY; switch (icurArrangement) { case FormWizard.COLUMNAR_LEFT: m_currentControlPosY = m_currentControlPosY + m_dbControlHeight + cVertDistance + getCheckBoxDiffHeight(LastIndex); nYRefPos = m_currentControlPosY; if ((m_currentControlPosY > cYOffset + nFormHeight) || (LastIndex == (FieldColumns.length - 1))) { repositionColumnarLeftControls(LastIndex); m_currentLabelPosX = m_maxPositionX + 2 * cHoriDistance; m_currentControlPosX = m_currentLabelPosX + cLabelGap + m_MaxLabelWidth; m_currentControlPosY = cYOffset; nYRefPos = m_currentControlPosY; initializeControlColumn(LastIndex); } else { /*a = a + 1;*/ /* a += 1;*/ ++a; } m_currentLabelPosY = m_currentControlPosY + getLabelDiffHeight(LastIndex); if ((nYRefPos + m_dbControlHeight) > m_controlMaxPosY) { m_controlMaxPosY = nYRefPos + m_dbControlHeight; } break; case FormWizard.COLUMNAR_TOP: m_currentLabelPosY = m_currentControlPosY + m_dbControlHeight + cVertDistance + getCheckBoxDiffHeight(LastIndex); if ((m_currentLabelPosY > cYOffset + nFormHeight) || (LastIndex == (FieldColumns.length - 1))) { m_currentControlPosX = m_maxPositionX + cHoriDistance; m_currentLabelPosX = m_currentControlPosX; nYRefPos = m_currentControlPosY; m_currentControlPosY = cYOffset + m_LabelHeight + cVertDistance; m_currentLabelPosY = cYOffset; initializeControlColumn(LastIndex); } else { ++a; } if ((nYRefPos + m_dbControlHeight + cVertDistance) > m_controlMaxPosY) { m_controlMaxPosY = nYRefPos + m_dbControlHeight + cVertDistance; } break; case FormWizard.IN_BLOCK_TOP: if (isReducable(a, m_LabelWidth, m_dbControlWidth)) { ++iReduceWidth; } if (m_maxPositionX > cXOffset + nFormWidth) { checkJustifiedPosition(a); nYRefPos = m_currentControlPosY; } else { m_currentLabelPosX = m_maxPositionX + cHoriDistance; } if (a == FieldColumns.length - 1) { checkJustifiedPosition(a); nYRefPos = m_currentControlPosY; } m_currentControlPosX = m_currentLabelPosX; ++a; if ((nYRefPos + m_dbControlHeight) > m_controlMaxPosY) { m_controlMaxPosY = nYRefPos + m_dbControlHeight; } break; } } private void repositionColumnarLeftControls(int LastIndex) { bIsFirstRun = true; for (int i = StartA; i <= LastIndex; i++) { if (i == StartA) { m_currentLabelPosX = LabelControlList[i].getPosition().X; m_currentControlPosX = m_currentLabelPosX + m_MaxLabelWidth + cHoriDistance; } LabelControlList[i].setSize(new Size(m_MaxLabelWidth, m_LabelHeight)); resetDBShape(DBControlList[i], m_currentControlPosX); checkOuterPoints(m_currentControlPosX, m_dbControlWidth, m_currentControlPosY, m_dbControlHeight, true); } } private void resetDBShape(Shape _curDBControl, int iXPos) { m_dbControlWidth = _curDBControl.getSize().Width; m_dbControlHeight = _curDBControl.getSize().Height; _curDBControl.setPosition(new Point(iXPos, _curDBControl.getPosition().Y)); } private void initializePosSizes() { m_controlMaxPosY = 0; m_currentLabelPosX = cXOffset; m_LabelWidth = 2000; m_dbControlWidth = 2000; m_dbControlHeight = oFormHandler.getControlReferenceHeight(); m_LabelHeight = oFormHandler.getLabelHeight(); iReduceWidth = 0; if (icurArrangement == FormWizard.COLUMNAR_LEFT) { m_currentLabelPosY = cYOffset + getLabelDiffHeight(0); m_currentControlPosX = cXOffset + 3050; m_currentControlPosY = cYOffset; } else { m_currentControlPosX = cXOffset; m_currentLabelPosY = cYOffset; } } private void insertLabel(int i, int _iAlign) { try { Point aPoint = new Point(m_currentLabelPosX, m_currentLabelPosY); Size aSize = new Size(m_LabelWidth, m_LabelHeight); if (bControlsareCreated) { LabelControlList[i].setPosition(aPoint); if (icurArrangement != FormWizard.COLUMNAR_LEFT) { m_LabelWidth = LabelControlList[i].getPreferredWidth(FieldColumns[i].getFieldTitle()); aSize.Width = m_LabelWidth; LabelControlList[i].setSize(aSize); } else { m_LabelWidth = LabelControlList[i].getSize().Width; } } else { final String sFieldName = FieldColumns[i].getFieldName(); LabelControlList[i] = new Control(oFormHandler, xFormName, FormHandler.SOLABEL, sFieldName, aPoint, aSize); if (bIsVeryFirstRun && icurArrangement == FormWizard.COLUMNAR_TOP) { m_currentControlPosY = m_currentLabelPosY + m_LabelHeight; } final String sTitle = FieldColumns[i].getFieldTitle(); m_LabelWidth = LabelControlList[i].getPreferredWidth(sTitle); aSize.Width = m_LabelWidth; LabelControlList[i].setSize(aSize); } Control curLabelControl = LabelControlList[i]; if (icurArrangement == FormWizard.COLUMNAR_LEFT) { // Note This If Sequence must be called before retrieving the outer Points if (bIsFirstRun) { m_MaxLabelWidth = m_LabelWidth; bIsFirstRun = false; } else if (m_LabelWidth > m_MaxLabelWidth) { m_MaxLabelWidth = m_LabelWidth; } } checkOuterPoints(m_currentLabelPosX, m_LabelWidth, m_currentLabelPosY, m_LabelHeight, false); if ((icurArrangement == FormWizard.COLUMNAR_TOP) || (icurArrangement == FormWizard.IN_BLOCK_TOP)) { m_currentControlPosX = m_currentLabelPosX; m_currentControlPosY = m_currentLabelPosY + m_LabelHeight; curLabelControl.xPropertySet.setPropertyValue(PropertyNames.PROPERTY_ALIGN, Short.valueOf((short) com.sun.star.awt.TextAlign.LEFT)); } else { curLabelControl.xPropertySet.setPropertyValue(PropertyNames.PROPERTY_ALIGN, Short.valueOf((short) _iAlign)); } if (!bControlsareCreated) { curLabelControl.setSize(new Size(m_LabelWidth, m_LabelHeight)); } } catch (Exception e) { e.printStackTrace(System.err); } } private void insertDBControl(int i) { try { String sFieldName = FieldColumns[i].getFieldName(); int nFieldType = FieldColumns[i].getFieldType(); boolean bFieldNullable = AnyConverter.toInt(FieldColumns[i].getXColumnPropertySet().getPropertyValue(PropertyNames.PROPERTY_IS_NULLABLE)) != ColumnValue.NO_NULLS; boolean bFieldHasDefaultValue = !AnyConverter.toString(FieldColumns[i].getXColumnPropertySet().getPropertyValue(PropertyNames.PROPERTY_DEFAULT_VALUE)).isEmpty(); Point aPoint = new Point(m_currentControlPosX, m_currentControlPosY); if (bControlsareCreated) { DBControlList[i].setPosition(aPoint); } else { if (nFieldType == DataType.TIMESTAMP) { DBControlList[i] = new TimeStampControl(new Resource(xMSF), oFormHandler, xFormName, sFieldName, aPoint); } else { DBControlList[i] = new DatabaseControl(oFormHandler, xFormName, sFieldName, nFieldType, aPoint); if (DBControlList[i].getControlType() == FormHandler.SOCHECKBOX) { // Checkboxes have no Label near by DBControlList[i].setPropertyValue(PropertyNames.PROPERTY_LABEL, PropertyNames.EMPTY_STRING); } } } DatabaseControl aDBControl = DBControlList[i]; m_dbControlHeight = aDBControl.getControlHeight(); m_dbControlWidth = aDBControl.getControlWidth(); if (nFieldType != DataType.TIMESTAMP) { aDBControl.setSize(new Size(m_dbControlWidth, m_dbControlHeight)); } if (aDBControl.getControlType() == FormHandler.SOCHECKBOX) { m_currentControlPosY = m_currentControlPosY + /*(int)*/ ((oFormHandler.getControlReferenceHeight() - m_dbControlHeight) / 2); aPoint = new Point(m_currentControlPosX, m_currentControlPosY); aDBControl.setPosition(aPoint); } if (nFieldType == DataType.LONGVARCHAR) /* memo */ { Helper.setUnoPropertyValue(aDBControl.xPropertySet, PropertyNames.PROPERTY_MULTILINE, Boolean.TRUE); } checkOuterPoints(m_currentControlPosX, m_dbControlWidth, m_currentControlPosY, m_dbControlHeight, true); aDBControl.setPropertyValue(PropertyNames.PROPERTY_BORDER, NBorderType); aDBControl.setPropertyValue(PropertyNames.PROPERTY_INPUT_REQUIRED, !(bFieldNullable || bFieldHasDefaultValue)); } catch (Exception e) { e.printStackTrace(System.err); } } public int getFormHeight() { return m_controlMaxPosY - cYOffset; } public int getEntryPointY() { if (icurArrangement == FormWizard.COLUMNAR_TOP) { Control curLabelControl2 = LabelControlList[0]; return curLabelControl2.getPosition().Y; } else { DatabaseControl curDBControl2 = DBControlList[0]; return curDBControl2.getPosition().Y; } } public void setStartPoint(Point _aPoint) { cXOffset = _aPoint.X; cYOffset = _aPoint.Y; } public void setFormSize(Size _FormSize) { nFormHeight = _FormSize.Height; nFormWidth = _FormSize.Width; } }