Refactor SWT UX.
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jun 2022 08:46:10 +0000 (10:46 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 26 Jun 2022 08:46:10 +0000 (10:46 +0200)
15 files changed:
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtContentHierarchicalPart.java [deleted file]
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/app/AcrContentTreeView.java
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/AbstractSwtPart.java
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtHierarchicalPart.java
eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabularPart.java
org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentHierarchicalPart.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractDataPart.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractHierarchicalPart.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractTabularPart.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/ColumnsPart.java
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DataPart.java
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DataView.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DefaultTabularPart.java [new file with mode: 0644]
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/HierarchicalPart.java
org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/TabularPart.java

diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtContentHierarchicalPart.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtContentHierarchicalPart.java
deleted file mode 100644 (file)
index 230cca4..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-package org.argeo.cms.swt.acr;
-
-import java.util.Iterator;
-
-import org.argeo.api.acr.Content;
-import org.argeo.cms.swt.widgets.SwtHierarchicalPart;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.TreeItem;
-
-public class SwtContentHierarchicalPart extends SwtHierarchicalPart {
-
-       public SwtContentHierarchicalPart(Composite parent, int style) {
-               super(parent, style);
-       }
-
-       public Content getContent() {
-               return (Content) getInput();
-       }
-
-       @Override
-       protected void refreshRootItem(TreeItem item) {
-               refreshItem(null, item);
-       }
-
-       @Override
-       protected void refreshItem(TreeItem parentItem, TreeItem item) {
-               int index = getTree().indexOf(item);
-               Content parentContent = parentItem == null ? getContent() : (Content) parentItem.getData();
-               Content content = null;
-               int count = 0;
-               children: for (Content c : parentContent) {
-                       if (count == index) {
-                               content = c;
-                               break children;
-                       }
-                       count++;
-               }
-               item.setData(content);
-               item.setText(content.getName().toString());
-               item.setItemCount(getChildrenCount(content));
-       }
-
-       @Override
-       protected int getRootItemCount() {
-               return getChildrenCount(getContent());
-       }
-
-       static int getChildrenCount(Content content) {
-               int count = 0;
-               for (Iterator<Content> it = content.iterator(); it.hasNext();it.next()) {
-                       count++;
-               }
-               return count;
-       }
-}
index 9d7b83ab18377925b905897bad51267493ca5974..cb339929f1042c1e1963edbabe73254b96b13a9a 100644 (file)
@@ -1,18 +1,22 @@
 package org.argeo.cms.swt.app;
 
+import static org.argeo.api.acr.NamespaceUtils.toPrefixedName;
+
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.xml.namespace.QName;
 
 import org.argeo.api.acr.Content;
+import org.argeo.api.acr.NamespaceUtils;
 import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.acr.SwtContentHierarchicalPart;
+import org.argeo.cms.swt.widgets.SwtHierarchicalPart;
 import org.argeo.cms.swt.widgets.SwtTabularPart;
+import org.argeo.cms.ux.acr.ContentHierarchicalPart;
 import org.argeo.cms.ux.widgets.Column;
+import org.argeo.cms.ux.widgets.DefaultTabularPart;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 
 public class AcrContentTreeView extends Composite {
@@ -20,51 +24,47 @@ public class AcrContentTreeView extends Composite {
 
        private Content rootContent;
 
-       private Content selected;
+//     private Content selected;
 
        public AcrContentTreeView(Composite parent, int style, Content content) {
                super(parent, style);
                this.rootContent = content;
-               this.selected = rootContent;
+               // this.selected = rootContent;
                setLayout(CmsSwtUtils.noSpaceGridLayout());
 
                SashForm split = new SashForm(this, SWT.HORIZONTAL);
                split.setLayoutData(CmsSwtUtils.fillAll());
 
-               SwtContentHierarchicalPart hPart = new SwtContentHierarchicalPart(split, getStyle());
-               Composite area = new Composite(split, SWT.NONE);
+               ContentHierarchicalPart contentPart = new ContentHierarchicalPart();
+               contentPart.setInput(rootContent);
+
+               SwtHierarchicalPart<Content> hPart = new SwtHierarchicalPart<>(split, getStyle(), contentPart);
+
+               Composite area = new Composite(split, SWT.BORDER);
                area.setLayout(CmsSwtUtils.noSpaceGridLayout(2));
                split.setWeights(new int[] { 30, 70 });
 
                // attributes
-               SwtTabularPart attributesPart = new SwtTabularPart(area, SWT.NONE) {
-                       List<QName> data;
+               DefaultTabularPart<Content, QName> attributesPart = new DefaultTabularPart<>() {
 
                        @Override
-                       protected Object getData(int row) {
-                               return data.get(row);
-                       }
-
-                       @Override
-                       protected int getItemCount() {
-                               data = new ArrayList<>(selected.keySet());
-                               return data.size();
+                       protected List<QName> asList(Content input) {
+                               return new ArrayList<>(input.keySet());
                        }
                };
-               attributesPart.getArea().setLayoutData(CmsSwtUtils.fillHeight());
 
                attributesPart.addColumn(new Column<QName>() {
 
                        @Override
                        public String getText(QName model) {
-                               return model.toString();
+                               return toPrefixedName(model);
                        }
                });
                attributesPart.addColumn(new Column<QName>() {
 
                        @Override
                        public String getText(QName model) {
-                               return selected.get(model).toString();
+                               return attributesPart.getInput().get(model).toString();
                        }
 
                        @Override
@@ -73,38 +73,40 @@ public class AcrContentTreeView extends Composite {
                        }
 
                });
+               // attributesPart.setInput(selected);
 
-               // types
-               SwtTabularPart typesPart = new SwtTabularPart(area, SWT.NONE) {
-                       List<QName> data;
+               SwtTabularPart<Content, QName> attributeTable = new SwtTabularPart<>(area, style, attributesPart);
+               attributeTable.setLayoutData(CmsSwtUtils.fillAll());
 
-                       @Override
-                       protected Object getData(int row) {
-                               return data.get(row);
-                       }
+               // types
+               DefaultTabularPart<Content, QName> typesPart = new DefaultTabularPart<>() {
 
                        @Override
-                       protected int getItemCount() {
-                               data = new ArrayList<>(selected.getContentClasses());
-                               return data.size();
+                       protected List<QName> asList(Content input) {
+                               return input.getContentClasses();
                        }
                };
                typesPart.addColumn(new Column<QName>() {
 
                        @Override
                        public String getText(QName model) {
-                               return model.toString();
+                               return toPrefixedName(model);
                        }
+
                });
-               typesPart.getArea().setLayoutData(CmsSwtUtils.fillHeight());
+
+               // typesPart.setInput(selected);
+
+               SwtTabularPart<Content, QName> typesTable = new SwtTabularPart<>(area, style, typesPart);
+               typesTable.setLayoutData(CmsSwtUtils.fillAll());
 
                // controller
-               hPart.setInput(rootContent);
-               hPart.onSelected((o) -> {
+               contentPart.setInput(rootContent);
+               contentPart.onSelected((o) -> {
                        Content c = (Content) o;
-                       selected = c;
-                       attributesPart.refresh();
-                       typesPart.refresh();
+//                     selected = c;
+                       attributesPart.setInput(c);
+                       typesPart.setInput(c);
                });
 
                attributesPart.refresh();
index e846bb54e13db47886e04f34ac460590157b6d41..c3d11a181124774d66b63bc1912d9a833a2fb9d1 100644 (file)
@@ -1,14 +1,45 @@
 package org.argeo.cms.swt.widgets;
 
 import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.ux.widgets.DataPart;
+import org.argeo.cms.ux.widgets.DataView;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.widgets.Composite;
 
-public abstract class AbstractSwtPart {
-       protected final Composite area;
+public abstract class AbstractSwtPart<INPUT, TYPE> extends Composite implements DataView<INPUT, TYPE> {
+       private static final long serialVersionUID = -1999179054267812170L;
 
-       public AbstractSwtPart(Composite parent, int style) {
-               area = new Composite(parent, style);
-               area.setLayout(CmsSwtUtils.noSpaceGridLayout());
+       protected DataPart<INPUT, TYPE> dataPart;
+
+       protected final SelectionListener selectionListener;
+
+       public AbstractSwtPart(Composite parent, int style, DataPart<INPUT, TYPE> dataPart) {
+               super(parent, style);
+               setLayout(CmsSwtUtils.noSpaceGridLayout());
+
+               this.dataPart = dataPart;
+
+               selectionListener = new SelectionListener() {
+
+                       private static final long serialVersionUID = 4334785560035009330L;
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               if (dataPart.getOnSelected() != null)
+                                       dataPart.getOnSelected().accept((TYPE) e.item.getData());
+                       }
+
+                       @Override
+                       public void widgetDefaultSelected(SelectionEvent e) {
+                               if (dataPart.getOnAction() != null)
+                                       dataPart.getOnAction().accept((TYPE) e.item.getData());
+                       }
+               };
+
+               dataPart.addView(this);
+               addDisposeListener((e) -> dataPart.removeView(this));
        }
 
+       public abstract void refresh();
 }
index a4ca061e69fd6a1f25f6e7e50ec2e434b137d57c..07c9bac2e1cb3266028a90cbe139008c591d42b4 100644 (file)
 package org.argeo.cms.swt.widgets;
 
-import java.util.function.Consumer;
+import java.util.List;
 
+import org.argeo.api.cms.ux.CmsIcon;
 import org.argeo.cms.swt.CmsSwtUtils;
 import org.argeo.cms.ux.widgets.HierarchicalPart;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeItem;
 
 /** {@link HierarchicalPart} implementation based on a {@link Tree}. */
-public class SwtHierarchicalPart implements HierarchicalPart {
-       private Composite area;
+public class SwtHierarchicalPart<T> extends AbstractSwtPart<T, T> {
+       private static final long serialVersionUID = -6247710601465713047L;
+
        private final Tree tree;
 
-       private Consumer<Object> onSelected;
-       private Consumer<Object> onAction;
+       private HierarchicalPart<T> hierarchicalPart;
+
+       public SwtHierarchicalPart(Composite parent, int style, HierarchicalPart<T> hierarchicalPart) {
+               super(parent, style, hierarchicalPart);
+               tree = new Tree(this, SWT.BORDER);
+               tree.setLayoutData(CmsSwtUtils.fillAll());
+               this.hierarchicalPart = hierarchicalPart;
 
-       public SwtHierarchicalPart(Composite parent, int style) {
-               area = new Composite(parent, style);
-               area.setLayout(CmsSwtUtils.noSpaceGridLayout());
-               tree = new Tree(area, SWT.VIRTUAL | SWT.BORDER);
+               tree.addSelectionListener(selectionListener);
        }
 
        @Override
        public void refresh() {
                // TODO optimise
-               tree.clearAll(true);
-               tree.addListener(SWT.SetData, event -> {
-                       TreeItem item = (TreeItem) event.item;
-                       TreeItem parentItem = item.getParentItem();
-                       if (parentItem == null) {
-                               refreshRootItem(item);
-                       } else {
-                               refreshItem(parentItem, item);
+               // tree.clearAll(true);
+
+               for (TreeItem rootItem : tree.getItems()) {
+                       rootItem.dispose();
+               }
+
+               List<T> rootItems = hierarchicalPart.getChildren(hierarchicalPart.getInput());
+               for (T child : rootItems) {
+                       TreeItem childItem = addTreeItem(null, child);
+//                     List<T> grandChildren = hierarchicalPart.getChildren(child);
+//                     for (T grandChild : grandChildren) {
+//                             addTreeItem(childItem, grandChild);
+//                     }
+               }
+//             tree.addListener(SWT.SetData, event -> {
+//                     TreeItem item = (TreeItem) event.item;
+//                     TreeItem parentItem = item.getParentItem();
+//                     if (parentItem == null) {
+//                             refreshRootItem(item);
+//                     } else {
+//                             refreshItem(parentItem, item);
+//                     }
+//             });
+//             tree.setItemCount(getRootItemCount());
+
+               tree.addListener(SWT.Expand, event -> {
+                       final TreeItem root = (TreeItem) event.item;
+                       TreeItem[] items = root.getItems();
+                       for (TreeItem item : items) {
+                               if (item.getData() != null) {
+//                                     List<T> grandChildren = hierarchicalPart.getChildren((T) item.getData());
+//                                     for (T grandChild : grandChildren) {
+//                                             addTreeItem(item, grandChild);
+//                                     }
+                                       return;
+                               }
+                               item.dispose();
                        }
-               });
-               tree.setItemCount(getRootItemCount());
-               CmsSwtUtils.fill(tree);
 
-               tree.addSelectionListener(new SelectionListener() {
-
-                       private static final long serialVersionUID = 4334785560035009330L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               if (onSelected != null)
-                                       onSelected.accept(e.item.getData());
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               if (onAction != null)
-                                       onAction.accept(e.item.getData());
+                       List<T> children = hierarchicalPart.getChildren((T) root.getData());
+                       for (T child : children) {
+                               TreeItem childItem = addTreeItem(root, child);
+//                             List<T> grandChildren = hierarchicalPart.getChildren(child);
+//                             for (T grandChild : grandChildren) {
+//                                     addTreeItem(childItem, grandChild);
+//                             }
                        }
                });
 
-       }
-
-       @Override
-       public void setInput(Object data) {
-               area.setData(data);
-               refresh();
-       }
-
-       @Override
-       public Object getInput() {
-               return area.getData();
-       }
-
-       protected void refreshRootItem(TreeItem item) {
-
-       }
-
-       protected void refreshItem(TreeItem parentItem, TreeItem item) {
+               CmsSwtUtils.fill(tree);
 
        }
 
-       protected int getRootItemCount() {
-               return 0;
+       protected TreeItem addTreeItem(TreeItem parent, T data) {
+               TreeItem item = parent == null ? new TreeItem(tree, SWT.NONE) : new TreeItem(parent, SWT.NONE);
+               item.setData(data);
+               String txt = hierarchicalPart.getText(data);
+               if (txt != null)
+                       item.setText(hierarchicalPart.getText(data));
+               CmsIcon icon = hierarchicalPart.getIcon(data);
+               // TODO optimize
+               List<T> grandChildren = hierarchicalPart.getChildren(data);
+               if (grandChildren.size() != 0)
+                       new TreeItem(item, SWT.NONE);
+               return item;
+//if(icon!=null)
+//     item.setImage(null);
        }
 
        protected Tree getTree() {
                return tree;
        }
 
-       public void onSelected(Consumer<Object> onSelected) {
-               this.onSelected = onSelected;
-       }
-
-       public void onAction(Consumer<Object> onAction) {
-               this.onAction = onAction;
-       }
-
-       public Composite getArea() {
-               return area;
-       }
-
 }
index 8fd4065ad92bce617dbcd2f195da80ddf6a49320..2f10cac75ef0765b94fe19f22f87247c2250b554 100644 (file)
@@ -1,7 +1,5 @@
 package org.argeo.cms.swt.widgets;
 
-import java.util.function.Consumer;
-
 import org.argeo.api.cms.ux.CmsIcon;
 import org.argeo.cms.swt.CmsSwtTheme;
 import org.argeo.cms.swt.CmsSwtUtils;
@@ -9,7 +7,6 @@ import org.argeo.cms.ux.widgets.Column;
 import org.argeo.cms.ux.widgets.TabularPart;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Table;
@@ -17,22 +14,22 @@ import org.eclipse.swt.widgets.TableColumn;
 import org.eclipse.swt.widgets.TableItem;
 
 /** {@link TabularPart} implementation based on a {@link Table}. */
-public class SwtTabularPart implements TabularPart {
-       private Composite area;
-
+public class SwtTabularPart<INPUT, T> extends AbstractSwtPart<INPUT, T> {
+       private static final long serialVersionUID = -1114155772446357750L;
        private final Table table;
-
-       private Consumer<Object> onSelected;
-       private Consumer<Object> onAction;
+       private TabularPart<INPUT, T> tabularPart;
 
        private CmsSwtTheme theme;
 
-       public SwtTabularPart(Composite parent, int style) {
+       public SwtTabularPart(Composite parent, int style, TabularPart<INPUT, T> tabularPart) {
+               super(parent, style, tabularPart);
                theme = CmsSwtUtils.getCmsTheme(parent);
-               area = new Composite(parent, style);
-               area.setLayout(CmsSwtUtils.noSpaceGridLayout());
-               table = new Table(area, SWT.VIRTUAL | SWT.BORDER);
+
+               table = new Table(this, SWT.VIRTUAL | SWT.BORDER);
                table.setLinesVisible(true);
+               table.setLayoutData(CmsSwtUtils.fillAll());
+
+               this.tabularPart = tabularPart;
        }
 
        @Override
@@ -43,50 +40,29 @@ public class SwtTabularPart implements TabularPart {
                        TableItem item = (TableItem) event.item;
                        refreshItem(item);
                });
-               table.setItemCount(getItemCount());
+               table.setItemCount(tabularPart.getItemCount());
+               for (int i = 0; i < tabularPart.getColumnCount(); i++) {
+                       TableColumn swtColumn = new TableColumn(table, SWT.NONE);
+                       swtColumn.setWidth(tabularPart.getColumn(i).getWidth());
+               }
                CmsSwtUtils.fill(table);
 
-               table.addSelectionListener(new SelectionListener() {
-                       private static final long serialVersionUID = -5225905921522775948L;
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               if (onSelected != null)
-                                       onSelected.accept(getDataFromEvent(e));
-                       }
-
-                       @Override
-                       public void widgetDefaultSelected(SelectionEvent e) {
-                               if (onAction != null)
-                                       onAction.accept(getDataFromEvent(e));
-                       }
-               });
+               table.addSelectionListener(selectionListener);
 
        }
 
        protected Object getDataFromEvent(SelectionEvent e) {
                Object data = e.item.getData();
                if (data == null)
-                       data = getData(getTable().indexOf((TableItem) e.item));
+                       data = tabularPart.getData(getTable().indexOf((TableItem) e.item));
                return data;
        }
 
-       @Override
-       public void setInput(Object data) {
-               area.setData(data);
-               refresh();
-       }
-
-       @Override
-       public Object getInput() {
-               return area.getData();
-       }
-
        protected void refreshItem(TableItem item) {
                int row = getTable().indexOf(item);
-               for (int i = 0; i < item.getParent().getColumnCount(); i++) {
-                       Column<Object> column = (Column<Object>) item.getParent().getColumn(i).getData();
-                       Object data = getData(row);
+               for (int i = 0; i < tabularPart.getColumnCount(); i++) {
+                       Column<T> column = tabularPart.getColumn(i);
+                       T data = tabularPart.getData(row);
                        item.setData(data);
                        String text = data != null ? column.getText(data) : "";
                        if (text != null)
@@ -99,36 +75,8 @@ public class SwtTabularPart implements TabularPart {
                }
        }
 
-       protected int getItemCount() {
-               return 0;
-       }
-
-       protected Object getData(int row) {
-               return null;
-       }
-
        protected Table getTable() {
                return table;
        }
 
-       public void onSelected(Consumer<Object> onSelected) {
-               this.onSelected = onSelected;
-       }
-
-       public void onAction(Consumer<Object> onAction) {
-               this.onAction = onAction;
-       }
-
-       @Override
-       public void addColumn(Column<?> column) {
-               TableColumn swtColumn = new TableColumn(table, SWT.NONE);
-               swtColumn.setWidth(column.getWidth());
-               swtColumn.setData(column);
-
-       }
-
-       public Composite getArea() {
-               return area;
-       }
-
 }
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentHierarchicalPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentHierarchicalPart.java
new file mode 100644 (file)
index 0000000..ad4df11
--- /dev/null
@@ -0,0 +1,29 @@
+package org.argeo.cms.ux.acr;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.argeo.api.acr.Content;
+import org.argeo.cms.ux.widgets.AbstractDataPart;
+import org.argeo.cms.ux.widgets.HierarchicalPart;
+
+public class ContentHierarchicalPart extends AbstractDataPart<Content, Content> implements HierarchicalPart<Content> {
+       @Override
+       public List<Content> getChildren(Content content) {
+               List<Content> res = new ArrayList<>();
+               if (content == null)
+                       return res;
+               for (Iterator<Content> it = content.iterator(); it.hasNext();) {
+                       res.add(it.next());
+               }
+
+               return res;
+       }
+
+       @Override
+       public String getText(Content model) {
+               return model.getName().toString();
+       }
+
+}
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractDataPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractDataPart.java
new file mode 100644 (file)
index 0000000..958fcde
--- /dev/null
@@ -0,0 +1,61 @@
+package org.argeo.cms.ux.widgets;
+
+import java.util.IdentityHashMap;
+import java.util.function.Consumer;
+
+public abstract class AbstractDataPart<INPUT, T> implements DataPart<INPUT, T> {
+
+       private Consumer<T> onSelected;
+       private Consumer<T> onAction;
+
+       private IdentityHashMap<DataView<INPUT, T>, Object> views = new IdentityHashMap<>();
+
+       private INPUT data;
+
+       @Override
+       public void setInput(INPUT data) {
+               this.data = data;
+               refresh();
+       }
+
+       @Override
+       public INPUT getInput() {
+               return data;
+       }
+
+       @Override
+       public void onSelected(Consumer<T> onSelected) {
+               this.onSelected = onSelected;
+       }
+
+       @Override
+       public void onAction(Consumer<T> onAction) {
+               this.onAction = onAction;
+       }
+
+       public Consumer<T> getOnSelected() {
+               return onSelected;
+       }
+
+       public Consumer<T> getOnAction() {
+               return onAction;
+       }
+
+       @Override
+       public void refresh() {
+               for (DataView<INPUT, T> view : views.keySet()) {
+                       view.refresh();
+               }
+       }
+
+       @Override
+       public void addView(DataView<INPUT, T> view) {
+               views.put(view, new Object());
+       }
+
+       @Override
+       public void removeView(DataView<INPUT, T> view) {
+               views.remove(view);
+       }
+
+}
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractHierarchicalPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractHierarchicalPart.java
new file mode 100644 (file)
index 0000000..dd1854d
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.cms.ux.widgets;
+
+public abstract class AbstractHierarchicalPart<T> extends AbstractDataPart<T, T> implements HierarchicalPart<T> {
+
+}
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractTabularPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/AbstractTabularPart.java
new file mode 100644 (file)
index 0000000..7e63ea8
--- /dev/null
@@ -0,0 +1,25 @@
+package org.argeo.cms.ux.widgets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractTabularPart<INPUT, T> extends AbstractDataPart<INPUT, T> implements TabularPart<INPUT, T> {
+
+       private List<Column<T>> columns = new ArrayList<>();
+
+       @Override
+       public Column<T> getColumn(int index) {
+               if (index >= columns.size())
+                       throw new IllegalArgumentException("There a only " + columns.size());
+               return columns.get(index);
+       }
+
+       public void addColumn(Column<T> column) {
+               columns.add(column);
+       }
+
+       @Override
+       public int getColumnCount() {
+               return columns.size();
+       }
+}
index 7df7086b3675380685dd81f69107cdabc01354d9..a60401c1fc0d0ceb8923a3d5797d3a8c86f21981 100644 (file)
@@ -1,5 +1,5 @@
 package org.argeo.cms.ux.widgets;
 
-public interface ColumnsPart extends DataPart {
+public interface ColumnsPart<INPUT, TYPE> extends DataPart<INPUT, TYPE> {
 
 }
index 5a8da469bf63a8a4e42e2e884e97327c34643b19..11a12cf7bfc77cf83bb41093cf25e464b883fc2e 100644 (file)
@@ -2,14 +2,22 @@ package org.argeo.cms.ux.widgets;
 
 import java.util.function.Consumer;
 
-public interface DataPart {
-       void setInput(Object data);
+public interface DataPart<INPUT, T> {
+       void setInput(INPUT data);
 
-       Object getInput();
+       INPUT getInput();
+
+       void onSelected(Consumer<T> onSelected);
+
+       Consumer<T> getOnSelected();
+
+       void onAction(Consumer<T> onAction);
+
+       Consumer<T> getOnAction();
 
        void refresh();
 
-       void onSelected(Consumer<Object> onSelected);
+       void addView(DataView<INPUT, T> view);
 
-       void onAction(Consumer<Object> onAction);
+       void removeView(DataView<INPUT, T> view);
 }
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DataView.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DataView.java
new file mode 100644 (file)
index 0000000..9768c68
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.cms.ux.widgets;
+
+public interface DataView<INPUT,TYPE> {
+       void refresh();
+}
diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DefaultTabularPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/DefaultTabularPart.java
new file mode 100644 (file)
index 0000000..cb30af6
--- /dev/null
@@ -0,0 +1,46 @@
+package org.argeo.cms.ux.widgets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DefaultTabularPart<INPUT, T> extends AbstractTabularPart<INPUT, T> implements TabularPart<INPUT, T> {
+       private List<T> content;
+
+       @Override
+       public int getItemCount() {
+               return content.size();
+       }
+
+       @Override
+       public T getData(int row) {
+               assert row < getItemCount();
+               return content.get(row);
+       }
+
+       @Override
+       public void refresh() {
+               INPUT input = getInput();
+               if (input == null) {
+                       content = new ArrayList<>();
+                       return;
+               }
+               content = asList(input);
+               super.refresh();
+       }
+
+       protected List<T> asList(INPUT input) {
+               List<T> res = new ArrayList<>();
+               content.clear();
+               if (input instanceof List) {
+                       content = (List<T>) input;
+               } else if (input instanceof Iterable) {
+                       for (T item : (Iterable<T>) input)
+                               content.add(item);
+               } else {
+                       throw new IllegalArgumentException(
+                                       "Unsupported class " + input.getClass() + ", method should be overridden.");
+               }
+               return res;
+       }
+
+}
index 0926ff527901728c13f2231a8885c55b79c8a655..372c295dcfb34c34cf44bfbfe4efd14743037c5a 100644 (file)
@@ -1,5 +1,16 @@
 package org.argeo.cms.ux.widgets;
 
-public interface HierarchicalPart extends ColumnsPart {
+import java.util.List;
+
+import org.argeo.api.cms.ux.CmsIcon;
+
+public interface HierarchicalPart<T> extends ColumnsPart<T, T> {
+       List<T> getChildren(T parent);
+
+       String getText(T model);
+
+       default CmsIcon getIcon(T model) {
+               return null;
+       }
 
 }
index 4c9320268f874141185d7490b92b1d0f429de73b..6adc0c3e6c1ffdf37c47c97a62793611aaec4765 100644 (file)
@@ -1,5 +1,11 @@
 package org.argeo.cms.ux.widgets;
 
-public interface TabularPart extends ColumnsPart {
-       void addColumn(Column<?> column);
+public interface TabularPart<INPUT, T> extends ColumnsPart<INPUT, T> {
+       int getItemCount();
+
+       T getData(int row);
+
+       Column<T> getColumn(int index);
+
+       int getColumnCount();
 }