/**************************************************************
 *
 * 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.
 *
 *************************************************************/

#include "svx/sidebar/ValueSetWithTextControl.hxx"
#include <svx/dialogs.hrc>
#include <svx/dialmgr.hxx>
#include <sfx2/sidebar/Theme.hxx>

#include <limits.h>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/style/NumberingType.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/text/XDefaultNumberingProvider.hpp>
#include <com/sun/star/text/XNumberingFormatter.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <comphelper/processfactory.hxx>
#include <com/sun/star/text/XNumberingTypeInfo.hpp>
#include <i18npool/mslangid.hxx>
#include <svtools/valueset.hxx>
#include <editeng/brshitem.hxx>
#include <vcl/graph.hxx>
#include <svx/nbdtmg.hxx>
#include <svx/nbdtmgfact.hxx>

using namespace com::sun::star::uno;
using namespace com::sun::star::beans;
using namespace com::sun::star::lang;
using namespace com::sun::star::i18n;
using namespace com::sun::star::text;
using namespace com::sun::star::container;
using namespace com::sun::star::style;
using rtl::OUString;

#define C2U(cChar) OUString::createFromAscii(cChar)

namespace svx { namespace sidebar {
static const sal_Char cValue[] = "Value";

static Font& lcl_GetDefaultBulletFont()
{
	static sal_Bool bInit = 0;
	static Font aDefBulletFont( UniString::CreateFromAscii(
		                        RTL_CONSTASCII_STRINGPARAM( "StarSymbol" ) ),
								String(), Size( 0, 14 ) );
	if(!bInit)
	{
		aDefBulletFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
		aDefBulletFont.SetFamily( FAMILY_DONTKNOW );
		aDefBulletFont.SetPitch( PITCH_DONTKNOW );
		aDefBulletFont.SetWeight( WEIGHT_DONTKNOW );
		aDefBulletFont.SetTransparent( sal_True );
		bInit = sal_True;
	}
	return aDefBulletFont;
}

ValueSetWithTextControl::ValueSetWithTextControl(
	const tControlType eControlType,
	Window* pParent,
	const ResId& rResId)
	: ValueSet( pParent, rResId )
	, meControlType( eControlType )
	, maItems()
{
	SetColCount( 1 );
}

ValueSetWithTextControl::~ValueSetWithTextControl(void)
{
}

void ValueSetWithTextControl::AddItem(
	const Image& rItemImage,
	const Image* pSelectedItemImage,
	const XubString& rItemText,
	const XubString* pItemHelpText )
{
	if ( meControlType != IMAGE_TEXT )
	{
		return;
	}

    ValueSetWithTextItem aItem;
    aItem.maItemImage = rItemImage;
    aItem.maSelectedItemImage = (pSelectedItemImage != 0)
                                ? *pSelectedItemImage
                                : rItemImage;
    aItem.maItemText = rItemText;

    maItems.push_back( aItem );

    InsertItem( maItems.size() );
    SetItemText( maItems.size(),
                    (pItemHelpText != 0) ? *pItemHelpText : rItemText );
}


void ValueSetWithTextControl::AddItem(
    const XubString& rItemText,
    const XubString& rItemText2,
    const XubString* pItemHelpText )
{
    if ( meControlType != TEXT_TEXT )
    {
        return;
    }

    ValueSetWithTextItem aItem;
    aItem.maItemText = rItemText;
    aItem.maItemText2 = rItemText2;

    maItems.push_back( aItem );

    InsertItem( maItems.size() );
    SetItemText( maItems.size(),
                    (pItemHelpText != 0) ? *pItemHelpText : rItemText );
}


void ValueSetWithTextControl::ReplaceItemImages(
    const sal_uInt16 nItemId,
    const Image& rItemImage,
    const Image* pSelectedItemImage )
{
    if ( meControlType != IMAGE_TEXT )
    {
        return;
    }

    if ( nItemId == 0 ||
         nItemId > maItems.size() )
    {
        return;
    }

    maItems[nItemId-1].maItemImage = rItemImage;
    maItems[nItemId-1].maSelectedItemImage = (pSelectedItemImage != 0)
                                             ? *pSelectedItemImage
                                             : rItemImage;
}


void ValueSetWithTextControl::UserDraw( const UserDrawEvent& rUDEvt )
{
    const Rectangle aRect = rUDEvt.GetRect();
    OutputDevice* pDev = rUDEvt.GetDevice();
    pDev->Push( PUSH_ALL );
    const sal_uInt16 nItemId = rUDEvt.GetItemId();

    const long nRectHeight = aRect.GetHeight();
    const Point aBLPos = aRect.TopLeft();

    Font aFont(OutputDevice::GetDefaultFont(DEFAULTFONT_UI_SANS, MsLangId::getSystemLanguage(), DEFAULTFONT_FLAGS_ONLYONE));
    {
        Size aSize = aFont.GetSize();
        aSize.Height() = (nRectHeight*4)/9;
        aFont.SetSize( aSize );
    }

    {
        // draw background
        if ( GetSelectItemId() == nItemId )
        {
            Rectangle aBackRect = aRect;
            aBackRect.Top() += 3;
            aBackRect.Bottom() -= 2;
            pDev->SetFillColor( sfx2::sidebar::Theme::GetColor( sfx2::sidebar::Theme::Color_Highlight ) );
            pDev->DrawRect(aBackRect);
        }
        else
        {
            pDev->SetFillColor( COL_TRANSPARENT );
            pDev->DrawRect(aRect);
        }

        // draw image + text resp. text + text
        Image* pImage = 0;
        if ( GetSelectItemId() == nItemId )
        {
            aFont.SetColor( sfx2::sidebar::Theme::GetColor( sfx2::sidebar::Theme::Color_HighlightText ) );
            pImage = &maItems[nItemId-1].maSelectedItemImage;
        }
        else
        {
            aFont.SetColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
            pImage = &maItems[nItemId-1].maItemImage;
        }

        Rectangle aStrRect = aRect;
        aStrRect.Top() += nRectHeight/4;
        aStrRect.Bottom() -= nRectHeight/4;

        switch ( meControlType )
        {
        case IMAGE_TEXT:
            {
                Point aImgStart(
                    aBLPos.X() + 4,
                    aBLPos.Y() + ( ( nRectHeight - pImage->GetSizePixel().Height() ) / 2 ) );
                pDev->DrawImage( aImgStart, *pImage );

                aStrRect.Left() += pImage->GetSizePixel().Width() + 12;
                pDev->SetFont(aFont);
                pDev->DrawText(aStrRect, maItems[nItemId-1].maItemText, TEXT_DRAW_ENDELLIPSIS);
            }
            break;
        case TEXT_TEXT:
            {
                const long nRectWidth = aRect.GetWidth();
                aStrRect.Left() += 8;
                aStrRect.Right() -= (nRectWidth*2)/3;
                pDev->SetFont(aFont);
                pDev->DrawText(aStrRect, maItems[nItemId-1].maItemText, TEXT_DRAW_ENDELLIPSIS);
                aStrRect.Left() += nRectWidth/3;
                aStrRect.Right() += (nRectWidth*2)/3;
                pDev->DrawText(aStrRect, maItems[nItemId-1].maItemText2, TEXT_DRAW_ENDELLIPSIS);
            }
            break;
		}
	}

	Invalidate( aRect );
	pDev->Pop();
}

SvxNumValueSet2::SvxNumValueSet2( Window* pParent, const ResId& rResId) :
	ValueSet( pParent, rResId ),
	aLineColor  ( COL_LIGHTGRAY ),
	pVDev       ( NULL )
{
	SetColCount( 3 );
	SetLineCount( 3 );
	SetStyle( GetStyle() | WB_ITEMBORDER );
}

