com.nokia.tools.theme.s60.ui.cstore.ComponentStoreWidget.java Source code

Java tutorial

Introduction

Here is the source code for com.nokia.tools.theme.s60.ui.cstore.ComponentStoreWidget.java

Source

/*
* Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.tools.theme.s60.ui.cstore;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.views.navigator.LocalSelectionTransfer;

import com.nokia.tools.content.core.IContentData;
import com.nokia.tools.media.utils.clipboard.ClipboardContentDescriptor;
import com.nokia.tools.media.utils.clipboard.ClipboardContentDescriptor.ContentType;
import com.nokia.tools.media.utils.layers.IImage;
import com.nokia.tools.media.utils.layers.IImageAdapter;
import com.nokia.tools.platform.theme.ThemeException;
import com.nokia.tools.resource.util.StringUtils;
import com.nokia.tools.screen.core.JEMUtil;
import com.nokia.tools.screen.ui.ISkinnableEntityAdapter;
import com.nokia.tools.screen.ui.IToolBoxAdapter;
import com.nokia.tools.theme.s60.cstore.ComponentStore;
import com.nokia.tools.theme.s60.cstore.ComponentPoolBackend.NamedResult;
import com.nokia.tools.theme.s60.cstore.ComponentStore.StoredElement;
import com.nokia.tools.theme.s60.ui.cstore.StoredElementViewer.ActionProvider2;
import com.nokia.tools.theme.s60.ui.cstore.StoredElementViewer.ModifyOperation;

/**
 * Component Store UI realization
 * 
 * 
 */
