org.eclipse.babel.editor.tree.KeyTreeContributor.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.babel.editor.tree.KeyTreeContributor.java

Source

/*******************************************************************************
 * Copyright (c) 2007 Pascal Essiembre.
 * 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:
 *    Pascal Essiembre - initial API and implementation
 ******************************************************************************/
package org.eclipse.babel.editor.tree;

import java.util.Observable;
import java.util.Observer;

import org.eclipse.babel.core.message.tree.DefaultKeyTreeModel;
import org.eclipse.babel.core.message.tree.IKeyTreeModel;
import org.eclipse.babel.core.message.tree.IKeyTreeModelListener;
import org.eclipse.babel.core.message.tree.KeyTreeNode;
import org.eclipse.babel.editor.IMessagesEditorChangeListener;
import org.eclipse.babel.editor.MessagesEditor;
import org.eclipse.babel.editor.MessagesEditorChangeAdapter;
import org.eclipse.babel.editor.MessagesEditorMarkers;
import org.eclipse.babel.editor.tree.actions.AddKeyAction;
import org.eclipse.babel.editor.tree.actions.DeleteKeyAction;
import org.eclipse.babel.editor.tree.actions.RenameKeyAction;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;

/**
 * @author Pascal Essiembre
 *
 */
public class KeyTreeContributor {

    //TODO consider keeping instance of this in MessagesEditor
    // and having class variables for the actions.

    private MessagesEditor editor;
    private IKeyTreeModel treeModel;

    /**
     * 
     */
    public KeyTreeContributor(final MessagesEditor editor) {
        super();
        this.editor = editor;
        this.treeModel = new DefaultKeyTreeModel(editor.getBundleGroup());
    }

    /**
     * 
     */
    public void contribute(final TreeViewer treeViewer) {

        treeViewer.setContentProvider(new KeyTreeContentProvider());
        treeViewer.setLabelProvider(new KeyTreeLabelProvider(editor, treeModel));
        treeViewer.setUseHashlookup(true);

        ViewerFilter onlyUnusedAndMissingKeysFilter = new OnlyUnsuedAndMissingKey();
        ViewerFilter[] filters = { onlyUnusedAndMissingKeysFilter };
        treeViewer.setFilters(filters);

        //        IKeyBindingService service = editor.getSite().getKeyBindingService();
        //        service.setScopes(new String[]{"org.eclilpse.babel.editor.editor.tree"});

        contributeActions(treeViewer);

        contributeKeySync(treeViewer);

        contributeModelChanges(treeViewer);

        contributeDoubleClick(treeViewer);

        contributeMarkers(treeViewer);

        // Set input model
        treeViewer.setInput(treeModel);
        treeViewer.expandAll();
    }

