Improve single sourcing
[gpl/argeo-suite.git] / org.argeo.suite.workbench.rap / src / org / argeo / suite / workbench / parts / QuickSearchView.java
1 package org.argeo.suite.workbench.parts;
2
3 import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty;
4
5 import javax.jcr.NodeIterator;
6 import javax.jcr.Repository;
7 import javax.jcr.RepositoryException;
8 import javax.jcr.Session;
9 import javax.jcr.query.Query;
10 import javax.jcr.query.QueryResult;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.argeo.activities.ActivitiesService;
15 import org.argeo.cms.util.CmsUtils;
16 import org.argeo.connect.ConnectTypes;
17 import org.argeo.connect.resources.ResourcesService;
18 import org.argeo.connect.ui.ConnectUiConstants;
19 import org.argeo.connect.ui.util.BasicNodeListContentProvider;
20 import org.argeo.connect.ui.widgets.DelayedText;
21 import org.argeo.connect.util.ConnectJcrUtils;
22 import org.argeo.connect.util.XPathUtils;
23 import org.argeo.connect.workbench.Refreshable;
24 import org.argeo.connect.workbench.SystemWorkbenchService;
25 import org.argeo.connect.workbench.util.JcrViewerDClickListener;
26 import org.argeo.eclipse.ui.EclipseUiUtils;
27 import org.argeo.jcr.JcrUtils;
28 import org.argeo.people.PeopleService;
29 import org.argeo.suite.workbench.AsUiPlugin;
30 import org.argeo.suite.workbench.SuiteWorkbenchException;
31 import org.argeo.suite.workbench.internal.EntitySingleColumnLabelProvider;
32 import org.eclipse.jface.layout.TableColumnLayout;
33 import org.eclipse.jface.viewers.ColumnWeightData;
34 import org.eclipse.jface.viewers.ILabelProvider;
35 import org.eclipse.jface.viewers.StructuredSelection;
36 import org.eclipse.jface.viewers.TableViewer;
37 import org.eclipse.rap.rwt.service.ServerPushSession;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.events.KeyEvent;
40 import org.eclipse.swt.events.KeyListener;
41 import org.eclipse.swt.events.ModifyEvent;
42 import org.eclipse.swt.events.ModifyListener;
43 import org.eclipse.swt.layout.GridData;
44 import org.eclipse.swt.layout.GridLayout;
45 import org.eclipse.swt.widgets.Composite;
46 import org.eclipse.swt.widgets.Table;
47 import org.eclipse.swt.widgets.TableColumn;
48 import org.eclipse.swt.widgets.Text;
49 import org.eclipse.ui.part.ViewPart;
50
51 /** A table with a quick search field. */
52 public class QuickSearchView extends ViewPart implements Refreshable {
53 private final static Log log = LogFactory.getLog(QuickSearchView.class);
54 public static final String ID = AsUiPlugin.PLUGIN_ID + ".quickSearchView";
55
56 /* DEPENDENCY INJECTION */
57 private Repository repository;
58 private Session session;
59 private ResourcesService resourcesService;
60 private ActivitiesService activitiesService;
61 private PeopleService peopleService;
62 private SystemWorkbenchService systemWorkbenchService;
63
64 // This page widgets
65 private TableViewer entityViewer;
66 private Text filterTxt;
67
68 @Override
69 public void createPartControl(Composite parent) {
70 session = ConnectJcrUtils.login(repository);
71 // MainLayout
72 parent.setLayout(new GridLayout());
73 addFilterPanel(parent);
74 entityViewer = createListPart(parent, new EntitySingleColumnLabelProvider(resourcesService, activitiesService,
75 peopleService, systemWorkbenchService));
76 refreshFilteredList();
77 }
78
79 public void addFilterPanel(Composite parent) {
80 // Use a delayed text: the query won't be done until the user stop
81 // typing for 800ms
82 int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL;
83 DelayedText delayedText = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY);
84 filterTxt = delayedText.getText();
85 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
86
87 final ServerPushSession pushSession = new ServerPushSession();
88 delayedText.addDelayedModifyListener(pushSession, new ModifyListener() {
89 private static final long serialVersionUID = 5003010530960334977L;
90
91 public void modifyText(ModifyEvent event) {
92 delayedText.getText().getDisplay().asyncExec(new Runnable() {
93 @Override
94 public void run() {
95 refreshFilteredList();
96 }
97 });
98 pushSession.stop();
99 }
100 });
101
102 // Jump to the first item of the list using the down arrow
103 filterTxt.addKeyListener(new KeyListener() {
104 private static final long serialVersionUID = -4523394262771183968L;
105
106 @Override
107 public void keyReleased(KeyEvent e) {
108 }
109
110 @Override
111 public void keyPressed(KeyEvent e) {
112 // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
113 // boolean altPressed = (e.stateMask & SWT.ALT) != 0;
114 if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) {
115 Object first = entityViewer.getElementAt(0);
116 if (first != null) {
117 entityViewer.getTable().setFocus();
118 entityViewer.setSelection(new StructuredSelection(first), true);
119 }
120 e.doit = false;
121 }
122 }
123 });
124 }
125
126 protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) {
127 parent.setLayout(new GridLayout());
128
129 Composite tableComposite = new Composite(parent, SWT.NONE);
130 GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL
131 | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
132 tableComposite.setLayoutData(gd);
133
134 TableViewer v = new TableViewer(tableComposite);
135 v.setLabelProvider(labelProvider);
136
137 TableColumn singleColumn = new TableColumn(v.getTable(), SWT.V_SCROLL);
138 TableColumnLayout tableColumnLayout = new TableColumnLayout();
139 tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(85));
140 tableComposite.setLayout(tableColumnLayout);
141
142 // Corresponding table & style
143 Table table = v.getTable();
144 table.setLinesVisible(true);
145 table.setHeaderVisible(false);
146 CmsUtils.markup(table);
147 CmsUtils.setItemHeight(table, 26);
148
149 v.setContentProvider(new BasicNodeListContentProvider());
150 v.addDoubleClickListener(new JcrViewerDClickListener());
151 return v;
152 }
153
154 @Override
155 public void dispose() {
156 JcrUtils.logoutQuietly(session);
157 super.dispose();
158 }
159
160 @Override
161 public void setFocus() {
162 refreshFilteredList();
163 filterTxt.setFocus();
164 }
165
166 @Override
167 public void forceRefresh(Object object) {
168 refreshFilteredList();
169 }
170
171 protected void refreshFilteredList() {
172 try {
173 String filter = filterTxt.getText();
174 // Prevents the query on the full repository
175 // if (isEmpty(filter)) {
176 // entityViewer.setInput(null);
177 // return;
178 // }
179
180 // XPATH Query
181 String xpathQueryStr = "//element(*, " + ConnectTypes.CONNECT_ENTITY + ")";
182 String xpathFilter = XPathUtils.getFreeTextConstraint(filter);
183 if (notEmpty(xpathFilter))
184 xpathQueryStr += "[" + xpathFilter + "]";
185
186 // boolean doOrder = orderResultsBtn != null
187 // && !(orderResultsBtn.isDisposed())
188 // && orderResultsBtn.getSelection();
189 // if (doOrder) {
190 // xpathQueryStr += " order by jcr:title";
191 // }
192
193 long begin = System.currentTimeMillis();
194 Query xpathQuery = XPathUtils.createQuery(session, xpathQueryStr);
195
196 xpathQuery.setLimit(ConnectUiConstants.SEARCH_DEFAULT_LIMIT);
197 QueryResult result = xpathQuery.execute();
198
199 NodeIterator nit = result.getNodes();
200 entityViewer.setInput(JcrUtils.nodeIteratorToList(nit));
201 if (log.isDebugEnabled()) {
202 long end = System.currentTimeMillis();
203 log.debug("Quick Search - Found: " + nit.getSize() + " in " + (end - begin)
204 + " ms by executing XPath query (" + xpathQueryStr + ").");
205 }
206 } catch (RepositoryException e) {
207 throw new SuiteWorkbenchException("Unable to list entities", e);
208 }
209 }
210
211 /* DEPENDENCY INJECTION */
212 public void setRepository(Repository repository) {
213 this.repository = repository;
214 }
215
216 public void setResourcesService(ResourcesService resourcesService) {
217 this.resourcesService = resourcesService;
218 }
219
220 public void setActivitiesService(ActivitiesService activitiesService) {
221 this.activitiesService = activitiesService;
222 }
223
224 public void setPeopleService(PeopleService peopleService) {
225 this.peopleService = peopleService;
226 }
227
228 public void setSystemWorkbenchService(SystemWorkbenchService systemWorkbenchService) {
229 this.systemWorkbenchService = systemWorkbenchService;
230 }
231 }