com.b3dgs.lionengine.editor.factory.FactoryView.java Source code

Java tutorial

Introduction

Here is the source code for com.b3dgs.lionengine.editor.factory.FactoryView.java

Source

/*
 * Copyright (C) 2013-2014 Byron 3D Games Studio (www.b3dgs.com) Pierre-Alexandre (contact@b3dgs.com)
 * 
 * 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 2
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package com.b3dgs.lionengine.editor.factory;

import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

import com.b3dgs.lionengine.LionEngineException;
import com.b3dgs.lionengine.UtilConversion;
import com.b3dgs.lionengine.UtilFile;
import com.b3dgs.lionengine.core.Media;
import com.b3dgs.lionengine.core.swt.UtilityMedia;
import com.b3dgs.lionengine.editor.Tools;
import com.b3dgs.lionengine.editor.palette.PaletteView;
import com.b3dgs.lionengine.editor.project.Project;
import com.b3dgs.lionengine.editor.project.tester.ObjectsFolderTester;
import com.b3dgs.lionengine.editor.world.WorldViewModel;
import com.b3dgs.lionengine.game.FactoryObjectGame;
import com.b3dgs.lionengine.game.SetupGame;
import com.b3dgs.lionengine.game.configurer.ConfigSurface;

/**
 * Represents the factory view, where the objects list is displayed.
 * 
 * @author Pierre-Alexandre (contact@b3dgs.com)
 */
public class FactoryView implements PaletteView {
    /** View ID. */
    public static final String ID = "factory";

    /**
     * Fill the combo items with its folder list.
     * 
     * @param typeCombo The combo reference.
     * @param folders The handled folders.
     */
    private static void fillCombo(Combo typeCombo, File[] folders) {
        final Collection<File> elements = new ArrayList<>(1);
        for (final File folder : folders) {
            if (folder.isDirectory()) {
                elements.add(folder);
            }
        }
        final File[] items = elements.toArray(new File[elements.size()]);
        final String[] names = new String[items.length];
        for (int i = 0; i < items.length; i++) {
            final String name = UtilConversion.toTitleCaseWord(items[i].getName());
            typeCombo.setData(name, items[i]);
            names[i] = name;
        }
        typeCombo.setItems(names);
    }

    /**
     * Create a combo from the type name.
     * 
     * @param typeName The type name.
     * @param parent The parent composite.
     * @return The combo instance.
     */
    private static Combo createCombo(String typeName, Composite parent) {
        final Composite typeComposite = new Composite(parent, SWT.NONE);
        final GridLayout layout = new GridLayout(2, true);
        layout.marginHeight = 0;
        typeComposite.setLayout(layout);

        final Label typeLabel = new Label(typeComposite, SWT.NONE);
        typeLabel.setText(typeName);

        final Combo typeCombo = new Combo(typeComposite, SWT.READ_ONLY);
        return typeCombo;
    }

    /**
     * Load the object icon if has.
     * 
     * @param objectLabel The object label reference.
     * @param file The object data file.
     * @param setup The object setup reference.
     * @throws LionEngineException If an error occurred when loading the icon.
     */
    private static void loadObjectIcon(Label objectLabel, File file, SetupGame setup) throws LionEngineException {
        try {
            final ConfigSurface configSurface = ConfigSurface.create(setup.getConfigurer());
            final String icon = configSurface.getIcon();
            final File iconPath = new File(file.getParentFile(), icon);
            if (iconPath.isFile()) {
                final ImageDescriptor descriptor = ImageDescriptor.createFromURL(iconPath.toURI().toURL());
                objectLabel.setImage(descriptor.createImage());
            }
        } catch (final MalformedURLException exception) {
            throw new LionEngineException(exception);
        }
    }

    /** Part service. */
    final EPartService partService;
    /** The combo hierarchy. */
    final Map<String, Composite> hierarchy = new HashMap<>();
    /** The factory reference. */
    private FactoryObjectGame<?> factory;
    /** Middle composite. */
    Composite middle;
    /** Bottom composite. */
    Composite bottom;
    /** Objects composite. */
    Composite objectsComposite;
    /** Last selected object. */
    Label lastObject;

    /**
     * Create the factory view.
     * 
     * @param partService The part service reference.
     */
    public FactoryView(EPartService partService) {
        this.partService = partService;
    }

    /**
     * Set the factory object used.
     * 
     * @param factory The factory reference.
     */
    public void setFactory(FactoryObjectGame<?> factory) {
        this.factory = factory;
    }

    /**
     * Load elements from root folder.
     * 
     * @param factory The factory reference.
     * @param path The folder path.
     * @param parent The composite parent.
     * @return The created child composite.
     * @throws FileNotFoundException If not a type folder.
     */
    Composite load(final FactoryObjectGame<?> factory, File path, final Composite parent)
            throws FileNotFoundException {
        final File[] folders = path.listFiles();
        if (folders != null) {
            final String typeName = Tools.getObjectsFolderTypeName(path);
            final Composite composite = new Composite(parent, SWT.NONE);
            final GridLayout layout = new GridLayout(1, false);
            layout.marginHeight = 0;
            composite.setLayout(layout);
            composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
            final Combo typeCombo = FactoryView.createCombo(typeName, composite);
            FactoryView.fillCombo(typeCombo, folders);

            middle.getShell().layout(true, true);

            typeCombo.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent selectionEvent) {
                    WorldViewModel.INSTANCE.setSelectedObject(null);
                    lastObject = null;
                    loadSub(typeCombo, typeName, composite);
                }
            });
            return composite;
        }
        return null;
    }

    /**
     * Load sub tree from current type.
     * 
     * @param typeCombo The type combo.
     * @param typeName The current type name.
     * @param composite The composite reference.
     */
    void loadSub(Combo typeCombo, String typeName, Composite composite) {
        final Object data = typeCombo.getData(typeCombo.getItem(typeCombo.getSelectionIndex()));
        if (data instanceof File) {
            if (objectsComposite != null) {
                objectsComposite.dispose();
            }
            final File typeFolder = (File) data;
            try {
                if (hierarchy.containsKey(typeName)) {
                    hierarchy.get(typeName).dispose();
                    hierarchy.remove(typeName);
                }
                final Composite child = load(factory, typeFolder, composite);
                if (child != null) {
                    hierarchy.put(typeName, child);
                }
            } catch (final FileNotFoundException exception) {
                createObjects(typeFolder.listFiles());
            }
        }
    }

    /**
     * Create the objects list from their file.
     * 
     * @param objectsFile The objects file.
     */
    void createObjects(File[] objectsFile) {
        objectsComposite = new Composite(bottom, SWT.BORDER);
        objectsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        objectsComposite.setLayout(new RowLayout());

        final FactoryObjectGame<?> factory = WorldViewModel.INSTANCE.getFactory();
        loadObjects(factory, objectsFile);
    }

    /**
     * Load all objects from their folder (filter them by extension, <code>*.xml</code> expected).
     * 
     * @param factory The factory reference.
     * @param objectFiles The objects path.
     */
    void loadObjects(FactoryObjectGame<?> factory, File[] objectFiles) {
        if (objectFiles != null) {
            for (final File objectFile : objectFiles) {
                if (objectFile.isFile() && ObjectsFolderTester.isObjectFile(UtilityMedia.get(objectFile))) {
                    loadObject(factory, objectFile);
                }
            }
        }
        if (!bottom.isDisposed()) {
            bottom.getShell().layout(true, true);
        }
    }

    /**
     * Load an object from its file data, and add it to the tab.
     * 
     * @param factory The factory reference.
     * @param file The object data file.
     */
    private void loadObject(FactoryObjectGame<?> factory, File file) {
        final Label objectLabel = new Label(objectsComposite, SWT.NONE);
        objectLabel.setLayoutData(new RowData(34, 34));
        objectLabel.setBackground(objectLabel.getDisplay().getSystemColor(SWT.COLOR_GRAY));
        final String name = UtilFile.removeExtension(file.getName());
        objectLabel.setText(name);

        objectLabel.addMouseTrackListener(new MouseTrackListener() {
            @Override
            public void mouseHover(MouseEvent e) {
                // Nothing to do
            }

            @Override
            public void mouseExit(MouseEvent e) {
                if (lastObject != objectLabel) {
                    objectLabel.setBackground(objectLabel.getDisplay().getSystemColor(SWT.COLOR_GRAY));
                }
            }

            @Override
            public void mouseEnter(MouseEvent e) {
                objectLabel.setBackground(objectLabel.getDisplay().getSystemColor(SWT.COLOR_BLACK));
            }
        });
        objectLabel.addMouseListener(new MouseListener() {
            @Override
            public void mouseUp(MouseEvent mouseEvent) {
                if (lastObject != null) {
                    lastObject.setBackground(lastObject.getDisplay().getSystemColor(SWT.COLOR_GRAY));
                }
                if (lastObject == objectLabel) {
                    WorldViewModel.INSTANCE.setSelectedObject(null);
                    lastObject = null;
                } else {
                    final Object data = objectLabel.getData();
                    if (data instanceof Media) {
                        WorldViewModel.INSTANCE.setSelectedObject((Media) data);
                        objectLabel.setBackground(objectLabel.getDisplay().getSystemColor(SWT.COLOR_BLACK));
                        lastObject = objectLabel;
                    }
                }
            }

            @Override
            public void mouseDown(MouseEvent mouseEvent) {
                // Nothing to do
            }

            @Override
            public void mouseDoubleClick(MouseEvent mouseEvent) {
                // Nothing to do
            }
        });

        final Media media = UtilityMedia.get(file);
        final SetupGame setup = factory.getSetup(media);

        FactoryView.loadObjectIcon(objectLabel, file, setup);
        objectLabel.setToolTipText(name);
        objectLabel.setData(media);
    }

    /**
     * Create the middle part, dedicated to group group selection.
     * 
     * @param parent The composite parent.
     */
    private void createMiddle(Composite parent) {
        middle = new Composite(parent, SWT.NONE);
        middle.setLayout(new GridLayout(1, false));
    }

    /**
     * Create the bottom part, dedicated to the object list.
     * 
     * @param parent The composite parent.
     */
    private void createBottom(Composite parent) {
        bottom = new Composite(parent, SWT.NONE);
        bottom.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        bottom.setLayout(new GridLayout(1, false));
    }

    /*
     * PaletteView
     */

    @Override
    public void create(Composite parent) {
        parent.setLayout(new GridLayout(1, false));

        createMiddle(parent);

        final Label separatorMiddle = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
        separatorMiddle.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

        createBottom(parent);

        final File objectsPath = new File(Project.getActive().getResourcesPath(), factory.getFolder());
        try {
            load(factory, objectsPath, middle);
        } catch (final FileNotFoundException exception) {
            createObjects(objectsPath.listFiles());
        }
    }

    @Override
    public String getId() {
        return FactoryView.ID;
    }
}