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