/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#include "tp_SeriesToAxis.hxx"
#include "tp_SeriesToAxis.hrc"

#include "ResId.hxx"
#include "chartview/ChartSfxItemIds.hxx"
#include "NoWarningThisInCTOR.hxx"

// header for class SfxBoolItem
#include <svl/eitem.hxx>
// header for SfxInt32Item
#include <svl/intitem.hxx>
//SfxIntegerListItem
#include <svl/ilstitem.hxx>
#include <svtools/controldims.hrc>

#include <com/sun/star/chart/MissingValueTreatment.hpp>

//.............................................................................
namespace chart
{
//.............................................................................

SchOptionTabPage::SchOptionTabPage(Window* pWindow,const SfxItemSet& rInAttrs) :
    SfxTabPage(pWindow, SchResId(TP_OPTIONS), rInAttrs),
    aGrpAxis(this, SchResId(GRP_OPT_AXIS)),
    aRbtAxis1(this,SchResId(RBT_OPT_AXIS_1)),
    aRbtAxis2(this,SchResId(RBT_OPT_AXIS_2)),

    aGrpBar(this, SchResId(GB_BAR)),
    aFTGap(this,SchResId(FT_GAP)),
    aMTGap(this,SchResId(MT_GAP)),
    aFTOverlap(this,SchResId(FT_OVERLAP)),
    aMTOverlap(this,SchResId(MT_OVERLAP)),
    aCBConnect(this,SchResId(CB_CONNECTOR)),
    aCBAxisSideBySide(this,SchResId(CB_BARS_SIDE_BY_SIDE)),
    m_aFL_PlotOptions(this,SchResId(FL_PLOT_OPTIONS)),
    m_aFT_MissingValues(this,SchResId(FT_MISSING_VALUES)),
    m_aRB_DontPaint(this,SchResId(RB_DONT_PAINT)),
    m_aRB_AssumeZero(this,SchResId(RB_ASSUME_ZERO)),
    m_aRB_ContinueLine(this,SchResId(RB_CONTINUE_LINE)),
    m_aCBIncludeHiddenCells(this,SchResId(CB_INCLUDE_HIDDEN_CELLS)),
    m_bProvidesSecondaryYAxis(true),
    m_bProvidesOverlapAndGapWidth(false)
{
    FreeResource();

    aRbtAxis1.SetClickHdl( LINK( this, SchOptionTabPage, EnableHdl ));
    aRbtAxis2.SetClickHdl( LINK( this, SchOptionTabPage, EnableHdl ));
}

SchOptionTabPage::~SchOptionTabPage()
{
}

IMPL_LINK_NOARG(SchOptionTabPage, EnableHdl)
{
    if( m_nAllSeriesAxisIndex == 0 )
        aCBAxisSideBySide.Enable( aRbtAxis2.IsChecked());
    else if( m_nAllSeriesAxisIndex == 1 )
        aCBAxisSideBySide.Enable( aRbtAxis1.IsChecked());

    return 0;
}

SfxTabPage* SchOptionTabPage::Create(Window* pWindow,const SfxItemSet& rOutAttrs)
{
    return new SchOptionTabPage(pWindow, rOutAttrs);
}

sal_Bool SchOptionTabPage::FillItemSet(SfxItemSet& rOutAttrs)
{
    if(aRbtAxis2.IsChecked())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_SECONDARY_Y));
    else
        rOutAttrs.Put(SfxInt32Item(SCHATTR_AXIS,CHART_AXIS_PRIMARY_Y));

    if(aMTGap.IsVisible())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_BAR_GAPWIDTH,static_cast< sal_Int32 >( aMTGap.GetValue())));

    if(aMTOverlap.IsVisible())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_BAR_OVERLAP,static_cast< sal_Int32 >( aMTOverlap.GetValue())));

    if(aCBConnect.IsVisible())
        rOutAttrs.Put(SfxBoolItem(SCHATTR_BAR_CONNECT,aCBConnect.IsChecked()));

    // model property is "group bars per axis", UI feature is the other way
    // round: "show bars side by side"
    if(aCBAxisSideBySide.IsVisible())
        rOutAttrs.Put(SfxBoolItem(SCHATTR_GROUP_BARS_PER_AXIS, ! aCBAxisSideBySide.IsChecked()));

    if(m_aRB_DontPaint.IsChecked())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP));
    else if(m_aRB_AssumeZero.IsChecked())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,::com::sun::star::chart::MissingValueTreatment::USE_ZERO));
    else if(m_aRB_ContinueLine.IsChecked())
        rOutAttrs.Put(SfxInt32Item(SCHATTR_MISSING_VALUE_TREATMENT,::com::sun::star::chart::MissingValueTreatment::CONTINUE));

    if (m_aCBIncludeHiddenCells.IsVisible())
        rOutAttrs.Put(SfxBoolItem(SCHATTR_INCLUDE_HIDDEN_CELLS, m_aCBIncludeHiddenCells.IsChecked()));

    return sal_True;
}

