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