| /************************************************************** |
| * |
| * 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/svdhdl.hxx> |
| #include <svx/svdpagv.hxx> |
| #include <svx/svdetc.hxx> |
| #include <svx/svdmrkv.hxx> |
| #include <vcl/window.hxx> |
| #include <vcl/virdev.hxx> |
| #include <tools/poly.hxx> |
| #include <vcl/bmpacc.hxx> |
| #include <svx/sxekitm.hxx> |
| #include <svx/svdstr.hrc> |
| #include <svx/svdglob.hxx> |
| #include <svx/svdmodel.hxx> |
| #include "gradtrns.hxx" |
| #include <svx/xflgrit.hxx> |
| #include <svx/svdundo.hxx> |
| #include <svx/dialmgr.hxx> |
| #include <svx/xflftrit.hxx> |
| #include <svx/svdopath.hxx> |
| #include <basegfx/vector/b2dvector.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <svx/sdr/overlay/overlaymanager.hxx> |
| #include <svx/sdr/overlay/overlayanimatedbitmapex.hxx> |
| #include <svx/sdr/overlay/overlaybitmapex.hxx> |
| #include <svx/sdr/overlay/overlayline.hxx> |
| #include <svx/sdr/overlay/overlaytriangle.hxx> |
| #include <svx/sdr/overlay/overlayrectangle.hxx> |
| #include <svx/sdrpagewindow.hxx> |
| #include <svx/sdrpaintwindow.hxx> |
| #include <vcl/svapp.hxx> |
| #include <svx/sdr/overlay/overlaypolypolygon.hxx> |
| #include <vcl/lazydelete.hxx> |
| #include <svx/svdlegacy.hxx> |
| #include <algorithm> |
| |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> |
| #include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx> |
| #include <drawinglayer/primitive2d/graphicprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/maskprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> |
| #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // #i15222# |
| // Due to the ressource problems in Win95/98 with bitmap ressources i |
| // will change this handle bitmap provinging class. Old version was splitting |
| // and preparing all small handle bitmaps in device bitmap format, now this will |
| // be done on the fly. Thus, tehre is only the one big bitmap remembered. With |
| // three source bitmaps, this will be 3 system bitmap ressources instead of hundreds. |
| // The price for that needs to be evaluated. Maybe we will need another change here |
| // if this is too expensive. |
| class SdrHdlBitmapSet |
| { |
| // the bitmap holding all infos |
| BitmapEx maMarkersBitmap; |
| |
| // the cropped Bitmaps for reusage |
| ::std::vector< BitmapEx > maRealMarkers; |
| |
| // elpers |
| BitmapEx& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle); |
| |
| public: |
| SdrHdlBitmapSet(sal_uInt16 nResId); |
| ~SdrHdlBitmapSet(); |
| |
| const BitmapEx& GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd=0); |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| #define KIND_COUNT (14) |
| #define INDEX_COUNT (6) |
| #define INDIVIDUAL_COUNT (4) |
| |
| SdrHdlBitmapSet::SdrHdlBitmapSet(sal_uInt16 nResId) |
| : maMarkersBitmap(ResId(nResId, *ImpGetResMgr())), // just use ressource with alpha channel |
| // 14 kinds (BitmapMarkerKind) use index [0..5], 4 extra |
| maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT) |
| { |
| } |
| |
| SdrHdlBitmapSet::~SdrHdlBitmapSet() |
| { |
| } |
| |
| BitmapEx& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const Rectangle& rRectangle) |
| { |
| BitmapEx& rTargetBitmap = maRealMarkers[nIndex]; |
| |
| if(rTargetBitmap.IsEmpty()) |
| { |
| rTargetBitmap = maMarkersBitmap; |
| rTargetBitmap.Crop(rRectangle); |
| } |
| |
| return rTargetBitmap; |
| } |
| |
| // change getting of bitmap to use the big ressource bitmap |
| const BitmapEx& SdrHdlBitmapSet::GetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd) |
| { |
| // fill in size and source position in maMarkersBitmap |
| const sal_uInt16 nYPos(nInd * 11); |
| |
| switch(eKindOfMarker) |
| { |
| default: |
| { |
| DBG_ERROR( "unknown kind of marker" ); |
| // no break here, return Rect_7x7 as default |
| } |
| case Rect_7x7: |
| { |
| return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, Rectangle(Point(0, nYPos), Size(7, 7))); |
| } |
| |
| case Rect_9x9: |
| { |
| return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, Rectangle(Point(7, nYPos), Size(9, 9))); |
| } |
| |
| case Rect_11x11: |
| { |
| return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, Rectangle(Point(16, nYPos), Size(11, 11))); |
| } |
| |
| case Rect_13x13: |
| { |
| const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd); |
| |
| switch(nInd) |
| { |
| case 0: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 66), Size(13, 13))); |
| } |
| case 1: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 66), Size(13, 13))); |
| } |
| case 2: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(72, 79), Size(13, 13))); |
| } |
| case 3: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(85, 79), Size(13, 13))); |
| } |
| case 4: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 79), Size(13, 13))); |
| } |
| default: // case 5: |
| { |
| return impGetOrCreateTargetBitmap(nIndex, Rectangle(Point(98, 66), Size(13, 13))); |
| } |
| } |
| } |
| |
| case Circ_7x7: |
| case Customshape_7x7: |
| { |
| return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, Rectangle(Point(27, nYPos), Size(7, 7))); |
| } |
| |
| case Circ_9x9: |
| case Customshape_9x9: |
| { |
| return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, Rectangle(Point(34, nYPos), Size(9, 9))); |
| } |
| |
| case Circ_11x11: |
| case Customshape_11x11: |
| { |
| return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, Rectangle(Point(43, nYPos), Size(11, 11))); |
| } |
| |
| case Elli_7x9: |
| { |
| return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, Rectangle(Point(54, nYPos), Size(7, 9))); |
| } |
| |
| case Elli_9x11: |
| { |
| return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, Rectangle(Point(61, nYPos), Size(9, 11))); |
| } |
| |
| case Elli_9x7: |
| { |
| return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, Rectangle(Point(70, nYPos), Size(9, 7))); |
| } |
| |
| case Elli_11x9: |
| { |
| return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, Rectangle(Point(79, nYPos), Size(11, 9))); |
| } |
| |
| case RectPlus_7x7: |
| { |
| return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, Rectangle(Point(90, nYPos), Size(7, 7))); |
| } |
| |
| case RectPlus_9x9: |
| { |
| return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, Rectangle(Point(97, nYPos), Size(9, 9))); |
| } |
| |
| case RectPlus_11x11: |
| { |
| return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, Rectangle(Point(106, nYPos), Size(11, 11))); |
| } |
| |
| case Crosshair: |
| { |
| return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, Rectangle(Point(0, 68), Size(15, 15))); |
| } |
| |
| case Glue: |
| { |
| return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, Rectangle(Point(15, 74), Size(9, 9))); |
| } |
| |
| case Anchor: // #101688# AnchorTR for SW |
| case AnchorTR: |
| { |
| return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, Rectangle(Point(24, 68), Size(24, 24))); |
| } |
| |
| // #98388# add AnchorPressed to be able to aninate anchor control |
| case AnchorPressed: |
| case AnchorPressedTR: |
| { |
| return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, Rectangle(Point(48, 68), Size(24, 24))); |
| } |
| } |
| |
| // cannot happen since all paths return something; return Rect_7x7 as default (see switch) |
| return maRealMarkers[0]; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SdrHdlBitmapSet& getSimpleSet() |
| { |
| static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aSimpleSet(new SdrHdlBitmapSet(SIP_SA_MARKERS)); |
| return *aSimpleSet.get(); |
| } |
| |
| SdrHdlBitmapSet& getModernSet() |
| { |
| static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet(new SdrHdlBitmapSet(SIP_SA_FINE_MARKERS)); |
| return *aModernSet.get(); |
| } |
| |
| SdrHdlBitmapSet& getHighContrastSet() |
| { |
| static vcl::DeleteOnDeinit< SdrHdlBitmapSet > aHighContrastSet(new SdrHdlBitmapSet(SIP_SA_ACCESSIBILITY_MARKERS)); |
| return *aHighContrastSet.get(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SdrHdl::SdrHdl( |
| SdrHdlList& rHdlList, |
| const SdrObject* pSdrHdlObject, |
| SdrHdlKind eNewKind, |
| const basegfx::B2DPoint& rPosition, |
| bool bIsFrameHandle) |
| : boost::noncopyable(), |
| mrHdlList(rHdlList), |
| mpSdrHdlObject(pSdrHdlObject), |
| meKind(eNewKind), |
| maPosition(rPosition), |
| maOverlayGroup(), |
| mnObjHdlNum(0), |
| mnPolyNum(0), |
| mnPPntNum(0), |
| mnSourceHdlNum(0), |
| mbSelect(false), |
| mb1PixMore(false), |
| mbPlusHdl(false), |
| mbIsFrameHandle(bIsFrameHandle), |
| mbMoveOutside(false), |
| mbMouseOver(false) |
| { |
| // add to owning list |
| mrHdlList.maList.push_back(this); |
| } |
| |
| SdrHdl::~SdrHdl() |
| { |
| GetRidOfIAObject(); |
| OSL_ENSURE(!mrHdlList.maList.size(), "SdrHdl deleted from someone else than SdrHdlList (!)"); |
| } |
| |
| void SdrHdl::Set1PixMore(bool bJa) |
| { |
| if(mb1PixMore != bJa) |
| { |
| mb1PixMore = bJa; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| void SdrHdl::SetMoveOutside( bool bMoveOutside ) |
| { |
| if(mbMoveOutside != bMoveOutside) |
| { |
| mbMoveOutside = bMoveOutside; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| const basegfx::B2DPoint& SdrHdl::getPosition() const |
| { |
| return maPosition; |
| } |
| |
| void SdrHdl::setPosition(const basegfx::B2DPoint& rNew) |
| { |
| if(maPosition != rNew) |
| { |
| // remember new position |
| maPosition = rNew; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| void SdrHdl::SetSelected(bool bJa) |
| { |
| if(mbSelect != bJa) |
| { |
| // remember new value |
| mbSelect = bJa; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| void SdrHdl::Touch() |
| { |
| // force update of graphic representation, but only when not empty. When |
| // it is empty, the finishing call to CreateVisualizations() is not yet |
| // done but can be expected. If not empty, attributes are changed outside |
| // handle creation (SdrMarkView::RecreateAllMarkHandles()), e.g. blinking or MouseOver |
| if(!getOverlayObjectList().isEmpty()) |
| { |
| CreateB2dIAObject(); |
| } |
| } |
| |
| void SdrHdl::GetRidOfIAObject() |
| { |
| // OVERLAYMANAGER |
| maOverlayGroup.clear(); |
| } |
| |
| void SdrHdl::CreateB2dIAObject() |
| { |
| // first throw away old one |
| GetRidOfIAObject(); |
| |
| SdrPageView* pPageView = mrHdlList.GetViewFromSdrHdlList().GetSdrPageView(); |
| |
| if(pPageView) |
| { |
| for(sal_uInt32 a(0); a < pPageView->PageWindowCount(); a++) |
| { |
| const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(a); |
| |
| if(rPageWindow.GetPaintWindow().OutputToWindow()) |
| { |
| ::sdr::overlay::OverlayManager* pOverlayManager = rPageWindow.GetOverlayManager(); |
| |
| if(pOverlayManager) |
| { |
| CreateB2dIAObject(*pOverlayManager); |
| } |
| } |
| } |
| } |
| } |
| |
| void SdrHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| BitmapColorIndex eColIndex = LightGreen; |
| BitmapMarkerKind eKindOfMarker = Rect_7x7; |
| bool bRot = mrHdlList.IsRotateShear(); |
| |
| if(!IsFrameHandle()) |
| { |
| eColIndex = (mbSelect) ? Cyan : LightCyan; |
| } |
| else if(bRot) |
| { |
| // Drehhandles in Rot |
| eColIndex = (mbSelect) ? Red : LightRed; |
| } |
| |
| switch(meKind) |
| { |
| case HDL_MOVE: |
| { |
| eKindOfMarker = (mb1PixMore) ? Rect_9x9 : Rect_7x7; |
| break; |
| } |
| case HDL_UPLFT: |
| case HDL_UPRGT: |
| case HDL_LWLFT: |
| case HDL_LWRGT: |
| { |
| // corner handles |
| if(bRot) |
| { |
| eKindOfMarker = Circ_7x7; |
| } |
| else |
| { |
| eKindOfMarker = Rect_7x7; |
| } |
| break; |
| } |
| case HDL_UPPER: |
| case HDL_LOWER: |
| { |
| // Upper/Lower handles |
| if(bRot) |
| { |
| eKindOfMarker = Elli_9x7; |
| } |
| else |
| { |
| eKindOfMarker = Rect_7x7; |
| } |
| break; |
| } |
| case HDL_LEFT: |
| case HDL_RIGHT: |
| { |
| // Left/Right handles |
| if(bRot) |
| { |
| eKindOfMarker = Elli_7x9; |
| } |
| else |
| { |
| eKindOfMarker = Rect_7x7; |
| } |
| break; |
| } |
| case HDL_POLY: |
| { |
| if(bRot) |
| { |
| eKindOfMarker = (mb1PixMore) ? Circ_9x9 : Circ_7x7; |
| } |
| else |
| { |
| eKindOfMarker = (mb1PixMore) ? Rect_9x9 : Rect_7x7; |
| break; |
| } |
| break; |
| } |
| case HDL_BWGT: // weight at poly |
| { |
| eKindOfMarker = Circ_7x7; |
| break; |
| } |
| case HDL_CIRC: |
| { |
| eKindOfMarker = Rect_11x11; |
| break; |
| } |
| case HDL_REF1: |
| case HDL_REF2: |
| { |
| eKindOfMarker = Crosshair; |
| break; |
| } |
| case HDL_GLUE: |
| { |
| eKindOfMarker = Glue; |
| break; |
| } |
| case HDL_ANCHOR: |
| { |
| eKindOfMarker = Anchor; |
| break; |
| } |
| case HDL_USER: |
| { |
| break; |
| } |
| // #101688# top right anchor for SW |
| case HDL_ANCHOR_TR: |
| { |
| eKindOfMarker = AnchorTR; |
| break; |
| } |
| |
| // for SJ and the CustomShapeHandles: |
| case HDL_CUSTOMSHAPE1: |
| { |
| eKindOfMarker = (mb1PixMore) ? Customshape_9x9 : Customshape_7x7; |
| eColIndex = Yellow; |
| break; |
| } |
| default: |
| break; |
| } |
| |
| sal_Int16 nMoveOutsideX(0); |
| sal_Int16 nMoveOutsideY(0); |
| |
| // add offset if necessary |
| if(mrHdlList.IsMoveOutside() || mbMoveOutside) |
| { |
| const basegfx::B2DVector aOffset(rOverlayManager.getOutputDevice().GetInverseViewTransformation() * basegfx::B2DVector(4.0, 4.0)); |
| |
| if(meKind == HDL_UPLFT || meKind == HDL_UPPER || meKind == HDL_UPRGT) |
| { |
| nMoveOutsideY = -1; |
| } |
| |
| if(meKind == HDL_LWLFT || meKind == HDL_LOWER || meKind == HDL_LWRGT) |
| { |
| nMoveOutsideY = 1; |
| } |
| |
| if(meKind == HDL_UPLFT || meKind == HDL_LEFT || meKind == HDL_LWLFT) |
| { |
| nMoveOutsideX = -1; |
| } |
| |
| if(meKind == HDL_UPRGT || meKind == HDL_RIGHT || meKind == HDL_LWRGT) |
| { |
| nMoveOutsideX = 1; |
| } |
| } |
| |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( |
| maPosition, |
| eColIndex, |
| eKindOfMarker, |
| nMoveOutsideX, |
| nMoveOutsideY); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd) const |
| { |
| BitmapMarkerKind eRetval(eKnd); |
| |
| switch(eKnd) |
| { |
| case Rect_7x7: eRetval = Rect_9x9; break; |
| case Rect_9x9: eRetval = Rect_11x11; break; |
| case Rect_11x11: eRetval = Rect_13x13; break; |
| //case Rect_13x13: eRetval = ; break; |
| |
| case Circ_7x7: eRetval = Circ_9x9; break; |
| case Circ_9x9: eRetval = Circ_11x11; break; |
| //case Circ_11x11: eRetval = ; break; |
| |
| case Customshape_7x7: eRetval = Customshape_9x9; break; |
| case Customshape_9x9: eRetval = Customshape_11x11; break; |
| //case Customshape_11x11: eRetval = ; break; |
| |
| case Elli_7x9: eRetval = Elli_9x11; break; |
| //case Elli_9x11: eRetval = ; break; |
| |
| case Elli_9x7: eRetval = Elli_11x9; break; |
| //case Elli_11x9: eRetval = ; break; |
| |
| case RectPlus_7x7: eRetval = RectPlus_9x9; break; |
| case RectPlus_9x9: eRetval = RectPlus_11x11; break; |
| //case RectPlus_11x11: eRetval = ; break; |
| |
| //case Crosshair: eRetval = ; break; |
| //case Glue: eRetval = ; break; |
| |
| // #98388# let anchor blink with it's pressed state |
| case Anchor: eRetval = AnchorPressed; break; |
| |
| // #101688# same for AnchorTR |
| case AnchorTR: eRetval = AnchorPressedTR; break; |
| default: |
| break; |
| } |
| |
| return eRetval; |
| } |
| |
| // #101928# |
| BitmapEx SdrHdl::ImpGetBitmapEx(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd, bool bFine, bool bIsHighContrast) |
| { |
| if(bIsHighContrast) |
| { |
| return getHighContrastSet().GetBitmapEx(eKindOfMarker, nInd); |
| } |
| else |
| { |
| if(bFine) |
| { |
| return getModernSet().GetBitmapEx(eKindOfMarker, nInd); |
| } |
| else |
| { |
| return getSimpleSet().GetBitmapEx(eKindOfMarker, nInd); |
| } |
| } |
| } |
| |
| ::sdr::overlay::OverlayObject* SdrHdl::CreateOverlayObject( |
| const basegfx::B2DPoint& rPos, |
| BitmapColorIndex eColIndex, |
| BitmapMarkerKind eKindOfMarker, |
| sal_Int16 nMoveOutsideX, |
| sal_Int16 nMoveOutsideY) |
| { |
| ::sdr::overlay::OverlayObject* pRetval = 0L; |
| bool bIsFineHdl(mrHdlList.IsFineHdl()); |
| const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
| bool bIsHighContrast(rStyleSettings.GetHighContrastMode()); |
| |
| // support bigger sizes |
| bool bForceBiggerSize(false); |
| |
| if(mrHdlList.GetHdlSize() > 3) |
| { |
| switch(eKindOfMarker) |
| { |
| case Anchor: |
| case AnchorPressed: |
| case AnchorTR: |
| case AnchorPressedTR: |
| { |
| // #121463# For anchor, do not simply make bigger because of HdlSize, |
| // do it dependent of IsSelected() which Writer can set in drag mode |
| if(IsSelected()) |
| { |
| bForceBiggerSize = true; |
| } |
| break; |
| } |
| default: |
| { |
| bForceBiggerSize = true; |
| break; |
| } |
| } |
| } |
| |
| // #101928# ...for high contrast, too. |
| if(!bForceBiggerSize && bIsHighContrast) |
| { |
| // #107925# |
| // ...but not for anchors, else they will not blink when activated |
| if(Anchor != eKindOfMarker && AnchorTR != eKindOfMarker) |
| { |
| bForceBiggerSize = true; |
| } |
| } |
| |
| if(bForceBiggerSize) |
| { |
| eKindOfMarker = GetNextBigger(eKindOfMarker); |
| } |
| |
| // #97016# II This handle has the focus, visualize it |
| if(IsFocusHdl() && mrHdlList.GetFocusHdl() == this) |
| { |
| // create animated handle |
| BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker); |
| |
| if(eNextBigger == eKindOfMarker) |
| { |
| // this may happen for the not supported getting-bigger types. |
| // Choose an alternative here |
| switch(eKindOfMarker) |
| { |
| case Rect_13x13: eNextBigger = Rect_11x11; break; |
| case Circ_11x11: eNextBigger = Elli_11x9; break; |
| case Elli_9x11: eNextBigger = Elli_11x9; break; |
| case Elli_11x9: eNextBigger = Elli_9x11; break; |
| case RectPlus_11x11: eNextBigger = Rect_13x13; break; |
| |
| case Crosshair: |
| eNextBigger = Glue; |
| break; |
| |
| case Glue: |
| eNextBigger = Crosshair; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| // create animated hdl |
| // #101928# use ImpGetBitmapEx(...) now |
| BitmapEx aBmpEx1 = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); |
| BitmapEx aBmpEx2 = ImpGetBitmapEx(eNextBigger, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); |
| |
| // #i53216# Use system cursor blink time. Use the unsigned value. |
| const sal_uInt32 nBlinkTime((sal_uInt32)Application::GetSettings().GetStyleSettings().GetCursorBlinkTime()); |
| |
| if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed) |
| { |
| // #98388# when anchor is used take upper left as reference point inside the handle |
| pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime); |
| } |
| else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR) |
| { |
| // #101688# AnchorTR for SW, take top right as (0,0) |
| pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1), 0, |
| (sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1), 0); |
| } |
| else |
| { |
| // create centered handle as default |
| pRetval = new ::sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmpEx1, aBmpEx2, nBlinkTime, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, |
| (sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1); |
| } |
| } |
| else |
| { |
| // create normal handle |
| // #101928# use ImpGetBitmapEx(...) now |
| BitmapEx aBmpEx = ImpGetBitmapEx(eKindOfMarker, (sal_uInt16)eColIndex, bIsFineHdl, bIsHighContrast); |
| |
| if(eKindOfMarker == Anchor || eKindOfMarker == AnchorPressed) |
| { |
| // #98388# upper left as reference point inside the handle for AnchorPressed, too |
| pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx); |
| } |
| else if(eKindOfMarker == AnchorTR || eKindOfMarker == AnchorPressedTR) |
| { |
| // #101688# AnchorTR for SW, take top right as (0,0) |
| pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, |
| (sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1), 0); |
| } |
| else |
| { |
| sal_uInt16 nCenX((sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1L) >> 1); |
| sal_uInt16 nCenY((sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1L) >> 1); |
| |
| if(nMoveOutsideX > 0) |
| { |
| nCenX = 0; |
| } |
| else if(nMoveOutsideX < 0) |
| { |
| nCenX = (sal_uInt16)(aBmpEx.GetSizePixel().Width() - 1); |
| } |
| |
| if(nMoveOutsideY > 0) |
| { |
| nCenY = 0; |
| } |
| else if(nMoveOutsideY < 0) |
| { |
| nCenY = (sal_uInt16)(aBmpEx.GetSizePixel().Height() - 1); |
| } |
| |
| // create centered handle as default |
| pRetval = new ::sdr::overlay::OverlayBitmapEx(rPos, aBmpEx, nCenX, nCenY); |
| } |
| } |
| |
| return pRetval; |
| } |
| |
| bool SdrHdl::IsHdlHit(const basegfx::B2DPoint& rPosition) const |
| { |
| // OVERLAYMANAGER |
| return maOverlayGroup.isHitLogic(rPosition); |
| } |
| |
| Pointer SdrHdl::GetPointer() const |
| { |
| PointerStyle ePtr=POINTER_MOVE; |
| const bool bSize=meKind>=HDL_UPLFT && meKind<=HDL_LWRGT; |
| const bool bRot=mrHdlList.IsRotateShear(); |
| const bool bDis=mrHdlList.IsDistortShear(); |
| if (bSize && (bRot || bDis)) { |
| switch (meKind) { |
| case HDL_UPLFT: case HDL_UPRGT: |
| case HDL_LWLFT: case HDL_LWRGT: ePtr=bRot ? POINTER_ROTATE : POINTER_REFHAND; break; |
| case HDL_LEFT : case HDL_RIGHT: ePtr=POINTER_VSHEAR; break; |
| case HDL_UPPER: case HDL_LOWER: ePtr=POINTER_HSHEAR; break; |
| default: |
| break; |
| } |
| } |
| else |
| { |
| // Fuer Resize von gedrehten Rechtecken die Mauszeiger etwas mitdrehen |
| bool bDone(false); |
| |
| if(bSize && mpSdrHdlObject) |
| { |
| const sal_Int32 aOldRot(sdr::legacy::GetRotateAngle(*mpSdrHdlObject)); |
| |
| if(aOldRot) |
| { |
| sal_Int32 nHdlWink(0); |
| |
| switch (meKind) |
| { |
| case HDL_LWRGT: nHdlWink=31500; break; |
| case HDL_LOWER: nHdlWink=27000; break; |
| case HDL_LWLFT: nHdlWink=22500; break; |
| case HDL_LEFT : nHdlWink=18000; break; |
| case HDL_UPLFT: nHdlWink=13500; break; |
| case HDL_UPPER: nHdlWink=9000; break; |
| case HDL_UPRGT: nHdlWink=4500; break; |
| case HDL_RIGHT: nHdlWink=0; break; |
| default: |
| break; |
| } |
| |
| nHdlWink += aOldRot + 2249; |
| |
| while(nHdlWink < 0) |
| { |
| nHdlWink += 36000; |
| } |
| |
| while(nHdlWink >= 36000) |
| { |
| nHdlWink -= 36000; |
| } |
| |
| nHdlWink/=4500; |
| |
| switch ((sal_uInt8)nHdlWink) |
| { |
| case 0: ePtr=POINTER_ESIZE; break; |
| case 1: ePtr=POINTER_NESIZE; break; |
| case 2: ePtr=POINTER_NSIZE; break; |
| case 3: ePtr=POINTER_NWSIZE; break; |
| case 4: ePtr=POINTER_WSIZE; break; |
| case 5: ePtr=POINTER_SWSIZE; break; |
| case 6: ePtr=POINTER_SSIZE; break; |
| case 7: ePtr=POINTER_SESIZE; break; |
| } |
| |
| bDone = true; |
| } |
| } |
| |
| if(!bDone) |
| { |
| switch (meKind) |
| { |
| case HDL_UPLFT: ePtr=POINTER_NWSIZE; break; |
| case HDL_UPPER: ePtr=POINTER_NSIZE; break; |
| case HDL_UPRGT: ePtr=POINTER_NESIZE; break; |
| case HDL_LEFT : ePtr=POINTER_WSIZE; break; |
| case HDL_RIGHT: ePtr=POINTER_ESIZE; break; |
| case HDL_LWLFT: ePtr=POINTER_SWSIZE; break; |
| case HDL_LOWER: ePtr=POINTER_SSIZE; break; |
| case HDL_LWRGT: ePtr=POINTER_SESIZE; break; |
| case HDL_POLY : ePtr=POINTER_MOVEPOINT; break; |
| case HDL_CIRC : ePtr=POINTER_HAND; break; |
| case HDL_REF1 : ePtr=POINTER_REFHAND; break; |
| case HDL_REF2 : ePtr=POINTER_REFHAND; break; |
| case HDL_BWGT : ePtr=POINTER_MOVEBEZIERWEIGHT; break; |
| case HDL_GLUE : ePtr=POINTER_MOVEPOINT; break; |
| case HDL_CUSTOMSHAPE1 : ePtr=POINTER_HAND; break; |
| default: |
| break; |
| } |
| } |
| } |
| return Pointer(ePtr); |
| } |
| |
| // #97016# II |
| bool SdrHdl::IsFocusHdl() const |
| { |
| switch(meKind) |
| { |
| case HDL_UPLFT: // Oben links |
| case HDL_UPPER: // Oben |
| case HDL_UPRGT: // Oben rechts |
| case HDL_LEFT: // Links |
| case HDL_RIGHT: // Rechts |
| case HDL_LWLFT: // Unten links |
| case HDL_LOWER: // Unten |
| case HDL_LWRGT: // Unten rechts |
| { |
| // if it's a activated TextEdit, it's moved to extended points |
| if(mrHdlList.IsMoveOutside()) |
| return sal_False; |
| else |
| return sal_True; |
| } |
| |
| case HDL_MOVE: // Handle zum Verschieben des Objekts |
| case HDL_POLY: // Punktselektion an Polygon oder Bezierkurve |
| case HDL_BWGT: // Gewicht an einer Bezierkurve |
| case HDL_CIRC: // Winkel an Kreissegmenten, Eckenradius am Rect |
| case HDL_REF1: // Referenzpunkt 1, z.B. Rotationsmitte |
| case HDL_REF2: // Referenzpunkt 2, z.B. Endpunkt der Spiegelachse |
| //case HDL_MIRX: // Die Spiegelachse selbst |
| case HDL_GLUE: // GluePoint |
| |
| // #98388# do NOT activate here, let SW implement their own SdrHdl and |
| // overload IsFocusHdl() there to make the anchor accessible |
| //case HDL_ANCHOR: // anchor symbol (SD, SW) |
| // #101688# same for AnchorTR |
| //case HDL_ANCHOR_TR: // anchor symbol (SD, SW) |
| |
| //case HDL_TRNS: // interactive transparence |
| //case HDL_GRAD: // interactive gradient |
| //case HDL_COLR: // interactive color |
| |
| // for SJ and the CustomShapeHandles: |
| case HDL_CUSTOMSHAPE1: |
| |
| case HDL_USER: |
| { |
| return sal_True; |
| } |
| |
| default: |
| { |
| return sal_False; |
| } |
| } |
| } |
| |
| void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/) |
| { |
| } |
| |
| void SdrHdl::onMouseLeave() |
| { |
| } |
| |
| bool SdrHdl::isMouseOver() const |
| { |
| return mbMouseOver; |
| } |
| |
| void SdrHdl::setMouseOver(bool bNew) |
| { |
| if(mbMouseOver != bNew) |
| { |
| // remember new value |
| mbMouseOver = bNew; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // #105678# Help struct for re-sorting handles |
| |
| struct ImplHdlAndIndex |
| { |
| SdrHdl* mpHdl; |
| sal_uInt32 mnIndex; |
| }; |
| |
| // #105678# Help method for sorting handles taking care of OrdNums, keeping order in |
| // single objects and re-sorting polygon handles intuitively |
| extern "C" int __LOADONCALLAPI ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 ) |
| { |
| const ImplHdlAndIndex* p1 = (ImplHdlAndIndex*)pVoid1; |
| const ImplHdlAndIndex* p2 = (ImplHdlAndIndex*)pVoid2; |
| |
| if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj()) |
| { |
| const SdrPathObj* pSdrPathObj = dynamic_cast< const SdrPathObj* >(p1->mpHdl->GetObj()); |
| |
| if(pSdrPathObj) |
| { |
| // same object and a path object |
| if((p1->mpHdl->GetKind() == HDL_POLY || p1->mpHdl->GetKind() == HDL_BWGT) |
| && (p2->mpHdl->GetKind() == HDL_POLY || p2->mpHdl->GetKind() == HDL_BWGT)) |
| { |
| // both handles are point or control handles |
| if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum()) |
| { |
| if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum()) |
| { |
| return -1; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum()) |
| { |
| return -1; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| } |
| } |
| else |
| { |
| if(!p1->mpHdl->GetObj()) |
| { |
| return -1; |
| } |
| else if(!p2->mpHdl->GetObj()) |
| { |
| return 1; |
| } |
| else |
| { |
| // different objects, use OrdNum for sort |
| const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetNavigationPosition(); |
| const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetNavigationPosition(); |
| |
| if(nOrdNum1 < nOrdNum2) |
| { |
| return -1; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| } |
| |
| // fallback to indices |
| if(p1->mnIndex < p2->mnIndex) |
| { |
| return -1; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SdrHdlList::SdrHdlList(SdrMarkView& rV) |
| : boost::noncopyable(), |
| mnFocusIndex(CONTAINER_ENTRY_NOTFOUND), |
| mrView(rV), |
| maList(), |
| mnHdlSize(3), |
| mbRotateShear(false), |
| mbDistortShear(false), |
| mbMoveOutside(false), |
| mbFineHandles(false) |
| { |
| } |
| |
| SdrHdlList::~SdrHdlList() |
| { |
| Clear(); |
| } |
| |
| void SdrHdlList::CreateVisualizations() |
| { |
| for(sal_uInt32 a(0); a < maList.size(); a++) |
| { |
| maList[a]->CreateB2dIAObject(); |
| } |
| } |
| |
| SdrHdl* SdrHdlList::GetHdlByIndex(sal_uInt32 nNum) const |
| { |
| if(nNum < maList.size()) |
| { |
| return *(maList.begin() + nNum); |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| |
| void SdrHdlList::TravelFocusHdl(bool bForward) |
| { |
| // security correction |
| if(CONTAINER_ENTRY_NOTFOUND != mnFocusIndex && mnFocusIndex >= GetHdlCount()) |
| { |
| mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; |
| } |
| |
| if(GetHdlCount()) |
| { |
| // take care of old handle |
| const sal_uInt32 nOldHdlNum(mnFocusIndex); |
| SdrHdl* pOld = CONTAINER_ENTRY_NOTFOUND != nOldHdlNum ? GetHdlByIndex(nOldHdlNum) : 0; |
| |
| if(pOld) |
| { |
| // switch off old handle |
| mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; |
| pOld->Touch(); |
| } |
| |
| // #105678# Alloc pointer array for sorted handle list |
| ImplHdlAndIndex* pHdlAndIndex = new ImplHdlAndIndex[GetHdlCount()]; |
| |
| // #105678# build sorted handle list |
| sal_uInt32 a(0); |
| |
| for(a = 0; a < GetHdlCount(); a++) |
| { |
| pHdlAndIndex[a].mpHdl = GetHdlByIndex(a); |
| pHdlAndIndex[a].mnIndex = a; |
| } |
| |
| // #105678# qsort all entries |
| qsort(pHdlAndIndex, GetHdlCount(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc); |
| |
| // #105678# look for old num in sorted array |
| sal_uInt32 nOldHdl(nOldHdlNum); |
| |
| if(nOldHdlNum != CONTAINER_ENTRY_NOTFOUND) |
| { |
| for(a = 0; a < GetHdlCount(); a++) |
| { |
| if(pHdlAndIndex[a].mpHdl == pOld) |
| { |
| nOldHdl = a; |
| break; |
| } |
| } |
| } |
| |
| // #105678# build new HdlNum |
| sal_uInt32 nNewHdl(nOldHdl); |
| |
| // #105678# do the focus travel |
| if(bForward) |
| { |
| if(nOldHdl != CONTAINER_ENTRY_NOTFOUND) |
| { |
| if(nOldHdl == GetHdlCount() - 1) |
| { |
| // end forward run |
| nNewHdl = CONTAINER_ENTRY_NOTFOUND; |
| } |
| else |
| { |
| // simply the next handle |
| nNewHdl++; |
| } |
| } |
| else |
| { |
| // start forward run at first entry |
| nNewHdl = 0; |
| } |
| } |
| else |
| { |
| if(nOldHdl == CONTAINER_ENTRY_NOTFOUND) |
| { |
| // start backward run at last entry |
| nNewHdl = GetHdlCount() - 1; |
| |
| } |
| else |
| { |
| if(nOldHdl == 0) |
| { |
| // end backward run |
| nNewHdl = CONTAINER_ENTRY_NOTFOUND; |
| } |
| else |
| { |
| // simply the previous handle |
| nNewHdl--; |
| } |
| } |
| } |
| |
| // #105678# build new HdlNum |
| sal_uInt32 nNewHdlNum(nNewHdl); |
| |
| // look for old num in sorted array |
| if(nNewHdl != CONTAINER_ENTRY_NOTFOUND) |
| { |
| SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl; |
| |
| for(a = 0; a < GetHdlCount(); a++) |
| { |
| if(GetHdlByIndex(a) == pNew) |
| { |
| nNewHdlNum = a; |
| break; |
| } |
| } |
| } |
| |
| // take care of next handle |
| if(nOldHdlNum != nNewHdlNum) |
| { |
| mnFocusIndex = nNewHdlNum; |
| SdrHdl* pNew = GetHdlByIndex(mnFocusIndex); |
| |
| if(pNew) |
| { |
| pNew->Touch(); |
| } |
| } |
| |
| // #105678# free mem again |
| delete [] pHdlAndIndex; |
| } |
| } |
| |
| SdrHdl* SdrHdlList::GetFocusHdl() const |
| { |
| if(CONTAINER_ENTRY_NOTFOUND != mnFocusIndex && mnFocusIndex < GetHdlCount()) |
| { |
| return GetHdlByIndex(mnFocusIndex); |
| } |
| else |
| { |
| return 0; |
| } |
| } |
| |
| void SdrHdlList::SetFocusHdl(SdrHdl* pNew) |
| { |
| if(pNew) |
| { |
| SdrHdl* pActual = GetFocusHdl(); |
| |
| if(!pActual || pActual != pNew) |
| { |
| const sal_uInt32 nNewHdlNum(GetHdlNum(pNew)); |
| |
| if(CONTAINER_ENTRY_NOTFOUND != nNewHdlNum) |
| { |
| mnFocusIndex = nNewHdlNum; |
| |
| if(pActual) |
| { |
| pActual->Touch(); |
| } |
| |
| if(pNew) |
| { |
| pNew->Touch(); |
| } |
| } |
| } |
| } |
| } |
| |
| void SdrHdlList::ResetFocusHdl() |
| { |
| SdrHdl* pHdl = GetFocusHdl(); |
| |
| mnFocusIndex = CONTAINER_ENTRY_NOTFOUND; |
| |
| if(pHdl) |
| { |
| pHdl->Touch(); |
| } |
| } |
| |
| void SdrHdlList::SetHdlSize(sal_uInt16 nSiz) |
| { |
| if(GetHdlSize() != nSiz) |
| { |
| // remember new value |
| mnHdlSize = nSiz; |
| |
| // propagate change to IAOs |
| for(sal_uInt32 i(0); i < GetHdlCount(); i++) |
| { |
| SdrHdl* pHdl = GetHdlByIndex(i); |
| pHdl->Touch(); |
| } |
| } |
| } |
| |
| void SdrHdlList::SetMoveOutside(bool bOn) |
| { |
| if(mbMoveOutside != bOn) |
| { |
| // remember new value |
| mbMoveOutside = bOn; |
| |
| // propagate change to IAOs |
| for(sal_uInt32 i(0); i < GetHdlCount(); i++) |
| { |
| SdrHdl* pHdl = GetHdlByIndex(i); |
| pHdl->Touch(); |
| } |
| } |
| } |
| |
| void SdrHdlList::SetFineHdl(bool bOn) |
| { |
| if(mbFineHandles != bOn) |
| { |
| // remember new state |
| mbFineHandles = bOn; |
| |
| // propagate change to IAOs |
| for(sal_uInt32 i(0); i < GetHdlCount(); i++) |
| { |
| SdrHdl* pHdl = GetHdlByIndex(i); |
| pHdl->Touch(); |
| } |
| } |
| } |
| |
| void SdrHdlList::Clear() |
| { |
| // keep a copy ad clear early to avoid that the delete calls |
| // for the SdrHdl have to iterate over the list to remove themselves |
| const SdrHdlContainerType aCopy(maList); |
| maList.clear(); |
| |
| for(sal_uInt32 i(0); i < aCopy.size(); i++) |
| { |
| delete aCopy[i]; |
| } |
| |
| mbRotateShear = false; |
| mbDistortShear = false; |
| } |
| |
| namespace |
| { |
| struct SdrHdlComparator |
| { |
| bool operator()(const SdrHdl* pA, const SdrHdl* pB) |
| { |
| OSL_ENSURE(pA && pB, "SdrHdlComparator: empty pointer (!)"); |
| const SdrHdlKind eKind1(pA->GetKind()); |
| const SdrHdlKind eKind2(pB->GetKind()); |
| |
| // Level 1: Erst normale Handles, dann Glue, dann User, dann Plushandles, dann Retpunkt-Handles |
| unsigned n1(1); |
| unsigned n2(1); |
| |
| if(eKind1 != eKind2) |
| { |
| if(HDL_REF1 == eKind1 || HDL_REF2 == eKind1 || HDL_MIRX == eKind1) |
| { |
| n1 = 5; |
| } |
| else if(HDL_GLUE == eKind1) |
| { |
| n1 = 2; |
| } |
| else if(HDL_USER == eKind1) |
| { |
| n1 = 3; |
| } |
| else if(HDL_SMARTTAG == eKind1) |
| { |
| n1 = 0; |
| } |
| |
| if(HDL_REF1 == eKind2 || HDL_REF2 == eKind2 || HDL_MIRX == eKind2) |
| { |
| n2 = 5; |
| } |
| else if(HDL_GLUE == eKind2) |
| { |
| n2 = 2; |
| } |
| else if(HDL_USER == eKind2) |
| { |
| n2 = 3; |
| } |
| else if(HDL_SMARTTAG == eKind2) |
| { |
| n2 = 0; |
| } |
| } |
| |
| if(pA->IsPlusHdl()) |
| { |
| n1 = 4; |
| } |
| |
| if(pB->IsPlusHdl()) |
| { |
| n2 = 4; |
| } |
| |
| if(n1 == n2) |
| { |
| // Level 2: Position (x+y) |
| const SdrObject* pObj1 = pA->GetObj(); |
| const SdrObject* pObj2 = pB->GetObj(); |
| |
| if(pObj1 == pObj2) |
| { |
| const sal_uInt32 nNum1(pA->GetObjHdlNum()); |
| const sal_uInt32 nNum2(pB->GetObjHdlNum()); |
| |
| if(nNum1 == nNum2) |
| { |
| // #48763# |
| if(eKind1 == eKind2) |
| { |
| return pA < pB; // Notloesung, um immer die gleiche Sortierung zu haben |
| } |
| else |
| { |
| return (sal_uInt16)eKind1 < (sal_uInt16)eKind2; |
| } |
| } |
| else |
| { |
| return nNum1 < nNum2; |
| } |
| } |
| else |
| { |
| return pObj1 < pObj2; |
| } |
| } |
| else |
| { |
| return n1 < n2; |
| } |
| |
| // should never happen and is even unreachable; just leave it here for security |
| return pA->getPosition().getX() < pB->getPosition().getX(); |
| } |
| }; |
| } |
| |
| void SdrHdlList::Sort() |
| { |
| // #97016# II: remember current focused handle |
| SdrHdl* pPrev = GetFocusHdl(); |
| |
| ::std::sort(maList.begin(), maList.end(), SdrHdlComparator()); |
| |
| // #97016# II: get now and compare |
| SdrHdl* pNow = GetFocusHdl(); |
| |
| if(pPrev != pNow) |
| { |
| if(pPrev) |
| { |
| pPrev->Touch(); |
| } |
| |
| if(pNow) |
| { |
| pNow->Touch(); |
| } |
| } |
| } |
| |
| sal_uInt32 SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const |
| { |
| if(!pHdl) |
| { |
| return CONTAINER_ENTRY_NOTFOUND; |
| } |
| |
| sal_uInt32 a(0); |
| |
| for(SdrHdlContainerType::const_iterator aCandidate(maList.begin()); |
| aCandidate != maList.end(); a++, aCandidate++) |
| { |
| if(*aCandidate == pHdl) |
| { |
| return a; |
| } |
| } |
| |
| return CONTAINER_ENTRY_NOTFOUND; |
| } |
| |
| SdrHdl* SdrHdlList::IsHdlListHit(const basegfx::B2DPoint& rPosition) const |
| { |
| SdrHdl* pRet = 0; |
| const sal_uInt32 nAnz(GetHdlCount()); |
| sal_uInt32 nNum(nAnz); |
| |
| while(nNum && !pRet) |
| { |
| nNum--; |
| SdrHdl* pHdl = GetHdlByIndex(nNum); |
| |
| if(pHdl->IsHdlHit(rPosition)) |
| { |
| pRet = pHdl; |
| } |
| } |
| |
| return pRet; |
| } |
| |
| SdrHdl* SdrHdlList::GetHdlByKind(SdrHdlKind eKind1) const |
| { |
| for(sal_uInt32 i(0); i < GetHdlCount(); i++) |
| { |
| SdrHdl* pHdl = GetHdlByIndex(i); |
| |
| if(pHdl->GetKind() == eKind1) |
| { |
| return pHdl; |
| } |
| } |
| |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // class SdrHdlColor |
| |
| SdrHdlColor::SdrHdlColor( |
| SdrHdlList& rHdlList, |
| const SdrObject& rSdrHdlObject, |
| const basegfx::B2DPoint& rRef, |
| Color aCol, |
| const Size& rSize, |
| bool bLum) |
| : SdrHdl(rHdlList, &rSdrHdlObject, HDL_COLR, rRef), |
| aMarkerSize(rSize), |
| bUseLuminance(bLum) |
| { |
| if(IsUseLuminance()) |
| aCol = GetLuminance(aCol); |
| |
| // remember color |
| aMarkerColor = aCol; |
| } |
| |
| SdrHdlColor::~SdrHdlColor() |
| { |
| } |
| |
| void SdrHdlColor::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| const Bitmap aBmpCol(CreateColorDropper(aMarkerColor)); |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = new |
| ::sdr::overlay::OverlayBitmapEx( |
| maPosition, |
| BitmapEx(aBmpCol), |
| (sal_uInt16)(aBmpCol.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpCol.GetSizePixel().Height() - 1) >> 1 |
| ); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| Bitmap SdrHdlColor::CreateColorDropper(Color aCol) |
| { |
| // get the Bitmap |
| Bitmap aRetval(aMarkerSize, 24); |
| aRetval.Erase(aCol); |
| |
| // get write access |
| BitmapWriteAccess* pWrite = aRetval.AcquireWriteAccess(); |
| DBG_ASSERT(pWrite, "Got NO write access to a new Bitmap !!!"); |
| |
| if(pWrite) |
| { |
| // draw outer border |
| sal_Int32 nWidth = aMarkerSize.Width(); |
| sal_Int32 nHeight = aMarkerSize.Height(); |
| |
| pWrite->SetLineColor(Color(COL_LIGHTGRAY)); |
| pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1)); |
| pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0)); |
| pWrite->SetLineColor(Color(COL_GRAY)); |
| pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1)); |
| pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2)); |
| |
| // draw lighter UpperLeft |
| const Color aLightColor( |
| (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetRed() + (sal_Int16)0x0040), (sal_Int16)0x00ff)), |
| (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetGreen() + (sal_Int16)0x0040), (sal_Int16)0x00ff)), |
| (sal_uInt8)(::std::min((sal_Int16)((sal_Int16)aCol.GetBlue() + (sal_Int16)0x0040), (sal_Int16)0x00ff))); |
| pWrite->SetLineColor(aLightColor); |
| pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2)); |
| pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1)); |
| |
| // draw darker LowerRight |
| const Color aDarkColor( |
| (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetRed() - (sal_Int16)0x0040), (sal_Int16)0x0000)), |
| (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetGreen() - (sal_Int16)0x0040), (sal_Int16)0x0000)), |
| (sal_uInt8)(::std::max((sal_Int16)((sal_Int16)aCol.GetBlue() - (sal_Int16)0x0040), (sal_Int16)0x0000))); |
| pWrite->SetLineColor(aDarkColor); |
| pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2)); |
| pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3)); |
| |
| // get rid of write access |
| delete pWrite; |
| } |
| |
| return aRetval; |
| } |
| |
| Color SdrHdlColor::GetLuminance(const Color& rCol) |
| { |
| sal_uInt8 aLum = rCol.GetLuminance(); |
| Color aRetval(aLum, aLum, aLum); |
| return aRetval; |
| } |
| |
| void SdrHdlColor::CallColorChangeLink() |
| { |
| aColorChangeHdl.Call(this); |
| } |
| |
| void SdrHdlColor::SetColor(Color aNew, bool bCallLink) |
| { |
| if(IsUseLuminance()) |
| aNew = GetLuminance(aNew); |
| |
| if(aMarkerColor != aNew) |
| { |
| // remember new color |
| aMarkerColor = aNew; |
| |
| // create new display |
| Touch(); |
| |
| // tell about change |
| if(bCallLink) |
| CallColorChangeLink(); |
| } |
| } |
| |
| void SdrHdlColor::SetSize(const Size& rNew) |
| { |
| if(rNew != aMarkerSize) |
| { |
| // remember new size |
| aMarkerSize = rNew; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // class SdrHdlGradient |
| |
| SdrHdlGradient::SdrHdlGradient( |
| SdrHdlList& rHdlList, |
| const SdrObject& rSdrHdlObject, |
| SdrHdlColor& rSdrHdlColor1, |
| SdrHdlColor& rSdrHdlColor2, |
| bool bGrad) |
| : SdrHdl(rHdlList, &rSdrHdlObject, bGrad ? HDL_GRAD : HDL_TRNS, rSdrHdlColor1.getPosition()), |
| mrColHdl1(rSdrHdlColor1), |
| mrColHdl2(rSdrHdlColor2), |
| bGradient(bGrad) |
| { |
| } |
| |
| SdrHdlGradient::~SdrHdlGradient() |
| { |
| } |
| |
| void SdrHdlGradient::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| // striped line in between |
| basegfx::B2DVector aVec(mrColHdl2.getPosition() - mrColHdl1.getPosition()); |
| double fVecLen = aVec.getLength(); |
| double fLongPercentArrow = (1.0 - 0.05) * fVecLen; |
| double fHalfArrowWidth = (0.05 * 0.5) * fVecLen; |
| |
| aVec.normalize(); |
| |
| const basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX()); |
| const basegfx::B2DPoint aMidPos(mrColHdl1.getPosition() + (aVec * fLongPercentArrow)); |
| |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = new |
| ::sdr::overlay::OverlayLineStriped( |
| mrColHdl1.getPosition(), |
| aMidPos); |
| |
| pNewOverlayObject->setBaseColor(IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE)); |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| |
| // arrowhead |
| const basegfx::B2DPoint aPositionLeft(aMidPos + (aPerpend * fHalfArrowWidth)); |
| const basegfx::B2DPoint aPositionRight(aMidPos- (aPerpend * fHalfArrowWidth)); |
| |
| pNewOverlayObject = new |
| ::sdr::overlay::OverlayTriangle( |
| aPositionLeft, |
| mrColHdl2.getPosition(), |
| aPositionRight, |
| IsGradient() ? Color(COL_BLACK) : Color(COL_BLUE)); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| IMPL_LINK(SdrHdlGradient, ColorChangeHdl, SdrHdl*, /*pHdl*/) |
| { |
| FromIAOToItem(true, true); |
| |
| return 0; |
| } |
| |
| const basegfx::B2DPoint& SdrHdlGradient::getPosition() const |
| { |
| return mrColHdl1.getPosition(); |
| } |
| |
| void SdrHdlGradient::setPosition(const basegfx::B2DPoint& rNew) |
| { |
| // call parent |
| SdrHdl::setPosition(rNew); |
| |
| if(rNew != mrColHdl1.getPosition()) |
| { |
| // remember new position |
| mrColHdl1.setPosition(rNew); |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| const basegfx::B2DPoint& SdrHdlGradient::get2ndPosition() const |
| { |
| return mrColHdl2.getPosition(); |
| } |
| |
| void SdrHdlGradient::set2ndPosition(const basegfx::B2DPoint& rNew) |
| { |
| if(rNew != mrColHdl2.getPosition()) |
| { |
| // remember new position |
| mrColHdl2.setPosition(rNew); |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| void SdrHdlGradient::FromIAOToItem(bool bSetItemOnObject, bool bUndo) |
| { |
| SdrObject* pTarget = const_cast< SdrObject* >(GetObj()); |
| |
| if(pTarget) |
| { |
| // from IAO positions and colors to gradient |
| const SfxItemSet& rSet = pTarget->GetMergedItemSet(); |
| GradTransformer aGradTransformer; |
| GradTransGradient aOldGradTransGradient; |
| GradTransGradient aGradTransGradient; |
| GradTransVector aGradTransVector; |
| String aString; |
| |
| aGradTransVector.maPositionA = mrColHdl1.getPosition(); |
| aGradTransVector.maPositionB = mrColHdl2.getPosition(); |
| aGradTransVector.aCol1 = mrColHdl1.GetColor(); |
| aGradTransVector.aCol2 = mrColHdl2.GetColor(); |
| |
| if(IsGradient()) |
| { |
| aOldGradTransGradient.aGradient = ((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue(); |
| } |
| else |
| { |
| aOldGradTransGradient.aGradient = ((XFillFloatTransparenceItem&)rSet.Get(XATTR_FILLFLOATTRANSPARENCE)).GetGradientValue(); |
| } |
| |
| // transform vector data to gradient |
| aGradTransformer.VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, pTarget, bMoveSingleHandle, bMoveFirstHandle); |
| |
| if(bSetItemOnObject) |
| { |
| SfxItemSet aNewSet(pTarget->GetObjectItemPool()); |
| |
| if(IsGradient()) |
| { |
| aString = String(); |
| XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient); |
| aNewSet.Put(aNewGradItem); |
| } |
| else |
| { |
| aString = String(); |
| XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient); |
| aNewSet.Put(aNewTransItem); |
| } |
| |
| SdrModel& rSdrModel = pTarget->getSdrModelFromSdrObject(); |
| |
| if(bUndo && rSdrModel.IsUndoEnabled()) |
| { |
| rSdrModel.BegUndo(SVX_RESSTR(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE)); |
| rSdrModel.AddUndo(rSdrModel.GetSdrUndoFactory().CreateUndoAttrObject(*pTarget)); |
| rSdrModel.EndUndo(); |
| } |
| |
| pTarget->SetMergedItemSetAndBroadcast(aNewSet); |
| } |
| |
| // back transformation, set values on pIAOHandle |
| aGradTransformer.GradToVec(aGradTransGradient, aGradTransVector, pTarget); |
| |
| setPosition(aGradTransVector.maPositionA); |
| mrColHdl1.setPosition(aGradTransVector.maPositionA); |
| mrColHdl2.setPosition(aGradTransVector.maPositionB); |
| mrColHdl1.SetColor(aGradTransVector.aCol1); |
| mrColHdl2.SetColor(aGradTransVector.aCol2); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SdrHdlLine::~SdrHdlLine() |
| { |
| } |
| |
| void SdrHdlLine::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| if(pHdl1 && pHdl2) |
| { |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = new |
| ::sdr::overlay::OverlayLineStriped( |
| pHdl1->getPosition(), |
| pHdl2->getPosition()); |
| |
| pNewOverlayObject->setBaseColor(Color(COL_LIGHTRED)); |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| } |
| |
| Pointer SdrHdlLine::GetPointer() const |
| { |
| return Pointer(POINTER_REFHAND); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SdrHdlBezWgt::~SdrHdlBezWgt() |
| { |
| } |
| |
| void SdrHdlBezWgt::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| // call parent, create control point handle |
| SdrHdl::CreateB2dIAObject(rOverlayManager); |
| |
| // create striped line part |
| if(pHdl1 && !pHdl1->getPosition().equal(maPosition)) |
| { |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = new |
| ::sdr::overlay::OverlayLineStriped( |
| pHdl1->getPosition(), |
| maPosition |
| ); |
| |
| // line part is not hittable |
| pNewOverlayObject->setHittable(false); |
| |
| // color(?) |
| pNewOverlayObject->setBaseColor(Color(COL_LIGHTBLUE)); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| E3dVolumeMarker::E3dVolumeMarker( |
| SdrHdlList& rHdlList, |
| const SdrObject* pSdrHdlObject, |
| const basegfx::B2DPolyPolygon& rWireframePoly) |
| : SdrHdl(rHdlList, pSdrHdlObject), |
| aWireframePoly(rWireframePoly) |
| { |
| } |
| |
| E3dVolumeMarker::~E3dVolumeMarker() |
| { |
| } |
| |
| void E3dVolumeMarker::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = new |
| ::sdr::overlay::OverlayPolyPolygonStripedAndFilled(aWireframePoly); |
| |
| pNewOverlayObject->setBaseColor(Color(COL_BLACK)); |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| ImpEdgeHdl::~ImpEdgeHdl() |
| { |
| } |
| |
| void ImpEdgeHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| const SdrEdgeObj* pEdge = dynamic_cast< const SdrEdgeObj* >(mpSdrHdlObject); |
| |
| if(pEdge && mnObjHdlNum <= 1) |
| { |
| BitmapColorIndex eColIndex = LightCyan; |
| BitmapMarkerKind eKindOfMarker = Rect_7x7; |
| |
| if(pEdge->GetSdrObjectConnection(mnObjHdlNum == 0)) |
| { |
| eColIndex = LightRed; |
| } |
| |
| if(mnPPntNum < 2) |
| { |
| // Handle with plus sign inside |
| eKindOfMarker = Circ_7x7; |
| } |
| |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( |
| maPosition, |
| eColIndex, |
| eKindOfMarker, |
| 0, 0); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| else |
| { |
| // call parent |
| SdrHdl::CreateB2dIAObject(rOverlayManager); |
| } |
| } |
| |
| void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode) |
| { |
| if(eLineCode != eCode) |
| { |
| // remember new value |
| eLineCode = eCode; |
| |
| // create new display |
| Touch(); |
| } |
| } |
| |
| Pointer ImpEdgeHdl::GetPointer() const |
| { |
| if(!mpSdrHdlObject) |
| { |
| return SdrHdl::GetPointer(); |
| } |
| |
| const SdrEdgeObj* pSdrEdgeObj = dynamic_cast< const SdrEdgeObj* >(mpSdrHdlObject); |
| |
| if(!pSdrEdgeObj) |
| { |
| return SdrHdl::GetPointer(); |
| } |
| |
| if(mnObjHdlNum <= 1) |
| { |
| return Pointer(POINTER_MOVEPOINT); //Pointer(POINTER_DRAW_CONNECT); |
| } |
| |
| if(IsHorzDrag()) |
| { |
| return Pointer(POINTER_ESIZE); |
| } |
| else |
| { |
| return Pointer(POINTER_SSIZE); |
| } |
| } |
| |
| bool ImpEdgeHdl::IsHorzDrag() const |
| { |
| const SdrEdgeObj* pEdge = dynamic_cast< const SdrEdgeObj* >(mpSdrHdlObject); |
| |
| if(pEdge) |
| { |
| if(mnObjHdlNum <= 1) |
| { |
| return false; |
| } |
| |
| return pEdge->checkHorizontalDrag(eLineCode, 2 == mnObjHdlNum); |
| } |
| |
| return false; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| ImpMeasureHdl::~ImpMeasureHdl() |
| { |
| } |
| |
| void ImpMeasureHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| BitmapColorIndex eColIndex = LightCyan; |
| BitmapMarkerKind eKindOfMarker = Rect_9x9; |
| |
| if(mnObjHdlNum > 1) |
| { |
| eKindOfMarker = Rect_7x7; |
| } |
| |
| if(mbSelect) |
| { |
| eColIndex = Cyan; |
| } |
| |
| ::sdr::overlay::OverlayObject* pNewOverlayObject = CreateOverlayObject( |
| maPosition, |
| eColIndex, |
| eKindOfMarker, |
| 0, 0); |
| |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| Pointer ImpMeasureHdl::GetPointer() const |
| { |
| switch (mnObjHdlNum) |
| { |
| case 0: case 1: return Pointer(POINTER_HAND); |
| case 2: case 3: return Pointer(POINTER_MOVEPOINT); |
| case 4: case 5: return SdrHdl::GetPointer(); // wird dann entsprechend gedreht |
| } // switch |
| return Pointer(POINTER_NOTALLOWED); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| ImpTextframeHdl::ImpTextframeHdl( |
| SdrHdlList& rHdlList, |
| const SdrObject& rSdrHdlObject, |
| const basegfx::B2DHomMatrix& rTransformation) |
| : SdrHdl(rHdlList, &rSdrHdlObject), |
| maTransformation(rTransformation) |
| { |
| // set member aPos, not sure if this is needed |
| setPosition(maTransformation * basegfx::B2DPoint(0.0, 0.0)); |
| } |
| |
| ImpTextframeHdl::~ImpTextframeHdl() |
| { |
| } |
| |
| void ImpTextframeHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; |
| const Color aHilightColor(aSvtOptionsDrawinglayer.getHilightColor()); |
| const double fTransparence(aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() * 0.01); |
| ::sdr::overlay::OverlayRectangle* pNewOverlayObject = new ::sdr::overlay::OverlayRectangle( |
| maTransformation, |
| aHilightColor, |
| fTransparence, |
| 3.0, |
| 3.0, |
| 500, |
| true); // allow animation; the Handle is not shown at text edit time |
| |
| pNewOverlayObject->setHittable(false); |
| rOverlayManager.add(*pNewOverlayObject); |
| maOverlayGroup.append(*pNewOverlayObject); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // SdrCropHdl |
| |
| SdrCropHdl::SdrCropHdl( |
| SdrHdlList& rHdlList, |
| const SdrObject& rSdrHdlObject, |
| SdrHdlKind eNewKind, |
| const basegfx::B2DPoint& rPnt, |
| double fShearX, |
| double fRotation) |
| : SdrHdl( rHdlList, &rSdrHdlObject, eNewKind, rPnt), |
| mfShearX(fShearX), |
| mfRotation(fRotation) |
| { |
| } |
| |
| SdrCropHdl::~SdrCropHdl() |
| { |
| } |
| |
| BitmapEx SdrCropHdl::GetHandlesBitmap( bool bIsFineHdl, bool bIsHighContrast ) |
| { |
| if( bIsHighContrast ) |
| { |
| static BitmapEx* pHighContrastBitmap = 0; |
| if( pHighContrastBitmap == 0 ) |
| pHighContrastBitmap = new BitmapEx(ResId(SIP_SA_ACCESSIBILITY_CROP_MARKERS, *ImpGetResMgr())); |
| return *pHighContrastBitmap; |
| } |
| else if( bIsFineHdl ) |
| { |
| static BitmapEx* pModernBitmap = 0; |
| if( pModernBitmap == 0 ) |
| pModernBitmap = new BitmapEx(ResId(SIP_SA_CROP_FINE_MARKERS, *ImpGetResMgr())); |
| return *pModernBitmap; |
| } |
| else |
| { |
| static BitmapEx* pSimpleBitmap = 0; |
| if( pSimpleBitmap == 0 ) |
| pSimpleBitmap = new BitmapEx(ResId(SIP_SA_CROP_MARKERS, *ImpGetResMgr())); |
| return *pSimpleBitmap; |
| } |
| } |
| |
| BitmapEx SdrCropHdl::GetBitmapForHandle( const BitmapEx& rBitmap, sal_uInt16 nSize ) |
| { |
| sal_uInt16 nPixelSize = 0, nX = 0, nY = 0, nOffset = 0; |
| |
| if( nSize <= 3 ) |
| { |
| nPixelSize = 13; |
| nOffset = 0; |
| } |
| else if( nSize <=4 ) |
| { |
| nPixelSize = 17; |
| nOffset = 36; |
| } |
| else |
| { |
| nPixelSize = 21; |
| nOffset = 84; |
| } |
| |
| switch( meKind ) |
| { |
| case HDL_UPLFT: nX = 0; nY = 0; break; |
| case HDL_UPPER: nX = 1; nY = 0; break; |
| case HDL_UPRGT: nX = 2; nY = 0; break; |
| case HDL_LEFT: nX = 0; nY = 1; break; |
| case HDL_RIGHT: nX = 2; nY = 1; break; |
| case HDL_LWLFT: nX = 0; nY = 2; break; |
| case HDL_LOWER: nX = 1; nY = 2; break; |
| case HDL_LWRGT: nX = 2; nY = 2; break; |
| default: break; |
| } |
| |
| Rectangle aSourceRect( Point( nX * (nPixelSize-1) + nOffset, nY * (nPixelSize-1)), Size(nPixelSize, nPixelSize) ); |
| |
| BitmapEx aRetval(rBitmap); |
| aRetval.Crop(aSourceRect); |
| return aRetval; |
| } |
| |
| void SdrCropHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| bool bIsFineHdl(mrHdlList.IsFineHdl()); |
| const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings(); |
| bool bIsHighContrast(rStyleSettings.GetHighContrastMode()); |
| sal_uInt16 nHdlSize = mrHdlList.GetHdlSize(); |
| |
| if( bIsHighContrast ) |
| nHdlSize = 4; |
| |
| const BitmapEx aHandlesBitmap( GetHandlesBitmap( bIsFineHdl, bIsHighContrast ) ); |
| BitmapEx aBmpEx1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) ); |
| ::sdr::overlay::OverlayObject* pOverlayObject = 0L; |
| |
| // animate focused handles |
| if(IsFocusHdl() && (mrHdlList.GetFocusHdl() == this)) |
| { |
| if( nHdlSize >= 2 ) |
| nHdlSize = 1; |
| |
| BitmapEx aBmpEx2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) ); |
| |
| const sal_uInt32 nBlinkTime = sal::static_int_cast<sal_uInt32>(rStyleSettings.GetCursorBlinkTime()); |
| |
| pOverlayObject = new ::sdr::overlay::OverlayAnimatedBitmapEx( |
| maPosition, |
| aBmpEx1, |
| aBmpEx2, |
| nBlinkTime, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, |
| (sal_uInt16)(aBmpEx2.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpEx2.GetSizePixel().Height() - 1) >> 1, |
| mfShearX, |
| mfRotation); |
| } |
| else |
| { |
| // create centered handle as default |
| pOverlayObject = new ::sdr::overlay::OverlayBitmapEx( |
| maPosition, |
| aBmpEx1, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Width() - 1) >> 1, |
| (sal_uInt16)(aBmpEx1.GetSizePixel().Height() - 1) >> 1, |
| 0.0, |
| mfShearX, |
| mfRotation); |
| } |
| |
| rOverlayManager.add(*pOverlayObject); |
| maOverlayGroup.append(*pOverlayObject); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff |
| // accordingly |
| |
| SdrCropViewHdl::SdrCropViewHdl( |
| SdrHdlList& rHdlList, |
| const SdrObject& rSdrHdlObject, |
| const basegfx::B2DHomMatrix& rObjectTransform, |
| const Graphic& rGraphic, |
| double fCropLeft, |
| double fCropTop, |
| double fCropRight, |
| double fCropBottom) |
| : SdrHdl(rHdlList, &rSdrHdlObject, HDL_USER), |
| maObjectTransform(rObjectTransform), |
| maGraphic(rGraphic), |
| mfCropLeft(fCropLeft), |
| mfCropTop(fCropTop), |
| mfCropRight(fCropRight), |
| mfCropBottom(fCropBottom) |
| { |
| } |
| |
| void SdrCropViewHdl::CreateB2dIAObject(::sdr::overlay::OverlayManager& rOverlayManager) |
| { |
| GetRidOfIAObject(); |
| |
| // decompose to have current translate and scale |
| basegfx::B2DVector aScale, aTranslate; |
| double fRotate, fShearX; |
| |
| maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); |
| |
| if(aScale.equalZero()) |
| { |
| return; |
| } |
| |
| // detect 180 degree rotation, this is the same as mirrored in X and Y, |
| // thus change to mirroring. Prefer mirroring here. Use the equal call |
| // with getSmallValue here, the original which uses rtl::math::approxEqual |
| // is too correct here. Maybe this changes with enhanced precision in aw080 |
| // to the better so that this can be reduced to the more precise call again |
| if(basegfx::fTools::equal(fabs(fRotate), F_PI, 0.000000001)) |
| { |
| aScale.setX(aScale.getX() * -1.0); |
| aScale.setY(aScale.getY() * -1.0); |
| fRotate = 0.0; |
| } |
| |
| // remember mirroring, reset at Scale and adapt crop values for usage; |
| // mirroring can stay in the object transformation, so do not have to |
| // cope with it here (except later for the CroppedImage transformation, |
| // see below) |
| const bool bMirroredX(aScale.getX() < 0.0); |
| const bool bMirroredY(aScale.getY() < 0.0); |
| double fCropLeft(mfCropLeft); |
| double fCropTop(mfCropTop); |
| double fCropRight(mfCropRight); |
| double fCropBottom(mfCropBottom); |
| |
| if(bMirroredX) |
| { |
| aScale.setX(-aScale.getX()); |
| } |
| |
| if(bMirroredY) |
| { |
| aScale.setY(-aScale.getY()); |
| } |
| |
| // create target translate and scale |
| const basegfx::B2DVector aTargetScale( |
| aScale.getX() + fCropRight + fCropLeft, |
| aScale.getY() + fCropBottom + fCropTop); |
| const basegfx::B2DVector aTargetTranslate( |
| aTranslate.getX() - fCropLeft, |
| aTranslate.getY() - fCropTop); |
| |
| // create ranges to make comparisons |
| const basegfx::B2DRange aCurrentForCompare( |
| aTranslate.getX(), aTranslate.getY(), |
| aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY()); |
| basegfx::B2DRange aCropped( |
| aTargetTranslate.getX(), aTargetTranslate.getY(), |
| aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY()); |
| |
| if(aCropped.isEmpty()) |
| { |
| // nothing to return since cropped content is completely empty |
| return; |
| } |
| |
| if(aCurrentForCompare.equal(aCropped)) |
| { |
| // no crop at all |
| return; |
| } |
| |
| // back-transform to have values in unit coordinates |
| basegfx::B2DHomMatrix aBackToUnit; |
| aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY()); |
| aBackToUnit.scale( |
| basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(), |
| basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY()); |
| |
| // transform cropped back to unit coordinates |
| aCropped.transform(aBackToUnit); |
| |
| // prepare crop PolyPolygon |
| basegfx::B2DPolygon aGraphicOutlinePolygon( |
| basegfx::tools::createPolygonFromRect( |
| aCropped)); |
| basegfx::B2DPolyPolygon aCropPolyPolygon(aGraphicOutlinePolygon); |
| |
| // current range is unit range |
| basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0); |
| |
| aOverlap.intersect(aCropped); |
| |
| if(!aOverlap.isEmpty()) |
| { |
| aCropPolyPolygon.append( |
| basegfx::tools::createPolygonFromRect( |
| aOverlap)); |
| } |
| |
| // transform to object coordinates to prepare for clip |
| aCropPolyPolygon.transform(maObjectTransform); |
| aGraphicOutlinePolygon.transform(maObjectTransform); |
| |
| // create cropped transformation |
| basegfx::B2DHomMatrix aCroppedTransform; |
| |
| aCroppedTransform.scale( |
| aCropped.getWidth(), |
| aCropped.getHeight()); |
| aCroppedTransform.translate( |
| aCropped.getMinX(), |
| aCropped.getMinY()); |
| aCroppedTransform = maObjectTransform * aCroppedTransform; |
| |
| // prepare graphic primitive (transformed) |
| const drawinglayer::primitive2d::Primitive2DReference aGraphic( |
| new drawinglayer::primitive2d::GraphicPrimitive2D( |
| aCroppedTransform, |
| maGraphic)); |
| |
| // prepare outline polygon for whole graphic |
| const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; |
| const basegfx::BColor aHilightColor(aSvtOptionsDrawinglayer.getHilightColor().getBColor()); |
| const drawinglayer::primitive2d::Primitive2DReference aGraphicOutline( |
| new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( |
| aGraphicOutlinePolygon, |
| aHilightColor)); |
| |
| // combine these |
| drawinglayer::primitive2d::Primitive2DSequence aCombination(2); |
| aCombination[0] = aGraphic; |
| aCombination[1] = aGraphicOutline; |
| |
| // embed to MaskPrimitive2D |
| const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic( |
| new drawinglayer::primitive2d::MaskPrimitive2D( |
| aCropPolyPolygon, |
| aCombination)); |
| |
| // embed to UnifiedTransparencePrimitive2D |
| const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic( |
| new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( |
| drawinglayer::primitive2d::Primitive2DSequence(&aMaskedGraphic, 1), |
| 0.8)); |
| |
| const drawinglayer::primitive2d::Primitive2DSequence aSequence(&aTransparenceMaskedGraphic, 1); |
| ::sdr::overlay::OverlayObject* pOverlayObject = new sdr::overlay::OverlayPrimitive2DSequenceObject(aSequence); |
| DBG_ASSERT(pOverlayObject, "Got NO new IAO!"); |
| |
| if(pOverlayObject) |
| { |
| // only informative object, no hit |
| pOverlayObject->setHittable(false); |
| |
| rOverlayManager.add(*pOverlayObject); |
| maOverlayGroup.append(*pOverlayObject); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // eof |