/**************************************************************
 *
 * 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_svx.hxx"
#include <svx/frmsel.hxx>

#include <algorithm>
#include <math.h>
#include "frmselimpl.hxx"
#include "AccessibleFrameSelector.hxx"
#include <svx/dialmgr.hxx>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLESTATETYPE_HDL_
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#endif

#ifndef _SVX_DIALOGS_HRC
#include <svx/dialogs.hrc>
#endif
#ifndef SVX_FRMSEL_HRC
#include "frmsel.hrc"
#endif

#include <tools/rcid.h>

namespace svx {

using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::com::sun::star::accessibility::XAccessible;
using namespace ::com::sun::star::accessibility;
// ============================================================================
// global functions from framebordertype.hxx

FrameBorderType GetFrameBorderTypeFromIndex( size_t nIndex )
{
    DBG_ASSERT( nIndex < (size_t)FRAMEBORDERTYPE_COUNT,
        "svx::GetFrameBorderTypeFromIndex - invalid index" );
    return static_cast< FrameBorderType >( nIndex + 1 );
}

size_t GetIndexFromFrameBorderType( FrameBorderType eBorder )
{
    DBG_ASSERT( eBorder != FRAMEBORDER_NONE,
        "svx::GetIndexFromFrameBorderType - invalid frame border type" );
    return static_cast< size_t >( eBorder ) - 1;
}

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

namespace {

/** Space between outer control border and any graphical element of the control. */
const long FRAMESEL_GEOM_OUTER    = 2;

/** Space between arrows and usable inner area. */
const long FRAMESEL_GEOM_INNER    = 3;

/** Maximum width to draw a frame border style. */
const long FRAMESEL_GEOM_WIDTH    = 9;

/** Additional margin for click area of outer lines. */
const long FRAMESEL_GEOM_ADD_CLICK_OUTER = 5;

/** Additional margin for click area of inner lines. */
const long FRAMESEL_GEOM_ADD_CLICK_INNER = 2;

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

static const frame::Style   OBJ_FRAMESTYLE_DONTCARE( 3, 0, 0 );
static const FrameBorder    OBJ_FRAMEBORDER_NONE( FRAMEBORDER_NONE );

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

/** Returns the corresponding flag for a frame border. */
FrameSelFlags lclGetFlagFromType( FrameBorderType eBorder )
{
    switch( eBorder )
    {
        case FRAMEBORDER_LEFT:      return FRAMESEL_LEFT;
        case FRAMEBORDER_RIGHT:     return FRAMESEL_RIGHT;
        case FRAMEBORDER_TOP:       return FRAMESEL_TOP;
        case FRAMEBORDER_BOTTOM:    return FRAMESEL_BOTTOM;
        case FRAMEBORDER_HOR:       return FRAMESEL_INNER_HOR;
        case FRAMEBORDER_VER:       return FRAMESEL_INNER_VER;
        case FRAMEBORDER_TLBR:      return FRAMESEL_DIAG_TLBR;
        case FRAMEBORDER_BLTR:      return FRAMESEL_DIAG_BLTR;
        case FRAMEBORDER_NONE : break;
    }
    return FRAMESEL_NONE;
}

/** Converts an SvxBorderLine line width (in twips) to a pixel line width. */
inline sal_uInt16 lclGetPixel( sal_uInt16 nWidth )
{
    // convert all core styles expect 0 to a visible UI style (at least 1 pixel), map 1pt to 1pixel
    return nWidth ? std::min< sal_uInt16 >( std::max< sal_uInt16 >( (nWidth + 5) / 20, 1 ), FRAMESEL_GEOM_WIDTH ) : 0;
}

/** Merges the rSource polypolygon into the rDest polypolygon. */
inline void lclPolyPolyUnion( PolyPolygon& rDest, const PolyPolygon& rSource )
{
    const PolyPolygon aTmp( rDest );
    aTmp.GetUnion( rSource, rDest );
}

} // namespace

// ============================================================================
// FrameBorder
// ============================================================================

FrameBorder::FrameBorder( FrameBorderType eType ) :
    meType( eType ),
    meState( FRAMESTATE_HIDE ),
    meKeyLeft( FRAMEBORDER_NONE ),
    meKeyRight( FRAMEBORDER_NONE ),
    meKeyTop( FRAMEBORDER_NONE ),
    meKeyBottom( FRAMEBORDER_NONE ),
    mbEnabled( false ),
    mbSelected( false )
{
}

void FrameBorder::Enable( FrameSelFlags nFlags )
{
    mbEnabled = (nFlags & lclGetFlagFromType( meType )) != 0;
    if( !mbEnabled )
        SetState( FRAMESTATE_HIDE );
}

void FrameBorder::SetCoreStyle( const SvxBorderLine* pStyle )
{
    if( pStyle )
        maCoreStyle = *pStyle;
    else
        maCoreStyle = SvxBorderLine();

    // from twips to points
    maUIStyle.Set( maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH, true );
    meState = maUIStyle.Prim() ? FRAMESTATE_SHOW : FRAMESTATE_HIDE;
}

void FrameBorder::SetState( FrameBorderState eState )
{
    meState = eState;
    switch( meState )
    {
        case FRAMESTATE_SHOW:
            DBG_ERRORFILE( "svx::FrameBorder::SetState - use SetCoreStyle to make border visible" );
        break;
        case FRAMESTATE_HIDE:
            maCoreStyle = SvxBorderLine();
            maUIStyle.Clear();
        break;
        case FRAMESTATE_DONTCARE:
            maCoreStyle = SvxBorderLine();
            maUIStyle = OBJ_FRAMESTYLE_DONTCARE;
        break;
	}
}

void FrameBorder::AddFocusPolygon( const Polygon& rFocus )
{
    lclPolyPolyUnion( maFocusArea, rFocus );
}

void FrameBorder::MergeFocusToPolyPolygon( PolyPolygon& rPPoly ) const
{
    lclPolyPolyUnion( rPPoly, maFocusArea );
}

