Improve the new Argeo Suite shell.
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 7 Oct 2020 09:17:16 +0000 (11:17 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 7 Oct 2020 09:17:16 +0000 (11:17 +0200)
19 files changed:
org.argeo.suite.theme.default/rap/work.css
org.argeo.suite.ui.rap/.classpath [deleted file]
org.argeo.suite.ui.rap/.project
org.argeo.suite.ui/OSGI-INF/cmsApp.xml
org.argeo.suite.ui/OSGI-INF/header.xml [new file with mode: 0644]
org.argeo.suite.ui/OSGI-INF/l10n/bundle.properties
org.argeo.suite.ui/OSGI-INF/workHeader.xml [deleted file]
org.argeo.suite.ui/bnd.bnd
org.argeo.suite.ui/config/dashboard.properties
org.argeo.suite.ui/config/header.properties [new file with mode: 0644]
org.argeo.suite.ui/config/leadPane.properties
org.argeo.suite.ui/config/loginScreen.properties
org.argeo.suite.ui/config/recentItems.properties
org.argeo.suite.ui/config/workHeader.properties [deleted file]
org.argeo.suite.ui/src/org/argeo/suite/ui/ArgeoSuiteApp.java
org.argeo.suite.ui/src/org/argeo/suite/ui/ArgeoSuiteUi.java
org.argeo.suite.ui/src/org/argeo/suite/ui/RecentItems.java
org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteMsg.java
org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteStyle.java

index 383fe17bf06f9ffa76b809890e069b3c373585f2..b617cf92332a4e0b730effe22fa6b6a8e614309c 100644 (file)
@@ -19,4 +19,10 @@ Button.argeo-suite-leadPane {
        font: bold 14px sans-serif;
        color: white;
        background-color: white;
+}
+
+.argeo-suite-recentItems {
+       font: bold 14px sans-serif;
+       color: white;
+       background-color: #204a87;
 }
\ No newline at end of file
diff --git a/org.argeo.suite.ui.rap/.classpath b/org.argeo.suite.ui.rap/.classpath
deleted file mode 100644 (file)
index e801ebf..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="output" path="bin"/>
-</classpath>
index 4e66caa8e73a7e887c670fca34efcac6d82a2d4c..eff6bb0e46e2439577ece1a0c04e1e55cf48f56c 100644 (file)
@@ -5,11 +5,6 @@
        <projects>
        </projects>
        <buildSpec>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
                <buildCommand>
                        <name>org.eclipse.pde.ManifestBuilder</name>
                        <arguments>
@@ -28,6 +23,5 @@
        </buildSpec>
        <natures>
                <nature>org.eclipse.pde.PluginNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
        </natures>
 </projectDescription>
index 54c16df552b1e7043e93cbf96e410410bff38b71..3d77a7d6736385e76d260740442e3cbe10b9db9e 100644 (file)
@@ -4,7 +4,8 @@
    <service>
       <provide interface="org.argeo.cms.ui.CmsApp"/>
    </service>
-   <reference bind="addUiProvider" cardinality="0..n" interface="org.argeo.cms.ui.CmsUiProvider" name="CmsUiProvider" policy="dynamic" target="(argeo.suite.ui=*)" unbind="removeUiProvider"/>
-   <reference bind="addTheme" cardinality="0..n" interface="org.argeo.cms.ui.CmsTheme" name="CmsTheme" policy="dynamic" unbind="removeTheme"/>
+   <reference bind="addUiProvider" cardinality="0..n" interface="org.argeo.cms.ui.CmsUiProvider" name="CmsUiProvider" policy="dynamic" unbind="removeUiProvider"/>
+   <reference bind="addTheme" cardinality="1..n" interface="org.argeo.cms.ui.CmsTheme" name="CmsTheme" policy="dynamic" unbind="removeTheme"/>
    <properties entry="config/cmsApp.properties"/>
+   <reference bind="setRepository" cardinality="1..1" interface="javax.jcr.Repository" name="Repository" policy="dynamic"/>
 </scr:component>
diff --git a/org.argeo.suite.ui/OSGI-INF/header.xml b/org.argeo.suite.ui/OSGI-INF/header.xml
new file mode 100644 (file)
index 0000000..a8fc66d
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" immediate="false" name="Default Work Header">
+   <implementation class="org.argeo.suite.ui.DefaultHeader"/>
+   <service>
+      <provide interface="org.argeo.cms.ui.CmsUiProvider"/>
+      <provide interface="org.osgi.service.cm.ManagedService"/>
+   </service>
+   <properties entry="config/header.properties"/>
+</scr:component>
index 6fe83d37a4bd1de221cf8649aeb2e93a91cc17bc..4792deddc395f6d02089385f9e40b9ca252a9bb6 100644 (file)
@@ -2,5 +2,6 @@ dashboard=dashboard
 people=contacts
 documents=documents
 locations=locations
+recentItems=recent items
 
-defaultWorkAppTitle=Argeo Suite
\ No newline at end of file
+appTitle=Argeo Suite
\ No newline at end of file
diff --git a/org.argeo.suite.ui/OSGI-INF/workHeader.xml b/org.argeo.suite.ui/OSGI-INF/workHeader.xml
deleted file mode 100644 (file)
index eaf3a30..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" immediate="false" name="Default Work Header">
-   <implementation class="org.argeo.suite.ui.DefaultHeader"/>
-   <service>
-      <provide interface="org.argeo.cms.ui.CmsUiProvider"/>
-      <provide interface="org.osgi.service.cm.ManagedService"/>
-   </service>
-   <properties entry="config/workHeader.properties"/>
-</scr:component>
index dca43fe510c7a879022fb47240e696f5a53a0e6d..c64a5cde7c9e21163a97878654638845e610b9bb 100644 (file)
@@ -1,6 +1,6 @@
 Service-Component:\
 OSGI-INF/cmsApp.xml,\
-OSGI-INF/workHeader.xml,\
+OSGI-INF/header.xml,\
 OSGI-INF/leadPane.xml,\
 OSGI-INF/loginScreen.xml,\
 OSGI-INF/recentItems.xml,\
@@ -10,4 +10,7 @@ Import-Package:\
 org.argeo.api,\
 org.eclipse.swt,\
 org.osgi.framework,\
+org.argeo.connect.ui,\
+org.argeo.entity,\
+org.eclipse.core.commands.common,\
 *
index ea5669dc5abfa9193d1116516263d3133c66f642..183254361b5df0b5511371ecd08ee8b5d49ce0fe 100644 (file)
@@ -1,2 +1 @@
 service.pid=argeo.suite.ui.dashboard
-argeo.suite.ui=true
diff --git a/org.argeo.suite.ui/config/header.properties b/org.argeo.suite.ui/config/header.properties
new file mode 100644 (file)
index 0000000..034d5f5
--- /dev/null
@@ -0,0 +1,4 @@
+service.pid=argeo.suite.ui.header
+argeo.suite.ui=true
+
+argeo.suite.ui.header.title=%appTitle
\ No newline at end of file
index fc3a3bac4e8a4e1a23d6e1f1102ed81a9514b01e..0d7b1934459e4ae314e57f81240987ff58188298 100644 (file)
@@ -1,2 +1 @@
 service.pid=argeo.suite.ui.leadPane
-argeo.suite.ui=true
index 81d54c0ba0c3851cad2de884b7eaaf34899a71b2..332614dcea72dec8424b9fd71cf63192f210cafa 100644 (file)
@@ -1,2 +1 @@
 service.pid=argeo.suite.ui.loginScreen
-argeo.suite.ui=true
index 1cf876616d4b3440a3e6e5c5ce22205ad15b6a44..7321c556432afb0080bc1462fa897042e3b5403b 100644 (file)
@@ -1,2 +1 @@
 service.pid=argeo.suite.ui.recentItems
-argeo.suite.ui=true
diff --git a/org.argeo.suite.ui/config/workHeader.properties b/org.argeo.suite.ui/config/workHeader.properties
deleted file mode 100644 (file)
index e5bc6b3..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-service.pid=argeo.suite.ui.header
-argeo.suite.ui=true
-
-argeo.suite.ui.header.title=%defaultWorkAppTitle
\ No newline at end of file
index fce2deb369fbb752c60017422725ecac42bb9a1a..da86e5b6c336bd13bb3a2693ff8e976407634d87 100644 (file)
@@ -1,8 +1,12 @@
 package org.argeo.suite.ui;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.SortedMap;
 import java.util.TreeMap;
 
 import javax.jcr.Node;
@@ -11,15 +15,16 @@ import javax.jcr.Session;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.argeo.api.RankingKey;
 import org.argeo.cms.ui.AbstractCmsApp;
 import org.argeo.cms.ui.CmsTheme;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.cms.ui.CmsView;
+import org.argeo.cms.ui.dialogs.CmsFeedback;
 import org.argeo.jcr.JcrUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
-import org.osgi.framework.Constants;
 
 /** The Argeo Suite App. */
 public class ArgeoSuiteApp extends AbstractCmsApp {
@@ -35,7 +40,12 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
        private final static String DEFAULT_UI_NAME = "work";
        private final static String DEFAULT_THEME_ID = "org.argeo.suite.theme.default";
 
-       private Map<String, CmsUiProvider> uiProviders = new TreeMap<>();
+       private SortedMap<RankingKey, CmsUiProvider> uiProviders = Collections.synchronizedSortedMap(new TreeMap<>());
+
+       // TODO make more optimal or via CmsSession/CmsView
+       private List<ArgeoSuiteUi> knownUis = new ArrayList<>();
+
+//     private CmsUiProvider headerPart = null;
 
        public void init(Map<String, String> properties) {
                if (log.isDebugEnabled())
@@ -43,6 +53,9 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
        }
 
        public void destroy(Map<String, String> properties) {
+               for (ArgeoSuiteUi ui : knownUis)
+                       if (!ui.isDisposed())
+                               ui.dispose();
                if (log.isDebugEnabled())
                        log.info("Argeo Suite App stopped");
 
@@ -62,6 +75,7 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
                if (theme != null)
                        CmsTheme.registerCmsTheme(parent.getShell(), theme);
                ArgeoSuiteUi argeoSuiteUi = new ArgeoSuiteUi(parent, SWT.NONE);
+               knownUis.add(argeoSuiteUi);
                refreshUi(argeoSuiteUi, null);
                return argeoSuiteUi;
        }
@@ -74,18 +88,30 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
 
        @Override
        public void refreshUi(Composite parent, String state) {
-               Node context = null;
-               ArgeoSuiteUi argeoSuiteUi = (ArgeoSuiteUi) parent;
-               refreshPart(findUiProvider(HEADER_PID, context), argeoSuiteUi.getHeader(), context);
-               CmsView cmsView = CmsView.getCmsView(parent);
-               if (cmsView.isAnonymous()) {
-                       refreshPart(findUiProvider(LOGIN_SCREEN_PID, context), argeoSuiteUi.getDefaultBody(), context);
-               } else {
-                       refreshPart(findUiProvider(DASHBOARD_PID, context), argeoSuiteUi.getDefaultBody(), context);
+               try {
+                       Node context = null;
+                       ArgeoSuiteUi argeoSuiteUi = (ArgeoSuiteUi) parent;
+                       refreshPart(findUiProvider(HEADER_PID, context), argeoSuiteUi.getHeader(), context);
+                       CmsView cmsView = CmsView.getCmsView(parent);
+                       if (cmsView.isAnonymous()) {
+                               refreshPart(findUiProvider(LOGIN_SCREEN_PID, context), argeoSuiteUi.getDefaultBody(), context);
+                       } else {
+                               try {
+                                       if (argeoSuiteUi.getSession() == null)
+                                               argeoSuiteUi.setSession(getRepository().login());
+                                       context = argeoSuiteUi.getSession().getRootNode();
+
+                               } catch (RepositoryException e) {
+                                       e.printStackTrace();
+                               }
+                               refreshPart(findUiProvider(DASHBOARD_PID, context), argeoSuiteUi.getDefaultBody(), context);
+                       }
+                       refreshPart(findUiProvider(LEAD_PANE_PID, context), argeoSuiteUi.getLeadPane(), context);
+                       refreshPart(findUiProvider(RECENT_ITEMS_PID, context), argeoSuiteUi.getEntryArea(), context);
+                       argeoSuiteUi.layout(true, true);
+               } catch (Exception e) {
+                       CmsFeedback.show("Unexpected exception", e);
                }
-               refreshPart(findUiProvider(LEAD_PANE_PID, context), argeoSuiteUi.getLeadPane(), context);
-               refreshPart(findUiProvider(RECENT_ITEMS_PID, context), argeoSuiteUi.getEntryArea(), context);
-               argeoSuiteUi.layout(true, true);
        }
 
        private void refreshPart(CmsUiProvider uiProvider, Composite part, Node context) {
@@ -96,8 +122,19 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
 
        private CmsUiProvider findUiProvider(String pid, Node context) {
                if (pid != null) {
-                       if (uiProviders.containsKey(pid))
-                               return uiProviders.get(pid);
+                       SortedMap<RankingKey, CmsUiProvider> subMap = uiProviders.subMap(RankingKey.minPid(pid),
+                                       RankingKey.maxPid(pid));
+                       CmsUiProvider found = null;
+                       providers: for (RankingKey key : subMap.keySet()) {
+                               if (key.getPid() == null || !key.getPid().equals(pid))
+                                       break providers;
+                               found = subMap.get(key);
+                               log.debug(key);
+                       }
+//                     if (uiProviders.containsKey(pid))
+//                             return uiProviders.get(pid);
+                       if (found != null)
+                               return found;
                }
 
                // nothing
@@ -158,21 +195,30 @@ public class ArgeoSuiteApp extends AbstractCmsApp {
         * Dependency injection.
         */
 
-       public void addUiProvider(CmsUiProvider uiProvider, Map<String, String> properties) {
-               String servicePid = properties.get(Constants.SERVICE_PID);
-               if (servicePid == null) {
-                       log.error("No service pid found for " + uiProvider.getClass() + ", " + properties);
-               } else {
-                       uiProviders.put(servicePid, uiProvider);
-                       if (log.isDebugEnabled())
-                               log.debug("Added UI provider " + servicePid + " to CMS app.");
-               }
+       public void addUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
+               RankingKey partKey = new RankingKey(properties);
+//             String servicePid = properties.get(Constants.SERVICE_PID);
+//             if (servicePid == null) {
+//                     log.error("No service pid found for " + uiProvider.getClass() + ", " + properties);
+//             } else {
+               uiProviders.put(partKey, uiProvider);
+               if (log.isDebugEnabled())
+                       log.debug("Added UI provider " + partKey + " to CMS app.");
+//             }
 
        }
 
-       public void removeUiProvider(CmsUiProvider uiProvider, Map<String, String> properties) {
-               String servicePid = properties.get(Constants.SERVICE_PID);
-               uiProviders.remove(servicePid);
+       public void removeUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
+               RankingKey partKey = new RankingKey(properties);
+//             String servicePid = properties.get(Constants.SERVICE_PID);
+               uiProviders.remove(partKey);
 
        }
+
+//     public void setHeaderPart(CmsUiProvider headerPart) {
+//             this.headerPart = headerPart;
+//             if (log.isDebugEnabled())
+//                     log.debug("Header set.");
+//     }
+
 }
index 08441a3e17a9f8868b9d511d0675d32bf297012f..73dc2f4e4be0d2eeaf6485d5ba720cd7bd475da6 100644 (file)
@@ -2,6 +2,8 @@ package org.argeo.suite.ui;
 
 import static org.argeo.suite.ui.SuiteIcon.dashboard;
 
+import javax.jcr.Session;
+
 import org.argeo.cms.ui.CmsTheme;
 import org.argeo.cms.ui.CmsView;
 import org.argeo.cms.ui.util.CmsUiUtils;
@@ -11,8 +13,6 @@ import org.eclipse.swt.custom.CTabItem;
 import org.eclipse.swt.custom.SashForm;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.layout.RowLayout;
-import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.ToolBar;
 import org.eclipse.swt.widgets.ToolItem;
@@ -33,6 +33,8 @@ public class ArgeoSuiteUi extends Composite {
        private Composite defaultBody;
 
        private CmsTheme theme;
+       
+       private Session session;
 
        public ArgeoSuiteUi(Composite parent, int style) {
                super(parent, style);
@@ -124,4 +126,13 @@ public class ArgeoSuiteUi extends Composite {
                return belowHeader;
        }
 
+       Session getSession() {
+               return session;
+       }
+
+       void setSession(Session session) {
+               this.session = session;
+       }
+
+       
 }
index 218563fab753b78eaae49810a05f2d3818e0e359..d481f2b0eda0a278ce5963017d11419a5978f149 100644 (file)
@@ -1,17 +1,51 @@
 package org.argeo.suite.ui;
 
+import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty;
+
+import java.util.List;
+import java.util.Map;
+
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
 
 import org.argeo.cms.ui.CmsTheme;
 import org.argeo.cms.ui.CmsUiProvider;
 import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.connect.ui.ConnectUiConstants;
+import org.argeo.connect.ui.util.BasicNodeListContentProvider;
+import org.argeo.connect.ui.widgets.DelayedText;
+import org.argeo.connect.util.XPathUtils;
+import org.argeo.eclipse.ui.EclipseUiUtils;
+import org.argeo.entity.EntityNames;
+import org.argeo.entity.EntityTypes;
+import org.argeo.jcr.JcrUtils;
+import org.eclipse.jface.layout.TableColumnLayout;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.Text;
 
 /** List recent items. */
@@ -19,25 +53,215 @@ public class RecentItems implements CmsUiProvider {
        int SEARCH_TEXT_DELAY = 800;
        private CmsTheme theme;
 
+       private String entityType;
+
        @Override
        public Control createUi(Composite parent, Node context) throws RepositoryException {
                theme = CmsTheme.getCmsTheme(parent);
                parent.setLayout(new GridLayout());
 
-               Composite top = new Composite(parent, SWT.NONE);
-               top.setLayoutData(CmsUiUtils.fillWidth());
-               top.setLayout(new GridLayout(2, false));
+//             Composite top = new Composite(parent, SWT.NONE);
+//             top.setLayoutData(CmsUiUtils.fillWidth());
+//             top.setLayout(new GridLayout(2, false));
 
-               Label search = new Label(top, SWT.NONE);
-               search.setImage(SuiteIcon.search.getSmallIcon(theme));
-               Text text = new Text(top, SWT.SINGLE | SWT.BORDER);
-               text.setLayoutData(CmsUiUtils.fillWidth());
-//             DelayedText delayedText = new DelayedText(top, SWT.SINGLE | SWT.BORDER, SEARCH_TEXT_DELAY);
-//             delayedText.getText().setLayoutData(CmsUiUtils.fillWidth());
+               Label lbl = new Label(parent, SWT.NONE);
+//             search.setImage(SuiteIcon.search.getSmallIcon(theme));
+               lbl.setText(SuiteMsg.recentItems.lead());
+               CmsUiUtils.style(lbl, SuiteStyle.recentItems);
+
+               if (context == null)
+                       return null;
+               SingleEntityViewer entityViewer = new SingleEntityViewer(parent, SWT.NONE, context.getSession());
+               entityViewer.setLayoutData(CmsUiUtils.fillAll());
+               entityViewer.createUi();
+               return entityViewer;
 
-               TableViewer viewer = new TableViewer(parent);
-               viewer.getTable().setLayoutData(CmsUiUtils.fillAll());
-               return text;
        }
 
+       public void init(Map<String, String> properties) {
+               entityType = properties.get(EntityNames.ENTITY_TYPE);
+       }
+
+       class SingleEntityViewer extends Composite {
+               Text filterTxt;
+               TableViewer entityViewer;
+               Session session;
+
+               public SingleEntityViewer(Composite parent, int style, Session session) {
+                       super(parent, style);
+                       this.session = session;
+               }
+
+               public void createUi() {
+                       // MainLayout
+                       setLayout(new GridLayout());
+                       addFilterPanel(this);
+                       entityViewer = createListPart(this, new SingleEntityLabelProvider());
+                       refreshFilteredList();
+
+                       try {
+                               String[] nodeTypes = entityType != null && entityType.contains(":") ? new String[] { entityType }
+                                               : null;
+                               session.getWorkspace().getObservationManager().addEventListener(new EventListener() {
+
+                                       @Override
+                                       public void onEvent(EventIterator events) {
+                                               getDisplay().asyncExec(() -> refreshFilteredList());
+                                       }
+                               }, Event.PROPERTY_CHANGED | Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED, "/", true,
+                                               null, nodeTypes, false);
+                       } catch (RepositoryException e) {
+                               throw new IllegalStateException("Cannot add JCR observer", e);
+                       }
+
+               }
+
+               private void addFilterPanel(Composite parent) {
+                       // Use a delayed text: the query won't be done until the user stop
+                       // typing for 800ms
+                       int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL;
+                       DelayedText delayedText = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY);
+                       filterTxt = delayedText.getText();
+                       filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
+
+                       // final ServerPushSession pushSession = new ServerPushSession();
+                       delayedText.addDelayedModifyListener(null, new ModifyListener() {
+                               private static final long serialVersionUID = 5003010530960334977L;
+
+                               public void modifyText(ModifyEvent event) {
+                                       delayedText.getText().getDisplay().asyncExec(new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       refreshFilteredList();
+                                               }
+                                       });
+                                       // pushSession.stop();
+                               }
+                       });
+
+                       // Jump to the first item of the list using the down arrow
+                       filterTxt.addKeyListener(new KeyListener() {
+                               private static final long serialVersionUID = -4523394262771183968L;
+
+                               @Override
+                               public void keyReleased(KeyEvent e) {
+                               }
+
+                               @Override
+                               public void keyPressed(KeyEvent e) {
+                                       // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0;
+                                       // boolean altPressed = (e.stateMask & SWT.ALT) != 0;
+                                       if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) {
+//                                     Object first = entityViewer.getElementAt(0);
+//                                     if (first != null) {
+//                                             entityViewer.getTable().setFocus();
+//                                             entityViewer.setSelection(new StructuredSelection(first), true);
+//                                     }
+                                               e.doit = false;
+                                       }
+                               }
+                       });
+
+                       addDisposeListener((e) -> {
+                               delayedText.close();
+                       });
+               }
+
+               protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) {
+                       parent.setLayout(new GridLayout());
+
+                       Composite tableComposite = new Composite(parent, SWT.NONE);
+                       GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL
+                                       | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
+                       tableComposite.setLayoutData(gd);
+
+                       TableViewer v = new TableViewer(tableComposite);
+                       v.setLabelProvider(labelProvider);
+
+                       TableColumn singleColumn = new TableColumn(v.getTable(), SWT.V_SCROLL);
+                       TableColumnLayout tableColumnLayout = new TableColumnLayout();
+                       tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(85));
+                       tableComposite.setLayout(tableColumnLayout);
+
+                       // Corresponding table & style
+                       Table table = v.getTable();
+                       table.setLinesVisible(true);
+                       table.setHeaderVisible(false);
+                       CmsUiUtils.markup(table);
+                       CmsUiUtils.setItemHeight(table, 26);
+
+                       v.setContentProvider(new BasicNodeListContentProvider());
+                       // v.addDoubleClickListener(new
+                       // JcrViewerDClickListener(systemWorkbenchService));
+                       v.addSelectionChangedListener(new ISelectionChangedListener() {
+                               public void selectionChanged(SelectionChangedEvent event) {
+                                       IStructuredSelection selection = (IStructuredSelection) event.getSelection();
+                                       List<?> lst = selection.toList();
+//                             if (lst != null && !lst.isEmpty())
+//                                     selectionService.setSelection(selection.toList());
+//                             else
+//                                     selectionService.setSelection(null);
+                               }
+                       });
+                       return v;
+               }
+
+//     public void dispose() {
+//             JcrUtils.logoutQuietly(session);
+//     }
+
+               public boolean setFocus() {
+                       refreshFilteredList();
+                       return super.setFocus();
+//             filterTxt.setFocus();
+               }
+
+               public void forceRefresh(Object object) {
+                       refreshFilteredList();
+               }
+
+               protected void refreshFilteredList() {
+                       try {
+                               String filter = filterTxt.getText();
+                               // Prevents the query on the full repository
+                               // if (isEmpty(filter)) {
+                               // entityViewer.setInput(null);
+                               // return;
+                               // }
+
+                               // XPATH Query
+                               String xpathQueryStr;
+                               if (entityType != null)
+                                       xpathQueryStr = entityType.contains(":") ? "//element(*, " + entityType + ")"
+                                                       : "//element(*, " + EntityTypes.ENTITY_ENTITY + ")[@entity:type='" + entityType + "']";
+                               else
+                                       xpathQueryStr = "//element(*, " + EntityTypes.ENTITY_ENTITY + ")";
+//                     String xpathQueryStr = "//element(*, " + ConnectTypes.CONNECT_ENTITY + ")";
+                               String xpathFilter = XPathUtils.getFreeTextConstraint(filter);
+                               if (notEmpty(xpathFilter))
+                                       xpathQueryStr += "[" + xpathFilter + "]";
+
+                               long begin = System.currentTimeMillis();
+                               // session.refresh(false);
+                               Query xpathQuery = XPathUtils.createQuery(session, xpathQueryStr);
+
+                               xpathQuery.setLimit(ConnectUiConstants.SEARCH_DEFAULT_LIMIT);
+                               QueryResult result = xpathQuery.execute();
+
+                               NodeIterator nit = result.getNodes();
+                               entityViewer.setInput(JcrUtils.nodeIteratorToList(nit));
+//                             if (log.isTraceEnabled()) {
+//                                     long end = System.currentTimeMillis();
+//                                     log.trace("Quick Search - Found: " + nit.getSize() + " in " + (end - begin)
+//                                                     + " ms by executing XPath query (" + xpathQueryStr + ").");
+//                             }
+                       } catch (RepositoryException e) {
+                               throw new IllegalStateException("Unable to list entities", e);
+                       }
+               }
+
+               class SingleEntityLabelProvider extends ColumnLabelProvider {
+
+               }
+       }
 }
index c6485c2573cc010ea7b943384addb95f12ce1b6c..037864f21f275fc8e549291b98f095b69cacbc33 100644 (file)
@@ -4,5 +4,5 @@ import org.argeo.cms.Localized;
 
 /** Localized messages. */
 public enum SuiteMsg implements Localized {
-       dashboard,people,documents,locations;
+       dashboard,people,documents,locations,recentItems;
 }
index 2251e67d6eeaaf250f18f680269723e15d32b099..6e8f4c5d1f5f02a646328175cab36beab3a11454 100644 (file)
@@ -6,6 +6,8 @@ import org.argeo.cms.ui.util.CmsStyle;
 public enum SuiteStyle implements CmsStyle {
        // Header
        header,headerTitle,
+       // Recent items
+       recentItems,
        // Lead pane
        leadPane;