0

如何制作一个 Nebula NatTable,其中混合了固定列,剩下的一个填充了所有可用的垂直空间,并且至关重要的是,用户调整了固定宽度列的大小?

视觉示例:

+-----------------------------------------+-------+-------+
|     ...fills available vert space...    | 100px | 100px |

用户通过将第 0 列和第 1 列之间的边框向左推来调整中间列的大小:

+---------------------------------------+----------+-------+
|     ...fills available vert space...  |   120px  | 100px |

用户通过将第 1 列和第 2 列之间的边界向左推来调整第 3 列的大小:

+------------------------------------+----------+----------+
|   ...fills available vert space... |   120px  |   120px  |

我非常接近这段代码:

    IRowDataProvider<String> bodyDataProvider = ...;
    DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
    SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer, false);
    ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);

    bodyDataLayer.setColumnPercentageSizing(0, true);
    bodyDataLayer.setColumnPositionResizable(0, true);

    bodyDataLayer.setColumnWidthByPosition(1, 100);
    bodyDataLayer.setColumnPositionResizable(1, true);

    bodyDataLayer.setColumnWidthByPosition(2, 100);
    bodyDataLayer.setColumnPositionResizable(2, true);

它在视觉上做了预期的事情,它也会对容器(Shell)按预期调整大小作出反应;即固定列保持 100px,只有第一列调整大小。到目前为止很好。但是有一个问题:列间调整大小发生了一些不好的事情。我只是反应奇怪。在第 0 列和第 1 列之间调整大小处理程序(标题边框)不做任何事情,只出现调整大小但不执行调整大小;在第 1 列和第 2 列之间调整大小的处理程序会做出反应,但只有第 1 列可以有效地调整大小,第 2 列始终保持其大小,无论您做什么。

不良行为示例:您想调整第 2 列(第 3 列)的大小以使其更大;您抓住第 1 列和第 2 列之间的边界,将边界向左拖动,以便通过有效地将第 1 列也向左推来使第 2 列变大。但相反,第 2 列保持不变,而第 1 列缩小!

更新

我的问题是如何实现所需的行为。我需要在哪里设置或重新实现什么?定制SizeConfig? 那里的方法听起来很有希望:calculatePercentages()calculateAvailableSpace()。谁和什么时候打电话给他们?如何捕获列调整大小事件?我需要在某处设置监听器吗?我怎样才能让 NatTable 使用自定义的SizeConfig?我在正确的轨道上吗?

4

2 回答 2

1

我自己想通了。最后也没那么难。所要做的就是注册一个定制的ColumnResizeCommand处理程序并实现它。

向 NatTable 创建代码块添加:

bodyDataLayer.registerCommandHandler(
     new BetweenColumnResizeCommandHandler(bodyDataLayer));

它可以在任何地方,我在定义列之后就拥有它

这会覆盖在方法BodyDataLayer中设置为默认类的默认设置ColumnResizeCommandHandler。该寄存器是基于映射的,因此可以重复覆盖。寄存器将类命令类(表示事件)映射到给定层(事件/命令的终端消费者)的操作(处理程序)。

这是我的BetweenColumnResizeCommandHandler类的实现:

import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.resize.command.ColumnResizeCommand;
import org.eclipse.nebula.widgets.nattable.resize.command.ColumnResizeCommandHandler;

/**
 * Customised version of {@link ColumnResizeCommandHandler}.
 * 
 * It implements "between" resizing mode, that is border is moved between two
 * adjacent column only, having no effects on any other columns; that is any
 * gain in size of the left side column is lost in size for right side column
 * and vice versa.
 * 
 * @author Espinosa
 */
public class BetweenColumnResizeCommandHandler extends AbstractLayerCommandHandler<ColumnResizeCommand> {

    private final DataLayer dataLayer;

    public BetweenColumnResizeCommandHandler(DataLayer dataLayer) {
        this.dataLayer = dataLayer;
    }

    @Override
    public Class<ColumnResizeCommand> getCommandClass() {
        return ColumnResizeCommand.class;
    }

    @Override
    protected boolean doCommand(ColumnResizeCommand command) {
        int leftSideColumn = command.getColumnPosition();
        int rightSideColumn = leftSideColumn + 1;

        int oldLeftSideColumnWidth = this.dataLayer.getColumnWidthByPosition(leftSideColumn);
        int newLeftSideColumnWidth = command.getNewColumnWidth();
        int dragWidth = newLeftSideColumnWidth - oldLeftSideColumnWidth;  
        // dragWidth has to be re-calculated back because it is lost in ColumnResizeCommandHandler :( 

        int oldRightSideColumnWidth = this.dataLayer.getColumnWidthByPosition(rightSideColumn);
        int newRightSideColumnWidth = oldRightSideColumnWidth - dragWidth;

        this.dataLayer.setColumnWidthByPosition(leftSideColumn, newLeftSideColumnWidth);
        if (rightSideColumn < this.dataLayer.getColumnCount()) {
            this.dataLayer.setColumnWidthByPosition(rightSideColumn, newRightSideColumnWidth);
        }
        return true;
    }
}

..它完全符合我的要求,如上例所示。

于 2017-05-11T19:28:14.530 回答
0

你的问题是你试图从右到左思考。但是调整大小是从左到右实现的。因此,如果您采用第 1 列和第 2 列之间的边界,则您正在调整第 1 列的大小,而不是第 2 列。方向无关紧要。

这是与众所周知的电子表格应用程序类似的行为。使用边框之间的句柄会将列的大小调整到左侧,而不是右侧。

于 2017-05-11T12:44:22.753 回答