void FrameBorder::AddClickRect( const Rectangle& rRect )
{
    lclPolyPolyUnion( maClickArea, Polygon( rRect ) );
}

bool FrameBorder::ContainsClickPoint( const Point& rPos ) const
{
    return Region( maClickArea ).IsInside( rPos );
}

void FrameBorder::MergeClickAreaToPolyPolygon( PolyPolygon& rPPoly ) const
{
    lclPolyPolyUnion( rPPoly, maClickArea );
}

Rectangle FrameBorder::GetClickBoundRect() const
{
    return maClickArea.GetBoundRect();
}

void FrameBorder::SetKeyboardNeighbors(
        FrameBorderType eLeft, FrameBorderType eRight, FrameBorderType eTop, FrameBorderType eBottom )
{
    meKeyLeft = eLeft;
    meKeyRight = eRight;
    meKeyTop = eTop;
    meKeyBottom = eBottom;
}

FrameBorderType FrameBorder::GetKeyboardNeighbor( sal_uInt16 nKeyCode ) const
{
    FrameBorderType eBorder = FRAMEBORDER_NONE;
    switch( nKeyCode )
    {
        case KEY_LEFT:  eBorder = meKeyLeft;      break;
        case KEY_RIGHT: eBorder = meKeyRight;     break;
        case KEY_UP:    eBorder = meKeyTop;       break;
        case KEY_DOWN:  eBorder = meKeyBottom;    break;
        default:        DBG_ERRORFILE( "svx::FrameBorder::GetKeyboardNeighbor - unknown key code" );
    }
    return eBorder;
}

// ============================================================================
// FrameSelectorImpl
// ============================================================================

FrameSelectorImpl::FrameSelectorImpl( FrameSelector& rFrameSel ) :
    Resource( SVX_RES( RID_SVXSTR_BORDER_CONTROL ) ),
    mrFrameSel( rFrameSel ),
    maILArrows( 16 ),
    maLeft( FRAMEBORDER_LEFT ),
    maRight( FRAMEBORDER_RIGHT ),
    maTop( FRAMEBORDER_TOP ),
    maBottom( FRAMEBORDER_BOTTOM ),
    maHor( FRAMEBORDER_HOR ),
    maVer( FRAMEBORDER_VER ),
    maTLBR( FRAMEBORDER_TLBR ),
    maBLTR( FRAMEBORDER_BLTR ),
    mnFlags( FRAMESEL_OUTER ),
    mbHor( false ),
    mbVer( false ),
    mbTLBR( false ),
    mbBLTR( false ),
    mbFullRepaint( true ),
    mbAutoSelect( true ),
    mbClicked( false ),
    mbHCMode( false ),
    mpAccess( 0 ),
    maChildVec( 8, static_cast< a11y::AccFrameSelector* >( 0 ) ),
    mxChildVec( 8 )
{
    FreeResource();

    maAllBorders.resize( FRAMEBORDERTYPE_COUNT, 0 );
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_LEFT   ) ] = &maLeft;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_RIGHT  ) ] = &maRight;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TOP    ) ] = &maTop;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BOTTOM ) ] = &maBottom;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_HOR    ) ] = &maHor;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_VER    ) ] = &maVer;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TLBR   ) ] = &maTLBR;
    maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BLTR   ) ] = &maBLTR;
#if OSL_DEBUG_LEVEL >= 2
    {
        bool bOk = true;
        for( FrameBorderCIter aIt( maAllBorders ); bOk && aIt.Is(); bOk = (*aIt != 0), ++aIt );
        DBG_ASSERT( bOk, "svx::FrameSelectorImpl::FrameSelectorImpl - missing entry in maAllBorders" );
    }
