net.leboxondelex.daplomb.ui.facets.ImageViewerFacet.java Source code

Java tutorial

Introduction

Here is the source code for net.leboxondelex.daplomb.ui.facets.ImageViewerFacet.java

Source

/*************************************************************************************************
 * Copyright (c) 2013, Lex @ le boxon de Lex: http://le-boxon-de-lex.fr
 *
 * This program is free software; you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program;
 * if not, see <http://www.gnu.org/licenses>.
 *
 * Additional permission under GNU GPL version 3 section 7
 *
 * If you modify this Program, or any covered work, by linking or combining it with Eclipse (or
 * a modified version of that library), containing parts covered by the terms of Eclipse Public
 * License (EPL), the licensors of this Program grant you additional permission to convey the
 * resulting work. Corresponding Source for a non-source form of such a combination shall include
 * the source code for the parts of D'Aplomb used as well as that of the covered work.
 ***************************************************************************************************/

package net.leboxondelex.daplomb.ui.facets;

import java.io.File;
import java.text.NumberFormat;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import net.leboxondelex.daplomb.Activator;
import net.leboxondelex.daplomb.images.ImageViewer;
import net.leboxondelex.daplomb.images.composers.AbstractImageComposer;
import net.leboxondelex.daplomb.images.composers.FirstIsBiggerComposer;
import net.leboxondelex.daplomb.images.composers.StripComposer;
import net.leboxondelex.daplomb.managers.ImageCacheManager;
import net.leboxondelex.daplomb.managers.PreferencesManager;
import net.leboxondelex.daplomb.managers.ResourceRegistry;
import net.leboxondelex.daplomb.model.AssemblyImage;
import net.leboxondelex.daplomb.translations.Messages;
import net.leboxondelex.daplomb.ui.swt.ImageCanvas;
import net.leboxondelex.daplomb.utils.ImageUtils;
import net.leboxondelex.daplomb.utils.Utils;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Spinner;

/**
 * @author Lex
 */
public class ImageViewerFacet extends ApplicationFacet {

    private static final int WIDGETS_TO_KEEP_COUNT = 5;

    private final ImageCacheManager imageCacheManager;
    private boolean lastTimeWasShuffled = false;

    private final Group statsGroup;
    private final ImageCanvas previewCanvas;
    private final Font appFont;

    /**
     * Constructor.
     * @param parent
     * @param appFont
     */
    public ImageViewerFacet(Composite parent, Font appFont) {
        super(parent);
        this.appFont = appFont;

        this.imageCacheManager = Activator.getPlugin().getImageCache();
        GridLayoutFactory.swtDefaults().margins(10, 10).spacing(20, 20).applyTo(this);
        setLayoutData(new GridData(GridData.FILL_BOTH));

        Composite groupsComposite = new Composite(this, SWT.NONE);
        GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).margins(0, 0).applyTo(groupsComposite);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(groupsComposite);

        this.statsGroup = new Group(groupsComposite, SWT.SHADOW_ETCHED_IN);
        this.statsGroup.setFont(appFont);
        GridLayoutFactory.swtDefaults().margins(7, 7).numColumns(2).applyTo(this.statsGroup);
        this.statsGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
        this.statsGroup.setText(Messages.getString("ImageViewerPart.4")); //$NON-NLS-1$
        updateProperties(null);

        final Group assemblyGroup = new Group(groupsComposite, SWT.SHADOW_ETCHED_IN);
        assemblyGroup.setFont(appFont);
        GridLayoutFactory.swtDefaults().numColumns(2).margins(7, 7).applyTo(assemblyGroup);
        assemblyGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
        assemblyGroup.setText(Messages.getString("ImageViewerPart.5")); //$NON-NLS-1$

        final Button randomButton = new Button(assemblyGroup, SWT.CHECK);
        randomButton.setFont(appFont);
        randomButton.setText(Messages.getString("ImageViewerPart.6")); //$NON-NLS-1$
        randomButton.setSelection(PreferencesManager.INSTANCE.isViewerRandom());
        GridDataFactory.swtDefaults().span(2, 1).applyTo(randomButton);

