1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_wasm_strip.h>
22 #include <sal/config.h>
24 #include <o3tl/safeint.hxx>
25 #include <svx/frmsel.hxx>
26 #include <vcl/event.hxx>
27 #include <sal/log.hxx>
28 #include <tools/debug.hxx>
29 #include <svtools/colorcfg.hxx>
34 #include <frmselimpl.hxx>
35 #include <AccessibleFrameSelector.hxx>
36 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <vcl/settings.hxx>
39 #include <vcl/svapp.hxx>
40 #include <drawinglayer/processor2d/processor2dtools.hxx>
41 #include <drawinglayer/processor2d/baseprocessor2d.hxx>
43 #include <bitmaps.hlst>
45 using namespace ::com::sun::star
;
46 using namespace ::editeng
;
50 using ::com::sun::star::uno::Reference
;
51 using ::com::sun::star::uno::Any
;
52 using ::com::sun::star::accessibility::XAccessible
;
53 using namespace ::com::sun::star::accessibility
;
55 // global functions from framebordertype.hxx
57 FrameBorderType
GetFrameBorderTypeFromIndex( size_t nIndex
)
59 DBG_ASSERT( nIndex
< o3tl::make_unsigned(FRAMEBORDERTYPE_COUNT
),
60 "svx::GetFrameBorderTypeFromIndex - invalid index" );
61 return static_cast< FrameBorderType
>( nIndex
+ 1 );
64 size_t GetIndexFromFrameBorderType( FrameBorderType eBorder
)
66 DBG_ASSERT( eBorder
!= FrameBorderType::NONE
,
67 "svx::GetIndexFromFrameBorderType - invalid frame border type" );
68 return static_cast< size_t >( eBorder
) - 1;
74 /** Space between outer control border and any graphical element of the control. */
75 const tools::Long FRAMESEL_GEOM_OUTER
= 2;
77 /** Space between arrows and usable inner area. */
78 const tools::Long FRAMESEL_GEOM_INNER
= 3;
80 /** Maximum width to draw a frame border style. */
81 const tools::Long FRAMESEL_GEOM_WIDTH
= 9;
83 /** Additional margin for click area of outer lines. */
84 const tools::Long FRAMESEL_GEOM_ADD_CLICK_OUTER
= 5;
86 /** Additional margin for click area of inner lines. */
87 const tools::Long FRAMESEL_GEOM_ADD_CLICK_INNER
= 2;
90 /** Returns the corresponding flag for a frame border. */
91 FrameSelFlags
lclGetFlagFromType( FrameBorderType eBorder
)
95 case FrameBorderType::Left
: return FrameSelFlags::Left
;
96 case FrameBorderType::Right
: return FrameSelFlags::Right
;
97 case FrameBorderType::Top
: return FrameSelFlags::Top
;
98 case FrameBorderType::Bottom
: return FrameSelFlags::Bottom
;
99 case FrameBorderType::Horizontal
: return FrameSelFlags::InnerHorizontal
;
100 case FrameBorderType::Vertical
: return FrameSelFlags::InnerVertical
;
101 case FrameBorderType::TLBR
: return FrameSelFlags::DiagonalTLBR
;
102 case FrameBorderType::BLTR
: return FrameSelFlags::DiagonalBLTR
;
103 case FrameBorderType::NONE
: break;
105 return FrameSelFlags::NONE
;
108 /** Merges the rSource polypolygon into the rDest polypolygon. */
109 void lclPolyPolyUnion( tools::PolyPolygon
& rDest
, const tools::PolyPolygon
& rSource
)
111 const tools::PolyPolygon
aTmp( rDest
);
112 aTmp
.GetUnion( rSource
, rDest
);
117 FrameBorder::FrameBorder( FrameBorderType eType
) :
119 meState( FrameBorderState::Hide
),
120 meKeyLeft( FrameBorderType::NONE
),
121 meKeyRight( FrameBorderType::NONE
),
122 meKeyTop( FrameBorderType::NONE
),
123 meKeyBottom( FrameBorderType::NONE
),
129 void FrameBorder::Enable( FrameSelFlags nFlags
)
131 mbEnabled
= bool(nFlags
& lclGetFlagFromType( meType
));
133 SetState( FrameBorderState::Hide
);
136 void FrameBorder::SetCoreStyle( const SvxBorderLine
* pStyle
)
139 maCoreStyle
= *pStyle
;
141 maCoreStyle
= SvxBorderLine();
143 // from twips to points
144 maUIStyle
.Set( &maCoreStyle
, FrameBorder::GetDefaultPatternScale(), FRAMESEL_GEOM_WIDTH
);
145 meState
= maUIStyle
.IsUsed() ? FrameBorderState::Show
: FrameBorderState::Hide
;
148 void FrameBorder::SetState( FrameBorderState eState
)
153 case FrameBorderState::Show
:
154 SAL_WARN( "svx.dialog", "svx::FrameBorder::SetState - use SetCoreStyle to make border visible" );
156 case FrameBorderState::Hide
:
157 maCoreStyle
= SvxBorderLine();
160 case FrameBorderState::DontCare
:
161 maCoreStyle
= SvxBorderLine();
162 maUIStyle
= frame::Style(3, 0, 0, SvxBorderLineStyle::SOLID
, FrameBorder::GetDefaultPatternScale()); //OBJ_FRAMESTYLE_DONTCARE
167 void FrameBorder::AddFocusPolygon( const tools::Polygon
& rFocus
)
169 lclPolyPolyUnion( maFocusArea
, rFocus
);
172 void FrameBorder::MergeFocusToPolyPolygon( tools::PolyPolygon
& rPPoly
) const
174 lclPolyPolyUnion( rPPoly
, maFocusArea
);
177 void FrameBorder::AddClickRect( const tools::Rectangle
& rRect
)
179 lclPolyPolyUnion( maClickArea
, tools::Polygon( rRect
) );
182 bool FrameBorder::ContainsClickPoint( const Point
& rPos
) const
184 return vcl::Region( maClickArea
).Contains( rPos
);
187 tools::Rectangle
FrameBorder::GetClickBoundRect() const
189 return maClickArea
.GetBoundRect();
192 void FrameBorder::SetKeyboardNeighbors(
193 FrameBorderType eLeft
, FrameBorderType eRight
, FrameBorderType eTop
, FrameBorderType eBottom
)
198 meKeyBottom
= eBottom
;
201 FrameBorderType
FrameBorder::GetKeyboardNeighbor( sal_uInt16 nKeyCode
) const
203 FrameBorderType eBorder
= FrameBorderType::NONE
;
206 case KEY_LEFT
: eBorder
= meKeyLeft
; break;
207 case KEY_RIGHT
: eBorder
= meKeyRight
; break;
208 case KEY_UP
: eBorder
= meKeyTop
; break;
209 case KEY_DOWN
: eBorder
= meKeyBottom
; break;
210 default: SAL_WARN( "svx.dialog", "svx::FrameBorder::GetKeyboardNeighbor - unknown key code" );
215 FrameSelectorImpl::FrameSelectorImpl( FrameSelector
& rFrameSel
) :
216 mrFrameSel( rFrameSel
),
217 mpVirDev( VclPtr
<VirtualDevice
>::Create() ),
218 maLeft( FrameBorderType::Left
),
219 maRight( FrameBorderType::Right
),
220 maTop( FrameBorderType::Top
),
221 maBottom( FrameBorderType::Bottom
),
222 maHor( FrameBorderType::Horizontal
),
223 maVer( FrameBorderType::Vertical
),
224 maTLBR( FrameBorderType::TLBR
),
225 maBLTR( FrameBorderType::BLTR
),
226 mnFlags( FrameSelFlags::Outer
),
237 mbFullRepaint( true ),
238 mbAutoSelect( true ),
240 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
244 maAllBorders
.resize( FRAMEBORDERTYPE_COUNT
, nullptr );
245 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Left
) ] = &maLeft
;
246 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Right
) ] = &maRight
;
247 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Top
) ] = &maTop
;
248 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Bottom
) ] = &maBottom
;
249 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Horizontal
) ] = &maHor
;
250 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::Vertical
) ] = &maVer
;
251 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::TLBR
) ] = &maTLBR
;
252 maAllBorders
[ GetIndexFromFrameBorderType( FrameBorderType::BLTR
) ] = &maBLTR
;
253 #if OSL_DEBUG_LEVEL >= 2
256 for( FrameBorderCIter
aIt( maAllBorders
); bOk
&& aIt
.Is(); bOk
= (*aIt
!= 0), ++aIt
);
257 DBG_ASSERT( bOk
, "svx::FrameSelectorImpl::FrameSelectorImpl - missing entry in maAllBorders" );
260 // left neighbor right neighbor upper neighbor lower neighbor
261 maLeft
.SetKeyboardNeighbors( FrameBorderType::NONE
, FrameBorderType::TLBR
, FrameBorderType::Top
, FrameBorderType::Bottom
);
262 maRight
.SetKeyboardNeighbors( FrameBorderType::BLTR
, FrameBorderType::NONE
, FrameBorderType::Top
, FrameBorderType::Bottom
);
263 maTop
.SetKeyboardNeighbors( FrameBorderType::Left
, FrameBorderType::Right
, FrameBorderType::NONE
, FrameBorderType::TLBR
);
264 maBottom
.SetKeyboardNeighbors( FrameBorderType::Left
, FrameBorderType::Right
, FrameBorderType::BLTR
, FrameBorderType::NONE
);
265 maHor
.SetKeyboardNeighbors( FrameBorderType::Left
, FrameBorderType::Right
, FrameBorderType::TLBR
, FrameBorderType::BLTR
);
266 maVer
.SetKeyboardNeighbors( FrameBorderType::TLBR
, FrameBorderType::BLTR
, FrameBorderType::Top
, FrameBorderType::Bottom
);
267 maTLBR
.SetKeyboardNeighbors( FrameBorderType::Left
, FrameBorderType::Vertical
, FrameBorderType::Top
, FrameBorderType::Horizontal
);
268 maBLTR
.SetKeyboardNeighbors( FrameBorderType::Vertical
, FrameBorderType::Right
, FrameBorderType::Horizontal
, FrameBorderType::Bottom
);
273 FrameSelectorImpl::~FrameSelectorImpl()
275 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
276 for( auto& rpChild
: maChildVec
)
279 rpChild
->Invalidate();
286 void FrameSelectorImpl::Initialize( FrameSelFlags nFlags
)
290 maEnabBorders
.clear();
291 for( FrameBorderIter
aIt( maAllBorders
); aIt
.Is(); ++aIt
)
293 (*aIt
)->Enable( mnFlags
);
294 if( (*aIt
)->IsEnabled() )
295 maEnabBorders
.push_back( *aIt
);
297 mbHor
= maHor
.IsEnabled();
298 mbVer
= maVer
.IsEnabled();
299 mbTLBR
= maTLBR
.IsEnabled();
300 mbBLTR
= maBLTR
.IsEnabled();
305 void FrameSelectorImpl::InitColors()
307 const StyleSettings
& rSettings
= Application::GetSettings().GetStyleSettings();
308 svtools::ColorConfig aColorConfig
;
309 maBackCol
= aColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
;
310 mbHCMode
= rSettings
.GetHighContrastMode();
311 maArrowCol
= aColorConfig
.GetColorValue(svtools::DOCBOUNDARIES
).nColor
;
312 maMarkCol
= aColorConfig
.GetColorValue(svtools::TABLEBOUNDARIES
).nColor
;
313 maHCLineCol
= COL_BLACK
;
316 constexpr rtl::OUStringConstExpr aImageIds
[] =
318 RID_SVXBMP_FRMSEL_ARROW1
,
319 RID_SVXBMP_FRMSEL_ARROW2
,
320 RID_SVXBMP_FRMSEL_ARROW3
,
321 RID_SVXBMP_FRMSEL_ARROW4
,
322 RID_SVXBMP_FRMSEL_ARROW5
,
323 RID_SVXBMP_FRMSEL_ARROW6
,
324 RID_SVXBMP_FRMSEL_ARROW7
,
325 RID_SVXBMP_FRMSEL_ARROW8
,
326 RID_SVXBMP_FRMSEL_ARROW9
,
327 RID_SVXBMP_FRMSEL_ARROW10
,
328 RID_SVXBMP_FRMSEL_ARROW11
,
329 RID_SVXBMP_FRMSEL_ARROW12
,
330 RID_SVXBMP_FRMSEL_ARROW13
,
331 RID_SVXBMP_FRMSEL_ARROW14
,
332 RID_SVXBMP_FRMSEL_ARROW15
,
333 RID_SVXBMP_FRMSEL_ARROW16
336 void FrameSelectorImpl::InitArrowImageList()
340 /* Build the arrow images bitmap with current colors. */
343 pColorAry1
[0] = Color( 0, 0, 0 );
344 pColorAry2
[0] = maArrowCol
; // black -> arrow color
345 pColorAry1
[1] = Color( 0, 255, 0 );
346 pColorAry2
[1] = maMarkCol
; // green -> marker color
347 pColorAry1
[2] = Color( 255, 0, 255 );
348 pColorAry2
[2] = maBackCol
; // magenta -> background
350 assert(SAL_N_ELEMENTS(aImageIds
) == 16);
351 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aImageIds
); ++i
)
353 BitmapEx aBmpEx
{ OUString(aImageIds
[i
]) };
354 aBmpEx
.Replace(pColorAry1
, pColorAry2
, 3);
355 maArrows
.emplace_back(aBmpEx
);
357 assert(maArrows
.size() == 16);
359 mnArrowSize
= maArrows
[0].GetSizePixel().Height();
362 void FrameSelectorImpl::InitGlobalGeometry()
364 Size
aCtrlSize(mrFrameSel
.GetOutputSizePixel());
365 /* nMinSize is the lower of width and height (control will always be squarish).
366 FRAMESEL_GEOM_OUTER is the minimal distance between inner control border
368 tools::Long nMinSize
= std::min( aCtrlSize
.Width(), aCtrlSize
.Height() ) - 2 * FRAMESEL_GEOM_OUTER
;
369 /* nFixedSize is the size all existing elements need in one direction:
370 the diag. arrow, space betw. arrow and frame border, outer frame border,
371 inner frame border, other outer frame border, space betw. frame border
372 and arrow, the other arrow. */
373 tools::Long nFixedSize
= 2 * mnArrowSize
+ 2 * FRAMESEL_GEOM_INNER
+ 3 * FRAMESEL_GEOM_WIDTH
;
374 /* nBetwBordersSize contains the size between an outer and inner frame border (made odd). */
375 tools::Long nBetwBordersSize
= (((nMinSize
- nFixedSize
) / 2) - 1) | 1;
377 /* The final size of the usable area. At least do not get negative */
378 mnCtrlSize
= 2 * nBetwBordersSize
+ nFixedSize
;
379 mnCtrlSize
= std::max(mnCtrlSize
, static_cast<tools::Long
>(0));
380 mpVirDev
->SetOutputSizePixel( Size( mnCtrlSize
, mnCtrlSize
) );
382 /* Center the virtual device in the control. */
383 maVirDevPos
= Point( (aCtrlSize
.Width() - mnCtrlSize
) / 2, (aCtrlSize
.Height() - mnCtrlSize
) / 2 );
386 void FrameSelectorImpl::InitBorderGeometry()
388 size_t nCol
, nCols
, nRow
, nRows
;
390 // Global border geometry values
391 /* mnLine* is the middle point inside a frame border (i.e. mnLine1 is mid X inside left border). */
392 mnLine1
= mnArrowSize
+ FRAMESEL_GEOM_INNER
+ FRAMESEL_GEOM_WIDTH
/ 2;
393 mnLine2
= mnCtrlSize
/ 2;
394 mnLine3
= 2 * mnLine2
- mnLine1
;
396 // Frame helper array
397 maArray
.Initialize( mbVer
? 2 : 1, mbHor
? 2 : 1 );
399 maArray
.SetXOffset( mnLine1
);
400 maArray
.SetAllColWidths( (mbVer
? mnLine2
: mnLine3
) - mnLine1
);
402 maArray
.SetYOffset( mnLine1
);
403 maArray
.SetAllRowHeights( (mbHor
? mnLine2
: mnLine3
) - mnLine1
);
406 /* Width for focus rectangles from center of frame borders. */
407 mnFocusOffs
= FRAMESEL_GEOM_WIDTH
/ 2 + 1;
409 maLeft
.ClearFocusArea();
410 maVer
.ClearFocusArea();
411 maRight
.ClearFocusArea();
412 maTop
.ClearFocusArea();
413 maHor
.ClearFocusArea();
414 maBottom
.ClearFocusArea();
416 maLeft
.AddFocusPolygon( tools::Rectangle( mnLine1
- mnFocusOffs
, mnLine1
- mnFocusOffs
, mnLine1
+ mnFocusOffs
, mnLine3
+ mnFocusOffs
) );
417 maVer
.AddFocusPolygon( tools::Rectangle( mnLine2
- mnFocusOffs
, mnLine1
- mnFocusOffs
, mnLine2
+ mnFocusOffs
, mnLine3
+ mnFocusOffs
) );
418 maRight
.AddFocusPolygon( tools::Rectangle( mnLine3
- mnFocusOffs
, mnLine1
- mnFocusOffs
, mnLine3
+ mnFocusOffs
, mnLine3
+ mnFocusOffs
) );
419 maTop
.AddFocusPolygon( tools::Rectangle( mnLine1
- mnFocusOffs
, mnLine1
- mnFocusOffs
, mnLine3
+ mnFocusOffs
, mnLine1
+ mnFocusOffs
) );
420 maHor
.AddFocusPolygon( tools::Rectangle( mnLine1
- mnFocusOffs
, mnLine2
- mnFocusOffs
, mnLine3
+ mnFocusOffs
, mnLine2
+ mnFocusOffs
) );
421 maBottom
.AddFocusPolygon( tools::Rectangle( mnLine1
- mnFocusOffs
, mnLine3
- mnFocusOffs
, mnLine3
+ mnFocusOffs
, mnLine3
+ mnFocusOffs
) );
423 maTLBR
.ClearFocusArea();
424 maBLTR
.ClearFocusArea();
426 for( nCol
= 0, nCols
= maArray
.GetColCount(); nCol
< nCols
; ++nCol
)
428 for( nRow
= 0, nRows
= maArray
.GetRowCount(); nRow
< nRows
; ++nRow
)
430 const basegfx::B2DRange
aCellRange(maArray
.GetCellRange( nCol
, nRow
));
431 const tools::Rectangle
aRect(
432 basegfx::fround(aCellRange
.getMinX()), basegfx::fround(aCellRange
.getMinY()),
433 basegfx::fround(aCellRange
.getMaxX()), basegfx::fround(aCellRange
.getMaxY()));
434 const double fHorDiagAngle(atan2(fabs(aCellRange
.getHeight()), fabs(aCellRange
.getWidth())));
435 const double fVerDiagAngle(fHorDiagAngle
> 0.0 ? M_PI_2
- fHorDiagAngle
: 0.0);
436 const tools::Long
nDiagFocusOffsX(basegfx::fround(-mnFocusOffs
/ tan(fHorDiagAngle
) + mnFocusOffs
/ sin(fHorDiagAngle
)));
437 const tools::Long
nDiagFocusOffsY(basegfx::fround(-mnFocusOffs
/ tan(fVerDiagAngle
) + mnFocusOffs
/ sin(fVerDiagAngle
)));
439 std::vector
< Point
> aFocusVec
;
440 aFocusVec
.emplace_back( aRect
.Left() - mnFocusOffs
, aRect
.Top() + nDiagFocusOffsY
);
441 aFocusVec
.emplace_back( aRect
.Left() - mnFocusOffs
, aRect
.Top() - mnFocusOffs
);
442 aFocusVec
.emplace_back( aRect
.Left() + nDiagFocusOffsX
, aRect
.Top() - mnFocusOffs
);
443 aFocusVec
.emplace_back( aRect
.Right() + mnFocusOffs
, aRect
.Bottom() - nDiagFocusOffsY
);
444 aFocusVec
.emplace_back( aRect
.Right() + mnFocusOffs
, aRect
.Bottom() + mnFocusOffs
);
445 aFocusVec
.emplace_back( aRect
.Right() - nDiagFocusOffsX
, aRect
.Bottom() + mnFocusOffs
);
446 maTLBR
.AddFocusPolygon( tools::Polygon( static_cast< sal_uInt16
>( aFocusVec
.size() ), aFocusVec
.data() ) );
449 aFocusVec
.emplace_back( aRect
.Right() + mnFocusOffs
, aRect
.Top() + nDiagFocusOffsY
);
450 aFocusVec
.emplace_back( aRect
.Right() + mnFocusOffs
, aRect
.Top() - mnFocusOffs
);
451 aFocusVec
.emplace_back( aRect
.Right() - nDiagFocusOffsX
, aRect
.Top() - mnFocusOffs
);
452 aFocusVec
.emplace_back( aRect
.Left() - mnFocusOffs
, aRect
.Bottom() - nDiagFocusOffsY
);
453 aFocusVec
.emplace_back( aRect
.Left() - mnFocusOffs
, aRect
.Bottom() + mnFocusOffs
);
454 aFocusVec
.emplace_back( aRect
.Left() + nDiagFocusOffsX
, aRect
.Bottom() + mnFocusOffs
);
455 maBLTR
.AddFocusPolygon( tools::Polygon( static_cast< sal_uInt16
>( aFocusVec
.size() ), aFocusVec
.data() ) );
460 for( FrameBorderIter
aIt( maAllBorders
); aIt
.Is(); ++aIt
)
461 (*aIt
)->ClearClickArea();
463 /* Additional space for click area: is added to the space available to draw
464 the frame borders. For instance left frame border:
465 - To left, top, and bottom always big additional space (outer area).
466 - To right: Dependent on existence of inner vertical frame border
467 (if enabled, use less space).
469 tools::Long nClO
= FRAMESEL_GEOM_WIDTH
/ 2 + FRAMESEL_GEOM_ADD_CLICK_OUTER
;
470 tools::Long nClI
= (mbTLBR
&& mbBLTR
) ? (FRAMESEL_GEOM_WIDTH
/ 2 + FRAMESEL_GEOM_ADD_CLICK_INNER
) : nClO
;
471 tools::Long nClH
= mbHor
? nClI
: nClO
; // additional space dependent of horizontal inner border
472 tools::Long nClV
= mbVer
? nClI
: nClO
; // additional space dependent of vertical inner border
474 maLeft
.AddClickRect( tools::Rectangle( mnLine1
- nClO
, mnLine1
- nClO
, mnLine1
+ nClV
, mnLine3
+ nClO
) );
475 maVer
.AddClickRect( tools::Rectangle( mnLine2
- nClI
, mnLine1
- nClO
, mnLine2
+ nClI
, mnLine3
+ nClO
) );
476 maRight
.AddClickRect( tools::Rectangle( mnLine3
- nClV
, mnLine1
- nClO
, mnLine3
+ nClO
, mnLine3
+ nClO
) );
477 maTop
.AddClickRect( tools::Rectangle( mnLine1
- nClO
, mnLine1
- nClO
, mnLine3
+ nClO
, mnLine1
+ nClH
) );
478 maHor
.AddClickRect( tools::Rectangle( mnLine1
- nClO
, mnLine2
- nClI
, mnLine3
+ nClO
, mnLine2
+ nClI
) );
479 maBottom
.AddClickRect( tools::Rectangle( mnLine1
- nClO
, mnLine3
- nClH
, mnLine3
+ nClO
, mnLine3
+ nClO
) );
481 /* Diagonal frame borders use the remaining space between outer and inner frame borders. */
482 if( !(mbTLBR
|| mbBLTR
) )
485 for( nCol
= 0, nCols
= maArray
.GetColCount(); nCol
< nCols
; ++nCol
)
487 for( nRow
= 0, nRows
= maArray
.GetRowCount(); nRow
< nRows
; ++nRow
)
489 // the usable area between horizontal/vertical frame borders of current quadrant
490 const basegfx::B2DRange
aCellRange(maArray
.GetCellRange( nCol
, nRow
));
491 const tools::Rectangle
aRect(
492 basegfx::fround(aCellRange
.getMinX()) + nClV
+ 1, basegfx::fround(aCellRange
.getMinY()) + nClH
+ 1,
493 basegfx::fround(aCellRange
.getMaxX()) - nClV
+ 1, basegfx::fround(aCellRange
.getMaxY()) - nClH
+ 1);
495 /* Both diagonal frame borders enabled. */
496 if( mbTLBR
&& mbBLTR
)
499 Point
aMid( aRect
.Center() );
500 maTLBR
.AddClickRect( tools::Rectangle( aRect
.TopLeft(), aMid
) );
501 maTLBR
.AddClickRect( tools::Rectangle( aMid
+ Point( 1, 1 ), aRect
.BottomRight() ) );
502 maBLTR
.AddClickRect( tools::Rectangle( aRect
.Left(), aMid
.Y() + 1, aMid
.X(), aRect
.Bottom() ) );
503 maBLTR
.AddClickRect( tools::Rectangle( aMid
.X() + 1, aRect
.Top(), aRect
.Right(), aMid
.Y() ) );
504 // centered rectangle for both frame borders
505 tools::Rectangle
aMidRect( aRect
.TopLeft(), Size( aRect
.GetWidth() / 3, aRect
.GetHeight() / 3 ) );
506 aMidRect
.Move( (aRect
.GetWidth() - aMidRect
.GetWidth()) / 2, (aRect
.GetHeight() - aMidRect
.GetHeight()) / 2 );
507 maTLBR
.AddClickRect( aMidRect
);
508 maBLTR
.AddClickRect( aMidRect
);
510 /* One of the diagonal frame borders enabled - use entire rectangle. */
511 else if( mbTLBR
&& !mbBLTR
) // top-left to bottom-right only
512 maTLBR
.AddClickRect( aRect
);
513 else if( !mbTLBR
&& mbBLTR
) // bottom-left to top-right only
514 maBLTR
.AddClickRect( aRect
);
519 void FrameSelectorImpl::InitVirtualDevice()
521 // initialize resources
523 InitArrowImageList();
528 void FrameSelectorImpl::sizeChanged()
530 // initialize geometry
531 InitGlobalGeometry();
532 InitBorderGeometry();
534 DoInvalidate( true );
537 // frame border access
538 const FrameBorder
& FrameSelectorImpl::GetBorder( FrameBorderType eBorder
) const
540 size_t nIndex
= GetIndexFromFrameBorderType( eBorder
);
541 if( nIndex
< maAllBorders
.size() )
542 return *maAllBorders
[ nIndex
];
543 SAL_WARN( "svx.dialog", "svx::FrameSelectorImpl::GetBorder - unknown border type" );
547 FrameBorder
& FrameSelectorImpl::GetBorderAccess( FrameBorderType eBorder
)
549 return const_cast< FrameBorder
& >( GetBorder( eBorder
) );
553 void FrameSelectorImpl::DrawBackground()
556 mpVirDev
->SetLineColor();
557 mpVirDev
->SetFillColor( maBackCol
);
558 mpVirDev
->DrawRect( tools::Rectangle( Point( 0, 0 ), mpVirDev
->GetOutputSizePixel() ) );
560 // draw the inner gray (or whatever color) rectangle
561 mpVirDev
->SetLineColor();
562 mpVirDev
->SetFillColor( maMarkCol
);
563 mpVirDev
->DrawRect( tools::Rectangle(
564 mnLine1
- mnFocusOffs
, mnLine1
- mnFocusOffs
, mnLine3
+ mnFocusOffs
, mnLine3
+ mnFocusOffs
) );
566 // draw the white space for enabled frame borders
567 tools::PolyPolygon aPPoly
;
568 for( FrameBorderCIter
aIt( maEnabBorders
); aIt
.Is(); ++aIt
)
569 (*aIt
)->MergeFocusToPolyPolygon( aPPoly
);
570 aPPoly
.Optimize( PolyOptimizeFlags::CLOSE
);
571 mpVirDev
->SetLineColor( maBackCol
);
572 mpVirDev
->SetFillColor( maBackCol
);
573 mpVirDev
->DrawPolyPolygon( aPPoly
);
576 void FrameSelectorImpl::DrawArrows( const FrameBorder
& rBorder
)
578 DBG_ASSERT( rBorder
.IsEnabled(), "svx::FrameSelectorImpl::DrawArrows - access to disabled border" );
580 tools::Long nLinePos
= 0;
581 switch( rBorder
.GetType() )
583 case FrameBorderType::Left
:
584 case FrameBorderType::Top
: nLinePos
= mnLine1
; break;
585 case FrameBorderType::Vertical
:
586 case FrameBorderType::Horizontal
: nLinePos
= mnLine2
; break;
587 case FrameBorderType::Right
:
588 case FrameBorderType::Bottom
: nLinePos
= mnLine3
; break;
589 default: ; //prevent warning
591 nLinePos
-= mnArrowSize
/ 2;
593 tools::Long nTLPos
= 0;
594 tools::Long nBRPos
= mnCtrlSize
- mnArrowSize
;
596 int nImgIndex1
= -1, nImgIndex2
= -1;
597 switch( rBorder
.GetType() )
599 case FrameBorderType::Left
:
600 case FrameBorderType::Right
:
601 case FrameBorderType::Vertical
:
602 aPos1
= Point( nLinePos
, nTLPos
); nImgIndex1
= 0;
603 aPos2
= Point( nLinePos
, nBRPos
); nImgIndex2
= 1;
606 case FrameBorderType::Top
:
607 case FrameBorderType::Bottom
:
608 case FrameBorderType::Horizontal
:
609 aPos1
= Point( nTLPos
, nLinePos
); nImgIndex1
= 2;
610 aPos2
= Point( nBRPos
, nLinePos
); nImgIndex2
= 3;
613 case FrameBorderType::TLBR
:
614 aPos1
= Point( nTLPos
, nTLPos
); nImgIndex1
= 4;
615 aPos2
= Point( nBRPos
, nBRPos
); nImgIndex2
= 5;
617 case FrameBorderType::BLTR
:
618 aPos1
= Point( nTLPos
, nBRPos
); nImgIndex1
= 6;
619 aPos2
= Point( nBRPos
, nTLPos
); nImgIndex2
= 7;
621 default: ; //prevent warning
624 // Arrow or marker? Do not draw arrows into disabled control.
625 sal_uInt16 nSelectAdd
= (mrFrameSel
.IsEnabled() && rBorder
.IsSelected()) ? 0 : 8;
627 mpVirDev
->DrawImage(aPos1
, maArrows
[nImgIndex1
+ nSelectAdd
]);
629 mpVirDev
->DrawImage(aPos2
, maArrows
[nImgIndex2
+ nSelectAdd
]);
632 Color
FrameSelectorImpl::GetDrawLineColor( const Color
& rColor
) const
634 Color
aColor( mbHCMode
? maHCLineCol
: rColor
);
635 if( aColor
== maBackCol
)
640 void FrameSelectorImpl::DrawAllFrameBorders()
642 // Translate core colors to current UI colors (regards current background and HC mode).
643 for( FrameBorderIter
aIt( maEnabBorders
); aIt
.Is(); ++aIt
)
645 Color aCoreColorPrim
= ((*aIt
)->GetState() == FrameBorderState::DontCare
) ? maMarkCol
: (*aIt
)->GetCoreStyle().GetColorOut();
646 Color aCoreColorSecn
= ((*aIt
)->GetState() == FrameBorderState::DontCare
) ? maMarkCol
: (*aIt
)->GetCoreStyle().GetColorIn();
647 (*aIt
)->SetUIColorPrim( GetDrawLineColor( aCoreColorPrim
) );
648 (*aIt
)->SetUIColorSecn( GetDrawLineColor( aCoreColorSecn
) );
651 // Copy all frame border styles to the helper array
652 maArray
.SetColumnStyleLeft( 0, maLeft
.GetUIStyle() );
653 if( mbVer
) maArray
.SetColumnStyleLeft( 1, maVer
.GetUIStyle() );
655 // Invert the style for the right line
656 const frame::Style rRightStyle
= maRight
.GetUIStyle( );
657 frame::Style
rInvertedRight( rRightStyle
.GetColorPrim(),
658 rRightStyle
.GetColorSecn(), rRightStyle
.GetColorGap(),
659 rRightStyle
.UseGapColor(),
660 rRightStyle
.Secn(), rRightStyle
.Dist(), rRightStyle
.Prim( ),
661 rRightStyle
.Type( ), rRightStyle
.PatternScale() );
662 maArray
.SetColumnStyleRight( mbVer
? 1 : 0, rInvertedRight
);
664 maArray
.SetRowStyleTop( 0, maTop
.GetUIStyle() );
667 // Invert the style for the hor line to match the real borders
668 const frame::Style rHorStyle
= maHor
.GetUIStyle();
669 frame::Style
rInvertedHor( rHorStyle
.GetColorPrim(),
670 rHorStyle
.GetColorSecn(), rHorStyle
.GetColorGap(),
671 rHorStyle
.UseGapColor(),
672 rHorStyle
.Secn(), rHorStyle
.Dist(), rHorStyle
.Prim( ),
673 rHorStyle
.Type(), rHorStyle
.PatternScale() );
674 maArray
.SetRowStyleTop( 1, rInvertedHor
);
677 // Invert the style for the bottom line
678 const frame::Style rBottomStyle
= maBottom
.GetUIStyle( );
679 frame::Style
rInvertedBottom( rBottomStyle
.GetColorPrim(),
680 rBottomStyle
.GetColorSecn(), rBottomStyle
.GetColorGap(),
681 rBottomStyle
.UseGapColor(),
682 rBottomStyle
.Secn(), rBottomStyle
.Dist(), rBottomStyle
.Prim( ),
683 rBottomStyle
.Type(), rBottomStyle
.PatternScale() );
684 maArray
.SetRowStyleBottom( mbHor
? 1 : 0, rInvertedBottom
);
686 for( sal_Int32 nCol
= 0; nCol
< maArray
.GetColCount(); ++nCol
)
687 for( sal_Int32 nRow
= 0; nRow
< maArray
.GetRowCount(); ++nRow
)
688 maArray
.SetCellStyleDiag( nCol
, nRow
, maTLBR
.GetUIStyle(), maBLTR
.GetUIStyle() );
690 // This is used in the dialog/control for 'Border' attributes. When using
691 // the original paint below instead of primitives, the advantage currently
692 // is the correct visualization of diagonal line(s) including overlaying,
693 // but the rest is bad. Since the edit views use primitives and the preview
694 // should be 'real' I opt for also changing this to primitives. I will
695 // keep the old solution and add a switch (above) based on a static bool so
696 // that interested people may test this out in the debugger.
697 // This is one more hint to enhance the primitive visualization further to
698 // support diagonals better - that's the way to go.
699 const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D
;
700 std::unique_ptr
<drawinglayer::processor2d::BaseProcessor2D
> pProcessor2D(
701 drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice(
703 aNewViewInformation2D
));
705 pProcessor2D
->process(maArray
.CreateB2DPrimitiveArray());
706 pProcessor2D
.reset();
709 void FrameSelectorImpl::DrawVirtualDevice()
712 for(FrameBorderCIter
aIt(maEnabBorders
); aIt
.Is(); ++aIt
)
714 DrawAllFrameBorders();
715 mbFullRepaint
= false;
718 void FrameSelectorImpl::CopyVirDevToControl(vcl::RenderContext
& rRenderContext
)
722 rRenderContext
.DrawBitmapEx(maVirDevPos
, mpVirDev
->GetBitmapEx(Point(0, 0), mpVirDev
->GetOutputSizePixel()));
725 void FrameSelectorImpl::DrawAllTrackingRects(vcl::RenderContext
& rRenderContext
)
727 tools::PolyPolygon aPPoly
;
728 if (mrFrameSel
.IsAnyBorderSelected())
730 for(SelFrameBorderCIter
aIt( maEnabBorders
); aIt
.Is(); ++aIt
)
731 (*aIt
)->MergeFocusToPolyPolygon(aPPoly
);
732 aPPoly
.Move(maVirDevPos
.X(), maVirDevPos
.Y());
735 // no frame border selected -> draw tracking rectangle around entire control
736 aPPoly
.Insert( tools::Polygon(tools::Rectangle(maVirDevPos
, mpVirDev
->GetOutputSizePixel())));
738 aPPoly
.Optimize(PolyOptimizeFlags::CLOSE
);
740 for(sal_uInt16 nIdx
= 0, nCount
= aPPoly
.Count(); nIdx
< nCount
; ++nIdx
)
741 rRenderContext
.Invert(aPPoly
.GetObject(nIdx
), InvertFlags::TrackFrame
);
744 Point
FrameSelectorImpl::GetDevPosFromMousePos( const Point
& rMousePos
) const
746 return rMousePos
- maVirDevPos
;
749 void FrameSelectorImpl::DoInvalidate( bool bFullRepaint
)
751 mbFullRepaint
|= bFullRepaint
;
752 mrFrameSel
.Invalidate();
755 // frame border state and style
756 void FrameSelectorImpl::SetBorderState( FrameBorder
& rBorder
, FrameBorderState eState
)
758 DBG_ASSERT( rBorder
.IsEnabled(), "svx::FrameSelectorImpl::SetBorderState - access to disabled border" );
761 Any
& rMod
= eState
== FrameBorderState::Show
? aNew
: aOld
;
762 rMod
<<= AccessibleStateType::CHECKED
;
764 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
765 rtl::Reference
< a11y::AccFrameSelectorChild
> xRet
;
766 size_t nVecIdx
= static_cast< size_t >( rBorder
.GetType() );
767 if( GetBorder(rBorder
.GetType()).IsEnabled() && (1 <= nVecIdx
) && (nVecIdx
<= maChildVec
.size()) )
768 xRet
= maChildVec
[ --nVecIdx
].get();
771 if( eState
== FrameBorderState::Show
)
772 SetBorderCoreStyle( rBorder
, &maCurrStyle
);
774 rBorder
.SetState( eState
);
776 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
778 xRet
->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOld
, aNew
);
781 DoInvalidate( true );
784 void FrameSelectorImpl::SetBorderCoreStyle( FrameBorder
& rBorder
, const SvxBorderLine
* pStyle
)
786 DBG_ASSERT( rBorder
.IsEnabled(), "svx::FrameSelectorImpl::SetBorderCoreStyle - access to disabled border" );
787 rBorder
.SetCoreStyle( pStyle
);
788 DoInvalidate( true );
791 void FrameSelectorImpl::ToggleBorderState( FrameBorder
& rBorder
)
793 bool bDontCare
= mrFrameSel
.SupportsDontCareState();
794 switch( rBorder
.GetState() )
796 // same order as tristate check box: visible -> don't care -> hidden
797 case FrameBorderState::Show
:
798 SetBorderState( rBorder
, bDontCare
? FrameBorderState::DontCare
: FrameBorderState::Hide
);
800 case FrameBorderState::Hide
:
801 SetBorderState( rBorder
, FrameBorderState::Show
);
803 case FrameBorderState::DontCare
:
804 SetBorderState( rBorder
, FrameBorderState::Hide
);
809 // frame border selection
810 void FrameSelectorImpl::SelectBorder( FrameBorder
& rBorder
, bool bSelect
)
812 DBG_ASSERT( rBorder
.IsEnabled(), "svx::FrameSelectorImpl::SelectBorder - access to disabled border" );
813 rBorder
.Select( bSelect
);
814 DrawArrows( rBorder
);
815 DoInvalidate( false );
818 void FrameSelectorImpl::SilentGrabFocus()
820 bool bOldAuto
= mbAutoSelect
;
821 mbAutoSelect
= false;
822 mrFrameSel
.GrabFocus();
823 mbAutoSelect
= bOldAuto
;
826 bool FrameSelectorImpl::SelectedBordersEqual() const
829 SelFrameBorderCIter
aIt( maEnabBorders
);
832 const SvxBorderLine
& rFirstStyle
= (*aIt
)->GetCoreStyle();
833 for( ++aIt
; bEqual
&& aIt
.Is(); ++aIt
)
834 bEqual
= ((*aIt
)->GetCoreStyle() == rFirstStyle
);
839 FrameSelector::FrameSelector()
843 void FrameSelector::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
845 CustomWidgetController::SetDrawingArea(pDrawingArea
);
846 mxImpl
.reset( new FrameSelectorImpl( *this ) );
847 Size aPrefSize
= pDrawingArea
->get_ref_device().LogicToPixel(Size(61, 65), MapMode(MapUnit::MapAppFont
));
848 pDrawingArea
->set_size_request(aPrefSize
.Width(), aPrefSize
.Height());
849 EnableRTL( false ); // #107808# don't mirror the mouse handling
852 FrameSelector::~FrameSelector()
854 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
856 mxAccess
->Invalidate();
860 void FrameSelector::Initialize( FrameSelFlags nFlags
)
862 mxImpl
->Initialize( nFlags
);
866 // enabled frame borders
867 bool FrameSelector::IsBorderEnabled( FrameBorderType eBorder
) const
869 return mxImpl
->GetBorder( eBorder
).IsEnabled();
872 sal_Int32
FrameSelector::GetEnabledBorderCount() const
874 return static_cast< sal_Int32
>( mxImpl
->maEnabBorders
.size() );
877 FrameBorderType
FrameSelector::GetEnabledBorderType( sal_Int32 nIndex
) const
879 FrameBorderType eBorder
= FrameBorderType::NONE
;
882 size_t nVecIdx
= static_cast< size_t >( nIndex
);
883 if( nVecIdx
< mxImpl
->maEnabBorders
.size() )
884 eBorder
= mxImpl
->maEnabBorders
[ nVecIdx
]->GetType();
889 // frame border state and style
890 bool FrameSelector::SupportsDontCareState() const
892 return bool(mxImpl
->mnFlags
& FrameSelFlags::DontCare
);
895 FrameBorderState
FrameSelector::GetFrameBorderState( FrameBorderType eBorder
) const
897 return mxImpl
->GetBorder( eBorder
).GetState();
900 const SvxBorderLine
* FrameSelector::GetFrameBorderStyle( FrameBorderType eBorder
) const
902 const SvxBorderLine
& rStyle
= mxImpl
->GetBorder( eBorder
).GetCoreStyle();
903 // rest of the world uses null pointer for invisible frame border
904 return rStyle
.GetOutWidth() ? &rStyle
: nullptr;
907 void FrameSelector::ShowBorder( FrameBorderType eBorder
, const SvxBorderLine
* pStyle
)
909 mxImpl
->SetBorderCoreStyle( mxImpl
->GetBorderAccess( eBorder
), pStyle
);
912 void FrameSelector::SetBorderDontCare( FrameBorderType eBorder
)
914 mxImpl
->SetBorderState( mxImpl
->GetBorderAccess( eBorder
), FrameBorderState::DontCare
);
917 bool FrameSelector::IsAnyBorderVisible() const
920 for( FrameBorderCIter
aIt( mxImpl
->maEnabBorders
); !bIsSet
&& aIt
.Is(); ++aIt
)
921 bIsSet
= ((*aIt
)->GetState() == FrameBorderState::Show
);
925 void FrameSelector::HideAllBorders()
927 for( FrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
928 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Hide
);
931 bool FrameSelector::GetVisibleWidth( tools::Long
& rnWidth
, SvxBorderLineStyle
& rnStyle
) const
933 VisFrameBorderCIter
aIt( mxImpl
->maEnabBorders
);
937 const SvxBorderLine
& rStyle
= (*aIt
)->GetCoreStyle();
939 for( ++aIt
; bFound
&& aIt
.Is(); ++aIt
)
942 (rStyle
.GetWidth() == (*aIt
)->GetCoreStyle().GetWidth()) &&
943 (rStyle
.GetBorderLineStyle() ==
944 (*aIt
)->GetCoreStyle().GetBorderLineStyle());
949 rnWidth
= rStyle
.GetWidth();
950 rnStyle
= rStyle
.GetBorderLineStyle();
955 bool FrameSelector::GetVisibleColor( Color
& rColor
) const
957 VisFrameBorderCIter
aIt( mxImpl
->maEnabBorders
);
961 const SvxBorderLine
& rStyle
= (*aIt
)->GetCoreStyle();
963 for( ++aIt
; bFound
&& aIt
.Is(); ++aIt
)
964 bFound
= (rStyle
.GetColor() == (*aIt
)->GetCoreStyle().GetColor());
967 rColor
= rStyle
.GetColor();
971 // frame border selection
972 const Link
<LinkParamNone
*,void>& FrameSelector::GetSelectHdl() const
974 return mxImpl
->maSelectHdl
;
977 void FrameSelector::SetSelectHdl( const Link
<LinkParamNone
*,void>& rHdl
)
979 mxImpl
->maSelectHdl
= rHdl
;
982 bool FrameSelector::IsBorderSelected( FrameBorderType eBorder
) const
984 return mxImpl
->GetBorder( eBorder
).IsSelected();
987 void FrameSelector::SelectBorder( FrameBorderType eBorder
)
989 mxImpl
->SelectBorder( mxImpl
->GetBorderAccess( eBorder
), true/*bSelect*/ );
990 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
991 // MT: bFireFox as API parameter is ugly...
994 rtl::Reference
< a11y::AccFrameSelectorChild
> xRet
= GetChildAccessible(eBorder
);
997 Any aOldValue
, aNewValue
;
998 aNewValue
<<= AccessibleStateType::FOCUSED
;
999 xRet
->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOldValue
, aNewValue
);
1005 bool FrameSelector::IsAnyBorderSelected() const
1007 // Construct an iterator for selected borders. If it is valid, there is a selected border.
1008 return SelFrameBorderCIter( mxImpl
->maEnabBorders
).Is();
1011 void FrameSelector::SelectAllBorders( bool bSelect
)
1013 for( FrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1014 mxImpl
->SelectBorder( **aIt
, bSelect
);
1017 void FrameSelector::SelectAllVisibleBorders()
1019 for( VisFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1020 mxImpl
->SelectBorder( **aIt
, true/*bSelect*/ );
1023 void FrameSelector::SetStyleToSelection( tools::Long nWidth
, SvxBorderLineStyle nStyle
)
1025 mxImpl
->maCurrStyle
.SetBorderLineStyle( nStyle
);
1026 mxImpl
->maCurrStyle
.SetWidth( nWidth
);
1027 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1028 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Show
);
1031 void FrameSelector::SetColorToSelection(const Color
& rColor
, model::ComplexColor
const& rComplexColor
)
1033 mxImpl
->maCurrStyle
.SetColor(rColor
);
1034 mxImpl
->maCurrStyle
.setComplexColor(rComplexColor
);
1036 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1037 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Show
);
1040 SvxBorderLineStyle
FrameSelector::getCurrentStyleLineStyle() const
1042 return mxImpl
->maCurrStyle
.GetBorderLineStyle();
1046 Reference
< XAccessible
> FrameSelector::CreateAccessible()
1048 #if !ENABLE_WASM_STRIP_ACCESSIBILITY
1049 if( !mxAccess
.is() )
1050 mxAccess
= new a11y::AccFrameSelector(*this);
1055 rtl::Reference
< a11y::AccFrameSelectorChild
> FrameSelector::GetChildAccessible( FrameBorderType eBorder
)
1057 rtl::Reference
< a11y::AccFrameSelectorChild
> xRet
;
1058 size_t nVecIdx
= static_cast< size_t >( eBorder
);
1059 if( IsBorderEnabled( eBorder
) && (1 <= nVecIdx
) && (nVecIdx
<= mxImpl
->maChildVec
.size()) )
1062 if( !mxImpl
->maChildVec
[ nVecIdx
].is() )
1063 mxImpl
->maChildVec
[ nVecIdx
] = new a11y::AccFrameSelectorChild( *this, eBorder
);
1064 xRet
= mxImpl
->maChildVec
[ nVecIdx
].get();
1069 Reference
< XAccessible
> FrameSelector::GetChildAccessible( sal_Int32 nIndex
)
1071 return GetChildAccessible( GetEnabledBorderType( nIndex
) );
1074 Reference
< XAccessible
> FrameSelector::GetChildAccessible( const Point
& rPos
)
1076 Reference
< XAccessible
> xRet
;
1077 for( FrameBorderCIter
aIt( mxImpl
->maEnabBorders
); !xRet
.is() && aIt
.Is(); ++aIt
)
1078 if( (*aIt
)->ContainsClickPoint( rPos
) )
1079 xRet
= GetChildAccessible( (*aIt
)->GetType() ).get();
1083 tools::Rectangle
FrameSelector::GetClickBoundRect( FrameBorderType eBorder
) const
1085 tools::Rectangle aRect
;
1086 const FrameBorder
& rBorder
= mxImpl
->GetBorder( eBorder
);
1087 if( rBorder
.IsEnabled() )
1088 aRect
= rBorder
.GetClickBoundRect();
1092 // virtual functions from base class
1093 void FrameSelector::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
1095 mxImpl
->CopyVirDevToControl(rRenderContext
);
1097 mxImpl
->DrawAllTrackingRects(rRenderContext
);
1100 bool FrameSelector::MouseButtonDown( const MouseEvent
& rMEvt
)
1103 * Click on an unselected frame border:
1104 Set current style/color, make frame border visible, deselect all
1105 other frame borders.
1106 * Click on a selected frame border:
1107 Toggle state of the frame border (visible -> don't care -> hidden),
1108 deselect all other frame borders.
1109 * SHIFT+Click or CTRL+Click on an unselected frame border:
1110 Extend selection, set current style/color to all selected frame
1111 borders independent of the state/style/color of the borders.
1112 * SHIFT+Click or CTRL+Click on a selected frame border:
1113 If all frame borders have same style/color, toggle state of all
1114 borders (see above), otherwise set current style/color to all
1116 * Click on unused area: Do not modify selection and selected frame
1120 // #107394# do not auto-select a frame border
1121 mxImpl
->SilentGrabFocus();
1123 if( rMEvt
.IsLeft() )
1125 Point
aPos( mxImpl
->GetDevPosFromMousePos( rMEvt
.GetPosPixel() ) );
1126 FrameBorderPtrVec aDeselectBorders
;
1128 bool bAnyClicked
= false; // Any frame border clicked?
1129 bool bNewSelected
= false; // Any unselected frame border selected?
1131 /* If frame borders are set to "don't care" and the control does not
1132 support this state, hide them on first mouse click.
1133 DR 2004-01-30: Why are the borders set to "don't care" then?!? */
1134 bool bHideDontCare
= !SupportsDontCareState();
1136 for( FrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1138 if( (*aIt
)->ContainsClickPoint( aPos
) )
1140 // frame border is clicked
1142 if( !(*aIt
)->IsSelected() )
1144 bNewSelected
= true;
1145 //mxImpl->SelectBorder( **aIt, true );
1146 SelectBorder((**aIt
).GetType());
1151 // hide a "don't care" frame border only if it is not clicked
1152 if( bHideDontCare
&& ((*aIt
)->GetState() == FrameBorderState::DontCare
) )
1153 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Hide
);
1155 // deselect frame borders not clicked (if SHIFT or CTRL are not pressed)
1156 if( !rMEvt
.IsShift() && !rMEvt
.IsMod1() )
1157 aDeselectBorders
.push_back( *aIt
);
1163 // any valid frame border clicked? -> deselect other frame borders
1164 for( FrameBorderIter
aIt( aDeselectBorders
); aIt
.Is(); ++aIt
)
1165 mxImpl
->SelectBorder( **aIt
, false );
1167 if( bNewSelected
|| !mxImpl
->SelectedBordersEqual() )
1169 // new frame border selected, selection extended, or selected borders different? -> show
1170 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1171 // SetBorderState() sets current style and color to the frame border
1172 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Show
);
1176 // all selected frame borders are equal -> toggle state
1177 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1178 mxImpl
->ToggleBorderState( **aIt
);
1181 GetSelectHdl().Call( nullptr );
1188 bool FrameSelector::KeyInput( const KeyEvent
& rKEvt
)
1190 bool bHandled
= false;
1191 vcl::KeyCode aKeyCode
= rKEvt
.GetKeyCode();
1192 if( !aKeyCode
.GetModifier() )
1194 sal_uInt16 nCode
= aKeyCode
.GetCode();
1199 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1200 mxImpl
->ToggleBorderState( **aIt
);
1210 if( !mxImpl
->maEnabBorders
.empty() )
1212 // start from first selected frame border
1213 SelFrameBorderCIter
aIt( mxImpl
->maEnabBorders
);
1214 FrameBorderType eBorder
= aIt
.Is() ? (*aIt
)->GetType() : mxImpl
->maEnabBorders
.front()->GetType();
1216 // search for next enabled frame border
1219 eBorder
= mxImpl
->GetBorder( eBorder
).GetKeyboardNeighbor( nCode
);
1221 while( (eBorder
!= FrameBorderType::NONE
) && !IsBorderEnabled( eBorder
) );
1223 // select the frame border
1224 if( eBorder
!= FrameBorderType::NONE
)
1226 DeselectAllBorders();
1227 SelectBorder( eBorder
);
1237 return CustomWidgetController::KeyInput(rKEvt
);
1240 void FrameSelector::GetFocus()
1242 // auto-selection of a frame border, if focus reaches control, and nothing is selected
1243 if( mxImpl
->mbAutoSelect
&& !IsAnyBorderSelected() && !mxImpl
->maEnabBorders
.empty() )
1244 mxImpl
->SelectBorder( *mxImpl
->maEnabBorders
.front(), true );
1246 mxImpl
->DoInvalidate( false );
1247 if (IsAnyBorderSelected())
1249 FrameBorderType borderType
= FrameBorderType::NONE
;
1250 if (mxImpl
->maLeft
.IsSelected())
1251 borderType
= FrameBorderType::Left
;
1252 else if (mxImpl
->maRight
.IsSelected())
1253 borderType
= FrameBorderType::Right
;
1254 else if (mxImpl
->maTop
.IsSelected())
1255 borderType
= FrameBorderType::Top
;
1256 else if (mxImpl
->maBottom
.IsSelected())
1257 borderType
= FrameBorderType::Bottom
;
1258 else if (mxImpl
->maHor
.IsSelected())
1259 borderType
= FrameBorderType::Horizontal
;
1260 else if (mxImpl
->maVer
.IsSelected())
1261 borderType
= FrameBorderType::Vertical
;
1262 else if (mxImpl
->maTLBR
.IsSelected())
1263 borderType
= FrameBorderType::TLBR
;
1264 else if (mxImpl
->maBLTR
.IsSelected())
1265 borderType
= FrameBorderType::BLTR
;
1266 SelectBorder(borderType
);
1268 for( SelFrameBorderIter
aIt( mxImpl
->maEnabBorders
); aIt
.Is(); ++aIt
)
1269 mxImpl
->SetBorderState( **aIt
, FrameBorderState::Show
);
1270 CustomWidgetController::GetFocus();
1273 void FrameSelector::LoseFocus()
1275 mxImpl
->DoInvalidate( false );
1276 CustomWidgetController::LoseFocus();
1279 void FrameSelector::StyleUpdated()
1281 mxImpl
->InitVirtualDevice();
1282 CustomWidgetController::StyleUpdated();
1285 void FrameSelector::Resize()
1287 CustomWidgetController::Resize();
1288 mxImpl
->sizeChanged();
1291 template< typename Cont
, typename Iter
, typename Pred
>
1292 FrameBorderIterBase
< Cont
, Iter
, Pred
>::FrameBorderIterBase( container_type
& rCont
) :
1293 maIt( rCont
.begin() ),
1294 maEnd( rCont
.end() )
1296 while( Is() && !maPred( *maIt
) ) ++maIt
;
1299 template< typename Cont
, typename Iter
, typename Pred
>
1300 FrameBorderIterBase
< Cont
, Iter
, Pred
>& FrameBorderIterBase
< Cont
, Iter
, Pred
>::operator++()
1302 do { ++maIt
; } while( Is() && !maPred( *maIt
) );
1308 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */