+++ /dev/null
-package org.argeo.cms.ui.viewers;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Observable;
-import java.util.Observer;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.security.auth.Subject;
-
-import org.argeo.api.cms.CmsLog;
-import org.argeo.api.cms.ux.CmsEditable;
-import org.argeo.cms.swt.SwtEditablePart;
-import org.argeo.cms.swt.widgets.ScrolledPage;
-import org.argeo.jcr.JcrException;
-import org.eclipse.jface.viewers.ContentViewer;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.StructuredSelection;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
-import org.eclipse.swt.events.MouseAdapter;
-import org.eclipse.swt.events.MouseListener;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Widget;
-import org.xml.sax.SAXParseException;
-
-/** Base class for viewers related to a page */
-public abstract class AbstractPageViewer extends ContentViewer implements Observer {
- private static final long serialVersionUID = 5438688173410341485L;
-
- private final static CmsLog log = CmsLog.getLog(AbstractPageViewer.class);
-
- private final boolean readOnly;
- /** The basis for the layouts, typically a ScrolledPage. */
- private final Composite page;
- private final CmsEditable cmsEditable;
-
- private MouseListener mouseListener;
- private FocusListener focusListener;
-
- private SwtEditablePart edited;
- private ISelection selection = StructuredSelection.EMPTY;
-
- private AccessControlContext accessControlContext;
-
- protected AbstractPageViewer(Section parent, int style, CmsEditable cmsEditable) {
- // read only at UI level
- readOnly = SWT.READ_ONLY == (style & SWT.READ_ONLY);
-
- this.cmsEditable = cmsEditable == null ? CmsEditable.NON_EDITABLE : cmsEditable;
- if (this.cmsEditable instanceof Observable)
- ((Observable) this.cmsEditable).addObserver(this);
-
- if (cmsEditable.canEdit()) {
- mouseListener = createMouseListener();
- focusListener = createFocusListener();
- }
- page = findPage(parent);
- accessControlContext = AccessController.getContext();
- }
-
- /**
- * Can be called to simplify the called to isModelInitialized() and initModel()
- */
- protected void initModelIfNeeded(Node node) {
- try {
- if (!isModelInitialized(node))
- if (getCmsEditable().canEdit()) {
- initModel(node);
- node.getSession().save();
- }
- } catch (RepositoryException e) {
- throw new JcrException("Cannot initialize model", e);
- }
- }
-
- /** Called if user can edit and model is not initialized */
- protected Boolean isModelInitialized(Node node) throws RepositoryException {
- return true;
- }
-
- /** Called if user can edit and model is not initialized */
- protected void initModel(Node node) throws RepositoryException {
- }
-
- /** Create (retrieve) the MouseListener to use. */
- protected MouseListener createMouseListener() {
- return new MouseAdapter() {
- private static final long serialVersionUID = 1L;
- };
- }
-
- /** Create (retrieve) the FocusListener to use. */
- protected FocusListener createFocusListener() {
- return new FocusListener() {
- private static final long serialVersionUID = 1L;
-
- @Override
- public void focusLost(FocusEvent event) {
- }
-
- @Override
- public void focusGained(FocusEvent event) {
- }
- };
- }
-
- protected Composite findPage(Composite composite) {
- if (composite instanceof ScrolledPage) {
- return (ScrolledPage) composite;
- } else {
- if (composite.getParent() == null)
- return composite;
- return findPage(composite.getParent());
- }
- }
-
- public void layoutPage() {
- if (page != null)
- page.layout(true, true);
- }
-
- protected void showControl(Control control) {
- if (page != null && (page instanceof ScrolledPage))
- ((ScrolledPage) page).showControl(control);
- }
-
- @Override
- public void update(Observable o, Object arg) {
- if (o == cmsEditable)
- editingStateChanged(cmsEditable);
- }
-
- /** To be overridden in order to provide the actual refresh */
- protected void refresh(Control control) throws RepositoryException {
- }
-
- /** To be overridden.Save the edited part. */
- protected void save(SwtEditablePart part) throws RepositoryException {
- }
-
- /** Prepare the edited part */
- protected void prepare(SwtEditablePart part, Object caretPosition) {
- }
-
- /** Notified when the editing state changed. Does nothing, to be overridden */
- protected void editingStateChanged(CmsEditable cmsEditable) {
- }
-
- @Override
- public void refresh() {
- // TODO check actual context in order to notice a discrepancy
- Subject viewerSubject = getViewerSubject();
- Subject.doAs(viewerSubject, (PrivilegedAction<Void>) () -> {
- try {
- if (cmsEditable.canEdit() && !readOnly)
- mouseListener = createMouseListener();
- else
- mouseListener = null;
- refresh(getControl());
- // layout(getControl());
- if (!getControl().isDisposed())
- layoutPage();
- } catch (RepositoryException e) {
- throw new JcrException("Cannot refresh", e);
- }
- return null;
- });
- }
-
- @Override
- public void setSelection(ISelection selection, boolean reveal) {
- this.selection = selection;
- }
-
- protected void updateContent(SwtEditablePart part) throws RepositoryException {
- }
-
- // LOW LEVEL EDITION
- protected void edit(SwtEditablePart part, Object caretPosition) {
- try {
- if (edited == part)
- return;
-
- if (edited != null && edited != part) {
- SwtEditablePart previouslyEdited = edited;
- try {
- stopEditing(true);
- } catch (Exception e) {
- notifyEditionException(e);
- edit(previouslyEdited, caretPosition);
- return;
- }
- }
-
- part.startEditing();
- edited = part;
- updateContent(part);
- prepare(part, caretPosition);
- edited.getControl().addFocusListener(new FocusListener() {
- private static final long serialVersionUID = 6883521812717097017L;
-
- @Override
- public void focusLost(FocusEvent event) {
- stopEditing(true);
- }
-
- @Override
- public void focusGained(FocusEvent event) {
- }
- });
-
- layout(part.getControl());
- showControl(part.getControl());
- } catch (RepositoryException e) {
- throw new JcrException("Cannot edit " + part, e);
- }
- }
-
- protected void stopEditing(Boolean save) {
- if (edited instanceof Widget && ((Widget) edited).isDisposed()) {
- edited = null;
- return;
- }
-
- assert edited != null;
- if (edited == null) {
- if (log.isTraceEnabled())
- log.warn("Told to stop editing while not editing anything");
- return;
- }
-
- try {
- if (save)
- save(edited);
-
- edited.stopEditing();
- SwtEditablePart editablePart = edited;
- Control control = ((SwtEditablePart) edited).getControl();
- edited = null;
- // TODO make edited state management more robust
- updateContent(editablePart);
- layout(control);
- } catch (RepositoryException e) {
- throw new JcrException("Cannot stop editing", e);
- } finally {
- edited = null;
- }
- }
-
- // METHODS AVAILABLE TO EXTENDING CLASSES
- protected void saveEdit() {
- if (edited != null)
- stopEditing(true);
- }
-
- protected void cancelEdit() {
- if (edited != null)
- stopEditing(false);
- }
-
- /** Layout this controls from the related base page. */
- public void layout(Control... controls) {
- page.layout(controls);
- }
-
- /**
- * Find the first {@link SwtEditablePart} in the parents hierarchy of this control
- */
- protected SwtEditablePart findDataParent(Control parent) {
- if (parent instanceof SwtEditablePart) {
- return (SwtEditablePart) parent;
- }
- if (parent.getParent() != null)
- return findDataParent(parent.getParent());
- else
- throw new IllegalStateException("No data parent found");
- }
-
- // UTILITIES
- /** Check whether the edited part is in a proper state */
- protected void checkEdited() {
- if (edited == null || (edited instanceof Widget) && ((Widget) edited).isDisposed())
- throw new IllegalStateException("Edited should not be null or disposed at this stage");
- }
-
- /** Persist all changes. */
- protected void persistChanges(Session session) throws RepositoryException {
- session.save();
- session.refresh(false);
- // TODO notify that changes have been persisted
- }
-
- /** Convenience method using a Node in order to save the underlying session. */
- protected void persistChanges(Node anyNode) throws RepositoryException {
- persistChanges(anyNode.getSession());
- }
-
- /** Notify edition exception */
- protected void notifyEditionException(Throwable e) {
- Throwable eToLog = e;
- if (e instanceof IllegalArgumentException)
- if (e.getCause() instanceof SAXParseException)
- eToLog = e.getCause();
- log.error(eToLog.getMessage(), eToLog);
-// if (log.isTraceEnabled())
-// log.trace("Full stack of " + eToLog.getMessage(), e);
- // TODO Light error notification popup
- }
-
- protected Subject getViewerSubject() {
- Subject res = null;
- if (accessControlContext != null) {
- res = Subject.getSubject(accessControlContext);
- }
- if (res == null)
- throw new IllegalStateException("No subject associated with this viewer");
- return res;
- }
-
- // GETTERS / SETTERS
- public boolean isReadOnly() {
- return readOnly;
- }
-
- protected SwtEditablePart getEdited() {
- return edited;
- }
-
- public MouseListener getMouseListener() {
- return mouseListener;
- }
-
- public FocusListener getFocusListener() {
- return focusListener;
- }
-
- public CmsEditable getCmsEditable() {
- return cmsEditable;
- }
-
- @Override
- public ISelection getSelection() {
- return selection;
- }
-}
\ No newline at end of file