#endif
    //                             left neighbor     right neighbor     upper neighbor    lower neighbor
    maLeft.SetKeyboardNeighbors(   FRAMEBORDER_NONE, FRAMEBORDER_TLBR,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
    maRight.SetKeyboardNeighbors(  FRAMEBORDER_BLTR, FRAMEBORDER_NONE,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
    maTop.SetKeyboardNeighbors(    FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_NONE, FRAMEBORDER_TLBR );
    maBottom.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_BLTR, FRAMEBORDER_NONE );
    maHor.SetKeyboardNeighbors(    FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_TLBR, FRAMEBORDER_BLTR );
    maVer.SetKeyboardNeighbors(    FRAMEBORDER_TLBR, FRAMEBORDER_BLTR,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
    maTLBR.SetKeyboardNeighbors(   FRAMEBORDER_LEFT, FRAMEBORDER_VER,   FRAMEBORDER_TOP,  FRAMEBORDER_HOR );
    maBLTR.SetKeyboardNeighbors(   FRAMEBORDER_VER,  FRAMEBORDER_RIGHT, FRAMEBORDER_HOR,  FRAMEBORDER_BOTTOM );
}

FrameSelectorImpl::~FrameSelectorImpl()
{
    if( mpAccess )
        mpAccess->Invalidate();
    for( AccessibleImplVec::iterator aIt = maChildVec.begin(), aEnd = maChildVec.end(); aIt != aEnd; ++aIt )
        if( *aIt )
            (*aIt)->Invalidate();
}

// initialization -------------------------------------------------------------

void FrameSelectorImpl::Initialize( FrameSelFlags nFlags )
{
    mnFlags = nFlags;

    maEnabBorders.clear();
    for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
    {
        (*aIt)->Enable( mnFlags );
        if( (*aIt)->IsEnabled() )
            maEnabBorders.push_back( *aIt );
    }
    mbHor = maHor.IsEnabled();
    mbVer = maVer.IsEnabled();
    mbTLBR = maTLBR.IsEnabled();
    mbBLTR = maBLTR.IsEnabled();

    InitVirtualDevice();
}

void FrameSelectorImpl::InitColors()
{
    const StyleSettings& rSett = mrFrameSel.GetSettings().GetStyleSettings();
    maBackCol = rSett.GetFieldColor();
    mbHCMode = rSett.GetHighContrastMode();
    maArrowCol = rSett.GetFieldTextColor();
    maMarkCol.operator=( maBackCol ).Merge( maArrowCol, mbHCMode ? 0x80 : 0xC0 );
    maHCLineCol = rSett.GetLabelTextColor();
}

void FrameSelectorImpl::InitArrowImageList()
{
    /* Build the arrow images bitmap with current colors. */
	Color pColorAry1[3];
	Color pColorAry2[3];
	pColorAry1[0] = Color( 0, 0, 0 );
	pColorAry2[0] = maArrowCol;       // black -> arrow color
	pColorAry1[1] = Color( 0, 255, 0 );
	pColorAry2[1] = maMarkCol;        // green -> marker color
	pColorAry1[2] = Color( 255, 0, 255 );
	pColorAry2[2] = maBackCol;       // magenta -> background

	GetRes( SVX_RES( RID_SVXSTR_BORDER_CONTROL ).SetRT( RSC_RESOURCE ) );
	maILArrows.InsertFromHorizontalBitmap(
		SVX_RES( BMP_FRMSEL_ARROWS ), 16, NULL, pColorAry1, pColorAry2, 3);
	FreeResource();
    DBG_ASSERT( maILArrows.GetImageSize().Height() == maILArrows.GetImageSize().Width(),
        "svx::FrameSelectorImpl::InitArrowImageList - images are not squarish" );
    mnArrowSize = maILArrows.GetImageSize().Height();
}

void FrameSelectorImpl::InitGlobalGeometry()
{
    Size aCtrlSize( mrFrameSel.CalcOutputSize( mrFrameSel.GetSizePixel() ) );
    /*  nMinSize is the lower of width and height (control will always be squarish).
        FRAMESEL_GEOM_OUTER is the minimal distance between inner control border
        and any element. */
    long nMinSize = Min( aCtrlSize.Width(), aCtrlSize.Height() ) - 2 * FRAMESEL_GEOM_OUTER;
    /*  nFixedSize is the size all existing elements need in one direction:
        the diag. arrow, space betw. arrow and frame border, outer frame border,
        inner frame border, other outer frame border, space betw. frame border
        and arrow, the other arrow. */
    long nFixedSize = 2 * mnArrowSize + 2 * FRAMESEL_GEOM_INNER + 3 * FRAMESEL_GEOM_WIDTH;
    /*  nBetwBordersSize contains the size between an outer and inner frame border (made odd). */
    long nBetwBordersSize = (((nMinSize - nFixedSize) / 2) - 1) | 1;

    /*  The final size of the usable area. */
    mnCtrlSize = 2 * nBetwBordersSize + nFixedSize;
    maVirDev.SetOutputSizePixel( Size( mnCtrlSize, mnCtrlSize ) );

    /*  Center the virtual device in the control. */
    maVirDevPos = Point( (aCtrlSize.Width() - mnCtrlSize) / 2, (aCtrlSize.Height() - mnCtrlSize) / 2 );
}

void FrameSelectorImpl::InitBorderGeometry()
{
    size_t nCol, nCols, nRow, nRows;

    // Global border geometry values ------------------------------------------

    /*  mnLine* is the middle point inside a frame border (i.e. mnLine1 is mid X inside left border). */
    mnLine1 = mnArrowSize + FRAMESEL_GEOM_INNER + FRAMESEL_GEOM_WIDTH / 2;
    mnLine2 = mnCtrlSize / 2;
    mnLine3 = 2 * mnLine2 - mnLine1;

    // Frame helper array -----------------------------------------------------

    maArray.Initialize( mbVer ? 2 : 1, mbHor ? 2 : 1 );
    maArray.SetUseDiagDoubleClipping( true );

    maArray.SetXOffset( mnLine1 );
    maArray.SetAllColWidths( (mbVer ? mnLine2 : mnLine3) - mnLine1 );

    maArray.SetYOffset( mnLine1 );
    maArray.SetAllRowHeights( (mbHor ? mnLine2 : mnLine3) - mnLine1 );

    Rectangle aTLRect( maArray.GetCellRect( 0, 0 ) );

    // Focus polygons ---------------------------------------------------------

    /*  Width for focus rectangles from center of frame borders. */
    mnFocusOffs = FRAMESEL_GEOM_WIDTH / 2 + 1;

    maLeft.AddFocusPolygon(   Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine1 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
    maVer.AddFocusPolygon(    Rectangle( mnLine2 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine2 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
    maRight.AddFocusPolygon(  Rectangle( mnLine3 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
    maTop.AddFocusPolygon(    Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine1 + mnFocusOffs ) );
    maHor.AddFocusPolygon(    Rectangle( mnLine1 - mnFocusOffs, mnLine2 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine2 + mnFocusOffs ) );
    maBottom.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine3 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );

    for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
    {
        for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
        {
            Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
            long nDiagFocusOffsX = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetHorDiagAngle( nCol, nRow ) );
            long nDiagFocusOffsY = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetVerDiagAngle( nCol, nRow ) );

            std::vector< Point > aFocusVec;
            aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Top()    + nDiagFocusOffsY ) );
            aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Top()    - mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Left()  + nDiagFocusOffsX, aRect.Top()    - mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Bottom() - nDiagFocusOffsY ) );
            aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Bottom() + mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs     ) );
            maTLBR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );

            aFocusVec.clear();
            aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Top()    + nDiagFocusOffsY ) );
            aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Top()    - mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Top()    - mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Bottom() - nDiagFocusOffsY ) );
            aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Bottom() + mnFocusOffs     ) );
            aFocusVec.push_back( Point( aRect.Left()  + nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs     ) );
            maBLTR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );
        }
    }

    // Click areas ------------------------------------------------------------

    for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
        (*aIt)->ClearClickArea();

    /*  Additional space for click area: is added to the space available to draw
        the frame borders. For instance left frame border:
        - To left, top, and bottom always big additional space (outer area).
        - To right: Dependent on existence of inner vertical frame border
            (if enabled, use less space).
     */
    long nClO = FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_OUTER;
    long nClI = (mbTLBR && mbBLTR) ? (FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_INNER) : nClO;
    long nClH = mbHor ? nClI : nClO;            // additional space dependent of horizontal inner border
    long nClV = mbVer ? nClI : nClO;            // additional space dependent of vertical inner border

    maLeft.AddClickRect(   Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine1 + nClV, mnLine3 + nClO ) );
    maVer.AddClickRect(    Rectangle( mnLine2 - nClI, mnLine1 - nClO, mnLine2 + nClI, mnLine3 + nClO ) );
    maRight.AddClickRect(  Rectangle( mnLine3 - nClV, mnLine1 - nClO, mnLine3 + nClO, mnLine3 + nClO ) );
    maTop.AddClickRect(    Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine3 + nClO, mnLine1 + nClH ) );
    maHor.AddClickRect(    Rectangle( mnLine1 - nClO, mnLine2 - nClI, mnLine3 + nClO, mnLine2 + nClI ) );
    maBottom.AddClickRect( Rectangle( mnLine1 - nClO, mnLine3 - nClH, mnLine3 + nClO, mnLine3 + nClO ) );

    /*  Diagonal frame borders use the remaining space between outer and inner frame borders. */
    if( mbTLBR || mbBLTR )
    {
        for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
        {
            for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
            {
                // the usable area between horizontal/vertical frame borders of current quadrant
                Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
                aRect.Left() += nClV + 1;
                aRect.Right() -= nClV + 1;
                aRect.Top() += nClH + 1;
                aRect.Bottom() -= nClH + 1;

                /*  Both diagonal frame borders enabled. */
                if( mbTLBR && mbBLTR )
                {
                    // single areas
                    Point aMid( aRect.Center() );
                    maTLBR.AddClickRect( Rectangle( aRect.TopLeft(), aMid ) );
                    maTLBR.AddClickRect( Rectangle( aMid + Point( 1, 1 ), aRect.BottomRight() ) );
                    maBLTR.AddClickRect( Rectangle( aRect.Left(), aMid.Y() + 1, aMid.X(), aRect.Bottom() ) );
                    maBLTR.AddClickRect( Rectangle( aMid.X() + 1, aRect.Top(), aRect.Right(), aMid.Y() ) );
                    // centered rectangle for both frame borders
                    Rectangle aMidRect( aRect.TopLeft(), Size( aRect.GetWidth() / 3, aRect.GetHeight() / 3 ) );
                    aMidRect.Move( (aRect.GetWidth() - aMidRect.GetWidth()) / 2, (aRect.GetHeight() - aMidRect.GetHeight()) / 2 );
                    maTLBR.AddClickRect( aMidRect );
                    maBLTR.AddClickRect( aMidRect );
                }
                /*  One of the diagonal frame borders enabled - use entire rectangle. */
                else if( mbTLBR && !mbBLTR )    // top-left to bottom-right only
                    maTLBR.AddClickRect( aRect );
                else if( !mbTLBR && mbBLTR )    // bottom-left to top-right only
                    maBLTR.AddClickRect( aRect );
            }
        }
    }
}

