View Javadoc
1   package org.argeo.tracker.ui.controls;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import javax.jcr.Node;
7   import javax.jcr.Property;
8   import javax.jcr.RepositoryException;
9   import javax.jcr.Value;
10  
11  import org.argeo.cms.util.CmsUtils;
12  import org.argeo.connect.ConnectException;
13  import org.argeo.connect.ui.AppWorkbenchService;
14  import org.argeo.connect.ui.ConnectUiStyles;
15  import org.argeo.connect.ui.ConnectUiUtils;
16  import org.argeo.connect.ui.parts.PickUpRelatedDialog;
17  import org.argeo.connect.util.ConnectJcrUtils;
18  import org.argeo.tracker.TrackerException;
19  import org.eclipse.jface.window.Window;
20  import org.eclipse.swt.SWT;
21  import org.eclipse.swt.events.SelectionAdapter;
22  import org.eclipse.swt.events.SelectionEvent;
23  import org.eclipse.swt.layout.GridData;
24  import org.eclipse.swt.layout.GridLayout;
25  import org.eclipse.swt.layout.RowLayout;
26  import org.eclipse.swt.widgets.Button;
27  import org.eclipse.swt.widgets.Composite;
28  import org.eclipse.swt.widgets.Label;
29  import org.eclipse.swt.widgets.Link;
30  
31  /** Wrap a composite to display and edit a list of related to entities */
32  public class RelatedToList extends Composite {
33  	private static final long serialVersionUID = -5339937283129519708L;
34  
35  	// Context
36  	private AppWorkbenchService appWorkbenchService;
37  	private final Node relatable;
38  	private List<String> chosenValues;
39  
40  	public List<String> getChosenValues() {
41  		return chosenValues;
42  	}
43  
44  	/**
45  	 * 
46  	 * @param parent
47  	 * @param style
48  	 * @param toolkit
49  	 * @param form
50  	 * @param peopleService
51  	 * @param peopleWorkbenchService
52  	 * @param taggable
53  	 * @param tagId
54  	 * @param newTagMsg
55  	 */
56  	public RelatedToList(Composite parent, int style, Node relatable, String propName,
57  			AppWorkbenchService appWorkbenchService) {
58  		super(parent, style);
59  		this.appWorkbenchService = appWorkbenchService;
60  		this.relatable = relatable;
61  		chosenValues = new ArrayList<>();
62  		try {
63  			if (relatable.hasProperty(propName)) {
64  				Value[] vals = relatable.getProperty(propName).getValues();
65  				for (Value val : vals)
66  					chosenValues.add(val.getString());
67  			}
68  		} catch (RepositoryException e) {
69  			throw new TrackerException("Cannot retrieve related to property on " + relatable, e);
70  		}
71  		populate(this);
72  	}
73  
74  	/**
75  	 * 
76  	 * @param parent
77  	 * @param style
78  	 * @param toolkit
79  	 * @param form
80  	 * @param peopleService
81  	 * @param peopleWorkbenchService
82  	 * @param taggable
83  	 * @param tagId
84  	 * @param newTagMsg
85  	 */
86  	public RelatedToList(Composite parent, int style, Node relatable, List<String> initialValues,
87  			AppWorkbenchService appWorkbenchService) {
88  		super(parent, style);
89  		this.relatable = relatable;
90  		this.appWorkbenchService = appWorkbenchService;
91  		if (initialValues == null)
92  			chosenValues = new ArrayList<>();
93  		else
94  			chosenValues = initialValues;
95  
96  		populate(this);
97  	}
98  
99  	public void populate(Composite parent) {
100 		RowLayout rl = new RowLayout(SWT.HORIZONTAL);
101 		rl.wrap = true;
102 		rl.marginLeft = rl.marginBottom = 0;
103 		rl.marginTop = 4;
104 		rl.marginRight = 8;
105 		parent.setLayout(rl);
106 
107 		for (String value : chosenValues) {
108 			addValueCmp(parent, ConnectJcrUtils.getNodeByIdentifier(relatable, value));
109 		}
110 
111 		Link addRelatedLk = new Link(parent, SWT.NONE);
112 		addRelatedLk.setText("<a>Add...</a>");
113 		addNewRelatedSelList(addRelatedLk);
114 	}
115 
116 	/**
117 	 * Configure the action launched when the user click the add link in the
118 	 * "relatedTo" composite
119 	 */
120 	private void addNewRelatedSelList(final Link link) {
121 		link.addSelectionListener(new SelectionAdapter() {
122 			private static final long serialVersionUID = -7118320199160680131L;
123 
124 			@Override
125 			public void widgetSelected(final SelectionEvent event) {
126 				try {
127 					PickUpRelatedDialog diag = new PickUpRelatedDialog(link.getShell(), "Choose a related item",
128 							relatable.getSession(), appWorkbenchService, relatable);
129 					int result = diag.open();
130 					if (Window.OK == result)
131 						addValue(link, diag.getSelected());
132 				} catch (RepositoryException e) {
133 					throw new ConnectException("Unable to link chosen node to current entity " + relatable, e);
134 				}
135 			}
136 		});
137 	}
138 
139 	private void addValue(Link link, Node node) {
140 		String id = ConnectJcrUtils.getIdentifier(node);
141 		if (chosenValues.contains(id))
142 			return;
143 
144 		chosenValues.add(id);
145 		Composite parent = link.getParent();
146 		Composite valueCmp = addValueCmp(parent, node);
147 		valueCmp.moveAbove(link);
148 		parent.layout(true, true);
149 	}
150 
151 	private Composite addValueCmp(Composite parent, Node node) {
152 		Composite valueCmp = new Composite(parent, SWT.NO_FOCUS);
153 		GridLayout layout = ConnectUiUtils.noSpaceGridLayout(2);
154 		layout.horizontalSpacing = 3;
155 		valueCmp.setLayout(layout);
156 		Label valueLbl = new Label(valueCmp, SWT.NONE);
157 		valueLbl.setText(" " + ConnectJcrUtils.get(node, Property.JCR_TITLE));
158 		addDeleteButton(valueCmp, ConnectJcrUtils.getIdentifier(node));
159 		return valueCmp;
160 	}
161 
162 	private void addDeleteButton(Composite parent, String value) {
163 		final Button deleteBtn = new Button(parent, SWT.FLAT);
164 		CmsUtils.style(deleteBtn, ConnectUiStyles.SMALL_DELETE_BTN);
165 		deleteBtn.setLayoutData(new GridData(8, 8));
166 		deleteBtn.addSelectionListener(new SelectionAdapter() {
167 			private static final long serialVersionUID = 1L;
168 
169 			@Override
170 			public void widgetSelected(final SelectionEvent event) {
171 				chosenValues.remove(value);
172 				Composite lineCmp = parent.getParent();
173 				parent.dispose();
174 				lineCmp.layout(true, true);
175 			}
176 		});
177 	}
178 
179 	/**
180 	 * Overwrite to call the relevant open editor command, does nothing by
181 	 * default
182 	 */
183 	protected void callOpenEditor(String tagKey) {
184 	}
185 }