001 /*
002 * Copyright 2007 - 2007 JEuclid, http://jeuclid.sf.net
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 /* $Id: ElementListSupport.java,v d02878fc1d01 2009/09/08 12:35:02 max $ */
018
019 package net.sourceforge.jeuclid.elements.support;
020
021 import java.awt.Color;
022 import java.awt.geom.Dimension2D;
023 import java.util.ArrayList;
024 import java.util.List;
025
026 import net.sourceforge.jeuclid.layout.FillRectObject;
027 import net.sourceforge.jeuclid.layout.GraphicsObject;
028 import net.sourceforge.jeuclid.layout.LayoutInfo;
029 import net.sourceforge.jeuclid.layout.LayoutStage;
030 import net.sourceforge.jeuclid.layout.LayoutView;
031 import net.sourceforge.jeuclid.layout.LayoutableNode;
032
033 import org.w3c.dom.Node;
034
035 /**
036 * Class to support Lists of MathElements.
037 * <p>
038 * This class can be used by all elements that have some kind of a list of
039 * children that they need to handle in a row-like manner.
040 *
041 * @version $Revision: d02878fc1d01 $
042 */
043 public final class ElementListSupport {
044
045 private ElementListSupport() {
046 // Utility class.
047 }
048
049 /**
050 * Creates a list of children for the given Element.
051 *
052 * @param parent
053 * the parent element.
054 * @return list of Children.
055 */
056 public static List<Node> createListOfChildren(final Node parent) {
057 final org.w3c.dom.NodeList childList = parent.getChildNodes();
058 final int len = childList.getLength();
059 final List<Node> children = new ArrayList<Node>(len);
060 for (int i = 0; i < len; i++) {
061 final Node child = childList.item(i);
062 children.add(child);
063 }
064 return children;
065
066 }
067
068 /**
069 * Creates a list of layoutable children for the given Element.
070 *
071 * @param parent
072 * the parent element.
073 * @return list of Children.
074 */
075 public static List<LayoutableNode> createListOfLayoutChildren(
076 final Node parent) {
077 final org.w3c.dom.NodeList childList = parent.getChildNodes();
078 final int len = childList.getLength();
079 final List<LayoutableNode> children = new ArrayList<LayoutableNode>(len);
080 for (int i = 0; i < len; i++) {
081 final Node child = childList.item(i);
082 if (child instanceof LayoutableNode) {
083 children.add((LayoutableNode) child);
084 }
085 }
086 return children;
087
088 }
089
090 /**
091 * @param view
092 * View Object
093 * @param info
094 * Info to fill
095 * @param parent
096 * Current Node
097 * @param stage
098 * Stage to load Info From
099 * @param borderLeftTop
100 * border around element.
101 * @param borderRightBottom
102 * border around element.
103 */
104 public static void fillInfoFromChildren(final LayoutView view,
105 final LayoutInfo info, final Node parent, final LayoutStage stage,
106 final Dimension2D borderLeftTop, final Dimension2D borderRightBottom) {
107 float ascentHeight = (float) borderLeftTop.getHeight();
108 float descentHeight = (float) borderRightBottom.getHeight();
109 final float startX = (float) borderLeftTop.getWidth();
110 float width = startX;
111 for (final LayoutableNode child : ElementListSupport
112 .createListOfLayoutChildren(parent)) {
113 final LayoutInfo childInfo = view.getInfo(child);
114 ascentHeight = Math.max(ascentHeight, -childInfo.getPosY(stage)
115 + childInfo.getAscentHeight(stage));
116 descentHeight = Math.max(descentHeight, childInfo.getPosY(stage)
117 + childInfo.getDescentHeight(stage));
118 width = Math.max(width, childInfo.getPosX(stage)
119 + childInfo.getWidth(stage));
120 }
121 info.setAscentHeight(ascentHeight + (float) borderLeftTop.getHeight(),
122 stage);
123 info.setDescentHeight(descentHeight
124 + (float) borderRightBottom.getHeight(), stage);
125 info.setHorizontalCenterOffset((width + startX) / 2.0f, stage);
126 info.setWidth(width + (float) borderRightBottom.getWidth(), stage);
127 }
128
129 /**
130 * @param view
131 * View Object
132 * @param info
133 * Info to fill
134 * @param children
135 * Children to layout
136 * @param stage
137 * Stage to load Info From
138 */
139 public static void layoutSequential(final LayoutView view,
140 final LayoutInfo info, final List<LayoutableNode> children,
141 final LayoutStage stage) {
142 float ascentHeight = 0.0f;
143 float descentHeight = 0.0f;
144 float posX = 0.0f;
145 float stretchAscent = 0.0f;
146 float stretchDescent = 0.0f;
147
148 for (final LayoutableNode child : children) {
149 final LayoutInfo childInfo = view.getInfo(child);
150 ascentHeight = Math.max(ascentHeight, childInfo
151 .getAscentHeight(stage));
152 descentHeight = Math.max(descentHeight, childInfo
153 .getDescentHeight(stage));
154 stretchAscent = Math.max(stretchAscent, childInfo
155 .getStretchAscent());
156 stretchDescent = Math.max(stretchDescent, childInfo
157 .getStretchDescent());
158 childInfo.moveTo(posX, 0.0f, stage);
159 posX += childInfo.getWidth(stage);
160 }
161 info.setAscentHeight(ascentHeight, stage);
162 info.setDescentHeight(descentHeight, stage);
163 info.setStretchAscent(stretchAscent);
164 info.setStretchDescent(stretchDescent);
165 info.setHorizontalCenterOffset(posX / 2.0f, stage);
166 info.setWidth(posX, stage);
167 }
168
169 /**
170 * Add a background Rectangle for the given background color.
171 *
172 * @param backgroundColor
173 * background color (may be null)
174 * @param info
175 * LayoutInfo object to add to. Must already be completely
176 * rendered (stage 2)
177 * @param useCeil
178 * if true, the {@link Math#ceil(double)} will be used to avoid
179 * anti-aliasing artifacts.
180 */
181 public static void addBackground(final Color backgroundColor,
182 final LayoutInfo info, final boolean useCeil) {
183 if (backgroundColor != null) {
184 final GraphicsObject fillObject;
185 if (useCeil) {
186 fillObject = new FillRectObject(backgroundColor, (float) Math
187 .ceil(info.getAscentHeight(LayoutStage.STAGE2)),
188 (float) Math.ceil(info
189 .getDescentHeight(LayoutStage.STAGE2)),
190 (float) Math.ceil(info.getWidth(LayoutStage.STAGE2)));
191 } else {
192 fillObject = new FillRectObject(backgroundColor, info
193 .getAscentHeight(LayoutStage.STAGE2), info
194 .getDescentHeight(LayoutStage.STAGE2), info
195 .getWidth(LayoutStage.STAGE2));
196
197 }
198
199 info.getGraphicObjects().add(0, fillObject);
200 }
201
202 }
203 }