void FrameSelectorImpl::InitVirtualDevice()
{
    // initialize resources
    InitColors();
    InitArrowImageList();

    // initialize geometry
    InitGlobalGeometry();
    InitBorderGeometry();

    // correct background around the used area
    mrFrameSel.SetBackground( Wallpaper( maBackCol ) );
    DoInvalidate( true );
}

// frame border access --------------------------------------------------------

const FrameBorder& FrameSelectorImpl::GetBorder( FrameBorderType eBorder ) const
{
    size_t nIndex = GetIndexFromFrameBorderType( eBorder );
    if( nIndex < maAllBorders.size() )
        return *maAllBorders[ nIndex ];
    DBG_ERRORFILE( "svx::FrameSelectorImpl::GetBorder - unknown border type" );
    return maTop;
}

FrameBorder& FrameSelectorImpl::GetBorderAccess( FrameBorderType eBorder )
{
    return const_cast< FrameBorder& >( GetBorder( eBorder ) );
}

// drawing --------------------------------------------------------------------

void FrameSelectorImpl::DrawBackground()
{
    // clear the area
    maVirDev.SetLineColor();
    maVirDev.SetFillColor( maBackCol );
    maVirDev.DrawRect( Rectangle( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) );

    // draw the inner gray (or whatever color) rectangle
    maVirDev.SetLineColor();
    maVirDev.SetFillColor( maMarkCol );
    maVirDev.DrawRect( Rectangle(
        mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );

    // draw the white space for enabled frame borders
    PolyPolygon aPPoly;
    for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
        (*aIt)->MergeFocusToPolyPolygon( aPPoly );
    aPPoly.Optimize( POLY_OPTIMIZE_CLOSE );
    maVirDev.SetLineColor( maBackCol );
    maVirDev.SetFillColor( maBackCol );
    maVirDev.DrawPolyPolygon( aPPoly );
}

void FrameSelectorImpl::DrawArrows( const FrameBorder& rBorder )
{
    DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::DrawArrows - access to disabled border" );

    long nLinePos = 0;
    switch( rBorder.GetType() )
    {
        case FRAMEBORDER_LEFT:
        case FRAMEBORDER_TOP:       nLinePos = mnLine1; break;
        case FRAMEBORDER_VER:
        case FRAMEBORDER_HOR:       nLinePos = mnLine2; break;
        case FRAMEBORDER_RIGHT:
        case FRAMEBORDER_BOTTOM:    nLinePos = mnLine3; break;
        default: ; //prevent warning
    }
    nLinePos -= mnArrowSize / 2;

    long nTLPos = 0;
    long nBRPos = mnCtrlSize - mnArrowSize;
    Point aPos1, aPos2;
    sal_uInt16 nImgId1 = 0, nImgId2 = 0;
    switch( rBorder.GetType() )
    {
        case FRAMEBORDER_LEFT:
        case FRAMEBORDER_RIGHT:
        case FRAMEBORDER_VER:
            aPos1 = Point( nLinePos, nTLPos ); nImgId1 = 1;
            aPos2 = Point( nLinePos, nBRPos ); nImgId2 = 2;
        break;

        case FRAMEBORDER_TOP:
        case FRAMEBORDER_BOTTOM:
        case FRAMEBORDER_HOR:
            aPos1 = Point( nTLPos, nLinePos ); nImgId1 = 3;
            aPos2 = Point( nBRPos, nLinePos ); nImgId2 = 4;
        break;

        case FRAMEBORDER_TLBR:
            aPos1 = Point( nTLPos, nTLPos ); nImgId1 = 5;
            aPos2 = Point( nBRPos, nBRPos ); nImgId2 = 6;
        break;
        case FRAMEBORDER_BLTR:
            aPos1 = Point( nTLPos, nBRPos ); nImgId1 = 7;
            aPos2 = Point( nBRPos, nTLPos ); nImgId2 = 8;
        break;
        default: ; //prevent warning
    }

    // Arrow or marker? Do not draw arrows into disabled control.
    sal_uInt16 nSelectAdd = (mrFrameSel.IsEnabled() && rBorder.IsSelected()) ? 0 : 8;
    maVirDev.DrawImage( aPos1, maILArrows.GetImage( nImgId1 + nSelectAdd ) );
    maVirDev.DrawImage( aPos2, maILArrows.GetImage( nImgId2 + nSelectAdd ) );
}

void FrameSelectorImpl::DrawAllArrows()
{
    for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
        DrawArrows( **aIt );
}

Color FrameSelectorImpl::GetDrawLineColor( const Color& rColor ) const
{
    Color aColor( mbHCMode ? maHCLineCol : rColor );
    if( aColor == maBackCol )
        aColor.Invert();
    return aColor;
}

void FrameSelectorImpl::DrawAllFrameBorders()
{
    // Translate core colors to current UI colors (regards current background and HC mode).
    for( FrameBorderIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
    {
        Color aCoreColor = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColor();
        (*aIt)->SetUIColor( GetDrawLineColor( aCoreColor ) );
    }

    // Copy all frame border styles to the helper array
    maArray.SetColumnStyleLeft( 0, maLeft.GetUIStyle() );
    if( mbVer ) maArray.SetColumnStyleLeft( 1, maVer.GetUIStyle() );
    maArray.SetColumnStyleRight( mbVer ? 1 : 0, maRight.GetUIStyle() );

    maArray.SetRowStyleTop( 0, maTop.GetUIStyle() );
    if( mbHor ) maArray.SetRowStyleTop( 1, maHor.GetUIStyle() );
    maArray.SetRowStyleBottom( mbHor ? 1 : 0, maBottom.GetUIStyle() );

    for( size_t nCol = 0; nCol < maArray.GetColCount(); ++nCol )
        for( size_t nRow = 0; nRow < maArray.GetRowCount(); ++nRow )
            maArray.SetCellStyleDiag( nCol, nRow, maTLBR.GetUIStyle(), maBLTR.GetUIStyle() );

    // Let the helper array draw itself
    maArray.DrawArray( maVirDev );
}

void FrameSelectorImpl::DrawVirtualDevice()
{
    DrawBackground();
    DrawAllArrows();
    DrawAllFrameBorders();
    mbFullRepaint = false;
}

void FrameSelectorImpl::CopyVirDevToControl()
{
    if( mbFullRepaint )
        DrawVirtualDevice();
    mrFrameSel.DrawBitmap( maVirDevPos, maVirDev.GetBitmap( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) );
}

void FrameSelectorImpl::DrawAllTrackingRects()
{
    PolyPolygon aPPoly;
    if( mrFrameSel.IsAnyBorderSelected() )
    {
        for( SelFrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
            (*aIt)->MergeFocusToPolyPolygon( aPPoly );
        aPPoly.Move( maVirDevPos.X(), maVirDevPos.Y() );
    }
    else
        // no frame border selected -> draw tracking rectangle around entire control
        aPPoly.Insert( Polygon( Rectangle( maVirDevPos, maVirDev.GetOutputSizePixel() ) ) );

    aPPoly.Optimize( POLY_OPTIMIZE_CLOSE );
    for( sal_uInt16 nIdx = 0, nCount = aPPoly.Count(); nIdx < nCount; ++nIdx )
        mrFrameSel.InvertTracking( aPPoly.GetObject( nIdx ), SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
}

Point FrameSelectorImpl::GetDevPosFromMousePos( const Point& rMousePos ) const
{
    return rMousePos - maVirDevPos;
}

void FrameSelectorImpl::DoInvalidate( bool bFullRepaint )
{
    mbFullRepaint |= bFullRepaint;
    mrFrameSel.Invalidate( INVALIDATE_NOERASE );
}

// frame border state and style -----------------------------------------------

void FrameSelectorImpl::SetBorderState( FrameBorder& rBorder, FrameBorderState eState )
{
    DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderState - access to disabled border" );
	Any aOld;
	Any aNew;
	Any& rMod = eState == FRAMESTATE_SHOW ? aNew : aOld;
	rMod <<= AccessibleStateType::CHECKED;
	Reference< XAccessible > xRet;
    size_t nVecIdx = static_cast< size_t >( rBorder.GetType() );
    if( GetBorder(rBorder.GetType()).IsEnabled() && (1 <= nVecIdx) && (nVecIdx <= maChildVec.size()) )
        xRet = mxChildVec[ --nVecIdx ];
	a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get());

    if( eState == FRAMESTATE_SHOW )
        SetBorderCoreStyle( rBorder, &maCurrStyle );
    else
        rBorder.SetState( eState );
	if (pFrameSelector)
			pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOld, aNew );
    DoInvalidate( true );
}

void FrameSelectorImpl::SetBorderCoreStyle( FrameBorder& rBorder, const SvxBorderLine* pStyle )
{
    DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderCoreStyle - access to disabled border" );
    rBorder.SetCoreStyle( pStyle );
    DoInvalidate( true );
}

void FrameSelectorImpl::ToggleBorderState( FrameBorder& rBorder )
{
    bool bDontCare = mrFrameSel.SupportsDontCareState();
    switch( rBorder.GetState() )
    {
        // same order as tristate check box: visible -> don't care -> hidden
        case FRAMESTATE_SHOW:
            SetBorderState( rBorder, bDontCare ? FRAMESTATE_DONTCARE : FRAMESTATE_HIDE );
        break;
        case FRAMESTATE_HIDE:
            SetBorderState( rBorder, FRAMESTATE_SHOW );
        break;
        case FRAMESTATE_DONTCARE:
            SetBorderState( rBorder, FRAMESTATE_HIDE );
        break;
    }
}

// frame border selection -----------------------------------------------------

void FrameSelectorImpl::SelectBorder( FrameBorder& rBorder, bool bSelect )
{
    DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SelectBorder - access to disabled border" );
    rBorder.Select( bSelect );
    DrawArrows( rBorder );
    DoInvalidate( false );
    maSelectHdl.Call( this );
}

void FrameSelectorImpl::SilentGrabFocus()
{
    bool bOldAuto = mbAutoSelect;
    mbAutoSelect = false;
    mrFrameSel.GrabFocus();
    mbAutoSelect = bOldAuto;
}

bool FrameSelectorImpl::SelectedBordersEqual() const
{
    bool bEqual = true;
    SelFrameBorderCIter aIt( maEnabBorders );
    if( aIt.Is() )
    {
        const SvxBorderLine& rFirstStyle = (*aIt)->GetCoreStyle();
        for( ++aIt; bEqual && aIt.Is(); ++aIt )
            bEqual = ((*aIt)->GetCoreStyle() == rFirstStyle);
    }
    return bEqual;
}

// ============================================================================
// FrameSelector
// ============================================================================

FrameSelector::FrameSelector( Window* pParent, const ResId& rResId ) :
    Control( pParent, rResId )
{
    // not in c'tor init list (avoid warning about usage of *this)
    mxImpl.reset( new FrameSelectorImpl( *this ) );
    EnableRTL( false ); // #107808# don't mirror the mouse handling
}

FrameSelector::~FrameSelector()
{
}

void FrameSelector::Initialize( FrameSelFlags nFlags )
{
    mxImpl->Initialize( nFlags );
	Show();
}

// enabled frame borders ------------------------------------------------------

bool FrameSelector::IsBorderEnabled( FrameBorderType eBorder ) const
{
    return mxImpl->GetBorder( eBorder ).IsEnabled();
}

sal_Int32 FrameSelector::GetEnabledBorderCount() const
{
    return static_cast< sal_Int32 >( mxImpl->maEnabBorders.size() );
}

FrameBorderType FrameSelector::GetEnabledBorderType( sal_Int32 nIndex ) const
{
    FrameBorderType eBorder = FRAMEBORDER_NONE;
    if( nIndex >= 0 )
    {
        size_t nVecIdx = static_cast< size_t >( nIndex );
        if( nVecIdx < mxImpl->maEnabBorders.size() )
            eBorder = mxImpl->maEnabBorders[ nVecIdx ]->GetType();
    }
    return eBorder;
}

sal_Int32 FrameSelector::GetEnabledBorderIndex( FrameBorderType eBorder ) const
{
    sal_Int32 nIndex = 0;
    for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt, ++nIndex )
        if( (*aIt)->GetType() == eBorder )
            return nIndex;
    return -1;
}

// frame border state and style -----------------------------------------------

bool FrameSelector::SupportsDontCareState() const
{
    return (mxImpl->mnFlags & FRAMESEL_DONTCARE) != 0;
}

FrameBorderState FrameSelector::GetFrameBorderState( FrameBorderType eBorder ) const
{
    return mxImpl->GetBorder( eBorder ).GetState();
}

const SvxBorderLine* FrameSelector::GetFrameBorderStyle( FrameBorderType eBorder ) const
{
    const SvxBorderLine& rStyle = mxImpl->GetBorder( eBorder ).GetCoreStyle();
    // rest of the world uses null pointer for invisible frame border
    return rStyle.GetOutWidth() ? &rStyle : 0;
}

void FrameSelector::ShowBorder( FrameBorderType eBorder, const SvxBorderLine* pStyle )
{
    mxImpl->SetBorderCoreStyle( mxImpl->GetBorderAccess( eBorder ), pStyle );
}

void FrameSelector::SetBorderDontCare( FrameBorderType eBorder )
{
    mxImpl->SetBorderState( mxImpl->GetBorderAccess( eBorder ), FRAMESTATE_DONTCARE );
}

bool FrameSelector::IsAnyBorderVisible() const
{
    bool bIsSet = false;
    for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bIsSet && aIt.Is(); ++aIt )
        bIsSet = ((*aIt)->GetState() == FRAMESTATE_SHOW);
    return bIsSet;
}

