All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.okapi.common.ui.ResponsiveTable Maven / Gradle / Ivy

The newest version!
/*
 * =============================================================================
 * Copyright (C) 2010-2022 by the Okapi Framework contributors
 * -----------------------------------------------------------------------------
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */
package net.sf.okapi.common.ui;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import java.util.Arrays;
import java.util.ResourceBundle;

public interface ResponsiveTable {
    void configureHeader(final String[] columnNames);
    void addRow(final String[] list);
    void configureBody();
    TableItem[] rows();

    final class Default implements ResponsiveTable {
        private static final String COLON = ":";
        private final Table table;
        private final Menu headerMenu;
        private final Menu bodyMenu;
        private ResourceBundle resourceBundle;

        public Default(final Table table, final Menu headerMenu, final Menu bodyMenu) {
            this.table = table;
            this.headerMenu = headerMenu;
            this.bodyMenu = bodyMenu;
        }

        @Override
        public void configureHeader(final String[] columnNames) {
            this.table.setHeaderVisible(true);
            Arrays.stream(columnNames).forEach(n -> {
                final TableColumn tc = new TableColumn(this.table, SWT.NONE);
                tc.setText(n);
            });
            final MenuItem mi = new MenuItem(this.headerMenu, SWT.PUSH);
            mi.setText(resourceBundle().getString("new"));
            mi.addListener(SWT.Selection, menuSelectionListenerWith(mi.getText()));
        }

        private ResourceBundle resourceBundle() {
            if (null == this.resourceBundle) {
                this.resourceBundle = ResourceBundle.getBundle("net.sf.okapi.common.ui.ResponsiveTable");
            }
            return this.resourceBundle;
        }

        @Override
        public void addRow(final String[] values) {
            final TableItem item = new TableItem(this.table, SWT.NONE);
            item.setText(values);
        }

        @Override
        public void configureBody() {
            this.table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
            Arrays.stream(this.table.getColumns()).forEach(c -> c.pack());
            configureBodyMenu();
            configureGeneralListeners();
        }

        private void configureBodyMenu() {
            MenuItem mi = new MenuItem(this.bodyMenu, SWT.PUSH);
            mi.setText(resourceBundle().getString("new"));
            mi.addListener(SWT.Selection, menuSelectionListenerWith(mi.getText()));
            mi = new MenuItem(this.bodyMenu, SWT.PUSH);
            mi.setText(resourceBundle().getString("edit"));
            mi.addListener(SWT.Selection, menuSelectionListenerWith(mi.getText()));
            mi = new MenuItem(this.bodyMenu, SWT.PUSH);
            mi.setText(resourceBundle().getString("remove"));
            mi.addListener(SWT.Selection, event -> this.table.remove(this.table.getSelectionIndices()));
        }

        private Listener menuSelectionListenerWith(final String dialogTitle) {
            return event -> handleInteraction(dialogTitle);
        }

        private void handleInteraction(final String dialogTitle) {
            final String[] inputValues = inputValuesFor(dialogTitle);
            final String[] outputValues = new ResponsiveTableDialog.Default(
                new Shell(this.table.getShell(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL),
                dialogTitle,
                Arrays.stream(this.table.getColumns())
                    .map(c -> c.getText().concat(COLON))
                    .toArray(v -> new String[v]),
                inputValues
            ).open();
            saveIfNeeded(dialogTitle, outputValues);
        }

        private String[] inputValuesFor(final String dialogTitle) {
            final String[] inputValues;
            if (resourceBundle().getString("new").equals(dialogTitle)) {
                inputValues = new String[0];
            } else {
                inputValues = new String[this.table.getColumnCount()];
                final TableItem ti = this.table.getSelection()[0];
                for (int i = 0; i < inputValues.length; i++) {
                    inputValues[i] = ti.getText(i);
                }
            }
            return inputValues;
        }

        private void saveIfNeeded(final String dialogTitle, final String[] outputValues) {
            if (resourceBundle().getString("new").equals(dialogTitle)) {
                if (0 < outputValues.length) {
                    addRow(outputValues);
                    this.table.select(this.table.getItemCount() - 1);
                }
            } else {
                final TableItem ti = this.table.getSelection()[0];
                ti.setText(outputValues);
            }
        }

        private void configureGeneralListeners() {
            this.table.addListener(SWT.MenuDetect, event -> {
                final Point p = this.table.getShell().getDisplay().map(
                    null,
                    this.table,
                    new Point(event.x, event.y)
                );
                final Rectangle clientArea = this.table.getClientArea();
                final boolean headerArea = clientArea.y <= p.y && p.y < (clientArea.y + this.table.getHeaderHeight());
                final boolean rowsPresent = 0 < this.table.getItemCount();
                this.table.setMenu(headerArea || !rowsPresent ? this.headerMenu : this.bodyMenu);
            });
            this.table.addListener(SWT.MouseDoubleClick, event -> {
                final Point p = new Point(event.x, event.y);
                final TableItem ti = this.table.getItem(p);
                if (null != ti) {
                    handleInteraction(resourceBundle().getString("edit"));
                }
            });
            // IMPORTANT: Dispose the menus (only the current menu, set with setMenu(), will be
            // automatically disposed)
            this.table.addListener(SWT.Dispose, event -> {
                this.headerMenu.dispose();
                this.bodyMenu.dispose();
            });
        }

        @Override
        public TableItem[] rows() {
            return this.table.getItems();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy