LCOV - code coverage report
Current view: top level - svx/source/dialog - frmsel.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 671 0.1 %
Date: 2015-06-13 12:38:46 Functions: 2 97 2.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <svx/frmsel.hxx>
      21             : #include <vcl/builderfactory.hxx>
      22             : 
      23             : #include <algorithm>
      24             : #include <math.h>
      25             : #include <frmselimpl.hxx>
      26             : #include <AccessibleFrameSelector.hxx>
      27             : #include <svx/dialmgr.hxx>
      28             : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
      29             : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
      30             : #include <vcl/settings.hxx>
      31             : 
      32             : #include <svx/dialogs.hrc>
      33             : #include "frmsel.hrc"
      34             : 
      35             : #include <tools/rcid.h>
      36             : 
      37             : using namespace ::com::sun::star;
      38             : using namespace ::editeng;
      39             : 
      40             : namespace svx {
      41             : 
      42             : using ::com::sun::star::uno::Reference;
      43             : using ::com::sun::star::uno::Any;
      44             : using ::com::sun::star::accessibility::XAccessible;
      45             : using namespace ::com::sun::star::accessibility;
      46             : 
      47             : // global functions from framebordertype.hxx
      48             : 
      49           0 : FrameBorderType GetFrameBorderTypeFromIndex( size_t nIndex )
      50             : {
      51             :     DBG_ASSERT( nIndex < (size_t)FRAMEBORDERTYPE_COUNT,
      52             :         "svx::GetFrameBorderTypeFromIndex - invalid index" );
      53           0 :     return static_cast< FrameBorderType >( nIndex + 1 );
      54             : }
      55             : 
      56           0 : size_t GetIndexFromFrameBorderType( FrameBorderType eBorder )
      57             : {
      58             :     DBG_ASSERT( eBorder != FRAMEBORDER_NONE,
      59             :         "svx::GetIndexFromFrameBorderType - invalid frame border type" );
      60           0 :     return static_cast< size_t >( eBorder ) - 1;
      61             : }
      62             : 
      63             : namespace
      64             : {
      65             : 
      66             : /** Space between outer control border and any graphical element of the control. */
      67             : const long FRAMESEL_GEOM_OUTER    = 2;
      68             : 
      69             : /** Space between arrows and usable inner area. */
      70             : const long FRAMESEL_GEOM_INNER    = 3;
      71             : 
      72             : /** Maximum width to draw a frame border style. */
      73             : const long FRAMESEL_GEOM_WIDTH    = 9;
      74             : 
      75             : /** Additional margin for click area of outer lines. */
      76             : const long FRAMESEL_GEOM_ADD_CLICK_OUTER = 5;
      77             : 
      78             : /** Additional margin for click area of inner lines. */
      79             : const long FRAMESEL_GEOM_ADD_CLICK_INNER = 2;
      80             : 
      81             : 
      82             : /** Returns the corresponding flag for a frame border. */
      83           0 : FrameSelFlags lclGetFlagFromType( FrameBorderType eBorder )
      84             : {
      85           0 :     switch( eBorder )
      86             :     {
      87           0 :         case FRAMEBORDER_LEFT:      return FRAMESEL_LEFT;
      88           0 :         case FRAMEBORDER_RIGHT:     return FRAMESEL_RIGHT;
      89           0 :         case FRAMEBORDER_TOP:       return FRAMESEL_TOP;
      90           0 :         case FRAMEBORDER_BOTTOM:    return FRAMESEL_BOTTOM;
      91           0 :         case FRAMEBORDER_HOR:       return FRAMESEL_INNER_HOR;
      92           0 :         case FRAMEBORDER_VER:       return FRAMESEL_INNER_VER;
      93           0 :         case FRAMEBORDER_TLBR:      return FRAMESEL_DIAG_TLBR;
      94           0 :         case FRAMEBORDER_BLTR:      return FRAMESEL_DIAG_BLTR;
      95           0 :         case FRAMEBORDER_NONE : break;
      96             :     }
      97           0 :     return FRAMESEL_NONE;
      98             : }
      99             : 
     100             : /** Merges the rSource polypolygon into the rDest polypolygon. */
     101           0 : inline void lclPolyPolyUnion( tools::PolyPolygon& rDest, const tools::PolyPolygon& rSource )
     102             : {
     103           0 :     const tools::PolyPolygon aTmp( rDest );
     104           0 :     aTmp.GetUnion( rSource, rDest );
     105           0 : }
     106             : 
     107             : } // namespace
     108             : 
     109           0 : FrameBorder::FrameBorder( FrameBorderType eType ) :
     110             :     meType( eType ),
     111             :     meState( FRAMESTATE_HIDE ),
     112             :     meKeyLeft( FRAMEBORDER_NONE ),
     113             :     meKeyRight( FRAMEBORDER_NONE ),
     114             :     meKeyTop( FRAMEBORDER_NONE ),
     115             :     meKeyBottom( FRAMEBORDER_NONE ),
     116             :     mbEnabled( false ),
     117           0 :     mbSelected( false )
     118             : {
     119           0 : }
     120             : 
     121           0 : void FrameBorder::Enable( FrameSelFlags nFlags )
     122             : {
     123           0 :     mbEnabled = (nFlags & lclGetFlagFromType( meType )) != 0;
     124           0 :     if( !mbEnabled )
     125           0 :         SetState( FRAMESTATE_HIDE );
     126           0 : }
     127             : 
     128           0 : void FrameBorder::SetCoreStyle( const SvxBorderLine* pStyle )
     129             : {
     130           0 :     if( pStyle )
     131           0 :         maCoreStyle = *pStyle;
     132             :     else
     133           0 :         maCoreStyle = SvxBorderLine();
     134             : 
     135             :     // from twips to points
     136           0 :     maUIStyle.Set( maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH );
     137           0 :     meState = maUIStyle.Prim() ? FRAMESTATE_SHOW : FRAMESTATE_HIDE;
     138           0 : }
     139             : 
     140           0 : void FrameBorder::SetState( FrameBorderState eState )
     141             : {
     142           0 :     meState = eState;
     143           0 :     switch( meState )
     144             :     {
     145             :         case FRAMESTATE_SHOW:
     146             :             SAL_WARN( "svx.dialog", "svx::FrameBorder::SetState - use SetCoreStyle to make border visible" );
     147           0 :         break;
     148             :         case FRAMESTATE_HIDE:
     149           0 :             maCoreStyle = SvxBorderLine();
     150           0 :             maUIStyle.Clear();
     151           0 :         break;
     152             :         case FRAMESTATE_DONTCARE:
     153           0 :             maCoreStyle = SvxBorderLine();
     154           0 :             maUIStyle = frame::Style(3, 0, 0, table::BorderLineStyle::SOLID); //OBJ_FRAMESTYLE_DONTCARE
     155           0 :         break;
     156             :     }
     157           0 : }
     158             : 
     159           0 : void FrameBorder::AddFocusPolygon( const Polygon& rFocus )
     160             : {
     161           0 :     lclPolyPolyUnion( maFocusArea, rFocus );
     162           0 : }
     163             : 
     164           0 : void FrameBorder::MergeFocusToPolyPolygon( tools::PolyPolygon& rPPoly ) const
     165             : {
     166           0 :     lclPolyPolyUnion( rPPoly, maFocusArea );
     167           0 : }
     168             : 
     169           0 : void FrameBorder::AddClickRect( const Rectangle& rRect )
     170             : {
     171           0 :     lclPolyPolyUnion( maClickArea, Polygon( rRect ) );
     172           0 : }
     173             : 
     174           0 : bool FrameBorder::ContainsClickPoint( const Point& rPos ) const
     175             : {
     176           0 :     return vcl::Region( maClickArea ).IsInside( rPos );
     177             : }
     178             : 
     179           0 : Rectangle FrameBorder::GetClickBoundRect() const
     180             : {
     181           0 :     return maClickArea.GetBoundRect();
     182             : }
     183             : 
     184           0 : void FrameBorder::SetKeyboardNeighbors(
     185             :         FrameBorderType eLeft, FrameBorderType eRight, FrameBorderType eTop, FrameBorderType eBottom )
     186             : {
     187           0 :     meKeyLeft = eLeft;
     188           0 :     meKeyRight = eRight;
     189           0 :     meKeyTop = eTop;
     190           0 :     meKeyBottom = eBottom;
     191           0 : }
     192             : 
     193           0 : FrameBorderType FrameBorder::GetKeyboardNeighbor( sal_uInt16 nKeyCode ) const
     194             : {
     195           0 :     FrameBorderType eBorder = FRAMEBORDER_NONE;
     196           0 :     switch( nKeyCode )
     197             :     {
     198           0 :         case KEY_LEFT:  eBorder = meKeyLeft;      break;
     199           0 :         case KEY_RIGHT: eBorder = meKeyRight;     break;
     200           0 :         case KEY_UP:    eBorder = meKeyTop;       break;
     201           0 :         case KEY_DOWN:  eBorder = meKeyBottom;    break;
     202             :         default:        SAL_WARN( "svx.dialog", "svx::FrameBorder::GetKeyboardNeighbor - unknown key code" );
     203             :     }
     204           0 :     return eBorder;
     205             : }
     206             : 
     207           0 : FrameSelectorImpl::FrameSelectorImpl( FrameSelector& rFrameSel ) :
     208           0 :     Resource( SVX_RES( RID_SVXSTR_BORDER_CONTROL ) ),
     209             :     mrFrameSel( rFrameSel ),
     210             :     mpVirDev( VclPtr<VirtualDevice>::Create() ),
     211             :     maILArrows( 16 ),
     212             :     maLeft( FRAMEBORDER_LEFT ),
     213             :     maRight( FRAMEBORDER_RIGHT ),
     214             :     maTop( FRAMEBORDER_TOP ),
     215             :     maBottom( FRAMEBORDER_BOTTOM ),
     216             :     maHor( FRAMEBORDER_HOR ),
     217             :     maVer( FRAMEBORDER_VER ),
     218             :     maTLBR( FRAMEBORDER_TLBR ),
     219             :     maBLTR( FRAMEBORDER_BLTR ),
     220             :     mnFlags( FRAMESEL_OUTER ),
     221             :     mnCtrlSize( 0 ),
     222             :     mnArrowSize( 0 ),
     223             :     mnLine1( 0 ),
     224             :     mnLine2( 0 ),
     225             :     mnLine3( 0 ),
     226             :     mnFocusOffs( 0 ),
     227             :     mbHor( false ),
     228             :     mbVer( false ),
     229             :     mbTLBR( false ),
     230             :     mbBLTR( false ),
     231             :     mbFullRepaint( true ),
     232             :     mbAutoSelect( true ),
     233             :     mbClicked( false ),
     234             :     mbHCMode( false ),
     235             :     mpAccess( 0 ),
     236             :     maChildVec( 8, static_cast< a11y::AccFrameSelector* >( 0 ) ),
     237           0 :     mxChildVec( 8 )
     238             : {
     239           0 :     FreeResource();
     240             : 
     241           0 :     maAllBorders.resize( FRAMEBORDERTYPE_COUNT, 0 );
     242           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_LEFT   ) ] = &maLeft;
     243           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_RIGHT  ) ] = &maRight;
     244           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TOP    ) ] = &maTop;
     245           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BOTTOM ) ] = &maBottom;
     246           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_HOR    ) ] = &maHor;
     247           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_VER    ) ] = &maVer;
     248           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TLBR   ) ] = &maTLBR;
     249           0 :     maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BLTR   ) ] = &maBLTR;
     250             : #if OSL_DEBUG_LEVEL >= 2
     251             :     {
     252             :         bool bOk = true;
     253             :         for( FrameBorderCIter aIt( maAllBorders ); bOk && aIt.Is(); bOk = (*aIt != 0), ++aIt );
     254             :         DBG_ASSERT( bOk, "svx::FrameSelectorImpl::FrameSelectorImpl - missing entry in maAllBorders" );
     255             :     }
     256             : #endif
     257             :     //                             left neighbor     right neighbor     upper neighbor    lower neighbor
     258           0 :     maLeft.SetKeyboardNeighbors(   FRAMEBORDER_NONE, FRAMEBORDER_TLBR,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
     259           0 :     maRight.SetKeyboardNeighbors(  FRAMEBORDER_BLTR, FRAMEBORDER_NONE,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
     260           0 :     maTop.SetKeyboardNeighbors(    FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_NONE, FRAMEBORDER_TLBR );
     261           0 :     maBottom.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_BLTR, FRAMEBORDER_NONE );
     262           0 :     maHor.SetKeyboardNeighbors(    FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_TLBR, FRAMEBORDER_BLTR );
     263           0 :     maVer.SetKeyboardNeighbors(    FRAMEBORDER_TLBR, FRAMEBORDER_BLTR,  FRAMEBORDER_TOP,  FRAMEBORDER_BOTTOM );
     264           0 :     maTLBR.SetKeyboardNeighbors(   FRAMEBORDER_LEFT, FRAMEBORDER_VER,   FRAMEBORDER_TOP,  FRAMEBORDER_HOR );
     265           0 :     maBLTR.SetKeyboardNeighbors(   FRAMEBORDER_VER,  FRAMEBORDER_RIGHT, FRAMEBORDER_HOR,  FRAMEBORDER_BOTTOM );
     266             : 
     267           0 :     Initialize(mnFlags);
     268           0 : }
     269             : 
     270           0 : FrameSelectorImpl::~FrameSelectorImpl()
     271             : 
     272             : {
     273           0 :     if( mpAccess )
     274           0 :         mpAccess->Invalidate();
     275           0 :     for( AccessibleImplVec::iterator aIt = maChildVec.begin(), aEnd = maChildVec.end(); aIt != aEnd; ++aIt )
     276           0 :         if( *aIt )
     277           0 :             (*aIt)->Invalidate();
     278           0 : }
     279             : 
     280             : // initialization
     281           0 : void FrameSelectorImpl::Initialize( FrameSelFlags nFlags )
     282             : {
     283           0 :     mnFlags = nFlags;
     284             : 
     285           0 :     maEnabBorders.clear();
     286           0 :     for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
     287             :     {
     288           0 :         (*aIt)->Enable( mnFlags );
     289           0 :         if( (*aIt)->IsEnabled() )
     290           0 :             maEnabBorders.push_back( *aIt );
     291             :     }
     292           0 :     mbHor = maHor.IsEnabled();
     293           0 :     mbVer = maVer.IsEnabled();
     294           0 :     mbTLBR = maTLBR.IsEnabled();
     295           0 :     mbBLTR = maBLTR.IsEnabled();
     296             : 
     297           0 :     InitVirtualDevice();
     298           0 : }
     299             : 
     300           0 : void FrameSelectorImpl::InitColors()
     301             : {
     302           0 :     const StyleSettings& rSettings = mrFrameSel.GetSettings().GetStyleSettings();
     303           0 :     maBackCol = rSettings.GetFieldColor();
     304           0 :     mbHCMode = rSettings.GetHighContrastMode();
     305           0 :     maArrowCol = rSettings.GetFieldTextColor();
     306           0 :     maMarkCol.operator=(maBackCol).Merge(maArrowCol, mbHCMode ? 0x80 : 0xC0);
     307           0 :     maHCLineCol = rSettings.GetLabelTextColor();
     308           0 : }
     309             : 
     310           0 : void FrameSelectorImpl::InitArrowImageList()
     311             : {
     312             :     /* Build the arrow images bitmap with current colors. */
     313           0 :     Color pColorAry1[3];
     314           0 :     Color pColorAry2[3];
     315           0 :     pColorAry1[0] = Color( 0, 0, 0 );
     316           0 :     pColorAry2[0] = maArrowCol;       // black -> arrow color
     317           0 :     pColorAry1[1] = Color( 0, 255, 0 );
     318           0 :     pColorAry2[1] = maMarkCol;        // green -> marker color
     319           0 :     pColorAry1[2] = Color( 255, 0, 255 );
     320           0 :     pColorAry2[2] = maBackCol;       // magenta -> background
     321             : 
     322           0 :     GetRes( SVX_RES( RID_SVXSTR_BORDER_CONTROL ).SetRT( RSC_RESOURCE ) );
     323             :     maILArrows.InsertFromHorizontalBitmap(
     324           0 :         SVX_RES( BMP_FRMSEL_ARROWS ), 16, NULL, pColorAry1, pColorAry2, 3);
     325           0 :     FreeResource();
     326             :     DBG_ASSERT( maILArrows.GetImageSize().Height() == maILArrows.GetImageSize().Width(),
     327             :         "svx::FrameSelectorImpl::InitArrowImageList - images are not squarish" );
     328           0 :     mnArrowSize = maILArrows.GetImageSize().Height();
     329           0 : }
     330             : 
     331           0 : void FrameSelectorImpl::InitGlobalGeometry()
     332             : {
     333           0 :     Size aCtrlSize( mrFrameSel.CalcOutputSize( mrFrameSel.GetSizePixel() ) );
     334             :     /*  nMinSize is the lower of width and height (control will always be squarish).
     335             :         FRAMESEL_GEOM_OUTER is the minimal distance between inner control border
     336             :         and any element. */
     337           0 :     long nMinSize = std::min( aCtrlSize.Width(), aCtrlSize.Height() ) - 2 * FRAMESEL_GEOM_OUTER;
     338             :     /*  nFixedSize is the size all existing elements need in one direction:
     339             :         the diag. arrow, space betw. arrow and frame border, outer frame border,
     340             :         inner frame border, other outer frame border, space betw. frame border
     341             :         and arrow, the other arrow. */
     342           0 :     long nFixedSize = 2 * mnArrowSize + 2 * FRAMESEL_GEOM_INNER + 3 * FRAMESEL_GEOM_WIDTH;
     343             :     /*  nBetwBordersSize contains the size between an outer and inner frame border (made odd). */
     344           0 :     long nBetwBordersSize = (((nMinSize - nFixedSize) / 2) - 1) | 1;
     345             : 
     346             :     /*  The final size of the usable area. */
     347           0 :     mnCtrlSize = 2 * nBetwBordersSize + nFixedSize;
     348           0 :     mpVirDev->SetOutputSizePixel( Size( mnCtrlSize, mnCtrlSize ) );
     349             : 
     350             :     /*  Center the virtual device in the control. */
     351           0 :     maVirDevPos = Point( (aCtrlSize.Width() - mnCtrlSize) / 2, (aCtrlSize.Height() - mnCtrlSize) / 2 );
     352           0 : }
     353             : 
     354           0 : void FrameSelectorImpl::InitBorderGeometry()
     355             : {
     356             :     size_t nCol, nCols, nRow, nRows;
     357             : 
     358             :     // Global border geometry values
     359             :     /*  mnLine* is the middle point inside a frame border (i.e. mnLine1 is mid X inside left border). */
     360           0 :     mnLine1 = mnArrowSize + FRAMESEL_GEOM_INNER + FRAMESEL_GEOM_WIDTH / 2;
     361           0 :     mnLine2 = mnCtrlSize / 2;
     362           0 :     mnLine3 = 2 * mnLine2 - mnLine1;
     363             : 
     364             :     // Frame helper array
     365           0 :     maArray.Initialize( mbVer ? 2 : 1, mbHor ? 2 : 1 );
     366           0 :     maArray.SetUseDiagDoubleClipping( true );
     367             : 
     368           0 :     maArray.SetXOffset( mnLine1 );
     369           0 :     maArray.SetAllColWidths( (mbVer ? mnLine2 : mnLine3) - mnLine1 );
     370             : 
     371           0 :     maArray.SetYOffset( mnLine1 );
     372           0 :     maArray.SetAllRowHeights( (mbHor ? mnLine2 : mnLine3) - mnLine1 );
     373             : 
     374             :     // Focus polygons
     375             :     /*  Width for focus rectangles from center of frame borders. */
     376           0 :     mnFocusOffs = FRAMESEL_GEOM_WIDTH / 2 + 1;
     377             : 
     378           0 :     maLeft.ClearFocusArea();
     379           0 :     maVer.ClearFocusArea();
     380           0 :     maRight.ClearFocusArea();
     381           0 :     maTop.ClearFocusArea();
     382           0 :     maHor.ClearFocusArea();
     383           0 :     maBottom.ClearFocusArea();
     384             : 
     385           0 :     maLeft.AddFocusPolygon(   Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine1 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
     386           0 :     maVer.AddFocusPolygon(    Rectangle( mnLine2 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine2 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
     387           0 :     maRight.AddFocusPolygon(  Rectangle( mnLine3 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
     388           0 :     maTop.AddFocusPolygon(    Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine1 + mnFocusOffs ) );
     389           0 :     maHor.AddFocusPolygon(    Rectangle( mnLine1 - mnFocusOffs, mnLine2 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine2 + mnFocusOffs ) );
     390           0 :     maBottom.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine3 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
     391             : 
     392           0 :     for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
     393             :     {
     394           0 :         for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
     395             :         {
     396           0 :             Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
     397           0 :             long nDiagFocusOffsX = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetHorDiagAngle( nCol, nRow ) );
     398           0 :             long nDiagFocusOffsY = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetVerDiagAngle( nCol, nRow ) );
     399             : 
     400           0 :             std::vector< Point > aFocusVec;
     401           0 :             aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Top()    + nDiagFocusOffsY ) );
     402           0 :             aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Top()    - mnFocusOffs     ) );
     403           0 :             aFocusVec.push_back( Point( aRect.Left()  + nDiagFocusOffsX, aRect.Top()    - mnFocusOffs     ) );
     404           0 :             aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Bottom() - nDiagFocusOffsY ) );
     405           0 :             aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Bottom() + mnFocusOffs     ) );
     406           0 :             aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs     ) );
     407           0 :             maTLBR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );
     408             : 
     409           0 :             aFocusVec.clear();
     410           0 :             aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Top()    + nDiagFocusOffsY ) );
     411           0 :             aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs,     aRect.Top()    - mnFocusOffs     ) );
     412           0 :             aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Top()    - mnFocusOffs     ) );
     413           0 :             aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Bottom() - nDiagFocusOffsY ) );
     414           0 :             aFocusVec.push_back( Point( aRect.Left()  - mnFocusOffs,     aRect.Bottom() + mnFocusOffs     ) );
     415           0 :             aFocusVec.push_back( Point( aRect.Left()  + nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs     ) );
     416           0 :             maBLTR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );
     417           0 :         }
     418             :     }
     419             : 
     420             :     // Click areas
     421           0 :     for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
     422           0 :         (*aIt)->ClearClickArea();
     423             : 
     424             :     /*  Additional space for click area: is added to the space available to draw
     425             :         the frame borders. For instance left frame border:
     426             :         - To left, top, and bottom always big additional space (outer area).
     427             :         - To right: Dependent on existence of inner vertical frame border
     428             :             (if enabled, use less space).
     429             :      */
     430           0 :     long nClO = FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_OUTER;
     431           0 :     long nClI = (mbTLBR && mbBLTR) ? (FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_INNER) : nClO;
     432           0 :     long nClH = mbHor ? nClI : nClO;            // additional space dependent of horizontal inner border
     433           0 :     long nClV = mbVer ? nClI : nClO;            // additional space dependent of vertical inner border
     434             : 
     435           0 :     maLeft.AddClickRect(   Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine1 + nClV, mnLine3 + nClO ) );
     436           0 :     maVer.AddClickRect(    Rectangle( mnLine2 - nClI, mnLine1 - nClO, mnLine2 + nClI, mnLine3 + nClO ) );
     437           0 :     maRight.AddClickRect(  Rectangle( mnLine3 - nClV, mnLine1 - nClO, mnLine3 + nClO, mnLine3 + nClO ) );
     438           0 :     maTop.AddClickRect(    Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine3 + nClO, mnLine1 + nClH ) );
     439           0 :     maHor.AddClickRect(    Rectangle( mnLine1 - nClO, mnLine2 - nClI, mnLine3 + nClO, mnLine2 + nClI ) );
     440           0 :     maBottom.AddClickRect( Rectangle( mnLine1 - nClO, mnLine3 - nClH, mnLine3 + nClO, mnLine3 + nClO ) );
     441             : 
     442             :     /*  Diagonal frame borders use the remaining space between outer and inner frame borders. */
     443           0 :     if( mbTLBR || mbBLTR )
     444             :     {
     445           0 :         for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
     446             :         {
     447           0 :             for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
     448             :             {
     449             :                 // the usable area between horizonal/vertical frame borders of current quadrant
     450           0 :                 Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
     451           0 :                 aRect.Left() += nClV + 1;
     452           0 :                 aRect.Right() -= nClV + 1;
     453           0 :                 aRect.Top() += nClH + 1;
     454           0 :                 aRect.Bottom() -= nClH + 1;
     455             : 
     456             :                 /*  Both diagonal frame borders enabled. */
     457           0 :                 if( mbTLBR && mbBLTR )
     458             :                 {
     459             :                     // single areas
     460           0 :                     Point aMid( aRect.Center() );
     461           0 :                     maTLBR.AddClickRect( Rectangle( aRect.TopLeft(), aMid ) );
     462           0 :                     maTLBR.AddClickRect( Rectangle( aMid + Point( 1, 1 ), aRect.BottomRight() ) );
     463           0 :                     maBLTR.AddClickRect( Rectangle( aRect.Left(), aMid.Y() + 1, aMid.X(), aRect.Bottom() ) );
     464           0 :                     maBLTR.AddClickRect( Rectangle( aMid.X() + 1, aRect.Top(), aRect.Right(), aMid.Y() ) );
     465             :                     // centered rectangle for both frame borders
     466           0 :                     Rectangle aMidRect( aRect.TopLeft(), Size( aRect.GetWidth() / 3, aRect.GetHeight() / 3 ) );
     467           0 :                     aMidRect.Move( (aRect.GetWidth() - aMidRect.GetWidth()) / 2, (aRect.GetHeight() - aMidRect.GetHeight()) / 2 );
     468           0 :                     maTLBR.AddClickRect( aMidRect );
     469           0 :                     maBLTR.AddClickRect( aMidRect );
     470             :                 }
     471             :                 /*  One of the diagonal frame borders enabled - use entire rectangle. */
     472           0 :                 else if( mbTLBR && !mbBLTR )    // top-left to bottom-right only
     473           0 :                     maTLBR.AddClickRect( aRect );
     474           0 :                 else if( !mbTLBR && mbBLTR )    // bottom-left to top-right only
     475           0 :                     maBLTR.AddClickRect( aRect );
     476             :             }
     477             :         }
     478             :     }
     479           0 : }
     480             : 
     481           0 : void FrameSelectorImpl::InitVirtualDevice()
     482             : {
     483             :     // initialize resources
     484           0 :     InitColors();
     485           0 :     InitArrowImageList();
     486             : 
     487           0 :     sizeChanged();
     488           0 : }
     489             : 
     490           0 : void FrameSelectorImpl::sizeChanged()
     491             : {
     492             :     // initialize geometry
     493           0 :     InitGlobalGeometry();
     494           0 :     InitBorderGeometry();
     495             : 
     496             :     // correct background around the used area
     497           0 :     mrFrameSel.SetBackground( Wallpaper( maBackCol ) );
     498           0 :     DoInvalidate( true );
     499           0 : }
     500             : 
     501             : // frame border access
     502           0 : const FrameBorder& FrameSelectorImpl::GetBorder( FrameBorderType eBorder ) const
     503             : {
     504           0 :     size_t nIndex = GetIndexFromFrameBorderType( eBorder );
     505           0 :     if( nIndex < maAllBorders.size() )
     506           0 :         return *maAllBorders[ nIndex ];
     507             :     SAL_WARN( "svx.dialog", "svx::FrameSelectorImpl::GetBorder - unknown border type" );
     508           0 :     return maTop;
     509             : }
     510             : 
     511           0 : FrameBorder& FrameSelectorImpl::GetBorderAccess( FrameBorderType eBorder )
     512             : {
     513           0 :     return const_cast< FrameBorder& >( GetBorder( eBorder ) );
     514             : }
     515             : 
     516             : // drawing
     517           0 : void FrameSelectorImpl::DrawBackground()
     518             : {
     519             :     // clear the area
     520           0 :     mpVirDev->SetLineColor();
     521           0 :     mpVirDev->SetFillColor( maBackCol );
     522           0 :     mpVirDev->DrawRect( Rectangle( Point( 0, 0 ), mpVirDev->GetOutputSizePixel() ) );
     523             : 
     524             :     // draw the inner gray (or whatever color) rectangle
     525           0 :     mpVirDev->SetLineColor();
     526           0 :     mpVirDev->SetFillColor( maMarkCol );
     527           0 :     mpVirDev->DrawRect( Rectangle(
     528           0 :         mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
     529             : 
     530             :     // draw the white space for enabled frame borders
     531           0 :     tools::PolyPolygon aPPoly;
     532           0 :     for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
     533           0 :         (*aIt)->MergeFocusToPolyPolygon( aPPoly );
     534           0 :     aPPoly.Optimize( PolyOptimizeFlags::CLOSE );
     535           0 :     mpVirDev->SetLineColor( maBackCol );
     536           0 :     mpVirDev->SetFillColor( maBackCol );
     537           0 :     mpVirDev->DrawPolyPolygon( aPPoly );
     538           0 : }
     539             : 
     540           0 : void FrameSelectorImpl::DrawArrows( const FrameBorder& rBorder )
     541             : {
     542             :     DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::DrawArrows - access to disabled border" );
     543             : 
     544           0 :     long nLinePos = 0;
     545           0 :     switch( rBorder.GetType() )
     546             :     {
     547             :         case FRAMEBORDER_LEFT:
     548           0 :         case FRAMEBORDER_TOP:       nLinePos = mnLine1; break;
     549             :         case FRAMEBORDER_VER:
     550           0 :         case FRAMEBORDER_HOR:       nLinePos = mnLine2; break;
     551             :         case FRAMEBORDER_RIGHT:
     552           0 :         case FRAMEBORDER_BOTTOM:    nLinePos = mnLine3; break;
     553             :         default: ; //prevent warning
     554             :     }
     555           0 :     nLinePos -= mnArrowSize / 2;
     556             : 
     557           0 :     long nTLPos = 0;
     558           0 :     long nBRPos = mnCtrlSize - mnArrowSize;
     559           0 :     Point aPos1, aPos2;
     560           0 :     sal_uInt16 nImgId1 = 0, nImgId2 = 0;
     561           0 :     switch( rBorder.GetType() )
     562             :     {
     563             :         case FRAMEBORDER_LEFT:
     564             :         case FRAMEBORDER_RIGHT:
     565             :         case FRAMEBORDER_VER:
     566           0 :             aPos1 = Point( nLinePos, nTLPos ); nImgId1 = 1;
     567           0 :             aPos2 = Point( nLinePos, nBRPos ); nImgId2 = 2;
     568           0 :         break;
     569             : 
     570             :         case FRAMEBORDER_TOP:
     571             :         case FRAMEBORDER_BOTTOM:
     572             :         case FRAMEBORDER_HOR:
     573           0 :             aPos1 = Point( nTLPos, nLinePos ); nImgId1 = 3;
     574           0 :             aPos2 = Point( nBRPos, nLinePos ); nImgId2 = 4;
     575           0 :         break;
     576             : 
     577             :         case FRAMEBORDER_TLBR:
     578           0 :             aPos1 = Point( nTLPos, nTLPos ); nImgId1 = 5;
     579           0 :             aPos2 = Point( nBRPos, nBRPos ); nImgId2 = 6;
     580           0 :         break;
     581             :         case FRAMEBORDER_BLTR:
     582           0 :             aPos1 = Point( nTLPos, nBRPos ); nImgId1 = 7;
     583           0 :             aPos2 = Point( nBRPos, nTLPos ); nImgId2 = 8;
     584           0 :         break;
     585             :         default: ; //prevent warning
     586             :     }
     587             : 
     588             :     // Arrow or marker? Do not draw arrows into disabled control.
     589           0 :     sal_uInt16 nSelectAdd = (mrFrameSel.IsEnabled() && rBorder.IsSelected()) ? 0 : 8;
     590           0 :     mpVirDev->DrawImage( aPos1, maILArrows.GetImage( nImgId1 + nSelectAdd ) );
     591           0 :     mpVirDev->DrawImage( aPos2, maILArrows.GetImage( nImgId2 + nSelectAdd ) );
     592           0 : }
     593             : 
     594           0 : void FrameSelectorImpl::DrawAllArrows()
     595             : {
     596           0 :     for(FrameBorderCIter aIt(maEnabBorders); aIt.Is(); ++aIt)
     597           0 :         DrawArrows(**aIt);
     598           0 : }
     599             : 
     600           0 : Color FrameSelectorImpl::GetDrawLineColor( const Color& rColor ) const
     601             : {
     602           0 :     Color aColor( mbHCMode ? maHCLineCol : rColor );
     603           0 :     if( aColor == maBackCol )
     604           0 :         aColor.Invert();
     605           0 :     return aColor;
     606             : }
     607             : 
     608           0 : void FrameSelectorImpl::DrawAllFrameBorders()
     609             : {
     610             :     // Translate core colors to current UI colors (regards current background and HC mode).
     611           0 :     for( FrameBorderIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
     612             :     {
     613           0 :         Color aCoreColorPrim = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColorOut();
     614           0 :         Color aCoreColorSecn = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColorIn();
     615           0 :         (*aIt)->SetUIColorPrim( GetDrawLineColor( aCoreColorPrim ) );
     616           0 :         (*aIt)->SetUIColorSecn( GetDrawLineColor( aCoreColorSecn ) );
     617             :     }
     618             : 
     619             :     // Copy all frame border styles to the helper array
     620           0 :     maArray.SetColumnStyleLeft( 0, maLeft.GetUIStyle() );
     621           0 :     if( mbVer ) maArray.SetColumnStyleLeft( 1, maVer.GetUIStyle() );
     622             : 
     623             :     // Invert the style for the right line
     624           0 :     const frame::Style rRightStyle = maRight.GetUIStyle( );
     625           0 :     frame::Style rInvertedRight( rRightStyle.GetColorPrim(),
     626           0 :             rRightStyle.GetColorSecn(), rRightStyle.GetColorGap(),
     627           0 :             rRightStyle.UseGapColor(),
     628             :             rRightStyle.Secn(), rRightStyle.Dist(), rRightStyle.Prim( ),
     629           0 :             rRightStyle.Type( ) );
     630           0 :     maArray.SetColumnStyleRight( mbVer ? 1 : 0, rInvertedRight );
     631             : 
     632           0 :     maArray.SetRowStyleTop( 0, maTop.GetUIStyle() );
     633           0 :     if( mbHor )
     634             :     {
     635             :         // Invert the style for the hor line to match the real borders
     636           0 :         const frame::Style rHorStyle = maHor.GetUIStyle();
     637           0 :         frame::Style rInvertedHor( rHorStyle.GetColorPrim(),
     638           0 :             rHorStyle.GetColorSecn(), rHorStyle.GetColorGap(),
     639           0 :             rHorStyle.UseGapColor(),
     640             :             rHorStyle.Secn(), rHorStyle.Dist(), rHorStyle.Prim( ),
     641           0 :             rHorStyle.Type() );
     642           0 :         maArray.SetRowStyleTop( 1, rInvertedHor );
     643             :     }
     644             : 
     645             :     // Invert the style for the bottom line
     646           0 :     const frame::Style rBottomStyle = maBottom.GetUIStyle( );
     647           0 :     frame::Style rInvertedBottom( rBottomStyle.GetColorPrim(),
     648           0 :             rBottomStyle.GetColorSecn(), rBottomStyle.GetColorGap(),
     649           0 :             rBottomStyle.UseGapColor(),
     650             :             rBottomStyle.Secn(), rBottomStyle.Dist(), rBottomStyle.Prim( ),
     651           0 :             rBottomStyle.Type() );
     652           0 :     maArray.SetRowStyleBottom( mbHor ? 1 : 0, rInvertedBottom );
     653             : 
     654           0 :     for( size_t nCol = 0; nCol < maArray.GetColCount(); ++nCol )
     655           0 :         for( size_t nRow = 0; nRow < maArray.GetRowCount(); ++nRow )
     656           0 :             maArray.SetCellStyleDiag( nCol, nRow, maTLBR.GetUIStyle(), maBLTR.GetUIStyle() );
     657             : 
     658             :     // Let the helper array draw itself
     659           0 :     maArray.DrawArray( *mpVirDev.get() );
     660           0 : }
     661             : 
     662           0 : void FrameSelectorImpl::DrawVirtualDevice()
     663             : {
     664           0 :     DrawBackground();
     665           0 :     DrawAllArrows();
     666           0 :     DrawAllFrameBorders();
     667           0 :     mbFullRepaint = false;
     668           0 : }
     669             : 
     670           0 : void FrameSelectorImpl::CopyVirDevToControl(vcl::RenderContext& rRenderContext)
     671             : {
     672           0 :     if (mbFullRepaint)
     673           0 :         DrawVirtualDevice();
     674           0 :     rRenderContext.DrawBitmap(maVirDevPos, mpVirDev->GetBitmap(Point(0, 0), mpVirDev->GetOutputSizePixel()));
     675           0 : }
     676             : 
     677           0 : void FrameSelectorImpl::DrawAllTrackingRects()
     678             : {
     679           0 :     tools::PolyPolygon aPPoly;
     680           0 :     if (mrFrameSel.IsAnyBorderSelected())
     681             :     {
     682           0 :         for(SelFrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt)
     683           0 :             (*aIt)->MergeFocusToPolyPolygon(aPPoly);
     684           0 :         aPPoly.Move(maVirDevPos.X(), maVirDevPos.Y());
     685             :     }
     686             :     else
     687             :         // no frame border selected -> draw tracking rectangle around entire control
     688           0 :         aPPoly.Insert(Polygon(Rectangle(maVirDevPos, mpVirDev->GetOutputSizePixel())));
     689             : 
     690           0 :     aPPoly.Optimize(PolyOptimizeFlags::CLOSE);
     691           0 :     for(sal_uInt16 nIdx = 0, nCount = aPPoly.Count(); nIdx < nCount; ++nIdx)
     692           0 :         mrFrameSel.InvertTracking(aPPoly.GetObject(nIdx), SHOWTRACK_SMALL | SHOWTRACK_WINDOW);
     693           0 : }
     694             : 
     695           0 : Point FrameSelectorImpl::GetDevPosFromMousePos( const Point& rMousePos ) const
     696             : {
     697           0 :     return rMousePos - maVirDevPos;
     698             : }
     699             : 
     700           0 : void FrameSelectorImpl::DoInvalidate( bool bFullRepaint )
     701             : {
     702           0 :     mbFullRepaint |= bFullRepaint;
     703           0 :     mrFrameSel.Invalidate( InvalidateFlags::NoErase );
     704           0 : }
     705             : 
     706             : // frame border state and style
     707           0 : void FrameSelectorImpl::SetBorderState( FrameBorder& rBorder, FrameBorderState eState )
     708             : {
     709             :     DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderState - access to disabled border" );
     710           0 :     Any aOld;
     711           0 :     Any aNew;
     712           0 :     Any& rMod = eState == FRAMESTATE_SHOW ? aNew : aOld;
     713           0 :     rMod <<= AccessibleStateType::CHECKED;
     714           0 :     Reference< XAccessible > xRet;
     715           0 :     size_t nVecIdx = static_cast< size_t >( rBorder.GetType() );
     716           0 :     if( GetBorder(rBorder.GetType()).IsEnabled() && (1 <= nVecIdx) && (nVecIdx <= maChildVec.size()) )
     717           0 :         xRet = mxChildVec[ --nVecIdx ];
     718           0 :     a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get());
     719             : 
     720           0 :     if( eState == FRAMESTATE_SHOW )
     721           0 :         SetBorderCoreStyle( rBorder, &maCurrStyle );
     722             :     else
     723           0 :         rBorder.SetState( eState );
     724           0 :     if (pFrameSelector)
     725           0 :             pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOld, aNew );
     726           0 :     DoInvalidate( true );
     727           0 : }
     728             : 
     729           0 : void FrameSelectorImpl::SetBorderCoreStyle( FrameBorder& rBorder, const SvxBorderLine* pStyle )
     730             : {
     731             :     DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderCoreStyle - access to disabled border" );
     732           0 :     rBorder.SetCoreStyle( pStyle );
     733           0 :     DoInvalidate( true );
     734           0 : }
     735             : 
     736           0 : void FrameSelectorImpl::ToggleBorderState( FrameBorder& rBorder )
     737             : {
     738           0 :     bool bDontCare = mrFrameSel.SupportsDontCareState();
     739           0 :     switch( rBorder.GetState() )
     740             :     {
     741             :         // same order as tristate check box: visible -> don't care -> hidden
     742             :         case FRAMESTATE_SHOW:
     743           0 :             SetBorderState( rBorder, bDontCare ? FRAMESTATE_DONTCARE : FRAMESTATE_HIDE );
     744           0 :         break;
     745             :         case FRAMESTATE_HIDE:
     746           0 :             SetBorderState( rBorder, FRAMESTATE_SHOW );
     747           0 :         break;
     748             :         case FRAMESTATE_DONTCARE:
     749           0 :             SetBorderState( rBorder, FRAMESTATE_HIDE );
     750           0 :         break;
     751             :     }
     752           0 : }
     753             : 
     754             : // frame border selection
     755           0 : void FrameSelectorImpl::SelectBorder( FrameBorder& rBorder, bool bSelect )
     756             : {
     757             :     DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SelectBorder - access to disabled border" );
     758           0 :     rBorder.Select( bSelect );
     759           0 :     DrawArrows( rBorder );
     760           0 :     DoInvalidate( false );
     761           0 : }
     762             : 
     763           0 : void FrameSelectorImpl::SilentGrabFocus()
     764             : {
     765           0 :     bool bOldAuto = mbAutoSelect;
     766           0 :     mbAutoSelect = false;
     767           0 :     mrFrameSel.GrabFocus();
     768           0 :     mbAutoSelect = bOldAuto;
     769           0 : }
     770             : 
     771           0 : bool FrameSelectorImpl::SelectedBordersEqual() const
     772             : {
     773           0 :     bool bEqual = true;
     774           0 :     SelFrameBorderCIter aIt( maEnabBorders );
     775           0 :     if( aIt.Is() )
     776             :     {
     777           0 :         const SvxBorderLine& rFirstStyle = (*aIt)->GetCoreStyle();
     778           0 :         for( ++aIt; bEqual && aIt.Is(); ++aIt )
     779           0 :             bEqual = ((*aIt)->GetCoreStyle() == rFirstStyle);
     780             :     }
     781           0 :     return bEqual;
     782             : }
     783             : 
     784           0 : FrameSelector::FrameSelector(vcl::Window* pParent)
     785           0 :     : Control(pParent, WB_BORDER|WB_TABSTOP)
     786             : {
     787             :     // not in c'tor init list (avoid warning about usage of *this)
     788           0 :     mxImpl.reset( new FrameSelectorImpl( *this ) );
     789           0 :     EnableRTL( false ); // #107808# don't mirror the mouse handling
     790           0 : }
     791             : 
     792           0 : FrameSelector::~FrameSelector()
     793             : {
     794           0 :     disposeOnce();
     795           0 : }
     796             : 
     797           0 : VCL_BUILDER_DECL_FACTORY(SvxFrameSelector)
     798             : {
     799             :     (void)rMap;
     800           0 :     rRet = VclPtr<FrameSelector>::Create(pParent);
     801           0 : }
     802             : 
     803           0 : void FrameSelector::Initialize( FrameSelFlags nFlags )
     804             : {
     805           0 :     mxImpl->Initialize( nFlags );
     806           0 :     Show();
     807           0 : }
     808             : 
     809             : // enabled frame borders
     810           0 : bool FrameSelector::IsBorderEnabled( FrameBorderType eBorder ) const
     811             : {
     812           0 :     return mxImpl->GetBorder( eBorder ).IsEnabled();
     813             : }
     814             : 
     815           0 : sal_Int32 FrameSelector::GetEnabledBorderCount() const
     816             : {
     817           0 :     return static_cast< sal_Int32 >( mxImpl->maEnabBorders.size() );
     818             : }
     819             : 
     820           0 : FrameBorderType FrameSelector::GetEnabledBorderType( sal_Int32 nIndex ) const
     821             : {
     822           0 :     FrameBorderType eBorder = FRAMEBORDER_NONE;
     823           0 :     if( nIndex >= 0 )
     824             :     {
     825           0 :         size_t nVecIdx = static_cast< size_t >( nIndex );
     826           0 :         if( nVecIdx < mxImpl->maEnabBorders.size() )
     827           0 :             eBorder = mxImpl->maEnabBorders[ nVecIdx ]->GetType();
     828             :     }
     829           0 :     return eBorder;
     830             : }
     831             : 
     832           0 : sal_Int32 FrameSelector::GetEnabledBorderIndex( FrameBorderType eBorder ) const
     833             : {
     834           0 :     sal_Int32 nIndex = 0;
     835           0 :     for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt, ++nIndex )
     836           0 :         if( (*aIt)->GetType() == eBorder )
     837           0 :             return nIndex;
     838           0 :     return -1;
     839             : }
     840             : 
     841             : // frame border state and style
     842           0 : bool FrameSelector::SupportsDontCareState() const
     843             : {
     844           0 :     return (mxImpl->mnFlags & FRAMESEL_DONTCARE) != 0;
     845             : }
     846             : 
     847           0 : FrameBorderState FrameSelector::GetFrameBorderState( FrameBorderType eBorder ) const
     848             : {
     849           0 :     return mxImpl->GetBorder( eBorder ).GetState();
     850             : }
     851             : 
     852           0 : const SvxBorderLine* FrameSelector::GetFrameBorderStyle( FrameBorderType eBorder ) const
     853             : {
     854           0 :     const SvxBorderLine& rStyle = mxImpl->GetBorder( eBorder ).GetCoreStyle();
     855             :     // rest of the world uses null pointer for invisible frame border
     856           0 :     return rStyle.GetOutWidth() ? &rStyle : 0;
     857             : }
     858             : 
     859           0 : void FrameSelector::ShowBorder( FrameBorderType eBorder, const SvxBorderLine* pStyle )
     860             : {
     861           0 :     mxImpl->SetBorderCoreStyle( mxImpl->GetBorderAccess( eBorder ), pStyle );
     862           0 : }
     863             : 
     864           0 : void FrameSelector::SetBorderDontCare( FrameBorderType eBorder )
     865             : {
     866           0 :     mxImpl->SetBorderState( mxImpl->GetBorderAccess( eBorder ), FRAMESTATE_DONTCARE );
     867           0 : }
     868             : 
     869           0 : bool FrameSelector::IsAnyBorderVisible() const
     870             : {
     871           0 :     bool bIsSet = false;
     872           0 :     for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bIsSet && aIt.Is(); ++aIt )
     873           0 :         bIsSet = ((*aIt)->GetState() == FRAMESTATE_SHOW);
     874           0 :     return bIsSet;
     875             : }
     876             : 
     877           0 : void FrameSelector::HideAllBorders()
     878             : {
     879           0 :     for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
     880           0 :         mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );
     881           0 : }
     882             : 
     883           0 : bool FrameSelector::GetVisibleWidth( long& rnWidth, SvxBorderStyle& rnStyle ) const
     884             : {
     885           0 :     VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
     886           0 :     if( !aIt.Is() )
     887           0 :         return false;
     888             : 
     889           0 :     const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
     890           0 :     bool bFound = true;
     891           0 :     for( ++aIt; bFound && aIt.Is(); ++aIt )
     892             :     {
     893             :         bFound =
     894           0 :             (rStyle.GetWidth() == (*aIt)->GetCoreStyle().GetWidth()) &&
     895           0 :             (rStyle.GetBorderLineStyle() ==
     896           0 :                 (*aIt)->GetCoreStyle().GetBorderLineStyle());
     897             :     }
     898             : 
     899           0 :     if( bFound )
     900             :     {
     901           0 :         rnWidth = rStyle.GetWidth();
     902           0 :         rnStyle = rStyle.GetBorderLineStyle();
     903             :     }
     904           0 :     return bFound;
     905             : }
     906             : 
     907           0 : bool FrameSelector::GetVisibleColor( Color& rColor ) const
     908             : {
     909           0 :     VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
     910           0 :     if( !aIt.Is() )
     911           0 :         return false;
     912             : 
     913           0 :     const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
     914           0 :     bool bFound = true;
     915           0 :     for( ++aIt; bFound && aIt.Is(); ++aIt )
     916           0 :         bFound = (rStyle.GetColor() == (*aIt)->GetCoreStyle().GetColor());
     917             : 
     918           0 :     if( bFound )
     919           0 :         rColor = rStyle.GetColor();
     920           0 :     return bFound;
     921             : }
     922             : 
     923             : // frame border selection
     924           0 : const Link<>& FrameSelector::GetSelectHdl() const
     925             : {
     926           0 :     return mxImpl->maSelectHdl;
     927             : }
     928             : 
     929           0 : void FrameSelector::SetSelectHdl( const Link<>& rHdl )
     930             : {
     931           0 :     mxImpl->maSelectHdl = rHdl;
     932           0 : }
     933             : 
     934           0 : bool FrameSelector::IsBorderSelected( FrameBorderType eBorder ) const
     935             : {
     936           0 :     return mxImpl->GetBorder( eBorder ).IsSelected();
     937             : }
     938             : 
     939           0 : void FrameSelector::SelectBorder( FrameBorderType eBorder, bool bSelect /*, bool bFocus */ )
     940             : {
     941           0 :     mxImpl->SelectBorder( mxImpl->GetBorderAccess( eBorder ), bSelect );
     942             :     // MT: bFireFox as API parameter is ugly...
     943             :     // if (bFocus)
     944             :     {
     945           0 :         Reference< XAccessible > xRet = GetChildAccessible(eBorder);
     946           0 :         a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get());
     947           0 :         if (pFrameSelector)
     948             :         {
     949           0 :             Any aOldValue, aNewValue;
     950           0 :             aNewValue <<= AccessibleStateType::FOCUSED;
     951           0 :             pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
     952           0 :         }
     953             :     }
     954           0 : }
     955             : 
     956           0 : bool FrameSelector::IsAnyBorderSelected() const
     957             : {
     958             :     // Construct an iterator for selected borders. If it is valid, there is a selected border.
     959           0 :     return SelFrameBorderCIter( mxImpl->maEnabBorders ).Is();
     960             : }
     961             : 
     962           0 : void FrameSelector::SelectAllBorders( bool bSelect )
     963             : {
     964           0 :     for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
     965           0 :         mxImpl->SelectBorder( **aIt, bSelect );
     966           0 : }
     967             : 
     968           0 : void FrameSelector::SelectAllVisibleBorders( bool bSelect )
     969             : {
     970           0 :     for( VisFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
     971           0 :         mxImpl->SelectBorder( **aIt, bSelect );
     972           0 : }
     973             : 
     974           0 : void FrameSelector::SetStyleToSelection( long nWidth, SvxBorderStyle nStyle )
     975             : {
     976           0 :     mxImpl->maCurrStyle.SetBorderLineStyle( nStyle );
     977           0 :     mxImpl->maCurrStyle.SetWidth( nWidth );
     978           0 :     for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
     979           0 :         mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
     980           0 : }
     981             : 
     982           0 : void FrameSelector::SetColorToSelection( const Color& rColor )
     983             : {
     984           0 :     mxImpl->maCurrStyle.SetColor( rColor );
     985           0 :     for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
     986           0 :         mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
     987           0 : }
     988             : 
     989             : // accessibility
     990           0 : Reference< XAccessible > FrameSelector::CreateAccessible()
     991             : {
     992           0 :     if( !mxImpl->mxAccess.is() )
     993           0 :         mxImpl->mxAccess = mxImpl->mpAccess =
     994           0 :             new a11y::AccFrameSelector( *this, FRAMEBORDER_NONE );
     995           0 :     return mxImpl->mxAccess;
     996             : }
     997             : 
     998           0 : Reference< XAccessible > FrameSelector::GetChildAccessible( FrameBorderType eBorder )
     999             : {
    1000           0 :     Reference< XAccessible > xRet;
    1001           0 :     size_t nVecIdx = static_cast< size_t >( eBorder );
    1002           0 :     if( IsBorderEnabled( eBorder ) && (1 <= nVecIdx) && (nVecIdx <= mxImpl->maChildVec.size()) )
    1003             :     {
    1004           0 :         --nVecIdx;
    1005           0 :         if( !mxImpl->maChildVec[ nVecIdx ] )
    1006           0 :             mxImpl->mxChildVec[ nVecIdx ] = mxImpl->maChildVec[ nVecIdx ] =
    1007           0 :                 new a11y::AccFrameSelector( *this, eBorder );
    1008           0 :         xRet = mxImpl->mxChildVec[ nVecIdx ];
    1009             :     }
    1010           0 :     return xRet;
    1011             : }
    1012             : 
    1013           0 : Reference< XAccessible > FrameSelector::GetChildAccessible( sal_Int32 nIndex )
    1014             : {
    1015           0 :     return GetChildAccessible( GetEnabledBorderType( nIndex ) );
    1016             : }
    1017             : 
    1018           0 : Reference< XAccessible > FrameSelector::GetChildAccessible( const Point& rPos )
    1019             : {
    1020           0 :     Reference< XAccessible > xRet;
    1021           0 :     for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !xRet.is() && aIt.Is(); ++aIt )
    1022           0 :         if( (*aIt)->ContainsClickPoint( rPos ) )
    1023           0 :             xRet = GetChildAccessible( (*aIt)->GetType() );
    1024           0 :     return xRet;
    1025             : }
    1026             : 
    1027           0 : bool FrameSelector::ContainsClickPoint( const Point& rPos ) const
    1028             : {
    1029           0 :     bool bContains = false;
    1030           0 :     for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bContains && aIt.Is(); ++aIt )
    1031           0 :         bContains = (*aIt)->ContainsClickPoint( rPos );
    1032           0 :     return bContains;
    1033             : }
    1034             : 
    1035           0 : Rectangle FrameSelector::GetClickBoundRect( FrameBorderType eBorder ) const
    1036             : {
    1037           0 :     Rectangle aRect;
    1038           0 :     const FrameBorder& rBorder = mxImpl->GetBorder( eBorder );
    1039           0 :     if( rBorder.IsEnabled() )
    1040           0 :         aRect = rBorder.GetClickBoundRect();
    1041           0 :     return aRect;
    1042             : }
    1043             : 
    1044             : // virtual functions from base class
    1045           0 : void FrameSelector::Paint(vcl::RenderContext& rRenderContext, const Rectangle&)
    1046             : {
    1047           0 :     mxImpl->CopyVirDevToControl(rRenderContext);
    1048           0 :     if (HasFocus())
    1049           0 :         mxImpl->DrawAllTrackingRects();
    1050           0 : }
    1051             : 
    1052           0 : void FrameSelector::MouseButtonDown( const MouseEvent& rMEvt )
    1053             : {
    1054             :     /*  Mouse handling:
    1055             :         * Click on an unselected frame border:
    1056             :             Set current style/color, make frame border visible, deselect all
    1057             :             other frame borders.
    1058             :         * Click on a selected frame border:
    1059             :             Toggle state of the frame border (visible -> don't care -> hidden),
    1060             :             deselect all other frame borders.
    1061             :         * SHIFT+Click or CTRL+Click on an unselected frame border:
    1062             :             Extend selection, set current style/color to all selected frame
    1063             :             borders independent of the state/style/color of the borders.
    1064             :         * SHIFT+Click or CTRL+Click on a selected frame border:
    1065             :             If all frame borders have same style/color, toggle state of all
    1066             :             borders (see above), otherwise set current style/color to all
    1067             :             borders.
    1068             :         * Click on unused area: Do not modify selection and selected frame
    1069             :             borders.
    1070             :      */
    1071             : 
    1072             :     // #107394# do not auto-select a frame border
    1073           0 :     mxImpl->SilentGrabFocus();
    1074             : 
    1075           0 :     if( rMEvt.IsLeft() )
    1076             :     {
    1077           0 :         Point aPos( mxImpl->GetDevPosFromMousePos( rMEvt.GetPosPixel() ) );
    1078           0 :         FrameBorderPtrVec aDeselectBorders;
    1079             : 
    1080           0 :         bool bAnyClicked = false;   // Any frame border clicked?
    1081           0 :         bool bNewSelected = false;  // Any unselected frame border selected?
    1082             : 
    1083             :         /*  If frame borders are set to "don't care" and the control does not
    1084             :             support this state, hide them on first mouse click.
    1085             :             DR 2004-01-30: Why are the borders set to "don't care" then?!? */
    1086           0 :         bool bHideDontCare = !mxImpl->mbClicked && !SupportsDontCareState();
    1087             : 
    1088           0 :         for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
    1089             :         {
    1090           0 :             if( (*aIt)->ContainsClickPoint( aPos ) )
    1091             :             {
    1092             :                 // frame border is clicked
    1093           0 :                 bAnyClicked = true;
    1094           0 :                 if( !(*aIt)->IsSelected() )
    1095             :                 {
    1096           0 :                     bNewSelected = true;
    1097             :                     //mxImpl->SelectBorder( **aIt, true );
    1098           0 :                     SelectBorder((**aIt).GetType(), true);
    1099             :                 }
    1100             :             }
    1101             :             else
    1102             :             {
    1103             :                 // hide a "don't care" frame border only if it is not clicked
    1104           0 :                 if( bHideDontCare && ((*aIt)->GetState() == FRAMESTATE_DONTCARE) )
    1105           0 :                     mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );
    1106             : 
    1107             :                 // deselect frame borders not clicked (if SHIFT or CTRL are not pressed)
    1108           0 :                 if( !rMEvt.IsShift() && !rMEvt.IsMod1() )
    1109           0 :                     aDeselectBorders.push_back( *aIt );
    1110             :             }
    1111             :         }
    1112             : 
    1113           0 :         if( bAnyClicked )
    1114             :         {
    1115             :             // any valid frame border clicked? -> deselect other frame borders
    1116           0 :             for( FrameBorderIter aIt( aDeselectBorders ); aIt.Is(); ++aIt )
    1117           0 :                 mxImpl->SelectBorder( **aIt, false );
    1118             : 
    1119           0 :             if( bNewSelected || !mxImpl->SelectedBordersEqual() )
    1120             :             {
    1121             :                 // new frame border selected, selection extended, or selected borders different? -> show
    1122           0 :                 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
    1123             :                     // SetBorderState() sets current style and color to the frame border
    1124           0 :                     mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
    1125             :             }
    1126             :             else
    1127             :             {
    1128             :                 // all selected frame borders are equal -> toggle state
    1129           0 :                 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
    1130           0 :                     mxImpl->ToggleBorderState( **aIt );
    1131             :             }
    1132             : 
    1133           0 :             GetSelectHdl().Call( this );
    1134           0 :         }
    1135             :     }
    1136           0 : }
    1137             : 
    1138           0 : void FrameSelector::KeyInput( const KeyEvent& rKEvt )
    1139             : {
    1140           0 :     bool bHandled = false;
    1141           0 :     vcl::KeyCode aKeyCode = rKEvt.GetKeyCode();
    1142           0 :     if( !aKeyCode.GetModifier() )
    1143             :     {
    1144           0 :         sal_uInt16 nCode = aKeyCode.GetCode();
    1145           0 :         switch( nCode )
    1146             :         {
    1147             :             case KEY_SPACE:
    1148             :             {
    1149           0 :                 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
    1150           0 :                     mxImpl->ToggleBorderState( **aIt );
    1151           0 :                 bHandled = true;
    1152             :             }
    1153           0 :             break;
    1154             : 
    1155             :             case KEY_UP:
    1156             :             case KEY_DOWN:
    1157             :             case KEY_LEFT:
    1158             :             case KEY_RIGHT:
    1159             :             {
    1160           0 :                 if( !mxImpl->maEnabBorders.empty() )
    1161             :                 {
    1162             :                     // start from first selected frame border
    1163           0 :                     SelFrameBorderCIter aIt( mxImpl->maEnabBorders );
    1164           0 :                     FrameBorderType eBorder = aIt.Is() ? (*aIt)->GetType() : mxImpl->maEnabBorders.front()->GetType();
    1165             : 
    1166             :                     // search for next enabled frame border
    1167           0 :                     do
    1168             :                     {
    1169           0 :                         eBorder = mxImpl->GetBorder( eBorder ).GetKeyboardNeighbor( nCode );
    1170             :                     }
    1171           0 :                     while( (eBorder != FRAMEBORDER_NONE) && !IsBorderEnabled( eBorder ) );
    1172             : 
    1173             :                     // select the frame border
    1174           0 :                     if( eBorder != FRAMEBORDER_NONE )
    1175             :                     {
    1176           0 :                         DeselectAllBorders();
    1177           0 :                         SelectBorder( eBorder );
    1178             :                     }
    1179             :                 }
    1180             :             }
    1181           0 :             break;
    1182             :         }
    1183             :     }
    1184           0 :     if( !bHandled )
    1185           0 :         Window::KeyInput(rKEvt);
    1186           0 : }
    1187             : 
    1188           0 : void FrameSelector::GetFocus()
    1189             : {
    1190             :     // auto-selection of a frame border, if focus reaches control, and nothing is selected
    1191           0 :     if( mxImpl->mbAutoSelect && !IsAnyBorderSelected() && !mxImpl->maEnabBorders.empty() )
    1192           0 :         mxImpl->SelectBorder( *mxImpl->maEnabBorders.front(), true );
    1193             : 
    1194           0 :     mxImpl->DoInvalidate( false );
    1195           0 :     if( mxImpl->mxAccess.is() )
    1196           0 :         mxImpl->mpAccess->NotifyFocusListeners( true );
    1197           0 :     if (IsAnyBorderSelected())
    1198             :     {
    1199           0 :         FrameBorderType borderType = FRAMEBORDER_NONE;
    1200           0 :         if (mxImpl->maLeft.IsSelected())
    1201           0 :             borderType = FRAMEBORDER_LEFT;
    1202           0 :         else if (mxImpl->maRight.IsSelected())
    1203           0 :             borderType = FRAMEBORDER_RIGHT;
    1204           0 :         else if (mxImpl->maTop.IsSelected())
    1205           0 :             borderType = FRAMEBORDER_TOP;
    1206           0 :         else if (mxImpl->maBottom.IsSelected())
    1207           0 :             borderType = FRAMEBORDER_BOTTOM;
    1208           0 :         else if (mxImpl->maHor.IsSelected())
    1209           0 :             borderType = FRAMEBORDER_HOR;
    1210           0 :         else if (mxImpl->maVer.IsSelected())
    1211           0 :             borderType = FRAMEBORDER_VER;
    1212           0 :         else if (mxImpl->maTLBR.IsSelected())
    1213           0 :             borderType = FRAMEBORDER_TLBR;
    1214           0 :         else if (mxImpl->maBLTR.IsSelected())
    1215           0 :             borderType = FRAMEBORDER_BLTR;
    1216           0 :         SelectBorder(borderType);
    1217             :     }
    1218           0 :     for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
    1219           0 :             mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
    1220           0 :     Control::GetFocus();
    1221           0 : }
    1222             : 
    1223           0 : void FrameSelector::LoseFocus()
    1224             : {
    1225           0 :     mxImpl->DoInvalidate( false );
    1226           0 :     if( mxImpl->mxAccess.is() )
    1227           0 :         mxImpl->mpAccess->NotifyFocusListeners( false );
    1228           0 :     Control::LoseFocus();
    1229           0 : }
    1230             : 
    1231           0 : void FrameSelector::DataChanged( const DataChangedEvent& rDCEvt )
    1232             : {
    1233           0 :     Control::DataChanged( rDCEvt );
    1234           0 :     if( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
    1235           0 :         mxImpl->InitVirtualDevice();
    1236           0 : }
    1237             : 
    1238           0 : void FrameSelector::Resize()
    1239             : {
    1240           0 :     Control::Resize();
    1241           0 :     mxImpl->sizeChanged();
    1242           0 : }
    1243             : 
    1244           0 : Size FrameSelector::GetOptimalSize() const
    1245             : {
    1246           0 :     return LogicToPixel(Size(61, 65), MAP_APPFONT);
    1247             : }
    1248             : 
    1249             : 
    1250             : 
    1251             : template< typename Cont, typename Iter, typename Pred >
    1252           0 : FrameBorderIterBase< Cont, Iter, Pred >::FrameBorderIterBase( container_type& rCont ) :
    1253             :     maIt( rCont.begin() ),
    1254           0 :     maEnd( rCont.end() )
    1255             : {
    1256           0 :     while( Is() && !maPred( *maIt ) ) ++maIt;
    1257           0 : }
    1258             : 
    1259             : template< typename Cont, typename Iter, typename Pred >
    1260           0 : FrameBorderIterBase< Cont, Iter, Pred >& FrameBorderIterBase< Cont, Iter, Pred >::operator++()
    1261             : {
    1262           0 :     do { ++maIt; } while( Is() && !maPred( *maIt ) );
    1263           0 :     return *this;
    1264             : }
    1265             : 
    1266             : 
    1267             : 
    1268         390 : }
    1269             : 
    1270             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11