--- /dev/null
+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();
+}
--- /dev/null
+package org.argeo.cms.swt.widgets;
+
+import org.argeo.cms.swt.CmsSwtUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Manages a lightweight shell which is related to a {@link Control}, typically
+ * in order to reproduce a dropdown semantic, but with more flexibility.
+ */
+public class ContextOverlay extends ScrolledPage {
+ private static final long serialVersionUID = 6702077429573324009L;
+
+// private Shell shell;
+ private Control control;
+
+ private int maxHeight = 400;
+
+ public ContextOverlay(Control control, int style) {
+ super(createShell(control, style), SWT.NONE);
+ Shell shell = getShell();
+ setLayoutData(CmsSwtUtils.fillAll());
+ // TODO make autohide configurable?
+ //shell.addShellListener(new AutoHideShellListener());
+ this.control = control;
+ control.addDisposeListener((e) -> {
+ dispose();
+ shell.dispose();
+ });
+ }
+
+ private static Composite createShell(Control control, int style) {
+ if (control == null)
+ throw new IllegalArgumentException("Control cannot be null");
+ if (control.isDisposed())
+ throw new IllegalArgumentException("Control is disposed");
+ Shell shell = new Shell(control.getShell(), SWT.NO_TRIM);
+ shell.setLayout(CmsSwtUtils.noSpaceGridLayout());
+ Composite placeholder = new Composite(shell, SWT.BORDER);
+ placeholder.setLayoutData(CmsSwtUtils.fillAll());
+ placeholder.setLayout(CmsSwtUtils.noSpaceGridLayout());
+ return placeholder;
+ }
+
+ public void show() {
+ Point relativeControlLocation = control.getLocation();
+ Point controlLocation = control.toDisplay(relativeControlLocation.x, relativeControlLocation.y);
+
+ int controlWidth = control.getBounds().width;
+
+ Shell shell = getShell();
+
+ layout(true, true);
+ shell.pack();
+ shell.layout(true, true);
+ int targetShellWidth = shell.getSize().x < controlWidth ? controlWidth : shell.getSize().x;
+ if (shell.getSize().y > maxHeight) {
+ shell.setSize(targetShellWidth, maxHeight);
+ } else {
+ shell.setSize(targetShellWidth, shell.getSize().y);
+ }
+
+ int shellHeight = shell.getSize().y;
+ int controlHeight = control.getBounds().height;
+ Point shellLocation = new Point(controlLocation.x, controlLocation.y + controlHeight);
+ int displayHeight = shell.getDisplay().getBounds().height;
+ if (shellLocation.y + shellHeight > displayHeight) {// bottom of page
+ shellLocation = new Point(controlLocation.x, controlLocation.y - shellHeight);
+ }
+ shell.setLocation(shellLocation);
+
+ if (getChildren().length != 0)
+ shell.open();
+ if (!control.isDisposed())
+ control.setFocus();
+ }
+
+ public void hide() {
+ getShell().setVisible(false);
+ onHide();
+ }
+
+ public boolean isShellVisible() {
+ if (isDisposed())
+ return false;
+ return getShell().isVisible();
+ }
+
+ /** to be overridden */
+ protected void onHide() {
+ // does nothing by default.
+ }
+
+ private class AutoHideShellListener extends ShellAdapter {
+ private static final long serialVersionUID = 7743287433907938099L;
+
+ @Override
+ public void shellDeactivated(ShellEvent e) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e1) {
+ // silent
+ }
+ if (!control.isDisposed() && !control.isFocusControl())
+ hide();
+ }
+ }
+}
+++ /dev/null
-package org.argeo.cms.ui;
-
-import java.util.EventObject;
-
-/** Notify of the edition lifecycle */
-public class CmsEditionEvent extends EventObject {
- private static final long serialVersionUID = 950914736016693110L;
-
- public final static Integer START_EDITING = 0;
- public final static Integer STOP_EDITING = 1;
-
- private final Integer type;
-
- public CmsEditionEvent(Object source, Integer type) {
- super(source);
- this.type = type;
- }
-
- public Integer getType() {
- return type;
- }
-
-}
import javax.jcr.Node;
import javax.jcr.RepositoryException;
-import org.argeo.cms.ui.viewers.EditablePart;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import javax.jcr.RepositoryException;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.viewers.EditablePart;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.cms.ui.widgets.StyledControl;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.jface.dialogs.MessageDialog;
import javax.jcr.RepositoryException;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.viewers.EditablePart;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.cms.ui.widgets.StyledControl;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.swt.SWT;
import javax.jcr.RepositoryException;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.ui.viewers.EditablePart;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.cms.ui.widgets.EditableText;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.swt.widgets.Composite;
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.ui.viewers.AbstractPageViewer;
-import org.argeo.cms.ui.viewers.EditablePart;
import org.argeo.cms.ui.viewers.Section;
import org.argeo.cms.ui.viewers.SectionPart;
import org.argeo.cms.ui.widgets.EditableImage;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsEditable;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.cms.swt.widgets.ScrolledPage;
import org.argeo.jcr.JcrException;
import org.eclipse.jface.viewers.ContentViewer;
+++ /dev/null
-package org.argeo.cms.ui.viewers;
-
-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();
-}
package org.argeo.cms.ui.viewers;
-import java.util.Observable;
-
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.jcr.version.VersionManager;
-import org.argeo.api.cms.ux.CmsEditable;
-import org.argeo.cms.CmsException;
-import org.argeo.cms.ui.CmsEditionEvent;
+import org.argeo.api.cms.ux.CmsEditionEvent;
+import org.argeo.cms.ux.AbstractCmsEditable;
+import org.argeo.jcr.JcrException;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Listener;
/** Provides the CmsEditable semantic based on JCR versioning. */
-public class JcrVersionCmsEditable extends Observable implements CmsEditable {
+public class JcrVersionCmsEditable extends AbstractCmsEditable {
private final String nodePath;// cache
private final VersionManager versionManager;
private final Boolean canEdit;
public JcrVersionCmsEditable(Node node) throws RepositoryException {
this.nodePath = node.getPath();
- if (node.getSession().hasPermission(node.getPath(),
- Session.ACTION_SET_PROPERTY)) {
+ if (node.getSession().hasPermission(node.getPath(), Session.ACTION_SET_PROPERTY)) {
// was Session.ACTION_ADD_NODE
canEdit = true;
if (!node.isNodeType(NodeType.MIX_VERSIONABLE)) {
node.addMixin(NodeType.MIX_VERSIONABLE);
node.getSession().save();
}
- versionManager = node.getSession().getWorkspace()
- .getVersionManager();
+ versionManager = node.getSession().getWorkspace().getVersionManager();
} else {
canEdit = false;
versionManager = null;
// bind keys
if (canEdit) {
Display display = Display.getCurrent();
- display.setData(RWT.ACTIVE_KEYS, new String[] { "CTRL+RETURN",
- "CTRL+E" });
+ display.setData(RWT.ACTIVE_KEYS, new String[] { "CTRL+RETURN", "CTRL+E" });
display.addFilter(SWT.KeyDown, new Listener() {
private static final long serialVersionUID = -4378653870463187318L;
return false;
return versionManager.isCheckedOut(nodePath);
} catch (RepositoryException e) {
- throw new CmsException("Cannot check whether " + nodePath
- + " is editing", e);
+ throw new JcrException("Cannot check whether " + nodePath + " is editing", e);
}
}
public void startEditing() {
try {
versionManager.checkout(nodePath);
- setChanged();
+// setChanged();
} catch (RepositoryException e1) {
- throw new CmsException("Cannot publish " + nodePath);
+ throw new JcrException("Cannot publish " + nodePath, e1);
}
- notifyObservers(new CmsEditionEvent(nodePath,
- CmsEditionEvent.START_EDITING));
+ notifyListeners(new CmsEditionEvent(nodePath, CmsEditionEvent.START_EDITING, this));
}
@Override
public void stopEditing() {
try {
versionManager.checkin(nodePath);
- setChanged();
+// setChanged();
} catch (RepositoryException e1) {
- throw new CmsException("Cannot publish " + nodePath, e1);
+ throw new JcrException("Cannot publish " + nodePath, e1);
}
- notifyObservers(new CmsEditionEvent(nodePath,
- CmsEditionEvent.STOP_EDITING));
+ notifyListeners(new CmsEditionEvent(nodePath, CmsEditionEvent.STOP_EDITING, this));
}
+
}
import javax.jcr.RepositoryException;
import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.swt.EditablePart;
import org.argeo.cms.ui.widgets.JcrComposite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
package org.argeo.cms.ui.viewers;
+import org.argeo.cms.swt.EditablePart;
/** An editable part dynamically related to a Section */
public interface SectionPart extends EditablePart, NodePart {
+++ /dev/null
-package org.argeo.cms.ui.widgets;
-
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.widgets.ScrolledPage;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ShellAdapter;
-import org.eclipse.swt.events.ShellEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Shell;
-
-/**
- * Manages a lightweight shell which is related to a {@link Control}, typically
- * in order to reproduce a dropdown semantic, but with more flexibility.
- */
-public class ContextOverlay extends ScrolledPage {
- private static final long serialVersionUID = 6702077429573324009L;
-
-// private Shell shell;
- private Control control;
-
- private int maxHeight = 400;
-
- public ContextOverlay(Control control, int style) {
- super(createShell(control, style), SWT.NONE);
- Shell shell = getShell();
- setLayoutData(CmsSwtUtils.fillAll());
- // TODO make autohide configurable?
- //shell.addShellListener(new AutoHideShellListener());
- this.control = control;
- control.addDisposeListener((e) -> {
- dispose();
- shell.dispose();
- });
- }
-
- private static Composite createShell(Control control, int style) {
- if (control == null)
- throw new IllegalArgumentException("Control cannot be null");
- if (control.isDisposed())
- throw new IllegalArgumentException("Control is disposed");
- Shell shell = new Shell(control.getShell(), SWT.NO_TRIM);
- shell.setLayout(CmsSwtUtils.noSpaceGridLayout());
- Composite placeholder = new Composite(shell, SWT.BORDER);
- placeholder.setLayoutData(CmsSwtUtils.fillAll());
- placeholder.setLayout(CmsSwtUtils.noSpaceGridLayout());
- return placeholder;
- }
-
- public void show() {
- Point relativeControlLocation = control.getLocation();
- Point controlLocation = control.toDisplay(relativeControlLocation.x, relativeControlLocation.y);
-
- int controlWidth = control.getBounds().width;
-
- Shell shell = getShell();
-
- layout(true, true);
- shell.pack();
- shell.layout(true, true);
- int targetShellWidth = shell.getSize().x < controlWidth ? controlWidth : shell.getSize().x;
- if (shell.getSize().y > maxHeight) {
- shell.setSize(targetShellWidth, maxHeight);
- } else {
- shell.setSize(targetShellWidth, shell.getSize().y);
- }
-
- int shellHeight = shell.getSize().y;
- int controlHeight = control.getBounds().height;
- Point shellLocation = new Point(controlLocation.x, controlLocation.y + controlHeight);
- int displayHeight = shell.getDisplay().getBounds().height;
- if (shellLocation.y + shellHeight > displayHeight) {// bottom of page
- shellLocation = new Point(controlLocation.x, controlLocation.y - shellHeight);
- }
- shell.setLocation(shellLocation);
-
- if (getChildren().length != 0)
- shell.open();
- if (!control.isDisposed())
- control.setFocus();
- }
-
- public void hide() {
- getShell().setVisible(false);
- onHide();
- }
-
- public boolean isShellVisible() {
- if (isDisposed())
- return false;
- return getShell().isVisible();
- }
-
- /** to be overridden */
- protected void onHide() {
- // does nothing by default.
- }
-
- private class AutoHideShellListener extends ShellAdapter {
- private static final long serialVersionUID = 7743287433907938099L;
-
- @Override
- public void shellDeactivated(ShellEvent e) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e1) {
- // silent
- }
- if (!control.isDisposed() && !control.isFocusControl())
- hide();
- }
- }
-}
public interface CmsEditable {
/** Whether the calling thread can edit, the value is immutable */
- public Boolean canEdit();
+ Boolean canEdit();
- public Boolean isEditing();
+ Boolean isEditing();
- public void startEditing();
+ void startEditing();
- public void stopEditing();
+ void stopEditing();
- public static CmsEditable NON_EDITABLE = new CmsEditable() {
+ void addCmsEditionListener(CmsEditionListener listener);
+
+ void removeCmsEditionListener(CmsEditionListener listener);
+
+ static CmsEditable NON_EDITABLE = new CmsEditable() {
@Override
public void stopEditing() {
public Boolean canEdit() {
return false;
}
+
+ @Override
+ public void addCmsEditionListener(CmsEditionListener listener) {
+ }
+
+ @Override
+ public void removeCmsEditionListener(CmsEditionListener listener) {
+ }
+
};
- public static CmsEditable ALWAYS_EDITING = new CmsEditable() {
+ static CmsEditable ALWAYS_EDITING = new CmsEditable() {
@Override
public void stopEditing() {
public Boolean canEdit() {
return true;
}
+
+ @Override
+ public void addCmsEditionListener(CmsEditionListener listener) {
+ }
+
+ @Override
+ public void removeCmsEditionListener(CmsEditionListener listener) {
+ }
+
};
}
--- /dev/null
+package org.argeo.api.cms.ux;
+
+import java.util.EventObject;
+
+/** Notify of the edition lifecycle */
+public class CmsEditionEvent extends EventObject {
+ private static final long serialVersionUID = 950914736016693110L;
+
+ public final static Integer START_EDITING = 0;
+ public final static Integer STOP_EDITING = 1;
+
+ private final Integer type;
+ private final CmsEditable cmsEditable;
+
+ public CmsEditionEvent(Object source, Integer type, CmsEditable cmsEditable) {
+ super(source);
+ this.type = type;
+ this.cmsEditable = cmsEditable;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public CmsEditable getCmsEditable() {
+ return cmsEditable;
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.ux;
+
+public interface CmsEditionListener {
+ void editionStarted(CmsEditionEvent e);
+
+ void editionStopped(CmsEditionEvent e);
+}
--- /dev/null
+package org.argeo.cms.ux;
+
+import java.util.IdentityHashMap;
+
+import org.argeo.api.cms.ux.CmsEditable;
+import org.argeo.api.cms.ux.CmsEditionEvent;
+import org.argeo.api.cms.ux.CmsEditionListener;
+
+public abstract class AbstractCmsEditable implements CmsEditable {
+ private IdentityHashMap<CmsEditionListener, Object> listeners = new IdentityHashMap<>();
+
+ protected void notifyListeners(CmsEditionEvent e) {
+ if (CmsEditionEvent.START_EDITING == e.getType()) {
+ for (CmsEditionListener listener : listeners.keySet())
+ listener.editionStarted(e);
+ } else if (CmsEditionEvent.STOP_EDITING == e.getType()) {
+ for (CmsEditionListener listener : listeners.keySet())
+ listener.editionStopped(e);
+ } else {
+ throw new IllegalArgumentException("Unkown edition event type " + e.getType());
+ }
+ }
+
+ @Override
+ public void addCmsEditionListener(CmsEditionListener listener) {
+ listeners.put(listener, new Object());
+ }
+
+ @Override
+ public void removeCmsEditionListener(CmsEditionListener listener) {
+ listeners.remove(listener, new Object());
+ }
+
+}