Commits

sami...@S-HADZIC.Nellarmonia.lan  committed c02af28

Really big modifications. Potentially instable. Read after:
I need to handle different rowHeight, as specified in RT-33045. So I've introduced that possibility. But this was causing huge problems with the VirtualFlow and fixedRows.
So we step back a little and said that it is only possible to fix the first "x" rows. We'll see after if it's possible to support fixing any rows.
I've modified our VirtualFlow. Basically I stopped crushing my brain in understanding and trying to be smart with the VirtualFlow. I just add my fixed row after if it's needed. This solution have the benefit of reducing like crazy our VirtualFlow.
Basically everything has been put in comment. If my solution is really working then we would have dealt with the "nasty" code inside our VirtualFlow.
This commit is not perfect but if I discover that it is robust, then I will improve the rest (see FIXME).

  • Participants
  • Parent commits 6203da3

Comments (0)

Files changed (10)

File src/main/java/impl/org/controlsfx/spreadsheet/CellView.java

         final SpreadsheetView.SpanType type = grid.getSpanType(spv, row, column);
         if ( type == SpreadsheetView.SpanType.NORMAL_CELL || type == SpreadsheetView.SpanType.ROW_VISIBLE) {
         	
-        	/* FIXME Currently we're adding a row two times if it's located in the fixedRows.
+        	/* THIS IS NOT ENTIRELY TRUE ANYMORE, will be fixed.
+        	 * (FIXME Currently we're adding a row two times if it's located in the fixedRows.
         	 * So we have a problem because some events, especially when editing
         	 * are received in double.
         	 * I don't know right now why this is happening but I have found a work-around.
         	 * I check if the current SpreadsheetRow is referenced in the SpreadsheetView,
-        	 * if not, then I know I can throw it away (setManaged(false) ?)
+        	 * if not, then I know I can throw it away (setManaged(false) ?) )
         	 */
         	if(spv.getFixedRows().contains(row)){//row <= spv.getFixedRows().size()){
 	        	boolean flag = false;
 	                    }
 	            }
 	        	if(!flag){
-	        		getTableRow().setManaged(false);
-	        		return;
+	        		//FIXME Still problem when de-fixing at the top
+	        		flag = false;
+	            	for (int j = 0; j< gvs.getCellsSize();j++ ) {
+	                    if(gvs.getRow(j).getIndex() == row){
+	                    	flag = true;
+	                    }
+	            	}
+	            	if(flag){
+//		        		System.out.println("non!");
+		        		getTableRow().setManaged(false);
+		        		return;
+	            	}
 	        	}
         	}
         	

File src/main/java/impl/org/controlsfx/spreadsheet/GridRow.java

      */
     private int indexVirtualFlow = -1;
     private boolean layoutFixedColumns = false;
-    private boolean currentlyFixed = false;
+//    private boolean currentlyFixed = false;
 
     /***************************************************************************
      *                                                                         *
         indexVirtualFlow = i;
     }
 
-    public Boolean getCurrentlyFixed() {
+    /*public Boolean getCurrentlyFixed() {
 		return currentlyFixed;
 	}
 
-	/**
+	*//**
 	 * Indicate that this row is bonded on the top.
 	 * @param currentlyFixed
-	 */
+	 *//*
 	public void setCurrentlyFixed(boolean currentlyFixed) {
 		this.currentlyFixed = currentlyFixed;
-	}
+	}*/
 	
     /**
      * For the fixed columns in order to just re-layout the fixed columns
         return null;
     }
 
+    @Override protected double computePrefHeight(double width) { 
+    	return handle.getView().getGrid().getRowHeight(getIndex());
+    }
+    
     @Override
     protected Skin<?> createDefaultSkin() {
         return new GridRowSkin(handle, this);

File src/main/java/impl/org/controlsfx/spreadsheet/GridRowSkin.java

 import org.controlsfx.control.spreadsheet.SpreadsheetCell;
 import org.controlsfx.control.spreadsheet.SpreadsheetView;
 
+
 import com.sun.javafx.scene.control.skin.TableRowSkin;
 
 public class GridRowSkin extends TableRowSkin<ObservableList<SpreadsheetCell>> {
     }
 
     /**
+     * FIXME Look into and understand the deep cause of that
      * We need to override this since B105 because it's messing up our
      * fixedRows and also our rows CSS.. (kind of flicker)
      */
          */
         double tableCellY = 0;
         int positionY = spreadsheetView.getFixedRows().indexOf(index);
