Skip to content

Commit 262a6b9

Browse files
committed
Clipboard function for tables
- add copy to clipboard via Ctrl+C - note: the true values will be copied to clipboard
1 parent a5d5a8f commit 262a6b9

File tree

1 file changed

+116
-64
lines changed

1 file changed

+116
-64
lines changed
Lines changed: 116 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
/***********************************************************************
2-
* Copyright by Michael Loesler, https://software.applied-geodesy.org *
3-
* *
4-
* This program is free software; you can redistribute it and/or modify *
5-
* it under the terms of the GNU General Public License as published by *
6-
* the Free Software Foundation; either version 3 of the License, or *
7-
* at your option any later version. *
8-
* *
9-
* This program is distributed in the hope that it will be useful, *
10-
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12-
* GNU General Public License for more details. *
13-
* *
14-
* You should have received a copy of the GNU General Public License *
15-
* along with this program; if not, see <http://www.gnu.org/licenses/> *
16-
* or write to the *
17-
* Free Software Foundation, Inc., *
18-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19-
* *
20-
***********************************************************************/
2+
* Copyright by Michael Loesler, https://software.applied-geodesy.org *
3+
* *
4+
* This program is free software; you can redistribute it and/or modify *
5+
* it under the terms of the GNU General Public License as published by *
6+
* the Free Software Foundation; either version 3 of the License, or *
7+
* at your option any later version. *
8+
* *
9+
* This program is distributed in the hope that it will be useful, *
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12+
* GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License *
15+
* along with this program; if not, see <http://www.gnu.org/licenses/> *
16+
* or write to the *
17+
* Free Software Foundation, Inc., *
18+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19+
* *
20+
***********************************************************************/
2121

2222
package org.applied_geodesy.jag3d.ui.table;
2323

@@ -41,64 +41,88 @@
4141
import javafx.scene.control.TableRow;
4242
import javafx.scene.control.TableColumn.CellDataFeatures;
4343
import javafx.scene.control.TableColumn.CellEditEvent;
44+
import javafx.scene.control.TablePosition;
4445
import javafx.scene.control.TableView;
4546
import javafx.scene.control.cell.CheckBoxTableCell;
47+
import javafx.scene.input.Clipboard;
48+
import javafx.scene.input.ClipboardContent;
49+
import javafx.scene.input.KeyCode;
50+
import javafx.scene.input.KeyCodeCombination;
51+
import javafx.scene.input.KeyCombination;
52+
import javafx.scene.input.KeyEvent;
4653
import javafx.scene.input.MouseButton;
4754
import javafx.scene.input.MouseEvent;
4855
import javafx.util.Callback;
4956

