1 package org.argeo.connect.e4.parts;
2
3 import java.util.List;
4
5 import javax.annotation.PostConstruct;
6 import javax.annotation.PreDestroy;
7 import javax.inject.Inject;
8 import javax.jcr.Repository;
9 import javax.jcr.Session;
10
11 import org.argeo.cms.util.CmsUtils;
12 import org.argeo.connect.ConnectConstants;
13 import org.argeo.connect.UserAdminService;
14 import org.argeo.connect.e4.ConnectE4Constants;
15 import org.argeo.connect.e4.resources.parts.TagOrUntagInstancesWizard;
16 import org.argeo.connect.resources.ResourcesNames;
17 import org.argeo.connect.resources.ResourcesService;
18 import org.argeo.connect.ui.ConnectColumnDefinition;
19 import org.argeo.connect.ui.ConnectUiConstants;
20 import org.argeo.connect.ui.ConnectUiStyles;
21 import org.argeo.connect.ui.ConnectUiUtils;
22 import org.argeo.connect.ui.Refreshable;
23 import org.argeo.connect.ui.SystemWorkbenchService;
24 import org.argeo.connect.ui.util.JcrViewerDClickListener;
25 import org.argeo.connect.ui.util.VirtualJcrTableViewer;
26 import org.argeo.connect.ui.widgets.DateText;
27 import org.argeo.connect.ui.widgets.DelayedText;
28 import org.argeo.connect.util.ConnectJcrUtils;
29 import org.argeo.eclipse.ui.EclipseUiUtils;
30 import org.argeo.jcr.JcrUtils;
31 import org.eclipse.e4.ui.di.Focus;
32 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
33 import org.eclipse.jface.dialogs.MessageDialog;
34 import org.eclipse.jface.viewers.TableViewer;
35 import org.eclipse.jface.wizard.Wizard;
36 import org.eclipse.jface.wizard.WizardDialog;
37 import org.eclipse.rap.rwt.service.ServerPushSession;
38 import org.eclipse.swt.SWT;
39 import org.eclipse.swt.events.ModifyEvent;
40 import org.eclipse.swt.events.ModifyListener;
41 import org.eclipse.swt.events.SelectionAdapter;
42 import org.eclipse.swt.events.SelectionEvent;
43 import org.eclipse.swt.events.ShellAdapter;
44 import org.eclipse.swt.events.ShellEvent;
45 import org.eclipse.swt.events.TraverseEvent;
46 import org.eclipse.swt.events.TraverseListener;
47 import org.eclipse.swt.graphics.Point;
48 import org.eclipse.swt.graphics.Rectangle;
49 import org.eclipse.swt.layout.GridData;
50 import org.eclipse.swt.layout.GridLayout;
51 import org.eclipse.swt.layout.RowData;
52 import org.eclipse.swt.layout.RowLayout;
53 import org.eclipse.swt.widgets.Button;
54 import org.eclipse.swt.widgets.Composite;
55 import org.eclipse.swt.widgets.Control;
56 import org.eclipse.swt.widgets.Label;
57 import org.eclipse.swt.widgets.Link;
58 import org.eclipse.swt.widgets.Shell;
59 import org.eclipse.swt.widgets.Text;
60
61
62
63
64
65 public abstract class AbstractSearchEntityEditor implements Refreshable {
66
67
68 @Inject
69 private Repository repository;
70 @Inject
71 private ResourcesService resourcesService;
72 @Inject
73 private UserAdminService userAdminService;
74 @Inject
75 private SystemWorkbenchService systemWorkbenchService;
76 @Inject
77 private MPart mPart;
78
79 private Session session;
80 private String entityType;
81 private String basePath;
82
83
84 private VirtualJcrTableViewer tableCmp;
85 private Text filterTxt;
86 private TraverseListener traverseListener;
87
88
89 private Object[] elements;
90 private String filterString;
91
92 public void init() {
93
94
95
96
97 session = ConnectJcrUtils.login(repository);
98 }
99
100 @PostConstruct
101 public void createPartControl(Composite parent) {
102 entityType = mPart.getPersistedState().get(ConnectE4Constants.NODE_TYPE);
103
104 init();
105 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
106
107 Composite searchCmp = new Composite(parent, SWT.NO_FOCUS);
108 searchCmp.setLayoutData(EclipseUiUtils.fillWidth());
109 if (!showStaticFilterSection()) {
110 searchCmp.setLayout(new GridLayout());
111 Composite filterCmp = new Composite(searchCmp, SWT.NO_FOCUS);
112 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
113 populateSearchPanel(filterCmp);
114 }
115
116 else
117
118 populateStaticSearchPanel(searchCmp);
119
120
121 if (hasCheckBoxes()) {
122 Composite menuCmp = new Composite(parent, SWT.NO_FOCUS);
123 createCheckBoxMenu(menuCmp);
124 menuCmp.setLayoutData(EclipseUiUtils.fillWidth());
125 }
126
127
128 Composite tableCmp = new Composite(parent, SWT.NO_FOCUS);
129 createListPart(tableCmp);
130 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
131
132 if (!systemWorkbenchService.lazyLoadLists())
133
134 refreshFilteredList();
135 }
136
137 protected abstract void refreshFilteredList();
138
139
140
141
142
143 protected boolean showStaticFilterSection() {
144 return true;
145 }
146
147
148 protected void populateStaticFilters(Composite body) {
149 }
150
151
152 protected void setNbOfFoundResultsLbl(Label resultNbLbl) {
153 if (elements == null)
154 resultNbLbl.setText(" (No result yet) ");
155 else if (elements.length == 0)
156 resultNbLbl.setText(" (No result found) ");
157 else if (elements.length == 1)
158 resultNbLbl.setText(" One result found ");
159 else
160 resultNbLbl.setText(elements.length + " results found ");
161 resultNbLbl.getParent().layout(true, true);
162 }
163
164 protected void setNbOfFoundResultsLbl(long nbOfResults) {
165 Label label = getResultLengthLbl();
166 if (label != null && !label.isDisposed())
167 setNbOfFoundResultsLbl(label);
168 }
169
170
171
172
173 protected Label getResultLengthLbl() {
174 return null;
175 }
176
177
178
179
180
181 protected boolean hasCheckBoxes() {
182 return false;
183 }
184
185 protected void createCheckBoxMenu(Composite parent) {
186 RowLayout layout = new RowLayout(SWT.HORIZONTAL);
187 parent.setLayout(layout);
188
189 final Button selectAllBtn = new Button(parent, SWT.PUSH);
190 selectAllBtn.setToolTipText("Select all");
191 selectAllBtn.setImage(parent.getDisplay().getSystemImage(SWT.CHECK));
192
193 RowData rd = new RowData(40, SWT.DEFAULT);
194 selectAllBtn.setLayoutData(rd);
195
196 selectAllBtn.addSelectionListener(new SelectionAdapter() {
197 private static final long serialVersionUID = 1L;
198
199 @Override
200 public void widgetSelected(SelectionEvent e) {
201 if (tableCmp.getSelectedElements().length == 0) {
202 tableCmp.setAllChecked(true);
203
204 selectAllBtn.setImage(parent.getDisplay().getSystemImage(SWT.CHECK));
205
206 selectAllBtn.setToolTipText("Unselect all (At least one element is already selected)");
207 } else {
208 tableCmp.setAllChecked(false);
209 selectAllBtn.setImage(null);
210
211 selectAllBtn.setToolTipText("Select all");
212 }
213 }
214 });
215
216 Button addTagBtn = new Button(parent, SWT.TOGGLE);
217 addTagBtn.setText("Tag");
218
219 addToggleStateTagBtnListener(addTagBtn, ConnectConstants.RESOURCE_TAG, ResourcesNames.CONNECT_TAGS);
220
221
222
223
224
225
226
227
228 }
229
230 private void addToggleStateTagBtnListener(final Button addTagBtn, final String tagId,
231 final String taggablePropName) {
232
233 addTagBtn.addSelectionListener(new SelectionAdapter() {
234 private static final long serialVersionUID = 9066664395274942610L;
235 private DropDownPopup dropDown;
236
237 @Override
238 public void widgetSelected(SelectionEvent e) {
239
240 boolean toggled = addTagBtn.getSelection();
241 if (toggled) {
242 if (dropDown != null && !dropDown.isDisposed())
243
244 dropDown.setVisible(true);
245 else {
246
247 dropDown = new DropDownPopup(addTagBtn, tagId, taggablePropName);
248 dropDown.open();
249 }
250 } else {
251 if (dropDown != null && !dropDown.isDisposed())
252 dropDown.dispose();
253 }
254 }
255 });
256 }
257
258 private class DropDownPopup extends Shell {
259 private static final long serialVersionUID = 1L;
260 private Button toggleBtn;
261 private String tagId;
262 private String taggablePropName;
263
264 public DropDownPopup(final Control source, String tagId, String taggablePropName) {
265 super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP);
266
267 toggleBtn = (Button) source;
268 this.tagId = tagId;
269 this.taggablePropName = taggablePropName;
270
271 populate();
272
273 CmsUtils.style(DropDownPopup.this, ConnectUiStyles.POPUP_SHELL);
274 pack();
275 layout();
276
277
278 Rectangle parPosition = source.getBounds();
279 Point absolute = source.toDisplay(source.getSize().x, source.getSize().y);
280 absolute.x = absolute.x - parPosition.width;
281 absolute.y = absolute.y + 2;
282 setLocation(absolute);
283
284 addShellListener(new ShellAdapter() {
285 private static final long serialVersionUID = 5178980294808435833L;
286
287 @Override
288 public void shellDeactivated(ShellEvent e) {
289 close();
290 dispose();
291 if (!source.isDisposed()) {
292 boolean toggled = toggleBtn.getSelection();
293 if (toggled)
294 toggleBtn.setSelection(false);
295 e.doit = false;
296 }
297
298 }
299 });
300 open();
301 }
302
303 protected void populate() {
304 Composite parent = DropDownPopup.this;
305 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
306
307 final Button addTagBtn = new Button(parent, SWT.LEAD | SWT.FLAT);
308 addTagBtn.setText("Add to selected");
309 addTagBtn.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
310 addBtnListener(toggleBtn.getShell(), addTagBtn, tagId, taggablePropName,
311 TagOrUntagInstancesWizard.TYPE_ADD);
312
313 final Button removeTagBtn = new Button(parent, SWT.LEAD | SWT.FLAT);
314 removeTagBtn.setText("Remove from selected");
315 removeTagBtn.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
316 addBtnListener(toggleBtn.getShell(), removeTagBtn, tagId, taggablePropName,
317 TagOrUntagInstancesWizard.TYPE_REMOVE);
318 }
319 }
320
321 protected boolean isOrgOrPerson() {
322
323
324
325
326
327
328 return false;
329 }
330
331 private void addBtnListener(final Shell parentShell, final Button button, final String tagId,
332 final String taggablePropName, final int actionType) {
333 button.addSelectionListener(new SelectionAdapter() {
334 private static final long serialVersionUID = 2236384303910015747L;
335
336 @Override
337 public void widgetSelected(SelectionEvent e) {
338 Object[] rows = tableCmp.getSelectedElements();
339
340 if (rows.length == 0)
341 MessageDialog.openInformation(parentShell, "Unvalid selection",
342 "No item is selected. Nothing has been done.");
343 else {
344
345
346 Wizard wizard = new TagOrUntagInstancesWizard(button.getDisplay(), actionType, session,
347 resourcesService, systemWorkbenchService, rows, null, tagId, taggablePropName);
348 WizardDialog dialog = new WizardDialog(parentShell, wizard);
349 int result = dialog.open();
350 if (result == WizardDialog.OK) {
351 refreshFilteredList();
352 }
353 }
354 }
355 });
356 }
357
358
359 protected int getCurrRowHeight() {
360 return 20;
361 }
362
363
364
365
366
367
368 protected boolean queryOnCreation() {
369 return true;
370 }
371
372
373
374
375
376 public abstract List<ConnectColumnDefinition> getColumnDefinition(String extractId);
377
378
379
380
381
382 protected void resetFilterText() {
383 getFilterText().setText("");
384 }
385
386
387
388
389
390
391 public Object[] getElements(String exportId) {
392 return elements;
393 }
394
395
396 public String getFilterAsString() {
397 return filterString;
398 }
399
400 protected void createListPart(Composite parent) {
401 parent.setLayout(new GridLayout());
402 tableCmp = new VirtualJcrTableViewer(parent, SWT.MULTI, getColumnDefinition(null), hasCheckBoxes());
403 TableViewer tableViewer = tableCmp.getTableViewer();
404 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
405
406
407 String entityType = getEntityType();
408
409 if (getColumnDefinition(null).get(0).getSelectorName() == null)
410 entityType = null;
411 tableViewer.addDoubleClickListener(new JcrViewerDClickListener(entityType));
412 }
413
414
415 protected void populateStaticSearchPanel(final Composite parent) {
416 parent.setLayout(new GridLayout(2, false));
417
418 Composite filterCmp = new Composite(parent, SWT.NO_FOCUS);
419 filterCmp.setLayoutData(EclipseUiUtils.fillWidth());
420 populateSearchPanel(filterCmp);
421
422
423 final Link more = new Link(parent, SWT.NONE);
424 CmsUtils.markup(more);
425 Composite staticFilterCmp = new Composite(parent, SWT.NO_FOCUS);
426 staticFilterCmp.setLayoutData(EclipseUiUtils.fillWidth(2));
427 populateStaticFilters(staticFilterCmp);
428
429 MoreLinkListener listener = new MoreLinkListener(more, staticFilterCmp, false);
430
431 listener.refresh();
432 more.addSelectionListener(listener);
433 }
434
435 private class MoreLinkListener extends SelectionAdapter {
436 private static final long serialVersionUID = -524987616510893463L;
437 private boolean isShown;
438 private final Composite staticFilterCmp;
439 private final Link moreLk;
440
441 public MoreLinkListener(Link moreLk, Composite staticFilterCmp, boolean isShown) {
442 this.moreLk = moreLk;
443 this.staticFilterCmp = staticFilterCmp;
444 this.isShown = isShown;
445 }
446
447 @Override
448 public void widgetSelected(SelectionEvent e) {
449 isShown = !isShown;
450 refresh();
451 }
452
453 public void refresh() {
454 GridData gd = (GridData) staticFilterCmp.getLayoutData();
455 if (isShown) {
456 moreLk.setText("<a> Less... </a>");
457 gd.heightHint = SWT.DEFAULT;
458 } else {
459 moreLk.setText("<a> More... </a>");
460 gd.heightHint = 0;
461 }
462 forceLayout();
463 }
464
465 private void forceLayout() {
466 staticFilterCmp.getParent().getParent().layout(true, true);
467 }
468
469 }
470
471
472 protected void populateSearchPanel(Composite parent) {
473 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
474 boolean isDyn = systemWorkbenchService.queryWhenTyping();
475 int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL;
476
477
478
479
480
481
482 if (isDyn) {
483 final DelayedText delayedText = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY);
484 final ServerPushSession pushSession = new ServerPushSession();
485 (delayedText).addDelayedModifyListener(pushSession, new ModifyListener() {
486 private static final long serialVersionUID = 5003010530960334977L;
487
488 public void modifyText(ModifyEvent event) {
489 delayedText.getText().getDisplay().asyncExec(new Runnable() {
490 @Override
491 public void run() {
492 refreshFilteredList();
493 }
494 });
495 pushSession.stop();
496 }
497 });
498 filterTxt = delayedText.getText();
499 } else {
500 filterTxt = new Text(parent, style);
501 }
502 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
503
504 traverseListener = new TraverseListener() {
505 private static final long serialVersionUID = 1914600503113422597L;
506
507 @Override
508 public void keyTraversed(TraverseEvent e) {
509 if (e.keyCode == SWT.CR) {
510 e.doit = false;
511 refreshFilteredList();
512 }
513 }
514 };
515 filterTxt.addTraverseListener(traverseListener);
516
517
518
519
520
521
522
523
524 }
525
526 protected TraverseListener getTraverseListener() {
527 return traverseListener;
528 }
529
530
531 protected Text getFilterText() {
532 return filterTxt;
533 }
534
535
536 protected void setViewerInput(Object[] items) {
537 this.elements = items;
538 TableViewer tableViewer = tableCmp.getTableViewer();
539
540 tableViewer.setInput(items);
541
542 tableViewer.setItemCount(items.length);
543 setNbOfFoundResultsLbl(items.length);
544 tableViewer.refresh();
545 }
546
547
548 protected void setFilterString(String filterString) {
549 this.filterString = filterString;
550 }
551
552
553 @Focus
554 public void setFocus() {
555 getFilterText().forceFocus();
556 }
557
558 @PreDestroy
559 public void dispose() {
560 JcrUtils.logoutQuietly(session);
561
562 }
563
564 @Override
565 public void forceRefresh(Object object) {
566 refreshFilteredList();
567 }
568
569
570
571 protected String getEntityType() {
572 return entityType;
573
574 }
575
576 protected String getBasePath() {
577 return basePath;
578
579 }
580
581 protected VirtualJcrTableViewer getTableViewer() {
582 return tableCmp;
583 }
584
585 protected Session getSession() {
586 return session;
587 }
588
589 protected UserAdminService getUserAdminService() {
590 return userAdminService;
591 }
592
593 protected ResourcesService getResourceService() {
594 return resourcesService;
595 }
596
597 protected SystemWorkbenchService getSystemWorkbenchService() {
598 return systemWorkbenchService;
599 }
600
601
602 protected Text createBoldLT(Composite parent, String title, String message, String tooltip) {
603 return createBoldLT(parent, title, message, tooltip, 1);
604 }
605
606 protected Text createBoldLT(Composite parent, String title, String message, String tooltip, int colspan) {
607 ConnectUiUtils.createBoldLabel(parent, title);
608 Text text = new Text(parent, SWT.BOTTOM | SWT.BORDER);
609 text.setLayoutData(EclipseUiUtils.fillAll(colspan, 1));
610 text.setMessage(message);
611 text.setToolTipText(tooltip);
612 return text;
613 }
614
615 protected DateText createLD(Composite parent, String title, String tooltip) {
616 DateText dateText = new DateText(parent, SWT.NO_FOCUS);
617 dateText.setToolTipText(tooltip);
618 dateText.setMessage(title);
619 return dateText;
620 }
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639 }