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