void FrameSelector::HideAllBorders()
{
    for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );
}

bool FrameSelector::GetVisibleWidth( sal_uInt16& rnPrim, sal_uInt16& rnDist, sal_uInt16& rnSecn ) const
{
    VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
    if( !aIt.Is() )
        return false;

    const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
    bool bFound = true;
    for( ++aIt; bFound && aIt.Is(); ++aIt )
        bFound =
            (rStyle.GetOutWidth() == (*aIt)->GetCoreStyle().GetOutWidth()) &&
            (rStyle.GetDistance() == (*aIt)->GetCoreStyle().GetDistance()) &&
            (rStyle.GetInWidth()  == (*aIt)->GetCoreStyle().GetInWidth());

    if( bFound )
    {
        rnPrim = rStyle.GetOutWidth();
        rnDist = rStyle.GetDistance();
        rnSecn = rStyle.GetInWidth();
    }
    return bFound;
}

bool FrameSelector::GetVisibleColor( Color& rColor ) const
{
    VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
    if( !aIt.Is() )
        return false;

    const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
    bool bFound = true;
    for( ++aIt; bFound && aIt.Is(); ++aIt )
        bFound = (rStyle.GetColor() == (*aIt)->GetCoreStyle().GetColor());

    if( bFound )
        rColor = rStyle.GetColor();
    return bFound;
}

