如何冻结 SWT NatTable 中的可见列
How do I freeze only visible columns in SWT NatTable
我目前有 column/row 冻结工作,我可以右键单击 column/row header,然后单击 'freeze',它将冻结列 I单击左侧的所有列。问题是,如果我向右滚动,然后单击列索引 20(实际上是隐藏左侧索引的任何索引),它将冻结该索引下方的所有列,这会导致 table 快速返回到索引 0,并且不允许我滚动(因为比显示更多的列被冻结)。如何只冻结我单击的列左侧的 VISIBLE 列?我遇到了 IFreezeCoordinatesProvider 并试图用它做一些厚颜无耻的事情但无济于事。下面是我创建右键菜单的自定义配置,其中包含冻结命令。非常感谢任何帮助!
public class ColumnHeaderRightClickConfiguration extends AbstractUiBindingConfiguration{
private final ViewportLayer viewportLayer;
private final CompositeFreezeLayer freezeLayer;
private Menu rightClickMenu;
private int localColumnIndex;
private int columnIndex;
private FreezeColumnCommand freezeCommand;
public ColumnHeaderRightClickConfiguration(final NatTable natTable, ViewportLayer viewportLayer, CompositeFreezeLayer freezeLayer){
this.viewportLayer = viewportLayer;
this.freezeLayer = freezeLayer;
this.rightClickMenu = createRightClickMenu(natTable).build();
natTable.addDisposeListener(new DisposeListener(){
@Override
public void widgetDisposed(DisposeEvent e) {
rightClickMenu.dispose();
}
});
}
private PopupMenuBuilder createRightClickMenu(NatTable natTable){
Menu menu = new Menu(natTable);
MenuItem freezeLeft = new MenuItem(menu, SWT.NONE);
freezeLeft.setText("Freeze");
MenuItem unfreeze = new MenuItem(menu, SWT.NONE);
unfreeze.setText("Unfreeze");
unfreeze.setEnabled(false);
freezeLeft.addSelectionListener(new SelectionListener(){
@Override
public void widgetSelected(SelectionEvent e) {
System.out.println(columnIndex);
freezeCommand = new FreezeColumnCommand(freezeLayer, columnIndex-1, true);
natTable.doCommand(freezeCommand);
freezeLeft.setEnabled(false);
unfreeze.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e){}
});
unfreeze.addSelectionListener(new SelectionListener(){
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(freezeCommand);
unfreeze.setEnabled(false);
freezeLeft.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
});
return new PopupMenuBuilder(natTable, menu);
}
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
MouseEventMatcher matcher = new MouseEventMatcher(SWT.NONE, GridRegion.COLUMN_HEADER, MouseEventMatcher.RIGHT_BUTTON){
@Override
public boolean matches(NatTable natTable, MouseEvent event, LabelStack regionLabels){
if (super.matches(natTable, event, regionLabels)){
localColumnIndex = natTable.getColumnPositionByX(event.x);
columnIndex = viewportLayer.localToUnderlyingColumnPosition(localColumnIndex);
return true;
}else{
return false;
}
}
};
uiBindingRegistry.registerMouseDownBinding(matcher, new ColumnPopupMenuAction(rightClickMenu));
}
}
目前 FreezeColumnCommand
不支持请求的功能。只有 FreezeSelectionCommand
能够通过移动视口外不可见的左侧列来执行冻结操作。原因是相应的 FreezeColumnStrategy
在计算冻结坐标时没有考虑当前视口状态。这肯定是 NatTable 中需要解决的问题,我为此创建了一张票:https://bugs.eclipse.org/bugs/show_bug.cgi?id=504489
在 NatTable 中修复此问题之前,您可以直接使用 FreezeHelper
。这会将冻结的内部计算和处理暴露到您的代码中,这通常应该避免,但现在这将是一种解决方法。
此外,您的菜单配置不符合 NatTable 准则。您正在做的很多事情不适合,例如创建您自己的菜单,但使用 PopupMenuBuilder。下面是适用于 NatTable 1.4 的代码。
public class ColumnHeaderRightClickConfiguration extends AbstractUiBindingConfiguration {
private Menu rightClickMenu;
private boolean frozen = false;
public ColumnHeaderRightClickConfiguration(
NatTable natTable,
CompositeFreezeLayer compositeFreezeLayer,
FreezeLayer freezeLayer,
ViewportLayer viewportLayer,
SelectionLayer selectionLayer) {
this.rightClickMenu = new PopupMenuBuilder(natTable)
.withMenuItemProvider("freeze", new IMenuItemProvider() {
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem freezeLeft = new MenuItem(popupMenu, SWT.NONE);
freezeLeft.setText("Freeze");
freezeLeft.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
int columnPosition = MenuItemProviders.getNatEventData(event).getColumnPosition();
int pos = LayerUtil.convertColumnPosition(natTable, columnPosition, selectionLayer);
// this should be the solution
// if (compositeFreezeLayer.doCommand(new FreezeColumnCommand(compositeFreezeLayer, pos, true))) {
// ColumnHeaderRightClickConfiguration.this.frozen = true;
// }
int coordCol = 0;
coordCol = viewportLayer.getScrollableLayer()
.getColumnPositionByX(viewportLayer.getOrigin().getX());
if (coordCol > 0
&& coordCol >= pos) {
coordCol = pos;
}
PositionCoordinate topLeftPosition = new PositionCoordinate(freezeLayer, coordCol, -1);
PositionCoordinate bottomRightPosition = new PositionCoordinate(freezeLayer, pos, -1);
FreezeHelper.freeze(freezeLayer, viewportLayer, topLeftPosition, bottomRightPosition);
ColumnHeaderRightClickConfiguration.this.frozen = true;
}
});
}
})
.withMenuItemProvider("unfreeze", new IMenuItemProvider() {
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem unfreeze = new MenuItem(popupMenu, SWT.NONE);
unfreeze.setText("Unfreeze");
unfreeze.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
natTable.doCommand(new UnFreezeGridCommand());
ColumnHeaderRightClickConfiguration.this.frozen = false;
}
});
}
})
.withEnabledState("freeze", new IMenuItemState() {
@Override
public boolean isActive(NatEventData natEventData) {
return !ColumnHeaderRightClickConfiguration.this.frozen;
}
})
.withEnabledState("unfreeze", new IMenuItemState() {
@Override
public boolean isActive(NatEventData natEventData) {
return ColumnHeaderRightClickConfiguration.this.frozen;
}
})
.build();
natTable.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
ColumnHeaderRightClickConfiguration.this.rightClickMenu.dispose();
}
});
}
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
MouseEventMatcher matcher = new MouseEventMatcher(
SWT.NONE,
GridRegion.COLUMN_HEADER,
MouseEventMatcher.RIGHT_BUTTON);
uiBindingRegistry.registerMouseDownBinding(
matcher,
new PopupMenuAction(this.rightClickMenu));
}
}
我目前有 column/row 冻结工作,我可以右键单击 column/row header,然后单击 'freeze',它将冻结列 I单击左侧的所有列。问题是,如果我向右滚动,然后单击列索引 20(实际上是隐藏左侧索引的任何索引),它将冻结该索引下方的所有列,这会导致 table 快速返回到索引 0,并且不允许我滚动(因为比显示更多的列被冻结)。如何只冻结我单击的列左侧的 VISIBLE 列?我遇到了 IFreezeCoordinatesProvider 并试图用它做一些厚颜无耻的事情但无济于事。下面是我创建右键菜单的自定义配置,其中包含冻结命令。非常感谢任何帮助!
public class ColumnHeaderRightClickConfiguration extends AbstractUiBindingConfiguration{
private final ViewportLayer viewportLayer;
private final CompositeFreezeLayer freezeLayer;
private Menu rightClickMenu;
private int localColumnIndex;
private int columnIndex;
private FreezeColumnCommand freezeCommand;
public ColumnHeaderRightClickConfiguration(final NatTable natTable, ViewportLayer viewportLayer, CompositeFreezeLayer freezeLayer){
this.viewportLayer = viewportLayer;
this.freezeLayer = freezeLayer;
this.rightClickMenu = createRightClickMenu(natTable).build();
natTable.addDisposeListener(new DisposeListener(){
@Override
public void widgetDisposed(DisposeEvent e) {
rightClickMenu.dispose();
}
});
}
private PopupMenuBuilder createRightClickMenu(NatTable natTable){
Menu menu = new Menu(natTable);
MenuItem freezeLeft = new MenuItem(menu, SWT.NONE);
freezeLeft.setText("Freeze");
MenuItem unfreeze = new MenuItem(menu, SWT.NONE);
unfreeze.setText("Unfreeze");
unfreeze.setEnabled(false);
freezeLeft.addSelectionListener(new SelectionListener(){
@Override
public void widgetSelected(SelectionEvent e) {
System.out.println(columnIndex);
freezeCommand = new FreezeColumnCommand(freezeLayer, columnIndex-1, true);
natTable.doCommand(freezeCommand);
freezeLeft.setEnabled(false);
unfreeze.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e){}
});
unfreeze.addSelectionListener(new SelectionListener(){
@Override
public void widgetSelected(SelectionEvent e) {
natTable.doCommand(freezeCommand);
unfreeze.setEnabled(false);
freezeLeft.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
});
return new PopupMenuBuilder(natTable, menu);
}
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
MouseEventMatcher matcher = new MouseEventMatcher(SWT.NONE, GridRegion.COLUMN_HEADER, MouseEventMatcher.RIGHT_BUTTON){
@Override
public boolean matches(NatTable natTable, MouseEvent event, LabelStack regionLabels){
if (super.matches(natTable, event, regionLabels)){
localColumnIndex = natTable.getColumnPositionByX(event.x);
columnIndex = viewportLayer.localToUnderlyingColumnPosition(localColumnIndex);
return true;
}else{
return false;
}
}
};
uiBindingRegistry.registerMouseDownBinding(matcher, new ColumnPopupMenuAction(rightClickMenu));
}
}
目前 FreezeColumnCommand
不支持请求的功能。只有 FreezeSelectionCommand
能够通过移动视口外不可见的左侧列来执行冻结操作。原因是相应的 FreezeColumnStrategy
在计算冻结坐标时没有考虑当前视口状态。这肯定是 NatTable 中需要解决的问题,我为此创建了一张票:https://bugs.eclipse.org/bugs/show_bug.cgi?id=504489
在 NatTable 中修复此问题之前,您可以直接使用 FreezeHelper
。这会将冻结的内部计算和处理暴露到您的代码中,这通常应该避免,但现在这将是一种解决方法。
此外,您的菜单配置不符合 NatTable 准则。您正在做的很多事情不适合,例如创建您自己的菜单,但使用 PopupMenuBuilder。下面是适用于 NatTable 1.4 的代码。
public class ColumnHeaderRightClickConfiguration extends AbstractUiBindingConfiguration {
private Menu rightClickMenu;
private boolean frozen = false;
public ColumnHeaderRightClickConfiguration(
NatTable natTable,
CompositeFreezeLayer compositeFreezeLayer,
FreezeLayer freezeLayer,
ViewportLayer viewportLayer,
SelectionLayer selectionLayer) {
this.rightClickMenu = new PopupMenuBuilder(natTable)
.withMenuItemProvider("freeze", new IMenuItemProvider() {
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem freezeLeft = new MenuItem(popupMenu, SWT.NONE);
freezeLeft.setText("Freeze");
freezeLeft.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
int columnPosition = MenuItemProviders.getNatEventData(event).getColumnPosition();
int pos = LayerUtil.convertColumnPosition(natTable, columnPosition, selectionLayer);
// this should be the solution
// if (compositeFreezeLayer.doCommand(new FreezeColumnCommand(compositeFreezeLayer, pos, true))) {
// ColumnHeaderRightClickConfiguration.this.frozen = true;
// }
int coordCol = 0;
coordCol = viewportLayer.getScrollableLayer()
.getColumnPositionByX(viewportLayer.getOrigin().getX());
if (coordCol > 0
&& coordCol >= pos) {
coordCol = pos;
}
PositionCoordinate topLeftPosition = new PositionCoordinate(freezeLayer, coordCol, -1);
PositionCoordinate bottomRightPosition = new PositionCoordinate(freezeLayer, pos, -1);
FreezeHelper.freeze(freezeLayer, viewportLayer, topLeftPosition, bottomRightPosition);
ColumnHeaderRightClickConfiguration.this.frozen = true;
}
});
}
})
.withMenuItemProvider("unfreeze", new IMenuItemProvider() {
@Override
public void addMenuItem(NatTable natTable, Menu popupMenu) {
MenuItem unfreeze = new MenuItem(popupMenu, SWT.NONE);
unfreeze.setText("Unfreeze");
unfreeze.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
natTable.doCommand(new UnFreezeGridCommand());
ColumnHeaderRightClickConfiguration.this.frozen = false;
}
});
}
})
.withEnabledState("freeze", new IMenuItemState() {
@Override
public boolean isActive(NatEventData natEventData) {
return !ColumnHeaderRightClickConfiguration.this.frozen;
}
})
.withEnabledState("unfreeze", new IMenuItemState() {
@Override
public boolean isActive(NatEventData natEventData) {
return ColumnHeaderRightClickConfiguration.this.frozen;
}
})
.build();
natTable.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
ColumnHeaderRightClickConfiguration.this.rightClickMenu.dispose();
}
});
}
@Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
MouseEventMatcher matcher = new MouseEventMatcher(
SWT.NONE,
GridRegion.COLUMN_HEADER,
MouseEventMatcher.RIGHT_BUTTON);
uiBindingRegistry.registerMouseDownBinding(
matcher,
new PopupMenuAction(this.rightClickMenu));
}
}