+        
+        //FIXME Integrate if fixedCellSize is enabled
+        //Computing how much space we need to translate
+        //because each row has different space.
+        double space = 0;
+        for(int o = 0;o< positionY; ++o){
+        	space += getTableRowHeight(spreadsheetView.getFixedRows().get(o));
+        }
+        
+        
         //If true, this row is fixed
-        if (positionY != -1 && getSkinnable().getLocalToParentTransform().getTy() <= positionY * GridViewSkin.DEFAULT_CELL_HEIGHT) {
+        if (positionY != -1 && getSkinnable().getLocalToParentTransform().getTy() <= space){//positionY * GridViewSkin.DEFAULT_CELL_HEIGHT) {
         	//This row is a bit hidden on top so we translate then for it to be fully visible
-            tableCellY = positionY * GridViewSkin.DEFAULT_CELL_HEIGHT
+            tableCellY = space//positionY * GridViewSkin.DEFAULT_CELL_HEIGHT
                     - getSkinnable().getLocalToParentTransform().getTy();
-            ((GridRow)getSkinnable()).setCurrentlyFixed(true);
-        }else{
+//            ((GridRow)getSkinnable()).setCurrentlyFixed(true);
+        }/*else{
         	((GridRow)getSkinnable()).setCurrentlyFixed(false);
-        }
+        }*/
         /**
          * We want to insert the removed tableCell in their correct position
          * because otherwise we have some glitch with the fixed columns when
                         // to the height variable
                         for (int i = 1; i < cellSpan.getRowSpan(); i++) {
                             // calculate the height
-                            final double rowHeight = GridViewSkin.DEFAULT_CELL_HEIGHT;// getTableRowHeight(index
-                                                                       // + i,
-                                                                       // getSkinnable());
+                            final double rowHeight = getTableRowHeight(index+ i);//GridViewSkin.DEFAULT_CELL_HEIGHT;// 
                             height += snapSize(rowHeight);
                         }
                     }
 
                 tableCell.resize(width, height);
                 // We want to place the layout always at the starting cell.
-                final double spaceBetweenTopAndMe = (index - cellSpan.getRow())
-                        * GridViewSkin.DEFAULT_CELL_HEIGHT;
+                //FIXME I don't understand why this is working.. Investigation will be done.
+                double spaceBetweenTopAndMe = (index - cellSpan.getRow())
+                 * GridViewSkin.DEFAULT_CELL_HEIGHT;
+               /* for(int p=cellSpan.getRow();p<index;++p){
+                	spaceBetweenTopAndMe+= getTableRowHeight(p);
+                }*/
+                		
                 tableCell.relocate(x + tableCellX, snappedTopInset()
                         - spaceBetweenTopAndMe + tableCellY);
 
     }
 
     /**
+     * Return the height of a row.
+     * @param i
+     * @return
+     */
+    private double getTableRowHeight(int i) {
+    	return handle.getView().getGrid().getRowHeight(i);
+	}
+
+	/**
      * Return true if the current cell is part of the sceneGraph.
      * 
      * @param x beginning of the cell

File src/main/java/impl/org/controlsfx/spreadsheet/GridViewSkin.java

 import javafx.geometry.HPos;
 import javafx.geometry.VPos;
 import javafx.scene.Node;
-import javafx.scene.control.Skin;
 import javafx.scene.control.TableCell;
 import javafx.scene.control.TableColumn;
 import javafx.scene.control.TableColumnBase;
 import org.controlsfx.control.spreadsheet.SpreadsheetColumn;
 import org.controlsfx.control.spreadsheet.SpreadsheetView;
 
-import com.sun.javafx.scene.control.skin.TableCellSkin;
 import com.sun.javafx.scene.control.skin.TableHeaderRow;
 import com.sun.javafx.scene.control.skin.TableViewSkin;
 import com.sun.javafx.scene.control.skin.VirtualFlow;
         }
         DEFAULT_CELL_HEIGHT = cell_size;
     }
+    
+    //FIXME This is not normal
     /** Default with of a "row header?". */
     private final double DEFAULT_ROWHEADER_WIDTH = 50.0;
     /** The editor. */
             }
         });
 
