Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright 2012 AndroidPlot.com
      3  *
      4  *    Licensed under the Apache License, Version 2.0 (the "License");
      5  *    you may not use this file except in compliance with the License.
      6  *    You may obtain a copy of the License at
      7  *
      8  *        http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  *    Unless required by applicable law or agreed to in writing, software
     11  *    distributed under the License is distributed on an "AS IS" BASIS,
     12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  *    See the License for the specific language governing permissions and
     14  *    limitations under the License.
     15  */
     16 
     17 package com.androidplot.ui;
     18 
     19 import android.graphics.RectF;
     20 
     21 import java.util.Iterator;
     22 
     23 /**
     24  * Encapsulates the visual aspects of a table; number of rows and columns
     25  * and the height and width in pixels of each element within the table.
     26  * There is no support (yet) for variable size cells within a table;  all
     27  * cells within a table share the same dimensions.
     28  *
     29  * The DynamicTableModel provides an Iterator implementation which returns a RectF
     30  * of each subsequent cell, based on the order of the plot.  Tables with
     31  * an order of COLUMN_MAJOR are traversed left to right column by column until
     32  * the end of the row is reached, then proceeding to the next row.
     33  * Tables with an order of ROW_MAJOR are traversed top to bottom row by row
     34  * until the end of the row is reached, then proceeding to the next column.
     35  */
     36 public class DynamicTableModel extends TableModel {
     37 
     38     //private float cellWidth;
     39     //private float cellHeight;
     40     //private TableSizingMethod rowSizingMethod;
     41     //private TableSizingMethod columnSizingMethod;
     42 
     43 
     44     private int numRows;
     45     private int numColumns;
     46 
     47     private Float cellWidth;
     48     private Float cellHeight;
     49 
     50     private CellSizingMethod rowSizingMethod;
     51     private CellSizingMethod columnSizingMethod;
     52 
     53     /**
     54      * Convenience method.  Sets order to ROW_MAJOR.
     55      * @param numColumns
     56      * @param numRows
     57      */
     58     public DynamicTableModel(int numColumns, int numRows) {
     59         this(numColumns, numRows, TableOrder.ROW_MAJOR);
     60 
     61     }
     62 
     63     public DynamicTableModel(int numColumns, int numRows, TableOrder order) {
     64         super(order);
     65         this.numColumns = numColumns;
     66         //this.cellWidth = cellWidth;
     67         //this.rowSizingMethod = rowSizingMethod;
     68         this.numRows = numRows;
     69         //this.cellHeight = cellHeight;
     70         //this.columnSizingMethod = columnSizingMethod;
     71         //this.order = order;
     72     }
     73 
     74     /*public DynamicTableModel(Number colVal, CellSizingMethod colSzMethod, Number rowVal, CellSizingMethod rowSzMethod, TableOrder order) {
     75         if(colVal == null || rowVal == null) {
     76             throw new NullPointerException();
     77         }
     78         columnSizingMethod = colSzMethod;
     79         switch(columnSizingMethod) {
     80             case FILL:
     81                 numColumns = colVal.intValue();
     82                 break;
     83             case FIXED:
     84                 cellWidth = colVal.floatValue();
     85                 break;
     86         }
     87         rowSzMethod = rowSzMethod;
     88     }*/
     89 
     90     @Override
     91     public TableModelIterator getIterator(RectF tableRect, int totalElements) {
     92         return new TableModelIterator(this, tableRect, totalElements);
     93     }
     94 
     95     /**
     96      * Calculates the dimensions of a single element of this table with
     97      * tableRect representing the overall dimensions of the table.
     98      * @param tableRect Dimensions/position of the table
     99      * @return a RectF representing the first (top-left) element in
    100      * the tableRect passed in.
    101      */
    102     public RectF getCellRect(RectF tableRect, int numElements) {
    103         RectF cellRect = new RectF();
    104         cellRect.left = tableRect.left;
    105         cellRect.top = tableRect.top;
    106         //cellRect.bottom = getElementHeightPix(tableRect);
    107         cellRect.bottom = tableRect.top + calculateCellSize(tableRect, TableModel.Axis.ROW, numElements);
    108         //cellRect.right = getElementWidthPix(tableRect);
    109         cellRect.right = tableRect.left + calculateCellSize(tableRect, TableModel.Axis.COLUMN, numElements);
    110         return cellRect;
    111     }
    112 
    113     /**
    114      * Figure out the size of a single cell across the specified axis.
    115      * @param tableRect
    116      * @param axis
    117      * @param numElementsInTable
    118      * @return
    119      */
    120     private float calculateCellSize(RectF tableRect,
    121                                     Axis axis,
    122                                     int numElementsInTable) {
    123         //float elementSizeInPix = 0;
    124         int axisElements = 0;
    125 
    126         float axisSizePix = 0;
    127         switch (axis) {
    128             case ROW:
    129                 //elementSizeInPix = cellHeight;
    130                 axisElements = numRows;
    131                 axisSizePix = tableRect.height();
    132                 break;
    133             case COLUMN:
    134                 //elementSizeInPix = cellWidth;
    135                 axisElements = numColumns;
    136                 axisSizePix = tableRect.width();
    137                 break;
    138         }
    139         //if (elementSizeInPix != 0) {
    140         //    return elementSizeInPix;
    141         if(axisElements != 0) {
    142             return axisSizePix / axisElements;
    143         } else {
    144             return axisSizePix / numElementsInTable;
    145         }
    146     }
    147 
    148 
    149 
    150     public int getNumRows() {
    151         return numRows;
    152     }
    153 
    154     public void setNumRows(int numRows) {
    155         this.numRows = numRows;
    156     }
    157 
    158     public int getNumColumns() {
    159         return numColumns;
    160     }
    161 
    162     public void setNumColumns(int numColumns) {
    163         this.numColumns = numColumns;
    164     }
    165 
    166 /*    public void setCellWidth(Float cellWidth) {
    167         this.cellWidth = cellWidth;
    168     }
    169 
    170     public Float getCellWidth() {
    171         return cellWidth;
    172     }
    173 
    174     public Float getCellHeight() {
    175         return cellHeight;
    176     }
    177 
    178     public void setCellHeight(Float cellHeight) {
    179         this.cellHeight = cellHeight;
    180     }*/
    181 
    182     private class TableModelIterator implements Iterator<RectF> {
    183         private boolean isOk = true;
    184         int lastColumn = 0;                     // most recent column iterated
    185         int lastRow = 0;                        // most recent row iterated
    186         int lastElement = 0;                    // last element index iterated
    187         private DynamicTableModel dynamicTableModel;
    188         private RectF tableRect;
    189         private RectF lastElementRect;
    190         private int totalElements;
    191         private TableOrder order;
    192 
    193         private int calculatedNumElements;
    194         private int calculatedRows;             // number of rows to be iterated
    195         private int calculatedColumns;          // number of columns to be iterated
    196 
    197         public TableModelIterator(DynamicTableModel dynamicTableModel, RectF tableRect, int totalElements) {
    198             this.dynamicTableModel = dynamicTableModel;
    199             this.tableRect = tableRect;
    200             this.totalElements = totalElements;
    201             order = dynamicTableModel.getOrder();
    202 
    203             // unlimited columns:
    204             if(dynamicTableModel.getNumColumns() == 0 && dynamicTableModel.getNumRows() >= 1) {
    205                 calculatedRows = dynamicTableModel.getNumRows();
    206 
    207                 // round up:
    208                 calculatedColumns = new Float((totalElements / (float) calculatedRows) + 0.5).intValue();
    209             } else if(dynamicTableModel.getNumRows() == 0 && dynamicTableModel.getNumColumns() >= 1) {
    210                 //order = TableOrder.ROW_MAJOR;
    211                 calculatedColumns = dynamicTableModel.getNumColumns();
    212                 calculatedRows = new Float((totalElements / (float) calculatedColumns) + 0.5).intValue();
    213             // unlimited rows and columns (impossible) so default a single row with n columns:
    214             }else if(dynamicTableModel.getNumColumns() == 0 && dynamicTableModel.getNumRows() == 0) {
    215                 calculatedRows = 1;
    216                 calculatedColumns = totalElements;
    217             } else {
    218                 //order = dynamicTableModel.getOrder();
    219                 calculatedRows = dynamicTableModel.getNumRows();
    220                 calculatedColumns = dynamicTableModel.getNumColumns();
    221             }
    222             calculatedNumElements = calculatedRows * calculatedColumns;
    223             lastElementRect = dynamicTableModel.getCellRect(tableRect, totalElements);
    224         }
    225 
    226         @Override
    227         public boolean hasNext() {
    228             return isOk && lastElement < calculatedNumElements;
    229         }
    230 
    231         @Override
    232         public RectF next() {
    233             if(!hasNext()) {
    234                 isOk = false;
    235                 throw new IndexOutOfBoundsException();
    236             }
    237 
    238             if (lastElement == 0) {
    239                 lastElement++;
    240                 return lastElementRect;
    241             }
    242 
    243             RectF nextElementRect = new RectF(lastElementRect);
    244 
    245             switch (order) {
    246                 case ROW_MAJOR:
    247                     if (dynamicTableModel.getNumColumns() > 0 && lastColumn >= (dynamicTableModel.getNumColumns() - 1)) {
    248                         // move to the begining of the next row down:// move to the begining of the next row down:
    249                         nextElementRect.offsetTo(tableRect.left, lastElementRect.bottom);
    250                         lastColumn = 0;
    251                         lastRow++;
    252                     } else {
    253                         // move to the next column over:
    254                         nextElementRect.offsetTo(lastElementRect.right, lastElementRect.top);
    255                         lastColumn++;
    256                     }
    257                     break;
    258                 case COLUMN_MAJOR:
    259                     if (dynamicTableModel.getNumRows() > 0 && lastRow >= (dynamicTableModel.getNumRows() - 1)) {
    260                         // move to the top of the next column over:
    261                         nextElementRect.offsetTo(lastElementRect.right, tableRect.top);
    262                         lastRow = 0;
    263                         lastColumn++;
    264                     } else {
    265                         // move to the next row down:
    266                         nextElementRect.offsetTo(lastElementRect.left, lastElementRect.bottom);
    267                         lastRow++;
    268                     }
    269                     break;
    270                 // unknown/unsupported enum val:
    271                 default:
    272                     isOk = false;
    273                     throw new IllegalArgumentException();
    274             }
    275             lastElement++;
    276             lastElementRect = nextElementRect;
    277             return nextElementRect;
    278 
    279         }
    280 
    281         @Override
    282         public void remove() {
    283             throw new UnsupportedOperationException();
    284         }
    285     }
    286 }
    287