/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.ie.widget;
import java.awt.Point;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.ie.IEObject;
import org.openflexo.foundation.ie.IETopComponent;
import org.openflexo.foundation.ie.IEWOComponent;
import org.openflexo.foundation.ie.IObject;
import org.openflexo.foundation.ie.dm.ColumnInserted;
import org.openflexo.foundation.ie.dm.ColumnRemoved;
import org.openflexo.foundation.ie.dm.IEDataModification;
import org.openflexo.foundation.ie.dm.PercentageChanged;
import org.openflexo.foundation.ie.dm.TRInserted;
import org.openflexo.foundation.ie.dm.TRRemoved;
import org.openflexo.foundation.ie.dm.table.DisplayBorderChanged;
import org.openflexo.foundation.ie.dm.table.WidgetAddedToTable;
import org.openflexo.foundation.ie.dm.table.WidgetRemovedFromTable;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.xml.FlexoComponentBuilder;
/**
* Widget representing an HTML Table
*
* @author bmangez
*/
public class IEHTMLTableWidget extends IEWidget implements ExtensibleWidget, IETopComponent, InnerBlocWidgetInterface {
/**
*
*/
public static final String HTML_TABLE_WIDGET = "html_table_widget";
private static final Logger logger = Logger.getLogger(IEHTMLTableWidget.class.getPackage().getName());
private boolean _grid = false;
private boolean _noCss = false;
private boolean _isShowingBorder = true;
private String _conditionals;
private Vector<Double> pourcentageArray;
private String _pourcentageWidths;
private IESequenceTR _sequenceTR;
public IEHTMLTableWidget(FlexoComponentBuilder builder) {
this(builder.woComponent, null, builder.getProject());
initializeDeserialization(builder);
}
public IEHTMLTableWidget(IEWOComponent woComponent, IEObject parent, FlexoProject prj) {
super(woComponent, parent, prj);
_sequenceTR = new IESequenceTR(woComponent, this, prj);
pourcentageArray = new Vector<Double>();
}
/**
* Overrides finalizeDeserialization
*
* @see org.openflexo.foundation.ie.widget.IEWidget#finalizeDeserialization(java.lang.Object)
*/
@Override
public void finalizeDeserialization(Object builder) {
// setParentOfSingleWidgetComponentInstance(this);
// First we parse all TR's to set their rowIndex (=yLocation)
setTRRowIndex();
// Then we insert all the cells that are recovered by a span
getSequenceTR().insertSpannedTD();
reIndexTable();
if (!isCreatedByCloning()) {// If we are created by cloneage from an
// original widget which already has correct
// data, the next operations are not necessary.
// Now we fill the table so that there are no holes inside of it.
int colCount = getMaxColCount();
for (int i = 0; i < getRowCount(); i++) {
for (int j = 0; j < colCount; j++) {
IETDWidget td = getTDAt(i, j);
if (td == null) {
getTR(i).insertEmptyTDAtCol(j);
}
}
}
initPourcentageArray();
// Let's check that all percentages are correct
if (pourcentageArray.size() < colCount) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Percentage array is to small: " + pourcentageArray.size() + " colcount=" + colCount);
}
int size = pourcentageArray.size();
for (int i = size; i < colCount; i++) {
double newColPourcentage = 1.0d / (pourcentageArray.size() + 1);
double oldColIncrement = -1.0d * newColPourcentage / pourcentageArray.size();
applyIncrementToCols(oldColIncrement, true);
pourcentageArray.add(new Double(newColPourcentage));
}
} else if (pourcentageArray.size() > colCount) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Percentage array is to big: " + pourcentageArray.size() + " colcount=" + colCount);
}
while (pourcentageArray.size() > colCount) {
Double d = pourcentageArray.lastElement();
pourcentageArray.remove(d);
applyIncrementToCols(d.doubleValue() / pourcentageArray.size(), true);
}
}
checkAndFixColumnWidth();
// Finally, we simplify the tree
_sequenceTR.simplifySequenceTree();
}
super.finalizeDeserialization(builder);
// SGU, 28/09/2006
// We had here a problem because the finalize deserialisation scheme is
// called here
// for a widget AFTER the one for the component has been performed,
// causing parent component
// to be marked as modified. Just call finalizer on parent again to
// clear modifications.
/*
* if (getWOComponent() != null) { getWOComponent().finalizeDeserialization(builder); }
*/
}
/*
* private void setParentOfSingleWidgetComponentInstance(IEHTMLTableWidget widget) {
* _sequenceTR.setParentOfSingleWidgetComponentInstance(widget);
*
* }
*/
private void reIndexTable() {
reIndexRows();
for (int i = 0; i < getRowCount(); i++) {
IETRWidget tr = getTR(i);
tr.reIndexCells();
}
}
public Vector<IWidget> getAllInnerTableWidget() {
Vector<IWidget> v = new Vector<IWidget>();
v.addAll(_sequenceTR.getAllInnerTableWidget());
return v;
}
/**
* Reindexes all rows of this table.
*
*/
private void reIndexRows() {
_sequenceTR.setTRRowIndex(new Incrementer());
}
/**
* @return
*/
private int getMaxColCount() {
int retval = 0;
for (int i = 0; i < getRowCount(); i++) {
IETRWidget tr = getTR(i);
if (tr.getColCount() > retval) {
retval = tr.getColCount();
}
}
return retval;
}
/**
* Set the row index on each TR of this table
*/
public void setTRRowIndex() {
_sequenceTR.setTRRowIndex(new Incrementer());
}
public String getPourcentageWidths() {
udatePourcentageWidths();
return _pourcentageWidths;
}
public void setPourcentageWidths(String s) {
_pourcentageWidths = s;
StringTokenizer tok = new StringTokenizer(s, ";", false);
while (tok.hasMoreElements()) {
pourcentageArray.add(new Double(tok.nextToken()));
}
}
private void udatePourcentageWidths() {
initPourcentageArray();
StringBuffer buf = new StringBuffer();
Enumeration en = pourcentageArray.elements();
while (en.hasMoreElements()) {
buf.append(((Double) en.nextElement()).doubleValue());
if (en.hasMoreElements()) {
buf.append(";");
}
}
_pourcentageWidths = buf.toString();
}
@Override
public String getDefaultInspectorName() {
return "HTMLTable.inspector";
}
public IETRWidget getFirstTR() {
if (_sequenceTR.size() > 0) {
return _sequenceTR.getFirstTR();
}
return null;
}
/**
* Removes the column col from the table.
*
* @param col
* - the column to remove
*/
public void deleteCol(int col) {
Vector<IETDWidget> spanners = new Vector<IETDWidget>();// Spanners are
// spanned TD
// that have a
// span-TD in
// the column to
// delete
for (int i = 0; i < getRowCount(); i++) {
IETDWidget td = getTDAt(i, col);
if (td instanceof IESpanTDWidget) {
IETDWidget sp = ((IESpanTDWidget) td).getSpanner();
if (!spanners.contains(sp)) {
spanners.add(sp);
}
}
if (td != null) {
td.makeRealDelete(true);
} else if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Could not delete TD at (" + i + "," + col + "). XML:\n" + getXMLRepresentation());
}
}
Enumeration<IETDWidget> en = spanners.elements();
while (en.hasMoreElements()) {
IETDWidget td = en.nextElement();
if (!td.isDeleted()) {
td.descreaseColSpanCausedByColumnDeletion();
}
}
reIndexTable();
int newColCount = getColCount();
double removedColPourcentage = pourcentageArray.get(col).doubleValue();
double oldColIncrement = removedColPourcentage / newColCount;
pourcentageArray.remove(col);
applyIncrementToCols(oldColIncrement, true);
notifyDisplayNeedsRefresh();
notifyPercentageChangeFromColToCol(0, getColCount());
setChanged();
notifyObservers(new ColumnRemoved(col));
}
/**
* Removes the row row from the table.
*
* @param row
* - the row to remove
*/
public void deleteRow(IETRWidget tr) {
Vector<IETDWidget> spanners = new Vector<IETDWidget>();
int colCount = getColCount();
for (int i = 0; i < colCount; i++) {
IETDWidget td = tr.getTD(i);
if (td instanceof IESpanTDWidget) {
IETDWidget sp = ((IESpanTDWidget) td).getSpanner();
if (!spanners.contains(sp)) {
spanners.add(sp);
}
}
if (td != null) {
td.makeRealDelete(true);
} else if (logger.isLoggable(Level.SEVERE)) {
logger.severe("Could not delete TD at (" + tr + "," + i + "). XML:\n" + getXMLRepresentation());
}
}
Enumeration<IETDWidget> en = spanners.elements();
while (en.hasMoreElements()) {
IETDWidget td = en.nextElement();
if (!td.isDeleted()) {
td.decreaseRowSpanCausedByRowDeletion();
}
}
reIndexRows();
setChanged();
notifyObservers(new TRRemoved(tr));
}
public void insertRow(IESequenceTR str, int row) {
Vector<IETDWidget> spanners = new Vector<IETDWidget>();
IETRWidget tr = new IETRWidget(getWOComponent(), str, true, getProject());
tr.setRowIndex(row);
int colCount = getColCount();
// Let's look at that current row
if (row < getRowCount()) {
for (int i = 0; i < colCount; i++) {
IETDWidget item = getTDAt(row, i);
if (item instanceof IESpanTDWidget) {
if (!((IESpanTDWidget) item).isOnRowSide()) {
if (!spanners.contains(((IESpanTDWidget) item).getSpanner())) {
spanners.add(((IESpanTDWidget) item).getSpanner());
}
}
}
}
}
// If the current row (row) has spans that are in the middle of a cell,
// we will increase the span of the spanner
Enumeration<IETDWidget> en = spanners.elements();
while (en.hasMoreElements()) {
IETDWidget td = en.nextElement();
td.increaseRowSpanCausedByRowInsertion(tr, row);
}
// We compute where to insert the new row
Enumeration<ITableRow> en1 = str.elements();
int index = 0;
while (en1.hasMoreElements()) {
ITableRow item = en1.nextElement();
if (item instanceof IETRWidget) {
if (((IETRWidget) item).getRowIndex() < row) {
index = ((IETRWidget) item).getIndex() + 1;
} else {
break;
}
}
}
// Watch out that next line launches a notification while the model is
// not completely correct (getYLocation methods are no more correct)
str.insertElementAt(tr, index);
reIndexRows();
setChanged();
notifyObservers(new TRInserted(tr));
}
public void insertCol(int col) {
// Let's find if some spanned cells are in the middle of the column we
// want to insert
Vector<IETDWidget> spanners = new Vector<IETDWidget>();
int rowCount = getRowCount();
for (int i = 0; i < rowCount; i++) {
IETDWidget td = getTDAt(i, col);
if (td instanceof IESpanTDWidget) {
if (!((IESpanTDWidget) td).isOnColSide()) {
if (!spanners.contains(((IESpanTDWidget) td).getSpanner())) {
spanners.add(((IESpanTDWidget) td).getSpanner());
}
}
}
}
// We adjust column width so that there is room for the new column
int newColCount = getColCount() + 1;
double newColPourcentage = 1.0d / newColCount;
double oldColIncrement = -1.0d * newColPourcentage / (newColCount - 1);
applyIncrementToCols(oldColIncrement, false);
pourcentageArray.insertElementAt(new Double(newColPourcentage), col);
checkAndFixColumnWidth();
// We insert the column, i.e. a cell in each row
for (int i = 0; i < rowCount; i++) {
IETRWidget tr = getTR(i);
tr.insertEmptyTDAtCol(col);// This also reIndexes cells inside that
// row
}
// Now we ask spanners to increase their colspan in the column
Enumeration<IETDWidget> en = spanners.elements();
while (en.hasMoreElements()) {
IETDWidget td = en.nextElement();
td.increaseColSpanCausedByColumnInsertion(col);
}
setChanged();
notifyObservers(new ColumnInserted(col));
}
public void setPercentageForTD(double percentage, IETDWidget td) throws InvalidPercentage {
if (!isPercentageAcceptable(td, (int) (percentage * 100))) {
throw new InvalidPercentage((int) (percentage * 100));
}
int col = td.getXLocation();
if (col > pourcentageArray.size()) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Tried to set a new percentage on a column that does not exist");
}
return;
}
if (percentage > 1) {
return;
}
if (col + 1 == pourcentageArray.size()) {
double offset = getPourcentage(col, 1) - percentage;
for (int i = col - 1; i >= 0 && offset != 0; i--) {
double p = pourcentageArray.get(i);
if (p + offset < 0) {
offset += p - 0.01;
p = 0.01;
} else {
p += offset;
offset = 0;
}
pourcentageArray.set(i, p);
}
pourcentageArray.set(col, percentage);
checkAndFixColumnWidth();
notifyDisplayNeedsRefresh();
notifyPercentageChangeFromColToCol(0, getColCount());
} else {
double offset = getPourcentage(col, 1) - percentage;
for (int i = col + 1; i < pourcentageArray.size(); i++) {
double p = pourcentageArray.get(i);
if (p + offset < 0) {
offset += p - 0.01;
p = 0.01;
} else {
p += offset;
offset = 0;
}
pourcentageArray.set(i, p);
}
pourcentageArray.set(col, percentage);
checkAndFixColumnWidth();
notifyDisplayNeedsRefresh();
notifyPercentageChangeFromColToCol(col, getColCount());
}
}
public boolean isPercentageAcceptable(IETDWidget td, int newPercentage) {
if (td.getXLocation() + 1 == getColCount()) {
double leftPercentage = getPourcentage(0, td.getXLocation());
if (newPercentage > td.getPercentage() && newPercentage - td.getPercentage() > leftPercentage * 100 - getColCount() - 1) {
return false;
}
} else {
double leftPercentage = (int) (getPourcentage(td.getXLocation() + 1, getColCount() - td.getXLocation() - 1) * 100);
leftPercentage /= 100;
if (newPercentage > td.getPercentage()
&& newPercentage - td.getPercentage() > leftPercentage * 100 - getColCount() + td.getXLocation()) {
return false;
}
}
return true;
}
/*
* private void applyIncrementToCols(double d) { applyIncrementToCols(d, true); }
*/
private void applyIncrementToCols(double d, boolean checkAndFix) {
initPourcentageArray();
for (int i = 0; i < pourcentageArray.size(); i++) {
Double newVal = new Double(pourcentageArray.get(i).doubleValue() + d);
pourcentageArray.set(i, newVal);
}
for (int i = 0; i < pourcentageArray.size(); i++) {
Double newVal = pourcentageArray.get(i);
if (newVal < 0.01) {
pourcentageArray.set(i, newVal);
}
}
if (checkAndFix) {
checkAndFixColumnWidth();
}
notifyDisplayNeedsRefresh();
notifyPercentageChangeFromColToCol(0, getColCount());
}
private void checkAndFixColumnWidth() {
// If there are too small values we set them to the minimum: 0.01
for (int i = 0; i < pourcentageArray.size(); i++) {
Double d = pourcentageArray.get(i);
if (d < 0.01) {
pourcentageArray.set(i, 0.01);
}
}
// We check that the sum of percentages equals to 1.
if (pourcentageArray.size() > 0) {
double sum = 0;
for (Double d : pourcentageArray) {
sum += d;
}
sum -= 1;
for (int i = pourcentageArray.size() - 1; i >= 0 && sum != 0; i--) {
double d = pourcentageArray.get(i);
if (d - 0.01 > sum) {
pourcentageArray.set(i, d - sum);
sum = 0;
} else {
sum -= d - 0.01;
pourcentageArray.set(i, 0.01);
}
}
} else {
if (logger.isLoggable(Level.SEVERE)) {
logger.severe("This table has no columns, I will attempt to remove it.");
}
removeFromContainer();
}
}
@Override
public void performOnDeleteOperations() {
_sequenceTR.setParent(null);
_sequenceTR.delete();
super.performOnDeleteOperations();
}
public Enumeration<ITableRow> rowsEnumeration() {
return _sequenceTR.elements();
}
/**
* Returns the number of columns of this Table
*
* @return - the number of columns
*/
public int getColCount() {
return getSequenceTR().getColCount();
}
/**
* Returns the number of rows of this table
*
* @return - the number of rows
*/
public int getRowCount() {
return getSequenceTR().getRowCount();
}
public void setColCount(int colCount) throws ColumnIsNotEmpty, ColCountCannotBeZeroOrNegative {
if (colCount < 1) {
throw new ColCountCannotBeZeroOrNegative();
}
if (getColCount() > colCount) {
int previousColCount = getColCount() + 1;
while (getColCount() > colCount && previousColCount > getColCount()) {
previousColCount = getColCount();
if (columnIsEmpty(getColCount() - 1)) {
IETDWidget td = getTDAt(0, getColCount() - 1);
if (!td.isDeleted()) {
td.deleteCol();
}
} else {
setChanged();
notifyObserversAsReentrantModification(new IEDataModification("colCount", previousColCount, getColCount()));
throw new ColumnIsNotEmpty(getColCount());
}
}
} else if (getColCount() < colCount) {
while (getColCount() < colCount) {
insertCol(getColCount());
}
} else if (logger.isLoggable(Level.INFO)) {
logger.info("Setting colcount to " + colCount + " and it is already the case");
}
}
/**
* @param i
* @return
*/
private boolean columnIsEmpty(int col) {
return isColFree(col, 0, getRowCount() - 1);
}
public void setRowCount(int rowCount) throws RowIsNotEmpty, RowCountCannotBeZeroOrNegative {
if (rowCount < 1) {
throw new RowCountCannotBeZeroOrNegative();
}
if (getRowCount() > rowCount) {
int previousRowcount = getRowCount() + 1;
while (getRowCount() > rowCount && previousRowcount > getRowCount()) {
previousRowcount = getRowCount();
if (rowIsEmpty(getRowCount() - 1)) {
getTDAt(getRowCount() - 1, 0).deleteRow();
} else {
setChanged();
notifyObserversAsReentrantModification(new IEDataModification("rowCount", previousRowcount, getRowCount()));
throw new RowIsNotEmpty(getRowCount());
}
}
} else if (getRowCount() < rowCount) {
while (getRowCount() < rowCount) {
logger.warning("This implementation is not correct: you should not use FlexoAction primitive from the model !");
// TODO: Please implement this better later
// Used editor will be null
insertRow(getTDAt(getRowCount() - 1, 0).tr().getSequenceTR(), getRowCount());
}
} else if (logger.isLoggable(Level.INFO)) {
logger.info("Setting rowCount to " + rowCount + " and it is already the case");
}
}
/**
* @param i
* @return
*/
private boolean rowIsEmpty(int col) {
return isRowFree(col, 0, getColCount() - 1);
}
/**
* Returns wheter all the cells in column col from startRow to endRow (included) are empty.
*
* @param col
* - the column to check
* @param startRow
* - the starting row to check
* @param endRow
* - the ending row to check (included too)
* @return - true if all cells located from (startRow,col) to (endRow,col) are empty
*/
public boolean isColFree(int col, int startRow, int endRow) {
if (col > getColCount() - 1) {
return false;
}
for (int i = startRow; i < endRow + 1; i++) {
IETDWidget td = null;
td = getTDAt(i, col);
if (td == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("This is weird. I could not find TD at (" + i + "," + col + ")");
}
continue;
}
if (td instanceof IESpanTDWidget) {
return false;
}
if (!td.isEmpty() || td.getRowSpan() > 1 || td.getColSpan() > 1) {
return false;
}
}
return true;
}
/**
* Returns all TD located in column col from row startRow until row endRow (included).
*
* @param col
* - the selected column
* @param startRow
* - the starting row
* @param endRow
* - the ending row (included)
* @return all cells from (startRow,col) until (endRow,col)
*/
public Vector<IETDWidget> tdsInCol(int col, int startRow, int endRow) {
Vector<IETDWidget> answer = new Vector<IETDWidget>();
for (int i = startRow; i < endRow + 1; i++) {
if (getTDAt(i, col) != null) {
answer.add(getTDAt(i, col));
}
}
return answer;
}
public Vector<Point> tdsShownInCol(int col, int startRow, int endRow) {
Vector<Point> answer = new Vector<Point>();
for (int i = startRow; i < endRow + 1; i++) {
answer.add(new Point(col, i));
}
return answer;
}
public boolean isRowFree(int row, int startCol, int endCol) {
if (row > _sequenceTR.getWidgetCount() - 1) {
return false;
}
for (int i = startCol; i < endCol + 1; i++) {
IETDWidget td = null;
td = getTDAt(row, i);
if (td == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("This is weird. Could not find TD located at (" + row + "," + i + ")");
}
continue;
}
if (td instanceof IESpanTDWidget) {
return false;
}
if (!td.isEmpty() || td.getRowSpan() > 1 || td.getColSpan() > 1) {
return false;
}
}
return true;
}
public Vector<IETDWidget> tdsInRow(int row, int startCol, int endCol) {
Vector<IETDWidget> answer = new Vector<IETDWidget>();
for (int i = startCol; i < endCol + 1; i++) {
if (getTDAt(row, i) != null) {
answer.add(getTDAt(row, i));
}
}
return answer;
}
public Vector<Point> tdsShownInRow(int row, int startCol, int endCol) {
Vector<Point> answer = new Vector<Point>();
for (int i = startCol; i < endCol + 1; i++) {
answer.add(new Point(i, row));
}
return answer;
}
/**
* Returns the TD located in row with rowIndex (row) and with xLocation equal to col
*
* @param row
* - the row in which the cell is located
* @param col
* - the column at which the cell is located
* @return
*/
public IETDWidget getTDAt(int row, int col) {
if (getTR(row) == null) {
return null;
}
return getTR(row).getTD(col);
}
/**
* Returns the row (indexed from 0) with rowIndex equal to row in the whole table.
*
* @param row
* - the row index of the row to retrieve
* @return the row with rowIndex equal to row
*/
public IETRWidget getTR(int row) {
return _sequenceTR.getTRAtRow(row);
}
public String getConditionals() {
return _conditionals;
}
public void setConditionals(String c) {
this._conditionals = c;
}
public boolean getGrid() {
return _grid;
}
public void setGrid(boolean g) {
this._grid = g;
}
public boolean getNoCSS() {
return _noCss;
}
public void setNoCSS(boolean css) {
boolean old = _noCss;
_noCss = css;
setChanged();
notifyModification("noCSS", old, _noCss);
}
/**
* Return a Vector of embedded IEObjects at this level. NOTE that this is NOT a recursive method
*
* @return a Vector of IEObject instances
*/
@Override
public Vector<IObject> getEmbeddedIEObjects() {
Vector<IObject> answer = new Vector<IObject>();
answer.add(_sequenceTR);
return answer;
}
@Override
public String getFullyQualifiedName() {
return "HTMLTable";
}
public boolean isShowingBorder() {
return _isShowingBorder;
}
public void setIsShowingBorder(boolean v) {
if (v == _isShowingBorder) {
return;
}
_isShowingBorder = v;
setChanged();
notifyObservers(new DisplayBorderChanged(this));
}
/**
* Overrides getClassNameKey
*
* @see org.openflexo.foundation.FlexoModelObject#getClassNameKey()
*/
@Override
public String getClassNameKey() {
return HTML_TABLE_WIDGET;
}
public IESequenceTR getSequenceTR() {
return _sequenceTR;
}
public IESequenceTR getRepeatedRow() {
return _sequenceTR.getFirstRepeatedSequence();
}
public void setSequenceTR(IESequenceTR _sequencetr) {
_sequenceTR = _sequencetr;
_sequenceTR.setParent(this);
}
public double getPourcentage(int start, int length) {
initPourcentageArray();
double reply = 0.0d;
for (int i = start; i < start + length; i++) {
reply = reply + pourcentageArray.get(i).doubleValue();
}
return reply;
}
private void initPourcentageArray() {
if (pourcentageArray.size() == 0) {
for (int i = 0; i < getColCount(); i++) {
pourcentageArray.insertElementAt(new Double(1.0d / (0.0d + getColCount())), i);
}
}
}
public void adjustPourcentage(IETDWidget td1, double p1, IETDWidget td2) {
initPourcentageArray();
int td1Width = td1.getColSpan();
int td2Width = td2.getColSpan();
double td1increment = p1 / td1Width;
double td2increment = -1 * p1 / td2Width;
if (!isPercentageAcceptable(td1, (int) (td1.getPourcentage() + p1 * 100))) {
return;
}
if (!isPercentageAcceptable(td2, (int) (td2.getPourcentage() - p1 * 100))) {
return;
}
for (int i = 0; i < td1Width; i++) {
pourcentageArray.set(td1.getXLocation() + i, new Double(td1increment
+ pourcentageArray.get(td1.getXLocation() + i).doubleValue()));
}
for (int i = 0; i < td2Width; i++) {
pourcentageArray.set(td2.getXLocation() + i, new Double(td2increment + pourcentageArray.get(td2.getXLocation()).doubleValue()));
}
udatePourcentageWidths();
notifyDisplayNeedsRefresh();
notifyPercentageChangeFromColToCol(td1.getXLocation(), td2.getXLocation() + 1);
}
@Override
public void notifyDisplayNeedsRefresh() {
int rowCount = getRowCount();
int colCount = getColCount();
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < colCount; j++) {
IETDWidget td = getTDAt(i, j);
if (td != null) {
td.notifyDisplayNeedsRefresh();
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("This is weird. Could not find TD located at (" + i + "," + j + ")");
}
continue;
}
}
}
_sequenceTR.setChanged();
_sequenceTR.notifyObservers(new PercentageChanged(this));
}
/**
* Notifies all TD located in column from startCol to endCol (not included). For example, if you want to notify all columns of column 0,
* then you need to pass startCol=0 and endCol=1.
*
* @param startCol
* - The starting column to notify
* @param endCol
* - The end column (not included)
*/
private void notifyPercentageChangeFromColToCol(int startCol, int endCol) {
int rowCount = getRowCount();
for (int i = 0; i < rowCount; i++) {
for (int j = startCol; j < endCol; j++) {
IETDWidget td = getTDAt(i, j);
if (td == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("This is weird. I could not find TD located at (" + i + "," + j + ")");
}
continue;
} else if (td instanceof IESpanTDWidget) {
continue;
} else {
td.notifyDisplayNeedsRefresh();
}
}
}
}
public IESequenceTR getFirstRepeatedSequence() {
return _sequenceTR.getFirstRepeatedSequence();
}
public IETRWidget getHeaderRowForSequence(ITableRow repeatedSequence) {
return getTR(repeatedSequence.getFirstTR().getRowIndex() - 1);
}
/**
* Inserts a spanned TD at location (row,col) for the td. The method will first create that spannedTD with <code>td</code> as its
* spanner. Then it will look for the TR in which the spannedTD must be inserted. If the TR cannot be found, it will be automatically
* created and inserted. Finally, we will look for the cell located at (row, col-1) and the spanned TD will be inserted right after it
* in that cell's sequence.
*
* @param row
* @param col
*/
public void insertSpannedTDAtForTD(int row, int col, IETDWidget td) {
IESpanTDWidget span = new IESpanTDWidget(td.getWOComponent(), td.getParent(), td, td.getProject());
span.setXLocation(col);
IETRWidget tr = _sequenceTR.getTRAtRow(row);
if (tr == null) {
if (logger.isLoggable(Level.INFO)) {
logger.info("Could not find tr at row " + row + ". I will create it");
}
tr = new IETRWidget(getWOComponent(), getSequenceTR(), false, getProject());
tr.setRowIndex(row);
((IESequenceTR) td.tr().getParent()).addToInnerWidgets(tr);
}
int index = col - 1;
IETDWidget previous = tr.getSequenceTD().getCellAtIndex(index);
while (previous == null && index > 0) {
previous = tr.getSequenceTD().getCellAtIndex(--index);
}
if (previous == null) {
tr.getSequenceTD().insertElementAt(span, 0);
} else {
previous.getParent().insertElementAt(span, previous.getIndex() + 1);
}
}
/**
* @param widget
* @param list
* @return
*/
@Override
public Vector<IETextFieldWidget> getAllDateTextfields() {
Vector<IETextFieldWidget> v = new Vector<IETextFieldWidget>();
Enumeration<ITableRow> en = rowsEnumeration();
while (en.hasMoreElements()) {
ITableRow element = en.nextElement();
v.addAll(element.getAllDateTextfields());
}
return v;
}
@Override
public Vector<IESequenceTab> getAllTabContainers() {
Vector<IESequenceTab> reply = new Vector<IESequenceTab>();
Enumeration en = _sequenceTR.elements();
while (en.hasMoreElements()) {
ITableRow top = (ITableRow) en.nextElement();
reply.addAll(top.getAllTabContainers());
}
return reply;
}
public void handleResize() {
if (getParent() instanceof IEBlocWidget) {
((IEBlocWidget) getParent()).handleContentResize();
}
}
/**
* @param w
*/
public void notifyWidgetRemoval(ITableRow w) {
setChanged();
notifyObservers(new WidgetRemovedFromTable((IEWidget) w));
handleResize();
}
/**
* @param o
*/
public void notifyWidgetInsertion(ITableRow o) {
setChanged();
notifyObservers(new WidgetAddedToTable((IEWidget) o, -1, -1));
if (getParent() instanceof IEBlocWidget) {
((IEBlocWidget) getParent()).handleContentResize();
}
handleResize();
}
@Override
public void setWOComponent(IEWOComponent woComponent) {
if (noWOChange(woComponent)) {
return;
}
super.setWOComponent(woComponent);
if (_sequenceTR != null) {
_sequenceTR.setWOComponent(woComponent);// This call is very important because it will update the WOComponent components cache
}
}
@Override
public boolean areComponentInstancesValid() {
if (_sequenceTR != null) {
return _sequenceTR.areComponentInstancesValid();
} else {
return true;
}
}
@Override
public void removeInvalidComponentInstances() {
if (_sequenceTR != null) {
_sequenceTR.removeInvalidComponentInstances();
}
}
/**
* Overrides getTitle
*
* @see org.openflexo.foundation.ie.IETopComponent#getTitle()
*/
@Override
public String getTitle() {
return getLabel();
}
@Override
public Vector<IEHyperlinkWidget> getAllButtonInterface() {
Vector<IEHyperlinkWidget> v = new Vector<IEHyperlinkWidget>();
Enumeration<ITableRow> en = rowsEnumeration();
while (en.hasMoreElements()) {
ITableRow element = en.nextElement();
v.addAll(element.getAllButtonInterface());
}
return v;
}
}