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