public JPanel demo(Graph g, final String label) {
    // create a new radial tree view
    final PhysioMapRadialGraphView gview =
        new PhysioMapRadialGraphView(settings, g, label, semsimmodel);
    Visualization vis = gview.getVisualization();

    // create a search panel for the tree map
    SearchQueryBinding sq =
        new SearchQueryBinding(
            (Table) vis.getGroup(treeNodes),
            label,
            (SearchTupleSet) vis.getGroup(Visualization.SEARCH_ITEMS));
    JSearchPanel search = sq.createSearchPanel();
    search.setShowResultCount(true);
    search.setBorder(BorderFactory.createEmptyBorder(5, 5, 4, 0));
    search.setFont(FontLib.getFont("Verdana", Font.PLAIN, 11));

    final JTextArea title = new JTextArea();
    title.setPreferredSize(new Dimension(450, 500));
    title.setMaximumSize(new Dimension(450, 500));
    title.setMinimumSize(new Dimension(450, 500));

    title.setAlignmentY(CENTER_ALIGNMENT);
    title.setLineWrap(true);
    title.setWrapStyleWord(true);
    title.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
    title.setFont(FontLib.getFont("Verdana", Font.PLAIN, 11));

    gview.addControlListener(
        new ControlAdapter() {
          public void itemEntered(VisualItem item, MouseEvent e) {}

          public void itemExited(VisualItem item, MouseEvent e) {
            title.setText(null);
          }
        });

    Box searchbox = new Box(BoxLayout.X_AXIS);
    searchbox.add(Box.createHorizontalStrut(10));
    searchbox.add(search);
    searchbox.add(Box.createHorizontalStrut(3));

    JPanel panel = new JPanel(new BorderLayout());
    panel.add(searchbox, BorderLayout.NORTH);
    panel.add(gview, BorderLayout.CENTER);
    panel.add(Box.createGlue(), BorderLayout.SOUTH);

    Color BACKGROUND = Color.WHITE;
    Color FOREGROUND = Color.DARK_GRAY;
    UILib.setColor(panel, BACKGROUND, FOREGROUND);

    return panel;
  }
  public Congress(Table t) {
    super(new BorderLayout());

    // --------------------------------------------------------------------
    // STEP 1: setup the visualized data

    final Visualization vis = new Visualization();
    m_vis = vis;

    final String group = "by_state";

    // filter to show only candidates receiving more than $100,000
    Predicate p = (Predicate) ExpressionParser.parse("[" + TOTAL_RECEIPTS + "] >= 100000");
    VisualTable vt = vis.addTable(group, t, p);

    // add a new column containing a label string showing
    // candidate name, party, state, year, and total receipts
    vt.addColumn(
        "label",
        "CONCAT(CAP(Candidate), ' (', "
            + "CAP([Party Designation]), '-', [State Code], "
            + "') ', Year, ': $', FORMAT([Total Receipts],2))");

    // add calculation for senators
    vt.addColumn("Senate", "District <= 0");

    vis.setRendererFactory(
        new RendererFactory() {
          AbstractShapeRenderer sr = new ShapeRenderer();
          Renderer arY = new AxisRenderer(Constants.RIGHT, Constants.TOP);
          Renderer arX = new AxisRenderer(Constants.CENTER, Constants.FAR_BOTTOM);

          public Renderer getRenderer(VisualItem item) {
            return item.isInGroup("ylab") ? arY : item.isInGroup("xlab") ? arX : sr;
          }
        });

    // --------------------------------------------------------------------
    // STEP 2: create actions to process the visual data

    // set up dynamic queries, search set
    RangeQueryBinding receiptsQ = new RangeQueryBinding(vt, RECEIPTS);
    ListQueryBinding yearsQ = new ListQueryBinding(vt, "Year");
    SearchQueryBinding searchQ = new SearchQueryBinding(vt, "Candidate");

    // construct the filtering predicate
    AndPredicate filter = new AndPredicate(searchQ.getPredicate());
    filter.add(yearsQ.getPredicate());
    filter.add(receiptsQ.getPredicate());

    // set up the actions
    AxisLayout xaxis = new AxisLayout(group, "State Code", Constants.X_AXIS, VisiblePredicate.TRUE);
    AxisLayout yaxis = new AxisLayout(group, RECEIPTS, Constants.Y_AXIS, VisiblePredicate.TRUE);
    // yaxis.setScale(Constants.LOG_SCALE);
    yaxis.setRangeModel(receiptsQ.getModel());
    receiptsQ.getNumberModel().setValueRange(0, 65000000, 0, 65000000);

    xaxis.setLayoutBounds(m_dataB);
    yaxis.setLayoutBounds(m_dataB);

    AxisLabelLayout ylabels = new AxisLabelLayout("ylab", yaxis, m_ylabB);
    NumberFormat nf = NumberFormat.getCurrencyInstance();
    nf.setMaximumFractionDigits(0);
    ylabels.setNumberFormat(nf);

    AxisLabelLayout xlabels = new AxisLabelLayout("xlab", xaxis, m_xlabB, 15);
    vis.putAction("xlabels", xlabels);

    // dems = blue, reps = red, other = gray
    int[] palette =
        new int[] {
          ColorLib.rgb(150, 150, 255), ColorLib.rgb(255, 150, 150), ColorLib.rgb(180, 180, 180)
        };
    DataColorAction color =
        new DataColorAction(group, "Party", Constants.ORDINAL, VisualItem.STROKECOLOR, palette);

    int[] shapes = new int[] {Constants.SHAPE_RECTANGLE, Constants.SHAPE_DIAMOND};
    DataShapeAction shape = new DataShapeAction(group, "Senate", shapes);

    Counter cntr = new Counter(group);

    ActionList draw = new ActionList();
    draw.add(cntr);
    draw.add(color);
    draw.add(shape);
    draw.add(xaxis);
    draw.add(yaxis);
    draw.add(ylabels);
    draw.add(new ColorAction(group, VisualItem.FILLCOLOR, 0));
    draw.add(new RepaintAction());
    vis.putAction("draw", draw);

    ActionList update = new ActionList();
    update.add(new VisibilityFilter(group, filter));
    update.add(cntr);
    update.add(xaxis);
    update.add(yaxis);
    update.add(ylabels);
    update.add(new RepaintAction());
    vis.putAction("update", update);

    UpdateListener lstnr =
        new UpdateListener() {
          public void update(Object src) {
            vis.run("update");
          }
        };
    filter.addExpressionListener(lstnr);

    // --------------------------------------------------------------------
    // STEP 4: set up a display and ui components to show the visualization

    m_display = new Display(vis);
    m_display.setItemSorter(
        new ItemSorter() {
          public int score(VisualItem item) {
            int score = super.score(item);
            if (item.isInGroup(group)) score += item.getInt(TOTAL_RECEIPTS);
            return score;
          }
        });
    m_display.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    m_display.setSize(700, 450);
    m_display.setHighQuality(true);
    m_display.addComponentListener(
        new ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            displayLayout();
          }
        });
    displayLayout();

    m_details = new JFastLabel(m_title);
    m_details.setPreferredSize(new Dimension(75, 20));
    m_details.setVerticalAlignment(SwingConstants.BOTTOM);

    m_total.setPreferredSize(new Dimension(500, 20));
    m_total.setHorizontalAlignment(SwingConstants.RIGHT);
    m_total.setVerticalAlignment(SwingConstants.BOTTOM);

    ToolTipControl ttc = new ToolTipControl("label");
    Control hoverc =
        new ControlAdapter() {
          public void itemEntered(VisualItem item, MouseEvent evt) {
            if (item.isInGroup(group)) {
              m_total.setText(item.getString("label"));
              item.setFillColor(item.getStrokeColor());
              item.setStrokeColor(ColorLib.rgb(0, 0, 0));
              item.getVisualization().repaint();
            }
          }

          public void itemExited(VisualItem item, MouseEvent evt) {
            if (item.isInGroup(group)) {
              m_total.setText(m_totalStr);
              item.setFillColor(item.getEndFillColor());
              item.setStrokeColor(item.getEndStrokeColor());
              item.getVisualization().repaint();
            }
          }
        };
    m_display.addControlListener(ttc);
    m_display.addControlListener(hoverc);

    // --------------------------------------------------------------------
    // STEP 5: launching the visualization

    this.addComponentListener(lstnr);

    // details
    Box infoBox = new Box(BoxLayout.X_AXIS);
    infoBox.add(Box.createHorizontalStrut(5));
    infoBox.add(m_details);
    infoBox.add(Box.createHorizontalGlue());
    infoBox.add(Box.createHorizontalStrut(5));
    infoBox.add(m_total);
    infoBox.add(Box.createHorizontalStrut(5));

    // set up search box
    JSearchPanel searcher = searchQ.createSearchPanel();
    searcher.setLabelText("Candidate: ");
    searcher.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0));

    // create dynamic queries
    Box radioBox = new Box(BoxLayout.X_AXIS);
    radioBox.add(Box.createHorizontalStrut(5));
    radioBox.add(searcher);
    radioBox.add(Box.createHorizontalGlue());
    radioBox.add(Box.createHorizontalStrut(5));
    radioBox.add(yearsQ.createRadioGroup());
    radioBox.add(Box.createHorizontalStrut(16));

    JRangeSlider slider = receiptsQ.createVerticalRangeSlider();
    slider.setThumbColor(null);
    slider.setMinExtent(150000);
    slider.addMouseListener(
        new MouseAdapter() {
          public void mousePressed(MouseEvent e) {
            m_display.setHighQuality(false);
          }

          public void mouseReleased(MouseEvent e) {
            m_display.setHighQuality(true);
            m_display.repaint();
          }
        });

    vis.run("draw");
    vis.run("xlabels");

    add(infoBox, BorderLayout.NORTH);
    add(m_display, BorderLayout.CENTER);
    add(slider, BorderLayout.EAST);
    add(radioBox, BorderLayout.SOUTH);
    UILib.setColor(this, ColorLib.getColor(255, 255, 255), Color.GRAY);
    slider.setForeground(Color.LIGHT_GRAY);
    UILib.setFont(radioBox, FontLib.getFont("Tahoma", 15));
    m_details.setFont(FontLib.getFont("Tahoma", 18));
    m_total.setFont(FontLib.getFont("Tahoma", 16));
  }
    @Override
    public void render(Graphics2D g, VisualItem item) {

      if (item.isVisible()) {
        item.setShape(Constants.SHAPE_RECTANGLE);
        RectangularShape shape = (RectangularShape) getShape(item);
        if (shape != null) {

          shape
              .getBounds2D()
              .setRect(
                  (double) item.get(VisualItem.X),
                  (double) item.get(VisualItem.Y),
                  item.getSize(),
                  item.getSize());

          // draw basic glyph
          Color strokeColor = ColorLib.getColor(item.getStrokeColor());
          Color fillColor = ColorLib.getColor(item.getFillColor());

          //                    int size = (int)item.getSize();
          int x = (int) item.getX() + bufferPx;
          int y = (int) item.getY() + bufferPx;
          int w = (int) item.getDouble(WIDTH) - 2 * bufferPx;
          int h = (int) item.getDouble(HEIGHT) - 2 * bufferPx;
          g.setPaint(fillColor);
          g.fillRect(x, y, w, h);

          // draw string on-top of glyph, filling the glyph's area

          //                    String s = "doc=" + item.getString(NODE_NAME) + "\n";
          String s = "";

          // set text: full document if no search term, else excerpts containing the search term
          String queryStr = searchQ.getSearchSet().getQuery();
          String focusText = item.getString(DocumentGridTable.NODE_FOCUS_TEXT);
          if (queryStr != null
              && !queryStr.isEmpty()
              && focusText != null
              && !focusText.equals("null")
              && !focusText.equals("")) {
            // if search query and terms present in document, use term-containing spans
            s += focusText;
          } else if (queryStr != null
              && !queryStr.isEmpty()
              && focusText.equals(FOCUS_SENT_SPLITTER)) {
            // if search query but no terms present in document, use blank
            s += "";
          } else if ((queryStr == null || queryStr.isEmpty()) && item.canGetInt(NODE_ID)) {
            // if no search query, build feature-oriented summary based on color attribute
            s = controller.getDocumentSummary(item.getInt(NODE_ID), colorAttrName);
          }

          // TODO : idea: set font size dynamically based on number of active nodes? based on size
          // of rect?
          int fontSize = 10;

          item.setFont(FontLib.getFont("Tahoma", Font.PLAIN, fontSize));

          Font f = item.getFont();

          // compute width, height for the given text
          // NOTE: this logic has been moved into drawStringMultiline
          //                    int[] textDims = getTextDims(g, f, s);

          // debug
          //                    System.out.println("debug: "+this.getClass().getName()+":
          // drawStringMultiline at x="+x1+", y="+y1+", w="+w+", h="+h);
          drawStringMultiline(g, f, s, x, y, w, h);
        }
      }
    }