public class ComponentStoreWidget extends Composite
        implements DropTargetListener, PropertyChangeListener, DisposeListener {

    public enum DisplayMode {
        IdMatching, All
    }

    /**
     * object used as indication that drag operation was inited from component
     * store
     */
    public static final String DRAG_FROM_POOL = "DragFromPool"; //$NON-NLS-1$

    /** indicating that element comes from element pool = similar components */
    static final String POOL_TYPE = "POOL_TYPE"; //$NON-NLS-1$

    protected List<ISelectionChangedListener> listeners = new ArrayList<ISelectionChangedListener>();

    /* widget for displaying list of IContentData */
    private StoredElementViewer contentViewer;

    private IContentData sourceContentData;

    private IWorkbenchPart sourcePart;

    private DisplayMode dispMode = DisplayMode.IdMatching;

    private List<String> filterTags = new ArrayList<String>();

    private ActionProvider2 clientActionProvider;

    /**
     * Store = user defined elements
     * 
     * @return
     */
    public IComponentStore getStore() {
        return ComponentStoreFactory.getComponentStore();
    }

    /**
     * pool = example themes source
     * 
     * @return
     */
    public IComponentPool getPool() {
        return ComponentStoreFactory.getComponentPool();
    }

    public ComponentStoreWidget(Composite parent, int style) {
        super(parent, style);

        ActionProvider2 actionProvider = new ActionProvider2() {

            public void fillElementContextMenu(IMenuManager manager, final Object _element,
                    final List<Object> selection) {
                final StoredElement element = (StoredElement) _element;

                // Action applySkin = new Action(Messages.cstore_apply) {
                // @Override
                // public void run() {
                // if (clientActionProvider != null)
                // clientActionProvider.processDoubleClick(
                // element.link, selection);
                // }
                // };
                // applySkin.setImageDescriptor(PlatformUI.getWorkbench()
                // .getSharedImages().getImageDescriptor(
                // ISharedImages.IMG_TOOL_REDO));
                // if (selection != null && selection.size() < 2)
                // manager.add(applySkin);

                if (clientActionProvider != null) {
                    try {
                        clientActionProvider.fillElementContextMenu(manager, element.link, selection);
                    } catch (Exception e) {
                    }
                }
                if (!POOL_TYPE.equals(element.metadata)) {

                    boolean disable = false;
                    if (selection.contains(element)) {
                        for (Object a : selection)
                            if (a instanceof StoredElement)
                                if (POOL_TYPE.equals(((StoredElement) a).metadata)) {
                                    disable = true;
                                    break;
                                }
                    }

                    Separator sep = new Separator();
                    manager.add(sep);
                    // custom element, can be deleted etc..
                    Action delete = new Action(Messages.cstore_delete) {
                        @Override
                        public void run() {
                            if (selection.contains(element)) {
                                List<StoredElement> l = new ArrayList<StoredElement>();
                                for (Object a : selection)
                                    if (a instanceof StoredElement)
                                        l.add((StoredElement) a);
                                ComponentStore.SINGLETON.deleteElements(l);
                            } else {
                                ComponentStore.SINGLETON.deleteElement(element);
                            }
                        }
                    };
                    delete.setEnabled(!disable);
                    delete.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages()
                            .getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
                    manager.add(delete);

                    // add other actions
                    ComponentStoreWidget.this.fillElementContextMenu(manager, element);
                }
            }

            public void processDoubleClick(Object element, List<Object> selection) {
                StoredElement se = (StoredElement) element;
                if (clientActionProvider != null)
                    clientActionProvider.processDoubleClick(se.link, selection);
            }

        };

        setLayout(new GridLayout());
        new Label(this, SWT.None).setText(Messages.cstore_default);
        contentViewer = new StoredElementViewer(this, SWT.None, actionProvider);

        Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getInstance(), FileTransfer.getInstance() };
        DropTarget target = new DropTarget(contentViewer.getContentComposite(), DND.DROP_COPY | DND.DROP_DEFAULT);
        target.setTransfer(transfers);
        target.addDropListener(this);

        getStore().addPropertyChangeListener(this);

        /* hook for saving on close */
        addDisposeListener(this);
    }

    public void setDisplayMode(DisplayMode mode) {
        if (dispMode != mode) {
            dispMode = mode;
            refreshContents();
        }
    }

    public void setFilterTags(List<String> tags) {
        this.filterTags.clear();
        if (tags != null)
            this.filterTags.addAll(tags);

        refreshContents();
    }

    public void selectionChanged(IWorkbenchPart part, ISelection selection) {

        if (selection instanceof IStructuredSelection && dispMode == DisplayMode.IdMatching) {
            IStructuredSelection ss = (IStructuredSelection) selection;

            Object element = ss.getFirstElement();
            IContentData icd = JEMUtil.getContentData(element);

            if (icd != null) {

                ISkinnableEntityAdapter skA = (ISkinnableEntityAdapter) icd
                        .getAdapter(ISkinnableEntityAdapter.class);

                /*
                 * filter non-list elements but allow nine-piece, those are list
                 * with childs..
                 */
                if (icd.getChildren() != null && icd.getChildren().length > 0
                        && (skA == null || (skA != null && !skA.supportsMultiPiece()))) {
                    //.supportsNinePiece()))) {
                    // clears the content viewer
                    sourceContentData = null;
                    sourcePart = null;
                    refreshContents();
                    return;
                }

                IToolBoxAdapter mfa = (IToolBoxAdapter) icd.getAdapter(IToolBoxAdapter.class);
                if (skA == null || mfa == null || skA.isColour() || mfa.isFile() || mfa.isText()) {
                    // clears the content viewer
                    sourceContentData = null;
                    sourcePart = null;
                    refreshContents();
                    return;
                }

                String prevId = sourceContentData == null ? null : sourceContentData.getId();
                if (icd.getId() != null
                        && !(icd.getId().equals(prevId) && icd.toString().equals(sourceContentData.toString()))) {
                    sourceContentData = icd;
                    sourcePart = part;
                    refreshContents();
                }
            } else {
                sourceContentData = null;
                sourcePart = null;
                refreshContents();
            }
        }
    }

    public void refreshContents() {

        // must be in UI thread
        if (Display.getCurrent() == null && false) {
            Display.getDefault().syncExec(new Runnable() {
                public void run() {
                    refreshContents();
                }
            });
            return;
        }

        try {
            if (getChildren()[0] instanceof Label) {
                getChildren()[0].dispose();
                setLayout(new FillLayout());
                layout(true);
                getParent().layout(true);
                getParent().pack(true);
            }
        } catch (Exception e) {
        }

        contentViewer.clearContent();

        if (dispMode == DisplayMode.IdMatching && sourceContentData != null) {

            String elementId = sourceContentData.getId();
            List<StoredElement> cList = new ArrayList<StoredElement>();

            cList.addAll(getStore().getMatches(elementId));

            try {
                NamedResult[] similar = getPool().getElementListFromPool(elementId, null);
                for (NamedResult nr : similar) {
                    if (nr == null)
                        continue;
                    IContentData data = (IContentData) nr.data;
                    StoredElement sElement = new StoredElement(null, nr.themeName, 0, null, data);
                    // mark as Pool type, comes from Example Themes, not from
                    // Custom Component Store
                    sElement.metadata = POOL_TYPE;
                    cList.add(sElement);
                }
            } catch (ThemeException e) {
                e.printStackTrace();
            }

            // determine display size
            IContentData cData = sourceContentData;
            IImageAdapter imgAd = (IImageAdapter) cData.getAdapter(IImageAdapter.class);

            IImage selectedElement = imgAd.getImage();

            if (selectedElement == null)
                return;

            int width = selectedElement.getWidth();
            int height = selectedElement.getHeight();

            int SIZE_LIMIT = 75;
            float scale = 1.0f;
            if (width > SIZE_LIMIT || height > SIZE_LIMIT) {
                float scaleX = SIZE_LIMIT / (float) width;
                float scaleY = SIZE_LIMIT / (float) height;
                scale = scaleX < scaleY ? scaleX : scaleY;
                width = Math.max((int) (width * scale), 25);
                height = Math.max((int) (height * scale), 25);
            } else {
                int SIZE_MIN_LIMIT = 40;
                scale = 1.0f;
                if (width < SIZE_MIN_LIMIT || height < SIZE_MIN_LIMIT) {
                    float scaleX = SIZE_MIN_LIMIT / (float) width;
                    float scaleY = SIZE_MIN_LIMIT / (float) height;
                    scale = scaleX < scaleY ? scaleX : scaleY;
                    width = (int) (width * scale);
                    height = (int) (height * scale);
                }
            }

            contentViewer.setContent(cList, width, height);
        }

        if (dispMode == DisplayMode.All) {

            List<StoredElement> cList = new ArrayList<StoredElement>();

            if (filterTags.size() > 0) {
                cList.addAll(getStore().getFilteredContent(filterTags));
            } else {
                cList.addAll(getStore().getContents());
            }

            if (cList.size() > 100)
                for (int i = cList.size() - 1; i >= 100; i--)
                    cList.remove(i);

            contentViewer.setContent(cList);
        }

    }

    /*
     * menu for each stored component
     */
    protected void fillElementContextMenu(IMenuManager mgr, final StoredElement __ei) {

        List<String> allTags = ComponentStore.SINGLETON.getAvailableTags();
        List<String> elTags = __ei.tags;
        if (elTags == null)
            elTags = new ArrayList<String>();

        MenuManager submenu = new MenuManager(Messages.cstore_filterTagsMenu);
        for (final String t : allTags) {
            Action tagAction = new TagFilterAction(t, __ei);
            tagAction.setChecked(elTags.contains(t));
            submenu.add(tagAction);
        }

        submenu.add(new Separator());
        Action newTag = new Action(Messages.cstore_newTagAction) {
            @Override
            public void run() {
                InputDialog input = new InputDialog(getShell(), Messages.cstore_newTagDlgLbl,
                        Messages.cstore_newTagDlgMsg, "", null); //$NON-NLS-3$ //$NON-NLS-1$
                if (input.open() == Window.OK) {
                    if (__ei.tags == null)
                        __ei.tags = new ArrayList<String>();
                    if (!__ei.tags.contains(input.getValue()) && !StringUtils.isEmpty(input.getValue()))
                        __ei.tags.add(input.getValue());
                }
            }
        };
        submenu.add(newTag);

        // #filter disabled not in 3rd iteration
        // mgr.add(submenu);

        if (dispMode == DisplayMode.All) {
            // action for selection of filter tags
            Action action = new Action(Messages.cstore_filterAction) {
                @Override
                public void run() {
                    doShowAdjustFiltersDialog();
                }
            };
            mgr.add(action);
        }

    }

    protected void doShowAdjustFiltersDialog() {
        ListSelectionDialog dialog = new ListSelectionDialog(getShell(),
                ComponentStore.SINGLETON.getAvailableTags(), new IStructuredContentProvider() {
                    public Object[] getElements(Object inputElement) {
                        return ((List) inputElement).toArray();
                    }

                    public void dispose() {
                    };

                    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
                    }
                }, new LabelProvider(), Messages.cstore_filterDlgLblb);
        dialog.setInitialElementSelections(filterTags);
        dialog.setTitle(Messages.cstore_filterDlgMsg);
        if (dialog.open() == Window.OK) {
            filterTags.clear();

            Object results[] = dialog.getResult();
            if (results != null && results.length > 0) {
                for (Object result : results) {
                    filterTags.add(result.toString());
                }
            }
            refreshContents();
        }
    }

    /* drop listener START */

    public void dragEnter(DropTargetEvent event) {
        dragOver(event);
    }

    public void dragLeave(DropTargetEvent event) {
        // turn off highlight
        contentViewer.getContentComposite().setBackground(getBackground());
    }

    public void dragOperationChanged(DropTargetEvent event) {
        dragOver(event);
    }

    public void dragOver(DropTargetEvent event) {

        boolean validDrag = false;
        if (!(event.data == DRAG_FROM_POOL || this.contentViewer.dragInProgress)
                && LocalSelectionTransfer.getInstance().isSupportedType(event.currentDataType)) {
            event.data = LocalSelectionTransfer.getInstance().getSelection();
            List<IContentData> param = getContentData(event);
            validDrag = param != null && param.size() > 0;
        }
        if (!validDrag) {
            event.detail = DND.DROP_NONE;
        } else {
            event.detail = DND.DROP_COPY;
            contentViewer.getContentComposite().setBackground(ColorConstants.blue);
        }
    }

    private List<IContentData> getContentData(DropTargetEvent event) {
        Object data = event.data;

        // test if content is selection with ClipboardContentDescriptor's
        if (data instanceof IStructuredSelection) {
            List items = Arrays.asList(((IStructuredSelection) data).toArray());
            boolean ccd = true;
            for (Object item : items) {
                if (!(item instanceof ClipboardContentDescriptor))
                    ccd = false;
            }
            if (ccd) {

                final List<IContentData> toAdd = new ArrayList<IContentData>();

                try {
                    for (Object item : items) {
                        ClipboardContentDescriptor cDesc = (ClipboardContentDescriptor) item;
                        if (cDesc.getType() == ContentType.CONTENT_ELEMENT) {
                            IContentData cData = JEMUtil.getContentData(cDesc.getContent());
                            IToolBoxAdapter toolbox = (IToolBoxAdapter) cData.getAdapter(IToolBoxAdapter.class);
                            if (toolbox != null) {
                                if (toolbox.isFile() || toolbox.isText())
                                    continue;
                                else {
                                    // lookup ThemeData, not ThemeScreenData
                                    IContentData resourceData = cData.getRoot().findById(cData.getId());
                                    if (resourceData != null && resourceData != cData)
                                        cData = resourceData;
                                    toAdd.add(cData);
                                }
                            }
                        }
                    }
                    return toAdd;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    // private List<File> getFileList(DropTargetEvent event) {
    // Object data = event.data;
    //
    // if (data instanceof IStructuredSelection) {
    // data = ((IStructuredSelection) data).getFirstElement();
    // }
    //
    // if (data instanceof Clipboard) {
    // data = ClipboardHelper
    // .getSupportedClipboardContent((Clipboard) data);
    // }
    //      
    // final List<File> imgFiles = new ArrayList<File>();
    //
    // if (data instanceof List) {
    // for (Object item : (List) data) {
    // File file = getFile(item);
    // if (file != null)
    // imgFiles.add(file);
    // }
    // } else if (data instanceof Object[]) {
    // for (Object item : (Object[]) data) {
    // File file = getFile(item);
    // if (file != null)
    // imgFiles.add(file);
    // }
    // }
    //      
    // if (getFile(data) != null) {
    // imgFiles.add((File) data);
    // }
    //      
    // /* assemble files / elements to be added */
    //      
    // if (imgFiles.size() == 1 && imgFiles.get(0).isDirectory()) {
    //
    // File[] list = imgFiles.get(0).listFiles();
    // List<File> dirContent = new ArrayList<File>();
    // for (File a : list) {
    // if (a.isFile() && ImageUtil.isParameterUsableAsImage(a)) {
    // dirContent.add(a);
    // }
    // }
    // imgFiles.clear();
    // imgFiles.addAll(dirContent);
    // } else {
    // for (int i = imgFiles.size() - 1; i >= 0; i--) {
    // File f = imgFiles.get(i);
    // if (f.isDirectory() || !f.exists()
    // || !ImageUtil.isParameterUsableAsImage(f))
    // imgFiles.remove(i);
    // }
    // }
    //      
    // return imgFiles;
    // }

    public void drop(DropTargetEvent event) {

        // test if content is selection with ClipboardContentDescriptor's
        final List<IContentData> cDataList = getContentData(event);

        if (cDataList != null) {
            /* run as job */

            final String jobName = "Adding " + cDataList.size() + " element(s).."; //$NON-NLS-1$ //$NON-NLS-2$

            Job job = new Job(jobName) {
                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    monitor.beginTask(jobName, cDataList.size());
                    try {
                        ComponentStore.SINGLETON.addElements(cDataList, monitor);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return Status.OK_STATUS;
                }
            };
            job.schedule();
            return;
        }
    }

    // private File getFile(Object data) {
    // if (data instanceof IFile) {
    // data = ((IFile) data).getLocation().toFile().getAbsoluteFile();
    // }
    // if (data instanceof String) {
    // data = new File((String) data);
    // }
    // if (data instanceof File) {
    // return (File) data;
    // }
    // return null;
    // }

    public void dropAccept(DropTargetEvent event) {

    }

    /* drop listener END */

    public void propertyChange(final PropertyChangeEvent evt) {

        if (ComponentStore.PROP_CONTENT_CHANGE.equals(evt.getPropertyName())) {
            refreshContents();
            return;
        }

        List<StoredElement> changed = new ArrayList<StoredElement>();
        Object data = evt.getNewValue();
        if (data instanceof StoredElement) {
            changed.add((StoredElement) data);
        } else if (data instanceof List) {
            for (Object item : ((List) data)) {
                if (item instanceof StoredElement) {
                    changed.add((StoredElement) item);
                }
            }
        }

        if (ComponentStore.PROP_CONTENT_REMOVED.equals(evt.getPropertyName())) {
            contentViewer.notifyModified(ModifyOperation.Removed, changed);
        }

        if (ComponentStore.PROP_CONTENT_ADDED.equals(evt.getPropertyName())) {

            if (sourceContentData != null && dispMode == DisplayMode.IdMatching) {
                String activeId = sourceContentData.getId();
                for (int i = changed.size() - 1; i >= 0; i--) {
                    if (!activeId.equals(changed.get(i).id))
                        changed.remove(i);
                }
                contentViewer.addDeltaContent(changed);
            } else {
                refreshContents();
            }
        }
    }

    public void widgetDisposed(DisposeEvent e) {
        ComponentStore.SINGLETON.removePropertyChangeListener(this);
        new Thread(new Runnable() {
            public void run() {
                ComponentStore.SINGLETON.saveStore();
            }
        }).start();
    }

    public void clearContents() {
        sourceContentData = null;
        sourcePart = null;
        contentViewer.clearContent();
    }

    public IWorkbenchPart getSourcePart() {
        return sourcePart;
    }

    public IContentData getSourceData() {
        return sourceContentData;
    }

    // /* selection provider */
    //
    // protected void fireSelectionEvent(IContentData element) {
    // _selected = new StructuredSelection(element);
    // SelectionChangedEvent evt = new SelectionChangedEvent(this, _selected);
    // for (ISelectionChangedListener l: listeners) try {
    // l.selectionChanged(evt);
    // } catch (Exception e) {
    // e.printStackTrace();
    // }
    // }
    // public void addSelectionChangedListener(ISelectionChangedListener
    // listener) {
    // listeners.add(listener);
    // }
    // public ISelection getSelection() {
    // return _selected;
    // }
    // public void removeSelectionChangedListener(ISelectionChangedListener
    // listener) {
    // listeners.remove(listener);
    // }
    // public void setSelection(ISelection selection) {
    // }

    /* selection provider END */

    public DisplayMode getDisplayMode() {
        return dispMode;
    }

    public void setClientActionProvider(ActionProvider2 clientActionProvider) {
        this.clientActionProvider = clientActionProvider;
    }

}