From 60e8274d08b93c5dbb46a2fc2a4f8b1a0d18c0ed Mon Sep 17 00:00:00 2001 From: Bruno Sinou Date: Thu, 26 Mar 2015 14:31:40 +0000 Subject: [PATCH] + Refactor Users Page + and a constant and an utils method to set RWT specific item height parameter on table with RWT custom variant set. git-svn-id: https://svn.argeo.org/commons/trunk@8040 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../src/org/argeo/cms/CmsApplication.java | 16 +- .../src/org/argeo/cms/CmsConstants.java | 1 + .../org/argeo/cms/users/UserViewerOld.java | 233 ------------------ .../cms/users/{Users.java => UsersPage.java} | 132 +++------- .../src/org/argeo/cms/util/CmsUtils.java | 5 + .../org/argeo/eclipse/ui/EclipseUiUtils.java | 36 +++ .../argeo/eclipse/ui/parts/UsersTable.java | 40 ++- 7 files changed, 99 insertions(+), 364 deletions(-) delete mode 100644 org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java rename org.argeo.cms/src/org/argeo/cms/users/{Users.java => UsersPage.java} (69%) diff --git a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java index f722befeb..d6341e5b3 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsApplication.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsApplication.java @@ -148,12 +148,12 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, } public void init() throws RepositoryException { -// if (workspace == null) -// throw new CmsException( -// "Workspace must be set when calling initialization." -// + " Please make sure that read-only and read-write roles" -// + " have been properly configured:" -// + " the defaults are open."); + // if (workspace == null) + // throw new CmsException( + // "Workspace must be set when calling initialization." + // + " Please make sure that read-only and read-write roles" + // + " have been properly configured:" + // + " the defaults are open."); Session session = null; try { @@ -318,7 +318,9 @@ public class CmsApplication implements CmsConstants, ApplicationConfiguration, bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY); bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT); + // Should not be set here: it then prevent all children + // composite to define a background color via CSS + // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT); bodyArea.setLayout(CmsUtils.noSpaceGridLayout()); refreshBody(); } catch (Exception e) { diff --git a/org.argeo.cms/src/org/argeo/cms/CmsConstants.java b/org.argeo.cms/src/org/argeo/cms/CmsConstants.java index cae0167c8..df8c02fb8 100644 --- a/org.argeo.cms/src/org/argeo/cms/CmsConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/CmsConstants.java @@ -8,6 +8,7 @@ public interface CmsConstants { // DATAKEYS public final static String STYLE = RWT.CUSTOM_VARIANT; public final static String MARKUP = RWT.MARKUP_ENABLED; + public final static String ITEM_HEIGHT = RWT.CUSTOM_ITEM_HEIGHT; // STANDARD RESOURCES public final static String LOADING_IMAGE = "icons/loading.gif"; diff --git a/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java b/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java deleted file mode 100644 index 6b522f5d9..000000000 --- a/org.argeo.cms/src/org/argeo/cms/users/UserViewerOld.java +++ /dev/null @@ -1,233 +0,0 @@ -package org.argeo.cms.users; - -import java.util.Observable; -import java.util.Observer; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.ArgeoException; -import org.argeo.cms.CmsEditable; -import org.argeo.cms.CmsException; -import org.argeo.cms.util.CmsUtils; -import org.argeo.cms.viewers.EditablePart; -import org.argeo.cms.viewers.JcrVersionCmsEditable; -import org.eclipse.jface.viewers.ContentViewer; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.StructuredSelection; -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; - -/** Manage edition of the users */ -public class UserViewerOld extends ContentViewer implements Observer { - private static final long serialVersionUID = -5055220955004863645L; - - private final static Log log = LogFactory.getLog(UserViewerOld.class); - - // private UserPart userPart = new UserPart(); - - private CmsEditable cmsEditable; - private Node currentDisplayed; - - /** The basis for the layouts, typically the body of a ScrolledPage. */ - private final Composite page; - - private MouseListener mouseListener; - - private EditablePart edited; - private ISelection selection = StructuredSelection.EMPTY; - - protected UserViewerOld(Composite composite) { - page = composite; - } - - void setDisplayedUser(Node node) { - try { - - if (!hasChanged(node)) - return; - - CmsUtils.clear(page); - // userPart.createUi(page, node); - - page.layout(); - page.getParent().layout(); - - // update - cmsEditable = new JcrVersionCmsEditable(node); - - if (this.cmsEditable instanceof Observable) - ((Observable) this.cmsEditable).addObserver(this); - // // if (cmsEditable.canEdit()) { - // // mouseListener = createMouseListener(); - // // refresh(); - // // } - } catch (RepositoryException re) { - throw new ArgeoException("Unable to display " + node, re); - } - } - - private boolean hasChanged(Node node) throws RepositoryException { - if (currentDisplayed == null && node == null) - return false; - else if (currentDisplayed == null || node == null) - return true; - else - return node.getIdentifier() - .equals(currentDisplayed.getIdentifier()); - } - - /** Create (retrieve) the MouseListener to use. */ - protected MouseListener createMouseListener() { - return new MouseAdapter() { - private static final long serialVersionUID = 1L; - }; - } - - @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(EditablePart part) throws RepositoryException { - } - - /** Prepare the edited part */ - protected void prepare(EditablePart part, Object caretPosition) { - } - - /** Notified when the editing state changed. Does nothing, to be overridden */ - protected void editingStateChanged(CmsEditable cmsEditable) { - } - - @Override - public Control getControl() { - return null; - } - - @Override - public void refresh() { - try { - // if (cmsEditable.canEdit() && !readOnly) - // mouseListener = createMouseListener(); - // else - // mouseListener = null; - refresh(getControl()); - layout(getControl()); - } catch (RepositoryException e) { - throw new CmsException("Cannot refresh", e); - } - } - - @Override - public void setSelection(ISelection selection, boolean reveal) { - this.selection = selection; - } - - protected void updateContent(EditablePart part) throws RepositoryException { - } - - // LOW LEVEL EDITION - protected void edit(EditablePart part, Object caretPosition) { - try { - if (edited == part) - return; - - if (edited != null && edited != part) - stopEditing(true); - - part.startEditing(); - updateContent(part); - prepare(part, caretPosition); - edited = part; - layout(part.getControl()); - } catch (RepositoryException e) { - throw new CmsException("Cannot edit " + part, e); - } - } - - private void stopEditing(Boolean save) throws RepositoryException { - 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; - } - - if (save) - save(edited); - - edited.stopEditing(); - updateContent(edited); - layout(((EditablePart) edited).getControl()); - edited = null; - } - - // METHODS AVAILABLE TO EXTENDING CLASSES - protected void saveEdit() { - try { - if (edited != null) - stopEditing(true); - } catch (RepositoryException e) { - throw new CmsException("Cannot stop editing", e); - } - } - - protected void cancelEdit() { - try { - if (edited != null) - stopEditing(false); - } catch (RepositoryException e) { - - throw new CmsException("Cannot cancel editing", e); - } - } - - /** Layout this controls from the related base page. */ - public void layout(Control... controls) { - page.layout(controls); - } - - // 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 CmsException( - "Edited should not be null or disposed at this stage"); - } - - // GETTERS / SETTERS - protected EditablePart getEdited() { - return edited; - } - - public MouseListener getMouseListener() { - return mouseListener; - } - - public CmsEditable getCmsEditable() { - return cmsEditable; - } - - @Override - public ISelection getSelection() { - return selection; - } -} \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/users/Users.java b/org.argeo.cms/src/org/argeo/cms/users/UsersPage.java similarity index 69% rename from org.argeo.cms/src/org/argeo/cms/users/Users.java rename to org.argeo.cms/src/org/argeo/cms/users/UsersPage.java index 2637ed4d9..d5bfeb7cd 100644 --- a/org.argeo.cms/src/org/argeo/cms/users/Users.java +++ b/org.argeo.cms/src/org/argeo/cms/users/UsersPage.java @@ -7,8 +7,6 @@ import java.util.TreeMap; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.security.AccessControlManager; -import javax.jcr.security.Privilege; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -38,29 +36,32 @@ 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.springframework.security.provisioning.UserDetailsManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; /** - * Simple page to manage users of a given repository. We still rely on Argeo - * model; with user stored in the main workspace + * Simple page to manage users of a given repository. It relies on Argeo user + * model: user profile nodes are stored in the main workspace */ -public class Users implements CmsUiProvider { +public class UsersPage implements CmsUiProvider { + private final static Log log = LogFactory.getLog(UsersPage.class); - private final static Log log = LogFactory.getLog(Users.class); - - // Enable user CRUD // INJECTED + /* DEPENDENCY INJECTION */ private UserAdminService userAdminService; - // private UserDetailsManager userDetailsManager; private String userWkspName; + // TODO use a constant + private final static String ROLE_USER_ADMIN = "ROLE_USER_ADMIN"; + // Local UI Providers - NonAdminPage nap = new NonAdminPage(); - UserPage userPage = new UserPage(); + private NonAdminPage nap = new NonAdminPage(); + private UserPage userPage = new UserPage(); - // Manage authorization @Override public Control createUi(Composite parent, Node context) throws RepositoryException { + // This page is only visible to user with role USER_ADMIN if (isAdmin(context)) { Session session = context.getSession().getRepository() .login(userWkspName); @@ -86,8 +87,6 @@ public class Users implements CmsUiProvider { final Composite right = new Composite(layoutCmp, SWT.NO_FOCUS); right.setLayoutData(CmsUtils.fillAll()); - // Composite innerPage = createUserPage(right); - // final UserViewerOld userViewer = new UserViewerOld(innerPage); final TableViewer viewer = table.getTableViewer(); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @@ -98,6 +97,8 @@ public class Users implements CmsUiProvider { .getSelection(); if (selection.isEmpty()) { // Should we clean the right column? + CmsUtils.clear(right); + right.layout(); return; } else { Node context = (Node) selection.getFirstElement(); @@ -136,7 +137,7 @@ public class Users implements CmsUiProvider { addBtn.setText("Create"); // Create the composite that displays the list and a filter - final UsersTable userTableCmp = new UsersTable(parent, SWT.NO_FOCUS, + final UsersTable userTableCmp = new UsersTable(parent, SWT.BORDER, session); userTableCmp.populate(true, false); userTableCmp.setLayoutData(CmsUtils.fillAll()); @@ -243,89 +244,23 @@ public class Users implements CmsUiProvider { return userTableCmp; } - // protected Composite createUserPage(Composite parent) { - // parent.setLayout(CmsUtils.noSpaceGridLayout()); - // ScrolledPage scrolled = new ScrolledPage(parent, SWT.NONE); - // scrolled.setLayoutData(CmsUtils.fillAll()); - // scrolled.setLayout(CmsUtils.noSpaceGridLayout()); - // // TODO manage style - // // CmsUtils.style(scrolled, "maintenance_user_form"); - // - // Composite page = new Composite(scrolled, SWT.NONE); - // page.setLayout(CmsUtils.noSpaceGridLayout()); - // page.setBackgroundMode(SWT.INHERIT_NONE); - // - // return page; - // } - private boolean isAdmin(Node node) throws RepositoryException { - // FIXME clean this once new user management policy has been - // implemented. - AccessControlManager acm = node.getSession().getAccessControlManager(); - Privilege[] privs = new Privilege[1]; - privs[0] = acm.privilegeFromName(Privilege.JCR_ALL); - return acm.hasPrivileges("/", privs); + return isUserInRole(ROLE_USER_ADMIN); } - // @Override - // public void dispose() { - // JcrUtils.removeListenerQuietly(session, userStructureListener); - // JcrUtils.removeListenerQuietly(session, userPropertiesListener); - // JcrUtils.logoutQuietly(session); - // super.dispose(); - // } - // - // // public void setSession(Session session) { - // // this.session = session; - // // } - // - // public void refresh() { - // this.getSite().getShell().getDisplay().asyncExec(new Runnable() { - // @Override - // public void run() { - // userTableCmp.refresh(); - // } - // }); - // } - // - // private class JcrUserListener implements EventListener { - // private final Display display; - // - // public JcrUserListener(Display display) { - // super(); - // this.display = display; - // } - // - // @Override - // public void onEvent(EventIterator events) { - // display.asyncExec(new Runnable() { - // @Override - // public void run() { - // userTableCmp.refresh(); - // } - // }); - // } - // } - // - // class ViewDoubleClickListener implements IDoubleClickListener { - // public void doubleClick(DoubleClickEvent evt) { - // if (evt.getSelection().isEmpty()) - // return; - // - // Object obj = ((IStructuredSelection) evt.getSelection()) - // .getFirstElement(); - // if (obj instanceof Node) { - // try { - // String username = ((Node) obj).getProperty(ARGEO_USER_ID) - // .getString(); - // String commandId = OpenArgeoUserEditor.COMMAND_ID; - // String paramName = OpenArgeoUserEditor.PARAM_USERNAME; - // CommandUtils.callCommand(commandId, paramName, username); - // } catch (RepositoryException e) { - // throw new ArgeoException("Cannot open user editor", e); - // } - // } - // } + /** + * Returns true if the current user is in the specified role TODO factoize + * in the user admin service + */ + private boolean isUserInRole(String role) { + Authentication authen = SecurityContextHolder.getContext() + .getAuthentication(); + for (GrantedAuthority ga : authen.getAuthorities()) { + if (ga.getAuthority().equals(role)) + return true; + } + return false; + } /* DEPENDENCY INJECTION */ public void setWorkspaceName(String workspaceName) { @@ -336,9 +271,4 @@ public class Users implements CmsUiProvider { this.userAdminService = userAdminService; userPage.setUserAdminService(userAdminService); } - - public void setUserDetailsManager(UserDetailsManager userDetailsManager) { - // this.userDetailsManager = userDetailsManager; - // userPage.setUserDetailsManager(userDetailsManager); - } } \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java index c1b319fbe..5d31e2c51 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java @@ -23,6 +23,7 @@ import org.eclipse.swt.layout.RowData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Widget; /** Static utilities for the CMS framework. */ @@ -72,6 +73,10 @@ public class CmsUtils implements CmsConstants { widget.setData(CmsConstants.MARKUP, true); } + public static void setItemHeight(Table table, int height) { + table.setData(CmsConstants.ITEM_HEIGHT, height); + } + /** @return the path or null if not instrumented */ public static String getDataPath(Widget widget) { // JCR item diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java index 3455577ce..06f569dce 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/EclipseUiUtils.java @@ -20,12 +20,48 @@ import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; /** Utilities to simplify UI development. */ public class EclipseUiUtils { + + + // + // Simplify grid layouts management + // + public static GridLayout noSpaceGridLayout() { + return noSpaceGridLayout(new GridLayout()); + } + + public static GridLayout noSpaceGridLayout(GridLayout layout) { + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.marginWidth = 0; + layout.marginHeight = 0; + return layout; + } + + public static GridData fillWidth() { + return grabWidth(SWT.FILL, SWT.FILL); + } + + public static GridData fillAll() { + return new GridData(SWT.FILL, SWT.FILL, true, true); + } + + public static GridData grabWidth(int horizontalAlignment, + int verticalAlignment) { + return new GridData(horizontalAlignment, horizontalAlignment, true, + false); + } + + + + + /** * Create a label and a text field for a grid layout, the text field grabbing * excess horizontal diff --git a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java index 0a7b8d1e0..41afb6a3a 100644 --- a/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java +++ b/org.argeo.eclipse.ui/src/org/argeo/eclipse/ui/parts/UsersTable.java @@ -52,23 +52,21 @@ public class UsersTable extends Composite implements ArgeoNames { private static final long serialVersionUID = -7385959046279360420L; + private Session session; + + private boolean hasFilter; + private boolean hasSelectionColumn; + private int tableStyle; + private TableViewer usersViewer; private Text filterTxt; - private final static String FILTER_HELP_MSG = "Type filter criterion " + private String filterHelpMsg = "Type filter criterion " + "separated by a space"; - private Session session; private Font italic; private Font bold; - private boolean hasFilter; - private boolean hasSelectionColumn; - - // private List selectedItems = new ArrayList(); - - /** - * Overwrite to display other columns - */ + /** Overwrite to display other columns */ public List getColumnsDef() { List columnDefs = new ArrayList(); @@ -91,7 +89,8 @@ public class UsersTable extends Composite implements ArgeoNames { } public UsersTable(Composite parent, int style, Session session) { - super(parent, style); + super(parent, SWT.NO_FOCUS); + this.tableStyle = style; this.session = session; } @@ -112,7 +111,9 @@ public class UsersTable extends Composite implements ArgeoNames { hasSelectionColumn = addSelection; // Main Layout - this.setLayout(new GridLayout(1, false)); + GridLayout layout = EclipseUiUtils.noSpaceGridLayout(); + layout.verticalSpacing = 5; + this.setLayout(layout); if (hasFilter) createFilterPart(parent); usersViewer = createTableViewer(parent); @@ -140,16 +141,14 @@ public class UsersTable extends Composite implements ArgeoNames { public TableViewer getTableViewer() { return usersViewer; } - - /** Returns filter String or null*/ + + /** Returns filter String or null */ protected String getFilterString() { return hasFilter ? filterTxt.getText() : null; } - - private TableViewer createTableViewer(final Composite parent) { - int style = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL; + int style = tableStyle | SWT.H_SCROLL | SWT.V_SCROLL; if (hasSelectionColumn) style = style | SWT.CHECK; @@ -164,9 +163,6 @@ public class UsersTable extends Composite implements ArgeoNames { table.setLinesVisible(true); table.setHeaderVisible(true); - // pass a mapping between col index and property name to the comparator. - // List propertiesList = new ArrayList(); - TableViewerColumn column; int offset = 0; if (hasSelectionColumn) { @@ -239,11 +235,9 @@ public class UsersTable extends Composite implements ArgeoNames { String username = getProperty(elem, ARGEO_USER_ID); if (username.equals(session.getUserID())) return bold; - // disabled try { Node userProfile = (Node) elem; - // Node userProfile = userHome.getNode(ARGEO_PROFILE); if (!userProfile.getProperty(ARGEO_ENABLED).getBoolean()) return italic; else @@ -298,7 +292,7 @@ public class UsersTable extends Composite implements ArgeoNames { // Text Area for the filter filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL); - filterTxt.setMessage(FILTER_HELP_MSG); + filterTxt.setMessage(filterHelpMsg); filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL)); filterTxt.addModifyListener(new ModifyListener() { -- 2.30.2