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