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