/**************************************************************
 * 
 * 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 "precompiled_sw.hxx"

#include <SidebarWin.hxx>
#include <SidebarWinAcc.hxx>
#include <PostItMgr.hxx>

#include <SidebarTxtControl.hxx>
#include <AnchorOverlayObject.hxx>
#include <ShadowOverlayObject.hxx>
#include <OverlayRanges.hxx>

#include <annotation.hrc>
#include <popup.hrc>
#include <docvw.hrc>
#include <app.hrc>
#include <access.hrc>

#include <viewopt.hxx>
#include <cmdid.h>

#include <editeng/fontitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/editview.hxx>
#include <editeng/outliner.hxx>
#include <editeng/editeng.hxx>
#include <editeng/eeitem.hxx>

#include <svl/zforlist.hxx>
#include <svl/undo.hxx>
#include <svl/stritem.hxx>

#include <sfx2/viewfrm.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>

#include <vcl/scrbar.hxx>
#include <vcl/svapp.hxx>
#include <vcl/menubtn.hxx>

#include <edtwin.hxx>
#include <view.hxx>
#include <docsh.hxx>
#include <wrtsh.hxx>
#include <doc.hxx>
#include <swmodule.hxx>
#include <langhelper.hxx>

#include <txtannotationfld.hxx>
#include <ndtxt.hxx>

#include <sw_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/shadowprimitive2d.hxx>

namespace css = ::com::sun::star;

namespace sw { namespace sidebarwindows {

#define METABUTTON_WIDTH        16
#define METABUTTON_HEIGHT       18
#define METABUTTON_AREA_WIDTH   30
#define POSTIT_META_HEIGHT  (sal_Int32)     30
#define POSTIT_MINIMUMSIZE_WITHOUT_META     50

#define POSTIT_SHADOW_BRIGHT    Color(180,180,180)
#define POSTIT_SHADOW_DARK      Color(83,83,83)

#define EMPTYSTRING             rtl::OUString::createFromAscii("")

/************** SwSidebarWin************************************/
SwSidebarWin::SwSidebarWin( SwEditWin& rEditWin,
                            WinBits nBits,
                            SwPostItMgr& aMgr,
                            SwPostItBits aBits,
                            SwSidebarItem& rSidebarItem )
    : Window(&rEditWin, nBits)
    , mrMgr(aMgr)
    , mrView( rEditWin.GetView() )
    , nFlags(aBits)
    , mnEventId(0)
    , mpOutlinerView(0)
    , mpOutliner(0)
    , mpSidebarTxtControl(0)
    , mpVScrollbar(0)
    , mpMetadataAuthor(0)
    , mpMetadataDate(0)
    , mpMenuButton(0)
    , mpAnchor( NULL )
    , mpShadow( NULL )
    , mpTextRangeOverlay( NULL )
    , mColorAnchor()
    , mColorDark()
    , mColorLight()
    , mChangeColor()
    , meSidebarPosition( sw::sidebarwindows::SIDEBAR_NONE )
    , mPosSize()
    , mAnchorRect()
    , mPageBorder( 0 )
    , mbMouseOver( false )
    , mLayoutStatus( SwPostItHelper::INVISIBLE )
    , mbReadonly( false )
    , mbIsFollow( false )
    , mrSidebarItem( rSidebarItem )
    , mpAnchorFrm( rSidebarItem.maLayoutInfo.mpAnchorFrm )
{
    mpShadow = ShadowOverlayObject::CreateShadowOverlayObject( mrView );
    if ( mpShadow )
    {
        mpShadow->setVisible(false);
    }

    mrMgr.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm),
                                  mrSidebarItem.GetFmtFld(),
                                  *this );
}

SwSidebarWin::~SwSidebarWin()
{
    mrMgr.DisconnectSidebarWinFromFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm),
                                       *this );

    Disable();

    if ( mpSidebarTxtControl )
    {
        if ( mpOutlinerView )
        {
            mpOutlinerView->SetWindow( 0 );
        }
        delete mpSidebarTxtControl;
        mpSidebarTxtControl = 0;
    }

    if ( mpOutlinerView )
    {
        delete mpOutlinerView;
        mpOutlinerView = 0;
    }

    if (mpOutliner)
    {
        delete mpOutliner;
        mpOutliner = 0;
    }

    if (mpMetadataAuthor)
    {
        mpMetadataAuthor->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );
        delete mpMetadataAuthor;
        mpMetadataAuthor = 0;
    }

    if (mpMetadataDate)
    {
        mpMetadataDate->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );
        delete mpMetadataDate;
        mpMetadataDate = 0;
    }

    if (mpVScrollbar)
    {
        mpVScrollbar->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );
        delete mpVScrollbar;
        mpVScrollbar = 0;
    }

    AnchorOverlayObject::DestroyAnchorOverlayObject( mpAnchor );
    mpAnchor = NULL;

    ShadowOverlayObject::DestroyShadowOverlayObject( mpShadow );
    mpShadow = NULL;

    delete mpTextRangeOverlay;
    mpTextRangeOverlay = NULL;

    delete mpMenuButton;
    mpMenuButton = 0;

    if (mnEventId)
        Application::RemoveUserEvent( mnEventId );
}

void SwSidebarWin::Paint( const Rectangle& rRect)
{
    Window::Paint(rRect);

    if (mpMetadataAuthor->IsVisible() )
    {
        //draw left over space
        if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
        {
            SetFillColor(COL_BLACK);
        }
        else
        {
            SetFillColor(mColorDark);
        }
        SetLineColor();
        DrawRect( PixelToLogic(
                Rectangle( Point( mpMetadataAuthor->GetPosPixel().X() +
                                    mpMetadataAuthor->GetSizePixel().Width(),
                                  mpMetadataAuthor->GetPosPixel().Y() ),
                           Size( GetMetaButtonAreaWidth(),
                                 mpMetadataAuthor->GetSizePixel().Height() +
                                    mpMetadataDate->GetSizePixel().Height() ) ) ) );
    }
}