/**
 * Concordance tree display. Display a prefix tree (trie) encoding the context to the right of a
 * concordance; or a (i.e. a right-to-left prefix tree) encoding the left context of a concordance
 *
 * @author S Luz &#60;[email protected]&#62;
 * @version <font size=-1>$Id: $</font>
 * @see
 */
public class ConcordanceTree extends Display {
  private static final String TREE = "tree";
  private static final String TREENODES = "tree.nodes";
  private static final String TREEEDGES = "tree.edges";
  public static final int WIDTH = 1200;
  public static final int HEIGHT = 800;
  public static final String NAME = "name";
  public static final String NAMEEMPTY = "_Empty_Concordance_Tree_";
  public static final String NODECOUNT = "nodecount";
  public static final String ROWCOUNT = "colcount";
  public static final int MAXCOLS = 200;

  private Tree tree;
  private LabelRenderer m_nodeRenderer;
  private EdgeRenderer m_edgeRenderer;
  FisheyeTreeFilter fisheyetreefilter = new FisheyeTreeFilter(TREE, 7);
  private static Font defaultTreeFont = FontLib.getFont("Tahoma", 16);
  private Display m_display_self; // myself

  private String m_label = "label";
  private int m_orientation = Constants.ORIENT_LEFT_RIGHT;
  private static int cutoff_frequency = 1;
  /** Describe rowCount here. */
  private static int rowCount = 1;

