phasereditor.ui.PhaserEditorUI.java Source code

Java tutorial

Introduction

Here is the source code for phasereditor.ui.PhaserEditorUI.java

Source

// The MIT License (MIT)
//
// Copyright (c) 2015 Arian Fornaris
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions: The above copyright notice and this permission
// notice shall be included in all copies or substantial portions of the
// Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
package phasereditor.ui;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;

import org.eclipse.core.resources.IFile;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wb.swt.SWTResourceManager;

import phasereditor.ui.views.PreviewView;

public class PhaserEditorUI {
    public static Color PREVIEW_BG_DARK = SWTResourceManager.getColor(180, 180, 180);
    public static Color PREVIEW_BG_LIGHT = SWTResourceManager.getColor(200, 200, 200);
    private static Set<Object> _supportedImageExts = new HashSet<>(
            Arrays.asList("png", "bmp", "jpg", "gif", "ico"));

    private PhaserEditorUI() {
    }

    public static boolean isEditorSupportedImage(IFile file) {
        return _supportedImageExts.contains(file.getFileExtension().toLowerCase());
    }

    public static IFile pickFileWithoutExtension(List<IFile> files, String... exts) {
        if (files.isEmpty()) {
            return null;
        }
        Set<String> set = new HashSet<>();
        for (String ext : exts) {
            set.add(ext.toLowerCase());
        }
        for (IFile file : files) {
            String ext = file.getFileExtension().toLowerCase();
            if (!set.contains(ext)) {
                return file;
            }
        }
        return files.get(0);
    }

    public static Path eclipseFileToJavaPath(IFile file) {
        return Paths.get(file.getLocation().toPortableString());
    }

    public interface ISearchFilter {
        public void setSearchText(String str);
    }