-        tableView.setFixedCellSize(getDefaultCellSize());
+//        tableView.setFixedCellSize(getDefaultCellSize());
 
         tableView.getStyleClass().add("cell-spreadsheet");
 

File src/main/java/impl/org/controlsfx/spreadsheet/GridVirtualFlow.java

  */
 package impl.org.controlsfx.spreadsheet;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
      * few cells in the addLeadingCell We need to add the remaining in the
      * addTrailingCell
      */
-    private int cellFixedAdded = 0;
+//    private int cellFixedAdded = 0;
     private boolean cellIndexCall = false;
 
     /**
         getVbar().valueProperty().addListener(listenerY);
         // FIXME Until RT-31777 is resolved
         getHbar().setUnitIncrement(10);
-
     }
 
     /***************************************************************************
     }
 
     protected T getAvailableCell(int prefIndex) {
-        cellIndexCall = true;
-        T tmp = super.getAvailableCell(prefIndex);
-        return tmp;
+	        cellIndexCall = true;
+	        T tmp = super.getAvailableCell(prefIndex);
+	        return tmp;
     }
 
     /**
         }
     }
 
-    @Override
+    /*@Override
     protected void addLeadingCells(int currentIndex, double startOffset) {
         addLeadingCells(new Helper<T>(this), currentIndex, startOffset);
     }
 
     private void addLeadingCells(Helper<T> ch, int currentIndex,
             double startOffset) {
+    	
+    	
+    	
         // The offset will keep track of the distance from the top of the
         // viewport to the top of the current index. We will increment it
         // as we lay out leading cells.
         // The index is the absolute index of the cell being laid out
         int index = currentIndex;
         
+        
+//        offset += spreadSheetView.getGrid().getRowHeight(index);
         // Offset should really be the bottom of the current index
         boolean first = true; // first time in, we just fudge the offset and let
         // it be the top of the current index then redefine
         // cells. If the offset is ever < 0, except in the case of the very
         // first cell, then we must quit.
         T cell = null;
-
+        
+//        cell = getAvailableCell(index);
+//        setCellIndex(cell, index);
+        
+        
+        cellFixedAdded = 0;
+        int numberOfCellsBelowIndex = 0;
+        boolean flag = false; // We only want to compute once
         // First pass to know how many cells we will add
         int cellToAdd = 0;
+        
+//        double myOffset = offset;
+//        while(numberOfCellsBelowIndex < spreadSheetView.getFixedRows().size()){
+//    		myOffset+=spreadSheetView.getGrid().getRowHeight(numberOfCellsBelowIndex);
+//    		++numberOfCellsBelowIndex;
+//        }
+        
+
         while (index >= 0 && (offset > 0 || first)) {
             if (first) {
                 first = false;
+                --index;
             } else {
-                // Careful here because I've seen that it could mess things up a
-                // bit
-                // Maybe use directly "fixedCellSize" if we're sure..
-                offset -= getCellLength(0);
+            	if(numberOfCellsBelowIndex < spreadSheetView.getFixedRows().size()){
+            		offset-=spreadSheetView.getGrid().getRowHeight(numberOfCellsBelowIndex);
+            		++numberOfCellsBelowIndex;
+            	}else{
+            		// Careful here because I've seen that it could mess things up a
+                    // bit
+                    // Maybe use directly "fixedCellSize" if we're sure..
+                    offset -= spreadSheetView.getGrid().getRowHeight(index);//getCellLength(0);
+                    --index;
+            	}
             }
-            --index;
+//            --index;
             ++cellToAdd;
         }
-
+        if(numberOfCellsBelowIndex  == spreadSheetView.getFixedRows().size())
+        	numberOfCellsBelowIndex--;
+        
+        System.out.println("celltoadd "+ cellToAdd);
+        
         // Now that we know how many cells we will add, we reset the variable
         offset = startOffset;
         index = currentIndex;
         first = true;
         cellFixedAdded = 0;
-        int numberOfCellsBelowIndex = 0;
-        boolean flag = false; // We only want to compute once
+//        numberOfCellsBelowIndex = 0;
+        flag = false; // We only want to compute once
         
-        while (index >= 0 && (offset > 0 || first)) {
+        while (index >= 0 && (offset > 0 || first)) {//cellToAdd >0){//index >= 0 && (offset > 0 || first)) {
             if (index >= getCellCount()) {
                 if (first) {
                     first = false;
                 --index;
                 --cellToAdd;
             } else {
+            	*//**
+            	 * We now try to determine if the current index is superior of any
+            	 * index of our FixedRows. If so, we compute how many FixedRow index 
+            	 * are below the current index.
+            	 *//*
+            	//Si mon index devient plus grand ou �gal qu'une ligne que je dois fixer
             	if(!flag && !getFixedRows().isEmpty() && index>=getFixedRows().get(cellFixedAdded)){
             		flag = true;
             		while(numberOfCellsBelowIndex < getFixedRows().size() && index >= getFixedRows().get(numberOfCellsBelowIndex) && numberOfCellsBelowIndex < cellToAdd){
             	
                 // If the number of remaining cells to add is the same of the fixedRows size
                 if (!getFixedRows().isEmpty() && cellToAdd <= getFixedRows().size()) {
-                	/**
-                	 * We now try to determine if the current index is superior of any
-                	 * index of our FixedRows. If so, we compute how many FixedRow index 
-                	 * are below the current index.
-                	 */
                 	
