Exemple #1
0
 /** @see prefuse.render.Renderer#render(java.awt.Graphics2D, prefuse.visual.VisualItem) */
 @Override
 public void render(Graphics2D g, VisualItem item) {
   // render the edge line
   super.render(g, item);
   // render the edge arrow head, if appropriate
   if (m_curArrow != null) {
     g.setPaint(ColorLib.getColor(item.getFillColor()));
     g.fill(m_curArrow);
   }
 }
    /** @see prefuse.render.Renderer#render(java.awt.Graphics2D, prefuse.visual.VisualItem) */
    @Override
    public void render(Graphics2D g, VisualItem item) {
      Shape s = getShape(item);
      GraphicsLib.paint(g, item, m_line, getStroke(item), getRenderType(item));

      // check if we have a text label, if so, render it
      String str;
      if (item.canGetString(VisualItem.LABEL)) {
        str = (String) item.getString(VisualItem.LABEL);
        if (str != null && !str.equals("")) {
          float x = (float) m_box.getMinX();
          float y = (float) m_box.getMinY() + m_ascent;

          // draw label background
          GraphicsLib.paint(g, item, s, null, RENDER_TYPE_FILL);

          AffineTransform origTransform = g.getTransform();
          AffineTransform transform = this.getTransform(item);
          if (transform != null) {
            g.setTransform(transform);
          }

          g.setFont(item.getFont());
          g.setColor(ColorLib.getColor(item.getTextColor()));

          if (!(str.length() > 5
              && str.substring(str.length() - 5, str.length()).equals("_last"))) {

            g.setColor(Color.WHITE);
            // TODO properly hunt down source of null str! for now, triage
            if (str != null) {
              // bump y down by appropriate amount
              FontMetrics fm = g.getFontMetrics(item.getFont());
              int strHeight = fm.getAscent();
              //                        g.drawString(str, x, y);
              g.drawString(str, x, y + strHeight);
            }

            if (transform != null) {
              g.setTransform(origTransform);
            }
          }
        }
      }
    }
 public void renderText(Graphics2D g, VisualItem item, Shape shape) {
   String s = getText(item);
   int textColor = item.getTextColor();
   if (s != null) {
     Rectangle2D r = shape.getBounds2D();
     g.setPaint(ColorLib.getColor(textColor));
     g.setFont(m_font);
     FontMetrics fm = g.getFontMetrics();
     double size = item.getSize();
     double x = r.getX() + size * m_horizBorder;
     double y = r.getY() + size * m_vertBorder;
     g.drawString(s, (float) x, (float) y + fm.getAscent());
     // if ( isHyperlink(item) ) {
     // int lx = (int)Math.round(x), ly = (int)Math.round(y);
     // g.drawLine(lx,ly,lx+fm.stringWidth(s),ly+fm.getHeight()-1);
     // }
   }
 }
  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);
        }
      }
    }
Exemple #6
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));
  }
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");
  }