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