title: Simplest way to make custom debug watch in Eclipse?
body: <p>Is it possible to create custom variable viewers in Eclipse? Suppose I wish to decompose bitfield or see bitmap as an image. Is it possible?</p>
  
  <p>Can you give some simplest example?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I have tried to implement the following example: <a href="http://alvinalexander.com/java/jwarehouse/eclipse/org.eclipse.jdt.debug.tests/test-plugin/org/eclipse/jdt/debug/testplugin/detailpane/SimpleDetailPane.java.shtml" rel="nofollow">http://alvinalexander.com/java/jwarehouse/eclipse/org.eclipse.jdt.debug.tests/test-plugin/org/eclipse/jdt/debug/testplugin/detailpane/SimpleDetailPane.java.shtml</a></p>
  
  <p>My <code>plugin.xml</code> is follows:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;?eclipse version="3.0"?&gt;
  
  &lt;plugin&gt;
     &lt;extension
           point="org.eclipse.debug.ui.detailPaneFactories"&gt;
        &lt;detailFactories
              class="tests.debug.details.DetailPaneFactory"
              id="tests.debug.details.detailFactories"&gt;
        &lt;/detailFactories&gt;
     &lt;/extension&gt;
  
  
  
  &lt;/plugin&gt;
  </code></pre>
  
  <p>My <code>DetailPaneFactory.java</code> is follows:</p>
  
  <pre><code>package tests.debug.details;
  
  import java.util.AbstractSet;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  
  import org.eclipse.debug.ui.IDetailPane;
  import org.eclipse.debug.ui.IDetailPaneFactory;
  import org.eclipse.jface.viewers.IStructuredSelection;
  
  public class DetailPaneFactory implements IDetailPaneFactory {
  
      private HashMap&lt;String,Class&lt;? extends IDetailPane&gt;&gt; classes = new HashMap&lt;String,Class&lt;? extends IDetailPane&gt;&gt;();
  
      private void addClass(Class&lt;? extends IDetailPane&gt; cls) {
          try {
              String paneID = (String) cls.getField("ID").get(null);
              classes.put(paneID, cls);
          } catch (IllegalArgumentException | IllegalAccessException
                  | NoSuchFieldException | SecurityException e) {
              throw new RuntimeException(e);
          }
          finally {
  
          }
  
      }
  
      private Class&lt;? extends IDetailPane&gt; getClass(String paneID) {
          Class&lt;? extends IDetailPane&gt; ans = classes.get(paneID);
          return ans;
      }
  
      public DetailPaneFactory() {
          addClass(SimpleDetailPane.class);
      }
  
  
      @Override
      public IDetailPane createDetailPane(String paneID) {
  
          Class&lt;? extends IDetailPane&gt; cls = getClass(paneID);
          if( cls != null ) {
              try {
                  return cls.newInstance();
              } catch (InstantiationException | IllegalAccessException e) {
                  throw new RuntimeException();
              }
          }
          else {
              return null;
          }
      }
  
      @Override
      public String getDetailPaneName(String paneID) {
          Class&lt;? extends IDetailPane&gt; cls = getClass(paneID);
          if( cls != null ) {
              try {
                  return (String)cls.getField("NAME").get(null);
              } catch (IllegalArgumentException | IllegalAccessException
                      | NoSuchFieldException | SecurityException e) {
                  throw new RuntimeException(e);
              }
          }
          else {
              return null;
          }
      }
  
      @Override
      public String getDetailPaneDescription(String paneID) {
          Class&lt;? extends IDetailPane&gt; cls = getClass(paneID);
          if( cls != null ) {
              try {
                  return (String)cls.getField("DESCRIPTION").get(null);
              } catch (IllegalArgumentException | IllegalAccessException
                      | NoSuchFieldException | SecurityException e) {
                  throw new RuntimeException(e);
              }
          }
          else {
              return null;
          }
      }
  
      @Override
      public Set&lt;String&gt; getDetailPaneTypes(IStructuredSelection selection) {
          return new AbstractSet&lt;String&gt;() {
  
              @Override
              public Iterator&lt;String&gt; iterator() {
                  return new Iterator&lt;String&gt;() {
  
                      private Iterator&lt;Map.Entry&lt;String,Class&lt;? extends IDetailPane&gt;&gt;&gt; it = classes.entrySet().iterator();
  
                      @Override
                      public void remove() {
                          it.remove();
                      }
  
                      @Override
                      public String next() {
                          return it.next().getKey();
                      }
  
                      @Override
                      public boolean hasNext() {
                          return it.hasNext();
                      }
                  };
              }
  
              @Override
              public int size() {
                  return classes.size();
              }
  
          };
      }
  
      @Override
      public String getDefaultDetailPane(IStructuredSelection selection) {
          return SimpleDetailPane.ID;
      }
  
  }
  </code></pre>
  
  <p>and my <code>SimpleDetailPane.java</code> is as in example.</p>
  
  <p>And it apparently works.</p>