View Javadoc
1   package org.argeo.documents.e4.parts;
2   
3   import java.nio.file.Path;
4   
5   import javax.annotation.PostConstruct;
6   import javax.annotation.PreDestroy;
7   import javax.inject.Inject;
8   import javax.inject.Named;
9   import javax.jcr.Node;
10  import javax.jcr.NodeIterator;
11  import javax.jcr.Repository;
12  import javax.jcr.RepositoryException;
13  import javax.jcr.Session;
14  import javax.jcr.query.Query;
15  import javax.jcr.query.QueryManager;
16  import javax.jcr.query.QueryResult;
17  
18  import org.argeo.cms.util.CmsUtils;
19  import org.argeo.connect.ui.ConnectUiConstants;
20  import org.argeo.connect.ui.SystemWorkbenchService;
21  import org.argeo.connect.ui.util.BasicNodeListContentProvider;
22  import org.argeo.connect.ui.widgets.DelayedText;
23  import org.argeo.connect.util.ConnectJcrUtils;
24  import org.argeo.connect.util.XPathUtils;
25  import org.argeo.documents.DocumentsException;
26  import org.argeo.documents.ui.DocumentsSingleColumnLP;
27  import org.argeo.eclipse.ui.EclipseUiUtils;
28  import org.argeo.jcr.JcrUtils;
29  import org.eclipse.e4.ui.di.Focus;
30  import org.eclipse.jface.layout.TableColumnLayout;
31  import org.eclipse.jface.viewers.ColumnWeightData;
32  import org.eclipse.jface.viewers.DoubleClickEvent;
33  import org.eclipse.jface.viewers.IDoubleClickListener;
34  import org.eclipse.jface.viewers.ILabelProvider;
35  import org.eclipse.jface.viewers.IStructuredSelection;
36  import org.eclipse.jface.viewers.StructuredSelection;
37  import org.eclipse.jface.viewers.TableViewer;
38  import org.eclipse.rap.rwt.RWT;
39  import org.eclipse.rap.rwt.client.service.BrowserNavigation;
40  import org.eclipse.swt.SWT;
41  import org.eclipse.swt.events.KeyEvent;
42  import org.eclipse.swt.events.KeyListener;
43  import org.eclipse.swt.events.ModifyEvent;
44  import org.eclipse.swt.events.ModifyListener;
45  import org.eclipse.swt.layout.GridData;
46  import org.eclipse.swt.layout.GridLayout;
47  import org.eclipse.swt.widgets.Composite;
48  import org.eclipse.swt.widgets.Table;
49  import org.eclipse.swt.widgets.TableColumn;
50  import org.eclipse.swt.widgets.Text;
51  
52  public class DocumentsDashboard implements IDoubleClickListener {
53  	@Inject
54  	@Named("(cn=home)")
55  	private Repository repository;
56  	@Inject
57  	private SystemWorkbenchService systemWorkbenchService;
58  
59  	private Session session;
60  	private Text filterTxt;
61  	private TableViewer searchResultsViewer;
62  	private Composite searchCmp;
63  
64  	@PostConstruct
65  	public void createPartControl(Composite parent) {
66  		session = ConnectJcrUtils.login(repository);
67  		// MainLayout
68  		parent.setLayout(new GridLayout());
69  		addFilterPanel(parent);
70  		searchCmp = new Composite(parent, SWT.NO_FOCUS);
71  		searchCmp.setLayout(EclipseUiUtils.noSpaceGridLayout());
72  		searchResultsViewer = createListPart(searchCmp, new DocumentsSingleColumnLP(systemWorkbenchService));
73  		GridData gd = EclipseUiUtils.fillWidth();
74  		gd.heightHint = 0;
75  		searchCmp.setLayoutData(gd);
76  	}
77  
78  	public void addFilterPanel(Composite parent) {
79  		// Use a delayed text: the query won't be done until the user stop
80  		// typing for 800ms
81  		int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL;
82  		DelayedText delayedText = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY);
83  		filterTxt = delayedText.getText();
84  		filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
85  
86  		// final ServerPushSession pushSession = new ServerPushSession();
87  		delayedText.addDelayedModifyListener(null, new ModifyListener() {
88  			private static final long serialVersionUID = 5003010530960334977L;
89  
90  			public void modifyText(ModifyEvent event) {
91  				delayedText.getText().getDisplay().asyncExec(new Runnable() {
92  					@Override
93  					public void run() {
94  						int resultNb = refreshFilteredList();
95  						if (resultNb > 0)
96  							((GridData) searchCmp.getLayoutData()).heightHint = 120;
97  						else
98  							((GridData) searchCmp.getLayoutData()).heightHint = 0;
99  						parent.layout(true, true);
100 					}
101 				});
102 				// pushSession.stop();
103 			}
104 		});
105 
106 		// Jump to the first item of the list using the down arrow
107 		filterTxt.addKeyListener(new KeyListener() {
108 			private static final long serialVersionUID = -4523394262771183968L;
109 
110 			@Override
111 			public void keyReleased(KeyEvent e) {
112 			}
113 
114 			@Override
115 			public void keyPressed(KeyEvent e) {
116 				// boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
117 				// boolean altPressed = (e.stateMask & SWT.ALT) != 0;
118 				if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) {
119 					Object first = searchResultsViewer.getElementAt(0);
120 					if (first != null) {
121 						searchResultsViewer.getTable().setFocus();
122 						searchResultsViewer.setSelection(new StructuredSelection(first), true);
123 					}
124 					e.doit = false;
125 				}
126 			}
127 		});
128 	}
129 
130 	protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) {
131 		parent.setLayout(new GridLayout());
132 
133 		Composite tableComposite = new Composite(parent, SWT.NONE);
134 		tableComposite.setLayoutData(EclipseUiUtils.fillAll());
135 
136 		TableViewer v = new TableViewer(tableComposite);
137 		v.setLabelProvider(labelProvider);
138 
139 		TableColumn singleColumn = new TableColumn(v.getTable(), SWT.V_SCROLL);
140 		TableColumnLayout tableColumnLayout = new TableColumnLayout();
141 		tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(100));
142 		tableComposite.setLayout(tableColumnLayout);
143 
144 		// Corresponding table & style
145 		Table table = v.getTable();
146 		table.setLinesVisible(false);
147 		table.setHeaderVisible(false);
148 		CmsUtils.markup(table);
149 		CmsUtils.setItemHeight(table, 26);
150 
151 		v.setContentProvider(new BasicNodeListContentProvider());
152 		v.addDoubleClickListener(this);
153 		return v;
154 	}
155 
156 	protected int refreshFilteredList() {
157 		try {
158 			String filter = filterTxt.getText();
159 			if (EclipseUiUtils.isEmpty(filter)) {
160 				searchResultsViewer.setInput(null);
161 				return 0;
162 			}
163 			// XPATH Query
164 			// String cf = XPathUtils.encodeXPathStringValue(filter);
165 			// String xpathQueryStr = "//element(*, nt:hierarchyNode)";
166 			// // + ConnectJcrUtils.getLocalJcrItemName(NodeType.NT_FILE) + ")";
167 			// String xpathFilter = XPathUtils.getFreeTextConstraint(filter);
168 			// if (notEmpty(xpathFilter))
169 			// xpathQueryStr += "[(" + xpathFilter + ") or "
170 			// //
171 			// + "(fn:name() = '" + cf + "' )" + "]";
172 			// QueryManager queryManager =
173 			// session.getWorkspace().getQueryManager();
174 			// Query xpathQuery = queryManager.createQuery(xpathQueryStr,
175 			// ConnectConstants.QUERY_XPATH);
176 
177 			// SQL2 QUERY
178 			String cf = XPathUtils.encodeXPathStringValue(filter);
179 			String qStr = "SELECT * FROM [nt:hierarchyNode] WHERE UPPER(LOCALNAME()) LIKE '%" + cf.toUpperCase() + "%'";
180 			QueryManager queryManager = session.getWorkspace().getQueryManager();
181 			Query xpathQuery = queryManager.createQuery(qStr, Query.JCR_SQL2);
182 
183 			// xpathQuery.setLimit(TrackerUiConstants.SEARCH_DEFAULT_LIMIT);
184 			QueryResult result = xpathQuery.execute();
185 			NodeIterator nit = result.getNodes();
186 			searchResultsViewer.setInput(JcrUtils.nodeIteratorToList(nit));
187 
188 			return (int) nit.getSize();
189 		} catch (RepositoryException e) {
190 			throw new DocumentsException("Unable to list files", e);
191 		}
192 	}
193 
194 	@Override
195 	public void doubleClick(DoubleClickEvent event) {
196 		IStructuredSelection selection = (IStructuredSelection) event.getSelection();
197 		if (selection.isEmpty())
198 			return;
199 		else {
200 			Object element = selection.getFirstElement();
201 			Node currNode;
202 
203 			if (element instanceof Node) {
204 				currNode = (Node) element;
205 			} else if (element instanceof Path) {
206 				Path currPath = (Path) element;
207 				String jcrPath = currPath.toString();
208 				// TODO rather directly use the jcrPath / an URI?
209 				currNode = ConnectJcrUtils.getNode(session, jcrPath);
210 			} else
211 				throw new IllegalArgumentException("Cannot manage " + element + ", only Node and Path are supported.");
212 			systemWorkbenchService.openEntityEditor(currNode);
213 		}
214 	}
215 
216 	@Focus
217 	public void setFocus() {
218 		// RAP specific
219 		RWT.getClient().getService(BrowserNavigation.class).pushState("~", "Docs");
220 	}
221 
222 	@PreDestroy
223 	public void destroy() {
224 		JcrUtils.logoutQuietly(session);
225 	}
226 }