1 package org
.argeo
.suite
.workbench
.parts
;
3 import static org
.argeo
.eclipse
.ui
.EclipseUiUtils
.notEmpty
;
5 import javax
.jcr
.NodeIterator
;
6 import javax
.jcr
.Repository
;
7 import javax
.jcr
.RepositoryException
;
8 import javax
.jcr
.Session
;
9 import javax
.jcr
.observation
.Event
;
10 import javax
.jcr
.observation
.EventIterator
;
11 import javax
.jcr
.observation
.EventListener
;
12 import javax
.jcr
.query
.Query
;
13 import javax
.jcr
.query
.QueryResult
;
15 import org
.apache
.commons
.logging
.Log
;
16 import org
.apache
.commons
.logging
.LogFactory
;
17 import org
.argeo
.activities
.ActivitiesService
;
18 import org
.argeo
.cms
.util
.CmsUtils
;
19 import org
.argeo
.connect
.ConnectTypes
;
20 import org
.argeo
.connect
.resources
.ResourcesService
;
21 import org
.argeo
.connect
.ui
.ConnectUiConstants
;
22 import org
.argeo
.connect
.ui
.Refreshable
;
23 import org
.argeo
.connect
.ui
.SystemWorkbenchService
;
24 import org
.argeo
.connect
.ui
.util
.BasicNodeListContentProvider
;
25 import org
.argeo
.connect
.ui
.util
.JcrViewerDClickListener
;
26 import org
.argeo
.connect
.ui
.widgets
.DelayedText
;
27 import org
.argeo
.connect
.util
.ConnectJcrUtils
;
28 import org
.argeo
.connect
.util
.XPathUtils
;
29 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
30 import org
.argeo
.jcr
.JcrUtils
;
31 import org
.argeo
.people
.PeopleService
;
32 import org
.argeo
.suite
.workbench
.AsUiPlugin
;
33 import org
.argeo
.suite
.workbench
.SuiteWorkbenchException
;
34 import org
.argeo
.suite
.workbench
.internal
.EntitySingleColumnLabelProvider
;
35 import org
.eclipse
.jface
.layout
.TableColumnLayout
;
36 import org
.eclipse
.jface
.viewers
.ColumnWeightData
;
37 import org
.eclipse
.jface
.viewers
.ILabelProvider
;
38 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
39 import org
.eclipse
.jface
.viewers
.TableViewer
;
40 import org
.eclipse
.rap
.rwt
.service
.ServerPushSession
;
41 import org
.eclipse
.swt
.SWT
;
42 import org
.eclipse
.swt
.events
.KeyEvent
;
43 import org
.eclipse
.swt
.events
.KeyListener
;
44 import org
.eclipse
.swt
.events
.ModifyEvent
;
45 import org
.eclipse
.swt
.events
.ModifyListener
;
46 import org
.eclipse
.swt
.layout
.GridData
;
47 import org
.eclipse
.swt
.layout
.GridLayout
;
48 import org
.eclipse
.swt
.widgets
.Composite
;
49 import org
.eclipse
.swt
.widgets
.Table
;
50 import org
.eclipse
.swt
.widgets
.TableColumn
;
51 import org
.eclipse
.swt
.widgets
.Text
;
52 import org
.eclipse
.ui
.IViewSite
;
53 import org
.eclipse
.ui
.PartInitException
;
54 import org
.eclipse
.ui
.part
.ViewPart
;
56 /** A table with a quick search field. */
57 public class QuickSearchView
extends ViewPart
implements Refreshable
{
58 private final static Log log
= LogFactory
.getLog(QuickSearchView
.class);
59 public static final String ID
= AsUiPlugin
.PLUGIN_ID
+ ".quickSearchView";
61 /* DEPENDENCY INJECTION */
62 private Repository repository
;
63 private Session session
;
64 private ResourcesService resourcesService
;
65 private ActivitiesService activitiesService
;
66 private PeopleService peopleService
;
67 private SystemWorkbenchService systemWorkbenchService
;
70 private TableViewer entityViewer
;
71 private Text filterTxt
;
74 public void init(IViewSite site
) throws PartInitException
{
79 public void createPartControl(Composite parent
) {
80 session
= ConnectJcrUtils
.login(repository
);
82 parent
.setLayout(new GridLayout());
83 addFilterPanel(parent
);
84 entityViewer
= createListPart(parent
, new EntitySingleColumnLabelProvider(resourcesService
, activitiesService
,
85 peopleService
, systemWorkbenchService
));
86 refreshFilteredList();
89 session
.getWorkspace().getObservationManager().addEventListener(new EventListener() {
92 public void onEvent(EventIterator events
) {
93 parent
.getDisplay().asyncExec(() -> refreshFilteredList());
95 }, Event
.PROPERTY_CHANGED
| Event
.NODE_ADDED
| Event
.NODE_REMOVED
| Event
.PROPERTY_ADDED
, "/", true, null,
96 new String
[] { ConnectTypes
.CONNECT_ENTITY
}, true);
97 } catch (RepositoryException e
) {
98 throw new SuiteWorkbenchException("Cannot add JCR observer", e
);
103 public void addFilterPanel(Composite parent
) {
104 // Use a delayed text: the query won't be done until the user stop
106 int style
= SWT
.BORDER
| SWT
.SEARCH
| SWT
.ICON_CANCEL
;
107 DelayedText delayedText
= new DelayedText(parent
, style
, ConnectUiConstants
.SEARCH_TEXT_DELAY
);
108 filterTxt
= delayedText
.getText();
109 filterTxt
.setLayoutData(EclipseUiUtils
.fillWidth());
111 final ServerPushSession pushSession
= new ServerPushSession();
112 delayedText
.addDelayedModifyListener(pushSession
, new ModifyListener() {
113 private static final long serialVersionUID
= 5003010530960334977L;
115 public void modifyText(ModifyEvent event
) {
116 delayedText
.getText().getDisplay().asyncExec(new Runnable() {
119 refreshFilteredList();
126 // Jump to the first item of the list using the down arrow
127 filterTxt
.addKeyListener(new KeyListener() {
128 private static final long serialVersionUID
= -4523394262771183968L;
131 public void keyReleased(KeyEvent e
) {
135 public void keyPressed(KeyEvent e
) {
136 // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
137 // boolean altPressed = (e.stateMask & SWT.ALT) != 0;
138 if (e
.keyCode
== SWT
.ARROW_DOWN
|| e
.keyCode
== SWT
.TAB
) {
139 Object first
= entityViewer
.getElementAt(0);
141 entityViewer
.getTable().setFocus();
142 entityViewer
.setSelection(new StructuredSelection(first
), true);
150 protected TableViewer
createListPart(Composite parent
, ILabelProvider labelProvider
) {
151 parent
.setLayout(new GridLayout());
153 Composite tableComposite
= new Composite(parent
, SWT
.NONE
);
154 GridData gd
= new GridData(GridData
.HORIZONTAL_ALIGN_FILL
| GridData
.GRAB_VERTICAL
155 | GridData
.VERTICAL_ALIGN_FILL
| GridData
.GRAB_HORIZONTAL
);
156 tableComposite
.setLayoutData(gd
);
158 TableViewer v
= new TableViewer(tableComposite
);
159 v
.setLabelProvider(labelProvider
);
161 TableColumn singleColumn
= new TableColumn(v
.getTable(), SWT
.V_SCROLL
);
162 TableColumnLayout tableColumnLayout
= new TableColumnLayout();
163 tableColumnLayout
.setColumnData(singleColumn
, new ColumnWeightData(85));
164 tableComposite
.setLayout(tableColumnLayout
);
166 // Corresponding table & style
167 Table table
= v
.getTable();
168 table
.setLinesVisible(true);
169 table
.setHeaderVisible(false);
170 CmsUtils
.markup(table
);
171 CmsUtils
.setItemHeight(table
, 26);
173 v
.setContentProvider(new BasicNodeListContentProvider());
174 v
.addDoubleClickListener(new JcrViewerDClickListener(systemWorkbenchService
));
179 public void dispose() {
180 JcrUtils
.logoutQuietly(session
);
185 public void setFocus() {
186 refreshFilteredList();
187 filterTxt
.setFocus();
191 public void forceRefresh(Object object
) {
192 refreshFilteredList();
195 protected void refreshFilteredList() {
197 String filter
= filterTxt
.getText();
198 // Prevents the query on the full repository
199 // if (isEmpty(filter)) {
200 // entityViewer.setInput(null);
205 String xpathQueryStr
= "//element(*, " + ConnectTypes
.CONNECT_ENTITY
+ ")";
206 String xpathFilter
= XPathUtils
.getFreeTextConstraint(filter
);
207 if (notEmpty(xpathFilter
))
208 xpathQueryStr
+= "[" + xpathFilter
+ "]";
210 // boolean doOrder = orderResultsBtn != null
211 // && !(orderResultsBtn.isDisposed())
212 // && orderResultsBtn.getSelection();
214 // xpathQueryStr += " order by jcr:title";
217 long begin
= System
.currentTimeMillis();
218 Query xpathQuery
= XPathUtils
.createQuery(session
, xpathQueryStr
);
220 xpathQuery
.setLimit(ConnectUiConstants
.SEARCH_DEFAULT_LIMIT
);
221 QueryResult result
= xpathQuery
.execute();
223 NodeIterator nit
= result
.getNodes();
224 entityViewer
.setInput(JcrUtils
.nodeIteratorToList(nit
));
225 if (log
.isDebugEnabled()) {
226 long end
= System
.currentTimeMillis();
227 log
.debug("Quick Search - Found: " + nit
.getSize() + " in " + (end
- begin
)
228 + " ms by executing XPath query (" + xpathQueryStr
+ ").");
230 } catch (RepositoryException e
) {
231 throw new SuiteWorkbenchException("Unable to list entities", e
);
235 /* DEPENDENCY INJECTION */
236 public void setRepository(Repository repository
) {
237 this.repository
= repository
;
240 public void setResourcesService(ResourcesService resourcesService
) {
241 this.resourcesService
= resourcesService
;
244 public void setActivitiesService(ActivitiesService activitiesService
) {
245 this.activitiesService
= activitiesService
;
248 public void setPeopleService(PeopleService peopleService
) {
249 this.peopleService
= peopleService
;
252 public void setSystemWorkbenchService(SystemWorkbenchService systemWorkbenchService
) {
253 this.systemWorkbenchService
= systemWorkbenchService
;