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