/**
   * This method should be called whenever a new set of histogram values is to be displayed (i.e.
   * when a different image gets focus).
   *
   * @param histogramData
   */
  public void setHistogramData(final HistogramDataGroup histogramData) {
    double[] minMaxView;
    double[] minMaxLUT;
    synchronized (_synchObject) {
      _histogramDataGroup = histogramData;
      _histogramDataGroup.setListener(new HistogramDataListener());
      minMaxView = _histogramDataGroup.getMinMaxView();
      minMaxLUT = _histogramDataGroup.getMinMaxLUT();
    }

    //		IJ.log("----");
    //		IJ.log("setHistogramData");
    //		IJ.log("view " + minMaxView[0] + " "  + minMaxView[1] + " lut " + minMaxLUT[0] + " " +
    // minMaxLUT[1]);
    //		IJ.log("----");

    if (null != _frame) {
      if (_frame.isVisible()) {
        _frame.setVisible(true);
      }
      _frame.setTitle(histogramData.getTitle());

      _histogramPanel.setStatistics(histogramData.getStatistics(WIDTH));

      final boolean autoRange = histogramData.getAutoRange();
      if (autoRange) {
        // turn cursors off
        _histogramPanel.setCursors(null, null);
      } else {
        // set cursors to edges
        _histogramPanel.setCursors(INSET, INSET + WIDTH - 1);
      }
      _uiPanel.setAutoRange(autoRange);
      _uiPanel.setExcludePixels(histogramData.getExcludePixels());
      _uiPanel.setCombineChannels(histogramData.getCombineChannels());
      _uiPanel.setDisplayChannels(histogramData.getDisplayChannels());
      _uiPanel.enableChannels(histogramData.hasChannels());
      _uiPanel.setMinMaxLUT(minMaxLUT[0], minMaxLUT[1]);

      _colorBarPanel.setMinMax(minMaxView[0], minMaxView[1], minMaxLUT[0], minMaxLUT[1]);
    }
  }
  // TODO TIDY THIS UP do we need "reset cursor positions"
  private void zoomToLUT() {
    final double minMaxLUT[] = _histogramDataGroup.getMinMaxLUT();
    final double minLUT = minMaxLUT[0];
    final double maxLUT = minMaxLUT[1];

    // zoom to fit current min/max LUT settings
    final double minView = minLUT;
    final double maxView = maxLUT;

    changed(minView, maxView, minLUT, maxLUT);

    // reset cursor positions
    _histogramPanel.resetCursors();
  }
  /*
   * Updates histogram and color bar during the fit.
   */
  private void changed(
      final double minView, final double maxView, final double minLUT, final double maxLUT) {
    synchronized (_synchObject) {
      // TODO ARG added this 9/27 to change hDG internal minMaxViews
      _histogramDataGroup.setMinMaxView(minView, maxView);
      _histogramPanel.setStatistics(_histogramDataGroup.getStatistics(WIDTH));
      _colorBarPanel.setMinMax(minView, maxView, minLUT, maxLUT);
      // TODO changed is currently called from two places:
      // i) the HistogramData listener will call it periodically during the
      // fit.
      // ii) if the user types in a new LUT range this gets called.
      // iii) in the future more UI interactions will wind up here
      //
      // TODO if the user drags a new LUT range this doesn't get called!

      // IJ.log("changed min/maxView " + minView + " " + maxView +
      // " min/maxLUT " + minLUT + " " + maxLUT);

      _histogramDataGroup.redisplay();
    }
  }
  /**
   * Initializer, handles layout and wiring. Called when set of images is created.
   *
   * @param hasChannels
   */
  public void show(final boolean hasChannels) {
    if (null == _frame || !_frame.isShowing()) {
      // create the histogram and color bar display panels
      _histogramPanel = new HistogramPanel(WIDTH, INSET, HISTOGRAM_HEIGHT);
      _histogramPanel.setListener(new HistogramPanelListener());
      _colorBarPanel = new ColorBarPanel(WIDTH, INSET, COLORBAR_HEIGHT);
      _colorBarPanel.setLUT(getLUT());

      _uiPanel = new HistogramUIPanel(hasChannels);
      _uiPanel.setListener(new UIPanelListener());

      _frame = new JFrame("Histogram");
      // _frame.setResizable(false);
      _frame.setLayout(new BorderLayout());

      final JPanel panel = new JPanel();
      panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
      panel.add(_colorBarPanel);
      panel.add(_uiPanel);
      _frame.getContentPane().add(_histogramPanel, BorderLayout.CENTER);
      _frame.getContentPane().add(panel, BorderLayout.SOUTH);
      _frame.pack();
      _frame.setVisible(true);
      // IJ.log("initial size " + _frame.getSize());
      _frame.addComponentListener(
          new ComponentListener() {

            @Override
            public void componentHidden(final ComponentEvent e) {}

            @Override
            public void componentMoved(final ComponentEvent e) {}

            @Override
            public void componentResized(final ComponentEvent e) {
              // constrain maximum size
              boolean resize = false;
              final Dimension size = _frame.getSize();
              if (size.width != (SET_WIDTH)) {
                size.width = SET_WIDTH;
                resize = true;
              }
              if (size.height > MAX_HEIGHT) {
                size.height = MAX_HEIGHT;
                resize = true;
              }
              if (size.height < MIN_HEIGHT) {
                size.height = MIN_HEIGHT;
                resize = true;
              }
              if (resize) {
                _frame.setSize(size);
              }
              saveSizeInPreferences(size);
            }

            @Override
            public void componentShown(final ComponentEvent e) {}
          });
      _frame.setSize(getSizeFromPreferences());
    }
  }