/*------------------------------------------------------------------------------
 src/lib/djWidget/imageIoDpxSaveWidget.cxx
 
 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "djImageIoDpxWidget.h"
#include <djLabelWidget.h>
#include <djGroupBoxWidget.h>
#include <djButtonWidget.h>
#include <djSliderWidget.h>
#include <djNumWidget.h>

namespace dj {
namespace ImageIoDpx {

SaveWidget::SaveWidget() :
  _callbacks(true)
{
  GroupBoxWidget * colorGroup = new GroupBoxWidget("Color Transfer");
  _colorWidget = new EnumWidget<COLOR>(colorStr());
  _colorWidget->alignPolicy(LEFT, CENTER);
  GroupBoxWidget * printGroup = new GroupBoxWidget("Print Options");
  LabelWidget * printBlackLabel = new LabelWidget("Black point:");
  _printBlackWidget = new IntWidget;
  _printBlackWidget->range(0, 1023);
  _printBlackSlider = new FloatSliderWidget;
  LabelWidget * printWhiteLabel = new LabelWidget("White point:");
  _printWhiteWidget = new IntWidget;
  _printWhiteWidget->range(0, 1023);
  _printWhiteSlider = new FloatSliderWidget;
  LabelWidget * printGammaLabel = new LabelWidget("Gamma:");
  _printGammaWidget = new FloatWidget;
  _printGammaSlider = new FloatSliderWidget;
  _printGammaSlider->range(0.0, 2.2);
  GroupBoxWidget * optionsGroup = new GroupBoxWidget("Options");
  LabelWidget * bitDepthLabel = new LabelWidget("Bit depth:");
  _bitDepthWidget = new EnumWidget<BIT_DEPTH>(bitDepthStr());
  LabelWidget * channelsLabel = new LabelWidget("Channels:");
  _channelsWidget = new EnumWidget<CHANNELS>(channelsStr());
  _packWidget = new CheckButtonWidget("Pack pixels.");
  _packWidget->alignPolicy(LEFT, CENTER);
  LabelWidget * endianLabel = new LabelWidget("Endian:");
  _endianWidget = new EnumWidget<ENDIAN>(endianStr());
  
  List<LabelWidget *> labelList;
  labelList += bitDepthLabel;
  labelList += channelsLabel;
  labelList += endianLabel;
  bitDepthLabel->labelGroup(labelList);
  channelsLabel->labelGroup(labelList);
  endianLabel->labelGroup(labelList);
  
  VLayout * layout = new VLayout(this);
  layout->add(colorGroup);
  colorGroup->layout()->add(_colorWidget);
  layout->add(printGroup);
  printGroup->layout()->add(printBlackLabel);
  HLayout * subLayout = new HLayout(printGroup->layout());
  subLayout->margin(0);
  subLayout->add(_printBlackWidget);
  subLayout->add(_printBlackSlider);
  printGroup->layout()->add(printWhiteLabel);
  subLayout = new HLayout(printGroup->layout());
  subLayout->margin(0);
  subLayout->add(_printWhiteWidget);
  subLayout->add(_printWhiteSlider);
  printGroup->layout()->add(printGammaLabel);
  subLayout = new HLayout(printGroup->layout());
  subLayout->margin(0);
  subLayout->add(_printGammaWidget);
  subLayout->add(_printGammaSlider);
  layout->add(optionsGroup);
  subLayout = new HLayout(optionsGroup->layout());
  subLayout->margin(0);
  subLayout->add(bitDepthLabel);
  subLayout->add(_bitDepthWidget);
  subLayout = new HLayout(optionsGroup->layout());
  subLayout->margin(0);
  subLayout->add(channelsLabel);
  subLayout->add(_channelsWidget);
  optionsGroup->layout()->add(_packWidget);
  subLayout = new HLayout(optionsGroup->layout());
  subLayout->margin(0);
  subLayout->add(endianLabel);
  subLayout->add(_endianWidget);
  layout->stretchAdd();
  
  widgetUpdate();
  
  _colorWidget->sig().set(this, colorCallback);
  _printBlackWidget->sig().set(this, printBlackCallback);
  _printBlackSlider->sig().set(this, printBlackCallback);
  _printWhiteWidget->sig().set(this, printWhiteCallback);
  _printWhiteSlider->sig().set(this, printWhiteCallback);
  _printGammaWidget->sig().set(this, printGammaCallback);
  _printGammaSlider->sig().set(this, printGammaCallback);
  _bitDepthWidget->sig().set(this, bitDepthCallback);
  _channelsWidget->sig().set(this, channelsCallback);
  _packWidget->sig().set(this, packCallback);
  _endianWidget->sig().set(this, endianCallback);
}

void SaveWidget::set(ImageSave * in)
{
  ImageSaveWidget::set(in);
  widgetUpdate();
}

void SaveWidget::widgetUpdate()
{
  _callbacks = false;
  
  COLOR color = COLOR(0);
  double printBlack = 0.0, printWhite = 0.0, printGamma = 0.0;
  BIT_DEPTH bitDepth = BIT_DEPTH(0);
  CHANNELS channels = CHANNELS(0);
  bool pack = false;
  ENDIAN endian = ENDIAN(0);
  if (_save) {
    StrList data = _save->attr(saveAttrStr()[Save::ATTR_COLOR]);
    inflateStr(data, &color, colorStr());
    data = _save->attr(saveAttrStr()[Save::ATTR_PRINT_BLACK]);
    inflateStr(data, &printBlack);
    data = _save->attr(saveAttrStr()[Save::ATTR_PRINT_WHITE]);
    inflateStr(data, &printWhite);
    data = _save->attr(saveAttrStr()[Save::ATTR_PRINT_GAMMA]);
    inflateStr(data, &printGamma);
    data = _save->attr(saveAttrStr()[Save::ATTR_BIT_DEPTH]);
    inflateStr(data, &bitDepth, bitDepthStr());
    data = _save->attr(saveAttrStr()[Save::ATTR_CHANNELS]);
    inflateStr(data, &channels, channelsStr());
    data = _save->attr(saveAttrStr()[Save::ATTR_PACK]);
    inflateStr(data, &pack);
    data = _save->attr(saveAttrStr()[Save::ATTR_ENDIAN]);
    inflateStr(data, &endian, endianStr());
  }
  _colorWidget->set(color);
  _printBlackWidget->set(int(printBlack * 1023.0 + 0.5));
  _printBlackSlider->set(printBlack);
  _printWhiteWidget->set(int(printWhite * 1023.0 + 0.5));
  _printWhiteSlider->set(printWhite);
  _printGammaWidget->set(printGamma);
  _printGammaSlider->set(printGamma);
  _bitDepthWidget->set(bitDepth);
  _channelsWidget->set(channels);
  _packWidget->set(pack);
  _endianWidget->set(endian);
  
  _callbacks = true;
}

void SaveWidget::colorCallback(COLOR in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_COLOR], deflateStr(in, colorStr()));
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::printBlackCallback(double in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_PRINT_BLACK], deflateStr(in));
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::printBlackCallback(int in) { printBlackCallback(in / 1023.0); }

void SaveWidget::printWhiteCallback(double in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_PRINT_WHITE], deflateStr(in));
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::printWhiteCallback(int in) { printWhiteCallback(in / 1023.0); }

void SaveWidget::printGammaCallback(double in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_PRINT_GAMMA], deflateStr(in));
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::bitDepthCallback(BIT_DEPTH in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(
    saveAttrStr()[Save::ATTR_BIT_DEPTH], deflateStr(in, bitDepthStr())
  );
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::channelsCallback(CHANNELS in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(
    saveAttrStr()[Save::ATTR_CHANNELS], deflateStr(in, channelsStr())
  );
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::packCallback(bool in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_PACK], deflateStr(in));
  sig().emit(true);
  widgetUpdate();
}

void SaveWidget::endianCallback(ENDIAN in)
{
  if (! _callbacks || ! _save) return;
  _save->attr(saveAttrStr()[Save::ATTR_ENDIAN], deflateStr(in, endianStr()));
  sig().emit(true);
  widgetUpdate();
}

}
}