 SvxNumValueSet2::~SvxNumValueSet2()
{
	delete pVDev;
}

void SvxNumValueSet2::SetNumberingSettings(
	const Sequence<Sequence<PropertyValue> >& aNum,
	Reference<XNumberingFormatter>& xFormat,
	const Locale& rLocale	)
{
	aNumSettings = aNum;
	xFormatter = xFormat;
	aLocale = rLocale;
		if(aNum.getLength() > 9)
		SetStyle( GetStyle()|WB_VSCROLL);
	InsertItem( DEFAULT_NONE, DEFAULT_NONE - 1 );
	SetItemText( DEFAULT_NONE, SVX_RESSTR( RID_SVXSTR_NUMBULLET_NONE ));

    	for ( sal_Int32 i = 0; i < aNum.getLength(); i++ )
    	{
    		InsertItem( i + 1);
            	if( i < 8 )
            	{
			NBOTypeMgrBase* pNumbering = NBOutlineTypeMgrFact::CreateInstance(eNBOType::NUMBERING);
			if ( pNumbering )
			{
				SetItemText( i + 1, pNumbering->GetDescription(i));
			}
            	}
	}
}

void  SvxNumValueSet2::UserDraw( const UserDrawEvent& rUDEvt )
{
	const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
	const Color aBackColor = rStyleSettings.GetFieldColor();
	const Color aTextColor = rStyleSettings.GetFieldTextColor();

	OutputDevice*  pDev = rUDEvt.GetDevice();
	Rectangle aRect = rUDEvt.GetRect();
	sal_uInt32	nItemId = rUDEvt.GetItemId();
	long nRectWidth = aRect.GetWidth();
	long nRectHeight = aRect.GetHeight();
	Size aRectSize(nRectWidth, aRect.GetHeight());
	Point aBLPos = aRect.TopLeft();
	Font aOldFont = pDev->GetFont();
	Color aOldColor = pDev->GetLineColor();
	pDev->SetLineColor(aBackColor);
	Font aFont(OutputDevice::GetDefaultFont(
                DEFAULTFONT_UI_SANS, MsLangId::getSystemLanguage(), DEFAULTFONT_FLAGS_ONLYONE));

	Size aSize = aFont.GetSize();
	aSize.Height() = nRectHeight/5;
	aFont.SetColor(aTextColor);
	aFont.SetFillColor(aBackColor);
	aFont.SetSize( aSize );
	pDev->SetFont(aFont);
	pDev->SetLineColor(aTextColor);
	if(!pVDev)
	{
		// Die Linien werden nur einmalig in das VirtualDevice gepainted
		// nur die Gliederungspage bekommt es aktuell
		pVDev = new VirtualDevice(*pDev);
		pVDev->SetMapMode(pDev->GetMapMode());
		pVDev->EnableRTL( IsRTLEnabled() );
 		pVDev->SetOutputSize( aRectSize );
		aOrgRect = aRect;

		pVDev->SetLineColor( aBackColor );
		pVDev->SetFillColor( aBackColor );
		pVDev->DrawRect(aOrgRect);

		if(aBackColor == aLineColor)
			aLineColor.Invert();
		if(GetSettings().GetStyleSettings().GetHighContrastMode())
			pVDev->SetLineColor(aTextColor);
		else
			pVDev->SetLineColor(aLineColor);
		// Linien nur einmalig Zeichnen
		Point aStart(aBLPos.X() + nRectWidth *30 / 100,0);
		Point aEnd(aBLPos.X() + nRectWidth * 9 / 10,0);
		for( sal_uInt32 i = 11; i < 100; i += 33)
		{
			aStart.Y() = aEnd.Y() = aBLPos.Y() + nRectHeight * i / 100;
			pVDev->DrawLine(aStart, aEnd);
			aStart.Y() = aEnd.Y() = aBLPos.Y() + nRectHeight * (i + 11) / 100;
			pVDev->DrawLine(aStart, aEnd);
		}
	}
	if ( nItemId != DEFAULT_NONE)
		pDev->DrawOutDev(	aRect.TopLeft(), aRectSize,
							aOrgRect.TopLeft(), aRectSize,
							*pVDev );
	const OUString sValue(C2U(cValue));

	Point aStart(aBLPos.X() + nRectWidth / 9,0);
	if ( nItemId == DEFAULT_NONE)
	{
		String sText(SVX_RESSTR( RID_SVXSTR_NUMBULLET_NONE));
		Font aFont = pDev->GetFont();
		Size aSize = aFont.GetSize();
		aSize.Height() = nRectHeight/4;
		aFont.SetSize( aSize );
		pDev->SetFont(aFont);
		long nTextWidth = pDev->GetTextWidth(sText);
		long nTextHeight = pDev->GetTextHeight();
		//GVT refine
		while (nTextWidth>nRectWidth && aSize.Height()>4) {
			aSize.Height() = aSize.Height()*0.9;
			aFont.SetSize( aSize );
			pDev->SetFont(aFont);
			nTextWidth = pDev->GetTextWidth(sText);
		}
		Point aSStart(aBLPos.X()+(nRectWidth-nTextWidth)/2, aBLPos.Y() +(nRectHeight-nTextHeight)/2);
		pDev->DrawText(aSStart, sText);
		pDev->SetFont(aOldFont);
	}
	else
	{
		NBOTypeMgrBase* pNumbering = NBOutlineTypeMgrFact::CreateInstance(eNBOType::NUMBERING);
		if ( pNumbering && nItemId <= DEFAULT_BULLET_TYPES )
		{
			for( sal_uInt32 i = 0; i < 3; i++ )
			{
				sal_uInt32 nY = 11 + i * 33;
				aStart.Y() = aBLPos.Y() + nRectHeight  * nY / 100;
				String sText;
				sal_uInt16 nLvl = 0;
				SvxNumRule aTempRule( 0, 10, false );
				pNumbering->ApplyNumRule(aTempRule,nItemId -1,1<<nLvl);
				SvxNumberFormat aNumFmt(aTempRule.GetLevel(nLvl));
				sText=aNumFmt.GetNumStr(i+1);
				sText.Insert( aNumFmt.GetPrefix(), 0 );
				sText += aNumFmt.GetSuffix();
				aStart.X() = aBLPos.X() + 2;
				aStart.Y() -= pDev->GetTextHeight()/2;
				pDev->DrawText(aStart, sText);
			}
		}
		pDev->SetFont(aOldFont);
		pDev->SetLineColor(aOldColor);
	}
	//End
}

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

SvxNumValueSet3::SvxNumValueSet3( Window* pParent, const ResId& rResId) :
	ValueSet( pParent, rResId )
{
	SetColCount( 3 );
    SetLineCount( 4 );
	SetStyle( GetStyle() | WB_ITEMBORDER );
}