  /** Describe minFreqRatio here. */
  private static float minFreqRatio = 1;

  public ConcordanceTree() {
    super(new Visualization());

    m_display_self = this;
    m_label = NAME;

    tree = new Tree();
    Table ntable = tree.getNodeTable();
    ntable.addColumn(NAME, String.class);
    ntable.addColumn(NODECOUNT, int.class);
    ntable.addColumn(ROWCOUNT, int.class);
    resetTree();

    m_vis.add(TREE, tree);
    // m_vis.add(TREE, t, new WordCountPredicate());

    m_nodeRenderer = new LabelRenderer(m_label);
    m_nodeRenderer.setRenderType(AbstractShapeRenderer.RENDER_TYPE_FILL);
    m_nodeRenderer.setHorizontalAlignment(Constants.LEFT);
    m_nodeRenderer.setRoundedCorner(8, 8);
    m_edgeRenderer = new EdgeRenderer(Constants.EDGE_TYPE_CURVE);

    DefaultRendererFactory rf = new DefaultRendererFactory(m_nodeRenderer);
    rf.add(new InGroupPredicate(TREEEDGES), m_edgeRenderer);
    m_vis.setRendererFactory(rf);

    // colors
    ItemAction nodeColor = new NodeColorAction(TREENODES);
    ItemAction textColor = new ColorAction(TREENODES, VisualItem.TEXTCOLOR, ColorLib.rgb(0, 0, 0));
    m_vis.putAction("textColor", textColor);

    ItemAction edgeColor =
        new ColorAction(TREEEDGES, VisualItem.STROKECOLOR, ColorLib.rgb(255, 155, 155));

    // quick repaint
    ActionList repaint = new ActionList();
    repaint.add(nodeColor);
    // WordSizeAction wsaction = new WordSizeAction(TREEEDGES);
    repaint.add(new RepaintAction());
    m_vis.putAction("repaint", repaint);

    // full paint
    ActionList fullPaint = new ActionList();
    fullPaint.add(nodeColor);
    m_vis.putAction("fullPaint", fullPaint);

    // animate paint change
    ActionList animatePaint = new ActionList(400);
    animatePaint.add(new ColorAnimator(TREENODES));
    animatePaint.add(new RepaintAction());
    m_vis.putAction("animatePaint", animatePaint);

    // create the tree layout action
    NodeLinkTreeLayout treeLayout = new NodeLinkTreeLayout(TREE, m_orientation, 10, 0, 0);

    Point2D anchor = new Point2D.Double(25, HEIGHT / 2);
    treeLayout.setLayoutAnchor(anchor);
    m_vis.putAction("treeLayout", treeLayout);

    CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(TREE, m_orientation);
    m_vis.putAction("subLayout", subLayout);

    AutoPanAction autoPan = new AutoPanAction();
    AutoCenterAction autocenter = new AutoCenterAction();
    AutoFitAction autofit = new AutoFitAction();

    ActionList positioning = new ActionList();
    positioning.add(autofit);
    m_vis.putAction("positioning", positioning);

    ActionList fna = new ActionList();
    fna.add(new WordFontAction(TREENODES, defaultTreeFont));
    //   fna.add(new EdgeWidthAction(TREEEDGES));
    // fna.add(new WordSizeAction(TREEEDGES));
    m_vis.putAction("fontnodeaction", fna);

    // create the filtering and layout
    ActionList filter = new ActionList();
    filter.add(fna);
    filter.add(fisheyetreefilter);
    // VisibilityFilter visibfilter = new VisibilityFilter(new WordCountPredicate());
    // filter.add(visibfilter);
    filter.add(treeLayout);
    filter.add(subLayout);
    filter.add(textColor);
    filter.add(nodeColor);
    filter.add(edgeColor);
    m_vis.putAction("filter", filter);

    // This doesn't quite work as expected; the layout is calculated
    // for the entire tree and low freq nodes are simply not shown,
    // leaving gaps in the layout
    //
    // setPredicate(new WordCountPredicate());

    // animated transition
    ActionList animate = new ActionList(1000);
    animate.setPacingFunction(new SlowInSlowOutPacer());
    // animate.add(autoPan);
    animate.add(new QualityControlAnimator());
    animate.add(new VisibilityAnimator(TREE));
    animate.add(new LocationAnimator(TREENODES));
    animate.add(new ColorAnimator(TREENODES));
    animate.add(new RepaintAction());
    m_vis.putAction("animate", animate);
    m_vis.alwaysRunAfter("filter", "animate");

    // create animator for orientation changes
    ActionList orient = new ActionList(2000);
    orient.setPacingFunction(new SlowInSlowOutPacer());
    // orient.add(autoPan);
    // orient.add(autocenter);
    orient.add(new QualityControlAnimator());
    orient.add(new LocationAnimator(TREENODES));
    orient.add(new RepaintAction());
    // orient.add(autofit);

    m_vis.putAction("orient", orient);

    // ------------------------------------------------

    // initialize the display
    setSize(WIDTH, HEIGHT);
    setItemSorter(new TreeDepthItemSorter());
    addControlListener(new ZoomToFitControl());
    addControlListener(new ZoomControl());
    addControlListener(new WheelZoomControl());
    addControlListener(new PanControl());
    addControlListener(new FocusControl(1, "filter"));
    addControlListener(new ToolTipControl(NODECOUNT));

    registerKeyboardAction(
        new OrientAction(Constants.ORIENT_LEFT_RIGHT),
        "left-to-right",
        KeyStroke.getKeyStroke("ctrl 1"),
        WHEN_IN_FOCUSED_WINDOW);
    registerKeyboardAction(
        new OrientAction(Constants.ORIENT_TOP_BOTTOM),
        "top-to-bottom",
        KeyStroke.getKeyStroke("ctrl 2"),
        WHEN_IN_FOCUSED_WINDOW);
    registerKeyboardAction(
        new OrientAction(Constants.ORIENT_RIGHT_LEFT),
        "right-to-left",
        KeyStroke.getKeyStroke("ctrl 3"),
        WHEN_IN_FOCUSED_WINDOW);
    registerKeyboardAction(
        new OrientAction(Constants.ORIENT_BOTTOM_TOP),
        "bottom-to-top",
        KeyStroke.getKeyStroke("ctrl 4"),
        WHEN_IN_FOCUSED_WINDOW);
    registerKeyboardAction(
        new FisheyeExpandAction(-1),
        "collapse-one",
        KeyStroke.getKeyStroke("ctrl 5"),
        WHEN_IN_FOCUSED_WINDOW);
    registerKeyboardAction(
        new FisheyeExpandAction(+1),
        "expand-one",
        KeyStroke.getKeyStroke("ctrl 6"),
        WHEN_IN_FOCUSED_WINDOW);

    // ------------------------------------------------

    // filter graph and perform layout
    setOrientation(m_orientation);
    m_vis.run("filter");

    /*
    TupleSet search = new PrefixSearchTupleSet();
      m_vis.addFocusGroup(Visualization.SEARCH_ITEMS, search);
      search.addTupleSetListener(new TupleSetListener() {
          public void tupleSetChanged(TupleSet t, Tuple[] add, Tuple[] rem) {
            m_vis.cancel("animatePaint");
            m_vis.run("fullPaint");
            m_vis.run("animatePaint");
          }
        });
       */

  }

