com.laex.cg2d.entityeditor.views.EntitiesView.java Source code

Java tutorial

Introduction

Here is the source code for com.laex.cg2d.entityeditor.views.EntitiesView.java

Source

/*
 * Copyright (c) 2012, 2013 Hemanta Sapkota.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Hemanta Sapkota (laex.pearl@gmail.com)
 */
package com.laex.cg2d.entityeditor.views;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ImageHyperlink;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;

import com.laex.cg2d.entityeditor.Activator;
import com.laex.cg2d.model.CGCProject;
import com.laex.cg2d.model.DNDFileTransfer;
import com.laex.cg2d.model.DNDFileTransfer.TransferType;
import com.laex.cg2d.model.EntityManager;
import com.laex.cg2d.model.EntityResourceChangeListener;
import com.laex.cg2d.model.EntityResourceChangeListener.EntityChangeListener;
import com.laex.cg2d.model.ICGCProject;
import com.laex.cg2d.model.IEntityManager;
import com.laex.cg2d.model.model.Entity;
import com.laex.cg2d.model.model.ModelValidator;
import com.laex.cg2d.model.model.ModelValidatorFactory;
import com.laex.cg2d.model.resources.ResourceManager;
import com.laex.cg2d.model.util.EntitiesUtil;

/**
 * The Class EntitiesView.
 */