 SvxNumValueSet3::~SvxNumValueSet3()
{
}

void  SvxNumValueSet3::UserDraw( const UserDrawEvent& rUDEvt )
{
	Rectangle aRect = rUDEvt.GetRect();
	OutputDevice*  pDev = rUDEvt.GetDevice();
	sal_uInt32	nItemId = rUDEvt.GetItemId();

	long nRectHeight = aRect.GetHeight();
	long nRectWidth = aRect.GetWidth();
	Point aBLPos = aRect.TopLeft();
	NBOTypeMgrBase* pBullets = NBOutlineTypeMgrFact::CreateInstance(eNBOType::MIXBULLETS);
	if ( pBullets )
	{
		if ( nItemId <= DEFAULT_BULLET_TYPES ) {
			sal_uInt16 nLvl = 0;
			SvxNumRule aTempRule( 0, 10, false );
			pBullets->ApplyNumRule(aTempRule,nItemId -1,1<<nLvl);
			SvxNumberFormat aFmt(aTempRule.GetLevel(nLvl));
			sal_Int16 eNumType = aFmt.GetNumberingType();
			if( eNumType == SVX_NUM_CHAR_SPECIAL)
			{
				sal_Unicode cChar = aFmt.GetBulletChar();
			//End
				const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
				const Color aBackColor = rStyleSettings.GetFieldColor();
				const Color aTextColor = rStyleSettings.GetFieldTextColor();

				Font aOldFont = pDev->GetFont();
				Font aFont( lcl_GetDefaultBulletFont() );

				Size aSize = aFont.GetSize();
				aSize.Height() = nRectHeight*3/6;
				aFont.SetColor(aTextColor);
				aFont.SetFillColor(aBackColor);
				aFont.SetSize( aSize );
				pDev->SetFont(aFont);
				pDev->SetFillColor( aBackColor ); //wj

				String sText;
				sText = cChar;
				Font aOldBulletFont = pDev->GetFont();
				Font aBulletFnt(aFmt.GetBulletFont() ? *aFmt.GetBulletFont() : aOldBulletFont);
				Size aBulSize = aOldBulletFont.GetSize();
				aBulletFnt.SetSize(aBulSize);
				pDev->SetFont(aBulletFnt);
				long nTextWidth = pDev->GetTextWidth(sText);
	            long nTextHeight = pDev->GetTextHeight();
				Point aStart(aBLPos.X()+(nRectWidth-nTextWidth)/2, aBLPos.Y() +(nRectHeight-nTextHeight)/2);
				pDev->DrawText(aStart, sText);
				pDev->SetFont(aOldFont);
			}else if ( eNumType == SVX_NUM_BITMAP )
			{
				const SvxBrushItem* pBrushItem = aFmt.GetBrush();
				if(pBrushItem)
				{
					const Graphic* pGrf = pBrushItem->GetGraphic();
					if(pGrf)
					{
						Size aSize(nRectHeight*6/20, nRectHeight*6/20);
						Point aStart(aBLPos.X() + nRectWidth*7/20, aBLPos.Y() + nRectHeight*7/20);

						pGrf->Draw( pDev, aStart, aSize );
					}
				}
			}
		}else if ( nItemId == DEFAULT_NONE)
		{
			const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
			const Color aBackColor = rStyleSettings.GetFieldColor();
			const Color aTextColor = rStyleSettings.GetFieldTextColor();

			Font aOldFont = pDev->GetFont();
			Font aFont(OutputDevice::GetDefaultFont(DEFAULTFONT_UI_SANS, MsLangId::getSystemLanguage(), DEFAULTFONT_FLAGS_ONLYONE));
			Size aSize = aFont.GetSize();
			//aSize.Height() = nRectHeight/5;
			aSize.Height() = nRectHeight/4;
			aFont.SetColor(aTextColor);
			aFont.SetFillColor(aBackColor);
			aFont.SetSize( aSize );
			pDev->SetFont(aFont);
			pDev->SetFillColor( aBackColor );

			String sText(SVX_RESSTR( RID_SVXSTR_NUMBULLET_NONE));

			long nTextWidth = pDev->GetTextWidth(sText);
	        long nTextHeight = pDev->GetTextHeight();
			//GVT refine
			while (nTextWidth>nRectWidth && aSize.Height()>4) {
				aSize.Height() = aSize.Height()*0.9;
				aFont.SetSize( aSize );
				pDev->SetFont(aFont);
				nTextWidth = pDev->GetTextWidth(sText);
			}
			Point aStart(aBLPos.X()+(nRectWidth-nTextWidth)/2, aBLPos.Y() +(nRectHeight-nTextHeight)/2);
			pDev->DrawText(aStart, sText);

			pDev->SetFont(aOldFont);
		}
	}

}

} } // end of namespace svx::sidebar

/* vim: set noet sw=4 ts=4: */
