001 /* FrameSetView.java -- Implements HTML frameset 002 Copyright (C) 2006 Free Software Foundation, Inc. 003 004 This file is part of GNU Classpath. 005 006 GNU Classpath is free software; you can redistribute it and/or modify 007 it under the terms of the GNU General Public License as published by 008 the Free Software Foundation; either version 2, or (at your option) 009 any later version. 010 011 GNU Classpath is distributed in the hope that it will be useful, but 012 WITHOUT ANY WARRANTY; without even the implied warranty of 013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 General Public License for more details. 015 016 You should have received a copy of the GNU General Public License 017 along with GNU Classpath; see the file COPYING. If not, write to the 018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 019 02110-1301 USA. 020 021 Linking this library statically or dynamically with other modules is 022 making a combined work based on this library. Thus, the terms and 023 conditions of the GNU General Public License cover the whole 024 combination. 025 026 As a special exception, the copyright holders of this library give you 027 permission to link this library with independent modules to produce an 028 executable, regardless of the license terms of these independent 029 modules, and to copy and distribute the resulting executable under 030 terms of your choice, provided that you also meet, for each linked 031 independent module, the terms and conditions of the license of that 032 module. An independent module is a module which is not derived from 033 or based on this library. If you modify this library, you may extend 034 this exception to your version of the library, but you are not 035 obligated to do so. If you do not wish to do so, delete this 036 exception statement from your version. */ 037 038 039 package javax.swing.text.html; 040 041 import java.util.StringTokenizer; 042 043 import javax.swing.text.AttributeSet; 044 import javax.swing.text.BoxView; 045 import javax.swing.text.Element; 046 import javax.swing.text.View; 047 import javax.swing.text.ViewFactory; 048 049 /** 050 * Implements HTML framesets. This is implemented as a vertical box that 051 * holds the rows of the frameset. Each row is again a horizontal box that 052 * holds the actual columns. 053 */ 054 public class FrameSetView 055 extends BoxView 056 { 057 058 /** 059 * A row of a frameset. 060 */ 061 private class FrameSetRow 062 extends BoxView 063 { 064 private int row; 065 FrameSetRow(Element el, int r) 066 { 067 super(el, X_AXIS); 068 row = r; 069 } 070 071 protected void loadChildren(ViewFactory f) 072 { 073 // Load the columns here. 074 Element el = getElement(); 075 View[] columns = new View[numViews[X_AXIS]]; 076 int offset = row * numViews[X_AXIS]; 077 for (int c = 0; c < numViews[X_AXIS]; c++) 078 { 079 Element child = el.getElement(offset + c); 080 columns[c] = f.create(child); 081 } 082 replace(0, 0, columns); 083 } 084 085 protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, 086 int[] spans) 087 { 088 int numRows = numViews[X_AXIS]; 089 int[] abs = absolute[X_AXIS]; 090 int[] rel = relative[X_AXIS]; 091 int[] perc = percent[X_AXIS]; 092 layoutViews(targetSpan, axis, offsets, spans, numRows, abs, rel, perc); 093 } 094 } 095 096 /** 097 * Holds the absolute layout information for the views along one axis. The 098 * indices are absolute[axis][index], where axis is either X_AXIS (columns) 099 * or Y_AXIS (rows). Rows or columns that don't have absolute layout have 100 * a -1 in this array. 101 */ 102 int[][] absolute; 103 104 /** 105 * Holds the relative (*) layout information for the views along one axis. 106 * The indices are relative[axis][index], where axis is either X_AXIS 107 * (columns) or Y_AXIS (rows). Rows or columns that don't have relative 108 * layout have a Float.NaN in this array. 109 */ 110 int[][] relative; 111 112 /** 113 * Holds the relative (%) layout information for the views along one axis. 114 * The indices are relative[axis][index], where axis is either X_AXIS 115 * (columns) or Y_AXIS (rows). Rows or columns that don't have relative 116 * layout have a Float.NaN in this array. 117 * 118 * The percentage is divided by 100 so that we hold the actual fraction here. 119 */ 120 int[][] percent; 121 122 /** 123 * The number of children in each direction. 124 */ 125 int[] numViews; 126 127 FrameSetView(Element el) 128 { 129 super(el, Y_AXIS); 130 numViews = new int[2]; 131 absolute = new int[2][]; 132 relative = new int[2][]; 133 percent = new int[2][]; 134 } 135 136 /** 137 * Loads the children and places them inside the grid. 138 */ 139 protected void loadChildren(ViewFactory f) 140 { 141 parseRowsCols(); 142 // Set up the rows. 143 View[] rows = new View[numViews[Y_AXIS]]; 144 for (int r = 0; r < numViews[Y_AXIS]; r++) 145 { 146 rows[r] = new FrameSetRow(getElement(), r); 147 } 148 replace(0, 0, rows); 149 } 150 151 /** 152 * Parses the rows and cols attributes and sets up the layout info. 153 */ 154 private void parseRowsCols() 155 { 156 Element el = getElement(); 157 AttributeSet atts = el.getAttributes(); 158 String cols = (String) atts.getAttribute(HTML.Attribute.COLS); 159 if (cols == null) // Defaults to '100%' when not specified. 160 cols = "100%"; 161 parseLayout(cols, X_AXIS); 162 String rows = (String) atts.getAttribute(HTML.Attribute.ROWS); 163 if (rows == null) // Defaults to '100%' when not specified. 164 rows = "100%"; 165 parseLayout(rows, Y_AXIS); 166 } 167 168 /** 169 * Parses the cols or rows attribute and places the layout info in the 170 * appropriate arrays. 171 * 172 * @param att the attributes to parse 173 * @param axis the axis 174 */ 175 private void parseLayout(String att, int axis) 176 { 177 StringTokenizer tokens = new StringTokenizer(att, ","); 178 numViews[axis] = tokens.countTokens(); 179 absolute[axis] = new int[numViews[axis]]; 180 relative[axis] = new int[numViews[axis]]; 181 percent[axis] = new int[numViews[axis]]; 182 for (int index = 0; tokens.hasMoreTokens(); index++) 183 { 184 String token = tokens.nextToken(); 185 int p = token.indexOf('%'); 186 int s = token.indexOf('*'); 187 if (p != -1) 188 { 189 // Percent value. 190 String number = token.substring(0, p); 191 try 192 { 193 percent[axis][index] = Integer.parseInt(number); 194 } 195 catch (NumberFormatException ex) 196 { 197 // Leave value as 0 then. 198 } 199 } 200 else if (s != -1) 201 { 202 // Star relative value. 203 String number = token.substring(0, s); 204 try 205 { 206 relative[axis][index] = Integer.parseInt(number); 207 } 208 catch (NumberFormatException ex) 209 { 210 // Leave value as 0 then. 211 } 212 } 213 else 214 { 215 // Absolute value. 216 try 217 { 218 absolute[axis][index] = Integer.parseInt(token); 219 } 220 catch (NumberFormatException ex) 221 { 222 // Leave value as 0 then. 223 } 224 } 225 } 226 } 227 228 protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, 229 int[] spans) 230 { 231 int numRows = numViews[Y_AXIS]; 232 int[] abs = absolute[Y_AXIS]; 233 int[] rel = relative[Y_AXIS]; 234 int[] perc = percent[Y_AXIS]; 235 layoutViews(targetSpan, axis, offsets, spans, numRows, abs, rel, perc); 236 } 237 238 void layoutViews(int targetSpan, int axis, int[] offsets, int[] spans, 239 int numViews, int[] abs, int[] rel, int[] perc) 240 { 241 // We need two passes. In the first pass we layout the absolute and 242 // percent values and accumulate the needed space. In the second pass 243 // the relative values are distributed and the offsets are set. 244 int total = 0; 245 int relTotal = 0; 246 for (int i = 0; i < numViews; i++) 247 { 248 if (abs[i] > 0) 249 { 250 spans[i] = abs[i]; 251 total += spans[i]; 252 } 253 else if (perc[i] > 0) 254 { 255 spans[i] = (targetSpan * perc[i]) / 100; 256 total += spans[i]; 257 } 258 else if (rel[i] > 0) 259 { 260 relTotal += rel[i]; 261 } 262 } 263 int offs = 0; 264 for (int i = 0; i < numViews; i++) 265 { 266 if (relTotal > 0 && rel[i] > 0) 267 { 268 spans[i] = targetSpan * (rel[i] / relTotal); 269 } 270 offsets[i] = offs; 271 offs += spans[i]; 272 } 273 } 274 }