50-
public abstract class UITableBuilder<T> {
57+
public abstract class UITableBuilder<T> {
58+
59+
class TableKeyEventHandler implements EventHandler<KeyEvent> {
60+
61+
KeyCodeCombination copyKeyCodeCompination = new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_ANY);
62+
public void handle(final KeyEvent keyEvent) {
63+
64+
if (copyKeyCodeCompination.match(keyEvent)) {
65+
if(keyEvent.getSource() instanceof TableView) {
66+
copySelectionToClipboard( (TableView<?>) keyEvent.getSource());
67+
keyEvent.consume();
68+
}
69+
}
70+
}
71+
}
72+
73+
5174
class TableCellChangeListener<S> implements ChangeListener<S> {
5275
private final int columnIndex;
5376
private final T rowData;
5477
TableCellChangeListener(int columnIndex, T rowData) {
5578
this.columnIndex = columnIndex;
5679
this.rowData = rowData;
5780
}
58-
81+
5982
@Override
6083
public void changed(ObservableValue<? extends S> observable, S oldValue, S newValue) {
6184
if (rowData != null) {
6285
setValue(rowData, columnIndex, -1, oldValue, newValue);
6386
}
6487
}
6588
}
66-
89+
6790
class TableCellEvent<S> implements EventHandler<CellEditEvent<T, S>> {
6891
private final int columnIndex;
6992
TableCellEvent(int columnIndex) {
7093
this.columnIndex = columnIndex;
7194
}
72-
95+
7396
@Override
7497
public void handle(CellEditEvent<T, S> event) {
7598
if (event.getTableColumn().isEditable()) {
76-
// event.getTablePosition().getRow()
99+
// event.getTablePosition().getRow()
77100
//int column = event.getTablePosition().getColumn();
78-
//setValue(event.getRowValue(), column, event.getNewValue());
101+
//setValue(event.getRowValue(), column, event.getNewValue());
79102
setValue(event.getRowValue(), this.columnIndex, event.getTablePosition().getRow(), event.getOldValue(), event.getNewValue());
80103
}
81104
}
82105
}
83-
106+
84107
static FormatterOptions options = FormatterOptions.getInstance();
85108
static I18N i18n = I18N.getInstance();
86109
TableView<T> table = this.createTable();
87-
110+
88111
UITableBuilder() {}
89-
112+
90113
TableView<T> createTable() {
91114
this.table = new TableView<T>();
92115
ObservableList<T> tableModel = FXCollections.observableArrayList();
93116
this.table.setItems(tableModel);
94117
this.table.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
95118
this.table.setTableMenuButtonVisible(false);
96-
// this.table.setPlaceholder(new Text(i18n.getString("UITableBuilder.emptytable", "No content in table.")));
119+
// this.table.setPlaceholder(new Text(i18n.getString("UITableBuilder.emptytable", "No content in table.")));
97120
this.table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
121+
this.table.setOnKeyPressed(new TableKeyEventHandler());
98122
tableModel.add(this.getEmptyRow());
99123
return table;
100124
}
101-
125+
102126
static <T> Callback<TableColumn<T,Integer>, TableCell<T,Integer>> getIntegerCallback() {
103127
return new Callback<TableColumn<T, Integer>, TableCell<T, Integer>>() {
104128
@Override
@@ -107,9 +131,9 @@ public TableCell<T, Integer> call(TableColumn<T, Integer> cell) {
107131
tableCell.setAlignment(Pos.CENTER_RIGHT);
108132
return tableCell;
109133
}
110-
};
134+
};
111135
}
112-
136+
113137
static <T> Callback<TableColumn<T,Double>, TableCell<T,Double>> getDoubleCallback(CellValueType cellValueType) {
114138
return new Callback<TableColumn<T, Double>, TableCell<T, Double>>() {
115139
@Override
@@ -118,9 +142,9 @@ public TableCell<T, Double> call(TableColumn<T, Double> cell) {
118142
tableCell.setAlignment(Pos.CENTER_RIGHT);
119143
return tableCell;
120144
}
121-
};
145+
};
122146
}
123-
147+
124148
static <T> Callback<TableColumn<T,Double>, TableCell<T,Double>> getDoubleCallback(CellValueType cellValueType, boolean displayUnit) {
125149
return new Callback<TableColumn<T, Double>, TableCell<T, Double>>() {
126150
@Override
@@ -129,31 +153,31 @@ public TableCell<T, Double> call(TableColumn<T, Double> cell) {
129153
tableCell.setAlignment(Pos.CENTER_RIGHT);
130154
return tableCell;
131155
}
132-
};
156+
};
133157
}
134-
158+
135159
static <T> Callback<TableColumn<T,String>, TableCell<T,String>> getStringCallback() {
136-
return new Callback<TableColumn<T,String>, TableCell<T,String>>() {
137-
@Override
138-
public TableCell<T,String> call(TableColumn<T,String> cell) {
139-
TableCell<T,String> tableCell = new EditableCell<T, String>(new EditableStringCellConverter());
140-
tableCell.setAlignment(Pos.CENTER_LEFT);
141-
return tableCell;
142-
}
143-
};
144-
}
145-
160+
return new Callback<TableColumn<T,String>, TableCell<T,String>>() {
161+
@Override
162+
public TableCell<T,String> call(TableColumn<T,String> cell) {
163+
TableCell<T,String> tableCell = new EditableCell<T, String>(new EditableStringCellConverter());
164+
tableCell.setAlignment(Pos.CENTER_LEFT);
165+
return tableCell;
166+
}
167+
};
168+
}
169+
146170
static <T> Callback<TableColumn<T,Boolean>, TableCell<T,Boolean>> getBooleanCallback() {
147171
return new Callback<TableColumn<T, Boolean>, TableCell<T, Boolean>>() {
148172
@Override
149173
public TableCell<T, Boolean> call(TableColumn<T, Boolean> column) {
150174
TableCell<T, Boolean> tableCell = new CheckBoxTableCell<T, Boolean>();
151175
tableCell.setAlignment(Pos.CENTER);
152-
return tableCell;
153-
}
154-
};
176+
return tableCell;
177+
}
178+
};
155179
}
156-
180+
157181
void addContextMenu(TableView<T> table, ContextMenu contextMenu) {
158182
table.setRowFactory(new Callback<TableView<T>, TableRow<T>>() {
159183
@Override
@@ -165,7 +189,7 @@ public TableRow<T> call(TableView<T> tableView) {
165189
}
166190
});
167191
}
168-
192+
169193
void addDynamicRowAdder(TableView<T> table) {
170194
table.setOnMouseClicked(new EventHandler<MouseEvent>() {
171195
@Override
@@ -186,20 +210,20 @@ else if (table.getItems() != null && table.getItems().size() == table.getSelecti
186210
}
187211
});
188212
}
189-
213+
190214
<S>TableColumn<T, S> getColumn(ColumnTooltipHeader header, Function<T, ObservableValue<S>> property, Callback<TableColumn<T, S>, TableCell<T, S>> callback, ColumnType type, int columnIndex, boolean editable) {
191215
final TableCellEvent<S> tableCellEvent = new TableCellEvent<S>(columnIndex);
192216
TableColumn<T, S> column = new TableColumn<T, S>();
193217
Label columnLabel = header.getLabel();
194-
columnLabel.getStyleClass().add("column-header-label");
195-
columnLabel.setMaxWidth(Double.MAX_VALUE);
196-
columnLabel.setTooltip(header.getTooltip());
197-
198-
column.setUserData(type);
199-
column.setEditable(editable);
200-
column.setGraphic(columnLabel);
201-
column.setMinWidth(25);
202-
column.setPrefWidth(125);
218+
columnLabel.getStyleClass().add("column-header-label");
219+
columnLabel.setMaxWidth(Double.MAX_VALUE);
220+
columnLabel.setTooltip(header.getTooltip());
221+
222+
column.setUserData(type);
223+
column.setEditable(editable);
224+
column.setGraphic(columnLabel);
225+
column.setMinWidth(25);
226+
column.setPrefWidth(125);
203227
column.setCellValueFactory(new Callback<CellDataFeatures<T, S>, ObservableValue<S>>() {
204228
@Override
205229
public ObservableValue<S> call(CellDataFeatures<T, S> param) {
@@ -219,8 +243,36 @@ public ObservableValue<S> call(CellDataFeatures<T, S> param) {
219243
public TableView<T> getTable() {
220244
return this.table;
221245
}
222-
246+
247+
public static void copySelectionToClipboard(TableView<?> table) {
248+
StringBuilder clipboardString = new StringBuilder();
249+
250+
for (TablePosition<?,?> position : table.getSelectionModel().getSelectedCells()) {
251+
int rowIndex = position.getRow();
252+
253+
if (rowIndex < 0 || rowIndex >= table.getItems().size())
254+
continue;
255+
256+
for (TableColumn<?, ?> column : table.getColumns()) {
257+
if (!column.isVisible())
258+
continue;
259+
260+
Object cell = column.getCellData(rowIndex);
261+
262+
if (cell == null)
263+
cell = " ";
264+
265+
clipboardString.append(cell.toString()).append('\t');
266+
}
267+
clipboardString.append("\r\n");
268+
}
269+
270+
final ClipboardContent clipboardContent = new ClipboardContent();
271+
clipboardContent.putString(clipboardString.toString());
272+
Clipboard.getSystemClipboard().setContent(clipboardContent);
273+
}
274+
223275
public static Object getValueAt(TableView<?> table, int columnIndex, int rowIndex) {
224-
return table.getColumns().get(columnIndex).getCellObservableValue(rowIndex).getValue();
276+
return table.getColumns().get(columnIndex).getCellObservableValue(rowIndex).getValue();
225277
}
226-
}
278+
}

0 commit comments

Comments
 (0)