org.dawnsci.internal.intro.universal.CustomizationContentsArea.java Source code

Java tutorial

Introduction

Here is the source code for org.dawnsci.internal.intro.universal.CustomizationContentsArea.java

Source

/*
 * Copyright (c) 2012 Diamond Light Source Ltd.
 *
 * 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.eclipse.org/legal/epl-v10.html
 */
package org.dawnsci.internal.intro.universal;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;

import org.dawnsci.internal.intro.universal.CustomizationContentsArea.IntroTheme;
import org.dawnsci.internal.intro.universal.util.BundleUtil;
import org.dawnsci.internal.intro.universal.util.ImageUtil;
import org.dawnsci.internal.intro.universal.util.Log;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.intro.impl.FontSelection;
import org.eclipse.ui.internal.intro.impl.IntroPlugin;
import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot;
import org.eclipse.ui.intro.IIntroManager;
import org.eclipse.ui.intro.IIntroPart;
import org.eclipse.ui.intro.config.CustomizableIntroPart;
import org.eclipse.ui.intro.config.IIntroURL;
import org.eclipse.ui.intro.config.IntroURLFactory;
import org.osgi.framework.Bundle;
import org.osgi.service.prefs.BackingStoreException;

@SuppressWarnings({ "unused", "restriction" })
public class CustomizationContentsArea {

    private static final String INTRO_ROOT_PAGES = "INTRO_ROOT_PAGES"; //$NON-NLS-1$
    private static final String INTRO_DATA = "INTRO_DATA"; //$NON-NLS-1$
    private static final String INTRO_THEME = "INTRO_THEME"; //$NON-NLS-1$
    private static final String NO_ROOT_PAGES = "no_root_pages"; //$NON-NLS-1$
    private TabFolder tabFolder;
    private String firstPageId;
    private Composite pageContainer;
    private TableViewer themes;
    private TableViewer available;
    private TableViewer topLeft;
    private TableViewer topRight;
    private TableViewer bottomLeft;
    private TableViewer bottomRight;
    private CheckboxTableViewer rootPages;
    private ArrayList<String> introRootPages = new ArrayList<String>();
    private ArrayList<IntroTheme> themeList = new ArrayList<IntroTheme>();
    private IntroTheme introTheme;
    private String introThemeId;
    private IntroData introData;
    private Canvas themePreview;
    private TableContentProvider contentProvider;
    private TableLabelProvider labelProvider;
    private Button applyToAll;
    private Button useRelativeFonts;
    private Image extensionImage;
    private Image themeImage;
    private Image ihighImage;
    private Image ilowImage;
    private Image inewImage;
    private Image icalloutImage;
    private Shell shell;
    private static final Transfer[] TRANSFER_TYPES = new Transfer[] { ExtensionDataTransfer.getInstance() };

    private static final RootPage ROOT_PAGE_TABLE[] = new RootPage[] {
            new RootPage(IUniversalIntroConstants.ID_OVERVIEW, Messages.WelcomeCustomizationPreferencePage_overview,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_overview),
            new RootPage(IUniversalIntroConstants.ID_FIRSTSTEPS,
                    Messages.WelcomeCustomizationPreferencePage_firststeps,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_firststeps),
            new RootPage(IUniversalIntroConstants.ID_TUTORIALS,
                    Messages.WelcomeCustomizationPreferencePage_tutorials,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_tutorials),
            new RootPage(IUniversalIntroConstants.ID_PERSPECTIVES,
                    Messages.WelcomeCustomizationPreferencePage_perspectives,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_perspectives),
            new RootPage(IUniversalIntroConstants.ID_SAMPLES, Messages.WelcomeCustomizationPreferencePage_samples,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_samples),
            new RootPage(IUniversalIntroConstants.ID_WHATSNEW, Messages.WelcomeCustomizationPreferencePage_whatsnew,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_whatsnew),
            new RootPage(IUniversalIntroConstants.ID_WEBRESOURCES,
                    Messages.WelcomeCustomizationPreferencePage_webresources,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_webresources),
            new RootPage(IUniversalIntroConstants.ID_MIGRATE, Messages.WelcomeCustomizationPreferencePage_migrate,
                    Messages.WelcomeCustomizationPreferencePage_NoMnemonic_migrate) };

    static class RootPage {

        public String id;
        public String name;
        public String nameNoMnemonic;

        public RootPage(String id, String name, String nameNoMnemonic) {
            this.id = id;
            this.name = name;
            this.nameNoMnemonic = nameNoMnemonic;
        }

        public String getName() {
            return name;
        }

        public String getNameNoMnemonic() {
            return nameNoMnemonic;
        }

        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (obj == null)
                return false;
            if (obj instanceof RootPage) {
                RootPage page = (RootPage) obj;
                return page.id.equals(id) && page.name.equals(name);
            }
            return false;
        }