// frame border selection -----------------------------------------------------

const Link& FrameSelector::GetSelectHdl() const
{
    return mxImpl->maSelectHdl;
}

void FrameSelector::SetSelectHdl( const Link& rHdl )
{
    mxImpl->maSelectHdl = rHdl;
}

bool FrameSelector::IsBorderSelected( FrameBorderType eBorder ) const
{
    return mxImpl->GetBorder( eBorder ).IsSelected();
}

void FrameSelector::SelectBorder( FrameBorderType eBorder, bool bSelect /*, bool bFocus */ )
{
    mxImpl->SelectBorder( mxImpl->GetBorderAccess( eBorder ), bSelect );
	// MT: bFireFox as API parameter is ugly...
	// if (bFocus)
	{
		Reference< XAccessible > xRet = GetChildAccessible(eBorder);
		a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get());
		if (pFrameSelector)
		{
			Any aOldValue, aNewValue;
			aNewValue <<= AccessibleStateType::FOCUSED;
			pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
		}
	}
}

bool FrameSelector::IsAnyBorderSelected() const
{
    // Construct an iterator for selected borders. If it is valid, there is a selected border.
    return SelFrameBorderCIter( mxImpl->maEnabBorders ).Is();
}

void FrameSelector::SelectAllBorders( bool bSelect )
{
    for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        mxImpl->SelectBorder( **aIt, bSelect );
}