    public static void initSearchText(Text text, StructuredViewer viewer, ViewerFilter filter) {
        String msg = "type filter text";
        text.setText(msg);

        viewer.setFilters(new ViewerFilter[] { filter });

        text.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                if (text.getText().equals(msg)) {
                    text.setText("");
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                if (text.getText().trim().length() == 0) {
                    text.setText(msg);
                }
            }
        });

        text.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                String str = text.getText();
                ((ISearchFilter) filter).setSearchText(str);
                viewer.refresh();
                if (viewer instanceof TreeViewer) {
                    if (str.trim().length() > 0) {
                        ((TreeViewer) viewer).expandAll();
                    }
                }
            }
        });
    }

    public static class SimpleSearchFilter extends ViewerFilter implements ISearchFilter {

        private String _searchString;
        private ILabelProvider _labelProvider;
        private Map<Object, Boolean> _cache;

        public SimpleSearchFilter(ILabelProvider labelProvider) {
            super();
            _labelProvider = labelProvider;
            _cache = new HashMap<>();
        }

        @Override
        public void setSearchText(String s) {
            this._searchString = ".*" + s.toLowerCase().replace("*", ".*") + ".*";
            _cache = new HashMap<>();
        }

        @Override
        public boolean select(Viewer viewer, Object parent, Object element) {
            if (_cache.containsKey(element)) {
                return _cache.get(element).booleanValue();
            }

            boolean b = select2(viewer, parent, element);

            _cache.put(element, Boolean.valueOf(b));

            return b;
        }

        private boolean select2(Viewer viewer, Object parent, Object element) {
            if (_searchString == null || _searchString.length() == 4) {
                return true;
            }

            {
                // if it is not final, then match it if any children match.
                IContentProvider provider = ((StructuredViewer) viewer).getContentProvider();
                if (provider instanceof ITreeContentProvider) {
                    Object[] children = ((ITreeContentProvider) provider).getChildren(element);
                    if (children.length > 0) {
                        for (Object child : children) {
                            if (select(viewer, element, child)) {
                                return true;
                            }
                        }
                    }
                }
            }

            if (matches(parent)) {
                return true;
            }

            return matches(element);
        }

        private boolean matches(Object element) {
            String text = _labelProvider.getText(element).toLowerCase();

            if (text.matches(_searchString)) {
                return true;
            }

            return false;
        }
    }

    public static void initSearchText(Text text, StructuredViewer viewer, ILabelProvider labelProvider) {
        initSearchText(text, viewer, new SimpleSearchFilter(labelProvider));
    }

    /**
     * <p>
     * Searches "searchTerm" in "content" and returns an array of int pairs
     * (index, length) for each occurrence. The search is case-sensitive. The
     * consecutive occurrences are merged together.
     * </p>
     * <p>
     * Examples:
     * </p>
     * 
     * <pre>
     * content = "123123x123"
     * searchTerm = "1"
     * --> [0, 1, 3, 1, 7, 1]
     * content = "123123x123"
     * searchTerm = "123"
     * --> [0, 6, 7, 3]
     * </pre>
     * 
     * http://www.vogella.com/tutorials/EclipseJFaceTableAdvanced/article.html
     * 
     * @param searchTerm
     *            can be null or empty. int[0] is returned in this case!
     * @param content
     *            a not-null string (can be empty!)
     * @return an array of int pairs (index, length)
     */

    public static int[] getSearchTermOccurrences(final String searchTerm, final String content) {
        if (searchTerm == null || searchTerm.length() == 0) {
            return new int[0];
        }
        if (content == null) {
            throw new IllegalArgumentException("content is null");
        }
        final List<Integer> list = new ArrayList<>();
        int searchTermLength = searchTerm.length();
        int index;
        int fromIndex = 0;
        int lastIndex = -1;
        int lastLength = 0;
        while (true) {
            index = content.indexOf(searchTerm, fromIndex);
            if (index == -1) {
                // no occurrence of "searchTerm" in "content" starting from
                // index "fromIndex"
                if (lastIndex != -1) {
                    // but there was a previous occurrence
                    list.add(Integer.valueOf(lastIndex));
                    list.add(Integer.valueOf(lastLength));
                }
                break;
            }
            if (lastIndex == -1) {
                // the first occurrence of "searchTerm" in "content"
                lastIndex = index;
                lastLength = searchTermLength;
            } else {
                if (lastIndex + lastLength == index) {
                    // the current occurrence is right after the previous
                    // occurrence
                    lastLength += searchTermLength;
                } else {
                    // there is at least one character between the current
                    // occurrence and the previous one
                    list.add(Integer.valueOf(lastIndex));
                    list.add(Integer.valueOf(lastLength));
                    lastIndex = index;
                    lastLength = searchTermLength;
                }
            }
            fromIndex = index + searchTermLength;
        }
        final int n = list.size();
        final int[] result = new int[n];
        for (int i = 0; i != n; i++) {
            result[i] = list.get(i).intValue();
        }
        return result;
    }

    public static StyledCellLabelProvider createSearchLabelProvider(Supplier<String> getStr,
            Function<Object, String> toStr) {
        return new StyledCellLabelProvider() {
            @Override
            public void update(ViewerCell cell) {
                String search = getStr.get();
                String cellText = toStr.apply(cell.getElement());
                cell.setText(cellText);
                if (search != null && search.length() > 0) {
                    int intRangesCorrectSize[] = getSearchTermOccurrences(search, cellText);
                    List<StyleRange> styleRange = new ArrayList<>();
                    for (int i = 0; i < intRangesCorrectSize.length / 2; i++) {
                        int start = intRangesCorrectSize[i];
                        int length = intRangesCorrectSize[++i];
                        StyleRange myStyledRange = new StyleRange(start, length, null, null);
                        myStyledRange.font = SWTResourceManager.getBoldFont(cell.getFont());
                        styleRange.add(myStyledRange);
                    }
                    cell.setStyleRanges(styleRange.toArray(new StyleRange[styleRange.size()]));
                } else {
                    cell.setStyleRanges(null);
                }

                super.update(cell);

            }
        };
    }

    public static void paintPreviewBackground(GC gc, Rectangle canvasBounds) {
        paintPreviewBackground(gc, canvasBounds, 10);
    }

    public static void paintPreviewBackground(GC gc, Rectangle canvasBounds, int space) {
        Rectangle oldClip = gc.getClipping();
        gc.setClipping(canvasBounds);
        int nx = canvasBounds.width / space + 2;
        int ny = canvasBounds.height / space + 2;
        for (int x = -1; x < nx; x++) {
            for (int y = 0; y < ny; y++) {
                int fx = canvasBounds.x / space * space + x * space;
                int fy = canvasBounds.y / space * space + y * space;
                if ((fx / space + fy / space) % 2 == 0) {
                    gc.setBackground(PREVIEW_BG_DARK);
                } else {
                    gc.setBackground(PREVIEW_BG_LIGHT);
                }
                gc.fillRectangle(fx, fy, space, space);
            }
        }
        gc.setClipping(oldClip);
    }

    public static void paintPreviewMessage(GC gc, Rectangle canvasBounds, String msg) {
        Point msgSize = gc.stringExtent(msg);
        int x = canvasBounds.width / 2 - msgSize.x / 2;
        if (x < 0) {
            x = 5;
        }
        int y = canvasBounds.height / 2 - msgSize.y / 2;
        gc.setBackground(PREVIEW_BG_DARK);
        gc.setForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
        gc.drawText(msg, x, y);
    }

    public static void swtRunRedraw(Control c) {
        swtRun(c, (c2) -> {
            c2.redraw();
        });
    }

    public static void swtRun(Runnable run) {
        try {
            Display display = Display.getDefault();
            display.asyncExec(new Runnable() {

                @Override
                public void run() {
                    try {
                        run.run();
                    } catch (SWTException e) {
                        // nothing
                    }
                }
            });
        } catch (SWTException e) {
            // nothing
        }
    }

    public static <T extends Control> void swtRun(final T c, Consumer<T> action) {
        Display display = Display.getDefault();

        if (display.isDisposed()) {
            return;
        }

        if (Thread.currentThread() == display.getThread()) {
            if (c.isDisposed()) {
                return;
            }

            action.accept(c);
            return;
        }

        try {
            display.asyncExec(new Runnable() {

                @Override
                public void run() {
                    if (!c.isDisposed()) {
                        action.accept(c);
                    }
                }
            });
        } catch (SWTException e) {
            //
        }
    }

    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            // e.printStackTrace();
        }
    }

    public static void openPreview(Object obj) {
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        try {
            PreviewView view = (PreviewView) page.showView(PreviewView.ID);
            view.preview(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
    private static final String[] Q = new String[] { "", "k", "m", "g", "t", "P", "E" };

    public static String getFileHumanSize(long bytes) {
        for (int i = 6; i > 0; i--) {
            double step = Math.pow(1024, i);
            if (bytes > step)
                return String.format("%3.1f %sb", Double.valueOf(bytes / step), Q[i]);
        }
        return Long.toString(bytes);
    }

    public static Rectangle computeImageZoom(Rectangle srcBounds, Rectangle dstBounds) {
        int srcW = srcBounds.width;
        int srcH = srcBounds.height;
        int dstW = srcW;
        int dstH = srcH;
        double ratio = srcW / (double) srcH;
        int controlHeight = dstBounds.height;
        int controlWidth = dstBounds.width;

        if (srcW >= dstW || srcH >= dstH) {
            if (srcW > srcH && srcW > controlWidth) {
                dstW = controlWidth;
                dstH = (int) (dstW / ratio);
            } else if (srcH > controlHeight) {
                dstH = controlHeight;
                dstW = (int) (dstH * ratio);
            }

            if (dstW > controlWidth) {
                dstW = controlWidth;
                dstH = (int) (dstW / ratio);
            }

            if (dstH > controlHeight) {
                dstH = controlHeight;
                dstW = (int) (dstH * ratio);
            }
        }

        int dstX = (controlWidth - dstW) / 2;
        int dstY = (controlHeight - dstH) / 2;

        return new Rectangle(dstX, dstY, dstW, dstH);
    }

    public static String readString(InputStream input) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        return sb.toString();
    }

    public static String getNameFromFilename(String name) {
        String name2 = name;
        name2 = Paths.get(name).getFileName().toString();
        int i = name2.lastIndexOf(".");
        if (i > 0) {
            name2 = name2.substring(0, i);
        }
        return name2;
    }

    public static String getExtensionFromFilename(String name) {
        int i = name.lastIndexOf(".");
        if (i > 0) {
            return name.substring(i + 1, name.length());
        }
        return "";
    }

    public static void setStyle(String style, Control... controls) {
        for (Control control : controls) {
            control.setData("org.eclipse.e4.ui.css.CssClassName", style);
        }
    }

    public static Image getFileImage(IFile file) {
        try (InputStream contents = file.getContents();) {
            Image img = getStreamImage(contents);
            return img;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Image getFileImage(Path file) {
        try (InputStream contents = Files.newInputStream(file)) {
            Image img = getStreamImage(contents);
            return img;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Image getStreamImage(InputStream stream) throws IOException {
        try {
            Display display = Display.getCurrent();
            ImageData data = new ImageData(stream);
            if (data.transparentPixel > 0) {
                return new Image(display, data, data.getTransparencyMask());
            }
            return new Image(display, data);
        } finally {
            stream.close();
        }
    }

    public static Rectangle getImageBounds(String filepath) {
        try (FileImageInputStream input = new FileImageInputStream(new File(filepath))) {
            ImageReader reader = ImageIO.getImageReaders(input).next();
            reader.setInput(input);
            int w = reader.getWidth(0);
            int h = reader.getHeight(0);
            return new Rectangle(0, 0, w, h);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Rectangle getImageBounds(IFile file) {
        return getImageBounds(file.getLocation().toPortableString());
    }

    public static Image makeColorIcon(RGB rgb) {
        RGB black = new RGB(0, 0, 0);
        PaletteData dataPalette = new PaletteData(new RGB[] { black, black, rgb });
        ImageData data = new ImageData(16, 16, 4, dataPalette);
        data.transparentPixel = 0;

        int start = 3;
        int end = 16 - start;
        for (int y = start; y <= end; y++) {
            for (int x = start; x <= end; x++) {
                if (x == start || y == start || x == end || y == end) {
                    data.setPixel(x, y, 1);
                } else {
                    data.setPixel(x, y, 2);
                }
            }
        }

        Image img = new Image(Display.getCurrent(), data);

        return img;
    }
}