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 5931f584a CAY-2998 Modeler: clickabe "Target" column to navigate
relationships
5931f584a is described below
commit 5931f584a036713fb2c5ca28c617ed782fb873f5
Author: Andrus Adamchik <[email protected]>
AuthorDate: Sat Aug 29 13:15:32 2026 -0400
CAY-2998 Modeler: clickabe "Target" column to navigate relationships
---
RELEASE-NOTES.txt | 8 ++++
.../dbentity/properties/DbRelationshipPanel.java | 51 ++++++++++++++++++++++
.../objentity/properties/ObjRelationshipPanel.java | 47 ++++++++++++++++++++
3 files changed, 106 insertions(+)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 468f612c7..0810d989c 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -7,6 +7,14 @@ https://cayenne.apache.org/
To browse individual bug reports check out project issue tracker:
https://issues.apache.org/jira/browse/CAY
+----------------------------------
+Release: 5.0-M4
+Date:
+----------------------------------
+Changes/New Features:
+
+CAY-2998 Modeler: clickabe "Target" column to navigate relationships
+
----------------------------------
Release: 5.0-M3
Date: Aug 21, 2026
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 5258cb378..d486ec1d7 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
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.modeler.ui.project.editor.dbentity.properties;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.EntityResolver;
@@ -55,6 +56,9 @@ import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
import java.util.List;
/**
@@ -100,6 +104,24 @@ public class DbRelationshipPanel extends ProjectPanel
implements DbEntityDisplay
}
private void initBindings() {
+ table.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2 &&
isTargetColumn(table.columnAtPoint(e.getPoint()))) {
+ openTarget(targetAt(table.rowAtPoint(e.getPoint())));
+ }
+ }
+ });
+
+ table.addMouseMotionListener(new MouseMotionAdapter() {
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ boolean link =
isTargetColumn(table.columnAtPoint(e.getPoint()))
+ && targetAt(table.rowAtPoint(e.getPoint())) != null;
+ table.setCursor(Cursor.getPredefinedCursor(link ?
Cursor.HAND_CURSOR : Cursor.DEFAULT_CURSOR));
+ }
+ });
+
session.addDbEntityDisplayListener(this);
session.addDbEntityListener(this);
session.addDbRelationshipListener(this);
@@ -118,6 +140,35 @@ public class DbRelationshipPanel extends ProjectPanel
implements DbEntityDisplay
return table;
}
+ private boolean isTargetColumn(int viewColumn) {
+ return viewColumn >= 0
+ &&
table.getColumnModel().getColumn(viewColumn).getModelIndex() ==
DbRelationshipTableModel.TARGET;
+ }
+
+ private DbEntity targetAt(int row) {
+ if (row < 0 || !(table.getModel() instanceof DbRelationshipTableModel
model)) {
+ return null;
+ }
+ DbRelationship relationship = model.getRelationship(row);
+ return relationship != null ? relationship.getTargetEntity() : null;
+ }
+
+ /**
+ * Navigates to the entity on the other end of the relationship.
+ */
+ private void openTarget(DbEntity target) {
+ if (target == null) {
+ return;
+ }
+
+ DataChannelDescriptor domain = (DataChannelDescriptor)
session.project().getRootNode();
+ session.displayDbEntity(new DbEntityDisplayEvent(
+ app.getFrame().getProjectView().getProjectTreeView(),
+ domain,
+ target.getDataMap(),
+ target));
+ }
+
@Override
public void tableChanged(TableModelEvent e) {
if (table.getSelectedRow() >= 0) {
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 d55768ef4..1e0ba6a0a 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
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.modeler.ui.project.editor.objentity.properties;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.map.DeleteRule;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.ObjRelationship;
@@ -55,6 +56,7 @@ import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
import java.util.List;
/**
@@ -123,6 +125,22 @@ public class ObjRelationshipPanel extends ProjectPanel
implements ObjEntityDispl
}
}
}
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount() == 2 &&
isTargetColumn(table.columnAtPoint(e.getPoint()))) {
+ openTarget(targetAt(table.rowAtPoint(e.getPoint())));
+ }
+ }
+ });
+
+ table.addMouseMotionListener(new MouseMotionAdapter() {
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ boolean link =
isTargetColumn(table.columnAtPoint(e.getPoint()))
+ && targetAt(table.rowAtPoint(e.getPoint())) != null;
+ table.setCursor(Cursor.getPredefinedCursor(link ?
Cursor.HAND_CURSOR : Cursor.DEFAULT_CURSOR));
+ }
});
editMenu.addActionListener(this::edit);
@@ -143,6 +161,35 @@ public class ObjRelationshipPanel extends ProjectPanel
implements ObjEntityDispl
return table;
}
+ private boolean isTargetColumn(int viewColumn) {
+ return viewColumn >= 0
+ &&
table.getColumnModel().getColumn(viewColumn).getModelIndex() ==
ObjRelationshipTableModel.REL_TARGET;
+ }
+
+ private ObjEntity targetAt(int row) {
+ if (row < 0 || !(table.getModel() instanceof ObjRelationshipTableModel
model)) {
+ return null;
+ }
+ ObjRelationship relationship = model.getRelationship(row);
+ return relationship != null ? relationship.getTargetEntity() : null;
+ }
+
+ /**
+ * Navigates to the entity on the other end of the relationship.
+ */
+ private void openTarget(ObjEntity target) {
+ if (target == null) {
+ return;
+ }
+
+ DataChannelDescriptor domain = (DataChannelDescriptor)
session.project().getRootNode();
+ session.displayObjEntity(new ObjEntityDisplayEvent(
+ app.getFrame().getProjectView().getProjectTreeView(),
+ domain,
+ target.getDataMap(),
+ target));
+ }
+
/**
* Selects a specified relationship in the relationships table.
*/