Package com.google.devtools.depan.eclipse.editors

Source Code of com.google.devtools.depan.eclipse.editors.Binop

/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.devtools.depan.eclipse.editors;

import com.google.devtools.depan.eclipse.utils.Resources;
import com.google.devtools.depan.eclipse.utils.Tools;
import com.google.devtools.depan.util.BinaryOperators;

import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.WorkbenchPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;


/**
* A class to edit binary operations between diferent objects T. This class
* extends Composite, and creates a TreeViewer and buttons usefull to edit
* a tree of binary operations.
*
* @author ycoppel@google.com (Yohann Coppel)
*
* @param <T> types you want to combine with binary operations.
*/
public class Binop<T extends BinaryOperators<T>>
    extends Composite implements IAdapterFactory {

  private T obj1 = null;
  private T obj2 = null;

  private Text expression = null;
  private Root<T> rootTree = new Root<T>();
  private Tree<T> selectedTree = null;

  private TreeViewer treeViewer;
  private TCreator<T> creator;

  /**
   * Possible operators in the expression tree.
   *
   * @author ycoppel@google.com (Yohann Coppel)
   */
  @SuppressWarnings("hiding")
  public enum Operators {
    AND("&"),
    OR("|"),
    XOR("^"),
    NOT("!");

    private String repr;

    private Operators(String repr) {
      this.repr = repr;
    }

    @Override
    public String toString() {
      return repr;
    }
  }

  public Binop(Composite parent, int style, WorkbenchPart part,
      TCreator<T> creator) {
    super(parent, style);
    this.creator = creator;

    int numColumns = 2;

    GridLayout g = new GridLayout();
    g.numColumns = numColumns;
    g.makeColumnsEqualWidth = false;
    this.setLayout(g);

    // {{{ // buttons
    Composite buttons = new Composite(this, SWT.NONE);
    GridLayout buttonsLayout = new GridLayout();
    buttons.setLayout(buttonsLayout);
    buttons.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true));

    Button and = new Button(buttons, SWT.PUSH);
    and.setText("AND");
    and.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    and.setImage(Tools.getImageFromPath("icons/and.png"));
    and.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        newTree(Operators.AND);
      }

      public void widgetSelected(SelectionEvent e) {
        newTree(Operators.AND);
      }
    });

    Button or = new Button(buttons, SWT.PUSH);
    or.setText("OR");
    or.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    or.setImage(Tools.getImageFromPath("icons/or.png"));
    or.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        newTree(Operators.OR);
      }

      public void widgetSelected(SelectionEvent e) {
        newTree(Operators.OR);
      }
    });

    Button xor = new Button(buttons, SWT.PUSH);
    xor.setText("XOR");
    xor.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    xor.setImage(Tools.getImageFromPath("icons/xor.png"));
    xor.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        newTree(Operators.XOR);
      }

      public void widgetSelected(SelectionEvent e) {
        newTree(Operators.XOR);
      }
    });

    Button not = new Button(buttons, SWT.PUSH);
    not.setText("NOT");
    not.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    not.setImage(Tools.getImageFromPath("icons/not.png"));
    not.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        newTree(Operators.NOT);
      }

      public void widgetSelected(SelectionEvent e) {
        newTree(Operators.NOT);
      }
    });

    Button delete = new Button(buttons, SWT.PUSH);
    delete.setText("Delete tree");
    delete.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    delete.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        widgetSelected(e);
      }
      @SuppressWarnings("unchecked")
      public void widgetSelected(SelectionEvent e) {
        Object o = ((ITreeSelection) treeViewer.getSelection())
          .getFirstElement();
        if (null != o && o instanceof Tree) {
          deleteTree((Tree) o);
        }
      }
    });
    // }}}

    // {{{
    Composite editor = new Composite(this, SWT.NONE);
    GridLayout g2 = new GridLayout();
    editor.setLayout(g2);
    editor.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 5));
    expression = new Text(editor, SWT.BORDER | SWT.MULTI);
    expression.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

    treeViewer = new TreeViewer(editor, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
    treeViewer.getTree().setLayoutData(
        new GridData(SWT.FILL, SWT.FILL, true, true));
    part.getSite().setSelectionProvider(treeViewer);
    Platform.getAdapterManager().registerAdapters(this, Tree.class);
    treeViewer.setLabelProvider(new WorkbenchLabelProvider());
    treeViewer.setContentProvider(new BaseWorkbenchContentProvider());
    treeViewer.setInput(rootTree);
    treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
      @SuppressWarnings("unchecked")
      public void selectionChanged(SelectionChangedEvent event) {
        Object o = ((ITreeSelection) treeViewer.getSelection())
            .getFirstElement();
        if (null != o && o instanceof Tree) {
          selectedTree = (Tree<T>) o;
        }
      }
    });
    // }}}

    Button createView = new Button(this, SWT.PUSH);
    createView.setText("Create View");
    createView.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false,
        numColumns, 1));
    createView.addSelectionListener(new SelectionListener() {
      public void widgetDefaultSelected(SelectionEvent e) {
        apply();
      }

      public void widgetSelected(SelectionEvent e) {
        apply();
      }
    });

  }

  private void updateTree() {
    expression.setText(rootTree.toString());
    treeViewer.refresh();
    treeViewer.expandAll();
  }

  protected void newTree(Operators op) {
    if (null != selectedTree && null != obj1 && null == obj2) {
      newTree(op, selectedTree, obj1);
    } else if (null != obj1 && null != obj2 && null == selectedTree) {
      rootTree.setFirstTree(new BinTree<T>(
          new Leaf<T>(obj1), new Leaf<T>(obj2), op));
      selectedTree = rootTree.firstTree;
    }
    updateTree();
  }

  @SuppressWarnings("unchecked")
  private void newTree(Operators op, Tree<T> with, T obj) {
    Tree<T> parent = with.parent;
    BinTree<T> insert = new BinTree<T>(with, new Leaf<T>(obj), op);

    if (parent instanceof Root) {
      // we are at the root.
      ((Root<T>) parent).setFirstTree(insert);
    } else if (parent instanceof BinTree) {
      BinTree<T> binParent = (BinTree<T>) parent;
      binParent.replaceBranch(with, insert);
    }
    selectedTree = insert;
  }

  @SuppressWarnings("unchecked")
  private void deleteTree(Tree<T> toDelete) {
    System.out.println("delete " + toDelete);
    Tree<T> parent = toDelete.parent;
    if (null == parent) {
      return;
    }
    if (parent instanceof BinTree) {
      System.out.println("    parent BinTree");
      Tree<T> superParent = parent.parent;
      if (superParent instanceof BinTree) {
        System.out.println("    parent.parent BinTree");
        ((BinTree<T>) superParent)
            .replaceBranch(parent, ((BinTree<T>) parent).getOther(toDelete));
      } else if (superParent instanceof Root) {
        System.out.println("    parent.parent Root");
        ((Root<T>) superParent)
            .setFirstTree(((BinTree<T>) parent).getOther(toDelete));
      }
    } else if (parent instanceof Root) {
      System.out.println("    parent�Root");
      ((Root<T>) parent).setFirstTree(null);
    }
    updateTree();
    selectedTree = null;
  }

  protected void apply() {
    T newT = build(rootTree);
    if (null != newT) {
      creator.create(newT);
    }
  }

  @SuppressWarnings("unchecked")
  private T build(Tree<T> tree) {
    if (tree instanceof BinTree) {
      return build((BinTree<T>) tree);
    } else if (tree instanceof Leaf) {
      return build((Leaf<T>) tree);
    } else if (tree instanceof Root) {
      return build((Root<T>) tree);
    }
    return null;
  }

  private T build(BinTree<T> tree) {
    T t1 = build(tree.o1);
    T t2 = build(tree.o2);
    if (null == t1 || null == t2) {
      return null;
    }
    switch(tree.op) {
    case AND:
      return t1.and(t2);
    case OR:
      return t1.or(t2);
    case XOR:
      return t1.xor(t2);
    case NOT:
      return t1.not(t2);
    default:
      break;
    }
    return null;
  }

  private T build(Leaf<T> tree) {
    return tree.leaf;
  }

  private T build(Root<T> tree) {
    return build(tree.firstTree);
  }

  public void setFirst(T o1) {
    this.obj1 = o1;
    this.obj2 = null;
  }

  public void setBoth(T o1, T o2) {
    this.obj1 = o1;
    this.obj2 = o2;
  }


  /**
   * a super class for a Tree.
   *
   * @author ycoppel@google.com (Yohann Coppel)
   *
   * @param <T>
   */
  @SuppressWarnings("hiding")
  public abstract class Tree<T extends BinaryOperators<T>>
      extends PlatformObject {
    Tree<T> parent;
    public void setParent(Tree<T> parent) {
      this.parent = parent;
    }
  }

  /**
   * A class for representing a tree of binary operations.
   *
   * @author ycoppel@google.com (Yohann Coppel)
   *
   * @param <T>
   */
  @SuppressWarnings("hiding")
  public class BinTree<T extends BinaryOperators<T>> extends Tree<T> {
    Tree<T> o1;
    Tree<T> o2;
    Operators op;

    public BinTree(Tree<T> operand1, Tree<T> operand2, Operators operator) {
      this.o1 = operand1;
      this.o2 = operand2;
      this.op = operator;
      o1.setParent(this);
      o2.setParent(this);
    }

    public Tree<T> getOther(Tree<T> notThisOne) {
      if (o1 == notThisOne) {
        return o2;
      } else {
        return o1;
      }
    }

    public void replaceBranch(Tree<T> fromThat, Tree<T> toThat) {
      if (o1 == fromThat) {
        o1 = toThat;
      } else if (o2 == fromThat) {
        o2 = toThat;
      }
      toThat.setParent(this);
    }

    @Override
    public String toString() {
      return "(" + o1 + " " + op + " " + o2 + ")";
    }
  }

  /**
   * Class for a leaf tree.
   *
   * @author ycoppel@google.com (Yohann Coppel)
   *
   * @param <T>
   */
  @SuppressWarnings("hiding")
  public class Leaf<T extends BinaryOperators<T>> extends Tree<T> {
    T leaf;

    public Leaf(T leaf) {
      this.leaf = leaf;
    }

    @Override
    public String toString() {
      return leaf.toString();
    }
  }

  /**
   * A Root Element for the tree. Usefull to display the root tree corectly in
   * the TreeViewer.
   *
   * @author ycoppel@google.com (Yohann Coppel)
   *
   * @param <T>
   */
  @SuppressWarnings("hiding")
  public class Root<T extends BinaryOperators<T>> extends Tree<T> {
    private Tree<T> firstTree;

    public void setFirstTree(Tree<T> firstTree) {
      this.firstTree = firstTree;
      if (this.firstTree != null) {
        this.firstTree.setParent(this);
      }
    }

    public Tree<T> getFirstTree() {
      return firstTree;
    }

    @Override
    public String toString() {
      return (null == firstTree ? "" : "" + firstTree);
    }
  }

  private IWorkbenchAdapter treeAdapter = new IWorkbenchAdapter() {

    @SuppressWarnings("unchecked")
    public Object[] getChildren(Object o) {
      if (o instanceof Root && null != ((Root) o).getFirstTree()) {
        return new Object[] {((Root) o).getFirstTree()};
      } else if (o instanceof BinTree) {
        return new Object[] {((BinTree) o).o1, ((BinTree) o).o2};
      }
      return new Object[] {};
    }

    @SuppressWarnings("unchecked")
    public ImageDescriptor getImageDescriptor(Object object) {
      if (object instanceof BinTree) {
        return AbstractUIPlugin.imageDescriptorFromPlugin(
            Resources.PLUGIN_ID, getIcon(((BinTree) object).op));
      } else {
        return null;
      }
    }

    private String getIcon(Operators o) {
      String base = "icons/";
      if (o == Binop.Operators.AND) {
        return base + "and16.png";
      } else if (o == Binop.Operators.OR) {
        return base + "or16.png";
      } else if (o == Binop.Operators.XOR) {
        return base + "xor16.png";
      } else if (o == Binop.Operators.NOT) {
        return base + "not16.png";
      }
      return "icons/sample.gif";
    }

    public String getLabel(Object o) {
      if (o instanceof BinTree) {
        return ((BinTree<?>) o).op.toString() + " - " + o.toString();
      }
      return o.toString();
    }

    public Object getParent(Object o) {
      return ((Tree<?>) o).parent;
    }
  };

  // suppress the warning for the Class, which should be parameterized.
  // We can't here: getAdapter is not declared with a parameterized Class.
  @SuppressWarnings("unchecked")
  public Object getAdapter(Object adaptableObject, Class adapterType) {
    if (adapterType != IWorkbenchAdapter.class) {
      return null;
    }
    if (adaptableObject instanceof Tree) {
      return treeAdapter;
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  public Class[] getAdapterList() {
    return new Class[] {IWorkbenchAdapter.class};
  }
}
TOP

Related Classes of com.google.devtools.depan.eclipse.editors.Binop

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.