  public Tree getTree() {
    return tree;
  }

  public void resetTree() {
    tree.clear();
    Node cnode = tree.addRoot();
    cnode.setString(NAME, NAMEEMPTY);
    cnode.setInt(NODECOUNT, 1);
    cnode.setInt(ROWCOUNT, 1);
  }

  public void initialView() {
    reset();
    m_vis.cancel("filter");
    m_vis.run("filter");
    m_vis.run("positioning");
  }

  /**
   * Get the <code>DefaultTreeFont</code> value.
   *
   * @return a <code>Font</code> value
   */
  public final Font getDefaultTreeFont() {
    return defaultTreeFont;
  }

  /**
   * Set the <code>DefaultTreeFont</code> value.
   *
   * @param newDefaultTreeFont The new DefaultTreeFont value.
   */
  public final void setDefaultTreeFont(final Font dtf) {
    defaultTreeFont = dtf;
  }

  // set orientation of layout
  public void setOrientation(int orientation) {
    NodeLinkTreeLayout rtl = (NodeLinkTreeLayout) m_vis.getAction("treeLayout");
    CollapsedSubtreeLayout stl = (CollapsedSubtreeLayout) m_vis.getAction("subLayout");
    Point2D anchor;
    switch (orientation) {
      case Constants.ORIENT_LEFT_RIGHT:
        m_nodeRenderer.setHorizontalAlignment(Constants.LEFT);
        m_edgeRenderer.setHorizontalAlignment1(Constants.RIGHT);
        m_edgeRenderer.setHorizontalAlignment2(Constants.LEFT);
        m_edgeRenderer.setVerticalAlignment1(Constants.CENTER);
        m_edgeRenderer.setVerticalAlignment2(Constants.CENTER);
        anchor = new Point2D.Double(25, getHeight() / 2);
        break;
      case Constants.ORIENT_RIGHT_LEFT:
        m_nodeRenderer.setHorizontalAlignment(Constants.RIGHT);
        m_edgeRenderer.setHorizontalAlignment1(Constants.LEFT);
        m_edgeRenderer.setHorizontalAlignment2(Constants.RIGHT);
        m_edgeRenderer.setVerticalAlignment1(Constants.CENTER);
        m_edgeRenderer.setVerticalAlignment2(Constants.CENTER);
        anchor = new Point2D.Double(getWidth() - 25, getHeight() / 2);
        break;
      case Constants.ORIENT_TOP_BOTTOM:
        m_nodeRenderer.setHorizontalAlignment(Constants.CENTER);
        m_edgeRenderer.setHorizontalAlignment1(Constants.CENTER);
        m_edgeRenderer.setHorizontalAlignment2(Constants.CENTER);
        m_edgeRenderer.setVerticalAlignment1(Constants.BOTTOM);
        m_edgeRenderer.setVerticalAlignment2(Constants.TOP);
        anchor = new Point2D.Double(getWidth() / 2, 35);
        break;
      case Constants.ORIENT_BOTTOM_TOP:
        m_nodeRenderer.setHorizontalAlignment(Constants.CENTER);
        m_edgeRenderer.setHorizontalAlignment1(Constants.CENTER);
        m_edgeRenderer.setHorizontalAlignment2(Constants.CENTER);
        m_edgeRenderer.setVerticalAlignment1(Constants.TOP);
        m_edgeRenderer.setVerticalAlignment2(Constants.BOTTOM);
        anchor = new Point2D.Double(getWidth() / 2, getHeight() - 35);
        break;
      default:
        throw new IllegalArgumentException("Unrecognized orientation value: " + orientation);
    }
    m_orientation = orientation;
    rtl.setOrientation(orientation);
    rtl.setLayoutAnchor(anchor);
    stl.setOrientation(orientation);
  }

  public int getOrientation() {
    return m_orientation;
  }

  /**
   * Get the <code>MinFreqRatio</code> value.
   *
   * @return a <code>float</code> value
   */
  public final float getMinFreqRatio() {
    return minFreqRatio;
  }

  /**
   * Set the <code>MinFreqRatio</code> value.
   *
   * @param newMinFreqRatio The new MinFreqRatio value.
   */
  public final void setMinFreqRatio(final float newMinFreqRatio) {
    this.minFreqRatio = newMinFreqRatio;
  }

  /**
   * Get the <code>ColumnCount</code> value.
   *
   * @return an <code>int</code> value
   */
  public final int getRowCount() {
    return rowCount;
  }

  /**
   * Set the <code>ColumnCount</code> value.
   *
   * @param newColumnCount The new ColumnCount value.
   */
  public final void setRowCount(final int rc) {
    this.rowCount = rc;
  }

  // Inner classes (actions etc)
  public class FisheyeExpandAction extends AbstractAction {
    private int expand;

    public FisheyeExpandAction(int b) {
      this.expand = b;
    }

    public void actionPerformed(ActionEvent evt) {
      fisheyetreefilter.setDistance(fisheyetreefilter.getDistance() + expand);
      getVisualization().cancel("filter");
      getVisualization().run("filter");
      getVisualization().run("treeLayout");
      System.err.println(fisheyetreefilter.getDistance());
    }
  }

  public class OrientAction extends AbstractAction {
    private int orientation;

    public OrientAction(int orientation) {
      this.orientation = orientation;
    }

    public void actionPerformed(ActionEvent evt) {
      setOrientation(orientation);
      m_vis.cancel("orient");
      m_vis.run("treeLayout");
      m_vis.run("orient");
      // getVisualization().cancel("orient");
      // getVisualization().run("treeLayout");
      // getVisualization().run("orient");
    }
  }

  public class AutoPanAction extends Action {
    private Point2D m_start = new Point2D.Double();
    private Point2D m_end = new Point2D.Double();
    private Point2D m_cur = new Point2D.Double();
    private int m_bias = 150;

    public void run(double frac) {
      TupleSet ts = m_vis.getFocusGroup(Visualization.FOCUS_ITEMS);
      // System.err.println("auto-panning"+frac);
      if (ts.getTupleCount() == 0) return;
      if (frac == 0.0) {
        int xbias = 0, ybias = 0;
        switch (m_orientation) {
          case Constants.ORIENT_LEFT_RIGHT:
            xbias = m_bias;
            break;
          case Constants.ORIENT_RIGHT_LEFT:
            xbias = -m_bias;
            break;
          case Constants.ORIENT_TOP_BOTTOM:
            ybias = m_bias;
            break;
          case Constants.ORIENT_BOTTOM_TOP:
            ybias = -m_bias;
            break;
        }
        VisualItem vi = (VisualItem) ts.tuples().next();
        m_cur.setLocation(getWidth() / 2, getHeight() / 2);
        getAbsoluteCoordinate(m_cur, m_start);
        m_end.setLocation(vi.getX() + xbias, vi.getY() + ybias);
      } else {
        m_cur.setLocation(
            m_start.getX() + frac * (m_end.getX() - m_start.getX()),
            m_start.getY() + frac * (m_end.getY() - m_start.getY()));
        panToAbs(m_cur);
      }
    }
  }