void SwSidebarWin::SetPosSizePixelRect( long nX,
                                        long nY,
                                        long nWidth,
                                        long nHeight,
                                        const SwRect& aAnchorRect,
                                        const long aPageBorder)
{
    mPosSize = Rectangle(Point(nX,nY),Size(nWidth,nHeight));
    mAnchorRect = aAnchorRect;
    mPageBorder = aPageBorder;
}

void SwSidebarWin::SetSize( const Size& rNewSize )
{
    mPosSize.SetSize(rNewSize);
}

void SwSidebarWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize)
{
    mPosSize = Rectangle(aPoint,aSize);
}

void SwSidebarWin::TranslateTopPosition(const long aAmount)
{
    mPosSize.Move(0,aAmount);
}

void SwSidebarWin::ShowAnchorOnly(const Point &aPoint)
{
    HideNote();
    SetPosAndSize();
    if (mpAnchor)
    {
        mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
        mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y()));
        mpAnchor->SetAnchorState(AS_ALL);
        mpAnchor->setVisible(true);
    }
    if (mpShadow)
        mpShadow->setVisible(false);
}

SfxItemSet SwSidebarWin::DefaultItem()
{
    SfxItemSet aItem( mrView.GetDocShell()->GetPool() );
    aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT));
    aItem.Put(SvxFontItem(FAMILY_SWISS,GetSettings().GetStyleSettings().GetFieldFont().GetName(),
        EMPTYSTRING,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW,EE_CHAR_FONTINFO));
    return aItem;
}

void SwSidebarWin::InitControls()
{
    AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );

    // actual window which holds the user text
    mpSidebarTxtControl = new SidebarTxtControl( *this,
                                                 WB_NODIALOGCONTROL,
                                                 mrView, mrMgr );
    mpSidebarTxtControl->SetPointer(Pointer(POINTER_TEXT));

    // window controls for author and date
    mpMetadataAuthor = new Edit( this, 0 );
    mpMetadataAuthor->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) );
    mpMetadataAuthor->SetReadOnly();
    mpMetadataAuthor->AlwaysDisableInput(true);
    mpMetadataAuthor->SetCallHandlersOnInputDisabled(true);
    mpMetadataAuthor->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );
    // we should leave this setting alone, but for this we need a better layout algo
    // with variable meta size height
    {
        AllSettings aSettings = mpMetadataAuthor->GetSettings();
        StyleSettings aStyleSettings = aSettings.GetStyleSettings();
        Font aFont = aStyleSettings.GetFieldFont();
        aFont.SetHeight(8);
        aStyleSettings.SetFieldFont(aFont);
        aSettings.SetStyleSettings(aStyleSettings);
        mpMetadataAuthor->SetSettings(aSettings);
    }

    mpMetadataDate = new Edit( this, 0 );
    mpMetadataDate->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_DATE_NAME ) );
    mpMetadataDate->SetReadOnly();
    mpMetadataDate->AlwaysDisableInput(true);
    mpMetadataDate->SetCallHandlersOnInputDisabled(true);
    mpMetadataDate->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );
    // we should leave this setting alone, but for this we need a better layout algo
    // with variable meta size height
    {
        AllSettings aSettings = mpMetadataDate->GetSettings();
        StyleSettings aStyleSettings = aSettings.GetStyleSettings();
        Font aFont = aStyleSettings.GetFieldFont();
        aFont.SetHeight(8);
        aStyleSettings.SetFieldFont(aFont);
        aSettings.SetStyleSettings(aStyleSettings);
        mpMetadataDate->SetSettings(aSettings);
    }


    SwDocShell* aShell = mrView.GetDocShell();
    mpOutliner = new Outliner(&aShell->GetPool(),OUTLINERMODE_TEXTOBJECT);
    aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner );
    mpOutliner->SetUpdateMode( sal_True );
    Rescale();

    mpOutlinerView = new OutlinerView ( mpOutliner, mpSidebarTxtControl );
    mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT);
    mpOutliner->InsertView(mpOutlinerView );
    mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,1,1) ) );

    mpOutlinerView->SetAttribs(DefaultItem());

    // TODO: ??
    EEHorizontalTextDirection aDefHoriTextDir = Application::GetSettings().GetLayoutRTL() ? EE_HTEXTDIR_R2L : EE_HTEXTDIR_L2R;
    mpOutliner->SetDefaultHorizontalTextDirection( aDefHoriTextDir );

    //create Scrollbars
    mpVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG);
    mpVScrollbar->EnableNativeWidget(false);
    mpVScrollbar->EnableRTL( false );
    mpVScrollbar->SetScrollHdl(LINK(this, SwSidebarWin, ScrollHdl));
    mpVScrollbar->EnableDrag();
    mpVScrollbar->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) );

    const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
    sal_uLong nCntrl = mpOutliner->GetControlWord();
    // TODO: crash when AUTOCOMPLETE enabled
    nCntrl |= EE_CNTRL_MARKFIELDS | EE_CNTRL_PASTESPECIAL | EE_CNTRL_AUTOCORRECT  | EV_CNTRL_AUTOSCROLL | EE_CNTRL_URLSFXEXECUTE; // | EE_CNTRL_AUTOCOMPLETE;
    if (pVOpt->IsFieldShadings())
        nCntrl |= EE_CNTRL_MARKFIELDS;
    else
        nCntrl &= ~EE_CNTRL_MARKFIELDS;
    if (pVOpt->IsOnlineSpell())
        nCntrl |= EE_CNTRL_ONLINESPELLING;
    else
        nCntrl &= ~EE_CNTRL_ONLINESPELLING;
    mpOutliner->SetControlWord(nCntrl);

    sal_uInt16 aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor());
    SetColor( mrMgr.GetColorDark(aIndex),
              mrMgr.GetColorLight(aIndex),
              mrMgr.GetColorAnchor(aIndex));

    CheckMetaText();

    mpMenuButton = CreateMenuButton();

    SetLanguage(GetLanguage());
    GetOutlinerView()->StartSpeller();
    SetPostItText();
    Engine()->CompleteOnlineSpelling();

    mpSidebarTxtControl->Show();
    mpMetadataAuthor->Show();
    mpMetadataDate->Show();
    mpVScrollbar->Show();
}

