bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / dialog / frmsel.cxx
blobf29a42a17cfe746a8610f64543b3339781def229
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svx/frmsel.hxx>
21 #include <vcl/builder.hxx>
23 #include <algorithm>
24 #include <math.h>
25 #include "frmselimpl.hxx"
26 #include "AccessibleFrameSelector.hxx"
27 #include <svx/dialmgr.hxx>
29 #include <svx/dialogs.hrc>
30 #include "frmsel.hrc"
32 #include <tools/rcid.h>
34 using namespace ::com::sun::star;
35 using namespace ::editeng;
37 namespace svx {
39 using ::com::sun::star::uno::Reference;
40 using ::com::sun::star::accessibility::XAccessible;
42 // ============================================================================
43 // global functions from framebordertype.hxx
45 FrameBorderType GetFrameBorderTypeFromIndex( size_t nIndex )
47 DBG_ASSERT( nIndex < (size_t)FRAMEBORDERTYPE_COUNT,
48 "svx::GetFrameBorderTypeFromIndex - invalid index" );
49 return static_cast< FrameBorderType >( nIndex + 1 );
52 size_t GetIndexFromFrameBorderType( FrameBorderType eBorder )
54 DBG_ASSERT( eBorder != FRAMEBORDER_NONE,
55 "svx::GetIndexFromFrameBorderType - invalid frame border type" );
56 return static_cast< size_t >( eBorder ) - 1;
59 // ============================================================================
61 namespace {
63 /** Space between outer control border and any graphical element of the control. */
64 const long FRAMESEL_GEOM_OUTER = 2;
66 /** Space between arrows and usable inner area. */
67 const long FRAMESEL_GEOM_INNER = 3;
69 /** Maximum width to draw a frame border style. */
70 const long FRAMESEL_GEOM_WIDTH = 9;
72 /** Additional margin for click area of outer lines. */
73 const long FRAMESEL_GEOM_ADD_CLICK_OUTER = 5;
75 /** Additional margin for click area of inner lines. */
76 const long FRAMESEL_GEOM_ADD_CLICK_INNER = 2;
78 // ----------------------------------------------------------------------------
80 /** Returns the corresponding flag for a frame border. */
81 FrameSelFlags lclGetFlagFromType( FrameBorderType eBorder )
83 switch( eBorder )
85 case FRAMEBORDER_LEFT: return FRAMESEL_LEFT;
86 case FRAMEBORDER_RIGHT: return FRAMESEL_RIGHT;
87 case FRAMEBORDER_TOP: return FRAMESEL_TOP;
88 case FRAMEBORDER_BOTTOM: return FRAMESEL_BOTTOM;
89 case FRAMEBORDER_HOR: return FRAMESEL_INNER_HOR;
90 case FRAMEBORDER_VER: return FRAMESEL_INNER_VER;
91 case FRAMEBORDER_TLBR: return FRAMESEL_DIAG_TLBR;
92 case FRAMEBORDER_BLTR: return FRAMESEL_DIAG_BLTR;
93 case FRAMEBORDER_NONE : break;
95 return FRAMESEL_NONE;
98 /** Merges the rSource polypolygon into the rDest polypolygon. */
99 inline void lclPolyPolyUnion( PolyPolygon& rDest, const PolyPolygon& rSource )
101 const PolyPolygon aTmp( rDest );
102 aTmp.GetUnion( rSource, rDest );
105 } // namespace
107 // ============================================================================
108 // FrameBorder
109 // ============================================================================
111 FrameBorder::FrameBorder( FrameBorderType eType ) :
112 meType( eType ),
113 meState( FRAMESTATE_HIDE ),
114 meKeyLeft( FRAMEBORDER_NONE ),
115 meKeyRight( FRAMEBORDER_NONE ),
116 meKeyTop( FRAMEBORDER_NONE ),
117 meKeyBottom( FRAMEBORDER_NONE ),
118 mbEnabled( false ),
119 mbSelected( false )
123 void FrameBorder::Enable( FrameSelFlags nFlags )
125 mbEnabled = (nFlags & lclGetFlagFromType( meType )) != 0;
126 if( !mbEnabled )
127 SetState( FRAMESTATE_HIDE );
130 void FrameBorder::SetCoreStyle( const SvxBorderLine* pStyle )
132 if( pStyle )
133 maCoreStyle = *pStyle;
134 else
135 maCoreStyle = SvxBorderLine();
137 // from twips to points
138 maUIStyle.Set( maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH );
139 meState = maUIStyle.Prim() ? FRAMESTATE_SHOW : FRAMESTATE_HIDE;
142 void FrameBorder::SetState( FrameBorderState eState )
144 meState = eState;
145 switch( meState )
147 case FRAMESTATE_SHOW:
148 SAL_WARN( "svx.dialog", "svx::FrameBorder::SetState - use SetCoreStyle to make border visible" );
149 break;
150 case FRAMESTATE_HIDE:
151 maCoreStyle = SvxBorderLine();
152 maUIStyle.Clear();
153 break;
154 case FRAMESTATE_DONTCARE:
155 maCoreStyle = SvxBorderLine();
156 maUIStyle = frame::Style(3, 0, 0, table::BorderLineStyle::SOLID); //OBJ_FRAMESTYLE_DONTCARE
157 break;
161 void FrameBorder::AddFocusPolygon( const Polygon& rFocus )
163 lclPolyPolyUnion( maFocusArea, rFocus );
166 void FrameBorder::MergeFocusToPolyPolygon( PolyPolygon& rPPoly ) const
168 lclPolyPolyUnion( rPPoly, maFocusArea );
171 void FrameBorder::AddClickRect( const Rectangle& rRect )
173 lclPolyPolyUnion( maClickArea, Polygon( rRect ) );
176 bool FrameBorder::ContainsClickPoint( const Point& rPos ) const
178 return Region( maClickArea ).IsInside( rPos );
181 Rectangle FrameBorder::GetClickBoundRect() const
183 return maClickArea.GetBoundRect();
186 void FrameBorder::SetKeyboardNeighbors(
187 FrameBorderType eLeft, FrameBorderType eRight, FrameBorderType eTop, FrameBorderType eBottom )
189 meKeyLeft = eLeft;
190 meKeyRight = eRight;
191 meKeyTop = eTop;
192 meKeyBottom = eBottom;
195 FrameBorderType FrameBorder::GetKeyboardNeighbor( sal_uInt16 nKeyCode ) const
197 FrameBorderType eBorder = FRAMEBORDER_NONE;
198 switch( nKeyCode )
200 case KEY_LEFT: eBorder = meKeyLeft; break;
201 case KEY_RIGHT: eBorder = meKeyRight; break;
202 case KEY_UP: eBorder = meKeyTop; break;
203 case KEY_DOWN: eBorder = meKeyBottom; break;
204 default: SAL_WARN( "svx.dialog", "svx::FrameBorder::GetKeyboardNeighbor - unknown key code" );
206 return eBorder;
209 // ============================================================================
210 // FrameSelectorImpl
211 // ============================================================================
213 FrameSelectorImpl::FrameSelectorImpl( FrameSelector& rFrameSel ) :
214 Resource( SVX_RES( RID_SVXSTR_BORDER_CONTROL ) ),
215 mrFrameSel( rFrameSel ),
216 maILArrows( 16 ),
217 maLeft( FRAMEBORDER_LEFT ),
218 maRight( FRAMEBORDER_RIGHT ),
219 maTop( FRAMEBORDER_TOP ),
220 maBottom( FRAMEBORDER_BOTTOM ),
221 maHor( FRAMEBORDER_HOR ),
222 maVer( FRAMEBORDER_VER ),
223 maTLBR( FRAMEBORDER_TLBR ),
224 maBLTR( FRAMEBORDER_BLTR ),
225 mnFlags( FRAMESEL_OUTER ),
226 mnCtrlSize( 0 ),
227 mnArrowSize( 0 ),
228 mnLine1( 0 ),
229 mnLine2( 0 ),
230 mnLine3( 0 ),
231 mnFocusOffs( 0 ),
232 mbHor( false ),
233 mbVer( false ),
234 mbTLBR( false ),
235 mbBLTR( false ),
236 mbFullRepaint( true ),
237 mbAutoSelect( true ),
238 mbClicked( false ),
239 mbHCMode( false ),
240 mpAccess( 0 ),
241 maChildVec( 8, static_cast< a11y::AccFrameSelector* >( 0 ) ),
242 mxChildVec( 8 )
244 FreeResource();
246 maAllBorders.resize( FRAMEBORDERTYPE_COUNT, 0 );
247 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_LEFT ) ] = &maLeft;
248 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_RIGHT ) ] = &maRight;
249 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TOP ) ] = &maTop;
250 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BOTTOM ) ] = &maBottom;
251 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_HOR ) ] = &maHor;
252 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_VER ) ] = &maVer;
253 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TLBR ) ] = &maTLBR;
254 maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BLTR ) ] = &maBLTR;
255 #if OSL_DEBUG_LEVEL >= 2
257 bool bOk = true;
258 for( FrameBorderCIter aIt( maAllBorders ); bOk && aIt.Is(); bOk = (*aIt != 0), ++aIt );
259 DBG_ASSERT( bOk, "svx::FrameSelectorImpl::FrameSelectorImpl - missing entry in maAllBorders" );
261 #endif
262 // left neighbor right neighbor upper neighbor lower neighbor
263 maLeft.SetKeyboardNeighbors( FRAMEBORDER_NONE, FRAMEBORDER_TLBR, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM );
264 maRight.SetKeyboardNeighbors( FRAMEBORDER_BLTR, FRAMEBORDER_NONE, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM );
265 maTop.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_NONE, FRAMEBORDER_TLBR );
266 maBottom.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_BLTR, FRAMEBORDER_NONE );
267 maHor.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_TLBR, FRAMEBORDER_BLTR );
268 maVer.SetKeyboardNeighbors( FRAMEBORDER_TLBR, FRAMEBORDER_BLTR, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM );
269 maTLBR.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_VER, FRAMEBORDER_TOP, FRAMEBORDER_HOR );
270 maBLTR.SetKeyboardNeighbors( FRAMEBORDER_VER, FRAMEBORDER_RIGHT, FRAMEBORDER_HOR, FRAMEBORDER_BOTTOM );
272 Initialize(mnFlags);
275 FrameSelectorImpl::~FrameSelectorImpl()
277 if( mpAccess )
278 mpAccess->Invalidate();
279 for( AccessibleImplVec::iterator aIt = maChildVec.begin(), aEnd = maChildVec.end(); aIt != aEnd; ++aIt )
280 if( *aIt )
281 (*aIt)->Invalidate();
284 // initialization -------------------------------------------------------------
286 void FrameSelectorImpl::Initialize( FrameSelFlags nFlags )
288 mnFlags = nFlags;
290 maEnabBorders.clear();
291 for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
293 (*aIt)->Enable( mnFlags );
294 if( (*aIt)->IsEnabled() )
295 maEnabBorders.push_back( *aIt );
297 mbHor = maHor.IsEnabled();
298 mbVer = maVer.IsEnabled();
299 mbTLBR = maTLBR.IsEnabled();
300 mbBLTR = maBLTR.IsEnabled();
302 InitVirtualDevice();
305 void FrameSelectorImpl::InitColors()
307 const StyleSettings& rSett = mrFrameSel.GetSettings().GetStyleSettings();
308 maBackCol = rSett.GetFieldColor();
309 mbHCMode = rSett.GetHighContrastMode();
310 maArrowCol = rSett.GetFieldTextColor();
311 maMarkCol.operator=( maBackCol ).Merge( maArrowCol, mbHCMode ? 0x80 : 0xC0 );
312 maHCLineCol = rSett.GetLabelTextColor();
315 void FrameSelectorImpl::InitArrowImageList()
317 /* Build the arrow images bitmap with current colors. */
318 Color pColorAry1[3];
319 Color pColorAry2[3];
320 pColorAry1[0] = Color( 0, 0, 0 );
321 pColorAry2[0] = maArrowCol; // black -> arrow color
322 pColorAry1[1] = Color( 0, 255, 0 );
323 pColorAry2[1] = maMarkCol; // green -> marker color
324 pColorAry1[2] = Color( 255, 0, 255 );
325 pColorAry2[2] = maBackCol; // magenta -> background
327 GetRes( SVX_RES( RID_SVXSTR_BORDER_CONTROL ).SetRT( RSC_RESOURCE ) );
328 maILArrows.InsertFromHorizontalBitmap(
329 SVX_RES( BMP_FRMSEL_ARROWS ), 16, NULL, pColorAry1, pColorAry2, 3);
330 FreeResource();
331 DBG_ASSERT( maILArrows.GetImageSize().Height() == maILArrows.GetImageSize().Width(),
332 "svx::FrameSelectorImpl::InitArrowImageList - images are not squarish" );
333 mnArrowSize = maILArrows.GetImageSize().Height();
336 void FrameSelectorImpl::InitGlobalGeometry()
338 Size aCtrlSize( mrFrameSel.CalcOutputSize( mrFrameSel.GetSizePixel() ) );
339 /* nMinSize is the lower of width and height (control will always be squarish).
340 FRAMESEL_GEOM_OUTER is the minimal distance between inner control border
341 and any element. */
342 long nMinSize = std::min( aCtrlSize.Width(), aCtrlSize.Height() ) - 2 * FRAMESEL_GEOM_OUTER;
343 /* nFixedSize is the size all existing elements need in one direction:
344 the diag. arrow, space betw. arrow and frame border, outer frame border,
345 inner frame border, other outer frame border, space betw. frame border
346 and arrow, the other arrow. */
347 long nFixedSize = 2 * mnArrowSize + 2 * FRAMESEL_GEOM_INNER + 3 * FRAMESEL_GEOM_WIDTH;
348 /* nBetwBordersSize contains the size between an outer and inner frame border (made odd). */
349 long nBetwBordersSize = (((nMinSize - nFixedSize) / 2) - 1) | 1;
351 /* The final size of the usable area. */
352 mnCtrlSize = 2 * nBetwBordersSize + nFixedSize;
353 maVirDev.SetOutputSizePixel( Size( mnCtrlSize, mnCtrlSize ) );
355 /* Center the virtual device in the control. */
356 maVirDevPos = Point( (aCtrlSize.Width() - mnCtrlSize) / 2, (aCtrlSize.Height() - mnCtrlSize) / 2 );
359 void FrameSelectorImpl::InitBorderGeometry()
361 size_t nCol, nCols, nRow, nRows;
363 // Global border geometry values ------------------------------------------
365 /* mnLine* is the middle point inside a frame border (i.e. mnLine1 is mid X inside left border). */
366 mnLine1 = mnArrowSize + FRAMESEL_GEOM_INNER + FRAMESEL_GEOM_WIDTH / 2;
367 mnLine2 = mnCtrlSize / 2;
368 mnLine3 = 2 * mnLine2 - mnLine1;
370 // Frame helper array -----------------------------------------------------
372 maArray.Initialize( mbVer ? 2 : 1, mbHor ? 2 : 1 );
373 maArray.SetUseDiagDoubleClipping( true );
375 maArray.SetXOffset( mnLine1 );
376 maArray.SetAllColWidths( (mbVer ? mnLine2 : mnLine3) - mnLine1 );
378 maArray.SetYOffset( mnLine1 );
379 maArray.SetAllRowHeights( (mbHor ? mnLine2 : mnLine3) - mnLine1 );
381 // Focus polygons ---------------------------------------------------------
383 /* Width for focus rectangles from center of frame borders. */
384 mnFocusOffs = FRAMESEL_GEOM_WIDTH / 2 + 1;
386 maLeft.ClearFocusArea();
387 maVer.ClearFocusArea();
388 maRight.ClearFocusArea();
389 maTop.ClearFocusArea();
390 maHor.ClearFocusArea();
391 maBottom.ClearFocusArea();
393 maLeft.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine1 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
394 maVer.AddFocusPolygon( Rectangle( mnLine2 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine2 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
395 maRight.AddFocusPolygon( Rectangle( mnLine3 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
396 maTop.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine1 + mnFocusOffs ) );
397 maHor.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine2 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine2 + mnFocusOffs ) );
398 maBottom.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine3 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
400 for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
402 for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
404 Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
405 long nDiagFocusOffsX = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetHorDiagAngle( nCol, nRow ) );
406 long nDiagFocusOffsY = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetVerDiagAngle( nCol, nRow ) );
408 std::vector< Point > aFocusVec;
409 aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Top() + nDiagFocusOffsY ) );
410 aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Top() - mnFocusOffs ) );
411 aFocusVec.push_back( Point( aRect.Left() + nDiagFocusOffsX, aRect.Top() - mnFocusOffs ) );
412 aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Bottom() - nDiagFocusOffsY ) );
413 aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Bottom() + mnFocusOffs ) );
414 aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs ) );
415 maTLBR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );
417 aFocusVec.clear();
418 aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Top() + nDiagFocusOffsY ) );
419 aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Top() - mnFocusOffs ) );
420 aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Top() - mnFocusOffs ) );
421 aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Bottom() - nDiagFocusOffsY ) );
422 aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Bottom() + mnFocusOffs ) );
423 aFocusVec.push_back( Point( aRect.Left() + nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs ) );
424 maBLTR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) );
428 // Click areas ------------------------------------------------------------
430 for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt )
431 (*aIt)->ClearClickArea();
433 /* Additional space for click area: is added to the space available to draw
434 the frame borders. For instance left frame border:
435 - To left, top, and bottom always big additional space (outer area).
436 - To right: Dependent on existence of inner vertical frame border
437 (if enabled, use less space).
439 long nClO = FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_OUTER;
440 long nClI = (mbTLBR && mbBLTR) ? (FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_INNER) : nClO;
441 long nClH = mbHor ? nClI : nClO; // additional space dependent of horizontal inner border
442 long nClV = mbVer ? nClI : nClO; // additional space dependent of vertical inner border
444 maLeft.AddClickRect( Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine1 + nClV, mnLine3 + nClO ) );
445 maVer.AddClickRect( Rectangle( mnLine2 - nClI, mnLine1 - nClO, mnLine2 + nClI, mnLine3 + nClO ) );
446 maRight.AddClickRect( Rectangle( mnLine3 - nClV, mnLine1 - nClO, mnLine3 + nClO, mnLine3 + nClO ) );
447 maTop.AddClickRect( Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine3 + nClO, mnLine1 + nClH ) );
448 maHor.AddClickRect( Rectangle( mnLine1 - nClO, mnLine2 - nClI, mnLine3 + nClO, mnLine2 + nClI ) );
449 maBottom.AddClickRect( Rectangle( mnLine1 - nClO, mnLine3 - nClH, mnLine3 + nClO, mnLine3 + nClO ) );
451 /* Diagonal frame borders use the remaining space between outer and inner frame borders. */
452 if( mbTLBR || mbBLTR )
454 for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol )
456 for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow )
458 // the usable area between horizonal/vertical frame borders of current quadrant
459 Rectangle aRect( maArray.GetCellRect( nCol, nRow ) );
460 aRect.Left() += nClV + 1;
461 aRect.Right() -= nClV + 1;
462 aRect.Top() += nClH + 1;
463 aRect.Bottom() -= nClH + 1;
465 /* Both diagonal frame borders enabled. */
466 if( mbTLBR && mbBLTR )
468 // single areas
469 Point aMid( aRect.Center() );
470 maTLBR.AddClickRect( Rectangle( aRect.TopLeft(), aMid ) );
471 maTLBR.AddClickRect( Rectangle( aMid + Point( 1, 1 ), aRect.BottomRight() ) );
472 maBLTR.AddClickRect( Rectangle( aRect.Left(), aMid.Y() + 1, aMid.X(), aRect.Bottom() ) );
473 maBLTR.AddClickRect( Rectangle( aMid.X() + 1, aRect.Top(), aRect.Right(), aMid.Y() ) );
474 // centered rectangle for both frame borders
475 Rectangle aMidRect( aRect.TopLeft(), Size( aRect.GetWidth() / 3, aRect.GetHeight() / 3 ) );
476 aMidRect.Move( (aRect.GetWidth() - aMidRect.GetWidth()) / 2, (aRect.GetHeight() - aMidRect.GetHeight()) / 2 );
477 maTLBR.AddClickRect( aMidRect );
478 maBLTR.AddClickRect( aMidRect );
480 /* One of the diagonal frame borders enabled - use entire rectangle. */
481 else if( mbTLBR && !mbBLTR ) // top-left to bottom-right only
482 maTLBR.AddClickRect( aRect );
483 else if( !mbTLBR && mbBLTR ) // bottom-left to top-right only
484 maBLTR.AddClickRect( aRect );
490 void FrameSelectorImpl::InitVirtualDevice()
492 // initialize resources
493 InitColors();
494 InitArrowImageList();
496 sizeChanged();
499 void FrameSelectorImpl::sizeChanged()
501 // initialize geometry
502 InitGlobalGeometry();
503 InitBorderGeometry();
505 // correct background around the used area
506 mrFrameSel.SetBackground( Wallpaper( maBackCol ) );
507 DoInvalidate( true );
510 // frame border access --------------------------------------------------------
512 const FrameBorder& FrameSelectorImpl::GetBorder( FrameBorderType eBorder ) const
514 size_t nIndex = GetIndexFromFrameBorderType( eBorder );
515 if( nIndex < maAllBorders.size() )
516 return *maAllBorders[ nIndex ];
517 SAL_WARN( "svx.dialog", "svx::FrameSelectorImpl::GetBorder - unknown border type" );
518 return maTop;
521 FrameBorder& FrameSelectorImpl::GetBorderAccess( FrameBorderType eBorder )
523 return const_cast< FrameBorder& >( GetBorder( eBorder ) );
526 // drawing --------------------------------------------------------------------
528 void FrameSelectorImpl::DrawBackground()
530 // clear the area
531 maVirDev.SetLineColor();
532 maVirDev.SetFillColor( maBackCol );
533 maVirDev.DrawRect( Rectangle( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) );
535 // draw the inner gray (or whatever color) rectangle
536 maVirDev.SetLineColor();
537 maVirDev.SetFillColor( maMarkCol );
538 maVirDev.DrawRect( Rectangle(
539 mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) );
541 // draw the white space for enabled frame borders
542 PolyPolygon aPPoly;
543 for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
544 (*aIt)->MergeFocusToPolyPolygon( aPPoly );
545 aPPoly.Optimize( POLY_OPTIMIZE_CLOSE );
546 maVirDev.SetLineColor( maBackCol );
547 maVirDev.SetFillColor( maBackCol );
548 maVirDev.DrawPolyPolygon( aPPoly );
551 void FrameSelectorImpl::DrawArrows( const FrameBorder& rBorder )
553 DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::DrawArrows - access to disabled border" );
555 long nLinePos = 0;
556 switch( rBorder.GetType() )
558 case FRAMEBORDER_LEFT:
559 case FRAMEBORDER_TOP: nLinePos = mnLine1; break;
560 case FRAMEBORDER_VER:
561 case FRAMEBORDER_HOR: nLinePos = mnLine2; break;
562 case FRAMEBORDER_RIGHT:
563 case FRAMEBORDER_BOTTOM: nLinePos = mnLine3; break;
564 default: ; //prevent warning
566 nLinePos -= mnArrowSize / 2;
568 long nTLPos = 0;
569 long nBRPos = mnCtrlSize - mnArrowSize;
570 Point aPos1, aPos2;
571 sal_uInt16 nImgId1 = 0, nImgId2 = 0;
572 switch( rBorder.GetType() )
574 case FRAMEBORDER_LEFT:
575 case FRAMEBORDER_RIGHT:
576 case FRAMEBORDER_VER:
577 aPos1 = Point( nLinePos, nTLPos ); nImgId1 = 1;
578 aPos2 = Point( nLinePos, nBRPos ); nImgId2 = 2;
579 break;
581 case FRAMEBORDER_TOP:
582 case FRAMEBORDER_BOTTOM:
583 case FRAMEBORDER_HOR:
584 aPos1 = Point( nTLPos, nLinePos ); nImgId1 = 3;
585 aPos2 = Point( nBRPos, nLinePos ); nImgId2 = 4;
586 break;
588 case FRAMEBORDER_TLBR:
589 aPos1 = Point( nTLPos, nTLPos ); nImgId1 = 5;
590 aPos2 = Point( nBRPos, nBRPos ); nImgId2 = 6;
591 break;
592 case FRAMEBORDER_BLTR:
593 aPos1 = Point( nTLPos, nBRPos ); nImgId1 = 7;
594 aPos2 = Point( nBRPos, nTLPos ); nImgId2 = 8;
595 break;
596 default: ; //prevent warning
599 // Arrow or marker? Do not draw arrows into disabled control.
600 sal_uInt16 nSelectAdd = (mrFrameSel.IsEnabled() && rBorder.IsSelected()) ? 0 : 8;
601 maVirDev.DrawImage( aPos1, maILArrows.GetImage( nImgId1 + nSelectAdd ) );
602 maVirDev.DrawImage( aPos2, maILArrows.GetImage( nImgId2 + nSelectAdd ) );
605 void FrameSelectorImpl::DrawAllArrows()
607 for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
608 DrawArrows( **aIt );
611 Color FrameSelectorImpl::GetDrawLineColor( const Color& rColor ) const
613 Color aColor( mbHCMode ? maHCLineCol : rColor );
614 if( aColor == maBackCol )
615 aColor.Invert();
616 return aColor;
619 void FrameSelectorImpl::DrawAllFrameBorders()
621 // Translate core colors to current UI colors (regards current background and HC mode).
622 for( FrameBorderIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
624 Color aCoreColorPrim = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColorOut();
625 Color aCoreColorSecn = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColorIn();
626 (*aIt)->SetUIColorPrim( GetDrawLineColor( aCoreColorPrim ) );
627 (*aIt)->SetUIColorSecn( GetDrawLineColor( aCoreColorSecn ) );
630 // Copy all frame border styles to the helper array
631 maArray.SetColumnStyleLeft( 0, maLeft.GetUIStyle() );
632 if( mbVer ) maArray.SetColumnStyleLeft( 1, maVer.GetUIStyle() );
634 // Invert the style for the right line
635 const frame::Style rRightStyle = maRight.GetUIStyle( );
636 frame::Style rInvertedRight( rRightStyle.GetColorPrim(),
637 rRightStyle.GetColorSecn(), rRightStyle.GetColorGap(),
638 rRightStyle.UseGapColor(),
639 rRightStyle.Secn(), rRightStyle.Dist(), rRightStyle.Prim( ),
640 rRightStyle.Type( ) );
641 maArray.SetColumnStyleRight( mbVer ? 1 : 0, rInvertedRight );
643 maArray.SetRowStyleTop( 0, maTop.GetUIStyle() );
644 if( mbHor )
646 // Invert the style for the hor line to match the real borders
647 const frame::Style rHorStyle = maHor.GetUIStyle();
648 frame::Style rInvertedHor( rHorStyle.GetColorPrim(),
649 rHorStyle.GetColorSecn(), rHorStyle.GetColorGap(),
650 rHorStyle.UseGapColor(),
651 rHorStyle.Secn(), rHorStyle.Dist(), rHorStyle.Prim( ),
652 rHorStyle.Type() );
653 maArray.SetRowStyleTop( 1, rInvertedHor );
656 // Invert the style for the bottom line
657 const frame::Style rBottomStyle = maBottom.GetUIStyle( );
658 frame::Style rInvertedBottom( rBottomStyle.GetColorPrim(),
659 rBottomStyle.GetColorSecn(), rBottomStyle.GetColorGap(),
660 rBottomStyle.UseGapColor(),
661 rBottomStyle.Secn(), rBottomStyle.Dist(), rBottomStyle.Prim( ),
662 rBottomStyle.Type() );
663 maArray.SetRowStyleBottom( mbHor ? 1 : 0, rInvertedBottom );
665 for( size_t nCol = 0; nCol < maArray.GetColCount(); ++nCol )
666 for( size_t nRow = 0; nRow < maArray.GetRowCount(); ++nRow )
667 maArray.SetCellStyleDiag( nCol, nRow, maTLBR.GetUIStyle(), maBLTR.GetUIStyle() );
669 // Let the helper array draw itself
670 maArray.DrawArray( maVirDev );
673 void FrameSelectorImpl::DrawVirtualDevice()
675 DrawBackground();
676 DrawAllArrows();
677 DrawAllFrameBorders();
678 mbFullRepaint = false;
681 void FrameSelectorImpl::CopyVirDevToControl()
683 if( mbFullRepaint )
684 DrawVirtualDevice();
685 mrFrameSel.DrawBitmap( maVirDevPos, maVirDev.GetBitmap( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) );
688 void FrameSelectorImpl::DrawAllTrackingRects()
690 PolyPolygon aPPoly;
691 if( mrFrameSel.IsAnyBorderSelected() )
693 for( SelFrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt )
694 (*aIt)->MergeFocusToPolyPolygon( aPPoly );
695 aPPoly.Move( maVirDevPos.X(), maVirDevPos.Y() );
697 else
698 // no frame border selected -> draw tracking rectangle around entire control
699 aPPoly.Insert( Polygon( Rectangle( maVirDevPos, maVirDev.GetOutputSizePixel() ) ) );
701 aPPoly.Optimize( POLY_OPTIMIZE_CLOSE );
702 for( sal_uInt16 nIdx = 0, nCount = aPPoly.Count(); nIdx < nCount; ++nIdx )
703 mrFrameSel.InvertTracking( aPPoly.GetObject( nIdx ), SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
706 Point FrameSelectorImpl::GetDevPosFromMousePos( const Point& rMousePos ) const
708 return rMousePos - maVirDevPos;
711 void FrameSelectorImpl::DoInvalidate( bool bFullRepaint )
713 mbFullRepaint |= bFullRepaint;
714 mrFrameSel.Invalidate( INVALIDATE_NOERASE );
717 // frame border state and style -----------------------------------------------
719 void FrameSelectorImpl::SetBorderState( FrameBorder& rBorder, FrameBorderState eState )
721 DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderState - access to disabled border" );
722 if( eState == FRAMESTATE_SHOW )
723 SetBorderCoreStyle( rBorder, &maCurrStyle );
724 else
725 rBorder.SetState( eState );
726 DoInvalidate( true );
729 void FrameSelectorImpl::SetBorderCoreStyle( FrameBorder& rBorder, const SvxBorderLine* pStyle )
731 DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderCoreStyle - access to disabled border" );
732 rBorder.SetCoreStyle( pStyle );
733 DoInvalidate( true );
736 void FrameSelectorImpl::ToggleBorderState( FrameBorder& rBorder )
738 bool bDontCare = mrFrameSel.SupportsDontCareState();
739 switch( rBorder.GetState() )
741 // same order as tristate check box: visible -> don't care -> hidden
742 case FRAMESTATE_SHOW:
743 SetBorderState( rBorder, bDontCare ? FRAMESTATE_DONTCARE : FRAMESTATE_HIDE );
744 break;
745 case FRAMESTATE_HIDE:
746 SetBorderState( rBorder, FRAMESTATE_SHOW );
747 break;
748 case FRAMESTATE_DONTCARE:
749 SetBorderState( rBorder, FRAMESTATE_HIDE );
750 break;
754 // frame border selection -----------------------------------------------------
756 void FrameSelectorImpl::SelectBorder( FrameBorder& rBorder, bool bSelect )
758 DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SelectBorder - access to disabled border" );
759 rBorder.Select( bSelect );
760 DrawArrows( rBorder );
761 DoInvalidate( false );
764 void FrameSelectorImpl::SilentGrabFocus()
766 bool bOldAuto = mbAutoSelect;
767 mbAutoSelect = false;
768 mrFrameSel.GrabFocus();
769 mbAutoSelect = bOldAuto;
772 bool FrameSelectorImpl::SelectedBordersEqual() const
774 bool bEqual = true;
775 SelFrameBorderCIter aIt( maEnabBorders );
776 if( aIt.Is() )
778 const SvxBorderLine& rFirstStyle = (*aIt)->GetCoreStyle();
779 for( ++aIt; bEqual && aIt.Is(); ++aIt )
780 bEqual = ((*aIt)->GetCoreStyle() == rFirstStyle);
782 return bEqual;
785 // ============================================================================
786 // FrameSelector
787 // ============================================================================
789 FrameSelector::FrameSelector(Window* pParent)
790 : Control(pParent, WB_BORDER|WB_TABSTOP)
792 // not in c'tor init list (avoid warning about usage of *this)
793 mxImpl.reset( new FrameSelectorImpl( *this ) );
794 EnableRTL( false ); // #107808# don't mirror the mouse handling
797 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeSvxFrameSelector(Window *pParent, VclBuilder::stringmap &)
799 return new FrameSelector(pParent);
802 FrameSelector::~FrameSelector()
806 void FrameSelector::Initialize( FrameSelFlags nFlags )
808 mxImpl->Initialize( nFlags );
809 Show();
812 // enabled frame borders ------------------------------------------------------
814 bool FrameSelector::IsBorderEnabled( FrameBorderType eBorder ) const
816 return mxImpl->GetBorder( eBorder ).IsEnabled();
819 sal_Int32 FrameSelector::GetEnabledBorderCount() const
821 return static_cast< sal_Int32 >( mxImpl->maEnabBorders.size() );
824 FrameBorderType FrameSelector::GetEnabledBorderType( sal_Int32 nIndex ) const
826 FrameBorderType eBorder = FRAMEBORDER_NONE;
827 if( nIndex >= 0 )
829 size_t nVecIdx = static_cast< size_t >( nIndex );
830 if( nVecIdx < mxImpl->maEnabBorders.size() )
831 eBorder = mxImpl->maEnabBorders[ nVecIdx ]->GetType();
833 return eBorder;
836 sal_Int32 FrameSelector::GetEnabledBorderIndex( FrameBorderType eBorder ) const
838 sal_Int32 nIndex = 0;
839 for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt, ++nIndex )
840 if( (*aIt)->GetType() == eBorder )
841 return nIndex;
842 return -1;
845 // frame border state and style -----------------------------------------------
847 bool FrameSelector::SupportsDontCareState() const
849 return (mxImpl->mnFlags & FRAMESEL_DONTCARE) != 0;
852 FrameBorderState FrameSelector::GetFrameBorderState( FrameBorderType eBorder ) const
854 return mxImpl->GetBorder( eBorder ).GetState();
857 const SvxBorderLine* FrameSelector::GetFrameBorderStyle( FrameBorderType eBorder ) const
859 const SvxBorderLine& rStyle = mxImpl->GetBorder( eBorder ).GetCoreStyle();
860 // rest of the world uses null pointer for invisible frame border
861 return rStyle.GetOutWidth() ? &rStyle : 0;
864 void FrameSelector::ShowBorder( FrameBorderType eBorder, const SvxBorderLine* pStyle )
866 mxImpl->SetBorderCoreStyle( mxImpl->GetBorderAccess( eBorder ), pStyle );
869 void FrameSelector::SetBorderDontCare( FrameBorderType eBorder )
871 mxImpl->SetBorderState( mxImpl->GetBorderAccess( eBorder ), FRAMESTATE_DONTCARE );
874 bool FrameSelector::IsAnyBorderVisible() const
876 bool bIsSet = false;
877 for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bIsSet && aIt.Is(); ++aIt )
878 bIsSet = ((*aIt)->GetState() == FRAMESTATE_SHOW);
879 return bIsSet;
882 void FrameSelector::HideAllBorders()
884 for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
885 mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );
888 bool FrameSelector::GetVisibleWidth( long& rnWidth, SvxBorderStyle& rnStyle ) const
890 VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
891 if( !aIt.Is() )
892 return false;
894 const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
895 bool bFound = true;
896 for( ++aIt; bFound && aIt.Is(); ++aIt )
898 bFound =
899 (rStyle.GetWidth() == (*aIt)->GetCoreStyle().GetWidth()) &&
900 (rStyle.GetBorderLineStyle() ==
901 (*aIt)->GetCoreStyle().GetBorderLineStyle());
904 if( bFound )
906 rnWidth = rStyle.GetWidth();
907 rnStyle = rStyle.GetBorderLineStyle();
909 return bFound;
912 bool FrameSelector::GetVisibleColor( Color& rColor ) const
914 VisFrameBorderCIter aIt( mxImpl->maEnabBorders );
915 if( !aIt.Is() )
916 return false;
918 const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle();
919 bool bFound = true;
920 for( ++aIt; bFound && aIt.Is(); ++aIt )
921 bFound = (rStyle.GetColor() == (*aIt)->GetCoreStyle().GetColor());
923 if( bFound )
924 rColor = rStyle.GetColor();
925 return bFound;
928 // frame border selection -----------------------------------------------------
930 const Link& FrameSelector::GetSelectHdl() const
932 return mxImpl->maSelectHdl;
935 void FrameSelector::SetSelectHdl( const Link& rHdl )
937 mxImpl->maSelectHdl = rHdl;
940 bool FrameSelector::IsBorderSelected( FrameBorderType eBorder ) const
942 return mxImpl->GetBorder( eBorder ).IsSelected();
945 void FrameSelector::SelectBorder( FrameBorderType eBorder, bool bSelect )
947 mxImpl->SelectBorder( mxImpl->GetBorderAccess( eBorder ), bSelect );
950 bool FrameSelector::IsAnyBorderSelected() const
952 // Construct an iterator for selected borders. If it is valid, there is a selected border.
953 return SelFrameBorderCIter( mxImpl->maEnabBorders ).Is();
956 void FrameSelector::SelectAllBorders( bool bSelect )
958 for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
959 mxImpl->SelectBorder( **aIt, bSelect );
962 void FrameSelector::SelectAllVisibleBorders( bool bSelect )
964 for( VisFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
965 mxImpl->SelectBorder( **aIt, bSelect );
968 void FrameSelector::SetStyleToSelection( long nWidth, SvxBorderStyle nStyle )
970 mxImpl->maCurrStyle.SetBorderLineStyle( nStyle );
971 mxImpl->maCurrStyle.SetWidth( nWidth );
972 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
973 mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
976 void FrameSelector::SetColorToSelection( const Color& rColor )
978 mxImpl->maCurrStyle.SetColor( rColor );
979 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
980 mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
983 // accessibility --------------------------------------------------------------
985 Reference< XAccessible > FrameSelector::CreateAccessible()
987 if( !mxImpl->mxAccess.is() )
988 mxImpl->mxAccess = mxImpl->mpAccess =
989 new a11y::AccFrameSelector( *this, FRAMEBORDER_NONE );
990 return mxImpl->mxAccess;
993 Reference< XAccessible > FrameSelector::GetChildAccessible( FrameBorderType eBorder )
995 Reference< XAccessible > xRet;
996 size_t nVecIdx = static_cast< size_t >( eBorder );
997 if( IsBorderEnabled( eBorder ) && (1 <= nVecIdx) && (nVecIdx <= mxImpl->maChildVec.size()) )
999 --nVecIdx;
1000 if( !mxImpl->maChildVec[ nVecIdx ] )
1001 mxImpl->mxChildVec[ nVecIdx ] = mxImpl->maChildVec[ nVecIdx ] =
1002 new a11y::AccFrameSelector( *this, eBorder );
1003 xRet = mxImpl->mxChildVec[ nVecIdx ];
1005 return xRet;
1008 Reference< XAccessible > FrameSelector::GetChildAccessible( sal_Int32 nIndex )
1010 return GetChildAccessible( GetEnabledBorderType( nIndex ) );
1013 Reference< XAccessible > FrameSelector::GetChildAccessible( const Point& rPos )
1015 Reference< XAccessible > xRet;
1016 for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !xRet.is() && aIt.Is(); ++aIt )
1017 if( (*aIt)->ContainsClickPoint( rPos ) )
1018 xRet = GetChildAccessible( (*aIt)->GetType() );
1019 return xRet;
1022 bool FrameSelector::ContainsClickPoint( const Point& rPos ) const
1024 bool bContains = false;
1025 for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bContains && aIt.Is(); ++aIt )
1026 bContains = (*aIt)->ContainsClickPoint( rPos );
1027 return bContains;
1030 Rectangle FrameSelector::GetClickBoundRect( FrameBorderType eBorder ) const
1032 Rectangle aRect;
1033 const FrameBorder& rBorder = mxImpl->GetBorder( eBorder );
1034 if( rBorder.IsEnabled() )
1035 aRect = rBorder.GetClickBoundRect();
1036 return aRect;
1039 // virtual functions from base class ------------------------------------------
1041 void FrameSelector::Paint( const Rectangle& )
1043 mxImpl->CopyVirDevToControl();
1044 if( HasFocus() )
1045 mxImpl->DrawAllTrackingRects();
1048 void FrameSelector::MouseButtonDown( const MouseEvent& rMEvt )
1050 /* Mouse handling:
1051 * Click on an unselected frame border:
1052 Set current style/color, make frame border visible, deselect all
1053 other frame borders.
1054 * Click on a selected frame border:
1055 Toggle state of the frame border (visible -> don't care -> hidden),
1056 deselect all other frame borders.
1057 * SHIFT+Click or CTRL+Click on an unselected frame border:
1058 Extend selection, set current style/color to all selected frame
1059 borders independent of the state/style/color of the borders.
1060 * SHIFT+Click or CTRL+Click on a selected frame border:
1061 If all frame borders have same style/color, toggle state of all
1062 borders (see above), otherwise set current style/color to all
1063 borders.
1064 * Click on unused area: Do not modify selection and selected frame
1065 borders.
1068 // #107394# do not auto-select a frame border
1069 mxImpl->SilentGrabFocus();
1071 if( rMEvt.IsLeft() )
1073 Point aPos( mxImpl->GetDevPosFromMousePos( rMEvt.GetPosPixel() ) );
1074 FrameBorderPtrVec aDeselectBorders;
1076 bool bAnyClicked = false; // Any frame border clicked?
1077 bool bNewSelected = false; // Any unselected frame border selected?
1079 /* If frame borders are set to "don't care" and the control does not
1080 support this state, hide them on first mouse click.
1081 DR 2004-01-30: Why are the borders set to "don't care" then?!? */
1082 bool bHideDontCare = !mxImpl->mbClicked && !SupportsDontCareState();
1084 for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
1086 if( (*aIt)->ContainsClickPoint( aPos ) )
1088 // frame border is clicked
1089 bAnyClicked = true;
1090 if( !(*aIt)->IsSelected() )
1092 bNewSelected = true;
1093 mxImpl->SelectBorder( **aIt, true );
1096 else
1098 // hide a "don't care" frame border only if it is not clicked
1099 if( bHideDontCare && ((*aIt)->GetState() == FRAMESTATE_DONTCARE) )
1100 mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE );
1102 // deselect frame borders not clicked (if SHIFT or CTRL are not pressed)
1103 if( !rMEvt.IsShift() && !rMEvt.IsMod1() )
1104 aDeselectBorders.push_back( *aIt );
1108 if( bAnyClicked )
1110 // any valid frame border clicked? -> deselect other frame borders
1111 for( FrameBorderIter aIt( aDeselectBorders ); aIt.Is(); ++aIt )
1112 mxImpl->SelectBorder( **aIt, false );
1114 if( bNewSelected || !mxImpl->SelectedBordersEqual() )
1116 // new frame border selected, selection extended, or selected borders different? -> show
1117 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
1118 // SetBorderState() sets current style and color to the frame border
1119 mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW );
1121 else
1123 // all selected frame borders are equal -> toggle state
1124 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
1125 mxImpl->ToggleBorderState( **aIt );
1128 GetSelectHdl().Call( this );
1133 void FrameSelector::KeyInput( const KeyEvent& rKEvt )
1135 bool bHandled = false;
1136 KeyCode aKeyCode = rKEvt.GetKeyCode();
1137 if( !aKeyCode.GetModifier() )
1139 sal_uInt16 nCode = aKeyCode.GetCode();
1140 switch( nCode )
1142 case KEY_SPACE:
1144 for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt )
1145 mxImpl->ToggleBorderState( **aIt );
1146 bHandled = true;
1148 break;
1150 case KEY_UP:
1151 case KEY_DOWN:
1152 case KEY_LEFT:
1153 case KEY_RIGHT:
1155 if( !mxImpl->maEnabBorders.empty() )
1157 // start from first selected frame border
1158 SelFrameBorderCIter aIt( mxImpl->maEnabBorders );
1159 FrameBorderType eBorder = aIt.Is() ? (*aIt)->GetType() : mxImpl->maEnabBorders.front()->GetType();
1161 // search for next enabled frame border
1164 eBorder = mxImpl->GetBorder( eBorder ).GetKeyboardNeighbor( nCode );
1166 while( (eBorder != FRAMEBORDER_NONE) && !IsBorderEnabled( eBorder ) );
1168 // select the frame border
1169 if( eBorder != FRAMEBORDER_NONE )
1171 DeselectAllBorders();
1172 SelectBorder( eBorder );
1176 break;
1179 if( !bHandled )
1180 Window::KeyInput(rKEvt);
1183 void FrameSelector::GetFocus()
1185 // auto-selection of a frame border, if focus reaches control, and nothing is selected
1186 if( mxImpl->mbAutoSelect && !IsAnyBorderSelected() && !mxImpl->maEnabBorders.empty() )
1187 mxImpl->SelectBorder( *mxImpl->maEnabBorders.front(), true );
1189 mxImpl->DoInvalidate( false );
1190 if( mxImpl->mxAccess.is() )
1191 mxImpl->mpAccess->NotifyFocusListeners( sal_True );
1192 Control::GetFocus();
1195 void FrameSelector::LoseFocus()
1197 mxImpl->DoInvalidate( false );
1198 if( mxImpl->mxAccess.is() )
1199 mxImpl->mpAccess->NotifyFocusListeners( sal_False );
1200 Control::LoseFocus();
1203 void FrameSelector::DataChanged( const DataChangedEvent& rDCEvt )
1205 Control::DataChanged( rDCEvt );
1206 if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) )
1207 mxImpl->InitVirtualDevice();
1210 void FrameSelector::Resize()
1212 Control::Resize();
1213 mxImpl->sizeChanged();
1216 Size FrameSelector::GetOptimalSize() const
1218 return LogicToPixel(Size(61, 65), MAP_APPFONT);
1221 // ============================================================================
1223 template< typename Cont, typename Iter, typename Pred >
1224 FrameBorderIterBase< Cont, Iter, Pred >::FrameBorderIterBase( container_type& rCont ) :
1225 maIt( rCont.begin() ),
1226 maEnd( rCont.end() )
1228 while( Is() && !maPred( *maIt ) ) ++maIt;
1231 template< typename Cont, typename Iter, typename Pred >
1232 FrameBorderIterBase< Cont, Iter, Pred >& FrameBorderIterBase< Cont, Iter, Pred >::operator++()
1234 do { ++maIt; } while( Is() && !maPred( *maIt ) );
1235 return *this;
1238 // ============================================================================
1240 } // namespace svx
1242 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */