| /******************************************************************************* |
| * Copyright (c) 2006 Sybase, Inc. and others. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Sybase, Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jst.pagedesigner.css2.layout.table; |
| |
| import java.util.List; |
| |
| import org.eclipse.draw2d.IFigure; |
| import org.eclipse.draw2d.geometry.Dimension; |
| import org.eclipse.draw2d.geometry.Rectangle; |
| import org.eclipse.jst.pagedesigner.css2.layout.BoxUtil; |
| import org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout; |
| import org.eclipse.jst.pagedesigner.css2.layout.CSSFigure; |
| import org.eclipse.jst.pagedesigner.css2.layout.FlowFigure; |
| |
| /** |
| * @author mengbo |
| * @version 1.5 |
| */ |
| public abstract class CachedTableCellLayout extends CSSBlockFlowLayout { |
| protected Dimension _pageSize = new Dimension(); |
| |
| protected boolean _calculatingSize = false; |
| |
| private int _pageSizeCacheKeys[] = new int[4]; |
| |
| private Dimension _pageSizeCacheValues[] = new Dimension[4]; |
| |
| private int _recommendedWidth; |
| |
| private Dimension _cacheMaxWidthSize = null; |
| |
| private boolean _isTable; |
| |
| /** |
| * @param cssfigure |
| */ |
| public CachedTableCellLayout(CSSFigure cssfigure) { |
| super(cssfigure); |
| } |
| |
| /** |
| * when figure revalidated, means some child or itself get changed somehow, |
| * so clear the cache information here. |
| */ |
| public void figureRevalidate() { |
| super.figureRevalidate(); |
| _pageSizeCacheKeys = new int[4]; |
| _pageSizeCacheValues = new Dimension[4]; |
| _pageSize = new Dimension(); |
| _recommendedWidth = 0; |
| _cacheMaxWidthSize = null; |
| _isTable = false; |
| } |
| |
| /** |
| * TODO: This method is not being called. |
| */ |
| public void postValidate() { |
| if (_isTable) { |
| if (_calculatingSize) { |
| _pageSize.width = _blockBox.getWidth(); |
| _pageSize.height = _blockBox.getHeight(); |
| } else { |
| if (_isTable) { |
| Rectangle rect = getCellRect(); |
| _blockBox.setXYWidthHeight(rect); |
| this.getCSSFigure().setBounds(rect); |
| } |
| } |
| List list = getCSSFigure().getChildren(); |
| for (int i = 0, n = list.size(); i < n; i++) { |
| ((FlowFigure) list.get(i)).postValidate(); |
| } |
| } else { |
| super.postValidate(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.jst.pagedesigner.css2.layout.CSSBlockFlowLayout#preLayout() |
| */ |
| protected void preLayout() { |
| _isTable = initializeTableInfo(); |
| if (_isTable) { |
| if (!_calculatingSize) { |
| // XXX: I don't know why need to call setValid(false) here, if I |
| // don't call |
| // it, the layout will be wrong. |
| getCSSFigure().setValid(false); |
| } |
| } |
| super.preLayout(); |
| } |
| |
| public abstract Rectangle getCellRect(); |
| |
| public abstract boolean initializeTableInfo(); |
| |
| protected void setupBlock() { |
| if (_isTable) { |
| // Remove all current Fragments |
| _blockBox.clear(); |
| |
| if (_calculatingSize) { |
| // we are not in the real layout |
| // Setup the one fragment for this Block with the correct X and |
| // available width |
| int recommendedWidth = getRecommendedWidth(); |
| _blockBox.setRecommendedWidth(recommendedWidth); |
| |
| if (recommendedWidth > 0 |
| && recommendedWidth != Integer.MAX_VALUE) { |
| _blockBox.setWidth(recommendedWidth); |
| } |
| } else { |
| Rectangle rect = getCellRect(); |
| _blockBox.setWidth(rect.width); |
| _blockBox.setRecommendedWidth(rect.width); |
| _blockBox.setHeight(rect.height); |
| _blockBox.setRecommendedHeight(rect.height); |
| } |
| |
| BoxUtil.setupBorderPaddingMargin(_blockBox, getCSSStyle()); |
| } else { |
| super.setupBlock(); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.Figure#getPreferredSize(int, int) |
| */ |
| public Dimension getPreferredSize(IFigure container, int width, int h) { |
| if (this.isCalculatingMaxWidth()) { |
| return getMaxContentWidthSize(container, width, h); |
| } |
| try { |
| _calculatingSize = true; |
| // if (width >= 0) |
| // { |
| // width = Math.max(0, width - container.getInsets().getWidth()); |
| // } |
| |
| for (int i = 0; i < 4; i++) { |
| if (_pageSizeCacheKeys[i] == width |
| && _pageSizeCacheValues[i] != null) { |
| if (h > _pageSizeCacheValues[i].height) { |
| return new Dimension(_pageSizeCacheValues[i].width, h); |
| } |
| return _pageSizeCacheValues[i]; |
| } |
| } |
| |
| _pageSizeCacheKeys[3] = _pageSizeCacheKeys[2]; |
| _pageSizeCacheKeys[2] = _pageSizeCacheKeys[1]; |
| _pageSizeCacheKeys[1] = _pageSizeCacheKeys[0]; |
| _pageSizeCacheKeys[0] = width; |
| |
| _pageSizeCacheValues[3] = _pageSizeCacheValues[2]; |
| _pageSizeCacheValues[2] = _pageSizeCacheValues[1]; |
| _pageSizeCacheValues[1] = _pageSizeCacheValues[0]; |
| |
| // Flowpage must temporarily layout to determine its preferred size |
| int oldWidth = getRecommendedWidth(); |
| setRecommendedWidth(width); |
| ((CSSFigure) container).setValid(false); |
| container.validate(); |
| ((CSSFigure) container).postValidate(); |
| _pageSizeCacheValues[0] = new Dimension(_pageSize); |
| |
| if (width != oldWidth) { |
| setRecommendedWidth(oldWidth); |
| // container.getUpdateManager().addInvalidFigure(container); |
| } |
| if (h > _pageSizeCacheValues[0].height) { |
| return new Dimension(_pageSizeCacheValues[0].width, h); |
| } |
| return _pageSizeCacheValues[0]; |
| } finally { |
| _calculatingSize = false; |
| } |
| } |
| |
| public int getRecommendedWidth() { |
| return _recommendedWidth; |
| } |
| |
| private void setRecommendedWidth(int width) { |
| if (_recommendedWidth == width) { |
| return; |
| } |
| _recommendedWidth = width; |
| } |
| |
| public Dimension getMaxContentWidthSize(IFigure container, int width, |
| int height) { |
| try { |
| _calculatingSize = true; |
| |
| if (this._cacheMaxWidthSize == null) { |
| boolean b = getCalcuatingMaxWidth(); |
| setCalculatingMaxWidth(true); |
| |
| // Flowpage must temporarily layout to determine its preferred |
| // size |
| int oldWidth = getRecommendedWidth(); |
| if (width <= 0) { |
| setRecommendedWidth(Integer.MAX_VALUE); |
| } else { |
| setRecommendedWidth(width); |
| } |
| ((CSSFigure) container).setValid(false); |
| container.validate(); |
| |
| ((CSSFigure) container).postValidate(); |
| _cacheMaxWidthSize = new Dimension(_pageSize); |
| if (height > _pageSize.height) { |
| _cacheMaxWidthSize.height = height; |
| } |
| |
| if (0 != oldWidth) { |
| setRecommendedWidth(oldWidth); |
| // container.getUpdateManager().addInvalidFigure(container); |
| } |
| |
| setCalculatingMaxWidth(b); |
| } |
| return _cacheMaxWidthSize; |
| } finally { |
| _calculatingSize = false; |
| } |
| } |
| |
| /** |
| * @return Returns the _isTable. |
| */ |
| protected boolean isTable() { |
| return _isTable; |
| } |
| } |