void SwSidebarWin::CheckMetaText()
{
    const SvtSysLocale aSysLocale;
    const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData();
    String sMeta = GetAuthor();
    if (sMeta.Len() == 0)
    {
        sMeta = String(SW_RES(STR_NOAUTHOR));
    }
    else if (sMeta.Len() > 22)
    {
        sMeta.Erase(20);
        sMeta = sMeta + rtl::OUString::createFromAscii("...");
    }
    if ( mpMetadataAuthor->GetText() != sMeta )
    {
        mpMetadataAuthor->SetText(sMeta);
    }

    Date aDate = GetDate();
    if (aDate==Date())
    {
        sMeta = String(SW_RES(STR_POSTIT_TODAY));
    }
    else if (aDate == Date(Date()-1))
    {
        sMeta = String(SW_RES(STR_POSTIT_YESTERDAY));
    }
    else if (aDate.IsValid() )
    {
        sMeta = rLocalData.getDate(aDate);
    }
    else
    {
        sMeta = String(SW_RES(STR_NODATE));
    }
    if (GetTime()!=0)
    {
        sMeta = sMeta + rtl::OUString::createFromAscii(" ")  + rLocalData.getTime( GetTime(),false );
    }
    if ( mpMetadataDate->GetText() != sMeta )
    {
        mpMetadataDate->SetText(sMeta);
    }

}

void SwSidebarWin::Rescale()
{
    MapMode aMode = GetParent()->GetMapMode();
    aMode.SetOrigin( Point() );
    mpOutliner->SetRefMapMode( aMode );
    SetMapMode( aMode );
    mpSidebarTxtControl->SetMapMode( aMode );
    if ( mpMetadataAuthor )
    {
        Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() );
        sal_Int32 nHeight = aFont.GetHeight();
        nHeight = nHeight * aMode.GetScaleY().GetNumerator() / aMode.GetScaleY().GetDenominator();
        aFont.SetHeight( nHeight );
        mpMetadataAuthor->SetControlFont( aFont );
    }
    if ( mpMetadataDate )
    {
        Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() );
        sal_Int32 nHeight = aFont.GetHeight();
        nHeight = nHeight * aMode.GetScaleY().GetNumerator() / aMode.GetScaleY().GetDenominator();
        aFont.SetHeight( nHeight );
        mpMetadataDate->SetControlFont( aFont );
    }
}

void SwSidebarWin::SetPosAndSize()
{
    bool bChange = false;

    if (GetSizePixel() != mPosSize.GetSize())
    {
        bChange = true;
        SetSizePixel(mPosSize.GetSize());
        DoResize();
    }

    if (GetPosPixel().X() != mPosSize.TopLeft().X() || (abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 5) )
    {
        bChange = true;
        SetPosPixel(mPosSize.TopLeft());

        Point aLineStart;
        Point aLineEnd ;
        switch ( meSidebarPosition )
        {
            case sw::sidebarwindows::SIDEBAR_LEFT:
            {
                aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
                aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
            }
            break;
            case sw::sidebarwindows::SIDEBAR_RIGHT:
            {
                aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) );
                aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) );
            }
            break;
            default:
                ASSERT( false,
                        "<SwSidebarWin::SetPosAndSize()> - unexpected position of sidebar" );
            break;
        }

        if (!IsPreview())
        {
            if (mpAnchor)
            {
                mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
                                          basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
                                          basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
                                          basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
                                          basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15),
                                          basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
                                          basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()));
                mpAnchor->SetHeight(mAnchorRect.Height());
            }
            else
            {
                mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView,
                                                                           mAnchorRect,
                                                                           mPageBorder,
                                                                           aLineStart,
                                                                           aLineEnd,
                                                                           mColorAnchor );
                if ( mpAnchor )
                {
                    mpAnchor->SetHeight(mAnchorRect.Height());
                    mpAnchor->setVisible(true);
                    mpAnchor->SetAnchorState(AS_TRI);
                    if (HasChildPathFocus())
                    {
                        mpAnchor->setLineSolid(true);
                    }
                }
            }
        }
    }
    else
    {
        if ( mpAnchor &&
             ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) )
        {
            mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15),
                                      basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15),
                                      basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15),
                                      basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15),
                                      basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15));
        }
    }

    if (bChange)
    {
        Point aStart = EditWin()->PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
        Point aEnd = EditWin()->PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
        mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
    }

    if (mrMgr.ShowNotes())
    {
        if (IsFollow() && !HasChildPathFocus())
        {
            if ( mpAnchor )
            {
                mpAnchor->SetAnchorState(AS_END);
            }
        }
        else
        {
            if ( mpAnchor )
            {
                mpAnchor->SetAnchorState(AS_ALL);
            }
            SwSidebarWin* pWin = GetTopReplyNote();
            if ( pWin && pWin->Anchor() )
            {        
                pWin->Anchor()->SetAnchorState(AS_END);
            }
        }
    }

    // text range overlay
    if ( mrMgr.ShowNotes()
         && mrSidebarItem.maLayoutInfo.mnStartNodeIdx != 0
         && mrSidebarItem.maLayoutInfo.mnStartContent != STRING_NOTFOUND )
    {
        std::vector< basegfx::B2DRange > aAnnotationTextRanges;
        {
            const SwTxtAnnotationFld* pTxtAnnotationFld =
                dynamic_cast< const SwTxtAnnotationFld* >( mrSidebarItem.GetFmtFld().GetTxtFld() );
            if ( pTxtAnnotationFld != NULL
                 && pTxtAnnotationFld->GetpTxtNode() != NULL )
            {
                SwTxtNode* pTxtNode = pTxtAnnotationFld->GetpTxtNode();
                SwNodes& rNds = pTxtNode->GetDoc()->GetNodes();
                SwCntntNode* const pCntntNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetCntntNode();
                SwPosition aStartPos( *pCntntNd, mrSidebarItem.maLayoutInfo.mnStartContent );
                SwShellCrsr* pTmpCrsr = NULL;
                const bool bTableCrsrNeeded = pTxtNode->FindTableBoxStartNode() != pCntntNd->FindTableBoxStartNode();
                if ( bTableCrsrNeeded )
                {
                    SwShellTableCrsr* pTableCrsr = new SwShellTableCrsr( DocView().GetWrtShell(), aStartPos );
                    pTableCrsr->SetMark();
                    pTableCrsr->GetMark()->nNode = *pTxtNode;
                    pTableCrsr->GetMark()->nContent.Assign( pTxtNode, *(pTxtAnnotationFld->GetStart())+1 );
                    pTableCrsr->NewTableSelection();
                    pTmpCrsr = pTableCrsr;
                }
                else
                {
                    SwShellCrsr* pCrsr = new SwShellCrsr( DocView().GetWrtShell(), aStartPos );
                    pCrsr->SetMark();
                    pCrsr->GetMark()->nNode = *pTxtNode;
                    pCrsr->GetMark()->nContent.Assign( pTxtNode, *(pTxtAnnotationFld->GetStart())+1 );
                    pTmpCrsr = pCrsr;
                }
                ::boost::scoped_ptr<SwShellCrsr> pTmpCrsrForAnnotationTextRange( pTmpCrsr );

                pTmpCrsrForAnnotationTextRange->FillRects();

                for( sal_uInt16 a(0); a < pTmpCrsrForAnnotationTextRange->Count(); ++a )
                {
                    const SwRect aNextRect((*pTmpCrsrForAnnotationTextRange)[a]);
                    const Rectangle aPntRect(aNextRect.SVRect());

                    aAnnotationTextRanges.push_back(basegfx::B2DRange(
                        aPntRect.Left(), aPntRect.Top(),
                        aPntRect.Right() + 1, aPntRect.Bottom() + 1));
                }
            }
        }

        if ( mpTextRangeOverlay != NULL )
        {
            mpTextRangeOverlay->setRanges( aAnnotationTextRanges );
            if ( mpAnchor != NULL && mpAnchor->getLineSolid() )
            {
                mpTextRangeOverlay->ShowSolidBorder();
            }
            else
            {
                mpTextRangeOverlay->HideSolidBorder();
            }
        }
        else
        {
            mpTextRangeOverlay =
                sw::overlay::OverlayRanges::CreateOverlayRange(
                    DocView(),
                    mColorAnchor,
                    aAnnotationTextRanges,
                    mpAnchor != NULL ? mpAnchor->getLineSolid() : false );
        }
    }
    else
    {
        delete mpTextRangeOverlay;
        mpTextRangeOverlay = NULL;
    }
}