public class EntitiesView extends ViewPart
        implements ISelectionListener, IEntityManager, EntityChangeListener, ControlListener {

    /** The Constant ID. */
    public static final String ID = EntityManager.ENTITIES_VIEW_ID; //$NON-NLS-1$

    /** The form toolkit. */
    private final FormToolkit formToolkit = new FormToolkit(Display.getDefault());

    /** The selected project. */
    private IProject selectedProject;

    /** The entities map. */
    private Map<String, Entity> entitiesMap = new HashMap<String, Entity>();

    /** The entities buttons. */
    private Map<String, Button> entitiesButtons = new HashMap<String, Button>();

    /** The temp removed list. */
    Map<String, Button> tempRemovedList = new HashMap<String, Button>();

    /** The entities resource listener. */
    private EntityResourceChangeListener entitiesResourceListener = new EntityResourceChangeListener();

    /** The work to do. */
    int workToDO = 0;

    /** The sctn entities. */
    private Section sctnEntities;

    /** The scrolled composite. */
    private ScrolledComposite scrolledComposite;

    /** The ent composite. */
    private Composite entComposite;

    /** The composite. */
    private Composite composite;

    /** The txt filter. */
    private Text txtFilter;

    /** The label. */
    private Label label;

    /**
     * Instantiates a new entities view.
     */
    public EntitiesView() {
    }

    /**
     * Create contents of the view part.
     *
     * @param parent the parent
     */
    @Override
    public void createPartControl(Composite parent) {
        {
            sctnEntities = formToolkit.createSection(parent, Section.TITLE_BAR);
            formToolkit.paintBordersFor(sctnEntities);
            sctnEntities.setExpanded(true);
            {
                scrolledComposite = new ScrolledComposite(sctnEntities, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
                formToolkit.adapt(scrolledComposite);
                formToolkit.paintBordersFor(scrolledComposite);
                sctnEntities.setClient(scrolledComposite);

                scrolledComposite.setExpandHorizontal(true);
                scrolledComposite.setExpandVertical(true);

                entComposite = formToolkit.createComposite(scrolledComposite, SWT.NONE);
                formToolkit.paintBordersFor(entComposite);
            }
            {
                composite = formToolkit.createComposite(sctnEntities, SWT.NONE);
                composite.setBackground(null);
                formToolkit.paintBordersFor(composite);
                sctnEntities.setTextClient(composite);
                composite.setLayout(new RowLayout(SWT.HORIZONTAL));

                ImageHyperlink mghprlnkNewImagehyperlink = formToolkit.createImageHyperlink(composite, SWT.NONE);
                mghprlnkNewImagehyperlink.addHyperlinkListener(new IHyperlinkListener() {
                    public void linkActivated(HyperlinkEvent e) {

                        txtFilter.setText("");

                        loadAllEntitiesWithProgress();
                    }

                    public void linkEntered(HyperlinkEvent e) {
                    }

                    public void linkExited(HyperlinkEvent e) {
                    }
                });
                mghprlnkNewImagehyperlink.setBackground(null);
                formToolkit.paintBordersFor(mghprlnkNewImagehyperlink);
                mghprlnkNewImagehyperlink.setText("Reload");
            }

            txtFilter = formToolkit.createText(sctnEntities, "", SWT.NONE);
            txtFilter.setText("");
            txtFilter.setMessage("Filter entities");
            txtFilter.addModifyListener(new ModifyListener() {
                @Override
                public void modifyText(ModifyEvent e) {
                    doFilter();
                }
            });

            sctnEntities.setDescriptionControl(txtFilter);

            label = formToolkit.createSeparator(sctnEntities, SWT.HORIZONTAL);
            sctnEntities.setSeparatorControl(label);
        }

        createActions();
        initializeToolBar();
        initializeMenu();

        getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this);

        ResourcesPlugin.getWorkspace().addResourceChangeListener(entitiesResourceListener,
                IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);

        entitiesResourceListener.addEntityChangeListener(this);
    }

    /**
     * Do filter.
     */
    protected void doFilter() {
        String text = txtFilter.getText().toLowerCase();
        boolean empty = StringUtils.isEmpty(text);

        for (String key : entitiesButtons.keySet()) {
            Button b = entitiesButtons.get(key);

            String entityName = EntitiesUtil.getDisplayName(new Path(key)).toLowerCase();

            RowData rd = new RowData();

            if (entityName.contains(text)) {
                b.setVisible(true);
                rd.exclude = false;
            } else {
                b.setVisible(false);
                rd.exclude = true;
            }

            if (empty) {
                b.setVisible(true);
                rd.exclude = false;
            }

            b.setLayoutData(rd);

        }

        setRowLayout();

    }

    /**
     * Create the actions.
     */
    private void createActions() {
        // Create the actions
    }

    /**
     * Initialize the toolbar.
     */
    private void initializeToolBar() {
        IToolBarManager toolbarManager = getViewSite().getActionBars().getToolBarManager();
    }

    /**
     * Initialize the menu.
     */
    private void initializeMenu() {
        IMenuManager menuManager = getViewSite().getActionBars().getMenuManager();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
    }

    /**
     * On entity button click.
     *
     * @param b the b
     */
    private void onEntityButtonClick(Button b) {

        Image newImage = ResourceManager.getImage(ResourceManager.rotate(b.getImage().getImageData(), SWT.RIGHT));

        b.setImage(newImage);
        b.setSize(newImage.getBounds().width, newImage.getBounds().height);

        entComposite.layout(true);

    }

    /**
     * Load new entity.
     *
     * @param resource the resource
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws CoreException the core exception
     */
    private void loadNewEntity(final IResource resource) throws IOException, CoreException {
        final Entity entity = Entity.createFromFile((IFile) resource);
        final String entityName = EntitiesUtil.getInternalName(resource.getFullPath());

        if (!validateEntity(resource, entityName, entity)) {
            return;
        }

        entitiesMap.put(entityName, entity);

        final Image imgScaled = ResourceManager.getImageDescriptor(entity.getDefaultFrame(), 0.5f).createImage();

        Button b = entitiesButtons.get(entityName);

        if (b == null || b.isDisposed()) {
            b = formToolkit.createButton(entComposite, "", SWT.None);

            b.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(org.eclipse.swt.events.SelectionEvent e) {
                    onEntityButtonClick((Button) e.getSource());
                };
            });

            DragSource dragSource = new DragSource(b, DND.DROP_COPY);
            dragSource.addDragListener(new DragSourceAdapter() {
                @Override
                public void dragSetData(DragSourceEvent event) {
                    DNDFileTransfer.transferType = TransferType.ENTITY;
                    DNDFileTransfer.entityResourceFile = (IFile) resource;
                    event.data = "BOGUS";
                }
            });
            dragSource.setTransfer(new Transfer[] { TextTransfer.getInstance() });
            entitiesButtons.put(entityName, b);
        }

        b.setImage(imgScaled);
        b.setToolTipText(entityName);

        /* Compute height hint */
        updateCount();
        setRowLayout();
    }

    /**
     * Validate entity.
     *
     * @param resource the resource
     * @param entityName the entity name
     * @param entity the entity
     * @return true, if successful
     */
    private boolean validateEntity(final IResource resource, String entityName, final Entity entity) {
        ModelValidator entityValidator = ModelValidatorFactory.getValidator(Entity.class, entity);
        boolean isValid = entityValidator.isValid();
        if (!isValid) {
            entitiesMap.remove(resource.getFullPath().toOSString());
            removeEntityButton(entityName);
        }
        return isValid;
    }

    /**
     * Calculate no of entities to load.
     */
    private void calculateNoOfEntitiesToLoad() {
        workToDO = 0;
        try {
            selectedProject.accept(new IResourceVisitor() {
                @Override
                public boolean visit(IResource resource) throws CoreException {
                    if (resource.getName().endsWith(ICGCProject.ENTITIES_EXTENSION)) {
                        workToDO++;
                    }
                    return true;
                }
            });
        } catch (CoreException e) {
            Activator.log(e);
        }

    }

    /**
     * Load entities.
     *
     * @param monitor the monitor
     * @throws CoreException the core exception
     */
    private void loadEntities(final IProgressMonitor monitor) throws CoreException {
        /* pass 1: Calculate the amount to work */
        calculateNoOfEntitiesToLoad();
        clearEntities();

        if (workToDO <= 0) {
            return;
        }

        monitor.beginTask("Loading entities", workToDO);

        EntitiesUtil.startCacheSpritesheets();

        selectedProject.accept(new IResourceVisitor() {
            @Override
            public boolean visit(final IResource resource) throws CoreException {

                /* Cancel the task */
                if (monitor.isCanceled()) {
                    return false;
                }

                if (!resource.getName().endsWith(ICGCProject.ENTITIES_EXTENSION)) {
                    return true;
                }

                monitor.subTask("Loading " + resource.getName());
                try {
                    loadNewEntity(resource);
                } catch (IOException e) {
                    Activator.log(e);
                }
                monitor.worked(1);

                return true;
            }
        });

        EntitiesUtil.stopCacheSpritesheet();

        setRowLayout();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
     */
    @Override
    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        if (!(selection instanceof IStructuredSelection)) {
            return;
        }

        IStructuredSelection strucSel = (IStructuredSelection) selection;
        Object firstElement = strucSel.getFirstElement();

        if (!(firstElement instanceof IResource)) {
            return;
        }

        final IResource res = (IResource) firstElement;

        boolean isScreen = res.getFileExtension() != null
                && res.getFileExtension().equals(ICGCProject.SCREEN_EXTENSION);
        if (!isScreen) {
            return;
        }

        final IProject prj = res.getProject();

        if (selectedProject != prj) {
            /* Start our entities loader */
            selectedProject = prj;
            loadAllEntitiesWithProgress();
        }

    }

    /**
     * Load all entities with progress.
     */
    private void loadAllEntitiesWithProgress() {

        if (selectedProject == null) {
            IEditorPart activeEditor = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                    .getActiveEditor();
            if (activeEditor != null) {
                selectedProject = CGCProject.getInstance().getCurrentProject(activeEditor.getEditorInput());
            } else {
                MessageDialog.openInformation(getSite().getShell(), "Select a resoure",
                        "Select a screen file from the project you want to load the entities or open an entity file.");
                return;
            }
        }

        ProgressMonitorDialog pmd = new ProgressMonitorDialog(getSite().getShell());
        try {
            pmd.run(false, true, new IRunnableWithProgress() {
                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

                    try {
                        loadEntities(monitor);
                    } catch (CoreException e) {
                        Activator.log(e);
                    }
                }
            });
        } catch (InvocationTargetException e) {
            Activator.log(e);
        } catch (InterruptedException e) {
            Activator.log(e);
        }
    }

    /**
     * Clear entities.
     */
    private void clearEntities() {

        for (String key : entitiesButtons.keySet()) {
            Button b = entitiesButtons.get(key);
            b.dispose();
            b = null;
        }
        entitiesButtons.clear();

        updateCount();
        setRowLayout();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this);
        ResourcesPlugin.getWorkspace().removeResourceChangeListener(entitiesResourceListener);

        super.dispose();
    }

    /* (non-Javadoc)
     * @see com.laex.cg2d.model.IEntityManager#findEntity(java.lang.String)
     */
    @Override
    public Entity findEntity(String key) {
        return entitiesMap.get(key);
    }

    /* (non-Javadoc)
     * @see com.laex.cg2d.model.IEntityManager#removeEntity(java.lang.String)
     */
    @Override
    public void removeEntity(String key) {
        entitiesMap.remove(key);
    }

    /**
     * Run in main thread.
     *
     * @param r the r
     */
    private void runInMainThread(Runnable r) {
        getSite().getShell().getDisplay().asyncExec(r);
    }

    /* (non-Javadoc)
     * @see com.laex.cg2d.model.EntityResourceChangeListener.EntityChangeListener#entityChanged(org.eclipse.core.resources.IResource)
     */
    @Override
    public void entityChanged(final IResource resource) {

        runInMainThread(new Runnable() {
            @Override
            public void run() {
                try {

                    loadNewEntity(resource);

                } catch (IOException e) {
                    Activator.log(e);
                } catch (CoreException e) {
                    Activator.log(e);
                }
            }
        });

    }

    /**
     * Removes the entity button.
     *
     * @param name the name
     */
    void removeEntityButton(final String name) {

        Button b = entitiesButtons.get(name);
        if (b != null && !b.isDisposed() && b.getToolTipText().equals(name)) {
            b.dispose();
            b = null;
        }

        entitiesButtons.remove(name);
        entitiesMap.get(name).dispose();
        entitiesMap.remove(name);

        updateCount();
        setRowLayout();
    }

    /* (non-Javadoc)
     * @see com.laex.cg2d.model.EntityResourceChangeListener.EntityChangeListener#entityRemoved(org.eclipse.core.resources.IResource)
     */
    @Override
    public void entityRemoved(final IResource resource) {
        runInMainThread(new Runnable() {

            @Override
            public void run() {

                Entity entity = entitiesMap.get(resource.getFullPath().toOSString());
                if (entity == null) {
                    return;
                }

                final String name = EntitiesUtil.getInternalName(resource.getFullPath());
                removeEntityButton(name);
            }
        });

    }

    /**
     * Update count.
     */
    private void updateCount() {
        sctnEntities.setText("Count: " + entitiesButtons.values().size());
        sctnEntities.redraw();
    }

    /**
     * Sets the row layout.
     */
    private void setRowLayout() {
        /*
         * Row Layout on EntComposite should be set once all the components have
         * been created
         */
        RowLayout rl = new RowLayout(SWT.HORIZONTAL);
        rl.wrap = true;
        entComposite.setLayout(rl);
        entComposite.layout(true);

        scrolledComposite.setContent(entComposite);

        Rectangle r = scrolledComposite.getClientArea();
        scrolledComposite.setMinSize(entComposite.computeSize(r.width, SWT.DEFAULT));

        scrolledComposite.removeControlListener(this);
        scrolledComposite.addControlListener(this);
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent)
     */
    @Override
    public void controlMoved(ControlEvent e) {
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent)
     */
    @Override
    public void controlResized(ControlEvent e) {
        Rectangle r = scrolledComposite.getClientArea();
        scrolledComposite.setMinSize(entComposite.computeSize(r.width, SWT.DEFAULT));
    }
}