/*
GNU LESSER GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
package org.lobobrowser.html.renderer;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import org.eclipse.jdt.annotation.NonNull;
import org.lobobrowser.html.domimpl.ModelNode;
import org.lobobrowser.html.style.RenderState;
import org.w3c.dom.html.HTMLDocument;
import org.w3c.dom.html.HTMLHtmlElement;
public class PositionedRenderable implements Renderable {
public static final PositionedRenderable[] EMPTY_ARRAY = new PositionedRenderable[0];
public final @NonNull BoundableRenderable renderable;
public final boolean verticalAlignable;
public final int ordinal;
public final boolean isFloat;
private final boolean isFixed;
private final boolean isDelegated;
public PositionedRenderable(final @NonNull BoundableRenderable renderable, final boolean verticalAlignable, final int ordinal,
final boolean isFloat, final boolean isFixed, final boolean isDelegated) {
super();
this.renderable = renderable;
this.verticalAlignable = verticalAlignable;
this.ordinal = ordinal;
this.isFloat = isFloat;
this.isFixed = isFixed;
this.isDelegated = isDelegated;
}
public RCollection getOriginalParent() {
return this.renderable.getOriginalParent();
}
@Override
public void paint(final Graphics gIn) {
if (isDelegated) {
return;
}
final RCollection originalParent = this.renderable.getOriginalParent();
final RCollection rparent = renderable.getParent();
/*
System.out.println("pr: " + this);
System.out.println(" parent : " + rparent);
System.out.println(" orig parent: " + originalParent);
*/
final Point or = originalParent.getOriginRelativeTo(rparent);
final int pos = this.renderable.getModelNode().getRenderState().getPosition();
if (isFloat || pos == RenderState.POSITION_ABSOLUTE || pos == RenderState.POSITION_FIXED) {
final Graphics g2 = gIn.create();
final Point some = getSome();
if (some != null) {
g2.translate(some.x, some.y);
}
/*
if (isFloat) {
g2.translate(or.x, or.y);
}*/
// g2.setColor(Color.GREEN);
// g2.fillRect(0, 0, renderable.getWidth(), 100);
this.renderable.paintTranslated(g2);
} else {
final Point orNoScroll = originalParent.getOriginRelativeToNoScroll(rparent);
// System.out.println(" orNoScroll: " + orNoScroll);
// System.out.println(" or : " + or);
// final Rectangle bounds = originalParent.getClipBounds();
final Rectangle bounds = getRelativeBounds();
// System.out.println(" clip bounds: " + bounds);
Graphics g2;
if (bounds != null) {
final int tx = bounds.x + orNoScroll.x;
final int ty = bounds.y + orNoScroll.y;
g2 = gIn.create(tx, ty, bounds.width, bounds.height);
g2.translate(-tx, -ty);
} else {
g2 = gIn.create();
}
g2.translate(or.x, or.y);
// g2.setColor(new java.awt.Color(0.5f, 0.5f, 0f, 0.8f));
// g2.fillRect(0, 0, bounds.width, bounds.height);
try {
this.renderable.paintTranslated(g2);
} finally {
g2.dispose();
}
}
}
private Rectangle getRelativeBounds() {
final RCollection origParent = this.renderable.getOriginalParent();
RCollection current = origParent;
Rectangle currentBounds = current.getClipBoundsWithoutInsets();
final RCollection parent = this.renderable.getParent();
while (current != parent) {
current = current.getParent();
if (current.getModelNode() instanceof HTMLHtmlElement) {
break;
}
final Rectangle newBounds = current.getClipBoundsWithoutInsets();
if (newBounds != null) {
final Point or = origParent.getOriginRelativeToNoScroll(current);
newBounds.translate(-or.x, -or.y);
if (currentBounds == null) {
currentBounds = newBounds;
} else {
currentBounds = currentBounds.intersection(newBounds);
}
}
}
return currentBounds;
}
@Override
public ModelNode getModelNode() {
return this.renderable.getModelNode();
}
@Override
public boolean isFixed() {
return isFixed;
}
@Override
public String toString() {
return "PosRndrbl [" + renderable + "]";
}
public Rectangle getVisualBounds() {
final Rectangle bounds = renderable.getVisualBounds();
final Point offset = getOffset();
bounds.translate(offset.x, offset.y);
return bounds;
}
public Point getOffset() {
final Point offset = new Point();
final int pos = this.renderable.getModelNode().getRenderState().getPosition();
final RCollection originalParent = this.renderable.getOriginalParent();
final RCollection rparent = renderable.getParent();
final Point or = originalParent.getOriginRelativeTo(rparent);
if (isFloat || pos == RenderState.POSITION_ABSOLUTE || pos == RenderState.POSITION_FIXED) {
final Point some = getSome();
if (some!= null) {
offset.translate(some.x, some.y);
}
} else {
offset.translate(or.x, or.y);
}
return offset;
}
// TODO: name this function well: what exactly does it compute?
private Point getSome() {
final RCollection rparent = renderable.getParent();
if (!isFixed && rparent.getModelNode() instanceof HTMLDocument) {
Renderable htmlRenderable = RenderUtils.findHtmlRenderable(rparent);
if (htmlRenderable instanceof PositionedRenderable) {
final PositionedRenderable htmlPR = (PositionedRenderable) htmlRenderable;
htmlRenderable = htmlPR.renderable;
}
// TODO: Handle other renderable types such as RTable
if (htmlRenderable instanceof RBlock) {
final RBlock htmlBlock = ((RBlock) htmlRenderable);
final Point htmlOffset = htmlBlock.bodyLayout.getOrigin();
final Insets htmlInsets = htmlBlock.getInsetsMarginBorder(htmlBlock.hasHScrollBar, htmlBlock.hasVScrollBar);
return new Point((int) htmlOffset.getX() - htmlInsets.left, (int) htmlOffset.getY() - htmlInsets.top);
}
}
return null;
}
public boolean contains(int x, int y) {
return getVisualBounds().contains(x, y);
}
@Override
public boolean isReadyToPaint() {
return renderable.isReadyToPaint();
}
}