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