This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
The following commit(s) were added to refs/heads/master by this push:
new 272cd0c24 CAY-3004 Modeler: Rework DbEntity PK generation UI to match
the XML model
272cd0c24 is described below
commit 272cd0c247745aa80033f0c84fb247274acee079
Author: Andrus Adamchik <[email protected]>
AuthorDate: Sun Aug 30 09:52:22 2026 -0400
CAY-3004 Modeler: Rework DbEntity PK generation UI to match the XML model
(also uinifying enabled/disabled checkbox rendering across all tables)
---
RELEASE-NOTES.txt | 6 +-
.../table/BooleanTableCellRenderer.java} | 33 ++--
.../editor/dbentity/main/DbEntityMainView.java | 177 +++++++--------------
.../main/PKCustomSequenceGeneratorPanel.java | 17 +-
.../editor/dbentity/main/PKDBGeneratorPanel.java | 155 ------------------
.../editor/dbentity/main/PKGeneratorPanel.java | 84 ----------
.../dbentity/properties/DbAttributePanel.java | 3 +
.../dbentity/properties/DbAttributeTableModel.java | 82 +++++++++-
.../dbentity/properties/DbRelationshipPanel.java | 26 +--
.../objentity/properties/ObjAttributePanel.java | 3 +
.../objentity/properties/ObjRelationshipPanel.java | 3 +
11 files changed, 173 insertions(+), 416 deletions(-)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 6e1947196..ec13dfd55 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -14,8 +14,12 @@ Date:
Changes/New Features:
CAY-2998 Modeler: clickabe "Target" column to navigate relationships
-CAY-2999 Modeler: A restricted method in java.lang.System has been called
CAY-3000 Modeler: unifying the main views of all model objects
+CAY-3004 Modeler: Rework DbEntity PK generation UI to match the XML model
+
+Bug Fixes:
+
+CAY-2999 Modeler: A restricted method in java.lang.System has been called
CAY-3001 Modeler: Auto-increment attribute is not picked up
CAY-3002 Modeler: NPE after clicking path chooser
CAY-3003 Modeler: NPE editing unmapped ObjAttribute
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDefaultGeneratorPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/BooleanTableCellRenderer.java
similarity index 50%
rename from
cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDefaultGeneratorPanel.java
rename to
cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/BooleanTableCellRenderer.java
index cb93f0664..09395b507 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDefaultGeneratorPanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/BooleanTableCellRenderer.java
@@ -17,27 +17,30 @@
* under the License.
****************************************************************/
-package org.apache.cayenne.modeler.ui.project.editor.dbentity.main;
+package org.apache.cayenne.modeler.toolkit.table;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.modeler.project.ProjectSession;
+import javax.swing.JTable;
+import javax.swing.table.TableCellRenderer;
+import java.awt.Component;
-import java.awt.Dimension;
+/**
+ * Renders Boolean columns with the look and feel's own checkbox renderer,
greying out the cells that
+ * the table model reports as non-editable. The stock renderer paints those as
if they were editable.
+ */
+public class BooleanTableCellRenderer implements TableCellRenderer {
-public class PKDefaultGeneratorPanel extends PKGeneratorPanel {
-
- public PKDefaultGeneratorPanel(ProjectSession session) {
- super(session);
+ private final TableCellRenderer lafRenderer;
- // nothing to show for the default strategy, so the panel must not
take up any space either
- setPreferredSize(new Dimension(0, 0));
+ public BooleanTableCellRenderer(TableCellRenderer lafRenderer) {
+ this.lafRenderer = lafRenderer;
}
- public void setDbEntity(DbEntity entity) {
- // noop
- }
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected,
+ boolean hasFocus, int row,
int col) {
- protected void onInitInternal(DbEntity entity) {
- resetStrategy(entity, true, true);
+ Component c = lafRenderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, col);
+ c.setEnabled(table.isCellEditable(row, col));
+ return c;
}
}
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/DbEntityMainView.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/DbEntityMainView.java
index 2f7d7d0b7..41bf842ee 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/DbEntityMainView.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/DbEntityMainView.java
@@ -22,17 +22,16 @@ package
org.apache.cayenne.modeler.ui.project.editor.dbentity.main;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;
import org.apache.cayenne.configuration.DataChannelDescriptor;
-import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbKeyGenerator;
import org.apache.cayenne.modeler.event.display.DbEntityDisplayEvent;
import org.apache.cayenne.modeler.event.display.DbEntityDisplayListener;
-import org.apache.cayenne.modeler.event.model.DbAttributeEvent;
-import org.apache.cayenne.modeler.event.model.DbAttributeListener;
import org.apache.cayenne.modeler.event.model.DbEntityEvent;
import org.apache.cayenne.modeler.project.ProjectSession;
import org.apache.cayenne.modeler.service.action.GlobalActions;
import org.apache.cayenne.modeler.toolkit.ProjectPanel;
import org.apache.cayenne.modeler.toolkit.text.CMUndoableTextField;
+import org.apache.cayenne.modeler.undo.ChangePKGeneratorUndoableEdit;
import org.apache.cayenne.modeler.ui.action.CreateAttributeAction;
import org.apache.cayenne.modeler.ui.action.CreateObjEntityFromDbAction;
import org.apache.cayenne.modeler.ui.action.CreateRelationshipAction;
@@ -50,13 +49,7 @@ import java.util.EventObject;
import java.util.Objects;
public class DbEntityMainView extends ProjectPanel
- implements ExistingSelectionProcessor, DbEntityDisplayListener,
DbAttributeListener {
-
- static final String PK_DEFAULT_GENERATOR = "Cayenne-Generated (Default)";
- static final String PK_DB_GENERATOR = "Database-Generated";
- static final String PK_CUSTOM_SEQUENCE_GENERATOR = "Custom Sequence";
-
- static final String[] PK_GENERATOR_TYPES = { PK_DEFAULT_GENERATOR,
PK_DB_GENERATOR, PK_CUSTOM_SEQUENCE_GENERATOR };
+ implements ExistingSelectionProcessor, DbEntityDisplayListener {
private final CMUndoableTextField name;
private final CMUndoableTextField catalog;
@@ -67,9 +60,8 @@ public class DbEntityMainView extends ProjectPanel
private final JLabel catalogLabel;
private final JLabel schemaLabel;
- private final JComboBox<String> pkGeneratorType;
- private final JPanel pkGeneratorDetail;
- private final CardLayout pkGeneratorDetailLayout;
+ private final JCheckBox customPKSequence;
+ private final PKCustomSequenceGeneratorPanel customPKSequencePanel;
private final JToolBar toolBar;
@@ -83,22 +75,8 @@ public class DbEntityMainView extends ProjectPanel
schema = new CMUndoableTextField(app.getUndoManager());
qualifier = new CMUndoableTextField(app.getUndoManager());
comment = new CMUndoableTextField(app.getUndoManager());
- pkGeneratorType = new JComboBox<>();
- pkGeneratorDetailLayout = new CardLayout();
-
- // unlike a plain CardLayout panel, this one takes the height of the
visible card only, so that
- // the comment row below it follows the PK fields instead of leaving a
gap under the short cards
- pkGeneratorDetail = new JPanel(pkGeneratorDetailLayout) {
- @Override
- public Dimension getPreferredSize() {
- for (Component card : getComponents()) {
- if (card.isVisible()) {
- return card.getPreferredSize();
- }
- }
- return super.getPreferredSize();
- }
- };
+ customPKSequence = new JCheckBox();
+ customPKSequencePanel = new PKCustomSequenceGeneratorPanel(session);
initLayout();
initBindings();
}
@@ -114,12 +92,6 @@ public class DbEntityMainView extends ProjectPanel
toolBar.add(globalActions.getAction(DbEntitySyncAction.class).buildButton(2));
toolBar.add(globalActions.getAction(DbEntityCounterpartAction.class).buildButton(3));
- pkGeneratorType.setEditable(false);
- pkGeneratorType.setModel(new
DefaultComboBoxModel<>(PK_GENERATOR_TYPES));
- pkGeneratorDetail.add(new PKDefaultGeneratorPanel(session),
PK_DEFAULT_GENERATOR);
- pkGeneratorDetail.add(new PKDBGeneratorPanel(session),
PK_DB_GENERATOR);
- pkGeneratorDetail.add(new PKCustomSequenceGeneratorPanel(session),
PK_CUSTOM_SEQUENCE_GENERATOR);
-
FormLayout layout = new FormLayout(EditorForm.LABEL_COLUMN + ",
$lcgap, fill:200dlu", "");
DefaultFormBuilder builder = new DefaultFormBuilder(layout);
builder.setBorder(EditorForm.formBorder());
@@ -127,16 +99,18 @@ public class DbEntityMainView extends ProjectPanel
builder.append(catalogLabel, catalog);
builder.append(schemaLabel, schema);
builder.append("Qualifier:", qualifier);
- builder.append("PK Strategy:", pkGeneratorType);
+ builder.append("Custom PK Sequence:", customPKSequence);
- // the comment goes last, below the PK generator panel, which varies
with the selected strategy
+ // the comment goes last, below the sequence panel, which is only
shown when the box is checked
DefaultFormBuilder commentBuilder = new DefaultFormBuilder(
new FormLayout(EditorForm.LABEL_COLUMN + ", $lcgap,
fill:200dlu", ""));
commentBuilder.setBorder(EditorForm.lastSectionBorder());
commentBuilder.append("Comment:", comment);
+ customPKSequencePanel.setVisible(false);
+
JPanel pkAndComment = new JPanel(new BorderLayout());
- pkAndComment.add(pkGeneratorDetail, BorderLayout.NORTH);
+ pkAndComment.add(customPKSequencePanel, BorderLayout.NORTH);
pkAndComment.add(commentBuilder.getPanel(), BorderLayout.CENTER);
JPanel mainPanel = new JPanel(new BorderLayout());
@@ -148,24 +122,6 @@ public class DbEntityMainView extends ProjectPanel
add(mainPanel, BorderLayout.CENTER);
}
- /**
- * Returns the PK generator card currently in front of the CardLayout, or
null if none is showing.
- */
- private PKGeneratorPanel visiblePKGeneratorPanel() {
- for (Component card : pkGeneratorDetail.getComponents()) {
- if (card.isVisible()) {
- return (PKGeneratorPanel) card;
- }
- }
- return null;
- }
-
- private void showPKGeneratorDetail(String type) {
- pkGeneratorDetailLayout.show(pkGeneratorDetail, type);
- // cards differ in height, so the panels below have to be laid out
again
- pkGeneratorDetail.revalidate();
- }
-
private void initBindings() {
name.addCommitListener(this::setEntityName);
catalog.addCommitListener(this::setCatalog);
@@ -173,14 +129,49 @@ public class DbEntityMainView extends ProjectPanel
qualifier.addCommitListener(this::setQualifier);
comment.addCommitListener(this::setComment);
session.addDbEntityDisplayListener(this);
- session.addDbAttributeListener(this);
- pkGeneratorType.addItemListener(e -> {
- showPKGeneratorDetail((String) pkGeneratorType.getSelectedItem());
- PKGeneratorPanel panel = visiblePKGeneratorPanel();
- if (panel != null) {
- panel.onInit(session.getSelectedDbEntity());
+ customPKSequence.addActionListener(e ->
setCustomPKSequence(customPKSequence.isSelected()));
+ }
+
+ /**
+ * Attaches or drops the entity's own PK sequence generator. This is
independent of the
+ * "Auto-Increment" attribute flag, matching the map XML, where
"db-key-generator" and
+ * "db-attribute/@isGenerated" are unrelated.
+ */
+ private void setCustomPKSequence(boolean custom) {
+
+ DbEntity entity = session.getSelectedDbEntity();
+
+ if (entity == null) {
+ return;
+ }
+
+ ChangePKGeneratorUndoableEdit edit = new
ChangePKGeneratorUndoableEdit(session, entity);
+ edit.captureOldState();
+
+ if (custom) {
+ if (entity.getPrimaryKeyGenerator() == null) {
+ DbKeyGenerator generator = new DbKeyGenerator();
+ generator.setGeneratorType(DbKeyGenerator.ORACLE_TYPE);
+ entity.setPrimaryKeyGenerator(generator);
}
- });
+ } else {
+ entity.setPrimaryKeyGenerator(null);
+ }
+
+ showCustomPKSequencePanel(entity, custom);
+ session.fireDbEntityEvent(DbEntityEvent.ofChange(this, entity));
+
+ edit.captureNewState();
+ if (edit.hasRealChange()) {
+ app.getUndoManager().addEdit(edit);
+ }
+ }
+
+ private void showCustomPKSequencePanel(DbEntity entity, boolean visible) {
+ customPKSequencePanel.setDbEntity(entity);
+ customPKSequencePanel.setVisible(visible);
+ // the panel appearing or collapsing shifts everything below it
+ customPKSequencePanel.getParent().revalidate();
}
public void processExistingSelection(EventObject e) {
@@ -198,40 +189,22 @@ public class DbEntityMainView extends ProjectPanel
return;
}
- // if entity hasn't changed, still notify PK Generator panels, as
entity PK may have changed...
- for (int i = 0; i < pkGeneratorDetail.getComponentCount(); i++) {
- ((PKGeneratorPanel)
pkGeneratorDetail.getComponent(i)).setDbEntity(entity);
- }
-
name.setText(entity.getName());
catalog.setText(entity.getCatalog());
schema.setText(entity.getSchema());
qualifier.setText(ExpressionConvertor.asString(entity.getQualifier()));
comment.setText(getComment(entity));
- String type = PK_DEFAULT_GENERATOR;
-
- if (entity.getPrimaryKeyGenerator() != null) {
- type = PK_CUSTOM_SEQUENCE_GENERATOR;
- } else {
- for (DbAttribute a : entity.getPrimaryKeys()) {
- if (a.isGenerated()) {
- type = PK_DB_GENERATOR;
- break;
- }
- }
- }
-
catalogLabel.setEnabled(true);
catalog.setEnabled(true);
schemaLabel.setEnabled(true);
schema.setEnabled(true);
- pkGeneratorDetail.setVisible(true);
- pkGeneratorType.setVisible(true);
- pkGeneratorType.setSelectedItem(type);
- showPKGeneratorDetail(type);
+ // setSelected() does not fire an ActionEvent, so this doesn't loop
back into the model
+ boolean custom = entity.getPrimaryKeyGenerator() != null;
+ customPKSequence.setSelected(custom);
+ showCustomPKSequencePanel(entity, custom);
if(entity.getDataMap().getMappedEntities(entity).isEmpty()) {
toolBar.getComponentAtIndex(4).setEnabled(false);
@@ -242,40 +215,6 @@ public class DbEntityMainView extends ProjectPanel
}
}
- @Override
- public void dbAttributeAdded(DbAttributeEvent e) {
- refreshPKGenerator(e);
- }
-
- @Override
- public void dbAttributeChanged(DbAttributeEvent e) {
- refreshPKGenerator(e);
- }
-
- @Override
- public void dbAttributeRemoved(DbAttributeEvent e) {
- refreshPKGenerator(e);
- }
-
- /**
- * The PK generator panels are driven by the entity attributes, so they
must be resynced whenever
- * attributes change, and not just on entity selection. Without this the
"Auto Increment" column
- * list goes stale as soon as PKs are added or removed from the Properties
tab.
- */
- private void refreshPKGenerator(DbAttributeEvent e) {
- DbEntity entity = session.getSelectedDbEntity();
-
- // attributes of some other entity, or a non-DbEntity node is selected
- if (entity == null || e.getEntity() != entity) {
- return;
- }
-
- PKGeneratorPanel panel = visiblePKGeneratorPanel();
- if (panel != null) {
- panel.onInit(entity);
- }
- }
-
void setEntityName(String newName) {
if (newName != null && newName.trim().isEmpty()) {
newName = null;
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKCustomSequenceGeneratorPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKCustomSequenceGeneratorPanel.java
index c4dbb5130..78a00fd1e 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKCustomSequenceGeneratorPanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKCustomSequenceGeneratorPanel.java
@@ -24,6 +24,7 @@ import com.jgoodies.forms.layout.FormLayout;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbKeyGenerator;
import org.apache.cayenne.modeler.event.model.DbEntityEvent;
+import org.apache.cayenne.modeler.toolkit.ProjectPanel;
import org.apache.cayenne.modeler.toolkit.text.CMUndoableTextField;
import org.apache.cayenne.modeler.project.ProjectSession;
import java.util.Objects;
@@ -33,7 +34,7 @@ import org.apache.cayenne.validation.ValidationException;
import javax.swing.*;
import java.awt.*;
-public class PKCustomSequenceGeneratorPanel extends PKGeneratorPanel {
+public class PKCustomSequenceGeneratorPanel extends ProjectPanel {
protected CMUndoableTextField customPKName;
protected CMUndoableTextField customPKSize;
@@ -71,18 +72,6 @@ public class PKCustomSequenceGeneratorPanel extends
PKGeneratorPanel {
add(builder.getPanel(), BorderLayout.CENTER);
}
- protected void onInitInternal(DbEntity entity) {
- resetStrategy(entity, false, true);
-
- if (entity.getPrimaryKeyGenerator() == null) {
- DbKeyGenerator generator = new DbKeyGenerator();
- generator.setGeneratorType(DbKeyGenerator.ORACLE_TYPE);
- entity.setPrimaryKeyGenerator(generator);
- } else {
- setDbEntity(entity);
- }
- }
-
public void setDbEntity(DbEntity entity) {
DbKeyGenerator generator = entity.getPrimaryKeyGenerator();
@@ -133,7 +122,7 @@ public class PKCustomSequenceGeneratorPanel extends
PKGeneratorPanel {
}
DbKeyGenerator generator =
session.getSelectedDbEntity().getPrimaryKeyGenerator();
- if (!Objects.equals(text, generator.getName())) {
+ if (!Objects.equals(text, generator.getGeneratorName())) {
generator.setGeneratorName(text);
session.fireDbEntityEvent(DbEntityEvent.ofChange(this,
generator.getDbEntity()));
}
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDBGeneratorPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDBGeneratorPanel.java
deleted file mode 100644
index 15ecefae8..000000000
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKDBGeneratorPanel.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * https://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 org.apache.cayenne.modeler.ui.project.editor.dbentity.main;
-
-import com.jgoodies.forms.builder.DefaultFormBuilder;
-import com.jgoodies.forms.layout.FormLayout;
-import org.apache.cayenne.dba.TypesMapping;
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.modeler.event.model.DbEntityEvent;
-import org.apache.cayenne.modeler.project.ProjectSession;
-import org.apache.cayenne.modeler.ui.project.editor.EditorForm;
-
-import javax.swing.*;
-import javax.swing.plaf.basic.BasicComboBoxRenderer;
-import java.awt.*;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.Collection;
-
-public class PKDBGeneratorPanel extends PKGeneratorPanel {
-
- private final JComboBox<Object> attributes;
-
- public PKDBGeneratorPanel(ProjectSession session) {
- super(session);
- this.attributes = new JComboBox<>();
- initLayout();
- }
-
- private void initLayout() {
- attributes.setEditable(false);
- attributes.setRenderer(new AttributeRenderer());
-
- DefaultFormBuilder builder = new DefaultFormBuilder(new FormLayout(
- EditorForm.LABEL_COLUMN + ", $lcgap, fill:200dlu",
- ""));
- builder.setBorder(EditorForm.sectionBorder());
- builder.append("Auto Increment:", attributes);
-
- setLayout(new BorderLayout());
- add(builder.getPanel(), BorderLayout.CENTER);
- }
-
- public void setDbEntity(DbEntity entity) {
- // refresh only if this entity
- if (isVisible()) {
- updateView(entity);
- }
- }
-
- protected void onInitInternal(DbEntity entity) {
- resetStrategy(entity, true, false);
-
- Collection pkAttributes = entity.getPrimaryKeys();
-
- // by default check the only numeric PK
- if (pkAttributes.size() == 1) {
- DbAttribute pk = (DbAttribute) pkAttributes.iterator().next();
- if (TypesMapping.isNumeric(pk.getType()) && !pk.isGenerated()) {
- pk.setGenerated(true);
- session.fireDbEntityEvent(DbEntityEvent.ofChange(this,
entity));
- }
- }
-
- updateView(entity);
- }
-
- void updateView(final DbEntity entity) {
- for (ItemListener listener : attributes.getItemListeners()) {
- attributes.removeItemListener(listener);
- }
-
- Collection<DbAttribute> pkAttributes = entity.getPrimaryKeys();
- if (pkAttributes.isEmpty()) {
- attributes.removeAllItems();
- attributes.addItem("<Entity has no PK columns>");
- attributes.setSelectedIndex(0);
- attributes.setEnabled(false);
- }
- else {
-
- attributes.setEnabled(true);
- MutableComboBoxModel<Object> model = new
DefaultComboBoxModel<>(pkAttributes.toArray());
- String noSelection = "<Select Generated Column>";
- model.insertElementAt(noSelection, 0);
- model.setSelectedItem(noSelection);
- attributes.setModel(model);
-
- for (DbAttribute a : pkAttributes) {
- if (a.isGenerated()) {
- model.setSelectedItem(a);
- break;
- }
- }
-
- // listen for selection changes of the new entity
- attributes.addItemListener(e -> {
- Object item = e.getItem();
- if (item instanceof DbAttribute a) {
-
- boolean generated = e.getStateChange() ==
ItemEvent.SELECTED;
-
- if (a.isGenerated() != generated) {
- a.setGenerated(generated);
- session.fireDbEntityEvent(DbEntityEvent.ofChange(this,
entity));
- }
- }
- });
- }
-
- // revalidate as children layout has changed...
- revalidate();
- }
-
- static class AttributeRenderer extends BasicComboBoxRenderer {
-
- public Component getListCellRendererComponent(
- JList list,
- Object value,
- int index,
- boolean isSelected,
- boolean cellHasFocus) {
-
- if (value instanceof DbAttribute a) {
- String type = TypesMapping.getSqlNameByType(a.getType());
- value = a.getName() + " (" + (type != null ? type : "?") + ")";
- }
-
- return super.getListCellRendererComponent(
- list,
- value,
- index,
- isSelected,
- cellHasFocus);
- }
- }
-}
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKGeneratorPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKGeneratorPanel.java
deleted file mode 100644
index 4c86d1511..000000000
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/main/PKGeneratorPanel.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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
- *
- * https://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 org.apache.cayenne.modeler.ui.project.editor.dbentity.main;
-
-import org.apache.cayenne.map.DbAttribute;
-import org.apache.cayenne.map.DbEntity;
-import org.apache.cayenne.modeler.event.model.DbEntityEvent;
-import org.apache.cayenne.modeler.project.ProjectSession;
-import org.apache.cayenne.modeler.toolkit.ProjectPanel;
-import org.apache.cayenne.modeler.undo.ChangePKGeneratorUndoableEdit;
-
-public abstract class PKGeneratorPanel extends ProjectPanel {
-
- public PKGeneratorPanel(ProjectSession session) {
- super(session);
- }
-
- /**
- * Called by parent when DbEntity changes, regardless of whether this
panel is visible
- * or not. Another case when this method is invoked is when entity tab
changes and
- * this panel may need a refresh.
- */
- public abstract void setDbEntity(DbEntity entity);
-
- /**
- * Called by parent when the panel becomes visible.
- */
- public void onInit(DbEntity entity) {
- ChangePKGeneratorUndoableEdit edit = new
ChangePKGeneratorUndoableEdit(session, entity);
- edit.captureOldState();
-
- onInitInternal(entity);
-
- edit.captureNewState();
- if (edit.hasRealChange()) {
- app.getUndoManager().addEdit(edit);
- }
- }
-
- protected abstract void onInitInternal(DbEntity entity);
-
- protected void resetStrategy(
- DbEntity entity,
- boolean resetCustomSequence,
- boolean resetDBGenerated) {
-
- boolean hasChanges = false;
-
- if (resetCustomSequence && entity.getPrimaryKeyGenerator() != null) {
- entity.setPrimaryKeyGenerator(null);
- hasChanges = true;
- }
-
- if (resetDBGenerated) {
- for (DbAttribute a : entity.getPrimaryKeys()) {
- if (a.isGenerated()) {
- a.setGenerated(false);
- hasChanges = true;
- }
- }
- }
-
- if (hasChanges) {
- session.fireDbEntityEvent(DbEntityEvent.ofChange(this, entity));
- }
- }
-}
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
index be320c60a..83da5c138 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java
@@ -33,6 +33,7 @@ import org.apache.cayenne.modeler.toolkit.ProjectPanel;
import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion;
import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox;
import org.apache.cayenne.modeler.toolkit.table.BoardTableCellRenderer;
+import org.apache.cayenne.modeler.toolkit.table.BooleanTableCellRenderer;
import
org.apache.cayenne.modeler.toolkit.combobox.CMAutoCompleteComboBoxCellEditor;
import org.apache.cayenne.modeler.toolkit.table.CMTable;
import org.apache.cayenne.modeler.toolkit.table.CMTablePanel;
@@ -74,6 +75,8 @@ public class DbAttributePanel extends ProjectPanel implements
DbEntityDisplayLis
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setDefaultRenderer(String.class, new BoardTableCellRenderer());
+ table.setDefaultRenderer(Boolean.class,
+ new
BooleanTableCellRenderer(table.getDefaultRenderer(Boolean.class)));
JPopupMenu popup = new JPopupMenu();
popup.add(globalActions.getAction(RemoveAttributeRelationshipAction.class).buildMenu());
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributeTableModel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributeTableModel.java
index c726389fa..72b9721a2 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributeTableModel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributeTableModel.java
@@ -27,6 +27,7 @@ import
org.apache.cayenne.modeler.event.model.DbAttributeEvent;
import org.apache.cayenne.modeler.project.DbAttributeOps;
import org.apache.cayenne.modeler.toolkit.table.CMTableModel;
import org.apache.cayenne.modeler.project.ProjectSession;
+import org.apache.cayenne.modeler.undo.ChangePKGeneratorUndoableEdit;
import org.apache.cayenne.project.extension.info.ObjectInfo;
import java.util.Objects;
@@ -34,6 +35,7 @@ import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
/**
* Model for DbEntity attributes. Allows adding/removing attributes, modifying
types and names.
@@ -43,10 +45,11 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
static final int DB_ATTRIBUTE_NAME = 0;
static final int DB_ATTRIBUTE_TYPE = 1;
static final int DB_ATTRIBUTE_PRIMARY_KEY = 2;
- static final int DB_ATTRIBUTE_MANDATORY = 3;
- static final int DB_ATTRIBUTE_MAX = 4;
- static final int DB_ATTRIBUTE_SCALE = 5;
- static final int DB_ATTRIBUTE_COMMENT = 6;
+ static final int DB_ATTRIBUTE_AUTO_INCREMENT = 3;
+ static final int DB_ATTRIBUTE_MANDATORY = 4;
+ static final int DB_ATTRIBUTE_MAX = 5;
+ static final int DB_ATTRIBUTE_SCALE = 6;
+ static final int DB_ATTRIBUTE_COMMENT = 7;
private final DbEntity entity;
@@ -62,7 +65,7 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
@Override
public int getColumnCount() {
- return 7;
+ return 8;
}
public DbAttribute getAttribute(int row) {
@@ -79,6 +82,8 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
return "Type";
case DB_ATTRIBUTE_PRIMARY_KEY:
return "PK";
+ case DB_ATTRIBUTE_AUTO_INCREMENT:
+ return "Auto-Increment";
case DB_ATTRIBUTE_SCALE:
return "Scale";
case DB_ATTRIBUTE_MANDATORY:
@@ -96,6 +101,7 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
public Class<?> getColumnClass(int col) {
switch (col) {
case DB_ATTRIBUTE_PRIMARY_KEY:
+ case DB_ATTRIBUTE_AUTO_INCREMENT:
case DB_ATTRIBUTE_MANDATORY:
return Boolean.class;
default:
@@ -117,6 +123,8 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
return getAttributeType(attr);
case DB_ATTRIBUTE_PRIMARY_KEY:
return isPrimaryKey(attr);
+ case DB_ATTRIBUTE_AUTO_INCREMENT:
+ return isGenerated(attr);
case DB_ATTRIBUTE_SCALE:
return getScale(attr);
case DB_ATTRIBUTE_MANDATORY:
@@ -130,6 +138,32 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
}
}
+ @Override
+ public void setValueAt(Object newVal, int row, int col) {
+
+ // Auto-Increment is an entity-wide setting: turning it on for one
attribute turns it off for
+ // another one. The single-cell edit registered by the superclass
can't restore that, so use the
+ // edit that captures the entity PK generation state as a whole.
+ if (col == DB_ATTRIBUTE_AUTO_INCREMENT) {
+ if (Objects.deepEquals(newVal, getValueAt(row, col))) {
+ return;
+ }
+
+ ChangePKGeneratorUndoableEdit edit = new
ChangePKGeneratorUndoableEdit(session, entity);
+ edit.captureOldState();
+
+ setUpdatedValueAt(newVal, row, col);
+
+ edit.captureNewState();
+ if (edit.hasRealChange()) {
+ session.app().getUndoManager().addEdit(edit);
+ }
+ return;
+ }
+
+ super.setValueAt(newVal, row, col);
+ }
+
public void setUpdatedValueAt(Object newVal, int row, int col) {
DbAttribute attr = getAttribute(row);
if (attr == null) {
@@ -151,6 +185,9 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
return;
}
break;
+ case DB_ATTRIBUTE_AUTO_INCREMENT:
+ setGenerated((Boolean) newVal, attr);
+ break;
case DB_ATTRIBUTE_SCALE:
setScale((String) newVal, attr);
break;
@@ -202,6 +239,10 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
return (attr.isPrimaryKey()) ? Boolean.TRUE : Boolean.FALSE;
}
+ public Boolean isGenerated(DbAttribute attr) {
+ return (attr.isGenerated()) ? Boolean.TRUE : Boolean.FALSE;
+ }
+
public Boolean isMandatory(DbAttribute attr) {
return (attr.isMandatory()) ? Boolean.TRUE : Boolean.FALSE;
}
@@ -287,10 +328,35 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
if (flag) {
attr.setMandatory(true);
fireTableCellUpdated(row, DB_ATTRIBUTE_MANDATORY);
+ } else {
+ fireTableCellUpdated(row, DB_ATTRIBUTE_AUTO_INCREMENT);
}
return true;
}
+ /**
+ * An entity can have at most one generated attribute, so setting this
flag clears it on all the
+ * other attributes.
+ */
+ public void setGenerated(Boolean newVal, DbAttribute attr) {
+
+ if (newVal) {
+ // copy, as setGenerated() mutates the entity's own collection
+ List<DbAttribute> generated = new
ArrayList<>(entity.getGeneratedAttributes());
+ for (DbAttribute other : generated) {
+ if (other != attr) {
+ other.setGenerated(false);
+ int otherRow = objectList.indexOf(other);
+ if (otherRow >= 0) {
+ fireTableCellUpdated(otherRow,
DB_ATTRIBUTE_AUTO_INCREMENT);
+ }
+ }
+ }
+ }
+
+ attr.setGenerated(newVal);
+ }
+
public void setMandatory(Boolean newVal, DbAttribute attr) {
attr.setMandatory(newVal);
}
@@ -305,6 +371,9 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
return false;
} else if (col == DB_ATTRIBUTE_MANDATORY) {
return !attrib.isPrimaryKey();
+ } else if (col == DB_ATTRIBUTE_AUTO_INCREMENT) {
+ // DbAttribute.encodeAsXML() only stores "isGenerated" for PKs, so
don't let it be set elsewhere
+ return attrib.isPrimaryKey();
}
return true;
}
@@ -343,6 +412,9 @@ public class DbAttributeTableModel extends
CMTableModel<DbAttribute> {
case DB_ATTRIBUTE_PRIMARY_KEY:
sortByElementProperty("primaryKey", isAscent);
break;
+ case DB_ATTRIBUTE_AUTO_INCREMENT:
+ sortByElementProperty("generated", isAscent);
+ break;
case DB_ATTRIBUTE_SCALE:
sortByElementProperty("scale", isAscent);
break;
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
index d486ec1d7..9b4ae3140 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java
@@ -41,6 +41,7 @@ import
org.apache.cayenne.modeler.event.display.DbRelationshipDisplayEvent;
import org.apache.cayenne.modeler.event.display.TablePopupHandler;
import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs;
import org.apache.cayenne.modeler.toolkit.table.BoardTableCellRenderer;
+import org.apache.cayenne.modeler.toolkit.table.BooleanTableCellRenderer;
import org.apache.cayenne.modeler.toolkit.table.CMTable;
import org.apache.cayenne.modeler.toolkit.table.CMTablePanel;
import org.apache.cayenne.modeler.toolkit.Renderers;
@@ -52,7 +53,6 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
-import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -90,6 +90,8 @@ public class DbRelationshipPanel extends ProjectPanel
implements DbEntityDisplay
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setDefaultRenderer(DbEntity.class,
Renderers.entityTableRendererWithIcons(session));
table.setDefaultRenderer(String.class, new BoardTableCellRenderer());
+ table.setDefaultRenderer(Boolean.class,
+ new
BooleanTableCellRenderer(table.getDefaultRenderer(Boolean.class)));
JPopupMenu popup = new JPopupMenu();
popup.add(editMenu);
@@ -241,9 +243,6 @@ public class DbRelationshipPanel extends ProjectPanel
implements DbEntityDisplay
TableColumn targetColumn =
table.getColumnModel().getColumn(DbRelationshipTableModel.TARGET);
targetColumn.setCellEditor(new
CMAutoCompleteComboBoxCellEditor(targetCombo));
- TableColumn toDepPkColumn =
table.getColumnModel().getColumn(DbRelationshipTableModel.TO_DEPENDENT_KEY);
- toDepPkColumn.setCellRenderer(new CheckBoxCellRenderer());
-
new
CMTablePrefs(app.getPrefsManager().uiNode("dbEntity/relationshipTable"))
.bind(table, null, DbRelationshipTableModel.NAME);
}
@@ -371,23 +370,4 @@ public class DbRelationshipPanel extends ProjectPanel
implements DbEntityDisplay
parentPanel.updateActions(rels);
}
-
- private static class CheckBoxCellRenderer implements TableCellRenderer {
-
- private final JCheckBox renderer;
-
- public CheckBoxCellRenderer() {
- renderer = new JCheckBox();
- renderer.setHorizontalAlignment(SwingConstants.CENTER);
- }
-
- @Override
- public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column) {
- Color color = isSelected ? table.getSelectionBackground() :
table.getBackground();
- renderer.setBackground(color);
- renderer.setEnabled(table.isCellEditable(row, column));
- renderer.setSelected(value != null && (Boolean) value);
- return renderer;
- }
- }
}
\ No newline at end of file
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
index 1ef32f16f..8b243a4b1 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java
@@ -33,6 +33,7 @@ import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
import org.apache.cayenne.modeler.event.model.ObjEntityListener;
import org.apache.cayenne.modeler.event.model.ProjectBeforeSaveEvent;
import org.apache.cayenne.modeler.event.model.ProjectBeforeSaveListener;
+import org.apache.cayenne.modeler.toolkit.table.BooleanTableCellRenderer;
import org.apache.cayenne.modeler.toolkit.ProjectPanel;
import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs;
import org.apache.cayenne.modeler.project.ObjEntityOps;
@@ -99,6 +100,8 @@ public class ObjAttributePanel extends ProjectPanel
implements ObjEntityDisplayL
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setDefaultRenderer(String.class, new CellRenderer());
+ table.setDefaultRenderer(Boolean.class,
+ new
BooleanTableCellRenderer(table.getDefaultRenderer(Boolean.class)));
JPopupMenu popup = new JPopupMenu();
popup.add(editMenu);
diff --git
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
index 1e0ba6a0a..90fbc2ebc 100644
---
a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
+++
b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java
@@ -26,6 +26,7 @@ import
org.apache.cayenne.modeler.event.model.ObjRelationshipEvent;
import org.apache.cayenne.modeler.event.model.ObjEntityEvent;
import org.apache.cayenne.modeler.event.model.ObjEntityListener;
import org.apache.cayenne.modeler.event.model.ObjRelationshipListener;
+import org.apache.cayenne.modeler.toolkit.table.BooleanTableCellRenderer;
import org.apache.cayenne.modeler.toolkit.ProjectPanel;
import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox;
import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor;
@@ -94,6 +95,8 @@ public class ObjRelationshipPanel extends ProjectPanel
implements ObjEntityDispl
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setDefaultRenderer(String.class, new StringRenderer());
+ table.setDefaultRenderer(Boolean.class,
+ new
BooleanTableCellRenderer(table.getDefaultRenderer(Boolean.class)));
table.setDefaultRenderer(ObjEntity.class, new EntityRenderer());
JPopupMenu popup = new JPopupMenu();