/**************************************************************
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



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



// INCLUDE ---------------------------------------------------------------

#include <svx/svdtrans.hxx>
#include <unotools/localedatawrapper.hxx>

#include "colrowba.hxx"
#include "document.hxx"
#include "scmod.hxx"
#include "tabvwsh.hxx"
#include "docsh.hxx"
#include "appoptio.hxx"
#include "globstr.hrc"

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

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

String lcl_MetricString( long nTwips, const String& rText )
{
	if ( nTwips <= 0 )
		return ScGlobal::GetRscString(STR_TIP_HIDE);
	else
	{
		FieldUnit eUserMet = SC_MOD()->GetAppOptions().GetAppMetric();

        sal_Int64 nUserVal = MetricField::ConvertValue( nTwips*100, 1, 2, FUNIT_TWIP, eUserMet );

		String aStr = rText;
		aStr += ' ';
        aStr += ScGlobal::pLocaleData->getNum( nUserVal, 2 );
		aStr += ' ';
		aStr += SdrFormatter::GetUnitStr(eUserMet);

		return aStr;
	}
}

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

ScColBar::ScColBar( Window* pParent, ScViewData* pData, ScHSplitPos eWhichPos,
					ScHeaderFunctionSet* pFunc, ScHeaderSelectionEngine* pEng ) :
			ScHeaderControl( pParent, pEng, MAXCOL+1, HDR_HORIZONTAL ),
			pViewData( pData ),
			eWhich( eWhichPos ),
			pFuncSet( pFunc ),
			pSelEngine( pEng )
{
	Show();
}

ScColBar::~ScColBar()
{
}

inline sal_Bool ScColBar::UseNumericHeader() const
{
    return pViewData->GetDocument()->GetAddressConvention() == formula::FormulaGrammar::CONV_XL_R1C1;
}

SCCOLROW ScColBar::GetPos()
{
	return pViewData->GetPosX(eWhich);
}

sal_uInt16 ScColBar::GetEntrySize( SCCOLROW nEntryNo )
{
	ScDocument* pDoc = pViewData->GetDocument();
	SCTAB nTab = pViewData->GetTabNo();
	SCCOL nLastCol = -1;
	if (pDoc->ColHidden(static_cast<SCCOL>(nEntryNo), nTab, nLastCol))
		return 0;
	else
		return (sal_uInt16) ScViewData::ToPixel( pDoc->GetColWidth( static_cast<SCCOL>(nEntryNo), nTab ), pViewData->GetPPTX() );
}

String ScColBar::GetEntryText( SCCOLROW nEntryNo )
{
	return UseNumericHeader()
	    ? String::CreateFromInt32( nEntryNo + 1 )
	    : ScColToAlpha( static_cast<SCCOL>(nEntryNo) );
}

void ScColBar::SetEntrySize( SCCOLROW nPos, sal_uInt16 nNewSize )
{
	sal_uInt16 nSizeTwips;
	ScSizeMode eMode = SC_SIZE_DIRECT;
	if (nNewSize>0 && nNewSize<10) nNewSize=10;				// (Pixel)

	if ( nNewSize == HDR_SIZE_OPTIMUM )
	{
		nSizeTwips = STD_EXTRA_WIDTH;
		eMode = SC_SIZE_OPTIMAL;
	}
	else
		nSizeTwips = (sal_uInt16) ( nNewSize / pViewData->GetPPTX() );

	ScMarkData& rMark = pViewData->GetMarkData();
//	SCTAB nTab = pViewData->GetTabNo();

	SCCOLROW* pRanges = new SCCOLROW[MAXCOL+1];
	SCCOL nRangeCnt = 0;
	if ( rMark.IsColumnMarked( static_cast<SCCOL>(nPos) ) )
	{
		SCCOL nStart = 0;
		while (nStart<=MAXCOL)
		{
			while (nStart<MAXCOL && !rMark.IsColumnMarked(nStart))
				++nStart;
			if (rMark.IsColumnMarked(nStart))
			{
				SCCOL nEnd = nStart;
				while (nEnd<MAXCOL && rMark.IsColumnMarked(nEnd))
					++nEnd;
				if (!rMark.IsColumnMarked(nEnd))
					--nEnd;
				pRanges[static_cast<size_t>(2*nRangeCnt)  ] = nStart;
				pRanges[static_cast<size_t>(2*nRangeCnt+1)] = nEnd;
				++nRangeCnt;
				nStart = nEnd+1;
			}
			else
				nStart = MAXCOL+1;
		}
	}
	else
	{
		pRanges[0] = nPos;
		pRanges[1] = nPos;
		nRangeCnt = 1;
	}

	pViewData->GetView()->SetWidthOrHeight( sal_True, nRangeCnt, pRanges, eMode, nSizeTwips );
	delete[] pRanges;
}

void ScColBar::HideEntries( SCCOLROW nStart, SCCOLROW nEnd )
{
	SCCOLROW nRange[2];
	nRange[0] = nStart;
	nRange[1] = nEnd;
	pViewData->GetView()->SetWidthOrHeight( sal_True, 1, nRange, SC_SIZE_DIRECT, 0 );
}

void ScColBar::SetMarking( sal_Bool bSet )
{
	pViewData->GetMarkData().SetMarking( bSet );
	if (!bSet)
	{
		pViewData->GetView()->UpdateAutoFillMark();
	}
}

void ScColBar::SelectWindow()
{
	ScTabViewShell* pViewSh = pViewData->GetViewShell();

	pViewSh->SetActive();			// Appear und SetViewFrame
	pViewSh->DrawDeselectAll();

	ScSplitPos eActive = pViewData->GetActivePart();
	if (eWhich==SC_SPLIT_LEFT)
	{
		if (eActive==SC_SPLIT_TOPRIGHT)		eActive=SC_SPLIT_TOPLEFT;
		if (eActive==SC_SPLIT_BOTTOMRIGHT)	eActive=SC_SPLIT_BOTTOMLEFT;
	}
	else
	{
		if (eActive==SC_SPLIT_TOPLEFT)		eActive=SC_SPLIT_TOPRIGHT;
		if (eActive==SC_SPLIT_BOTTOMLEFT)	eActive=SC_SPLIT_BOTTOMRIGHT;
	}
	pViewSh->ActivatePart( eActive );

	pFuncSet->SetColumn( sal_True );
	pFuncSet->SetWhich( eActive );

	pViewSh->ActiveGrabFocus();
}

sal_Bool ScColBar::IsDisabled()
{
	ScModule* pScMod = SC_MOD();
	return pScMod->IsFormulaMode() || pScMod->IsModalMode();
}

sal_Bool ScColBar::ResizeAllowed()
{
	return !pViewData->HasEditView( pViewData->GetActivePart() ) &&
			!pViewData->GetDocShell()->IsReadOnly();
}

void ScColBar::DrawInvert( long nDragPosP )
{
	Rectangle aRect( nDragPosP,0, nDragPosP+HDR_SLIDERSIZE-1,GetOutputSizePixel().Width()-1 );
	Update();
	Invert(aRect);

	pViewData->GetView()->InvertVertical(eWhich,nDragPosP);
}

String ScColBar::GetDragHelp( long nVal )
{
	long nTwips = (long) ( nVal / pViewData->GetPPTX() );
	return lcl_MetricString( nTwips, ScGlobal::GetRscString(STR_TIP_WIDTH) );
}

sal_Bool ScColBar::IsLayoutRTL()		// overloaded only for columns
{
	return pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
}

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

ScRowBar::ScRowBar( Window* pParent, ScViewData* pData, ScVSplitPos eWhichPos,
					ScHeaderFunctionSet* pFunc, ScHeaderSelectionEngine* pEng ) :
			ScHeaderControl( pParent, pEng, MAXROW+1, HDR_VERTICAL ),
			pViewData( pData ),
			eWhich( eWhichPos ),
			pFuncSet( pFunc ),
			pSelEngine( pEng )
{
	Show();
}

ScRowBar::~ScRowBar()
{
}

SCCOLROW ScRowBar::GetPos()
{
	return pViewData->GetPosY(eWhich);
}

sal_uInt16 ScRowBar::GetEntrySize( SCCOLROW nEntryNo )
{
	ScDocument* pDoc = pViewData->GetDocument();
	SCTAB nTab = pViewData->GetTabNo();
	SCROW nLastRow = -1;
	if (pDoc->RowHidden(nEntryNo, nTab, nLastRow))
		return 0;
	else
        return (sal_uInt16) ScViewData::ToPixel( pDoc->GetOriginalHeight( nEntryNo,
                    nTab ), pViewData->GetPPTY() );
}

String ScRowBar::GetEntryText( SCCOLROW nEntryNo )
{
	return String::CreateFromInt32( nEntryNo + 1 );
}

void ScRowBar::SetEntrySize( SCCOLROW nPos, sal_uInt16 nNewSize )
{
	sal_uInt16 nSizeTwips;
	ScSizeMode eMode = SC_SIZE_DIRECT;
	if (nNewSize>0 && nNewSize<10) nNewSize=10;				// (Pixel)

	if ( nNewSize == HDR_SIZE_OPTIMUM )
	{
		nSizeTwips = 0;
		eMode = SC_SIZE_OPTIMAL;
	}
	else
		nSizeTwips = (sal_uInt16) ( nNewSize / pViewData->GetPPTY() );

	ScMarkData& rMark = pViewData->GetMarkData();
//	SCTAB nTab = pViewData->GetTabNo();

	SCCOLROW* pRanges = new SCCOLROW[MAXROW+1];
	SCROW nRangeCnt = 0;
	if ( rMark.IsRowMarked( nPos ) )
	{
		SCROW nStart = 0;
		while (nStart<=MAXROW)
		{
			while (nStart<MAXROW && !rMark.IsRowMarked(nStart))
				++nStart;
			if (rMark.IsRowMarked(nStart))
			{
				SCROW nEnd = nStart;
				while (nEnd<MAXROW && rMark.IsRowMarked(nEnd))
					++nEnd;
				if (!rMark.IsRowMarked(nEnd))
					--nEnd;
				pRanges[static_cast<size_t>(2*nRangeCnt)  ] = nStart;
				pRanges[static_cast<size_t>(2*nRangeCnt+1)] = nEnd;
				++nRangeCnt;
				nStart = nEnd+1;
			}
			else
				nStart = MAXROW+1;
		}
	}
	else
	{
		pRanges[0] = nPos;
		pRanges[1] = nPos;
		nRangeCnt = 1;
	}

	pViewData->GetView()->SetWidthOrHeight( sal_False, nRangeCnt, pRanges, eMode, nSizeTwips );
	delete[] pRanges;
}

void ScRowBar::HideEntries( SCCOLROW nStart, SCCOLROW nEnd )
{
	SCCOLROW nRange[2];
	nRange[0] = nStart;
	nRange[1] = nEnd;
	pViewData->GetView()->SetWidthOrHeight( sal_False, 1, nRange, SC_SIZE_DIRECT, 0 );
}

void ScRowBar::SetMarking( sal_Bool bSet )
{
	pViewData->GetMarkData().SetMarking( bSet );
	if (!bSet)
	{
		pViewData->GetView()->UpdateAutoFillMark();
	}
}

void ScRowBar::SelectWindow()
{
	ScTabViewShell* pViewSh = pViewData->GetViewShell();

	pViewSh->SetActive();			// Appear und SetViewFrame
	pViewSh->DrawDeselectAll();

	ScSplitPos eActive = pViewData->GetActivePart();
	if (eWhich==SC_SPLIT_TOP)
	{
		if (eActive==SC_SPLIT_BOTTOMLEFT)	eActive=SC_SPLIT_TOPLEFT;
		if (eActive==SC_SPLIT_BOTTOMRIGHT)	eActive=SC_SPLIT_TOPRIGHT;
	}
	else
	{
		if (eActive==SC_SPLIT_TOPLEFT)		eActive=SC_SPLIT_BOTTOMLEFT;
		if (eActive==SC_SPLIT_TOPRIGHT)		eActive=SC_SPLIT_BOTTOMRIGHT;
	}
	pViewSh->ActivatePart( eActive );

	pFuncSet->SetColumn( sal_False );
	pFuncSet->SetWhich( eActive );

	pViewSh->ActiveGrabFocus();
}

sal_Bool ScRowBar::IsDisabled()
{
	ScModule* pScMod = SC_MOD();
	return pScMod->IsFormulaMode() || pScMod->IsModalMode();
}

sal_Bool ScRowBar::ResizeAllowed()
{
	return !pViewData->HasEditView( pViewData->GetActivePart() ) &&
			!pViewData->GetDocShell()->IsReadOnly();
}

void ScRowBar::DrawInvert( long nDragPosP )
{
	Rectangle aRect( 0,nDragPosP, GetOutputSizePixel().Width()-1,nDragPosP+HDR_SLIDERSIZE-1 );
	Update();
	Invert(aRect);

	pViewData->GetView()->InvertHorizontal(eWhich,nDragPosP);
}

String ScRowBar::GetDragHelp( long nVal )
{
	long nTwips = (long) ( nVal / pViewData->GetPPTY() );
	return lcl_MetricString( nTwips, ScGlobal::GetRscString(STR_TIP_HEIGHT) );
}

//	GetHiddenCount ist nur fuer Zeilen ueberladen

SCROW ScRowBar::GetHiddenCount( SCROW nEntryNo )
{
	ScDocument* pDoc = pViewData->GetDocument();
	SCTAB nTab = pViewData->GetTabNo();
	return pDoc->GetHiddenRowCount( nEntryNo, nTab );
}

sal_Bool ScRowBar::IsMirrored()			// overloaded only for rows
{
	return pViewData->GetDocument()->IsLayoutRTL( pViewData->GetTabNo() );
}


