/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#undef SC_DLLIMPLEMENTATION



//------------------------------------------------------------------

#include "scitems.hxx"

#include "tptable.hxx"
#include "global.hxx"
#include "attrib.hxx"
#include "scresid.hxx"
#include "sc.hrc"
#include "pagedlg.hrc"

// =======================================================================

void EmptyNumericField::Modify()
{
    if( GetText().Len() )
        NumericField::Modify();
    else
        SetEmptyFieldValue();
}

void EmptyNumericField::SetValue( sal_Int64 nValue )
{
    if( nValue == 0 )
        SetEmptyFieldValue();
    else
        NumericField::SetValue( nValue );
}

sal_Int64 EmptyNumericField::GetValue() const
{
    return IsEmptyFieldValue() ? 0 : NumericField::GetValue();
}

// =======================================================================

// STATIC DATA -----------------------------------------------------------

static sal_uInt16 pPageTableRanges[] =
{
	ATTR_PAGE_NOTES, ATTR_PAGE_FIRSTPAGENO,
	0
};

sal_Bool lcl_PutVObjModeItem( sal_uInt16			nWhich,
						  SfxItemSet&		rCoreSet,
						  const SfxItemSet&	rOldSet,
						  const CheckBox&	rBtn );

sal_Bool lcl_PutScaleItem( sal_uInt16				nWhich,
					   SfxItemSet&			rCoreSet,
					   const SfxItemSet&	rOldSet,
                       const ListBox&       rListBox,
                       sal_uInt16               nLBEntry,
                       const SpinField&     rEd,
                       sal_uInt16               nValue );

sal_Bool lcl_PutScaleItem2( sal_uInt16               nWhich,
                       SfxItemSet&          rCoreSet,
                       const SfxItemSet&    rOldSet,
                       const ListBox&       rListBox,
                       sal_uInt16               nLBEntry,
                       const NumericField&  rEd1,
                       const NumericField&  rEd2 );

sal_Bool lcl_PutBoolItem( sal_uInt16			nWhich,
					  SfxItemSet&		rCoreSet,
					  const SfxItemSet&	rOldSet,
					  sal_Bool				bIsChecked,
					  sal_Bool				bSavedValue );

//------------------------------------------------------------------------

#define PAGENO_HDL 			LINK(this,ScTablePage,PageNoHdl)
#define PAGEDIR_HDL 		LINK(this,ScTablePage,PageDirHdl)
#define SCALE_HDL			LINK(this,ScTablePage,ScaleHdl)

#define WAS_DEFAULT(w,s)    (SFX_ITEM_DEFAULT==(s).GetItemState((w),sal_True))
#define GET_BOOL(sid,set)	((const SfxBoolItem&)((set).Get(GetWhich((sid))))).GetValue()
#define GET_USHORT(sid,set)	(sal_uInt16)((const SfxUInt16Item&)((set).Get(GetWhich((sid))))).GetValue()
#define GET_SHOW(sid,set) 	( ScVObjMode( ((const ScViewObjectModeItem&)((set).Get(GetWhich((sid))))).GetValue() ) \
							  == VOBJ_MODE_SHOW )

//========================================================================