        public String toString() {
            return name;
        }
    }

    class TableContentProvider implements IStructuredContentProvider {

        public Object[] getElements(Object inputElement) {
            if (inputElement == ROOT_PAGE_TABLE)
                return ROOT_PAGE_TABLE;
            if (inputElement instanceof GroupData) {
                return ((GroupData) inputElement).getChildren();
            }
            if (inputElement == themes) {
                return themeList.toArray();
            }
            return new Object[0];
        }

        public void dispose() {
        }

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

    class TableDragSourceListener implements DragSourceListener {

        TableViewer viewer;
        BaseData[] sel;

        public TableDragSourceListener(TableViewer viewer) {
            this.viewer = viewer;
        }

        public void dragStart(DragSourceEvent event) {
            IStructuredSelection ssel = (IStructuredSelection) viewer.getSelection();
            if (ssel.size() > 0) {
                event.doit = true;
            } else {
                event.doit = false;
            }
        };

        public void dragSetData(DragSourceEvent event) {
            IStructuredSelection ssel = (IStructuredSelection) viewer.getSelection();
            BaseData[] array = new BaseData[ssel.size()];
            int i = 0;
            for (Iterator<?> iter = ssel.iterator(); iter.hasNext();) {
                array[i++] = (BaseData) iter.next();
            }
            event.data = array;
            sel = array;
        }

        public void dragFinished(DragSourceEvent event) {
            if (event.detail == DND.DROP_MOVE) {
                GroupData gd = (GroupData) viewer.getInput();
                for (int i = 0; i < sel.length; i++) {
                    BaseData ed = sel[i];
                    gd.remove(ed);
                }
                viewer.refresh();
                updateColumnSizes(viewer);
            }
            sel = null;
        }
    }

    CustomizationContentsArea() {
    }

    class TableDropTargetListener extends ViewerDropAdapter {

        public TableDropTargetListener(TableViewer viewer) {
            super(viewer);
        }

        public boolean performDrop(Object data) {
            BaseData target = (BaseData) getCurrentTarget();
            int loc = getCurrentLocation();
            GroupData gd = (GroupData) getViewer().getInput();
            if (gd == null)
                gd = createTargetGd(getViewer());
            BaseData[] sel = (BaseData[]) data;

            int index = target != null ? gd.getIndexOf(target) : -1;
            int startingIndex = getStartIndex(gd, sel);
            if (target != null) {
                if (loc == LOCATION_AFTER || (loc == LOCATION_ON && startingIndex != -1 && startingIndex < index))
                    index++;
                else if (index > 0 && loc == LOCATION_BEFORE)
                    index--;
            }

            for (int i = 0; i < sel.length; i++) {
                BaseData ed = sel[i];
                if (index == -1)
                    gd.add(ed);
                else
                    gd.add(index++, ed);
            }
            if (getViewer().getInput() != null)
                getViewer().refresh();
            else
                getViewer().setInput(gd);
            updateColumnSizes((TableViewer) getViewer());
            return true;
        }

        private int getStartIndex(GroupData gd, BaseData[] sel) {
            for (int i = 0; i < sel.length; i++) {
                BaseData ed = sel[i];
                int index = gd.getIndexOf(ed.getId());
                if (index != -1)
                    return index;
            }
            return -1;
        }

        public boolean validateDrop(Object target, int operation, TransferData transferType) {
            return ExtensionDataTransfer.getInstance().isSupportedType(transferType);
        }
    }

    class TableLabelProvider extends LabelProvider implements ITableLabelProvider {

        public String getText(Object obj) {
            if (obj instanceof RootPage) {
                return ((RootPage) obj).getNameNoMnemonic();
            }
            if (obj instanceof ExtensionData) {
                ExtensionData ed = (ExtensionData) obj;
                String name = ed.getName();
                if (name != null && name.length() > 0)
                    return name;
                return ed.getId();
            }
            if (obj instanceof SeparatorData) {
                return Messages.WelcomeCustomizationPreferencePage_horizontalSeparator;
            }
            if (obj instanceof IntroTheme) {
                IntroTheme bg = (IntroTheme) obj;
                return bg.getName();
            }
            return super.getText(obj);
        }

        public Image getImage(Object obj) {
            if (obj instanceof ExtensionData) {
                ExtensionData ed = (ExtensionData) obj;
                switch (ed.getImportance()) {
                case ExtensionData.HIGH:
                    return ihighImage;
                case ExtensionData.LOW:
                    return ilowImage;
                case ExtensionData.NEW:
                    return inewImage;
                case ExtensionData.CALLOUT:
                    return icalloutImage;
                }
                return extensionImage;
            }
            if (obj instanceof IntroTheme)
                return themeImage;
            return null;
        }

        public Image getColumnImage(Object element, int columnIndex) {
            if (columnIndex == 0)
                return getImage(element);
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            if (columnIndex == 1 || element instanceof IntroTheme || element instanceof RootPage)
                return getText(element);
            return null;
        }
    }

    class IntroTheme {
        IConfigurationElement element;
        Image previewImage;

        public String getName() {
            return element.getAttribute("name"); //$NON-NLS-1$
        }

        public String getId() {
            return element.getAttribute("id"); //$NON-NLS-1$
        }

        public boolean isScalable() {
            return "true".equals(element.getAttribute(FontSelection.ATT_SCALABLE)); //$NON-NLS-1$
        }

        public IntroTheme(IConfigurationElement element) {
            this.element = element;
        }

        public Image getPreviewImage() {
            if (previewImage == null) {
                String path = element.getAttribute("previewImage"); //$NON-NLS-1$
                if (path != null) {
                    String bid = element.getDeclaringExtension().getNamespaceIdentifier();
                    Bundle bundle = Platform.getBundle(bid);
                    if (bundle != null) {
                        ImageDescriptor desc = ImageUtil.createImageDescriptor(bundle, path);
                        previewImage = desc.createImage();
                    }
                }
            }
            return previewImage;
        }

        public void dispose() {
            if (previewImage != null) {
                previewImage.dispose();
                previewImage = null;
            }
        }
    }

    protected Control createContents(Composite parent) {
        Composite container = new Composite(parent, SWT.NULL);
        GridData data = new GridData();
        data.verticalAlignment = GridData.FILL;
        data.horizontalAlignment = GridData.FILL;
        container.setLayoutData(data);
        GridLayout layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        container.setLayout(layout);
        tabFolder = new TabFolder(container, SWT.TOP);
        tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH));
        tabFolder.addSelectionListener(new SelectionAdapter() {

            public void widgetSelected(SelectionEvent e) {
                TabItem[] selection = tabFolder.getSelection();
                onTabChange(selection[0]);
            }
        });
        useRelativeFonts = new Button(container, SWT.CHECK);
        useRelativeFonts.setText(Messages.WelcomeCustomizationPreferencePage_useRelative);
        applyToAll = new Button(container, SWT.CHECK);
        applyToAll.setText(Messages.WelcomeCustomizationPreferencePage_applyToAll);
        contentProvider = new TableContentProvider();
        labelProvider = new TableLabelProvider();
        if (isCustomizationMode()) {
            Button serialize = new Button(container, SWT.PUSH);
            serialize.setText(Messages.WelcomeCustomizationPreferencePage_serialize);
            serialize.addSelectionListener(new SelectionAdapter() {

                public void widgetSelected(SelectionEvent e) {
                    doSerializeState();
                }
            });
        }
        extensionImage = ImageUtil.createImage("full/obj16/extension_obj.gif"); //$NON-NLS-1$
        ihighImage = ImageUtil.createImage("full/obj16/ihigh_obj.gif"); //$NON-NLS-1$
        ilowImage = ImageUtil.createImage("full/obj16/ilow_obj.gif"); //$NON-NLS-1$
        inewImage = ImageUtil.createImage("full/obj16/inew_obj.gif"); //$NON-NLS-1$
        icalloutImage = ImageUtil.createImage("full/obj16/icallout_obj.gif"); //$NON-NLS-1$
        themeImage = ImageUtil.createImage("full/obj16/image_obj.gif"); //$NON-NLS-1$
        addPages();
        org.eclipse.jface.dialogs.Dialog.applyDialogFont(container);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(parent,
                "org.dawnsci.intro.universal.universalWelcomePreference"); //$NON-NLS-1$
        return container;
    }

    private void doSerializeState() {
        FileDialog fd = new FileDialog(shell, SWT.SAVE);
        fd.setText(Messages.WelcomeCustomizationPreferencePage_serializeTitle);
        String fileName = fd.open();
        if (fileName != null) {
            try {
                FileWriter writer = new FileWriter(fileName);
                PrintWriter pwriter = new PrintWriter(writer);
                introData.write(pwriter);
                pwriter.close();
            } catch (IOException e) {
                // show an error dialog in addition
                Log.error("Error while saving the intro data file", e); //$NON-NLS-1$
            }
        }
    }

    private boolean isCustomizationMode() {
        /*
         * String[] args = Platform.getApplicationArgs(); for (int i = 0; i < args.length; i++) { if
         * (args[i].equalsIgnoreCase("-welcomeCustomization")) //$NON-NLS-1$ return true; } return
         * false;
         */
        return true;
    }

    public void init(IWorkbench workbench) {
    }

    private void addPages() {
        loadData(false);
        addHomePage();
        createPageContainer();
        addRootPages();
        updateWidgetsFromData();
        selectFirstPage();
    }

    private void addRootPages() {
        addPage(IUniversalIntroConstants.ID_OVERVIEW);
        addPage(IUniversalIntroConstants.ID_FIRSTSTEPS);
        addPage(IUniversalIntroConstants.ID_TUTORIALS);
        addPage(IUniversalIntroConstants.ID_PERSPECTIVES);
        addPage(IUniversalIntroConstants.ID_SAMPLES);
        addPage(IUniversalIntroConstants.ID_WHATSNEW);
        addPage(IUniversalIntroConstants.ID_WEBRESOURCES);
        addPage(IUniversalIntroConstants.ID_MIGRATE);
    }

    private void createPageContainer() {
        pageContainer = new Composite(tabFolder, SWT.NULL);
        GridLayout layout = new GridLayout();
        //layout.horizontalSpacing = 10;
        pageContainer.setLayout(layout);
        layout.numColumns = 4;
        //layout.makeColumnsEqualWidth = true;
        Label label;
        label = new Label(pageContainer, SWT.WRAP);
        label.setText(Messages.WelcomeCustomizationPreferencePage_pageDesc);
        GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        gd.horizontalSpan = 4;
        label.setLayoutData(gd);
        label = new Label(pageContainer, SWT.SEPARATOR | SWT.HORIZONTAL);
        gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        gd.horizontalSpan = 4;
        label.setLayoutData(gd);
        label = new Label(pageContainer, SWT.NULL);
        label.setText(Messages.WelcomeCustomizationPreferencePage_available);
        gd = new GridData();
        label.setLayoutData(gd);
        label = new Label(pageContainer, SWT.SEPARATOR | SWT.VERTICAL);
        gd = new GridData(GridData.VERTICAL_ALIGN_FILL);
        gd.verticalSpan = 3;
        gd.widthHint = 10;
        label.setLayoutData(gd);

        label = new Label(pageContainer, SWT.NULL);
        label.setText(Messages.WelcomeCustomizationPreferencePage_left);
        label = new Label(pageContainer, SWT.NULL);
        label.setText(Messages.WelcomeCustomizationPreferencePage_right);
        available = createTableViewer(pageContainer, "hidden"); //$NON-NLS-1$
        available.setComparator(new ViewerComparator());
        gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL);
        gd.verticalSpan = 2;
        gd.widthHint = 100;
        //gd.horizontalSpan = 2;
        available.getControl().setLayoutData(gd);

        topLeft = createTableViewer(pageContainer, "top-left"); //$NON-NLS-1$
        gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = 100;
        topLeft.getControl().setLayoutData(gd);

        topRight = createTableViewer(pageContainer, "top-right"); //$NON-NLS-1$
        gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = 100;
        topRight.getControl().setLayoutData(gd);

        //label = new Label(pageContainer, SWT.NULL);
        //label.setText(Messages.WelcomeCustomizationPreferencePage_bottom);
        bottomLeft = createTableViewer(pageContainer, "bottom-left"); //$NON-NLS-1$
        gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = 100;
        bottomLeft.getControl().setLayoutData(gd);

        bottomRight = createTableViewer(pageContainer, "bottom-right"); //$NON-NLS-1$
        gd = new GridData(GridData.FILL_BOTH);
        gd.widthHint = 100;
        bottomRight.getControl().setLayoutData(gd);
    }

    private void updatePageContainer(String pageId, PageData pd) {
        if (pageId == null)
            return;
        refreshQuadrant(topLeft, pd, IUniversalIntroConstants.DIV_LAYOUT_TOP_LEFT);
        refreshQuadrant(topRight, pd, IUniversalIntroConstants.DIV_LAYOUT_TOP_RIGHT);
        refreshQuadrant(bottomLeft, pd, IUniversalIntroConstants.DIV_LAYOUT_BOTTOM_LEFT);
        refreshQuadrant(bottomRight, pd, IUniversalIntroConstants.DIV_LAYOUT_BOTTOM_RIGHT);
        refreshQuadrant(available, pd, IUniversalIntroConstants.HIDDEN);
    }

    private void refreshQuadrant(TableViewer viewer, PageData pd, String quadrant) {
        GroupData gd = pd != null ? pd.findGroup(quadrant) : null;
        viewer.setInput(gd);
        if (gd != null)
            updateColumnSizes(viewer);
    }

    private void onTabChange(TabItem item) {
        String id = (String) item.getData();
        if (item.getControl() == pageContainer)
            updatePageContainer(id, (PageData) item.getData("pageData")); //$NON-NLS-1$
    }

    private void loadData(boolean fromDefault) {
        IProduct product = Platform.getProduct();
        if (product == null)
            return;
        String pid = product.getId();
        introRootPages.clear();
        // 1. Root pages
        // try product-qualified value first
        String rootPages = getIntroPreference(INTRO_ROOT_PAGES, fromDefault, pid, UniversalIntroPlugin.PLUGIN_ID);
        if (rootPages.length() > 0) {
            StringTokenizer stok = new StringTokenizer(rootPages, ","); //$NON-NLS-1$
            while (stok.hasMoreTokens()) {
                String tok = stok.nextToken().trim();
                if (!NO_ROOT_PAGES.equals(tok)) {
                    introRootPages.add(tok);
                }
            }
        }
        // 2. Font Style
        String fontStyle = FontSelection.getFontStyle();
        useRelativeFonts.setSelection(FontSelection.FONT_RELATIVE.equals(fontStyle));
        // 3. Active theme
        String value = getIntroPreference(INTRO_THEME, fromDefault, pid, IntroPlugin.PLUGIN_ID);
        if (value.length() > 0)
            introThemeId = value;
        // 4. Intro data
        value = getIntroPreference(INTRO_DATA, fromDefault, pid, UniversalIntroPlugin.PLUGIN_ID);
        if (value.length() == 0)
            value = null;
        if (value != null && value.startsWith("product:")) //$NON-NLS-1$
            value = value.substring(8);
        value = BundleUtil.getResolvedResourceLocation(value, product.getDefiningBundle());
        introData = new IntroData(pid, value, true);
        introData.addImplicitContent();
    }

    private String getIntroPreference(String key, boolean fromDefault, String pid, String pluginId) {
        IEclipsePreferences prefs;
        String pidKey = pid + "_" + key; //$NON-NLS-1$
        String value;
        if (!fromDefault) {
            prefs = InstanceScope.INSTANCE.getNode(pluginId);
            value = getPreference(key, prefs, pidKey, null);
            if (value != null) {
                return value;
            }
        }
        prefs = DefaultScope.INSTANCE.getNode(pluginId);
        return getPreference(key, prefs, pidKey, ""); //$NON-NLS-1$
    }

    private String getPreference(String key, IEclipsePreferences prefs, String pidKey, String defaultValue) {
        String value = prefs.get(pidKey, null);
        if (value == null) {
            value = prefs.get(key, defaultValue);
        }
        return value;
    }

    public void dispose() {
        Iterator<IntroTheme> iter = themeList.iterator();
        while (iter.hasNext()) {
            ((IntroTheme) iter.next()).dispose();
        }
        extensionImage.dispose();
        ihighImage.dispose();
        ilowImage.dispose();
        inewImage.dispose();
        icalloutImage.dispose();
        themeImage.dispose();
    }

    private void updateIntroThemeFromData() {
        if (introThemeId != null) {
            for (int i = 0; i < themeList.size(); i++) {
                IntroTheme theme = (IntroTheme) themeList.get(i);
                if (theme.getId().equals(introThemeId)) {
                    introTheme = theme;
                    break;
                }
            }
        }
        updateThemePreview();
    }

    private void updateWidgetsFromData() {
        // sync up intro background part
        updateIntroThemeFromData();
        enableFontsButton();
        // sync up the root page checklist
        rootPages.setInput(ROOT_PAGE_TABLE);
        ArrayList<RootPage> selected = new ArrayList<RootPage>();
        for (int i = 0; i < ROOT_PAGE_TABLE.length; i++) {
            String id = ROOT_PAGE_TABLE[i].id;
            if (introRootPages.contains(id))
                selected.add(ROOT_PAGE_TABLE[i]);
        }
        rootPages.setCheckedElements(selected.toArray());
    }

    private void enableFontsButton() {
        if (introTheme != null) {
            useRelativeFonts.setEnabled(introTheme.isScalable());
        }
    }

    private void updateThemePreview() {
        themes.setInput(themes);
        if (introTheme != null)
            themes.setSelection(new StructuredSelection(introTheme), true);
        themePreview.redraw();
    }

    public boolean performOk() {
        saveData();
        BusyIndicator.showWhile(shell.getDisplay(), new Runnable() {
            public void run() {
                restartIntro();
            }
        });
        return true;
    }

    /**
     * Remember the current page, close intro, reopen it and show the saved page.
     * 
     */
    private void restartIntro() {
        IIntroManager manager = PlatformUI.getWorkbench().getIntroManager();
        IIntroPart part = manager.getIntro();
        if (part != null && part instanceof CustomizableIntroPart) {
            IntroModelRoot modelRoot = IntroPlugin.getDefault().getIntroModelRoot();
            String currentPageId = modelRoot.getCurrentPageId();
            IWorkbenchWindow window = part.getIntroSite().getWorkbenchWindow();
            boolean standby = manager.isIntroStandby(part);
            PlatformUI.getWorkbench().getIntroManager().closeIntro(part);
            IntroPlugin.getDefault().resetVolatileImageRegistry();
            UniversalIntroPlugin.getDefault().resetVolatileImageRegistry();
            part = PlatformUI.getWorkbench().getIntroManager().showIntro(window, standby);
            if (part != null && !standby) {
                StringBuffer url = new StringBuffer();
                url.append("http://org.eclipse.ui.intro/showPage?id="); //$NON-NLS-1$
                url.append(currentPageId);
                IIntroURL introURL = IntroURLFactory.createIntroURL(url.toString());
                if (introURL != null)
                    introURL.execute();
            }
        }
    }

    protected void performDefaults() {
        loadData(true);
        // Dispose all the root page tabs
        TabItem[] items = tabFolder.getItems();
        for (int i = 0; i < items.length; i++) {
            if (items[i].getData("pageData") != null) //$NON-NLS-1$
                items[i].dispose();
        }
        // Add them back in based on the checked state
        addRootPages();
        updateWidgetsFromData();
        // Get the items again
        items = tabFolder.getItems();
        // Select root
        onTabChange(items[0]);
    }

    private void saveData() {
        IEclipsePreferences iprefs = InstanceScope.INSTANCE.getNode(IntroPlugin.PLUGIN_ID);
        IEclipsePreferences uprefs = InstanceScope.INSTANCE.getNode(UniversalIntroPlugin.PLUGIN_ID);
        boolean toAll = applyToAll.getSelection();
        IProduct product = Platform.getProduct();
        if (product == null)
            return;
        String pid = product.getId();
        StringBuffer sbuf = new StringBuffer();
        if (introRootPages.size() == 0) {
            // An empty string means no preference so special value needed
            // to indicate no root pages.
            sbuf.append(NO_ROOT_PAGES);
        }
        for (int i = 0; i < introRootPages.size(); i++) {
            if (i > 0)
                sbuf.append(","); //$NON-NLS-1$
            sbuf.append((String) introRootPages.get(i));
        }
        String key = pid + "_" + INTRO_ROOT_PAGES; //$NON-NLS-1$
        uprefs.put(key, sbuf.toString());
        if (toAll) {
            key = INTRO_ROOT_PAGES;
            uprefs.put(key, sbuf.toString());
        }
        // Store font style
        key = pid + "_" + FontSelection.VAR_FONT_STYLE; //$NON-NLS-1$
        String fontStyle = useRelativeFonts.getSelection() ? FontSelection.FONT_RELATIVE
                : FontSelection.FONT_ABSOLUTE;
        if (fontStyle.equals(FontSelection.FONT_ABSOLUTE)) {
            // reset font scaling for next time relative is selected
            FontSelection.resetScalePercentage();
        }
        iprefs.put(key, fontStyle);
        if (toAll) {
            key = FontSelection.VAR_FONT_STYLE;
            iprefs.put(key, fontStyle);
        }
        // store page layouts
        StringWriter writer = new StringWriter();
        PrintWriter pwriter = new PrintWriter(writer);
        introData.write(pwriter);
        pwriter.close();
        String value = writer.toString();
        key = pid + "_" + INTRO_DATA; //$NON-NLS-1$
        uprefs.put(key, value);
        if (toAll) {
            key = INTRO_DATA;
            uprefs.put(key, value);
        }
        if (introTheme != null) {
            key = pid + "_" + INTRO_THEME; //$NON-NLS-1$
            value = introTheme.getId();
            iprefs.put(key, value);
        }
        if (toAll) {
            key = INTRO_THEME;
            iprefs.put(key, value);
        }
        try {
            uprefs.flush();
            iprefs.flush();
        } catch (BackingStoreException e) {
            e.printStackTrace();
        }
    }

    private void addHomePage() {
        TabItem item = new TabItem(tabFolder, SWT.NULL);
        item.setText(Messages.WelcomeCustomizationPreferencePage_home);
        Composite container = new Composite(tabFolder, SWT.NULL);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        container.setLayout(layout);
        Composite leftColumn = new Composite(container, SWT.NULL);
        layout = new GridLayout();
        layout.marginWidth = layout.marginHeight = 0;
        leftColumn.setLayout(layout);
        leftColumn.setLayoutData(new GridData(GridData.FILL_BOTH));
        Composite rightColumn = new Composite(container, SWT.NULL);
        layout = new GridLayout();
        layout.marginWidth = layout.marginHeight = 0;
        rightColumn.setLayout(layout);
        rightColumn.setLayoutData(new GridData(GridData.FILL_BOTH));

        Label themeLabel = new Label(leftColumn, SWT.NULL);
        themeLabel.setText(Messages.WelcomeCustomizationPreferencePage_background);
        GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
        themeLabel.setLayoutData(gd);
        themes = new TableViewer(leftColumn, SWT.BORDER);
        themes.getControl().setLayoutData(new GridData(GridData.FILL_BOTH));
        themes.setContentProvider(contentProvider);
        themes.setLabelProvider(labelProvider);
        themes.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent e) {
                Object sel = ((StructuredSelection) e.getSelection()).getFirstElement();
                introTheme = (IntroTheme) sel;
                themePreview.redraw();
                enableFontsButton();
            }
        });
        loadThemes();
        Label previewLabel = new Label(rightColumn, SWT.NULL);
        previewLabel.setText(Messages.WelcomeCustomizationPreferencePage_preview);
        themePreview = new Canvas(rightColumn, SWT.BORDER);
        gd = new GridData();
        gd.widthHint = 160 + 20;
        gd.heightHint = 120 + 20;
        themePreview.setLayoutData(gd);
        themePreview.addPaintListener(new PaintListener() {

            public void paintControl(PaintEvent e) {
                if (introTheme == null)
                    return;
                Image bgImage = introTheme.getPreviewImage();
                if (bgImage == null)
                    return;
                //Rectangle carea = themePreview.getClientArea();
                Rectangle ibounds = bgImage.getBounds();
                e.gc.drawImage(bgImage, 0, 0, ibounds.width, ibounds.height, 10, 10, 160, 120);
            }
        });
        Label label = new Label(container, SWT.NULL);
        label.setText(Messages.WelcomeCustomizationPreferencePage_rootpages);
        gd = new GridData();
        gd.horizontalSpan = 2;
        label.setLayoutData(gd);
        rootPages = CheckboxTableViewer.newCheckList(container, SWT.BORDER);
        rootPages.setContentProvider(contentProvider);
        rootPages.setLabelProvider(labelProvider);
        gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
        gd.horizontalSpan = 2;
        rootPages.getControl().setLayoutData(gd);
        rootPages.addCheckStateListener(new ICheckStateListener() {

            public void checkStateChanged(CheckStateChangedEvent event) {
                RootPage page = (RootPage) event.getElement();
                boolean checked = event.getChecked();
                onPageChecked(page.id, checked);
            }
        });
        item.setControl(container);
    }

    private void loadThemes() {
        IConfigurationElement[] elements = Platform.getExtensionRegistry()
                .getConfigurationElementsFor("org.eclipse.ui.intro.configExtension"); //$NON-NLS-1$
        for (int i = 0; i < elements.length; i++) {
            if (elements[i].getName().equals("theme")) { //$NON-NLS-1$
                themeList.add(new IntroTheme(elements[i]));
            }
        }
    }

    private void addPage(String id) {
        if (!getRootPageSelected(id))
            return;
        TabItem item = new TabItem(tabFolder, SWT.NULL);
        item.setText(getRootPageName(id));
        item.setControl(pageContainer);
        item.setData(id);
        PageData pd = introData.getPage(id);
        item.setData("pageData", pd); //$NON-NLS-1$
    }

    private void onPageChecked(String id, boolean checked) {
        TabItem[] items = tabFolder.getItems();
        if (checked) {
            for (int i = 0; i < items.length; i++) {
                TabItem item = items[i];
                if (item.getData() != null)
                    item.dispose();
            }
            introRootPages.add(id);
            addRootPages();
        } else {
            for (int i = 0; i < items.length; i++) {
                TabItem item = items[i];
                String itemId = (String) item.getData();
                if (itemId != null && itemId.equals(id)) {
                    item.dispose();
                    introRootPages.remove(id);
                    return;
                }
            }
        }
    }

    private String getRootPageName(String id) {
        for (int i = 0; i < ROOT_PAGE_TABLE.length; i++) {
            if (ROOT_PAGE_TABLE[i].id.equals(id))
                return ROOT_PAGE_TABLE[i].getName();
        }
        return "?"; //$NON-NLS-1$
    }

    private boolean getRootPageSelected(String id) {
        for (int i = 0; i < introRootPages.size(); i++) {
            String cid = (String) introRootPages.get(i);
            if (cid.equals(id))
                return true;
        }
        return false;
    }

    public void setInitializationData(IConfigurationElement config, String propertyName, Object data)
            throws CoreException {
    }

    private void createPopupMenu(final TableViewer viewer) {
        MenuManager manager = new MenuManager();
        manager.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(manager.getMenu());
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {

            public void menuAboutToShow(IMenuManager manager) {
                fillPopupMenu(manager, viewer);
            }
        });
    }

    private void addDNDSupport(TableViewer viewer) {
        viewer.addDragSupport(DND.DROP_MOVE, TRANSFER_TYPES, new TableDragSourceListener(viewer));
        viewer.addDropSupport(DND.DROP_MOVE, TRANSFER_TYPES, new TableDropTargetListener(viewer));
    }

    private TableViewer createTableViewer(Composite parent, String id) {
        final Table table = new Table(parent, SWT.BORDER | SWT.FULL_SELECTION);
        final TableColumn column1 = new TableColumn(table, SWT.NULL);
        column1.setMoveable(false);
        column1.setWidth(20);
        column1.setResizable(false);
        final TableColumn column2 = new TableColumn(table, SWT.NULL);
        column2.setResizable(true);
        final TableViewer viewer = new TableViewer(table);
        CellEditor[] editors = new CellEditor[2];
        editors[0] = new ComboBoxCellEditor(table, ExtensionData.IMPORTANCE_NAME_TABLE, SWT.READ_ONLY);
        viewer.setCellEditors(editors);
        viewer.setColumnProperties(
                new String[] { IUniversalIntroConstants.P_IMPORTANCE, IUniversalIntroConstants.P_NAME });
        viewer.setCellModifier(new ICellModifier() {

            public boolean canModify(Object element, String property) {
                return property.equals(IUniversalIntroConstants.P_IMPORTANCE);
            }

            public Object getValue(Object element, String property) {
                if (element instanceof ExtensionData) {
                    ExtensionData ed = (ExtensionData) element;
                    if (property.equals(IUniversalIntroConstants.P_IMPORTANCE))
                        return new Integer(ed.getImportance());
                }
                return null;
            }

            public void modify(Object element, String property, Object value) {
                Integer ivalue = (Integer) value;
                TableItem item = (TableItem) element;
                ExtensionData ed = (ExtensionData) item.getData();
                ed.setImportance(ivalue.intValue());
                viewer.update(ed, new String[] { IUniversalIntroConstants.P_IMPORTANCE });
            }
        });
        viewer.setContentProvider(contentProvider);
        viewer.setLabelProvider(labelProvider);
        viewer.setData("id", id); //$NON-NLS-1$
        createPopupMenu(viewer);
        addDNDSupport(viewer);
        return viewer;
    }

    private void fillPopupMenu(IMenuManager manager, final TableViewer viewer) {
        StructuredSelection ssel = (StructuredSelection) viewer.getSelection();

        manager.add(new Separator());
        Action addSeparator = new Action(Messages.WelcomeCustomizationPreferencePage_addSeparator) {
            public void run() {
                doAddSeparator(viewer);
            }
        };

        manager.add(addSeparator);
        manager.add(new Separator());

        if (ssel.size() == 1 && viewer != available) {
            Action upAction = new Action(Messages.WelcomeCustomizationPreferencePage_up) {

                public void run() {
                    doMove(viewer, true);
                }
            };
            Action downAction = new Action(Messages.WelcomeCustomizationPreferencePage_down) {

                public void run() {
                    doMove(viewer, false);
                }
            };
            BaseData ed = (BaseData) ssel.getFirstElement();
            GroupData gd = (GroupData) viewer.getInput();
            upAction.setEnabled(gd.canMoveUp(ed));
            downAction.setEnabled(gd.canMoveDown(ed));
            manager.add(upAction);
            manager.add(downAction);
        }
        if (ssel.size() > 0) {
            manager.add(new Separator());
            MenuManager menu = new MenuManager(Messages.WelcomeCustomizationPreferencePage_moveTo);
            addMoveToAction(menu, available, viewer, Messages.WelcomeCustomizationPreferencePage_menu_available);
            addMoveToAction(menu, topLeft, viewer, Messages.WelcomeCustomizationPreferencePage_menu_top_left);
            addMoveToAction(menu, topRight, viewer, Messages.WelcomeCustomizationPreferencePage_menu_top_right);
            addMoveToAction(menu, bottomLeft, viewer, Messages.WelcomeCustomizationPreferencePage_menu_bottom_left);
            addMoveToAction(menu, bottomRight, viewer,
                    Messages.WelcomeCustomizationPreferencePage_menu_bottom_right);
            manager.add(menu);

            boolean addDeleteSeparator = false;

            for (Iterator<?> iter = ssel.iterator(); iter.hasNext();) {
                Object obj = iter.next();
                if (obj instanceof SeparatorData)
                    addDeleteSeparator = true;
                else {
                    addDeleteSeparator = false;
                    break;
                }
            }
            if (addDeleteSeparator) {
                Action deleteSeparator = new Action(Messages.WelcomeCustomizationPreferencePage_removeSeparator) {
                    public void run() {
                        doRemoveSeparators(viewer);
                    }
                };
                manager.add(deleteSeparator);
            }
        }
    }

    private void addMoveToAction(MenuManager menu, final TableViewer target, final TableViewer source,
            String name) {
        if (source == target)
            return;
        Action action = new Action(name) {

            public void run() {
                doMoveTo(source, target);
            }
        };
        menu.add(action);
    }

    private void doMove(Viewer viewer, boolean up) {
        Object obj = ((StructuredSelection) viewer.getSelection()).getFirstElement();
        GroupData gd = (GroupData) viewer.getInput();
        if (up)
            gd.moveUp((BaseData) obj);
        else
            gd.moveDown((BaseData) obj);
        viewer.refresh();
    }

    private void doAddSeparator(Viewer viewer) {
        Object obj = ((StructuredSelection) viewer.getSelection()).getFirstElement();
        GroupData gd = (GroupData) viewer.getInput();
        if (gd == null) {
            gd = createTargetGd(viewer);
            viewer.setInput(gd);
        }
        gd.addSeparator((BaseData) obj);
        viewer.refresh();
        updateColumnSizes((TableViewer) viewer);
    }

    private void doRemoveSeparators(Viewer viewer) {
        StructuredSelection ssel = ((StructuredSelection) viewer.getSelection());
        GroupData gd = (GroupData) viewer.getInput();
        for (Iterator<?> iter = ssel.iterator(); iter.hasNext();) {
            SeparatorData sdata = (SeparatorData) iter.next();
            gd.remove(sdata);
        }
        viewer.refresh();
    }

    private void doMoveTo(TableViewer source, TableViewer target) {
        Object[] selObjs = ((StructuredSelection) source.getSelection()).toArray();
        GroupData sourceGd = (GroupData) source.getInput();
        GroupData targetGd = (GroupData) target.getInput();
        if (targetGd == null) {
            targetGd = createTargetGd(target);
        }
        for (int i = 0; i < selObjs.length; i++) {
            BaseData ed = (BaseData) selObjs[i];
            sourceGd.remove(ed);
            targetGd.add(ed);
        }
        source.refresh();
        updateColumnSizes(source);
        if (target.getInput() != null)
            target.refresh();
        else
            target.setInput(targetGd);
        updateColumnSizes(target);
    }

    private void updateColumnSizes(TableViewer viewer) {
        TableColumn sc = viewer.getTable().getColumn(1);
        sc.pack();
    }

    private GroupData createTargetGd(Viewer target) {
        GroupData targetGd = null;
        if (target == topLeft)
            targetGd = new GroupData(PageData.P_TOP_LEFT, false);
        else if (target == topRight)
            targetGd = new GroupData(PageData.P_TOP_RIGHT, false);
        else if (target == bottomLeft)
            targetGd = new GroupData(PageData.P_BOTTOM_LEFT, false);
        else if (target == bottomRight)
            targetGd = new GroupData(PageData.P_BOTTOM_RIGHT, false);
        else if (target == available)
            targetGd = new GroupData(IUniversalIntroConstants.HIDDEN, false);
        else
            return null;
        TabItem[] items = tabFolder.getSelection();
        PageData pd = (PageData) items[0].getData("pageData"); //$NON-NLS-1$
        if (pd == null) {
            String pageId = (String) items[0].getData();
            pd = new PageData(pageId);
            items[0].setData("pageData", pd); //$NON-NLS-1$
            introRootPages.add(pageId);
        }
        pd.add(targetGd);
        return targetGd;
    }

    private void selectFirstPage() {
        if (firstPageId == null)
            return;
        TabItem[] items = tabFolder.getItems();
        for (int i = 0; i < items.length; i++) {
            TabItem item = items[i];
            PageData pd = (PageData) item.getData("pageData"); //$NON-NLS-1$
            if (pd != null && pd.getId().equals(firstPageId)) {
                tabFolder.setSelection(i);
                onTabChange(item);
                return;
            }
        }
    }

    public void setCurrentPage(String pageId) {
        firstPageId = pageId;
    }

    public void setShell(Shell shell) {
        this.shell = shell;
    }
}