Bug 580670 - Tree collapse doesn't work with big spanning

Signed-off-by: Dirk Fauth <dirk.fauth@googlemail.com>

Change-Id: Ic0ff928a3be0c32fda9a3921ba3db2146b02ff12
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/hierarchical/command/HierarchicalTreeExpandCollapseCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/hierarchical/command/HierarchicalTreeExpandCollapseCommandHandler.java
index 7145c76..e56ccbc 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/hierarchical/command/HierarchicalTreeExpandCollapseCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/hierarchical/command/HierarchicalTreeExpandCollapseCommandHandler.java
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (c) 2018, 2020 Dirk Fauth.
+ * Copyright (c) 2018, 2022 Dirk Fauth.
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,7 @@
 
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
 import org.eclipse.nebula.widgets.nattable.hierarchical.HierarchicalTreeLayer;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.tree.command.TreeExpandCollapseCommand;
 
 /**
@@ -50,15 +51,30 @@
 
     @Override
     protected boolean doCommand(TreeExpandCollapseCommand command) {
+
+        int rowIndex = command.getParentIndex();
+        int columnIndex = command.getColumnIndex();
+
+        if (rowIndex < 0) {
+            // if the parent index is a negative value, the tree cell is a
+            // spanned cell whose origin row was scrolled out of the visible
+            // area, therefore we need to find the correct parent index now
+            int rowPos = this.treeLayer.getRowPositionByIndex(rowIndex * -1);
+            int colPos = this.treeLayer.getColumnPositionByIndex(columnIndex);
+
+            ILayerCell cell = this.treeLayer.getCellByPosition(colPos, rowPos);
+            rowIndex = this.treeLayer.getRowIndexByPosition(cell.getOriginRowPosition());
+        }
+
         if (command instanceof HierarchicalTreeExpandCollapseCommand) {
             this.treeLayer.expandOrCollapse(
-                    command.getColumnIndex(),
-                    command.getParentIndex(),
+                    columnIndex,
+                    rowIndex,
                     ((HierarchicalTreeExpandCollapseCommand) command).getToLevel());
         } else {
             this.treeLayer.expandOrCollapse(
-                    command.getColumnIndex(),
-                    command.getParentIndex());
+                    columnIndex,
+                    rowIndex);
         }
         return true;
     }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/action/TreeExpandCollapseAction.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/action/TreeExpandCollapseAction.java
index da7d484..67b614f 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/action/TreeExpandCollapseAction.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/action/TreeExpandCollapseAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2020 Original authors and others.
+ * Copyright (c) 2012, 2022 Original authors and others.
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0
@@ -36,6 +36,13 @@
         if (cell != null) {
             int rowIndex = cell.getLayer().getRowIndexByPosition(cell.getOriginRowPosition());
             int columnIndex = cell.getLayer().getColumnIndexByPosition(cell.getOriginColumnPosition());
+
+            if (cell.getOriginRowPosition() < 0) {
+                // if the origin row is not visible we will transport the index
+                // of the clicked row as negative value so the handler can react
+                rowIndex = cell.getLayer().getRowIndexByPosition(cell.getRowPosition()) * -1;
+            }
+
             TreeExpandCollapseCommand command = new TreeExpandCollapseCommand(rowIndex, columnIndex);
             natTable.doCommand(command);
         }
diff --git a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/command/TreeExpandCollapseCommandHandler.java b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/command/TreeExpandCollapseCommandHandler.java
index 99ead7f..61d2cd4 100644
--- a/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/command/TreeExpandCollapseCommandHandler.java
+++ b/org.eclipse.nebula.widgets.nattable.core/src/org/eclipse/nebula/widgets/nattable/tree/command/TreeExpandCollapseCommandHandler.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2020 Original authors and others.
+ * Copyright (c) 2012, 2022 Original authors and others.
  *
  * This program and the accompanying materials are made
  * available under the terms of the Eclipse Public License 2.0
@@ -13,6 +13,7 @@
 package org.eclipse.nebula.widgets.nattable.tree.command;
 
 import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
+import org.eclipse.nebula.widgets.nattable.layer.cell.ILayerCell;
 import org.eclipse.nebula.widgets.nattable.tree.TreeLayer;
 
 public class TreeExpandCollapseCommandHandler extends AbstractLayerCommandHandler<TreeExpandCollapseCommand> {
@@ -31,6 +32,18 @@
     @Override
     protected boolean doCommand(TreeExpandCollapseCommand command) {
         int parentIndex = command.getParentIndex();
+
+        if (command.getParentIndex() < 0) {
+            // if the parent index is a negative value, the tree cell is a
+            // spanned cell whose origin row was scrolled out of the visible
+            // area, therefore we need to find the correct parent index now
+            int rowPos = this.treeLayer.getRowPositionByIndex(command.getParentIndex() * -1);
+            int colPos = this.treeLayer.isUseTreeColumnIndex() ? this.treeLayer.getColumnPositionByIndex(0) : 0;
+
+            ILayerCell cell = this.treeLayer.getCellByPosition(colPos, rowPos);
+            parentIndex = this.treeLayer.getRowIndexByPosition(cell.getOriginRowPosition());
+        }
+
         this.treeLayer.expandOrCollapseIndex(parentIndex);
         return true;
     }