ScTablePage::ScTablePage( Window* pParent, const SfxItemSet& rCoreAttrs ) :

        SfxTabPage( pParent, ScResId( RID_SCPAGE_TABLE ), rCoreAttrs ),

        aFlPageDir          ( this, ScResId( FL_PAGEDIR ) ),
		aBtnTopDown 		( this, ScResId( BTN_TOPDOWN ) ),
		aBtnLeftRight		( this, ScResId( BTN_LEFTRIGHT ) ),
		aBmpPageDir 		( this, ScResId( BMP_PAGEDIR ) ),
		aImgLeftRight		( ScResId( IMG_LEFTRIGHT ) ),
		aImgTopDown 		( ScResId( IMG_TOPDOWN ) ),
        aImgLeftRightHC     ( ScResId( IMG_LEFTRIGHT_H ) ),
        aImgTopDownHC       ( ScResId( IMG_TOPDOWN_H ) ),
		aBtnPageNo			( this, ScResId( BTN_PAGENO ) ),
		aEdPageNo			( this, ScResId( ED_PAGENO ) ),
        aFlPrint            ( this, ScResId( FL_PRINT ) ),
		aBtnHeaders 		( this, ScResId( BTN_HEADER ) ),
		aBtnGrid			( this, ScResId( BTN_GRID ) ),
		aBtnNotes			( this, ScResId( BTN_NOTES ) ),
		aBtnObjects 		( this, ScResId( BTN_OBJECTS ) ),
		aBtnCharts			( this, ScResId( BTN_CHARTS ) ),
		aBtnDrawings		( this, ScResId( BTN_DRAWINGS ) ),
		aBtnFormulas		( this, ScResId( BTN_FORMULAS ) ),
		aBtnNullVals		( this, ScResId( BTN_NULLVALS ) ),
        aFlScale            ( this, ScResId( FL_SCALE ) ),
        aFtScaleMode        ( this, ScResId( FT_SCALEMODE ) ),
        aLbScaleMode        ( this, ScResId( LB_SCALEMODE ) ),
        aFtScaleAll         ( this, ScResId( FT_SCALEFACTOR ) ),
		aEdScaleAll 		( this, ScResId( ED_SCALEALL ) ),
        aFtScalePageWidth   ( this, ScResId( FT_SCALEPAGEWIDTH ) ),
        aEdScalePageWidth   ( this, ScResId( ED_SCALEPAGEWIDTH ) ),
        aFtScalePageHeight  ( this, ScResId( FT_SCALEPAGEHEIGHT ) ),
        aEdScalePageHeight  ( this, ScResId( ED_SCALEPAGEHEIGHT ) ),
        aFtScalePageNum     ( this, ScResId( FT_SCALEPAGENUM ) ),
        aEdScalePageNum     ( this, ScResId( ED_SCALEPAGENUM ) )
{
	SetExchangeSupport();
    aBtnPageNo.SetClickHdl( PAGENO_HDL );
    aBtnTopDown.SetClickHdl( PAGEDIR_HDL );
    aBtnLeftRight.SetClickHdl( PAGEDIR_HDL );
    aLbScaleMode.SetSelectHdl( SCALE_HDL );

    Size aBmpSize = Image( ScResId( IMG_LEFTRIGHT ) ).GetSizePixel();
    aBmpPageDir.SetOutputSizePixel( aBmpSize );

	FreeResource();

	aEdPageNo.SetAccessibleName(aBtnPageNo.GetText());
	aEdPageNo.SetAccessibleRelationLabeledBy(&aBtnPageNo);
}

// -----------------------------------------------------------------------

void ScTablePage::ShowImage()
{
    bool bHC = GetSettings().GetStyleSettings().GetHighContrastMode();
    bool bLeftRight = aBtnLeftRight.IsChecked();
    aBmpPageDir.SetImage( bHC ?
        (bLeftRight ? aImgLeftRightHC : aImgTopDownHC) :
        (bLeftRight ? aImgLeftRight : aImgTopDown) );
}

// -----------------------------------------------------------------------

ScTablePage::~ScTablePage()
{
}

//------------------------------------------------------------------------

sal_uInt16* ScTablePage::GetRanges()
{
	return pPageTableRanges;
}

// -----------------------------------------------------------------------

SfxTabPage* ScTablePage::Create( Window* pParent, const SfxItemSet& rCoreSet )
{
	return ( new ScTablePage( pParent, rCoreSet ) );
}

// -----------------------------------------------------------------------

