public static void main(String[] args) {
    final Display display = new Display();
    Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());
    final Tree tree = new Tree(shell, SWT.FULL_SELECTION | SWT.BORDER);
    tree.setHeaderVisible(true);
    TreeColumn column0 = new TreeColumn(tree, SWT.LEFT);
    column0.setText("Column 0");
    TreeColumn column1 = new TreeColumn(tree, SWT.LEFT);
    column1.setText("Column 1");
    TreeColumn column2 = new TreeColumn(tree, SWT.LEFT);
    column2.setText("Column 2");
    for (int i = 0; i < 9; i++) {
      TreeItem item = new TreeItem(tree, SWT.NONE);
      item.setText("item " + i);
      item.setText(1, "column 1 - " + i);
      item.setText(2, "column 2 - " + i);
      for (int j = 0; j < 9; j++) {
        TreeItem subItem = new TreeItem(item, SWT.NONE);
        subItem.setText("item " + i + " " + j);
        subItem.setText(1, "column 1 - " + i + " " + j);
        subItem.setText(2, "column 2 - " + i + " " + j);
        for (int k = 0; k < 9; k++) {
          TreeItem subsubItem = new TreeItem(subItem, SWT.NONE);
          subsubItem.setText("item " + i + " " + j + " " + k);
          subsubItem.setText(1, "column 1 - " + i + " " + j + " " + k);
          subsubItem.setText(2, "column 2 - " + i + " " + j + " " + k);
        }
      }
    }
    column0.pack();
    column1.pack();
    column2.pack();

    Heartbeat =
        new Runnable() {
          @Override
          public void run() {
            if (!Tracking || tree.isDisposed()) return;
            Point cursor = display.getCursorLocation();
            cursor = display.map(null, tree, cursor);
            Scroll(tree, cursor.x, cursor.y);
            display.timerExec(ScrollSpeed, Heartbeat);
          }
        };
    Listener listener =
        new Listener() {
          @Override
          public void handleEvent(Event event) {
            switch (event.type) {
              case SWT.MouseEnter:
                Tracking = true;
                display.timerExec(0, Heartbeat);
                break;
              case SWT.MouseExit:
                Tracking = false;
                break;
            }
          }
        };
    tree.addListener(SWT.MouseEnter, listener);
    tree.addListener(SWT.MouseExit, listener);
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) display.sleep();
    }
    display.dispose();
  }
  /*
   * (non-Javadoc)
   * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
   */
  public void createControl(Composite parent) {
    display = parent.getDisplay();
    sashForm = new SashForm(parent, SWT.VERTICAL);
    FillLayout layout = new FillLayout();
    sashForm.setLayout(layout);
    GridData data = new GridData(GridData.FILL_BOTH);
    sashForm.setLayoutData(data);
    initializeDialogUnits(sashForm);

    Composite composite = new Composite(sashForm, SWT.NONE);
    GridLayout gridLayout = new GridLayout();
    gridLayout.marginWidth = 0;
    gridLayout.marginHeight = 0;
    composite.setLayout(gridLayout);

    treeViewer = createTreeViewer(composite);
    data = new GridData(GridData.FILL_BOTH);
    data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT);
    data.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH);
    Tree tree = treeViewer.getTree();
    tree.setLayoutData(data);
    tree.setHeaderVisible(true);
    activateCopy(tree);
    TreeViewerColumn nameColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);
    nameColumn.getColumn().setText(ProvUIMessages.ProvUI_NameColumnTitle);
    nameColumn.getColumn().setWidth(400);
    nameColumn.getColumn().setMoveable(true);
    nameColumn.setLabelProvider(
        new ColumnLabelProvider() {
          public String getText(Object element) {
            IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
            String label = iu.getProperty(IInstallableUnit.PROP_NAME, null);
            if (label == null) label = iu.getId();
            return label;
          }

          public Image getImage(Object element) {
            if (element instanceof ProvElement) return ((ProvElement) element).getImage(element);
            if (ProvUI.getAdapter(element, IInstallableUnit.class) != null)
              return ProvUIImages.getImage(ProvUIImages.IMG_IU);
            return null;
          }

          public String getToolTipText(Object element) {
            if (element instanceof AvailableIUElement
                && ((AvailableIUElement) element).getImageOverlayId(null) == ProvUIImages.IMG_INFO)
              return ProvUIMessages.RemedyElementNotHighestVersion;
            return super.getToolTipText(element);
          }
        });
    TreeViewerColumn versionColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);
    versionColumn.getColumn().setText(ProvUIMessages.ProvUI_VersionColumnTitle);
    versionColumn.getColumn().setWidth(200);
    versionColumn.setLabelProvider(
        new ColumnLabelProvider() {
          public String getText(Object element) {
            IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
            if (element instanceof IIUElement) {
              if (((IIUElement) element).shouldShowVersion()) return iu.getVersion().toString();
              return ""; //$NON-NLS-1$
            }
            return iu.getVersion().toString();
          }
        });
    TreeViewerColumn idColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);
    idColumn.getColumn().setText(ProvUIMessages.ProvUI_IdColumnTitle);
    idColumn.getColumn().setWidth(200);

    idColumn.setLabelProvider(
        new ColumnLabelProvider() {
          public String getText(Object element) {
            IInstallableUnit iu = ProvUI.getAdapter(element, IInstallableUnit.class);
            return iu.getId();
          }
        });

    // Filters and sorters before establishing content, so we don't refresh unnecessarily.
    IUComparator comparator = new IUComparator(IUComparator.IU_NAME);
    comparator.useColumnConfig(getColumnConfig());
    treeViewer.setComparator(comparator);
    treeViewer.setComparer(new ProvElementComparer());
    ColumnViewerToolTipSupport.enableFor(treeViewer);
    contentProvider = new ProvElementContentProvider();
    treeViewer.setContentProvider(contentProvider);
    //		labelProvider = new IUDetailsLabelProvider(null, getColumnConfig(), getShell());
    //		treeViewer.setLabelProvider(labelProvider);

    // Optional area to show the size
    createSizingInfo(composite);

    // The text area shows a description of the selected IU, or error detail if applicable.
    iuDetailsGroup =
        new IUDetailsGroup(
            sashForm,
            treeViewer,
            convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH),
            true);

    setControl(sashForm);
    sashForm.setWeights(getSashWeights());
    Dialog.applyDialogFont(sashForm);

    // Controls for filtering/presentation/site selection
    Composite controlsComposite = new Composite(composite, SWT.NONE);
    gridLayout = new GridLayout();
    gridLayout.marginWidth = 0;
    gridLayout.marginHeight = 0;
    gridLayout.numColumns = 2;
    gridLayout.makeColumnsEqualWidth = true;
    gridLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
    controlsComposite.setLayout(layout);
    GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
    controlsComposite.setLayoutData(gd);

    final Runnable runnable =
        new Runnable() {
          public void run() {
            treeViewer.addSelectionChangedListener(
                new ISelectionChangedListener() {
                  public void selectionChanged(SelectionChangedEvent event) {
                    setDetailText(resolvedOperation);
                  }
                });
            setDrilldownElements(input, resolvedOperation);
            treeViewer.setInput(input);
          }
        };

    if (resolvedOperation != null && !resolvedOperation.hasResolved()) {
      try {
        getContainer()
            .run(
                true,
                false,
                new IRunnableWithProgress() {
                  public void run(IProgressMonitor monitor) {
                    resolvedOperation.resolveModal(monitor);
                    display.asyncExec(runnable);
                  }
                });
      } catch (Exception e) {
        StatusManager.getManager()
            .handle(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e));
      }
    } else {
      runnable.run();
    }
  }