        Label l = new Label(assemblyGroup, SWT.NONE);
        l.setText(Messages.getString("ImageViewerPart.7")); //$NON-NLS-1$
        l.setFont(appFont);

        final Spinner assemblySpinner = new Spinner(assemblyGroup, SWT.BORDER);
        assemblySpinner.setFont(appFont);
        assemblySpinner.setValues(PreferencesManager.INSTANCE.getViewerNbPerAssembly(), 1, 10, 0, 1, 1);

        l = new Label(assemblyGroup, SWT.NONE);
        l.setText(Messages.getString("ImageViewerPart.8")); //$NON-NLS-1$
        l.setFont(appFont);

        final ComboViewer strategyViewer = new ComboViewer(assemblyGroup,
                SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN);
        strategyViewer.getCombo().setFont(appFont);
        strategyViewer.setLabelProvider(new LabelProvider());
        strategyViewer.setContentProvider(new ArrayContentProvider());
        strategyViewer.setInput(AbstractImageComposer.getComposers());

        this.previewCanvas = new ImageCanvas(this);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(this.previewCanvas);

        Composite buttonsComposite = new Composite(this, SWT.NONE);
        GridLayoutFactory.swtDefaults().margins(0, 0).numColumns(2).applyTo(buttonsComposite);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(buttonsComposite);

        final Button startButton = new Button(buttonsComposite, SWT.PUSH);
        startButton.setFont(appFont);
        startButton.setText(Messages.getString("ImageViewerPart.9")); //$NON-NLS-1$
        startButton.setToolTipText("Regarder en plein cran");
        startButton.setImage(ResourceRegistry.ICON_BROWSE_48x48);
        GridDataFactory.swtDefaults().align(SWT.FILL, SWT.BOTTOM).grab(true, false).hint(SWT.DEFAULT, 60)
                .applyTo(startButton);

        final Button shuffleButton = new Button(buttonsComposite, SWT.PUSH);
        shuffleButton.setImage(ResourceRegistry.ICON_SHUFFLE_48x48);
        shuffleButton.setToolTipText(Messages.getString("ImageViewerPart.10")); //$NON-NLS-1$
        GridDataFactory.swtDefaults().hint(SWT.DEFAULT, 60).applyTo(shuffleButton);

