net.sf.eclipsensis.installoptions.actions.PreviewAction.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.eclipsensis.installoptions.actions.PreviewAction.java

Source

/*******************************************************************************
 * Copyright (c) 2004-2010 Sunil Kamath (IcemanK).
 * All rights reserved.
 * This program is made available under the terms of the Common Public License
 * v1.0 which is available at http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     Sunil Kamath (IcemanK) - initial API and implementation
 *******************************************************************************/
package net.sf.eclipsensis.installoptions.actions;

import java.io.*;
import java.util.*;

import net.sf.eclipsensis.*;
import net.sf.eclipsensis.console.*;
import net.sf.eclipsensis.editor.NSISEditorUtilities;
import net.sf.eclipsensis.installoptions.*;
import net.sf.eclipsensis.installoptions.editor.IInstallOptionsEditor;
import net.sf.eclipsensis.installoptions.figures.DashedLineBorder;
import net.sf.eclipsensis.installoptions.ini.*;
import net.sf.eclipsensis.installoptions.model.*;
import net.sf.eclipsensis.installoptions.util.*;
import net.sf.eclipsensis.lang.*;
import net.sf.eclipsensis.makensis.*;
import net.sf.eclipsensis.script.NSISScriptProblem;
import net.sf.eclipsensis.settings.*;
import net.sf.eclipsensis.util.*;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.gef.Disposable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.operation.*;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.*;

public class PreviewAction extends Action implements Disposable, IMakeNSISRunListener, INSISHomeListener {
    public static final String PREVIEW_CLASSIC_ID = "net.sf.eclipsensis.installoptions.preview_classic"; //$NON-NLS-1$
    public static final String PREVIEW_MUI_ID = "net.sf.eclipsensis.installoptions.preview_mui"; //$NON-NLS-1$

    private static final String cMUIDialogSizeName = InstallOptionsPlugin.getResourceString("mui.dialog.size.name"); //$NON-NLS-1$
    private static final String cClassicDialogSizeName = InstallOptionsPlugin
            .getResourceString("classic.dialog.size.name"); //$NON-NLS-1$
    private static INSISConsole cDummyConsole = new NullNSISConsole();
    private static Map<PreviewCacheKey, File> cPreviewCache = new HashMap<PreviewCacheKey, File>();
    private static Map<Dimension, File> cBitmapCache = new HashMap<Dimension, File>();
    private static Map<Dimension, File> cIconCache = new HashMap<Dimension, File>();

    private IInstallOptionsEditor mEditor;
    private NSISSettings mSettings = new DummyNSISSettings();
    private IPreferenceStore mPreferenceStore = InstallOptionsPlugin.getDefault().getPreferenceStore();

    public PreviewAction(int type, IInstallOptionsEditor editor) {
        super();
        mEditor = editor;
        String resource;
        Map<String, String> symbols = new LinkedHashMap<String, String>();
        switch (type) {
        case IInstallOptionsConstants.PREVIEW_CLASSIC:
            setId(PREVIEW_CLASSIC_ID);
            resource = "preview.action.classic.label"; //$NON-NLS-1$
            break;
        default:
            setId(PREVIEW_MUI_ID);
            resource = "preview.action.mui.label"; //$NON-NLS-1$
            symbols.put("PREVIEW_MUI", null); //$NON-NLS-1$
        }
        mSettings.setVerbosity(INSISSettingsConstants.VERBOSITY_DEFAULT);
        mSettings.setSymbols(symbols);
        String label = InstallOptionsPlugin.getResourceString(resource);
        setText(label);
        setToolTipText(label);
        NSISPreferences.getInstance().addListener(this);
        MakeNSISRunner.addListener(this);
        updateEnabled();
    }

    public void nsisHomeChanged(IProgressMonitor monitor, NSISHome oldHome, NSISHome newHome) {
        updateEnabled();
    }

    private void updateEnabled() {
        setEnabled((mEditor != null && EclipseNSISPlugin.getDefault().isConfigured()
                && !MakeNSISRunner.isCompiling()));
    }