void ScTablePage::Reset( const SfxItemSet& rCoreSet )
{
	sal_Bool	bTopDown = GET_BOOL( SID_SCATTR_PAGE_TOPDOWN, rCoreSet );
	sal_uInt16	nWhich   = 0;

	//-----------
	// sal_Bool-Flags
	//-----------
	aBtnNotes		.Check( GET_BOOL(SID_SCATTR_PAGE_NOTES,rCoreSet) );
	aBtnGrid		.Check( GET_BOOL(SID_SCATTR_PAGE_GRID,rCoreSet) );
	aBtnHeaders 	.Check( GET_BOOL(SID_SCATTR_PAGE_HEADERS,rCoreSet) );
	aBtnFormulas	.Check( GET_BOOL(SID_SCATTR_PAGE_FORMULAS,rCoreSet) );
	aBtnNullVals	.Check( GET_BOOL(SID_SCATTR_PAGE_NULLVALS,rCoreSet) );
	aBtnTopDown 	.Check( bTopDown );
	aBtnLeftRight	.Check( !bTopDown );

	//------------------
	// Erste Druckseite:
	//------------------
	sal_uInt16 nPage = GET_USHORT(SID_SCATTR_PAGE_FIRSTPAGENO,rCoreSet);
	aBtnPageNo.Check( nPage != 0 );
	aEdPageNo.SetValue( (nPage != 0) ? nPage : 1 );
	PageNoHdl( NULL );

	//-------------------
	// Objektdarstellung:
	//-------------------
	aBtnCharts		.Check( GET_SHOW( SID_SCATTR_PAGE_CHARTS, rCoreSet ) );
	aBtnObjects 	.Check( GET_SHOW( SID_SCATTR_PAGE_OBJECTS, rCoreSet ) );
	aBtnDrawings	.Check( GET_SHOW( SID_SCATTR_PAGE_DRAWINGS, rCoreSet ) );

	//------------
	// Skalierung:
	//------------

	nWhich = GetWhich(SID_SCATTR_PAGE_SCALE);
	if ( rCoreSet.GetItemState( nWhich, sal_True ) >= SFX_ITEM_AVAILABLE )
	{
		sal_uInt16 nScale = ((const SfxUInt16Item&)rCoreSet.Get(nWhich)).GetValue();
        if( nScale > 0 )
            aLbScaleMode.SelectEntryPos( SC_TPTABLE_SCALE_PERCENT );
        aEdScaleAll.SetValue( (nScale > 0) ? nScale : 100 );
	}

    nWhich = GetWhich(SID_SCATTR_PAGE_SCALETO);
    if ( rCoreSet.GetItemState( nWhich, sal_True ) >= SFX_ITEM_AVAILABLE )
    {
        const ScPageScaleToItem& rItem = static_cast< const ScPageScaleToItem& >( rCoreSet.Get( nWhich ) );
        sal_uInt16 nWidth = rItem.GetWidth();
        sal_uInt16 nHeight = rItem.GetHeight();

        /*  width==0 and height==0 is invalid state, used as "not selected".
            Dialog shows width=height=1 then. */
        bool bValid = nWidth || nHeight;
        if( bValid )
            aLbScaleMode.SelectEntryPos( SC_TPTABLE_SCALE_TO );
        aEdScalePageWidth.SetValue( bValid ? nWidth : 1 );
        aEdScalePageHeight.SetValue( bValid ? nHeight : 1 );
    }

	nWhich = GetWhich(SID_SCATTR_PAGE_SCALETOPAGES);
	if ( rCoreSet.GetItemState( nWhich, sal_True ) >= SFX_ITEM_AVAILABLE )
	{
		sal_uInt16 nPages = ((const SfxUInt16Item&)rCoreSet.Get(nWhich)).GetValue();
        if( nPages > 0 )
            aLbScaleMode.SelectEntryPos( SC_TPTABLE_SCALE_TO_PAGES );
        aEdScalePageNum.SetValue( (nPages > 0) ? nPages : 1 );
	}

    if( aLbScaleMode.GetSelectEntryCount() == 0 )
    {
        // fall back to 100%
        DBG_ERRORFILE( "ScTablePage::Reset - missing scaling item" );
        aLbScaleMode.SelectEntryPos( SC_TPTABLE_SCALE_PERCENT );
        aEdScaleAll.SetValue( 100 );
    }

	PageDirHdl( NULL );
	ScaleHdl( NULL );

	// merken fuer FillItemSet
	aBtnFormulas	.SaveValue();
	aBtnNullVals	.SaveValue();
	aBtnNotes		.SaveValue();
	aBtnGrid		.SaveValue();
	aBtnHeaders 	.SaveValue();
	aBtnTopDown 	.SaveValue();
	aBtnLeftRight	.SaveValue();
    aLbScaleMode    .SaveValue();
	aBtnCharts		.SaveValue();
	aBtnObjects 	.SaveValue();
	aBtnDrawings	.SaveValue();
	aBtnPageNo		.SaveValue();
	aEdPageNo		.SaveValue();
	aEdScaleAll		.SaveValue();
    aEdScalePageWidth.SaveValue();
    aEdScalePageHeight.SaveValue();
	aEdScalePageNum	.SaveValue();
}

// -----------------------------------------------------------------------

