| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svx.hxx" |
| #include <svx/frmsel.hxx> |
| |
| #include <algorithm> |
| #include <math.h> |
| #include "frmselimpl.hxx" |
| #include "AccessibleFrameSelector.hxx" |
| #include <svx/dialmgr.hxx> |
| #include <com/sun/star/accessibility/AccessibleEventId.hpp> |
| #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLESTATETYPE_HDL_ |
| #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
| #endif |
| |
| #ifndef _SVX_DIALOGS_HRC |
| #include <svx/dialogs.hrc> |
| #endif |
| #ifndef SVX_FRMSEL_HRC |
| #include "frmsel.hrc" |
| #endif |
| |
| #include <tools/rcid.h> |
| |
| namespace svx { |
| |
| using ::com::sun::star::uno::Reference; |
| using ::com::sun::star::uno::Any; |
| using ::com::sun::star::accessibility::XAccessible; |
| using namespace ::com::sun::star::accessibility; |
| // ============================================================================ |
| // global functions from framebordertype.hxx |
| |
| FrameBorderType GetFrameBorderTypeFromIndex( size_t nIndex ) |
| { |
| DBG_ASSERT( nIndex < (size_t)FRAMEBORDERTYPE_COUNT, |
| "svx::GetFrameBorderTypeFromIndex - invalid index" ); |
| return static_cast< FrameBorderType >( nIndex + 1 ); |
| } |
| |
| size_t GetIndexFromFrameBorderType( FrameBorderType eBorder ) |
| { |
| DBG_ASSERT( eBorder != FRAMEBORDER_NONE, |
| "svx::GetIndexFromFrameBorderType - invalid frame border type" ); |
| return static_cast< size_t >( eBorder ) - 1; |
| } |
| |
| // ============================================================================ |
| |
| namespace { |
| |
| /** Space between outer control border and any graphical element of the control. */ |
| const long FRAMESEL_GEOM_OUTER = 2; |
| |
| /** Space between arrows and usable inner area. */ |
| const long FRAMESEL_GEOM_INNER = 3; |
| |
| /** Maximum width to draw a frame border style. */ |
| const long FRAMESEL_GEOM_WIDTH = 9; |
| |
| /** Additional margin for click area of outer lines. */ |
| const long FRAMESEL_GEOM_ADD_CLICK_OUTER = 5; |
| |
| /** Additional margin for click area of inner lines. */ |
| const long FRAMESEL_GEOM_ADD_CLICK_INNER = 2; |
| |
| // ---------------------------------------------------------------------------- |
| |
| static const frame::Style OBJ_FRAMESTYLE_DONTCARE( 3, 0, 0 ); |
| static const FrameBorder OBJ_FRAMEBORDER_NONE( FRAMEBORDER_NONE ); |
| |
| // ---------------------------------------------------------------------------- |
| |
| /** Returns the corresponding flag for a frame border. */ |
| FrameSelFlags lclGetFlagFromType( FrameBorderType eBorder ) |
| { |
| switch( eBorder ) |
| { |
| case FRAMEBORDER_LEFT: return FRAMESEL_LEFT; |
| case FRAMEBORDER_RIGHT: return FRAMESEL_RIGHT; |
| case FRAMEBORDER_TOP: return FRAMESEL_TOP; |
| case FRAMEBORDER_BOTTOM: return FRAMESEL_BOTTOM; |
| case FRAMEBORDER_HOR: return FRAMESEL_INNER_HOR; |
| case FRAMEBORDER_VER: return FRAMESEL_INNER_VER; |
| case FRAMEBORDER_TLBR: return FRAMESEL_DIAG_TLBR; |
| case FRAMEBORDER_BLTR: return FRAMESEL_DIAG_BLTR; |
| case FRAMEBORDER_NONE : break; |
| } |
| return FRAMESEL_NONE; |
| } |
| |
| /** Converts an SvxBorderLine line width (in twips) to a pixel line width. */ |
| inline sal_uInt16 lclGetPixel( sal_uInt16 nWidth ) |
| { |
| // convert all core styles expect 0 to a visible UI style (at least 1 pixel), map 1pt to 1pixel |
| return nWidth ? std::min< sal_uInt16 >( std::max< sal_uInt16 >( (nWidth + 5) / 20, 1 ), FRAMESEL_GEOM_WIDTH ) : 0; |
| } |
| |
| /** Merges the rSource polypolygon into the rDest polypolygon. */ |
| inline void lclPolyPolyUnion( PolyPolygon& rDest, const PolyPolygon& rSource ) |
| { |
| const PolyPolygon aTmp( rDest ); |
| aTmp.GetUnion( rSource, rDest ); |
| } |
| |
| } // namespace |
| |
| // ============================================================================ |
| // FrameBorder |
| // ============================================================================ |
| |
| FrameBorder::FrameBorder( FrameBorderType eType ) : |
| meType( eType ), |
| meState( FRAMESTATE_HIDE ), |
| meKeyLeft( FRAMEBORDER_NONE ), |
| meKeyRight( FRAMEBORDER_NONE ), |
| meKeyTop( FRAMEBORDER_NONE ), |
| meKeyBottom( FRAMEBORDER_NONE ), |
| mbEnabled( false ), |
| mbSelected( false ) |
| { |
| } |
| |
| void FrameBorder::Enable( FrameSelFlags nFlags ) |
| { |
| mbEnabled = (nFlags & lclGetFlagFromType( meType )) != 0; |
| if( !mbEnabled ) |
| SetState( FRAMESTATE_HIDE ); |
| } |
| |
| void FrameBorder::SetCoreStyle( const SvxBorderLine* pStyle ) |
| { |
| if( pStyle ) |
| maCoreStyle = *pStyle; |
| else |
| maCoreStyle = SvxBorderLine(); |
| |
| // from twips to points |
| maUIStyle.Set( maCoreStyle, 0.05, FRAMESEL_GEOM_WIDTH, true ); |
| meState = maUIStyle.Prim() ? FRAMESTATE_SHOW : FRAMESTATE_HIDE; |
| } |
| |
| void FrameBorder::SetState( FrameBorderState eState ) |
| { |
| meState = eState; |
| switch( meState ) |
| { |
| case FRAMESTATE_SHOW: |
| DBG_ERRORFILE( "svx::FrameBorder::SetState - use SetCoreStyle to make border visible" ); |
| break; |
| case FRAMESTATE_HIDE: |
| maCoreStyle = SvxBorderLine(); |
| maUIStyle.Clear(); |
| break; |
| case FRAMESTATE_DONTCARE: |
| maCoreStyle = SvxBorderLine(); |
| maUIStyle = OBJ_FRAMESTYLE_DONTCARE; |
| break; |
| } |
| } |
| |
| void FrameBorder::AddFocusPolygon( const Polygon& rFocus ) |
| { |
| lclPolyPolyUnion( maFocusArea, rFocus ); |
| } |
| |
| void FrameBorder::MergeFocusToPolyPolygon( PolyPolygon& rPPoly ) const |
| { |
| lclPolyPolyUnion( rPPoly, maFocusArea ); |
| } |
| |
| void FrameBorder::AddClickRect( const Rectangle& rRect ) |
| { |
| lclPolyPolyUnion( maClickArea, Polygon( rRect ) ); |
| } |
| |
| bool FrameBorder::ContainsClickPoint( const Point& rPos ) const |
| { |
| return Region( maClickArea ).IsInside( rPos ); |
| } |
| |
| void FrameBorder::MergeClickAreaToPolyPolygon( PolyPolygon& rPPoly ) const |
| { |
| lclPolyPolyUnion( rPPoly, maClickArea ); |
| } |
| |
| Rectangle FrameBorder::GetClickBoundRect() const |
| { |
| return maClickArea.GetBoundRect(); |
| } |
| |
| void FrameBorder::SetKeyboardNeighbors( |
| FrameBorderType eLeft, FrameBorderType eRight, FrameBorderType eTop, FrameBorderType eBottom ) |
| { |
| meKeyLeft = eLeft; |
| meKeyRight = eRight; |
| meKeyTop = eTop; |
| meKeyBottom = eBottom; |
| } |
| |
| FrameBorderType FrameBorder::GetKeyboardNeighbor( sal_uInt16 nKeyCode ) const |
| { |
| FrameBorderType eBorder = FRAMEBORDER_NONE; |
| switch( nKeyCode ) |
| { |
| case KEY_LEFT: eBorder = meKeyLeft; break; |
| case KEY_RIGHT: eBorder = meKeyRight; break; |
| case KEY_UP: eBorder = meKeyTop; break; |
| case KEY_DOWN: eBorder = meKeyBottom; break; |
| default: DBG_ERRORFILE( "svx::FrameBorder::GetKeyboardNeighbor - unknown key code" ); |
| } |
| return eBorder; |
| } |
| |
| // ============================================================================ |
| // FrameSelectorImpl |
| // ============================================================================ |
| |
| FrameSelectorImpl::FrameSelectorImpl( FrameSelector& rFrameSel ) : |
| Resource( SVX_RES( RID_SVXSTR_BORDER_CONTROL ) ), |
| mrFrameSel( rFrameSel ), |
| maILArrows( 16 ), |
| maLeft( FRAMEBORDER_LEFT ), |
| maRight( FRAMEBORDER_RIGHT ), |
| maTop( FRAMEBORDER_TOP ), |
| maBottom( FRAMEBORDER_BOTTOM ), |
| maHor( FRAMEBORDER_HOR ), |
| maVer( FRAMEBORDER_VER ), |
| maTLBR( FRAMEBORDER_TLBR ), |
| maBLTR( FRAMEBORDER_BLTR ), |
| mnFlags( FRAMESEL_OUTER ), |
| mbHor( false ), |
| mbVer( false ), |
| mbTLBR( false ), |
| mbBLTR( false ), |
| mbFullRepaint( true ), |
| mbAutoSelect( true ), |
| mbClicked( false ), |
| mbHCMode( false ), |
| mpAccess( 0 ), |
| maChildVec( 8, static_cast< a11y::AccFrameSelector* >( 0 ) ), |
| mxChildVec( 8 ) |
| { |
| FreeResource(); |
| |
| maAllBorders.resize( FRAMEBORDERTYPE_COUNT, 0 ); |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_LEFT ) ] = &maLeft; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_RIGHT ) ] = &maRight; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TOP ) ] = &maTop; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BOTTOM ) ] = &maBottom; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_HOR ) ] = &maHor; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_VER ) ] = &maVer; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_TLBR ) ] = &maTLBR; |
| maAllBorders[ GetIndexFromFrameBorderType( FRAMEBORDER_BLTR ) ] = &maBLTR; |
| #if OSL_DEBUG_LEVEL >= 2 |
| { |
| bool bOk = true; |
| for( FrameBorderCIter aIt( maAllBorders ); bOk && aIt.Is(); bOk = (*aIt != 0), ++aIt ); |
| DBG_ASSERT( bOk, "svx::FrameSelectorImpl::FrameSelectorImpl - missing entry in maAllBorders" ); |
| } |
| #endif |
| // left neighbor right neighbor upper neighbor lower neighbor |
| maLeft.SetKeyboardNeighbors( FRAMEBORDER_NONE, FRAMEBORDER_TLBR, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM ); |
| maRight.SetKeyboardNeighbors( FRAMEBORDER_BLTR, FRAMEBORDER_NONE, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM ); |
| maTop.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_NONE, FRAMEBORDER_TLBR ); |
| maBottom.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_BLTR, FRAMEBORDER_NONE ); |
| maHor.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_RIGHT, FRAMEBORDER_TLBR, FRAMEBORDER_BLTR ); |
| maVer.SetKeyboardNeighbors( FRAMEBORDER_TLBR, FRAMEBORDER_BLTR, FRAMEBORDER_TOP, FRAMEBORDER_BOTTOM ); |
| maTLBR.SetKeyboardNeighbors( FRAMEBORDER_LEFT, FRAMEBORDER_VER, FRAMEBORDER_TOP, FRAMEBORDER_HOR ); |
| maBLTR.SetKeyboardNeighbors( FRAMEBORDER_VER, FRAMEBORDER_RIGHT, FRAMEBORDER_HOR, FRAMEBORDER_BOTTOM ); |
| } |
| |
| FrameSelectorImpl::~FrameSelectorImpl() |
| { |
| if( mpAccess ) |
| mpAccess->Invalidate(); |
| for( AccessibleImplVec::iterator aIt = maChildVec.begin(), aEnd = maChildVec.end(); aIt != aEnd; ++aIt ) |
| if( *aIt ) |
| (*aIt)->Invalidate(); |
| } |
| |
| // initialization ------------------------------------------------------------- |
| |
| void FrameSelectorImpl::Initialize( FrameSelFlags nFlags ) |
| { |
| mnFlags = nFlags; |
| |
| maEnabBorders.clear(); |
| for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt ) |
| { |
| (*aIt)->Enable( mnFlags ); |
| if( (*aIt)->IsEnabled() ) |
| maEnabBorders.push_back( *aIt ); |
| } |
| mbHor = maHor.IsEnabled(); |
| mbVer = maVer.IsEnabled(); |
| mbTLBR = maTLBR.IsEnabled(); |
| mbBLTR = maBLTR.IsEnabled(); |
| |
| InitVirtualDevice(); |
| } |
| |
| void FrameSelectorImpl::InitColors() |
| { |
| const StyleSettings& rSett = mrFrameSel.GetSettings().GetStyleSettings(); |
| maBackCol = rSett.GetFieldColor(); |
| mbHCMode = rSett.GetHighContrastMode(); |
| maArrowCol = rSett.GetFieldTextColor(); |
| maMarkCol.operator=( maBackCol ).Merge( maArrowCol, mbHCMode ? 0x80 : 0xC0 ); |
| maHCLineCol = rSett.GetLabelTextColor(); |
| } |
| |
| void FrameSelectorImpl::InitArrowImageList() |
| { |
| /* Build the arrow images bitmap with current colors. */ |
| Color pColorAry1[3]; |
| Color pColorAry2[3]; |
| pColorAry1[0] = Color( 0, 0, 0 ); |
| pColorAry2[0] = maArrowCol; // black -> arrow color |
| pColorAry1[1] = Color( 0, 255, 0 ); |
| pColorAry2[1] = maMarkCol; // green -> marker color |
| pColorAry1[2] = Color( 255, 0, 255 ); |
| pColorAry2[2] = maBackCol; // magenta -> background |
| |
| GetRes( SVX_RES( RID_SVXSTR_BORDER_CONTROL ).SetRT( RSC_RESOURCE ) ); |
| maILArrows.InsertFromHorizontalBitmap( |
| SVX_RES( BMP_FRMSEL_ARROWS ), 16, NULL, pColorAry1, pColorAry2, 3); |
| FreeResource(); |
| DBG_ASSERT( maILArrows.GetImageSize().Height() == maILArrows.GetImageSize().Width(), |
| "svx::FrameSelectorImpl::InitArrowImageList - images are not squarish" ); |
| mnArrowSize = maILArrows.GetImageSize().Height(); |
| } |
| |
| void FrameSelectorImpl::InitGlobalGeometry() |
| { |
| Size aCtrlSize( mrFrameSel.CalcOutputSize( mrFrameSel.GetSizePixel() ) ); |
| /* nMinSize is the lower of width and height (control will always be squarish). |
| FRAMESEL_GEOM_OUTER is the minimal distance between inner control border |
| and any element. */ |
| long nMinSize = Min( aCtrlSize.Width(), aCtrlSize.Height() ) - 2 * FRAMESEL_GEOM_OUTER; |
| /* nFixedSize is the size all existing elements need in one direction: |
| the diag. arrow, space betw. arrow and frame border, outer frame border, |
| inner frame border, other outer frame border, space betw. frame border |
| and arrow, the other arrow. */ |
| long nFixedSize = 2 * mnArrowSize + 2 * FRAMESEL_GEOM_INNER + 3 * FRAMESEL_GEOM_WIDTH; |
| /* nBetwBordersSize contains the size between an outer and inner frame border (made odd). */ |
| long nBetwBordersSize = (((nMinSize - nFixedSize) / 2) - 1) | 1; |
| |
| /* The final size of the usable area. */ |
| mnCtrlSize = 2 * nBetwBordersSize + nFixedSize; |
| maVirDev.SetOutputSizePixel( Size( mnCtrlSize, mnCtrlSize ) ); |
| |
| /* Center the virtual device in the control. */ |
| maVirDevPos = Point( (aCtrlSize.Width() - mnCtrlSize) / 2, (aCtrlSize.Height() - mnCtrlSize) / 2 ); |
| } |
| |
| void FrameSelectorImpl::InitBorderGeometry() |
| { |
| size_t nCol, nCols, nRow, nRows; |
| |
| // Global border geometry values ------------------------------------------ |
| |
| /* mnLine* is the middle point inside a frame border (i.e. mnLine1 is mid X inside left border). */ |
| mnLine1 = mnArrowSize + FRAMESEL_GEOM_INNER + FRAMESEL_GEOM_WIDTH / 2; |
| mnLine2 = mnCtrlSize / 2; |
| mnLine3 = 2 * mnLine2 - mnLine1; |
| |
| // Frame helper array ----------------------------------------------------- |
| |
| maArray.Initialize( mbVer ? 2 : 1, mbHor ? 2 : 1 ); |
| maArray.SetUseDiagDoubleClipping( true ); |
| |
| maArray.SetXOffset( mnLine1 ); |
| maArray.SetAllColWidths( (mbVer ? mnLine2 : mnLine3) - mnLine1 ); |
| |
| maArray.SetYOffset( mnLine1 ); |
| maArray.SetAllRowHeights( (mbHor ? mnLine2 : mnLine3) - mnLine1 ); |
| |
| Rectangle aTLRect( maArray.GetCellRect( 0, 0 ) ); |
| |
| // Focus polygons --------------------------------------------------------- |
| |
| /* Width for focus rectangles from center of frame borders. */ |
| mnFocusOffs = FRAMESEL_GEOM_WIDTH / 2 + 1; |
| |
| maLeft.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine1 + mnFocusOffs, mnLine3 + mnFocusOffs ) ); |
| maVer.AddFocusPolygon( Rectangle( mnLine2 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine2 + mnFocusOffs, mnLine3 + mnFocusOffs ) ); |
| maRight.AddFocusPolygon( Rectangle( mnLine3 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) ); |
| maTop.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine1 + mnFocusOffs ) ); |
| maHor.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine2 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine2 + mnFocusOffs ) ); |
| maBottom.AddFocusPolygon( Rectangle( mnLine1 - mnFocusOffs, mnLine3 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) ); |
| |
| for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol ) |
| { |
| for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow ) |
| { |
| Rectangle aRect( maArray.GetCellRect( nCol, nRow ) ); |
| long nDiagFocusOffsX = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetHorDiagAngle( nCol, nRow ) ); |
| long nDiagFocusOffsY = frame::GetTLDiagOffset( -mnFocusOffs, mnFocusOffs, maArray.GetVerDiagAngle( nCol, nRow ) ); |
| |
| std::vector< Point > aFocusVec; |
| aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Top() + nDiagFocusOffsY ) ); |
| aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Top() - mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Left() + nDiagFocusOffsX, aRect.Top() - mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Bottom() - nDiagFocusOffsY ) ); |
| aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Bottom() + mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs ) ); |
| maTLBR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) ); |
| |
| aFocusVec.clear(); |
| aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Top() + nDiagFocusOffsY ) ); |
| aFocusVec.push_back( Point( aRect.Right() + mnFocusOffs, aRect.Top() - mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Right() - nDiagFocusOffsX, aRect.Top() - mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Bottom() - nDiagFocusOffsY ) ); |
| aFocusVec.push_back( Point( aRect.Left() - mnFocusOffs, aRect.Bottom() + mnFocusOffs ) ); |
| aFocusVec.push_back( Point( aRect.Left() + nDiagFocusOffsX, aRect.Bottom() + mnFocusOffs ) ); |
| maBLTR.AddFocusPolygon( Polygon( static_cast< sal_uInt16 >( aFocusVec.size() ), &aFocusVec[ 0 ] ) ); |
| } |
| } |
| |
| // Click areas ------------------------------------------------------------ |
| |
| for( FrameBorderIter aIt( maAllBorders ); aIt.Is(); ++aIt ) |
| (*aIt)->ClearClickArea(); |
| |
| /* Additional space for click area: is added to the space available to draw |
| the frame borders. For instance left frame border: |
| - To left, top, and bottom always big additional space (outer area). |
| - To right: Dependent on existence of inner vertical frame border |
| (if enabled, use less space). |
| */ |
| long nClO = FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_OUTER; |
| long nClI = (mbTLBR && mbBLTR) ? (FRAMESEL_GEOM_WIDTH / 2 + FRAMESEL_GEOM_ADD_CLICK_INNER) : nClO; |
| long nClH = mbHor ? nClI : nClO; // additional space dependent of horizontal inner border |
| long nClV = mbVer ? nClI : nClO; // additional space dependent of vertical inner border |
| |
| maLeft.AddClickRect( Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine1 + nClV, mnLine3 + nClO ) ); |
| maVer.AddClickRect( Rectangle( mnLine2 - nClI, mnLine1 - nClO, mnLine2 + nClI, mnLine3 + nClO ) ); |
| maRight.AddClickRect( Rectangle( mnLine3 - nClV, mnLine1 - nClO, mnLine3 + nClO, mnLine3 + nClO ) ); |
| maTop.AddClickRect( Rectangle( mnLine1 - nClO, mnLine1 - nClO, mnLine3 + nClO, mnLine1 + nClH ) ); |
| maHor.AddClickRect( Rectangle( mnLine1 - nClO, mnLine2 - nClI, mnLine3 + nClO, mnLine2 + nClI ) ); |
| maBottom.AddClickRect( Rectangle( mnLine1 - nClO, mnLine3 - nClH, mnLine3 + nClO, mnLine3 + nClO ) ); |
| |
| /* Diagonal frame borders use the remaining space between outer and inner frame borders. */ |
| if( mbTLBR || mbBLTR ) |
| { |
| for( nCol = 0, nCols = maArray.GetColCount(); nCol < nCols; ++nCol ) |
| { |
| for( nRow = 0, nRows = maArray.GetRowCount(); nRow < nRows; ++nRow ) |
| { |
| // the usable area between horizonal/vertical frame borders of current quadrant |
| Rectangle aRect( maArray.GetCellRect( nCol, nRow ) ); |
| aRect.Left() += nClV + 1; |
| aRect.Right() -= nClV + 1; |
| aRect.Top() += nClH + 1; |
| aRect.Bottom() -= nClH + 1; |
| |
| /* Both diagonal frame borders enabled. */ |
| if( mbTLBR && mbBLTR ) |
| { |
| // single areas |
| Point aMid( aRect.Center() ); |
| maTLBR.AddClickRect( Rectangle( aRect.TopLeft(), aMid ) ); |
| maTLBR.AddClickRect( Rectangle( aMid + Point( 1, 1 ), aRect.BottomRight() ) ); |
| maBLTR.AddClickRect( Rectangle( aRect.Left(), aMid.Y() + 1, aMid.X(), aRect.Bottom() ) ); |
| maBLTR.AddClickRect( Rectangle( aMid.X() + 1, aRect.Top(), aRect.Right(), aMid.Y() ) ); |
| // centered rectangle for both frame borders |
| Rectangle aMidRect( aRect.TopLeft(), Size( aRect.GetWidth() / 3, aRect.GetHeight() / 3 ) ); |
| aMidRect.Move( (aRect.GetWidth() - aMidRect.GetWidth()) / 2, (aRect.GetHeight() - aMidRect.GetHeight()) / 2 ); |
| maTLBR.AddClickRect( aMidRect ); |
| maBLTR.AddClickRect( aMidRect ); |
| } |
| /* One of the diagonal frame borders enabled - use entire rectangle. */ |
| else if( mbTLBR && !mbBLTR ) // top-left to bottom-right only |
| maTLBR.AddClickRect( aRect ); |
| else if( !mbTLBR && mbBLTR ) // bottom-left to top-right only |
| maBLTR.AddClickRect( aRect ); |
| } |
| } |
| } |
| } |
| |
| void FrameSelectorImpl::InitVirtualDevice() |
| { |
| // initialize resources |
| InitColors(); |
| InitArrowImageList(); |
| |
| // initialize geometry |
| InitGlobalGeometry(); |
| InitBorderGeometry(); |
| |
| // correct background around the used area |
| mrFrameSel.SetBackground( Wallpaper( maBackCol ) ); |
| DoInvalidate( true ); |
| } |
| |
| // frame border access -------------------------------------------------------- |
| |
| const FrameBorder& FrameSelectorImpl::GetBorder( FrameBorderType eBorder ) const |
| { |
| size_t nIndex = GetIndexFromFrameBorderType( eBorder ); |
| if( nIndex < maAllBorders.size() ) |
| return *maAllBorders[ nIndex ]; |
| DBG_ERRORFILE( "svx::FrameSelectorImpl::GetBorder - unknown border type" ); |
| return maTop; |
| } |
| |
| FrameBorder& FrameSelectorImpl::GetBorderAccess( FrameBorderType eBorder ) |
| { |
| return const_cast< FrameBorder& >( GetBorder( eBorder ) ); |
| } |
| |
| // drawing -------------------------------------------------------------------- |
| |
| void FrameSelectorImpl::DrawBackground() |
| { |
| // clear the area |
| maVirDev.SetLineColor(); |
| maVirDev.SetFillColor( maBackCol ); |
| maVirDev.DrawRect( Rectangle( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) ); |
| |
| // draw the inner gray (or whatever color) rectangle |
| maVirDev.SetLineColor(); |
| maVirDev.SetFillColor( maMarkCol ); |
| maVirDev.DrawRect( Rectangle( |
| mnLine1 - mnFocusOffs, mnLine1 - mnFocusOffs, mnLine3 + mnFocusOffs, mnLine3 + mnFocusOffs ) ); |
| |
| // draw the white space for enabled frame borders |
| PolyPolygon aPPoly; |
| for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt ) |
| (*aIt)->MergeFocusToPolyPolygon( aPPoly ); |
| aPPoly.Optimize( POLY_OPTIMIZE_CLOSE ); |
| maVirDev.SetLineColor( maBackCol ); |
| maVirDev.SetFillColor( maBackCol ); |
| maVirDev.DrawPolyPolygon( aPPoly ); |
| } |
| |
| void FrameSelectorImpl::DrawArrows( const FrameBorder& rBorder ) |
| { |
| DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::DrawArrows - access to disabled border" ); |
| |
| long nLinePos = 0; |
| switch( rBorder.GetType() ) |
| { |
| case FRAMEBORDER_LEFT: |
| case FRAMEBORDER_TOP: nLinePos = mnLine1; break; |
| case FRAMEBORDER_VER: |
| case FRAMEBORDER_HOR: nLinePos = mnLine2; break; |
| case FRAMEBORDER_RIGHT: |
| case FRAMEBORDER_BOTTOM: nLinePos = mnLine3; break; |
| default: ; //prevent warning |
| } |
| nLinePos -= mnArrowSize / 2; |
| |
| long nTLPos = 0; |
| long nBRPos = mnCtrlSize - mnArrowSize; |
| Point aPos1, aPos2; |
| sal_uInt16 nImgId1 = 0, nImgId2 = 0; |
| switch( rBorder.GetType() ) |
| { |
| case FRAMEBORDER_LEFT: |
| case FRAMEBORDER_RIGHT: |
| case FRAMEBORDER_VER: |
| aPos1 = Point( nLinePos, nTLPos ); nImgId1 = 1; |
| aPos2 = Point( nLinePos, nBRPos ); nImgId2 = 2; |
| break; |
| |
| case FRAMEBORDER_TOP: |
| case FRAMEBORDER_BOTTOM: |
| case FRAMEBORDER_HOR: |
| aPos1 = Point( nTLPos, nLinePos ); nImgId1 = 3; |
| aPos2 = Point( nBRPos, nLinePos ); nImgId2 = 4; |
| break; |
| |
| case FRAMEBORDER_TLBR: |
| aPos1 = Point( nTLPos, nTLPos ); nImgId1 = 5; |
| aPos2 = Point( nBRPos, nBRPos ); nImgId2 = 6; |
| break; |
| case FRAMEBORDER_BLTR: |
| aPos1 = Point( nTLPos, nBRPos ); nImgId1 = 7; |
| aPos2 = Point( nBRPos, nTLPos ); nImgId2 = 8; |
| break; |
| default: ; //prevent warning |
| } |
| |
| // Arrow or marker? Do not draw arrows into disabled control. |
| sal_uInt16 nSelectAdd = (mrFrameSel.IsEnabled() && rBorder.IsSelected()) ? 0 : 8; |
| maVirDev.DrawImage( aPos1, maILArrows.GetImage( nImgId1 + nSelectAdd ) ); |
| maVirDev.DrawImage( aPos2, maILArrows.GetImage( nImgId2 + nSelectAdd ) ); |
| } |
| |
| void FrameSelectorImpl::DrawAllArrows() |
| { |
| for( FrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt ) |
| DrawArrows( **aIt ); |
| } |
| |
| Color FrameSelectorImpl::GetDrawLineColor( const Color& rColor ) const |
| { |
| Color aColor( mbHCMode ? maHCLineCol : rColor ); |
| if( aColor == maBackCol ) |
| aColor.Invert(); |
| return aColor; |
| } |
| |
| void FrameSelectorImpl::DrawAllFrameBorders() |
| { |
| // Translate core colors to current UI colors (regards current background and HC mode). |
| for( FrameBorderIter aIt( maEnabBorders ); aIt.Is(); ++aIt ) |
| { |
| Color aCoreColor = ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ? maMarkCol : (*aIt)->GetCoreStyle().GetColor(); |
| (*aIt)->SetUIColor( GetDrawLineColor( aCoreColor ) ); |
| } |
| |
| // Copy all frame border styles to the helper array |
| maArray.SetColumnStyleLeft( 0, maLeft.GetUIStyle() ); |
| if( mbVer ) maArray.SetColumnStyleLeft( 1, maVer.GetUIStyle() ); |
| maArray.SetColumnStyleRight( mbVer ? 1 : 0, maRight.GetUIStyle() ); |
| |
| maArray.SetRowStyleTop( 0, maTop.GetUIStyle() ); |
| if( mbHor ) maArray.SetRowStyleTop( 1, maHor.GetUIStyle() ); |
| maArray.SetRowStyleBottom( mbHor ? 1 : 0, maBottom.GetUIStyle() ); |
| |
| for( size_t nCol = 0; nCol < maArray.GetColCount(); ++nCol ) |
| for( size_t nRow = 0; nRow < maArray.GetRowCount(); ++nRow ) |
| maArray.SetCellStyleDiag( nCol, nRow, maTLBR.GetUIStyle(), maBLTR.GetUIStyle() ); |
| |
| // Let the helper array draw itself |
| maArray.DrawArray( maVirDev ); |
| } |
| |
| void FrameSelectorImpl::DrawVirtualDevice() |
| { |
| DrawBackground(); |
| DrawAllArrows(); |
| DrawAllFrameBorders(); |
| mbFullRepaint = false; |
| } |
| |
| void FrameSelectorImpl::CopyVirDevToControl() |
| { |
| if( mbFullRepaint ) |
| DrawVirtualDevice(); |
| mrFrameSel.DrawBitmap( maVirDevPos, maVirDev.GetBitmap( Point( 0, 0 ), maVirDev.GetOutputSizePixel() ) ); |
| } |
| |
| void FrameSelectorImpl::DrawAllTrackingRects() |
| { |
| PolyPolygon aPPoly; |
| if( mrFrameSel.IsAnyBorderSelected() ) |
| { |
| for( SelFrameBorderCIter aIt( maEnabBorders ); aIt.Is(); ++aIt ) |
| (*aIt)->MergeFocusToPolyPolygon( aPPoly ); |
| aPPoly.Move( maVirDevPos.X(), maVirDevPos.Y() ); |
| } |
| else |
| // no frame border selected -> draw tracking rectangle around entire control |
| aPPoly.Insert( Polygon( Rectangle( maVirDevPos, maVirDev.GetOutputSizePixel() ) ) ); |
| |
| aPPoly.Optimize( POLY_OPTIMIZE_CLOSE ); |
| for( sal_uInt16 nIdx = 0, nCount = aPPoly.Count(); nIdx < nCount; ++nIdx ) |
| mrFrameSel.InvertTracking( aPPoly.GetObject( nIdx ), SHOWTRACK_SMALL | SHOWTRACK_WINDOW ); |
| } |
| |
| Point FrameSelectorImpl::GetDevPosFromMousePos( const Point& rMousePos ) const |
| { |
| return rMousePos - maVirDevPos; |
| } |
| |
| void FrameSelectorImpl::DoInvalidate( bool bFullRepaint ) |
| { |
| mbFullRepaint |= bFullRepaint; |
| mrFrameSel.Invalidate( INVALIDATE_NOERASE ); |
| } |
| |
| // frame border state and style ----------------------------------------------- |
| |
| void FrameSelectorImpl::SetBorderState( FrameBorder& rBorder, FrameBorderState eState ) |
| { |
| DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderState - access to disabled border" ); |
| Any aOld; |
| Any aNew; |
| Any& rMod = eState == FRAMESTATE_SHOW ? aNew : aOld; |
| rMod <<= AccessibleStateType::CHECKED; |
| Reference< XAccessible > xRet; |
| size_t nVecIdx = static_cast< size_t >( rBorder.GetType() ); |
| if( GetBorder(rBorder.GetType()).IsEnabled() && (1 <= nVecIdx) && (nVecIdx <= maChildVec.size()) ) |
| xRet = mxChildVec[ --nVecIdx ]; |
| a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get()); |
| |
| if( eState == FRAMESTATE_SHOW ) |
| SetBorderCoreStyle( rBorder, &maCurrStyle ); |
| else |
| rBorder.SetState( eState ); |
| if (pFrameSelector) |
| pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOld, aNew ); |
| DoInvalidate( true ); |
| } |
| |
| void FrameSelectorImpl::SetBorderCoreStyle( FrameBorder& rBorder, const SvxBorderLine* pStyle ) |
| { |
| DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SetBorderCoreStyle - access to disabled border" ); |
| rBorder.SetCoreStyle( pStyle ); |
| DoInvalidate( true ); |
| } |
| |
| void FrameSelectorImpl::ToggleBorderState( FrameBorder& rBorder ) |
| { |
| bool bDontCare = mrFrameSel.SupportsDontCareState(); |
| switch( rBorder.GetState() ) |
| { |
| // same order as tristate check box: visible -> don't care -> hidden |
| case FRAMESTATE_SHOW: |
| SetBorderState( rBorder, bDontCare ? FRAMESTATE_DONTCARE : FRAMESTATE_HIDE ); |
| break; |
| case FRAMESTATE_HIDE: |
| SetBorderState( rBorder, FRAMESTATE_SHOW ); |
| break; |
| case FRAMESTATE_DONTCARE: |
| SetBorderState( rBorder, FRAMESTATE_HIDE ); |
| break; |
| } |
| } |
| |
| // frame border selection ----------------------------------------------------- |
| |
| void FrameSelectorImpl::SelectBorder( FrameBorder& rBorder, bool bSelect ) |
| { |
| DBG_ASSERT( rBorder.IsEnabled(), "svx::FrameSelectorImpl::SelectBorder - access to disabled border" ); |
| rBorder.Select( bSelect ); |
| DrawArrows( rBorder ); |
| DoInvalidate( false ); |
| maSelectHdl.Call( this ); |
| } |
| |
| void FrameSelectorImpl::SilentGrabFocus() |
| { |
| bool bOldAuto = mbAutoSelect; |
| mbAutoSelect = false; |
| mrFrameSel.GrabFocus(); |
| mbAutoSelect = bOldAuto; |
| } |
| |
| bool FrameSelectorImpl::SelectedBordersEqual() const |
| { |
| bool bEqual = true; |
| SelFrameBorderCIter aIt( maEnabBorders ); |
| if( aIt.Is() ) |
| { |
| const SvxBorderLine& rFirstStyle = (*aIt)->GetCoreStyle(); |
| for( ++aIt; bEqual && aIt.Is(); ++aIt ) |
| bEqual = ((*aIt)->GetCoreStyle() == rFirstStyle); |
| } |
| return bEqual; |
| } |
| |
| // ============================================================================ |
| // FrameSelector |
| // ============================================================================ |
| |
| FrameSelector::FrameSelector( Window* pParent, const ResId& rResId ) : |
| Control( pParent, rResId ) |
| { |
| // not in c'tor init list (avoid warning about usage of *this) |
| mxImpl.reset( new FrameSelectorImpl( *this ) ); |
| EnableRTL( false ); // #107808# don't mirror the mouse handling |
| } |
| |
| FrameSelector::~FrameSelector() |
| { |
| } |
| |
| void FrameSelector::Initialize( FrameSelFlags nFlags ) |
| { |
| mxImpl->Initialize( nFlags ); |
| Show(); |
| } |
| |
| // enabled frame borders ------------------------------------------------------ |
| |
| bool FrameSelector::IsBorderEnabled( FrameBorderType eBorder ) const |
| { |
| return mxImpl->GetBorder( eBorder ).IsEnabled(); |
| } |
| |
| sal_Int32 FrameSelector::GetEnabledBorderCount() const |
| { |
| return static_cast< sal_Int32 >( mxImpl->maEnabBorders.size() ); |
| } |
| |
| FrameBorderType FrameSelector::GetEnabledBorderType( sal_Int32 nIndex ) const |
| { |
| FrameBorderType eBorder = FRAMEBORDER_NONE; |
| if( nIndex >= 0 ) |
| { |
| size_t nVecIdx = static_cast< size_t >( nIndex ); |
| if( nVecIdx < mxImpl->maEnabBorders.size() ) |
| eBorder = mxImpl->maEnabBorders[ nVecIdx ]->GetType(); |
| } |
| return eBorder; |
| } |
| |
| sal_Int32 FrameSelector::GetEnabledBorderIndex( FrameBorderType eBorder ) const |
| { |
| sal_Int32 nIndex = 0; |
| for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt, ++nIndex ) |
| if( (*aIt)->GetType() == eBorder ) |
| return nIndex; |
| return -1; |
| } |
| |
| // frame border state and style ----------------------------------------------- |
| |
| bool FrameSelector::SupportsDontCareState() const |
| { |
| return (mxImpl->mnFlags & FRAMESEL_DONTCARE) != 0; |
| } |
| |
| FrameBorderState FrameSelector::GetFrameBorderState( FrameBorderType eBorder ) const |
| { |
| return mxImpl->GetBorder( eBorder ).GetState(); |
| } |
| |
| const SvxBorderLine* FrameSelector::GetFrameBorderStyle( FrameBorderType eBorder ) const |
| { |
| const SvxBorderLine& rStyle = mxImpl->GetBorder( eBorder ).GetCoreStyle(); |
| // rest of the world uses null pointer for invisible frame border |
| return rStyle.GetOutWidth() ? &rStyle : 0; |
| } |
| |
| void FrameSelector::ShowBorder( FrameBorderType eBorder, const SvxBorderLine* pStyle ) |
| { |
| mxImpl->SetBorderCoreStyle( mxImpl->GetBorderAccess( eBorder ), pStyle ); |
| } |
| |
| void FrameSelector::SetBorderDontCare( FrameBorderType eBorder ) |
| { |
| mxImpl->SetBorderState( mxImpl->GetBorderAccess( eBorder ), FRAMESTATE_DONTCARE ); |
| } |
| |
| bool FrameSelector::IsAnyBorderVisible() const |
| { |
| bool bIsSet = false; |
| for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bIsSet && aIt.Is(); ++aIt ) |
| bIsSet = ((*aIt)->GetState() == FRAMESTATE_SHOW); |
| return bIsSet; |
| } |
| |
| void FrameSelector::HideAllBorders() |
| { |
| for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE ); |
| } |
| |
| bool FrameSelector::GetVisibleWidth( sal_uInt16& rnPrim, sal_uInt16& rnDist, sal_uInt16& rnSecn ) const |
| { |
| VisFrameBorderCIter aIt( mxImpl->maEnabBorders ); |
| if( !aIt.Is() ) |
| return false; |
| |
| const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle(); |
| bool bFound = true; |
| for( ++aIt; bFound && aIt.Is(); ++aIt ) |
| bFound = |
| (rStyle.GetOutWidth() == (*aIt)->GetCoreStyle().GetOutWidth()) && |
| (rStyle.GetDistance() == (*aIt)->GetCoreStyle().GetDistance()) && |
| (rStyle.GetInWidth() == (*aIt)->GetCoreStyle().GetInWidth()); |
| |
| if( bFound ) |
| { |
| rnPrim = rStyle.GetOutWidth(); |
| rnDist = rStyle.GetDistance(); |
| rnSecn = rStyle.GetInWidth(); |
| } |
| return bFound; |
| } |
| |
| bool FrameSelector::GetVisibleColor( Color& rColor ) const |
| { |
| VisFrameBorderCIter aIt( mxImpl->maEnabBorders ); |
| if( !aIt.Is() ) |
| return false; |
| |
| const SvxBorderLine& rStyle = (*aIt)->GetCoreStyle(); |
| bool bFound = true; |
| for( ++aIt; bFound && aIt.Is(); ++aIt ) |
| bFound = (rStyle.GetColor() == (*aIt)->GetCoreStyle().GetColor()); |
| |
| if( bFound ) |
| rColor = rStyle.GetColor(); |
| return bFound; |
| } |
| |
| // frame border selection ----------------------------------------------------- |
| |
| const Link& FrameSelector::GetSelectHdl() const |
| { |
| return mxImpl->maSelectHdl; |
| } |
| |
| void FrameSelector::SetSelectHdl( const Link& rHdl ) |
| { |
| mxImpl->maSelectHdl = rHdl; |
| } |
| |
| bool FrameSelector::IsBorderSelected( FrameBorderType eBorder ) const |
| { |
| return mxImpl->GetBorder( eBorder ).IsSelected(); |
| } |
| |
| void FrameSelector::SelectBorder( FrameBorderType eBorder, bool bSelect /*, bool bFocus */ ) |
| { |
| mxImpl->SelectBorder( mxImpl->GetBorderAccess( eBorder ), bSelect ); |
| // MT: bFireFox as API parameter is ugly... |
| // if (bFocus) |
| { |
| Reference< XAccessible > xRet = GetChildAccessible(eBorder); |
| a11y::AccFrameSelector* pFrameSelector = static_cast<a11y::AccFrameSelector*>(xRet.get()); |
| if (pFrameSelector) |
| { |
| Any aOldValue, aNewValue; |
| aNewValue <<= AccessibleStateType::FOCUSED; |
| pFrameSelector->NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); |
| } |
| } |
| } |
| |
| bool FrameSelector::IsAnyBorderSelected() const |
| { |
| // Construct an iterator for selected borders. If it is valid, there is a selected border. |
| return SelFrameBorderCIter( mxImpl->maEnabBorders ).Is(); |
| } |
| |
| void FrameSelector::SelectAllBorders( bool bSelect ) |
| { |
| for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SelectBorder( **aIt, bSelect ); |
| } |
| |
| void FrameSelector::SelectAllVisibleBorders( bool bSelect ) |
| { |
| for( VisFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SelectBorder( **aIt, bSelect ); |
| } |
| |
| void FrameSelector::SetStyleToSelection( sal_uInt16 nPrim, sal_uInt16 nDist, sal_uInt16 nSecn ) |
| { |
| mxImpl->maCurrStyle.SetOutWidth( nPrim ); |
| mxImpl->maCurrStyle.SetDistance( nDist ); |
| mxImpl->maCurrStyle.SetInWidth( nSecn ); |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW ); |
| } |
| |
| void FrameSelector::SetColorToSelection( const Color& rColor ) |
| { |
| mxImpl->maCurrStyle.SetColor( rColor ); |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW ); |
| } |
| |
| // accessibility -------------------------------------------------------------- |
| |
| Reference< XAccessible > FrameSelector::CreateAccessible() |
| { |
| if( !mxImpl->mxAccess.is() ) |
| mxImpl->mxAccess = mxImpl->mpAccess = |
| new a11y::AccFrameSelector( *this, FRAMEBORDER_NONE ); |
| return mxImpl->mxAccess; |
| } |
| |
| Reference< XAccessible > FrameSelector::GetChildAccessible( FrameBorderType eBorder ) |
| { |
| Reference< XAccessible > xRet; |
| size_t nVecIdx = static_cast< size_t >( eBorder ); |
| if( IsBorderEnabled( eBorder ) && (1 <= nVecIdx) && (nVecIdx <= mxImpl->maChildVec.size()) ) |
| { |
| --nVecIdx; |
| if( !mxImpl->maChildVec[ nVecIdx ] ) |
| mxImpl->mxChildVec[ nVecIdx ] = mxImpl->maChildVec[ nVecIdx ] = |
| new a11y::AccFrameSelector( *this, eBorder ); |
| xRet = mxImpl->mxChildVec[ nVecIdx ]; |
| } |
| return xRet; |
| } |
| |
| Reference< XAccessible > FrameSelector::GetChildAccessible( sal_Int32 nIndex ) |
| { |
| return GetChildAccessible( GetEnabledBorderType( nIndex ) ); |
| } |
| |
| Reference< XAccessible > FrameSelector::GetChildAccessible( const Point& rPos ) |
| { |
| Reference< XAccessible > xRet; |
| for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !xRet.is() && aIt.Is(); ++aIt ) |
| if( (*aIt)->ContainsClickPoint( rPos ) ) |
| xRet = GetChildAccessible( (*aIt)->GetType() ); |
| return xRet; |
| } |
| |
| bool FrameSelector::ContainsClickPoint( const Point& rPos ) const |
| { |
| bool bContains = false; |
| for( FrameBorderCIter aIt( mxImpl->maEnabBorders ); !bContains && aIt.Is(); ++aIt ) |
| bContains = (*aIt)->ContainsClickPoint( rPos ); |
| return bContains; |
| } |
| |
| Rectangle FrameSelector::GetClickBoundRect( FrameBorderType eBorder ) const |
| { |
| Rectangle aRect; |
| const FrameBorder& rBorder = mxImpl->GetBorder( eBorder ); |
| if( rBorder.IsEnabled() ) |
| aRect = rBorder.GetClickBoundRect(); |
| return aRect; |
| } |
| |
| // virtual functions from base class ------------------------------------------ |
| |
| void FrameSelector::Paint( const Rectangle& ) |
| { |
| mxImpl->CopyVirDevToControl(); |
| if( HasFocus() ) |
| mxImpl->DrawAllTrackingRects(); |
| } |
| |
| void FrameSelector::MouseButtonDown( const MouseEvent& rMEvt ) |
| { |
| /* Mouse handling: |
| * Click on an unselected frame border: |
| Set current style/color, make frame border visible, deselect all |
| other frame borders. |
| * Click on a selected frame border: |
| Toggle state of the frame border (visible -> don't care -> hidden), |
| deselect all other frame borders. |
| * SHIFT+Click or CTRL+Click on an unselected frame border: |
| Extend selection, set current style/color to all selected frame |
| borders independent of the state/style/color of the borders. |
| * SHIFT+Click or CTRL+Click on a selected frame border: |
| If all frame borders have same style/color, toggle state of all |
| borders (see above), otherwise set current style/color to all |
| borders. |
| * Click on unused area: Do not modify selection and selected frame |
| borders. |
| */ |
| |
| // #107394# do not auto-select a frame border |
| mxImpl->SilentGrabFocus(); |
| |
| if( rMEvt.IsLeft() ) |
| { |
| Point aPos( mxImpl->GetDevPosFromMousePos( rMEvt.GetPosPixel() ) ); |
| FrameBorderPtrVec aDeselectBorders; |
| |
| bool bAnyClicked = false; // Any frame border clicked? |
| bool bNewSelected = false; // Any unselected frame border selected? |
| |
| /* If frame borders are set to "don't care" and the control does not |
| support this state, hide them on first mouse click. |
| DR 2004-01-30: Why are the borders set to "don't care" then?!? */ |
| bool bHideDontCare = !mxImpl->mbClicked && !SupportsDontCareState(); |
| |
| for( FrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| { |
| if( (*aIt)->ContainsClickPoint( aPos ) ) |
| { |
| // frame border is clicked |
| bAnyClicked = true; |
| if( !(*aIt)->IsSelected() ) |
| { |
| bNewSelected = true; |
| //mxImpl->SelectBorder( **aIt, true ); |
| SelectBorder((**aIt).GetType(), true); |
| } |
| } |
| else |
| { |
| // hide a "don't care" frame border only if it is not clicked |
| if( bHideDontCare && ((*aIt)->GetState() == FRAMESTATE_DONTCARE) ) |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_HIDE ); |
| |
| // deselect frame borders not clicked (if SHIFT or CTRL are not pressed) |
| if( !rMEvt.IsShift() && !rMEvt.IsMod1() ) |
| aDeselectBorders.push_back( *aIt ); |
| } |
| } |
| |
| if( bAnyClicked ) |
| { |
| // any valid frame border clicked? -> deselect other frame borders |
| for( FrameBorderIter aIt( aDeselectBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SelectBorder( **aIt, false ); |
| |
| if( bNewSelected || !mxImpl->SelectedBordersEqual() ) |
| { |
| // new frame border selected, selection extended, or selected borders different? -> show |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| // SetBorderState() sets current style and color to the frame border |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW ); |
| } |
| else |
| { |
| // all selected frame borders are equal -> toggle state |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->ToggleBorderState( **aIt ); |
| } |
| } |
| } |
| } |
| |
| void FrameSelector::KeyInput( const KeyEvent& rKEvt ) |
| { |
| bool bHandled = false; |
| KeyCode aKeyCode = rKEvt.GetKeyCode(); |
| if( !aKeyCode.GetModifier() ) |
| { |
| sal_uInt16 nCode = aKeyCode.GetCode(); |
| switch( nCode ) |
| { |
| case KEY_SPACE: |
| { |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->ToggleBorderState( **aIt ); |
| bHandled = true; |
| } |
| break; |
| |
| case KEY_UP: |
| case KEY_DOWN: |
| case KEY_LEFT: |
| case KEY_RIGHT: |
| { |
| if( !mxImpl->maEnabBorders.empty() ) |
| { |
| // start from first selected frame border |
| SelFrameBorderCIter aIt( mxImpl->maEnabBorders ); |
| FrameBorderType eBorder = aIt.Is() ? (*aIt)->GetType() : mxImpl->maEnabBorders.front()->GetType(); |
| |
| // search for next enabled frame border |
| do |
| { |
| eBorder = mxImpl->GetBorder( eBorder ).GetKeyboardNeighbor( nCode ); |
| } |
| while( (eBorder != FRAMEBORDER_NONE) && !IsBorderEnabled( eBorder ) ); |
| |
| // select the frame border |
| if( eBorder != FRAMEBORDER_NONE ) |
| { |
| DeselectAllBorders(); |
| SelectBorder( eBorder ); |
| } |
| } |
| } |
| break; |
| } |
| } |
| if( !bHandled ) |
| Window::KeyInput(rKEvt); |
| } |
| |
| void FrameSelector::GetFocus() |
| { |
| // auto-selection of a frame border, if focus reaches control, and nothing is selected |
| if( mxImpl->mbAutoSelect && !IsAnyBorderSelected() && !mxImpl->maEnabBorders.empty() ) |
| mxImpl->SelectBorder( *mxImpl->maEnabBorders.front(), true ); |
| |
| mxImpl->DoInvalidate( false ); |
| if( mxImpl->mxAccess.is() ) |
| mxImpl->mpAccess->NotifyFocusListeners( sal_True ); |
| if (IsAnyBorderSelected()) |
| { |
| FrameBorderType borderType = FRAMEBORDER_NONE; |
| if (mxImpl->maLeft.IsSelected()) |
| borderType = FRAMEBORDER_LEFT; |
| else if (mxImpl->maRight.IsSelected()) |
| borderType = FRAMEBORDER_RIGHT; |
| else if (mxImpl->maTop.IsSelected()) |
| borderType = FRAMEBORDER_TOP; |
| else if (mxImpl->maBottom.IsSelected()) |
| borderType = FRAMEBORDER_BOTTOM; |
| else if (mxImpl->maHor.IsSelected()) |
| borderType = FRAMEBORDER_HOR; |
| else if (mxImpl->maVer.IsSelected()) |
| borderType = FRAMEBORDER_VER; |
| else if (mxImpl->maTLBR.IsSelected()) |
| borderType = FRAMEBORDER_TLBR; |
| else if (mxImpl->maBLTR.IsSelected()) |
| borderType = FRAMEBORDER_BLTR; |
| SelectBorder(borderType); |
| } |
| for( SelFrameBorderIter aIt( mxImpl->maEnabBorders ); aIt.Is(); ++aIt ) |
| mxImpl->SetBorderState( **aIt, FRAMESTATE_SHOW ); |
| Control::GetFocus(); |
| } |
| |
| void FrameSelector::LoseFocus() |
| { |
| mxImpl->DoInvalidate( false ); |
| if( mxImpl->mxAccess.is() ) |
| mxImpl->mpAccess->NotifyFocusListeners( sal_False ); |
| Control::LoseFocus(); |
| } |
| |
| void FrameSelector::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Control::DataChanged( rDCEvt ); |
| if( (rDCEvt.GetType() == DATACHANGED_SETTINGS) && (rDCEvt.GetFlags() & SETTINGS_STYLE) ) |
| mxImpl->InitVirtualDevice(); |
| } |
| |
| // ============================================================================ |
| |
| template< typename Cont, typename Iter, typename Pred > |
| FrameBorderIterBase< Cont, Iter, Pred >::FrameBorderIterBase( container_type& rCont ) : |
| maIt( rCont.begin() ), |
| maEnd( rCont.end() ) |
| { |
| while( Is() && !maPred( *maIt ) ) ++maIt; |
| } |
| |
| template< typename Cont, typename Iter, typename Pred > |
| FrameBorderIterBase< Cont, Iter, Pred >& FrameBorderIterBase< Cont, Iter, Pred >::operator++() |
| { |
| do { ++maIt; } while( Is() && !maPred( *maIt ) ); |
| return *this; |
| } |
| |
| // ============================================================================ |
| |
| } // namespace svx |
| |