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