org.rssowl.ui.internal.ApplicationActionBarAdvisor.java Source code

Java tutorial

Introduction

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

    import org.eclipse.core.runtime.Platform;
    import org.eclipse.jface.action.Action;
    import org.eclipse.jface.action.GroupMarker;
    import org.eclipse.jface.action.IAction;
    import org.eclipse.jface.action.IContributionItem;
    import org.eclipse.jface.action.ICoolBarManager;
    import org.eclipse.jface.action.IMenuListener;
    import org.eclipse.jface.action.IMenuManager;
    import org.eclipse.jface.action.IStatusLineManager;
    import org.eclipse.jface.action.MenuManager;
    import org.eclipse.jface.action.Separator;
    import org.eclipse.jface.bindings.TriggerSequence;
    import org.eclipse.jface.dialogs.IDialogConstants;
    import org.eclipse.jface.resource.ImageDescriptor;
    import org.eclipse.jface.resource.JFaceResources;
    import org.eclipse.jface.resource.LocalResourceManager;
    import org.eclipse.jface.resource.ResourceManager;
    import org.eclipse.jface.viewers.DecorationOverlayIcon;
    import org.eclipse.jface.viewers.IDecoration;
    import org.eclipse.jface.viewers.IStructuredSelection;
    import org.eclipse.jface.viewers.StructuredSelection;
    import org.eclipse.jface.window.IShellProvider;
    import org.eclipse.osgi.util.NLS;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.graphics.Image;
    import org.eclipse.swt.graphics.RGB;
    import org.eclipse.swt.program.Program;
    import org.eclipse.swt.widgets.DirectoryDialog;
    import org.eclipse.swt.widgets.FileDialog;
    import org.eclipse.swt.widgets.MessageBox;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.ui.IActionDelegate;
    import org.eclipse.ui.IEditorReference;
    import org.eclipse.ui.IWorkbench;
    import org.eclipse.ui.IWorkbenchActionConstants;
    import org.eclipse.ui.IWorkbenchPage;
    import org.eclipse.ui.IWorkbenchWindow;
    import org.eclipse.ui.PlatformUI;
    import org.eclipse.ui.actions.ActionFactory;
    import org.eclipse.ui.actions.ContributionItemFactory;
    import org.eclipse.ui.application.ActionBarAdvisor;
    import org.eclipse.ui.application.IActionBarConfigurer;
    import org.eclipse.ui.dialogs.PreferencesUtil;
    import org.eclipse.ui.keys.IBindingService;
    import org.rssowl.core.Owl;
    import org.rssowl.core.internal.persist.pref.DefaultPreferences;
    import org.rssowl.core.persist.IAttachment;
    import org.rssowl.core.persist.IBookMark;
    import org.rssowl.core.persist.IFilterAction;
    import org.rssowl.core.persist.IFolder;
    import org.rssowl.core.persist.IFolderChild;
    import org.rssowl.core.persist.ILabel;
    import org.rssowl.core.persist.IMark;
    import org.rssowl.core.persist.INews;
    import org.rssowl.core.persist.INewsBin;
    import org.rssowl.core.persist.INewsMark;
    import org.rssowl.core.persist.ISearchFilter;
    import org.rssowl.core.persist.ISearchMark;
    import org.rssowl.core.persist.dao.DynamicDAO;
    import org.rssowl.core.persist.dao.IBookMarkDAO;
    import org.rssowl.core.persist.pref.IPreferenceScope;
    import org.rssowl.core.util.CoreUtils;
    import org.rssowl.core.util.Pair;
    import org.rssowl.core.util.StringUtils;
    import org.rssowl.core.util.URIUtils;
    import org.rssowl.ui.internal.OwlUI.Layout;
    import org.rssowl.ui.internal.OwlUI.PageSize;
    import org.rssowl.ui.internal.actions.ArchiveNewsAction;
    import org.rssowl.ui.internal.actions.AssignLabelsAction;
    import org.rssowl.ui.internal.actions.AutomateFilterAction;
    import org.rssowl.ui.internal.actions.CopyLinkAction;
    import org.rssowl.ui.internal.actions.CreateFilterAction;
    import org.rssowl.ui.internal.actions.CreateFilterAction.PresetAction;
    import org.rssowl.ui.internal.actions.FindAction;
    import org.rssowl.ui.internal.actions.LabelAction;
    import org.rssowl.ui.internal.actions.MakeNewsStickyAction;
    import org.rssowl.ui.internal.actions.MarkAllNewsReadAction;
    import org.rssowl.ui.internal.actions.MoveCopyNewsToBinAction;
    import org.rssowl.ui.internal.actions.OpenInBrowserAction;
    import org.rssowl.ui.internal.actions.OpenInExternalBrowserAction;
    import org.rssowl.ui.internal.actions.OpenInNewTabAction;
    import org.rssowl.ui.internal.actions.RedoAction;
    import org.rssowl.ui.internal.actions.ReloadAllAction;
    import org.rssowl.ui.internal.actions.ReloadTypesAction;
    import org.rssowl.ui.internal.actions.SearchNewsAction;
    import org.rssowl.ui.internal.actions.SendLinkAction;
    import org.rssowl.ui.internal.actions.ToggleReadStateAction;
    import org.rssowl.ui.internal.actions.UndoAction;
    import org.rssowl.ui.internal.dialogs.CustomizeToolbarDialog;
    import org.rssowl.ui.internal.dialogs.LabelDialog;
    import org.rssowl.ui.internal.dialogs.LabelDialog.DialogMode;
    import org.rssowl.ui.internal.dialogs.preferences.ManageLabelsPreferencePage;
    import org.rssowl.ui.internal.dialogs.preferences.NotifierPreferencesPage;
    import org.rssowl.ui.internal.dialogs.preferences.OverviewPreferencesPage;
    import org.rssowl.ui.internal.dialogs.preferences.SharingPreferencesPage;
    import org.rssowl.ui.internal.dialogs.welcome.TutorialPage.Chapter;
    import org.rssowl.ui.internal.dialogs.welcome.TutorialWizard;
    import org.rssowl.ui.internal.editors.browser.WebBrowserContext;
    import org.rssowl.ui.internal.editors.feed.FeedView;
    import org.rssowl.ui.internal.editors.feed.FeedViewInput;
    import org.rssowl.ui.internal.editors.feed.NewsColumn;
    import org.rssowl.ui.internal.editors.feed.NewsColumnViewModel;
    import org.rssowl.ui.internal.editors.feed.NewsFilter;
    import org.rssowl.ui.internal.editors.feed.NewsGrouping;
    import org.rssowl.ui.internal.filter.DownloadAttachmentsNewsAction;
    import org.rssowl.ui.internal.handler.RemoveLabelsHandler;
    import org.rssowl.ui.internal.handler.TutorialHandler;
    import org.rssowl.ui.internal.services.DownloadService.DownloadRequest;
    import org.rssowl.ui.internal.util.BrowserUtils;
    import org.rssowl.ui.internal.util.EditorUtils;
    import org.rssowl.ui.internal.util.ModelUtils;
    import org.rssowl.ui.internal.views.explorer.BookMarkExplorer;
    import org.rssowl.ui.internal.views.explorer.BookMarkFilter;

    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.EnumSet;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;

    /**
     * @author bpasero
     */
    public class ApplicationActionBarAdvisor extends ActionBarAdvisor {

        /** Name of the "Manage Extensions" SubMenu */
        public static final String M_MANAGE_EXTENSIONS = "manageExtensions"; //$NON-NLS-1$

        /** Name of the View Top Menu */
        public static final String M_VIEW = "view"; //$NON-NLS-1$

        /** Start of the View Top Menu */
        public static final String M_VIEW_START = "viewStart"; //$NON-NLS-1$

        /** End of the View Top Menu */
        public static final String M_VIEW_END = "viewEnd"; //$NON-NLS-1$

        /* Local Resource Manager (lives across entire application life) */
        private static ResourceManager fgResources = new LocalResourceManager(JFaceResources.getResources());

        private CoolBarAdvisor fCoolBarAdvisor;
        private IContributionItem fOpenWindowsItem;
        private IContributionItem fReopenEditors;
        private FindAction fFindAction;

        /**
         * @param configurer
         */
        public ApplicationActionBarAdvisor(IActionBarConfigurer configurer) {
            super(configurer);
        }

        /*
         * @see org.eclipse.ui.application.ActionBarAdvisor#makeActions(org.eclipse.ui.IWorkbenchWindow)
         */
        @Override
        protected void makeActions(IWorkbenchWindow window) {

            /* Menu: File */
            register(ActionFactory.SAVE_AS.create(window));
            register(ActionFactory.CLOSE.create(window));
            register(ActionFactory.CLOSE_ALL.create(window));
            register(ActionFactory.PRINT.create(window));
            register(ActionFactory.QUIT.create(window));

            fReopenEditors = ContributionItemFactory.REOPEN_EDITORS.create(window);

            /* Menu: Edit */
            register(ActionFactory.CUT.create(window));
            register(ActionFactory.COPY.create(window));
            register(ActionFactory.PASTE.create(window));
            register(ActionFactory.DELETE.create(window));
            register(ActionFactory.SELECT_ALL.create(window));
            register(ActionFactory.PROPERTIES.create(window));

            fFindAction = new FindAction();
            register(fFindAction);

            /* Menu: Tools */
            register(ActionFactory.PREFERENCES.create(window));

            /* Menu: Window */
            register(ActionFactory.OPEN_NEW_WINDOW.create(window));
            getAction(ActionFactory.OPEN_NEW_WINDOW.getId()).setText(Messages.ApplicationActionBarAdvisor_NEW_WINDOW);
            fOpenWindowsItem = ContributionItemFactory.OPEN_WINDOWS.create(window);

            //    register(ActionFactory.TOGGLE_COOLBAR.create(window));
            //    register(ActionFactory.RESET_PERSPECTIVE.create(window));
            //    register(ActionFactory.EDIT_ACTION_SETS.create(window));
            //    register(ActionFactory.ACTIVATE_EDITOR.create(window));
            //    register(ActionFactory.MAXIMIZE.create(window));
            //    register(ActionFactory.MINIMIZE.create(window));
            //    register(ActionFactory.NEXT_EDITOR.create(window));
            //    register(ActionFactory.PREVIOUS_EDITOR.create(window));
            //    register(ActionFactory.PREVIOUS_PART.create(window));
            //    register(ActionFactory.NEXT_PART.create(window));
            //    register(ActionFactory.SHOW_EDITOR.create(window));

            /* Menu: Help */
            // register(ActionFactory.INTRO.create(window));
            register(ActionFactory.ABOUT.create(window));
            getAction(ActionFactory.ABOUT.getId()).setText(Messages.ApplicationActionBarAdvisor_ABOUT_RSSOWL);

            /* CoolBar: Contextual Menu */
            register(ActionFactory.LOCK_TOOL_BAR.create(window));
        }

        /*
         * @see org.eclipse.ui.application.ActionBarAdvisor#fillMenuBar(org.eclipse.jface.action.IMenuManager)
         */
        @Override
        protected void fillMenuBar(IMenuManager menuBar) {

            /* File Menu */
            createFileMenu(menuBar);

            /* Edit Menu */
            createEditMenu(menuBar);

            /* View Menu */
            createViewMenu(menuBar);

            /* Go Menu */
            createGoMenu(menuBar);

            /* Bookmarks Menu */
            createBookMarksMenu(menuBar);

            /* News Menu */
            createNewsMenu(menuBar);

            /* Allow Top-Level Menu Contributions here */
            menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

            /* Menu: Tools */
            createToolsMenu(menuBar);

            /* Window Menu */
            createWindowMenu(menuBar);

            /* Menu: Help */
            createHelpMenu(menuBar);
        }

        /* Menu: File */
        private void createFileMenu(IMenuManager menuBar) {
            MenuManager fileMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_FILE,
                    IWorkbenchActionConstants.M_FILE);
            menuBar.add(fileMenu);

            fileMenu.add(new GroupMarker(IWorkbenchActionConstants.FILE_START));
            fileMenu.add(new GroupMarker(IWorkbenchActionConstants.NEW_EXT));
            fileMenu.add(new Separator());

            fileMenu.add(getAction(ActionFactory.CLOSE.getId()));
            fileMenu.add(getAction(ActionFactory.CLOSE_ALL.getId()));
            fileMenu.add(new GroupMarker(IWorkbenchActionConstants.CLOSE_EXT));
            fileMenu.add(new Separator());
            fileMenu.add(getAction(ActionFactory.SAVE_AS.getId()));
            if (!Application.IS_MAC) { //Printing is not supported on Mac
                fileMenu.add(new Separator());
                fileMenu.add(getAction(ActionFactory.PRINT.getId()));
            }

            fileMenu.add(new Separator());
            fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

            fileMenu.add(new Separator());
            fileMenu.add(new GroupMarker(IWorkbenchActionConstants.FILE_END));
            fileMenu.add(new Separator());

            if (Application.IS_LINUX) {
                fileMenu.add(getAction(ActionFactory.PROPERTIES.getId()));
                fileMenu.add(new Separator());
            }

            fileMenu.add(getAction(ActionFactory.QUIT.getId()));
        }

        /* Menu: Edit */
        private void createEditMenu(IMenuManager menuBar) {
            MenuManager editMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_EDIT,
                    IWorkbenchActionConstants.M_EDIT);
            editMenu.add(getAction(ActionFactory.COPY.getId())); //Dummy action
            menuBar.add(editMenu);

            editMenu.setRemoveAllWhenShown(true);
            editMenu.addMenuListener(new IMenuListener() {
                public void menuAboutToShow(IMenuManager editMenu) {
                    editMenu.add(new GroupMarker(IWorkbenchActionConstants.EDIT_START));
                    editMenu.add(new Separator());

                    editMenu.add(new UndoAction());
                    editMenu.add(new RedoAction());
                    editMenu.add(new GroupMarker(IWorkbenchActionConstants.UNDO_EXT));
                    editMenu.add(new Separator());

                    editMenu.add(getAction(ActionFactory.CUT.getId()));
                    editMenu.add(getAction(ActionFactory.COPY.getId()));
                    editMenu.add(new CopyLinkAction());
                    editMenu.add(getAction(ActionFactory.PASTE.getId()));
                    editMenu.add(new Separator());
                    editMenu.add(getAction(ActionFactory.DELETE.getId()));
                    editMenu.add(getAction(ActionFactory.SELECT_ALL.getId()));

                    editMenu.add(new Separator());

                    editMenu.add(new SearchNewsAction(OwlUI.getWindow()));
                    editMenu.add(fFindAction);

                    editMenu.add(new GroupMarker(IWorkbenchActionConstants.EDIT_END));
                    editMenu.add(new Separator());

                    if (Application.IS_LINUX) {
                        IAction preferences = getAction(ActionFactory.PREFERENCES.getId());
                        preferences.setImageDescriptor(OwlUI.getImageDescriptor("icons/elcl16/preferences.gif")); //$NON-NLS-1$
                        editMenu.add(preferences);
                    } else
                        editMenu.add(getAction(ActionFactory.PROPERTIES.getId()));
                }
            });
        }

        /* Menu: View */
        private void createViewMenu(IMenuManager menuBar) {
            final IPreferenceScope globalPreferences = Owl.getPreferenceService().getGlobalScope();
            final IPreferenceScope eclipsePrefs = Owl.getPreferenceService().getEclipseScope();

            MenuManager viewMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_VIEW, M_VIEW);
            viewMenu.setRemoveAllWhenShown(true);
            menuBar.add(viewMenu);

            /* Add dummy action to show the top level menu */
            viewMenu.add(new Action("") { //$NON-NLS-1$
                @Override
                public void run() {
                }
            });

            /* Build Menu dynamically */
            viewMenu.addMenuListener(new IMenuListener() {
                public void menuAboutToShow(IMenuManager manager) {
                    final FeedView activeFeedView = OwlUI.getActiveFeedView();
                    final IPreferenceScope entityPreferences = OwlUI.getActiveFeedViewPreferences();
                    final Layout layout = OwlUI
                            .getLayout(entityPreferences != null ? entityPreferences : globalPreferences);
                    final PageSize pageSize = OwlUI
                            .getPageSize(entityPreferences != null ? entityPreferences : globalPreferences);

                    manager.add(new GroupMarker(M_VIEW_START));

                    /* Layout */
                    MenuManager layoutMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_LAYOUT);
                    layoutMenu.add(
                            new Action(Messages.ApplicationActionBarAdvisor_CLASSIC_LAYOUT, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                        updateLayoutPreferences(globalPreferences, entityPreferences, Layout.CLASSIC);
                                }

                                @Override
                                public boolean isChecked() {
                                    return layout == Layout.CLASSIC;
                                }
                            });

                    layoutMenu.add(
                            new Action(Messages.ApplicationActionBarAdvisor_VERTICAL_LAYOUT, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                        updateLayoutPreferences(globalPreferences, entityPreferences, Layout.VERTICAL);
                                }

                                @Override
                                public boolean isChecked() {
                                    return layout == Layout.VERTICAL;
                                }
                            });

                    layoutMenu
                            .add(new Action(Messages.ApplicationActionBarAdvisor_LIST_LAYOUT, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                        updateLayoutPreferences(globalPreferences, entityPreferences, Layout.LIST);
                                }

                                @Override
                                public boolean isChecked() {
                                    return layout == Layout.LIST;
                                }
                            });

                    layoutMenu.add(
                            new Action(Messages.ApplicationActionBarAdvisor_NEWSPAPER_LAYOUT, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                        updateLayoutPreferences(globalPreferences, entityPreferences, Layout.NEWSPAPER);
                                }

                                @Override
                                public boolean isChecked() {
                                    return layout == Layout.NEWSPAPER;
                                }
                            });

                    layoutMenu.add(
                            new Action(Messages.ApplicationActionBarAdvisor_HEADLINES_LAYOUT, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                        updateLayoutPreferences(globalPreferences, entityPreferences, Layout.HEADLINES);
                                }

                                @Override
                                public boolean isChecked() {
                                    return layout == Layout.HEADLINES;
                                }
                            });

                    /* Add the Page Size if using Newspaper or Headlines layout */
                    if (layout == Layout.NEWSPAPER || layout == Layout.HEADLINES) {
                        layoutMenu.add(new Separator());

                        MenuManager pageMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_PAGE_SIZE);

                        pageMenu.add(
                                new Action(Messages.ApplicationActionBarAdvisor_T_ARTICLES, IAction.AS_RADIO_BUTTON) {
                                    @Override
                                    public void run() {
                                        if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                            updatePageSizePreferences(globalPreferences, entityPreferences,
                                                    PageSize.TEN);
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return pageSize == PageSize.TEN;
                                    }
                                });

                        pageMenu.add(
                                new Action(Messages.ApplicationActionBarAdvisor_TF_ARTICLES, IAction.AS_RADIO_BUTTON) {
                                    @Override
                                    public void run() {
                                        if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                            updatePageSizePreferences(globalPreferences, entityPreferences,
                                                    PageSize.TWENTY_FIVE);
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return pageSize == PageSize.TWENTY_FIVE;
                                    }
                                });

                        pageMenu.add(
                                new Action(Messages.ApplicationActionBarAdvisor_F_ARTICLES, IAction.AS_RADIO_BUTTON) {
                                    @Override
                                    public void run() {
                                        if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                            updatePageSizePreferences(globalPreferences, entityPreferences,
                                                    PageSize.FIFTY);
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return pageSize == PageSize.FIFTY;
                                    }
                                });

                        pageMenu.add(
                                new Action(Messages.ApplicationActionBarAdvisor_H_ARTICLES, IAction.AS_RADIO_BUTTON) {
                                    @Override
                                    public void run() {
                                        if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                            updatePageSizePreferences(globalPreferences, entityPreferences,
                                                    PageSize.HUNDRED);
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return pageSize == PageSize.HUNDRED;
                                    }
                                });

                        pageMenu.add(new Separator());

                        pageMenu.add(
                                new Action(Messages.ApplicationActionBarAdvisor_ALL_ARTICLES, IAction.AS_RADIO_BUTTON) {
                                    @Override
                                    public void run() {
                                        if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                            updatePageSizePreferences(globalPreferences, entityPreferences,
                                                    PageSize.NO_PAGING);
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return pageSize == PageSize.NO_PAGING;
                                    }
                                });

                        layoutMenu.add(pageMenu);
                    }

                    manager.add(layoutMenu);

                    /* Columns */
                    final boolean isColumnsEnabled = (layout != Layout.NEWSPAPER && layout != Layout.HEADLINES);
                    MenuManager columnsMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_COLUMNS);
                    final NewsColumnViewModel model = NewsColumnViewModel
                            .loadFrom(entityPreferences != null ? entityPreferences : globalPreferences);
                    NewsColumn[] columns = NewsColumn.values();
                    for (final NewsColumn column : columns) {
                        if (column.isSelectable()) {
                            columnsMenu.add(new Action(column.getName(), IAction.AS_CHECK_BOX) {
                                @Override
                                public void run() {
                                    if (model.contains(column))
                                        model.removeColumn(column);
                                    else
                                        model.addColumn(column);

                                    updateColumnsPreferences(globalPreferences, entityPreferences, model,
                                            DefaultPreferences.BM_NEWS_COLUMNS);
                                }

                                @Override
                                public boolean isChecked() {
                                    return model.contains(column);
                                }

                                @Override
                                public boolean isEnabled() {
                                    return isColumnsEnabled;
                                };
                            });
                        }
                    }
                    columnsMenu.add(new Separator());
                    columnsMenu.add(new Action(Messages.ApplicationActionBarAdvisor_RESTORE_DEFAULT_COLUMNS) {
                        @Override
                        public void run() {
                            NewsColumnViewModel defaultModel = NewsColumnViewModel.createDefault(false);
                            updateColumnsPreferences(globalPreferences, entityPreferences, defaultModel,
                                    DefaultPreferences.BM_NEWS_COLUMNS, DefaultPreferences.BM_NEWS_SORT_COLUMN,
                                    DefaultPreferences.BM_NEWS_SORT_ASCENDING);
                        }

                        @Override
                        public boolean isEnabled() {
                            return isColumnsEnabled;
                        };
                    });

                    manager.add(columnsMenu);

                    /* Sorting */
                    MenuManager sortingMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_SORT_BY);
                    for (final NewsColumn column : columns) {
                        if (column.isSelectable()) {
                            sortingMenu.add(new Action(column.getName(), IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) { //Need to use parent scope to get real selection state from UI and not Model
                                        model.setSortColumn(column);
                                        updateColumnsPreferences(globalPreferences, entityPreferences, model,
                                                DefaultPreferences.BM_NEWS_SORT_COLUMN);
                                    }
                                }

                                @Override
                                public boolean isChecked() {
                                    return model.getSortColumn().equals(column);
                                }
                            });
                        }
                    }

                    sortingMenu.add(new Separator());

                    sortingMenu
                            .add(new Action(Messages.ApplicationActionBarAdvisor_ASCENDING, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) { //Need to use parent scope to get real selection state from UI and not Model
                                        model.setAscending(true);
                                        updateColumnsPreferences(globalPreferences, entityPreferences, model,
                                                DefaultPreferences.BM_NEWS_SORT_ASCENDING);
                                    }
                                }

                                @Override
                                public boolean isChecked() {
                                    return model.isAscending();
                                }
                            });

                    sortingMenu
                            .add(new Action(Messages.ApplicationActionBarAdvisor_DESCENDING, IAction.AS_RADIO_BUTTON) {
                                @Override
                                public void run() {
                                    if (super.isChecked()) { //Need to use parent scope to get real selection state from UI and not Model
                                        model.setAscending(false);
                                        updateColumnsPreferences(globalPreferences, entityPreferences, model,
                                                DefaultPreferences.BM_NEWS_SORT_ASCENDING);
                                    }
                                }

                                @Override
                                public boolean isChecked() {
                                    return !model.isAscending();
                                }
                            });

                    manager.add(sortingMenu);

                    /* News Filter */
                    manager.add(new Separator());
                    MenuManager filterMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_FILTER_NEWS);

                    int selectedFilterIndex;
                    if (entityPreferences != null)
                        selectedFilterIndex = ModelUtils.loadIntegerValueWithFallback(entityPreferences,
                                DefaultPreferences.BM_NEWS_FILTERING, globalPreferences,
                                DefaultPreferences.FV_FILTER_TYPE);
                    else
                        selectedFilterIndex = ModelUtils.loadIntegerValueWithFallback(globalPreferences,
                                DefaultPreferences.BM_NEWS_FILTERING, globalPreferences,
                                DefaultPreferences.FV_FILTER_TYPE);

                    final NewsFilter.Type selectedFilter = NewsFilter.Type.values()[selectedFilterIndex];
                    NewsFilter.Type[] filters = new NewsFilter.Type[] { NewsFilter.Type.SHOW_ALL,
                            NewsFilter.Type.SHOW_NEW, NewsFilter.Type.SHOW_UNREAD, NewsFilter.Type.SHOW_STICKY,
                            NewsFilter.Type.SHOW_LABELED, NewsFilter.Type.SHOW_RECENT,
                            NewsFilter.Type.SHOW_LAST_5_DAYS };
                    for (final NewsFilter.Type filter : filters) {
                        filterMenu.add(new Action(filter.getName(), IAction.AS_RADIO_BUTTON) {
                            @Override
                            public void run() {
                                if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                    updateFilterAndGroupingPreferences(globalPreferences, entityPreferences, filter,
                                            null);
                            };

                            @Override
                            public boolean isChecked() {
                                return filter == selectedFilter;
                            };
                        });

                        /* Add Separators to improve readability of filter options */
                        if (filter == NewsFilter.Type.SHOW_ALL || filter == NewsFilter.Type.SHOW_UNREAD
                                || filter == NewsFilter.Type.SHOW_LABELED)
                            filterMenu.add(new Separator());
                    }

                    manager.add(filterMenu);

                    /* News Grouping */
                    MenuManager groupMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_GROUP_NEWS);

                    int selectedGroupIndex;
                    if (entityPreferences != null)
                        selectedGroupIndex = ModelUtils.loadIntegerValueWithFallback(entityPreferences,
                                DefaultPreferences.BM_NEWS_GROUPING, globalPreferences,
                                DefaultPreferences.FV_GROUP_TYPE);
                    else
                        selectedGroupIndex = ModelUtils.loadIntegerValueWithFallback(globalPreferences,
                                DefaultPreferences.BM_NEWS_GROUPING, globalPreferences,
                                DefaultPreferences.FV_GROUP_TYPE);

                    final NewsGrouping.Type selectedGroup = NewsGrouping.Type.values()[selectedGroupIndex];
                    NewsGrouping.Type[] groups = new NewsGrouping.Type[] { NewsGrouping.Type.NO_GROUPING,
                            NewsGrouping.Type.GROUP_BY_DATE, NewsGrouping.Type.GROUP_BY_AUTHOR,
                            NewsGrouping.Type.GROUP_BY_CATEGORY, NewsGrouping.Type.GROUP_BY_TOPIC,
                            NewsGrouping.Type.GROUP_BY_FEED, NewsGrouping.Type.GROUP_BY_STATE,
                            NewsGrouping.Type.GROUP_BY_STICKY, NewsGrouping.Type.GROUP_BY_LABEL };
                    for (final NewsGrouping.Type group : groups) {
                        groupMenu.add(new Action(group.getName(), IAction.AS_RADIO_BUTTON) {
                            @Override
                            public void run() {
                                if (super.isChecked()) //Need to use parent scope to get real selection state from UI and not Model
                                    updateFilterAndGroupingPreferences(globalPreferences, entityPreferences, null,
                                            group);
                            };

                            @Override
                            public boolean isChecked() {
                                return group == selectedGroup;
                            };
                        });

                        /* Add Separators to improve readability of grouping options */
                        if (group == NewsGrouping.Type.NO_GROUPING || group == NewsGrouping.Type.GROUP_BY_FEED
                                || group == NewsGrouping.Type.GROUP_BY_STICKY)
                            groupMenu.add(new Separator());
                    }

                    manager.add(groupMenu);

                    /* Zoom (In, Out, Reset) */
                    final boolean isZoomingEnabled = (activeFeedView != null && activeFeedView.isBrowserShowingNews());
                    manager.add(new Separator());
                    MenuManager zoomMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_ZOOM);

                    /* Zoom In */
                    zoomMenu.add(new Action(Messages.ApplicationActionBarAdvisor_ZOOM_IN) {
                        @Override
                        public void run() {
                            OwlUI.zoomNewsText(true, false);
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.ZoomInCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.ZoomInCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public boolean isEnabled() {
                            return isZoomingEnabled;
                        }
                    });

                    /* Zoom Out */
                    zoomMenu.add(new Action(Messages.ApplicationActionBarAdvisor_ZOOM_OUT) {
                        @Override
                        public void run() {
                            OwlUI.zoomNewsText(false, false);
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.ZoomOutCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.ZoomOutCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public boolean isEnabled() {
                            return isZoomingEnabled;
                        }
                    });

                    /* Reset */
                    zoomMenu.add(new Separator());
                    zoomMenu.add(new Action(Messages.ApplicationActionBarAdvisor_RESET) {
                        @Override
                        public void run() {
                            OwlUI.zoomNewsText(false, true);
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.ZoomResetCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.ZoomResetCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public boolean isEnabled() {
                            return isZoomingEnabled;
                        }
                    });

                    manager.add(zoomMenu);

                    /* Toolbars */
                    manager.add(new Separator());
                    final MenuManager toolbarsMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_TOOLBARS);
                    toolbarsMenu.setRemoveAllWhenShown(true);
                    toolbarsMenu.addMenuListener(new IMenuListener() {
                        public void menuAboutToShow(IMenuManager manager) {
                            boolean useExternalBrowser = OwlUI.useExternalBrowser();

                            /* Main Toolbar */
                            toolbarsMenu.add(
                                    new Action(Messages.ApplicationActionBarAdvisor_TOOLBAR, IAction.AS_CHECK_BOX) {
                                        @Override
                                        public void run() {
                                            ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.fgPrimaryApplicationWorkbenchWindowAdvisor;

                                            boolean isMainToolBarVisible = globalPreferences
                                                    .getBoolean(DefaultPreferences.SHOW_TOOLBAR);
                                            configurer.setToolBarVisible(!isMainToolBarVisible, true);
                                            globalPreferences.putBoolean(DefaultPreferences.SHOW_TOOLBAR,
                                                    !isMainToolBarVisible);
                                        }

                                        @Override
                                        public boolean isChecked() {
                                            return globalPreferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
                                        }
                                    });

                            /* Feed Toolbar */
                            toolbarsMenu.add(new Action(Messages.ApplicationActionBarAdvisor_FEED_TOOLBAR,
                                    IAction.AS_CHECK_BOX) {
                                @Override
                                public void run() {
                                    boolean isFeedToolBarHidden = globalPreferences
                                            .getBoolean(DefaultPreferences.FV_FEED_TOOLBAR_HIDDEN);
                                    globalPreferences.putBoolean(DefaultPreferences.FV_FEED_TOOLBAR_HIDDEN,
                                            !isFeedToolBarHidden);

                                    /* Update opened Feedviews */
                                    EditorUtils.updateToolbarVisibility();
                                }

                                @Override
                                public boolean isChecked() {
                                    return !globalPreferences.getBoolean(DefaultPreferences.FV_FEED_TOOLBAR_HIDDEN);
                                }
                            });

                            /* Browser Toolbar */
                            if (!useExternalBrowser) {
                                toolbarsMenu.add(new Action(Messages.ApplicationActionBarAdvisor_BROWSER_TOOLBAR,
                                        IAction.AS_CHECK_BOX) {
                                    @Override
                                    public void run() {
                                        boolean isBrowserToolBarHidden = globalPreferences
                                                .getBoolean(DefaultPreferences.FV_BROWSER_TOOLBAR_HIDDEN);
                                        globalPreferences.putBoolean(DefaultPreferences.FV_BROWSER_TOOLBAR_HIDDEN,
                                                !isBrowserToolBarHidden);

                                        /* Update opened Feedviews */
                                        EditorUtils.updateToolbarVisibility();
                                    }

                                    @Override
                                    public boolean isChecked() {
                                        return !globalPreferences
                                                .getBoolean(DefaultPreferences.FV_BROWSER_TOOLBAR_HIDDEN);
                                    }
                                });
                            }
                        }
                    });
                    manager.add(toolbarsMenu);

                    /* Toggle State of Status Bar Visibility */
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_STATUS, IAction.AS_CHECK_BOX) {
                        @Override
                        public void run() {
                            ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.fgPrimaryApplicationWorkbenchWindowAdvisor;

                            boolean isStatusVisible = globalPreferences.getBoolean(DefaultPreferences.SHOW_STATUS);
                            configurer.setStatusVisible(!isStatusVisible, true);
                            globalPreferences.putBoolean(DefaultPreferences.SHOW_STATUS, !isStatusVisible);
                        }

                        @Override
                        public boolean isChecked() {
                            return globalPreferences.getBoolean(DefaultPreferences.SHOW_STATUS);
                        }
                    });

                    /* Toggle State of Bookmarks Visibility */
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_BOOKMARKS, IAction.AS_CHECK_BOX) {
                        @Override
                        public void run() {
                            OwlUI.toggleBookmarks();
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.ToggleBookmarksCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.ToggleBookmarksCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public boolean isChecked() {
                            IWorkbenchPage page = OwlUI.getPage();
                            if (page != null)
                                return page.findView(BookMarkExplorer.VIEW_ID) != null;

                            return false;
                        }
                    });

                    /* Customize Toolbar */
                    manager.add(new Separator());
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_CUSTOMIZE_TOOLBAR) {
                        @Override
                        public void run() {

                            /* Unhide Toolbar if hidden */
                            ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.fgPrimaryApplicationWorkbenchWindowAdvisor;

                            boolean isToolBarVisible = globalPreferences.getBoolean(DefaultPreferences.SHOW_TOOLBAR);
                            if (!isToolBarVisible) {
                                configurer.setToolBarVisible(true, true);
                                globalPreferences.putBoolean(DefaultPreferences.SHOW_TOOLBAR, true);
                            }

                            /* Open Dialog to Customize Toolbar */
                            CustomizeToolbarDialog dialog = new CustomizeToolbarDialog(
                                    getActionBarConfigurer().getWindowConfigurer().getWindow().getShell());
                            if (dialog.open() == IDialogConstants.OK_ID)
                                fCoolBarAdvisor.advise(true);
                        }
                    });

                    /* Tabbed Browsing */
                    manager.add(new Separator());
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_TABBED_BROWSING, IAction.AS_CHECK_BOX) {
                        @Override
                        public void run() {
                            boolean tabbedBrowsingEnabled = isChecked();

                            /* Disable Tabbed Browsing */
                            if (tabbedBrowsingEnabled) {

                                /* Close other Tabs if necessary */
                                boolean doit = true;
                                IWorkbenchPage page = OwlUI.getPage();
                                if (page != null) {
                                    IEditorReference[] editorReferences = page.getEditorReferences();
                                    if (editorReferences.length > 1) {
                                        MessageBox confirmDialog = new MessageBox(page.getWorkbenchWindow().getShell(),
                                                SWT.ICON_QUESTION | SWT.YES | SWT.NO);
                                        confirmDialog
                                                .setText(Messages.ApplicationActionBarAdvisor_DISABLE_TABBED_BROWSING);
                                        confirmDialog
                                                .setMessage(NLS.bind(Messages.ApplicationActionBarAdvisor_TABS_MESSAGE,
                                                        editorReferences.length));
                                        if (confirmDialog.open() == SWT.YES)
                                            OwlUI.closeOtherEditors();
                                        else
                                            doit = false;
                                    }
                                }

                                /* Update Preferences */
                                if (doit) {
                                    eclipsePrefs.putBoolean(DefaultPreferences.ECLIPSE_MULTIPLE_TABS, false);
                                    eclipsePrefs.putBoolean(DefaultPreferences.ECLIPSE_AUTOCLOSE_TABS, true);
                                    eclipsePrefs.putInteger(DefaultPreferences.ECLIPSE_AUTOCLOSE_TABS_THRESHOLD, 1);
                                }
                            }

                            /* Enable Tabbed Browsing */
                            else {
                                eclipsePrefs.putBoolean(DefaultPreferences.ECLIPSE_MULTIPLE_TABS, true);
                                eclipsePrefs.putBoolean(DefaultPreferences.ECLIPSE_AUTOCLOSE_TABS, false);
                                eclipsePrefs.putInteger(DefaultPreferences.ECLIPSE_AUTOCLOSE_TABS_THRESHOLD, 5);
                            }
                        }

                        @Override
                        public boolean isChecked() {
                            return OwlUI.isTabbedBrowsingEnabled();
                        }
                    });

                    /* Fullscreen Mode */
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_FULL_SCREEN, IAction.AS_CHECK_BOX) {
                        @Override
                        public void run() {
                            OwlUI.toggleFullScreen();
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.FullScreenCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.FullScreenCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public boolean isChecked() {
                            Shell shell = OwlUI.getActiveShell();
                            if (shell != null)
                                return shell.getFullScreen();

                            return super.isChecked();
                        }
                    });

                    /* Minimize */
                    manager.add(new Action(Messages.ApplicationActionBarAdvisor_MINIMIZE) {
                        @Override
                        public void run() {
                            Shell shell = OwlUI.getActiveShell();
                            if (shell != null)
                                shell.setMinimized(true);
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return "org.rssowl.ui.MinimizeCommand"; //$NON-NLS-1$
                        }

                        @Override
                        public String getId() {
                            return "org.rssowl.ui.MinimizeCommand"; //$NON-NLS-1$
                        }
                    });

                    manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
                    manager.add(new GroupMarker(M_VIEW_START));
                }
            });
        }

        private void updatePageSizePreferences(IPreferenceScope globalPreferences, IPreferenceScope entityPreferences,
                PageSize pageSize) {

            /* Update Global */
            globalPreferences.putInteger(DefaultPreferences.NEWS_BROWSER_PAGE_SIZE, pageSize.getPageSize());

            /* Update Entity if it was configured explicitly */
            if (entityPreferences != null) {
                if (entityPreferences.hasKey(DefaultPreferences.NEWS_BROWSER_PAGE_SIZE)) {
                    entityPreferences.delete(DefaultPreferences.NEWS_BROWSER_PAGE_SIZE);
                    entityPreferences.flush();
                }
            }
        }

        private void updateLayoutPreferences(IPreferenceScope globalPreferences, IPreferenceScope entityPreferences,
                Layout layout) {

            /* Update Global */
            globalPreferences.putInteger(DefaultPreferences.FV_LAYOUT, layout.ordinal());

            /* Update Entity if it was configured explicitly */
            if (entityPreferences != null) {
                if (entityPreferences.hasKey(DefaultPreferences.FV_LAYOUT)) {
                    entityPreferences.delete(DefaultPreferences.FV_LAYOUT);
                    entityPreferences.flush();
                }
            }

            /* Update Feed Views */
            EditorUtils.updateLayout();
        }

        private void updateFilterAndGroupingPreferences(IPreferenceScope globalPreferences,
                IPreferenceScope entityPreferences, NewsFilter.Type filter, NewsGrouping.Type grouping) {

            /* Update Global */
            if (filter != null)
                globalPreferences.putInteger(DefaultPreferences.BM_NEWS_FILTERING, filter.ordinal());
            if (grouping != null)
                globalPreferences.putInteger(DefaultPreferences.BM_NEWS_GROUPING, grouping.ordinal());

            /* Update Entity if it was configured explicitly */
            if (entityPreferences != null) {
                boolean flush = false;

                if (filter != null && entityPreferences.hasKey(DefaultPreferences.BM_NEWS_FILTERING)) {
                    entityPreferences.delete(DefaultPreferences.BM_NEWS_FILTERING);
                    flush = true;
                }

                if (grouping != null && entityPreferences.hasKey(DefaultPreferences.BM_NEWS_GROUPING)) {
                    entityPreferences.delete(DefaultPreferences.BM_NEWS_GROUPING);
                    flush = true;
                }

                if (flush)
                    entityPreferences.flush();
            }

            /* Update Feed Views */
            EditorUtils.updateFilterAndGrouping();
        }

        private void updateColumnsPreferences(IPreferenceScope globalPreferences, IPreferenceScope entityPreferences,
                NewsColumnViewModel model, String... prefKeys) {

            /* Update Global */
            boolean saveColumns = contains(DefaultPreferences.BM_NEWS_COLUMNS, prefKeys);
            boolean saveSortColumn = contains(DefaultPreferences.BM_NEWS_SORT_COLUMN, prefKeys);
            boolean saveSortDirection = contains(DefaultPreferences.BM_NEWS_SORT_ASCENDING, prefKeys);

            model.saveTo(globalPreferences, false, saveColumns, saveSortColumn, saveSortDirection);

            /* Update Entity if it was configured explicitly */
            if (entityPreferences != null && prefKeys != null) {
                boolean flush = false;

                for (String prefKey : prefKeys) {
                    if (entityPreferences.hasKey(prefKey)) {
                        entityPreferences.delete(prefKey);
                        flush = true;
                    }
                }

                if (flush)
                    entityPreferences.flush();
            }

            /* Update Feed Views */
            EditorUtils.updateColumns();
        }

        private boolean contains(String key, String... elements) {
            if (elements == null)
                return false;

            for (String element : elements) {
                if (key.equals(element))
                    return true;
            }

            return false;
        }

        /* Menu: Go */
        private void createGoMenu(IMenuManager menuBar) {
            MenuManager goMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_GO,
                    IWorkbenchActionConstants.M_NAVIGATE);
            menuBar.add(goMenu);

            goMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
            goMenu.add(fReopenEditors);
        }

        /* Menu: Bookmarks */
        private void createBookMarksMenu(IMenuManager menuBar) {
            MenuManager bmMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_BOOKMARKS, "bookmarks"); //$NON-NLS-1$
            bmMenu.setRemoveAllWhenShown(true);
            bmMenu.add(new Action("") {
//$NON-NLS-0$
            }); //Dummy Action 
            bmMenu.addMenuListener(new IMenuListener() {
                public void menuAboutToShow(IMenuManager manager) {
                    fillBookMarksMenu(manager, getActionBarConfigurer().getWindowConfigurer().getWindow());
                    manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
                }
            });

            menuBar.add(bmMenu);
        }

        /* Menu News */
        private void createNewsMenu(IMenuManager menuBar) {
            final MenuManager newsMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_NEWS, "news"); //$NON-NLS-1$
            menuBar.add(newsMenu);
            newsMenu.setRemoveAllWhenShown(true);

            newsMenu.addMenuListener(new IMenuListener() {
                public void menuAboutToShow(IMenuManager manager) {
                    final IStructuredSelection selection;

                    FeedView activeFeedView = OwlUI.getActiveFeedView();
                    FeedViewInput activeInput = null;
                    if (activeFeedView != null) {
                        selection = (IStructuredSelection) activeFeedView.getSite().getSelectionProvider()
                                .getSelection();
                        activeInput = (FeedViewInput) activeFeedView.getEditorInput();
                    } else
                        selection = StructuredSelection.EMPTY;

                    boolean isEntityGroupSelected = ModelUtils.isEntityGroupSelected(selection);

                    /* Open */
                    if (!isEntityGroupSelected) {
                        manager.add(new Separator("open")); //$NON-NLS-1$

                        /* Open News in Browser */
                        manager.add(new OpenInBrowserAction(selection,
                                WebBrowserContext.createFrom(selection, activeFeedView)) {
                            @Override
                            public boolean isEnabled() {
                                return !selection.isEmpty();
                            }
                        });

                        /* Open Externally - Show only when internal browser is used */
                        if (!selection.isEmpty() && !OwlUI.useExternalBrowser())
                            manager.add(new OpenInExternalBrowserAction(selection));
                    }

                    /* Attachments */
                    {
                        fillAttachmentsMenu(manager, selection,
                                getActionBarConfigurer().getWindowConfigurer().getWindow(), false);
                    }

                    /* Mark / Label */
                    {
                        manager.add(new Separator("mark")); //$NON-NLS-1$

                        /* Mark */
                        {
                            MenuManager markMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_MARK, "mark"); //$NON-NLS-1$
                            manager.add(markMenu);

                            /* Mark as Read */
                            IAction action = new ToggleReadStateAction(selection);
                            action.setEnabled(!selection.isEmpty());
                            markMenu.add(action);

                            /* Mark All Read */
                            action = new MarkAllNewsReadAction();
                            action.setEnabled(activeFeedView != null);
                            markMenu.add(action);

                            /* Sticky */
                            markMenu.add(new Separator());
                            action = new MakeNewsStickyAction(selection);
                            action.setEnabled(!selection.isEmpty());
                            markMenu.add(action);
                        }

                        /* Label */
                        fillLabelMenu(manager, selection, getActionBarConfigurer().getWindowConfigurer().getWindow(),
                                false);
                    }

                    /* Move To / Copy To */
                    if (!selection.isEmpty()) {
                        manager.add(new Separator("movecopy")); //$NON-NLS-1$

                        /* Load all news bins and sort by name */
                        List<INewsBin> newsbins = new ArrayList<INewsBin>(DynamicDAO.loadAll(INewsBin.class));

                        Comparator<INewsBin> comparator = new Comparator<INewsBin>() {
                            public int compare(INewsBin o1, INewsBin o2) {
                                return o1.getName().compareTo(o2.getName());
                            };
                        };

                        Collections.sort(newsbins, comparator);

                        /* Move To */
                        MenuManager moveMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_MOVE_TO, "moveto"); //$NON-NLS-1$
                        manager.add(moveMenu);

                        for (INewsBin bin : newsbins) {
                            if (activeInput != null && activeInput.getMark().equals(bin))
                                continue;

                            moveMenu.add(new MoveCopyNewsToBinAction(selection, bin, true));
                        }

                        moveMenu.add(new MoveCopyNewsToBinAction(selection, null, true));
                        moveMenu.add(new Separator());
                        moveMenu.add(new AutomateFilterAction(PresetAction.MOVE, selection));

                        /* Copy To */
                        MenuManager copyMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_COPY_TO, "copyto"); //$NON-NLS-1$
                        manager.add(copyMenu);

                        for (INewsBin bin : newsbins) {
                            if (activeInput != null && activeInput.getMark().equals(bin))
                                continue;

                            copyMenu.add(new MoveCopyNewsToBinAction(selection, bin, false));
                        }

                        copyMenu.add(new MoveCopyNewsToBinAction(selection, null, false));
                        copyMenu.add(new Separator());
                        copyMenu.add(new AutomateFilterAction(PresetAction.COPY, selection));

                        /* Archive */
                        manager.add(new ArchiveNewsAction(selection));
                    }

                    /* Share */
                    fillShareMenu(manager, selection, getActionBarConfigurer().getWindowConfigurer().getWindow(),
                            false);

                    /* Filter */
                    if (!selection.isEmpty()) {
                        manager.add(new Separator("filter")); //$NON-NLS-1$

                        /* Create Filter */
                        manager.add(new Action(Messages.ApplicationActionBarAdvisor_CREATE_FILTER) {
                            @Override
                            public void run() {
                                CreateFilterAction action = new CreateFilterAction();
                                action.selectionChanged(null, selection);
                                action.run(null);
                            }

                            @Override
                            public ImageDescriptor getImageDescriptor() {
                                return OwlUI.FILTER;
                            }

                            @Override
                            public String getActionDefinitionId() {
                                return CreateFilterAction.ID;
                            };

                            @Override
                            public String getId() {
                                return CreateFilterAction.ID;
                            };
                        });
                    }

                    /* Update */
                    {
                        manager.add(new Separator("reload")); //$NON-NLS-1$

                        /* Update */
                        manager.add(new Action(Messages.ApplicationActionBarAdvisor_UPDATE) {
                            @Override
                            public void run() {
                                IActionDelegate action = new ReloadTypesAction();
                                action.selectionChanged(null, selection);
                                action.run(null);
                            }

                            @Override
                            public ImageDescriptor getImageDescriptor() {
                                return OwlUI.getImageDescriptor("icons/elcl16/reload.gif"); //$NON-NLS-1$
                            }

                            @Override
                            public ImageDescriptor getDisabledImageDescriptor() {
                                return OwlUI.getImageDescriptor("icons/dlcl16/reload.gif"); //$NON-NLS-1$
                            }

                            @Override
                            public boolean isEnabled() {
                                return !selection.isEmpty() || OwlUI.getActiveFeedView() != null;
                            }

                            @Override
                            public String getActionDefinitionId() {
                                return ReloadTypesAction.ID;
                            }

                            @Override
                            public String getId() {
                                return ReloadTypesAction.ID;
                            }
                        });

                        /* Update All */
                        manager.add(new ReloadAllAction());
                    }

                    manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
                }
            });
        }

        /* Menu: Tools */
        private void createToolsMenu(IMenuManager menuBar) {
            MenuManager toolsMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_TOOLS, OwlUI.M_TOOLS);
            menuBar.add(toolsMenu);

            /* Contributions */
            toolsMenu.add(new GroupMarker("begin")); //$NON-NLS-1$
            toolsMenu.add(new Separator());
            toolsMenu.add(new GroupMarker("middle")); //$NON-NLS-1$
            toolsMenu.add(new Separator("addons")); //$NON-NLS-1$
            toolsMenu.add(new Separator());
            toolsMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
            toolsMenu.add(new Separator());
            toolsMenu.add(new GroupMarker("end")); //$NON-NLS-1$

            /* Preferences (Windows, Mac) */
            if (!Application.IS_LINUX) {
                toolsMenu.add(new Separator());
                IAction preferences = getAction(ActionFactory.PREFERENCES.getId());
                preferences.setImageDescriptor(OwlUI.getImageDescriptor("icons/elcl16/preferences.gif")); //$NON-NLS-1$
                toolsMenu.add(preferences);
                if (Application.IS_MAC) {
                    IContributionItem item = toolsMenu.find(ActionFactory.PREFERENCES.getId());
                    if (item != null)
                        item.setVisible(false);
                }
            }
        }

        /* Menu: Window */
        private void createWindowMenu(IMenuManager menuBar) {
            MenuManager windowMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_WINDOW,
                    IWorkbenchActionConstants.M_WINDOW);
            menuBar.add(windowMenu);

            IAction openNewWindowAction = getAction(ActionFactory.OPEN_NEW_WINDOW.getId());
            openNewWindowAction.setImageDescriptor(OwlUI.getImageDescriptor("icons/elcl16/newwindow.gif")); //$NON-NLS-1$
            windowMenu.add(openNewWindowAction);

            windowMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
            windowMenu.add(fOpenWindowsItem);

            //    MenuManager showViewMenu = new MenuManager("&Show View");
            //    windowMenu.add(showViewMenu);
            //    showViewMenu.add(fShowViewMenu);
            //    windowMenu.add(new Separator());

            //    windowMenu.add(getAction(ActionFactory.EDIT_ACTION_SETS.getId()));
            //    windowMenu.add(getAction(ActionFactory.RESET_PERSPECTIVE.getId()));
            //    windowMenu.add(new Separator());
            //
            //    MenuManager navigationMenu = new MenuManager("&Navigation");
            //    windowMenu.add(navigationMenu);
            //
            //    navigationMenu.add(getAction(ActionFactory.SHOW_PART_PANE_MENU.getId()));
            //    navigationMenu.add(getAction(ActionFactory.SHOW_VIEW_MENU.getId()));
            //    navigationMenu.add(new Separator());
            //    navigationMenu.add(getAction(ActionFactory.MAXIMIZE.getId()));
            //    navigationMenu.add(getAction(ActionFactory.MINIMIZE.getId()));
            //    navigationMenu.add(new Separator());
            //    navigationMenu.add(getAction(ActionFactory.ACTIVATE_EDITOR.getId()));
            //    navigationMenu.add(getAction(ActionFactory.SHOW_EDITOR.getId()));
            //    navigationMenu.add(getAction(ActionFactory.NEXT_EDITOR.getId()));
            //    navigationMenu.add(getAction(ActionFactory.PREVIOUS_EDITOR.getId()));
            //    navigationMenu.add(getAction(ActionFactory.SHOW_OPEN_EDITORS.getId()));
            //    navigationMenu.add(getAction(ActionFactory.SHOW_WORKBOOK_EDITORS.getId()));
            //    navigationMenu.add(new Separator());
            //    navigationMenu.add(getAction(ActionFactory.NEXT_PART.getId()));
            //    navigationMenu.add(getAction(ActionFactory.PREVIOUS_PART.getId()));
        }

        /* Menu: Help */
        private void createHelpMenu(IMenuManager menuBar) {
            MenuManager helpMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_HELP,
                    IWorkbenchActionConstants.M_HELP);
            menuBar.add(helpMenu);

            helpMenu.add(new GroupMarker(IWorkbenchActionConstants.HELP_START));

            /* Tutorial Wizard */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_TUTORIAL) {
                @Override
                public void run() {
                    TutorialWizard wizard = new TutorialWizard();
                    OwlUI.openWizard(getActionBarConfigurer().getWindowConfigurer().getWindow().getShell(), wizard,
                            false, false, null);
                }

                @Override
                public ImageDescriptor getImageDescriptor() {
                    return OwlUI.getImageDescriptor("icons/elcl16/help.gif"); //$NON-NLS-1$
                }

                @Override
                public String getId() {
                    return TutorialHandler.ID;
                }

                @Override
                public String getActionDefinitionId() {
                    return TutorialHandler.ID;
                }
            });

            /* Google Reader Synchronization */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_GOOGLE_READER_SYNC) {
                @Override
                public void run() {
                    TutorialWizard wizard = new TutorialWizard(Chapter.SYNCHRONIZATION);
                    OwlUI.openWizard(getActionBarConfigurer().getWindowConfigurer().getWindow().getShell(), wizard,
                            false, false, null);
                }
            });

            /* Link to Help */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_FAQ) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://www.rssowl.org/help"); //$NON-NLS-1$
                }
            });

            /* Link to Forum */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_VISIT_FORUM) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://sourceforge.net/projects/rssowl/forums/forum/296910"); //$NON-NLS-1$
                }

                @Override
                public ImageDescriptor getImageDescriptor() {
                    return OwlUI.getImageDescriptor("icons/obj16/forum.gif"); //$NON-NLS-1$
                }
            });

            /* Show Key Bindings */
            helpMenu.add(new Separator());
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_SHOW_KEY_BINDINGS) {
                @Override
                public void run() {
                    IWorkbench workbench = PlatformUI.getWorkbench();
                    IBindingService bindingService = (IBindingService) workbench.getService(IBindingService.class);
                    bindingService.openKeyAssistDialog();
                }
            });

            helpMenu.add(new Separator());

            /* Report Bugs */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_REPORT_PROBLEMS) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://dev.rssowl.org"); //$NON-NLS-1$
                }

                @Override
                public ImageDescriptor getImageDescriptor() {
                    return OwlUI.getImageDescriptor("icons/elcl16/bug.gif"); //$NON-NLS-1$
                }
            });

            /* Export Log to File */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_EXPORT_LOGFILE) {
                @Override
                public void run() {
                    FileDialog dialog = new FileDialog(
                            getActionBarConfigurer().getWindowConfigurer().getWindow().getShell(), SWT.SAVE);
                    dialog.setText(Messages.ApplicationActionBarAdvisor_EXPORT_LOGFILE_DIALOG);
                    dialog.setFilterExtensions(new String[] { "*.log" }); //$NON-NLS-1$
                    dialog.setFileName("rssowl.log"); //$NON-NLS-1$
                    dialog.setOverwrite(true);

                    String file = dialog.open();
                    if (StringUtils.isSet(file)) {
                        try {

                            /* Check for Log Message from Core to have a complete log */
                            String logMessages = CoreUtils.getAndFlushLogMessages();
                            if (logMessages != null && logMessages.length() > 0)
                                Activator.safeLogError(logMessages, null);

                            /* Help to find out where the log is coming from */
                            Activator.safeLogInfo("Error Log Exported"); //$NON-NLS-1$

                            /* Export Log File */
                            File logFile = Platform.getLogFileLocation().toFile();
                            InputStream inS;
                            if (logFile.exists())
                                inS = new FileInputStream(logFile);
                            else
                                inS = new ByteArrayInputStream(new byte[0]);
                            FileOutputStream outS = new FileOutputStream(new File(file));
                            CoreUtils.copy(inS, outS);

                            /* Append a Report of Feeds that are not loading if any */
                            String nl = System.getProperty("line.separator"); //$NON-NLS-1$
                            if (!StringUtils.isSet(nl))
                                nl = "\n"; //$NON-NLS-1$

                            StringBuilder errorReport = new StringBuilder();
                            Collection<IBookMark> bookmarks = DynamicDAO.getDAO(IBookMarkDAO.class).loadAll();
                            for (IBookMark bookmark : bookmarks) {
                                if (bookmark.isErrorLoading()) {
                                    Object errorObj = bookmark.getProperty(Controller.LOAD_ERROR_KEY);
                                    if (errorObj != null && errorObj instanceof String) {
                                        errorReport.append(Controller.getDefault().createLogEntry(bookmark, null,
                                                (String) errorObj));
                                        errorReport.append(nl).append(nl);
                                    }
                                }
                            }

                            if (errorReport.length() > 0) {
                                FileWriter writer = new FileWriter(new File(file), true);
                                try {
                                    writer.append(nl).append(nl).append(nl);
                                    writer.write(
                                            "--- Summary of Feeds that are not Loading -----------------------------------------------"); //$NON-NLS-1$
                                    writer.append(nl).append(nl);
                                    writer.write(errorReport.toString());
                                    writer.close();
                                } finally {
                                    writer.close();
                                }
                            }
                        } catch (FileNotFoundException e) {
                            Activator.getDefault().logError(e.getMessage(), e);
                        } catch (IOException e) {
                            Activator.getDefault().logError(e.getMessage(), e);
                        }
                    }
                }
            });

            helpMenu.add(new Separator());

            /* Homepage */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_HOMEPAGE) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://www.rssowl.org"); //$NON-NLS-1$
                }
            });

            /* License */
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_LICENSE) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://www.rssowl.org/legal/epl-v10.html"); //$NON-NLS-1$
                }
            });

            /* Donate */
            helpMenu.add(new Separator());
            helpMenu.add(new Action(Messages.ApplicationActionBarAdvisor_DONATE) {
                @Override
                public void run() {
                    BrowserUtils.openLinkExternal("http://sourceforge.net/donate/index.php?group_id=86683"); //$NON-NLS-1$
                }
            });

            helpMenu.add(new Separator());

            helpMenu.add(new Separator());
            helpMenu.add(new GroupMarker(IWorkbenchActionConstants.HELP_END));
            helpMenu.add(new Separator());

            helpMenu.add(getAction(ActionFactory.ABOUT.getId()));
            if (Application.IS_MAC) {
                IContributionItem item = helpMenu.find(ActionFactory.ABOUT.getId());
                if (item != null)
                    item.setVisible(false);
            }
        }

        /*
         * @see org.eclipse.ui.application.ActionBarAdvisor#fillStatusLine(org.eclipse.jface.action.IStatusLineManager)
         */
        @Override
        protected void fillStatusLine(IStatusLineManager statusLine) {
            super.fillStatusLine(statusLine);
        }

        /*
         * @see org.eclipse.ui.application.ActionBarAdvisor#fillActionBars(int)
         */
        @Override
        public void fillActionBars(int flags) {
            super.fillActionBars(flags);
        }

        /**
         * @param trayItem
         * @param shell
         * @param advisor
         */
        protected void fillTrayItem(IMenuManager trayItem, final Shell shell,
                final ApplicationWorkbenchWindowAdvisor advisor) {
            trayItem.add(new ReloadAllAction(false));
            trayItem.add(new Separator());

            trayItem.add(new Action(Messages.ApplicationActionBarAdvisor_CONFIGURE_NOTIFICATIONS) {
                @Override
                public void run() {
                    advisor.restoreFromTray(shell);
                    PreferencesUtil.createPreferenceDialogOn(shell, NotifierPreferencesPage.ID, null, null).open();
                }

                @Override
                public ImageDescriptor getImageDescriptor() {
                    return OwlUI.getImageDescriptor("icons/elcl16/notification.gif"); //$NON-NLS-1$
                }
            });

            trayItem.add(new Action(Messages.ApplicationActionBarAdvisor_PREFERENCES) {
                @Override
                public void run() {
                    advisor.restoreFromTray(shell);
                    PreferencesUtil.createPreferenceDialogOn(shell, OverviewPreferencesPage.ID, null, null).open();
                }

                @Override
                public ImageDescriptor getImageDescriptor() {
                    return OwlUI.getImageDescriptor("icons/elcl16/preferences.gif"); //$NON-NLS-1$
                }
            });

            trayItem.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

            trayItem.add(new Action(Messages.ApplicationActionBarAdvisor_EXIT) {
                @Override
                public void run() {
                    PlatformUI.getWorkbench().close();
                }
            });
        }

        /*
         * @see org.eclipse.ui.application.ActionBarAdvisor#fillCoolBar(org.eclipse.jface.action.ICoolBarManager)
         */
        @Override
        protected void fillCoolBar(ICoolBarManager coolBar) {

            /* CoolBar Context Menu */
            MenuManager coolBarContextMenuManager = new MenuManager(null, "org.rssowl.ui.CoolBarContextMenu"); //$NON-NLS-1$
            coolBar.setContextMenuManager(coolBarContextMenuManager);

            /* Customize Coolbar */
            coolBarContextMenuManager.add(new Action(Messages.ApplicationActionBarAdvisor_CUSTOMIZE_TOOLBAR) {
                @Override
                public void run() {
                    CustomizeToolbarDialog dialog = new CustomizeToolbarDialog(
                            getActionBarConfigurer().getWindowConfigurer().getWindow().getShell());
                    if (dialog.open() == IDialogConstants.OK_ID)
                        fCoolBarAdvisor.advise(true);
                }
            });

            /* Lock Coolbar  */
            coolBarContextMenuManager.add(new Separator());
            IAction lockToolbarAction = getAction(ActionFactory.LOCK_TOOL_BAR.getId());
            lockToolbarAction.setText(Messages.ApplicationActionBarAdvisor_LOCK_TOOLBAR);
            coolBarContextMenuManager.add(lockToolbarAction);

            /* Toggle State of Toolbar Visibility */
            coolBarContextMenuManager.add(new Action(Messages.ApplicationActionBarAdvisor_HIDE_TOOLBAR) {
                @Override
                public void run() {
                    ApplicationWorkbenchWindowAdvisor configurer = ApplicationWorkbenchAdvisor.fgPrimaryApplicationWorkbenchWindowAdvisor;
                    configurer.setToolBarVisible(false, true);
                    Owl.getPreferenceService().getGlobalScope().putBoolean(DefaultPreferences.SHOW_TOOLBAR, false);
                }
            });

            /* Support for more Contributions */
            coolBarContextMenuManager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));

            /* Coolbar Advisor */
            fCoolBarAdvisor = new CoolBarAdvisor(coolBar, getActionBarConfigurer().getWindowConfigurer().getWindow());
            fCoolBarAdvisor.advise();
        }

        /**
         * @param manager the {@link IMenuManager} to fill this menu into.
         * @param selection the current {@link IStructuredSelection} of {@link INews}.
         * @param shellProvider a {@link IShellProvider} for dialogs.
         * @param directMenu if <code>true</code> directly fill all items to the menu,
         * otherwise create a sub menu.
         */
        public static void fillAttachmentsMenu(IMenuManager manager, final IStructuredSelection selection,
                final IShellProvider shellProvider, boolean directMenu) {
            final List<Pair<IAttachment, URI>> attachments = ModelUtils.getAttachmentLinks(selection);
            if (!attachments.isEmpty()) {
                manager.add(new Separator("attachments")); //$NON-NLS-1$

                /* Either as direct Menu or Submenu */
                IMenuManager attachmentMenu;
                if (directMenu)
                    attachmentMenu = manager;
                else {
                    attachmentMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_ATTACHMENTS, "attachments"); //$NON-NLS-1$
                    manager.add(attachmentMenu);
                }

                final IPreferenceScope preferences = Owl.getPreferenceService().getGlobalScope();

                /* Offer to Download All */
                if (attachments.size() > 1) {
                    int sumBytes = 0;
                    for (Pair<IAttachment, URI> attachment : attachments) {
                        if (attachment.getFirst().getLength() > 0) {
                            sumBytes += attachment.getFirst().getLength();
                        } else {
                            sumBytes = 0;
                            break;
                        }
                    }
                    String sumSize = OwlUI.getSize(sumBytes);

                    Action downloadAllAction = new Action(sumSize != null
                            ? (NLS.bind(Messages.ApplicationActionBarAdvisor_DOWNLOAD_ALL_WITH_SIZE, sumSize))
                            : (Messages.ApplicationActionBarAdvisor_DOWNLOAD_ALL)) {
                        @Override
                        public void run() {
                            DirectoryDialog dialog = new DirectoryDialog(shellProvider.getShell(), SWT.None);
                            dialog.setText(Messages.ApplicationActionBarAdvisor_SELECT_FOLDER_FOR_DOWNLOADS);

                            String downloadFolder = preferences.getString(DefaultPreferences.DOWNLOAD_FOLDER);
                            if (StringUtils.isSet(downloadFolder) && new File(downloadFolder).exists())
                                dialog.setFilterPath(downloadFolder);

                            String folder = dialog.open();
                            if (StringUtils.isSet(folder)) {
                                for (Pair<IAttachment, URI> attachment : attachments) {
                                    Controller.getDefault().getDownloadService()
                                            .download(DownloadRequest.createAttachmentDownloadRequest(
                                                    attachment.getFirst(), attachment.getSecond(), new File(folder),
                                                    true, null));
                                }

                                /* Remember Download Folder in Settings */
                                preferences.putString(DefaultPreferences.DOWNLOAD_FOLDER, folder);
                            }
                        }
                    };
                    downloadAllAction.setImageDescriptor(OwlUI.getImageDescriptor("icons/elcl16/save_all.gif")); //$NON-NLS-1$
                    attachmentMenu.add(downloadAllAction);
                    attachmentMenu.add(new Separator());
                }

                /* Collect openable Attachments that have already been downloaded */
                List<Action> openActions = new ArrayList<Action>(1);
                Set<String> downloadLocations = getDownloadLocations();

                /* Offer Download Action for each */
                for (final Pair<IAttachment, URI> attachmentPair : attachments) {
                    IAttachment attachment = attachmentPair.getFirst();
                    final String fileName = URIUtils.getFile(attachmentPair.getSecond(),
                            OwlUI.getExtensionForMime(attachment.getType()));
                    String size = OwlUI.getSize(attachment.getLength());

                    Action action = new Action(
                            size != null ? (NLS.bind(Messages.ApplicationActionBarAdvisor_FILE_SIZE, fileName, size))
                                    : (fileName)) {
                        @Override
                        public void run() {
                            FileDialog dialog = new FileDialog(shellProvider.getShell(), SWT.SAVE);
                            dialog.setText(Messages.ApplicationActionBarAdvisor_SELECT_FILE_FOR_DOWNLOAD);
                            dialog.setFileName(
                                    Application.IS_WINDOWS ? CoreUtils.getSafeFileNameForWindows(fileName) : fileName);
                            dialog.setOverwrite(true);

                            String downloadFolder = preferences.getString(DefaultPreferences.DOWNLOAD_FOLDER);
                            if (StringUtils.isSet(downloadFolder) && new File(downloadFolder).exists())
                                dialog.setFilterPath(downloadFolder);

                            String selectedFileName = dialog.open();
                            if (StringUtils.isSet(selectedFileName)) {
                                File file = new File(selectedFileName);
                                Controller.getDefault().getDownloadService()
                                        .download(DownloadRequest.createAttachmentDownloadRequest(
                                                attachmentPair.getFirst(), attachmentPair.getSecond(),
                                                file.getParentFile(), true, file.getName()));

                                /* Remember Download Folder in Settings */
                                preferences.putString(DefaultPreferences.DOWNLOAD_FOLDER,
                                        file.getParentFile().toString());
                            }
                        }
                    };

                    action.setImageDescriptor(OwlUI.getImageDescriptor("icons/etool16/save_as.gif")); //$NON-NLS-1$
                    attachmentMenu.add(action);

                    /* Check if Attachment already exists and offer Open Action then */
                    String usedFileName = Application.IS_WINDOWS ? CoreUtils.getSafeFileNameForWindows(fileName)
                            : fileName;
                    if (shouldOfferOpenAction(usedFileName)) {
                        for (String downloadLocation : downloadLocations) {
                            final File downloadedFile = new File(downloadLocation, usedFileName);
                            if (downloadedFile.exists()) {
                                Action openAction = new Action(
                                        NLS.bind(Messages.ApplicationActionBarAdvisor_OPEN_FILE, fileName)) {
                                    @Override
                                    public void run() {
                                        Program.launch(downloadedFile.toString());
                                    }
                                };

                                openAction.setImageDescriptor(
                                        OwlUI.getAttachmentImage(fileName, attachmentPair.getFirst().getType()));
                                openActions.add(openAction);

                                break;
                            }
                        }
                    }
                }

                boolean separate = true;

                /* Offer Open Action for each downloaded */
                if (!openActions.isEmpty()) {
                    attachmentMenu.add(new Separator());
                    for (Action openAction : openActions) {
                        attachmentMenu.add(openAction);
                    }
                }

                /* Offer Copy Action for Attachment Link */
                else if (attachments.size() == 1) {
                    separate = false;
                    attachmentMenu.add(new Separator());
                    CopyLinkAction action = new CopyLinkAction();
                    action.setIgnoreActiveSelection(true);
                    action.selectionChanged(action, new StructuredSelection(attachments.iterator().next().getFirst()));
                    attachmentMenu.add(action);
                }

                /* Offer to Automize Downloading */
                if (separate)
                    attachmentMenu.add(new Separator());
                attachmentMenu.add(new AutomateFilterAction(PresetAction.DOWNLOAD, selection));
            }
        }

        private static boolean shouldOfferOpenAction(String filename) {
            if (Application.IS_WINDOWS)
                return !filename.endsWith(".exe") && !filename.endsWith(".bat") && !filename.endsWith(".com"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

            return true;
        }

        private static Set<String> getDownloadLocations() {
            IPreferenceScope preferences = Owl.getPreferenceService().getGlobalScope();
            Set<String> locations = new HashSet<String>(1);

            /* Check Preference */
            String folderPath = preferences.getString(DefaultPreferences.DOWNLOAD_FOLDER);
            if (folderPath != null) {
                File folder = new File(folderPath);
                if (folder.exists())
                    locations.add(folderPath);
            }

            /* Check Filters */
            Collection<ISearchFilter> filters = DynamicDAO.loadAll(ISearchFilter.class);
            for (ISearchFilter filter : filters) {
                List<IFilterAction> actions = filter.getActions();
                for (IFilterAction action : actions) {
                    if (DownloadAttachmentsNewsAction.ID.equals(action.getActionId())
                            && action.getData() instanceof String) {
                        folderPath = (String) action.getData();
                        if (folderPath != null) {
                            File folder = new File(folderPath);
                            if (folder.exists())
                                locations.add(folderPath);
                        }
                    }
                }
            }

            return locations;
        }

        /**
         * @param manager the {@link IMenuManager} to fill this menu into.
         * @param selection the current {@link IStructuredSelection} of {@link INews}.
         * @param shellProvider a {@link IShellProvider} for dialogs.
         * @param directMenu if <code>true</code> directly fill all items to the menu,
         * otherwise create a sub menu.
         */
        public static void fillShareMenu(IMenuManager manager, final IStructuredSelection selection,
                final IShellProvider shellProvider, boolean directMenu) {
            manager.add(new Separator("share")); //$NON-NLS-1$

            /* Either as direct Menu or Submenu */
            IMenuManager shareMenu;
            if (directMenu)
                shareMenu = manager;
            else {
                shareMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_SHARE_NEWS, OwlUI.SHARE, "sharenews"); //$NON-NLS-1$
                manager.add(shareMenu);
            }

            /* List all selected Share Providers  */
            final boolean isEnabled = !selection.isEmpty() && !ModelUtils.isEntityGroupSelected(selection);
            List<ShareProvider> providers = Controller.getDefault().getShareProviders();
            for (final ShareProvider provider : providers) {
                if (provider.isEnabled()) {
                    shareMenu.add(new Action(provider.getName()) {
                        @Override
                        public void run() {
                            Controller.getDefault().share(selection, provider);
                        };

                        @Override
                        public ImageDescriptor getImageDescriptor() {
                            if (StringUtils.isSet(provider.getIconPath()))
                                return OwlUI.getImageDescriptor(provider.getPluginId(), provider.getIconPath());

                            return super.getImageDescriptor();
                        };

                        @Override
                        public String getText() {
                            IBindingService bs = (IBindingService) PlatformUI.getWorkbench()
                                    .getService(IBindingService.class);
                            TriggerSequence binding = bs.getBestActiveBindingFor(provider.getId());

                            return binding != null ? NLS.bind(Messages.ApplicationActionBarAdvisor_SHARE_BINDING,
                                    provider.getName(), binding.format()) : provider.getName();
                        }

                        @Override
                        public boolean isEnabled() {
                            return isEnabled;
                        }

                        @Override
                        public String getActionDefinitionId() {
                            return SendLinkAction.ID.equals(provider.getId()) ? SendLinkAction.ID
                                    : super.getActionDefinitionId();
                        }

                        @Override
                        public String getId() {
                            return SendLinkAction.ID.equals(provider.getId()) ? SendLinkAction.ID : super.getId();
                        }
                    });
                }
            }

            /* Allow to Configure Providers */
            shareMenu.add(new Separator());
            shareMenu.add(new Action(Messages.ApplicationActionBarAdvisor_CONFIGURE) {
                @Override
                public void run() {
                    PreferencesUtil
                            .createPreferenceDialogOn(shellProvider.getShell(), SharingPreferencesPage.ID, null, null)
                            .open();
                };
            });
        }

        /**
         * @param manager the {@link IMenuManager} to fill this menu into.
         * @param selection the current {@link IStructuredSelection} of {@link INews}.
         * @param shellProvider a {@link IShellProvider} for dialogs.
         * @param directMenu if <code>true</code> directly fill all items to the menu,
         * otherwise create a sub menu.
         */
        public static void fillLabelMenu(IMenuManager manager, final IStructuredSelection selection,
                final IShellProvider shellProvider, boolean directMenu) {

            /* Either as direct Menu or Submenu */
            IMenuManager labelMenu;
            if (directMenu)
                labelMenu = manager;
            else {
                labelMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_LABEL);
                manager.add(labelMenu);
            }

            /* Assign  Labels */
            labelMenu.add(new AssignLabelsAction(shellProvider.getShell(), selection));

            /* Organize Labels */
            labelMenu.add(new Action(Messages.ApplicationActionBarAdvisor_ORGANIZE_LABELS) {
                @Override
                public void run() {
                    PreferencesUtil.createPreferenceDialogOn(shellProvider.getShell(), ManageLabelsPreferencePage.ID,
                            null, null).open();
                }
            });

            /* Load Labels */
            final Collection<ILabel> labels = CoreUtils.loadSortedLabels();

            /* Retrieve Labels that all selected News contain */
            labelMenu.add(new Separator());
            Set<ILabel> selectedLabels = ModelUtils.getLabelsForAll(selection);
            for (final ILabel label : labels) {
                LabelAction labelAction = new LabelAction(label, selection);
                labelAction.setChecked(selectedLabels.contains(label));
                labelMenu.add(labelAction);
            }

            /* New Label */
            labelMenu.add(new Action(Messages.ApplicationActionBarAdvisor_NEW_LABEL) {
                @Override
                public void run() {
                    LabelDialog dialog = new LabelDialog(shellProvider.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(labels.size());
                        DynamicDAO.save(newLabel);

                        LabelAction labelAction = new LabelAction(newLabel, selection);
                        labelAction.run();
                    }
                }

                @Override
                public boolean isEnabled() {
                    return !selection.isEmpty();
                }
            });

            /* Remove All Labels */
            labelMenu.add(new Separator());
            LabelAction removeAllLabels = new LabelAction(null, selection);
            removeAllLabels.setId(RemoveLabelsHandler.ID);
            removeAllLabels.setActionDefinitionId(RemoveLabelsHandler.ID);
            removeAllLabels.setEnabled(!selection.isEmpty() && !labels.isEmpty());
            labelMenu.add(removeAllLabels);
        }

        /**
         * @param menu the {@link IMenuManager} to fill.
         * @param window the {@link IWorkbenchWindow} where the menu is living.
         */
        public static void fillBookMarksMenu(IMenuManager menu, IWorkbenchWindow window) {
            Set<IFolder> roots = CoreUtils.loadRootFolders();

            /* Filter Options */
            final IPreferenceScope preferences = Owl.getPreferenceService().getGlobalScope();
            BookMarkFilter.Type[] allFilters = BookMarkFilter.Type.values();
            BookMarkFilter.Type selectedFilter = allFilters[preferences.getInteger(DefaultPreferences.BM_MENU_FILTER)];
            List<BookMarkFilter.Type> displayedFilters = Arrays
                    .asList(new BookMarkFilter.Type[] { BookMarkFilter.Type.SHOW_ALL, BookMarkFilter.Type.SHOW_NEW,
                            BookMarkFilter.Type.SHOW_UNREAD, BookMarkFilter.Type.SHOW_STICKY });

            MenuManager optionsMenu = new MenuManager(Messages.ApplicationActionBarAdvisor_FILTER_ELEMENTS,
                    (selectedFilter == BookMarkFilter.Type.SHOW_ALL) ? OwlUI.FILTER
                            : OwlUI.getImageDescriptor("icons/etool16/filter_active.gif"), //$NON-NLS-1$
                    null);
            for (final BookMarkFilter.Type filter : displayedFilters) {
                String name = Messages.ApplicationActionBarAdvisor_SHOW_ALL;
                switch (filter) {
                case SHOW_NEW:
                    name = Messages.ApplicationActionBarAdvisor_SHOW_NEW;
                    break;
                case SHOW_UNREAD:
                    name = Messages.ApplicationActionBarAdvisor_SHOW_UNREAD;
                    break;
                case SHOW_STICKY:
                    name = Messages.ApplicationActionBarAdvisor_SHOW_STICKY;
                    break;
                }

                Action action = new Action(name, IAction.AS_RADIO_BUTTON) {
                    @Override
                    public void run() {
                        if (isChecked())
                            preferences.putInteger(DefaultPreferences.BM_MENU_FILTER, filter.ordinal());
                    }
                };
                action.setChecked(filter == selectedFilter);
                optionsMenu.add(action);
                if (filter == BookMarkFilter.Type.SHOW_ALL)
                    optionsMenu.add(new Separator());
            }
            menu.add(optionsMenu);
            menu.add(new Separator());

            /* Single Bookmark Set */
            if (roots.size() == 1) {
                fillBookMarksMenu(window, preferences, menu, roots.iterator().next().getChildren(), selectedFilter);
            }

            /* More than one Bookmark Set */
            else {
                for (IFolder root : roots) {
                    if (shouldShow(root, selectedFilter)) {
                        MenuManager rootItem = new MenuManager(root.getName(), OwlUI.BOOKMARK_SET, null);
                        menu.add(rootItem);

                        fillBookMarksMenu(window, preferences, rootItem, root.getChildren(), selectedFilter);
                    }
                }
            }

            /* Indicate that no Items are Showing */
            if (menu.getItems().length == 2 && selectedFilter != BookMarkFilter.Type.SHOW_ALL) {
                boolean hasBookMarks = false;
                for (IFolder root : roots) {
                    if (!root.getChildren().isEmpty()) {
                        hasBookMarks = true;
                        break;
                    }
                }

                if (hasBookMarks) {
                    menu.add(new Action(Messages.ApplicationActionBarAdvisor_SOME_ELEMENTS_FILTERED) {
                        @Override
                        public boolean isEnabled() {
                            return false;
                        }
                    });
                }
            }
        }

        private static boolean shouldShow(IFolderChild child, BookMarkFilter.Type filter) {
            switch (filter) {
            case SHOW_ALL:
                return true;

            case SHOW_NEW:
                return hasNewsWithState(child, EnumSet.of(INews.State.NEW));

            case SHOW_UNREAD:
                return hasNewsWithState(child, EnumSet.of(INews.State.NEW, INews.State.UNREAD, INews.State.UPDATED));

            case SHOW_STICKY:
                return hasStickyNews(child);

            default:
                return true;
            }
        }

        private static void fillBookMarksMenu(final IWorkbenchWindow window, final IPreferenceScope preferences,
                IMenuManager parent, List<IFolderChild> childs, final BookMarkFilter.Type filter) {
            for (final IFolderChild child : childs) {

                /* Check if a Filter applies */
                if (!shouldShow(child, filter))
                    continue;

                /* News Mark or Empty Folder */
                if (child instanceof INewsMark
                        || (child instanceof IFolder && ((IFolder) child).getChildren().isEmpty())) {
                    String name = child.getName();
                    if (child instanceof INewsMark) {
                        int unreadNewsCount = (((INewsMark) child)
                                .getNewsCount(EnumSet.of(INews.State.NEW, INews.State.UNREAD, INews.State.UPDATED)));
                        if (unreadNewsCount > 0)
                            name = NLS.bind(Messages.ApplicationActionBarAdvisor_MARK_UNREAD_COUNT, name,
                                    unreadNewsCount);
                    }

                    Action action = new Action(name) {
                        @Override
                        public void run() {
                            if (child instanceof INewsMark)
                                OwlUI.openInFeedView(window.getActivePage(), new StructuredSelection(child));
                        }
                    };
                    action.setImageDescriptor(getImageDescriptor(child));
                    parent.add(action);
                }

                /* Folder with Children */
                else if (child instanceof IFolder) {
                    final IFolder folder = (IFolder) child;

                    final MenuManager folderMenu = new MenuManager(folder.getName(), getImageDescriptor(folder), null);
                    parent.add(folderMenu);
                    folderMenu.add(new Action("") {
//$NON-NLS-0$
                    }); //Dummy Action 
                    folderMenu.setRemoveAllWhenShown(true);
                    folderMenu.addMenuListener(new IMenuListener() {
                        public void menuAboutToShow(IMenuManager manager) {

                            /* Open Folder */
                            folderMenu.add(new Action(Messages.ApplicationActionBarAdvisor_OPEN_FOLDER) {
                                @Override
                                public void run() {
                                    OwlUI.openInFeedView(window.getActivePage(), new StructuredSelection(child));
                                }
                            });

                            /* Offer Actions to force open a new Tab */
                            if (preferences.getBoolean(DefaultPreferences.ALWAYS_REUSE_FEEDVIEW)
                                    && OwlUI.isTabbedBrowsingEnabled()) {

                                /* Open Folder in New Tab */
                                folderMenu.add(
                                        new OpenInNewTabAction(OwlUI.getPage(window), new StructuredSelection(child)));

                                /* Open All in New Tabs */
                                folderMenu.add(new OpenInNewTabAction(OwlUI.getPage(window), folder));
                            }

                            folderMenu.add(new Separator());

                            /* Show other entries */
                            fillBookMarksMenu(window, preferences, folderMenu, folder.getChildren(), filter);
                        }
                    });
                }
            }
        }

        private static ImageDescriptor getImageDescriptor(IFolderChild child) {
            boolean hasNewNews = hasNewsWithState(child, EnumSet.of(INews.State.NEW));

            /* Bookmark */
            if (child instanceof IBookMark) {
                ImageDescriptor favicon = OwlUI.getFavicon((IBookMark) child);
                if (!hasNewNews)
                    return (favicon != null) ? favicon : OwlUI.BOOKMARK;

                /* Overlay if News are *new* */
                Image base = (favicon != null) ? OwlUI.getImage(fgResources, favicon)
                        : OwlUI.getImage(fgResources, OwlUI.BOOKMARK);
                DecorationOverlayIcon overlay = new DecorationOverlayIcon(base,
                        OwlUI.getImageDescriptor("icons/ovr16/new.gif"), IDecoration.BOTTOM_RIGHT); //$NON-NLS-1$
                return overlay;
            }

            /* Saved Search */
            else if (child instanceof ISearchMark) {
                if (hasNewNews)
                    return OwlUI.SEARCHMARK_NEW;
                else if (((INewsMark) child).getNewsCount(INews.State.getVisible()) != 0)
                    return OwlUI.SEARCHMARK;

                return OwlUI.SEARCHMARK_EMPTY;
            }

            /* News Bin */
            else if (child instanceof INewsBin) {
                boolean isArchive = child.getProperty(DefaultPreferences.ARCHIVE_BIN_MARKER) != null;

                if (hasNewNews)
                    return isArchive ? OwlUI.ARCHIVE_NEW : OwlUI.NEWSBIN_NEW;
                else if (isArchive)
                    return OwlUI.ARCHIVE;
                else if (((INewsMark) child).getNewsCount(INews.State.getVisible()) != 0)
                    return OwlUI.NEWSBIN;

                return OwlUI.NEWSBIN_EMPTY;
            }

            /* Folder */
            else if (child instanceof IFolder)
                return hasNewNews ? OwlUI.FOLDER_NEW : OwlUI.FOLDER;

            return null;
        }

        private static boolean hasNewsWithState(IFolderChild child, EnumSet<INews.State> states) {
            if (child instanceof IFolder)
                return hasNewsWithStates((IFolder) child, states);

            return ((INewsMark) child).getNewsCount(states) != 0;
        }

        private static boolean hasNewsWithStates(IFolder folder, EnumSet<INews.State> states) {
            List<IMark> marks = folder.getMarks();
            for (IMark mark : marks) {
                if (mark instanceof INewsMark && ((INewsMark) mark).getNewsCount(states) != 0)
                    return true;
            }

            List<IFolder> folders = folder.getFolders();
            for (IFolder child : folders) {
                if (hasNewsWithStates(child, states))
                    return true;
            }

            return false;
        }

        private static boolean hasStickyNews(IFolderChild child) {
            if (child instanceof IFolder)
                return hasStickyNews((IFolder) child);

            if (child instanceof IBookMark)
                return ((IBookMark) child).getStickyNewsCount() != 0;

            return false;
        }

        private static boolean hasStickyNews(IFolder folder) {
            List<IMark> marks = folder.getMarks();
            for (IMark mark : marks) {
                if (mark instanceof IBookMark && ((IBookMark) mark).getStickyNewsCount() != 0)
                    return true;
            }

            List<IFolder> folders = folder.getFolders();
            for (IFolder child : folders) {
                if (hasStickyNews(child))
                    return true;
            }

            return false;
        }
    }