package org.nightlabs.jfire.entityuserset.ui; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import javax.jdo.JDOHelper; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.action.Action; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.forms.editor.IFormPage; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.editor.ToolBarSectionPart; import org.nightlabs.base.ui.resource.SharedImages; import org.nightlabs.base.ui.table.AbstractTableComposite; import org.nightlabs.jfire.base.admin.ui.editor.authority.AuthorizedObjectTableViewer; import org.nightlabs.jfire.entityuserset.ui.resource.Messages; import org.nightlabs.jfire.security.AuthorizedObject; import org.nightlabs.jfire.security.User; import org.nightlabs.jfire.security.UserLocal; import org.nightlabs.jfire.security.id.AuthorizedObjectID; /** * @author Daniel Mazurek - Daniel.Mazurek [dot] nightlabs [dot] de * */ public class AuthorizedObjectSection<Entity> extends ToolBarSectionPart implements ISelectionProvider { class SelectAllAction extends Action { public SelectAllAction() { super(); setText(Messages.getString("org.nightlabs.jfire.entityuserset.ui.AuthorizedObjectSection.action.selectAll.text")); //$NON-NLS-1$ setToolTipText(Messages.getString("org.nightlabs.jfire.entityuserset.ui.AuthorizedObjectSection.action.selectAll.tooltip")); //$NON-NLS-1$ setImageDescriptor(SharedImages.getSharedImageDescriptor(Activator.getDefault(), SelectAllAction.class)); } @Override public void run() { for (Map.Entry<AuthorizedObject, Boolean> entry : authorizedObjects) { entry.setValue(true); } authorizedObjectTable.setInput(authorizedObjects); markDirty(); } } class DeselectAllAction extends Action { public DeselectAllAction() { super(); setText(Messages.getString("org.nightlabs.jfire.entityuserset.ui.AuthorizedObjectSection.action.deselectAll.text")); //$NON-NLS-1$ setToolTipText(Messages.getString("org.nightlabs.jfire.entityuserset.ui.AuthorizedObjectSection.action.deselectAll.tooltip")); //$NON-NLS-1$ setImageDescriptor(SharedImages.getSharedImageDescriptor(Activator.getDefault(), DeselectAllAction.class)); } @Override public void run() { for (Map.Entry<AuthorizedObject, Boolean> entry : authorizedObjects) { entry.setValue(false); } authorizedObjectTable.setInput(authorizedObjects); markDirty(); } } private AuthorizedObjectTableViewer authorizedObjectTable; private List<Map.Entry<AuthorizedObject, Boolean>> authorizedObjects = new ArrayList<Map.Entry<AuthorizedObject,Boolean>>(); private EntityUserSetPageControllerHelper<Entity> entityUserSetPageControllerHelper; private ListenerList selectionChangedListeners = new ListenerList(); private List<AuthorizedObject> selectedAuthorizedObjects = null; private IStructuredSelection selection = null; /** * @param page * @param parent */ public AuthorizedObjectSection(IFormPage page, Composite parent) { super(page, parent, ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED, Messages.getString("org.nightlabs.jfire.entityuserset.ui.AuthorizedObjectSection.title")); //$NON-NLS-1$ authorizedObjectTable = new AuthorizedObjectTableViewer(getContainer(), this, AbstractTableComposite.DEFAULT_STYLE_SINGLE | XComposite.getBorderStyle(getContainer())); authorizedObjectTable.setInput(authorizedObjects); authorizedObjectTable.getTable().addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent event) { setEntityUserSetPageControllerHelper(null); } }); authorizedObjectTable.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { selectedAuthorizedObjects = null; selection = null; fireSelectionChangedEvent(); } }); getToolBarManager().add(new SelectAllAction()); getToolBarManager().add(new DeselectAllAction()); updateToolBarManager(); } public EntityUserSetPageControllerHelper<Entity> getEntityUserSetPageControllerHelper() { return entityUserSetPageControllerHelper; } /** * Set the {@link EntityUserSetPageControllerHelper} that is used for the current editor page. It is possible to * pass <code>null</code> in order to indicate that there is nothing to be managed right now (and thus to clear * the UI). * * @param entityUserSetPageControllerHelper an instance of <code>EntityUserSetPageControllerHelper</code> or <code>null</code>. */ public synchronized void setEntityUserSetPageControllerHelper(EntityUserSetPageControllerHelper<Entity> entityUserSetPageControllerHelper) { if (this.entityUserSetPageControllerHelper != null) { this.entityUserSetPageControllerHelper.removePropertyChangeListener( EntityUserSetPageControllerHelper.PROPERTY_NAME_ENTITY_USER_SET_LOADED, propertyChangeListenerEntityUserSetLoaded ); } this.entityUserSetPageControllerHelper = entityUserSetPageControllerHelper; getSection().getDisplay().asyncExec(new Runnable() { public void run() { entityUserSetChanged(); } }); if (this.entityUserSetPageControllerHelper != null) { this.entityUserSetPageControllerHelper.addPropertyChangeListener( EntityUserSetPageControllerHelper.PROPERTY_NAME_ENTITY_USER_SET_LOADED, propertyChangeListenerEntityUserSetLoaded ); } } private PropertyChangeListener propertyChangeListenerEntityUserSetLoaded = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { getSection().getDisplay().asyncExec(new Runnable() { public void run() { entityUserSetChanged(); } }); } }; private void entityUserSetChanged() { authorizedObjects.clear(); if (entityUserSetPageControllerHelper != null) { for (Map.Entry<AuthorizedObject, Boolean> entry : entityUserSetPageControllerHelper.getAuthorizedObjects().entrySet()) { AuthorizedObject authorizedObject = entry.getKey(); if (authorizedObject instanceof UserLocal) { UserLocal userLocal = (UserLocal) authorizedObject; if (User.USER_ID_OTHER.equals(userLocal.getUserID()) || User.USER_ID_SYSTEM.equals(userLocal.getUserID())) { continue; } } authorizedObjects.add(entry); } } if (!authorizedObjectTable.getTable().isDisposed()) authorizedObjectTable.refresh(); } protected void fireSelectionChangedEvent() { SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); for (Object listener : selectionChangedListeners.getListeners()) ((ISelectionChangedListener)listener).selectionChanged(event); } @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { selectionChangedListeners.add(listener); } @Override public void removeSelectionChangedListener(ISelectionChangedListener listener) { selectionChangedListeners.remove(listener); } /** * Get the selected authorizedObjects. This method provides a more specific API than the general (and not typed) * {@link #getSelection()}, but the returned instances of {@link AuthorizedObject} are the same. * * @return the selected authorizedObjects. */ public List<AuthorizedObject> getSelectedAuthorizedObjects() { getSelection(); // ensure the existence of our data and that we are on the correct thread return selectedAuthorizedObjects; } /** * Get an {@link IStructuredSelection} containing {@link AuthorizedObject} instances. The instances are the same as * returned by {@link #getSelectedAuthorizedObjects()}. * * {@inheritDoc} */ @SuppressWarnings("unchecked") //$NON-NLS-1$ @Override public ISelection getSelection() { if (Display.getCurrent() == null) throw new IllegalStateException("Wrong thread! This method must be called on the SWT UI thread!"); //$NON-NLS-1$ if (selectedAuthorizedObjects == null || selection == null) { selectedAuthorizedObjects = new ArrayList<AuthorizedObject>(); selection = null; IStructuredSelection sel = (IStructuredSelection) authorizedObjectTable.getSelection(); for (Object object : sel.toArray()) { Map.Entry<AuthorizedObject, Boolean> me = (Entry<AuthorizedObject, Boolean>) object; selectedAuthorizedObjects.add(me.getKey()); } selection = new StructuredSelection(selectedAuthorizedObjects); } return selection; } /** * Set an {@link IStructuredSelection} containing {@link AuthorizedObject} or {@link AuthorizedObjectID} instances. */ @Override public void setSelection(ISelection selection) { if (!(selection instanceof IStructuredSelection)) throw new IllegalArgumentException("selection must be an instance of IStructuredSelection!"); //$NON-NLS-1$ if (Display.getCurrent() == null) throw new IllegalStateException("Wrong thread! This method must be called on the SWT UI thread!"); //$NON-NLS-1$ IStructuredSelection sel = (IStructuredSelection) selection; Set<AuthorizedObjectID> selectedAuthorizedObjectIDs = new HashSet<AuthorizedObjectID>(sel.size()); for (Object object : sel.toArray()) { if (object instanceof AuthorizedObjectID) selectedAuthorizedObjectIDs.add((AuthorizedObjectID) object); else if (object instanceof AuthorizedObject) { AuthorizedObjectID authorizedObjectID = (AuthorizedObjectID) JDOHelper.getObjectId(object); if (authorizedObjectID == null) throw new IllegalArgumentException("The selection contains a AuthorizedObject that has no AuthorizedObjectID assigned!"); // should never happen, since all the authorizedObjects we manage are already persisted and detached. //$NON-NLS-1$ selectedAuthorizedObjectIDs.add(authorizedObjectID); } else throw new IllegalArgumentException("The selection contains an object that's neither an instance of AuthorizedObjectID nor an instance of AuthorizedObject! The object is: " + object); //$NON-NLS-1$ } // now that we have all AuthorizedObjectIDs that should be selected in our set, we iterate the authorizedObjects that are in our authorizedObjectTable and collect the elements that should be selected List<Map.Entry<AuthorizedObject, Boolean>> elementsToBeSelected = new ArrayList<Entry<AuthorizedObject,Boolean>>(selectedAuthorizedObjectIDs.size()); for (Map.Entry<AuthorizedObject, Boolean> me : authorizedObjects) { if (selectedAuthorizedObjectIDs.contains(JDOHelper.getObjectId(me.getKey()))) elementsToBeSelected.add(me); } authorizedObjectTable.setSelection(new StructuredSelection(elementsToBeSelected)); } }