void SwSidebarWin::DoResize()
{
    long aTextHeight    =  LogicToPixel( mpOutliner->CalcTextSize()).Height();
    long aHeight        =  GetSizePixel().Height();
    unsigned long aWidth    =  GetSizePixel().Width();

    aHeight -= GetMetaHeight();
    mpMetadataAuthor->Show();
    mpMetadataDate->Show();
    mpSidebarTxtControl->SetQuickHelpText(EMPTYSTRING);

    if ((aTextHeight > aHeight) && !IsPreview())
    {   // we need vertical scrollbars and have to reduce the width
        aWidth -= GetScrollbarWidth();
        mpVScrollbar->Show();
    }
    else
    {
        mpVScrollbar->Hide();
    }

    {
        const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(),
                                            GetMetaHeight()/2 );
        mpMetadataAuthor->SetPosSizePixel( 0,
                                           aHeight,
                                           aSizeOfMetadataControls.Width(),
                                           aSizeOfMetadataControls.Height() );
        mpMetadataDate->SetPosSizePixel( 0,
                                         aHeight + aSizeOfMetadataControls.Height(),
                                         aSizeOfMetadataControls.Width(),
                                         aSizeOfMetadataControls.Height() );
    }

    mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ;
    mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,aWidth,aHeight) ) );
    if (!mpVScrollbar->IsVisible())
    {   // if we do not have a scrollbar anymore, we want to see the complete text
        mpOutlinerView->SetVisArea( PixelToLogic( Rectangle(0,0,aWidth,aHeight) ) );
    }

    if (!Application::GetSettings().GetLayoutRTL())
    {
        mpSidebarTxtControl->SetPosSizePixel(0, 0, aWidth, aHeight);
        mpVScrollbar->SetPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight);
    }
    else
    {
        mpSidebarTxtControl->SetPosSizePixel( ( (aTextHeight > aHeight) && !IsPreview()
                                      ? GetScrollbarWidth() : 0 ) , 0,
                                      aWidth, aHeight);
        mpVScrollbar->SetPosSizePixel( 0, 0, GetScrollbarWidth(), aHeight);
    }

    mpVScrollbar->SetVisibleSize( PixelToLogic(Size(0,aHeight)).Height() );
    mpVScrollbar->SetPageSize( PixelToLogic(Size(0,aHeight)).Height() * 8 / 10 );
    mpVScrollbar->SetLineSize( mpOutliner->GetTextHeight() / 10 );
    SetScrollbar();
    mpVScrollbar->SetRange( Range(0, mpOutliner->GetTextHeight()));

    //calculate rects for meta- button
    const Fraction& fx( GetMapMode().GetScaleX() );
    const Fraction& fy( GetMapMode().GetScaleY() );

    const Point aPos( mpMetadataAuthor->GetPosPixel());
    Rectangle aRectMetaButton;
    if (IsPreview())
    {
        aRectMetaButton = PixelToLogic(
            Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH*4+10)*fx.GetNumerator()/fx.GetDenominator(),
                              aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ),
                       Size( METABUTTON_WIDTH*4*fx.GetNumerator()/fx.GetDenominator(),
                             METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) );
    }
    else
    {
        aRectMetaButton = PixelToLogic(
            Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx.GetNumerator()/fx.GetDenominator(),
                              aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ),
                       Size( METABUTTON_WIDTH*fx.GetNumerator()/fx.GetDenominator(),
                             METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) );
    }

    {
        const Rectangle aRectMetaButtonPixel( LogicToPixel( aRectMetaButton ) );
        mpMenuButton->SetPosSizePixel( aRectMetaButtonPixel.Left(),
                                       aRectMetaButtonPixel.Top(),
                                       aRectMetaButtonPixel.GetWidth(),
                                       aRectMetaButtonPixel.GetHeight() );
    }
}