-                	if(flag && cellToAdd<= (numberOfCellsBelowIndex+1)){
+                	if(flag && numberOfCellsBelowIndex >=0 && cellToAdd<= (numberOfCellsBelowIndex+1)){
                 		
 	                    final int realIndex = getFixedRows().get(numberOfCellsBelowIndex);
 	                    cell = getAvailableCell(realIndex); // We grab the right one
                     cell = getAvailableCell(index);
                     setCellIndex(cell, index);
                 }
+            	
+                // If the remaining cells to add are in the header
+
+//                if (!getFixedRows().isEmpty() && cellToAdd <= getFixedRows().size()) {
+//                    final int realIndex = getFixedRows().get(numberOfCellsBelowIndex);
+//                    // System.out.println("JaddC"+realIndex+"/"+index);
+//                    cell = getAvailableCell(realIndex); // We grab the right one
+//                    setCellIndex(cell, realIndex); // the index is the real one
+//                    setCellIndexVirtualFlow(cell, index); // But the index for
+//                                                          // the Virtual Flow
+//                                                          // remain his (not the
+//                                                          // real one)
+//                    --numberOfCellsBelowIndex;
+//                    ++cellFixedAdded;
+//                } else {
+                    // System.out.println("JaddC"+index);
+            	if(index < spreadSheetView.getFixedRows().size()){
+            		bitSet.set(index, true);
+            	}
+                    cell = getAvailableCell(index);
+                    setCellIndex(cell, index);
+//                }
+//                System.out.println("je mets "+cell.getIndex());
                 resizeCellSize(cell); // resize must be after config
-                ch.addFirst(cell);
+//                if(index >= spreadSheetView.getFixedRows().size())
+                	ch.addFirst(cell);
+
 
                 // A little gross but better than alternatives because it
                 // reduces
                 --cellToAdd;
             }
         }
+        
 
         // There are times when after laying out the cells we discover that
         // the top of the first cell which represents index 0 is below the top
                 offset += getCellLength(cell);
             }
         }
+        
+    }
+    @Override
+    protected double getCellLength(T cell) {
+        if (cell == null) return 0;
+
+        return spreadSheetView.getGrid().getRowHeight(cell.getIndex());
+    }
+    
+    @Override
+    protected void resizeCellSize(T cell) {
+        if (cell == null) return;
+        
+        double width = cell.getWidth();
+        cell.resize(width, spreadSheetView.getGrid().getRowHeight(cell.getIndex()));
     }
 
     @Override
                 if (!fillEmptyCells) { return filledWithNonEmpty; }
             }
             T cell = null;
