NatTable смесь столбца с фиксированной шириной и заполнением оставшегося пространства
Как создать Nebula NatTable со смесью фиксированных столбцов и одного оставшегося, заполняющего все доступное вертикальное пространство, и где, главное, размер столбца фиксированной ширины может быть изменен пользователем?
Визуальный пример:
+-----------------------------------------+-------+-------+
| ...fills available vert space... | 100px | 100px |
Пользователь меняет средний столбец, нажимая границу между столбцами 0 и 1 влево:
+---------------------------------------+----------+-------+
| ...fills available vert space... | 120px | 100px |
Пользователь изменяет размер 3-го столбца, выдвигая границу между столбцами 1 и 2 влево:
+------------------------------------+----------+----------+
| ...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, перетаскивая границу влево, чтобы увеличить столбец 2, эффективно толкая столбец 1 влево. Но вместо этого столбец 2 остается прежним, в то время как столбец 1 уменьшается!
ОБНОВИТЬ
Мой вопрос заключается в том, как реализовать желаемое поведение. Что и где мне нужно установить или повторно внедрить? Настроить SizeConfig
? Методы там звучит многообещающе: calculatePercentages()
а также calculateAvailableSpace()
, Кто и когда звонит им? Как поймать событие изменения размера столбца? Нужно ли где-нибудь установить слушателя? Как я могу сделать NatTable использовать индивидуальные SizeConfig
? Я на правильном пути?
2 ответа
Я понял это сам. В конце концов это было не так сложно. Все, что нужно сделать, это зарегистрировать 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 и 2, вы изменяете размер столбца 1, а не столбца 2. Направление не имеет значения.
Это аналогичное поведение, чем в хорошо известных приложениях для работы с электронными таблицами. Перемещение между границами приведет к изменению размера столбца влево, а не вправо.