void SwSidebarWin::SetSizePixel( const Size& rNewSize )
{
    Window::SetSizePixel(rNewSize);

    if (mpShadow)
    {
        Point aStart = EditWin()->PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height()));
        Point aEnd = EditWin()->PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height()));
        mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y()));
    }
}

void SwSidebarWin::SetScrollbar()
{
    mpVScrollbar->SetThumbPos( mpOutlinerView->GetVisArea().Top()+ mpOutlinerView->GetEditView().GetCursor()->GetOffsetY());
}

void SwSidebarWin::ResizeIfNeccessary(long aOldHeight, long aNewHeight)
{
    if (aOldHeight != aNewHeight)
    {
        //check for lower border or next note
        long aBorder = mrMgr.GetNextBorder();
        if (aBorder != -1)
        {
            if (aNewHeight > GetMinimumSizeWithoutMeta())
            {
                long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight();
                if (aNewLowerValue < aBorder)
                    SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight()));
                else
                    SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y()));
                DoResize();
                Invalidate();
            }
            else
            {
                if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight())
                    SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight()));
                DoResize();
                Invalidate();
            }
        }
        else
        {
            DoResize();
            Invalidate();
        }
    }
    else
    {
        SetScrollbar();
    }
}

void SwSidebarWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor)
{
    mColorDark =  aColorDark;
    mColorLight = aColorLight;
    mColorAnchor = aColorAnchor;

    if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
    {
        {
            mpMetadataAuthor->SetControlBackground(mColorDark);
            AllSettings aSettings = mpMetadataAuthor->GetSettings();
            StyleSettings aStyleSettings = aSettings.GetStyleSettings();
            aStyleSettings.SetFieldTextColor(aColorAnchor);
            aSettings.SetStyleSettings(aStyleSettings);
            mpMetadataAuthor->SetSettings(aSettings);
        }

        {
            mpMetadataDate->SetControlBackground(mColorDark);
            AllSettings aSettings = mpMetadataDate->GetSettings();
            StyleSettings aStyleSettings = aSettings.GetStyleSettings();
            aStyleSettings.SetFieldTextColor(aColorAnchor);
            aSettings.SetStyleSettings(aStyleSettings);
            mpMetadataDate->SetSettings(aSettings);
        }

        AllSettings aSettings2 = mpVScrollbar->GetSettings();
        StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings();
        aStyleSettings2.SetButtonTextColor(Color(0,0,0));
        aStyleSettings2.SetCheckedColor(mColorLight); //hintergund
        aStyleSettings2.SetShadowColor(mColorAnchor);
        aStyleSettings2.SetFaceColor(mColorDark);
        aSettings2.SetStyleSettings(aStyleSettings2);
        mpVScrollbar->SetSettings(aSettings2);
    }
}

void SwSidebarWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition)
{
    meSidebarPosition = eSidebarPosition;
}

void SwSidebarWin::SetReadonly(sal_Bool bSet)
{
    mbReadonly = bSet;
    GetOutlinerView()->SetReadOnly(bSet);
}

void SwSidebarWin::SetLanguage(const SvxLanguageItem aNewItem)
{
    Link pLink = Engine()->GetModifyHdl();
    Engine()->SetModifyHdl( Link() );
    ESelection aOld = GetOutlinerView()->GetSelection();

    ESelection aNewSelection( 0, 0, (sal_uInt16)Engine()->GetParagraphCount()-1, USHRT_MAX );
    GetOutlinerView()->SetSelection( aNewSelection );
    SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs());
    aEditAttr.Put(aNewItem);
    GetOutlinerView()->SetAttribs( aEditAttr );

    GetOutlinerView()->SetSelection(aOld);
    Engine()->SetModifyHdl( pLink );

    const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
    sal_uLong nCntrl = Engine()->GetControlWord();
    // turn off
    if (!pVOpt->IsOnlineSpell())
        nCntrl &= ~EE_CNTRL_ONLINESPELLING;
    else
        nCntrl &= ~EE_CNTRL_ONLINESPELLING;
    Engine()->SetControlWord(nCntrl);

    //turn back on
    if (pVOpt->IsOnlineSpell())
        nCntrl |= EE_CNTRL_ONLINESPELLING;
    else
        nCntrl &= ~EE_CNTRL_ONLINESPELLING;
    Engine()->SetControlWord(nCntrl);

    Engine()->CompleteOnlineSpelling();
    Invalidate();
}

void SwSidebarWin::DataChanged( const DataChangedEvent& aEvent)
{
    Window::DataChanged( aEvent );
}

void SwSidebarWin::GetFocus()
{
    if (mpSidebarTxtControl)
        mpSidebarTxtControl->GrabFocus();
}

void SwSidebarWin::LoseFocus()
{
}

void SwSidebarWin::ShowNote()
{
    SetPosAndSize();
    if (!IsVisible())
        Window::Show();
    if (mpShadow && !mpShadow->isVisible())
        mpShadow->setVisible(true);
    if (mpAnchor && !mpAnchor->isVisible())
        mpAnchor->setVisible(true);
}

void SwSidebarWin::HideNote()
{
    if (IsVisible())
        Window::Hide();
    if (mpAnchor)
    {
        if (mrMgr.IsShowAnchor())
            mpAnchor->SetAnchorState(AS_TRI);
        else
            mpAnchor->setVisible(false);
    }
    if (mpShadow && mpShadow->isVisible())
        mpShadow->setVisible(false);
}