        // Listeners
        final AtomicBoolean refreshIsAllowed = new AtomicBoolean(false);
        strategyViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {

                Object o = ((IStructuredSelection) event.getSelection()).getFirstElement();
                AbstractImageComposer composer = (AbstractImageComposer) o;
                ImageViewerFacet.this.imageCacheManager.setImageComposer(composer);

                boolean needsRefresh = !composer.getName()
                        .equals(PreferencesManager.INSTANCE.getViewerAssemblyStrategy());
                if (needsRefresh) {
                    PreferencesManager.INSTANCE.saveViewerAssemblyStrategy(composer.getName());
                    if (refreshIsAllowed.get()) {
                        populateOptions(assemblyGroup, ImageViewerFacet.this.previewCanvas);
                        ImageViewerFacet.this.imageCacheManager.paintImage(ImageViewerFacet.this.previewCanvas);
                    }
                }
            }
        });

        randomButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                PreferencesManager.INSTANCE.saveViewerRandom(randomButton.getSelection());
            }
        });

        assemblySpinner.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                PreferencesManager.INSTANCE.saveViewerNbPerAssembly(assemblySpinner.getSelection());
                ImageViewerFacet.this.imageCacheManager.paintImage(ImageViewerFacet.this.previewCanvas);
            }
        });

        startButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {
                new ImageViewer().open(ImageViewerFacet.this.previewCanvas);
            }
        });

        shuffleButton.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event event) {

                boolean shuffle = System.nanoTime() % 2 == 0 && !ImageViewerFacet.this.lastTimeWasShuffled;
                shuffle = shuffle && ImageViewerFacet.this.imageCacheManager.canShuffle();
                ImageViewerFacet.this.lastTimeWasShuffled = shuffle;
                if (!shuffle)
                    ImageViewerFacet.this.imageCacheManager.nextImage();

                ImageViewerFacet.this.imageCacheManager.paintImage(ImageViewerFacet.this.previewCanvas, shuffle);
            }
        });

        // Initialize everything
        strategyViewer.setSelection(new StructuredSelection(this.imageCacheManager.getImageComposer()));
        populateOptions(assemblyGroup, this.previewCanvas);

        refreshIsAllowed.set(true);
        this.imageCacheManager.paintImage(this.previewCanvas);
    }

    /**
     * Populates the strategy options in the UI.
     * @param parent
     * @param previewCanvas
     */
    private void populateOptions(Group parent, final ImageCanvas previewCanvas) {

        int cpt = 0;
        for (Control c : parent.getChildren()) {
            cpt++;
            if (cpt <= WIDGETS_TO_KEEP_COUNT)
                continue;

            if (!c.isDisposed())
                c.dispose();
        }

        // "First is bigger" options
        final AbstractImageComposer composer = this.imageCacheManager.getImageComposer();
        if (composer instanceof FirstIsBiggerComposer) {
            Label l = new Label(parent, SWT.NONE);
            l.setText(Messages.getString("ImageViewerPart.12")); //$NON-NLS-1$
            l.setFont(this.appFont);

            Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY | SWT.DROP_DOWN);
            combo.setFont(this.appFont);
            combo.add(Messages.getString("ImageViewerPart.13")); //$NON-NLS-1$
            combo.add(Messages.getString("ImageViewerPart.14")); //$NON-NLS-1$
            combo.add(Messages.getString("ImageViewerPart.15")); //$NON-NLS-1$

            int sort = PreferencesManager.INSTANCE.getSaveStrategyFirstIsBiggerSort();
            combo.select(sort == -1 ? 2 : sort);
            combo.addListener(SWT.Selection, new Listener() {
                @Override
                public void handleEvent(Event event) {
                    int index = ((Combo) event.widget).getSelectionIndex();
                    int sort = index == 0 ? 0 : index == 1 ? 1 : -1;
                    ((FirstIsBiggerComposer) composer).setSort(sort);
                    ImageViewerFacet.this.imageCacheManager.imageComposerPropertyChanged();

                    PreferencesManager.INSTANCE.saveStrategyFirstIsBiggerSort(sort);
                    ImageViewerFacet.this.imageCacheManager.paintImage(previewCanvas);
                }
            });

            new Label(parent, SWT.NONE);
            Button limitSizeButton = new Button(parent, SWT.CHECK);
            limitSizeButton.setFont(this.appFont);
            limitSizeButton.setText(Messages.getString("ImageViewerPart.16")); //$NON-NLS-1$

            boolean limit = PreferencesManager.INSTANCE.isStrategyFirstIsBiggerLimit();
            limitSizeButton.setSelection(limit);
            limitSizeButton.addListener(SWT.Selection, new Listener() {
                @Override
                public void handleEvent(Event event) {
                    boolean selection = ((Button) event.widget).getSelection();
                    ((FirstIsBiggerComposer) composer).setLimitSize(selection);
                    ImageViewerFacet.this.imageCacheManager.imageComposerPropertyChanged();

                    PreferencesManager.INSTANCE.saveStrategyFirstIsBiggerLimit(selection);
                    ImageViewerFacet.this.imageCacheManager.paintImage(previewCanvas);
                }
            });
        }

        // "Best Fit" options
        else if (composer instanceof StripComposer) {
            new Label(parent, SWT.NONE);

            Button applyCorrectionsButton = new Button(parent, SWT.CHECK);
            applyCorrectionsButton.setFont(this.appFont);
            applyCorrectionsButton.setText(Messages.getString("ImageViewerPart.17")); //$NON-NLS-1$

            boolean democratic = PreferencesManager.INSTANCE.isStrategyStripsDemocratic();
            applyCorrectionsButton.setSelection(!democratic);
            applyCorrectionsButton.addListener(SWT.Selection, new Listener() {
                @Override
                public void handleEvent(Event event) {
                    boolean democratic = !((Button) event.widget).getSelection();
                    ((StripComposer) composer).setDemocraticStrategy(democratic);
                    ImageViewerFacet.this.imageCacheManager.imageComposerPropertyChanged();

                    PreferencesManager.INSTANCE.saveStrategyStripsDemocratic(democratic);
                    ImageViewerFacet.this.imageCacheManager.paintImage(previewCanvas);
                }
            });
        }

        parent.layout();
        parent.getParent().layout();
        parent.getParent().getParent().layout();
    }

    /*
     * (non-Javadoc)
     * @see net.leboxondelex.daplomb.ui.facets.ApplicationFacet
     * #registerFileMenus(org.eclipse.swt.widgets.Menu)
     */
    @Override
    public void registerFileMenus(Menu fileMenu) {

        MenuItem item = new MenuItem(fileMenu, SWT.PUSH, 0);
        item.setText("Ouvrir...");
        item.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event e) {

                File f = PreferencesManager.INSTANCE.getViewerDirectory();
                DirectoryDialog dlg = new DirectoryDialog(getShell());
                if (f != null)
                    dlg.setFilterPath(f.getAbsolutePath());

                String s = dlg.open();
                if (s != null) {
                    f = new File(s);
                    PreferencesManager.INSTANCE.saveViewerDirectory(f);
                    updateProperties(f);
                    ImageViewerFacet.this.imageCacheManager.paintImage(ImageViewerFacet.this.previewCanvas, false,
                            1);
                }
            }
        });

        item = new MenuItem(fileMenu, SWT.PUSH, 1);
        item.setText("Enregistrer l'Image...");
        item.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event e) {

                FileDialog dlg = new FileDialog(getShell(), SWT.SAVE);
                dlg.setOverwrite(true);
                dlg.setFilterExtensions(new String[] { "*.jpg" });
                dlg.setFilterNames(new String[] { "JPG" });

                String s = dlg.open();
                if (s != null) {
                    AssemblyImage img = ImageViewerFacet.this.previewCanvas.getImage();
                    ImageUtils.saveAssemblyImage(img, new File(s));
                }
            }
        });

        item = new MenuItem(fileMenu, SWT.PUSH, 2);
        item.setText("Copier dans le Presse-Papier");
        item.addListener(SWT.Selection, new Listener() {
            @Override
            public void handleEvent(Event e) {
                ImageViewerFacet.this.previewCanvas.copyContentToClipboard();
            }
        });

        new MenuItem(fileMenu, SWT.SEPARATOR, 3);
    }

    /**
     * @param f
     */
    private void updateProperties(File f) {
        for (Control c : this.statsGroup.getChildren()) {
            if (!c.isDisposed())
                c.dispose();
        }

        if (f == null)
            f = PreferencesManager.INSTANCE.getViewerDirectory();

        final Label nameLabel = new Label(this.statsGroup, SWT.NONE);
        nameLabel.setText(Messages.getString("ImageViewerPart.0")); //$NON-NLS-1$
        nameLabel.setFont(this.appFont);
        new Label(this.statsGroup, SWT.NONE).setText(f.getName().isEmpty() ? "-" : f.getName());

        final Label pathLabel = new Label(this.statsGroup, SWT.NONE);
        pathLabel.setText(Messages.getString("ImageViewerPart.1")); //$NON-NLS-1$
        pathLabel.setFont(this.appFont);
        new Label(this.statsGroup, SWT.NONE).setText(f.getAbsolutePath());

        final Label nbImgLabel = new Label(this.statsGroup, SWT.NONE);
        nbImgLabel.setText(Messages.getString("ImageViewerPart.2")); //$NON-NLS-1$
        nbImgLabel.setFont(this.appFont);

        // Complete this update
        this.statsGroup.layout();

        // Counting image files can take time
        final AtomicInteger imgCount = new AtomicInteger();
        final Runnable displayUpdate = new Runnable() {
            @Override
            public void run() {
                String s = NumberFormat.getInstance().format(imgCount.get());
                new Label(ImageViewerFacet.this.statsGroup, SWT.NONE).setText(s);
                ImageViewerFacet.this.statsGroup.layout();
            }
        };

        final File theFile = f;
        Runnable asyncCount = new Runnable() {
            @Override
            public void run() {
                int cpt = Utils.findImageFiles(theFile).length;
                imgCount.set(cpt);
                getDisplay().asyncExec(displayUpdate);
            }
        };

        new Thread(asyncCount).start();
    }
}