-            /**
+            *//**
              * If we have a lot of rows in header, we need to add the remaining
              * in the trailingCells. I Added fillEmptyCells because it appears 
              * that when AddtrailingCells is called from adjustPixel,
              * we add several time the rows in fixedHeader...
-             */
+             *//*
             if (!getFixedRows().isEmpty() && cellFixedAdded < getFixedRows().size()
                     && fillEmptyCells ) {
             	if(index>=getFixedRows().get(cellFixedAdded)){
                 // System.out.println("JaddD"+index);
                 cell = getAvailableCell(index);
                 setCellIndex(cell, index);
-            }
+//            }
             resizeCellSize(cell); // resize happens after config!
             ch.addLast(cell);
 
             }
 
         }
+        
+        return filledWithNonEmpty;
+    }*/
 
-        return filledWithNonEmpty;
-    }
-
-    protected void setCellIndex(T cell, int index) {
+   /* protected void setCellIndex(T cell, int index) {
         super.setCellIndex(cell, index);
         setCellIndexVirtualFlow(cell, index);
     }
 
-    /***************************************************************************
+    *//***************************************************************************
      * * Private Methods * *
-     **************************************************************************/
+     **************************************************************************//*
 
     private void setCellIndexVirtualFlow(T cell, int index) {
         if (cell == null) { return; }
 
         ((GridRow) cell).setIndexVirtualFlow(index);
-    }
+    }*/
 
     /**
      * Layout the fixed rows to position them correctly
      */
     private void layoutFixedRows() {
         sortRows();
-        if (!getCells().isEmpty() && !getFixedRows().isEmpty()) {
+       /* if (!getCells().isEmpty() && !getFixedRows().isEmpty()) {
             for (int i = getFixedRows().size() - 1; i >= 0; --i) {
                 GridRow cell = (GridRow) getCells().get(i);
                 if (cell != null && getFixedRows().contains(cell.getIndex())) {
                     cell.requestLayout();
                 }
             }
+        }*/
+        /**
+         * What I do is just going after the VirtualFlow in order to ADD
+         * (not replace like before) new rows at the top.
+         * 
+         * If the VirtualFlow has the row, then I will hide mine and let
+         * him handle. But if the row is missing, then I must show mine
+         * in order to have the fixed row.
+         *FIXME we can find a better solution instead of going 
+         *through all the rows of the VirtualFlow of course.
+         */
+        if(myCells.size() <spreadSheetView.getFixedRows().size()  && getFirstVisibleCellWithinViewPort() != null){
+        	 T cell = null;
+// 	            Helper ch = new Helper<T>(this);
+// 	            double offset = 0;
+ 	            for(Integer i :spreadSheetView.getFixedRows()){
+ 	            	boolean flag = true;
+ 	            	for(T cell2:getCells()){
+ 	            		if(cell2.getIndex() == i){
+ 	            			flag = false;
+ 	            			cell2.toFront();
+ 	            		}
+ 	            	}
+ 	            	if(flag && myCells.size() <= i){
+ 	            	cell = getAvailableCell(i);
+ 	            	setCellIndex(cell, i); 
+// 	                setCellIndexVirtualFlow(cell, fakeIndex);
+// 	                fakeIndex++;
+ 	                resizeCellSize(cell);
+// 	                ch.addLast(cell);
+// 	                positionCell(cell, offset);
+ 	                cell.setVisible(true);
+// 	                offset+=getCellLength(cell);
+ 	                cell.toFront();
+ 	                myCells.add(cell);
+// 	                cell.requestLayout();
+ 	            	}
+ 	            }
         }
+    	for(T cell:myCells){
+    		boolean flag = true;
+        	for(T cell2:getCells()){
+        		if(cell2.getIndex() == cell.getIndex()){
+        			flag = false;
+        			cell2.toFront();
+        		}
+        	}
+        	if(flag){
+        		cell.setVisible(true);
+//	        		setCellIndexVirtualFlow(cell, fakeIndex);
+        		cell.toFront();
+        		cell.requestLayout();
+        	}else{
+        		cell.setVisible(false);
+        	}
+    	}
     }
 
+    private ArrayList<T> myCells = new ArrayList<>();
+    
     /**
      * Sort the rows so that they stay in order for layout
      */
 /**
  * Helper class to workaround RT-31692
  */
-class Helper<T extends IndexedCell<?>> {
+/*class Helper<T extends IndexedCell<?>> {
     Object cells;
     static Field fcells;
     static Method getFirst;
             e.printStackTrace();
         }
     }
-}
+    
+}*/

File src/main/java/impl/org/controlsfx/spreadsheet/VerticalHeader.java

 				}else{
 					label.setText(String.valueOf(row.getIndexVirtualFlow() + 1)+" ");
 				}
-				label.resize(prefWidth, prefHeight);
+				label.resize(prefWidth, spreadsheetView.getGrid().getRowHeight(row.getIndexVirtualFlow()));
 				label.relocate(x, y);
 				label.setContextMenu(getRowContextMenu(row
 						.getIndexVirtualFlow()));
 				} else {
 					css.removeAll("fixed");
 				}