sal_Bool ScTablePage::FillItemSet( SfxItemSet& rCoreSet )
{
	const SfxItemSet&	rOldSet		 = GetItemSet();
	sal_uInt16				nWhichPageNo = GetWhich(SID_SCATTR_PAGE_FIRSTPAGENO);
	sal_Bool				bDataChanged = sal_False;

	//-----------
	// sal_Bool-Flags
	//-----------

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_NOTES),
									 rCoreSet, rOldSet,
									 aBtnNotes.IsChecked(),
                                     aBtnNotes.GetSavedValue() != STATE_NOCHECK );

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_GRID),
									 rCoreSet, rOldSet,
									 aBtnGrid.IsChecked(),
                                     aBtnGrid.GetSavedValue() != STATE_NOCHECK );

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_HEADERS),
									 rCoreSet, rOldSet,
									 aBtnHeaders.IsChecked(),
                                     aBtnHeaders.GetSavedValue() != STATE_NOCHECK );

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_TOPDOWN),
									 rCoreSet, rOldSet,
									 aBtnTopDown.IsChecked(),
									 aBtnTopDown.GetSavedValue() );

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_FORMULAS),
									 rCoreSet, rOldSet,
									 aBtnFormulas.IsChecked(),
                                     aBtnFormulas.GetSavedValue() != STATE_NOCHECK );

	bDataChanged |= lcl_PutBoolItem( GetWhich(SID_SCATTR_PAGE_NULLVALS),
									 rCoreSet, rOldSet,
									 aBtnNullVals.IsChecked(),
                                     aBtnNullVals.GetSavedValue() != STATE_NOCHECK );

	//------------------
	// Erste Druckseite:
	//------------------
	sal_Bool bUseValue = aBtnPageNo.IsChecked();

	if (   WAS_DEFAULT(nWhichPageNo,rOldSet)
		&& (	(!bUseValue && bUseValue == aBtnPageNo.GetSavedValue())
			|| (   bUseValue && bUseValue == aBtnPageNo.GetSavedValue()
				&& aEdPageNo.GetText() == aEdPageNo.GetSavedValue() ) ) )
	{
			rCoreSet.ClearItem( nWhichPageNo );
	}
	else
	{
		sal_uInt16 nPage = (sal_uInt16)( aBtnPageNo.IsChecked()
									? aEdPageNo.GetValue()
									: 0 );

		rCoreSet.Put( SfxUInt16Item( nWhichPageNo, nPage ) );
		bDataChanged = sal_True;
	}

	//-------------------
	// Objektdarstellung:
	//-------------------

	bDataChanged |= lcl_PutVObjModeItem( GetWhich(SID_SCATTR_PAGE_CHARTS),
										 rCoreSet, rOldSet, aBtnCharts );

	bDataChanged |= lcl_PutVObjModeItem( GetWhich(SID_SCATTR_PAGE_OBJECTS),
										 rCoreSet, rOldSet, aBtnObjects );

	bDataChanged |= lcl_PutVObjModeItem( GetWhich(SID_SCATTR_PAGE_DRAWINGS),
										 rCoreSet, rOldSet, aBtnDrawings );

	//------------
	// Skalierung:
	//------------

    if( !aEdScalePageWidth.GetValue() && !aEdScalePageHeight.GetValue() )
    {
        aLbScaleMode.SelectEntryPos( SC_TPTABLE_SCALE_PERCENT );
        aEdScaleAll.SetValue( 100 );
    }

	bDataChanged |= lcl_PutScaleItem( GetWhich(SID_SCATTR_PAGE_SCALE),
									  rCoreSet, rOldSet,
                                      aLbScaleMode, SC_TPTABLE_SCALE_PERCENT,
                                      aEdScaleAll, (sal_uInt16)aEdScaleAll.GetValue() );

    bDataChanged |= lcl_PutScaleItem2( GetWhich(SID_SCATTR_PAGE_SCALETO),
                                      rCoreSet, rOldSet,
                                      aLbScaleMode, SC_TPTABLE_SCALE_TO,
                                      aEdScalePageWidth, aEdScalePageHeight );

	bDataChanged |= lcl_PutScaleItem( GetWhich(SID_SCATTR_PAGE_SCALETOPAGES),
									  rCoreSet, rOldSet,
                                      aLbScaleMode, SC_TPTABLE_SCALE_TO_PAGES,
                                      aEdScalePageNum, (sal_uInt16)aEdScalePageNum.GetValue() );

	return bDataChanged;
}

//------------------------------------------------------------------------

int ScTablePage::DeactivatePage( SfxItemSet* pSetP )
{
    if ( pSetP )
        FillItemSet( *pSetP );

	return LEAVE_PAGE;
}

//------------------------------------------------------------------------

void ScTablePage::DataChanged( const DataChangedEvent& rDCEvt )
{
    if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
        ShowImage();
    SfxTabPage::DataChanged( rDCEvt );
}

//------------------------------------------------------------------------
// Handler:
//------------------------------------------------------------------------

