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. Направление не имеет значения.

Это аналогичное поведение, чем в хорошо известных приложениях для работы с электронными таблицами. Перемещение между границами приведет к изменению размера столбца влево, а не вправо.

Другие вопросы по тегам