void FrameSelector::SelectAllVisibleBorders( bool bSelect )
{
    for( VisFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        mxImpl->SelectBorder( **aIt, bSelect );
}

void FrameSelector::SetStyleToSelection( sal_uInt16 nPrim, sal_uInt16 nDist, sal_uInt16 nSecn )
{
    mxImpl->maCurrStyle.SetOutWidth( nPrim );
    mxImpl->maCurrStyle.SetDistance( nDist );
    mxImpl->maCurrStyle.SetInWidth( nSecn );
    for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
}

void FrameSelector::SetColorToSelection( const Color& rColor )
{
    mxImpl->maCurrStyle.SetColor( rColor );
    for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
}

// accessibility --------------------------------------------------------------

Reference< XAccessible > FrameSelector::CreateAccessible()
{
    if( !mxImpl->mxAccess.is() )
        mxImpl->mxAccess = mxImpl->mpAccess =
            new a11y::AccFrameSelector( *this, FRAMEBORDER_NONE );
    return mxImpl->mxAccess;
}

Reference< XAccessible > FrameSelector::GetChildAccessible( FrameBorderType eBorder )
{
    Reference< XAccessible > xRet;
    size_t nVecIdx = static_cast< size_t >( eBorder );
    if( IsBorderEnabled( eBorder ) && (1 <= nVecIdx) && (nVecIdx <= mxImpl->maChildVec.size()) )
    {
        --nVecIdx;
        if( !mxImpl->maChildVec[ nVecIdx ] )
            mxImpl->mxChildVec[ nVecIdx ] = mxImpl->maChildVec[ nVecIdx ] =
                new a11y::AccFrameSelector( *this, eBorder );
        xRet = mxImpl->mxChildVec[ nVecIdx ];
    }
    return xRet;
}

Reference< XAccessible > FrameSelector::GetChildAccessible( sal_Int32 nIndex )
{
    return GetChildAccessible( GetEnabledBorderType( nIndex ) );
}

Reference< XAccessible > FrameSelector::GetChildAccessible( const Point& rPos )
{
    Reference< XAccessible > xRet;
    for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !xRet.is() && aIt.Is(); ++aIt )
        if( (*aIt)->ContainsClickPoint( rPos ) )
            xRet = GetChildAccessible( (*aIt)->GetType() );
    return xRet;
}

bool FrameSelector::ContainsClickPoint( const Point& rPos ) const
{
    bool bContains = false;
    for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bContains && aIt.Is(); ++aIt )
        bContains = (*aIt)->ContainsClickPoint( rPos );
    return bContains;
}

Rectangle FrameSelector::GetClickBoundRect( FrameBorderType eBorder ) const
{
    Rectangle aRect;
    const FrameBorder& rBorder = mxImpl->GetBorder( eBorder );
    if( rBorder.IsEnabled() )
        aRect = rBorder.GetClickBoundRect();
    return aRect;
}

// virtual functions from base class ------------------------------------------

void FrameSelector::Paint( const Rectangle& )
{
    mxImpl->CopyVirDevToControl();
    if( HasFocus() )
        mxImpl->DrawAllTrackingRects();
}

