org.rssowl.ui.internal.dialogs.ManageSetsDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.rssowl.ui.internal.dialogs.ManageSetsDialog.java

Source

/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2005-2009 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License v1.0 which accompanies this    **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl Development Team - initial API and implementation             **
 **                                                                          **
 **  **********************************************************************  */

package org.rssowl.ui.internal.dialogs;

import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
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;
import org.eclipse.swt.widgets.Table;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IFolderChild;
import org.rssowl.core.persist.IMark;
import org.rssowl.core.persist.INewsBin;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.IFolderDAO;
import org.rssowl.core.persist.event.FolderAdapter;
import org.rssowl.core.persist.event.FolderEvent;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.LoggingSafeRunnable;
import org.rssowl.core.util.ReparentInfo;
import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.actions.DeleteTypesAction;
import org.rssowl.ui.internal.actions.EntityPropertyDialogAction;
import org.rssowl.ui.internal.actions.NewFolderAction;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.LayoutUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * The <code>ManageSetsDialog</code> allows to manage bookmark-sets. These are
 * root-leveld Folders containing other Folders and Marks.
 *
 * @author bpasero
 */
public class ManageSetsDialog extends TitleAreaDialog {

    /* Keep the visible instance saved */
    private static ManageSetsDialog fgVisibleInstance;

    private LocalResourceManager fResources;
    private TableViewer fViewer;
    private Label fStatusLabel;
    private Button fEditButton;
    private Button fDeleteButton;
    private IFolder fSelectedSet;
    private FolderAdapter fFolderListener;

    /**
     * @param parentShell
     * @param selectedSet
     */
    public ManageSetsDialog(Shell parentShell, IFolder selectedSet) {
        super(parentShell);
        fSelectedSet = selectedSet;
        fResources = new LocalResourceManager(JFaceResources.getResources());
    }

    /**
     * @return Returns an instance of <code>ManageSetsDialog</code> or
     * <code>NULL</code> in case no instance is currently open.
     */
    public static ManageSetsDialog getVisibleInstance() {
        return fgVisibleInstance;
    }

    /*
     * @see org.eclipse.jface.window.Window#open()
     */
    @Override
    public int open() {
        fgVisibleInstance = this;
        registerListeners();
        return super.open();
    }

    private void registerListeners() {
        fFolderListener = new FolderAdapter() {
            @Override
            public void entitiesAdded(final Set<FolderEvent> events) {
                JobRunner.runInUIThread(fViewer.getControl(), new Runnable() {
                    public void run() {
                        for (FolderEvent folderEvent : events) {
                            IFolder folder = folderEvent.getEntity();
                            if (folder.getParent() == null) {
                                fViewer.add(folder);
                                fViewer.setSelection(new StructuredSelection(folder));
                            }
                        }
                    }
                });
            }
        };

        DynamicDAO.addEntityListener(IFolder.class, fFolderListener);
    }

    /*
     * @see org.eclipse.jface.dialogs.TitleAreaDialog#close()
     */
    @Override
    public boolean close() {
        unregisterListeners();
        fgVisibleInstance = null;
        fResources.dispose();
        return super.close();
    }

    private void unregisterListeners() {
        DynamicDAO.removeEntityListener(IFolder.class, fFolderListener);
    }

