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