From 38b1c40accd8da0b5bd791cc2b2257773b69ac56 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 15 Jul 2021 08:26:44 +0200 Subject: [PATCH] Introduce fixed entry area. --- .../argeo/suite/ui/DefaultEditionLayer.java | 164 ++++++++++++++---- .../src/org/argeo/suite/ui/SuiteApp.java | 42 +++-- .../src/org/argeo/suite/ui/SuiteLayer.java | 4 +- .../src/org/argeo/suite/ui/SuiteUi.java | 1 + .../argeo/suite/ui/widgets/TabbedArea.java | 21 ++- 5 files changed, 186 insertions(+), 46 deletions(-) diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java index 68081b4..7004ad0 100644 --- a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/DefaultEditionLayer.java @@ -11,6 +11,7 @@ import org.argeo.cms.Localized; import org.argeo.cms.ui.CmsTheme; import org.argeo.cms.ui.CmsUiProvider; import org.argeo.cms.ui.util.CmsUiUtils; +import org.argeo.jcr.JcrException; import org.argeo.suite.ui.widgets.TabbedArea; import org.argeo.util.LangUtils; import org.eclipse.swt.SWT; @@ -24,21 +25,33 @@ import org.osgi.framework.wiring.BundleWiring; /** An app layer based on an entry area and an editor area. */ public class DefaultEditionLayer implements SuiteLayer { private CmsUiProvider entryArea; + private CmsUiProvider defaultView; private CmsUiProvider workArea; private List weights = new ArrayList<>(); private boolean startMaximized = false; + private boolean fixedEntryArea = false; private boolean singleTab = false; private Localized title = null; @Override public Control createUi(Composite parent, Node context) throws RepositoryException { + // TODO Factorize more, or split into more specialised classes? if (entryArea != null) { - SashFormEditionArea sashFormEditionArea = new SashFormEditionArea(parent, parent.getStyle()); - entryArea.createUi(sashFormEditionArea.getEntryArea(), context); - if (this.workArea != null) { - this.workArea.createUi(sashFormEditionArea.getEditorArea(), context); + if (fixedEntryArea) { + FixedEditionArea editionArea = new FixedEditionArea(parent, parent.getStyle()); + entryArea.createUi(editionArea.getEntryArea(), context); + if (this.defaultView != null) { + editionArea.getTabbedArea().view(defaultView, context); + } + return editionArea; + } else { + SashFormEditionArea editionArea = new SashFormEditionArea(parent, parent.getStyle()); + entryArea.createUi(editionArea.getEntryArea(), context); + if (this.defaultView != null) { + editionArea.getTabbedArea().view(defaultView, context); + } + return editionArea; } - return sashFormEditionArea; } else { if (this.workArea != null) { Composite area = new Composite(parent, SWT.NONE); @@ -52,15 +65,51 @@ public class DefaultEditionLayer implements SuiteLayer { } @Override - public void view(CmsUiProvider uiProvider, Composite workArea, Node context) { - TabbedArea tabbedArea; + public void view(CmsUiProvider uiProvider, Composite workAreaC, Node context) { + if (workArea != null) { + try { + CmsUiUtils.clear(workAreaC); + workArea.createUi(workAreaC, context); + workAreaC.requestLayout(); + return; + } catch (RepositoryException e) { + throw new JcrException("Cannot rebuild work area", e); + } + } + + // tabbed area + TabbedArea tabbedArea = findTabbedArea(workAreaC); + if (tabbedArea == null) + throw new IllegalArgumentException("Unsupported work area " + workAreaC.getClass().getName()); + if (uiProvider == null) { + // reset + tabbedArea.closeAllTabs(); + if (this.defaultView != null) { + tabbedArea.view(defaultView, context); + } + } else { + tabbedArea.view(uiProvider, context); + } + } + + @Override + public Node getCurrentContext(Composite workArea) { + TabbedArea tabbedArea = findTabbedArea(workArea); + if (tabbedArea == null) + return null; + return tabbedArea.getCurrentContext(); + } + + private TabbedArea findTabbedArea(Composite workArea) { + TabbedArea tabbedArea = null; if (workArea instanceof SashFormEditionArea) { tabbedArea = ((SashFormEditionArea) workArea).getTabbedArea(); + } else if (workArea instanceof FixedEditionArea) { + tabbedArea = ((FixedEditionArea) workArea).getTabbedArea(); } else if (workArea instanceof TabbedArea) { tabbedArea = (TabbedArea) workArea; - } else - throw new IllegalArgumentException("Unsupported work area " + workArea.getClass().getName()); - tabbedArea.view(uiProvider, context); + } + return tabbedArea; } @Override @@ -78,6 +127,12 @@ public class DefaultEditionLayer implements SuiteLayer { weights = LangUtils.toStringList(properties.get(Property.weights.name())); startMaximized = properties.containsKey(Property.startMaximized.name()) && "true".equals(properties.get(Property.startMaximized.name())); + fixedEntryArea = properties.containsKey(Property.fixedEntryArea.name()) + && "true".equals(properties.get(Property.fixedEntryArea.name())); + if (fixedEntryArea && weights.size() != 0) { + throw new IllegalArgumentException("Property " + Property.weights.name() + " should not be set if property " + + Property.fixedEntryArea.name() + " is set."); + } singleTab = properties.containsKey(Property.singleTab.name()) && "true".equals(properties.get(Property.singleTab.name())); @@ -116,6 +171,10 @@ public class DefaultEditionLayer implements SuiteLayer { this.workArea = workArea; } + public void setDefaultView(CmsUiProvider defaultView) { + this.defaultView = defaultView; + } + TabbedArea createTabbedArea(Composite parent, CmsTheme theme) { TabbedArea tabbedArea = new TabbedArea(parent, SWT.NONE); tabbedArea.setSingleTab(singleTab); @@ -127,26 +186,26 @@ public class DefaultEditionLayer implements SuiteLayer { return tabbedArea; } - /** A work area based on an entry area and and a tabbed area. */ +// /** A work area based on an entry area and and a tabbed area. */ class SashFormEditionArea extends SashForm { private static final long serialVersionUID = 2219125778722702618L; - private CmsTheme theme; - private Composite entryArea; - private Composite editorArea; private TabbedArea tabbedArea; + private Composite entryC; SashFormEditionArea(Composite parent, int style) { super(parent, SWT.HORIZONTAL); - theme = CmsTheme.getCmsTheme(parent); + CmsTheme theme = CmsTheme.getCmsTheme(parent); + Composite editorC; if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. - editorArea = new Composite(this, SWT.BORDER); - entryArea = new Composite(this, SWT.BORDER); + editorC = new Composite(this, SWT.BORDER); + entryC = new Composite(this, SWT.BORDER); } else { - entryArea = new Composite(this, SWT.NONE); - editorArea = new Composite(this, SWT.NONE); + entryC = new Composite(this, SWT.NONE); + editorC = new Composite(this, SWT.NONE); } + // sash form specific if (weights.size() != 0) { int[] actualWeight = new int[weights.size()]; for (int i = 0; i < weights.size(); i++) { @@ -158,30 +217,69 @@ public class DefaultEditionLayer implements SuiteLayer { setWeights(actualWeights); } if (startMaximized) - setMaximizedControl(editorArea); - GridLayout editorAreaLayout = new GridLayout(); - editorAreaLayout.verticalSpacing = 0; - editorAreaLayout.marginBottom = 0; - editorAreaLayout.marginHeight = 0; - editorArea.setLayout(editorAreaLayout); - - if (DefaultEditionLayer.this.workArea == null) { - tabbedArea = createTabbedArea(editorArea, theme); - } + setMaximizedControl(editorC); + + GridLayout editorAreaLayout = CmsUiUtils.noSpaceGridLayout(); +// editorAreaLayout.verticalSpacing = 0; +// editorAreaLayout.marginBottom = 0; +// editorAreaLayout.marginHeight = 0; +// editorAreaLayout.marginLeft = 0; +// editorAreaLayout.marginRight = 0; + editorC.setLayout(editorAreaLayout); + tabbedArea = createTabbedArea(editorC, theme); + } + + TabbedArea getTabbedArea() { + return tabbedArea; } Composite getEntryArea() { - return entryArea; + return entryC; + } + + } + + class FixedEditionArea extends Composite { + private static final long serialVersionUID = -5525672639277322465L; + private TabbedArea tabbedArea; + private Composite entryC; + + public FixedEditionArea(Composite parent, int style) { + super(parent, style); + CmsTheme theme = CmsTheme.getCmsTheme(parent); + + setLayout(CmsUiUtils.noSpaceGridLayout(2)); + + Composite editorC; + if (SWT.RIGHT_TO_LEFT == (style & SWT.RIGHT_TO_LEFT)) {// arabic, hebrew, etc. + editorC = new Composite(this, SWT.NONE); + entryC = new Composite(this, SWT.NONE); + } else { + entryC = new Composite(this, SWT.NONE); + editorC = new Composite(this, SWT.NONE); + } + entryC.setLayoutData(CmsUiUtils.fillHeight()); + + GridLayout editorAreaLayout = CmsUiUtils.noSpaceGridLayout(); +// editorAreaLayout.verticalSpacing = 0; +// editorAreaLayout.marginBottom = 0; +// editorAreaLayout.marginHeight = 0; +// editorAreaLayout.marginLeft = 0; +// editorAreaLayout.marginRight = 0; + editorC.setLayout(editorAreaLayout); + editorC.setLayoutData(CmsUiUtils.fillAll()); + + tabbedArea = createTabbedArea(editorC, theme); } TabbedArea getTabbedArea() { return tabbedArea; } - Composite getEditorArea() { - return editorArea; + Composite getEntryArea() { + return entryC; } - } + } \ No newline at end of file diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java index bdcf30c..dabd8af 100644 --- a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java @@ -57,6 +57,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId"; public final static String DEFAULT_LAYER_PROPERTY = "defaultLayer"; private final static String LOGIN = "login"; + private final static String HOME_STATE = "~"; private String publicBasePath = null; @@ -335,7 +336,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { if (!state.startsWith("/")) { if (parent instanceof SuiteUi) { SuiteUi ui = (SuiteUi) parent; - if (LOGIN.equals(state) || state.equals("~")) { + if (LOGIN.equals(state) || state.equals(HOME_STATE)) { String appTitle = ""; if (ui.getTitle() != null) appTitle = ui.getTitle().lead(); @@ -343,20 +344,21 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { return; } String currentLayerId = ui.getCurrentLayerId(); - if (state.equals(currentLayerId)) - return; // does nothing - else { - Map properties = new HashMap<>(); - properties.put(SuiteEvent.LAYER, state); - ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties); - } +// if (state.equals(currentLayerId)) +// return; // does nothing +// else { + Map properties = new HashMap<>(); + properties.put(SuiteEvent.LAYER, state); + properties.put(SuiteEvent.NODE_PATH, HOME_STATE); + ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties); +// } } return; } SuiteUi suiteUi = (SuiteUi) parent; Node node = stateToNode(suiteUi, state); if (node == null) { - suiteUi.getCmsView().navigateTo("~"); + suiteUi.getCmsView().navigateTo(HOME_STATE); } else { suiteUi.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node)); suiteUi.getCmsView().sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node)); @@ -441,11 +443,27 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { // ui.switchToLayer(layerId, ui.getUserDir()); SuiteLayer suiteLayer = findLayer(layerId); Localized layerTitle = suiteLayer.getTitle(); - ui.getCmsView().runAs(() -> ui.switchToLayer(layerId, ui.getUserDir())); + // FIXME make sure we don't rebuild the work area twice + Composite workArea = ui.getCmsView().doAs(() -> ui.switchToLayer(layerId, ui.getUserDir())); String title = null; if (layerTitle != null) title = layerTitle.lead(); - ui.getCmsView().stateChanged(layerId, appTitle + title); + Node nodeFromState = getNode(ui, event); + if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDir().getPath())) { + // default layer view is forced + ui.getCmsView().stateChanged(layerId, appTitle + title); + suiteLayer.view(null, workArea, nodeFromState); + } else { + Node layerCurrentContext = suiteLayer.getCurrentContext(workArea); + if (layerCurrentContext != null) { + // layer was already showing a context so we set the state to it + ui.getCmsView().stateChanged(nodeToState(layerCurrentContext), + appTitle + Jcr.getTitle(layerCurrentContext)); + } else { + // no context was shown + ui.getCmsView().stateChanged(layerId, appTitle + title); + } + } } else { Node node = getNode(ui, event); if (node != null) { @@ -463,6 +481,8 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { private Node getNode(SuiteUi ui, Event event) { String nodePath = get(event, SuiteEvent.NODE_PATH); + if (nodePath != null && nodePath.equals(HOME_STATE)) + return ui.getUserDir(); String workspaceName = get(event, SuiteEvent.WORKSPACE); Session session = ui.getSession(workspaceName); Node node; diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java index c081662..d18192f 100644 --- a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteLayer.java @@ -9,10 +9,12 @@ import org.eclipse.swt.widgets.Composite; /** An UI layer for the main work area. */ public interface SuiteLayer extends CmsUiProvider { static enum Property { - title, icon, weights, startMaximized, singleTab; + title, icon, weights, startMaximized, singleTab, fixedEntryArea; } void view(CmsUiProvider uiProvider, Composite workArea, Node context); + + Node getCurrentContext(Composite workArea); default void open(CmsUiProvider uiProvider, Composite workArea, Node context) { view(uiProvider, workArea, context); diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java index ca2d9c3..c29ff59 100644 --- a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteUi.java @@ -149,6 +149,7 @@ class SuiteUi extends Composite { } throw new IllegalArgumentException("Layer is not registered."); } + void addLayer(String id, SuiteLayer layer) { layers.put(id, layer); diff --git a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/TabbedArea.java b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/TabbedArea.java index 8ce5fed..c281904 100644 --- a/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/TabbedArea.java +++ b/core/org.argeo.suite.ui/src/org/argeo/suite/ui/widgets/TabbedArea.java @@ -45,7 +45,7 @@ public class TabbedArea extends Composite { private boolean singleTab = false; public TabbedArea(Composite parent, int style) { - super(parent, style); + super(parent, SWT.NONE); CmsUiUtils.style(parent, bodyStyle); setLayout(CmsUiUtils.noSpaceGridLayout()); @@ -200,6 +200,16 @@ public class TabbedArea extends Composite { refreshTabHeaders(); showTab(nextIndex); } + + public void closeAllTabs() { + for(Section section:sections) { + section.dispose(); + } + sections.clear(); + emptyState(); + refreshTabHeaders(); + layout(true, true); + } protected void emptyState() { new Section(body, SWT.NONE, null); @@ -214,6 +224,15 @@ public class TabbedArea extends Composite { return (Section) stackLayout.topControl; } + public Node getCurrentContext() { + Section section = getCurrentSection(); + if (section != null) { + return section.getNode(); + } else { + return null; + } + } + public void setTabStyle(String tabStyle) { this.tabStyle = tabStyle; } -- 2.30.2