  public class AutoFitAction extends Action {
    private int m_margin = 20;
    private long m_duration = 1000;
    private String m_group = Visualization.ALL_ITEMS;

    public void run(double frac) {
      Rectangle2D bounds = m_vis.getBounds(m_group);
      GraphicsLib.expand(bounds, m_margin + (int) (1 / m_display_self.getScale()));
      DisplayLib.fitViewToBounds(m_display_self, bounds, m_duration);
    }
  }

  public class AutoCenterAction extends Action {
    private Point2D m_start = new Point2D.Double();
    private Point2D m_end = new Point2D.Double();
    private Point2D m_cur = new Point2D.Double();
    private int m_bias = 0;

    public void run(double frac) {
      System.err.println("auto-centering" + frac);
      if (frac == 0.0) {
        int xbias = 0, ybias = 0;
        switch (m_orientation) {
          case Constants.ORIENT_LEFT_RIGHT:
            xbias = m_bias;
            break;
          case Constants.ORIENT_RIGHT_LEFT:
            xbias = -m_bias;
            break;
          case Constants.ORIENT_TOP_BOTTOM:
            ybias = m_bias;
            break;
          case Constants.ORIENT_BOTTOM_TOP:
            ybias = -m_bias;
            break;
        }
        Rectangle2D vb = m_vis.getBounds(TREE);
        m_cur.setLocation(getWidth() / 2, getHeight() / 2);
        getAbsoluteCoordinate(m_cur, m_start);
        m_end.setLocation(vb.getX() + xbias, vb.getY() + ybias);
      } else {
        m_cur.setLocation(
            m_start.getX() + frac * (m_end.getX() - m_start.getX()),
            m_start.getY() + frac * (m_end.getY() - m_start.getY()));
        panToAbs(m_cur);
      }
    }
  }

  public static class NodeColorAction extends ColorAction {

    public NodeColorAction(String group) {
      super(group, VisualItem.FILLCOLOR);
    }

    public int getColor(VisualItem item) {
      if (m_vis.isInGroup(item, Visualization.SEARCH_ITEMS)) return ColorLib.rgb(255, 190, 190);
      else if (m_vis.isInGroup(item, Visualization.FOCUS_ITEMS)) return ColorLib.rgb(198, 229, 229);
      else if (item.getDOI() > -1) return ColorLib.rgb(164, 193, 193);
      else return ColorLib.rgba(255, 255, 255, 0);
    }
  }

  public static class WordFontAction extends FontAction {

    public WordFontAction(String group, Font df) {
      super(group, df);
    }

    public Font getFont(VisualItem item) {
      int nc = item.getInt(NODECOUNT);
      // if (nc==1)
      //  return defaultTreeFont;

      // int cc = item.getInt(ROWCOUNT);

      // float smin = 1f/cc;

      float s = (float) nc / rowCount;
      float fs = defaultTreeFont.getSize();
      if (s > 1) fs = fs * 2f;
      if (s > minFreqRatio * 60) fs = fs * 3f;
      else if (s > minFreqRatio * 40) fs = fs * 3f;
      else if (s > minFreqRatio * 20) fs = fs * 2.8f;
      else if (s > minFreqRatio * 15) fs = fs * 2.5f;
      else if (s > minFreqRatio * 10) fs = fs * 2f;
      else if (s > minFreqRatio * 6) fs = fs * 1.8f;
      else if (s > minFreqRatio * 3) fs = fs * 1.6f;
      else if (s > minFreqRatio * 2) fs = fs * 1.4f;
      else if (s > minFreqRatio * 1.4) fs = fs * 1.2f;
      else if (s <= minFreqRatio) fs = fs * 0.5f;

      Font font = defaultTreeFont.deriveFont(fs);
      System.err.println(
          "w="
              + item.getString(NAME)
              + " fs="
              + fs
              + " rc="
              + rowCount
              + " s="
              + s
              + " minFreqRatio="
              + minFreqRatio
              + " fn="
              + font);
      return font;
      // }
      // return defaultFont;
    }
  }

  public static class EdgeWidthAction extends StrokeAction {

    public EdgeWidthAction(String group) {
      super(group);
      defaultStroke = this.getDefaultStroke();
    }

    public BasicStroke getStroke(VisualItem item) {
      Node tn = ((Edge) item).getTargetNode();
      int nc = tn.getInt(NODECOUNT);
      if (nc == 1) return new BasicStroke(0f);
      return defaultStroke;
    }
  }

  public static class WordSizeAction extends ItemAction {

    public WordSizeAction(String group) {
      super(group);
    }

    public void process(VisualItem item, double frac) {
      // if (item instanceof Node ){
      // int dp = item.getDepth()+1;
      // double incfactor =
      NodeItem tn = ((EdgeItem) item).getTargetItem();
      int nc = tn.getInt(NODECOUNT);
      if (nc == 1) {
        System.err.println("hiding___" + item);
        PrefuseLib.updateVisible(tn, false);
        PrefuseLib.updateVisible(item, false);
      }
    }
  }

  public static class WordCountPredicate extends prefuse.data.expression.AbstractPredicate {