void SwSidebarWin::ActivatePostIt()
{
    mrMgr.AssureStdModeAtShell();

    mpOutliner->ClearModifyFlag();
    mpOutliner->GetUndoManager().Clear();

    CheckMetaText();
    SetViewState(VS_EDIT);
    GetOutlinerView()->ShowCursor();

    mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->IsInsMode());

    if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
        GetOutlinerView()->SetBackgroundColor(mColorDark);
}

void SwSidebarWin::DeactivatePostIt()
{
    // remove selection, #i87073#
    if (GetOutlinerView()->GetEditView().HasSelection())
    {
        ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection();
        aSelection.nEndPara = aSelection.nStartPara;
        aSelection.nEndPos = aSelection.nStartPos;
        GetOutlinerView()->GetEditView().SetSelection(aSelection);
    }

    mpOutliner->CompleteOnlineSpelling();

    SetViewState(VS_NORMAL);
    // write the visible text back into the SwField
    UpdateData();

    if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
        GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT);


    if ( !IsProtected() &&
         Engine()->GetEditEngine().GetText()==String(EMPTYSTRING) )
    {
        mnEventId = Application::PostUserEvent( LINK( this, SwSidebarWin, DeleteHdl), 0 );
    }
}

void SwSidebarWin::ToggleInsMode()
{
    if (!mrView.GetWrtShell().IsRedlineOn())
    {
        //change outliner
        mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode());
        //change documnet
        mrView.GetWrtShell().ToggleInsMode();
        //update statusbar
        SfxBindings &rBnd = mrView.GetViewFrame()->GetBindings();
        rBnd.Invalidate(SID_ATTR_INSERT);
        rBnd.Update(SID_ATTR_INSERT);
    }
}

void SwSidebarWin::ExecuteCommand(sal_uInt16 nSlot)
{
    mrMgr.AssureStdModeAtShell();

    switch (nSlot)
    {
        case FN_POSTIT:
        case FN_REPLY:
        {
            // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note
            // will be created
            if (Engine()->GetEditEngine().GetText() != String(EMPTYSTRING))
            {
                OutlinerParaObject* pPara = new OutlinerParaObject(*GetOutlinerView()->GetEditView().CreateTextObject());
                mrMgr.RegisterAnswer(pPara);
            }
            if (mrMgr.HasActiveSidebarWin())
                mrMgr.SetActiveSidebarWin(0);
            SwitchToFieldPos();
            mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT);
            break;
        }
        case FN_DELETE_COMMENT:

                //Delete(); // do not kill the parent of our open popup menu
                mnEventId = Application::PostUserEvent( LINK( this, SwSidebarWin, DeleteHdl), 0 );
            break;
        case FN_DELETE_ALL_NOTES:
        case FN_HIDE_ALL_NOTES:
            // not possible as slot as this would require that "this" is the active postit
            mrView.GetViewFrame()->GetBindings().Execute( nSlot, 0, 0, SFX_CALLMODE_ASYNCHRON );
            break;
        case FN_DELETE_NOTE_AUTHOR:
        case FN_HIDE_NOTE_AUTHOR:
        {
            // not possible as slot as this would require that "this" is the active postit
            SfxStringItem aItem( nSlot, GetAuthor() );
            const SfxPoolItem* aItems[2];
            aItems[0] = &aItem;
            aItems[1] = 0;
            mrView.GetViewFrame()->GetBindings().Execute( nSlot, aItems, 0, SFX_CALLMODE_ASYNCHRON );
        }
        default:
            mrView.GetViewFrame()->GetBindings().Execute( nSlot );
            break;
    }
}

SwEditWin*  SwSidebarWin::EditWin()
{
    return &mrView.GetEditWin();
}

long SwSidebarWin::GetPostItTextHeight()
{
    return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0;
}

void SwSidebarWin::SwitchToPostIt(sal_uInt16 aDirection)
{
    SwSidebarWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this);
    if (pPostIt)
        pPostIt->GrabFocus();
}