    /*
     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
     */
    @Override
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(Messages.ManageSetsDialog_MANAGE_SETS);
    }

    /*
     * @see org.eclipse.jface.dialogs.TitleAreaDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createDialogArea(Composite parent) {

        /* Title */
        setTitle(Messages.ManageSetsDialog_SETS);

        /* Title Image */
        setTitleImage(OwlUI.getImage(fResources, "icons/wizban/bkmrk_set_title.gif")); //$NON-NLS-1$

        /* Title Message */
        showInfo();

        /* Separator */
        new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL)
                .setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        /* Composite to hold all components */
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayout(LayoutUtils.createGridLayout(2, 5, 10));
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

        /* TableViewer to display Bookmark Sets */
        fViewer = new TableViewer(composite, SWT.BORDER);
        fViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        ((GridData) fViewer.getTable().getLayoutData()).heightHint = fViewer.getTable().getItemHeight() * 7;
        fViewer.getTable().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object());

        /* Drag and Drop */
        initDragAndDrop();

        /* ContentProvider returns Root-Folders */
        fViewer.setContentProvider(new IStructuredContentProvider() {
            public Object[] getElements(Object inputElement) {
                return CoreUtils.loadRootFolders().toArray();
            }

            public void dispose() {
            }

            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            }
        });

        /* Simple LabelProvider */
        fViewer.setLabelProvider(new LabelProvider() {

            @Override
            public String getText(Object element) {
                return ((IFolder) element).getName();
            }

            @Override
            public Image getImage(Object element) {
                return OwlUI.getImage(fResources, OwlUI.BOOKMARK_SET);
            }
        });

        /* Sort by ID to show latest Set at bottom */
        fViewer.setComparator(new ViewerComparator() {
            @Override
            public int compare(Viewer viewer, Object e1, Object e2) {
                IFolder folder1 = (IFolder) e1;
                IFolder folder2 = (IFolder) e2;

                return folder1.getId().compareTo(folder2.getId());
            }
        });

        /* Edit on Doubleclick */
        fViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                onEdit();
            }
        });

        /* Set input (ignored by ContentProvider anyways) */
        fViewer.setInput(this);

        /* Container for the Buttons to Manage Sets */
        Composite buttonContainer = new Composite(composite, SWT.None);
        buttonContainer.setLayout(LayoutUtils.createGridLayout(1, 0, 0));
        buttonContainer.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, false));

        /* Adds a new Bookmark Set */
        Button addButton = new Button(buttonContainer, SWT.PUSH);
        addButton.setText(Messages.ManageSetsDialog_NEW);
        applyDialogFont(addButton);
        setButtonLayoutData(addButton);
        addButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onAdd();
            }
        });

        /* Edits a selected Bookmark Set */
        fEditButton = new Button(buttonContainer, SWT.PUSH);
        fEditButton.setText(Messages.ManageSetsDialog_EDIT);
        applyDialogFont(fEditButton);
        setButtonLayoutData(fEditButton);
        fEditButton.setEnabled(false);
        fEditButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onEdit();
            }
        });

        /* Deletes the selected Bookmark Set */
        fDeleteButton = new Button(buttonContainer, SWT.PUSH);
        fDeleteButton.setText(Messages.ManageSetsDialog_DELETE);
        applyDialogFont(fDeleteButton);
        setButtonLayoutData(fDeleteButton);
        ((GridData) fDeleteButton.getLayoutData()).verticalAlignment = SWT.END;
        ((GridData) fDeleteButton.getLayoutData()).grabExcessVerticalSpace = true;
        fDeleteButton.setEnabled(false);
        fDeleteButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onDelete();
            }
        });

        /* Container for the status-message */
        Composite statusContainer = new Composite(composite, SWT.None);
        statusContainer.setLayout(LayoutUtils.createGridLayout(1, 5, 0));
        statusContainer.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false, 2, 1));

        fStatusLabel = new Label(statusContainer, SWT.NONE);
        fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        /* Update Status Label when selection changes */
        fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                onSelectionChange();
            }
        });

        /* Pre-Select the current visible Set */
        Collection<IFolder> rootFolders = DynamicDAO.getDAO(IFolderDAO.class).loadRoots();
        for (IFolder rootFolder : rootFolders) {
            if (rootFolder.equals(fSelectedSet)) {
                fViewer.setSelection(new StructuredSelection(rootFolder));
                break;
            }
        }

        /* Separator */
        new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL)
                .setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));

        applyDialogFont(composite);

        return composite;
    }

    private void initDragAndDrop() {
        int ops = DND.DROP_COPY | DND.DROP_MOVE;
        Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getTransfer() };

        ViewerDropAdapter dropAdapter = new ViewerDropAdapter(fViewer) {
            @Override
            public boolean validateDrop(final Object target, int operation, TransferData transferType) {
                if (LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) {
                    final boolean[] result = new boolean[] { false };
                    SafeRunner.run(new LoggingSafeRunnable() {
                        public void run() throws Exception {
                            ISelection selection = LocalSelectionTransfer.getTransfer().getSelection();
                            if (selection instanceof IStructuredSelection) {
                                List<?> draggedObjects = ((IStructuredSelection) selection).toList();
                                result[0] = isValidDrop(draggedObjects, target);
                            }
                        }
                    });

                    return result[0];
                }

                return false;
            }

            @Override
            public boolean performDrop(final Object data) {
                if (data instanceof IStructuredSelection) {
                    SafeRunner.run(new LoggingSafeRunnable() {
                        public void run() throws Exception {
                            IStructuredSelection selection = (IStructuredSelection) data;
                            List<?> draggedObjects = selection.toList();
                            perfromDrop(draggedObjects, getCurrentTarget());
                        }
                    });

                    return true;
                }

                return false;
            }
        };

        dropAdapter.setFeedbackEnabled(false);
        fViewer.addDropSupport(ops, transfers, dropAdapter);
    }

    private boolean isValidDrop(List<?> draggedObjects, Object dropTarget) {

        /* Require Folder as Target */
        if (!(dropTarget instanceof IFolder))
            return false;

        /* Check validity for each dragged Object */
        IFolder dropFolder = (IFolder) dropTarget;
        for (Object draggedObject : draggedObjects) {

            /* Dragged Folder */
            if (draggedObject instanceof IFolder) {
                IFolder draggedFolder = (IFolder) draggedObject;
                if (CoreUtils.hasChildRelation(dropFolder, draggedFolder))
                    return false;
            }

            /* Dragged Mark */
            else if (draggedObject instanceof IMark) {
                IMark draggedMark = (IMark) draggedObject;
                if (CoreUtils.hasChildRelation(dropFolder, draggedMark))
                    return false;
            }
        }

        return true;
    }

    private void perfromDrop(List<?> draggedObjects, Object dropTarget) {

        /* Require a Folder as drop target */
        if (!(dropTarget instanceof IFolder) || draggedObjects.isEmpty())
            return;

        IFolder dropFolder = (IFolder) dropTarget;

        List<ReparentInfo<IFolderChild, IFolder>> reparenting = new ArrayList<ReparentInfo<IFolderChild, IFolder>>(
                draggedObjects.size());

        /* For each dragged Object */
        for (Object object : draggedObjects) {
            if (object instanceof IFolder || object instanceof IMark) {
                IFolderChild draggedFolderChild = (IFolderChild) object;
                reparenting.add(ReparentInfo.create(draggedFolderChild, dropFolder, null, null));
            }
        }

        /* Perform reparenting */
        CoreUtils.reparentWithProperties(reparenting);
        fViewer.setSelection(fViewer.getSelection());
    }

    private void onAdd() {
        showInfo();
        NewFolderAction newFolderAction = new NewFolderAction(getShell(), null, null);
        newFolderAction.setRootMode(true);
        newFolderAction.run(null);
        fViewer.refresh();

        /* Select and Focus the added Set */
        Table table = fViewer.getTable();
        Object lastItem = table.getItem(table.getItemCount() - 1).getData();
        fViewer.setSelection(new StructuredSelection(lastItem));
        table.setFocus();
    }

    private void onEdit() {
        showInfo();

        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        if (!selection.isEmpty()) {
            new EntityPropertyDialogAction(this, fViewer).run();
            fViewer.refresh();
        }
    }

    private void onDelete() {
        showInfo();

        /* Require at least 1 Set to remain undeleted */
        if (fViewer.getTable().getItemCount() == 1) {
            setErrorMessage(Messages.ManageSetsDialog_DELETE_LAST_SET_ERROR);
            return;
        }

        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        if (!selection.isEmpty()) {
            DeleteTypesAction deleteAction = new DeleteTypesAction(getShell(), selection);
            deleteAction.run();

            if (deleteAction.isConfirmed())
                fViewer.remove(selection.getFirstElement());
        }
    }

    private void onSelectionChange() {
        updateStatusLabel();

        ISelection selection = fViewer.getSelection();
        fEditButton.setEnabled(!selection.isEmpty());
        fDeleteButton.setEnabled(!selection.isEmpty());
    }

    /*
     * @see org.eclipse.jface.window.Window#getShellStyle()
     */
    @Override
    protected int getShellStyle() {
        int style = SWT.TITLE | SWT.BORDER | SWT.CLOSE | getDefaultOrientation();

        return style;
    }

    /*
     * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
    }

    /*
     * @see org.eclipse.jface.dialogs.Dialog#initializeBounds()
     */
    @Override
    protected void initializeBounds() {
        super.initializeBounds();

        Shell shell = getShell();

        /* Minimum Size */
        int minWidth = convertHorizontalDLUsToPixels(OwlUI.MIN_DIALOG_WIDTH_DLU);
        int minHeight = shell.computeSize(minWidth, SWT.DEFAULT).y;

        /* Required Size */
        Point requiredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);

        shell.setSize(Math.max(minWidth, requiredSize.x), Math.max(minHeight, requiredSize.y));
        LayoutUtils.positionShell(shell);
    }

    private void showInfo() {
        setErrorMessage(null);
        setMessage(Messages.ManageSetsDialog_SELECT_SET);
    }

    private void updateStatusLabel() {
        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        if (selection.isEmpty())
            fStatusLabel.setText(""); //$NON-NLS-1$
        else {
            IFolder bookmarkSet = (IFolder) selection.getFirstElement();
            int counter[] = new int[4];

            count(bookmarkSet, counter);

            StringBuilder itemBuilder = new StringBuilder();
            if (counter[0] > 0)
                itemBuilder.append(counter[0] == 1 ? Messages.ManageSetsDialog_1_FOLDER
                        : (NLS.bind(Messages.ManageSetsDialog_N_FOLDERS, counter[0]))).append(", "); //$NON-NLS-1$
            if (counter[1] > 0)
                itemBuilder.append(counter[1] == 1 ? Messages.ManageSetsDialog_1_BOOKMARK
                        : (NLS.bind(Messages.ManageSetsDialog_N_BOOKMARKS, counter[1]))).append(", "); //$NON-NLS-1$
            if (counter[2] > 0)
                itemBuilder.append(counter[2] == 1 ? Messages.ManageSetsDialog_1_SEARCH
                        : (NLS.bind(Messages.ManageSetsDialog_N_SEARCHES, counter[2]))).append(", "); //$NON-NLS-1$
            if (counter[3] > 0)
                itemBuilder.append(counter[3] == 1 ? Messages.ManageSetsDialog_1_BIN
                        : (NLS.bind(Messages.ManageSetsDialog_N_BINS, counter[3]))).append(", "); //$NON-NLS-1$

            /* Set is Empty */
            if (counter[0] == 0 && counter[1] == 0 && counter[2] == 0 && counter[3] == 0)
                itemBuilder = new StringBuilder(Messages.ManageSetsDialog_EMPTY_SET);
            else if (itemBuilder.length() > 0)
                itemBuilder.delete(itemBuilder.length() - 2, itemBuilder.length());

            fStatusLabel.setText(
                    NLS.bind(Messages.ManageSetsDialog_SET_CONTENT, bookmarkSet.getName(), itemBuilder.toString()));
        }
    }

    private void count(IFolder folder, int[] counter) {

        /* Count Marks */
        List<IMark> marks = folder.getMarks();
        for (IMark mark : marks) {
            if (mark instanceof IBookMark)
                counter[1]++;
            else if (mark instanceof ISearchMark)
                counter[2]++;
            else if (mark instanceof INewsBin)
                counter[3]++;
        }

        /* Count in Sub-Folders */
        List<IFolder> childs = folder.getFolders();
        counter[0] += childs.size();
        for (IFolder child : childs)
            count(child, counter);
    }
}