    public boolean getBoolean(Tuple t) {
      if (t instanceof Node) {
        System.err.println("===" + ((Node) t).getInt(NODECOUNT));
        if (((Node) t).getDepth() == 0) return true;
        else return t.canGetInt(NODECOUNT) && ((Node) t).getInt(NODECOUNT) > cutoff_frequency;
      }
      if (((Edge) t).getSourceNode().getInt(NODECOUNT) <= cutoff_frequency) return false;
      if (((Edge) t).getTargetNode().getInt(NODECOUNT) <= cutoff_frequency) return false;
      return true;
    }
  }
}
Exemple #5
0
  public MPtrack(Table t) {
    super(new BorderLayout());

    // --------------------------------------------------------------------
    // STEP 1: setup the visualized data

    final Visualization vis = new Visualization();
    m_vis = vis;

    final String group = "by_state";

    VisualTable vt = vis.addTable(group, t);

    vis.setRendererFactory(
        new RendererFactory() {
          AbstractShapeRenderer sr = new ShapeRenderer(30);
          Renderer arY = new AxisRenderer(Constants.RIGHT, Constants.TOP);
          Renderer arX = new AxisRenderer(Constants.CENTER, Constants.FAR_BOTTOM);

          public Renderer getRenderer(VisualItem item) {
            return item.isInGroup("ylab") ? arY : item.isInGroup("xlab") ? arX : sr;
          }
        });

    // --------------------------------------------------------------------

    // set up the actions
    AxisLayout xaxis = new AxisLayout(group, "States", Constants.X_AXIS, VisiblePredicate.TRUE);
    AxisLayout yaxis = new AxisLayout(group, PARTY, Constants.Y_AXIS, VisiblePredicate.TRUE);
    // yaxis.setScale(Constants.LOG_SCALE);

    xaxis.setLayoutBounds(m_dataB);
    yaxis.setLayoutBounds(m_dataB);

    AxisLabelLayout ylabels = new AxisLabelLayout("ylab", yaxis, m_ylabB, 5);

    AxisLabelLayout xlabels = new AxisLabelLayout("xlab", xaxis, m_xlabB, 5);
    vis.putAction("xlabels", xlabels);

    int[] palette = new int[] {ColorLib.rgb(150, 150, 255)};

    int[] palette2 = new int[200];

    for (int i = 0; i < 200; i++) {
      palette2[i] = ColorLib.rgba(255, 0, 0, 2 * i);
    }

    /*
    DataColorAction color = new DataColorAction(group, "Party",
            Constants.ORDINAL, VisualItem.STROKECOLOR, palette);
            */

    DataColorAction color2 =
        new DataColorAction(group, "Attendance", Constants.ORDINAL, VisualItem.FILLCOLOR, palette2);

    ActionList draw = new ActionList();
    draw.add(color2);
    draw.add(xaxis);
    draw.add(yaxis);
    draw.add(ylabels);
    draw.add(new RepaintAction());
    vis.putAction("draw", draw);

    ActionList update = new ActionList();
    update.add(xaxis);
    update.add(yaxis);
    update.add(ylabels);
    update.add(new RepaintAction());
    vis.putAction("update", update);

    UpdateListener lstnr =
        new UpdateListener() {
          public void update(Object src) {
            vis.run("update");
          }
        };

    // --------------------------------------------------------------------
    // STEP 4: set up a display and ui components to show the visualization

    m_display = new Display(vis);

    m_display.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
    m_display.setSize(700, 450);
    m_display.setHighQuality(true);
    m_display.addComponentListener(
        new ComponentAdapter() {
          public void componentResized(ComponentEvent e) {
            displayLayout();
          }
        });
    displayLayout();

    m_details = new JFastLabel(m_title);
    m_details.setPreferredSize(new Dimension(75, 20));
    m_details.setVerticalAlignment(SwingConstants.BOTTOM);

    ToolTipControl ttc = new ToolTipControl("label");
    Control hoverc =
        new ControlAdapter() {
          public void itemEntered(VisualItem item, MouseEvent evt) {
            if (item.isInGroup(group)) {
              item.setFillColor(item.getStrokeColor());
              item.setStrokeColor(ColorLib.rgb(0, 0, 0));
              item.getVisualization().repaint();
            }
          }

          public void itemExited(VisualItem item, MouseEvent evt) {
            if (item.isInGroup(group)) {
              item.setFillColor(item.getEndFillColor());
              item.setStrokeColor(item.getEndStrokeColor());
              item.getVisualization().repaint();
            }
          }
        };
    m_display.addControlListener(ttc);
    m_display.addControlListener(hoverc);

    // --------------------------------------------------------------------
    // STEP 5: launching the visualization

    this.addComponentListener(lstnr);

    // details
    Box infoBox = new Box(BoxLayout.X_AXIS);
    infoBox.add(Box.createHorizontalStrut(5));
    infoBox.add(m_details);
    infoBox.add(Box.createHorizontalGlue());
    infoBox.add(Box.createHorizontalStrut(5));
    infoBox.add(Box.createHorizontalStrut(5));

    // create dynamic queries
    Box radioBox = new Box(BoxLayout.X_AXIS);
    radioBox.add(Box.createHorizontalStrut(5));
    radioBox.add(Box.createHorizontalGlue());
    radioBox.add(Box.createHorizontalStrut(5));
    radioBox.add(Box.createHorizontalStrut(16));

    vis.run("draw");
    vis.run("xlabels");

    add(infoBox, BorderLayout.NORTH);
    add(m_display, BorderLayout.CENTER);
    add(radioBox, BorderLayout.SOUTH);
    UILib.setColor(this, ColorLib.getColor(255, 255, 255), Color.GRAY);
    UILib.setFont(radioBox, FontLib.getFont("Tahoma", 15));
    m_details.setFont(FontLib.getFont("Tahoma", 18));
  }
  public PhysioMapRadialGraphView(
      SemGenSettings sets, Graph g, String label, SemSimModel semsimmodel) {
    super(new Visualization());
    this.semsimmodel = semsimmodel;

    // -- set up visualization --
    m_vis.add(tree, g);
    m_vis.setInteractive(treeEdges, null, false);

    // -- set up renderers --
    LabelRenderer m_nodeRenderer = new LabelRenderer(label);
    m_nodeRenderer.setRenderType(AbstractShapeRenderer.RENDER_TYPE_DRAW_AND_FILL);
    m_nodeRenderer.setHorizontalAlignment(Constants.CENTER);
    m_nodeRenderer.setRoundedCorner(8, 8);
    EdgeRenderer m_edgeRenderer =
        new EdgeRenderer(Constants.EDGE_TYPE_LINE, prefuse.Constants.EDGE_ARROW_REVERSE);
    m_edgeRenderer.setArrowType(prefuse.Constants.EDGE_ARROW_REVERSE);
    m_edgeRenderer.setArrowHeadSize(8, 8);

    // MAYBE HERE?
    DefaultRendererFactory rf = new DefaultRendererFactory(m_nodeRenderer);
    rf.add(new InGroupPredicate(treeEdges), m_edgeRenderer);
    m_vis.setRendererFactory(rf);
    // m_vis.

    // -- set up processing actions --
    // colors
    ItemAction nodeColor = new NodeColorAction(treeNodes);
    ItemAction borderColor = new BorderColorAction(treeNodes);
    m_vis.putAction("borderColor", borderColor);
    ItemAction textColor = new TextColorAction(treeNodes);
    m_vis.putAction("textColor", textColor);
    ItemAction edgeColor =
        new ColorAction(treeEdges, VisualItem.STROKECOLOR, ColorLib.rgb(0, 0, 0));
    ItemAction arrowColor = new ArrowColorAction(treeEdges);
    m_vis.putAction("arrowColor", arrowColor);

    FontAction fonts = new FontAction(treeNodes, FontLib.getFont("Verdana", 12));
    fonts.add("ingroup('_focus_')", FontLib.getFont("Verdana", 12));

    // recolor
    // When recolor, do these actions
    ActionList recolor = new ActionList();
    recolor.add(nodeColor);
    recolor.add(borderColor);
    recolor.add(textColor);
    recolor.add(arrowColor);
    m_vis.putAction("recolor", recolor);

    // repaint
    ActionList repaint = new ActionList();
    repaint.add(recolor);
    repaint.add(new RepaintAction());
    m_vis.putAction("repaint", repaint);

    // animate paint change
    ActionList animatePaint = new ActionList(400);
    animatePaint.add(new ColorAnimator(treeNodes));
    animatePaint.add(new RepaintAction());
    m_vis.putAction("animatePaint", animatePaint);

    // create the tree layout action
    RadialTreeLayout treeLayout = new RadialTreeLayout(tree);
    treeLayout.setAutoScale(true);
    m_vis.putAction("treeLayout", treeLayout);

    CollapsedSubtreeLayout subLayout = new CollapsedSubtreeLayout(tree);
    m_vis.putAction("subLayout", subLayout);

    // create the filtering and layout
    ActionList filter = new ActionList();
    filter.add(new TreeRootAction(tree));
    filter.add(fonts);
    filter.add(treeLayout);
    filter.add(borderColor);
    filter.add(subLayout);
    filter.add(textColor);
    filter.add(nodeColor);
    filter.add(edgeColor);
    filter.add(arrowColor);
    m_vis.putAction("filter", filter);

    // animated transition
    ActionList animate = new ActionList(700);
    animate.setPacingFunction(new SlowInSlowOutPacer());
    animate.add(new QualityControlAnimator());
    animate.add(new VisibilityAnimator(tree));
    animate.add(new PolarLocationAnimator(treeNodes, linear));
    animate.add(new ColorAnimator(treeNodes));
    animate.add(new RepaintAction());
    m_vis.putAction("animate", animate);
    m_vis.alwaysRunAfter("filter", "animate");
    // ------------------------------------------------

    // initialize the display

    setSize(sets.getAppWidth() - ExtractorTab.leftpanewidth - 50, sets.getAppHeight() - 235);
    setItemSorter(new TreeDepthItemSorter());
    addControlListener(new DragControl());
    addControlListener(new ZoomToFitControl());
    addControlListener(new ZoomControl());
    addControlListener(new PanControl());
    addControlListener(new FocusControl(1, "filter"));
    addControlListener(new HoverActionControl("repaint"));

    // ------------------------------------------------

    // filter graph and perform layout
    m_vis.run("filter");

    // maintain a set of items that should be interpolated linearly
    // this isn't absolutely necessary, but makes the animations nicer
    // the PolarLocationAnimator should read this set and act accordingly
    m_vis.addFocusGroup(linear, new DefaultTupleSet());
    m_vis
        .getGroup(Visualization.FOCUS_ITEMS)
        .addTupleSetListener(
            new TupleSetListener() {
              public void tupleSetChanged(TupleSet t, Tuple[] add, Tuple[] rem) {
                TupleSet linearInterp = m_vis.getGroup(linear);
                if (add.length < 1) return;
                linearInterp.clear();
                for (Node n = (Node) add[0]; n != null; n = n.getParent()) linearInterp.addTuple(n);
              }
            });

    SearchTupleSet search = new PrefixSearchTupleSet();
    m_vis.addFocusGroup(Visualization.SEARCH_ITEMS, search);
    search.addTupleSetListener(
        new TupleSetListener() {
          public void tupleSetChanged(TupleSet t, Tuple[] add, Tuple[] rem) {
            m_vis.cancel("animatePaint");
            m_vis.run("recolor");
            m_vis.run("animatePaint");
          }
        });
  }
