/** ***************************************************************************** */
  BddtHistoryBubble(BddtLaunchControl ctrl, BddtHistoryData hd) {
    history_data = hd;
    for_control = ctrl;
    history_graph = null;
    last_update = 0;
    update_needed = true;
    restart_needed = true;
    x_scale = 1;
    y_scale = 1;
    thread_colors = new HashMap<BumpThread, Color>();
    type_strokes = new EnumMap<LinkType, Stroke>(LinkType.class);
    type_strokes.put(
        LinkType.ENTER,
        new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, DOTTED, 0));
    type_strokes.put(
        LinkType.RETURN,
        new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1.0f, DASHED, 0));
    type_strokes.put(LinkType.NEXT, new BasicStroke(1));
    arrow_stroke = new BasicStroke(1);

    updateGraph();

    hd.addHistoryListener(this);

    setupPanel();

    draw_area.addMouseListener(new FocusOnEntry());
  }
  /** ***************************************************************************** */
  private void updateGraph() {
    synchronized (this) {
      update_needed = false;
      if (restart_needed || history_graph == null) {
        history_graph = new HistoryGraph();
        last_update = 0;
        restart_needed = false;
      }
    }

    synchronized (history_graph) {
      for (BumpThread bt : history_data.getThreads()) {
        history_graph.addThreadItems(history_data.getItems(bt), last_update);
      }
      last_update = history_graph.finishBuild();
    }
  }
 protected void localDispose() {
   history_data.removeHistoryListener(this);
 }