From 46e85e4b2db0de3d3590af45af713ebeab040069 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Mon, 26 Mar 2018 14:20:53 +0200 Subject: [PATCH] Improve Eclipse 4 edition lifecycle --- org.argeo.suite.e4/META-INF/MANIFEST.MF | 7 + org.argeo.suite.e4/e4xmi/argeo-office.e4xmi | 30 +- .../e4/parts/AbstractSuiteDashboard.java | 161 +++++++ .../e4/parts/DefaultDashboardEditor.java | 401 ++++++++++++++++++ 4 files changed, 592 insertions(+), 7 deletions(-) create mode 100644 org.argeo.suite.e4/src/org/argeo/suite/e4/parts/AbstractSuiteDashboard.java create mode 100644 org.argeo.suite.e4/src/org/argeo/suite/e4/parts/DefaultDashboardEditor.java diff --git a/org.argeo.suite.e4/META-INF/MANIFEST.MF b/org.argeo.suite.e4/META-INF/MANIFEST.MF index b5f2931..3531127 100644 --- a/org.argeo.suite.e4/META-INF/MANIFEST.MF +++ b/org.argeo.suite.e4/META-INF/MANIFEST.MF @@ -12,6 +12,8 @@ Import-Package: javax.inject;version="1.0.0", org.apache.commons.logging;version="1.1.1", org.argeo.activities;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.activities.ui;version="2.1.79.SNAPSHOT-r201803241506", + org.argeo.cms.auth;version="2.1.73.SNAPSHOT-r201803221729", + org.argeo.cms.ui.eclipse.forms;version="2.1.73.SNAPSHOT-r201803221729", org.argeo.cms.util;version="2.1.73.SNAPSHOT-r201803221729", org.argeo.connect;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.connect.e4.handlers, @@ -22,12 +24,17 @@ Import-Package: javax.inject;version="1.0.0", org.argeo.connect.util;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.eclipse.ui;version="2.1.73.SNAPSHOT-r201803221729", org.argeo.jcr;version="2.1.73.SNAPSHOT-r201803221729", + org.argeo.node;version="2.1.0", org.argeo.people;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.people.e4, org.argeo.people.e4.parts, org.argeo.people.ui.providers;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.tracker;version="2.1.79.SNAPSHOT-r201803241506", + org.argeo.tracker.core;version="2.1.79.SNAPSHOT-r201803241506", org.argeo.tracker.ui;version="2.1.79.SNAPSHOT-r201803241506", + org.eclipse.core.commands.common, + org.eclipse.core.runtime;version="3.5.0", + org.eclipse.e4.ui.di, org.eclipse.jface, org.eclipse.jface.layout, org.eclipse.jface.viewers, diff --git a/org.argeo.suite.e4/e4xmi/argeo-office.e4xmi b/org.argeo.suite.e4/e4xmi/argeo-office.e4xmi index 263881f..f7fd8c9 100644 --- a/org.argeo.suite.e4/e4xmi/argeo-office.e4xmi +++ b/org.argeo.suite.e4/e4xmi/argeo-office.e4xmi @@ -6,17 +6,23 @@ - - + + minimized + - + entityEditorArea + - + + + + + @@ -30,12 +36,22 @@ - - - + + + + + + + + + + + + + diff --git a/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/AbstractSuiteDashboard.java b/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/AbstractSuiteDashboard.java new file mode 100644 index 0000000..9691901 --- /dev/null +++ b/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/AbstractSuiteDashboard.java @@ -0,0 +1,161 @@ +package org.argeo.suite.e4.parts; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.Session; + +import org.argeo.cms.ui.eclipse.forms.FormToolkit; +import org.argeo.cms.util.CmsUtils; +import org.argeo.connect.SystemAppService; +import org.argeo.connect.resources.ResourcesService; +import org.argeo.connect.ui.AppWorkbenchService; +import org.argeo.connect.ui.ConnectUiStyles; +import org.argeo.connect.ui.SystemWorkbenchService; +import org.argeo.connect.util.ConnectJcrUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.jcr.JcrUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; + +/** Generic dashboard for Argeo Suite applications */ +public abstract class AbstractSuiteDashboard { + + // DEPENDENCY INJECTION + private Repository repository; + private ResourcesService resourcesService; + private SystemAppService systemAppService; + private SystemWorkbenchService systemWorkbenchService; + + private Session session; + + // UI Objects + private FormToolkit toolkit; + + public void init() { + session = ConnectJcrUtils.login(repository); +// updateTooltip(input); + } + +// private void updateTooltip(IEditorInput input) { +// if (input instanceof EntityEditorInput) { +// EntityEditorInput sei = (EntityEditorInput) input; +// sei.setTooltipText("My Dashboard"); +// } +// } + + /** + * Implementing classes must call super in order to create the correct form + * toolkit + */ + @PostConstruct + public void createPartControl(Composite parent) { + toolkit = new FormToolkit(Display.getCurrent()); + init(); + } + + // UTILS + protected Composite createGadgetCmp(Composite parent, int widthHint, int heightHint) { + Composite gadgetCmp = toolkit.createComposite(parent, SWT.BORDER); + GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); + gd.widthHint = widthHint; + gd.heightHint = heightHint; + gadgetCmp.setLayoutData(gd); + CmsUtils.style(gadgetCmp, ConnectUiStyles.GADGET_BOX); + return gadgetCmp; + } + + protected Composite createGadgetTitleCmp(Composite parent, String title) { + Composite titleCmp = toolkit.createComposite(parent, SWT.BACKGROUND | SWT.INHERIT_NONE); + CmsUtils.style(titleCmp, ConnectUiStyles.GADGET_HEADER); + titleCmp.setBackground(null); + GridData gd = new GridData(SWT.FILL, SWT.TOP, true, false); + titleCmp.setLayoutData(gd); + titleCmp.setLayout(new GridLayout()); + + Label titleLbl = toolkit.createLabel(titleCmp, title + " ", SWT.BOLD); + CmsUtils.style(titleLbl, ConnectUiStyles.GADGET_HEADER); + titleLbl.setBackground(null); + return titleCmp; + } + + protected Composite createGadgetBodyCmp(Composite parent) { + Composite bodyCmp = toolkit.createComposite(parent, SWT.BACKGROUND | SWT.INHERIT_NONE); + bodyCmp.setLayoutData(EclipseUiUtils.fillAll()); + bodyCmp.setLayout(new GridLayout()); + return bodyCmp; + } + + protected Link createOpenEntityEditorLink(final AppWorkbenchService peopleUiService, Composite parent, + final String label, final Node entity) { + Link link = new Link(parent, SWT.NONE); + link.setText("" + label + ""); + link.setLayoutData(EclipseUiUtils.fillWidth()); + link.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = 1L; + + @Override + public void widgetSelected(final SelectionEvent event) { + // Map params = new HashMap(); + // params.put(ConnectEditor.PARAM_JCR_ID, + // ConnectJcrUtils.getIdentifier(entity)); + // CommandUtils.callCommand(peopleUiService.getOpenEntityEditorCmdId(), params); + peopleUiService.openEntityEditor(entity); + } + }); + return link; + } + + // Life cycle + @PreDestroy + public void dispose() { + JcrUtils.logoutQuietly(session); + } + + + // Expose to implementing classes + protected Session getSession() { + return session; + } + + public ResourcesService getResourcesService() { + return resourcesService; + } + + protected SystemAppService getSystemAppService() { + return systemAppService; + } + + protected SystemWorkbenchService getSystemWorkbenchService() { + return systemWorkbenchService; + } + + protected FormToolkit getFormToolkit() { + return toolkit; + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setResourcesService(ResourcesService resourcesService) { + this.resourcesService = resourcesService; + } + + public void setSystemAppService(SystemAppService systemAppService) { + this.systemAppService = systemAppService; + } + + public void setSystemWorkbenchService(SystemWorkbenchService systemWorkbenchService) { + this.systemWorkbenchService = systemWorkbenchService; + } +} diff --git a/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/DefaultDashboardEditor.java b/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/DefaultDashboardEditor.java new file mode 100644 index 0000000..d068575 --- /dev/null +++ b/org.argeo.suite.e4/src/org/argeo/suite/e4/parts/DefaultDashboardEditor.java @@ -0,0 +1,401 @@ +package org.argeo.suite.e4.parts; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.activities.ActivitiesNames; +import org.argeo.activities.ActivitiesService; +import org.argeo.activities.ui.TaskViewerContextMenu; +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.util.CmsUtils; +import org.argeo.connect.ConnectException; +import org.argeo.connect.ConnectNames; +import org.argeo.connect.ui.ConnectWorkbenchUtils; +import org.argeo.connect.ui.Refreshable; +import org.argeo.connect.util.ConnectJcrUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.jcr.JcrUtils; +import org.argeo.node.NodeUtils; +import org.argeo.tracker.TrackerNames; +import org.argeo.tracker.TrackerService; +import org.argeo.tracker.TrackerTypes; +import org.argeo.tracker.core.TrackerUtils; +import org.argeo.tracker.ui.TaskListLabelProvider; +import org.argeo.tracker.ui.TaskVirtualListComposite; +import org.eclipse.e4.ui.di.Focus; +import org.eclipse.jface.viewers.ColumnLabelProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Link; + +/** Argeo Suite Default Dashboard */ +public class DefaultDashboardEditor extends AbstractSuiteDashboard implements Refreshable { + final static Log log = LogFactory.getLog(DefaultDashboardEditor.class); + // public final static String ID = AsUiPlugin.PLUGIN_ID + + // ".defaultDashboardEditor"; + + private ActivitiesService activitiesService; + private TrackerService trackerService; + + private String datePattern = "dd MMM yyyy"; + + private Composite headerCmp; + private Composite taskListCmp; + private TaskVirtualListComposite tvlc; + + @PostConstruct + public void createPartControl(Composite parent) { + super.createPartControl(parent); + parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); + Composite bodyCmp = new Composite(parent, SWT.NO_FOCUS); + bodyCmp.setLayoutData(EclipseUiUtils.fillAll()); + bodyCmp.setLayout(new GridLayout()); + + headerCmp = new Composite(bodyCmp, SWT.NO_FOCUS); + headerCmp.setLayoutData(EclipseUiUtils.fillWidth()); + + taskListCmp = new Composite(bodyCmp, SWT.NO_FOCUS); + taskListCmp.setLayoutData(EclipseUiUtils.fillAll()); + forceRefresh(null); + } + + @Override + public void forceRefresh(Object object) { + CmsUtils.clear(headerCmp); + populateHeaderPart(headerCmp, NodeUtils.getUserHome(getSession())); + + CmsUtils.clear(taskListCmp); + populateTaskListCmp(taskListCmp); + + headerCmp.getParent().layout(true, true); + } + + private void populateTaskListCmp(Composite parent) { + parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); + NodeIterator nit = activitiesService.getMyTasks(getSession(), true); + if (!nit.hasNext()) { + Composite noTaskCmp = new Composite(parent, SWT.NO_FOCUS); + noTaskCmp.setLayoutData(EclipseUiUtils.fillAll()); + noTaskCmp.setLayout(new GridLayout()); + + Label noTaskLbl = new Label(noTaskCmp, SWT.CENTER); + noTaskLbl.setText(" You have no pending Task. "); + CmsUtils.markup(noTaskLbl); + noTaskLbl.setLayoutData(new GridData(SWT.CENTER, SWT.BOTTOM, true, true)); + + final Link createTaskLk = new Link(noTaskCmp, SWT.CENTER); + createTaskLk.setText(" Create a task "); + createTaskLk.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, true)); + + createTaskLk.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = -9028457805156989935L; + + @Override + public void widgetSelected(SelectionEvent e) { + String mainMixin = TrackerTypes.TRACKER_TASK; + String pathCreated = ConnectWorkbenchUtils.createAndConfigureEntity(createTaskLk.getShell(), + getSession(), getSystemAppService(), getSystemWorkbenchService(), mainMixin); + if (EclipseUiUtils.notEmpty(pathCreated)) + forceRefresh(null); + } + }); + + } else { + TaskListLabelProvider labelProvider = new TaskListLabelProvider(trackerService); + tvlc = new TaskVirtualListComposite(parent, SWT.NO_FOCUS, (ILabelProvider) labelProvider, 54); + tvlc.setLayoutData(EclipseUiUtils.fillAll()); + final TableViewer viewer = tvlc.getTableViewer(); + viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray()); + final TaskViewerContextMenu contextMenu = new TaskViewerContextMenu(viewer, getSession(), + activitiesService) { + @Override + public boolean performAction(String actionId) { + boolean hasChanged = super.performAction(actionId); + if (hasChanged) { + viewer.getTable().setFocus(); + forceRefresh(null); + // NodeIterator nit = + // activitiesService.getMyTasks(getSession(), true); + // viewer.setInput(JcrUtils.nodeIteratorToList(nit).toArray()); + } + return hasChanged; + } + }; + viewer.getTable().addMouseListener(new MouseAdapter() { + private static final long serialVersionUID = 6737579410648595940L; + + @Override + public void mouseDown(MouseEvent e) { + if (e.button == 3) { + // contextMenu.setCurrFolderPath(currDisplayedFolder); + contextMenu.show(viewer.getTable(), new Point(e.x, e.y), + (IStructuredSelection) viewer.getSelection()); + } + } + }); + + } + } + + private boolean isOverdue(Node node, String propName) { + try { + Calendar now = GregorianCalendar.getInstance(); + return node.hasProperty(propName) && node.getProperty(propName).getDate().before(now); + } catch (RepositoryException e) { + throw new ConnectException("Cannot check overdue status with property " + propName + " on " + node, e); + } + } + + private void populateHeaderPart(Composite bodyCmp, Node context) { + bodyCmp.setLayout(EclipseUiUtils.noSpaceGridLayout(new GridLayout(2, true))); + + Composite leftCmp = new Composite(bodyCmp, SWT.NO_FOCUS); + leftCmp.setLayout(new GridLayout()); + leftCmp.setLayoutData(EclipseUiUtils.fillWidth()); + Composite rightCmp = new Composite(bodyCmp, SWT.NO_FOCUS); + rightCmp.setLayout(new GridLayout()); + rightCmp.setLayoutData(EclipseUiUtils.fillWidth()); + + // Title + Label titleLbl = new Label(leftCmp, SWT.WRAP | SWT.LEAD); + CmsUtils.markup(titleLbl); + String titleStr = " Hello " + CurrentUser.getDisplayName() + " "; + titleLbl.setText(titleStr); + GridData gd = new GridData(SWT.TOP, SWT.BOTTOM, false, false); + gd.verticalIndent = 5; + gd.horizontalIndent = 10; + titleLbl.setLayoutData(gd); + + NodeIterator nit = activitiesService.getMyTasks(getSession(), true); + if (nit.hasNext()) { + List overdueTasks = new ArrayList<>(); + while (nit.hasNext()) { + Node currNode = nit.nextNode(); + if (isOverdue(currNode, ActivitiesNames.ACTIVITIES_DUE_DATE)) + overdueTasks.add(currNode); + } + if (!overdueTasks.isEmpty()) { + Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS); + long size = overdueTasks.size(); + String overdueStr = "You have " + size + " overdue task" + (size > 1 ? "s" : "") + ": "; + populateMuliValueClickableList(overdueCmp, overdueTasks.toArray(new Node[0]), new TaskLp(), overdueStr); + } + } + + nit = trackerService.getMyMilestones(getSession(), true); + List openMilestones = new ArrayList<>(); + + if (nit.hasNext()) { + List overdueMilestones = new ArrayList<>(); + while (nit.hasNext()) { + Node currNode = nit.nextNode(); + openMilestones.add(currNode); + if (isOverdue(currNode, TrackerNames.TRACKER_TARGET_DATE)) + overdueMilestones.add(currNode); + } + if (!overdueMilestones.isEmpty()) { + Composite overdueCmp = new Composite(leftCmp, SWT.NO_FOCUS); + long size = overdueMilestones.size(); + String overdueStr = "You have " + size + " overdue milestone" + (size > 1 ? "s" : "") + ": "; + populateMuliValueClickableList(overdueCmp, overdueMilestones.toArray(new Node[0]), new MilestoneLp(), + overdueStr); + } + } + + // My projects + List openProjects = JcrUtils.nodeIteratorToList(trackerService.getMyProjects(getSession(), true)); + if (!openProjects.isEmpty()) { + Group myProjectsGp = new Group(rightCmp, SWT.NO_FOCUS); + myProjectsGp.setText("My open projects"); + myProjectsGp.setLayoutData(EclipseUiUtils.fillWidth()); + populateMuliValueClickableList(myProjectsGp, openProjects.toArray(new Node[0]), new ProjectLp(), null); + } + + // My Milestones + if (!openMilestones.isEmpty()) { + Group myMilestoneGp = new Group(rightCmp, SWT.NO_FOCUS); + myMilestoneGp.setText("My open milestones"); + myMilestoneGp.setLayoutData(EclipseUiUtils.fillWidth()); + populateMuliValueClickableList(myMilestoneGp, openMilestones.toArray(new Node[0]), new MilestoneLp(), null); + } + } + + private class ProjectLp extends ColumnLabelProvider { + private static final long serialVersionUID = 7231233932794865555L; + + @Override + public String getText(Object element) { + Node project = (Node) element; + + String percent; + NodeIterator nit = TrackerUtils.getIssues(project, null, null, null, true); + long openNb = nit.getSize(); + + nit = TrackerUtils.getIssues(project, null, null, null, false); + long allNb = nit.getSize(); + + if (allNb < 1) + percent = "empty"; + else { + double num = allNb - openNb; + double result = num / allNb * 100; + percent = String.format("%.1f", result) + "% done"; + } + StringBuilder builder = new StringBuilder(); + builder.append("").append(ConnectJcrUtils.get(project, Property.JCR_TITLE)).append(""); + builder.append(" (").append(percent).append(")"); + + return builder.toString(); + } + } + + private class MilestoneLp extends ColumnLabelProvider { + private static final long serialVersionUID = 7231233932794865555L; + + @Override + public String getText(Object element) { + Node milestone = (Node) element; + Node project = TrackerUtils.getRelatedProject(trackerService, milestone); + String dueDate = ConnectJcrUtils.getDateFormattedAsString(milestone, TrackerNames.TRACKER_TARGET_DATE, + datePattern); + + String percent; + String propName = TrackerNames.TRACKER_MILESTONE_UID; + String muid = ConnectJcrUtils.get(milestone, ConnectNames.CONNECT_UID); + NodeIterator nit = TrackerUtils.getIssues(project, null, propName, muid, true); + long openNb = nit.getSize(); + + nit = TrackerUtils.getIssues(project, null, propName, muid, false); + long allNb = nit.getSize(); + + if (allNb < 1) + percent = "empty"; + else { + double num = allNb - openNb; + double result = num / allNb * 100; + percent = String.format("%.1f", result) + "% done"; + } + StringBuilder builder = new StringBuilder(); + builder.append("").append(ConnectJcrUtils.get(milestone, Property.JCR_TITLE)).append(""); + builder.append(" ("); + if (EclipseUiUtils.notEmpty(dueDate)) + builder.append("due to ").append(dueDate).append(", "); + + builder.append(percent).append(")"); + return builder.toString(); + } + + @Override + public Color getForeground(Object element) { + Node milestone = (Node) element; + Calendar dueDate = ConnectJcrUtils.getDateValue(milestone, TrackerNames.TRACKER_TARGET_DATE); + if (dueDate != null && dueDate.before(Calendar.getInstance())) + return Display.getCurrent().getSystemColor(SWT.COLOR_RED); + return null; + } + } + + private class TaskLp extends ColumnLabelProvider { + private static final long serialVersionUID = 7231233932794865555L; + + @Override + public String getText(Object element) { + Node task = (Node) element; + String dueDate = ConnectJcrUtils.getDateFormattedAsString(task, ActivitiesNames.ACTIVITIES_DUE_DATE, + datePattern); + + StringBuilder builder = new StringBuilder(); + builder.append("").append(ConnectJcrUtils.get(task, Property.JCR_TITLE)).append(""); + if (EclipseUiUtils.notEmpty(dueDate)) + builder.append(" (").append("due to ").append(dueDate).append(")"); + return builder.toString(); + } + + @Override + public Color getForeground(Object element) { + Node milestone = (Node) element; + Calendar dueDate = ConnectJcrUtils.getDateValue(milestone, TrackerNames.TRACKER_TARGET_DATE); + if (dueDate != null && dueDate.before(Calendar.getInstance())) + return Display.getCurrent().getSystemColor(SWT.COLOR_RED); + return null; + } + } + + @Focus + public void setFocus() { + // refreshDocListGadget(); + } + + public void setActivitiesService(ActivitiesService activitiesService) { + this.activitiesService = activitiesService; + } + + public void setTrackerService(TrackerService trackerService) { + this.trackerService = trackerService; + } + + // LOCAL HELPERS + private void populateMuliValueClickableList(Composite parent, Node[] nodes, ColumnLabelProvider lp, + String listLabel) { + CmsUtils.clear(parent); + RowLayout rl = new RowLayout(SWT.HORIZONTAL | SWT.WRAP); + rl.wrap = true; + rl.marginLeft = rl.marginTop = rl.marginBottom = 0; + rl.marginRight = 8; + parent.setLayout(rl); + + if (EclipseUiUtils.notEmpty(listLabel)) { + Link link = new Link(parent, SWT.NONE); + link.setText(listLabel); + link.setFont(EclipseUiUtils.getBoldFont(parent)); + } + + int i = 1; + for (Node node : nodes) { + Link link = new Link(parent, SWT.NONE); + CmsUtils.markup(link); + link.setText(lp.getText(node) + (i != nodes.length ? ", " : "")); + i++; + // Color fc = lp.getForeground(node); + // if (fc != null) + // link.setForeground(fc); + + link.addSelectionListener(new SelectionAdapter() { + private static final long serialVersionUID = 1L; + + @Override + public void widgetSelected(final SelectionEvent event) { + // CommandUtils.callCommand(getSystemWorkbenchService().getOpenEntityEditorCmdId(), + // ConnectEditor.PARAM_JCR_ID, ConnectJcrUtils.getIdentifier(node)); + getSystemWorkbenchService().openEntityEditor(node); + } + }); + } + } + +} -- 2.30.2