Exemple #7
0
  /*
   * Constructor for the class
   * This is where all the important stuff happens
   */
  public TabularDataVis(Table t) {
    super(new BorderLayout());

    /*
     * Step 1: Setup the Visualization
     */

    // create a new visualization object, and assign it to the global variable
    final Visualization vis = new Visualization();
    g_vis = vis;

    // create a visual abstraction of the table data (loaded in the buildFrame method)
    // call our data "canUrban"
    VisualTable vt = vis.addTable("canUrban", t);

    // add a new column containing a label string showing
    // the Geographic name and population
    // note: uses the prefuse expression language
    vt.addColumn(
        "label", "CONCAT([Geographic name], ' (Population: ', FORMAT([2006 Population],0), ')')");

    // add a new column that divides the provinces by their geographic location (derived values)
    // note: uses the prefuse expression language
    vt.addColumn(
        "geographic location",
        "IF ([Province]='BC') THEN 1 ELSE "
            + "(IF ([Province] = 'AB' OR [Province] = 'SK' OR [Province] = 'MB') THEN 2 ELSE "
            + "(IF ([Province] = 'ON' OR [Province] = 'QC') THEN 3 ELSE"
            + "(IF ([Province] = 'NS' OR [Province] = 'NB' OR [Province] = 'PE' OR [Province] = 'NL') THEN 4 ELSE 5)))");

    // add a new column that converts the population data to ordinal data (derived values)
    // note: uses the prefuse expression language
    vt.addColumn(
        "population ordinal",
        "IF ([2006 Population] > 5000000) THEN 7 ELSE "
            + "(IF ([2006 Population] > 1000000) THEN 6 ELSE "
            + "(IF ([2006 Population] > 250000) THEN 5 ELSE "
            + "(IF ([2006 Population] > 100000) THEN 4 ELSE "
            + "(IF ([2006 Population] > 50000) THEN 3 ELSE "
            + "(IF ([2006 Population] > 20000) THEN 2 ELSE 1)))))");

    // create a new renderer factory for drawing the visual items
    vis.setRendererFactory(
        new RendererFactory() {

          // specify the default shape renderer (the actions will decide how to actually render the
          // visual elements)
          AbstractShapeRenderer sr = new ShapeRenderer();
          // renderers for the axes
          Renderer arY = new AxisRenderer(Constants.RIGHT, Constants.TOP);
          Renderer arX = new AxisRenderer(Constants.CENTER, Constants.FAR_BOTTOM);

          // return the appropriate renderer for a given visual item
          public Renderer getRenderer(VisualItem item) {
            return item.isInGroup("ylab") ? arY : item.isInGroup("xlab") ? arX : sr;
          }
        });

    /*
     * Step 2: Add X-Axis
     */

    // add the x-axis
    AxisLayout xaxis =
        new AxisLayout("canUrban", "Province", Constants.X_AXIS, VisiblePredicate.TRUE);

    // ensure the axis spans the width of the data container
    xaxis.setLayoutBounds(g_dataB);

    // add the labels to the x-axis
    AxisLabelLayout xlabels = new AxisLabelLayout("xlab", xaxis, g_xlabB, 15);

    /*
     * Step 3: Add the Y-Axis and its dynamic query feature
     */

    // dynamic query based on population data
    RangeQueryBinding populationQ = new RangeQueryBinding(vt, "2006 Population");
    AndPredicate filter = new AndPredicate(populationQ.getPredicate());

    // add the y-axis
    AxisLayout yaxis =
        new AxisLayout("canUrban", "2006 Population", Constants.Y_AXIS, VisiblePredicate.TRUE);

    // set the range controls on the y-axis
    yaxis.setRangeModel(populationQ.getModel());
    populationQ.getNumberModel().setValueRange(0, 6000000, 0, 6000000);

    // ensure the y-axis spans the height of the data container
    yaxis.setLayoutBounds(g_dataB);

    // add the labels to the y-axis
    AxisLabelLayout ylabels = new AxisLabelLayout("ylab", yaxis, g_ylabB);
    NumberFormat nf = NumberFormat.getIntegerInstance();
    nf.setMaximumFractionDigits(0);
    ylabels.setNumberFormat(nf);

    /*
     * Step 4: Add the search box
     */

    // dynamic query based on Geographic name data
    SearchQueryBinding searchQ = new SearchQueryBinding(vt, "Geographic name");
    filter.add(searchQ.getPredicate()); // reuse the same filter as the population query

    /*
     * Step 5: Colours and Shapes
     */

    // assign a set of five perceptually distinct colours to assign to the provinces
    // chosen from ColorBrewer (5-class qualitative Set1)
    int[] palette =
        new int[] {
          ColorLib.rgb(77, 175, 74),
          ColorLib.rgb(55, 126, 184),
          ColorLib.rgb(228, 26, 28),
          ColorLib.rgb(152, 78, 163),
          ColorLib.rgb(255, 127, 0)
        };

    // specify the stroke (exterior line) based on the ordinal data
    DataColorAction color =
        new DataColorAction(
            "canUrban", "geographic location", Constants.ORDINAL, VisualItem.STROKECOLOR, palette);

    // specify the fill (interior) as a static colour (white)
    ColorAction fill = new ColorAction("canUrban", VisualItem.FILLCOLOR, 0);

    // represent all the data points with rectangles
    ShapeAction shape = new ShapeAction("canUrban", Constants.SHAPE_RECTANGLE);

    // assign the size of the visual element based on the population data (we
    // converted the 2006 Population data to ordinal values)
    DataSizeAction size = new DataSizeAction("canUrban", "population ordinal");

    // setup a counter to keep track of which data points are currently being viewed
    Counter cntr = new Counter("canUrban");

    /*
     * Step 6: Create the action list for drawing the visual elements
     */

    ActionList draw = new ActionList();
    draw.add(cntr);
    draw.add(color);
    draw.add(fill);
    draw.add(shape);
    draw.add(size);
    draw.add(xaxis);
    draw.add(yaxis);
    draw.add(ylabels);
    draw.add(new RepaintAction());
    vis.putAction("draw", draw);
    vis.putAction("xlabels", xlabels);

    /*
     * create the action list for updating the visual elements
     * (during interactive operations and re-sizing of the window)
     */
    ActionList update = new ActionList();
    update.add(new VisibilityFilter("canUrban", filter)); // filter performs the size/name filtering
    update.add(cntr);
    update.add(xaxis);
    update.add(yaxis);
    update.add(ylabels);
    update.add(new RepaintAction());
    vis.putAction("update", update);

    // create an update listener that will update the visualization when fired
    UpdateListener lstnr =
        new UpdateListener() {

          public void update(Object src) {
            vis.run("update");
          }
        };

    // add this update listener to the filter, so that when the filter changes (i.e.,
    // the user adjusts the axis parameters, or enters a name for filtering), the
    // visualization is updated
    filter.addExpressionListener(lstnr);

    /*
     * Step 7: Setup the Display and the other Interface components
     * (scroll bar, query box, tool tips)
     */

    // create the display
    g_display = new Display(vis);

    // set the display properties
    g_display.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
    g_display.setSize(700, 450);
    g_display.setHighQuality(true);

    // call the function that sets the sizes of the containers that contain
    // the data and the axes
    displayLayout();

    // whenever the window is re-sized, update the layout of the axes
    g_display.addComponentListener(
        new ComponentAdapter() {

          public void componentResized(ComponentEvent e) {
            displayLayout();
          }
        });

    // title label (top left)
    JFastLabel g_details = new JFastLabel("Canadian Urban Population");
    g_details.setPreferredSize(new Dimension(350, 20));
    g_details.setVerticalAlignment(SwingConstants.BOTTOM);

    // total label (top right)
    g_total.setPreferredSize(new Dimension(350, 20));
    g_total.setHorizontalAlignment(SwingConstants.RIGHT);
    g_total.setVerticalAlignment(SwingConstants.BOTTOM);

    // tool tips
    ToolTipControl ttc = new ToolTipControl("label");
    Control hoverc =
        new ControlAdapter() {

          public void itemEntered(VisualItem item, MouseEvent evt) {
            if (item.isInGroup("canUrban")) {
              g_total.setText(item.getString("label"));
              item.setFillColor(item.getStrokeColor());
              item.setStrokeColor(ColorLib.rgb(0, 0, 0));
              item.getVisualization().repaint();
            }
          }

          public void itemExited(VisualItem item, MouseEvent evt) {
            if (item.isInGroup("canUrban")) {
              g_total.setText(g_totalStr);
              item.setFillColor(item.getEndFillColor());
              item.setStrokeColor(item.getEndStrokeColor());
              item.getVisualization().repaint();
            }
          }
        };
    g_display.addControlListener(ttc);
    g_display.addControlListener(hoverc);

    // vertical slider for adjusting the population filter
    JRangeSlider slider = populationQ.createVerticalRangeSlider();
    slider.setThumbColor(null);
    slider.setToolTipText("drag the arrows to filter the data");
    // smallest window: 200,000
    slider.setMinExtent(200000);
    slider.addMouseListener(
        new MouseAdapter() {

          public void mousePressed(MouseEvent e) {
            g_display.setHighQuality(false);
          }

          public void mouseReleased(MouseEvent e) {
            g_display.setHighQuality(true);
            g_display.repaint();
          }
        });

    // search box
    JSearchPanel searcher = searchQ.createSearchPanel();
    searcher.setLabelText("Urban Centre: ");
    searcher.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 0));

    /*
     * Step 8: Create Containers for the Interface Elements
     */

    // add the listener to this component
    this.addComponentListener(lstnr);

    // container for elements at the top of the screen
    Box topContainer = new Box(BoxLayout.X_AXIS);
    topContainer.add(Box.createHorizontalStrut(5));
    topContainer.add(g_details);
    topContainer.add(Box.createHorizontalGlue());
    topContainer.add(Box.createHorizontalStrut(5));
    topContainer.add(g_total);
    topContainer.add(Box.createHorizontalStrut(5));

    // container for elements at the bottom of the screen
    Box bottomContainer = new Box(BoxLayout.X_AXIS);
    bottomContainer.add(Box.createHorizontalStrut(5));
    bottomContainer.add(searcher);
    bottomContainer.add(Box.createHorizontalGlue());
    bottomContainer.add(Box.createHorizontalStrut(5));
    bottomContainer.add(Box.createHorizontalStrut(16));

    // fonts, colours, etc.
    UILib.setColor(this, ColorLib.getColor(255, 255, 255), Color.GRAY);
    slider.setForeground(Color.LIGHT_GRAY);
    UILib.setFont(bottomContainer, FontLib.getFont("Tahoma", 15));
    g_details.setFont(FontLib.getFont("Tahoma", 18));
    g_total.setFont(FontLib.getFont("Tahoma", 16));

    // add the containers to the JPanel
    add(topContainer, BorderLayout.NORTH);
    add(g_display, BorderLayout.CENTER);
    add(slider, BorderLayout.EAST);
    add(bottomContainer, BorderLayout.SOUTH);

    /*
     * Step 9: Start the Visualization
     */

    vis.run("draw");
    vis.run("xlabels");
  }