Java tutorial
/************************************************************************************************* * 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(); } }