-				y += prefHeight;
+				y += spreadsheetView.getGrid().getRowHeight(row.getIndexVirtualFlow());
 				++i;
 			}
-
+			
+			double spaceUsedByFixedRows = 0;
 			// Then we iterate over the FixedRows if any
 			if (!spreadsheetView.getFixedRows().isEmpty() && cellSize != 0) {
 				for (i = 0; i < spreadsheetView.getFixedRows().size(); ++i) {
-					if (skin.getCell(i).getCurrentlyFixed()) {
+//					if (skin.getCell(i).getCurrentlyFixed()) {
 						label = getLabel(rowCount++);
 						label.setText(String.valueOf(spreadsheetView
 								.getFixedRows().get(i) + 1)+":");
-						label.resize(prefWidth, prefHeight);
+						label.resize(prefWidth, spreadsheetView.getGrid().getRowHeight(spreadsheetView
+								.getFixedRows().get(i)));
 						label.setContextMenu(getRowContextMenu(spreadsheetView
 								.getFixedRows().get(i)));
 						// If the columnHeader is here, we need to translate a
 						// bit
 						if (spreadsheetView.showColumnHeaderProperty().get()) {
 							label.relocate(x, snappedTopInset() + prefHeight
-									* (i + 1));
+									+spaceUsedByFixedRows);
 						} else {
-							label.relocate(x, snappedTopInset() + prefHeight
-									* i);
+							label.relocate(x, snappedTopInset() + spaceUsedByFixedRows);
 						}
 						final ObservableList<String> css = label
 								.getStyleClass();
 							css.removeAll("selected");
 						}
 						css.addAll("fixed");
-						y += prefHeight;
-					}
+						spaceUsedByFixedRows+=spreadsheetView.getGrid().getRowHeight(spreadsheetView
+								.getFixedRows().get(i));
+						y += spreadsheetView.getGrid().getRowHeight(spreadsheetView
+								.getFixedRows().get(i));
+//					}
 				}
 			}
 
 						public void changed(
 								ObservableValue<? extends Boolean> arg0,
 								Boolean arg1, Boolean arg2) {
-
+							
 							if (spreadsheetView.getFixedRows().contains(i)) {
-								spreadsheetView.getFixedRows().remove(i);
+								spreadsheetView.getFixedRows().clear();
+								
+								for(int j=0;j<= i-1;++j){
+									spreadsheetView.getFixedRows().add(j);
+								}
 							} else {
-								spreadsheetView.getFixedRows().add(i);
+								spreadsheetView.getFixedRows().clear();
+								
+								for(int j=0;j<= i;++j){
+									spreadsheetView.getFixedRows().add(j);
+								}
 							}
 							// We MUST have the fixed rows sorted!
 							FXCollections.sort(spreadsheetView.getFixedRows());

File src/main/java/org/controlsfx/control/spreadsheet/Grid.java

      * Return the {@link SpanType} for a given cell row/column intersection.
      */
     public SpanType getSpanType(final SpreadsheetView spv, final int row, final int column);
+    
+    /**
+     * Return the height of a row.
+     * @param row
+     * @return
+     */
+    public double getRowHeight(int row);
 }

File src/main/java/org/controlsfx/control/spreadsheet/GridBase.java

 import impl.org.controlsfx.spreadsheet.GridViewSkin;
 
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
     private ObservableList<ObservableList<SpreadsheetCell>> rows;
     private int rowCount;
     private int columnCount;
