Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 2a44ec535eecf37b661e13d50fd50240093a445f (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                            
                                                 
 

                                              


                                              
                                                    
 

                                        

                                                










                                                            
                                          
                                      
                                      

                                         
                                         
                                     
                                           
                                    

                                         
                                    
                                     
                                 


                                    


                           
                       



                       
                                                                                                                  


                                                 






                                     
 
                                                       





                                                
 



                                  
                                












                                                      

                                                                             

                                                          
                                    
 











                                                                             
 






                                                                        
                                              






                                                                 
                                                

                                                                     



                                           
                                           





















                                                                                                               
                                                                                  

                                             
                  



                             
       
     
                                                                      


                         




                                         
           



           


                                   











                                                                   

                                        


        



                      








                                                                   
                                                                







                                                                          
                                                         








                                               





                                                       




                                            
     
     
   
 




                                       
                                       
   
                                           



                              

                                         
         
                                                  
                                



          
                              



                       
     

                              
                                   


        
                                          




                                                     
       
                                                                 


          
                                   
       

     

                                                
 
                              
     








                                        
     

                    















                                                        
                                    
   



                                                                                  

   
                                 
   



                                                      

   
                                      
   



                                                    

   
                                                                                   
   








                                                                





                                                      

                                                        
                            

   
     
                         
     
                                 
   















                                                                                                        
                                     


         




                         
                                                                              







                                                                        
   
 



























                                                                                           

                                              
                              


           
                                                          













                                   
                                                         
   





                                                      
                                                              

                                            


                        
                                   
                 
                                                             


                                             
                                                                   







                                   
                
     
   
 





                                                               
     




                                         

                                                         








                                  
     
   
 





                                                           
     























                                                           
                                                           















                                                      
                                                     













                                                                 









                                       
/***************************************************************************
 * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
 * 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:
 *    Eike Stepper - initial API and implementation
 **************************************************************************/
package org.eclipse.net4j.util.internal.ui.views;

import org.eclipse.net4j.util.ReflectUtil;
import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.event.EventUtil;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.internal.ui.bundle.OM;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * @author Eike Stepper
 */
public class Net4jIntrospectorView extends ViewPart implements ISelectionListener, IDoubleClickListener, IListener
{
  private static final Object[] NO_ELEMENTS = {};

  private TableViewer currentViewer;

  private TableViewer objectViewer;

  private TableViewer iterableViewer;

  private TableViewer mapViewer;

  private Stack<Object> elements = new Stack<Object>();

  private Text classLabel;

  private Text objectLabel;

  private IAction backAction = new BackAction();

  private StackLayout stackLayout;

  private Composite stacked;

  public Net4jIntrospectorView()
  {
  }

  @Override
  public void dispose()
  {
    getSite().getPage().removeSelectionListener(this);
    super.dispose();
  }

  @Override
  public void createPartControl(Composite parent)
  {
    Color bg = parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
    Color gray = parent.getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);

    Composite composite = new Composite(parent, SWT.NONE);
    composite.setLayout(newGrid(1));

    Composite c = new Composite(composite, SWT.BORDER);
    c.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    c.setLayout(newGrid(2));

    classLabel = new Text(c, SWT.READ_ONLY);
    classLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    classLabel.setBackground(bg);
    classLabel.setForeground(gray);

    objectLabel = new Text(c, SWT.READ_ONLY);
    objectLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
    objectLabel.setBackground(bg);

    stackLayout = new StackLayout();
    stacked = new Composite(composite, SWT.NONE);
    stacked.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    stacked.setLayout(stackLayout);

    objectViewer = createViewer(stacked);
    createObjectColmuns();
    objectViewer.addDoubleClickListener(this);
    objectViewer.setContentProvider(new ObjectContentProvider());
    objectViewer.setLabelProvider(new ObjectLabelProvider());
    objectViewer.setSorter(new NameSorter());
    objectViewer.setInput(getViewSite());

    iterableViewer = createViewer(stacked);
    createIterableColmuns();
    iterableViewer.addDoubleClickListener(this);
    iterableViewer.setContentProvider(new IterableContentProvider());
    iterableViewer.setLabelProvider(new IterableLabelProvider());
    iterableViewer.setInput(getViewSite());

    mapViewer = createViewer(stacked);
    createMapColmuns();
    mapViewer.addDoubleClickListener(this);
    mapViewer.setContentProvider(new MapContentProvider());
    mapViewer.setLabelProvider(new MapLabelProvider());
    mapViewer.setSorter(new NameSorter());
    mapViewer.setInput(getViewSite());

    IActionBars bars = getViewSite().getActionBars();
    fillLocalPullDown(bars.getMenuManager());
    fillLocalToolBar(bars.getToolBarManager());
    getSite().getPage().addSelectionListener(this);
    setCurrentViewer(objectViewer);
  }

  private void setCurrentViewer(TableViewer viewer)
  {
    currentViewer = viewer;
    stackLayout.topControl = currentViewer.getControl();
    stacked.layout();
  }

  private TableViewer createViewer(Composite parent)
  {
    TableViewer viewer = new TableViewer(parent, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
    viewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    viewer.getTable().setHeaderVisible(true);
    viewer.getTable().setLinesVisible(true);
    return viewer;
  }

  public void refreshViewer()
  {
    try
    {
      currentViewer.getControl().getDisplay().asyncExec(new Runnable()
      {
        public void run()
        {
          try
          {
            currentViewer.refresh();
          }
          catch (RuntimeException ignore)
          {
          }
        }
      });
    }
    catch (RuntimeException ignore)
    {
    }
  }

  public void selectionChanged(IWorkbenchPart part, ISelection sel)
  {
    if (part == this)
    {
      return;
    }

    if (sel instanceof IStructuredSelection)
    {
      IStructuredSelection ssel = (IStructuredSelection)sel;
      elements.clear();
      setObject(ssel.getFirstElement());
    }
    else
    {
      setObject(null);
    }
  }

  public void doubleClick(DoubleClickEvent event)
  {
    ISelection sel = event.getSelection();
    if (sel instanceof IStructuredSelection)
    {
      IStructuredSelection ssel = (IStructuredSelection)sel;
      Object element = ssel.getFirstElement();
      if (currentViewer == objectViewer && element instanceof Pair)
      {
        Pair<Field, Object> pair = (Pair<Field, Object>)element;
        Field field = pair.getElement1();
        if (!field.getType().isPrimitive())
        {
          setObject(pair.getElement2());
        }
      }
      else if (currentViewer == mapViewer && element instanceof Map.Entry)
      {
        Map.Entry<?, ?> entry = (Map.Entry<?, ?>)element;
        setObject(entry.getValue());
      }
      else if (currentViewer == iterableViewer)
      {
        setObject(element);
      }
    }
  }

  /**
   * Passing the focus request to the viewer's control.
   */
  @Override
  public void setFocus()
  {
    try
    {
      currentViewer.getControl().setFocus();
    }
    catch (RuntimeException ignore)
    {
    }
  }

  public void notifyEvent(IEvent event)
  {
    refreshViewer();
  }

  private void setObject(Object object)
  {
    EventUtil.removeListener(object, this);
    if (object != null)
    {
      if (!elements.isEmpty())
      {
        Object element = elements.peek();
        if (element != object)
        {
          EventUtil.removeListener(element, this);
          elements.push(object);
        }
      }
      else
      {
        elements.push(object);
      }
    }

    if (object == null)
    {
      classLabel.setText("");
      objectLabel.setText("");
      currentViewer = objectViewer;
    }
    else
    {
      EventUtil.addListener(object, this);
      String className = object.getClass().getName();
      classLabel.setText(className);

      String value = object.toString();
      if (value.startsWith(className + "@"))
      {
        objectLabel.setText(value.substring(className.length()));
      }
      else
      {
        objectLabel.setText(value);
      }
    }

    classLabel.getParent().layout();
    backAction.setEnabled(elements.size() >= 2);

    if (object instanceof Map)
    {
      setCurrentViewer(mapViewer);
    }
    else if (object instanceof Iterable)
    {
      setCurrentViewer(iterableViewer);
    }
    else
    {
      setCurrentViewer(objectViewer);
    }

    refreshViewer();
  }

  private GridLayout newGrid(int numColumns)
  {
    GridLayout grid = new GridLayout(numColumns, false);
    grid.marginTop = 0;
    grid.marginLeft = 0;
    grid.marginRight = 0;
    grid.marginBottom = 0;
    grid.marginWidth = 0;
    grid.marginHeight = 0;
    grid.horizontalSpacing = 0;
    grid.verticalSpacing = 0;
    return grid;
  }

  private void createObjectColmuns()
  {
    Table table = objectViewer.getTable();
    String[] columnNames = { "Field", "Value", "Declared Type", "Concrete Type" };
    int[] columnWidths = { 200, 400, 300, 300 };
    createColumns(table, columnNames, columnWidths);
  }

  private void createMapColmuns()
  {
    Table table = mapViewer.getTable();
    String[] columnNames = { "Key", "Value", "Type" };
    int[] columnWidths = { 200, 400, 300 };
    createColumns(table, columnNames, columnWidths);
  }

  private void createIterableColmuns()
  {
    Table table = iterableViewer.getTable();
    String[] columnNames = { "Element", "Type" };
    int[] columnWidths = { 400, 300 };
    createColumns(table, columnNames, columnWidths);
  }

  private void createColumns(Table table, String[] columnNames, int[] columnWidths)
  {
    TableColumn[] columns = new TableColumn[columnNames.length];
    for (int i = 0; i < columns.length; i++)
    {
      TableColumn column = new TableColumn(table, SWT.LEFT, i);
      column.setText(columnNames[i]);
      column.setWidth(columnWidths[i]);
      column.setMoveable(true);
      column.setResizable(true);
    }
  }

  private void fillLocalPullDown(IMenuManager manager)
  {
  }

  private void fillLocalToolBar(IToolBarManager manager)
  {
    manager.add(backAction);
  }

  /**
   * @author Eike Stepper
   */
  class BackAction extends Action
  {
    private BackAction()
    {
      super("Back");
      ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages();
      setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_BACK));
      setDisabledImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_BACK_DISABLED));
    }

    @Override
    public void run()
    {
      if (!elements.isEmpty())
      {
        elements.pop();
        if (!elements.isEmpty())
        {
          setObject(elements.peek());
        }
      }
    }
  }

  /**
   * @author Eike Stepper
   */
  abstract class AbstractContentProvider implements IStructuredContentProvider
  {
    public void inputChanged(Viewer v, Object oldInput, Object newInput)
    {
    }

    public void dispose()
    {
    }
  }

  /**
   * @author Eike Stepper
   */
  abstract class AbstractLabelProvider extends LabelProvider implements ITableLabelProvider
  {
    @Override
    public String getText(Object element)
    {
      return getColumnText(element, 0);
    }

    public Image getColumnImage(Object obj, int index)
    {
      return null;
    }

    @Override
    public Image getImage(Object obj)
    {
      return null;
    }
  }

  /**
   * @author Eike Stepper
   */
  class ObjectContentProvider extends AbstractContentProvider
  {
    public Object[] getElements(Object parent)
    {
      if (!elements.isEmpty())
      {
        try
        {
          return ReflectUtil.dumpToArray(elements.peek());
        }
        catch (RuntimeException ex)
        {
          OM.LOG.error(ex);
        }
      }

      return NO_ELEMENTS;
    }
  }

  /**
   * @author Eike Stepper
   */
  class ObjectLabelProvider extends AbstractLabelProvider
  {
    public String getColumnText(Object obj, int index)
    {
      if (obj instanceof Pair)
      {
        try
        {
          Pair<Field, Object> pair = (Pair<Field, Object>)obj;
          Field field = pair.getElement1();
          Object value = pair.getElement2();
          switch (index)
          {
          case 0:
            return field.getName();
          case 1:
            return value == null ? "null" : value.toString();
          case 2:
            return field.getType().getName();
          case 3:
            return value == null ? "" : value.getClass().getName();
          }
        }
        catch (RuntimeException ex)
        {
          OM.LOG.error(ex);
        }
      }

      return "";
    }
  }

  /**
   * @author Eike Stepper
   */
  class IterableContentProvider extends AbstractContentProvider
  {
    public Object[] getElements(Object parent)
    {
      if (!elements.isEmpty())
      {
        Object element = elements.peek();
        if (element instanceof Iterable)
        {
          List<Object> result = new ArrayList<Object>();
          for (Object object : (Iterable<Object>)element)
          {
            result.add(object);
          }

          return result.toArray();
        }
      }

      return NO_ELEMENTS;
    }
  }

  /**
   * @author Eike Stepper
   */
  class IterableLabelProvider extends AbstractLabelProvider
  {
    public String getColumnText(Object obj, int index)
    {
      switch (index)
      {
      case 0:
        return obj == null ? "null" : obj.toString();
      case 1:
        return obj == null ? "" : obj.getClass().getName();
      }

      return "";
    }
  }

  /**
   * @author Eike Stepper
   */
  class MapContentProvider extends AbstractContentProvider
  {
    public Object[] getElements(Object parent)
    {
      if (!elements.isEmpty())
      {
        Object element = elements.peek();
        if (element instanceof Map)
        {
          return ((Map<?, ?>)element).entrySet().toArray();
        }
      }

      return NO_ELEMENTS;
    }
  }

  /**
   * @author Eike Stepper
   */
  class MapLabelProvider extends AbstractLabelProvider
  {
    public String getColumnText(Object obj, int index)
    {
      if (obj instanceof Map.Entry)
      {
        Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
        Object key = entry.getKey();
        Object value = entry.getValue();
        switch (index)
        {
        case 0:
          return key == null ? "null" : key.toString();
        case 1:
          return value == null ? "null" : value.toString();
        case 2:
          return value == null ? "" : value.getClass().getName();
        }
      }

      return "";
    }
  }

  /**
   * @author Eike Stepper
   */
  class NameSorter extends ViewerSorter
  {
  }
}

Back to the top