    private class OnlyUnsuedAndMissingKey extends ViewerFilter implements IKeyTreeModel.IKeyTreeNodeLeafFilter {

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer,
         *      java.lang.Object, java.lang.Object)
         */
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            if (editor.isShowOnlyUnusedAndMissingKeys() == IMessagesEditorChangeListener.SHOW_ALL
                    || !(element instanceof KeyTreeNode)) {
                //no filtering. the element is displayed by default.
                return true;
            }
            if (editor.getI18NPage() != null && editor.getI18NPage().isKeyTreeVisible()) {
                return editor.getKeyTreeModel().isBranchFiltered(this, (KeyTreeNode) element);
            } else {
                return isFilteredLeaf((KeyTreeNode) element);
            }
        }

        /**
        * @param node
        * @return true if this node should be in the filter. Does not navigate the tree
        * of KeyTreeNode. false unless the node is a missing or unused key.
        */
        public boolean isFilteredLeaf(KeyTreeNode node) {
            MessagesEditorMarkers markers = KeyTreeContributor.this.editor.getMarkers();
            String key = node.getMessageKey();
            boolean missingOrUnused = markers.isMissingOrUnusedKey(key);
            if (!missingOrUnused) {
                return false;
            }
            switch (editor.isShowOnlyUnusedAndMissingKeys()) {
            case IMessagesEditorChangeListener.SHOW_ONLY_MISSING_AND_UNUSED:
                return missingOrUnused;
            case IMessagesEditorChangeListener.SHOW_ONLY_MISSING:
                return !markers.isUnusedKey(key, missingOrUnused);
            case IMessagesEditorChangeListener.SHOW_ONLY_UNUSED:
                return markers.isUnusedKey(key, missingOrUnused);
            default:
                return false;
            }
        }

    }

    /**
     * Contributes markers.
     * @param treeViewer tree viewer
     */
    private void contributeMarkers(final TreeViewer treeViewer) {
        editor.getMarkers().addObserver(new Observer() {
            public void update(Observable o, Object arg) {
                treeViewer.refresh();
            }
        });
        //      editor.addChangeListener(new MessagesEditorChangeAdapter() {
        //      public void editorDisposed() {
        //          editor.getMarkers().clear();
        //      }
        //  });

        //        final IMarkerListener markerListener = new IMarkerListener() {
        //            public void markerAdded(IMarker marker) {
        //                PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable () {
        //                    public void run() {
        //                        if (!PlatformUI.getWorkbench().getDisplay().isDisposed()) {
        //                            treeViewer.refresh(true);
        //                        }
        //                    }
        //                });
        //            }
        //            public void markerRemoved(IMarker marker) {
        //                PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable () {
        //                    public void run() {
        //                        if (!PlatformUI.getWorkbench().getDisplay().isDisposed()) {
        //                            treeViewer.refresh(true);
        //                        }
        //                    }
        //                });
        //            }
        //        };
        //        editor.getMarkerManager().addMarkerListener(markerListener);
        //        editor.addChangeListener(new MessagesEditorChangeAdapter() {
        //            public void editorDisposed() {
        //                editor.getMarkerManager().removeMarkerListener(markerListener);
        //            }
        //        });
    }

    /**
     * Contributes double-click support, expanding/collapsing nodes.
     * @param treeViewer tree viewer
     */
    private void contributeDoubleClick(final TreeViewer treeViewer) {
        treeViewer.getTree().addMouseListener(new MouseAdapter() {
            public void mouseDoubleClick(MouseEvent event) {
                IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
                Object element = selection.getFirstElement();
                if (treeViewer.isExpandable(element)) {
                    if (treeViewer.getExpandedState(element)) {
                        treeViewer.collapseToLevel(element, 1);
                    } else {
                        treeViewer.expandToLevel(element, 1);
                    }
                }
            }
        });
    }

    /**
     * Contributes key synchronization between editor and tree selected keys.
     * @param treeViewer tree viewer
     */
    private void contributeModelChanges(final TreeViewer treeViewer) {
        final IKeyTreeModelListener keyTreeListener = new IKeyTreeModelListener() {
            //TODO be smarter about refreshes.
            public void nodeAdded(KeyTreeNode node) {
                treeViewer.refresh(true);
            };

            //            public void nodeChanged(KeyTreeNode node) {
            //                treeViewer.refresh(true);
            //            };
            public void nodeRemoved(KeyTreeNode node) {
                treeViewer.refresh(true);
            };
        };
        treeModel.addKeyTreeModelListener(keyTreeListener);
        editor.addChangeListener(new MessagesEditorChangeAdapter() {
            public void keyTreeModelChanged(IKeyTreeModel oldModel, IKeyTreeModel newModel) {
                oldModel.removeKeyTreeModelListener(keyTreeListener);
                newModel.addKeyTreeModelListener(keyTreeListener);
                treeViewer.setInput(newModel);
                treeViewer.refresh();
            }

            public void showOnlyUnusedAndMissingChanged(int hideEverythingElse) {
                treeViewer.refresh();
            }
        });
    }

    /**
     * Contributes key synchronization between editor and tree selected keys.
     * @param treeViewer tree viewer
     */
    private void contributeKeySync(final TreeViewer treeViewer) {
        // changes in tree selected key update the editor
        treeViewer.getTree().addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {
                IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
                if (selection != null && selection.getFirstElement() != null) {
                    KeyTreeNode node = (KeyTreeNode) selection.getFirstElement();
                    System.out.println("viewer key/hash:" + node.getMessageKey() + "/" + node.hashCode());
                    editor.setSelectedKey(node.getMessageKey());
                } else {
                    editor.setSelectedKey(null);
                }
            }
        });
        // changes in editor selected key updates the tree
        editor.addChangeListener(new MessagesEditorChangeAdapter() {
            public void selectedKeyChanged(String oldKey, String newKey) {
                ITreeContentProvider provider = (ITreeContentProvider) treeViewer.getContentProvider();
                KeyTreeNode node = findKeyTreeNode(provider, provider.getElements(null), newKey);
                System.out.println("editor key/hash:" + node.getMessageKey() + "/" + node.hashCode());

                //                String[] test = newKey.split("\\.");
                //                treeViewer.setSelection(new StructuredSelection(test), true);

                treeViewer.setSelection(new StructuredSelection(node), true);
                treeViewer.getTree().showSelection();
            }
        });
    }

    /**
     * Contributes actions to the tree.
     * @param treeViewer tree viewer
     */
    private void contributeActions(final TreeViewer treeViewer) {
        Tree tree = treeViewer.getTree();

        // Add menu
        MenuManager menuManager = new MenuManager();
        Menu menu = menuManager.createContextMenu(tree);

        // Add
        final IAction addAction = new AddKeyAction(editor, treeViewer);
        menuManager.add(addAction);
        // Delete
        final IAction deleteAction = new DeleteKeyAction(editor, treeViewer);
        menuManager.add(deleteAction);
        // Rename
        final IAction renameAction = new RenameKeyAction(editor, treeViewer);
        menuManager.add(renameAction);

        menuManager.update(true);
        tree.setMenu(menu);

        // Bind actions to tree
        tree.addKeyListener(new KeyAdapter() {
            public void keyReleased(KeyEvent event) {
                if (event.character == SWT.DEL) {
                    deleteAction.run();
                } else if (event.keyCode == SWT.F2) {
                    renameAction.run();
                }
            }
        });
    }

    private KeyTreeNode findKeyTreeNode(ITreeContentProvider provider, Object[] nodes, String key) {
        for (int i = 0; i < nodes.length; i++) {
            KeyTreeNode node = (KeyTreeNode) nodes[i];
            if (node.getMessageKey().equals(key)) {
                return node;
            }
            node = findKeyTreeNode(provider, provider.getChildren(node), key);
            if (node != null) {
                return node;
            }
        }
        return null;
    }

}