void FrameSelector::MouseButtonDown( const MouseEvent& rMEvt )
{
    /*  Mouse handling:
        * Click on an unselected frame border:
            Set current style/color, make frame border visible, deselect all
            other frame borders.
        * Click on a selected frame border:
            Toggle state of the frame border (visible -> don't care -> hidden),
            deselect all other frame borders.
        * SHIFT+Click or CTRL+Click on an unselected frame border:
            Extend selection, set current style/color to all selected frame
            borders independent of the state/style/color of the borders.
        * SHIFT+Click or CTRL+Click on a selected frame border:
            If all frame borders have same style/color, toggle state of all
            borders (see above), otherwise set current style/color to all
            borders.
        * Click on unused area: Do not modify selection and selected frame
            borders.
     */

    // #107394# do not auto-select a frame border
    mxImpl->SilentGrabFocus();

    if( rMEvt.IsLeft() )
    {
        Point aPos( mxImpl->GetDevPosFromMousePos( rMEvt.GetPosPixel() ) );
        FrameBorderPtrVec aDeselectBorders;

        bool bAnyClicked = false;   // Any frame border clicked?
        bool bNewSelected = false;  // Any unselected frame border selected?

        /*  If frame borders are set to "don't care" and the control does not
            support this state, hide them on first mouse click.
            DR 2004-01-30: Why are the borders set to "don't care" then?!? */
        bool bHideDontCare = !mxImpl->mbClicked && !SupportsDontCareState();

        for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
        {
            if( (*aIt)->ContainsClickPoint( aPos ) )
            {
                // frame border is clicked
                bAnyClicked = true;
                if( !(*aIt)->IsSelected() )
                {
                    bNewSelected = true;
                    //mxImpl->SelectBorder( **aIt, true );
			SelectBorder((**aIt).GetType(), true);
                }
            }
            else
            {
                // hide a "don't care" frame border only if it is not clicked
                if( bHideDontCare && ((*aIt)->GetState() == FRAMESTATE_DONTCARE) )
                    mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );

                // deselect frame borders not clicked (if SHIFT or CTRL are not pressed)
                if( !rMEvt.IsShift() && !rMEvt.IsMod1() )
                    aDeselectBorders.push_back( *aIt );
            }
        }

        if( bAnyClicked )
        {
            // any valid frame border clicked? -> deselect other frame borders
            for( FrameBorderIter aIt( aDeselectBorders ); aIt.Is(); ++aIt )
                mxImpl->SelectBorder( **aIt, false );

            if( bNewSelected || !mxImpl->SelectedBordersEqual() )
            {
                // new frame border selected, selection extended, or selected borders different? -> show
                for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
                    // SetBorderState() sets current style and color to the frame border
                    mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
            }
            else
            {
                // all selected frame borders are equal -> toggle state
                for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
                    mxImpl->ToggleBorderState( **aIt );
            }
        }
    }
}

void FrameSelector::KeyInput( const KeyEvent& rKEvt )
{
    bool bHandled = false;
    KeyCode aKeyCode = rKEvt.GetKeyCode();
    if( !aKeyCode.GetModifier() )
    {
        sal_uInt16 nCode = aKeyCode.GetCode();
        switch( nCode )
        {
            case KEY_SPACE:
            {
                for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
                    mxImpl->ToggleBorderState( **aIt );
                bHandled = true;
            }
            break;

            case KEY_UP:
            case KEY_DOWN:
            case KEY_LEFT:
            case KEY_RIGHT:
            {
                if( !mxImpl->maEnabBorders.empty() )
                {
                    // start from first selected frame border
                    SelFrameBorderCIter aIt( mxImpl->maEnabBorders );
                    FrameBorderType eBorder = aIt.Is() ? (*aIt)->GetType() : mxImpl->maEnabBorders.front()->GetType();

                    // search for next enabled frame border
                    do
                    {
                        eBorder = mxImpl->GetBorder( eBorder ).GetKeyboardNeighbor( nCode );
                    }
                    while( (eBorder != FRAMEBORDER_NONE) && !IsBorderEnabled( eBorder ) );

                    // select the frame border
                    if( eBorder != FRAMEBORDER_NONE )
                    {
                        DeselectAllBorders();
                        SelectBorder( eBorder );
                    }
                }
            }
            break;
        }
    }
    if( !bHandled )
        Window::KeyInput(rKEvt);
}

void FrameSelector::GetFocus()
{
    // auto-selection of a frame border, if focus reaches control, and nothing is selected
    if( mxImpl->mbAutoSelect && !IsAnyBorderSelected() && !mxImpl->maEnabBorders.empty() )
        mxImpl->SelectBorder( *mxImpl->maEnabBorders.front(), true );

    mxImpl->DoInvalidate( false );
    if( mxImpl->mxAccess.is() )
        mxImpl->mpAccess->NotifyFocusListeners( sal_True );
	if (IsAnyBorderSelected())
	{
		FrameBorderType borderType = FRAMEBORDER_NONE;
		if (mxImpl->maLeft.IsSelected())
			borderType = FRAMEBORDER_LEFT;
		else if (mxImpl->maRight.IsSelected())
			borderType = FRAMEBORDER_RIGHT;
		else if (mxImpl->maTop.IsSelected())
			borderType = FRAMEBORDER_TOP;
		else if (mxImpl->maBottom.IsSelected())
			borderType = FRAMEBORDER_BOTTOM;
		else if (mxImpl->maHor.IsSelected())
			borderType = FRAMEBORDER_HOR;
		else if (mxImpl->maVer.IsSelected())
			borderType = FRAMEBORDER_VER;
		else if (mxImpl->maTLBR.IsSelected())
			borderType = FRAMEBORDER_TLBR;
		else if (mxImpl->maBLTR.IsSelected())
			borderType = FRAMEBORDER_BLTR;
		SelectBorder(borderType);
	}
	for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
			mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
    Control::GetFocus();
}

void FrameSelector::LoseFocus()
{
    mxImpl->DoInvalidate( false );
    if( mxImpl->mxAccess.is() )
        mxImpl->mpAccess->NotifyFocusListeners( sal_False );
    Control::LoseFocus();
}

void FrameSelector::DataChanged( const DataChangedEvent& rDCEvt )
{
    Control::DataChanged( rDCEvt );
    if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
        mxImpl->InitVirtualDevice();
}

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

template< typename Cont, typename Iter, typename Pred >
FrameBorderIterBase< Cont, Iter, Pred >::FrameBorderIterBase( container_type& rCont ) :
    maIt( rCont.begin() ),
    maEnd( rCont.end() )
{
    while( Is() && !maPred( *maIt ) ) ++maIt;
}

template< typename Cont, typename Iter, typename Pred >
FrameBorderIterBase< Cont, Iter, Pred >& FrameBorderIterBase< Cont, Iter, Pred >::operator++()
{
    do { ++maIt; } while( Is() && !maPred( *maIt ) );
    return *this;
}

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

} // namespace svx