void SchOptionTabPage::Reset(const SfxItemSet& rInAttrs)
{
    const SfxPoolItem *pPoolItem = NULL;

    aRbtAxis1.Check(sal_True);
    aRbtAxis2.Check(sal_False);
    if (rInAttrs.GetItemState(SCHATTR_AXIS,sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        long nVal=((const SfxInt32Item*)pPoolItem)->GetValue();
        if(nVal==CHART_AXIS_SECONDARY_Y)
        {
            aRbtAxis2.Check(sal_True);
            aRbtAxis1.Check(sal_False);
        }
    }

    long nTmp;
    if (rInAttrs.GetItemState(SCHATTR_BAR_GAPWIDTH, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        nTmp = (long)((const SfxInt32Item*)pPoolItem)->GetValue();
        aMTGap.SetValue(nTmp);
    }

    if (rInAttrs.GetItemState(SCHATTR_BAR_OVERLAP, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        nTmp = (long)((const SfxInt32Item*)pPoolItem)->GetValue();
        aMTOverlap.SetValue(nTmp);
    }

    if (rInAttrs.GetItemState(SCHATTR_BAR_CONNECT, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        sal_Bool bCheck = static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
        aCBConnect.Check(bCheck);
    }

    if (rInAttrs.GetItemState(SCHATTR_AXIS_FOR_ALL_SERIES, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        m_nAllSeriesAxisIndex = static_cast< const SfxInt32Item * >( pPoolItem )->GetValue();
        aCBAxisSideBySide.Disable();
    }
    if (rInAttrs.GetItemState(SCHATTR_GROUP_BARS_PER_AXIS, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        // model property is "group bars per axis", UI feature is the other way
        // round: "show bars side by side"
        sal_Bool bCheck = ! static_cast< const SfxBoolItem * >( pPoolItem )->GetValue();
        aCBAxisSideBySide.Check( bCheck );
    }
    else
    {
        aCBAxisSideBySide.Show(sal_False);
    }


    //missing value treatment
    {
        ::com::sun::star::uno::Sequence < sal_Int32 > aMissingValueTreatments;
        if( rInAttrs.GetItemState(SCHATTR_AVAILABLE_MISSING_VALUE_TREATMENTS, sal_True, &pPoolItem) == SFX_ITEM_SET )
            aMissingValueTreatments =((const SfxIntegerListItem*)pPoolItem)->GetConstSequence();

        if ( aMissingValueTreatments.getLength()>1 && rInAttrs.GetItemState(SCHATTR_MISSING_VALUE_TREATMENT,sal_True, &pPoolItem) == SFX_ITEM_SET)
        {
            m_aRB_DontPaint.Enable(sal_False);
            m_aRB_AssumeZero.Enable(sal_False);
            m_aRB_ContinueLine.Enable(sal_False);

            for( sal_Int32 nN =0; nN<aMissingValueTreatments.getLength(); nN++ )
            {
                sal_Int32 nVal = aMissingValueTreatments[nN];
                if(nVal==::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
                    m_aRB_DontPaint.Enable(sal_True);
                else if(nVal==::com::sun::star::chart::MissingValueTreatment::USE_ZERO)
                    m_aRB_AssumeZero.Enable(sal_True);
                else if(nVal==::com::sun::star::chart::MissingValueTreatment::CONTINUE)
                    m_aRB_ContinueLine.Enable(sal_True);
            }

            long nVal=((const SfxInt32Item*)pPoolItem)->GetValue();
            if(nVal==::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP)
                m_aRB_DontPaint.Check(sal_True);
            else if(nVal==::com::sun::star::chart::MissingValueTreatment::USE_ZERO)
                m_aRB_AssumeZero.Check(sal_True);
            else if(nVal==::com::sun::star::chart::MissingValueTreatment::CONTINUE)
                m_aRB_ContinueLine.Check(sal_True);
        }
        else
        {
            m_aFT_MissingValues.Show(sal_False);
            m_aRB_DontPaint.Show(sal_False);
            m_aRB_AssumeZero.Show(sal_False);
            m_aRB_ContinueLine.Show(sal_False);
        }
    }

    // Include hidden cells
    if (rInAttrs.GetItemState(SCHATTR_INCLUDE_HIDDEN_CELLS, sal_True, &pPoolItem) == SFX_ITEM_SET)
    {
        bool bVal = static_cast<const SfxBoolItem*>(pPoolItem)->GetValue();
        m_aCBIncludeHiddenCells.Check(bVal);
    }
    else
    {
        m_aCBIncludeHiddenCells.Show(sal_False);
        if(!m_aFT_MissingValues.IsVisible())
            m_aFL_PlotOptions.Show(sal_False);
    }

    AdaptControlPositionsAndVisibility();
}

void SchOptionTabPage::Init( bool bProvidesSecondaryYAxis, bool bProvidesOverlapAndGapWidth, bool bProvidesBarConnectors )
{
    m_bProvidesSecondaryYAxis = bProvidesSecondaryYAxis;
    m_bProvidesOverlapAndGapWidth = bProvidesOverlapAndGapWidth;
    m_bProvidesBarConnectors = bProvidesBarConnectors;

    AdaptControlPositionsAndVisibility();
}

void lcl_offsetControl(Control& rCtrl, long nXOffset, long nYOffset )
{
    Point aPos = rCtrl.GetPosPixel();
    rCtrl.SetPosPixel( Point(aPos.getX() + nXOffset, aPos.getY() + nYOffset) );
}

void lcl_optimzeRadioButtonSize( RadioButton& rCtrl )
{
    rCtrl.SetSizePixel( rCtrl.CalcMinimumSize() );
}

void SchOptionTabPage::AdaptControlPositionsAndVisibility()
{
    aRbtAxis1.Show(m_bProvidesSecondaryYAxis);
    aRbtAxis2.Show(m_bProvidesSecondaryYAxis);
    aGrpAxis.Show(m_bProvidesSecondaryYAxis);

    aMTGap.Show(m_bProvidesOverlapAndGapWidth);
    aFTGap.Show(m_bProvidesOverlapAndGapWidth);

    aMTOverlap.Show(m_bProvidesOverlapAndGapWidth);
    aFTOverlap.Show(m_bProvidesOverlapAndGapWidth);

    aCBConnect.Show(m_bProvidesBarConnectors);

    if( !aMTGap.IsVisible() && !aMTOverlap.IsVisible() )
    {
        aGrpBar.Show(sal_False);
        Point aPos;
        if( !aRbtAxis1.IsVisible() && !aRbtAxis2.IsVisible() )
            aPos = aGrpAxis.GetPosPixel();
        else
            aPos = aGrpBar.GetPosPixel();

        long nYOffset = aPos.getY() - m_aFL_PlotOptions.GetPosPixel().getY();
        lcl_offsetControl(m_aFL_PlotOptions,       0, nYOffset);
        lcl_offsetControl(m_aFT_MissingValues,     0, nYOffset);
        lcl_offsetControl(m_aRB_DontPaint,         0, nYOffset);
        lcl_offsetControl(m_aRB_AssumeZero,        0, nYOffset);
        lcl_offsetControl(m_aRB_ContinueLine,      0, nYOffset);
        lcl_offsetControl(m_aCBIncludeHiddenCells, 0, nYOffset);
    }

    m_aFT_MissingValues.SetSizePixel( m_aFT_MissingValues.CalcMinimumSize() );
    lcl_optimzeRadioButtonSize( m_aRB_DontPaint );
    lcl_optimzeRadioButtonSize( m_aRB_AssumeZero );
    lcl_optimzeRadioButtonSize( m_aRB_ContinueLine );

    Size aControlDistance( m_aFT_MissingValues.LogicToPixel( Size(RSC_SP_CTRL_DESC_X,RSC_SP_CTRL_GROUP_Y), MapMode(MAP_APPFONT) ) );
    long nXOffset = m_aFT_MissingValues.GetPosPixel().getX() + m_aFT_MissingValues.GetSizePixel().getWidth() + aControlDistance.getWidth() - m_aRB_DontPaint.GetPosPixel().getX();
    lcl_offsetControl(m_aRB_DontPaint,         nXOffset, 0);
    lcl_offsetControl(m_aRB_AssumeZero,        nXOffset, 0);
    lcl_offsetControl(m_aRB_ContinueLine,      nXOffset, 0);

    if( !m_aFT_MissingValues.IsVisible() )
    {
        //for example for stock charts
        m_aCBIncludeHiddenCells.SetPosPixel( m_aFT_MissingValues.GetPosPixel() );
    }
}
//.............................................................................
} //namespace chart
//.............................................................................

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