    public void eventOccurred(MakeNSISRunEvent event) {
        switch (event.getType()) {
        case MakeNSISRunEvent.STARTED:
            setEnabled(false);
            break;
        case MakeNSISRunEvent.STOPPED:
            updateEnabled();
            break;
        }
    }

    public void scriptUpdated() {
        updateEnabled();
    }

    public void dispose() {
        NSISPreferences.getInstance().removeListener(this);
        MakeNSISRunner.removeListener(this);
    }

    @Override
    public void run() {
        if (mEditor != null) {
            Shell shell = mEditor.getSite().getShell();
            if (mEditor.isDirty()) {
                boolean autosaveBeforePreview = mPreferenceStore
                        .getBoolean(IInstallOptionsConstants.PREFERENCE_AUTOSAVE_BEFORE_PREVIEW);
                boolean shouldSave = autosaveBeforePreview;
                if (!shouldSave) {
                    MessageDialogWithToggle dialog = new MessageDialogWithToggle(shell,
                            EclipseNSISPlugin.getResourceString("confirm.title"), //$NON-NLS-1$
                            InstallOptionsPlugin.getShellImage(),
                            InstallOptionsPlugin.getResourceString("save.before.preview.confirm"), //$NON-NLS-1$
                            MessageDialog.QUESTION,
                            new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL }, 0,
                            InstallOptionsPlugin.getResourceString("confirm.toggle.message"), false); //$NON-NLS-1$
                    dialog.open();
                    shouldSave = dialog.getReturnCode() == IDialogConstants.OK_ID;
                    if (shouldSave && dialog.getToggleState()) {
                        mPreferenceStore.setValue(IInstallOptionsConstants.PREFERENCE_AUTOSAVE_BEFORE_PREVIEW,
                                true);
                    }
                }
                if (shouldSave) {
                    ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
                    dialog.open();
                    IProgressMonitor progressMonitor = dialog.getProgressMonitor();
                    mEditor.doSave(progressMonitor);
                    dialog.close();
                    if (progressMonitor.isCanceled()) {
                        return;
                    }
                } else {
                    return;
                }
            }
            INIFile iniFile = mEditor.getINIFile();
            if (iniFile.hasErrors()) {
                Common.openError(shell, InstallOptionsPlugin.getResourceString("ini.errors.preview.error"), //$NON-NLS-1$
                        InstallOptionsPlugin.getShellImage());
                return;
            }
            INISection settings = iniFile.findSections(InstallOptionsModel.SECTION_SETTINGS)[0];
            INIKeyValue numFields = settings.findKeyValues(InstallOptionsModel.PROPERTY_NUMFIELDS)[0];
            if (Integer.parseInt(numFields.getValue()) <= 0) {
                Common.openError(shell, InstallOptionsPlugin.getResourceString("ini.numfields.preview.error"), //$NON-NLS-1$
                        InstallOptionsPlugin.getShellImage());
            } else {
                IPathEditorInput editorInput = NSISEditorUtilities.getPathEditorInput(mEditor);
                if (editorInput instanceof IFileEditorInput) {
                    IFile file = ((IFileEditorInput) editorInput).getFile();
                    if (file.exists()) {
                        IPath location = file.getLocation();
                        if (location != null) {
                            doPreview(iniFile, location.toFile());
                        } else {
                            Common.openError(shell, EclipseNSISPlugin.getResourceString("local.filesystem.error"), //$NON-NLS-1$
                                    InstallOptionsPlugin.getShellImage());
                        }
                    }
                } else if (editorInput != null) {
                    doPreview(iniFile, new File(editorInput.getPath().toOSString()));
                }
            }
        }
    }

    private void doPreview(final INIFile iniFile, final File file) {
        final Shell shell = mEditor.getSite().getShell();
        BusyIndicator.showWhile(shell.getDisplay(), new Runnable() {
            public void run() {
                final ProgressMonitorDialog pmd = new ProgressMonitorDialog(shell) {
                    @Override
                    protected void configureShell(Shell shell) {
                        super.configureShell(shell);
                        Rectangle rect = shell.getDisplay().getBounds();
                        shell.setLocation(rect.x + rect.width + 1, rect.y + rect.height + 1);
                    }

                    @Override
                    protected Rectangle getConstrainedShellBounds(Rectangle preferredSize) {
                        Rectangle rect = shell.getDisplay().getBounds();
                        return new Rectangle(rect.x + rect.width + 1, rect.y + rect.height + 1, preferredSize.width,
                                preferredSize.height);
                    }
                };
                pmd.open();
                try {
                    ModalContext.run(new IRunnableWithProgress() {
                        private File createPreviewFile(File previewFile, INIFile inifile, final NSISLanguage lang)
                                throws IOException {
                            File previewFile2 = previewFile;
                            INIFile inifile2 = inifile;
                            if (previewFile2 == null) {
                                previewFile2 = File.createTempFile("preview", ".ini"); //$NON-NLS-1$ //$NON-NLS-2$
                                previewFile2.deleteOnExit();
                            }
                            inifile2 = inifile2.copy();
                            InstallOptionsDialog dialog = InstallOptionsDialog.loadINIFile(inifile2);
                            DialogSize dialogSize;
                            if (getId().equals(PREVIEW_MUI_ID)) {
                                dialogSize = DialogSizeManager.getDialogSize(cMUIDialogSizeName);
                            } else {
                                dialogSize = DialogSizeManager.getDialogSize(cClassicDialogSizeName);
                            }
                            if (dialogSize == null) {
                                dialogSize = DialogSizeManager.getDefaultDialogSize();
                            }
                            dialog.setDialogSize(dialogSize);
                            Font font = FontUtility.getFont(lang);
                            for (Iterator<InstallOptionsWidget> iter = dialog.getChildren().iterator(); iter
                                    .hasNext();) {
                                InstallOptionsWidget widget = iter.next();
                                if (widget instanceof InstallOptionsPicture) {
                                    final InstallOptionsPicture picture = (InstallOptionsPicture) widget;
                                    final Dimension dim = widget.toGraphical(widget.getPosition(), font).getSize();
                                    final Map<Dimension, File> cache;
                                    switch (picture.getSWTImageType()) {
                                    case SWT.IMAGE_BMP:
                                        cache = cBitmapCache;
                                        break;
                                    case SWT.IMAGE_ICO:
                                        cache = cIconCache;
                                        break;
                                    default:
                                        continue;
                                    }
                                    final File[] imageFile = new File[] { cache.get(dim) };
                                    if (!IOUtility.isValidFile(imageFile[0])) {
                                        shell.getDisplay().syncExec(new Runnable() {
                                            public void run() {
                                                Image widgetImage = picture.getImage();
                                                ImageData data = widgetImage.getImageData();
                                                data.width = dim.width;
                                                data.height = dim.height;
                                                data.type = picture.getSWTImageType();

                                                Image bitmap = new Image(shell.getDisplay(), data);
                                                GC gc = new GC(bitmap);
                                                gc.setBackground(shell.getDisplay()
                                                        .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
                                                gc.setForeground(
                                                        shell.getDisplay().getSystemColor(SWT.COLOR_BLACK));
                                                gc.fillRectangle(0, 0, dim.width, dim.height);
                                                Rectangle rect = widgetImage.getBounds();
                                                int x, y, width, height;
                                                if (rect.width > dim.width) {
                                                    x = 0;
                                                    width = dim.width;
                                                } else {
                                                    x = (dim.width - rect.width) / 2;
                                                    width = rect.width;
                                                }
                                                if (rect.height > dim.height) {
                                                    y = 0;
                                                    height = dim.height;
                                                } else {
                                                    y = (dim.height - rect.height) / 2;
                                                    height = rect.height;
                                                }
                                                gc.drawImage(widgetImage, 0, 0, rect.width, rect.height, x, y,
                                                        width, height);
                                                gc.setLineStyle(SWT.LINE_CUSTOM);
                                                gc.setLineDash(DashedLineBorder.DASHES);
                                                gc.drawRectangle(0, 0, dim.width - 1, dim.height - 1);
                                                gc.dispose();
                                                ImageLoader loader = new ImageLoader();
                                                loader.data = new ImageData[] { bitmap.getImageData() };
                                                try {
                                                    imageFile[0] = File.createTempFile("preview", //$NON-NLS-1$
                                                            picture.getFileExtension());
                                                    imageFile[0].deleteOnExit();
                                                    loader.save(imageFile[0].getAbsolutePath(),
                                                            picture.getSWTImageType());
                                                    cache.put(dim, imageFile[0]);
                                                } catch (IOException e) {
                                                    imageFile[0] = null;
                                                    InstallOptionsPlugin.getDefault().log(e);
                                                    cache.remove(dim);
                                                }
                                            }
                                        });
                                    }
                                    if (imageFile[0] != null) {
                                        picture.setPropertyValue(InstallOptionsModel.PROPERTY_TEXT,
                                                imageFile[0].getAbsolutePath());
                                    }
                                }
                            }
                            inifile2 = dialog.updateINIFile();
                            IOUtility.writeContentToFile(previewFile2, inifile2.toString().getBytes());
                            return previewFile2;
                        }

                        public void run(IProgressMonitor monitor) {
                            try {
                                monitor.beginTask(
                                        InstallOptionsPlugin.getResourceString("previewing.script.task.name"), //$NON-NLS-1$
                                        IProgressMonitor.UNKNOWN);
                                String pref = InstallOptionsPlugin.getDefault().getPreferenceStore()
                                        .getString(IInstallOptionsConstants.PREFERENCE_PREVIEW_LANG);
                                NSISLanguage lang;
                                if (pref.equals("")) { //$NON-NLS-1$
                                    lang = NSISLanguageManager.getInstance().getDefaultLanguage();
                                } else {
                                    lang = NSISLanguageManager.getInstance().getLanguage(pref);
                                    if (lang == null) {
                                        lang = NSISLanguageManager.getInstance().getDefaultLanguage();
                                        InstallOptionsPlugin.getDefault().getPreferenceStore()
                                                .setValue(IInstallOptionsConstants.PREFERENCE_PREVIEW_LANG, ""); //$NON-NLS-1$
                                    }
                                }
                                PreviewCacheKey key = new PreviewCacheKey(file, lang);
                                File previewFile = cPreviewCache.get(key);
                                if (previewFile == null || file.lastModified() > previewFile.lastModified()) {
                                    previewFile = createPreviewFile(previewFile, iniFile, lang);
                                    cPreviewCache.put(key, previewFile);
                                }

                                Map<String, String> symbols = mSettings.getSymbols();

                                symbols.put("PREVIEW_INI", previewFile.getAbsolutePath()); //$NON-NLS-1$
                                symbols.put("PREVIEW_LANG", lang.getName()); //$NON-NLS-1$
                                Locale locale = NSISLanguageManager.getInstance()
                                        .getLocaleForLangId(lang.getLangId());
                                if (getId().equals(PREVIEW_MUI_ID)) {
                                    symbols.put("PREVIEW_TITLE", //$NON-NLS-1$
                                            InstallOptionsPlugin.getResourceString(locale, "preview.setup.title")); //$NON-NLS-1$
                                    symbols.put("PREVIEW_SUBTITLE", InstallOptionsPlugin.getResourceString(locale, //$NON-NLS-1$
                                            "preview.setup.subtitle")); //$NON-NLS-1$
                                } else {
                                    symbols.put("PREVIEW_BRANDING", InstallOptionsPlugin.getResourceString(locale, //$NON-NLS-1$
                                            "preview.setup.branding")); //$NON-NLS-1$
                                }
                                symbols.put("PREVIEW_NAME", //$NON-NLS-1$
                                        InstallOptionsPlugin.getResourceString(locale, "preview.setup.name")); //$NON-NLS-1$
                                if (EclipseNSISPlugin.getDefault().isWinVista() && NSISPreferences.getInstance()
                                        .getNSISVersion().compareTo(INSISVersions.VERSION_2_21) >= 0) {
                                    symbols.put("WINDOWS_VISTA", ""); //$NON-NLS-1$ //$NON-NLS-2$
                                }

                                mSettings.setSymbols(symbols);
                                final File previewScript = getPreviewScript();
                                long timestamp = System.currentTimeMillis();
                                MakeNSISResults results = null;
                                results = MakeNSISRunner.compile(previewScript, mSettings, cDummyConsole,
                                        new INSISConsoleLineProcessor() {
                                            public NSISConsoleLine processText(String text) {
                                                return NSISConsoleLine.info(text);
                                            }

                                            public void reset() {
                                            }
                                        });
                                if (results != null) {
                                    if (results.getReturnCode() != 0) {
                                        List<NSISScriptProblem> errors = results.getProblems();
                                        final String error;
                                        if (!Common.isEmptyCollection(errors)) {
                                            Iterator<NSISScriptProblem> iter = errors.iterator();
                                            StringBuffer buf = new StringBuffer(iter.next().getText());
                                            while (iter.hasNext()) {
                                                buf.append(INSISConstants.LINE_SEPARATOR)
                                                        .append(iter.next().getText());
                                            }
                                            error = buf.toString();
                                        } else {
                                            error = InstallOptionsPlugin.getResourceString("preview.compile.error"); //$NON-NLS-1$
                                        }
                                        shell.getDisplay().asyncExec(new Runnable() {
                                            public void run() {
                                                Common.openError(shell, error,
                                                        InstallOptionsPlugin.getShellImage());
                                            }
                                        });
                                    } else {
                                        final File outfile = new File(results.getOutputFileName());
                                        if (IOUtility.isValidFile(outfile) && outfile.lastModified() > timestamp) {
                                            MakeNSISRunner.testInstaller(outfile.getAbsolutePath(), null, true);
                                        }
                                    }
                                }
                            } catch (final Exception e) {
                                InstallOptionsPlugin.getDefault().log(e);
                                shell.getDisplay().asyncExec(new Runnable() {
                                    public void run() {
                                        Common.openError(shell, e.getMessage(),
                                                InstallOptionsPlugin.getShellImage());
                                    }
                                });
                            } finally {
                                monitor.done();
                            }
                        }
                    }, true, pmd.getProgressMonitor(), shell.getDisplay());
                } catch (Exception e) {
                    InstallOptionsPlugin.getDefault().log(e);
                    Common.openError(shell, e.getMessage(), InstallOptionsPlugin.getShellImage());
                } finally {
                    pmd.close();
                }
            }
        });
    }

    private File getPreviewScript() throws IOException {
        return IOUtility.ensureLatest(InstallOptionsPlugin.getDefault().getBundle(),
                new Path("/preview/preview.nsi"), //$NON-NLS-1$
                new File(InstallOptionsPlugin.getPluginStateLocation(), "preview")); //$NON-NLS-1$
    }

    private class PreviewCacheKey {
        private File mFile;
        private NSISLanguage mLanguage;

        public PreviewCacheKey(File file, NSISLanguage language) {
            mFile = file;
            mLanguage = language;
        }

        @Override
        public int hashCode() {
            int result = 31 + (mFile == null ? 0 : mFile.hashCode());
            result = 31 * result + (mLanguage == null ? 0 : mLanguage.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (obj != this) {
                if (obj instanceof PreviewCacheKey) {
                    return Common.objectsAreEqual(mFile, ((PreviewCacheKey) obj).mFile)
                            && Common.objectsAreEqual(mLanguage, ((PreviewCacheKey) obj).mLanguage);
                }
                return false;
            }
            return true;
        }
    }
}