org.rssowl.ui.internal.dialogs.preferences.ManageLabelsPreferencePage.java Source code

Java tutorial

Introduction

Here is the source code for org.rssowl.ui.internal.dialogs.preferences.ManageLabelsPreferencePage.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.preferences;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
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.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.rssowl.core.Owl;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.ILabelDAO;
import org.rssowl.core.persist.reference.NewsReference;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.SearchHit;
import org.rssowl.core.util.SyncItem;
import org.rssowl.core.util.SyncUtils;
import org.rssowl.ui.internal.Activator;
import org.rssowl.ui.internal.ApplicationWorkbenchWindowAdvisor;
import org.rssowl.ui.internal.Controller;
import org.rssowl.ui.internal.OwlUI;
import org.rssowl.ui.internal.dialogs.ConfirmDialog;
import org.rssowl.ui.internal.dialogs.LabelDialog;
import org.rssowl.ui.internal.dialogs.LabelDialog.DialogMode;
import org.rssowl.ui.internal.dialogs.NewsFiltersListDialog;
import org.rssowl.ui.internal.util.JobRunner;
import org.rssowl.ui.internal.util.LayoutUtils;
import org.rssowl.ui.internal.util.ModelUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author bpasero
 */
public class ManageLabelsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

    /** ID of the Page */
    public static final String ID = "org.rssowl.ui.ManageLabels"; //$NON-NLS-1$

    /* Number of News to process when deleting labels */
    private static final int LABELS_CHUNK_SIZE = 100;

    private LocalResourceManager fResources;
    private TreeViewer fViewer;
    private Button fMoveDownButton;
    private Button fMoveUpButton;

    /** Leave for reflection */
    public ManageLabelsPreferencePage() {
        fResources = new LocalResourceManager(JFaceResources.getResources());
        setImageDescriptor(OwlUI.getImageDescriptor("icons/elcl16/labels.gif")); //$NON-NLS-1$
    }

    /*
     * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
     */
    public void init(IWorkbench workbench) {
        noDefaultAndApplyButton();
    }

    /*
     * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createContents(Composite parent) {
        Composite container = createContainer(parent);

        /* Label */
        Label infoLabel = new Label(container, SWT.None);
        infoLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
        infoLabel.setText(Messages.ManageLabelsPreferencePage_LABEL_INFO);

        /* Label Viewer */
        createViewer(container);

        /* Button Box */
        createButtons(container);

        /* Info Container */
        Composite infoContainer = new Composite(container, SWT.None);
        infoContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
        infoContainer.setLayout(LayoutUtils.createGridLayout(2, 0, 0));

        Label infoImg = new Label(infoContainer, SWT.NONE);
        infoImg.setImage(OwlUI.getImage(fResources, "icons/obj16/info.gif")); //$NON-NLS-1$
        infoImg.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

        Link infoText = new Link(infoContainer, SWT.WRAP);
        infoText.setText(Messages.ManageLabelsPreferencePage_LABEL_TIP);
        infoText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        infoText.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                NewsFiltersListDialog dialog = NewsFiltersListDialog.getVisibleInstance();
                if (dialog == null) {
                    dialog = new NewsFiltersListDialog(getShell());
                    dialog.setBlockOnOpen(false);
                    dialog.open();
                } else {
                    dialog.getShell().forceActive();
                    if (dialog.getShell().getMinimized())
                        dialog.getShell().setMinimized(false);
                }
            }
        });

        applyDialogFont(container);

        return container;
    }

    private void createButtons(Composite container) {
        Composite buttonBox = new Composite(container, SWT.None);
        buttonBox.setLayout(LayoutUtils.createGridLayout(1, 0, 0));
        buttonBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));

        Button addButton = new Button(buttonBox, SWT.PUSH);
        addButton.setText(Messages.ManageLabelsPreferencePage_NEW);
        Dialog.applyDialogFont(addButton);
        setButtonLayoutData(addButton);
        addButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onAdd();
            }
        });

        final Button editButton = new Button(buttonBox, SWT.PUSH);
        editButton.setText(Messages.ManageLabelsPreferencePage_EDIT);
        editButton.setEnabled(!fViewer.getSelection().isEmpty());
        Dialog.applyDialogFont(editButton);
        setButtonLayoutData(editButton);
        editButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onEdit();
            }
        });

        final Button deleteButton = new Button(buttonBox, SWT.PUSH);
        deleteButton.setText(Messages.ManageLabelsPreferencePage_DELETE);
        deleteButton.setEnabled(!fViewer.getSelection().isEmpty());
        Dialog.applyDialogFont(deleteButton);
        setButtonLayoutData(deleteButton);
        deleteButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onDelete();
            }
        });

        /* Move Label Up */
        fMoveUpButton = new Button(buttonBox, SWT.PUSH);
        fMoveUpButton.setText(Messages.ManageLabelsPreferencePage_MOVE_UP);
        fMoveUpButton.setEnabled(false);
        Dialog.applyDialogFont(fMoveUpButton);
        setButtonLayoutData(fMoveUpButton);
        ((GridData) fMoveUpButton.getLayoutData()).verticalIndent = 10;
        fMoveUpButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onMove(true);
            }
        });

        /* Move Label Down */
        fMoveDownButton = new Button(buttonBox, SWT.PUSH);
        fMoveDownButton.setText(Messages.ManageLabelsPreferencePage_MOVE_DOWN);
        fMoveDownButton.setEnabled(false);
        Dialog.applyDialogFont(fMoveDownButton);
        setButtonLayoutData(fMoveDownButton);
        fMoveDownButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                onMove(false);
            }
        });

        fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                editButton.setEnabled(!event.getSelection().isEmpty());
                deleteButton.setEnabled(!event.getSelection().isEmpty());
                updateMoveEnablement();
            }
        });
    }

    private void onMove(boolean up) {
        TreeItem[] items = fViewer.getTree().getItems();
        List<ILabel> sortedLabels = new ArrayList<ILabel>(items.length);
        for (TreeItem item : items) {
            sortedLabels.add((ILabel) item.getData());
        }

        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        ILabel selectedLabel = (ILabel) selection.getFirstElement();
        int selectedLabelOrder = selectedLabel.getOrder();
        ILabel otherLabel = null;
        int index = sortedLabels.indexOf(selectedLabel);

        /* Move Up */
        if (up && index > 0) {
            otherLabel = sortedLabels.get(index - 1);
            selectedLabel.setOrder(otherLabel.getOrder());
            otherLabel.setOrder(selectedLabelOrder);
        }

        /* Move Down */
        else if (!up && index < sortedLabels.size() - 1) {
            otherLabel = sortedLabels.get(index + 1);
            selectedLabel.setOrder(otherLabel.getOrder());
            otherLabel.setOrder(selectedLabelOrder);
        }

        DynamicDAO.getDAO(ILabelDAO.class).saveAll(Arrays.asList(new ILabel[] { selectedLabel, otherLabel }));
        fViewer.refresh();
        fViewer.getTree().showSelection();
        updateMoveEnablement();
    }

    private void updateMoveEnablement() {
        boolean enableMoveUp = true;
        boolean enableMoveDown = true;

        TreeItem[] selection = fViewer.getTree().getSelection();
        int[] selectionIndices = new int[selection.length];
        for (int i = 0; i < selection.length; i++)
            selectionIndices[i] = fViewer.getTree().indexOf(selection[i]);

        if (selectionIndices.length == 1) {
            enableMoveUp = selectionIndices[0] != 0;
            enableMoveDown = selectionIndices[0] != fViewer.getTree().getItemCount() - 1;
        } else {
            enableMoveUp = false;
            enableMoveDown = false;
        }

        fMoveUpButton.setEnabled(enableMoveUp);
        fMoveDownButton.setEnabled(enableMoveDown);
    }

    private void onAdd() {
        LabelDialog dialog = new LabelDialog(getShell(), DialogMode.ADD, null);
        if (dialog.open() == IDialogConstants.OK_ID) {
            String name = dialog.getName();
            RGB color = dialog.getColor();

            ILabel newLabel = Owl.getModelFactory().createLabel(null, name);
            newLabel.setColor(OwlUI.toString(color));
            newLabel.setOrder(fViewer.getTree().getItemCount());
            DynamicDAO.save(newLabel);

            fViewer.refresh();
            fViewer.setSelection(new StructuredSelection(newLabel));
        }
        fViewer.getTree().setFocus();
    }

    private void onEdit() {
        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        if (!selection.isEmpty()) {
            ILabel label = (ILabel) selection.getFirstElement();
            LabelDialog dialog = new LabelDialog(getShell(), DialogMode.EDIT, label);
            if (dialog.open() == IDialogConstants.OK_ID) {
                boolean changed = false;
                String name = dialog.getName();
                RGB color = dialog.getColor();

                if (!label.getName().equals(name)) {
                    onLabelNameChanged(label, label.getName(), name);
                    label.setName(name);
                    changed = true;
                }

                String colorStr = OwlUI.toString(color);
                if (!label.getColor().equals(colorStr)) {
                    label.setColor(colorStr);
                    changed = true;
                }

                /* Save Label */
                if (changed) {
                    Controller.getDefault().getSavedSearchService().forceQuickUpdate();
                    DynamicDAO.save(label);
                    fViewer.update(label, null);
                }
            }
        }
        fViewer.getTree().setFocus();
    }

    private void onDelete() {
        IStructuredSelection selection = (IStructuredSelection) fViewer.getSelection();
        if (!selection.isEmpty()) {
            final List<ILabel> selectedLabels = ModelUtils.getEntities(selection, ILabel.class);

            String msg;
            if (selectedLabels.size() == 1)
                msg = NLS.bind(Messages.ManageLabelsPreferencePage_DELETE_LABEL_N, selectedLabels.get(0).getName());
            else
                msg = NLS.bind(Messages.ManageLabelsPreferencePage_DELETE_N_LABELS, selectedLabels.size());

            ConfirmDialog dialog = new ConfirmDialog(getShell(), Messages.ManageLabelsPreferencePage_CONFIRM_DELETE,
                    Messages.ManageLabelsPreferencePage_NO_UNDO, msg, null);
            if (dialog.open() == IDialogConstants.OK_ID)
                deleteInBackground(selectedLabels);
        }
    }

    private void onLabelNameChanged(final ILabel label, final String oldName, final String newName) {
        IRunnableWithProgress runnableWithProgress = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                monitor.beginTask(Messages.ManageLabelsPreferencePage_WAIT_UPDATE, IProgressMonitor.UNKNOWN);
                try {
                    List<SyncItem> syncItems = new ArrayList<SyncItem>();

                    ISearchField labelField = Owl.getModelFactory().createSearchField(INews.LABEL,
                            INews.class.getName());
                    ISearchField feedField = Owl.getModelFactory().createSearchField(INews.FEED,
                            INews.class.getName());

                    ISearchCondition labelCondition = Owl.getModelFactory().createSearchCondition(labelField,
                            SearchSpecifier.IS, oldName);
                    ISearchCondition feedCondition = Owl.getModelFactory().createSearchCondition(feedField,
                            SearchSpecifier.BEGINS_WITH, SyncUtils.READER_HTTP_SCHEME);

                    /* Find all news that are under sync control and have the label assigned */
                    List<SearchHit<NewsReference>> result = Owl.getPersistenceService().getModelSearch()
                            .searchNews(Arrays.asList(labelCondition, feedCondition), true);
                    List<List<SearchHit<NewsReference>>> chunks = CoreUtils.toChunks(result, LABELS_CHUNK_SIZE);
                    for (List<SearchHit<NewsReference>> chunk : chunks) {
                        for (SearchHit<NewsReference> item : chunk) {
                            INews news = item.getResult().resolve();

                            /* Item Exists */
                            if (news != null && news.isVisible()) {
                                if (SyncUtils.isSynchronized(news) && news.getLabels().contains(label)) {
                                    SyncItem syncItem = SyncItem.toSyncItem(news);
                                    syncItem.addLabel(newName);
                                    syncItem.removeLabel(oldName);
                                    syncItems.add(syncItem);
                                }
                            }

                            /* Index Issue */
                            else
                                CoreUtils.reportIndexIssue();
                        }
                    }

                    /* Tell SyncService to synchronize */
                    if (!syncItems.isEmpty())
                        Controller.getDefault().getSyncService().synchronize(syncItems);
                } finally {
                    monitor.done();
                }
            }
        };

        /* Progress Dialog */
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()) {
            @Override
            protected void initializeBounds() {
                super.initializeBounds();

                /* Size */
                Shell shell = getShell();
                int width = convertHorizontalDLUsToPixels(OwlUI.MIN_DIALOG_WIDTH_DLU);
                shell.setSize(width, shell.getSize().y);

                /* New Location */
                Rectangle containerBounds = shell.getParent().getBounds();
                int x = Math.max(0, containerBounds.x + (containerBounds.width - width) / 2);
                shell.setLocation(x, shell.getLocation().y);
            }
        };

        /* Open and Run */
        try {
            dialog.run(true, false, runnableWithProgress);
        } catch (InvocationTargetException e) {
            Activator.safeLogError(e.getMessage(), e);
        } catch (InterruptedException e) {
            Activator.safeLogError(e.getMessage(), e);
        }
    }

    private void deleteInBackground(final List<ILabel> labelsToDelete) {
        IRunnableWithProgress runnableWithProgress = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                monitor.beginTask(Messages.ManageLabelsPreferencePage_WAIT_DELETE, IProgressMonitor.UNKNOWN);
                try {

                    /* Can have an impact on news, thereby force quick update */
                    Controller.getDefault().getSavedSearchService().forceQuickUpdate();

                    /* Remove Labels from News in batched mode to reduce load */
                    List<SearchHit<NewsReference>> labeledNews = findLabeledNews(labelsToDelete);
                    if (!labeledNews.isEmpty()) {
                        monitor.subTask(NLS.bind(Messages.ManageLabelsPreferencePage_UPDATE_NEWS_REMOVE_LABELS,
                                labeledNews.size()));

                        /* Chunkify */
                        List<List<SearchHit<NewsReference>>> chunks = CoreUtils.toChunks(labeledNews,
                                LABELS_CHUNK_SIZE);
                        for (List<SearchHit<NewsReference>> chunk : chunks) {
                            List<INews> newsToSave = new ArrayList<INews>(chunk.size());

                            /* For each item in chunk */
                            for (SearchHit<NewsReference> hit : chunk) {
                                boolean needsSave = false;
                                INews item = hit.getResult().resolve();

                                /* Item Exists */
                                if (item != null && item.isVisible()) {
                                    for (ILabel labelToDelete : labelsToDelete) {
                                        if (item.removeLabel(labelToDelete))
                                            needsSave = true;
                                    }

                                    if (needsSave)
                                        newsToSave.add(item);
                                }

                                /* Index Issue */
                                else
                                    CoreUtils.reportIndexIssue();
                            }

                            /* Save */
                            if (!newsToSave.isEmpty())
                                DynamicDAO.saveAll(newsToSave);
                        }
                    }

                    /* Delete Labels from DB */
                    DynamicDAO.deleteAll(labelsToDelete);

                    /* Update UI */
                    JobRunner.runInUIThread(fViewer.getControl(), new Runnable() {
                        public void run() {
                            fViewer.refresh();
                            fixOrderAfterDelete();
                            fViewer.getTree().setFocus();
                        }
                    });
                } finally {
                    monitor.done();
                }
            }
        };

        /* Progress Dialog */
        ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell()) {
            @Override
            protected void initializeBounds() {
                super.initializeBounds();

                /* Size */
                Shell shell = getShell();
                int width = convertHorizontalDLUsToPixels(OwlUI.MIN_DIALOG_WIDTH_DLU);
                shell.setSize(width, shell.getSize().y);

                /* New Location */
                Rectangle containerBounds = shell.getParent().getBounds();
                int x = Math.max(0, containerBounds.x + (containerBounds.width - width) / 2);
                shell.setLocation(x, shell.getLocation().y);
            }
        };

        /* Open and Run */
        try {
            dialog.run(true, false, runnableWithProgress);
        } catch (InvocationTargetException e) {
            Activator.safeLogError(e.getMessage(), e);
        } catch (InterruptedException e) {
            Activator.safeLogError(e.getMessage(), e);
        }
    }

    private List<SearchHit<NewsReference>> findLabeledNews(List<ILabel> selectedLabels) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>(selectedLabels.size());
        ISearchField labelField = Owl.getModelFactory().createSearchField(INews.LABEL, INews.class.getName());
        for (ILabel label : selectedLabels) {
            ISearchCondition condition = Owl.getModelFactory().createSearchCondition(labelField, SearchSpecifier.IS,
                    label.getName());
            conditions.add(condition);
        }

        return Owl.getPersistenceService().getModelSearch().searchNews(conditions, false);
    }

    /* Ensure that after Delete, the orders are in sync again */
    private void fixOrderAfterDelete() {
        List<ILabel> labelsToSave = new ArrayList<ILabel>();

        TreeItem[] items = fViewer.getTree().getItems();
        for (int i = 0; i < items.length; i++) {
            TreeItem item = items[i];
            ILabel label = (ILabel) item.getData();
            label.setOrder(i);

            labelsToSave.add(label);
        }

        DynamicDAO.saveAll(labelsToSave);
    }

    private void createViewer(Composite container) {
        fViewer = new TreeViewer(container, SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI);
        fViewer.getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        ((GridData) fViewer.getTree().getLayoutData()).heightHint = 190;
        fViewer.getTree().setFont(OwlUI.getBold(JFaceResources.DIALOG_FONT));
        fViewer.getTree().setData(ApplicationWorkbenchWindowAdvisor.FOCUSLESS_SCROLL_HOOK, new Object());

        /* Content Provider */
        fViewer.setContentProvider(new ITreeContentProvider() {
            public Object[] getElements(Object inputElement) {
                return CoreUtils.loadSortedLabels().toArray();
            }

            public Object[] getChildren(Object parentElement) {
                return null;
            }

            public Object getParent(Object element) {
                return null;
            }

            public boolean hasChildren(Object element) {
                return false;
            }

            public void dispose() {
            }

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

        /* Label Provider */
        final RGB listBackground = fViewer.getControl().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)
                .getRGB();
        final RGB listSelectionBackground = fViewer.getControl().getDisplay()
                .getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB();
        fViewer.setLabelProvider(new CellLabelProvider() {
            @Override
            public void update(ViewerCell cell) {
                ILabel label = (ILabel) cell.getElement();

                /* Text */
                cell.setText(label.getName());

                /* Color */
                if (!OwlUI.isHighContrast()) {
                    RGB labelRGB = OwlUI.getRGB(label);
                    if (!listBackground.equals(labelRGB) && !listSelectionBackground.equals(labelRGB))
                        cell.setForeground(OwlUI.getColor(fResources, labelRGB));
                    else
                        cell.setForeground(null);
                }
            }
        });

        /* Set dummy Input */
        fViewer.setInput(new Object());

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

    private Composite createContainer(Composite parent) {
        Composite composite = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout(2, false);
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));
        composite.setFont(parent.getFont());
        return composite;
    }

    /*
     * @see org.eclipse.jface.dialogs.DialogPage#dispose()
     */
    @Override
    public void dispose() {
        super.dispose();
        fResources.dispose();
    }
}