Source for javax.swing.text.TableView

   1: /* TableView.java -- A view impl for tables inside styled text
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.text;
  40: 
  41: import java.awt.Rectangle;
  42: import java.awt.Shape;
  43: 
  44: import javax.swing.SizeRequirements;
  45: import javax.swing.event.DocumentEvent;
  46: 
  47: /**
  48:  * A {@link View} implementation for rendering tables inside styled text.
  49:  * Tables are rendered as vertical boxes (see {@link BoxView}). These boxes
  50:  * have a number of child views, which are the rows of the table. These are
  51:  * horizontal boxes containing the actuall cells of the table. These cells
  52:  * can be arbitrary view implementations and are fetched via the
  53:  * {@link ViewFactory} returned by {@link View#getViewFactory}.
  54:  * 
  55:  * @author Roman Kennke (kennke@aicas.com)
  56:  */
  57: public class TableView
  58:   extends BoxView
  59: {
  60: 
  61:   /**
  62:    * A view implementation that renders a row of a <code>TableView</code>.
  63:    * This is implemented as a horizontal box that contains the actual cells
  64:    * of the table.
  65:    *
  66:    * @author Roman Kennke (kennke@aicas.com)
  67:    */
  68:   public class TableRow
  69:     extends BoxView
  70:   {
  71:     /**
  72:      * Creates a new instance of <code>TableRow</code>.
  73:      *
  74:      * @param el the element for which to create a row view
  75:      */
  76:     public TableRow(Element el)
  77:     {
  78:       super(el, X_AXIS);
  79:     }
  80: 
  81:     /**
  82:      * Replaces some child views with a new set of child views. This is
  83:      * implemented to call the superclass behaviour and invalidates the row
  84:      * grid so that rows and columns will be recalculated.
  85:      *
  86:      * @param offset the start offset at which to replace views
  87:      * @param length the number of views to remove
  88:      * @param views the new set of views
  89:      */
  90:     public void replace(int offset, int length, View[] views)
  91:     {
  92:       super.replace(offset, length, views);
  93:       layoutChanged(X_AXIS);
  94:     }
  95: 
  96:     /**
  97:      * Lays out the box's child views along the major axis. This is
  98:      * reimplemented so that the child views all have the width of their
  99:      * column.
 100:      *
 101:      * @param targetSpan the total span of the view
 102:      * @param axis the axis that is laid out
 103:      * @param offsets an array that holds the offsets of the child views after
 104:      *        this method returned
 105:      * @param spans an array that holds the spans of the child views after this
 106:      *        method returned
 107:      */
 108:     protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets,
 109:                                    int[] spans)
 110:     {
 111:       // TODO: Maybe prepare columnSpans and columnOffsets.
 112: 
 113:       // Some sanity checks. If these preconditions are not met, then the
 114:       // following code will not work. Also, there must be something
 115:       // seriously wrong then.
 116:       assert(offsets.length == columnOffsets.length);
 117:       assert(spans.length == columnSpans.length);
 118:       assert(offsets.length == spans.length);
 119:       for (int i = 0; i < offsets.length; ++i)
 120:         {
 121:           offsets[i] = columnOffsets[i];
 122:           spans[i] = columnSpans[i];
 123:         }
 124:     }
 125: 
 126:     /**
 127:      * Lays out the box's child views along the minor axis (the orthogonal axis
 128:      * to the major axis). This is reimplemented to call the super behaviour
 129:      * and then adjust the span of the child views that span multiple rows.
 130:      *
 131:      * @param targetSpan the total span of the view
 132:      * @param axis the axis that is laid out
 133:      * @param offsets an array that holds the offsets of the child views after
 134:      *        this method returned
 135:      * @param spans an array that holds the spans of the child views after this
 136:      *        method returned
 137:      */
 138:     protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
 139:                                    int[] spans)
 140:     {
 141:       // FIXME: Figure out how to fetch the row heights from the TableView's
 142:       // element.
 143:       super.layoutMajorAxis(targetSpan, axis, offsets, spans);
 144:     }
 145: 
 146:     /**
 147:      * Determines the resizeability of this view along the specified axis.
 148:      *
 149:      * @param axis the axis of which to fetch the resizability
 150:      *
 151:      * @return the resize weight or &lt;= 0 if this view is not resizable
 152:      *
 153:      * @throws IllegalArgumentException when an illegal axis is specified
 154:      */
 155:     public int getResizeWeight(int axis)
 156:     {
 157:       // TODO: Figure out if this is ok. I would think so, but better test
 158:       // this.
 159:       return 0;
 160:     }
 161: 
 162:     /**
 163:      * Returns the child view that represents the specified position in the
 164:      * model. This is reimplemented because in this view we do not necessarily
 165:      * have a one to one mapping of child elements to child views.
 166:      *
 167:      * @param pos the model position for which to query the view
 168:      * @param a the allocation of this view
 169:      *
 170:      * @return the view that corresponds to the specified model position or
 171:      *         <code>null</code> if there is none
 172:      */
 173:     protected View getViewAtPosition(int pos, Rectangle a)
 174:     {
 175:       // FIXME: Do not call super here. Instead walk through the child views
 176:       // and look for a range that contains the given position.
 177:       return super.getViewAtPosition(pos, a);
 178:     }
 179:   }
 180: 
 181:   /**
 182:    * This class is deprecated and not used anymore. Table cells are
 183:    * rendered by an arbitrary <code>View</code> implementation.
 184:    *
 185:    * @author Roman Kennke (kennke@aicas.com)
 186:    *
 187:    * @deprecated Table cells are now rendered by an arbitrary <code>View</code>
 188:    *             implementation.
 189:    */
 190:   public class TableCell
 191:     extends BoxView
 192:   {
 193: 
 194:     /**
 195:      * The row number of this cell.
 196:      */
 197:     private int row;
 198: 
 199:     /**
 200:      * The column number of this cell.
 201:      */
 202:     private int column;
 203: 
 204:     /**
 205:      * Creates a new instance.
 206:      *
 207:      * @param el the element
 208:      *
 209:      * @deprecated Table cells are now rendered by an arbitrary
 210:      *             <code>View</code> implementation.
 211:      */
 212:     public TableCell(Element el)
 213:     {
 214:       super(el, X_AXIS);
 215:     }
 216: 
 217:     /**
 218:      * Returns the number of columns that this cell spans.
 219:      *
 220:      * @return the number of columns that this cell spans
 221:      *
 222:      * @deprecated Table cells are now rendered by an arbitrary
 223:      *             <code>View</code> implementation.
 224:      */
 225:     public int getColumnCount()
 226:     {
 227:       // TODO: Figure out if this is right. However, this is not so important
 228:       // since this class isn't used anyway (except maybe be application code
 229:       // that still uses this deprecated class).
 230:       return 1;
 231:     }
 232: 
 233:     /**
 234:      * Returns the number of rows that this cell spans.
 235:      *
 236:      * @return the number of rows that this cell spans
 237:      *
 238:      * @deprecated Table cells are now rendered by an arbitrary
 239:      *             <code>View</code> implementation.
 240:      */
 241:     public int getRowCount()
 242:     {
 243:       // TODO: Figure out if this is right. However, this is not so important
 244:       // since this class isn't used anyway (except maybe be application code
 245:       // that still uses this deprecated class).
 246:       return 1;
 247:     }
 248: 
 249:     /**
 250:      * Sets the grid location of this table cell.
 251:      *
 252:      * @param r the row of this cell
 253:      * @param c the column of this cell
 254:      *
 255:      * @deprecated Table cells are now rendered by an arbitrary
 256:      *             <code>View</code> implementation.
 257:      */
 258:     public void setGridLocation(int r, int c)
 259:     {
 260:       row = r;
 261:       column = c;
 262:     }
 263: 
 264:     /**
 265:      * Returns the row number of this cell.
 266:      *
 267:      * @return the row number of this cell
 268:      *
 269:      * @deprecated Table cells are now rendered by an arbitrary
 270:      *             <code>View</code> implementation.
 271:      */
 272:     public int getGridRow()
 273:     {
 274:       return row;
 275:     }
 276: 
 277:     /**
 278:      * Returns the column number of this cell.
 279:      *
 280:      * @return the column number of this cell
 281:      *
 282:      * @deprecated Table cells are now rendered by an arbitrary
 283:      *             <code>View</code> implementation.
 284:      */
 285:     public int getGridColumn()
 286:     {
 287:       return column;
 288:     }
 289:   }
 290: 
 291:   /**
 292:    * The offsets of the columns of this table. Package private to avoid
 293:    * synthetic accessor methods.
 294:    */
 295:   int[] columnOffsets;
 296: 
 297:   /**
 298:    * The spans of the columns of this table. Package private to avoid
 299:    * synthetic accessor methods.
 300:    */
 301:   int[] columnSpans;
 302: 
 303:   /**
 304:    * The size requirements of the columns.
 305:    */
 306:   private SizeRequirements[] columnRequirements;
 307: 
 308:   /**
 309:    * Creates a new instance of <code>TableView</code>.
 310:    *
 311:    * @param el the element for which to create a table view
 312:    */
 313:   public TableView(Element el)
 314:   {
 315:     super(el, Y_AXIS);
 316:     int numChildren = el.getElementCount();
 317:     View[] rows = new View[numChildren];
 318:     for (int i = 0; i < numChildren; ++i)
 319:       {
 320:         Element rowEl = el.getElement(i);
 321:         TableRow rowView = createTableRow(rowEl);
 322:         rows[i] = rowView;
 323:       }
 324:     replace(0, 0, rows);
 325:   }
 326: 
 327:   /**
 328:    * Replaces a number of child views with a set of new child views. This is
 329:    * implemented to call the superclass behaviour and invalidate the layout.
 330:    *
 331:    * @param offset the offset at which to replace child views
 332:    * @param length the number of child views to remove
 333:    * @param views the new set of views
 334:    */
 335:   public void replace(int offset, int length, View[] views)
 336:   {
 337:     super.replace(offset, length, views);
 338:     layoutChanged(Y_AXIS);
 339:   }
 340: 
 341:   /**
 342:    * Creates a view for a table row.
 343:    *
 344:    * @param el the element that represents the table row
 345:    *
 346:    * @return a view for rendering the table row
 347:    */
 348:   protected TableRow createTableRow(Element el)
 349:   {
 350:     return new TableRow(el);
 351:   }
 352: 
 353:   /**
 354:    * Creates a view for a table cell. This method is deprecated and not used
 355:    * anymore.
 356:    *
 357:    * @param el the element that represents the table cell
 358:    *
 359:    * @return a view for rendering the table cell
 360:    *
 361:    * @deprecated Table cells are now rendered by an arbitrary
 362:    *             <code>View</code> implementation.
 363:    */
 364:   protected TableCell createTableCell(Element el)
 365:   {
 366:     return new TableCell(el);
 367:   }
 368: 
 369:   protected void forwardUpdate(DocumentEvent.ElementChange ec, DocumentEvent e,
 370:                                Shape a, ViewFactory vf)
 371:   {
 372:     // TODO: Figure out what to do here.
 373:   }
 374: 
 375:   /**
 376:    * Lays out the columns to fit within the specified target span.
 377:    *
 378:    * @param targetSpan the total span for the columns
 379:    * @param offsets an array that holds the offsets of the columns when this
 380:    *        method returns
 381:    * @param spans an array that holds the spans of the columns when this method
 382:    *        returns
 383:    * @param reqs the size requirements for each column
 384:    */
 385:   protected void layoutColumns(int targetSpan, int[] offsets, int spans[],
 386:                                SizeRequirements[] reqs)
 387:   {
 388:     // TODO: Figure out what exactly to do here. 
 389:   }
 390: 
 391:   /**
 392:    * Lays out the child views along the minor axis of the table (that is the
 393:    * horizontal axis). This is implemented to call {@link #layoutColumns} to
 394:    * layout the column layout of this table, and then forward to the superclass
 395:    * to actually lay out the rows.
 396:    *
 397:    * @param targetSpan the available span along the minor (horizontal) axis
 398:    * @param axis the axis
 399:    * @param offsets an array that holds the offsets of the columns when this
 400:    *        method returns
 401:    * @param spans an array that holds the spans of the columns when this method
 402:    *        returns
 403:    */
 404:   protected void layoutMinorAxis(int targetSpan, int axis, int[] offsets,
 405:                                  int[] spans)
 406:   {
 407:     // TODO: Prepare size requirements for the columns.
 408:     layoutColumns(targetSpan, columnOffsets, columnSpans, columnRequirements);
 409:     super.layoutMinorAxis(targetSpan, axis, offsets, spans);
 410:   }
 411: 
 412:   /**
 413:    * Calculates the requirements of this view for the minor (== horizontal)
 414:    * axis.
 415:    * 
 416:    * This is reimplemented to calculate the requirements as the sum of the
 417:    * size requirements of the columns.
 418:    *
 419:    * @param axis the axis
 420:    * @param req the size requirements object to use, if <code>null</code> a new
 421:    *        one will be created
 422:    */
 423:   protected SizeRequirements calculateMinorAxisRequirements(int axis,
 424:                                                             SizeRequirements req)
 425:   {
 426:     // TODO: Maybe prepare columnRequirements.
 427:     SizeRequirements res = req;
 428:     if (res == null)
 429:       res = new SizeRequirements();
 430:     else
 431:       {
 432:         res.alignment = 0.5f;
 433:         res.maximum = 0;
 434:         res.minimum = 0;
 435:         res.preferred = 0;
 436:       }
 437: 
 438:     for (int i = 0; i < columnRequirements.length; ++i)
 439:       {
 440:         res.minimum += columnRequirements[i].minimum;
 441:         res.preferred += columnRequirements[i].preferred;
 442:         res.maximum += columnRequirements[i].maximum;
 443:         // TODO: Do we have to handle alignment somehow?
 444:       }
 445:     return res;
 446:   }
 447: 
 448:   /**
 449:    * Returns the child view that represents the specified position in the
 450:    * model. This is reimplemented because in this view we do not necessarily
 451:    * have a one to one mapping of child elements to child views.
 452:    *
 453:    * @param pos the model position for which to query the view
 454:    * @param a the allocation of this view
 455:    *
 456:    * @return the view that corresponds to the specified model position or
 457:    *         <code>null</code> if there is none
 458:    */
 459:   protected View getViewAtPosition(int pos, Rectangle a)
 460:   {
 461:     // FIXME: Do not call super here. Instead walk through the child views
 462:     // and look for a range that contains the given position.
 463:     return super.getViewAtPosition(pos, a);
 464:   }
 465: }