+    private Map<Integer,Double> rowHeight;
     
     
 
      * Creates a grid with a fixed number of rows and columns.
      */
     public GridBase(int rowCount, int columnCount) {
-        this(rowCount, columnCount,FXCollections.<ObservableList<SpreadsheetCell>> emptyObservableList());
+        this(rowCount, columnCount,FXCollections.<ObservableList<SpreadsheetCell>> emptyObservableList(), new HashMap<Integer,Double>());
     }
 
-    public GridBase(int rowCount, int columnCount, ObservableList<ObservableList<SpreadsheetCell>> rows) {
+    public GridBase(int rowCount, int columnCount,  Map<Integer,Double> rowHeight) {
+        this(rowCount, columnCount,FXCollections.<ObservableList<SpreadsheetCell>> emptyObservableList(), rowHeight);
+    }
+    
+    public GridBase(int rowCount, int columnCount, ObservableList<ObservableList<SpreadsheetCell>> rows, Map<Integer,Double> rowHeight) {
         this.rowCount = rowCount;
         this.columnCount = columnCount;
         this.rows = rows;
+        this.rowHeight = rowHeight;
     }
 
-    
-    
     /***************************************************************************
      * 
      * Public Methods (Inherited from Grid) 
         }
     }
     
-    
+    @Override
+    public double getRowHeight(int i){
+    	Double value = rowHeight.get((Integer)i);
+    	//FIXME We must use a variable here instead
+    	return value == null? 24.0:value;
+    }
     
     /***************************************************************************
      * 

File src/main/java/org/controlsfx/control/spreadsheet/SpreadsheetView.java

 import javafx.animation.Timeline;
 import javafx.application.Platform;
 import javafx.beans.property.BooleanProperty;
-import javafx.beans.property.ReadOnlyBooleanProperty;
 import javafx.beans.property.ReadOnlyObjectWrapper;
 import javafx.beans.property.SimpleBooleanProperty;
 import javafx.beans.value.ChangeListener;
     private void initRowFix(Grid grid){
     	ObservableList< ObservableList<SpreadsheetCell>> rows = grid.getRows();
 		rowFix = new BitSet(rows.size());
-		rows : for(int r = 0; r < rows.size(); ++r){
+		/*rows :*/ for(int r = 0; r < rows.size(); ++r){
 			ObservableList<SpreadsheetCell> row = rows.get(r);
 			for(SpreadsheetCell cell: row){
 				if(cell.getRowSpan() >1){
-					continue rows;
+					return;
+//					continue rows;
 				}
 			}
 			rowFix.set(r);

File src/samples/java/org/controlsfx/samples/HelloSpreadsheetView.java

 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import javafx.application.Application;
 import javafx.beans.value.ChangeListener;
 		
 		int rowCount = 50;
 		int columnCount = 10;
-		GridBase grid = new GridBase(rowCount, columnCount);
+		
+		GridBase grid = new GridBase(rowCount, columnCount, generateRowHeight());
 		normalGrid(grid);
 		buildBothGrid(grid);
 
 	}
 	
 	/**
+	 * FIXME need to be removed afetr
+	 * Compute RowHeight for test
+	 * @return
+	 */
+	private Map<Integer,Double> generateRowHeight(){
+		Map<Integer,Double> rowHeight = new HashMap<>();
+		rowHeight.put(0, 50.0);
+		rowHeight.put(5, 50.0);
+		rowHeight.put(8, 70.0);
+		rowHeight.put(12, 40.0);
+		return rowHeight;
+	}
+	/**
 	 * Build a common control Grid with some options on the left to control the
 	 * SpreadsheetViewInternal
 	 * @param gridType 
 				if(arg2.equals(0)){
 					int rowCount = 50;
 					int columnCount = 10;
-					GridBase grid = new GridBase(rowCount, columnCount);
+					GridBase grid = new GridBase(rowCount, columnCount, generateRowHeight());
 					normalGrid(grid);
 					
 					SpreadsheetView spreadSheetView = new SpreadsheetView(grid);
 				}else{
 					int rowCount = 50;
 					int columnCount = 10;
-					GridBase grid = new GridBase(rowCount, columnCount);
+					GridBase grid = new GridBase(rowCount, columnCount, generateRowHeight());
 					normalGrid(grid);
 					buildBothGrid(grid);