IMPL_LINK( SwSidebarWin, WindowEventListener, VclSimpleEvent*, pEvent )
{
    VclWindowEvent* pWinEvent = dynamic_cast<VclWindowEvent*>(pEvent);
    if ( pWinEvent )
    {
        if ( pWinEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
        {
            MouseEvent* pMouseEvt = (MouseEvent*)pWinEvent->GetData();
            if ( pMouseEvt->IsEnterWindow() )
            {
                mbMouseOver = true;
                if ( !HasFocus() )
                {
                    SetViewState(VS_VIEW);
                    Invalidate();
                }
            }
            else if ( pMouseEvt->IsLeaveWindow())
            {
                if (IsPreview())
                {
                    //doLazyDelete();
                }
                else
                {
                    mbMouseOver = false;
                    if ( !HasFocus() )
                    {
                        SetViewState(VS_NORMAL);
                        Invalidate();
                    }
                }
            }
        }
        else if ( pWinEvent->GetId() == VCLEVENT_WINDOW_ACTIVATE &&
                  pWinEvent->GetWindow() == mpSidebarTxtControl )
        {
            const sal_Bool bLockView = mrView.GetWrtShell().IsViewLocked();
            mrView.GetWrtShell().LockView( sal_True );

            if ( !IsPreview() )
            {
                mrMgr.SetActiveSidebarWin( this );
            }

            mrView.GetWrtShell().LockView( bLockView );
            mrMgr.MakeVisible( this );
        }
        else if ( pWinEvent->GetWindow() == mpSidebarTxtControl )
        {
            int i = 5;
            ++i;
        }
    }
    return sal_True;
}

void SwSidebarWin::Delete()
{
    if ( mrMgr.GetActiveSidebarWin() == this)
    {
        mrMgr.SetActiveSidebarWin(0);
        // if the note is empty, the previous line will send a delete event, but we are already there
        if (mnEventId)
        {
            Application::RemoveUserEvent( mnEventId );
            mnEventId = 0;
        }
    }
}

IMPL_LINK(SwSidebarWin, ScrollHdl, ScrollBar*, pScroll)
{
    long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos();
    GetOutlinerView()->Scroll( 0, nDiff );
    return 0;
}

IMPL_LINK(SwSidebarWin, ModifyHdl, void*, pVoid)
{
    // no warnings, please
    pVoid=0;
    mrView.GetDocShell()->SetModified(sal_True);
    return 0;
}

IMPL_LINK(SwSidebarWin, DeleteHdl, void*, pVoid)
{
    // no warnings, please
    pVoid=0;
    mnEventId = 0;
    Delete();
    return 0;
}


void SwSidebarWin::ResetAttributes()
{
    mpOutlinerView->RemoveAttribsKeepLanguages(sal_True);
    mpOutliner->RemoveFields(sal_True);
    mpOutlinerView->SetAttribs(DefaultItem());
}

sal_Int32 SwSidebarWin::GetScrollbarWidth()
{
    return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10;
}

sal_Int32 SwSidebarWin::GetMetaButtonAreaWidth()
{
    const Fraction& f( GetMapMode().GetScaleX() );
    if (IsPreview())
        return 3 * METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator();
    else
        return METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator();
}

sal_Int32 SwSidebarWin::GetMetaHeight()
{
    const Fraction& f( GetMapMode().GetScaleY() );
    return POSTIT_META_HEIGHT * f.GetNumerator() / f.GetDenominator();
}

sal_Int32 SwSidebarWin::GetMinimumSizeWithMeta()
{
    return mrMgr.GetMinimumSizeWithMeta();
}

sal_Int32 SwSidebarWin::GetMinimumSizeWithoutMeta()
{
    const Fraction& f( GetMapMode().GetScaleY() );
    return POSTIT_MINIMUMSIZE_WITHOUT_META * f.GetNumerator() / f.GetDenominator();
}

void SwSidebarWin::SetSpellChecking()
{
    const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions();
    sal_uLong nCntrl = mpOutliner->GetControlWord();
    if (pVOpt->IsOnlineSpell())
        nCntrl |= EE_CNTRL_ONLINESPELLING;
    else
        nCntrl &= ~EE_CNTRL_ONLINESPELLING;
    mpOutliner->SetControlWord(nCntrl);

    mpOutliner->CompleteOnlineSpelling();
    Invalidate();
}

void SwSidebarWin::SetViewState(ViewState bViewState)
{
    switch (bViewState)
    {
        case VS_EDIT:
        {
            if (mpAnchor)
            {
                mpAnchor->SetAnchorState(AS_ALL);
                SwSidebarWin* pWin = GetTopReplyNote();
                // --> OD 2010-06-03 #i111964#
                if ( pWin && pWin->Anchor() )
                // <--                        
                {        
                    pWin->Anchor()->SetAnchorState(AS_END);
                }
                mpAnchor->setLineSolid(true);
                if ( mpTextRangeOverlay != NULL )
                {
                    mpTextRangeOverlay->ShowSolidBorder();
                }
            }
            if (mpShadow)
                mpShadow->SetShadowState(SS_EDIT);
            break;
        }
        case VS_VIEW:
        {
            if (mpAnchor)
            {
                mpAnchor->setLineSolid(true);
                if ( mpTextRangeOverlay != NULL )
                {
                    mpTextRangeOverlay->ShowSolidBorder();
                }
            }
            if (mpShadow)
                mpShadow->SetShadowState(SS_VIEW);
            break;
        }
        case VS_NORMAL:
        {
            if (mpAnchor)
            {
                if (IsFollow())
                {
                    // if there is no visible parent note, we want to see the complete anchor ??
                    //if (IsAnyStackParentVisible())
                    mpAnchor->SetAnchorState(AS_END);
                    SwSidebarWin* pTopWinSelf = GetTopReplyNote();
                    SwSidebarWin* pTopWinActive = mrMgr.HasActiveSidebarWin()
                                                  ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote()
                                                  : 0;
                    if ( pTopWinSelf && ( pTopWinSelf != pTopWinActive ) &&
                         pTopWinSelf->Anchor() )
                    {
                        if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() )
                        {
                            pTopWinSelf->Anchor()->setLineSolid(false);
                            if ( pTopWinSelf->TextRange() != NULL )
                            {
                                pTopWinSelf->TextRange()->HideSolidBorder();
                            }
                        }
                        pTopWinSelf->Anchor()->SetAnchorState(AS_ALL);
                    }
                }
                mpAnchor->setLineSolid(false);
                if ( mpTextRangeOverlay != NULL )
                {
                    mpTextRangeOverlay->HideSolidBorder();
                }
            }
            if ( mpShadow )
            {        
                mpShadow->SetShadowState(SS_NORMAL);
            }
            break;
        }
    }
}

SwSidebarWin* SwSidebarWin::GetTopReplyNote()
{
    SwSidebarWin* pTopNote = 0;
    SwSidebarWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : 0;
    while (pSidebarWin)
    {
        pTopNote = pSidebarWin;
        pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : 0;
    }
    return pTopNote;
}

void SwSidebarWin::SwitchToFieldPos()
{
    if ( mrMgr.GetActiveSidebarWin() == this )
            mrMgr.SetActiveSidebarWin(0);
    GotoPos();
    sal_uInt32 aCount = MoveCaret();
    if (aCount)
        mrView.GetDocShell()->GetWrtShell()->SwCrsrShell::Right(aCount, 0, sal_False);
    GrabFocusToDocument();
}

SvxLanguageItem SwSidebarWin::GetLanguage(void)
{
    return SvxLanguageItem(SwLangHelper::GetLanguage(mrView.GetWrtShell(),RES_CHRATR_LANGUAGE),RES_CHRATR_LANGUAGE);
}

void SwSidebarWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus,
                                      const Color& aChangeColor )
{
    if ( (mLayoutStatus != aLayoutStatus) ||
         (mChangeColor != aChangeColor) )
    {
        mLayoutStatus = aLayoutStatus;
        mChangeColor = aChangeColor;
        Invalidate();
    }
}

bool SwSidebarWin::HasScrollbar() const
{
    return mpVScrollbar != 0;
}

bool SwSidebarWin::IsScrollbarVisible() const
{
    return HasScrollbar() && mpVScrollbar->IsVisible();
}

void SwSidebarWin::ChangeSidebarItem( SwSidebarItem& rSidebarItem )
{
    const bool bAnchorChanged = mpAnchorFrm != rSidebarItem.maLayoutInfo.mpAnchorFrm;
    if ( bAnchorChanged )
    {
        mrMgr.DisconnectSidebarWinFromFrm( *(mpAnchorFrm), *this );
    }

    mrSidebarItem = rSidebarItem;
    mpAnchorFrm = mrSidebarItem.maLayoutInfo.mpAnchorFrm;

    if ( GetWindowPeer() )
    {
        SidebarWinAccessible* pAcc =
                        static_cast<SidebarWinAccessible*>( GetWindowPeer() );
        ASSERT( dynamic_cast<SidebarWinAccessible*>( GetWindowPeer() ),
                "<SwSidebarWin::ChangeSidebarItem(..)> - unexpected type of window peer -> crash possible!" );
        pAcc->ChangeSidebarItem( mrSidebarItem );
    }

    if ( bAnchorChanged )
    {
        mrMgr.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm),
                                      mrSidebarItem.GetFmtFld(),
                                      *this );
    }
}

css::uno::Reference< css::accessibility::XAccessible > SwSidebarWin::CreateAccessible()
{
    SidebarWinAccessible* pAcc( new SidebarWinAccessible( *this,
                                                          mrView.GetWrtShell(),
                                                          mrSidebarItem ) );
    css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc );
    SetWindowPeer( xWinPeer, pAcc );

    css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY );
    return xAcc;
}

} } // eof of namespace sw::sidebarwindows

/********** SwRedComment**************/
/*
SwRedComment::SwRedComment( Window* pParent, WinBits nBits,SwPostItMgr* aMgr,SwPostItBits aBits,SwRedline* pRed)
    : SwSidebarWin(pParent,nBits,aMgr,aBits),
    pRedline(pRed)
{
}

void SwRedComment::SetPopup()
{
    mpButtonPopup = new PopupMenu(SW_RES(MN_REDCOMMENT_BUTTON));
    //mpButtonPopup->SetMenuFlags(MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES);
}

void SwRedComment::UpdateData()
{
    if ( Engine()->IsModified() )
    {
        // so we get a new layout of notes (Anchor position is still the same and we would otherwise not get one)
        Mgr()->SetLayout();
        // SetRedline is calling SetModified already
        DocView()->GetWrtShell().SetRedlineComment(Engine()->GetEditEngine().GetText());
    }
    Engine()->ClearModifyFlag();
    Engine()->GetUndoManager().Clear();
}

void SwRedComment::SetPostItText()
{
    Engine()->SetModifyHdl( Link() );
    Engine()->EnableUndo( sal_False );

    Engine()->Clear();
    View()->SetAttribs(DefaultItem());
    View()->InsertText(pRedline->GetComment(),false);

    Engine()->ClearModifyFlag();
    Engine()->GetUndoManager().Clear();
    Engine()->EnableUndo( sal_True );
    Engine()->SetModifyHdl( LINK( this, SwSidebarWin, ModifyHdl ) );
    Invalidate();
}

void SwRedComment::DeactivatePostIt()
{
    SwSidebarWin::DeactivatePostIt();
    // current Redline is still selected
    DocView()->GetWrtShellPtr()->ClearMark();
}

void SwRedComment::ActivatePostIt()
{
    SwSidebarWin::ActivatePostIt();

    // do we want the redline selected?
    // otherwise, SwRedComment::ActivatePostIt() as well as SwRedComment::DeactivatePostIt()
    // can be thrown out completly
    DocView()->GetDocShell()->GetWrtShell()->GotoRedline(
        DocView()->GetDocShell()->GetWrtShell()->FindRedlineOfData(pRedline->GetRedlineData()),true);
}

void SwRedComment::MouseButtonDown( const MouseEvent& rMEvt )
{
    if (mRectMetaButton.IsInside(PixelToLogic(rMEvt.GetPosPixel())) && rMEvt.IsLeft())
    {
        ExecuteCommand( mpButtonPopup->Execute( this,Rectangle(LogicToPixel(mRectMetaButton.BottomLeft()),LogicToPixel(mRectMetaButton.BottomLeft())),POPUPMENU_EXECUTE_DOWN | POPUPMENU_NOMOUSEUPCLOSE) );
    }
}

void SwRedComment::Delete()
{
    SwSidebarWin::Delete();
    // we are not necessarily on our redline, so let's move there
    GotoPos();
    DocView()->GetWrtShell().SetRedlineComment(EMPTYSTRING);
    DocView()->GetWrtShell().ClearMark();
    // so we get a new layout of notes (Anchor position is still the same and we would otherwise not get one)
    Mgr()->SetLayout();
    Mgr()->RemoveItem(pRedline);
}

void SwRedComment::GotoPos()
{
    DocView()->GetDocShell()->GetWrtShell()->GotoRedline(
        DocView()->GetDocShell()->GetWrtShell()->FindRedlineOfData(pRedline->GetRedlineData()));
}

String SwRedComment::GetAuthor()
{
    return pRedline->GetAuthorString();
}

Date SwRedComment::GetDate()
{
    return pRedline->GetTimeStamp().GetDate();
}

Time SwRedComment::GetTime()
{
    return pRedline->GetTimeStamp().GetTime();
}

bool SwRedComment::IsProtected()
{
    return SwSidebarWin::IsProtected() || pRedline->Start()->nNode.GetNode().GetTxtNode()->IsInProtectSect();
}
*/
