NatTable混合固定宽度列和可调整大小的填充剩余空间

时间:2017-05-11 12:36:43

标签: java swt nattable 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? 我是在正确的轨道上吗?

2 个答案:

答案 0 :(得分: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;
    }
}

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

答案 1 :(得分:0)

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

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