diff --git a/org.eclipse.wb.swing/META-INF/MANIFEST.MF b/org.eclipse.wb.swing/META-INF/MANIFEST.MF index 51318ac68..c457d9cae 100644 --- a/org.eclipse.wb.swing/META-INF/MANIFEST.MF +++ b/org.eclipse.wb.swing/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.wb.swing;singleton:=true -Bundle-Version: 1.10.400.qualifier +Bundle-Version: 1.11.0.qualifier Bundle-ClassPath: . Bundle-Activator: org.eclipse.wb.internal.swing.Activator Bundle-Vendor: %providerName diff --git a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderDialog.java b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderDialog.java index bdce34ab3..abfe5a945 100644 --- a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderDialog.java +++ b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2025 Google, Inc. and others. + * Copyright (c) 2011, 2026 Google, Inc. and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -62,8 +62,6 @@ import javax.swing.border.Border; -import swingintegration.example.EmbeddedSwingComposite2; - /** * Dialog for {@link Border} editing. * @@ -193,11 +191,6 @@ public void handleEvent(Event event) { GridDataFactory.create(previewGroup).spanH(2).grabH().fillH(); GridLayoutFactory.create(previewGroup); previewGroup.setText(ModelMessages.BorderDialog_preview); - // - if (EmbeddedSwingComposite2.canUseAwt()) { - m_previewCanvas = new BorderPreviewCanvas(previewGroup, SWT.NONE); - GridDataFactory.create(m_previewCanvas).grab().fill().hintV(100); - } } // updateGUI(); diff --git a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderPreviewCanvas.java b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderPreviewCanvas.java index 4d5ddccf4..68fa5a1cc 100644 --- a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderPreviewCanvas.java +++ b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/border/BorderPreviewCanvas.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2025 Google, Inc. and others. + * Copyright (c) 2011, 2026 Google, Inc. and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -28,7 +28,7 @@ import javax.swing.border.Border; import javax.swing.border.LineBorder; -import swingintegration.example.EmbeddedSwingComposite2; +import swingintegration.example.EmbeddedSwingComposite; /** * {@link Composite} for displaying {@link Border}. @@ -36,7 +36,7 @@ * @author scheglov_ke * @coverage swing.property.editor */ -public final class BorderPreviewCanvas extends EmbeddedSwingComposite2 { +public final class BorderPreviewCanvas extends EmbeddedSwingComposite { private JPanel m_awtRoot; private JPanel m_emptyPanel; private JPanel m_filledPanel_1; diff --git a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelDialog.java b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelDialog.java index 53a5b2675..3e32c63f0 100644 --- a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelDialog.java +++ b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2024 Google, Inc. + * Copyright (c) 2011, 2026 Google, Inc. and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -19,44 +19,24 @@ import org.eclipse.wb.internal.core.utils.ui.UiUtils; import org.eclipse.wb.internal.core.utils.ui.dialogs.ResizableDialog; import org.eclipse.wb.internal.swing.model.ModelMessages; +import org.eclipse.wb.internal.swing.model.property.editor.models.table.TableModelPreviewCanvas.TableSelection; +import org.eclipse.wb.internal.swing.model.property.editor.models.table.TableModelPreviewCanvas.TableOperationRunnable; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; -import org.eclipse.swt.widgets.Widget; import org.apache.commons.collections4.BidiMap; import org.apache.commons.collections4.bidimap.DualHashBidiMap; import org.apache.commons.collections4.bidimap.UnmodifiableBidiMap; -import java.awt.EventQueue; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; - -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.event.TableColumnModelEvent; -import javax.swing.event.TableColumnModelListener; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; -import javax.swing.table.TableModel; - -import swingintegration.example.EmbeddedSwingComposite2; - /** * Dialog for editing {@link TableModelDescription}. * @@ -107,8 +87,7 @@ public TableModelDialog(Shell parentShell, String title, TableModelDescription m private TitledComposite m_columnsComposite; private TitledComposite m_rowsComposite; private TitledComposite m_columnPropertiesComposite; - private EmbeddedSwingComposite2 m_swingComposite; - private JTable m_table; + private TableModelPreviewCanvas m_swingComposite; // columns private CSpinner m_columnCountSpinner; private Button m_insertColumnButton; @@ -158,18 +137,12 @@ private void createJTableComposite(Composite parent) { GridLayoutFactory.create(m_tableComposite).noMargins(); new Label(m_tableComposite, SWT.NONE).setText(ModelMessages.TableModelDialog_itemsLabel); { - m_swingComposite = new EmbeddedSwingComposite2(m_tableComposite, SWT.NONE) { - @Override - protected JComponent createSwingComponent() { - TableModel model = m_model.createTableModel(); - m_table = new JTable(model); - m_table.setCellSelectionEnabled(true); - m_table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); - updateTableModel(); - trackTableSelection(); - return new JScrollPane(m_table); + m_swingComposite = new TableModelPreviewCanvas(m_model, m_tableComposite, SWT.NONE); + m_swingComposite.addPropertyChangeListener(event -> { + if (TableModelPreviewCanvas.PROP_MODEL_CHANGED.equals(event.getPropertyName())) { + updateControls((TableSelection) event.getNewValue()); } - }; + }); GridDataFactory.create(m_swingComposite).grab().fill(); } { @@ -190,7 +163,7 @@ private void createColumnsComposite(Composite parent) { new Label(container, SWT.NONE).setText(ModelMessages.TableModelDialog_columnsCount); m_columnCountSpinner = new CSpinner(container, SWT.BORDER); GridDataFactory.create(m_columnCountSpinner).grabH().fillH().hintHC(5); - addJTableOperationSelectionListener(m_columnCountSpinner, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnCountSpinner, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.setColumnCount(m_columnCountSpinner.getSelection()); @@ -202,7 +175,7 @@ public void run(int row, int column) { m_insertColumnButton = new Button(container, SWT.NONE); GridDataFactory.create(m_insertColumnButton).spanH(2).hintHC(13).alignHC(); m_insertColumnButton.setText(ModelMessages.TableModelDialog_columnInsertButton); - addJTableOperationSelectionListener(m_insertColumnButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_insertColumnButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.insertColumn(getInsertColumnIndex(column)); @@ -210,7 +183,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(row, getInsertColumnIndex(column)); + m_swingComposite.setTableSelection(row, getInsertColumnIndex(column)); } }); } @@ -219,7 +192,7 @@ public void run(int row, int column) { m_deleteColumnButton = new Button(container, SWT.NONE); GridDataFactory.create(m_deleteColumnButton).spanH(2).hintHC(13).alignHC(); m_deleteColumnButton.setText(ModelMessages.TableModelDialog_columnDeleteButton); - addJTableOperationSelectionListener(m_deleteColumnButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_deleteColumnButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.removeColumn(column); @@ -227,10 +200,10 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - if (column < m_table.getColumnCount()) { - setTableSelection(row, column); + if (column < m_model.getColumnCount()) { + m_swingComposite.setTableSelection(row, column); } else { - setTableSelection(row, column - 1); + m_swingComposite.setTableSelection(row, column - 1); } } }); @@ -240,7 +213,7 @@ public void run(int row, int column) { m_moveColumnLeftButton = new Button(container, SWT.NONE); GridDataFactory.create(m_moveColumnLeftButton).spanH(2).hintHC(13).alignHC(); m_moveColumnLeftButton.setText(ModelMessages.TableModelDialog_columnMoveLeftButton); - addJTableOperationSelectionListener(m_moveColumnLeftButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_moveColumnLeftButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.moveColumn(column, column - 1); @@ -248,7 +221,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(row, column - 1); + m_swingComposite.setTableSelection(row, column - 1); } }); } @@ -257,7 +230,7 @@ public void run(int row, int column) { m_moveColumnRightButton = new Button(container, SWT.NONE); GridDataFactory.create(m_moveColumnRightButton).spanH(2).hintHC(13).alignHC(); m_moveColumnRightButton.setText(ModelMessages.TableModelDialog_columnMoveRightButton); - addJTableOperationSelectionListener(m_moveColumnRightButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_moveColumnRightButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.moveColumn(column, column + 1); @@ -265,7 +238,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(row, column + 1); + m_swingComposite.setTableSelection(row, column + 1); } }); } @@ -282,7 +255,7 @@ private void createRowsComposite(Composite parent) { new Label(container, SWT.NONE).setText(ModelMessages.TableModelDialog_rowsCount); m_rowCountSpinner = new CSpinner(container, SWT.BORDER); GridDataFactory.create(m_rowCountSpinner).grabH().fillH().hintHC(5); - addJTableOperationSelectionListener(m_rowCountSpinner, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_rowCountSpinner, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.setRowCount(m_rowCountSpinner.getSelection()); @@ -294,7 +267,7 @@ public void run(int row, int column) { m_insertRowButton = new Button(container, SWT.NONE); GridDataFactory.create(m_insertRowButton).spanH(2).hintHC(13).alignHC(); m_insertRowButton.setText(ModelMessages.TableModelDialog_rowInsertButton); - addJTableOperationSelectionListener(m_insertRowButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_insertRowButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.insertRow(getInsertRowIndex(row)); @@ -302,7 +275,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(getInsertRowIndex(row), column); + m_swingComposite.setTableSelection(getInsertRowIndex(row), column); } }); } @@ -311,7 +284,7 @@ public void run(int row, int column) { m_deleteRowButton = new Button(container, SWT.NONE); GridDataFactory.create(m_deleteRowButton).spanH(2).hintHC(13).alignHC(); m_deleteRowButton.setText(ModelMessages.TableModelDialog_rowDeleteButton); - addJTableOperationSelectionListener(m_deleteRowButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_deleteRowButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.removeRow(row); @@ -319,10 +292,10 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - if (row < m_table.getRowCount()) { - setTableSelection(row, column); + if (row < m_model.getRowCount()) { + m_swingComposite.setTableSelection(row, column); } else { - setTableSelection(row - 1, column); + m_swingComposite.setTableSelection(row - 1, column); } } }); @@ -332,7 +305,7 @@ public void run(int row, int column) { m_moveRowUpButton = new Button(container, SWT.NONE); GridDataFactory.create(m_moveRowUpButton).spanH(2).hintHC(13).alignHC(); m_moveRowUpButton.setText(ModelMessages.TableModelDialog_rowMoveUpButton); - addJTableOperationSelectionListener(m_moveRowUpButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_moveRowUpButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.moveRow(row, row - 1); @@ -340,7 +313,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(row - 1, column); + m_swingComposite.setTableSelection(row - 1, column); } }); } @@ -349,7 +322,7 @@ public void run(int row, int column) { m_moveRowDownButton = new Button(container, SWT.NONE); GridDataFactory.create(m_moveRowDownButton).spanH(2).hintHC(13).alignHC(); m_moveRowDownButton.setText(ModelMessages.TableModelDialog_rowMoveDownButton); - addJTableOperationSelectionListener(m_moveRowDownButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_moveRowDownButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.moveRow(row, row + 1); @@ -357,7 +330,7 @@ public void run(int row, int column) { }, new TableOperationRunnable() { @Override public void run(int row, int column) { - setTableSelection(row + 1, column); + m_swingComposite.setTableSelection(row + 1, column); } }); } @@ -385,7 +358,7 @@ private void createColumnPropertiesComposite(Composite parent) { new Label(container, SWT.NONE).setText(ModelMessages.TableModelDialog_columnPropertiesTitle); m_columnPropertyTitle = new Text(container, SWT.BORDER); GridDataFactory.create(m_columnPropertyTitle).spanH(2).hintHC(40).fillH(); - addJTableOperationListener(m_columnPropertyTitle, SWT.Modify, new TableOperationRunnable() { + m_swingComposite.addJTableOperationListener(m_columnPropertyTitle, SWT.Modify, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_name = m_columnPropertyTitle.getText(); @@ -398,7 +371,7 @@ public void run(int row, int column) { m_columnPropertyPrefWidth = new CSpinner(container, SWT.BORDER); GridDataFactory.create(m_columnPropertyPrefWidth).hintHC(15); m_columnPropertyPrefWidth.setRange(0, Integer.MAX_VALUE); - addJTableOperationSelectionListener(m_columnPropertyPrefWidth, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnPropertyPrefWidth, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_preferredWidth = m_columnPropertyPrefWidth.getSelection(); @@ -407,7 +380,7 @@ public void run(int row, int column) { } { ToolItem clearButton = createClearSpinnerButton(container); - addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_preferredWidth = @@ -426,7 +399,7 @@ public void run(int row, int column) { } m_columnPropertyType.setVisibleItemCount(COLUMN_TYPES.size()); // listener - addJTableOperationSelectionListener(m_columnPropertyType, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnPropertyType, new TableOperationRunnable() { @Override public void run(int row, int column) { String typeTitle = m_columnPropertyType.getText(); @@ -459,7 +432,7 @@ public void run(int row, int column) { m_columnPropertyMinWidth = new CSpinner(container, SWT.BORDER); GridDataFactory.create(m_columnPropertyMinWidth).hintHC(15); m_columnPropertyMinWidth.setRange(0, Integer.MAX_VALUE); - addJTableOperationSelectionListener(m_columnPropertyMinWidth, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnPropertyMinWidth, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_minWidth = m_columnPropertyMinWidth.getSelection(); @@ -468,7 +441,7 @@ public void run(int row, int column) { } { ToolItem clearButton = createClearSpinnerButton(container); - addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_minWidth = TableColumnDescription.DEFAULT_MIN_WIDTH; @@ -483,7 +456,7 @@ public void run(int row, int column) { { m_columnPropertyEditable = new Button(booleanContainer, SWT.CHECK); m_columnPropertyEditable.setText(ModelMessages.TableModelDialog_columnPropertiesEditable); - addJTableOperationSelectionListener(m_columnPropertyEditable, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnPropertyEditable, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_editable = m_columnPropertyEditable.getSelection(); @@ -493,7 +466,7 @@ public void run(int row, int column) { { m_columnPropertyResizable = new Button(booleanContainer, SWT.CHECK); m_columnPropertyResizable.setText(ModelMessages.TableModelDialog_columnPropertiesResizable); - addJTableOperationSelectionListener( + m_swingComposite.addJTableOperationSelectionListener( m_columnPropertyResizable, new TableOperationRunnable() { @Override @@ -509,7 +482,7 @@ public void run(int row, int column) { m_columnPropertyMaxWidth = new CSpinner(container, SWT.BORDER); GridDataFactory.create(m_columnPropertyMaxWidth).hintHC(15); m_columnPropertyMaxWidth.setRange(0, Integer.MAX_VALUE); - addJTableOperationSelectionListener(m_columnPropertyMaxWidth, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(m_columnPropertyMaxWidth, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_maxWidth = m_columnPropertyMaxWidth.getSelection(); @@ -518,7 +491,7 @@ public void run(int row, int column) { } { ToolItem clearButton = createClearSpinnerButton(container); - addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { + m_swingComposite.addJTableOperationSelectionListener(clearButton, new TableOperationRunnable() { @Override public void run(int row, int column) { m_model.getColumn(column).m_maxWidth = TableColumnDescription.DEFAULT_MAX_WIDTH; @@ -554,92 +527,17 @@ private static int getInsertRowIndex(int row) { return row != -1 ? row : 0; } - //////////////////////////////////////////////////////////////////////////// - // - // Selection in JTable - // - //////////////////////////////////////////////////////////////////////////// - private int m_tableSelectedColumn; - private int m_tableSelectedRow; - private boolean m_processTableSelectionEvent = true; - - private void trackTableSelection() { - m_tableSelectedRow = -1; - m_tableSelectedColumn = -1; - ListSelectionListener listener = new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - if (m_processTableSelectionEvent) { - m_tableSelectedColumn = m_table.getSelectedColumn(); - m_tableSelectedRow = m_table.getSelectedRow(); - updateControls(); - } - } - }; - m_table.getSelectionModel().addListSelectionListener(listener); - m_table.getColumnModel().getSelectionModel().addListSelectionListener(listener); - updateControls(); - // XXX - final PropertyChangeListener columnWidthListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (m_processTableSelectionEvent) { - TableColumn column = (TableColumn) evt.getSource(); - int index = column.getModelIndex(); - m_model.getColumn(index).m_preferredWidth = (Integer) evt.getNewValue(); - updateControls(); - } - } - }; - m_table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { - @Override - public void columnAdded(TableColumnModelEvent e) { - TableColumnModel columnModel = (TableColumnModel) e.getSource(); - int columnIndex = e.getToIndex(); - columnModel.getColumn(columnIndex).addPropertyChangeListener(columnWidthListener); - } - - @Override - public void columnSelectionChanged(ListSelectionEvent e) { - } - - @Override - public void columnRemoved(TableColumnModelEvent e) { - } - - @Override - public void columnMoved(TableColumnModelEvent e) { - } - - @Override - public void columnMarginChanged(ChangeEvent e) { - } - }); - } - - private void setTableSelection(int row, int column) { - m_table.changeSelection(row, column, false, false); - } - //////////////////////////////////////////////////////////////////////////// // // Updates // //////////////////////////////////////////////////////////////////////////// - private void updateControls() { - Display.getDefault().asyncExec(new Runnable() { - @Override - public void run() { - updateControlsInDisplay(); - } - }); - } - private void updateControlsInDisplay() { - int row = m_tableSelectedRow; - int column = m_tableSelectedColumn; - int rowCount = m_table.getRowCount(); - int columnCount = m_table.getColumnCount(); + private void updateControls(TableSelection selection) { + int row = selection.row(); + int column = selection.column(); + int rowCount = m_model.getRowCount(); + int columnCount = m_model.getColumnCount(); // m_columnCountSpinner.setSelection(m_model.getColumnCount()); m_rowCountSpinner.setSelection(m_model.getRowCount()); @@ -667,66 +565,4 @@ private void updateControlsInDisplay() { m_columnPropertyResizable.setSelection(columnDescription.m_resizable); } } - - private interface TableOperationRunnable { - void run(int row, int column); - } - - private final TableOperationRunnable DEFAULT_TABLE_UPDATE = new TableOperationRunnable() { - @Override - public void run(int row, int column) { - setTableSelection(row, column); - updateControls(); - } - }; - - private void addJTableOperationListener(Widget eventTarget, - int eventType, - TableOperationRunnable operation) { - addJTableOperationSelectionListener(eventTarget, eventType, operation, DEFAULT_TABLE_UPDATE); - } - - private void addJTableOperationSelectionListener(Widget eventTarget, - TableOperationRunnable operation) { - addJTableOperationSelectionListener(eventTarget, operation, DEFAULT_TABLE_UPDATE); - } - - private void addJTableOperationSelectionListener(Widget eventTarget, - final TableOperationRunnable operation, - final TableOperationRunnable tableUpdateRunnable) { - addJTableOperationSelectionListener(eventTarget, SWT.Selection, operation, tableUpdateRunnable); - } - - private void addJTableOperationSelectionListener(Widget eventTarget, - int eventType, - final TableOperationRunnable operation, - final TableOperationRunnable tableUpdateRunnable) { - eventTarget.addListener(eventType, new Listener() { - @Override - public void handleEvent(Event event) { - final int row = m_table.getSelectedRow(); - final int column = m_table.getSelectedColumn(); - operation.run(row, column); - // update JTable and controls - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - updateTableModel(); - tableUpdateRunnable.run(row, column); - updateControls(); - } - }); - } - }); - } - - private void updateTableModel() { - m_processTableSelectionEvent = false; - try { - m_table.tableChanged(null); - m_model.applyModel(m_table); - } finally { - m_processTableSelectionEvent = true; - } - } } diff --git a/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelPreviewCanvas.java b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelPreviewCanvas.java new file mode 100644 index 000000000..310f402ee --- /dev/null +++ b/org.eclipse.wb.swing/src/org/eclipse/wb/internal/swing/model/property/editor/models/table/TableModelPreviewCanvas.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2011, 2026 Google, Inc. and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * https://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Google, Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.wb.internal.swing.model.property.editor.models.table; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Widget; + +import java.awt.EventQueue; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.TableColumnModelEvent; +import javax.swing.event.TableColumnModelListener; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; + +import swingintegration.example.EmbeddedSwingComposite; + +/** + * {@link Composite} for displaying {@link TableModel}. + */ +public class TableModelPreviewCanvas extends EmbeddedSwingComposite { + /* package */ static final String PROP_MODEL_CHANGED = "modify"; + private final PropertyChangeSupport m_propertyChangeSupport; + private final TableModelDescription m_model; + private JTable m_table; + + public TableModelPreviewCanvas(TableModelDescription model, Composite parent, int style) { + super(parent, style); + m_propertyChangeSupport = new PropertyChangeSupport(this); + m_model = model; + } + + @Override + protected JComponent createSwingComponent() { + TableModel model = m_model.createTableModel(); + m_table = new JTable(model); + m_table.setCellSelectionEnabled(true); + m_table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + updateTableModel(); + trackTableSelection(); + return new JScrollPane(m_table); + } + + /* package */ static final record TableSelection(int row, int column) { + + } + + /* package */ static interface TableOperationRunnable { + void run(int row, int column); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Selection in JTable + // + //////////////////////////////////////////////////////////////////////////// + private int m_tableSelectedColumn; + private int m_tableSelectedRow; + private boolean m_processTableSelectionEvent = true; + + private void trackTableSelection() { + m_tableSelectedRow = -1; + m_tableSelectedColumn = -1; + ListSelectionListener listener = e -> { + if (m_processTableSelectionEvent) { + m_tableSelectedColumn = m_table.getSelectedColumn(); + m_tableSelectedRow = m_table.getSelectedRow(); + firePropertyChange(); + } + }; + m_table.getSelectionModel().addListSelectionListener(listener); + m_table.getColumnModel().getSelectionModel().addListSelectionListener(listener); + firePropertyChange(); + // XXX + final PropertyChangeListener columnWidthListener = evt -> { + if (m_processTableSelectionEvent) { + TableColumn column = (TableColumn) evt.getSource(); + int index = column.getModelIndex(); + m_model.getColumn(index).m_preferredWidth = (Integer) evt.getNewValue(); + firePropertyChange(); + } + }; + m_table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { + @Override + public void columnAdded(TableColumnModelEvent e) { + TableColumnModel columnModel = (TableColumnModel) e.getSource(); + int columnIndex = e.getToIndex(); + columnModel.getColumn(columnIndex).addPropertyChangeListener(columnWidthListener); + } + + @Override + public void columnSelectionChanged(ListSelectionEvent e) { + } + + @Override + public void columnRemoved(TableColumnModelEvent e) { + } + + @Override + public void columnMoved(TableColumnModelEvent e) { + } + + @Override + public void columnMarginChanged(ChangeEvent e) { + } + }); + } + + /* package */ void setTableSelection(int row, int column) { + Assert.isTrue(SwingUtilities.isEventDispatchThread(), "Must be called from AWT event dispatcher thread"); + m_table.changeSelection(row, column, false, false); + } + + //////////////////////////////////////////////////////////////////////////// + // + // Updates + // + //////////////////////////////////////////////////////////////////////////// + + private final TableOperationRunnable DEFAULT_TABLE_UPDATE = (row, column) -> { + setTableSelection(row, column); + firePropertyChange(); + }; + + /* package */ void addJTableOperationListener(Widget eventTarget, + int eventType, + TableOperationRunnable operation) { + addJTableOperationSelectionListener(eventTarget, eventType, operation, DEFAULT_TABLE_UPDATE); + } + + /* package */ void addJTableOperationSelectionListener(Widget eventTarget, + TableOperationRunnable operation) { + addJTableOperationSelectionListener(eventTarget, operation, DEFAULT_TABLE_UPDATE); + } + + /* package */ void addJTableOperationSelectionListener(Widget eventTarget, + final TableOperationRunnable operation, + final TableOperationRunnable tableUpdateRunnable) { + addJTableOperationSelectionListener(eventTarget, SWT.Selection, operation, tableUpdateRunnable); + } + + /* package */ void addJTableOperationSelectionListener(Widget eventTarget, + int eventType, + final TableOperationRunnable operation, + final TableOperationRunnable tableUpdateRunnable) { + eventTarget.addListener(eventType, event -> { + final int row = m_table.getSelectedRow(); + final int column = m_table.getSelectedColumn(); + operation.run(row, column); + // update JTable and controls + EventQueue.invokeLater(() -> { + updateTableModel(); + tableUpdateRunnable.run(row, column); + firePropertyChange(); + }); + }); + } + + private void updateTableModel() { + m_processTableSelectionEvent = false; + try { + m_table.tableChanged(null); + m_model.applyModel(m_table); + } finally { + m_processTableSelectionEvent = true; + } + } + //////////////////////////////////////////////////////////////////////////// + // + // PropertyChangeSupport + // + //////////////////////////////////////////////////////////////////////////// + + /* package */ void addPropertyChangeListener(PropertyChangeListener listener) { + m_propertyChangeSupport.addPropertyChangeListener(listener); + } + + private void firePropertyChange() { + TableSelection selection = new TableSelection(m_tableSelectedRow, m_tableSelectedColumn); + Display.getDefault().asyncExec(() -> m_propertyChangeSupport.firePropertyChange(PROP_MODEL_CHANGED, null, selection)); + } +} diff --git a/org.eclipse.wb.swing/src/swingintegration/example/EmbeddedSwingComposite2.java b/org.eclipse.wb.swing/src/swingintegration/example/EmbeddedSwingComposite2.java deleted file mode 100644 index 731e79f03..000000000 --- a/org.eclipse.wb.swing/src/swingintegration/example/EmbeddedSwingComposite2.java +++ /dev/null @@ -1,445 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2007, 2025 SAS Institute. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * https://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: SAS Institute - initial API and implementation - *******************************************************************************/ -package swingintegration.example; - -import org.eclipse.wb.internal.core.EnvironmentUtils; -import org.eclipse.wb.internal.swing.utils.SwingImageUtils; -import org.eclipse.wb.internal.swing.utils.SwingUtils; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.SWTException; -import org.eclipse.swt.awt.SWT_AWT; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Widget; - -import java.awt.EventQueue; -import java.awt.Frame; -import java.awt.im.InputContext; - -import javax.swing.JApplet; -import javax.swing.JComponent; -import javax.swing.RootPaneContainer; - -/** - * A SWT composite widget for embedding Swing components in a SWT composite within an RCP or - * standalone-SWT application. The Eclipse platform provides limited support for embedding Swing - * components through {@link org.eclipse.swt.awt.SWT_AWT}. This class extends that support by - *
- * If, rather than embedding Swing components, you are integrating with Swing by opening Swing - * dialogs, see the {@link AwtEnvironment} class. - *
- * This is an abstract that is normally used by extending it and implementing the - * {@link #createSwingComponent()} method. For example, - * - *
- * embeddedComposite = new EmbeddedSwingComposite(parent, SWT.NONE) {
- * protected JComponent createSwingComponent() {
- * scrollPane = new JScrollPane();
- * table = new JTable();
- * scrollPane.setViewportView(table);
- * return scrollPane;
- * }
- * };
- * embeddedComposite.populate();
- *
- *
- * - * The Swing component is created inside a standard Swing containment hierarchy, rooted in a - * {@link javax.swing.RootPaneContainer}. The root pane container is placed inside an AWT frame, as - * returned by {@link org.eclipse.swt.awt.SWT_AWT#new_Frame(Composite)} - *
- * Note: When you mix components from Swing/AWT and SWT toolkits, there will be two UI event - * threads, one for AWT, one for SWT. Most SWT APIs require that you call them from the SWT thread. - * Swing has similar restrictions though it does not enforce them as much as SWT. - *
- * Applications need to be aware of the current thread, and, where necessary, schedule tasks to run - * on another thread. This has always been required in the pure Swing or SWT environments, but when - * mixing Swing and SWT, more of this scheduling will be necessary. - *
- * To schedule work on the AWT event thread, you can use: - *
- * (or similar methods in {@link java.awt.EventQueue}) - *
- * To schedule work on the SWT event thread, use: - *
- * This method must be called from the SWT event thread. - *
- * The style value is either one of the style constants defined in class SWT which is
- * applicable to instances of this class, or must be built by bitwise OR'ing together
- * (that is, using the int "|" operator) two or more of those SWT style
- * constants. The class description lists the style constants that are applicable to the class.
- * Style bits are also inherited from superclasses.
- *
- * The styles SWT.EMBEDDED and SWT.NO_BACKGROUND will be added to the specified style. Usually, no - * other style bits are needed. - * - * @param parent - * a widget which will be the parent of the new instance (cannot be null) - * @param style - * the style of widget to construct - * - * @exception IllegalArgumentException - *
- * This method must be called from the SWT event thread. - *
- * The Swing component will be created by calling {@link #createSwingComponent()}. The creation is - * scheduled asynchronously on the AWT event thread. This method does not wait for completion of - * this asynchronous task, so it may return before createSwingComponent() is complete. - *
- * The Swing component is created inside a standard Swing containment hierarchy, rooted in a - * {@link javax.swing.RootPaneContainer}. Clients can override - * {@link #addRootPaneContainer(Frame)} to provide their own root pane container implementation. - *
- * This method can be called multiple times for a single instance. If an embedded frame exists - * from a previous call, it is disposed. - * - * @exception SWTException - *
- * Implement this method to provide the Swing component that will be shown inside this composite. - * The returned component will be added to the Swing content pane. At least one component must be - * created by this method; null is not a valid return value. - * - * @return a non-null Swing component - */ - protected abstract JComponent createSwingComponent(); - - /** - * Adds a root pane container to the embedded AWT frame. Override this to provide your own - * {@link javax.swing.RootPaneContainer} implementation. In most cases, it is not necessary to - * override this method. - *
- * This method is called from the AWT event thread. - *
- * If you are defining your own root pane container, make sure that there is at least one - * heavyweight (AWT) component in the frame's containment hierarchy; otherwise, event processing - * will not work correctly. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522 for - * more information. - * - * @param frame - * the frame to which the root pane container is added - * @return a non-null Swing component - */ - protected RootPaneContainer addRootPaneContainer(Frame frame) { - assert EventQueue.isDispatchThread(); // On AWT event thread - assert frame != null; - // It is important to set up the proper top level components in the frame: - // 1) For Swing to work properly, Sun documents that there must be an implementor of - // javax.swing.RootPaneContainer at the top of the component hierarchy. - // 2) For proper event handling there must be a heavyweight - // an AWT frame must contain a heavyweight component (see - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4982522) - // 3) The Swing implementation further narrows the options by expecting that the - // top of the hierarchy be a JFrame, JDialog, JWindow, or JApplet. See javax.swing.PopupFactory. - // All this drives the choice of JApplet for the top level Swing component. It is the - // only single component that satisfies all the above. This does not imply that - // we have a true applet; in particular, there is no notion of an applet lifecycle in this - // context. - // - // We need to intercept call of "getInputContext" because it make native call - // and causes dead-lock in SWT. - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376561 - // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291326 - JApplet applet = new JApplet() { - private static final long serialVersionUID = 1L; - - @Override - public InputContext getInputContext() { - return null; - } - }; - // In JRE 1.4, the JApplet makes itself a focus cycle root. This - // interferes with the focus handling installed on the parent frame, so - // change it back to a non-root here. - // TODO: consider moving the focus policy from the Frame down to the JApplet - applet.setFocusCycleRoot(false); - frame.add(applet); - return applet; - } - - /** - * Performs custom updates to newly set fonts. This method is called whenever a change to the - * system font through the system settings (i.e. control panel) is detected. - *
- * This method is called from the AWT event thread. - *
- * In most cases it is not necessary to override this method. Normally, the implementation of this - * class will automatically propogate font changes to the embedded Swing components through - * Swing's Look and Feel support. However, if additional special processing is necessary, it can - * be done inside this method. - * - * @param newFont - * New AWT font - */ - protected void updateAwtFont(java.awt.Font newFont) { - } - - /** - * Returns the embedded AWT frame. The returned frame is the root of the AWT containment hierarchy - * for the embedded Swing component. This method can be called from any thread. - * - * @return the embedded frame - */ - public Frame getFrame() { - // Intentionally leaving out checkWidget() call. This may need to be called from within user's - // createSwingComponent() method. Accessing from a non-SWT thread is OK, but we still check - // for disposal - if (getDisplay() == null || isDisposed()) { - SWT.error(SWT.ERROR_WIDGET_DISPOSED); - } - return awtContext != null ? awtContext.getFrame() : null; - } - - private void createFrame() { - assert Display.getCurrent() != null; // On SWT event thread - // Make sure Awt environment is initialized. - //AwtEnvironment.getInstance(getDisplay()); - if (awtContext != null) { - final Frame oldFrame = awtContext.getFrame(); - // Schedule disposal of old frame on AWT thread so that there are no problems with - // already-scheduled operations that have not completed. - // Note: the implementation of Frame.dispose() would schedule the use of the AWT - // thread even if it was not done here, but it uses invokeAndWait() which is - // prone to deadlock (and not necessary for this case). - EventQueue.invokeLater(() -> oldFrame.dispose()); - } - Frame frame = SWT_AWT.new_Frame(this); - frame.getInputContext(); - awtContext = new AwtContext(frame); - // Glue the two frameworks together. Do this before anything is added to the frame - // so that all necessary listeners are in place. - createFocusHandlers(); - // This listener clears garbage during resizing, making it looker much cleaner - addControlListener(new CleanResizeListener()); - } - - private void createFocusHandlers() { - assert awtContext != null; - assert Display.getCurrent() != null; // On SWT event thread - Frame frame = awtContext.getFrame(); - awtHandler = new AwtFocusHandler(frame); - SwtFocusHandler swtHandler = new SwtFocusHandler(this); - awtHandler.setSwtHandler(swtHandler); - swtHandler.setAwtHandler(awtHandler); - // Ensure that AWT popups are dismissed whenever a SWT menu is shown - getDisplay().addFilter(SWT.Show, menuListener); - EmbeddedChildFocusTraversalPolicy policy = new EmbeddedChildFocusTraversalPolicy(awtHandler); - frame.setFocusTraversalPolicy(policy); - } - - private void scheduleComponentCreation() { - assert awtContext != null; - // Create AWT/Swing components on the AWT thread. This is - // especially necessary to avoid an AWT leak bug (6411042). - final AwtContext currentContext = awtContext; - EventQueue.invokeLater(() -> { - RootPaneContainer container = addRootPaneContainer(currentContext.getFrame()); - JComponent swingComponent = createSwingComponent(); - currentContext.setSwingComponent(swingComponent); - container.getRootPane().getContentPane().add(swingComponent); - }); - } - - private boolean isFocusable() { - if (awtContext == null) { - return false; - } - JComponent swingComponent = awtContext.getSwingComponent(); - return swingComponent != null && swingComponent.isFocusable(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#setFocus() - */ - @Override - public boolean setFocus() { - checkWidget(); - if (!isFocusable()) { - return false; - } - return super.setFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Control#forceFocus() - */ - @Override - public boolean forceFocus() { - checkWidget(); - if (!isFocusable()) { - return false; - } - return super.forceFocus(); - } - - /* (non-Javadoc) - * @see org.eclipse.swt.widgets.Widget#dispose() - */ - @Override - public void dispose() { - if (!isDisposed()) { - dispose_AWT(); - super.dispose(); - } - } - - private void dispose_AWT() { - // remove listeners - getDisplay().removeFilter(SWT.Show, menuListener); - // dispose frame to avoid lock down in EventQueue.invokeAndWait() later - // must be done in the AWT even thread. See: - // https://github.com/eclipse-windowbuilder/windowbuilder/discussions/937 - if (awtContext != null) { - SwingUtils.runLog(() -> { - Frame oldFrame = awtContext.getFrame(); - oldFrame.dispose(); - }); - } - } - - /** - * There is problem with running SWT_AWT on OSX with Java 1.7 - *
- * https://bugs.eclipse.org/bugs/show_bug.cgi?id=374199 - *
- * It is marked "fixed", but still does not work. - */ - public static boolean canUseAwt() { - if (EnvironmentUtils.IS_MAC) { - Shell shell = new Shell(); - try { - try { - Frame frame = SWT_AWT.new_Frame(shell); - frame.dispose(); - return true; - } catch (Throwable e) { - return false; - } - } finally { - shell.dispose(); - } - } - return true; - } -}