From: Mathieu Baudier Date: Thu, 23 Jun 2022 10:59:13 +0000 (+0200) Subject: Move UX components between packages X-Git-Tag: v2.3.10~165 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=9fd6744d04e89fac07e34947d962aec1509ff9f8;p=lgpl%2Fargeo-commons.git Move UX components between packages --- diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java index 98e80936d..46e1b6507 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/JcrBrowserView.java @@ -27,8 +27,8 @@ import org.argeo.cms.ui.jcr.NodeLabelProvider; import org.argeo.cms.ui.jcr.OsgiRepositoryRegister; import org.argeo.cms.ui.jcr.PropertiesContentProvider; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.jcr.AsyncUiEventListener; import org.argeo.eclipse.ui.jcr.util.NodeViewerComparer; import org.argeo.jcr.JcrUtils; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java index 8f5bc36e1..09fa760cd 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/AddFolderNode.java @@ -10,7 +10,7 @@ import javax.jcr.nodetype.NodeType; import org.argeo.cms.e4.jcr.JcrBrowserView; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; import org.argeo.cms.ui.jcr.model.WorkspaceElem; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.argeo.eclipse.ui.dialogs.SingleValue; import org.eclipse.e4.core.di.annotations.Execute; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java index 1974e4d44..b8de06b46 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/DeleteNodes.java @@ -9,8 +9,8 @@ import javax.jcr.RepositoryException; import org.argeo.cms.e4.jcr.JcrBrowserView; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; import org.argeo.cms.ui.jcr.model.WorkspaceElem; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.ui.basic.MPart; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java index 4ae072cb5..036e70ac1 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/jcr/handlers/Refresh.java @@ -6,7 +6,7 @@ import javax.inject.Named; import org.argeo.cms.e4.jcr.JcrBrowserView; import org.argeo.cms.ui.jcr.JcrBrowserUtils; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.eclipse.e4.core.di.annotations.Execute; import org.eclipse.e4.ui.model.application.ui.basic.MPart; import org.eclipse.e4.ui.services.IServiceConstants; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/BundleNode.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/BundleNode.java index 962ad386e..e9536830f 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/BundleNode.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/BundleNode.java @@ -1,6 +1,6 @@ package org.argeo.cms.e4.monitoring; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceReference; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ModulesView.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ModulesView.java index f0d8c2952..6317882c4 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ModulesView.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ModulesView.java @@ -5,7 +5,7 @@ import java.util.List; import javax.annotation.PostConstruct; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.eclipse.e4.ui.di.Focus; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; diff --git a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ServiceReferenceNode.java b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ServiceReferenceNode.java index d9c45fe11..1c60811d2 100644 --- a/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ServiceReferenceNode.java +++ b/eclipse/org.argeo.cms.e4/src/org/argeo/cms/e4/monitoring/ServiceReferenceNode.java @@ -1,6 +1,6 @@ package org.argeo.cms.e4.monitoring; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceReference; diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/jface/dialog/CmsWizardDialog.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/jface/dialog/CmsWizardDialog.java new file mode 100644 index 000000000..33841a1bb --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/jface/dialog/CmsWizardDialog.java @@ -0,0 +1,222 @@ +package org.argeo.cms.jface.dialog; + +import java.lang.reflect.InvocationTargetException; + +import org.argeo.cms.CmsMsg; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.swt.Selected; +import org.argeo.cms.swt.dialogs.LightweightDialog; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.wizard.IWizard; +import org.eclipse.jface.wizard.IWizardContainer2; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FormAttachment; +import org.eclipse.swt.layout.FormData; +import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; + +/** A wizard dialog based on {@link LightweightDialog}. */ +public class CmsWizardDialog extends LightweightDialog implements IWizardContainer2 { + private static final long serialVersionUID = -2123153353654812154L; + + private IWizard wizard; + private IWizardPage currentPage; + private int currentPageIndex; + + private Label titleBar; + private Label message; + private Composite[] pageBodies; + private Composite buttons; + private Button back; + private Button next; + private Button finish; + + public CmsWizardDialog(Shell parentShell, IWizard wizard) { + super(parentShell); + this.wizard = wizard; + wizard.setContainer(this); + // create the pages + wizard.addPages(); + currentPage = wizard.getStartingPage(); + if (currentPage == null) + throw new IllegalArgumentException("At least one wizard page is required"); + } + + @Override + protected Control createDialogArea(Composite parent) { + updateWindowTitle(); + + Composite messageArea = new Composite(parent, SWT.NONE); + messageArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + { + messageArea.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(2, false))); + titleBar = new Label(messageArea, SWT.WRAP); + titleBar.setFont(EclipseUiUtils.getBoldFont(parent)); + titleBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); + updateTitleBar(); + Button cancelButton = new Button(messageArea, SWT.FLAT); + cancelButton.setText(CmsMsg.cancel.lead()); + cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3)); + cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL)); + message = new Label(messageArea, SWT.WRAP); + message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2)); + updateMessage(); + } + + Composite body = new Composite(parent, SWT.BORDER); + body.setLayout(new FormLayout()); + body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + pageBodies = new Composite[wizard.getPageCount()]; + IWizardPage[] pages = wizard.getPages(); + for (int i = 0; i < pages.length; i++) { + pageBodies[i] = new Composite(body, SWT.NONE); + pageBodies[i].setLayout(CmsSwtUtils.noSpaceGridLayout()); + setSwitchingFormData(pageBodies[i]); + pages[i].createControl(pageBodies[i]); + } + showPage(currentPage); + + buttons = new Composite(parent, SWT.NONE); + buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); + { + boolean singlePage = wizard.getPageCount() == 1; + // singlePage = false;// dev + GridLayout layout = new GridLayout(singlePage ? 1 : 3, true); + layout.marginWidth = 0; + layout.marginHeight = 0; + buttons.setLayout(layout); + // TODO revert order for right-to-left languages + + if (!singlePage) { + back = new Button(buttons, SWT.PUSH); + back.setText(CmsMsg.wizardBack.lead()); + back.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + back.addSelectionListener((Selected) (e) -> backPressed()); + + next = new Button(buttons, SWT.PUSH); + next.setText(CmsMsg.wizardNext.lead()); + next.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + next.addSelectionListener((Selected) (e) -> nextPressed()); + } + finish = new Button(buttons, SWT.PUSH); + finish.setText(CmsMsg.wizardFinish.lead()); + finish.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); + finish.addSelectionListener((Selected) (e) -> finishPressed()); + + updateButtons(); + } + return body; + } + + @Override + public IWizardPage getCurrentPage() { + return currentPage; + } + + @Override + public Shell getShell() { + return getForegoundShell(); + } + + @Override + public void showPage(IWizardPage page) { + IWizardPage[] pages = wizard.getPages(); + int index = -1; + for (int i = 0; i < pages.length; i++) { + if (page == pages[i]) { + index = i; + break; + } + } + if (index < 0) + throw new IllegalArgumentException("Cannot find index of wizard page " + page); + pageBodies[index].moveAbove(pageBodies[currentPageIndex]); + + // // clear + // for (Control c : body.getChildren()) + // c.dispose(); + // page.createControl(body); + // body.layout(true, true); + currentPageIndex = index; + currentPage = page; + } + + @Override + public void updateButtons() { + if (back != null) + back.setEnabled(wizard.getPreviousPage(currentPage) != null); + if (next != null) + next.setEnabled(wizard.getNextPage(currentPage) != null && currentPage.canFlipToNextPage()); + if (finish != null) { + finish.setEnabled(wizard.canFinish()); + } + } + + @Override + public void updateMessage() { + if (currentPage.getMessage() != null) + message.setText(currentPage.getMessage()); + } + + @Override + public void updateTitleBar() { + if (currentPage.getTitle() != null) + titleBar.setText(currentPage.getTitle()); + } + + @Override + public void updateWindowTitle() { + setTitle(wizard.getWindowTitle()); + } + + @Override + public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) + throws InvocationTargetException, InterruptedException { + // FIXME it creates a dependency to Eclipse Core Runtime + // runnable.run(null); + } + + @Override + public void updateSize() { + // TODO pack? + } + + protected boolean onCancel() { + return wizard.performCancel(); + } + + protected void nextPressed() { + IWizardPage page = wizard.getNextPage(currentPage); + showPage(page); + updateButtons(); + } + + protected void backPressed() { + IWizardPage page = wizard.getPreviousPage(currentPage); + showPage(page); + updateButtons(); + } + + protected void finishPressed() { + if (wizard.performFinish()) + closeShell(OK); + } + + private static void setSwitchingFormData(Composite composite) { + FormData fdLabel = new FormData(); + fdLabel.top = new FormAttachment(0, 0); + fdLabel.left = new FormAttachment(0, 0); + fdLabel.right = new FormAttachment(100, 0); + fdLabel.bottom = new FormAttachment(100, 0); + composite.setLayoutData(fdLabel); + } + +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/EditablePart.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/EditablePart.java deleted file mode 100644 index 90c16773c..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/EditablePart.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.argeo.cms.swt; - -import org.eclipse.swt.widgets.Control; - -/** Manages whether an editable or non editable control is shown. */ -public interface EditablePart { - public void startEditing(); - - public void stopEditing(); - - public Control getControl(); -} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/SwtEditablePart.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/SwtEditablePart.java new file mode 100644 index 000000000..f2cceef07 --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/SwtEditablePart.java @@ -0,0 +1,9 @@ +package org.argeo.cms.swt; + +import org.argeo.cms.ux.widgets.EditablePart; +import org.eclipse.swt.widgets.Control; + +/** Manages whether an editable or non editable control is shown. */ +public interface SwtEditablePart extends EditablePart { + public Control getControl(); +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSection.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSection.java new file mode 100644 index 000000000..89d003870 --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSection.java @@ -0,0 +1,158 @@ +package org.argeo.cms.swt.acr; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.argeo.api.acr.Content; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.ux.widgets.EditablePart; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** A structured UI related to a JCR context. */ +public class SwtSection extends ContentComposite { + private static final long serialVersionUID = -5933796173755739207L; + + private final SwtSection parentSection; + private Composite sectionHeader; + private final Integer relativeDepth; + + public SwtSection(Composite parent, int style, Content node) { + this(parent, findSection(parent), style, node); + } + + public SwtSection(SwtSection section, int style, Content node) { + this(section, section, style, node); + } + + protected SwtSection(Composite parent, SwtSection parentSection, int style, Content node) { + super(parent, style, node); + this.parentSection = parentSection; + if (parentSection != null) { + relativeDepth = getProvidedContent().getDepth() - parentSection.getProvidedContent().getDepth(); + } else { + relativeDepth = 0; + } + setLayout(CmsSwtUtils.noSpaceGridLayout()); + } + + public Map getSubSections() { + LinkedHashMap result = new LinkedHashMap(); + for (Control child : getChildren()) { + if (child instanceof Composite) { + collectDirectSubSections((Composite) child, result); + } + } + return Collections.unmodifiableMap(result); + } + + private void collectDirectSubSections(Composite composite, LinkedHashMap subSections) { + if (composite == sectionHeader || composite instanceof EditablePart) + return; + if (composite instanceof SwtSection) { + SwtSection section = (SwtSection) composite; + subSections.put(section.getProvidedContent().getSessionLocalId(), section); + return; + } + + for (Control child : composite.getChildren()) + if (child instanceof Composite) + collectDirectSubSections((Composite) child, subSections); + } + + public Composite createHeader() { + return createHeader(this); + } + + public Composite createHeader(Composite parent) { + if (sectionHeader != null) + sectionHeader.dispose(); + + sectionHeader = new Composite(parent, SWT.NONE); + sectionHeader.setLayoutData(CmsSwtUtils.fillWidth()); + sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout()); + // sectionHeader.moveAbove(null); + // layout(); + return sectionHeader; + } + + public Composite getHeader() { + if (sectionHeader != null && sectionHeader.isDisposed()) + sectionHeader = null; + return sectionHeader; + } + + // SECTION PARTS + public SwtSectionPart getSectionPart(String partId) { + for (Control child : getChildren()) { + if (child instanceof SwtSectionPart) { + SwtSectionPart sectionPart = (SwtSectionPart) child; + if (sectionPart.getPartId().equals(partId)) + return sectionPart; + } + } + return null; + } + + public SwtSectionPart nextSectionPart(SwtSectionPart sectionPart) { + Control[] children = getChildren(); + for (int i = 0; i < children.length; i++) { + if (sectionPart == children[i]) { + for (int j = i + 1; j < children.length; j++) { + if (children[i + 1] instanceof SwtSectionPart) { + return (SwtSectionPart) children[i + 1]; + } + } + +// if (i + 1 < children.length) { +// Composite next = (Composite) children[i + 1]; +// return (SectionPart) next; +// } else { +// // next section +// } + } + } + return null; + } + + public SwtSectionPart previousSectionPart(SwtSectionPart sectionPart) { + Control[] children = getChildren(); + for (int i = 0; i < children.length; i++) { + if (sectionPart == children[i]) + if (i != 0) { + Composite previous = (Composite) children[i - 1]; + return (SwtSectionPart) previous; + } else { + // previous section + } + } + return null; + } + + @Override + public String toString() { + if (parentSection == null) + return "Main section " + getContent(); + return "Section " + getContent(); + } + + public SwtSection getParentSection() { + return parentSection; + } + + public Integer getRelativeDepth() { + return relativeDepth; + } + + /** Recursively finds the related section in the parents (can be itself) */ + public static SwtSection findSection(Control control) { + if (control == null) + return null; + if (control instanceof SwtSection) + return (SwtSection) control; + else + return findSection(control.getParent()); + } +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSectionPart.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSectionPart.java new file mode 100644 index 000000000..7fbf4bbca --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtSectionPart.java @@ -0,0 +1,11 @@ +package org.argeo.cms.swt.acr; + +import org.argeo.cms.ux.acr.ContentPart; +import org.argeo.cms.ux.widgets.EditablePart; + +/** An editable part dynamically related to a Section */ +public interface SwtSectionPart extends EditablePart, ContentPart { + public String getPartId(); + + public SwtSection getSection(); +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtTabbedArea.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtTabbedArea.java new file mode 100644 index 000000000..cd4e37d19 --- /dev/null +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/acr/SwtTabbedArea.java @@ -0,0 +1,258 @@ +package org.argeo.cms.swt.acr; + +import java.util.ArrayList; +import java.util.List; + +import org.argeo.api.acr.Content; +import org.argeo.api.acr.spi.ProvidedContent; +import org.argeo.cms.swt.CmsSwtUtils; +import org.argeo.cms.swt.Selected; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.ToolItem; + +/** Manages {@link SwtSection} in a tab-like structure. */ +public class SwtTabbedArea extends Composite { + private static final long serialVersionUID = 8659669229482033444L; + + private Composite headers; + private Composite body; + + private List sections = new ArrayList<>(); + + private ProvidedContent previousNode; + private SwtUiProvider previousUiProvider; + private SwtUiProvider currentUiProvider; + + private String tabStyle; + private String tabSelectedStyle; + private String bodyStyle; + private Image closeIcon; + + private StackLayout stackLayout; + + private boolean singleTab = false; + + public SwtTabbedArea(Composite parent, int style) { + super(parent, SWT.NONE); + CmsSwtUtils.style(parent, bodyStyle); + + setLayout(CmsSwtUtils.noSpaceGridLayout()); + + // TODO manage tabs at bottom or sides + headers = new Composite(this, SWT.NONE); + headers.setLayoutData(CmsSwtUtils.fillWidth()); + body = new Composite(this, SWT.NONE); + body.setLayoutData(CmsSwtUtils.fillAll()); + // body.setLayout(new FormLayout()); + stackLayout = new StackLayout(); + body.setLayout(stackLayout); + emptyState(); + } + + protected void refreshTabHeaders() { + int tabCount = sections.size() > 0 ? sections.size() : 1; + for (Control tab : headers.getChildren()) + tab.dispose(); + + headers.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(tabCount, true))); + + if (sections.size() == 0) { + Composite emptyHeader = new Composite(headers, SWT.NONE); + emptyHeader.setLayoutData(CmsSwtUtils.fillAll()); + emptyHeader.setLayout(new GridLayout()); + Label lbl = new Label(emptyHeader, SWT.NONE); + lbl.setText(""); + lbl.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false)); + + } + + SwtSection currentSection = getCurrentSection(); + for (SwtSection section : sections) { + boolean selected = section == currentSection; + Composite sectionHeader = section.createHeader(headers); + CmsSwtUtils.style(sectionHeader, selected ? tabSelectedStyle : tabStyle); + int headerColumns = singleTab ? 1 : 2; + sectionHeader.setLayout(new GridLayout(headerColumns, false)); + sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout(headerColumns)); + Button title = new Button(sectionHeader, SWT.FLAT); + CmsSwtUtils.style(title, selected ? tabSelectedStyle : tabStyle); + title.setLayoutData(CmsSwtUtils.fillWidth()); + title.addSelectionListener((Selected) (e) -> showTab(tabIndex(section.getNode()))); + Content node = section.getContent(); + + // FIXME find a standard way to display titles + String titleStr = node.getName().getLocalPart(); + + // TODO internationalize + title.setText(titleStr); + if (!singleTab) { + ToolBar toolBar = new ToolBar(sectionHeader, SWT.NONE); + ToolItem closeItem = new ToolItem(toolBar, SWT.FLAT); + if (closeIcon != null) + closeItem.setImage(closeIcon); + else + closeItem.setText("X"); + CmsSwtUtils.style(closeItem, selected ? tabSelectedStyle : tabStyle); + closeItem.addSelectionListener((Selected) (e) -> closeTab(section)); + } + } + + } + + public void view(SwtUiProvider uiProvider, Content context) { + if (body.isDisposed()) + return; + int index = tabIndex(context); + if (index >= 0) { + showTab(index); + previousNode = (ProvidedContent) context; + previousUiProvider = uiProvider; + return; + } + SwtSection section = (SwtSection) body.getChildren()[0]; + previousNode = (ProvidedContent) section.getNode(); + if (previousNode == null) {// empty state + previousNode = (ProvidedContent) context; + previousUiProvider = uiProvider; + } else { + previousUiProvider = currentUiProvider; + } + currentUiProvider = uiProvider; + section.setContent(context); + // section.setLayoutData(CmsUiUtils.coverAll()); + build(section, uiProvider, context); + if (sections.size() == 0) + sections.add(section); + refreshTabHeaders(); + index = tabIndex(context); + showTab(index); + layout(true, true); + } + + public void open(SwtUiProvider uiProvider, Content context) { + if (singleTab) + throw new UnsupportedOperationException("Open is not supported in single tab mode."); + + if (previousNode != null + && previousNode.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId())) { + // does nothing + return; + } + if (sections.size() == 0) + CmsSwtUtils.clear(body); + SwtSection currentSection = getCurrentSection(); + int currentIndex = sections.indexOf(currentSection); + SwtSection previousSection = new SwtSection(body, SWT.NONE, context); + build(previousSection, previousUiProvider, previousNode); + // previousSection.setLayoutData(CmsUiUtils.coverAll()); + int newIndex = currentIndex + 1; + sections.add(currentIndex, previousSection); +// sections.add(newIndex, previousSection); + showTab(newIndex); + refreshTabHeaders(); + layout(true, true); + } + + public void showTab(int index) { + SwtSection sectionToShow = sections.get(index); + // sectionToShow.moveAbove(null); + stackLayout.topControl = sectionToShow; + refreshTabHeaders(); + layout(true, true); + } + + protected void build(SwtSection section, SwtUiProvider uiProvider, Content context) { + for (Control child : section.getChildren()) + child.dispose(); + CmsSwtUtils.style(section, bodyStyle); + section.setContent(context); + uiProvider.createUiPart(section, context); + + } + + private int tabIndex(Content context) { + for (int i = 0; i < sections.size(); i++) { + SwtSection section = sections.get(i); + if (section.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId())) + return i; + } + return -1; + } + + public void closeTab(SwtSection section) { + int currentIndex = sections.indexOf(section); + int nextIndex = currentIndex == 0 ? 0 : currentIndex - 1; + sections.remove(section); + section.dispose(); + if (sections.size() == 0) { + emptyState(); + refreshTabHeaders(); + layout(true, true); + return; + } + refreshTabHeaders(); + showTab(nextIndex); + } + + public void closeAllTabs() { + for (SwtSection section : sections) { + section.dispose(); + } + sections.clear(); + emptyState(); + refreshTabHeaders(); + layout(true, true); + } + + protected void emptyState() { + new SwtSection(body, SWT.NONE, null); + refreshTabHeaders(); + } + + public Composite getCurrent() { + return getCurrentSection(); + } + + protected SwtSection getCurrentSection() { + return (SwtSection) stackLayout.topControl; + } + + public Content getCurrentContext() { + SwtSection section = getCurrentSection(); + if (section != null) { + return section.getNode(); + } else { + return null; + } + } + + public void setTabStyle(String tabStyle) { + this.tabStyle = tabStyle; + } + + public void setTabSelectedStyle(String tabSelectedStyle) { + this.tabSelectedStyle = tabSelectedStyle; + } + + public void setBodyStyle(String bodyStyle) { + this.bodyStyle = bodyStyle; + } + + public void setCloseIcon(Image closeIcon) { + this.closeIcon = closeIcon; + } + + public void setSingleTab(boolean singleTab) { + this.singleTab = singleTab; + } + +} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java deleted file mode 100644 index d9957d63c..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/dialogs/CmsWizardDialog.java +++ /dev/null @@ -1,221 +0,0 @@ -package org.argeo.cms.swt.dialogs; - -import java.lang.reflect.InvocationTargetException; - -import org.argeo.cms.CmsMsg; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.Selected; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.jface.operation.IRunnableWithProgress; -import org.eclipse.jface.wizard.IWizard; -import org.eclipse.jface.wizard.IWizardContainer2; -import org.eclipse.jface.wizard.IWizardPage; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FormAttachment; -import org.eclipse.swt.layout.FormData; -import org.eclipse.swt.layout.FormLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Shell; - -/** A wizard dialog based on {@link LightweightDialog}. */ -public class CmsWizardDialog extends LightweightDialog implements IWizardContainer2 { - private static final long serialVersionUID = -2123153353654812154L; - - private IWizard wizard; - private IWizardPage currentPage; - private int currentPageIndex; - - private Label titleBar; - private Label message; - private Composite[] pageBodies; - private Composite buttons; - private Button back; - private Button next; - private Button finish; - - public CmsWizardDialog(Shell parentShell, IWizard wizard) { - super(parentShell); - this.wizard = wizard; - wizard.setContainer(this); - // create the pages - wizard.addPages(); - currentPage = wizard.getStartingPage(); - if (currentPage == null) - throw new IllegalArgumentException("At least one wizard page is required"); - } - - @Override - protected Control createDialogArea(Composite parent) { - updateWindowTitle(); - - Composite messageArea = new Composite(parent, SWT.NONE); - messageArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - { - messageArea.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(2, false))); - titleBar = new Label(messageArea, SWT.WRAP); - titleBar.setFont(EclipseUiUtils.getBoldFont(parent)); - titleBar.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); - updateTitleBar(); - Button cancelButton = new Button(messageArea, SWT.FLAT); - cancelButton.setText(CmsMsg.cancel.lead()); - cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3)); - cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL)); - message = new Label(messageArea, SWT.WRAP); - message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2)); - updateMessage(); - } - - Composite body = new Composite(parent, SWT.BORDER); - body.setLayout(new FormLayout()); - body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - pageBodies = new Composite[wizard.getPageCount()]; - IWizardPage[] pages = wizard.getPages(); - for (int i = 0; i < pages.length; i++) { - pageBodies[i] = new Composite(body, SWT.NONE); - pageBodies[i].setLayout(CmsSwtUtils.noSpaceGridLayout()); - setSwitchingFormData(pageBodies[i]); - pages[i].createControl(pageBodies[i]); - } - showPage(currentPage); - - buttons = new Composite(parent, SWT.NONE); - buttons.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); - { - boolean singlePage = wizard.getPageCount() == 1; - // singlePage = false;// dev - GridLayout layout = new GridLayout(singlePage ? 1 : 3, true); - layout.marginWidth = 0; - layout.marginHeight = 0; - buttons.setLayout(layout); - // TODO revert order for right-to-left languages - - if (!singlePage) { - back = new Button(buttons, SWT.PUSH); - back.setText(CmsMsg.wizardBack.lead()); - back.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - back.addSelectionListener((Selected) (e) -> backPressed()); - - next = new Button(buttons, SWT.PUSH); - next.setText(CmsMsg.wizardNext.lead()); - next.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - next.addSelectionListener((Selected) (e) -> nextPressed()); - } - finish = new Button(buttons, SWT.PUSH); - finish.setText(CmsMsg.wizardFinish.lead()); - finish.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false)); - finish.addSelectionListener((Selected) (e) -> finishPressed()); - - updateButtons(); - } - return body; - } - - @Override - public IWizardPage getCurrentPage() { - return currentPage; - } - - @Override - public Shell getShell() { - return getForegoundShell(); - } - - @Override - public void showPage(IWizardPage page) { - IWizardPage[] pages = wizard.getPages(); - int index = -1; - for (int i = 0; i < pages.length; i++) { - if (page == pages[i]) { - index = i; - break; - } - } - if (index < 0) - throw new IllegalArgumentException("Cannot find index of wizard page " + page); - pageBodies[index].moveAbove(pageBodies[currentPageIndex]); - - // // clear - // for (Control c : body.getChildren()) - // c.dispose(); - // page.createControl(body); - // body.layout(true, true); - currentPageIndex = index; - currentPage = page; - } - - @Override - public void updateButtons() { - if (back != null) - back.setEnabled(wizard.getPreviousPage(currentPage) != null); - if (next != null) - next.setEnabled(wizard.getNextPage(currentPage) != null && currentPage.canFlipToNextPage()); - if (finish != null) { - finish.setEnabled(wizard.canFinish()); - } - } - - @Override - public void updateMessage() { - if (currentPage.getMessage() != null) - message.setText(currentPage.getMessage()); - } - - @Override - public void updateTitleBar() { - if (currentPage.getTitle() != null) - titleBar.setText(currentPage.getTitle()); - } - - @Override - public void updateWindowTitle() { - setTitle(wizard.getWindowTitle()); - } - - @Override - public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) - throws InvocationTargetException, InterruptedException { - // FIXME it creates a dependency to Eclipse Core Runtime - // runnable.run(null); - } - - @Override - public void updateSize() { - // TODO pack? - } - - protected boolean onCancel() { - return wizard.performCancel(); - } - - protected void nextPressed() { - IWizardPage page = wizard.getNextPage(currentPage); - showPage(page); - updateButtons(); - } - - protected void backPressed() { - IWizardPage page = wizard.getPreviousPage(currentPage); - showPage(page); - updateButtons(); - } - - protected void finishPressed() { - if (wizard.performFinish()) - closeShell(OK); - } - - private static void setSwitchingFormData(Composite composite) { - FormData fdLabel = new FormData(); - fdLabel.top = new FormAttachment(0, 0); - fdLabel.left = new FormAttachment(0, 0); - fdLabel.right = new FormAttachment(100, 0); - fdLabel.bottom = new FormAttachment(100, 0); - composite.setLayoutData(fdLabel); - } - -} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSection.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSection.java deleted file mode 100644 index 5562bcf4e..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSection.java +++ /dev/null @@ -1,159 +0,0 @@ -package org.argeo.cms.swt.widgets; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.argeo.api.acr.Content; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.acr.ContentComposite; -import org.argeo.cms.ux.widgets.EditablePart; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** A structured UI related to a JCR context. */ -public class SwtSection extends ContentComposite { - private static final long serialVersionUID = -5933796173755739207L; - - private final SwtSection parentSection; - private Composite sectionHeader; - private final Integer relativeDepth; - - public SwtSection(Composite parent, int style, Content node) { - this(parent, findSection(parent), style, node); - } - - public SwtSection(SwtSection section, int style, Content node) { - this(section, section, style, node); - } - - protected SwtSection(Composite parent, SwtSection parentSection, int style, Content node) { - super(parent, style, node); - this.parentSection = parentSection; - if (parentSection != null) { - relativeDepth = getProvidedContent().getDepth() - parentSection.getProvidedContent().getDepth(); - } else { - relativeDepth = 0; - } - setLayout(CmsSwtUtils.noSpaceGridLayout()); - } - - public Map getSubSections() { - LinkedHashMap result = new LinkedHashMap(); - for (Control child : getChildren()) { - if (child instanceof Composite) { - collectDirectSubSections((Composite) child, result); - } - } - return Collections.unmodifiableMap(result); - } - - private void collectDirectSubSections(Composite composite, LinkedHashMap subSections) { - if (composite == sectionHeader || composite instanceof EditablePart) - return; - if (composite instanceof SwtSection) { - SwtSection section = (SwtSection) composite; - subSections.put(section.getProvidedContent().getSessionLocalId(), section); - return; - } - - for (Control child : composite.getChildren()) - if (child instanceof Composite) - collectDirectSubSections((Composite) child, subSections); - } - - public Composite createHeader() { - return createHeader(this); - } - - public Composite createHeader(Composite parent) { - if (sectionHeader != null) - sectionHeader.dispose(); - - sectionHeader = new Composite(parent, SWT.NONE); - sectionHeader.setLayoutData(CmsSwtUtils.fillWidth()); - sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout()); - // sectionHeader.moveAbove(null); - // layout(); - return sectionHeader; - } - - public Composite getHeader() { - if (sectionHeader != null && sectionHeader.isDisposed()) - sectionHeader = null; - return sectionHeader; - } - - // SECTION PARTS - public SwtSectionPart getSectionPart(String partId) { - for (Control child : getChildren()) { - if (child instanceof SwtSectionPart) { - SwtSectionPart sectionPart = (SwtSectionPart) child; - if (sectionPart.getPartId().equals(partId)) - return sectionPart; - } - } - return null; - } - - public SwtSectionPart nextSectionPart(SwtSectionPart sectionPart) { - Control[] children = getChildren(); - for (int i = 0; i < children.length; i++) { - if (sectionPart == children[i]) { - for (int j = i + 1; j < children.length; j++) { - if (children[i + 1] instanceof SwtSectionPart) { - return (SwtSectionPart) children[i + 1]; - } - } - -// if (i + 1 < children.length) { -// Composite next = (Composite) children[i + 1]; -// return (SectionPart) next; -// } else { -// // next section -// } - } - } - return null; - } - - public SwtSectionPart previousSectionPart(SwtSectionPart sectionPart) { - Control[] children = getChildren(); - for (int i = 0; i < children.length; i++) { - if (sectionPart == children[i]) - if (i != 0) { - Composite previous = (Composite) children[i - 1]; - return (SwtSectionPart) previous; - } else { - // previous section - } - } - return null; - } - - @Override - public String toString() { - if (parentSection == null) - return "Main section " + getContent(); - return "Section " + getContent(); - } - - public SwtSection getParentSection() { - return parentSection; - } - - public Integer getRelativeDepth() { - return relativeDepth; - } - - /** Recursively finds the related section in the parents (can be itself) */ - public static SwtSection findSection(Control control) { - if (control == null) - return null; - if (control instanceof SwtSection) - return (SwtSection) control; - else - return findSection(control.getParent()); - } -} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSectionPart.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSectionPart.java deleted file mode 100644 index e0578609e..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtSectionPart.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.argeo.cms.swt.widgets; - -import org.argeo.cms.ux.widgets.ContentPart; -import org.argeo.cms.ux.widgets.EditablePart; - -/** An editable part dynamically related to a Section */ -public interface SwtSectionPart extends EditablePart, ContentPart { - public String getPartId(); - - public SwtSection getSection(); -} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabbedArea.java b/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabbedArea.java deleted file mode 100644 index a2f7671c0..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/cms/swt/widgets/SwtTabbedArea.java +++ /dev/null @@ -1,259 +0,0 @@ -package org.argeo.cms.swt.widgets; - -import java.util.ArrayList; -import java.util.List; - -import org.argeo.api.acr.Content; -import org.argeo.api.acr.spi.ProvidedContent; -import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.Selected; -import org.argeo.cms.swt.acr.SwtUiProvider; -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.StackLayout; -import org.eclipse.swt.graphics.Image; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; - -/** Manages {@link SwtSection} in a tab-like structure. */ -public class SwtTabbedArea extends Composite { - private static final long serialVersionUID = 8659669229482033444L; - - private Composite headers; - private Composite body; - - private List sections = new ArrayList<>(); - - private ProvidedContent previousNode; - private SwtUiProvider previousUiProvider; - private SwtUiProvider currentUiProvider; - - private String tabStyle; - private String tabSelectedStyle; - private String bodyStyle; - private Image closeIcon; - - private StackLayout stackLayout; - - private boolean singleTab = false; - - public SwtTabbedArea(Composite parent, int style) { - super(parent, SWT.NONE); - CmsSwtUtils.style(parent, bodyStyle); - - setLayout(CmsSwtUtils.noSpaceGridLayout()); - - // TODO manage tabs at bottom or sides - headers = new Composite(this, SWT.NONE); - headers.setLayoutData(CmsSwtUtils.fillWidth()); - body = new Composite(this, SWT.NONE); - body.setLayoutData(CmsSwtUtils.fillAll()); - // body.setLayout(new FormLayout()); - stackLayout = new StackLayout(); - body.setLayout(stackLayout); - emptyState(); - } - - protected void refreshTabHeaders() { - int tabCount = sections.size() > 0 ? sections.size() : 1; - for (Control tab : headers.getChildren()) - tab.dispose(); - - headers.setLayout(CmsSwtUtils.noSpaceGridLayout(new GridLayout(tabCount, true))); - - if (sections.size() == 0) { - Composite emptyHeader = new Composite(headers, SWT.NONE); - emptyHeader.setLayoutData(CmsSwtUtils.fillAll()); - emptyHeader.setLayout(new GridLayout()); - Label lbl = new Label(emptyHeader, SWT.NONE); - lbl.setText(""); - lbl.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false)); - - } - - SwtSection currentSection = getCurrentSection(); - for (SwtSection section : sections) { - boolean selected = section == currentSection; - Composite sectionHeader = section.createHeader(headers); - CmsSwtUtils.style(sectionHeader, selected ? tabSelectedStyle : tabStyle); - int headerColumns = singleTab ? 1 : 2; - sectionHeader.setLayout(new GridLayout(headerColumns, false)); - sectionHeader.setLayout(CmsSwtUtils.noSpaceGridLayout(headerColumns)); - Button title = new Button(sectionHeader, SWT.FLAT); - CmsSwtUtils.style(title, selected ? tabSelectedStyle : tabStyle); - title.setLayoutData(CmsSwtUtils.fillWidth()); - title.addSelectionListener((Selected) (e) -> showTab(tabIndex(section.getNode()))); - Content node = section.getContent(); - - // FIXME find a standard way to display titles - String titleStr = node.getName().getLocalPart(); - - // TODO internationalize - title.setText(titleStr); - if (!singleTab) { - ToolBar toolBar = new ToolBar(sectionHeader, SWT.NONE); - ToolItem closeItem = new ToolItem(toolBar, SWT.FLAT); - if (closeIcon != null) - closeItem.setImage(closeIcon); - else - closeItem.setText("X"); - CmsSwtUtils.style(closeItem, selected ? tabSelectedStyle : tabStyle); - closeItem.addSelectionListener((Selected) (e) -> closeTab(section)); - } - } - - } - - public void view(SwtUiProvider uiProvider, Content context) { - if (body.isDisposed()) - return; - int index = tabIndex(context); - if (index >= 0) { - showTab(index); - previousNode = (ProvidedContent) context; - previousUiProvider = uiProvider; - return; - } - SwtSection section = (SwtSection) body.getChildren()[0]; - previousNode = (ProvidedContent) section.getNode(); - if (previousNode == null) {// empty state - previousNode = (ProvidedContent) context; - previousUiProvider = uiProvider; - } else { - previousUiProvider = currentUiProvider; - } - currentUiProvider = uiProvider; - section.setContent(context); - // section.setLayoutData(CmsUiUtils.coverAll()); - build(section, uiProvider, context); - if (sections.size() == 0) - sections.add(section); - refreshTabHeaders(); - index = tabIndex(context); - showTab(index); - layout(true, true); - } - - public void open(SwtUiProvider uiProvider, Content context) { - if (singleTab) - throw new UnsupportedOperationException("Open is not supported in single tab mode."); - - if (previousNode != null - && previousNode.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId())) { - // does nothing - return; - } - if (sections.size() == 0) - CmsSwtUtils.clear(body); - SwtSection currentSection = getCurrentSection(); - int currentIndex = sections.indexOf(currentSection); - SwtSection previousSection = new SwtSection(body, SWT.NONE, context); - build(previousSection, previousUiProvider, previousNode); - // previousSection.setLayoutData(CmsUiUtils.coverAll()); - int newIndex = currentIndex + 1; - sections.add(currentIndex, previousSection); -// sections.add(newIndex, previousSection); - showTab(newIndex); - refreshTabHeaders(); - layout(true, true); - } - - public void showTab(int index) { - SwtSection sectionToShow = sections.get(index); - // sectionToShow.moveAbove(null); - stackLayout.topControl = sectionToShow; - refreshTabHeaders(); - layout(true, true); - } - - protected void build(SwtSection section, SwtUiProvider uiProvider, Content context) { - for (Control child : section.getChildren()) - child.dispose(); - CmsSwtUtils.style(section, bodyStyle); - section.setContent(context); - uiProvider.createUiPart(section, context); - - } - - private int tabIndex(Content context) { - for (int i = 0; i < sections.size(); i++) { - SwtSection section = sections.get(i); - if (section.getSessionLocalId().equals(((ProvidedContent) context).getSessionLocalId())) - return i; - } - return -1; - } - - public void closeTab(SwtSection section) { - int currentIndex = sections.indexOf(section); - int nextIndex = currentIndex == 0 ? 0 : currentIndex - 1; - sections.remove(section); - section.dispose(); - if (sections.size() == 0) { - emptyState(); - refreshTabHeaders(); - layout(true, true); - return; - } - refreshTabHeaders(); - showTab(nextIndex); - } - - public void closeAllTabs() { - for (SwtSection section : sections) { - section.dispose(); - } - sections.clear(); - emptyState(); - refreshTabHeaders(); - layout(true, true); - } - - protected void emptyState() { - new SwtSection(body, SWT.NONE, null); - refreshTabHeaders(); - } - - public Composite getCurrent() { - return getCurrentSection(); - } - - protected SwtSection getCurrentSection() { - return (SwtSection) stackLayout.topControl; - } - - public Content getCurrentContext() { - SwtSection section = getCurrentSection(); - if (section != null) { - return section.getNode(); - } else { - return null; - } - } - - public void setTabStyle(String tabStyle) { - this.tabStyle = tabStyle; - } - - public void setTabSelectedStyle(String tabSelectedStyle) { - this.tabSelectedStyle = tabSelectedStyle; - } - - public void setBodyStyle(String bodyStyle) { - this.bodyStyle = bodyStyle; - } - - public void setCloseIcon(Image closeIcon) { - this.closeIcon = closeIcon; - } - - public void setSingleTab(boolean singleTab) { - this.singleTab = singleTab; - } - -} diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/AbstractTreeContentProvider.java b/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/AbstractTreeContentProvider.java index c882eb766..64ea2dbc9 100644 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/AbstractTreeContentProvider.java +++ b/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/AbstractTreeContentProvider.java @@ -1,5 +1,6 @@ package org.argeo.eclipse.ui; +import org.argeo.cms.ux.widgets.TreeParent; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; diff --git a/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/TreeParent.java b/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/TreeParent.java deleted file mode 100644 index cf3c15795..000000000 --- a/eclipse/org.argeo.cms.swt/src/org/argeo/eclipse/ui/TreeParent.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.argeo.eclipse.ui; - -import java.util.ArrayList; -import java.util.List; - -/** Parent / children semantic to be used for simple UI Tree structure */ -public class TreeParent { - private String name; - private TreeParent parent; - - private List children; - - /** - * Unique id within the context of a tree display. If set, equals() and - * hashCode() methods will be based on it - */ - private String path = null; - - /** False until at least one child has been added, then true until cleared */ - private boolean loaded = false; - - public TreeParent(String name) { - this.name = name; - children = new ArrayList(); - } - - public synchronized void addChild(Object child) { - loaded = true; - children.add(child); - if (child instanceof TreeParent) - ((TreeParent) child).setParent(this); - } - - /** - * Remove this child. The child is disposed. - */ - public synchronized void removeChild(Object child) { - children.remove(child); - if (child instanceof TreeParent) { - ((TreeParent) child).dispose(); - } - } - - public synchronized void clearChildren() { - for (Object obj : children) { - if (obj instanceof TreeParent) - ((TreeParent) obj).dispose(); - } - loaded = false; - children.clear(); - } - - /** - * If overridden, super.dispose() must be called, typically - * after custom cleaning. - */ - public synchronized void dispose() { - clearChildren(); - parent = null; - children = null; - } - - public synchronized Object[] getChildren() { - return children.toArray(new Object[children.size()]); - } - - @SuppressWarnings("unchecked") - public synchronized List getChildrenOfType(Class clss) { - List lst = new ArrayList(); - for (Object obj : children) { - if (clss.isAssignableFrom(obj.getClass())) - lst.add((T) obj); - } - return lst; - } - - public synchronized boolean hasChildren() { - return children.size() > 0; - } - - public Object getChildByName(String name) { - for (Object child : children) { - if (child.toString().equals(name)) - return child; - } - return null; - } - - public synchronized Boolean isLoaded() { - return loaded; - } - - public String getName() { - return name; - } - - public void setParent(TreeParent parent) { - this.parent = parent; - if (parent != null && parent.path != null) - this.path = parent.path + '/' + name; - else - this.path = '/' + name; - } - - public TreeParent getParent() { - return parent; - } - - public String toString() { - return getName(); - } - - public int compareTo(TreeParent o) { - return name.compareTo(o.name); - } - - @Override - public int hashCode() { - if (path != null) - return path.hashCode(); - else - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (path != null && obj instanceof TreeParent) - return path.equals(((TreeParent) obj).path); - else - return name.equals(obj.toString()); - } - -} diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableLink.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableLink.java index 689fca316..3c1e8cda5 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableLink.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableLink.java @@ -3,7 +3,7 @@ package org.argeo.cms.ui.forms; import javax.jcr.Node; import javax.jcr.RepositoryException; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.eclipse.ui.EclipseUiUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; @@ -13,7 +13,7 @@ import org.eclipse.swt.widgets.Text; /** Editable String that displays a browsable link when read-only */ public class EditableLink extends EditablePropertyString implements - EditablePart { + SwtEditablePart { private static final long serialVersionUID = 5055000749992803591L; private String type; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java index a04537ef4..ff8270046 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditableMultiStringProperty.java @@ -6,7 +6,7 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.ui.widgets.StyledControl; import org.argeo.eclipse.ui.EclipseUiUtils; import org.eclipse.jface.dialogs.MessageDialog; @@ -24,7 +24,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; /** Display, add or remove values from a list in a CMS context */ -public class EditableMultiStringProperty extends StyledControl implements EditablePart { +public class EditableMultiStringProperty extends StyledControl implements SwtEditablePart { private static final long serialVersionUID = -7044614381252178595L; private String propertyName; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java index 0f80ca78c..641f916f2 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyDate.java @@ -8,7 +8,7 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.ui.widgets.StyledControl; import org.argeo.eclipse.ui.EclipseUiUtils; import org.eclipse.swt.SWT; @@ -29,7 +29,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** CMS form part to display and edit a date */ -public class EditablePropertyDate extends StyledControl implements EditablePart { +public class EditablePropertyDate extends StyledControl implements SwtEditablePart { private static final long serialVersionUID = 2500215515778162468L; // Context diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java index ffe7e36f7..f2575e1f9 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/EditablePropertyString.java @@ -7,7 +7,7 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.ui.widgets.EditableText; import org.argeo.eclipse.ui.EclipseUiUtils; import org.eclipse.swt.widgets.Composite; @@ -16,7 +16,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; /** Editable String in a CMS context */ -public class EditablePropertyString extends EditableText implements EditablePart { +public class EditablePropertyString extends EditableText implements SwtEditablePart { private static final long serialVersionUID = 5055000749992803591L; private String propertyName; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java index e10dd4556..1888055fc 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/forms/FormPageViewer.java @@ -19,7 +19,7 @@ import org.argeo.api.cms.ux.Cms2DSize; import org.argeo.api.cms.ux.CmsEditable; import org.argeo.api.cms.ux.CmsImageManager; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.ui.viewers.AbstractPageViewer; import org.argeo.cms.ui.viewers.Section; import org.argeo.cms.ui.viewers.SectionPart; @@ -86,14 +86,14 @@ public class FormPageViewer extends AbstractPageViewer { } @Override - protected void prepare(EditablePart part, Object caretPosition) { + protected void prepare(SwtEditablePart part, Object caretPosition) { if (part instanceof Img) { ((Img) part).setFileUploadListener(fileUploadListener); } } /** To be overridden.Save the edited part. */ - protected void save(EditablePart part) throws RepositoryException { + protected void save(SwtEditablePart part) throws RepositoryException { Node node = null; if (part instanceof EditableMultiStringProperty) { EditableMultiStringProperty ept = (EditableMultiStringProperty) part; @@ -148,7 +148,7 @@ public class FormPageViewer extends AbstractPageViewer { } @Override - protected void updateContent(EditablePart part) throws RepositoryException { + protected void updateContent(SwtEditablePart part) throws RepositoryException { if (part instanceof EditableMultiStringProperty) { EditableMultiStringProperty ept = (EditableMultiStringProperty) part; // SWT : View @@ -259,7 +259,7 @@ public class FormPageViewer extends AbstractPageViewer { if (getCmsEditable().isEditing() && !(getEdited() instanceof Img)) { if (source == mainSection) return; - EditablePart part = findDataParent(source); + SwtEditablePart part = findDataParent(source); upload(part); } else { getCmsEditable().startEditing(); @@ -273,7 +273,7 @@ public class FormPageViewer extends AbstractPageViewer { if (getCmsEditable().isEditing()) { if (e.button == 1) { Control source = (Control) e.getSource(); - EditablePart composite = findDataParent(source); + SwtEditablePart composite = findDataParent(source); Point point = new Point(e.x, e.y); if (!(composite instanceof Img)) edit(composite, source.toDisplay(point)); @@ -286,7 +286,7 @@ public class FormPageViewer extends AbstractPageViewer { } } - protected synchronized void upload(EditablePart part) { + protected synchronized void upload(SwtEditablePart part) { if (part instanceof SectionPart) { if (part instanceof Img) { if (getEdited() == part) @@ -561,7 +561,7 @@ public class FormPageViewer extends AbstractPageViewer { if (source instanceof Button) { Button btn = (Button) source; Object obj = btn.getData(FormConstants.LINKED_VALUE); - EditablePart ep = findDataParent(btn); + SwtEditablePart ep = findDataParent(btn); if (ep != null && ep instanceof EditableMultiStringProperty) { EditableMultiStringProperty emsp = (EditableMultiStringProperty) ep; List values = emsp.getValues(); diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java index e4c5873a0..b36acc368 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/JcrBrowserUtils.java @@ -9,8 +9,8 @@ import org.argeo.cms.ui.jcr.model.RepositoriesElem; import org.argeo.cms.ui.jcr.model.RepositoryElem; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; import org.argeo.cms.ui.jcr.model.WorkspaceElem; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; /** Useful methods to manage the JCR Browser */ public class JcrBrowserUtils { diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java index 00449df26..0625cc872 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/NodeContentProvider.java @@ -16,7 +16,7 @@ import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.cms.security.Keyring; import org.argeo.cms.ui.jcr.model.RepositoriesElem; import org.argeo.cms.ui.jcr.model.SingleJcrNodeElem; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java index 61654b61a..d33b33f63 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/MaintainedRepositoryElem.java @@ -2,7 +2,7 @@ package org.argeo.cms.ui.jcr.model; import javax.jcr.Repository; -import org.argeo.eclipse.ui.TreeParent; +import org.argeo.cms.ux.widgets.TreeParent; /** Wrap a MaintainedRepository */ public class MaintainedRepositoryElem extends RepositoryElem { diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java index 428e7f1cd..908d1b135 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RemoteRepositoryElem.java @@ -12,8 +12,8 @@ import javax.jcr.SimpleCredentials; import org.argeo.cms.ArgeoNames; import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.cms.security.Keyring; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; /** Root of a remote repository */ public class RemoteRepositoryElem extends RepositoryElem { diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java index 858633202..742800b0b 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoriesElem.java @@ -13,8 +13,8 @@ import org.argeo.cms.ArgeoNames; import org.argeo.cms.jcr.CmsJcrUtils; import org.argeo.cms.security.Keyring; import org.argeo.cms.ui.jcr.RepositoryRegister; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; import org.argeo.eclipse.ui.dialogs.ErrorFeedback; /** diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java index afff3ef9e..296c36922 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/RepositoryElem.java @@ -5,8 +5,8 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.api.cms.CmsConstants; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; import org.argeo.jcr.JcrUtils; /** diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java index 859deee97..a2584a5e8 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/SingleJcrNodeElem.java @@ -5,8 +5,8 @@ import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Workspace; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; /** * UI Tree component. Wraps a node of a JCR {@link Workspace}. It also keeps a diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java index 24fc5758d..2d786669f 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/jcr/model/WorkspaceElem.java @@ -8,8 +8,8 @@ import javax.jcr.Session; // import javax.jcr.Workspace; import javax.jcr.Workspace; +import org.argeo.cms.ux.widgets.TreeParent; import org.argeo.eclipse.ui.EclipseUiException; -import org.argeo.eclipse.ui.TreeParent; import org.argeo.jcr.JcrUtils; /** diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java index a247313e1..e23846e92 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/AbstractPageViewer.java @@ -13,7 +13,7 @@ import javax.security.auth.Subject; import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.ux.CmsEditable; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.swt.widgets.ScrolledPage; import org.argeo.jcr.JcrException; import org.eclipse.jface.viewers.ContentViewer; @@ -43,7 +43,7 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ private MouseListener mouseListener; private FocusListener focusListener; - private EditablePart edited; + private SwtEditablePart edited; private ISelection selection = StructuredSelection.EMPTY; private AccessControlContext accessControlContext; @@ -141,11 +141,11 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ } /** To be overridden.Save the edited part. */ - protected void save(EditablePart part) throws RepositoryException { + protected void save(SwtEditablePart part) throws RepositoryException { } /** Prepare the edited part */ - protected void prepare(EditablePart part, Object caretPosition) { + protected void prepare(SwtEditablePart part, Object caretPosition) { } /** Notified when the editing state changed. Does nothing, to be overridden */ @@ -178,17 +178,17 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ this.selection = selection; } - protected void updateContent(EditablePart part) throws RepositoryException { + protected void updateContent(SwtEditablePart part) throws RepositoryException { } // LOW LEVEL EDITION - protected void edit(EditablePart part, Object caretPosition) { + protected void edit(SwtEditablePart part, Object caretPosition) { try { if (edited == part) return; if (edited != null && edited != part) { - EditablePart previouslyEdited = edited; + SwtEditablePart previouslyEdited = edited; try { stopEditing(true); } catch (Exception e) { @@ -240,8 +240,8 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ save(edited); edited.stopEditing(); - EditablePart editablePart = edited; - Control control = ((EditablePart) edited).getControl(); + SwtEditablePart editablePart = edited; + Control control = ((SwtEditablePart) edited).getControl(); edited = null; // TODO make edited state management more robust updateContent(editablePart); @@ -270,11 +270,11 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ } /** - * Find the first {@link EditablePart} in the parents hierarchy of this control + * Find the first {@link SwtEditablePart} in the parents hierarchy of this control */ - protected EditablePart findDataParent(Control parent) { - if (parent instanceof EditablePart) { - return (EditablePart) parent; + protected SwtEditablePart findDataParent(Control parent) { + if (parent instanceof SwtEditablePart) { + return (SwtEditablePart) parent; } if (parent.getParent() != null) return findDataParent(parent.getParent()); @@ -328,7 +328,7 @@ public abstract class AbstractPageViewer extends ContentViewer implements Observ return readOnly; } - protected EditablePart getEdited() { + protected SwtEditablePart getEdited() { return edited; } diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/Section.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/Section.java index 0e489e05f..b27fa3845 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/Section.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/Section.java @@ -8,7 +8,7 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import org.argeo.cms.swt.CmsSwtUtils; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; import org.argeo.cms.ui.widgets.JcrComposite; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; @@ -57,7 +57,7 @@ public class Section extends JcrComposite { private void collectDirectSubSections(Composite composite, LinkedHashMap subSections) throws RepositoryException { - if (composite == sectionHeader || composite instanceof EditablePart) + if (composite == sectionHeader || composite instanceof SwtEditablePart) return; if (composite instanceof Section) { Section section = (Section) composite; diff --git a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/SectionPart.java b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/SectionPart.java index df3c734c2..4278c83cc 100644 --- a/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/SectionPart.java +++ b/jcr/org.argeo.cms.ui/src/org/argeo/cms/ui/viewers/SectionPart.java @@ -1,9 +1,9 @@ package org.argeo.cms.ui.viewers; -import org.argeo.cms.swt.EditablePart; +import org.argeo.cms.swt.SwtEditablePart; /** An editable part dynamically related to a Section */ -public interface SectionPart extends EditablePart, NodePart { +public interface SectionPart extends SwtEditablePart, NodePart { public String getPartId(); public Section getSection(); diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentPart.java new file mode 100644 index 000000000..8d674f8a3 --- /dev/null +++ b/org.argeo.cms.ux/src/org/argeo/cms/ux/acr/ContentPart.java @@ -0,0 +1,12 @@ +package org.argeo.cms.ux.acr; + +import org.argeo.api.acr.Content; + +/** A part displaying or editing a content. */ +public interface ContentPart { + Content getContent(); + + @Deprecated + Content getNode(); + +} diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/ContentPart.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/ContentPart.java deleted file mode 100644 index 5e91f5c79..000000000 --- a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/ContentPart.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.argeo.cms.ux.widgets; - -import org.argeo.api.acr.Content; - -/** A part displaying or editing a content. */ -public interface ContentPart { - Content getContent(); - - @Deprecated - Content getNode(); - -} diff --git a/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/TreeParent.java b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/TreeParent.java new file mode 100644 index 000000000..97dedcc24 --- /dev/null +++ b/org.argeo.cms.ux/src/org/argeo/cms/ux/widgets/TreeParent.java @@ -0,0 +1,133 @@ +package org.argeo.cms.ux.widgets; + +import java.util.ArrayList; +import java.util.List; + +/** Parent / children semantic to be used for simple UI Tree structure */ +public class TreeParent { + private String name; + private TreeParent parent; + + private List children; + + /** + * Unique id within the context of a tree display. If set, equals() and + * hashCode() methods will be based on it + */ + private String path = null; + + /** False until at least one child has been added, then true until cleared */ + private boolean loaded = false; + + public TreeParent(String name) { + this.name = name; + children = new ArrayList(); + } + + public synchronized void addChild(Object child) { + loaded = true; + children.add(child); + if (child instanceof TreeParent) + ((TreeParent) child).setParent(this); + } + + /** + * Remove this child. The child is disposed. + */ + public synchronized void removeChild(Object child) { + children.remove(child); + if (child instanceof TreeParent) { + ((TreeParent) child).dispose(); + } + } + + public synchronized void clearChildren() { + for (Object obj : children) { + if (obj instanceof TreeParent) + ((TreeParent) obj).dispose(); + } + loaded = false; + children.clear(); + } + + /** + * If overridden, super.dispose() must be called, typically + * after custom cleaning. + */ + public synchronized void dispose() { + clearChildren(); + parent = null; + children = null; + } + + public synchronized Object[] getChildren() { + return children.toArray(new Object[children.size()]); + } + + @SuppressWarnings("unchecked") + public synchronized List getChildrenOfType(Class clss) { + List lst = new ArrayList(); + for (Object obj : children) { + if (clss.isAssignableFrom(obj.getClass())) + lst.add((T) obj); + } + return lst; + } + + public synchronized boolean hasChildren() { + return children.size() > 0; + } + + public Object getChildByName(String name) { + for (Object child : children) { + if (child.toString().equals(name)) + return child; + } + return null; + } + + public synchronized Boolean isLoaded() { + return loaded; + } + + public String getName() { + return name; + } + + public void setParent(TreeParent parent) { + this.parent = parent; + if (parent != null && parent.path != null) + this.path = parent.path + '/' + name; + else + this.path = '/' + name; + } + + public TreeParent getParent() { + return parent; + } + + public String toString() { + return getName(); + } + + public int compareTo(TreeParent o) { + return name.compareTo(o.name); + } + + @Override + public int hashCode() { + if (path != null) + return path.hashCode(); + else + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (path != null && obj instanceof TreeParent) + return path.equals(((TreeParent) obj).path); + else + return name.equals(obj.toString()); + } + +}