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.
      */

Reply via email to