IMPL_LINK( ScTablePage, PageDirHdl, RadioButton*, EMPTYARG )
{
    ShowImage();
	return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( ScTablePage, PageNoHdl, CheckBox*, pBtn )
{
	if ( aBtnPageNo.IsChecked() )
	{
		aEdPageNo.Enable();
		if ( pBtn )
			aEdPageNo.GrabFocus();
	}
	else
		aEdPageNo.Disable();

	return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( ScTablePage, ScaleHdl, ListBox*, EMPTYARG )
{
    // controls for "Reduce/enlarge"
    bool bPercent = (aLbScaleMode.GetSelectEntryPos() == SC_TPTABLE_SCALE_PERCENT);
    aFtScaleAll.Show( bPercent );
    aEdScaleAll.Show( bPercent );

    // controls for "Scale to width/height"
    bool bScaleTo = (aLbScaleMode.GetSelectEntryPos() == SC_TPTABLE_SCALE_TO);
    aFtScalePageWidth.Show( bScaleTo );
    aEdScalePageWidth.Show( bScaleTo );
    aFtScalePageHeight.Show( bScaleTo );
    aEdScalePageHeight.Show( bScaleTo );

    // controls for "Scale to pages"
    bool bScalePages = (aLbScaleMode.GetSelectEntryPos() == SC_TPTABLE_SCALE_TO_PAGES);
    aFtScalePageNum.Show( bScalePages );
    aEdScalePageNum.Show( bScalePages );

	return 0;
}

//========================================================================
// Hilfsfunktionen fuer FillItemSet:
//========================================================================

sal_Bool lcl_PutBoolItem( sal_uInt16			nWhich,
					 SfxItemSet&		rCoreSet,
					 const SfxItemSet&	rOldSet,
					 sal_Bool				bIsChecked,
					 sal_Bool				bSavedValue )
{
	sal_Bool bDataChanged = (   bSavedValue == bIsChecked
						 && WAS_DEFAULT(nWhich,rOldSet) );

	if ( bDataChanged )
		rCoreSet.ClearItem(nWhich);
	else
		rCoreSet.Put( SfxBoolItem( nWhich, bIsChecked ) );

	return bDataChanged;
}

//------------------------------------------------------------------------

sal_Bool lcl_PutVObjModeItem( sal_uInt16			nWhich,
						 SfxItemSet&		rCoreSet,
						 const SfxItemSet&	rOldSet,
						 const CheckBox&	rBtn )
{
	sal_Bool bIsChecked   = rBtn.IsChecked();
	sal_Bool bDataChanged = (   rBtn.GetSavedValue() == bIsChecked
						 && WAS_DEFAULT(nWhich,rOldSet) );

	if ( bDataChanged )
		rCoreSet.ClearItem( nWhich );

	else
		rCoreSet.Put( ScViewObjectModeItem( nWhich, bIsChecked
													? VOBJ_MODE_SHOW
													: VOBJ_MODE_HIDE ) );
	return bDataChanged;
}

//------------------------------------------------------------------------

sal_Bool lcl_PutScaleItem( sal_uInt16				nWhich,
					  SfxItemSet&			rCoreSet,
					  const SfxItemSet&		rOldSet,
                      const ListBox&        rListBox,
                      sal_uInt16                nLBEntry,
                      const SpinField&      rEd,
                      sal_uInt16                nValue )
{
    sal_Bool bIsSel = (rListBox.GetSelectEntryPos() == nLBEntry);
    sal_Bool bDataChanged = (rListBox.GetSavedValue() != nLBEntry) ||
                        (rEd.GetSavedValue() != rEd.GetText()) ||
                        !WAS_DEFAULT( nWhich, rOldSet );

    if( bDataChanged )
        rCoreSet.Put( SfxUInt16Item( nWhich, bIsSel ? nValue : 0 ) );
    else
        rCoreSet.ClearItem( nWhich );

	return bDataChanged;
}


sal_Bool lcl_PutScaleItem2( sal_uInt16               nWhich,
                      SfxItemSet&           rCoreSet,
                      const SfxItemSet&     rOldSet,
                      const ListBox&        rListBox,
                      sal_uInt16                nLBEntry,
                      const NumericField&   rEd1,
                      const NumericField&   rEd2 )
{
    sal_uInt16 nValue1 = (sal_uInt16)rEd1.GetValue();
    sal_uInt16 nValue2 = (sal_uInt16)rEd2.GetValue();
    sal_Bool bIsSel = (rListBox.GetSelectEntryPos() == nLBEntry);
    sal_Bool bDataChanged = (rListBox.GetSavedValue() != nLBEntry) ||
                        (rEd1.GetSavedValue() != rEd1.GetText()) ||
                        (rEd2.GetSavedValue() != rEd2.GetText()) ||
                        !WAS_DEFAULT( nWhich, rOldSet );

    if( bDataChanged )
    {
        ScPageScaleToItem aItem;
        if( bIsSel )
            aItem.Set( nValue1, nValue2 );
        rCoreSet.Put( aItem );
    }
    else
        rCoreSet.ClearItem( nWhich );

    return bDataChanged;
}