diff options
Diffstat (limited to 'sw/source/uibase/docvw')
33 files changed, 16880 insertions, 0 deletions
diff --git a/sw/source/uibase/docvw/AnchorOverlayObject.cxx b/sw/source/uibase/docvw/AnchorOverlayObject.cxx new file mode 100644 index 000000000000..d3f1ee04bcf8 --- /dev/null +++ b/sw/source/uibase/docvw/AnchorOverlayObject.cxx @@ -0,0 +1,449 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <AnchorOverlayObject.hxx> +#include <SidebarWindowsConsts.hxx> + +#include <swrect.hxx> +#include <view.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/svdview.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> + +#include <sw_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/shadowprimitive2d.hxx> + +namespace sw { namespace sidebarwindows { + +// helper class: Primitive for discrete visualisation +class AnchorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D +{ +private: + basegfx::B2DPolygon maTriangle; + basegfx::B2DPolygon maLine; + basegfx::B2DPolygon maLineTop; + const AnchorState maAnchorState; + basegfx::BColor maColor; + + // discrete line width + double mfDiscreteLineWidth; + + // bitfield + bool mbShadow : 1; + bool mbLineSolid : 1; + +protected: + virtual drawinglayer::primitive2d::Primitive2DSequence create2DDecomposition( + const drawinglayer::geometry::ViewInformation2D& rViewInformation) const SAL_OVERRIDE; + +public: + AnchorPrimitive( const basegfx::B2DPolygon& rTriangle, + const basegfx::B2DPolygon& rLine, + const basegfx::B2DPolygon& rLineTop, + AnchorState aAnchorState, + const basegfx::BColor& rColor, + double fDiscreteLineWidth, + bool bShadow, + bool bLineSolid ) + : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), + maTriangle(rTriangle), + maLine(rLine), + maLineTop(rLineTop), + maAnchorState(aAnchorState), + maColor(rColor), + mfDiscreteLineWidth(fDiscreteLineWidth), + mbShadow(bShadow), + mbLineSolid(bLineSolid) + {} + + // data access + const basegfx::B2DPolygon& getTriangle() const { return maTriangle; } + const basegfx::B2DPolygon& getLine() const { return maLine; } + const basegfx::B2DPolygon& getLineTop() const { return maLineTop; } + AnchorState getAnchorState() const { return maAnchorState; } + const basegfx::BColor& getColor() const { return maColor; } + double getDiscreteLineWidth() const { return mfDiscreteLineWidth; } + bool getShadow() const { return mbShadow; } + bool getLineSolid() const { return mbLineSolid; } + + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const SAL_OVERRIDE; + + DeclPrimitive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence AnchorPrimitive::create2DDecomposition( + const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + + if ( AS_TRI == maAnchorState || + AS_ALL == maAnchorState || + AS_START == maAnchorState ) + { + // create triangle + const drawinglayer::primitive2d::Primitive2DReference aTriangle( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(getTriangle()), + getColor())); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aTriangle); + } + + // prepare view-independent LineWidth and color + const drawinglayer::attribute::LineAttribute aLineAttribute( + getColor(), + getDiscreteLineWidth() * getDiscreteUnit()); + + if ( AS_ALL == maAnchorState || + AS_START == maAnchorState ) + { + // create line start + if(getLineSolid()) + { + const drawinglayer::primitive2d::Primitive2DReference aSolidLine( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + getLine(), + aLineAttribute)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aSolidLine); + } + else + { + ::std::vector< double > aDotDashArray; + const double fDistance(3.0 * 15.0); + const double fDashLen(5.0 * 15.0); + + aDotDashArray.push_back(fDashLen); + aDotDashArray.push_back(fDistance); + + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute( + aDotDashArray, + fDistance + fDashLen); + + const drawinglayer::primitive2d::Primitive2DReference aStrokedLine( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + getLine(), + aLineAttribute, + aStrokeAttribute)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aStrokedLine); + } + } + + if(aRetval.hasElements() && getShadow()) + { + // shadow is only for triangle and line start, and in upper left + // and lower right direction, in different colors + const double fColorChange(20.0 / 255.0); + const basegfx::B3DTuple aColorChange(fColorChange, fColorChange, fColorChange); + basegfx::BColor aLighterColor(getColor() + aColorChange); + basegfx::BColor aDarkerColor(getColor() - aColorChange); + + aLighterColor.clamp(); + aDarkerColor.clamp(); + + // create shadow sequence + drawinglayer::primitive2d::Primitive2DSequence aShadows(2); + basegfx::B2DHomMatrix aTransform; + + aTransform.set(0, 2, -getDiscreteUnit()); + aTransform.set(1, 2, -getDiscreteUnit()); + + aShadows[0] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::ShadowPrimitive2D( + aTransform, + aLighterColor, + aRetval)); + + aTransform.set(0, 2, getDiscreteUnit()); + aTransform.set(1, 2, getDiscreteUnit()); + + aShadows[1] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::ShadowPrimitive2D( + aTransform, + aDarkerColor, + aRetval)); + + // add shadow before geometry to make it be proccessed first + const drawinglayer::primitive2d::Primitive2DSequence aTemporary(aRetval); + + aRetval = aShadows; + drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(aRetval, aTemporary); + } + + if ( AS_ALL == maAnchorState || + AS_END == maAnchorState ) + { + // LineTop has to be created, too, but uses no shadow, so add after + // the other parts are created + const drawinglayer::primitive2d::Primitive2DReference aLineTop( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + getLineTop(), + aLineAttribute)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aLineTop); + } + + return aRetval; +} + +bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive); + + return (getTriangle() == rCompare.getTriangle() + && getLine() == rCompare.getLine() + && getLineTop() == rCompare.getLineTop() + && getAnchorState() == rCompare.getAnchorState() + && getColor() == rCompare.getColor() + && getDiscreteLineWidth() == rCompare.getDiscreteLineWidth() + && getShadow() == rCompare.getShadow() + && getLineSolid() == rCompare.getLineSolid()); + } + + return false; +} + +ImplPrimitive2DIDBlock(AnchorPrimitive, PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE) + +/*static*/ AnchorOverlayObject* AnchorOverlayObject::CreateAnchorOverlayObject( + SwView& rDocView, + const SwRect& aAnchorRect, + const long& aPageBorder, + const Point& aLineStart, + const Point& aLineEnd, + const Color& aColorAnchor ) +{ + AnchorOverlayObject* pAnchorOverlayObject( 0 ); + if ( rDocView.GetDrawView() ) + { + SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0); + if( pPaintWindow ) + { + rtl::Reference< ::sdr::overlay::OverlayManager > xOverlayManager = pPaintWindow->GetOverlayManager(); + + if ( xOverlayManager.is() ) + { + pAnchorOverlayObject = new AnchorOverlayObject( + basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15), + basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15), + basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15), + basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), + basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) , + aColorAnchor, + false, + false); + xOverlayManager->add(*pAnchorOverlayObject); + } + } + } + + return pAnchorOverlayObject; +} + +/*static*/ void AnchorOverlayObject::DestroyAnchorOverlayObject( AnchorOverlayObject* pAnchor ) +{ + if ( pAnchor ) + { + if ( pAnchor->getOverlayManager() ) + { + // remove this object from the chain + pAnchor->getOverlayManager()->remove(*pAnchor); + } + delete pAnchor; + } +} + +AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos, + const basegfx::B2DPoint& rSecondPos, + const basegfx::B2DPoint& rThirdPos, + const basegfx::B2DPoint& rFourthPos, + const basegfx::B2DPoint& rFifthPos, + const basegfx::B2DPoint& rSixthPos, + const basegfx::B2DPoint& rSeventhPos, + const Color aBaseColor, + const bool bShadowedEffect, + const bool bLineSolid) + : OverlayObjectWithBasePosition( rBasePos, aBaseColor ) + , maSecondPosition(rSecondPos) + , maThirdPosition(rThirdPos) + , maFourthPosition(rFourthPos) + , maFifthPosition(rFifthPos) + , maSixthPosition(rSixthPos) + , maSeventhPosition(rSeventhPos) + , maTriangle() + , maLine() + , maLineTop() + , mHeight(0) + , mAnchorState(AS_ALL) + , mbShadowedEffect(bShadowedEffect) + , mbLineSolid(bLineSolid) +{ +} + +AnchorOverlayObject::~AnchorOverlayObject() +{ +} + +void AnchorOverlayObject::implEnsureGeometry() +{ + if(!maTriangle.count()) + { + maTriangle.append(getBasePosition()); + maTriangle.append(GetSecondPosition()); + maTriangle.append(GetThirdPosition()); + maTriangle.setClosed(true); + } + + if(!maLine.count()) + { + maLine.append(GetFourthPosition()); + maLine.append(GetFifthPosition()); + maLine.append(GetSixthPosition()); + } + + if(!maLineTop.count()) + { + maLineTop.append(GetSixthPosition()); + maLineTop.append(GetSeventhPosition()); + } +} + +void AnchorOverlayObject::implResetGeometry() +{ + maTriangle.clear(); + maLine.clear(); + maLineTop.clear(); +} + +drawinglayer::primitive2d::Primitive2DSequence AnchorOverlayObject::createOverlayObjectPrimitive2DSequence() +{ + implEnsureGeometry(); + + static double aDiscreteLineWidth(1.6); + const drawinglayer::primitive2d::Primitive2DReference aReference( + new AnchorPrimitive( maTriangle, + maLine, + maLineTop, + GetAnchorState(), + getBaseColor().getBColor(), + ANCHORLINE_WIDTH * aDiscreteLineWidth, + getShadowedEffect(), + getLineSolid()) ); + + return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); +} + +void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2, + const basegfx::B2DPoint& rPoint3, + const basegfx::B2DPoint& rPoint4, + const basegfx::B2DPoint& rPoint5, + const basegfx::B2DPoint& rPoint6, + const basegfx::B2DPoint& rPoint7) +{ + if ( rPoint1 != getBasePosition() || + rPoint2 != GetSecondPosition() || + rPoint3 != GetThirdPosition() || + rPoint4 != GetFourthPosition() || + rPoint5 != GetFifthPosition() || + rPoint6 != GetSixthPosition() || + rPoint7 != GetSeventhPosition() ) + { + maBasePosition = rPoint1; + maSecondPosition = rPoint2; + maThirdPosition = rPoint3; + maFourthPosition = rPoint4; + maFifthPosition = rPoint5; + maSixthPosition = rPoint6; + maSeventhPosition = rPoint7; + + implResetGeometry(); + objectChange(); + } +} + +void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew) +{ + if(rNew != maSixthPosition) + { + maSixthPosition = rNew; + implResetGeometry(); + objectChange(); + } +} + +void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew) +{ + if(rNew != maSeventhPosition) + { + maSeventhPosition = rNew; + implResetGeometry(); + objectChange(); + } +} + +void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3, + const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5) +{ + if(rPoint1 != getBasePosition() + || rPoint2 != GetSecondPosition() + || rPoint3 != GetThirdPosition() + || rPoint4 != GetFourthPosition() + || rPoint5 != GetFifthPosition()) + { + maBasePosition = rPoint1; + maSecondPosition = rPoint2; + maThirdPosition = rPoint3; + maFourthPosition = rPoint4; + maFifthPosition = rPoint5; + + implResetGeometry(); + objectChange(); + } +} + +void AnchorOverlayObject::setLineSolid( const bool bNew ) +{ + if ( bNew != getLineSolid() ) + { + mbLineSolid = bNew; + objectChange(); + } +} + +void AnchorOverlayObject::SetAnchorState( const AnchorState aState) +{ + if ( mAnchorState != aState) + { + mAnchorState = aState; + objectChange(); + } +} + +} } // end of namespace sw::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/AnchorOverlayObject.hxx b/sw/source/uibase/docvw/AnchorOverlayObject.hxx new file mode 100644 index 000000000000..c4b4c1c5ce16 --- /dev/null +++ b/sw/source/uibase/docvw/AnchorOverlayObject.hxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ANCHOROVERLAYOBJECT_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ANCHOROVERLAYOBJECT_HXX + +#include <svx/sdr/overlay/overlayobject.hxx> + +#include <basegfx/polygon/b2dpolygon.hxx> + +class SwView; +class SwRect; +class Point; + +namespace sw { namespace sidebarwindows { + +enum AnchorState +{ + AS_ALL, + AS_START, + AS_END, + AS_TRI +}; + +class AnchorOverlayObject: public sdr::overlay::OverlayObjectWithBasePosition +{ + public: + static AnchorOverlayObject* CreateAnchorOverlayObject( SwView& rDocView, + const SwRect& aAnchorRect, + const long& aPageBorder, + const Point& aLineStart, + const Point& aLineEnd, + const Color& aColorAnchor ); + static void DestroyAnchorOverlayObject( AnchorOverlayObject* pAnchor ); + + inline const basegfx::B2DPoint& GetSecondPosition() const { return maSecondPosition; } + const basegfx::B2DPoint& GetThirdPosition() const { return maThirdPosition; } + const basegfx::B2DPoint& GetFourthPosition() const { return maFourthPosition; } + const basegfx::B2DPoint& GetFifthPosition() const { return maFifthPosition; } + const basegfx::B2DPoint& GetSixthPosition() const { return maSixthPosition; } + const basegfx::B2DPoint& GetSeventhPosition() const { return maSeventhPosition; } + + void SetAllPosition( const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2, + const basegfx::B2DPoint& rPoint3, + const basegfx::B2DPoint& rPoint4, + const basegfx::B2DPoint& rPoint5, + const basegfx::B2DPoint& rPoint6, + const basegfx::B2DPoint& rPoint7 ); + void SetTriPosition( const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2, + const basegfx::B2DPoint& rPoint3, + const basegfx::B2DPoint& rPoint4, + const basegfx::B2DPoint& rPoint5 ); + void SetSixthPosition( const basegfx::B2DPoint& rNew ); + void SetSeventhPosition( const basegfx::B2DPoint& rNew ); + + void setLineSolid( const bool bNew ); + inline bool getLineSolid() const { return mbLineSolid; } + + inline void SetHeight( const unsigned long aHeight ) { mHeight = aHeight; }; + + bool getShadowedEffect() const { return mbShadowedEffect; } + + void SetAnchorState( const AnchorState aState ); + inline AnchorState GetAnchorState() const { return mAnchorState; } + + protected: + /* 6------------7 + 1 / + /4\ ---------------5 + 2 - 3 + */ + + basegfx::B2DPoint maSecondPosition; + basegfx::B2DPoint maThirdPosition; + basegfx::B2DPoint maFourthPosition; + basegfx::B2DPoint maFifthPosition; + basegfx::B2DPoint maSixthPosition; + basegfx::B2DPoint maSeventhPosition; + + // helpers to fill and reset geometry + void implEnsureGeometry(); + void implResetGeometry(); + + // geometry creation for OverlayObject + virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence() SAL_OVERRIDE; + + private: + // object's geometry + basegfx::B2DPolygon maTriangle; + basegfx::B2DPolygon maLine; + basegfx::B2DPolygon maLineTop; + unsigned long mHeight; + AnchorState mAnchorState; + + bool mbShadowedEffect : 1; + bool mbLineSolid : 1; + + AnchorOverlayObject( const basegfx::B2DPoint& rBasePos, + const basegfx::B2DPoint& rSecondPos, + const basegfx::B2DPoint& rThirdPos, + const basegfx::B2DPoint& rFourthPos, + const basegfx::B2DPoint& rFifthPos, + const basegfx::B2DPoint& rSixthPos, + const basegfx::B2DPoint& rSeventhPos, + const Color aBaseColor, + const bool bShadowedEffect, + const bool bLineSolid ); + virtual ~AnchorOverlayObject(); +}; + +} } // end of namespace sw::annotation + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/AnnotationMenuButton.cxx b/sw/source/uibase/docvw/AnnotationMenuButton.cxx new file mode 100644 index 000000000000..051d7eebcd7c --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationMenuButton.cxx @@ -0,0 +1,205 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <AnnotationMenuButton.hxx> + +#include <annotation.hrc> +#include <app.hrc> +#include <access.hrc> + +#include <unotools/useroptions.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/menu.hxx> +#include <vcl/decoview.hxx> +#include <vcl/gradient.hxx> +#include <vcl/settings.hxx> + +#include <cmdid.h> +#include <SidebarWin.hxx> + +namespace sw { namespace annotation { + +Color ColorFromAlphaColor( const sal_uInt8 aTransparency, + const Color &aFront, + const Color &aBack ) +{ + return Color((sal_uInt8)(aFront.GetRed() * aTransparency/(double)255 + aBack.GetRed() * (1-aTransparency/(double)255)), + (sal_uInt8)(aFront.GetGreen() * aTransparency/(double)255 + aBack.GetGreen() * (1-aTransparency/(double)255)), + (sal_uInt8)(aFront.GetBlue() * aTransparency/(double)255 + aBack.GetBlue() * (1-aTransparency/(double)255))); +} + +AnnotationMenuButton::AnnotationMenuButton( sw::sidebarwindows::SwSidebarWin& rSidebarWin ) + : MenuButton( &rSidebarWin ) + , mrSidebarWin( rSidebarWin ) +{ + AddEventListener( LINK( &mrSidebarWin, sw::sidebarwindows::SwSidebarWin, WindowEventListener ) ); + + SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_BUTTON_NAME ) ); + SetAccessibleDescription( SW_RES( STR_ACCESS_ANNOTATION_BUTTON_DESC ) ); + SetQuickHelpText( GetAccessibleDescription() ); +} + +AnnotationMenuButton::~AnnotationMenuButton() +{ + RemoveEventListener( LINK( &mrSidebarWin, sw::sidebarwindows::SwSidebarWin, WindowEventListener ) ); +} + +void AnnotationMenuButton::Select() +{ + mrSidebarWin.ExecuteCommand( GetCurItemId() ); +} + +void AnnotationMenuButton::MouseButtonDown( const MouseEvent& rMEvt ) +{ + PopupMenu* pButtonPopup( GetPopupMenu() ); + if ( mrSidebarWin.IsReadOnly() ) + { + pButtonPopup->EnableItem( FN_REPLY, false ); + pButtonPopup->EnableItem( FN_DELETE_COMMENT, false ); + pButtonPopup->EnableItem( FN_DELETE_NOTE_AUTHOR, false ); + pButtonPopup->EnableItem( FN_DELETE_ALL_NOTES, false ); + pButtonPopup->EnableItem( FN_FORMAT_ALL_NOTES, false ); + } + else + { + pButtonPopup->EnableItem( FN_DELETE_COMMENT, !mrSidebarWin.IsProtected() ); + pButtonPopup->EnableItem( FN_DELETE_NOTE_AUTHOR, true ); + pButtonPopup->EnableItem( FN_DELETE_ALL_NOTES, true ); + pButtonPopup->EnableItem( FN_FORMAT_ALL_NOTES, true ); + } + + if ( mrSidebarWin.IsProtected() ) + { + pButtonPopup->EnableItem( FN_REPLY, false ); + } + else + { + SvtUserOptions aUserOpt; + OUString sAuthor; + if ( (sAuthor = aUserOpt.GetFullName()).isEmpty() ) + { + if ( (sAuthor = aUserOpt.GetID()).isEmpty() ) + { + sAuthor = SW_RES( STR_REDLINE_UNKNOWN_AUTHOR ); + } + } + // do not allow to reply to ourself and no answer possible if this note is in a protected section + if ( sAuthor == mrSidebarWin.GetAuthor() ) + { + pButtonPopup->EnableItem( FN_REPLY, false ); + } + else + { + pButtonPopup->EnableItem( FN_REPLY, true ); + } + } + + MenuButton::MouseButtonDown( rMEvt ); +} + +void AnnotationMenuButton::Paint( const Rectangle& /*rRect*/ ) +{ + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + SetFillColor(COL_BLACK); + else + SetFillColor( mrSidebarWin.ColorDark() ); + SetLineColor(); + const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) ); + DrawRect( aRect ); + + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + //draw rect around button + SetFillColor(COL_BLACK); + SetLineColor(COL_WHITE); + } + else + { + //draw button + Gradient aGradient; + if ( IsMouseOver() ) + aGradient = Gradient( GradientStyle_LINEAR, + ColorFromAlphaColor( 80, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark() ), + ColorFromAlphaColor( 15, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark() )); + else + aGradient = Gradient( GradientStyle_LINEAR, + ColorFromAlphaColor( 15, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark() ), + ColorFromAlphaColor( 80, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark() )); + DrawGradient( aRect, aGradient ); + + //draw rect around button + SetFillColor(); + SetLineColor( ColorFromAlphaColor( 90, mrSidebarWin.ColorAnchor(), mrSidebarWin.ColorDark() )); + } + DrawRect( aRect ); + + if ( mrSidebarWin.IsPreview() ) + { + Font aOldFont( mrSidebarWin.GetFont() ); + Font aFont(aOldFont); + Color aCol( COL_BLACK); + aFont.SetColor( aCol ); + aFont.SetHeight(200); + aFont.SetWeight(WEIGHT_MEDIUM); + SetFont( aFont ); + DrawText( aRect , + OUString("Edit Note"), + TEXT_DRAW_CENTER ); + SetFont( aOldFont ); + } + else + { + Rectangle aSymbolRect( aRect ); + // 25% distance to the left and right button border + const long nBorderDistanceLeftAndRight = ((aSymbolRect.GetWidth()*250)+500)/1000; + aSymbolRect.Left()+=nBorderDistanceLeftAndRight; + aSymbolRect.Right()-=nBorderDistanceLeftAndRight; + // 40% distance to the top button border + const long nBorderDistanceTop = ((aSymbolRect.GetHeight()*400)+500)/1000; + aSymbolRect.Top()+=nBorderDistanceTop; + // 15% distance to the bottom button border + const long nBorderDistanceBottom = ((aSymbolRect.GetHeight()*150)+500)/1000; + aSymbolRect.Bottom()-=nBorderDistanceBottom; + DecorationView aDecoView( this ); + aDecoView.DrawSymbol( aSymbolRect, SYMBOL_SPIN_DOWN, + ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() + ? Color( COL_WHITE ) + : Color( COL_BLACK ) ) ); + } +} + +void AnnotationMenuButton::KeyInput( const KeyEvent& rKeyEvt ) +{ + const KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + const sal_uInt16 nKey = rKeyCode.GetCode(); + if ( nKey == KEY_TAB ) + { + mrSidebarWin.ActivatePostIt(); + mrSidebarWin.GrabFocus(); + } + else + { + MenuButton::KeyInput( rKeyEvt ); + } +} + +} } // end of namespace sw::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/AnnotationMenuButton.hxx b/sw/source/uibase/docvw/AnnotationMenuButton.hxx new file mode 100644 index 000000000000..b90dea4de951 --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationMenuButton.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ANNOTATIONMENUBUTTON_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ANNOTATIONMENUBUTTON_HXX + +#include <vcl/menubtn.hxx> + +namespace sw { namespace sidebarwindows { + class SwSidebarWin; +} } + +namespace sw { namespace annotation { + +class AnnotationMenuButton : public MenuButton +{ + public: + AnnotationMenuButton( sw::sidebarwindows::SwSidebarWin& rSidebarWin ); + virtual ~AnnotationMenuButton(); + + // overloaded <MenuButton> methods + virtual void Select() SAL_OVERRIDE; + + // overloaded <Window> methods + virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE; + virtual void Paint( const Rectangle& rRect ) SAL_OVERRIDE; + virtual void KeyInput( const KeyEvent& rKeyEvt ) SAL_OVERRIDE; + + private: + sw::sidebarwindows::SwSidebarWin& mrSidebarWin; +}; + +} } // end of namespace sw::annotation + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/AnnotationWin.cxx b/sw/source/uibase/docvw/AnnotationWin.cxx new file mode 100644 index 000000000000..9ef1e482bae0 --- /dev/null +++ b/sw/source/uibase/docvw/AnnotationWin.cxx @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <AnnotationWin.hxx> + +#include <AnnotationMenuButton.hxx> +#include <PostItMgr.hxx> + +#include <annotation.hrc> +#include <popup.hrc> +#include <cmdid.h> + +#include <vcl/menu.hxx> + +#include <svl/undo.hxx> +#include <unotools/syslocale.hxx> +#include <svl/languageoptions.hxx> + +#include <editeng/postitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/langitem.hxx> + +#include <editeng/editview.hxx> +#include <editeng/outliner.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editobj.hxx> + +#include <docufld.hxx> +#include <txtfld.hxx> +#include <ndtxt.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <doc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <SwUndoField.hxx> + +#include <boost/scoped_ptr.hpp> + +namespace sw { namespace annotation { + +SwAnnotationWin::SwAnnotationWin( SwEditWin& rEditWin, + WinBits nBits, + SwPostItMgr& aMgr, + SwPostItBits aBits, + SwSidebarItem& rSidebarItem, + SwFmtFld* aField ) + : SwSidebarWin( rEditWin, nBits, aMgr, aBits, rSidebarItem ) + , mpFmtFld(aField) + , mpFld( static_cast<SwPostItField*>(aField->GetField())) + , mpButtonPopup(0) +{ +} + +SwAnnotationWin::~SwAnnotationWin() +{ + delete mpButtonPopup; +} + +void SwAnnotationWin::SetPostItText() +{ + //If the cursor was visible, then make it visible again after + //changing text, e.g. fdo#33599 + Cursor *pCursor = GetOutlinerView()->GetEditView().GetCursor(); + bool bCursorVisible = pCursor && pCursor->IsVisible(); + + //If the new text is the same as the old text, keep the same insertion + //point .e.g. fdo#33599 + mpFld = static_cast<SwPostItField*>(mpFmtFld->GetField()); + OUString sNewText = mpFld->GetPar2(); + bool bTextUnchanged = sNewText.equals(Engine()->GetEditEngine().GetText()); + ESelection aOrigSelection(GetOutlinerView()->GetEditView().GetSelection()); + + // get text from SwPostItField and insert into our textview + Engine()->SetModifyHdl( Link() ); + Engine()->EnableUndo( false ); + if( mpFld->GetTextObject() ) + Engine()->SetText( *mpFld->GetTextObject() ); + else + { + Engine()->Clear(); + GetOutlinerView()->SetAttribs(DefaultItem()); + GetOutlinerView()->InsertText(sNewText,false); + } + + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); + Engine()->EnableUndo( true ); + Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); + if (bTextUnchanged) + GetOutlinerView()->GetEditView().SetSelection(aOrigSelection); + if (bCursorVisible) + GetOutlinerView()->ShowCursor(); + Invalidate(); +} + +void SwAnnotationWin::UpdateData() +{ + if ( Engine()->IsModified() ) + { + IDocumentUndoRedo & rUndoRedo( + DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); + boost::scoped_ptr<SwField> pOldField; + if (rUndoRedo.DoesUndo()) + { + pOldField.reset(mpFld->Copy()); + } + mpFld->SetPar2(Engine()->GetEditEngine().GetText()); + mpFld->SetTextObject(Engine()->CreateParaObject()); + if (rUndoRedo.DoesUndo()) + { + SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + rUndoRedo.AppendUndo( + new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); + } + // so we get a new layout of notes (anchor position is still the same and we would otherwise not get one) + Mgr().SetLayout(); + // #i98686# if we have several views, all notes should update their text + mpFmtFld->Broadcast(SwFmtFldHint( 0, SWFMTFLD_CHANGED)); + DocView().GetDocShell()->SetModified(); + } + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); +} + +void SwAnnotationWin::Delete() +{ + SwSidebarWin::Delete(); + // we delete the field directly, the Mgr cleans up the PostIt by listening + DocView().GetWrtShellPtr()->GotoField(*mpFmtFld); + GrabFocusToDocument(); + DocView().GetWrtShellPtr()->DelRight(); +} + +void SwAnnotationWin::GotoPos() +{ + DocView().GetDocShell()->GetWrtShell()->GotoField(*mpFmtFld); +} + +sal_uInt32 SwAnnotationWin::MoveCaret() +{ + // if this is an answer, do not skip over all following ones, but insert directly behind the current one + // but when just leaving a note, skip all following ones as well to continue typing + return Mgr().IsAnswer() + ? 1 + : 1 + CountFollowing(); +} + +//returns true, if there is another note right before this note +bool SwAnnotationWin::CalcFollow() +{ + SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + SwTxtAttr * const pTxtAttr = + pTxtFld->GetTxtNode().GetTxtAttrForCharAt( + aPosition.nContent.GetIndex() - 1, + RES_TXTATR_ANNOTATION ); + const SwField* pFld = pTxtAttr ? pTxtAttr->GetFmtFld().GetField() : 0; + return pFld && (pFld->Which()== RES_POSTITFLD); +} + +// counts how many SwPostItField we have right after the current one +sal_uInt32 SwAnnotationWin::CountFollowing() +{ + sal_uInt32 aCount = 1; // we start with 1, so we have to subtract one at the end again + SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + + SwTxtAttr * pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( + aPosition.nContent.GetIndex() + 1, + RES_TXTATR_ANNOTATION ); + SwField* pFld = pTxtAttr + ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField()) + : 0; + while ( pFld && ( pFld->Which()== RES_POSTITFLD ) ) + { + aCount++; + pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( + aPosition.nContent.GetIndex() + aCount, + RES_TXTATR_ANNOTATION ); + pFld = pTxtAttr + ? const_cast<SwField*>(pTxtAttr->GetFmtFld().GetField()) + : 0; + } + return aCount - 1; +} + +MenuButton* SwAnnotationWin::CreateMenuButton() +{ + mpButtonPopup = new PopupMenu(SW_RES(MN_ANNOTATION_BUTTON)); + OUString aText = mpButtonPopup->GetItemText( FN_DELETE_NOTE_AUTHOR ); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1,GetAuthor()); + aText = aRewriter.Apply(aText); + mpButtonPopup->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); + MenuButton* pMenuButton = new AnnotationMenuButton( *this ); + pMenuButton->SetPopupMenu( mpButtonPopup ); + pMenuButton->Show(); + return pMenuButton; +} + +void SwAnnotationWin::InitAnswer(OutlinerParaObject* pText) +{ + //collect our old meta data + SwSidebarWin* pWin = Mgr().GetNextPostIt(KEY_PAGEUP, this); + const SvtSysLocale aSysLocale; + const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData(); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, pWin->GetAuthor()); + const OUString aText = aRewriter.Apply(SW_RESSTR(STR_REPLY)) + + " (" + rLocalData.getDate( pWin->GetDate()) + + ", " + rLocalData.getTime( pWin->GetTime(), false) + + "): \""; + GetOutlinerView()->InsertText(aText,false); + + // insert old, selected text or "..." + // TODO: iterate over all paragraphs, not only first one to find out if it is empty + if (!pText->GetTextObject().GetText(0).isEmpty()) + GetOutlinerView()->GetEditView().InsertText(pText->GetTextObject()); + else + GetOutlinerView()->InsertText(OUString("..."),false); + GetOutlinerView()->InsertText(OUString("\"\n"),false); + + GetOutlinerView()->SetSelection(ESelection(0,0,EE_PARA_ALL,EE_TEXTPOS_ALL)); + SfxItemSet aAnswerSet( DocView().GetDocShell()->GetPool() ); + aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT)); + aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC)); + GetOutlinerView()->SetAttribs(aAnswerSet); + GetOutlinerView()->SetSelection(ESelection(EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT,EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT)); + + //remove all attributes and reset our standard ones + GetOutlinerView()->GetEditView().RemoveAttribsKeepLanguages(true); + GetOutlinerView()->SetAttribs(DefaultItem()); + // lets insert an undo step so the initial text can be easily deleted + // but do not use UpdateData() directly, would set modified state again and reentrance into Mgr + Engine()->SetModifyHdl( Link() ); + IDocumentUndoRedo & rUndoRedo( + DocView().GetDocShell()->GetDoc()->GetIDocumentUndoRedo()); + boost::scoped_ptr<SwField> pOldField; + if (rUndoRedo.DoesUndo()) + { + pOldField.reset(mpFld->Copy()); + } + mpFld->SetPar2(Engine()->GetEditEngine().GetText()); + mpFld->SetTextObject(Engine()->CreateParaObject()); + if (rUndoRedo.DoesUndo()) + { + SwTxtFld *const pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + rUndoRedo.AppendUndo( + new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); + } + Engine()->SetModifyHdl( LINK( this, SwAnnotationWin, ModifyHdl ) ); + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); +} + +SvxLanguageItem SwAnnotationWin::GetLanguage(void) +{ + // set initial language for outliner + sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpFld->GetLanguage() ); + sal_uInt16 nLangWhichId = 0; + switch (nScriptType) + { + case SCRIPTTYPE_LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break; + case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; + case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; + default: OSL_FAIL("GetLanguage: wrong script type"); + } + return SvxLanguageItem(mpFld->GetLanguage(),nLangWhichId); +} + +bool SwAnnotationWin::IsProtected() +{ + return SwSidebarWin::IsProtected() || + GetLayoutStatus() == SwPostItHelper::DELETED || + ( mpFmtFld && mpFmtFld->IsProtect() ); +} + +OUString SwAnnotationWin::GetAuthor() +{ + return mpFld->GetPar1(); +} + +Date SwAnnotationWin::GetDate() +{ + return mpFld->GetDate(); +} + +Time SwAnnotationWin::GetTime() +{ + return mpFld->GetTime(); +} + +} } // end of namespace sw::annotation + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/DashedLine.cxx b/sw/source/uibase/docvw/DashedLine.cxx new file mode 100644 index 000000000000..e9e343b3dc27 --- /dev/null +++ b/sw/source/uibase/docvw/DashedLine.cxx @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <DashedLine.hxx> + +#include <basegfx/color/bcolortools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +SwDashedLine::SwDashedLine( Window* pParent, Color& ( *pColorFn )() ) : + FixedLine( pParent, WB_DIALOGCONTROL | WB_HORZ ), + m_pColorFn( pColorFn ) +{ +} + +SwDashedLine::~SwDashedLine( ) +{ +} + +void SwDashedLine::Paint( const Rectangle& ) +{ + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + drawinglayer::processor2d::BaseProcessor2D * pProcessor = + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( + *this, aNewViewInfos ); + + // Compute the start and end points + const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) ); + double nHalfWidth = double( aRect.Top() + aRect.Bottom() ) / 2.0; + + basegfx::B2DPoint aStart( double( aRect.Left() ), nHalfWidth ); + basegfx::B2DPoint aEnd( double( aRect.Right() ), nHalfWidth ); + + basegfx::B2DPolygon aPolygon; + aPolygon.append( aStart ); + aPolygon.append( aEnd ); + + drawinglayer::primitive2d::Primitive2DSequence aSeq( 1 ); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + + std::vector< double > aStrokePattern; + basegfx::BColor aColor = m_pColorFn().getBColor(); + if ( rSettings.GetHighContrastMode( ) ) + { + // Only a solid line in high contrast mode + aColor = rSettings.GetDialogTextColor().getBColor(); + } + else + { + // Get a color for the contrast + basegfx::BColor aHslLine = basegfx::tools::rgb2hsl( aColor ); + double nLuminance = aHslLine.getZ(); + nLuminance += ( 1.0 - nLuminance ) * 0.75; + if ( aHslLine.getZ() > 0.7 ) + nLuminance = aHslLine.getZ() * 0.7; + aHslLine.setZ( nLuminance ); + const basegfx::BColor aOtherColor = basegfx::tools::hsl2rgb( aHslLine ); + + // Compute the plain line + drawinglayer::primitive2d::PolygonHairlinePrimitive2D * pPlainLine = + new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aPolygon, aOtherColor ); + + aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( pPlainLine ); + // Dashed line in twips + aStrokePattern.push_back( 3 ); + aStrokePattern.push_back( 3 ); + + aSeq.realloc( 2 ); + } + + // Compute the dashed line primitive + drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D * pLine = + new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D ( + basegfx::B2DPolyPolygon( aPolygon ), + drawinglayer::attribute::LineAttribute( m_pColorFn().getBColor() ), + drawinglayer::attribute::StrokeAttribute( aStrokePattern ) ); + + aSeq[ aSeq.getLength() - 1 ] = drawinglayer::primitive2d::Primitive2DReference( pLine ); + + pProcessor->process( aSeq ); + delete pProcessor; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/FrameControlsManager.cxx b/sw/source/uibase/docvw/FrameControlsManager.cxx new file mode 100644 index 000000000000..67d8006f4aa5 --- /dev/null +++ b/sw/source/uibase/docvw/FrameControlsManager.cxx @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <edtwin.hxx> +#include <FrameControlsManager.hxx> +#include <HeaderFooterWin.hxx> +#include <PageBreakWin.hxx> +#include <pagefrm.hxx> +#include <viewopt.hxx> +#include <view.hxx> +#include <wrtsh.hxx> + +using namespace std; + +SwFrameControlsManager::SwFrameControlsManager( SwEditWin* pEditWin ) : + m_pEditWin( pEditWin ), + m_aControls( ) +{ +} + +SwFrameControlsManager::~SwFrameControlsManager() +{ +} + +SwFrameControlsManager::SwFrameControlsManager( const SwFrameControlsManager& rCopy ) : + m_pEditWin( rCopy.m_pEditWin ), + m_aControls( rCopy.m_aControls ) +{ +} + +const SwFrameControlsManager& SwFrameControlsManager::operator=( const SwFrameControlsManager& rCopy ) +{ + m_pEditWin = rCopy.m_pEditWin; + m_aControls = rCopy.m_aControls; + return *this; +} + +SwFrameControlPtr SwFrameControlsManager::GetControl( FrameControlType eType, const SwFrm* pFrm ) +{ + SwFrameControlPtrMap& rControls = m_aControls[eType]; + + SwFrameControlPtrMap::iterator aIt = rControls.find(pFrm); + + if (aIt != rControls.end()) + return aIt->second; + + return SwFrameControlPtr(); +} + +void SwFrameControlsManager::RemoveControls( const SwFrm* pFrm ) +{ + map< FrameControlType, SwFrameControlPtrMap >::iterator pIt = m_aControls.begin(); + + while ( pIt != m_aControls.end() ) + { + SwFrameControlPtrMap& rMap = pIt->second; + rMap.erase(pFrm); + ++pIt; + } +} + +void SwFrameControlsManager::RemoveControlsByType( FrameControlType eType, const SwFrm* pFrm ) +{ + SwFrameControlPtrMap& rMap = m_aControls[eType]; + rMap.erase(pFrm); +} + +void SwFrameControlsManager::HideControls( FrameControlType eType ) +{ + SwFrameControlPtrMap::iterator pIt = m_aControls[eType].begin(); + while ( pIt != m_aControls[eType].end() ) + { + pIt->second->ShowAll( false ); + ++pIt; + } +} + +void SwFrameControlsManager::SetReadonlyControls( bool bReadonly ) +{ + map< FrameControlType, SwFrameControlPtrMap >::iterator pIt = m_aControls.begin(); + + while ( pIt != m_aControls.end() ) + { + SwFrameControlPtrMap::iterator aCtrlIt = pIt->second.begin(); + while ( aCtrlIt != pIt->second.end() ) + { + aCtrlIt->second->SetReadonly( bReadonly ); + ++aCtrlIt; + } + ++pIt; + } +} + +void SwFrameControlsManager::SetHeaderFooterControl( const SwPageFrm* pPageFrm, FrameControlType eType, Point aOffset ) +{ + OSL_ASSERT( eType == Header || eType == Footer ); + + // Check if we already have the control + SwFrameControlPtr pControl; + const bool bHeader = ( eType == Header ); + + SwFrameControlPtrMap& rControls = m_aControls[eType]; + + SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrm); + if (lb != rControls.end() && !(rControls.key_comp()(pPageFrm, lb->first))) + pControl = lb->second; + else + { + SwFrameControlPtr pNewControl( new SwHeaderFooterWin( m_pEditWin, pPageFrm, bHeader ) ); + const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions(); + pNewControl->SetReadonly( pViewOpt->IsReadonly() ); + rControls.insert(lb, make_pair(pPageFrm, pNewControl)); + pControl.swap( pNewControl ); + } + + Rectangle aPageRect = m_pEditWin->LogicToPixel( pPageFrm->Frm().SVRect() ); + + SwHeaderFooterWin* pHFWin = dynamic_cast< SwHeaderFooterWin* >( pControl.get() ); + assert(pHFWin->IsHeader() == bHeader); + pHFWin->SetOffset( aOffset, aPageRect.Left(), aPageRect.Right() ); + + if ( !pHFWin->IsVisible() ) + pControl->ShowAll( true ); +} + +void SwFrameControlsManager::SetPageBreakControl( const SwPageFrm* pPageFrm ) +{ + // Check if we already have the control + SwFrameControlPtr pControl; + + SwFrameControlPtrMap& rControls = m_aControls[PageBreak]; + + SwFrameControlPtrMap::iterator lb = rControls.lower_bound(pPageFrm); + if (lb != rControls.end() && !(rControls.key_comp()(pPageFrm, lb->first))) + pControl = lb->second; + else + { + SwFrameControlPtr pNewControl( new SwPageBreakWin( m_pEditWin, pPageFrm ) ); + const SwViewOption* pViewOpt = m_pEditWin->GetView().GetWrtShell().GetViewOptions(); + pNewControl->SetReadonly( pViewOpt->IsReadonly() ); + + rControls.insert(lb, make_pair(pPageFrm, pNewControl)); + + pControl.swap( pNewControl ); + } + + SwPageBreakWin* pWin = dynamic_cast< SwPageBreakWin* >( pControl.get() ); + pWin->UpdatePosition(); + if ( !pWin->IsVisible() ) + pControl->ShowAll( true ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/HeaderFooterWin.cxx b/sw/source/uibase/docvw/HeaderFooterWin.cxx new file mode 100644 index 000000000000..b68c59a194d8 --- /dev/null +++ b/sw/source/uibase/docvw/HeaderFooterWin.cxx @@ -0,0 +1,520 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <app.hrc> +#include <docvw.hrc> +#include <globals.hrc> +#include <popup.hrc> +#include <svtools/svtools.hrc> + +#include <cmdid.h> +#include <DashedLine.hxx> +#include <docsh.hxx> +#include <edtwin.hxx> +#include <fmthdft.hxx> +#include <HeaderFooterWin.hxx> +#include <pagedesc.hxx> +#include <pagefrm.hxx> +#include <SwRewriter.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <wrtsh.hxx> + +#include <basegfx/color/bcolortools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/vector/b2dsize.hxx> +#include <drawinglayer/attribute/fillgradientattribute.hxx> +#include <drawinglayer/attribute/fontattribute.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/textlayoutdevice.hxx> +#include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <editeng/boxitem.hxx> +#include <svtools/svtresid.hxx> +#include <svx/hdft.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <vcl/decoview.hxx> +#include <vcl/gradient.hxx> +#include <vcl/menubtn.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#define TEXT_PADDING 5 +#define BOX_DISTANCE 10 +#define BUTTON_WIDTH 18 + +using namespace basegfx; +using namespace basegfx::tools; +using namespace drawinglayer::attribute; + +namespace +{ + static basegfx::BColor lcl_GetFillColor( basegfx::BColor aLineColor ) + { + basegfx::BColor aHslLine = basegfx::tools::rgb2hsl( aLineColor ); + double nLuminance = aHslLine.getZ() * 2.5; + if ( nLuminance == 0 ) + nLuminance = 0.5; + else if ( nLuminance >= 1.0 ) + nLuminance = aHslLine.getZ() * 0.4; + aHslLine.setZ( nLuminance ); + return basegfx::tools::hsl2rgb( aHslLine ); + } + + static basegfx::BColor lcl_GetLighterGradientColor( basegfx::BColor aDarkColor ) + { + basegfx::BColor aHslDark = basegfx::tools::rgb2hsl( aDarkColor ); + double nLuminance = aHslDark.getZ() * 255 + 20; + aHslDark.setZ( nLuminance / 255.0 ); + return basegfx::tools::hsl2rgb( aHslDark ); + } + + static B2DPolygon lcl_GetPolygon( const Rectangle& rRect, bool bHeader ) + { + const double nRadius = 3; + const double nKappa((M_SQRT2 - 1.0) * 4.0 / 3.0); + + B2DPolygon aPolygon; + aPolygon.append( B2DPoint( rRect.Left(), rRect.Top() ) ); + + { + B2DPoint aCorner( rRect.Left(), rRect.Bottom() ); + B2DPoint aStart( rRect.Left(), rRect.Bottom() - nRadius ); + B2DPoint aEnd( rRect.Left() + nRadius, rRect.Bottom() ); + aPolygon.append( aStart ); + aPolygon.appendBezierSegment( + interpolate( aStart, aCorner, nKappa ), + interpolate( aEnd, aCorner, nKappa ), + aEnd ); + } + + { + B2DPoint aCorner( rRect.Right(), rRect.Bottom() ); + B2DPoint aStart( rRect.Right() - nRadius, rRect.Bottom() ); + B2DPoint aEnd( rRect.Right(), rRect.Bottom() - nRadius ); + aPolygon.append( aStart ); + aPolygon.appendBezierSegment( + interpolate( aStart, aCorner, nKappa ), + interpolate( aEnd, aCorner, nKappa ), + aEnd ); + } + + aPolygon.append( B2DPoint( rRect.Right(), rRect.Top() ) ); + + if ( !bHeader ) + { + B2DRectangle aBRect( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ); + B2DHomMatrix aRotation = createRotateAroundPoint( + aBRect.getCenterX(), aBRect.getCenterY(), M_PI ); + aPolygon.transform( aRotation ); + } + + return aPolygon; + } +} + +SwHeaderFooterWin::SwHeaderFooterWin( SwEditWin* pEditWin, const SwPageFrm* pPageFrm, bool bHeader ) : + MenuButton( pEditWin, WB_DIALOGCONTROL ), + SwFrameControl( pEditWin, pPageFrm ), + m_sLabel( ), + m_bIsHeader( bHeader ), + m_pPopupMenu( NULL ), + m_pLine( NULL ), + m_bIsAppearing( false ), + m_nFadeRate( 100 ), + m_aFadeTimer( ) +{ + // Get the font and configure it + Font aFont = GetSettings().GetStyleSettings().GetToolFont(); + SetZoomedPointFont( aFont ); + + // Use pixels for the rest of the drawing + SetMapMode( MapMode ( MAP_PIXEL ) ); + + // Create the line control + m_pLine = new SwDashedLine( GetEditWin(), &SwViewOption::GetHeaderFooterMarkColor ); + m_pLine->SetZOrder( this, WINDOW_ZORDER_BEFOR ); + + // Create and set the PopupMenu + m_pPopupMenu = new PopupMenu( SW_RES( MN_HEADERFOOTER_BUTTON ) ); + + // Rewrite the menu entries' text + if ( m_bIsHeader ) + { + m_pPopupMenu->SetItemText( FN_HEADERFOOTER_EDIT, SW_RESSTR( STR_FORMAT_HEADER ) ); + m_pPopupMenu->SetItemText( FN_HEADERFOOTER_DELETE, SW_RESSTR( STR_DELETE_HEADER ) ); + } + else + { + m_pPopupMenu->SetItemText( FN_HEADERFOOTER_EDIT, SW_RESSTR( STR_FORMAT_FOOTER ) ); + m_pPopupMenu->SetItemText( FN_HEADERFOOTER_DELETE, SW_RESSTR( STR_DELETE_FOOTER ) ); + } + + SetPopupMenu( m_pPopupMenu ); + + m_aFadeTimer.SetTimeout( 50 ); + m_aFadeTimer.SetTimeoutHdl( LINK( this, SwHeaderFooterWin, FadeHandler ) ); +} + +SwHeaderFooterWin::~SwHeaderFooterWin( ) +{ + delete m_pPopupMenu; + delete m_pLine; +} + +const SwPageFrm* SwHeaderFooterWin::GetPageFrame( ) +{ + return static_cast< const SwPageFrm * >( GetFrame( ) ); +} + +void SwHeaderFooterWin::SetOffset( Point aOffset, long nXLineStart, long nXLineEnd ) +{ + // Compute the text to show + m_sLabel = SW_RESSTR( STR_HEADER_TITLE ); + if ( !m_bIsHeader ) + m_sLabel = SW_RESSTR( STR_FOOTER_TITLE ); + sal_Int32 nPos = m_sLabel.lastIndexOf( "%1" ); + m_sLabel = m_sLabel.replaceAt( nPos, 2, GetPageFrame()->GetPageDesc()->GetName() ); + + // Compute the text size and get the box position & size from it + Rectangle aTextRect; + GetTextBoundRect( aTextRect, OUString( m_sLabel ) ); + Rectangle aTextPxRect = LogicToPixel( aTextRect ); + FontMetric aFontMetric = GetFontMetric( GetFont() ); + Size aBoxSize ( aTextPxRect.GetWidth() + BUTTON_WIDTH + TEXT_PADDING * 2, + aFontMetric.GetLineHeight() + TEXT_PADDING * 2 ); + + long nYFooterOff = 0; + if ( !m_bIsHeader ) + nYFooterOff = aBoxSize.Height(); + + Point aBoxPos( aOffset.X() - aBoxSize.Width() - BOX_DISTANCE, + aOffset.Y() - nYFooterOff ); + + if ( Application::GetSettings().GetLayoutRTL() ) + { + aBoxPos.setX( aOffset.X() + BOX_DISTANCE ); + } + + // Set the position & Size of the window + SetPosSizePixel( aBoxPos, aBoxSize ); + + double nYLinePos = aBoxPos.Y(); + if ( !m_bIsHeader ) + nYLinePos += aBoxSize.Height(); + Point aLinePos( nXLineStart, nYLinePos ); + Size aLineSize( nXLineEnd - nXLineStart, 1 ); + m_pLine->SetPosSizePixel( aLinePos, aLineSize ); +} + +void SwHeaderFooterWin::ShowAll( bool bShow ) +{ + if ( !PopupMenu::IsInExecute() ) + { + m_bIsAppearing = bShow; + + if ( m_aFadeTimer.IsActive( ) ) + m_aFadeTimer.Stop(); + m_aFadeTimer.Start( ); + } +} + +bool SwHeaderFooterWin::Contains( const Point &rDocPt ) const +{ + Rectangle aRect( GetPosPixel(), GetSizePixel() ); + if ( aRect.IsInside( rDocPt ) ) + return true; + + Rectangle aLineRect( m_pLine->GetPosPixel(), m_pLine->GetSizePixel() ); + if ( aLineRect.IsInside( rDocPt ) ) + return true; + + return false; +} + +void SwHeaderFooterWin::Paint( const Rectangle& ) +{ + const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) ); + drawinglayer::primitive2d::Primitive2DSequence aSeq( 3 ); + + B2DPolygon aPolygon = lcl_GetPolygon( aRect, m_bIsHeader ); + + // Colors + basegfx::BColor aLineColor = SwViewOption::GetHeaderFooterMarkColor().getBColor(); + basegfx::BColor aFillColor = lcl_GetFillColor( aLineColor ); + basegfx::BColor aLighterColor = lcl_GetLighterGradientColor( aFillColor ); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + if ( rSettings.GetHighContrastMode() ) + { + aFillColor = rSettings.GetDialogColor( ).getBColor(); + aLineColor = rSettings.GetDialogTextColor( ).getBColor(); + + aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + B2DPolyPolygon( aPolygon ), aFillColor ) ); + } + else + { + B2DRectangle aGradientRect( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() ); + double nAngle = M_PI; + if ( m_bIsHeader ) + nAngle = 0; + FillGradientAttribute aFillAttrs( GRADIENTSTYLE_LINEAR, 0.0, 0.0, 0.0, nAngle, + aLighterColor, aFillColor, 10 ); + aSeq[0] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::FillGradientPrimitive2D( + aGradientRect, aFillAttrs ) ); + } + + // Create the border lines primitive + aSeq[1] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aPolygon, aLineColor ) ); + + // Create the text primitive + B2DVector aFontSize; + FontAttribute aFontAttr = drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontSize, GetFont(), false, false ); + + FontMetric aFontMetric = GetFontMetric( GetFont() ); + double nTextOffsetY = aFontMetric.GetAscent() + TEXT_PADDING; + Point aTextPos( TEXT_PADDING, nTextOffsetY ); + + basegfx::B2DHomMatrix aTextMatrix( createScaleTranslateB2DHomMatrix( + aFontSize.getX(), aFontSize.getY(), + double( aTextPos.X() ), double( aTextPos.Y() ) ) ); + + aSeq[2] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::TextSimplePortionPrimitive2D( + aTextMatrix, + OUString( m_sLabel ), 0, m_sLabel.getLength(), + std::vector< double >( ), + aFontAttr, + com::sun::star::lang::Locale(), + aLineColor ) ); + + // Create the 'plus' or 'arrow' primitive + B2DRectangle aSignArea( B2DPoint( aRect.Right() - BUTTON_WIDTH, 0.0 ), + B2DSize( aRect.Right(), aRect.getHeight() ) ); + + B2DPolygon aSign; + if ( IsEmptyHeaderFooter( ) ) + { + // Create the + polygon + double nLeft = aSignArea.getMinX() + TEXT_PADDING; + double nRight = aSignArea.getMaxX() - TEXT_PADDING; + double nHalfW = ( nRight - nLeft ) / 2.0; + + double nTop = aSignArea.getCenterY() - nHalfW; + double nBottom = aSignArea.getCenterY() + nHalfW; + + aSign.append( B2DPoint( nLeft, aSignArea.getCenterY() - 1.0 ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() - 1.0 ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() - 1.0, nTop ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() + 1.0, nTop ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() - 1.0 ) ); + aSign.append( B2DPoint( nRight, aSignArea.getCenterY() - 1.0 ) ); + aSign.append( B2DPoint( nRight, aSignArea.getCenterY() + 1.0 ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() + 1.0, aSignArea.getCenterY() + 1.0 ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() + 1.0, nBottom ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() - 1.0, nBottom ) ); + aSign.append( B2DPoint( aSignArea.getCenterX() - 1.0, aSignArea.getCenterY() + 1.0 ) ); + aSign.append( B2DPoint( nLeft, aSignArea.getCenterY() + 1.0 ) ); + aSign.setClosed( true ); + } + else + { + // Create the v polygon + B2DPoint aLeft( aSignArea.getMinX() + TEXT_PADDING, aSignArea.getCenterY() ); + B2DPoint aRight( aSignArea.getMaxX() - TEXT_PADDING, aSignArea.getCenterY() ); + B2DPoint aBottom( ( aLeft.getX() + aRight.getX() ) / 2.0, aLeft.getY() + 4.0 ); + aSign.append( aLeft ); + aSign.append( aRight ); + aSign.append( aBottom ); + aSign.setClosed( true ); + } + + BColor aSignColor = Color( COL_BLACK ).getBColor( ); + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + aSignColor = Color( COL_WHITE ).getBColor( ); + + aSeq.realloc( aSeq.getLength() + 1 ); + aSeq[ aSeq.getLength() - 1 ] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + B2DPolyPolygon( aSign ), aSignColor ) ); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + drawinglayer::processor2d::BaseProcessor2D * pProcessor = + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( + *this, aNewViewInfos ); + + // TODO Ghost it all if needed + drawinglayer::primitive2d::Primitive2DSequence aGhostedSeq( 1 ); + double nFadeRate = double( m_nFadeRate ) / 100.0; + const basegfx::BColorModifierSharedPtr aBColorModifier( + new basegfx::BColorModifier_interpolate( + Color( COL_WHITE ).getBColor(), + 1.0 - nFadeRate)); + aGhostedSeq[0] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::ModifiedColorPrimitive2D( + aSeq, aBColorModifier ) ); + + pProcessor->process( aGhostedSeq ); + delete pProcessor; +} + +bool SwHeaderFooterWin::IsEmptyHeaderFooter( ) +{ + bool bResult = true; + + // Actually check it + const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + + bool const bFirst(GetPageFrame()->OnFirstPage()); + const SwFrmFmt *const pFmt = (GetPageFrame()->OnRightPage()) + ? pDesc->GetRightFmt(bFirst) + : pDesc->GetLeftFmt(bFirst); + + if ( pFmt ) + { + if ( m_bIsHeader ) + bResult = !pFmt->GetHeader().IsActive(); + else + bResult = !pFmt->GetFooter().IsActive(); + } + + return bResult; +} + +void SwHeaderFooterWin::ExecuteCommand( sal_uInt16 nSlot ) +{ + SwView& rView = GetEditWin()->GetView(); + SwWrtShell& rSh = rView.GetWrtShell(); + + const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + switch ( nSlot ) + { + case FN_HEADERFOOTER_EDIT: + { + OString sPageId = m_bIsHeader ? OString("header") : OString("footer"); + rView.GetDocShell()->FormatPage(rStyleName, sPageId, rSh); + } + break; + case FN_HEADERFOOTER_BORDERBACK: + { + const SwPageDesc* pDesc = GetPageFrame()->GetPageDesc(); + const SwFrmFmt& rMaster = pDesc->GetMaster(); + SwFrmFmt* pHFFmt = const_cast< SwFrmFmt* >( rMaster.GetFooter().GetFooterFmt() ); + if ( m_bIsHeader ) + pHFFmt = const_cast< SwFrmFmt* >( rMaster.GetHeader().GetHeaderFmt() ); + + SfxItemPool* pPool = pHFFmt->GetAttrSet().GetPool(); + SfxItemSet aSet( *pPool, + RES_BACKGROUND, RES_BACKGROUND, + RES_BOX, RES_BOX, + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER, + RES_SHADOW, RES_SHADOW, 0 ); + + aSet.Put( pHFFmt->GetAttrSet() ); + + // Create a box info item... needed by the dialog + SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER ); + const SfxPoolItem *pBoxInfo; + if ( SFX_ITEM_SET == pHFFmt->GetAttrSet().GetItemState( SID_ATTR_BORDER_INNER, + true, &pBoxInfo) ) + aBoxInfo = *(SvxBoxInfoItem*)pBoxInfo; + + aBoxInfo.SetTable( false ); + aBoxInfo.SetDist( true); + aBoxInfo.SetMinDist( false ); + aBoxInfo.SetDefDist( MIN_BORDER_DIST ); + aBoxInfo.SetValid( VALID_DISABLE ); + aSet.Put( aBoxInfo ); + + if ( svx::ShowBorderBackgroundDlg( this, &aSet, true ) ) + { + const SfxPoolItem* pItem; + if ( SFX_ITEM_SET == aSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) { + pHFFmt->SetFmtAttr( *pItem ); + rView.GetDocShell()->SetModified(true); + } + + if ( SFX_ITEM_SET == aSet.GetItemState( RES_BOX, false, &pItem ) ) { + pHFFmt->SetFmtAttr( *pItem ); + rView.GetDocShell()->SetModified(true); + } + + if ( SFX_ITEM_SET == aSet.GetItemState( RES_SHADOW, false, &pItem ) ) { + pHFFmt->SetFmtAttr( *pItem ); + rView.GetDocShell()->SetModified(true); + } + } + } + break; + case FN_HEADERFOOTER_DELETE: + { + rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, false, true ); + } + break; + default: + break; + } +} + +void SwHeaderFooterWin::SetReadonly( bool bReadonly ) +{ + ShowAll( !bReadonly ); +} + +void SwHeaderFooterWin::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( IsEmptyHeaderFooter( ) ) + { + SwView& rView = GetEditWin()->GetView(); + SwWrtShell& rSh = rView.GetWrtShell(); + + const OUString& rStyleName = GetPageFrame()->GetPageDesc()->GetName(); + rSh.ChangeHeaderOrFooter( rStyleName, m_bIsHeader, true, false ); + } + else + MenuButton::MouseButtonDown( rMEvt ); +} + +void SwHeaderFooterWin::Select( ) +{ + ExecuteCommand( GetCurItemId() ); +} + +IMPL_LINK_NOARG(SwHeaderFooterWin, FadeHandler) +{ + if ( m_bIsAppearing && m_nFadeRate > 0 ) + m_nFadeRate -= 25; + else if ( !m_bIsAppearing && m_nFadeRate < 100 ) + m_nFadeRate += 25; + + if ( m_nFadeRate != 100 && !IsVisible() ) + { + Show( true ); + m_pLine->Show( true ); + } + else if ( m_nFadeRate == 100 && IsVisible( ) ) + { + Show( false ); + m_pLine->Show( false ); + } + else + Invalidate(); + + if ( IsVisible( ) && m_nFadeRate > 0 && m_nFadeRate < 100 ) + m_aFadeTimer.Start(); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/OverlayRanges.cxx b/sw/source/uibase/docvw/OverlayRanges.cxx new file mode 100644 index 000000000000..7b44a9b3bdb9 --- /dev/null +++ b/sw/source/uibase/docvw/OverlayRanges.cxx @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <OverlayRanges.hxx> +#include <view.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/svdview.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygoncutter.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> + +namespace +{ + // combine ranges geometrically to a single, ORed polygon + basegfx::B2DPolyPolygon impCombineRangesToPolyPolygon(const std::vector< basegfx::B2DRange >& rRanges) + { + const sal_uInt32 nCount(rRanges.size()); + basegfx::B2DPolyPolygon aRetval; + + for(sal_uInt32 a(0); a < nCount; a++) + { + const basegfx::B2DPolygon aDiscretePolygon(basegfx::tools::createPolygonFromRect(rRanges[a])); + + if(0 == a) + { + aRetval.append(aDiscretePolygon); + } + else + { + aRetval = basegfx::tools::solvePolygonOperationOr(aRetval, basegfx::B2DPolyPolygon(aDiscretePolygon)); + } + } + + return aRetval; + } +} + +namespace sw +{ + namespace overlay + { + drawinglayer::primitive2d::Primitive2DSequence OverlayRanges::createOverlayObjectPrimitive2DSequence() + { + const sal_uInt32 nCount(getRanges().size()); + drawinglayer::primitive2d::Primitive2DSequence aRetval; + aRetval.realloc(nCount); + for ( sal_uInt32 a = 0; a < nCount; ++a ) + { + const basegfx::BColor aRGBColor(getBaseColor().getBColor()); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(maRanges[a])); + aRetval[a] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + aRGBColor)); + } + // embed all rectangles in transparent paint + const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer; + const sal_uInt16 nTransparence( aSvtOptionsDrawinglayer.GetTransparentSelectionPercent() ); + const double fTransparence( nTransparence / 100.0 ); + const drawinglayer::primitive2d::Primitive2DReference aUnifiedTransparence( + new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + aRetval, + fTransparence)); + + if ( mbShowSolidBorder ) + { + const basegfx::BColor aRGBColor(getBaseColor().getBColor()); + const basegfx::B2DPolyPolygon aPolyPolygon(impCombineRangesToPolyPolygon(getRanges())); + const drawinglayer::primitive2d::Primitive2DReference aOutline( + new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( + aPolyPolygon, + aRGBColor)); + + aRetval.realloc(2); + aRetval[0] = aUnifiedTransparence; + aRetval[1] = aOutline; + } + else + { + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aUnifiedTransparence, 1); + } + + return aRetval; + } + + /*static*/ OverlayRanges* OverlayRanges::CreateOverlayRange( + SwView& rDocView, + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ) + { + OverlayRanges* pOverlayRanges = NULL; + + SdrView* pView = rDocView.GetDrawView(); + if ( pView != NULL ) + { + SdrPaintWindow* pCandidate = pView->GetPaintWindow(0); + rtl::Reference<sdr::overlay::OverlayManager> xTargetOverlay = pCandidate->GetOverlayManager(); + + if ( xTargetOverlay.is() ) + { + pOverlayRanges = new sw::overlay::OverlayRanges( rColor, rRanges, bShowSolidBorder ); + xTargetOverlay->add( *pOverlayRanges ); + } + } + + return pOverlayRanges; + } + + OverlayRanges::OverlayRanges( + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ) + : sdr::overlay::OverlayObject( rColor ) + , maRanges( rRanges ) + , mbShowSolidBorder( bShowSolidBorder ) + { + // no AA for highlight overlays + allowAntiAliase(false); + } + + OverlayRanges::~OverlayRanges() + { + if( getOverlayManager() ) + { + getOverlayManager()->remove(*this); + } + } + + void OverlayRanges::setRanges(const std::vector< basegfx::B2DRange >& rNew) + { + if(rNew != maRanges) + { + maRanges = rNew; + objectChange(); + } + } + + void OverlayRanges::ShowSolidBorder() + { + if ( !mbShowSolidBorder ) + { + mbShowSolidBorder = true; + objectChange(); + } + } + + void OverlayRanges::HideSolidBorder() + { + if ( mbShowSolidBorder ) + { + mbShowSolidBorder = false; + objectChange(); + } + } + + } // end of namespace overlay +} // end of namespace sdr + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/OverlayRanges.hxx b/sw/source/uibase/docvw/OverlayRanges.hxx new file mode 100644 index 000000000000..4458af4587f2 --- /dev/null +++ b/sw/source/uibase/docvw/OverlayRanges.hxx @@ -0,0 +1,78 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_OVERLAYRANGES_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_OVERLAYRANGES_HXX + +#include <svx/sdr/overlay/overlayobject.hxx> +#include <basegfx/range/b2drange.hxx> + +#include <vector> + +class SwView; + +namespace sw +{ + namespace overlay + { + class OverlayRanges : public sdr::overlay::OverlayObject + { + protected: + // geometry of overlay + std::vector< basegfx::B2DRange > maRanges; + + bool mbShowSolidBorder; + + // geometry creation for OverlayObject + virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence() SAL_OVERRIDE; + + public: + static OverlayRanges* CreateOverlayRange( + SwView& rDocView, + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ); + + virtual ~OverlayRanges(); + + // data read access + inline const std::vector< basegfx::B2DRange >& getRanges() const + { + return maRanges; + } + + // data write access + void setRanges(const std::vector< basegfx::B2DRange >& rNew); + + void ShowSolidBorder(); + void HideSolidBorder(); + + private: + OverlayRanges( + const Color& rColor, + const std::vector< basegfx::B2DRange >& rRanges, + const bool bShowSolidBorder ); + + }; + } // end of namespace overlay +} // end of namespace sw + +#endif // INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_OVERLAYRANGES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/PageBreakWin.cxx b/sw/source/uibase/docvw/PageBreakWin.cxx new file mode 100644 index 000000000000..876961aab601 --- /dev/null +++ b/sw/source/uibase/docvw/PageBreakWin.cxx @@ -0,0 +1,463 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <globals.hrc> +#include <popup.hrc> +#include <utlui.hrc> + +#include <cmdid.h> +#include <cntfrm.hxx> +#include <DashedLine.hxx> +#include <doc.hxx> +#include <edtwin.hxx> +#include <fmtpdsc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <PageBreakWin.hxx> +#include <pagefrm.hxx> +#include <PostItMgr.hxx> +#include <uiitems.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <wrtsh.hxx> + +#include <basegfx/color/bcolortools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx> +#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <editeng/formatbreakitem.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/stritem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> + +#define BUTTON_WIDTH 30 +#define BUTTON_HEIGHT 19 +#define ARROW_WIDTH 9 + +using namespace basegfx; +using namespace basegfx::tools; + +namespace +{ + class SwBreakDashedLine : public SwDashedLine + { + private: + SwPageBreakWin* m_pWin; + + public: + SwBreakDashedLine( Window* pParent, Color& ( *pColorFn )(), SwPageBreakWin* pWin ) : + SwDashedLine( pParent, pColorFn ), + m_pWin( pWin ) {}; + + virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE; + }; + + void SwBreakDashedLine::MouseMove( const MouseEvent& rMEvt ) + { + if ( rMEvt.IsLeaveWindow() ) + { + // don't fade if we just move to the 'button' + Point aEventPos( GetPosPixel() + rMEvt.GetPosPixel() ); + if ( !m_pWin->Contains( aEventPos ) || !m_pWin->IsVisible() ) + m_pWin->Fade( false ); + } + else if ( !m_pWin->IsVisible() ) + { + m_pWin->Fade( true ); + } + + if ( !rMEvt.IsSynthetic() && !m_pWin->IsVisible() ) + { + Point* pPtr = new Point( rMEvt.GetPosPixel() ); + m_pWin->UpdatePosition( pPtr ); + } + } +} + +SwPageBreakWin::SwPageBreakWin( SwEditWin* pEditWin, const SwPageFrm* pPageFrm ) : + MenuButton( pEditWin, WB_DIALOGCONTROL ), + SwFrameControl( pEditWin, pPageFrm ), + m_pPopupMenu( NULL ), + m_pLine( NULL ), + m_bIsAppearing( false ), + m_nFadeRate( 100 ), + m_nDelayAppearing( 0 ), + m_bDestroyed( false ), + m_pMousePt( NULL ) +{ + // Use pixels for the rest of the drawing + SetMapMode( MapMode ( MAP_PIXEL ) ); + + // Create the line control + m_pLine = new SwBreakDashedLine( GetEditWin(), &SwViewOption::GetPageBreakColor, this ); + + // Create the popup menu + m_pPopupMenu = new PopupMenu( SW_RES( MN_PAGEBREAK_BUTTON ) ); + m_pPopupMenu->SetDeactivateHdl( LINK( this, SwPageBreakWin, HideHandler ) ); + SetPopupMenu( m_pPopupMenu ); + + m_aFadeTimer.SetTimeout( 50 ); + m_aFadeTimer.SetTimeoutHdl( LINK( this, SwPageBreakWin, FadeHandler ) ); +} + +SwPageBreakWin::~SwPageBreakWin( ) +{ + m_bDestroyed = true; + m_aFadeTimer.Stop(); + + delete m_pPopupMenu; + delete m_pLine; + delete m_pMousePt; +} + +void SwPageBreakWin::Paint( const Rectangle& ) +{ + const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) ); + + // Properly paint the control + BColor aColor = SwViewOption::GetPageBreakColor().getBColor(); + + BColor aHslLine = rgb2hsl( aColor ); + double nLuminance = aHslLine.getZ(); + nLuminance += ( 1.0 - nLuminance ) * 0.75; + if ( aHslLine.getZ() > 0.7 ) + nLuminance = aHslLine.getZ() * 0.7; + aHslLine.setZ( nLuminance ); + BColor aOtherColor = hsl2rgb( aHslLine ); + + const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings(); + if ( rSettings.GetHighContrastMode( ) ) + { + aColor = rSettings.GetDialogTextColor().getBColor(); + aOtherColor = rSettings.GetDialogColor( ).getBColor(); + } + + bool bRtl = Application::GetSettings().GetLayoutRTL(); + + drawinglayer::primitive2d::Primitive2DSequence aSeq( 3 ); + B2DRectangle aBRect( double( aRect.Left() ), double( aRect.Top( ) ), + double( aRect.Right() ), double( aRect.Bottom( ) ) ); + B2DPolygon aPolygon = createPolygonFromRect( aBRect, 3.0 / BUTTON_WIDTH, 3.0 / BUTTON_HEIGHT ); + + // Create the polygon primitives + aSeq[0] = Primitive2DReference( new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + B2DPolyPolygon( aPolygon ), aOtherColor ) ); + aSeq[1] = Primitive2DReference( new drawinglayer::primitive2d::PolygonHairlinePrimitive2D( + aPolygon, aColor ) ); + + // Create the primitive for the image + Image aImg( SW_RES( IMG_PAGE_BREAK ) ); + double nImgOfstX = 3.0; + if ( bRtl ) + nImgOfstX = aRect.Right() - aImg.GetSizePixel().Width() - 3.0; + aSeq[2] = Primitive2DReference( new drawinglayer::primitive2d::DiscreteBitmapPrimitive2D( + aImg.GetBitmapEx(), B2DPoint( nImgOfstX, 1.0 ) ) ); + + double nTop = double( aRect.getHeight() ) / 2.0; + double nBottom = nTop + 4.0; + double nLeft = aRect.getWidth( ) - ARROW_WIDTH - 6.0; + if ( bRtl ) + nLeft = ARROW_WIDTH - 2.0; + double nRight = nLeft + 8.0; + + B2DPolygon aTriangle; + aTriangle.append( B2DPoint( nLeft, nTop ) ); + aTriangle.append( B2DPoint( nRight, nTop ) ); + aTriangle.append( B2DPoint( ( nLeft + nRight ) / 2.0, nBottom ) ); + aTriangle.setClosed( true ); + + BColor aTriangleColor = Color( COL_BLACK ).getBColor( ); + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + aTriangleColor = Color( COL_WHITE ).getBColor( ); + + aSeq.realloc( aSeq.getLength() + 1 ); + aSeq[ aSeq.getLength() - 1 ] = Primitive2DReference( new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + B2DPolyPolygon( aTriangle ), aTriangleColor ) ); + + Primitive2DSequence aGhostedSeq( 1 ); + double nFadeRate = double( m_nFadeRate ) / 100.0; + const basegfx::BColorModifierSharedPtr aBColorModifier( + new basegfx::BColorModifier_interpolate( + Color( COL_WHITE ).getBColor(), + 1.0 - nFadeRate)); + aGhostedSeq[0] = Primitive2DReference( new drawinglayer::primitive2d::ModifiedColorPrimitive2D( + aSeq, aBColorModifier ) ); + + // Create the processor and process the primitives + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + drawinglayer::processor2d::BaseProcessor2D * pProcessor = + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( + *this, aNewViewInfos ); + + pProcessor->process( aGhostedSeq ); + delete pProcessor; +} + +void SwPageBreakWin::Select( ) +{ + SwFrameControlPtr pThis = GetEditWin()->GetFrameControlsManager( ).GetControl( PageBreak, GetFrame() ); + + switch( GetCurItemId( ) ) + { + case FN_PAGEBREAK_EDIT: + { + const SwLayoutFrm* pBodyFrm = static_cast< const SwLayoutFrm* >( GetPageFrame()->Lower() ); + while ( pBodyFrm && !pBodyFrm->IsBodyFrm() ) + pBodyFrm = static_cast< const SwLayoutFrm* >( pBodyFrm->GetNext() ); + + SwEditWin* pEditWin = GetEditWin(); + + if ( pBodyFrm ) + { + SwWrtShell& rSh = pEditWin->GetView().GetWrtShell(); + bool bOldLock = rSh.IsViewLocked(); + rSh.LockView( true ); + + if ( pBodyFrm->Lower()->IsTabFrm() ) + { + rSh.Push( ); + rSh.ClearMark(); + + SwCntntFrm *pCnt = const_cast< SwCntntFrm* >( pBodyFrm->ContainsCntnt() ); + SwCntntNode* pNd = pCnt->GetNode(); + rSh.SetSelection( *pNd ); + + SfxStringItem aItem(pEditWin->GetView().GetPool().GetWhich(FN_FORMAT_TABLE_DLG), "textflow"); + pEditWin->GetView().GetViewFrame()->GetDispatcher()->Execute( + FN_FORMAT_TABLE_DLG, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD, &aItem, NULL ); + + rSh.Pop( false ); + } + else + { + SwCntntFrm *pCnt = const_cast< SwCntntFrm* >( pBodyFrm->ContainsCntnt() ); + SwCntntNode* pNd = pCnt->GetNode(); + + SwPaM aPaM( *pNd ); + SwPaMItem aPaMItem( pEditWin->GetView().GetPool( ).GetWhich( FN_PARAM_PAM ), &aPaM ); + SfxStringItem aItem( pEditWin->GetView().GetPool( ).GetWhich( SID_PARA_DLG ), "textflow" ); + pEditWin->GetView().GetViewFrame()->GetDispatcher()->Execute( + SID_PARA_DLG, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD, &aItem, &aPaMItem, NULL ); + } + rSh.LockView( bOldLock ); + pEditWin->GrabFocus( ); + } + } + break; + case FN_PAGEBREAK_DELETE: + { + const SwLayoutFrm* pBodyFrm = static_cast< const SwLayoutFrm* >( GetPageFrame()->Lower() ); + while ( pBodyFrm && !pBodyFrm->IsBodyFrm() ) + pBodyFrm = static_cast< const SwLayoutFrm* >( pBodyFrm->GetNext() ); + + if ( pBodyFrm ) + { + SwCntntFrm *pCnt = const_cast< SwCntntFrm* >( pBodyFrm->ContainsCntnt() ); + SwCntntNode* pNd = pCnt->GetNode(); + + pNd->GetDoc()->GetIDocumentUndoRedo( ).StartUndo( UNDO_UI_DELETE_PAGE_BREAK, NULL ); + + SfxItemSet aSet( GetEditWin()->GetView().GetWrtShell().GetAttrPool(), + RES_PAGEDESC, RES_PAGEDESC, + RES_BREAK, RES_BREAK, + NULL ); + aSet.Put( SvxFmtBreakItem( SVX_BREAK_NONE, RES_BREAK ) ); + aSet.Put( SwFmtPageDesc( NULL ) ); + + SwPaM aPaM( *pNd ); + pNd->GetDoc()->InsertItemSet( aPaM, aSet, nsSetAttrMode::SETATTR_DEFAULT ); + + pNd->GetDoc()->GetIDocumentUndoRedo( ).EndUndo( UNDO_UI_DELETE_PAGE_BREAK, NULL ); + } + } + break; + } + + // Only fade if there is more than this temporary shared pointer: + // The main reference has been deleted due to a page break removal + if ( pThis.use_count() > 1 ) + Fade( false ); +} + +void SwPageBreakWin::MouseMove( const MouseEvent& rMEvt ) +{ + if ( rMEvt.IsLeaveWindow() ) + { + // don't fade if we just move to the 'line', or the popup menu is open + Point aEventPos( rMEvt.GetPosPixel() + rMEvt.GetPosPixel() ); + if ( !Contains( aEventPos ) && !PopupMenu::IsInExecute() ) + Fade( false ); + } + else if ( !IsVisible() ) + Fade( true ); +} + +void SwPageBreakWin::Activate( ) +{ + Fade( true ); + MenuButton::Activate(); +} + +void SwPageBreakWin::UpdatePosition( const Point* pEvtPt ) +{ + if ( pEvtPt != NULL ) + { + if ( pEvtPt == m_pMousePt ) + return; + delete m_pMousePt; + m_pMousePt = pEvtPt; + } + + const SwPageFrm* pPageFrm = GetPageFrame(); + const SwFrm* pPrevPage = pPageFrm; + do + { + pPrevPage = pPrevPage->GetPrev(); + } + while ( pPrevPage && ( ( pPrevPage->Frm().Top( ) == pPageFrm->Frm().Top( ) ) + || static_cast< const SwPageFrm* >( pPrevPage )->IsEmptyPage( ) ) ); + + Rectangle aBoundRect = GetEditWin()->LogicToPixel( pPageFrm->GetBoundRect().SVRect() ); + Rectangle aFrmRect = GetEditWin()->LogicToPixel( pPageFrm->Frm().SVRect() ); + + long nYLineOffset = ( aBoundRect.Top() + aFrmRect.Top() ) / 2; + if ( pPrevPage ) + { + Rectangle aPrevFrmRect = GetEditWin()->LogicToPixel( pPrevPage->Frm().SVRect() ); + nYLineOffset = ( aPrevFrmRect.Bottom() + aFrmRect.Top() ) / 2; + } + + // Get the page + sidebar coords + long nPgLeft = aFrmRect.Left(); + long nPgRight = aFrmRect.Right(); + + unsigned long nSidebarWidth = 0; + const SwPostItMgr* pPostItMngr = GetEditWin()->GetView().GetWrtShell().GetPostItMgr(); + if ( pPostItMngr && pPostItMngr->HasNotes() && pPostItMngr->ShowNotes() ) + nSidebarWidth = pPostItMngr->GetSidebarBorderWidth( true ) + pPostItMngr->GetSidebarWidth( true ); + + if ( pPageFrm->SidebarPosition( ) == sw::sidebarwindows::SIDEBAR_LEFT ) + nPgLeft -= nSidebarWidth; + else if ( pPageFrm->SidebarPosition( ) == sw::sidebarwindows::SIDEBAR_RIGHT ) + nPgRight += nSidebarWidth; + + Size aBtnSize( BUTTON_WIDTH + ARROW_WIDTH, BUTTON_HEIGHT ); + + // Place the button on the left or right? + Rectangle aVisArea = GetEditWin()->LogicToPixel( GetEditWin()->GetView().GetVisArea() ); + + long nLineLeft = std::max( nPgLeft, aVisArea.Left() ); + long nLineRight = std::min( nPgRight, aVisArea.Right() ); + long nBtnLeft = nLineLeft; + + if ( m_pMousePt ) + { + nBtnLeft = nLineLeft + m_pMousePt->X() - aBtnSize.getWidth() / 2; + + if ( nBtnLeft < nLineLeft ) + nBtnLeft = nLineLeft; + else if ( ( nBtnLeft + aBtnSize.getWidth() ) > nLineRight ) + nBtnLeft = nLineRight - aBtnSize.getWidth(); + } + + // Set the button position + Point aBtnPos( nBtnLeft, nYLineOffset - BUTTON_HEIGHT / 2 ); + SetPosSizePixel( aBtnPos, aBtnSize ); + + // Set the line position + Point aLinePos( nLineLeft, nYLineOffset - 5 ); + Size aLineSize( nLineRight - nLineLeft, 10 ); + m_pLine->SetPosSizePixel( aLinePos, aLineSize ); +} + +void SwPageBreakWin::ShowAll( bool bShow ) +{ + m_pLine->Show( bShow ); +} + +bool SwPageBreakWin::Contains( const Point &rDocPt ) const +{ + Rectangle aRect( GetPosPixel(), GetSizePixel() ); + if ( aRect.IsInside( rDocPt ) ) + return true; + + Rectangle aLineRect( m_pLine->GetPosPixel(), m_pLine->GetSizePixel() ); + if ( aLineRect.IsInside( rDocPt ) ) + return true; + + return false; +} + +const SwPageFrm* SwPageBreakWin::GetPageFrame( ) +{ + return static_cast< const SwPageFrm * >( GetFrame( ) ); +} + +void SwPageBreakWin::SetReadonly( bool bReadonly ) +{ + ShowAll( !bReadonly ); +} + +void SwPageBreakWin::Fade( bool bFadeIn ) +{ + m_bIsAppearing = bFadeIn; + if ( bFadeIn ) + m_nDelayAppearing = 0; + + if ( !m_bDestroyed && m_aFadeTimer.IsActive( ) ) + m_aFadeTimer.Stop(); + if ( !m_bDestroyed ) + m_aFadeTimer.Start( ); +} + +IMPL_LINK_NOARG(SwPageBreakWin, HideHandler) +{ + Fade( false ); + + return 0; +} + +IMPL_LINK_NOARG(SwPageBreakWin, FadeHandler) +{ + const int TICKS_BEFORE_WE_APPEAR = 10; + if ( m_bIsAppearing && m_nDelayAppearing < TICKS_BEFORE_WE_APPEAR ) + { + ++m_nDelayAppearing; + m_aFadeTimer.Start(); + return 0; + } + + if ( m_bIsAppearing && m_nFadeRate > 0 ) + m_nFadeRate -= 25; + else if ( !m_bIsAppearing && m_nFadeRate < 100 ) + m_nFadeRate += 25; + + if ( m_nFadeRate != 100 && !IsVisible() ) + Show(); + else if ( m_nFadeRate == 100 && IsVisible( ) ) + Hide(); + else + { + UpdatePosition(); + Invalidate(); + } + + if ( IsVisible( ) && m_nFadeRate > 0 && m_nFadeRate < 100 ) + m_aFadeTimer.Start(); + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/PostItMgr.cxx b/sw/source/uibase/docvw/PostItMgr.cxx new file mode 100644 index 000000000000..d51ebff2b082 --- /dev/null +++ b/sw/source/uibase/docvw/PostItMgr.cxx @@ -0,0 +1,2029 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include "PostItMgr.hxx" +#include <postithelper.hxx> + +#include <SidebarWin.hxx> +#include <AnnotationWin.hxx> +#include <frmsidebarwincontainer.hxx> +#include <accmap.hxx> + +#include <SidebarWindowsConsts.hxx> +#include <AnchorOverlayObject.hxx> +#include <ShadowOverlayObject.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/scrbar.hxx> +#include <vcl/outdev.hxx> +#include <vcl/settings.hxx> + +#include <chrdlgmodes.hxx> +#include <viewopt.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <doc.hxx> +#include <fldbas.hxx> +#include <fmtfld.hxx> +#include <docufld.hxx> +#include <edtwin.hxx> +#include <txtfld.hxx> +#include <txtannotationfld.hxx> +#include <ndtxt.hxx> +#include <redline.hxx> +#include <docary.hxx> +#include <SwRewriter.hxx> +#include <tools/color.hxx> + +#include <swmodule.hxx> +#include <annotation.hrc> +#include "cmdid.h" + +#include <sfx2/request.hxx> +#include <sfx2/event.hxx> +#include <svl/srchitem.hxx> + +#include <svl/languageoptions.hxx> +#include <svtools/langtab.hxx> +#include <svl/smplhint.hxx> + +#include <svx/svdview.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/kernitem.hxx> +#include <editeng/outliner.hxx> + +#include <i18nlangtag/mslangid.hxx> +#include <i18nlangtag/lang.h> + +#include "annotsh.hxx" +#include "swabstdlg.hxx" +#include "swevent.hxx" +#include "switerator.hxx" + +// distance between Anchor Y and initial note position +#define POSTIT_INITIAL_ANCHOR_DISTANCE 20 +//distance between two postits +#define POSTIT_SPACE_BETWEEN 8 +#define POSTIT_MINIMUMSIZE_WITH_META 60 +#define POSTIT_SCROLL_SIDEBAR_HEIGHT 20 + +// if we layout more often we stop, this should never happen +#define MAX_LOOP_COUNT 50 + +using namespace sw::sidebarwindows; + +bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b) +{ + // sort by anchor position + SwPosition aPosAnchorA = a->GetAnchorPosition(); + SwPosition aPosAnchorB = b->GetAnchorPosition(); + + bool aAnchorAInFooter = false; + bool aAnchorBInFooter = false; + + // is the anchor placed in Footnote or the Footer? + if( aPosAnchorA.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorA.nNode.GetNode().FindFooterStartNode() ) + aAnchorAInFooter = true; + if( aPosAnchorB.nNode.GetNode().FindFootnoteStartNode() || aPosAnchorB.nNode.GetNode().FindFooterStartNode() ) + aAnchorBInFooter = true; + + // fdo#34800 + // if AnchorA is in footnote, and AnchorB isn't + // we do not want to change over the position + if( aAnchorAInFooter && !aAnchorBInFooter ) + return false; + // if aAnchorA is not placed in a footnote, and aAnchorB is + // force a change over + else if( !aAnchorAInFooter && aAnchorBInFooter ) + return true; + // If neither or both are in the footer, compare the positions. + // Since footnotes are in Inserts section of nodes array and footers + // in Autotext section, all footnotes precede any footers so no need + // to check that. + else + return aPosAnchorA < aPosAnchorB; +} + +SwPostItMgr::SwPostItMgr(SwView* pView) + : mpView(pView) + , mpWrtShell(mpView->GetDocShell()->GetWrtShell()) + , mpEditWin(&mpView->GetEditWin()) + , mnEventId(0) + , mbWaitingForCalcRects(false) + , mpActivePostIt(0) + , mbLayout(false) + , mbLayoutHeight(0) + , mbLayouting(false) + , mbReadOnly(mpView->GetDocShell()->IsReadOnly()) + , mbDeleteNote(true) + , mpAnswer(0) + , mbIsShowAnchor( false ) + , mpFrmSidebarWinContainer( 0 ) +{ + if(!mpView->GetDrawView() ) + mpView->GetWrtShell().MakeDrawView(); + + SwNoteProps aProps; + mbIsShowAnchor = aProps.IsShowAnchor(); + + //make sure we get the colour yellow always, even if not the first one of comments or redlining + SW_MOD()->GetRedlineAuthor(); + + // collect all PostIts and redline comments that exist after loading the document + // don't check for existence for any of them, don't focus them + AddPostIts(false,false); + /* this code can be used once we want redline comments in the Sidebar + AddRedlineComments(false,false); + */ + // we want to receive stuff like SFX_HINT_DOCCHANGED + StartListening(*mpView->GetDocShell()); + if (!mvPostItFlds.empty()) + { + mbWaitingForCalcRects = true; + mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 ); + } +} + +SwPostItMgr::~SwPostItMgr() +{ + if ( mnEventId ) + Application::RemoveUserEvent( mnEventId ); + // forget about all our Sidebar windows + RemoveSidebarWin(); + EndListening( *mpView->GetDocShell() ); + + for(std::vector<SwPostItPageItem*>::iterator i = mPages.begin(); i != mPages.end() ; ++i) + delete (*i); + mPages.clear(); + + delete mpFrmSidebarWinContainer; + mpFrmSidebarWinContainer = 0; +} + +void SwPostItMgr::CheckForRemovedPostIts() +{ + bool bRemoved = false; + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end(); ) + { + std::list<SwSidebarItem*>::iterator it = i++; + if ( !(*it)->UseElement() ) + { + SwSidebarItem* p = (*it); + mvPostItFlds.remove(*it); + if (GetActiveSidebarWin() == p->pPostIt) + SetActiveSidebarWin(0); + if (p->pPostIt) + delete p->pPostIt; + delete p; + bRemoved = true; + } + } + + if ( bRemoved ) + { + // make sure that no deleted items remain in page lists + // todo: only remove deleted ones?! + if ( mvPostItFlds.empty() ) + { + PreparePageContainer(); + PrepareView(); + } + else + // if postits are their make sure that page lists are not empty + // otherwise sudden paints can cause pain (in BorderOverPageBorder) + CalcRects(); + } +} + +void SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus) +{ + if (bCheckExistance) + { + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->GetBroadCaster() == pItem ) + return; + } + } + mbLayout = bFocus; + if (pItem->ISA(SwFmtFld)) + mvPostItFlds.push_back(new SwAnnotationItem(static_cast<SwFmtFld&>(*pItem), true, bFocus) ); + OSL_ENSURE(pItem->ISA(SwFmtFld),"Mgr::InsertItem: seems like new stuff was added"); + StartListening(*pItem); +} + +void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast ) +{ + EndListening(*pBroadcast); + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->GetBroadCaster() == pBroadcast ) + { + SwSidebarItem* p = (*i); + if (GetActiveSidebarWin() == p->pPostIt) + SetActiveSidebarWin(0); + mvPostItFlds.remove(*i); + delete p->pPostIt; + delete p; + break; + } + } + mbLayout = true; + PrepareView(); +} + +void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxEventHint) ) ) + { + sal_uInt32 nId = ((SfxEventHint&)rHint).GetEventId(); + if ( nId == SW_EVENT_LAYOUT_FINISHED ) + { + if ( !mbWaitingForCalcRects && !mvPostItFlds.empty()) + { + mbWaitingForCalcRects = true; + mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 ); + } + } + } + else if ( rHint.IsA(TYPE(SfxSimpleHint) ) ) + { + sal_uInt32 nId = ((SfxSimpleHint&)rHint).GetId(); + switch ( nId ) + { + case SFX_HINT_MODECHANGED: + { + if ( mbReadOnly != !!(mpView->GetDocShell()->IsReadOnly()) ) + { + mbReadOnly = !mbReadOnly; + SetReadOnlyState(); + mbLayout = true; + } + break; + } + case SFX_HINT_DOCCHANGED: + { + if ( mpView->GetDocShell() == &rBC ) + { + if ( !mbWaitingForCalcRects && !mvPostItFlds.empty()) + { + mbWaitingForCalcRects = true; + mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 ); + } + } + break; + } + case SFX_HINT_USER04: + { + // if we are in a SplitNode/Cut operation, do not delete note and then add again, as this will flicker + mbDeleteNote = !mbDeleteNote; + break; + } + case SFX_HINT_DYING: + { + if ( mpView->GetDocShell() != &rBC ) + { + // field to be removed is the broadcaster + OSL_FAIL("Notification for removed SwFmtFld was not sent!"); + RemoveItem(&rBC); + } + break; + } + } + } + else if ( rHint.IsA(TYPE(SwFmtFldHint) ) ) + { + const SwFmtFldHint& rFmtHint = static_cast<const SwFmtFldHint&>(rHint); + SwFmtFld* pFld = const_cast <SwFmtFld*>( rFmtHint.GetField() ); + switch ( rFmtHint.Which() ) + { + case SWFMTFLD_INSERTED : + { + if (!pFld) + { + AddPostIts(true); + break; + } + // get field to be inserted from hint + if ( pFld->IsFldInDoc() ) + { + bool bEmpty = !HasNotes(); + InsertItem( pFld, true, false ); + if (bEmpty && !mvPostItFlds.empty()) + PrepareView(true); + } + else + { + OSL_FAIL("Inserted field not in document!" ); + } + break; + } + case SWFMTFLD_REMOVED: + { + if (mbDeleteNote) + { + if (!pFld) + { + CheckForRemovedPostIts(); + break; + } + RemoveItem(pFld); + } + break; + } + case SWFMTFLD_FOCUS: + { + if (rFmtHint.GetView()== mpView) + Focus(rBC); + break; + } + case SWFMTFLD_CHANGED: + { + SwFmtFld* pFmtFld = dynamic_cast<SwFmtFld*>(&rBC); + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( pFmtFld == (*i)->GetBroadCaster() ) + { + if ((*i)->pPostIt) + { + (*i)->pPostIt->SetPostItText(); + mbLayout = true; + } + break; + } + } + break; + } + + case SWFMTFLD_LANGUAGE: + { + SwFmtFld* pFmtFld = dynamic_cast<SwFmtFld*>(&rBC); + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( pFmtFld == (*i)->GetBroadCaster() ) + { + if ((*i)->pPostIt) + { + const sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( (*i)->GetFmtFld().GetField()->GetLanguage() ); + sal_uInt16 nLangWhichId = 0; + switch (nScriptType) + { + case SCRIPTTYPE_LATIN : nLangWhichId = EE_CHAR_LANGUAGE ; break; + case SCRIPTTYPE_ASIAN : nLangWhichId = EE_CHAR_LANGUAGE_CJK; break; + case SCRIPTTYPE_COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; + } + (*i)->pPostIt->SetLanguage( + SvxLanguageItem( + (*i)->GetFmtFld().GetField()->GetLanguage(), + nLangWhichId) ); + } + break; + } + } + break; + } + } + } +} + +void SwPostItMgr::Focus(SfxBroadcaster& rBC) +{ + if (!mpWrtShell->GetViewOptions()->IsPostIts()) + { + SfxRequest aRequest(mpView->GetViewFrame(),FN_VIEW_NOTES); + mpView->ExecViewOptions(aRequest); + } + + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + // field to get the focus is the broadcaster + if ( &rBC == (*i)->GetBroadCaster() ) + { + if ((*i)->pPostIt) + { + (*i)->pPostIt->GrabFocus(); + MakeVisible((*i)->pPostIt); + } + else + { + // when the layout algorithm starts, this postit is created and receives focus + (*i)->bFocus = true; + } + } + } +} + +bool SwPostItMgr::CalcRects() +{ + if ( mnEventId ) + { + // if CalcRects() was forced and an event is still pending: remove it + // it is superfluous and also may cause reentrance problems if triggered while layouting + Application::RemoveUserEvent( mnEventId ); + mnEventId = 0; + } + + bool bChange = false; + bool bRepair = false; + PreparePageContainer(); + if ( !mvPostItFlds.empty() ) + { + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + SwSidebarItem* pItem = (*i); + if ( !pItem->UseElement() ) + { + OSL_FAIL("PostIt is not in doc or other wrong use"); + bRepair = true; + continue; + } + + const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition ); + const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus; + const sal_uLong nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx ); + const sal_Int32 nOldStartContent( pItem->maLayoutInfo.mnStartContent ); + { + // update layout information + const SwTxtAnnotationFld* pTxtAnnotationFld = + dynamic_cast< const SwTxtAnnotationFld* >( pItem->GetFmtFld().GetTxtFld() ); + const ::sw::mark::IMark* pAnnotationMark = + pTxtAnnotationFld != NULL ? pTxtAnnotationFld->GetAnnotationMark() : NULL; + if ( pAnnotationMark != NULL ) + { + pItem->mLayoutStatus = + SwPostItHelper::getLayoutInfos( + pItem->maLayoutInfo, + pItem->GetAnchorPosition(), + &pAnnotationMark->GetMarkStart() ); + } + else + { + pItem->mLayoutStatus = + SwPostItHelper::getLayoutInfos( pItem->maLayoutInfo, pItem->GetAnchorPosition() ); + } + } + bChange = bChange + || pItem->maLayoutInfo.mPosition != aOldAnchorRect + || pItem->mLayoutStatus != eOldLayoutStatus + || pItem->maLayoutInfo.mnStartNodeIdx != nOldStartNodeIdx + || pItem->maLayoutInfo.mnStartContent != nOldStartContent; + } + + // show notes in right order in navigator + //prevent Anchors during layout to overlap, e.g. when moving a frame + Sort(SORT_POS); + + // sort the items into the right page vector, so layout can be done by page + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + SwSidebarItem* pItem = (*i); + if( SwPostItHelper::INVISIBLE == pItem->mLayoutStatus ) + { + if (pItem->pPostIt) + pItem->pPostIt->HideNote(); + continue; + } + + if( SwPostItHelper::HIDDEN == pItem->mLayoutStatus ) + { + if (!mpWrtShell->GetViewOptions()->IsShowHiddenChar()) + { + if (pItem->pPostIt) + pItem->pPostIt->HideNote(); + continue; + } + } + + const unsigned long aPageNum = pItem->maLayoutInfo.mnPageNumber; + if (aPageNum > mPages.size()) + { + const unsigned long nNumberOfPages = mPages.size(); + for (unsigned int j=0; j<aPageNum - nNumberOfPages; ++j) + mPages.push_back( new SwPostItPageItem()); + } + mPages[aPageNum-1]->mList->push_back(pItem); + mPages[aPageNum-1]->mPageRect = pItem->maLayoutInfo.mPageFrame; + mPages[aPageNum-1]->eSidebarPosition = pItem->maLayoutInfo.meSidebarPosition; + } + + if (!bChange && mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE)) + { + long nLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() ); + if( nLayoutHeight > mbLayoutHeight ) + { + if (mPages[0]->bScrollbar || HasScrollbars()) + bChange = true; + } + else if( nLayoutHeight < mbLayoutHeight ) + { + if (mPages[0]->bScrollbar || !BorderOverPageBorder(1)) + bChange = true; + } + } + } + + if ( bRepair ) + CheckForRemovedPostIts(); + + mbLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() ); + mbWaitingForCalcRects = false; + return bChange; +} + +bool SwPostItMgr::HasScrollbars() const +{ + for(std::list<SwSidebarItem*>::const_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ((*i)->bShow && (*i)->pPostIt && (*i)->pPostIt->HasScrollbar()) + return true; + } + return false; +} + +void SwPostItMgr::PreparePageContainer() +{ + // we do not just delete the SwPostItPageItem, so offset/scrollbar is not lost + long lPageSize = mpWrtShell->GetNumPages(); + long lContainerSize = mPages.size(); + + if (lContainerSize < lPageSize) + { + for (int i=0; i<lPageSize - lContainerSize;i++) + mPages.push_back( new SwPostItPageItem()); + } + else if (lContainerSize > lPageSize) + { + for (int i=mPages.size()-1; i >= lPageSize;--i) + { + delete mPages[i]; + mPages.pop_back(); + } + } + // only clear the list, DO NOT delete the objects itself + for(std::vector<SwPostItPageItem*>::iterator i = mPages.begin(); i != mPages.end() ; ++i) + { + (*i)->mList->clear(); + if (mvPostItFlds.empty()) + (*i)->bScrollbar = false; + + } +} + +void SwPostItMgr::LayoutPostIts() +{ + if ( !mvPostItFlds.empty() && !mbWaitingForCalcRects ) + { + mbLayouting = true; + + //loop over all pages and do the layout + // - create SwPostIt if necessary + // - place SwPostIts on their initial position + // - calculate necessary height for all PostIts together + bool bUpdate = false; + for (unsigned long n=0;n<mPages.size();n++) + { + // only layout if there are notes on this page + if (mPages[n]->mList->size()>0) + { + std::list<SwSidebarWin*> aVisiblePostItList; + unsigned long lNeededHeight = 0; + long mlPageBorder = 0; + long mlPageEnd = 0; + + for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i != mPages[n]->mList->end(); ++i) + { + SwSidebarItem* pItem = (*i); + SwSidebarWin* pPostIt = pItem->pPostIt; + + if (mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT ) + { + // x value for notes positioning + mlPageBorder = mpEditWin->LogicToPixel( Point( mPages[n]->mPageRect.Left(), 0)).X() - GetSidebarWidth(true);// - GetSidebarBorderWidth(true); + //bending point + mlPageEnd = + mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) + ? pItem->maLayoutInfo.mPagePrtArea.Left() + : mPages[n]->mPageRect.Left() + 350; + } + else if (mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT ) + { + // x value for notes positioning + mlPageBorder = mpEditWin->LogicToPixel( Point(mPages[n]->mPageRect.Right(), 0)).X() + GetSidebarBorderWidth(true); + //bending point + mlPageEnd = + mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) + ? pItem->maLayoutInfo.mPagePrtArea.Right() : + mPages[n]->mPageRect.Right() - 350; + } + + if (pItem->bShow) + { + long Y = mpEditWin->LogicToPixel( Point(0,pItem->maLayoutInfo.mPosition.Bottom())).Y(); + long aPostItHeight = 0; + if (!pPostIt) + { + pPostIt = (*i)->GetSidebarWindow( mpView->GetEditWin(), + WB_DIALOGCONTROL, + *this, + 0 ); + pPostIt->InitControls(); + pPostIt->SetReadonly(mbReadOnly); + pItem->pPostIt = pPostIt; + if (mpAnswer) + { + if (pPostIt->CalcFollow()) //do we really have another note in front of this one + static_cast<sw::annotation::SwAnnotationWin*>(pPostIt)->InitAnswer(mpAnswer); + delete mpAnswer; + mpAnswer = 0; + } + } + + pPostIt->SetChangeTracking( + pItem->mLayoutStatus, + GetColorAnchor(pItem->maLayoutInfo.mRedlineAuthor)); + pPostIt->SetSidebarPosition(mPages[n]->eSidebarPosition); + pPostIt->SetFollow(pPostIt->CalcFollow()); + aPostItHeight = ( pPostIt->GetPostItTextHeight() < pPostIt->GetMinimumSizeWithoutMeta() + ? pPostIt->GetMinimumSizeWithoutMeta() + : pPostIt->GetPostItTextHeight() ) + + pPostIt->GetMetaHeight(); + pPostIt->SetPosSizePixelRect( mlPageBorder , + Y - GetInitialAnchorDistance(), + GetNoteWidth() , + aPostItHeight, + pItem->maLayoutInfo.mPosition, + mlPageEnd ); + pPostIt->ChangeSidebarItem( *pItem ); + + if (pItem->bFocus) + { + mbLayout = true; + pPostIt->GrabFocus(); + pItem->bFocus = false; + } + // only the visible postits are used for the final layout + aVisiblePostItList.push_back(pPostIt); + lNeededHeight += pPostIt->IsFollow() ? aPostItHeight : aPostItHeight+GetSpaceBetween(); + } + else // we don't want to see it + { + if (pPostIt) + pPostIt->HideNote(); + } + } + + if ((!aVisiblePostItList.empty()) && ShowNotes()) + { + bool bOldScrollbar = mPages[n]->bScrollbar; + if (ShowNotes()) + mPages[n]->bScrollbar = LayoutByPage(aVisiblePostItList, mPages[n]->mPageRect.SVRect(), lNeededHeight); + else + mPages[n]->bScrollbar = false; + if (!mPages[n]->bScrollbar) + { + mPages[n]->lOffset = 0; + } + else + { + //when we changed our zoom level, the offset value can be to big, so lets check for the largest possible zoom value + long aAvailableHeight = mpEditWin->LogicToPixel(Size(0,mPages[n]->mPageRect.Height())).Height() - 2 * GetSidebarScrollerHeight(); + long lOffset = -1 * GetScrollSize() * (aVisiblePostItList.size() - aAvailableHeight / GetScrollSize()); + if (mPages[n]->lOffset < lOffset) + mPages[n]->lOffset = lOffset; + } + bUpdate = (bOldScrollbar != mPages[n]->bScrollbar) || bUpdate; + const long aSidebarheight = mPages[n]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0; + /* + TODO + - enlarge all notes till GetNextBorder(), as we resized to average value before + */ + //lets hide the ones which overlap the page + for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i) + { + if (mPages[n]->lOffset != 0) + (*i)->TranslateTopPosition(mPages[n]->lOffset); + + bool bBottom = mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y()+(*i)->VirtualSize().Height())).Y() <= (mPages[n]->mPageRect.Bottom()-aSidebarheight); + bool bTop = mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y())).Y() >= (mPages[n]->mPageRect.Top()+aSidebarheight); + if ( bBottom && bTop ) + { + (*i)->ShowNote(); + } + else + { + if (mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y())).Y() < (mPages[n]->mPageRect.Top()+aSidebarheight)) + { + if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT ) + (*i)->ShowAnchorOnly(Point( mPages[n]->mPageRect.Left(), + mPages[n]->mPageRect.Top())); + else if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT ) + (*i)->ShowAnchorOnly(Point( mPages[n]->mPageRect.Right(), + mPages[n]->mPageRect.Top())); + } + else + { + if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT ) + (*i)->ShowAnchorOnly(Point(mPages[n]->mPageRect.Left(), + mPages[n]->mPageRect.Bottom())); + else if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT ) + (*i)->ShowAnchorOnly(Point(mPages[n]->mPageRect.Right(), + mPages[n]->mPageRect.Bottom())); + } + OSL_ENSURE(mPages[n]->bScrollbar,"SwPostItMgr::LayoutByPage(): note overlaps, but bScrollbar is not true"); + } + } + } + else + { + for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i) + (*i)->SetPosAndSize(); + + bool bOldScrollbar = mPages[n]->bScrollbar; + mPages[n]->bScrollbar = false; + bUpdate = (bOldScrollbar != mPages[n]->bScrollbar) || bUpdate; + } + aVisiblePostItList.clear(); + } + else + { + bUpdate = true; + mPages[n]->bScrollbar = false; + } + } + + if (!ShowNotes()) + { // we do not want to see the notes anymore -> Options-Writer-View-Notes + bool bRepair = false; + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + SwSidebarItem* pItem = (*i); + if ( !pItem->UseElement() ) + { + OSL_FAIL("PostIt is not in doc!"); + bRepair = true; + continue; + } + + if ((*i)->pPostIt) + { + (*i)->pPostIt->HideNote(); + if ((*i)->pPostIt->HasChildPathFocus()) + { + SetActiveSidebarWin(0); + (*i)->pPostIt->GrabFocusToDocument(); + } + } + } + + if ( bRepair ) + CheckForRemovedPostIts(); + } + + // notes scrollbar is otherwise not drawn correctly for some cases + // scrollbar area is enough + if (bUpdate) + mpEditWin->Invalidate(); + mbLayouting = false; + } +} + +bool SwPostItMgr::BorderOverPageBorder(unsigned long aPage) const +{ + if ( mPages[aPage-1]->mList->empty() ) + { + OSL_FAIL("Notes SidePane painted but no rects and page lists calculated!"); + return false; + } + + SwSidebarItem_iterator aItem = mPages[aPage-1]->mList->end(); + --aItem; + OSL_ENSURE ((*aItem)->pPostIt,"BorderOverPageBorder: NULL postIt, should never happen"); + if ((*aItem)->pPostIt) + { + const long aSidebarheight = mPages[aPage-1]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0; + const long aEndValue = mpEditWin->PixelToLogic(Point(0,(*aItem)->pPostIt->GetPosPixel().Y()+(*aItem)->pPostIt->GetSizePixel().Height())).Y(); + return aEndValue <= mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight; + } + else + return false; +} + +void SwPostItMgr::DrawNotesForPage(OutputDevice *pOutDev, sal_uInt32 nPage) +{ + assert(nPage < mPages.size()); + if (nPage >= mPages.size()) + return; + for(SwSidebarItem_iterator i = mPages[nPage]->mList->begin(); i != mPages[nPage]->mList->end(); ++i) + { + SwSidebarWin* pPostIt = (*i)->pPostIt; + if (!pPostIt) + continue; + Point aPoint(mpEditWin->PixelToLogic(pPostIt->GetPosPixel())); + Size aSize(pPostIt->PixelToLogic(pPostIt->GetSizePixel())); + pPostIt->Draw(pOutDev, aPoint, aSize, 0); + } +} + +void SwPostItMgr::Scroll(const long lScroll,const unsigned long aPage) +{ + OSL_ENSURE((lScroll % GetScrollSize() )==0,"SwPostItMgr::Scroll: scrolling by wrong value"); + // do not scroll more than necessary up or down + if ( ((mPages[aPage-1]->lOffset == 0) && (lScroll>0)) || ( BorderOverPageBorder(aPage) && (lScroll<0)) ) + return; + + const bool bOldUp = ArrowEnabled(KEY_PAGEUP,aPage); + const bool bOldDown = ArrowEnabled(KEY_PAGEDOWN,aPage); + const long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height(); + for(SwSidebarItem_iterator i = mPages[aPage-1]->mList->begin(); i != mPages[aPage-1]->mList->end(); ++i) + { + SwSidebarWin* pPostIt = (*i)->pPostIt; + // if this is an answer, we should take the normal position and not the real, slightly moved position + pPostIt->SetVirtualPosSize(pPostIt->GetPosPixel(),pPostIt->GetSizePixel()); + pPostIt->TranslateTopPosition(lScroll); + + if ((*i)->bShow) + { + bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y()+pPostIt->VirtualSize().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight); + bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight); + if ( bBottom && bTop) + { + pPostIt->ShowNote(); + } + else + { + if ( mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() < (mPages[aPage-1]->mPageRect.Top()+aSidebarheight)) + { + if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT) + pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Top())); + else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT) + pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Top())); + } + else + { + if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT) + pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Bottom())); + else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT) + pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Bottom())); + } + } + } + } + mPages[aPage-1]->lOffset += lScroll; + if ( (bOldUp != ArrowEnabled(KEY_PAGEUP,aPage)) ||(bOldDown != ArrowEnabled(KEY_PAGEDOWN,aPage)) ) + { + mpEditWin->Invalidate(GetBottomScrollRect(aPage)); + mpEditWin->Invalidate(GetTopScrollRect(aPage)); + } +} + +void SwPostItMgr::AutoScroll(const SwSidebarWin* pPostIt,const unsigned long aPage ) +{ + // otherwise all notes are visible + if (mPages[aPage-1]->bScrollbar) + { + const long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height(); + const bool bBottom = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight); + const bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight); + if ( !(bBottom && bTop)) + { + const long aDiff = bBottom ? mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Top() + aSidebarheight)).Y() - pPostIt->GetPosPixel().Y() : + mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Bottom() - aSidebarheight)).Y() - (pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height()); + // this just adds the missing value to get the next a* GetScrollSize() after aDiff + // e.g aDiff= 61 POSTIT_SCOLL=50 --> lScroll = 100 + const long lScroll = bBottom ? (aDiff + ( GetScrollSize() - (aDiff % GetScrollSize()))) : (aDiff - (GetScrollSize() + (aDiff % GetScrollSize()))); + Scroll(lScroll, aPage); + } + } +} + +void SwPostItMgr::MakeVisible(const SwSidebarWin* pPostIt,long aPage ) +{ + if (aPage == -1) + { + // we dont know the page yet, lets find it ourselves + for (unsigned long n=0;n<mPages.size();n++) + { + if (mPages[n]->mList->size()>0) + { + for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i != mPages[n]->mList->end(); ++i) + { + if ((*i)->pPostIt==pPostIt) + { + aPage = n+1; + break; + } + } + } + } + } + if (aPage!=-1) + AutoScroll(pPostIt,aPage); + Rectangle aNoteRect (Point(pPostIt->GetPosPixel().X(),pPostIt->GetPosPixel().Y()-5),pPostIt->GetSizePixel()); + if (!aNoteRect.IsEmpty()) + mpWrtShell->MakeVisible(SwRect(mpEditWin->PixelToLogic(aNoteRect))); +} + +bool SwPostItMgr::ArrowEnabled(sal_uInt16 aDirection,unsigned long aPage) const +{ + switch (aDirection) + { + case KEY_PAGEUP: + { + return (mPages[aPage-1]->lOffset != 0); + } + case KEY_PAGEDOWN: + { + return (!BorderOverPageBorder(aPage)); + } + default: return false; + } +} + +Color SwPostItMgr::GetArrowColor(sal_uInt16 aDirection,unsigned long aPage) const +{ + if (ArrowEnabled(aDirection,aPage)) + { + if (Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + return Color(COL_WHITE); + else + return COL_NOTES_SIDEPANE_ARROW_ENABLED; + } + else + { + return COL_NOTES_SIDEPANE_ARROW_DISABLED; + } +} + +bool SwPostItMgr::LayoutByPage(std::list<SwSidebarWin*> &aVisiblePostItList,const Rectangle aBorder, long lNeededHeight) +{ + /*** General layout idea:***/ + // - if we have space left, we always move the current one up, + // otherwise the next one down + // - first all notes are resized + // - then the real layout starts + + //rBorder is the page rect + const Rectangle rBorder = mpEditWin->LogicToPixel( aBorder); + long lTopBorder = rBorder.Top() + 5; + long lBottomBorder = rBorder.Bottom() - 5; + const long lVisibleHeight = lBottomBorder - lTopBorder; //rBorder.GetHeight() ; + long lTranslatePos = 0; + bool bScrollbars = false; + + // do all necessary resizings + if (lVisibleHeight < lNeededHeight) + { + // ok, now we have to really resize and adding scrollbars + const long lAverageHeight = (lVisibleHeight - aVisiblePostItList.size()*GetSpaceBetween()) / aVisiblePostItList.size(); + if (lAverageHeight<GetMinimumSizeWithMeta()) + { + bScrollbars = true; + lTopBorder += GetSidebarScrollerHeight() + 10; + lBottomBorder -= (GetSidebarScrollerHeight() + 10); + for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i) + (*i)->SetSize(Size((*i)->VirtualSize().getWidth(),(*i)->GetMinimumSizeWithMeta())); + } + else + { + for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i) + { + if ( (*i)->VirtualSize().getHeight() > lAverageHeight) + (*i)->SetSize(Size((*i)->VirtualSize().getWidth(),lAverageHeight)); + } + } + } + + //start the real layout so nothing overlaps anymore + if (aVisiblePostItList.size()>1) + { + long lSpaceUsed = 0; + int loop = 0; + bool bDone = false; + // if no window is moved anymore we are finished + while (!bDone) + { + loop++; + bDone = true; + lSpaceUsed = lTopBorder + GetSpaceBetween(); + for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i != aVisiblePostItList.end() ; ++i) + { + SwSidebarWin_iterator aNextPostIt = i; + ++aNextPostIt; + + if (aNextPostIt != aVisiblePostItList.end()) + { + lTranslatePos = ( (*i)->VirtualPos().Y() + (*i)->VirtualSize().Height()) - (*aNextPostIt)->VirtualPos().Y(); + if (lTranslatePos > 0) // note windows overlaps the next one + { + // we are not done yet, loop at least once more + bDone = false; + // if there is space left, move the current note up + // it could also happen that there is no space left for the first note due to a scrollbar + // then we also jump into, so we move the current one up and the next one down + if ( (lSpaceUsed <= (*i)->VirtualPos().Y()) || (i==aVisiblePostItList.begin())) + { + // we have space left, so let's move the current one up + if ( ((*i)->VirtualPos().Y()- lTranslatePos - GetSpaceBetween()) > lTopBorder) + { + if ((*aNextPostIt)->IsFollow()) + (*i)->TranslateTopPosition(-1*(lTranslatePos+ANCHORLINE_WIDTH)); + else + (*i)->TranslateTopPosition(-1*(lTranslatePos+GetSpaceBetween())); + } + else + { + long lMoveUp = (*i)->VirtualPos().Y() - lTopBorder; + (*i)->TranslateTopPosition(-1* lMoveUp); + if ((*aNextPostIt)->IsFollow()) + (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+ANCHORLINE_WIDTH) - lMoveUp); + else + (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+GetSpaceBetween()) - lMoveUp); + } + } + else + { + // no space left, left move the next one down + if ((*aNextPostIt)->IsFollow()) + (*aNextPostIt)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH); + else + (*aNextPostIt)->TranslateTopPosition(lTranslatePos+GetSpaceBetween()); + } + } + else + { + // the first one could overlap the topborder instead of a second note + if (i==aVisiblePostItList.begin()) + { + long lMoveDown = lTopBorder - (*i)->VirtualPos().Y(); + if (lMoveDown>0) + { + bDone = false; + (*i)->TranslateTopPosition( lMoveDown); + } + } + } + if ( (*aNextPostIt)->IsFollow() ) + lSpaceUsed += (*i)->VirtualSize().Height() + ANCHORLINE_WIDTH; + else + lSpaceUsed += (*i)->VirtualSize().Height() + GetSpaceBetween(); + } + else + { + //(*i) is the last visible item + SwSidebarWin_iterator aPrevPostIt = i; + --aPrevPostIt; + lTranslatePos = ( (*aPrevPostIt)->VirtualPos().Y() + (*aPrevPostIt)->VirtualSize().Height() ) - (*i)->VirtualPos().Y(); + if (lTranslatePos > 0) + { + bDone = false; + if ( ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()+lTranslatePos) < lBottomBorder) + { + if ( (*i)->IsFollow() ) + (*i)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH); + else + (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween()); + } + else + { + (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()) ); + } + } + else + { + // note does not overlap, but we might be over the lower border + // only do this if there are no scrollbars, otherwise notes are supposed to overlap the border + if (!bScrollbars && ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height() > lBottomBorder) ) + { + bDone = false; + (*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height())); + } + } + } + } + // security check so we don't loop forever + if (loop>MAX_LOOP_COUNT) + { + OSL_FAIL("PostItMgr::Layout(): We are looping forever"); + break; + } + } + } + else + { + // only one left, make sure it is not hidden at the top or bottom + SwSidebarWin_iterator i = aVisiblePostItList.begin(); + lTranslatePos = lTopBorder - (*i)->VirtualPos().Y(); + if (lTranslatePos>0) + { + (*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween()); + } + lTranslatePos = lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()); + if (lTranslatePos<0) + { + (*i)->TranslateTopPosition(lTranslatePos); + } + } + return bScrollbars; + } + +void SwPostItMgr::AddPostIts(bool bCheckExistance, bool bFocus) +{ + bool bEmpty = mvPostItFlds.empty(); + SwFieldType* pType = mpView->GetDocShell()->GetDoc()->GetFldType(RES_POSTITFLD, OUString(),false); + SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); + SwFmtFld* pSwFmtFld = aIter.First(); + while(pSwFmtFld) + { + if ( pSwFmtFld->GetTxtFld()) + { + if ( pSwFmtFld->IsFldInDoc() ) + InsertItem(pSwFmtFld,bCheckExistance,bFocus); + } + pSwFmtFld = aIter.Next(); + } + + // if we just added the first one we have to update the view for centering + if (bEmpty && !mvPostItFlds.empty()) + PrepareView(true); +} + +void SwPostItMgr::RemoveSidebarWin() +{ + if (!mvPostItFlds.empty()) + { + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + EndListening( *(const_cast<SfxBroadcaster*>((*i)->GetBroadCaster())) ); + if ((*i)->pPostIt) + delete (*i)->pPostIt; + delete (*i); + } + mvPostItFlds.clear(); + } + + // all postits removed, no items should be left in pages + PreparePageContainer(); +} + +// copy to new vector, otherwise RemoveItem would operate and delete stuff on mvPostItFlds as well +// RemoveItem will clean up the core field and visible postit if necessary +// we cannot just delete everything as before, as postits could move into change tracking +void SwPostItMgr::Delete(const OUString& aAuthor) +{ + mpWrtShell->StartAllAction(); + if ( HasActiveSidebarWin() && (GetActiveSidebarWin()->GetAuthor()==aAuthor) ) + { + SetActiveSidebarWin(0); + } + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, SW_RESSTR(STR_DELETE_AUTHOR_NOTES) + aAuthor); + mpWrtShell->StartUndo( UNDO_DELETE, &aRewriter ); + + std::vector<const SwFmtFld*> aTmp; + aTmp.reserve( mvPostItFlds.size() ); + for(std::list<SwSidebarItem*>::iterator pPostIt = mvPostItFlds.begin(); pPostIt!= mvPostItFlds.end() ; ++pPostIt) + { + if (((*pPostIt)->pPostIt->GetAuthor() == aAuthor) ) + aTmp.push_back( &(*pPostIt)->GetFmtFld() ); + } + for(std::vector<const SwFmtFld*>::iterator i = aTmp.begin(); i != aTmp.end() ; ++i) + { + mpWrtShell->GotoField( *(*i) ); + mpWrtShell->DelRight(); + } + mpWrtShell->EndUndo(); + PrepareView(); + mpWrtShell->EndAllAction(); + mbLayout = true; + CalcRects(); + LayoutPostIts(); +} + +void SwPostItMgr::Delete() +{ + mpWrtShell->StartAllAction(); + SetActiveSidebarWin(0); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, SW_RES(STR_DELETE_ALL_NOTES) ); + mpWrtShell->StartUndo( UNDO_DELETE, &aRewriter ); + + std::vector<const SwFmtFld*> aTmp; + aTmp.reserve( mvPostItFlds.size() ); + for(std::list<SwSidebarItem*>::iterator pPostIt = mvPostItFlds.begin(); pPostIt!= mvPostItFlds.end() ; ++pPostIt) + { + aTmp.push_back( &(*pPostIt)->GetFmtFld() ); + } + for(std::vector<const SwFmtFld*>::iterator i = aTmp.begin(); i != aTmp.end() ; ++i) + { + mpWrtShell->GotoField( *(*i) ); + mpWrtShell->DelRight(); + } + + mpWrtShell->EndUndo(); + PrepareView(); + mpWrtShell->EndAllAction(); + mbLayout = true; + CalcRects(); + LayoutPostIts(); +} + +void SwPostItMgr::ExecuteFormatAllDialog(SwView& rView) +{ + if (mvPostItFlds.empty()) + return; + sw::sidebarwindows::SwSidebarWin *pOrigActiveWin = GetActiveSidebarWin(); + sw::sidebarwindows::SwSidebarWin *pWin = pOrigActiveWin; + if (!pWin) + { + for (SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end(); ++i) + { + pWin = (*i)->pPostIt; + if (pWin) + break; + } + } + if (!pWin) + return; + SetActiveSidebarWin(pWin); + OutlinerView* pOLV = pWin->GetOutlinerView(); + SfxItemSet aEditAttr(pOLV->GetAttribs()); + SfxItemPool* pPool(SwAnnotationShell::GetAnnotationPool(rView)); + SfxItemSet aDlgAttr(*pPool, EE_ITEMS_START, EE_ITEMS_END); + aDlgAttr.Put(aEditAttr); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + SfxAbstractTabDialog* pDlg = pFact->CreateSwCharDlg(rView.GetWindow(), rView, aDlgAttr, DLG_CHAR_ANN); + sal_uInt16 nRet = pDlg->Execute(); + if (RET_OK == nRet) + { + aDlgAttr.Put(*pDlg->GetOutputItemSet()); + FormatAll(aDlgAttr); + } + delete pDlg; + SetActiveSidebarWin(pOrigActiveWin); +} + +void SwPostItMgr::FormatAll(const SfxItemSet &rNewAttr) +{ + mpWrtShell->StartAllAction(); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, SW_RES(STR_FORMAT_ALL_NOTES) ); + mpWrtShell->StartUndo( UNDO_INSATTR, &aRewriter ); + + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if (!(*i)->pPostIt) + continue; + OutlinerView* pOLV = (*i)->pPostIt->GetOutlinerView(); + //save old selection + ESelection aOrigSel(pOLV->GetSelection()); + //select all + Outliner *pOutliner = pOLV->GetOutliner(); + if (pOutliner) + { + sal_Int32 nParaCount = pOutliner->GetParagraphCount(); + if (nParaCount > 0) + pOLV->SelectRange(0, nParaCount); + } + //set new char properties + pOLV->SetAttribs(rNewAttr); + //restore old selection + pOLV->SetSelection(aOrigSel); + } + + mpWrtShell->EndUndo(); + PrepareView(); + mpWrtShell->EndAllAction(); + mbLayout = true; + CalcRects(); + LayoutPostIts(); +} + +void SwPostItMgr::Hide( const OUString& rAuthor ) +{ + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->pPostIt && ((*i)->pPostIt->GetAuthor() == rAuthor) ) + { + (*i)->bShow = false; + (*i)->pPostIt->HideNote(); + } + } + + LayoutPostIts(); +} + +void SwPostItMgr::Hide() +{ + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + (*i)->bShow = false; + (*i)->pPostIt->HideNote(); + } +} + +void SwPostItMgr::Show() +{ + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + (*i)->bShow = true; + } + LayoutPostIts(); +} + +void SwPostItMgr::Sort(const short aType) +{ + if (mvPostItFlds.size()>1 ) + { + switch (aType) + { + case SORT_POS: + mvPostItFlds.sort(comp_pos); + break; + } + } +} + +SwSidebarWin* SwPostItMgr::GetSidebarWin( const SfxBroadcaster* pBroadcaster) const +{ + for(const_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->GetBroadCaster() == pBroadcaster) + return (*i)->pPostIt; + } + return NULL; +} + +sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const SwPostItField* pFld) const +{ + for(const_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->GetFmtFld().GetField() == pFld ) + return dynamic_cast<sw::annotation::SwAnnotationWin*>((*i)->pPostIt); + } + return NULL; +} + +SwSidebarWin* SwPostItMgr::GetNextPostIt( sal_uInt16 aDirection, + SwSidebarWin* aPostIt ) +{ + if (mvPostItFlds.size()>1) + { + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + if ( (*i)->pPostIt == aPostIt) + { + SwSidebarItem_iterator iNextPostIt = i; + if (aDirection == KEY_PAGEUP) + { + if ( iNextPostIt == mvPostItFlds.begin() ) + { + return NULL; + } + --iNextPostIt; + } + else + { + ++iNextPostIt; + if ( iNextPostIt == mvPostItFlds.end() ) + { + return NULL; + } + } + // lets quit, we are back at the beginning + if ( (*iNextPostIt)->pPostIt == aPostIt) + return NULL; + return (*iNextPostIt)->pPostIt; + } + } + return NULL; + } + else + return NULL; +} + +long SwPostItMgr::GetNextBorder() +{ + for (unsigned long n=0;n<mPages.size();n++) + { + for(SwSidebarItem_iterator b = mPages[n]->mList->begin(); b!= mPages[n]->mList->end(); ++b) + { + if ((*b)->pPostIt == mpActivePostIt) + { + SwSidebarItem_iterator aNext = b; + ++aNext; + bool bFollow = (aNext == mPages[n]->mList->end()) ? false : (*aNext)->pPostIt->IsFollow(); + if ( mPages[n]->bScrollbar || bFollow ) + { + return -1; + } + else + { + //if this is the last item, return the bottom border otherwise the next item + if (aNext == mPages[n]->mList->end()) + return mpEditWin->LogicToPixel(Point(0,mPages[n]->mPageRect.Bottom())).Y() - GetSpaceBetween(); + else + return (*aNext)->pPostIt->GetPosPixel().Y() - GetSpaceBetween(); + } + } + } + } + + OSL_FAIL("SwPostItMgr::GetNextBorder(): We have to find a next border here"); + return -1; +} + +void SwPostItMgr::SetShadowState(const SwPostItField* pFld,bool bCursor) +{ + if (pFld) + { + if (pFld !=mShadowState.mpShadowFld) + { + if (mShadowState.mpShadowFld) + { + // reset old one if still alive + // TODO: does not work properly if mouse and cursor was set + sw::annotation::SwAnnotationWin* pOldPostIt = + GetAnnotationWin(mShadowState.mpShadowFld); + if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT)) + pOldPostIt->SetViewState(VS_NORMAL); + } + //set new one, if it is not currently edited + sw::annotation::SwAnnotationWin* pNewPostIt = GetAnnotationWin(pFld); + if (pNewPostIt && pNewPostIt->Shadow() && (pNewPostIt->Shadow()->GetShadowState() != SS_EDIT)) + { + pNewPostIt->SetViewState(VS_VIEW); + //remember our new field + mShadowState.mpShadowFld = pFld; + mShadowState.bCursor = false; + mShadowState.bMouse = false; + } + } + if (bCursor) + mShadowState.bCursor = true; + else + mShadowState.bMouse = true; + } + else + { + if (mShadowState.mpShadowFld) + { + if (bCursor) + mShadowState.bCursor = false; + else + mShadowState.bMouse = false; + if (!mShadowState.bCursor && !mShadowState.bMouse) + { + // reset old one if still alive + sw::annotation::SwAnnotationWin* pOldPostIt = GetAnnotationWin(mShadowState.mpShadowFld); + if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT)) + { + pOldPostIt->SetViewState(VS_NORMAL); + mShadowState.mpShadowFld = 0; + } + } + } + } +} + +void SwPostItMgr::PrepareView(bool bIgnoreCount) +{ + if (!HasNotes() || bIgnoreCount) + { + mpWrtShell->StartAllAction(); + SwRootFrm* pLayout = mpWrtShell->GetLayout(); + if ( pLayout ) + SwPostItHelper::setSidebarChanged( pLayout, + mpWrtShell->getIDocumentSettingAccess()->get( IDocumentSettingAccess::BROWSE_MODE ) ); + mpWrtShell->EndAllAction(); + } +} + +bool SwPostItMgr::ShowScrollbar(const unsigned long aPage) const +{ + if (mPages.size() > aPage-1) + return (mPages[aPage-1]->bScrollbar && !mbWaitingForCalcRects); + else + return false; +} + +bool SwPostItMgr::IsHit(const Point &aPointPixel) +{ + if (HasNotes() && ShowNotes()) + { + const Point aPoint = mpEditWin->PixelToLogic(aPointPixel); + const SwRootFrm* pLayout = mpWrtShell->GetLayout(); + SwRect aPageFrm; + const unsigned long nPageNum = SwPostItHelper::getPageInfo( aPageFrm, pLayout, aPoint ); + if( nPageNum ) + { + Rectangle aRect; + OSL_ENSURE(mPages.size()>nPageNum-1,"SwPostitMgr:: page container size wrong"); + aRect = mPages[nPageNum-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? Rectangle(Point(aPageFrm.Left()-GetSidebarWidth()-GetSidebarBorderWidth(),aPageFrm.Top()),Size(GetSidebarWidth(),aPageFrm.Height())) + : Rectangle( Point(aPageFrm.Right()+GetSidebarBorderWidth(),aPageFrm.Top()) , Size(GetSidebarWidth(),aPageFrm.Height())); + if (aRect.IsInside(aPoint)) + { + // we hit the note's sidebar + // lets now test for the arrow area + if (mPages[nPageNum-1]->bScrollbar) + return ScrollbarHit(nPageNum,aPoint); + else + return false; + } + } + } + return false; +} +Rectangle SwPostItMgr::GetBottomScrollRect(const unsigned long aPage) const +{ + SwRect aPageRect = mPages[aPage-1]->mPageRect; + Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? Point(aPageRect.Left() - GetSidebarWidth() - GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height()) + : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height()); + Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ; + return Rectangle(aPointBottom,aSize); +} + +Rectangle SwPostItMgr::GetTopScrollRect(const unsigned long aPage) const +{ + SwRect aPageRect = mPages[aPage-1]->mPageRect; + Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? Point(aPageRect.Left() - GetSidebarWidth() -GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height()) + : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height()); + Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ; + return Rectangle(aPointTop,aSize); +} + +//IMPORTANT: if you change the rects here, also change SwPageFrm::PaintNotesSidebar() +bool SwPostItMgr::ScrollbarHit(const unsigned long aPage,const Point &aPoint) +{ + SwRect aPageRect = mPages[aPage-1]->mPageRect; + Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height()) + : Point(aPageRect.Right() + GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height()); + + Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height()) + : Point(aPageRect.Right()+GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height()); + + Rectangle aRectBottom(GetBottomScrollRect(aPage)); + Rectangle aRectTop(GetTopScrollRect(aPage)); + + if (aRectBottom.IsInside(aPoint)) + { + if (aPoint.X() < long((aPointBottom.X() + GetSidebarWidth()/3))) + Scroll( GetScrollSize(),aPage); + else + Scroll( -1*GetScrollSize(), aPage); + return true; + } + else if (aRectTop.IsInside(aPoint)) + { + if (aPoint.X() < long((aPointTop.X() + GetSidebarWidth()/3*2))) + Scroll(GetScrollSize(), aPage); + else + Scroll(-1*GetScrollSize(), aPage); + return true; + } + return false; +} + +void SwPostItMgr::CorrectPositions() +{ + if ( mbWaitingForCalcRects || mbLayouting || mvPostItFlds.empty() ) + return; + + // find first valid note + SwSidebarWin *pFirstPostIt = 0; + for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + { + pFirstPostIt = (*i)->pPostIt; + if (pFirstPostIt) + break; + } + + //if we have not found a valid note, forget about it and leave + if (!pFirstPostIt) + return; + + // yeah, I know, if this is a left page it could be wrong, but finding the page and the note is probably not even faster than just doing it + // check, if anchor overlay object exists. + const long aAnchorX = pFirstPostIt->Anchor() + ? mpEditWin->LogicToPixel( Point((long)(pFirstPostIt->Anchor()->GetSixthPosition().getX()),0)).X() + : 0; + const long aAnchorY = pFirstPostIt->Anchor() + ? mpEditWin->LogicToPixel( Point(0,(long)(pFirstPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1 + : 0; + if (Point(aAnchorX,aAnchorY) != pFirstPostIt->GetPosPixel()) + { + long aAnchorPosX = 0; + long aAnchorPosY = 0; + for (unsigned long n=0;n<mPages.size();n++) + { + for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i != mPages[n]->mList->end(); ++i) + { + // check, if anchor overlay object exists. + if ( (*i)->bShow && (*i)->pPostIt && (*i)->pPostIt->Anchor() ) + { + aAnchorPosX = mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT + ? mpEditWin->LogicToPixel( Point((long)((*i)->pPostIt->Anchor()->GetSeventhPosition().getX()),0)).X() + : mpEditWin->LogicToPixel( Point((long)((*i)->pPostIt->Anchor()->GetSixthPosition().getX()),0)).X(); + aAnchorPosY = mpEditWin->LogicToPixel( Point(0,(long)((*i)->pPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1; + (*i)->pPostIt->SetPosPixel(Point(aAnchorPosX,aAnchorPosY)); + } + } + } + } +} + +bool SwPostItMgr::ShowNotes() const +{ + // we only want to see notes if Options - Writer - View - Notes is ticked + return mpWrtShell->GetViewOptions()->IsPostIts(); +} + +bool SwPostItMgr::HasNotes() const +{ + return !mvPostItFlds.empty(); +} + +unsigned long SwPostItMgr::GetSidebarWidth(bool bPx) const +{ + unsigned long aWidth = (unsigned long)(mpWrtShell->GetViewOptions()->GetZoom() * 1.8); + if (bPx) + return aWidth; + else + return mpEditWin->PixelToLogic(Size( aWidth ,0)).Width(); +} + +unsigned long SwPostItMgr::GetSidebarBorderWidth(bool bPx) const +{ + if (bPx) + return 2; + else + return mpEditWin->PixelToLogic(Size(2,0)).Width(); +} + +unsigned long SwPostItMgr::GetNoteWidth() +{ + return GetSidebarWidth(true); +} + +Color SwPostItMgr::GetColorDark(sal_uInt16 aAuthorIndex) +{ + if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + static const Color aArrayNormal[] = { + COL_AUTHOR1_NORMAL, COL_AUTHOR2_NORMAL, COL_AUTHOR3_NORMAL, + COL_AUTHOR4_NORMAL, COL_AUTHOR5_NORMAL, COL_AUTHOR6_NORMAL, + COL_AUTHOR7_NORMAL, COL_AUTHOR8_NORMAL, COL_AUTHOR9_NORMAL }; + + return Color( aArrayNormal[ aAuthorIndex % (sizeof( aArrayNormal )/ sizeof( aArrayNormal[0] ))]); + } + else + return Color(COL_WHITE); +} + +Color SwPostItMgr::GetColorLight(sal_uInt16 aAuthorIndex) +{ + if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + static const Color aArrayLight[] = { + COL_AUTHOR1_LIGHT, COL_AUTHOR2_LIGHT, COL_AUTHOR3_LIGHT, + COL_AUTHOR4_LIGHT, COL_AUTHOR5_LIGHT, COL_AUTHOR6_LIGHT, + COL_AUTHOR7_LIGHT, COL_AUTHOR8_LIGHT, COL_AUTHOR9_LIGHT }; + + return Color( aArrayLight[ aAuthorIndex % (sizeof( aArrayLight )/ sizeof( aArrayLight[0] ))]); + } + else + return Color(COL_WHITE); +} + +Color SwPostItMgr::GetColorAnchor(sal_uInt16 aAuthorIndex) +{ + if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + static const Color aArrayAnchor[] = { + COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK, + COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK, + COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK }; + + return Color( aArrayAnchor[ aAuthorIndex % (sizeof( aArrayAnchor ) / sizeof( aArrayAnchor[0] ))]); + } + else + return Color(COL_WHITE); +} + +void SwPostItMgr::SetActiveSidebarWin( SwSidebarWin* p) +{ + if ( p != mpActivePostIt ) + { + // we need the temp variable so we can set mpActivePostIt before we call DeactivatePostIt + // therefore we get a new layout in DOCCHANGED when switching from postit to document, + // otherwise, GetActivePostIt() would still hold our old postit + SwSidebarWin* pActive = mpActivePostIt; + mpActivePostIt = p; + if (pActive) + { + pActive->DeactivatePostIt(); + mShadowState.mpShadowFld = 0; + } + if (mpActivePostIt) + { + mpActivePostIt->GotoPos(); + mpView->SetAnnotationMode(true); + mpView->AttrChangedNotify(0); + mpView->SetAnnotationMode(false); + mpActivePostIt->ActivatePostIt(); + } + } +} + +IMPL_LINK( SwPostItMgr, CalcHdl, void*, /* pVoid*/ ) +{ + mnEventId = 0; + if ( mbLayouting ) + { + OSL_FAIL("Reentrance problem in Layout Manager!"); + mbWaitingForCalcRects = false; + return 0; + } + + // do not change order, even if it would seem so in the first place, we need the calcrects always + if (CalcRects() || mbLayout) + { + mbLayout = false; + LayoutPostIts(); + } + return 0; +} + +void SwPostItMgr::Rescale() +{ + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + if ( (*i)->pPostIt ) + (*i)->pPostIt->Rescale(); +} + +sal_Int32 SwPostItMgr::GetInitialAnchorDistance() const +{ + const Fraction& f( mpEditWin->GetMapMode().GetScaleY() ); + return POSTIT_INITIAL_ANCHOR_DISTANCE * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwPostItMgr::GetSpaceBetween() const +{ + const Fraction& f( mpEditWin->GetMapMode().GetScaleY() ); + return ( POSTIT_SPACE_BETWEEN ) * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwPostItMgr::GetScrollSize() const +{ + const Fraction& f( mpEditWin->GetMapMode().GetScaleY() ); + return ( POSTIT_SPACE_BETWEEN + POSTIT_MINIMUMSIZE_WITH_META ) * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwPostItMgr::GetMinimumSizeWithMeta() const +{ + const Fraction& f( mpEditWin->GetMapMode().GetScaleY() ); + return POSTIT_MINIMUMSIZE_WITH_META * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwPostItMgr::GetSidebarScrollerHeight() const +{ + const Fraction& f( mpEditWin->GetMapMode().GetScaleY() ); + return POSTIT_SCROLL_SIDEBAR_HEIGHT * f.GetNumerator() / f.GetDenominator(); +} + +void SwPostItMgr::SetSpellChecking() +{ + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + if ( (*i)->pPostIt ) + (*i)->pPostIt->SetSpellChecking(); +} + +void SwPostItMgr::SetReadOnlyState() +{ + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + if ( (*i)->pPostIt ) + (*i)->pPostIt->SetReadonly( mbReadOnly ); +} + +void SwPostItMgr::CheckMetaText() +{ + for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i != mvPostItFlds.end() ; ++i) + if ( (*i)->pPostIt ) + (*i)->pPostIt->CheckMetaText(); + +} + +sal_uInt16 SwPostItMgr::Replace(SvxSearchItem* pItem) +{ + SwSidebarWin* pWin = GetActiveSidebarWin(); + sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( *pItem ); + if (!aResult) + SetActiveSidebarWin(0); + return aResult; +} + +sal_uInt16 SwPostItMgr::FinishSearchReplace(const ::com::sun::star::util::SearchOptions& rSearchOptions, bool bSrchForward) +{ + SwSidebarWin* pWin = GetActiveSidebarWin(); + SvxSearchItem aItem(SID_SEARCH_ITEM ); + aItem.SetSearchOptions(rSearchOptions); + aItem.SetBackward(!bSrchForward); + sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem ); + if (!aResult) + SetActiveSidebarWin(0); + return aResult; +} + +sal_uInt16 SwPostItMgr::SearchReplace(const SwFmtFld &pFld, const ::com::sun::star::util::SearchOptions& rSearchOptions, bool bSrchForward) +{ + sal_uInt16 aResult = 0; + SwSidebarWin* pWin = GetSidebarWin(&pFld); + if (pWin) + { + ESelection aOldSelection = pWin->GetOutlinerView()->GetSelection(); + if (bSrchForward) + pWin->GetOutlinerView()->SetSelection(ESelection(0,0,0,0)); + else + pWin->GetOutlinerView()->SetSelection( + ESelection(EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT,EE_PARA_MAX_COUNT,EE_TEXTPOS_MAX_COUNT)); + SvxSearchItem aItem(SID_SEARCH_ITEM ); + aItem.SetSearchOptions(rSearchOptions); + aItem.SetBackward(!bSrchForward); + aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem ); + if (!aResult) + pWin->GetOutlinerView()->SetSelection(aOldSelection); + else + { + SetActiveSidebarWin(pWin); + MakeVisible(pWin); + } + } + return aResult; +} + +void SwPostItMgr::AssureStdModeAtShell() +{ + // deselect any drawing or frame and leave editing mode + SdrView* pSdrView = mpWrtShell->GetDrawView(); + if ( pSdrView && pSdrView->IsTextEdit() ) + { + bool bLockView = mpWrtShell->IsViewLocked(); + mpWrtShell->LockView( true ); + mpWrtShell->EndTextEdit(); + mpWrtShell->LockView( bLockView ); + } + + if( mpWrtShell->IsSelFrmMode() || mpWrtShell->IsObjSelected()) + { + mpWrtShell->UnSelectFrm(); + mpWrtShell->LeaveSelFrmMode(); + mpWrtShell->GetView().LeaveDrawCreate(); + mpWrtShell->EnterStdMode(); + + mpWrtShell->DrawSelChanged(); + mpView->StopShellTimer(); + } +} + +bool SwPostItMgr::HasActiveSidebarWin() const +{ + return mpActivePostIt != 0; +} + +bool SwPostItMgr::HasActiveAnnotationWin() const +{ + return HasActiveSidebarWin() && + dynamic_cast<sw::annotation::SwAnnotationWin*>(mpActivePostIt) != 0; +} + +void SwPostItMgr::GrabFocusOnActiveSidebarWin() +{ + if ( HasActiveSidebarWin() ) + { + mpActivePostIt->GrabFocus(); + } +} + +void SwPostItMgr::UpdateDataOnActiveSidebarWin() +{ + if ( HasActiveSidebarWin() ) + { + mpActivePostIt->UpdateData(); + } +} + +void SwPostItMgr::DeleteActiveSidebarWin() +{ + if ( HasActiveSidebarWin() ) + { + mpActivePostIt->Delete(); + } +} + +void SwPostItMgr::HideActiveSidebarWin() +{ + if ( HasActiveSidebarWin() ) + { + mpActivePostIt->Hide(); + } +} + +void SwPostItMgr::ToggleInsModeOnActiveSidebarWin() +{ + if ( HasActiveSidebarWin() ) + { + mpActivePostIt->ToggleInsMode(); + } +} + +void SwPostItMgr::ConnectSidebarWinToFrm( const SwFrm& rFrm, + const SwFmtFld& rFmtFld, + SwSidebarWin& rSidebarWin ) +{ + if ( mpFrmSidebarWinContainer == 0 ) + { + mpFrmSidebarWinContainer = new SwFrmSidebarWinContainer(); + } + + const bool bInserted = mpFrmSidebarWinContainer->insert( rFrm, rFmtFld, rSidebarWin ); + if ( bInserted && + mpWrtShell->GetAccessibleMap() ) + { + mpWrtShell->GetAccessibleMap()->InvalidatePosOrSize( 0, 0, &rSidebarWin, SwRect() ); + } +} + +void SwPostItMgr::DisconnectSidebarWinFromFrm( const SwFrm& rFrm, + SwSidebarWin& rSidebarWin ) +{ + if ( mpFrmSidebarWinContainer != 0 ) + { + const bool bRemoved = mpFrmSidebarWinContainer->remove( rFrm, rSidebarWin ); + if ( bRemoved && + mpWrtShell->GetAccessibleMap() ) + { + mpWrtShell->GetAccessibleMap()->Dispose( 0, 0, &rSidebarWin ); + } + } +} + +bool SwPostItMgr::HasFrmConnectedSidebarWins( const SwFrm& rFrm ) +{ + bool bRet( false ); + + if ( mpFrmSidebarWinContainer != 0 ) + { + bRet = !mpFrmSidebarWinContainer->empty( rFrm ); + } + + return bRet; +} + +Window* SwPostItMgr::GetSidebarWinForFrmByIndex( const SwFrm& rFrm, + const sal_Int32 nIndex ) +{ + Window* pSidebarWin( 0 ); + + if ( mpFrmSidebarWinContainer != 0 ) + { + pSidebarWin = mpFrmSidebarWinContainer->get( rFrm, nIndex ); + } + + return pSidebarWin; +} + +void SwPostItMgr::GetAllSidebarWinForFrm( const SwFrm& rFrm, + std::vector< Window* >* pChildren ) +{ + if ( mpFrmSidebarWinContainer != 0 ) + { + mpFrmSidebarWinContainer->getAll( rFrm, pChildren ); + } +} + +void SwNoteProps::Commit() {} +void SwNoteProps::Notify( const ::com::sun::star::uno::Sequence< OUString >& ) {} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/ShadowOverlayObject.cxx b/sw/source/uibase/docvw/ShadowOverlayObject.cxx new file mode 100644 index 000000000000..2b9b4d2fa7f8 --- /dev/null +++ b/sw/source/uibase/docvw/ShadowOverlayObject.cxx @@ -0,0 +1,252 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <ShadowOverlayObject.hxx> + +#include <view.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/svdview.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> + +#include <sw_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> + +namespace sw { namespace sidebarwindows { + +// helper SwPostItShadowPrimitive + +// Used to allow view-dependent primitive definition. For that purpose, the +// initially created primitive (this one) always has to be view-independent, +// but the decomposition is made view-dependent. Very simple primitive which +// just remembers the discrete data and applies it at decomposition time. +class ShadowPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D +{ +private: + basegfx::B2DPoint maBasePosition; + basegfx::B2DPoint maSecondPosition; + ShadowState maShadowState; + +protected: + virtual drawinglayer::primitive2d::Primitive2DSequence create2DDecomposition( + const drawinglayer::geometry::ViewInformation2D& rViewInformation) const SAL_OVERRIDE; + +public: + ShadowPrimitive( + const basegfx::B2DPoint& rBasePosition, + const basegfx::B2DPoint& rSecondPosition, + ShadowState aShadowState) + : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), + maBasePosition(rBasePosition), + maSecondPosition(rSecondPosition), + maShadowState(aShadowState) + {} + + // data access + const basegfx::B2DPoint& getBasePosition() const { return maBasePosition; } + const basegfx::B2DPoint& getSecondPosition() const { return maSecondPosition; } + ShadowState getShadowState() const { return maShadowState; } + + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const SAL_OVERRIDE; + + DeclPrimitive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence ShadowPrimitive::create2DDecomposition( + const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const +{ + // get logic sizes in object coordinate system + drawinglayer::primitive2d::Primitive2DSequence xRetval; + basegfx::B2DRange aRange(getBasePosition()); + + switch(maShadowState) + { + case SS_NORMAL: + { + aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (2.0 * getDiscreteUnit()))); + const ::drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GRADIENTSTYLE_LINEAR, + 0.0, + 0.5, + 0.5, + 1800.0 * F_PI1800, + basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0), + basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0), + 2); + + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + aFillGradientAttribute)); + + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + break; + } + case SS_VIEW: + { + aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit()))); + const drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GRADIENTSTYLE_LINEAR, + 0.0, + 0.5, + 0.5, + 1800.0 * F_PI1800, + basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0), + basegfx::BColor(180.0/255.0,180.0/255.0,180.0/255.0), + 4); + + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + aFillGradientAttribute)); + + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + break; + } + case SS_EDIT: + { + aRange.expand(basegfx::B2DTuple(getSecondPosition().getX(), getSecondPosition().getY() + (4.0 * getDiscreteUnit()))); + const drawinglayer::attribute::FillGradientAttribute aFillGradientAttribute( + drawinglayer::attribute::GRADIENTSTYLE_LINEAR, + 0.0, + 0.5, + 0.5, + 1800.0 * F_PI1800, + basegfx::BColor(230.0/255.0,230.0/255.0,230.0/255.0), + basegfx::BColor(83.0/255.0,83.0/255.0,83.0/255.0), + 4); + + const drawinglayer::primitive2d::Primitive2DReference xReference( + new drawinglayer::primitive2d::FillGradientPrimitive2D( + aRange, + aFillGradientAttribute)); + + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); + break; + } + default: + { + break; + } + } + + return xRetval; +} + +bool ShadowPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const ShadowPrimitive& rCompare = static_cast< const ShadowPrimitive& >(rPrimitive); + + return (getBasePosition() == rCompare.getBasePosition() + && getSecondPosition() == rCompare.getSecondPosition() + && getShadowState() == rCompare.getShadowState()); + } + + return false; +} + +ImplPrimitive2DIDBlock(ShadowPrimitive, PRIMITIVE2D_ID_SWSIDEBARSHADOWPRIMITIVE) + +/* static */ ShadowOverlayObject* ShadowOverlayObject::CreateShadowOverlayObject( SwView& rDocView ) +{ + ShadowOverlayObject* pShadowOverlayObject( 0 ); + + if ( rDocView.GetDrawView() ) + { + SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0); + if( pPaintWindow ) + { + rtl::Reference< ::sdr::overlay::OverlayManager > xOverlayManager = pPaintWindow->GetOverlayManager(); + + if ( xOverlayManager.is() ) + { + pShadowOverlayObject = new ShadowOverlayObject( basegfx::B2DPoint(0,0), + basegfx::B2DPoint(0,0), + Color(0,0,0), + SS_NORMAL ); + xOverlayManager->add(*pShadowOverlayObject); + } + } + } + + return pShadowOverlayObject; +} + +/* static */ void ShadowOverlayObject::DestroyShadowOverlayObject( ShadowOverlayObject* pShadow ) +{ + if ( pShadow ) + { + if ( pShadow->getOverlayManager() ) + { + pShadow->getOverlayManager()->remove(*pShadow); + } + delete pShadow; + } +} + +ShadowOverlayObject::ShadowOverlayObject( const basegfx::B2DPoint& rBasePos, + const basegfx::B2DPoint& rSecondPosition, + Color aBaseColor, + ShadowState aState ) + : OverlayObjectWithBasePosition(rBasePos, aBaseColor) + , maSecondPosition(rSecondPosition) + , mShadowState(aState) +{ +} + +ShadowOverlayObject::~ShadowOverlayObject() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence ShadowOverlayObject::createOverlayObjectPrimitive2DSequence() +{ + const drawinglayer::primitive2d::Primitive2DReference aReference( + new ShadowPrimitive( getBasePosition(), + GetSecondPosition(), + GetShadowState() ) ); + return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); +} + +void ShadowOverlayObject::SetShadowState(ShadowState aState) +{ + if (mShadowState != aState) + { + mShadowState = aState; + + objectChange(); + } +} + +void ShadowOverlayObject::SetPosition( const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2) +{ + if(!rPoint1.equal(getBasePosition()) || !rPoint2.equal(GetSecondPosition())) + { + maBasePosition = rPoint1; + maSecondPosition = rPoint2; + + objectChange(); + } +} + +} } // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/ShadowOverlayObject.hxx b/sw/source/uibase/docvw/ShadowOverlayObject.hxx new file mode 100644 index 000000000000..a6751824d362 --- /dev/null +++ b/sw/source/uibase/docvw/ShadowOverlayObject.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SHADOWOVERLAYOBJECT_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SHADOWOVERLAYOBJECT_HXX + +#include <svx/sdr/overlay/overlayobject.hxx> + +class SwView; + +namespace sw { namespace sidebarwindows { + +enum ShadowState +{ + SS_NORMAL, + SS_VIEW, + SS_EDIT +}; + +class ShadowOverlayObject: public sdr::overlay::OverlayObjectWithBasePosition +{ + protected: + // geometry creation for OverlayObject + virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence() SAL_OVERRIDE; + + private: + basegfx::B2DPoint maSecondPosition; + ShadowState mShadowState; + + ShadowOverlayObject( const basegfx::B2DPoint& rBasePos, + const basegfx::B2DPoint& rSecondPosition, + Color aBaseColor, + ShadowState aState ); + virtual ~ShadowOverlayObject(); + + public: + void SetShadowState(ShadowState aState); + inline ShadowState GetShadowState() {return mShadowState;} + + inline const basegfx::B2DPoint& GetSecondPosition() const { return maSecondPosition; } + void SetSecondPosition( const basegfx::B2DPoint& rNew ); + + void SetPosition( const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2 ); + + static ShadowOverlayObject* CreateShadowOverlayObject( SwView& rDocView ); + static void DestroyShadowOverlayObject( ShadowOverlayObject* pShadow ); +}; + +} } // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControl.cxx b/sw/source/uibase/docvw/SidebarTxtControl.cxx new file mode 100644 index 000000000000..5834c020832a --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.cxx @@ -0,0 +1,433 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <SidebarTxtControl.hxx> + +#include <SidebarTxtControlAcc.hxx> + +#include <SidebarWin.hxx> +#include <PostItMgr.hxx> + +#include <cmdid.h> +#include <docvw.hrc> + +#include <unotools/securityoptions.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/mnumgr.hxx> + +#include <vcl/svapp.hxx> +#include <vcl/help.hxx> +#include <vcl/layout.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/gradient.hxx> +#include <vcl/scrbar.hxx> +#include <vcl/settings.hxx> + +#include <editeng/outliner.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editview.hxx> +#include <editeng/flditem.hxx> + +#include <uitool.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <shellres.hxx> +#include <SwRewriter.hxx> + +namespace sw { namespace sidebarwindows { + +SidebarTxtControl::SidebarTxtControl( SwSidebarWin& rSidebarWin, + WinBits nBits, + SwView& rDocView, + SwPostItMgr& rPostItMgr ) + : Control( &rSidebarWin, nBits ) + , mrSidebarWin( rSidebarWin ) + , mrDocView( rDocView ) + , mrPostItMgr( rPostItMgr ) +{ + AddEventListener( LINK( &mrSidebarWin, SwSidebarWin, WindowEventListener ) ); +} + +SidebarTxtControl::~SidebarTxtControl() +{ + RemoveEventListener( LINK( &mrSidebarWin, SwSidebarWin, WindowEventListener ) ); +} + +OutlinerView* SidebarTxtControl::GetTextView() const +{ + return mrSidebarWin.GetOutlinerView(); +} + +void SidebarTxtControl::GetFocus() +{ + Window::GetFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTxtControl::LoseFocus() +{ + // write the visible text back into the SwField + mrSidebarWin.UpdateData(); + + Window::LoseFocus(); + if ( !mrSidebarWin.IsMouseOver() ) + { + Invalidate(); + } +} + +void SidebarTxtControl::RequestHelp(const HelpEvent &rEvt) +{ + sal_uInt16 nResId = 0; + switch( mrSidebarWin.GetLayoutStatus() ) + { + case SwPostItHelper::INSERTED: nResId = STR_REDLINE_INSERT; break; + case SwPostItHelper::DELETED: nResId = STR_REDLINE_DELETE; break; + default: nResId = 0; + } + + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_REDLINE ); + if ( nResId && + mrDocView.GetWrtShell().GetContentAtPos( mrSidebarWin.GetAnchorPos(), aCntntAtPos ) ) + { + OUString sTxt = SW_RESSTR( nResId ) + ": " + + aCntntAtPos.aFnd.pRedl->GetAuthorString() + " - " + + GetAppLangDateTimeString( aCntntAtPos.aFnd.pRedl->GetTimeStamp() ); + Help::ShowQuickHelp( this,PixelToLogic(Rectangle(rEvt.GetMousePosPixel(),Size(50,10))),sTxt); + } +} + +void SidebarTxtControl::Draw(OutputDevice* pDev, const Point& rPt, const Size& rSz, sal_uLong) +{ + //Take the control's height, but overwrite the scrollbar area if there was one + Size aSize(PixelToLogic(GetSizePixel())); + aSize.Width() = rSz.Width(); + + if ( GetTextView() ) + { + GetTextView()->GetOutliner()->Draw(pDev, Rectangle(rPt, aSize)); + } + + if ( mrSidebarWin.GetLayoutStatus()==SwPostItHelper::DELETED ) + { + SetLineColor(mrSidebarWin.GetChangeColor()); + pDev->DrawLine( PixelToLogic( GetPosPixel(), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(), + GetSizePixel().Height() ), pDev->GetMapMode() ) ); + pDev->DrawLine( PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(),0), pDev->GetMapMode() ), + PixelToLogic( GetPosPixel() + + Point( 0, GetSizePixel().Height() ), pDev->GetMapMode() ) ); + } +} + +void SidebarTxtControl::Paint( const Rectangle& rRect) +{ + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + if ( mrSidebarWin.IsMouseOverSidebarWin() || + HasFocus() ) + { + DrawGradient( Rectangle( Point(0,0), PixelToLogic(GetSizePixel()) ), + Gradient( GradientStyle_LINEAR, + mrSidebarWin.ColorDark(), + mrSidebarWin.ColorDark() ) ); + } + else + { + DrawGradient( Rectangle( Point(0,0), PixelToLogic(GetSizePixel()) ), + Gradient( GradientStyle_LINEAR, + mrSidebarWin.ColorLight(), + mrSidebarWin.ColorDark())); + } + } + + if ( GetTextView() ) + { + GetTextView()->Paint( rRect ); + } + + if ( mrSidebarWin.GetLayoutStatus()==SwPostItHelper::DELETED ) + { + SetLineColor(mrSidebarWin.GetChangeColor()); + DrawLine( PixelToLogic( GetPosPixel() ), + PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(), + GetSizePixel().Height() ) ) ); + DrawLine( PixelToLogic( GetPosPixel() + + Point( GetSizePixel().Width(),0) ), + PixelToLogic( GetPosPixel() + + Point( 0, GetSizePixel().Height() ) ) ); + } +} + +void SidebarTxtControl::KeyInput( const KeyEvent& rKeyEvt ) +{ + const KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + sal_uInt16 nKey = rKeyCode.GetCode(); + if ( ( rKeyCode.IsMod1() && rKeyCode.IsMod2() ) && + ( (nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN) ) ) + { + mrSidebarWin.SwitchToPostIt(nKey); + } + else if ( nKey == KEY_ESCAPE || + ( rKeyCode.IsMod1() && + ( nKey == KEY_PAGEUP || + nKey == KEY_PAGEDOWN ) ) ) + { + mrSidebarWin.SwitchToFieldPos(); + } + else if ( nKey == KEY_INSERT ) + { + if ( !rKeyCode.IsMod1() && !rKeyCode.IsMod2() ) + { + mrSidebarWin.ToggleInsMode(); + } + } + else + { + //let's make sure we see our note + mrPostItMgr.MakeVisible(&mrSidebarWin); + + long aOldHeight = mrSidebarWin.GetPostItTextHeight(); + bool bDone = false; + + /// HACK: need to switch off processing of Undo/Redo in Outliner + if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) ) + { + bool bIsProtected = mrSidebarWin.IsProtected(); + if ( !bIsProtected || + ( bIsProtected && + !mrSidebarWin.GetOutlinerView()->GetOutliner()->GetEditEngine().DoesKeyChangeText(rKeyEvt)) ) + { + bDone = GetTextView() && GetTextView()->PostKeyEvent( rKeyEvt ); + } + else + { + MessageDialog(this, "InfoReadonlyDialog", + "modules/swriter/ui/inforeadonlydialog.ui").Execute(); + } + } + if (bDone) + mrSidebarWin.ResizeIfNecessary( aOldHeight, mrSidebarWin.GetPostItTextHeight() ); + else + { + // write back data first when showing navigator + if ( nKey==KEY_F5 ) + mrSidebarWin.UpdateData(); + if (!mrDocView.KeyInput(rKeyEvt)) + Window::KeyInput(rKeyEvt); + } + } + + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTxtControl::MouseMove( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + OutlinerView* pOutlinerView( GetTextView() ); + pOutlinerView->MouseMove( rMEvt ); + // mba: why does OutlinerView not handle the modifier setting?! + // this forces the postit to handle *all* pointer types + SetPointer( pOutlinerView->GetPointer( rMEvt.GetPosPixel() ) ); + + const EditView& aEV = pOutlinerView->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pFld = pItem->GetField(); + const SvxURLField* pURL = PTR_CAST( SvxURLField, pFld ); + if ( pURL ) + { + OUString sURL( pURL->GetURL() ); + SvtSecurityOptions aSecOpts; + if ( aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK) ) + sURL = SwViewShell::GetShellRes()->aLinkCtrlClick + ": " + sURL; + else + sURL = SwViewShell::GetShellRes()->aLinkClick + ": " + sURL; + Help::ShowQuickHelp( this,PixelToLogic(Rectangle(GetPosPixel(),Size(50,10))),sURL); + } + } + } +} + +void SidebarTxtControl::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + { + SvtSecurityOptions aSecOpts; + bool bExecuteMod = aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK); + + if ( !bExecuteMod || (bExecuteMod && rMEvt.GetModifier() == KEY_MOD1)) + { + const EditView& aEV = GetTextView()->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pFld = pItem->GetField(); + const SvxURLField* pURL = PTR_CAST( SvxURLField, pFld ); + if ( pURL ) + { + GetTextView()->MouseButtonDown( rMEvt ); + SwWrtShell &rSh = mrDocView.GetWrtShell(); + OUString sURL( pURL->GetURL() ); + OUString sTarget( pURL->GetTargetFrame() ); + ::LoadURL(rSh, sURL, URLLOAD_NOFILTER, sTarget); + return; + } + } + } + } + + GrabFocus(); + if ( GetTextView() ) + { + GetTextView()->MouseButtonDown( rMEvt ); + } + mrDocView.GetViewFrame()->GetBindings().InvalidateAll(false); +} + +void SidebarTxtControl::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( GetTextView() ) + GetTextView()->MouseButtonUp( rMEvt ); +} + +IMPL_LINK( SidebarTxtControl, OnlineSpellCallback, SpellCallbackInfo*, pInfo ) +{ + if ( pInfo->nCommand == SPELLCMD_STARTSPELLDLG ) + { + mrDocView.GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SFX_CALLMODE_ASYNCHRON); + } + return 0; +} + +IMPL_LINK( SidebarTxtControl, Select, Menu*, pSelMenu ) +{ + mrSidebarWin.ExecuteCommand( pSelMenu->GetCurItemId() ); + return 0; +} + +void SidebarTxtControl::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU ) + { + if ( !mrSidebarWin.IsProtected() && + GetTextView() && + GetTextView()->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(), true )) + { + Link aLink = LINK(this, SidebarTxtControl, OnlineSpellCallback); + GetTextView()->ExecuteSpellPopup(rCEvt.GetMousePosPixel(),&aLink); + } + else + { + SfxPopupMenuManager* pMgr = mrDocView.GetViewFrame()->GetDispatcher()->Popup(0, this,&rCEvt.GetMousePosPixel()); + ((PopupMenu*)pMgr->GetSVMenu())->SetSelectHdl( LINK(this, SidebarTxtControl, Select) ); + + { + OUString aText = ((PopupMenu*)pMgr->GetSVMenu())->GetItemText( FN_DELETE_NOTE_AUTHOR ); + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, mrSidebarWin.GetAuthor()); + aText = aRewriter.Apply(aText); + ((PopupMenu*)pMgr->GetSVMenu())->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); + } + + Point aPos; + if (rCEvt.IsMouseEvent()) + aPos = rCEvt.GetMousePosPixel(); + else + { + const Size aSize = GetSizePixel(); + aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); + } + + //!! call different Execute function to get rid of the new thesaurus sub menu + //!! pointer created in the call to Popup. + //!! Otherwise we would have a memory leak (see also #i107205#) + pMgr->Execute( aPos, this ); + delete pMgr; + } + } + else + if (rCEvt.GetCommand() == COMMAND_WHEEL) + { + if (mrSidebarWin.IsScrollbarVisible()) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if (pData->IsShift() || pData->IsMod1() || pData->IsMod2()) + { + mrDocView.HandleWheelCommands(rCEvt); + } + else + { + HandleScrollCommand( rCEvt, 0 , mrSidebarWin.Scrollbar()); + } + } + else + { + mrDocView.HandleWheelCommands(rCEvt); + } + } + else + { + if ( GetTextView() ) + GetTextView()->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +OUString SidebarTxtControl::GetSurroundingText() const +{ + if (GetTextView()) + return GetTextView()->GetSurroundingText(); + return OUString(); +} + +Selection SidebarTxtControl::GetSurroundingTextSelection() const +{ + if( GetTextView() ) + return GetTextView()->GetSurroundingTextSelection(); + else + return Selection( 0, 0 ); +} + +css::uno::Reference< css::accessibility::XAccessible > SidebarTxtControl::CreateAccessible() +{ + + SidebarTxtControlAccessible* pAcc( new SidebarTxtControlAccessible( *this ) ); + css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc ); + SetWindowPeer( xWinPeer, pAcc ); + + css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY ); + return xAcc; +} + +} } // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControl.hxx b/sw/source/uibase/docvw/SidebarTxtControl.hxx new file mode 100644 index 000000000000..d98503d01519 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControl.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARTXTCONTROL_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARTXTCONTROL_HXX + +#include <vcl/ctrl.hxx> + +class OutlinerView; +class SwView; +class SwPostItMgr; +struct SpellCallbackInfo; + +namespace sw { namespace sidebarwindows { + +class SwSidebarWin; + +class SidebarTxtControl : public Control +{ + private: + SwSidebarWin& mrSidebarWin; + SwView& mrDocView; + SwPostItMgr& mrPostItMgr; + + protected: + virtual void Paint( const Rectangle& rRect) SAL_OVERRIDE; + virtual void KeyInput( const KeyEvent& rKeyEvt ) SAL_OVERRIDE; + virtual void MouseMove( const MouseEvent& rMEvt ) SAL_OVERRIDE; + virtual void MouseButtonDown( const MouseEvent& rMEvt ) SAL_OVERRIDE; + virtual void MouseButtonUp( const MouseEvent& rMEvt ) SAL_OVERRIDE; + virtual void Command( const CommandEvent& rCEvt ) SAL_OVERRIDE; + virtual void LoseFocus() SAL_OVERRIDE; + virtual void RequestHelp(const HelpEvent &rEvt) SAL_OVERRIDE; + virtual OUString GetSurroundingText() const SAL_OVERRIDE; + virtual Selection GetSurroundingTextSelection() const SAL_OVERRIDE; + + DECL_LINK( Select, Menu* ); + + public: + SidebarTxtControl( SwSidebarWin& rSidebarWin, + WinBits nBits, + SwView& rDocView, + SwPostItMgr& rPostItMgr ); + virtual ~SidebarTxtControl(); + + virtual void GetFocus() SAL_OVERRIDE; + + OutlinerView* GetTextView() const; + + DECL_LINK( OnlineSpellCallback, SpellCallbackInfo*); + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible() SAL_OVERRIDE; + + virtual void Draw(OutputDevice* pDev, const Point&, const Size&, sal_uLong) SAL_OVERRIDE; +}; + +} } // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx b/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx new file mode 100644 index 000000000000..5bbd2e8eef2e --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControlAcc.cxx @@ -0,0 +1,293 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <SidebarTxtControlAcc.hxx> + +#include <SidebarTxtControl.hxx> + +#include <svl/brdcst.hxx> +#include <toolkit/awt/vclxaccessiblecomponent.hxx> +#include <editeng/unoedsrc.hxx> +#include <editeng/unoforou.hxx> +#include <editeng/unoviwou.hxx> +#include <editeng/unoedhlp.hxx> +#include <svx/AccessibleTextHelper.hxx> +#include <editeng/outliner.hxx> + +#include <boost/scoped_ptr.hpp> + +namespace sw { namespace sidebarwindows { + +// declaration and implementation of <SvxEditSource> +// for <::accessibiliy::AccessibleTextHelper> instance +class SidebarTextEditSource : public SvxEditSource, + public SfxBroadcaster +{ + public: + SidebarTextEditSource( SidebarTxtControl& rSidebarTxtControl ); + virtual ~SidebarTextEditSource(); + + virtual SvxEditSource* Clone() const SAL_OVERRIDE; + + virtual SvxTextForwarder* GetTextForwarder() SAL_OVERRIDE; + virtual SvxViewForwarder* GetViewForwarder() SAL_OVERRIDE; + virtual SvxEditViewForwarder* GetEditViewForwarder( bool bCreate = false ) SAL_OVERRIDE; + + virtual void UpdateData() SAL_OVERRIDE; + + virtual SfxBroadcaster& GetBroadcaster() const SAL_OVERRIDE; + DECL_LINK( NotifyHdl, EENotify* ); + + private: + SidebarTxtControl& mrSidebarTxtControl; + SvxOutlinerForwarder mTextForwarder; + SvxDrawOutlinerViewForwarder mViewForwarder; +}; + +SidebarTextEditSource::SidebarTextEditSource( SidebarTxtControl& rSidebarTxtControl ) + : SvxEditSource() + , mrSidebarTxtControl( rSidebarTxtControl ) + , mTextForwarder( *(rSidebarTxtControl.GetTextView()->GetOutliner()), false ) + , mViewForwarder( *(rSidebarTxtControl.GetTextView()) ) +{ + if ( mrSidebarTxtControl.GetTextView() ) + { + mrSidebarTxtControl.GetTextView()->GetOutliner()->SetNotifyHdl( LINK(this, SidebarTextEditSource, NotifyHdl) ); + } +} + +SidebarTextEditSource::~SidebarTextEditSource() +{ + if ( mrSidebarTxtControl.GetTextView() ) + { + mrSidebarTxtControl.GetTextView()->GetOutliner()->SetNotifyHdl( Link() ); + } +} + +SvxEditSource* SidebarTextEditSource::Clone() const +{ + return new SidebarTextEditSource( mrSidebarTxtControl ); +} + +SvxTextForwarder* SidebarTextEditSource::GetTextForwarder() +{ + return &mTextForwarder; +} + +SvxViewForwarder* SidebarTextEditSource::GetViewForwarder() +{ + return &mViewForwarder; +} + +SvxEditViewForwarder* SidebarTextEditSource::GetEditViewForwarder( bool /*bCreate*/ ) +{ + return &mViewForwarder; +} + +void SidebarTextEditSource::UpdateData() +{ + // nothing to do +} + +SfxBroadcaster& SidebarTextEditSource::GetBroadcaster() const +{ + return *( const_cast< SidebarTextEditSource* > (this) ); +} + +IMPL_LINK(SidebarTextEditSource, NotifyHdl, EENotify*, pNotify) +{ + if ( pNotify ) + { + boost::scoped_ptr< SfxHint > aHint( SvxEditSourceHelper::EENotification2Hint( pNotify ) ); + + if( aHint.get() ) + { + Broadcast( *aHint.get() ); + } + } + + return 0; +} + +// declaration and implementation of accessible context for <SidebarTxtControl> instance +class SidebarTxtControlAccessibleContext : public VCLXAccessibleComponent +{ + public: + explicit SidebarTxtControlAccessibleContext( SidebarTxtControl& rSidebarTxtControl ); + virtual ~SidebarTxtControlAccessibleContext(); + + virtual sal_Int32 SAL_CALL + getAccessibleChildCount() + throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL + getAccessibleChild( sal_Int32 i ) + throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + + virtual void SAL_CALL + addAccessibleEventListener ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessibleEventListener >& xListener) + throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + virtual void SAL_CALL + removeAccessibleEventListener ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessibleEventListener >& xListener) + throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE; + + protected: + virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) SAL_OVERRIDE; + + private: + SidebarTxtControl& mrSidebarTxtControl; + ::accessibility::AccessibleTextHelper* mpAccessibleTextHelper; + + ::osl::Mutex maMutex; + + void defunc(); +}; + +SidebarTxtControlAccessibleContext::SidebarTxtControlAccessibleContext( SidebarTxtControl& rSidebarTxtControl ) + : VCLXAccessibleComponent( rSidebarTxtControl.GetWindowPeer() ) + , mrSidebarTxtControl( rSidebarTxtControl ) + , mpAccessibleTextHelper( 0 ) + , maMutex() +{ + ::std::auto_ptr<SvxEditSource> pEditSource( + new SidebarTextEditSource( mrSidebarTxtControl ) ); + mpAccessibleTextHelper = new ::accessibility::AccessibleTextHelper( pEditSource ); + mpAccessibleTextHelper->SetEventSource( mrSidebarTxtControl.GetWindowPeer() ); +} + +SidebarTxtControlAccessibleContext::~SidebarTxtControlAccessibleContext() +{ + defunc(); +} + +void SidebarTxtControlAccessibleContext::defunc() +{ + delete mpAccessibleTextHelper; + mpAccessibleTextHelper = 0; +} + +sal_Int32 SAL_CALL SidebarTxtControlAccessibleContext::getAccessibleChildCount() + throw (::com::sun::star::uno::RuntimeException, std::exception) +{ + osl::MutexGuard aGuard( maMutex ); + + sal_Int32 nChildCount( 0 ); + + if ( mpAccessibleTextHelper ) + { + nChildCount = mpAccessibleTextHelper->GetChildCount(); + } + + return nChildCount; +} + +css::uno::Reference< css::accessibility::XAccessible > SAL_CALL SidebarTxtControlAccessibleContext::getAccessibleChild( sal_Int32 i ) + throw ( css::lang::IndexOutOfBoundsException, css::uno::RuntimeException, std::exception ) +{ + osl::MutexGuard aGuard( maMutex ); + + css::uno::Reference< css::accessibility::XAccessible > xChild; + + if ( mpAccessibleTextHelper ) + { + xChild = mpAccessibleTextHelper->GetChild( i ); + } + + return xChild; +} + +void SAL_CALL SidebarTxtControlAccessibleContext::addAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) + throw (css::uno::RuntimeException, std::exception) +{ + osl::MutexGuard aGuard( maMutex ); + + if ( mpAccessibleTextHelper ) + { + mpAccessibleTextHelper->AddEventListener(xListener); + } +} + +void SAL_CALL SidebarTxtControlAccessibleContext::removeAccessibleEventListener ( + const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener) + throw (css::uno::RuntimeException, std::exception) +{ + osl::MutexGuard aGuard( maMutex ); + + if ( mpAccessibleTextHelper ) + { + mpAccessibleTextHelper->RemoveEventListener(xListener); + } +} + +void SidebarTxtControlAccessibleContext::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) +{ + if ( mpAccessibleTextHelper ) + { + switch ( rVclWindowEvent.GetId() ) + { + case VCLEVENT_OBJECT_DYING: + { + defunc(); + } + break; + case VCLEVENT_WINDOW_GETFOCUS: + case VCLEVENT_CONTROL_GETFOCUS: + { + mpAccessibleTextHelper->SetFocus( true ); + } + break; + case VCLEVENT_WINDOW_LOSEFOCUS: + case VCLEVENT_CONTROL_LOSEFOCUS: + { + mpAccessibleTextHelper->SetFocus( false ); + } + break; + } + } + + VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); +} + +// implementaion of accessible for <SidebarTxtControl> instance +SidebarTxtControlAccessible::SidebarTxtControlAccessible( SidebarTxtControl& rSidebarTxtControl ) + : VCLXWindow() + , mrSidebarTxtControl( rSidebarTxtControl ) +{ + SetWindow( &mrSidebarTxtControl ); +} + +SidebarTxtControlAccessible::~SidebarTxtControlAccessible() +{ +} + +css::uno::Reference< css::accessibility::XAccessibleContext > SidebarTxtControlAccessible::CreateAccessibleContext() +{ + SidebarTxtControlAccessibleContext* pAccContext( + new SidebarTxtControlAccessibleContext( mrSidebarTxtControl ) ); + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc( pAccContext ); + return xAcc; +} + +} } // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarTxtControlAcc.hxx b/sw/source/uibase/docvw/SidebarTxtControlAcc.hxx new file mode 100644 index 000000000000..7ac25969e787 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarTxtControlAcc.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARTXTCONTROLACC_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARTXTCONTROLACC_HXX + +#include <toolkit/awt/vclxwindow.hxx> + +namespace sw { namespace sidebarwindows { + +class SidebarTxtControl; + +class SidebarTxtControlAccessible : public VCLXWindow +{ + public: + explicit SidebarTxtControlAccessible( SidebarTxtControl& rSidebarTxtControl ); + virtual ~SidebarTxtControlAccessible(); + + virtual com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessibleContext > + CreateAccessibleContext() SAL_OVERRIDE; + + private: + SidebarTxtControl& mrSidebarTxtControl; +}; + +} } // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarWin.cxx b/sw/source/uibase/docvw/SidebarWin.cxx new file mode 100644 index 000000000000..34aaa23243c7 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarWin.cxx @@ -0,0 +1,1420 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <cstdlib> + +#include <SidebarWin.hxx> +#include <SidebarWinAcc.hxx> +#include <PostItMgr.hxx> + +#include <SidebarTxtControl.hxx> +#include <AnchorOverlayObject.hxx> +#include <ShadowOverlayObject.hxx> +#include <OverlayRanges.hxx> + +#include <annotation.hrc> +#include <popup.hrc> +#include <docvw.hrc> +#include <app.hrc> +#include <access.hrc> + +#include <viewopt.hxx> +#include <cmdid.h> + +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/editview.hxx> +#include <editeng/outliner.hxx> +#include <editeng/editeng.hxx> +#include <editeng/eeitem.hxx> + +#include <svl/zforlist.hxx> +#include <svl/undo.hxx> +#include <svl/stritem.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> + +#include <vcl/scrbar.hxx> +#include <vcl/svapp.hxx> +#include <vcl/menubtn.hxx> +#include <vcl/settings.hxx> + +#include <edtwin.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <wrtsh.hxx> +#include <doc.hxx> +#include <swmodule.hxx> +#include <langhelper.hxx> + +#include <txtannotationfld.hxx> +#include <ndtxt.hxx> + +#include <sw_primitivetypes2d.hxx> +#include <drawinglayer/processor2d/baseprocessor2d.hxx> +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/processor2d/processorfromoutputdevice.hxx> +#include <drawinglayer/primitive2d/shadowprimitive2d.hxx> + +namespace sw { namespace sidebarwindows { + +#define METABUTTON_WIDTH 16 +#define METABUTTON_HEIGHT 18 +#define METABUTTON_AREA_WIDTH 30 +#define POSTIT_META_HEIGHT (sal_Int32) 30 +#define POSTIT_MINIMUMSIZE_WITHOUT_META 50 + +SwSidebarWin::SwSidebarWin( SwEditWin& rEditWin, + WinBits nBits, + SwPostItMgr& aMgr, + SwPostItBits aBits, + SwSidebarItem& rSidebarItem ) + : Window(&rEditWin, nBits) + , mrMgr(aMgr) + , mrView( rEditWin.GetView() ) + , nFlags(aBits) + , mnEventId(0) + , mpOutlinerView(0) + , mpOutliner(0) + , mpSidebarTxtControl(0) + , mpVScrollbar(0) + , mpMetadataAuthor(0) + , mpMetadataDate(0) + , mpMenuButton(0) + , mpAnchor( NULL ) + , mpShadow( NULL ) + , mpTextRangeOverlay( NULL ) + , mColorAnchor() + , mColorDark() + , mColorLight() + , mChangeColor() + , meSidebarPosition( sw::sidebarwindows::SIDEBAR_NONE ) + , mPosSize() + , mAnchorRect() + , mPageBorder( 0 ) + , mbMouseOver( false ) + , mLayoutStatus( SwPostItHelper::INVISIBLE ) + , mbReadonly( false ) + , mbIsFollow( false ) + , mrSidebarItem( rSidebarItem ) + , mpAnchorFrm( rSidebarItem.maLayoutInfo.mpAnchorFrm ) +{ + mpShadow = ShadowOverlayObject::CreateShadowOverlayObject( mrView ); + if ( mpShadow ) + { + mpShadow->setVisible(false); + } + + mrMgr.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), + mrSidebarItem.GetFmtFld(), + *this ); +} + +SwSidebarWin::~SwSidebarWin() +{ + mrMgr.DisconnectSidebarWinFromFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), + *this ); + + Disable(); + + if ( mpSidebarTxtControl ) + { + if ( mpOutlinerView ) + { + mpOutlinerView->SetWindow( 0 ); + } + delete mpSidebarTxtControl; + mpSidebarTxtControl = 0; + } + + if ( mpOutlinerView ) + { + delete mpOutlinerView; + mpOutlinerView = 0; + } + + if (mpOutliner) + { + delete mpOutliner; + mpOutliner = 0; + } + + if (mpMetadataAuthor) + { + mpMetadataAuthor->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + delete mpMetadataAuthor; + mpMetadataAuthor = 0; + } + + if (mpMetadataDate) + { + mpMetadataDate->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + delete mpMetadataDate; + mpMetadataDate = 0; + } + + if (mpVScrollbar) + { + mpVScrollbar->RemoveEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + delete mpVScrollbar; + mpVScrollbar = 0; + } + + AnchorOverlayObject::DestroyAnchorOverlayObject( mpAnchor ); + mpAnchor = NULL; + + ShadowOverlayObject::DestroyShadowOverlayObject( mpShadow ); + mpShadow = NULL; + + delete mpTextRangeOverlay; + mpTextRangeOverlay = NULL; + + delete mpMenuButton; + mpMenuButton = 0; + + if (mnEventId) + Application::RemoveUserEvent( mnEventId ); +} + +void SwSidebarWin::Paint( const Rectangle& rRect) +{ + Window::Paint(rRect); + + if (mpMetadataAuthor->IsVisible() ) + { + //draw left over space + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + SetFillColor(COL_BLACK); + } + else + { + SetFillColor(mColorDark); + } + SetLineColor(); + DrawRect( PixelToLogic( + Rectangle( Point( mpMetadataAuthor->GetPosPixel().X() + + mpMetadataAuthor->GetSizePixel().Width(), + mpMetadataAuthor->GetPosPixel().Y() ), + Size( GetMetaButtonAreaWidth(), + mpMetadataAuthor->GetSizePixel().Height() + + mpMetadataDate->GetSizePixel().Height() ) ) ) ); + } +} + +void SwSidebarWin::Draw(OutputDevice* pDev, const Point& rPt, const Size& rSz, sal_uLong nInFlags) +{ + if (mpMetadataAuthor->IsVisible() ) + { + pDev->SetFillColor(mColorDark); + pDev->SetLineColor(); + pDev->DrawRect( Rectangle( rPt, rSz ) ); + } + + if (mpMetadataAuthor->IsVisible()) + { + Font aOrigFont(mpMetadataAuthor->GetControlFont()); + Size aSize(PixelToLogic(mpMetadataAuthor->GetSizePixel())); + Point aPos(PixelToLogic(mpMetadataAuthor->GetPosPixel())); + aPos += rPt; + Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataAuthor->SetControlFont( aFont ); + mpMetadataAuthor->Draw(pDev, aPos, aSize, nInFlags); + mpMetadataAuthor->SetControlFont( aOrigFont ); + } + + if (mpMetadataDate->IsVisible()) + { + Font aOrigFont(mpMetadataDate->GetControlFont()); + Size aSize(PixelToLogic(mpMetadataDate->GetSizePixel())); + Point aPos(PixelToLogic(mpMetadataDate->GetPosPixel())); + aPos += rPt; + Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataDate->SetControlFont( aFont ); + mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags); + mpMetadataDate->SetControlFont( aOrigFont ); + } + + mpSidebarTxtControl->Draw(pDev, rPt, rSz, nInFlags); + + const drawinglayer::geometry::ViewInformation2D aNewViewInfos; + drawinglayer::processor2d::BaseProcessor2D * pProcessor = + drawinglayer::processor2d::createBaseProcessor2DFromOutputDevice( + *pDev, aNewViewInfos ); + + if (mpAnchor) + pProcessor->process(mpAnchor->getOverlayObjectPrimitive2DSequence()); + if (mpTextRangeOverlay) + pProcessor->process(mpTextRangeOverlay->getOverlayObjectPrimitive2DSequence()); + delete pProcessor; + + if (mpVScrollbar->IsVisible()) + { + Font aOrigFont(mpMetadataDate->GetControlFont()); + Color aOrigBg( mpMetadataDate->GetControlBackground() ); + OUString sOrigText(mpMetadataDate->GetText()); + + Size aSize(PixelToLogic(mpMenuButton->GetSizePixel())); + Point aPos(PixelToLogic(mpMenuButton->GetPosPixel())); + aPos += rPt; + + Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + mpMetadataDate->SetControlFont( aFont ); + mpMetadataDate->SetControlBackground( 0xFFFFFF ); + mpMetadataDate->SetText("..."); + mpMetadataDate->Draw(pDev, aPos, aSize, nInFlags); + + mpMetadataDate->SetText(sOrigText); + mpMetadataDate->SetControlFont( aOrigFont ); + mpMetadataDate->SetControlBackground( aOrigBg ); + } +} + +void SwSidebarWin::SetPosSizePixelRect( long nX, + long nY, + long nWidth, + long nHeight, + const SwRect& aAnchorRect, + const long aPageBorder) +{ + mPosSize = Rectangle(Point(nX,nY),Size(nWidth,nHeight)); + mAnchorRect = aAnchorRect; + mPageBorder = aPageBorder; +} + +void SwSidebarWin::SetSize( const Size& rNewSize ) +{ + mPosSize.SetSize(rNewSize); +} + +void SwSidebarWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize) +{ + mPosSize = Rectangle(aPoint,aSize); +} + +void SwSidebarWin::TranslateTopPosition(const long aAmount) +{ + mPosSize.Move(0,aAmount); +} + +void SwSidebarWin::ShowAnchorOnly(const Point &aPoint) +{ + HideNote(); + SetPosAndSize(); + if (mpAnchor) + { + mpAnchor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y())); + mpAnchor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y())); + mpAnchor->SetAnchorState(AS_ALL); + mpAnchor->setVisible(true); + } + if (mpShadow) + mpShadow->setVisible(false); +} + +SfxItemSet SwSidebarWin::DefaultItem() +{ + SfxItemSet aItem( mrView.GetDocShell()->GetPool() ); + aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT)); + return aItem; +} + +void SwSidebarWin::InitControls() +{ + AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + + // actual window which holds the user text + mpSidebarTxtControl = new SidebarTxtControl( *this, + WB_NODIALOGCONTROL, + mrView, mrMgr ); + mpSidebarTxtControl->SetPointer(Pointer(POINTER_TEXT)); + + // window controls for author and date + mpMetadataAuthor = new Edit( this, 0 ); + mpMetadataAuthor->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_AUTHOR_NAME ) ); + mpMetadataAuthor->EnableRTL(Application::GetSettings().GetLayoutRTL()); + mpMetadataAuthor->SetReadOnly(); + mpMetadataAuthor->AlwaysDisableInput(true); + mpMetadataAuthor->SetCallHandlersOnInputDisabled(true); + mpMetadataAuthor->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + { + AllSettings aSettings = mpMetadataAuthor->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataAuthor->SetSettings(aSettings); + } + + mpMetadataDate = new Edit( this, 0 ); + mpMetadataDate->SetAccessibleName( SW_RES( STR_ACCESS_ANNOTATION_DATE_NAME ) ); + mpMetadataDate->EnableRTL(Application::GetSettings().GetLayoutRTL()); + mpMetadataDate->SetReadOnly(); + mpMetadataDate->AlwaysDisableInput(true); + mpMetadataDate->SetCallHandlersOnInputDisabled(true); + mpMetadataDate->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + { + AllSettings aSettings = mpMetadataDate->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataDate->SetSettings(aSettings); + } + + SwDocShell* aShell = mrView.GetDocShell(); + mpOutliner = new Outliner(&aShell->GetPool(),OUTLINERMODE_TEXTOBJECT); + aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner ); + mpOutliner->SetUpdateMode( true ); + Rescale(); + + mpSidebarTxtControl->EnableRTL( false ); + mpOutlinerView = new OutlinerView ( mpOutliner, mpSidebarTxtControl ); + mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT); + mpOutliner->InsertView(mpOutlinerView ); + mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,1,1) ) ); + + mpOutlinerView->SetAttribs(DefaultItem()); + + //create Scrollbars + mpVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); + mpVScrollbar->EnableNativeWidget(false); + mpVScrollbar->EnableRTL( false ); + mpVScrollbar->SetScrollHdl(LINK(this, SwSidebarWin, ScrollHdl)); + mpVScrollbar->EnableDrag(); + mpVScrollbar->AddEventListener( LINK( this, SwSidebarWin, WindowEventListener ) ); + + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + sal_uLong nCntrl = mpOutliner->GetControlWord(); + // TODO: crash when AUTOCOMPLETE enabled + nCntrl |= EE_CNTRL_MARKFIELDS | EE_CNTRL_PASTESPECIAL | EE_CNTRL_AUTOCORRECT | EV_CNTRL_AUTOSCROLL | EE_CNTRL_URLSFXEXECUTE; // | EE_CNTRL_AUTOCOMPLETE; + if (pVOpt->IsFieldShadings()) + nCntrl |= EE_CNTRL_MARKFIELDS; + else + nCntrl &= ~EE_CNTRL_MARKFIELDS; + if (pVOpt->IsOnlineSpell()) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + sal_uInt16 aIndex = SW_MOD()->InsertRedlineAuthor(GetAuthor()); + SetColor( mrMgr.GetColorDark(aIndex), + mrMgr.GetColorLight(aIndex), + mrMgr.GetColorAnchor(aIndex)); + + CheckMetaText(); + + mpMenuButton = CreateMenuButton(); + + SetLanguage(GetLanguage()); + GetOutlinerView()->StartSpeller(); + SetPostItText(); + Engine()->CompleteOnlineSpelling(); + + mpSidebarTxtControl->Show(); + mpMetadataAuthor->Show(); + mpMetadataDate->Show(); + mpVScrollbar->Show(); +} + +void SwSidebarWin::CheckMetaText() +{ + const SvtSysLocale aSysLocale; + const LocaleDataWrapper& rLocalData = aSysLocale.GetLocaleData(); + OUString sMeta = GetAuthor(); + if (sMeta.isEmpty()) + { + sMeta = SW_RESSTR(STR_NOAUTHOR); + } + else if (sMeta.getLength() > 23) + { + sMeta = sMeta.copy(0, 20) + "..."; + } + if ( mpMetadataAuthor->GetText() != sMeta ) + { + mpMetadataAuthor->SetText(sMeta); + } + + Date aSysDate( Date::SYSTEM ); + Date aDate = GetDate(); + if (aDate==aSysDate) + { + sMeta = SW_RESSTR(STR_POSTIT_TODAY); + } + else if (aDate == Date(aSysDate-1)) + { + sMeta = SW_RESSTR(STR_POSTIT_YESTERDAY); + } + else if (aDate.IsValidAndGregorian() ) + { + sMeta = rLocalData.getDate(aDate); + } + else + { + sMeta = SW_RESSTR(STR_NODATE); + } + if (GetTime()!=0) + { + sMeta += " " + rLocalData.getTime( GetTime(),false ); + } + if ( mpMetadataDate->GetText() != sMeta ) + { + mpMetadataDate->SetText(sMeta); + } +} + +void SwSidebarWin::Rescale() +{ + MapMode aMode = GetParent()->GetMapMode(); + aMode.SetOrigin( Point() ); + mpOutliner->SetRefMapMode( aMode ); + SetMapMode( aMode ); + mpSidebarTxtControl->SetMapMode( aMode ); + if ( mpMetadataAuthor ) + { + Font aFont( mpMetadataAuthor->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = aFont.GetHeight(); + nHeight = nHeight * aMode.GetScaleY().GetNumerator() / aMode.GetScaleY().GetDenominator(); + aFont.SetHeight( nHeight ); + mpMetadataAuthor->SetControlFont( aFont ); + } + if ( mpMetadataDate ) + { + Font aFont( mpMetadataDate->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = aFont.GetHeight(); + nHeight = nHeight * aMode.GetScaleY().GetNumerator() / aMode.GetScaleY().GetDenominator(); + aFont.SetHeight( nHeight ); + mpMetadataDate->SetControlFont( aFont ); + } +} + +void SwSidebarWin::SetPosAndSize() +{ + bool bChange = false; + + if (GetSizePixel() != mPosSize.GetSize()) + { + bChange = true; + SetSizePixel(mPosSize.GetSize()); + DoResize(); + } + + if (GetPosPixel().X() != mPosSize.TopLeft().X() || (std::abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 5) ) + { + bChange = true; + SetPosPixel(mPosSize.TopLeft()); + + Point aLineStart; + Point aLineEnd ; + switch ( meSidebarPosition ) + { + case sw::sidebarwindows::SIDEBAR_LEFT: + { + aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) ); + aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) ); + } + break; + case sw::sidebarwindows::SIDEBAR_RIGHT: + { + aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) ); + aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) ); + } + break; + default: + OSL_FAIL( "<SwSidebarWin::SetPosAndSize()> - unexpected position of sidebar" ); + break; + } + + if (!IsPreview()) + { + if (mpAnchor) + { + mpAnchor->SetAllPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15), + basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15), + basegfx::B2DPoint( mPageBorder ,mAnchorRect.Bottom()+2*15), + basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), + basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y())); + mpAnchor->SetHeight(mAnchorRect.Height()); + } + else + { + mpAnchor = AnchorOverlayObject::CreateAnchorOverlayObject( mrView, + mAnchorRect, + mPageBorder, + aLineStart, + aLineEnd, + mColorAnchor ); + if ( mpAnchor ) + { + mpAnchor->SetHeight(mAnchorRect.Height()); + mpAnchor->setVisible(true); + mpAnchor->SetAnchorState(AS_TRI); + if (HasChildPathFocus()) + { + mpAnchor->setLineSolid(true); + } + } + } + } + } + else + { + if ( mpAnchor && + ( mpAnchor->getBasePosition() != basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom()-5*15) ) ) + { + mpAnchor->SetTriPosition( basegfx::B2DPoint( mAnchorRect.Left() , mAnchorRect.Bottom() - 5* 15), + basegfx::B2DPoint( mAnchorRect.Left()-5*15 , mAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnchorRect.Left()+5*15 , mAnchorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnchorRect.Left(), mAnchorRect.Bottom()+2*15), + basegfx::B2DPoint( mPageBorder , mAnchorRect.Bottom()+2*15)); + } + } + + if (bChange) + { + Point aStart = EditWin()->PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height())); + Point aEnd = EditWin()->PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height())); + mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y())); + } + + if (mrMgr.ShowNotes()) + { + if (IsFollow() && !HasChildPathFocus()) + { + // #i111964# + if ( mpAnchor ) + { + mpAnchor->SetAnchorState(AS_END); + } + } + else + { + // #i111964# + if ( mpAnchor ) + { + mpAnchor->SetAnchorState(AS_ALL); + } + SwSidebarWin* pWin = GetTopReplyNote(); + // #i111964# + if ( pWin && pWin->Anchor() ) + { + pWin->Anchor()->SetAnchorState(AS_END); + } + } + } + + // text range overlay + if ( mrMgr.ShowNotes() + && mrSidebarItem.maLayoutInfo.mnStartNodeIdx != 0 + && mrSidebarItem.maLayoutInfo.mnStartContent != -1 ) + { + std::vector< basegfx::B2DRange > aAnnotationTextRanges; + { + const SwTxtAnnotationFld* pTxtAnnotationFld = + dynamic_cast< const SwTxtAnnotationFld* >( mrSidebarItem.GetFmtFld().GetTxtFld() ); + if ( pTxtAnnotationFld != NULL + && pTxtAnnotationFld->GetpTxtNode() != NULL ) + { + SwTxtNode* pTxtNode = pTxtAnnotationFld->GetpTxtNode(); + SwNodes& rNds = pTxtNode->GetDoc()->GetNodes(); + SwCntntNode* const pCntntNd = rNds[mrSidebarItem.maLayoutInfo.mnStartNodeIdx]->GetCntntNode(); + SwPosition aStartPos( *pCntntNd, mrSidebarItem.maLayoutInfo.mnStartContent ); + SwShellCrsr* pTmpCrsr = NULL; + const bool bTableCrsrNeeded = pTxtNode->FindTableBoxStartNode() != pCntntNd->FindTableBoxStartNode(); + if ( bTableCrsrNeeded ) + { + SwShellTableCrsr* pTableCrsr = new SwShellTableCrsr( DocView().GetWrtShell(), aStartPos ); + pTableCrsr->SetMark(); + pTableCrsr->GetMark()->nNode = *pTxtNode; + pTableCrsr->GetMark()->nContent.Assign( pTxtNode, *(pTxtAnnotationFld->GetStart())+1 ); + pTableCrsr->NewTableSelection(); + pTmpCrsr = pTableCrsr; + } + else + { + SwShellCrsr* pCrsr = new SwShellCrsr( DocView().GetWrtShell(), aStartPos ); + pCrsr->SetMark(); + pCrsr->GetMark()->nNode = *pTxtNode; + pCrsr->GetMark()->nContent.Assign( pTxtNode, *(pTxtAnnotationFld->GetStart())+1 ); + pTmpCrsr = pCrsr; + } + ::boost::scoped_ptr<SwShellCrsr> pTmpCrsrForAnnotationTextRange( pTmpCrsr ); + + pTmpCrsrForAnnotationTextRange->FillRects(); + + for( sal_uInt16 a(0); a < pTmpCrsrForAnnotationTextRange->size(); ++a ) + { + const SwRect aNextRect((*pTmpCrsrForAnnotationTextRange)[a]); + const Rectangle aPntRect(aNextRect.SVRect()); + + aAnnotationTextRanges.push_back(basegfx::B2DRange( + aPntRect.Left(), aPntRect.Top(), + aPntRect.Right() + 1, aPntRect.Bottom() + 1)); + } + } + } + + if ( mpTextRangeOverlay != NULL ) + { + mpTextRangeOverlay->setRanges( aAnnotationTextRanges ); + if ( mpAnchor != NULL && mpAnchor->getLineSolid() ) + { + mpTextRangeOverlay->ShowSolidBorder(); + } + else + { + mpTextRangeOverlay->HideSolidBorder(); + } + } + else + { + mpTextRangeOverlay = + sw::overlay::OverlayRanges::CreateOverlayRange( + DocView(), + mColorAnchor, + aAnnotationTextRanges, + mpAnchor && mpAnchor->getLineSolid() ); + } + } + else + { + delete mpTextRangeOverlay; + mpTextRangeOverlay = NULL; + } +} + +void SwSidebarWin::DoResize() +{ + long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height(); + long aHeight = GetSizePixel().Height(); + unsigned long aWidth = GetSizePixel().Width(); + + aHeight -= GetMetaHeight(); + mpMetadataAuthor->Show(); + mpMetadataDate->Show(); + mpSidebarTxtControl->SetQuickHelpText(OUString()); + + if ((aTextHeight > aHeight) && !IsPreview()) + { // we need vertical scrollbars and have to reduce the width + aWidth -= GetScrollbarWidth(); + mpVScrollbar->Show(); + } + else + { + mpVScrollbar->Hide(); + } + + { + const Size aSizeOfMetadataControls( GetSizePixel().Width() - GetMetaButtonAreaWidth(), + GetMetaHeight()/2 ); + mpMetadataAuthor->setPosSizePixel( 0, + aHeight, + aSizeOfMetadataControls.Width(), + aSizeOfMetadataControls.Height() ); + mpMetadataDate->setPosSizePixel( 0, + aHeight + aSizeOfMetadataControls.Height(), + aSizeOfMetadataControls.Width(), + aSizeOfMetadataControls.Height() ); + } + + mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ; + if (!mpVScrollbar->IsVisible()) + { // if we do not have a scrollbar anymore, we want to see the complete text + mpOutlinerView->SetVisArea( PixelToLogic( Rectangle(0,0,aWidth,aHeight) ) ); + } + mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,aWidth,aHeight) ) ); + + if (!Application::GetSettings().GetLayoutRTL()) + { + mpSidebarTxtControl->setPosSizePixel(0, 0, aWidth, aHeight); + mpVScrollbar->setPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight); + } + else + { + mpSidebarTxtControl->setPosSizePixel( ( (aTextHeight > aHeight) && !IsPreview() + ? GetScrollbarWidth() : 0 ) , 0, + aWidth, aHeight); + mpVScrollbar->setPosSizePixel( 0, 0, GetScrollbarWidth(), aHeight); + } + + mpVScrollbar->SetVisibleSize( PixelToLogic(Size(0,aHeight)).Height() ); + mpVScrollbar->SetPageSize( PixelToLogic(Size(0,aHeight)).Height() * 8 / 10 ); + mpVScrollbar->SetLineSize( mpOutliner->GetTextHeight() / 10 ); + SetScrollbar(); + mpVScrollbar->SetRange( Range(0, mpOutliner->GetTextHeight())); + + //calculate rects for meta- button + const Fraction& fx( GetMapMode().GetScaleX() ); + const Fraction& fy( GetMapMode().GetScaleY() ); + + const Point aPos( mpMetadataAuthor->GetPosPixel()); + Rectangle aRectMetaButton; + if (IsPreview()) + { + aRectMetaButton = PixelToLogic( + Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH*4+10)*fx.GetNumerator()/fx.GetDenominator(), + aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ), + Size( METABUTTON_WIDTH*4*fx.GetNumerator()/fx.GetDenominator(), + METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) ); + } + else + { + aRectMetaButton = PixelToLogic( + Rectangle( Point( aPos.X()+GetSizePixel().Width()-(METABUTTON_WIDTH+10)*fx.GetNumerator()/fx.GetDenominator(), + aPos.Y()+5*fy.GetNumerator()/fy.GetDenominator() ), + Size( METABUTTON_WIDTH*fx.GetNumerator()/fx.GetDenominator(), + METABUTTON_HEIGHT*fy.GetNumerator()/fy.GetDenominator() ) ) ); + } + + { + const Rectangle aRectMetaButtonPixel( LogicToPixel( aRectMetaButton ) ); + mpMenuButton->setPosSizePixel( aRectMetaButtonPixel.Left(), + aRectMetaButtonPixel.Top(), + aRectMetaButtonPixel.GetWidth(), + aRectMetaButtonPixel.GetHeight() ); + } +} + +void SwSidebarWin::SetSizePixel( const Size& rNewSize ) +{ + Window::SetSizePixel(rNewSize); + + if (mpShadow) + { + Point aStart = EditWin()->PixelToLogic(GetPosPixel()+Point(0,GetSizePixel().Height())); + Point aEnd = EditWin()->PixelToLogic(GetPosPixel()+Point(GetSizePixel().Width()-1,GetSizePixel().Height())); + mpShadow->SetPosition(basegfx::B2DPoint(aStart.X(),aStart.Y()), basegfx::B2DPoint(aEnd.X(),aEnd.Y())); + } +} + +void SwSidebarWin::SetScrollbar() +{ + mpVScrollbar->SetThumbPos(mpOutlinerView->GetVisArea().Top()); +} + +void SwSidebarWin::ResizeIfNecessary(long aOldHeight, long aNewHeight) +{ + if (aOldHeight != aNewHeight) + { + //check for lower border or next note + long aBorder = mrMgr.GetNextBorder(); + if (aBorder != -1) + { + if (aNewHeight > GetMinimumSizeWithoutMeta()) + { + long aNewLowerValue = GetPosPixel().Y() + aNewHeight + GetMetaHeight(); + if (aNewLowerValue < aBorder) + SetSizePixel(Size(GetSizePixel().Width(),aNewHeight+GetMetaHeight())); + else + SetSizePixel(Size(GetSizePixel().Width(),aBorder - GetPosPixel().Y())); + DoResize(); + Invalidate(); + } + else + { + if (GetSizePixel().Height() != GetMinimumSizeWithoutMeta() + GetMetaHeight()) + SetSizePixel(Size(GetSizePixel().Width(),GetMinimumSizeWithoutMeta() + GetMetaHeight())); + DoResize(); + Invalidate(); + } + } + else + { + DoResize(); + Invalidate(); + } + } + else + { + SetScrollbar(); + } +} + +void SwSidebarWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnchor) +{ + mColorDark = aColorDark; + mColorLight = aColorLight; + mColorAnchor = aColorAnchor; + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + { + mpMetadataAuthor->SetControlBackground(mColorDark); + AllSettings aSettings = mpMetadataAuthor->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnchor); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataAuthor->SetSettings(aSettings); + } + + { + mpMetadataDate->SetControlBackground(mColorDark); + AllSettings aSettings = mpMetadataDate->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnchor); + aSettings.SetStyleSettings(aStyleSettings); + mpMetadataDate->SetSettings(aSettings); + } + + AllSettings aSettings2 = mpVScrollbar->GetSettings(); + StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings(); + aStyleSettings2.SetButtonTextColor(Color(0,0,0)); + aStyleSettings2.SetCheckedColor(mColorLight); // backgound + aStyleSettings2.SetShadowColor(mColorAnchor); + aStyleSettings2.SetFaceColor(mColorDark); + aSettings2.SetStyleSettings(aStyleSettings2); + mpVScrollbar->SetSettings(aSettings2); + } +} + +void SwSidebarWin::SetSidebarPosition(sw::sidebarwindows::SidebarPosition eSidebarPosition) +{ + meSidebarPosition = eSidebarPosition; +} + +void SwSidebarWin::SetReadonly(bool bSet) +{ + mbReadonly = bSet; + GetOutlinerView()->SetReadOnly(bSet); +} + +void SwSidebarWin::SetLanguage(const SvxLanguageItem aNewItem) +{ + Link pLink = Engine()->GetModifyHdl(); + Engine()->SetModifyHdl( Link() ); + ESelection aOld = GetOutlinerView()->GetSelection(); + + ESelection aNewSelection( 0, 0, Engine()->GetParagraphCount()-1, EE_TEXTPOS_ALL ); + GetOutlinerView()->SetSelection( aNewSelection ); + SfxItemSet aEditAttr(GetOutlinerView()->GetAttribs()); + aEditAttr.Put(aNewItem); + GetOutlinerView()->SetAttribs( aEditAttr ); + + GetOutlinerView()->SetSelection(aOld); + Engine()->SetModifyHdl( pLink ); + + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + sal_uLong nCntrl = Engine()->GetControlWord(); + // turn off + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + Engine()->SetControlWord(nCntrl); + + //turn back on + if (pVOpt->IsOnlineSpell()) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + Engine()->SetControlWord(nCntrl); + + Engine()->CompleteOnlineSpelling(); + Invalidate(); +} + +void SwSidebarWin::DataChanged( const DataChangedEvent& aEvent) +{ + Window::DataChanged( aEvent ); +} + +void SwSidebarWin::GetFocus() +{ + if (mpSidebarTxtControl) + mpSidebarTxtControl->GrabFocus(); +} + +void SwSidebarWin::LoseFocus() +{ +} + +void SwSidebarWin::ShowNote() +{ + SetPosAndSize(); + if (!IsVisible()) + Window::Show(); + if (mpShadow && !mpShadow->isVisible()) + mpShadow->setVisible(true); + if (mpAnchor && !mpAnchor->isVisible()) + mpAnchor->setVisible(true); +} + +void SwSidebarWin::HideNote() +{ + if (IsVisible()) + Window::Hide(); + if (mpAnchor) + { + if (mrMgr.IsShowAnchor()) + mpAnchor->SetAnchorState(AS_TRI); + else + mpAnchor->setVisible(false); + } + if (mpShadow && mpShadow->isVisible()) + mpShadow->setVisible(false); +} + +void SwSidebarWin::ActivatePostIt() +{ + mrMgr.AssureStdModeAtShell(); + + mpOutliner->ClearModifyFlag(); + mpOutliner->GetUndoManager().Clear(); + + CheckMetaText(); + SetViewState(VS_EDIT); + GetOutlinerView()->ShowCursor(); + + mpOutlinerView->GetEditView().SetInsertMode(mrView.GetWrtShellPtr()->IsInsMode()); + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + GetOutlinerView()->SetBackgroundColor(mColorDark); +} + +void SwSidebarWin::DeactivatePostIt() +{ + // remove selection, #i87073# + if (GetOutlinerView()->GetEditView().HasSelection()) + { + ESelection aSelection = GetOutlinerView()->GetEditView().GetSelection(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos; + GetOutlinerView()->GetEditView().SetSelection(aSelection); + } + + mpOutliner->CompleteOnlineSpelling(); + + SetViewState(VS_NORMAL); + // write the visible text back into the SwField + UpdateData(); + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + GetOutlinerView()->SetBackgroundColor(COL_TRANSPARENT); + + if ( !IsProtected() && Engine()->GetEditEngine().GetText().isEmpty() ) + { + mnEventId = Application::PostUserEvent( LINK( this, SwSidebarWin, DeleteHdl), 0 ); + } +} + +void SwSidebarWin::ToggleInsMode() +{ + if (!mrView.GetWrtShell().IsRedlineOn()) + { + //change outliner + mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode()); + //change document + mrView.GetWrtShell().ToggleInsMode(); + //update statusbar + SfxBindings &rBnd = mrView.GetViewFrame()->GetBindings(); + rBnd.Invalidate(SID_ATTR_INSERT); + rBnd.Update(SID_ATTR_INSERT); + } +} + +void SwSidebarWin::ExecuteCommand(sal_uInt16 nSlot) +{ + mrMgr.AssureStdModeAtShell(); + + switch (nSlot) + { + case FN_POSTIT: + case FN_REPLY: + { + // if this note is empty, it will be deleted once losing the focus, so no reply, but only a new note + // will be created + if (!Engine()->GetEditEngine().GetText().isEmpty()) + { + OutlinerParaObject* pPara = new OutlinerParaObject(*GetOutlinerView()->GetEditView().CreateTextObject()); + mrMgr.RegisterAnswer(pPara); + } + if (mrMgr.HasActiveSidebarWin()) + mrMgr.SetActiveSidebarWin(0); + SwitchToFieldPos(); + mrView.GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT); + break; + } + case FN_DELETE_COMMENT: + + //Delete(); // do not kill the parent of our open popup menu + mnEventId = Application::PostUserEvent( LINK( this, SwSidebarWin, DeleteHdl), 0 ); + break; + case FN_FORMAT_ALL_NOTES: + case FN_DELETE_ALL_NOTES: + case FN_HIDE_ALL_NOTES: + // not possible as slot as this would require that "this" is the active postit + mrView.GetViewFrame()->GetBindings().Execute( nSlot, 0, 0, SFX_CALLMODE_ASYNCHRON ); + break; + case FN_DELETE_NOTE_AUTHOR: + case FN_HIDE_NOTE_AUTHOR: + { + // not possible as slot as this would require that "this" is the active postit + SfxStringItem aItem( nSlot, GetAuthor() ); + const SfxPoolItem* aItems[2]; + aItems[0] = &aItem; + aItems[1] = 0; + mrView.GetViewFrame()->GetBindings().Execute( nSlot, aItems, 0, SFX_CALLMODE_ASYNCHRON ); + } + break; + default: + mrView.GetViewFrame()->GetBindings().Execute( nSlot ); + break; + } +} + +SwEditWin* SwSidebarWin::EditWin() +{ + return &mrView.GetEditWin(); +} + +long SwSidebarWin::GetPostItTextHeight() +{ + return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0; +} + +void SwSidebarWin::SwitchToPostIt(sal_uInt16 aDirection) +{ + SwSidebarWin* pPostIt = mrMgr.GetNextPostIt(aDirection, this); + if (pPostIt) + pPostIt->GrabFocus(); +} + +IMPL_LINK( SwSidebarWin, WindowEventListener, VclSimpleEvent*, pEvent ) +{ + VclWindowEvent* pWinEvent = dynamic_cast<VclWindowEvent*>(pEvent); + if ( pWinEvent ) + { + if ( pWinEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE ) + { + MouseEvent* pMouseEvt = (MouseEvent*)pWinEvent->GetData(); + if ( pMouseEvt->IsEnterWindow() ) + { + mbMouseOver = true; + if ( !HasFocus() ) + { + SetViewState(VS_VIEW); + Invalidate(); + } + } + else if ( pMouseEvt->IsLeaveWindow()) + { + if (!IsPreview()) + { + mbMouseOver = false; + if ( !HasFocus() ) + { + SetViewState(VS_NORMAL); + Invalidate(); + } + } + } + } + else if ( pWinEvent->GetId() == VCLEVENT_WINDOW_ACTIVATE && + pWinEvent->GetWindow() == mpSidebarTxtControl ) + { + const bool bLockView = mrView.GetWrtShell().IsViewLocked(); + mrView.GetWrtShell().LockView( true ); + + if ( !IsPreview() ) + { + mrMgr.SetActiveSidebarWin( this ); + } + + mrView.GetWrtShell().LockView( bLockView ); + mrMgr.MakeVisible( this ); + } + } + return sal_True; +} + +void SwSidebarWin::Delete() +{ + if ( mrMgr.GetActiveSidebarWin() == this) + { + mrMgr.SetActiveSidebarWin(0); + // if the note is empty, the previous line will send a delete event, but we are already there + if (mnEventId) + { + Application::RemoveUserEvent( mnEventId ); + mnEventId = 0; + } + } +} + +IMPL_LINK(SwSidebarWin, ScrollHdl, ScrollBar*, pScroll) +{ + long nDiff = GetOutlinerView()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos(); + GetOutlinerView()->Scroll( 0, nDiff ); + return 0; +} + +IMPL_LINK_NOARG(SwSidebarWin, ModifyHdl) +{ + mrView.GetDocShell()->SetModified(true); + return 0; +} + +IMPL_LINK_NOARG(SwSidebarWin, DeleteHdl) +{ + mnEventId = 0; + Delete(); + return 0; +} + +void SwSidebarWin::ResetAttributes() +{ + mpOutlinerView->RemoveAttribsKeepLanguages(true); + mpOutliner->RemoveFields(true); + mpOutlinerView->SetAttribs(DefaultItem()); +} + +sal_Int32 SwSidebarWin::GetScrollbarWidth() +{ + return mrView.GetWrtShell().GetViewOptions()->GetZoom() / 10; +} + +sal_Int32 SwSidebarWin::GetMetaButtonAreaWidth() +{ + const Fraction& f( GetMapMode().GetScaleX() ); + if (IsPreview()) + return 3 * METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator(); + else + return METABUTTON_AREA_WIDTH * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwSidebarWin::GetMetaHeight() +{ + const Fraction& f( GetMapMode().GetScaleY() ); + return POSTIT_META_HEIGHT * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwSidebarWin::GetMinimumSizeWithMeta() +{ + return mrMgr.GetMinimumSizeWithMeta(); +} + +sal_Int32 SwSidebarWin::GetMinimumSizeWithoutMeta() +{ + const Fraction& f( GetMapMode().GetScaleY() ); + return POSTIT_MINIMUMSIZE_WITHOUT_META * f.GetNumerator() / f.GetDenominator(); +} + +void SwSidebarWin::SetSpellChecking() +{ + const SwViewOption* pVOpt = mrView.GetWrtShellPtr()->GetViewOptions(); + sal_uLong nCntrl = mpOutliner->GetControlWord(); + if (pVOpt->IsOnlineSpell()) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + mpOutliner->CompleteOnlineSpelling(); + Invalidate(); +} + +void SwSidebarWin::SetViewState(ViewState bViewState) +{ + switch (bViewState) + { + case VS_EDIT: + { + if (mpAnchor) + { + mpAnchor->SetAnchorState(AS_ALL); + SwSidebarWin* pWin = GetTopReplyNote(); + // #i111964# + if ( pWin && pWin->Anchor() ) + { + pWin->Anchor()->SetAnchorState(AS_END); + } + mpAnchor->setLineSolid(true); + if ( mpTextRangeOverlay != NULL ) + { + mpTextRangeOverlay->ShowSolidBorder(); + } + } + if (mpShadow) + mpShadow->SetShadowState(SS_EDIT); + break; + } + case VS_VIEW: + { + if (mpAnchor) + { + mpAnchor->setLineSolid(true); + if ( mpTextRangeOverlay != NULL ) + { + mpTextRangeOverlay->ShowSolidBorder(); + } + } + if (mpShadow) + mpShadow->SetShadowState(SS_VIEW); + break; + } + case VS_NORMAL: + { + if (mpAnchor) + { + if (IsFollow()) + { + // if there is no visible parent note, we want to see the complete anchor ?? + //if (IsAnyStackParentVisible()) + mpAnchor->SetAnchorState(AS_END); + SwSidebarWin* pTopWinSelf = GetTopReplyNote(); + SwSidebarWin* pTopWinActive = mrMgr.HasActiveSidebarWin() + ? mrMgr.GetActiveSidebarWin()->GetTopReplyNote() + : 0; + // #i111964# + if ( pTopWinSelf && ( pTopWinSelf != pTopWinActive ) && + pTopWinSelf->Anchor() ) + { + if ( pTopWinSelf != mrMgr.GetActiveSidebarWin() ) + { + pTopWinSelf->Anchor()->setLineSolid(false); + if ( pTopWinSelf->TextRange() != NULL ) + { + pTopWinSelf->TextRange()->HideSolidBorder(); + } + } + pTopWinSelf->Anchor()->SetAnchorState(AS_ALL); + } + } + mpAnchor->setLineSolid(false); + if ( mpTextRangeOverlay != NULL ) + { + mpTextRangeOverlay->HideSolidBorder(); + } + } + if ( mpShadow ) + { + mpShadow->SetShadowState(SS_NORMAL); + } + break; + } + } +} + +SwSidebarWin* SwSidebarWin::GetTopReplyNote() +{ + SwSidebarWin* pTopNote = 0; + SwSidebarWin* pSidebarWin = IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, this) : 0; + while (pSidebarWin) + { + pTopNote = pSidebarWin; + pSidebarWin = pSidebarWin->IsFollow() ? mrMgr.GetNextPostIt(KEY_PAGEUP, pSidebarWin) : 0; + } + return pTopNote; +} + +void SwSidebarWin::SwitchToFieldPos() +{ + if ( mrMgr.GetActiveSidebarWin() == this ) + mrMgr.SetActiveSidebarWin(0); + GotoPos(); + sal_uInt32 aCount = MoveCaret(); + if (aCount) + mrView.GetDocShell()->GetWrtShell()->SwCrsrShell::Right(aCount, 0, false); + GrabFocusToDocument(); +} + +SvxLanguageItem SwSidebarWin::GetLanguage(void) +{ + return SvxLanguageItem(SwLangHelper::GetLanguage(mrView.GetWrtShell(),RES_CHRATR_LANGUAGE),RES_CHRATR_LANGUAGE); +} + +void SwSidebarWin::SetChangeTracking( const SwPostItHelper::SwLayoutStatus aLayoutStatus, + const Color& aChangeColor ) +{ + if ( (mLayoutStatus != aLayoutStatus) || + (mChangeColor != aChangeColor) ) + { + mLayoutStatus = aLayoutStatus; + mChangeColor = aChangeColor; + Invalidate(); + } +} + +bool SwSidebarWin::HasScrollbar() const +{ + return mpVScrollbar != 0; +} + +bool SwSidebarWin::IsScrollbarVisible() const +{ + return HasScrollbar() && mpVScrollbar->IsVisible(); +} + +void SwSidebarWin::ChangeSidebarItem( SwSidebarItem& rSidebarItem ) +{ + const bool bAnchorChanged = mpAnchorFrm != rSidebarItem.maLayoutInfo.mpAnchorFrm; + if ( bAnchorChanged ) + { + mrMgr.DisconnectSidebarWinFromFrm( *(mpAnchorFrm), *this ); + } + + mrSidebarItem = rSidebarItem; + mpAnchorFrm = mrSidebarItem.maLayoutInfo.mpAnchorFrm; + + if ( GetWindowPeer() ) + { + SidebarWinAccessible* pAcc = + static_cast<SidebarWinAccessible*>( GetWindowPeer() ); + OSL_ENSURE( dynamic_cast<SidebarWinAccessible*>( GetWindowPeer() ), + "<SwSidebarWin::ChangeSidebarItem(..)> - unexpected type of window peer -> crash possible!" ); + pAcc->ChangeSidebarItem( mrSidebarItem ); + } + + if ( bAnchorChanged ) + { + mrMgr.ConnectSidebarWinToFrm( *(mrSidebarItem.maLayoutInfo.mpAnchorFrm), + mrSidebarItem.GetFmtFld(), + *this ); + } +} + +css::uno::Reference< css::accessibility::XAccessible > SwSidebarWin::CreateAccessible() +{ + SidebarWinAccessible* pAcc( new SidebarWinAccessible( *this, + mrView.GetWrtShell(), + mrSidebarItem ) ); + css::uno::Reference< css::awt::XWindowPeer > xWinPeer( pAcc ); + SetWindowPeer( xWinPeer, pAcc ); + + css::uno::Reference< css::accessibility::XAccessible > xAcc( xWinPeer, css::uno::UNO_QUERY ); + return xAcc; +} + +} } // eof of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarWinAcc.cxx b/sw/source/uibase/docvw/SidebarWinAcc.cxx new file mode 100644 index 000000000000..57850b9b3af6 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarWinAcc.cxx @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <SidebarWinAcc.hxx> + +#include <SidebarWin.hxx> +#include <viewsh.hxx> +#include <accmap.hxx> +#include <toolkit/awt/vclxaccessiblecomponent.hxx> + +#include <com/sun/star/accessibility/AccessibleRole.hpp> + +namespace sw { namespace sidebarwindows { + +// declaration and implementation of accessible context for <SidebarWinAccessible> instance +class SidebarWinAccessibleContext : public VCLXAccessibleComponent +{ + public: + explicit SidebarWinAccessibleContext( SwSidebarWin& rSidebarWin, + SwViewShell& rViewShell, + const SwFrm* pAnchorFrm ) + : VCLXAccessibleComponent( rSidebarWin.GetWindowPeer() ) + , mrViewShell( rViewShell ) + , mpAnchorFrm( pAnchorFrm ) + , maMutex() + { + rSidebarWin.SetAccessibleRole( css::accessibility::AccessibleRole::COMMENT ); + } + + virtual ~SidebarWinAccessibleContext() + {} + + void ChangeAnchor( const SwFrm* pAnchorFrm ) + { + osl::MutexGuard aGuard(maMutex); + + mpAnchorFrm = pAnchorFrm; + } + + virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL + getAccessibleParent() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + osl::MutexGuard aGuard(maMutex); + + css::uno::Reference< css::accessibility::XAccessible > xAccParent; + + if ( mpAnchorFrm && + mrViewShell.GetAccessibleMap() ) + { + xAccParent = mrViewShell.GetAccessibleMap()->GetContext( mpAnchorFrm, false ); + } + + return xAccParent; + } + + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + osl::MutexGuard aGuard(maMutex); + + sal_Int32 nIndex( -1 ); + + if ( mpAnchorFrm && GetWindow() && + mrViewShell.GetAccessibleMap() ) + { + nIndex = mrViewShell.GetAccessibleMap()->GetChildIndex( *mpAnchorFrm, + *GetWindow() ); + } + + return nIndex; + } + + private: + SwViewShell& mrViewShell; + const SwFrm* mpAnchorFrm; + + ::osl::Mutex maMutex; +}; + +// implementaion of accessible for <SwSidebarWin> instance +SidebarWinAccessible::SidebarWinAccessible( SwSidebarWin& rSidebarWin, + SwViewShell& rViewShell, + const SwSidebarItem& rSidebarItem ) + : VCLXWindow() + , mrSidebarWin( rSidebarWin ) + , mrViewShell( rViewShell ) + , mpAnchorFrm( rSidebarItem.maLayoutInfo.mpAnchorFrm ) + , bAccContextCreated( false ) +{ + SetWindow( &mrSidebarWin ); +} + +SidebarWinAccessible::~SidebarWinAccessible() +{ +} + +void SidebarWinAccessible::ChangeSidebarItem( const SwSidebarItem& rSidebarItem ) +{ + if ( bAccContextCreated ) + { + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc + = getAccessibleContext(); + if ( xAcc.is() ) + { + SidebarWinAccessibleContext* pAccContext = + dynamic_cast<SidebarWinAccessibleContext*>(xAcc.get()); + if ( pAccContext ) + { + pAccContext->ChangeAnchor( rSidebarItem.maLayoutInfo.mpAnchorFrm ); + } + } + } +} + +css::uno::Reference< css::accessibility::XAccessibleContext > SidebarWinAccessible::CreateAccessibleContext() +{ + SidebarWinAccessibleContext* pAccContext = + new SidebarWinAccessibleContext( mrSidebarWin, + mrViewShell, + mpAnchorFrm ); + css::uno::Reference< css::accessibility::XAccessibleContext > xAcc( pAccContext ); + bAccContextCreated = true; + return xAcc; +} + +} } // end of namespace sw::sidebarwindows + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/SidebarWinAcc.hxx b/sw/source/uibase/docvw/SidebarWinAcc.hxx new file mode 100644 index 000000000000..9d4dc49436b4 --- /dev/null +++ b/sw/source/uibase/docvw/SidebarWinAcc.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARWINACC_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_SIDEBARWINACC_HXX + +#include <toolkit/awt/vclxwindow.hxx> + +class SwViewShell; +class SwSidebarItem; +class SwFrm; + +namespace sw { namespace sidebarwindows { + +class SwSidebarWin; + +class SidebarWinAccessible : public VCLXWindow +{ + public: + explicit SidebarWinAccessible( SwSidebarWin& rSidebarWin, + SwViewShell& rViewShell, + const SwSidebarItem& rSidebarItem ); + virtual ~SidebarWinAccessible(); + + virtual com::sun::star::uno::Reference< com::sun::star::accessibility::XAccessibleContext > + CreateAccessibleContext() SAL_OVERRIDE; + + void ChangeSidebarItem( const SwSidebarItem& rSidebarItem ); + + private: + SwSidebarWin& mrSidebarWin; + SwViewShell& mrViewShell; + const SwFrm* mpAnchorFrm; + bool bAccContextCreated; +}; + +} } // end of namespace sw::sidebarwindows + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/annotation.hrc b/sw/source/uibase/docvw/annotation.hrc new file mode 100644 index 000000000000..e94aa557b29b --- /dev/null +++ b/sw/source/uibase/docvw/annotation.hrc @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef _ANNOTATION_HRC +#define _ANNOTATION_HRC + +#include "rcid.hrc" + +#define STR_POSTIT_TODAY (RC_ANNOTATION_BEGIN + 1) +#define STR_POSTIT_YESTERDAY (RC_ANNOTATION_BEGIN + 2) + +#define STR_DELETE_ALL_NOTES (RC_ANNOTATION_BEGIN + 3) +#define STR_DELETE_AUTHOR_NOTES (RC_ANNOTATION_BEGIN + 4) + +#define STR_NODATE (RC_ANNOTATION_BEGIN + 5) +#define STR_NOAUTHOR (RC_ANNOTATION_BEGIN + 6) + +#define STR_REPLY (RC_ANNOTATION_BEGIN + 7) +#define STR_FORMAT_ALL_NOTES (RC_ANNOTATION_BEGIN + 8) + +#define ANNOTATION_ACT_END STR_REPLY +#if ANNOTATION_ACT_END > RC_ANNOTATION_END +#error Resource-Id Ueberlauf in #file, #line +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/docvw.hrc b/sw/source/uibase/docvw/docvw.hrc new file mode 100644 index 000000000000..3347b1862639 --- /dev/null +++ b/sw/source/uibase/docvw/docvw.hrc @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#ifndef _DOCVW_HRC +#define _DOCVW_HRC + +#include "rcid.hrc" + +#define MN_READONLY_POPUP (RC_DOCVW_BEGIN + 1) +#define MN_READONLY_OPENURL (RC_DOCVW_BEGIN + 2) +#define MN_READONLY_OPENURLNEW (RC_DOCVW_BEGIN + 3) +#define MN_READONLY_EDITDOC (RC_DOCVW_BEGIN + 4) +// free (5) +#define MN_READONLY_BROWSE_BACKWARD (RC_DOCVW_BEGIN + 6) +#define MN_READONLY_BROWSE_FORWARD (RC_DOCVW_BEGIN + 7) +#define MN_READONLY_SELECTION_MODE (RC_DOCVW_BEGIN + 8) +#define MN_READONLY_SAVEGRAPHIC (RC_DOCVW_BEGIN + 11) +#define MN_READONLY_SAVEBACKGROUND (RC_DOCVW_BEGIN + 12) +#define MN_READONLY_COPYLINK (RC_DOCVW_BEGIN + 13) +#define MN_READONLY_COPYGRAPHIC (RC_DOCVW_BEGIN + 14) +#define MN_READONLY_LOADGRAPHIC (RC_DOCVW_BEGIN + 15) +#define MN_READONLY_GRAPHICOFF (RC_DOCVW_BEGIN + 16) +#define MN_READONLY_PLUGINOFF (RC_DOCVW_BEGIN + 17) +#define MN_READONLY_TOGALLERYLINK (RC_DOCVW_BEGIN + 18) +#define MN_READONLY_TOGALLERYCOPY (RC_DOCVW_BEGIN + 19) +#define MN_READONLY_SOURCEVIEW (RC_DOCVW_BEGIN + 20) +#define MN_READONLY_RELOAD_FRAME (RC_DOCVW_BEGIN + 21) +#define MN_READONLY_RELOAD (RC_DOCVW_BEGIN + 22) +#define MN_READONLY_COPY (RC_DOCVW_BEGIN + 23) + +//For the following we need space for the gallery-themes +#define MN_READONLY_GRAPHICTOGALLERY (RC_DOCVW_BEGIN + 24) +#define MN_READONLY_BACKGROUNDTOGALLERY (RC_DOCVW_BEGIN + 60) + +#define STR_CHAIN_OK (RC_DOCVW_BEGIN + 2) +#define STR_CHAIN_NOT_EMPTY (RC_DOCVW_BEGIN + 3) +#define STR_CHAIN_IS_IN_CHAIN (RC_DOCVW_BEGIN + 4) +#define STR_CHAIN_WRONG_AREA (RC_DOCVW_BEGIN + 5) +#define STR_CHAIN_NOT_FOUND (RC_DOCVW_BEGIN + 6) +#define STR_CHAIN_SOURCE_CHAINED (RC_DOCVW_BEGIN + 7) +#define STR_CHAIN_SELF (RC_DOCVW_BEGIN + 8) +#define STR_REDLINE_INSERT (RC_DOCVW_BEGIN + 9) +#define STR_REDLINE_DELETE (RC_DOCVW_BEGIN + 10) +#define STR_REDLINE_FORMAT (RC_DOCVW_BEGIN + 11) +#define STR_REDLINE_TABLE (RC_DOCVW_BEGIN + 12) +#define STR_REDLINE_FMTCOLL (RC_DOCVW_BEGIN + 13) +#define STR_ENDNOTE (RC_DOCVW_BEGIN + 14) +#define STR_FTNNOTE (RC_DOCVW_BEGIN + 15) + +#define STR_TABLE_COL_ADJUST (RC_DOCVW_BEGIN + 16) +#define STR_TABLE_ROW_ADJUST (RC_DOCVW_BEGIN + 17) +#define STR_TABLE_SELECT_ALL (RC_DOCVW_BEGIN + 18) +#define STR_TABLE_SELECT_ROW (RC_DOCVW_BEGIN + 19) +#define STR_TABLE_SELECT_COL (RC_DOCVW_BEGIN + 20) + +#define STR_SMARTTAG_CLICK (RC_DOCVW_BEGIN + 21) + +#define STR_HEADER_TITLE (RC_DOCVW_BEGIN + 22) +#define STR_FOOTER_TITLE (RC_DOCVW_BEGIN + 23) +#define STR_DELETE_HEADER (RC_DOCVW_BEGIN + 24) +#define STR_FORMAT_HEADER (RC_DOCVW_BEGIN + 25) +#define STR_DELETE_FOOTER (RC_DOCVW_BEGIN + 26) +#define STR_FORMAT_FOOTER (RC_DOCVW_BEGIN + 27) + +#define DOCVW_ACT_END STR_SMARTTAG_CLICK + +#if DOCVW_ACT_END > RC_DOCVW_END +#error Resource-Id Ueberlauf in #file, #line +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/docvw.src b/sw/source/uibase/docvw/docvw.src new file mode 100644 index 000000000000..ff10f368a012 --- /dev/null +++ b/sw/source/uibase/docvw/docvw.src @@ -0,0 +1,307 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include "docvw.hrc" +#include "cmdid.h" +#include "helpid.h" +#define SEPARATOR MenuItem { Separator = TRUE; }; +Menu MN_READONLY_POPUP +{ + ItemList = + { + MenuItem + { + Identifier = MN_READONLY_OPENURL ; + HelpId = CMD_SID_OPENDOC ; + Text [ en-US ] = "~Open" ; + }; + MenuItem + { + Identifier = MN_READONLY_OPENURLNEW ; + HelpId = CMD_SID_OPENDOC ; + Text [ en-US ] = "Open in New Window" ; + }; + MenuItem + { + Identifier = MN_READONLY_EDITDOC ; + HelpId = CMD_SID_EDITDOC ; + Text [ en-US ] = "~Edit" ; + }; + MenuItem + { + Identifier = MN_READONLY_SELECTION_MODE ; + HelpId = CMD_FN_READONLY_SELECTION_MODE ; + Text [ en-US ] = "Select Text"; + }; + MenuItem + { + Identifier = MN_READONLY_RELOAD; + HelpId = CMD_SID_RELOAD; + Text [ en-US ] = "Re~load"; + }; + MenuItem + { + Identifier = MN_READONLY_RELOAD_FRAME; + HelpId = CMD_SID_RELOAD; + Text [ en-US ] = "Reload Frame"; + }; + MenuItem + { + Identifier = MN_READONLY_SOURCEVIEW ; + HelpId = HID_SOURCEVIEW ; + Text [ en-US ] = "HT~ML Source" ; + }; + SEPARATOR + MenuItem + { + Identifier = MN_READONLY_BROWSE_BACKWARD ; + HelpId = CMD_SID_BROWSE_BACKWARD ; + Text [ en-US ] = "Backwards" ; + }; + MenuItem + { + Identifier = MN_READONLY_BROWSE_FORWARD ; + HelpId = CMD_SID_BROWSE_FORWARD ; + Text [ en-US ] = "~Forward" ; + }; + SEPARATOR + MenuItem + { + Identifier = MN_READONLY_SAVEGRAPHIC ; + HelpID = HID_MN_READONLY_SAVEGRAPHIC ; + Text [ en-US ] = "Save Image..." ; + }; + MenuItem + { + Identifier = MN_READONLY_GRAPHICTOGALLERY ; + HelpID = HID_MN_READONLY_GRAPHICTOGALLERY ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = MN_READONLY_TOGALLERYLINK ; + HelpID = HID_MN_READONLY_TOGALLERYLINK ; + Text [ en-US ] = "As Link" ; + }; + MenuItem + { + Identifier = MN_READONLY_TOGALLERYCOPY ; + HelpID = HID_MN_READONLY_TOGALLERYCOPY ; + Text [ en-US ] = "Copy" ; + }; + SEPARATOR + }; + }; + Text [ en-US ] = "Add Image" ; + }; + MenuItem + { + Identifier = MN_READONLY_SAVEBACKGROUND ; + HelpID = HID_MN_READONLY_SAVEBACKGROUND ; + Text [ en-US ] = "Save Background..." ; + }; + MenuItem + { + Identifier = MN_READONLY_BACKGROUNDTOGALLERY ; + HelpID = HID_MN_READONLY_BACKGROUNDTOGALLERY ; + SubMenu = Menu + { + ItemList = + { + MenuItem + { + Identifier = MN_READONLY_TOGALLERYLINK ; + HelpID = HID_MN_READONLY_TOGALLERYLINK ; + Text [ en-US ] = "As Link" ; + }; + MenuItem + { + Identifier = MN_READONLY_TOGALLERYCOPY ; + HelpID = HID_MN_READONLY_TOGALLERYCOPY ; + Text [ en-US ] = "Copy" ; + }; + SEPARATOR + }; + }; + Text [ en-US ] = "Add Background" ; + }; + SEPARATOR + MenuItem + { + Identifier = MN_READONLY_COPYLINK ; + HelpID = HID_MN_READONLY_COPYLINK ; + Text [ en-US ] = "Copy ~Link" ; + }; + MenuItem + { + Identifier = MN_READONLY_COPYGRAPHIC ; + HelpID = HID_MN_READONLY_COPYGRAPHIC ; + Text [ en-US ] = "Copy ~Image" ; + }; + SEPARATOR + MenuItem + { + Identifier = MN_READONLY_LOADGRAPHIC ; + HelpID = HID_MN_READONLY_LOADGRAPHIC ; + Text [ en-US ] = "Load Image" ; + }; + MenuItem + { + Identifier = MN_READONLY_GRAPHICOFF ; + HelpID = HID_MN_READONLY_GRAPHICOFF ; + Text [ en-US ] = "Image Off" ; + }; + MenuItem + { + Identifier = MN_READONLY_PLUGINOFF ; + HelpID = HID_MN_READONLY_PLUGINOFF ; + Text [ en-US ] = "Plug-ins Off" ; + }; + SEPARATOR + MenuItem + { + Identifier = SID_WIN_FULLSCREEN; + HelpId = CMD_SID_WIN_FULLSCREEN; + Text [ en-US ] = "Leave Full-Screen Mode" ; + }; + SEPARATOR + MenuItem + { + Identifier = MN_READONLY_COPY ; + HelpId = CMD_SID_COPY; + Text [ en-US ] = "~Copy" ; + }; + }; +}; +String STR_CHAIN_OK +{ + Text [ en-US ] = "Click the left mouse button to link the frames." ; +}; +String STR_CHAIN_NOT_EMPTY +{ + Text [ en-US ] = "Target frame not empty." ; +}; +String STR_CHAIN_IS_IN_CHAIN +{ + Text [ en-US ] = "Target frame is already linked." ; +}; +String STR_CHAIN_WRONG_AREA +{ + Text [ en-US ] = "The target frame for the link is in an invalid area." ; +}; +String STR_CHAIN_NOT_FOUND +{ + Text [ en-US ] = "Target frame not found at current position." ; +}; +String STR_CHAIN_SOURCE_CHAINED +{ + Text [ en-US ] = "The source frame is already the source of a link." ; +}; +String STR_CHAIN_SELF +{ + Text [ en-US ] = "A closed link is not possible." ; +}; +String STR_REDLINE_INSERT +{ + Text [ en-US ] = "Inserted" ; +}; +String STR_REDLINE_DELETE +{ + Text [ en-US ] = "Deleted" ; +}; +String STR_REDLINE_FORMAT +{ + Text [ en-US ] = "Formatted" ; +}; +String STR_REDLINE_TABLE +{ + Text [ en-US ] = "Table changed" ; +}; +String STR_REDLINE_FMTCOLL +{ + Text [ en-US ] = "Applied Paragraph Styles"; +}; +String STR_ENDNOTE +{ + Text [ en-US ] = "Endnote: " ; +}; +String STR_FTNNOTE +{ + Text [ en-US ] = "Footnote: " ; +}; + +String STR_TABLE_COL_ADJUST +{ + Text [ en-US ] = "Adjust table column" ; +}; +String STR_TABLE_ROW_ADJUST +{ + Text [ en-US ] = "Adjust table row" ; +}; +String STR_TABLE_SELECT_ALL +{ + Text [ en-US ] = "Select whole table" ; +}; +String STR_TABLE_SELECT_ROW +{ + Text [ en-US ] = "Select table row" ; +}; +String STR_TABLE_SELECT_COL +{ + Text [ en-US ] = "Select table column" ; +}; + +String STR_SMARTTAG_CLICK +{ + Text [ en-US ] = "%s-click to open Smart Tag menu" ; +}; + +String STR_HEADER_TITLE +{ + Text [ en-US ] = "Header (%1)" ; +}; + +String STR_FOOTER_TITLE +{ + Text [ en-US ] = "Footer (%1)" ; +}; + +String STR_DELETE_HEADER +{ + Text [ en-US ] = "Delete Header..." ; +}; + +String STR_FORMAT_HEADER +{ + Text [ en-US ] = "Format Header..." ; +}; + +String STR_DELETE_FOOTER +{ + Text [ en-US ] = "Delete Footer..." ; +}; + +String STR_FORMAT_FOOTER +{ + Text [ en-US ] = "Format Footer..." ; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtdd.cxx b/sw/source/uibase/docvw/edtdd.cxx new file mode 100644 index 000000000000..c43fb80eb81e --- /dev/null +++ b/sw/source/uibase/docvw/edtdd.cxx @@ -0,0 +1,495 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <hintids.hxx> + +#include <svx/svdview.hxx> +#include <editeng/outliner.hxx> +#include <svx/svdobj.hxx> +#include <sot/exchange.hxx> +#include <sot/formats.hxx> +#include <sfx2/bindings.hxx> + +#include <sfx2/viewfrm.hxx> +#include <fmturl.hxx> +#include <frmfmt.hxx> +#include <wrtsh.hxx> +#include <edtwin.hxx> +#include <view.hxx> +#include <viewopt.hxx> +#include <swdtflvr.hxx> +#include <swmodule.hxx> +#include <docsh.hxx> +#include <wdocsh.hxx> +#include <swundo.hxx> + +using namespace ::com::sun::star; + +// no include "dbgoutsw.hxx" here!!!!!! + +extern bool bNoInterrupt; +extern bool bFrmDrag; +extern bool bDDTimerStarted; + +bool bExecuteDrag = false; + +void SwEditWin::StartDDTimer() +{ + m_aTimer.SetTimeoutHdl(LINK(this, SwEditWin, DDHandler)); + m_aTimer.SetTimeout(480); + m_aTimer.Start(); + bDDTimerStarted = true; +} + +void SwEditWin::StopDDTimer(SwWrtShell *pSh, const Point &rPt) +{ + m_aTimer.Stop(); + bDDTimerStarted = false; + if(!pSh->IsSelFrmMode()) + pSh->SetCursor(&rPt, false); + m_aTimer.SetTimeoutHdl(LINK(this,SwEditWin, TimerHandler)); +} + +void SwEditWin::StartDrag( sal_Int8 /*nAction*/, const Point& rPosPixel ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + if( rSh.GetDrawView() ) + { + CommandEvent aDragEvent( rPosPixel, COMMAND_STARTDRAG, true ); + if( rSh.GetDrawView()->Command( aDragEvent, this ) ) + { + m_rView.GetViewFrame()->GetBindings().InvalidateAll(false); + return; // Event evaluated by SdrView + } + } + + if ( !m_pApplyTempl && !rSh.IsDrawCreate() && !IsDrawAction()) + { + bool bStart = false, bDelSelect = false; + SdrObject *pObj = NULL; + Point aDocPos( PixelToLogic( rPosPixel ) ); + if ( !rSh.IsInSelect() && rSh.ChgCurrPam( aDocPos, true, true)) + //We are not selecting and aren't at a selection + bStart = true; + else if ( !bFrmDrag && rSh.IsSelFrmMode() && + rSh.IsInsideSelectedObj( aDocPos ) ) + { + //We are not dragging internally and are not at an + //object (frame, draw object) + + bStart = true; + } + else if( !bFrmDrag && m_rView.GetDocShell()->IsReadOnly() && + OBJCNT_NONE != rSh.GetObjCntType( aDocPos, pObj )) + { + rSh.LockPaint(); + if( rSh.SelectObj( aDocPos, 0, pObj )) + bStart = bDelSelect = true; + else + rSh.UnlockPaint(); + } + else + { + SwContentAtPos aSwContentAtPos( SwContentAtPos::SW_INETATTR ); + bStart = rSh.GetContentAtPos( aDocPos, + aSwContentAtPos, + false ); + } + + if ( bStart && !m_bIsInDrag ) + { + m_bMBPressed = false; + ReleaseMouse(); + bFrmDrag = false; + bExecuteDrag = true; + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + m_aMovePos = aDocPos; + StartExecuteDrag(); + if( bDelSelect ) + { + rSh.UnSelectFrm(); + rSh.UnlockPaint(); + } + } + } +} + +void SwEditWin::StartExecuteDrag() +{ + if( !bExecuteDrag || m_bIsInDrag ) + return; + + m_bIsInDrag = true; + + SwTransferable* pTransfer = new SwTransferable( m_rView.GetWrtShell() ); + uno::Reference< + datatransfer::XTransferable > xRef( pTransfer ); + + pTransfer->StartDrag( this, m_aMovePos ); +} + +void SwEditWin::DragFinished() +{ + DropCleanup(); + m_aTimer.SetTimeoutHdl( LINK(this,SwEditWin, TimerHandler) ); + m_bIsInDrag = false; +} + +void SwEditWin::DropCleanup() +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + // reset statuses + bNoInterrupt = false; + if ( m_bOldIdleSet ) + { + ((SwViewOption*)rSh.GetViewOptions())->SetIdle( m_bOldIdle ); + m_bOldIdleSet = false; + } + if ( m_pUserMarker ) + CleanupDropUserMarker(); + else + rSh.UnSetVisCrsr(); + +} + +void SwEditWin::CleanupDropUserMarker() +{ + if ( m_pUserMarker ) + { + delete m_pUserMarker; + m_pUserMarker = 0; + m_pUserMarkerObj = 0; + } +} + +//exhibition hack (MA,MBA) +void SwView::SelectShellForDrop() +{ + if ( !GetCurShell() ) + SelectShell(); +} + +sal_Int8 SwEditWin::ExecuteDrop( const ExecuteDropEvent& rEvt ) +{ + GetView().SelectShellForDrop(); + DropCleanup(); + sal_Int8 nRet = DND_ACTION_NONE; + + //A Drop to an open OutlinerView doesn't concern us (also see QueryDrop) + SwWrtShell &rSh = m_rView.GetWrtShell(); + const Point aDocPt( PixelToLogic( rEvt.maPosPixel )); + SdrObject *pObj = 0; + OutlinerView* pOLV; + rSh.GetObjCntType( aDocPt, pObj ); + + if( pObj && 0 != ( pOLV = rSh.GetDrawView()->GetTextEditOutlinerView() )) + { + Rectangle aRect( pOLV->GetOutputArea() ); + aRect.Union( pObj->GetLogicRect() ); + const Point aPos = pOLV->GetWindow()->PixelToLogic(rEvt.maPosPixel); + if ( aRect.IsInside(aPos) ) + { + rSh.StartAllAction(); + rSh.EndAllAction(); + return nRet; + } + } + + // There's a special treatment for file lists with a single + // element, that depends on the actual content of the + // Transferable to be accessible. Since the transferable + // may only be accessed after the drop has been accepted + // (according to KA due to Java D&D), we'll have to + // reevaluate the drop action once more _with_ the + // Transferable. + sal_uInt16 nEventAction; + sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT + : rEvt.mnAction; + m_nDropAction = SotExchange::GetExchangeAction( + GetDataFlavorExVector(), + m_nDropDestination, + rEvt.mnAction, + nUserOpt, m_nDropFormat, nEventAction, 0, + &rEvt.maDropEvent.Transferable ); + + TransferableDataHelper aData( rEvt.maDropEvent.Transferable ); + nRet = rEvt.mnAction; + if( !SwTransferable::PasteData( aData, rSh, m_nDropAction, m_nDropFormat, + m_nDropDestination, false, rEvt.mbDefault, &aDocPt, nRet)) + nRet = DND_ACTION_NONE; + else if ( SW_MOD()->pDragDrop ) + //Don't clean up anymore at internal D&D! + SW_MOD()->pDragDrop->SetCleanUp( false ); + + return nRet; +} + +sal_uInt16 SwEditWin::GetDropDestination( const Point& rPixPnt, SdrObject ** ppObj ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + const Point aDocPt( PixelToLogic( rPixPnt ) ); + if( rSh.ChgCurrPam( aDocPt ) + || rSh.IsOverReadOnlyPos( aDocPt ) + || rSh.DocPtInsideInputFld( aDocPt ) ) + return 0; + + SdrObject *pObj = NULL; + const ObjCntType eType = rSh.GetObjCntType( aDocPt, pObj ); + + //Drop to OutlinerView (TextEdit in Drawing) should decide it on its own! + if( pObj ) + { + OutlinerView* pOLV = rSh.GetDrawView()->GetTextEditOutlinerView(); + if ( pOLV ) + { + Rectangle aRect( pOLV->GetOutputArea() ); + aRect.Union( pObj->GetLogicRect() ); + const Point aPos = pOLV->GetWindow()->PixelToLogic( rPixPnt ); + if( aRect.IsInside( aPos ) ) + return 0; + } + } + + //What do we want to drop on now? + sal_uInt16 nDropDestination = 0; + + //Did anything else arrive from the DrawingEngine? + if( OBJCNT_NONE != eType ) + { + switch ( eType ) + { + case OBJCNT_GRF: + { + bool bLink, + bIMap = 0 != rSh.GetFmtFromObj( aDocPt )->GetURL().GetMap(); + OUString aDummy; + rSh.GetGrfAtPos( aDocPt, aDummy, bLink ); + if ( bLink && bIMap ) + nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPH_W_IMAP; + else if ( bLink ) + nDropDestination = EXCHG_DEST_DOC_LNKD_GRAPHOBJ; + else if ( bIMap ) + nDropDestination = EXCHG_DEST_DOC_GRAPH_W_IMAP; + else + nDropDestination = EXCHG_DEST_DOC_GRAPHOBJ; + } + break; + case OBJCNT_FLY: + if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) + nDropDestination = EXCHG_DEST_DOC_TEXTFRAME_WEB; + else + nDropDestination = EXCHG_DEST_DOC_TEXTFRAME; + break; + case OBJCNT_OLE: nDropDestination = EXCHG_DEST_DOC_OLEOBJ; break; + case OBJCNT_CONTROL: /* no Action avail */ + case OBJCNT_SIMPLE: nDropDestination = EXCHG_DEST_DOC_DRAWOBJ; break; + case OBJCNT_URLBUTTON: nDropDestination = EXCHG_DEST_DOC_URLBUTTON; break; + case OBJCNT_GROUPOBJ: nDropDestination = EXCHG_DEST_DOC_GROUPOBJ; break; + + default: OSL_ENSURE( !this, "new ObjectType?" ); + } + } + if ( !nDropDestination ) + { + if( rSh.GetView().GetDocShell()->ISA(SwWebDocShell) ) + nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA_WEB; + else + nDropDestination = EXCHG_DEST_SWDOC_FREE_AREA; + } + if( ppObj ) + *ppObj = pObj; + return nDropDestination; +} + +sal_Int8 SwEditWin::AcceptDrop( const AcceptDropEvent& rEvt ) +{ + if( rEvt.mbLeaving ) + { + DropCleanup(); + return rEvt.mnAction; + } + + if( m_rView.GetDocShell()->IsReadOnly() ) + return DND_ACTION_NONE; + + SwWrtShell &rSh = m_rView.GetWrtShell(); + + Point aPixPt( rEvt.maPosPixel ); + + // If the cursor is near the inner boundary + // we attempt to scroll towards the desired direction. + Point aPoint; + Rectangle aWin(aPoint,GetOutputSizePixel()); + const int nMargin = 10; + aWin.Left() += nMargin; + aWin.Top() += nMargin; + aWin.Right() -= nMargin; + aWin.Bottom() -= nMargin; + if(!aWin.IsInside(aPixPt)) { + static sal_uLong last_tick = 0; + sal_uLong current_tick = Time::GetSystemTicks(); + if((current_tick-last_tick) > 500) { + last_tick = current_tick; + if(!m_bOldIdleSet) { + m_bOldIdle = rSh.GetViewOptions()->IsIdle(); + ((SwViewOption *)rSh.GetViewOptions())->SetIdle(false); + m_bOldIdleSet = true; + } + CleanupDropUserMarker(); + if(aPixPt.X() > aWin.Right()) aPixPt.X() += nMargin; + if(aPixPt.X() < aWin.Left()) aPixPt.X() -= nMargin; + if(aPixPt.Y() > aWin.Bottom()) aPixPt.Y() += nMargin; + if(aPixPt.Y() < aWin.Top()) aPixPt.Y() -= nMargin; + Point aDocPt(PixelToLogic(aPixPt)); + SwRect rect(aDocPt,Size(1,1)); + rSh.MakeVisible(rect); + } + } + + if(m_bOldIdleSet) { + ((SwViewOption *)rSh.GetViewOptions())->SetIdle( m_bOldIdle ); + m_bOldIdleSet = false; + } + + SdrObject *pObj = NULL; + m_nDropDestination = GetDropDestination( aPixPt, &pObj ); + if( !m_nDropDestination ) + return DND_ACTION_NONE; + + sal_uInt16 nEventAction; + sal_Int8 nUserOpt = rEvt.mbDefault ? EXCHG_IN_ACTION_DEFAULT + : rEvt.mnAction; + + m_nDropAction = SotExchange::GetExchangeAction( + GetDataFlavorExVector(), + m_nDropDestination, + rEvt.mnAction, + nUserOpt, m_nDropFormat, nEventAction ); + + if( EXCHG_INOUT_ACTION_NONE != m_nDropAction ) + { + const Point aDocPt( PixelToLogic( aPixPt ) ); + + //With the default action we still want to have a say. + SwModule *pMod = SW_MOD(); + if( pMod->pDragDrop ) + { + bool bCleanup = false; + //Drawing objects in Headers/Footers are not allowed + + SwWrtShell *pSrcSh = pMod->pDragDrop->GetShell(); + if( (pSrcSh->GetSelFrmType() == FRMTYPE_DRAWOBJ) && + pSrcSh->IsSelContainsControl() && + (rSh.GetFrmType( &aDocPt, false ) & (FRMTYPE_HEADER|FRMTYPE_FOOTER)) ) + { + bCleanup = true; + } + // don't more position protected objects! + else if( DND_ACTION_MOVE == rEvt.mnAction && + pSrcSh->IsSelObjProtected( FLYPROTECT_POS ) ) + { + bCleanup = true; + } + else if( rEvt.mbDefault ) + { + // internal Drag&Drop: within same Doc a Move + // otherwise a Copy - Task 54974 + nEventAction = pSrcSh->GetDoc() == rSh.GetDoc() + ? DND_ACTION_MOVE + : DND_ACTION_COPY; + } + if ( bCleanup ) + { + CleanupDropUserMarker(); + rSh.UnSetVisCrsr(); + return DND_ACTION_NONE; + } + } + else + { + //D&D from outside of SW should be a Copy per default. + if( EXCHG_IN_ACTION_DEFAULT == nEventAction && + DND_ACTION_MOVE == rEvt.mnAction ) + nEventAction = DND_ACTION_COPY; + + if( (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE == m_nDropFormat && + EXCHG_IN_ACTION_LINK == m_nDropAction) || + SOT_FORMATSTR_ID_SBA_CTRLDATAEXCHANGE == m_nDropFormat ) + { + SdrMarkView* pMView = PTR_CAST( SdrMarkView, rSh.GetDrawView() ); + if( pMView && !pMView->IsDesignMode() ) + return DND_ACTION_NONE; + } + } + + if ( EXCHG_IN_ACTION_DEFAULT != nEventAction ) + nUserOpt = (sal_Int8)nEventAction; + + // show DropCursor or UserMarker ? + if( EXCHG_DEST_SWDOC_FREE_AREA_WEB == m_nDropDestination || + EXCHG_DEST_SWDOC_FREE_AREA == m_nDropDestination ) + { + CleanupDropUserMarker(); + SwContentAtPos aCont( SwContentAtPos::SW_CONTENT_CHECK ); + if(rSh.GetContentAtPos(aDocPt, aCont)) + rSh.SwCrsrShell::SetVisCrsr( aDocPt ); + } + else + { + rSh.UnSetVisCrsr(); + + if ( m_pUserMarkerObj != pObj ) + { + CleanupDropUserMarker(); + m_pUserMarkerObj = pObj; + + if(m_pUserMarkerObj) + { + m_pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), *m_pUserMarkerObj ); + } + } + } + return nUserOpt; + } + + CleanupDropUserMarker(); + rSh.UnSetVisCrsr(); + return DND_ACTION_NONE; +} + +IMPL_LINK_NOARG(SwEditWin, DDHandler) +{ + bDDTimerStarted = false; + m_aTimer.Stop(); + m_aTimer.SetTimeout(240); + m_bMBPressed = false; + ReleaseMouse(); + bFrmDrag = false; + + if ( m_rView.GetViewFrame() ) + { + bExecuteDrag = true; + StartExecuteDrag(); + } + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx new file mode 100644 index 000000000000..5b96f7945d1e --- /dev/null +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -0,0 +1,6147 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <config_features.h> + +#include <swtypes.hxx> +#include <hintids.hxx> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <comphelper/processfactory.hxx> +#include <comphelper/string.hxx> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <com/sun/star/i18n/InputSequenceCheckMode.hpp> + +#include <com/sun/star/i18n/UnicodeScript.hpp> + +#include <vcl/help.hxx> +#include <vcl/graph.hxx> +#include <vcl/msgbox.hxx> +#include <sot/storage.hxx> +#include <svl/macitem.hxx> +#include <unotools/securityoptions.hxx> +#include <basic/sbxvar.hxx> +#include <svl/ctloptions.hxx> +#include <basic/sbx.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <sfx2/ipclient.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <svl/ptitem.hxx> +#include <editeng/sizeitem.hxx> +#include <editeng/langitem.hxx> +#include <sfx2/htmlmode.hxx> +#include <svx/svdview.hxx> +#include <svx/svdhdl.hxx> +#include <svx/svdoutl.hxx> +#include <editeng/editeng.hxx> +#include <editeng/svxacorr.hxx> +#include <editeng/scripttypeitem.hxx> +#include <editeng/flditem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/protitem.hxx> +#include <unotools/charclass.hxx> +#include <basegfx/color/bcolortools.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +#include <touch/touch-impl.h> + +#include <editeng/acorrcfg.hxx> +#include <SwSmartTagMgr.hxx> +#include <edtwin.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <IDocumentSettingAccess.hxx> +#include <fldbas.hxx> +#include <swmodule.hxx> +#include <docsh.hxx> +#include <viewopt.hxx> +#include <drawbase.hxx> +#include <dselect.hxx> +#include <textsh.hxx> +#include <shdwcrsr.hxx> +#include <txatbase.hxx> +#include <fmtanchr.hxx> +#include <fmtornt.hxx> +#include <fmtfsize.hxx> +#include <fmtclds.hxx> +#include <fmthdft.hxx> +#include <frmfmt.hxx> +#include <modcfg.hxx> +#include <fmtcol.hxx> +#include <wview.hxx> +#include <listsh.hxx> +#include <gloslst.hxx> +#include <inputwin.hxx> +#include <gloshdl.hxx> +#include <swundo.hxx> +#include <drwtxtsh.hxx> +#include <fchrfmt.hxx> +#include <fmturl.hxx> +#include <romenu.hxx> +#include <initui.hxx> +#include <frmatr.hxx> +#include <extinput.hxx> +#include <acmplwrd.hxx> +#include <swcalwrp.hxx> +#include <swdtflvr.hxx> +#include <wdocsh.hxx> +#include <crsskip.hxx> +#include <breakit.hxx> +#include <checkit.hxx> +#include <pagefrm.hxx> +#include <HeaderFooterWin.hxx> + +#include <helpid.h> +#include <cmdid.h> +#include <docvw.hrc> +#include <uitool.hxx> +#include <fmtfollowtextflow.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <charfmt.hxx> +#include <numrule.hxx> +#include <pagedesc.hxx> +#include <svtools/ruler.hxx> +#include "formatclipboard.hxx" +#include <osl/mutex.hxx> +#include <vcl/svapp.hxx> +#include <docstat.hxx> +#include <wordcountdialog.hxx> +#include <swwait.hxx> + +#include <IMark.hxx> +#include <doc.hxx> +#include <xmloff/odffields.hxx> + +#include <PostItMgr.hxx> + +#include <algorithm> +#include <vector> + +#include "../../core/inc/rootfrm.hxx" + +#include <unotools/syslocaleoptions.hxx> + +using namespace sw::mark; +using namespace ::com::sun::star; + +/** + * Globals + */ +static bool bInputLanguageSwitched = false; +extern bool bNoInterrupt; // in mainwn.cxx + +// Usually in MouseButtonUp a selection is revoked when the selection is +// not currently being pulled open. Unfortunately in MouseButtonDown there +// is being selected at double/triple click. That selection is completely +// finished in the Handler and thus can't be distinguished in the Up. +// To resolve this bHoldSelection is set in Down at evaluated in Up. +static bool bHoldSelection = false; + +bool bFrmDrag = false; +bool bValidCrsrPos = false; +bool bModePushed = false; +bool bDDTimerStarted = false; +bool bFlushCharBuffer = false; +bool bDDINetAttr = false; +SdrHdlKind eSdrMoveHdl = HDL_USER; + +QuickHelpData* SwEditWin::m_pQuickHlpData = 0; + +long SwEditWin::m_nDDStartPosY = 0; +long SwEditWin::m_nDDStartPosX = 0; +/** + * The initial color shown on the button is set in /core/svx/source/tbxctrls/tbxcolorupdate.cxx + * (ToolboxButtonColorUpdater::ToolboxButtonColorUpdater()) . + * The initial color used by the button is set in /core/svx/source/tbxcntrls/tbcontrl.cxx + * (SvxColorToolBoxControl::SvxColorToolBoxControl()) + * and in case of writer for text(background)color also in /core/sw/source/uibase/docvw/edtwin.cxx + * (SwEditWin::m_aTextBackColor and SwEditWin::m_aTextColor) + */ +Color SwEditWin::m_aTextBackColor(COL_YELLOW); +Color SwEditWin::m_aTextColor(COL_RED); + +extern bool bExecuteDrag; + +static SfxShell* lcl_GetShellFromDispatcher( SwView& rView, TypeId nType ); + +class SwAnchorMarker +{ + SdrHdl* pHdl; + Point aHdlPos; + Point aLastPos; + bool bTopRightHandle; +public: + SwAnchorMarker( SdrHdl* pH ) + : pHdl( pH ) + , aHdlPos( pH->GetPos() ) + , aLastPos( pH->GetPos() ) + , bTopRightHandle( pH->GetKind() == HDL_ANCHOR_TR ) + {} + const Point& GetLastPos() const { return aLastPos; } + void SetLastPos( const Point& rNew ) { aLastPos = rNew; } + void SetPos( const Point& rNew ) { pHdl->SetPos( rNew ); } + const Point& GetPos() { return pHdl->GetPos(); } + const Point& GetHdlPos() { return aHdlPos; } + SdrHdl* GetHdl() const { return pHdl; } + void ChgHdl( SdrHdl* pNew ) + { + pHdl = pNew; + if ( pHdl ) + { + bTopRightHandle = (pHdl->GetKind() == HDL_ANCHOR_TR); + } + } + const Point GetPosForHitTest( const OutputDevice& rOut ) + { + Point aHitTestPos( GetPos() ); + aHitTestPos = rOut.LogicToPixel( aHitTestPos ); + if ( bTopRightHandle ) + { + aHitTestPos += Point( -1, 1 ); + } + else + { + aHitTestPos += Point( 1, 1 ); + } + aHitTestPos = rOut.PixelToLogic( aHitTestPos ); + + return aHitTestPos; + } +}; + +/// Assists with auto-completion of AutoComplete words and AutoText names. +struct QuickHelpData +{ + /// Strings that at least partially match an input word. + std::vector<OUString> m_aHelpStrings; + /// Index of the current help string. + sal_uInt16 nCurArrPos; + /// Length of the input word associated with the help data. + sal_uInt16 nLen; + + /// Help data stores AutoText names rather than AutoComplete words. + bool m_bIsAutoText; + /// Display help string as a tip rather than inline. + bool m_bIsTip; + /// Tip ID when a help string is displayed as a tip. + sal_uLong nTipId; + /// Append a space character to the displayed help string (if appropriate). + bool m_bAppendSpace; + + /// Help string is currently displayed. + bool m_bIsDisplayed; + + QuickHelpData() { ClearCntnt(); } + + void Move( QuickHelpData& rCpy ); + void ClearCntnt(); + void Start( SwWrtShell& rSh, sal_uInt16 nWrdLen ); + void Stop( SwWrtShell& rSh ); + + bool HasCntnt() const { return !m_aHelpStrings.empty() && 0 != nLen; } + + /// Next help string. + void Next( bool bEndLess ) + { + if( ++nCurArrPos >= m_aHelpStrings.size() ) + nCurArrPos = (bEndLess && !m_bIsAutoText ) ? 0 : nCurArrPos-1; + } + /// Previous help string. + void Previous( bool bEndLess ) + { + if( 0 == nCurArrPos-- ) + nCurArrPos = (bEndLess && !m_bIsAutoText ) ? m_aHelpStrings.size()-1 : 0; + } + + // Fills internal structures with hopefully helpful information. + void FillStrArr( SwWrtShell& rSh, const OUString& rWord ); + void SortAndFilter(const OUString &rOrigWord); +}; + +/** + * Avoid minimal movement shiver + */ +#define HIT_PIX 2 /* hit tolerance in pixel */ +#define MIN_MOVE 4 + +inline bool IsMinMove(const Point &rStartPos, const Point &rLPt) +{ + return std::abs(rStartPos.X() - rLPt.X()) > MIN_MOVE || + std::abs(rStartPos.Y() - rLPt.Y()) > MIN_MOVE; +} + +/** + * For MouseButtonDown - determine whether a DrawObject + * an NO SwgFrame was hit! Shift/Ctrl should only result + * in selecting, with DrawObjects; at SwgFlys to trigger + * hyperlinks if applicable (Download/NewWindow!) + */ +inline bool IsDrawObjSelectable( const SwWrtShell& rSh, const Point& rPt ) +{ + bool bRet = true; + SdrObject* pObj; + switch( rSh.GetObjCntType( rPt, pObj )) + { + case OBJCNT_NONE: + case OBJCNT_FLY: + case OBJCNT_GRF: + case OBJCNT_OLE: + bRet = false; + break; + default:; //prevent warning + } + return bRet; +} + +/* + * Switch pointer + */ +void SwEditWin::UpdatePointer(const Point &rLPt, sal_uInt16 nModifier ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + if( m_pApplyTempl ) + { + PointerStyle eStyle = POINTER_FILL; + if ( rSh.IsOverReadOnlyPos( rLPt ) ) + { + delete m_pUserMarker; + m_pUserMarker = 0L; + + eStyle = POINTER_NOTALLOWED; + } + else + { + SwRect aRect; + SwRect* pRect = &aRect; + const SwFrmFmt* pFmt = 0; + + bool bFrameIsValidTarget = false; + if( m_pApplyTempl->m_pFormatClipboard ) + bFrameIsValidTarget = m_pApplyTempl->m_pFormatClipboard->HasContentForThisType( nsSelectionType::SEL_FRM ); + else if( !m_pApplyTempl->nColor ) + bFrameIsValidTarget = ( m_pApplyTempl->eType == SFX_STYLE_FAMILY_FRAME ); + + if( bFrameIsValidTarget && + 0 !=(pFmt = rSh.GetFmtFromObj( rLPt, &pRect )) && + PTR_CAST(SwFlyFrmFmt, pFmt)) + { + //turn on highlight for frame + Rectangle aTmp( pRect->SVRect() ); + + if ( !m_pUserMarker ) + { + m_pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ); + } + } + else + { + delete m_pUserMarker; + m_pUserMarker = 0L; + } + + rSh.SwCrsrShell::SetVisCrsr( rLPt ); + } + SetPointer( eStyle ); + return; + } + + if( !rSh.VisArea().Width() ) + return; + + SET_CURR_SHELL(&rSh); + + if ( IsChainMode() ) + { + SwRect aRect; + int nChainable = rSh.Chainable( aRect, *rSh.GetFlyFrmFmt(), rLPt ); + PointerStyle eStyle = nChainable + ? POINTER_CHAIN_NOTALLOWED : POINTER_CHAIN; + if ( !nChainable ) + { + Rectangle aTmp( aRect.SVRect() ); + + if ( !m_pUserMarker ) + { + m_pUserMarker = new SdrDropMarkerOverlay( *rSh.GetDrawView(), aTmp ); + } + } + else + { + delete m_pUserMarker; + m_pUserMarker = 0L; + } + + SetPointer( eStyle ); + return; + } + + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK ); + if ( ( bSecureOption && nModifier == KEY_MOD1 ) || + ( !bSecureOption && nModifier != KEY_MOD1 ) ) + bExecHyperlinks = true; + } + + const bool bExecSmarttags = nModifier == KEY_MOD1; + + SdrView *pSdrView = rSh.GetDrawView(); + bool bPrefSdrPointer = false; + bool bHitHandle = false; + bool bCntAtPos = false; + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && + rSh.IsCrsrReadonly(); + m_aActHitType = SDRHIT_NONE; + PointerStyle eStyle = POINTER_TEXT; + if ( !pSdrView ) + bCntAtPos = true; + else if ( (bHitHandle = pSdrView->PickHandle( rLPt ) != 0) ) + { + m_aActHitType = SDRHIT_OBJECT; + bPrefSdrPointer = true; + } + else + { + const bool bNotInSelObj = !rSh.IsInsideSelectedObj( rLPt ); + if ( m_rView.GetDrawFuncPtr() && !m_bInsDraw && bNotInSelObj ) + { + m_aActHitType = SDRHIT_OBJECT; + if (IsObjectSelect()) + eStyle = POINTER_ARROW; + else + bPrefSdrPointer = true; + } + else + { + SdrObject* pObj; SdrPageView* pPV; + pSdrView->SetHitTolerancePixel( HIT_PIX ); + if ( bNotInSelObj && bExecHyperlinks && + pSdrView->PickObj( rLPt, pSdrView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO )) + { + SdrObjMacroHitRec aTmp; + aTmp.aPos = rLPt; + aTmp.pPageView = pPV; + SetPointer( pObj->GetMacroPointer( aTmp ) ); + return; + } + else + { + // dvo: IsObjSelectable() eventually calls SdrView::PickObj, so + // apparently this is used to determine whether this is a + // drawling layer object or not. + if ( rSh.IsObjSelectable( rLPt ) ) + { + if (pSdrView->IsTextEdit()) + { + m_aActHitType = SDRHIT_NONE; + bPrefSdrPointer = true; + } + else + { + SdrViewEvent aVEvt; + SdrHitKind eHit = pSdrView->PickAnything(rLPt, aVEvt); + + if (eHit == SDRHIT_URLFIELD && bExecHyperlinks) + { + m_aActHitType = SDRHIT_OBJECT; + bPrefSdrPointer = true; + } + else + { + // if we're over a selected object, we show an + // ARROW by default. We only show a MOVE if 1) the + // object is selected, and 2) it may be moved + // (i.e., position is not protected). + bool bMovable = + (!bNotInSelObj) && + (rSh.IsObjSelected() || rSh.IsFrmSelected()) && + (!rSh.IsSelObjProtected(FLYPROTECT_POS)); + + SdrObject* pSelectableObj = rSh.GetObjAt(rLPt); + // Don't update pointer if this is a background image only. + if (pSelectableObj->GetLayer() != rSh.GetDoc()->GetHellId()) + eStyle = bMovable ? POINTER_MOVE : POINTER_ARROW; + m_aActHitType = SDRHIT_OBJECT; + } + } + } + else + { + if ( rSh.IsFrmSelected() && !bNotInSelObj ) + { + // dvo: this branch appears to be dead and should be + // removed in a future version. Reason: The condition + // !bNotInSelObj means that this branch will only be + // executed in the cursor points inside a selected + // object. However, if this is the case, the previous + // if( rSh.IsObjSelectable(rLPt) ) must always be true: + // rLPt is inside a selected object, then obviously + // rLPt is over a selectable object. + if (rSh.IsSelObjProtected(FLYPROTECT_SIZE)) + eStyle = POINTER_NOTALLOWED; + else + eStyle = POINTER_MOVE; + m_aActHitType = SDRHIT_OBJECT; + } + else + { + if ( m_rView.GetDrawFuncPtr() ) + bPrefSdrPointer = true; + else + bCntAtPos = true; + } + } + } + } + } + if ( bPrefSdrPointer ) + { + if (bIsDocReadOnly || (rSh.IsObjSelected() && rSh.IsSelObjProtected(FLYPROTECT_CONTENT))) + SetPointer( POINTER_NOTALLOWED ); + else + { + if (m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->IsInsertForm() && !bHitHandle) + SetPointer( POINTER_DRAW_RECT ); + else + SetPointer( pSdrView->GetPreferredPointer( rLPt, rSh.GetOut() ) ); + } + } + else + { + if( !rSh.IsPageAtPos( rLPt ) || m_pAnchorMarker ) + eStyle = POINTER_ARROW; + else + { + // Even if we already have something, prefer URLs if possible. + SwContentAtPos aUrlPos(SwContentAtPos::SW_INETATTR); + if (bCntAtPos || rSh.GetContentAtPos(rLPt, aUrlPos)) + { + SwContentAtPos aSwContentAtPos( + SwContentAtPos::SW_CLICKFIELD| + SwContentAtPos::SW_INETATTR| + SwContentAtPos::SW_FTN | + SwContentAtPos::SW_SMARTTAG ); + if( rSh.GetContentAtPos( rLPt, aSwContentAtPos) ) + { + const bool bClickToFollow = SwContentAtPos::SW_INETATTR == aSwContentAtPos.eCntntAtPos || + SwContentAtPos::SW_SMARTTAG == aSwContentAtPos.eCntntAtPos; + + if( !bClickToFollow || + (SwContentAtPos::SW_INETATTR == aSwContentAtPos.eCntntAtPos && bExecHyperlinks) || + (SwContentAtPos::SW_SMARTTAG == aSwContentAtPos.eCntntAtPos && bExecSmarttags) ) + eStyle = POINTER_REFHAND; + } + } + } + + // which kind of text pointer have we to show - horz / vert - ? + if( POINTER_TEXT == eStyle && rSh.IsInVerticalText( &rLPt )) + eStyle = POINTER_TEXT_VERTICAL; + + SetPointer( eStyle ); + } +} + +/** + * Increase timer for selection + */ +IMPL_LINK_NOARG(SwEditWin, TimerHandler) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + Point aModPt( m_aMovePos ); + const SwRect aOldVis( rSh.VisArea() ); + bool bDone = false; + + if ( !rSh.VisArea().IsInside( aModPt ) ) + { + if ( m_bInsDraw ) + { + const int nMaxScroll = 40; + m_rView.Scroll( Rectangle(aModPt,Size(1,1)), nMaxScroll, nMaxScroll); + bDone = true; + } + else if ( bFrmDrag ) + { + rSh.Drag(&aModPt, false); + bDone = true; + } + if ( !bDone ) + aModPt = rSh.GetCntntPos( aModPt,aModPt.Y() > rSh.VisArea().Bottom() ); + } + if ( !bDone && !(bFrmDrag || m_bInsDraw) ) + { + if ( m_pRowColumnSelectionStart ) + { + Point aPos( aModPt ); + rSh.SelectTableRowCol( *m_pRowColumnSelectionStart, &aPos, m_bIsRowDrag ); + } + else + rSh.SetCursor( &aModPt, false ); + + // It can be that a "jump" over a table cannot be accomplished like + // that. So we jump over the table by Up/Down here. + const SwRect& rVisArea = rSh.VisArea(); + if( aOldVis == rVisArea && !rSh.IsStartOfDoc() && !rSh.IsEndOfDoc() ) + { + // take the center point of VisArea to + // decide in which direction the user want. + if( aModPt.Y() < ( rVisArea.Top() + rVisArea.Height() / 2 ) ) + rSh.Up( true, 1 ); + else + rSh.Down( true, 1 ); + } + } + + m_aMovePos += rSh.VisArea().Pos() - aOldVis.Pos(); + JustifyAreaTimer(); + return 0; +} + +void SwEditWin::JustifyAreaTimer() +{ + const Rectangle &rVisArea = GetView().GetVisArea(); +#ifdef UNX + const long coMinLen = 100; +#else + const long coMinLen = 50; +#endif + long nTimeout = 800, + nDiff = std::max( + std::max( m_aMovePos.Y() - rVisArea.Bottom(), rVisArea.Top() - m_aMovePos.Y() ), + std::max( m_aMovePos.X() - rVisArea.Right(), rVisArea.Left() - m_aMovePos.X())); + m_aTimer.SetTimeout( std::max( coMinLen, nTimeout - nDiff*2L) ); +} + +void SwEditWin::LeaveArea(const Point &rPos) +{ + m_aMovePos = rPos; + JustifyAreaTimer(); + if( !m_aTimer.IsActive() ) + m_aTimer.Start(); + delete m_pShadCrsr, m_pShadCrsr = 0; +} + +inline void SwEditWin::EnterArea() +{ + m_aTimer.Stop(); +} + +/** + * Insert mode for frames + */ +void SwEditWin::InsFrm(sal_uInt16 nCols) +{ + StdDrawMode( OBJ_NONE, false ); + m_bInsFrm = true; + m_nInsFrmColCount = nCols; +} + +void SwEditWin::StdDrawMode( SdrObjKind eSdrObjectKind, bool bObjSelect ) +{ + SetSdrDrawMode( eSdrObjectKind ); + + if (bObjSelect) + m_rView.SetDrawFuncPtr(new DrawSelection( &m_rView.GetWrtShell(), this, &m_rView )); + else + m_rView.SetDrawFuncPtr(new SwDrawBase( &m_rView.GetWrtShell(), this, &m_rView )); + + m_rView.SetSelDrawSlot(); + SetSdrDrawMode( eSdrObjectKind ); + if (bObjSelect) + m_rView.GetDrawFuncPtr()->Activate( SID_OBJECT_SELECT ); + else + m_rView.GetDrawFuncPtr()->Activate( sal::static_int_cast< sal_uInt16 >(eSdrObjectKind) ); + m_bInsFrm = false; + m_nInsFrmColCount = 1; +} + +void SwEditWin::StopInsFrm() +{ + if (m_rView.GetDrawFuncPtr()) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + } + m_rView.LeaveDrawCreate(); // leave construction mode + m_bInsFrm = false; + m_nInsFrmColCount = 1; +} + +bool SwEditWin::IsInputSequenceCheckingRequired( const OUString &rText, const SwPaM& rCrsr ) const +{ + const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); + if ( !rCTLOptions.IsCTLFontEnabled() || + !rCTLOptions.IsCTLSequenceChecking() ) + return false; + + if ( 0 == rCrsr.Start()->nContent.GetIndex() ) /* first char needs not to be checked */ + return false; + + SwBreakIt *pBreakIter = SwBreakIt::Get(); + uno::Reference < i18n::XBreakIterator > xBI = pBreakIter->GetBreakIter(); + long nCTLScriptPos = -1; + + if (xBI.is()) + { + if (xBI->getScriptType( rText, 0 ) == i18n::ScriptType::COMPLEX) + nCTLScriptPos = 0; + else + nCTLScriptPos = xBI->nextScript( rText, 0, i18n::ScriptType::COMPLEX ); + } + + return (0 <= nCTLScriptPos && nCTLScriptPos <= rText.getLength()); +} + +//return INVALID_HINT if language should not be explictly overridden, the correct +//HintId to use for the eBufferLanguage otherwise +static sal_uInt16 lcl_isNonDefaultLanguage(LanguageType eBufferLanguage, SwView& rView, + const OUString &rInBuffer) +{ + sal_uInt16 nWhich = INVALID_HINT; + + //If the option to IgnoreLanguageChange is set, short-circuit this method + //which results in the document/paragraph language remaining the same + //despite a change to the keyboard/input language + SvtSysLocaleOptions aSysLocaleOptions; + if(aSysLocaleOptions.IsIgnoreLanguageChange()) + { + return INVALID_HINT; + } + + bool bLang = true; + if(eBufferLanguage != LANGUAGE_DONTKNOW) + { + switch( GetI18NScriptTypeOfLanguage( eBufferLanguage )) + { + case i18n::ScriptType::ASIAN: nWhich = RES_CHRATR_CJK_LANGUAGE; break; + case i18n::ScriptType::COMPLEX: nWhich = RES_CHRATR_CTL_LANGUAGE; break; + case i18n::ScriptType::LATIN: nWhich = RES_CHRATR_LANGUAGE; break; + default: bLang = false; + } + if(bLang) + { + SfxItemSet aLangSet(rView.GetPool(), nWhich, nWhich); + SwWrtShell& rSh = rView.GetWrtShell(); + rSh.GetCurAttr(aLangSet); + if(SFX_ITEM_DEFAULT <= aLangSet.GetItemState(nWhich, true)) + { + LanguageType eLang = static_cast<const SvxLanguageItem&>(aLangSet.Get(nWhich)).GetLanguage(); + if ( eLang == eBufferLanguage ) + { + // current language attribute equal to language reported from system + bLang = false; + } + else if ( !bInputLanguageSwitched && RES_CHRATR_LANGUAGE == nWhich ) + { + // special case: switching between two "LATIN" languages + // In case the current keyboard setting might be suitable + // for both languages we can't safely assume that the user + // wants to use the language reported from the system, + // except if we knew that it was explicitly switched (thus + // the check for "bInputLangeSwitched"). + + // The language reported by the system could be just the + // system default language that the user is not even aware + // of, because no language selection tool is installed at + // all. In this case the OOo language should get preference + // as it might have been selected by the user explicitly. + + // Usually this case happens if the OOo language is + // different to the system language but the system keyboard + // is still suitable for the OOo language (e.g. writing + // English texts with a German keyboard). + + // For non-latin keyboards overwriting the attribute is + // still valid. We do this for kyrillic and greek ATM. In + // future versions of OOo this should be replaced by a + // configuration switch that allows to give the preference + // to the OOo setting or the system setting explicitly + // and/or a better handling of the script type. + i18n::UnicodeScript eType = !rInBuffer.isEmpty() ? + (i18n::UnicodeScript)GetAppCharClass().getScript( rInBuffer, 0 ) : + i18n::UnicodeScript_kScriptCount; + + bool bSystemIsNonLatin = false; + switch ( eType ) + { + case i18n::UnicodeScript_kGreek: + case i18n::UnicodeScript_kCyrillic: + // in case other UnicodeScripts require special + // keyboards they can be added here + bSystemIsNonLatin = true; + break; + default: + break; + } + + bool bOOoLangIsNonLatin = MsLangId::isNonLatinWestern( eLang); + + bLang = (bSystemIsNonLatin != bOOoLangIsNonLatin); + } + } + } + } + return bLang ? nWhich : INVALID_HINT; +} + +/** + * Character buffer is inserted into the document + */ +void SwEditWin::FlushInBuffer() +{ + if ( !m_aInBuffer.isEmpty() ) + { + SwWrtShell& rSh = m_rView.GetWrtShell(); + + // generate new sequence input checker if not already done + if ( !pCheckIt ) + pCheckIt = new SwCheckIt; + + uno::Reference < i18n::XExtendedInputSequenceChecker > xISC = pCheckIt->xCheck; + if ( xISC.is() && IsInputSequenceCheckingRequired( m_aInBuffer, *rSh.GetCrsr() ) ) + { + + // apply (Thai) input sequence checking/correction + + rSh.Push(); // push current cursor to stack + + // get text from the beginning (i.e left side) of current selection + // to the start of the paragraph + rSh.NormalizePam(); // make point be the first (left) one + if (!rSh.GetCrsr()->HasMark()) + rSh.GetCrsr()->SetMark(); + rSh.GetCrsr()->GetMark()->nContent = 0; + + const OUString aOldText( rSh.GetCrsr()->GetTxt() ); + const sal_Int32 nOldLen = aOldText.getLength(); + + SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions(); + + sal_Int32 nExpandSelection = 0; + if (nOldLen > 0) + { + sal_Int32 nTmpPos = nOldLen; + sal_Int16 nCheckMode = rCTLOptions.IsCTLSequenceCheckingRestricted() ? + i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; + + OUString aNewText( aOldText ); + if (rCTLOptions.IsCTLSequenceCheckingTypeAndReplace()) + { + for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k) + { + const sal_Unicode cChar = m_aInBuffer[k]; + const sal_Int32 nPrevPos =xISC->correctInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode ); + + // valid sequence or sequence could be corrected: + if (nPrevPos != aNewText.getLength()) + nTmpPos = nPrevPos + 1; + } + + // find position of first character that has changed + sal_Int32 nNewLen = aNewText.getLength(); + const sal_Unicode *pOldTxt = aOldText.getStr(); + const sal_Unicode *pNewTxt = aNewText.getStr(); + sal_Int32 nChgPos = 0; + while ( nChgPos < nOldLen && nChgPos < nNewLen && + pOldTxt[nChgPos] == pNewTxt[nChgPos] ) + ++nChgPos; + + const sal_Int32 nChgLen = nNewLen - nChgPos; + if (nChgLen) + { + m_aInBuffer = aNewText.copy( nChgPos, nChgLen ); + nExpandSelection = nOldLen - nChgPos; + } + else + m_aInBuffer = ""; + } + else + { + for( sal_Int32 k = 0; k < m_aInBuffer.getLength(); ++k ) + { + const sal_Unicode cChar = m_aInBuffer[k]; + if (xISC->checkInputSequence( aNewText, nTmpPos - 1, cChar, nCheckMode )) + { + // character can be inserted: + aNewText += OUString( (sal_Unicode) cChar ); + ++nTmpPos; + } + } + m_aInBuffer = aNewText.copy( aOldText.getLength() ); // copy new text to be inserted to buffer + } + } + + // at this point now we will insert the buffer text 'normally' some lines below... + + rSh.Pop( false ); // pop old cursor from stack + + if (m_aInBuffer.isEmpty()) + return; + + // if text prior to the original selection needs to be changed + // as well, we now expand the selection accordingly. + SwPaM &rCrsr = *rSh.GetCrsr(); + const sal_Int32 nCrsrStartPos = rCrsr.Start()->nContent.GetIndex(); + OSL_ENSURE( nCrsrStartPos >= nExpandSelection, "cannot expand selection as specified!!" ); + if (nExpandSelection && nCrsrStartPos >= nExpandSelection) + { + if (!rCrsr.HasMark()) + rCrsr.SetMark(); + rCrsr.Start()->nContent -= nExpandSelection; + } + } + + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_rView.GetViewFrame()->GetBindings().GetRecorder(); + if ( xRecorder.is() ) + { + // determine shell + SfxShell *pSfxShell = lcl_GetShellFromDispatcher( m_rView, TYPE(SwTextShell) ); + // generate request and record + if (pSfxShell) + { + SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING ); + aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, m_aInBuffer ) ); + aReq.Done(); + } + } + + sal_uInt16 nWhich = lcl_isNonDefaultLanguage(m_eBufferLanguage, m_rView, m_aInBuffer); + if (nWhich != INVALID_HINT ) + { + SvxLanguageItem aLangItem( m_eBufferLanguage, nWhich ); + rSh.SetAttrItem( aLangItem ); + } + + rSh.Insert( m_aInBuffer ); + m_eBufferLanguage = LANGUAGE_DONTKNOW; + m_aInBuffer = ""; + bFlushCharBuffer = false; + } +} + +#define MOVE_LEFT_SMALL 0 +#define MOVE_UP_SMALL 1 +#define MOVE_RIGHT_BIG 2 +#define MOVE_DOWN_BIG 3 +#define MOVE_LEFT_BIG 4 +#define MOVE_UP_BIG 5 +#define MOVE_RIGHT_SMALL 6 +#define MOVE_DOWN_SMALL 7 + +// #i121236# Support for shift key in writer +#define MOVE_LEFT_HUGE 8 +#define MOVE_UP_HUGE 9 +#define MOVE_RIGHT_HUGE 10 +#define MOVE_DOWN_HUGE 11 + +void SwEditWin::ChangeFly( sal_uInt8 nDir, bool bWeb ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + SwRect aTmp = rSh.GetFlyRect(); + if( aTmp.HasArea() && + !rSh.IsSelObjProtected( FLYPROTECT_POS ) ) + { + SfxItemSet aSet(rSh.GetAttrPool(), + RES_FRM_SIZE, RES_FRM_SIZE, + RES_VERT_ORIENT, RES_ANCHOR, + RES_COL, RES_COL, + RES_PROTECT, RES_PROTECT, + RES_FOLLOW_TEXT_FLOW, RES_FOLLOW_TEXT_FLOW, 0); + rSh.GetFlyFrmAttr( aSet ); + RndStdIds eAnchorId = ((SwFmtAnchor&)aSet.Get(RES_ANCHOR)).GetAnchorId(); + Size aSnap; + bool bHuge(MOVE_LEFT_HUGE == nDir || + MOVE_UP_HUGE == nDir || + MOVE_RIGHT_HUGE == nDir || + MOVE_DOWN_HUGE == nDir); + + if(MOVE_LEFT_SMALL == nDir || + MOVE_UP_SMALL == nDir || + MOVE_RIGHT_SMALL == nDir || + MOVE_DOWN_SMALL == nDir ) + { + aSnap = PixelToLogic(Size(1,1)); + } + else + { + aSnap = rSh.GetViewOptions()->GetSnapSize(); + short nDiv = rSh.GetViewOptions()->GetDivisionX(); + if ( nDiv > 0 ) + aSnap.Width() = std::max( (sal_uLong)1, (sal_uLong)aSnap.Width() / nDiv ); + nDiv = rSh.GetViewOptions()->GetDivisionY(); + if ( nDiv > 0 ) + aSnap.Height() = std::max( (sal_uLong)1, (sal_uLong)aSnap.Height() / nDiv ); + } + + if(bHuge) + { + // #i121236# 567twips == 1cm, but just take three times the normal snap + aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3); + } + + SwRect aBoundRect; + Point aRefPoint; + // adjustment for allowing vertical position + // aligned to page for fly frame anchored to paragraph or to character. + { + SwFmtVertOrient aVert( (SwFmtVertOrient&)aSet.Get(RES_VERT_ORIENT) ); + const bool bFollowTextFlow = + static_cast<const SwFmtFollowTextFlow&>(aSet.Get(RES_FOLLOW_TEXT_FLOW)).GetValue(); + const SwPosition* pToCharCntntPos = ((SwFmtAnchor&)aSet.Get(RES_ANCHOR)).GetCntntAnchor(); + rSh.CalcBoundRect( aBoundRect, eAnchorId, + text::RelOrientation::FRAME, aVert.GetRelationOrient(), + pToCharCntntPos, bFollowTextFlow, + false, &aRefPoint ); + } + long nLeft = std::min( aTmp.Left() - aBoundRect.Left(), aSnap.Width() ); + long nRight = std::min( aBoundRect.Right() - aTmp.Right(), aSnap.Width() ); + long nUp = std::min( aTmp.Top() - aBoundRect.Top(), aSnap.Height() ); + long nDown = std::min( aBoundRect.Bottom() - aTmp.Bottom(), aSnap.Height() ); + + switch ( nDir ) + { + case MOVE_LEFT_BIG: + case MOVE_LEFT_HUGE: + case MOVE_LEFT_SMALL: aTmp.Left( aTmp.Left() - nLeft ); + break; + + case MOVE_UP_BIG: + case MOVE_UP_HUGE: + case MOVE_UP_SMALL: aTmp.Top( aTmp.Top() - nUp ); + break; + + case MOVE_RIGHT_SMALL: + if( aTmp.Width() < aSnap.Width() + MINFLY ) + break; + nRight = aSnap.Width(); // no break + case MOVE_RIGHT_HUGE: + case MOVE_RIGHT_BIG: aTmp.Left( aTmp.Left() + nRight ); + break; + + case MOVE_DOWN_SMALL: + if( aTmp.Height() < aSnap.Height() + MINFLY ) + break; + nDown = aSnap.Height(); // no break + case MOVE_DOWN_HUGE: + case MOVE_DOWN_BIG: aTmp.Top( aTmp.Top() + nDown ); + break; + + default: OSL_ENSURE(true, "ChangeFly: Unknown direction." ); + } + bool bSet = false; + if ((FLY_AS_CHAR == eAnchorId) && ( nDir % 2 )) + { + long aDiff = aTmp.Top() - aRefPoint.Y(); + if( aDiff > 0 ) + aDiff = 0; + else if ( aDiff < -aTmp.Height() ) + aDiff = -aTmp.Height(); + SwFmtVertOrient aVert( (SwFmtVertOrient&)aSet.Get(RES_VERT_ORIENT) ); + sal_Int16 eNew; + if( bWeb ) + { + eNew = aVert.GetVertOrient(); + bool bDown = 0 != ( nDir & 0x02 ); + switch( eNew ) + { + case text::VertOrientation::CHAR_TOP: + if( bDown ) eNew = text::VertOrientation::CENTER; + break; + case text::VertOrientation::CENTER: + eNew = bDown ? text::VertOrientation::TOP : text::VertOrientation::CHAR_TOP; + break; + case text::VertOrientation::TOP: + if( !bDown ) eNew = text::VertOrientation::CENTER; + break; + case text::VertOrientation::LINE_TOP: + if( bDown ) eNew = text::VertOrientation::LINE_CENTER; + break; + case text::VertOrientation::LINE_CENTER: + eNew = bDown ? text::VertOrientation::LINE_BOTTOM : text::VertOrientation::LINE_TOP; + break; + case text::VertOrientation::LINE_BOTTOM: + if( !bDown ) eNew = text::VertOrientation::LINE_CENTER; + break; + default:; //prevent warning + } + } + else + { + aVert.SetPos( aDiff ); + eNew = text::VertOrientation::NONE; + } + aVert.SetVertOrient( eNew ); + aSet.Put( aVert ); + bSet = true; + } + if (bWeb && (FLY_AT_PARA == eAnchorId) + && ( nDir==MOVE_LEFT_SMALL || nDir==MOVE_RIGHT_BIG )) + { + SwFmtHoriOrient aHori( (SwFmtHoriOrient&)aSet.Get(RES_HORI_ORIENT) ); + sal_Int16 eNew; + eNew = aHori.GetHoriOrient(); + switch( eNew ) + { + case text::HoriOrientation::RIGHT: + if( nDir==MOVE_LEFT_SMALL ) + eNew = text::HoriOrientation::LEFT; + break; + case text::HoriOrientation::LEFT: + if( nDir==MOVE_RIGHT_BIG ) + eNew = text::HoriOrientation::RIGHT; + break; + default:; //prevent warning + } + if( eNew != aHori.GetHoriOrient() ) + { + aHori.SetHoriOrient( eNew ); + aSet.Put( aHori ); + bSet = true; + } + } + rSh.StartAllAction(); + if( bSet ) + rSh.SetFlyFrmAttr( aSet ); + bool bSetPos = (FLY_AS_CHAR != eAnchorId); + if(bSetPos && bWeb) + { + if (FLY_AT_PAGE != eAnchorId) + { + bSetPos = false; + } + else + { + bSetPos = true; + } + } + if( bSetPos ) + rSh.SetFlyPos( aTmp.Pos() ); + rSh.EndAllAction(); + } +} + +void SwEditWin::ChangeDrawing( sal_uInt8 nDir ) +{ + // start undo action in order to get only one + // undo action for this change. + SwWrtShell &rSh = m_rView.GetWrtShell(); + rSh.StartUndo(); + + long nX = 0; + long nY = 0; + const bool bOnePixel( + MOVE_LEFT_SMALL == nDir || + MOVE_UP_SMALL == nDir || + MOVE_RIGHT_SMALL == nDir || + MOVE_DOWN_SMALL == nDir); + const bool bHuge( + MOVE_LEFT_HUGE == nDir || + MOVE_UP_HUGE == nDir || + MOVE_RIGHT_HUGE == nDir || + MOVE_DOWN_HUGE == nDir); + sal_uInt16 nAnchorDir = SW_MOVE_UP; + switch(nDir) + { + case MOVE_LEFT_SMALL: + case MOVE_LEFT_HUGE: + case MOVE_LEFT_BIG: + nX = -1; + nAnchorDir = SW_MOVE_LEFT; + break; + case MOVE_UP_SMALL: + case MOVE_UP_HUGE: + case MOVE_UP_BIG: + nY = -1; + break; + case MOVE_RIGHT_SMALL: + case MOVE_RIGHT_HUGE: + case MOVE_RIGHT_BIG: + nX = +1; + nAnchorDir = SW_MOVE_RIGHT; + break; + case MOVE_DOWN_SMALL: + case MOVE_DOWN_HUGE: + case MOVE_DOWN_BIG: + nY = +1; + nAnchorDir = SW_MOVE_DOWN; + break; + } + + if(0 != nX || 0 != nY) + { + sal_uInt8 nProtect = rSh.IsSelObjProtected( FLYPROTECT_POS|FLYPROTECT_SIZE ); + Size aSnap( rSh.GetViewOptions()->GetSnapSize() ); + short nDiv = rSh.GetViewOptions()->GetDivisionX(); + if ( nDiv > 0 ) + aSnap.Width() = std::max( (sal_uLong)1, (sal_uLong)aSnap.Width() / nDiv ); + nDiv = rSh.GetViewOptions()->GetDivisionY(); + if ( nDiv > 0 ) + aSnap.Height() = std::max( (sal_uLong)1, (sal_uLong)aSnap.Height() / nDiv ); + + if(bOnePixel) + { + aSnap = PixelToLogic(Size(1,1)); + } + else if(bHuge) + { + // #i121236# 567twips == 1cm, but just take three times the normal snap + aSnap = Size(aSnap.Width() * 3, aSnap.Height() * 3); + } + + nX *= aSnap.Width(); + nY *= aSnap.Height(); + + SdrView *pSdrView = rSh.GetDrawView(); + const SdrHdlList& rHdlList = pSdrView->GetHdlList(); + SdrHdl* pHdl = rHdlList.GetFocusHdl(); + rSh.StartAllAction(); + if(0L == pHdl) + { + // now move the selected draw objects + // if the object's position is not protected + if(0 == (nProtect&FLYPROTECT_POS)) + { + // Check if object is anchored as character and move direction + bool bDummy1, bDummy2; + const bool bVertAnchor = rSh.IsFrmVertical( true, bDummy1, bDummy2 ); + bool bHoriMove = !bVertAnchor == !( nDir % 2 ); + bool bMoveAllowed = + !bHoriMove || (rSh.GetAnchorId() != FLY_AS_CHAR); + if ( bMoveAllowed ) + { + pSdrView->MoveAllMarked(Size(nX, nY)); + rSh.SetModified(); + } + } + } + else + { + // move handle with index nHandleIndex + if(pHdl && (nX || nY)) + { + if( HDL_ANCHOR == pHdl->GetKind() || + HDL_ANCHOR_TR == pHdl->GetKind() ) + { + // anchor move cannot be allowed when position is protected + if(0 == (nProtect&FLYPROTECT_POS)) + rSh.MoveAnchor( nAnchorDir ); + } + //now resize if size is protected + else if(0 == (nProtect&FLYPROTECT_SIZE)) + { + // now move the Handle (nX, nY) + Point aStartPoint(pHdl->GetPos()); + Point aEndPoint(pHdl->GetPos() + Point(nX, nY)); + const SdrDragStat& rDragStat = pSdrView->GetDragStat(); + + // start dragging + pSdrView->BegDragObj(aStartPoint, 0, pHdl, 0); + + if(pSdrView->IsDragObj()) + { + bool bWasNoSnap = rDragStat.IsNoSnap(); + bool bWasSnapEnabled = pSdrView->IsSnapEnabled(); + + // switch snapping off + if(!bWasNoSnap) + ((SdrDragStat&)rDragStat).SetNoSnap(true); + if(bWasSnapEnabled) + pSdrView->SetSnapEnabled(false); + + pSdrView->MovAction(aEndPoint); + pSdrView->EndDragObj(); + rSh.SetModified(); + + // restore snap + if(!bWasNoSnap) + ((SdrDragStat&)rDragStat).SetNoSnap(bWasNoSnap); + if(bWasSnapEnabled) + pSdrView->SetSnapEnabled(bWasSnapEnabled); + } + } + } + } + rSh.EndAllAction(); + } + + rSh.EndUndo(); +} + +/** + * KeyEvents + */ +void SwEditWin::KeyInput(const KeyEvent &rKEvt) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + if( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && + m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard ) + { + m_pApplyTempl->m_pFormatClipboard->Erase(); + SetApplyTemplate(SwApplyTemplate()); + m_rView.GetViewFrame()->GetBindings().Invalidate(SID_FORMATPAINTBRUSH); + } + else if ( rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE && + rSh.IsHeaderFooterEdit( ) ) + { + bool bHeader = FRMTYPE_HEADER & rSh.GetFrmType(0,false); + if ( bHeader ) + rSh.SttPg(); + else + rSh.EndPg(); + rSh.ToggleHeaderFooterEdit(); + } + + SfxObjectShell *pObjSh = (SfxObjectShell*)m_rView.GetViewFrame()->GetObjectShell(); + if ( m_bLockInput || (pObjSh && pObjSh->GetProgress()) ) + // When the progress bar is active or a progress is + // running on a document, no order is being taken + return; + + delete m_pShadCrsr, m_pShadCrsr = 0; + m_aKeyInputFlushTimer.Stop(); + + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && + rSh.IsCrsrReadonly(); + + //if the language changes the buffer must be flushed + LanguageType eNewLanguage = GetInputLanguage(); + if(!bIsDocReadOnly && m_eBufferLanguage != eNewLanguage && !m_aInBuffer.isEmpty()) + { + FlushInBuffer(); + } + m_eBufferLanguage = eNewLanguage; + + QuickHelpData aTmpQHD; + if( m_pQuickHlpData->m_bIsDisplayed ) + { + aTmpQHD.Move( *m_pQuickHlpData ); + m_pQuickHlpData->Stop( rSh ); + } + + // OS:the DrawView also needs a readonly-Flag as well + if ( !bIsDocReadOnly && rSh.GetDrawView() && rSh.GetDrawView()->KeyInput( rKEvt, this ) ) + { + rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll( false ); + rSh.SetModified(); + return; // Event evaluated by SdrView + } + + if ( m_rView.GetDrawFuncPtr() && m_bInsFrm ) + { + StopInsFrm(); + rSh.Edit(); + } + + bool bFlushBuffer = false; + bool bNormalChar = false; + bool bAppendSpace = m_pQuickHlpData->m_bAppendSpace; + m_pQuickHlpData->m_bAppendSpace = false; + + if ( getenv("SW_DEBUG") && rKEvt.GetKeyCode().GetCode() == KEY_F12 ) + { + if( rKEvt.GetKeyCode().IsShift()) + { + GetView().GetDocShell()->GetDoc()->dumpAsXml(); + return; + } + else + { + SwRootFrm* pLayout = GetView().GetDocShell()->GetWrtShell()->GetLayout(); + pLayout->dumpAsXml( ); + return; + } + } + + KeyEvent aKeyEvent( rKEvt ); + // look for vertical mappings + if( !bIsDocReadOnly && !rSh.IsSelFrmMode() && !rSh.IsObjSelected() ) + { + // must changed from switch to if, because the Linux + // compiler has problem with the code. Has to remove if the new general + // handler exist. + sal_uInt16 nKey = rKEvt.GetKeyCode().GetCode(); + + if( KEY_UP == nKey || KEY_DOWN == nKey || + KEY_LEFT == nKey || KEY_RIGHT == nKey ) + { + // In general, we want to map the direction keys if we are inside + // some vertical formatted text. + // 1. Exception: For a table cursor in a horizontal table, the + // directions should never be mapped. + // 2. Exception: For a table cursor in a vertical table, the + // directions should always be mapped. + const bool bVertText = rSh.IsInVerticalText(); + const bool bTblCrsr = rSh.GetTableCrsr(); + const bool bVertTable = rSh.IsTableVertical(); + if( ( bVertText && ( !bTblCrsr || bVertTable ) ) || + ( bTblCrsr && bVertTable ) ) + { + // Attempt to integrate cursor travelling for mongolian layout does not work. + // Thus, back to previous mapping of cursor keys to direction keys. + if( KEY_UP == nKey ) nKey = KEY_LEFT; + else if( KEY_DOWN == nKey ) nKey = KEY_RIGHT; + else if( KEY_LEFT == nKey ) nKey = KEY_DOWN; + else if( KEY_RIGHT == nKey ) nKey = KEY_UP; + } + + if ( rSh.IsInRightToLeftText() ) + { + if( KEY_LEFT == nKey ) nKey = KEY_RIGHT; + else if( KEY_RIGHT == nKey ) nKey = KEY_LEFT; + } + + aKeyEvent = KeyEvent( rKEvt.GetCharCode(), + KeyCode( nKey, rKEvt.GetKeyCode().GetModifier() ), + rKEvt.GetRepeat() ); + } + } + + const KeyCode& rKeyCode = aKeyEvent.GetKeyCode(); + sal_Unicode aCh = aKeyEvent.GetCharCode(); + + // enable switching to notes ankor with Ctrl - Alt - Page Up/Down + // pressing this inside a note will switch to next/previous note + if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((rKeyCode.GetCode() == KEY_PAGEUP) || (rKeyCode.GetCode() == KEY_PAGEDOWN))) + { + const bool bNext = rKeyCode.GetCode()==KEY_PAGEDOWN; + const SwFieldType* pFldType = rSh.GetFldType( 0, RES_POSTITFLD ); + rSh.MoveFldType( pFldType, bNext ); + return; + } + + const SwFrmFmt* pFlyFmt = rSh.GetFlyFrmFmt(); + if( pFlyFmt ) + { + sal_uInt16 nEvent; + + if( 32 <= aCh && + 0 == (( KEY_MOD1 | KEY_MOD2 ) & rKeyCode.GetModifier() )) + nEvent = SW_EVENT_FRM_KEYINPUT_ALPHA; + else + nEvent = SW_EVENT_FRM_KEYINPUT_NOALPHA; + + const SvxMacro* pMacro = pFlyFmt->GetMacro().GetMacroTable().Get( nEvent ); + if( pMacro ) + { + SbxArrayRef xArgs = new SbxArray; + SbxVariableRef xVar = new SbxVariable; + xVar->PutString( pFlyFmt->GetName() ); + xArgs->Put( &xVar, 1 ); + + xVar = new SbxVariable; + if( SW_EVENT_FRM_KEYINPUT_ALPHA == nEvent ) + xVar->PutChar( aCh ); + else + xVar->PutUShort( rKeyCode.GetModifier() | rKeyCode.GetCode() ); + xArgs->Put( &xVar, 2 ); + + OUString sRet; + rSh.ExecMacro( *pMacro, &sRet, &xArgs ); + if( !sRet.isEmpty() && sRet.toInt32()!=0 ) + return ; + } + } + int nLclSelectionType; + //A is converted to 1 + if( rKeyCode.GetFullCode() == (KEY_A | KEY_MOD1 |KEY_SHIFT) + && rSh.HasDrawView() && + (0 != (nLclSelectionType = rSh.GetSelectionType()) && + ((nLclSelectionType & (nsSelectionType::SEL_FRM|nsSelectionType::SEL_GRF)) || + ((nLclSelectionType & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM)) && + rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1)))) + { + SdrHdlList& rHdlList = (SdrHdlList&)rSh.GetDrawView()->GetHdlList(); + SdrHdl* pAnchor = rHdlList.GetHdl(HDL_ANCHOR); + if ( ! pAnchor ) + pAnchor = rHdlList.GetHdl(HDL_ANCHOR_TR); + if(pAnchor) + rHdlList.SetFocusHdl(pAnchor); + return; + } + + SvxAutoCorrCfg* pACfg = 0; + SvxAutoCorrect* pACorr = 0; + + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_rView.GetViewFrame()->GetBindings().GetRecorder(); + if ( !xRecorder.is() ) + { + pACfg = &SvxAutoCorrCfg::Get(); + pACorr = pACfg->GetAutoCorrect(); + } + + SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + + TblChgWidthHeightType eTblChgMode = nsTblChgWidthHeightType::WH_COL_LEFT; // initialization just for warning-free code + sal_uInt16 nTblChgSize = 0; + bool bStopKeyInputTimer = true; + OUString sFmlEntry; + + enum SW_KeyState { KS_Start, + KS_CheckKey, KS_InsChar, KS_InsTab, + KS_NoNum, KS_NumOff, KS_NumOrNoNum, KS_NumDown, KS_NumUp, + KS_NumIndentInc, KS_NumIndentDec, + + KS_OutlineLvOff, + KS_NextCell, KS_PrevCell, KS_OutlineUp, KS_OutlineDown, + KS_GlossaryExpand, KS_NextPrevGlossary, + KS_AutoFmtByInput, + KS_NextObject, KS_PrevObject, + KS_KeyToView, + KS_LaunchOLEObject, KS_GoIntoFly, KS_GoIntoDrawing, + KS_EnterDrawHandleMode, + KS_CheckDocReadOnlyKeys, + KS_CheckAutoCorrect, KS_EditFormula, + KS_ColLeftBig, KS_ColRightBig, + KS_ColLeftSmall, KS_ColRightSmall, + KS_ColTopBig, KS_ColBottomBig, + KS_ColTopSmall, KS_ColBottomSmall, + KS_CellLeftBig, KS_CellRightBig, + KS_CellLeftSmall, KS_CellRightSmall, + KS_CellTopBig, KS_CellBottomBig, + KS_CellTopSmall, KS_CellBottomSmall, + + KS_InsDel_ColLeftBig, KS_InsDel_ColRightBig, + KS_InsDel_ColLeftSmall, KS_InsDel_ColRightSmall, + KS_InsDel_ColTopBig, KS_InsDel_ColBottomBig, + KS_InsDel_ColTopSmall, KS_InsDel_ColBottomSmall, + KS_InsDel_CellLeftBig, KS_InsDel_CellRightBig, + KS_InsDel_CellLeftSmall, KS_InsDel_CellRightSmall, + KS_InsDel_CellTopBig, KS_InsDel_CellBottomBig, + KS_InsDel_CellTopSmall, KS_InsDel_CellBottomSmall, + KS_TblColCellInsDel, + + KS_Fly_Change, KS_Draw_Change, + KS_SpecialInsert, + KS_EnterCharCell, + KS_GotoNextFieldMark, + KS_GotoPrevFieldMark, + KS_End }; + + SW_KeyState eKeyState = bIsDocReadOnly ? KS_CheckDocReadOnlyKeys : KS_CheckKey; + SW_KeyState eNextKeyState = KS_End; + sal_uInt8 nDir = 0; + + if (m_nKS_NUMDOWN_Count > 0) + m_nKS_NUMDOWN_Count--; + + if (m_nKS_NUMINDENTINC_Count > 0) + m_nKS_NUMINDENTINC_Count--; + + while( KS_End != eKeyState ) + { + SW_KeyState eFlyState = KS_KeyToView; + + switch( eKeyState ) + { + case KS_CheckKey: + eKeyState = KS_KeyToView; // default forward to View + +#if OSL_DEBUG_LEVEL > 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // for switching curor behaviour in ReadOnly regions + if( 0x7210 == rKeyCode.GetFullCode() ) + rSh.SetReadOnlyAvailable( !rSh.IsReadOnlyAvailable() ); + else +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#endif + + if( !rKeyCode.IsMod2() && '=' == aCh && + !rSh.IsTableMode() && rSh.GetTableFmt() && + rSh.IsSttPara() && + !rSh.HasReadonlySel() ) + { + // at the beginning of the table's cell a '=' -> + // call EditRow (F2-functionality) + rSh.Push(); + if( !rSh.MoveSection( fnSectionCurr, fnSectionStart) && + !rSh.IsTableBoxTextFormat() ) + { + // is at the beginning of the box + eKeyState = KS_EditFormula; + if( rSh.HasMark() ) + rSh.SwapPam(); + else + rSh.SttSelect(); + rSh.MoveSection( fnSectionCurr, fnSectionEnd ); + rSh.Pop( true ); + rSh.EndSelect(); + sFmlEntry = "="; + } + else + rSh.Pop( false ); + } + else + { + if( pACorr && aTmpQHD.HasCntnt() && !rSh.HasSelection() && + !rSh.HasReadonlySel() && !aTmpQHD.m_bIsAutoText && + pACorr->GetSwFlags().nAutoCmpltExpandKey == + (rKeyCode.GetModifier() | rKeyCode.GetCode()) ) + { + eKeyState = KS_GlossaryExpand; + break; + } + + switch( rKeyCode.GetModifier() | rKeyCode.GetCode() ) + { + case KEY_RIGHT | KEY_MOD2: + eKeyState = KS_ColRightBig; + eFlyState = KS_Fly_Change; + nDir = MOVE_RIGHT_SMALL; + goto KEYINPUT_CHECKTABLE; + + case KEY_LEFT | KEY_MOD2: + eKeyState = KS_ColRightSmall; + eFlyState = KS_Fly_Change; + nDir = MOVE_LEFT_SMALL; + goto KEYINPUT_CHECKTABLE; + + case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT: + eKeyState = KS_ColLeftSmall; + goto KEYINPUT_CHECKTABLE; + + case KEY_LEFT | KEY_MOD2 | KEY_SHIFT: + eKeyState = KS_ColLeftBig; + goto KEYINPUT_CHECKTABLE; + + case KEY_RIGHT | KEY_MOD2 | KEY_MOD1: + eKeyState = KS_CellRightBig; + goto KEYINPUT_CHECKTABLE; + + case KEY_LEFT | KEY_MOD2 | KEY_MOD1: + eKeyState = KS_CellRightSmall; + goto KEYINPUT_CHECKTABLE; + + case KEY_RIGHT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: + eKeyState = KS_CellLeftSmall; + goto KEYINPUT_CHECKTABLE; + + case KEY_LEFT | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: + eKeyState = KS_CellLeftBig; + goto KEYINPUT_CHECKTABLE; + + case KEY_UP | KEY_MOD2: + eKeyState = KS_ColBottomSmall; + eFlyState = KS_Fly_Change; + nDir = MOVE_UP_SMALL; + goto KEYINPUT_CHECKTABLE; + + case KEY_DOWN | KEY_MOD2: + eKeyState = KS_ColBottomBig; + eFlyState = KS_Fly_Change; + nDir = MOVE_DOWN_SMALL; + goto KEYINPUT_CHECKTABLE; + + case KEY_UP | KEY_MOD2 | KEY_MOD1: + eKeyState = KS_CellBottomSmall; + goto KEYINPUT_CHECKTABLE; + + case KEY_DOWN | KEY_MOD2 | KEY_MOD1: + eKeyState = KS_CellBottomBig; + goto KEYINPUT_CHECKTABLE; + + case KEY_UP | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: + eKeyState = KS_CellTopBig; + goto KEYINPUT_CHECKTABLE; + + case KEY_DOWN | KEY_MOD2 | KEY_SHIFT | KEY_MOD1: + eKeyState = KS_CellTopSmall; + goto KEYINPUT_CHECKTABLE; + +KEYINPUT_CHECKTABLE: + if( rSh.IsTableMode() || !rSh.GetTableFmt() ) + { + if(KS_KeyToView != eFlyState) + { + if(!pFlyFmt && KS_KeyToView != eFlyState && + (rSh.GetSelectionType() & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM)) && + rSh.GetDrawView()->AreObjectsMarked()) + eKeyState = KS_Draw_Change; + } + + if( pFlyFmt ) + eKeyState = eFlyState; + else if( KS_Draw_Change != eKeyState) + eKeyState = KS_EnterCharCell; + } + break; + + // huge object move + case KEY_RIGHT | KEY_SHIFT: + case KEY_LEFT | KEY_SHIFT: + case KEY_UP | KEY_SHIFT: + case KEY_DOWN | KEY_SHIFT: + { + const int nSelectionType = rSh.GetSelectionType(); + if ( ( pFlyFmt + && ( nSelectionType & (nsSelectionType::SEL_FRM|nsSelectionType::SEL_OLE|nsSelectionType::SEL_GRF) ) ) + || ( ( nSelectionType & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM) ) + && rSh.GetDrawView()->AreObjectsMarked() ) ) + { + eKeyState = pFlyFmt ? KS_Fly_Change : KS_Draw_Change; + switch ( rKeyCode.GetCode() ) + { + case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break; + case KEY_LEFT: nDir = MOVE_LEFT_HUGE; break; + case KEY_UP: nDir = MOVE_UP_HUGE; break; + case KEY_DOWN: nDir = MOVE_DOWN_HUGE; break; + } + } + break; + } + + case KEY_LEFT: + case KEY_LEFT | KEY_MOD1: + { + bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); + if(!bMod1) + { + eFlyState = KS_Fly_Change; + nDir = MOVE_LEFT_BIG; + } + eTblChgMode = nsTblChgWidthHeightType::WH_FLAG_INSDEL | + ( bMod1 + ? nsTblChgWidthHeightType::WH_CELL_LEFT + : nsTblChgWidthHeightType::WH_COL_LEFT ); + nTblChgSize = pModOpt->GetTblVInsert(); + } + goto KEYINPUT_CHECKTABLE_INSDEL; + case KEY_RIGHT | KEY_MOD1: + { + eTblChgMode = nsTblChgWidthHeightType::WH_FLAG_INSDEL | nsTblChgWidthHeightType::WH_CELL_RIGHT; + nTblChgSize = pModOpt->GetTblVInsert(); + } + goto KEYINPUT_CHECKTABLE_INSDEL; + case KEY_UP: + case KEY_UP | KEY_MOD1: + { + bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); + if(!bMod1) + { + eFlyState = KS_Fly_Change; + nDir = MOVE_UP_BIG; + } + eTblChgMode = nsTblChgWidthHeightType::WH_FLAG_INSDEL | + ( bMod1 + ? nsTblChgWidthHeightType::WH_CELL_TOP + : nsTblChgWidthHeightType::WH_ROW_TOP ); + nTblChgSize = pModOpt->GetTblHInsert(); + } + goto KEYINPUT_CHECKTABLE_INSDEL; + case KEY_DOWN: + case KEY_DOWN | KEY_MOD1: + { + bool bMod1 = 0 != (rKeyCode.GetModifier() & KEY_MOD1); + if(!bMod1) + { + eFlyState = KS_Fly_Change; + nDir = MOVE_DOWN_BIG; + } + eTblChgMode = nsTblChgWidthHeightType::WH_FLAG_INSDEL | + ( bMod1 + ? nsTblChgWidthHeightType::WH_CELL_BOTTOM + : nsTblChgWidthHeightType::WH_ROW_BOTTOM ); + nTblChgSize = pModOpt->GetTblHInsert(); + } + goto KEYINPUT_CHECKTABLE_INSDEL; + +KEYINPUT_CHECKTABLE_INSDEL: + if( rSh.IsTableMode() || !rSh.GetTableFmt() || + !m_bTblInsDelMode || + false /* table protected */ + ) + { + const int nSelectionType = rSh.GetSelectionType(); + + eKeyState = KS_KeyToView; + if(KS_KeyToView != eFlyState) + { + if((nSelectionType & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM)) && + rSh.GetDrawView()->AreObjectsMarked()) + eKeyState = KS_Draw_Change; + else if(nSelectionType & (nsSelectionType::SEL_FRM|nsSelectionType::SEL_OLE|nsSelectionType::SEL_GRF)) + eKeyState = KS_Fly_Change; + } + } + else + { + if( !m_bTblIsInsMode ) + eTblChgMode = eTblChgMode | nsTblChgWidthHeightType::WH_FLAG_BIGGER; + eKeyState = KS_TblColCellInsDel; + } + break; + + case KEY_DELETE: + if ( !rSh.HasReadonlySel() ) + { + if (rSh.IsInFrontOfLabel() && rSh.NumOrNoNum(false)) + eKeyState = KS_NumOrNoNum; + } + else + { + MessageDialog(this, "InfoReadonlyDialog", + "modules/swriter/ui/inforeadonlydialog.ui").Execute(); + eKeyState = KS_End; + } + break; + + case KEY_DELETE | KEY_MOD2: + if( !rSh.IsTableMode() && rSh.GetTableFmt() ) + { + eKeyState = KS_End; + m_bTblInsDelMode = true; + m_bTblIsInsMode = false; + m_aKeyInputTimer.Start(); + bStopKeyInputTimer = false; + } + break; + case KEY_INSERT | KEY_MOD2: + if( !rSh.IsTableMode() && rSh.GetTableFmt() ) + { + eKeyState = KS_End; + m_bTblInsDelMode = true; + m_bTblIsInsMode = true; + m_aKeyInputTimer.Start(); + bStopKeyInputTimer = false; + } + break; + + case KEY_RETURN: + { + if ( !rSh.HasReadonlySel() + && !rSh.CrsrInsideInputFld() ) + { + const int nSelectionType = rSh.GetSelectionType(); + if(nSelectionType & nsSelectionType::SEL_OLE) + eKeyState = KS_LaunchOLEObject; + else if(nSelectionType & nsSelectionType::SEL_FRM) + eKeyState = KS_GoIntoFly; + else if((nSelectionType & nsSelectionType::SEL_DRW) && + 0 == (nSelectionType & nsSelectionType::SEL_DRW_TXT) && + rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1) + eKeyState = KS_GoIntoDrawing; + else if( aTmpQHD.HasCntnt() && !rSh.HasSelection() && + aTmpQHD.m_bIsAutoText ) + eKeyState = KS_GlossaryExpand; + + //RETURN and empty paragraph in numbering -> end numbering + else if( m_aInBuffer.isEmpty() && + rSh.GetNumRuleAtCurrCrsrPos() && + !rSh.GetNumRuleAtCurrCrsrPos()->IsOutlineRule() && + !rSh.HasSelection() && + rSh.IsSttPara() && rSh.IsEndPara() ) + eKeyState = KS_NumOff, eNextKeyState = KS_OutlineLvOff; + + //RETURN for new paragraph with AutoFormating + else if( pACfg && pACfg->IsAutoFmtByInput() && + !(nSelectionType & (nsSelectionType::SEL_GRF | + nsSelectionType::SEL_OLE | nsSelectionType::SEL_FRM | + nsSelectionType::SEL_TBL_CELLS | nsSelectionType::SEL_DRW | + nsSelectionType::SEL_DRW_TXT)) ) + eKeyState = KS_CheckAutoCorrect, eNextKeyState = KS_AutoFmtByInput; + else + eNextKeyState = eKeyState, eKeyState = KS_CheckAutoCorrect; + } + } + break; + case KEY_RETURN | KEY_MOD2: + { + if ( !rSh.HasReadonlySel() + && !rSh.IsSttPara() + && rSh.GetNumRuleAtCurrCrsrPos() + && !rSh.CrsrInsideInputFld() ) + { + eKeyState = KS_NoNum; + } + else if( rSh.CanSpecialInsert() ) + eKeyState = KS_SpecialInsert; + } + break; + case KEY_BACKSPACE: + case KEY_BACKSPACE | KEY_SHIFT: + if ( !rSh.HasReadonlySel() + && !rSh.CrsrInsideInputFld() ) + { + bool bDone = false; + // try to add comment for code snip: + // Remove the paragraph indent, if the cursor is at the + // beginning of a paragraph, there is no selection + // and no numbering rule found at the current paragraph + // Also try to remove indent, if current paragraph + // has numbering rule, but isn't counted and only + // key <backspace> is hit. + const bool bOnlyBackspaceKey( KEY_BACKSPACE == rKeyCode.GetFullCode() ); + if ( rSh.IsSttPara() + && !rSh.HasSelection() + && ( rSh.GetNumRuleAtCurrCrsrPos() == NULL + || ( rSh.IsNoNum() && bOnlyBackspaceKey ) ) ) + { + bDone = rSh.TryRemoveIndent(); + } + + if (bDone) + eKeyState = KS_End; + else + { + if ( rSh.IsSttPara() && !rSh.IsNoNum() ) + { + if (m_nKS_NUMDOWN_Count > 0 && + 0 < rSh.GetNumLevel()) + { + eKeyState = KS_NumUp; + m_nKS_NUMDOWN_Count = 2; + bDone = true; + } + else if (m_nKS_NUMINDENTINC_Count > 0) + { + eKeyState = KS_NumIndentDec; + m_nKS_NUMINDENTINC_Count = 2; + bDone = true; + } + } + + // If the cursor is in an empty paragraph, which has + // a numbering, but not the outline numbering, and + // there is no selection, the numbering has to be + // deleted on key <Backspace>. + // Otherwise method <SwEditShell::NumOrNoNum(..)> + // should only change the <IsCounted()> state of + // the current paragraph depending of the key. + // On <backspace> it is set to <false>, + // on <shift-backspace> it is set to <true>. + // Thus, assure that method <SwEditShell::NumOrNum(..)> + // is only called for the intended purpose. + if ( !bDone && rSh.IsSttPara() ) + { + bool bCallNumOrNoNum( false ); + if ( bOnlyBackspaceKey && !rSh.IsNoNum() ) + { + bCallNumOrNoNum = true; + } + else if ( !bOnlyBackspaceKey && rSh.IsNoNum() ) + { + bCallNumOrNoNum = true; + } + else if ( bOnlyBackspaceKey + && rSh.IsSttPara() + && rSh.IsEndPara() + && !rSh.HasSelection() ) + { + const SwNumRule* pCurrNumRule( rSh.GetNumRuleAtCurrCrsrPos() ); + if ( pCurrNumRule != NULL + && pCurrNumRule != rSh.GetOutlineNumRule() ) + { + bCallNumOrNoNum = true; + } + } + if ( bCallNumOrNoNum + && rSh.NumOrNoNum( !bOnlyBackspaceKey, true ) ) + { + eKeyState = KS_NumOrNoNum; + } + } + } + } + else + { + MessageDialog(this, "InfoReadonlyDialog", + "modules/swriter/ui/inforeadonlydialog.ui").Execute(); + eKeyState = KS_End; + } + break; + + case KEY_RIGHT: + { + eFlyState = KS_Fly_Change; + nDir = MOVE_RIGHT_BIG; + eTblChgMode = nsTblChgWidthHeightType::WH_FLAG_INSDEL | nsTblChgWidthHeightType::WH_COL_RIGHT; + nTblChgSize = pModOpt->GetTblVInsert(); + goto KEYINPUT_CHECKTABLE_INSDEL; + } + case KEY_TAB: + { + + if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark() || rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) + { + eKeyState=KS_GotoNextFieldMark; + } + else if ( !rSh.IsMultiSelection() && rSh.CrsrInsideInputFld() ) + { + GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_NEXT_INPUTFLD ); + eKeyState = KS_End; + } + else if( rSh.GetNumRuleAtCurrCrsrPos() + && rSh.IsSttOfPara() + && !rSh.HasReadonlySel() ) + { + if ( !rSh.IsMultiSelection() + && rSh.IsFirstOfNumRuleAtCrsrPos() + && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) + eKeyState = KS_NumIndentInc; + else + eKeyState = KS_NumDown; + } + else if ( rSh.GetTableFmt() ) + { + if( rSh.HasSelection() || rSh.HasReadonlySel() ) + eKeyState = KS_NextCell; + else + eKeyState = KS_CheckAutoCorrect, eNextKeyState = KS_NextCell; + } + else if ( rSh.GetSelectionType() & + (nsSelectionType::SEL_GRF | + nsSelectionType::SEL_FRM | + nsSelectionType::SEL_OLE | + nsSelectionType::SEL_DRW | + nsSelectionType::SEL_DRW_FORM)) + + eKeyState = KS_NextObject; + else + { + eKeyState = KS_InsTab; + if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() ) + { + SwTxtFmtColl* pColl = rSh.GetCurTxtFmtColl(); + if( pColl && + + pColl->IsAssignedToListLevelOfOutlineStyle() + && MAXLEVEL-1 > pColl->GetAssignedOutlineStyleLevel() ) + eKeyState = KS_OutlineDown; + } + } + } + break; + case KEY_TAB | KEY_SHIFT: + { + if (rSh.IsFormProtected() || rSh.GetCurrentFieldmark()|| rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) + { + eKeyState=KS_GotoPrevFieldMark; + } + else if ( !rSh.IsMultiSelection() && rSh.CrsrInsideInputFld() ) + { + GetView().GetViewFrame()->GetDispatcher()->Execute( FN_GOTO_PREV_INPUTFLD ); + eKeyState = KS_End; + } + else if( rSh.GetNumRuleAtCurrCrsrPos() + && rSh.IsSttOfPara() + && !rSh.HasReadonlySel() ) + { + if ( !rSh.IsMultiSelection() + && rSh.IsFirstOfNumRuleAtCrsrPos() + && numfunc::ChangeIndentOnTabAtFirstPosOfFirstListItem() ) + eKeyState = KS_NumIndentDec; + else + eKeyState = KS_NumUp; + } + else if ( rSh.GetTableFmt() ) + { + if( rSh.HasSelection() || rSh.HasReadonlySel() ) + eKeyState = KS_PrevCell; + else + eKeyState = KS_CheckAutoCorrect, eNextKeyState = KS_PrevCell; + } + else if ( rSh.GetSelectionType() & + (nsSelectionType::SEL_GRF | + nsSelectionType::SEL_FRM | + nsSelectionType::SEL_OLE | + nsSelectionType::SEL_DRW | + nsSelectionType::SEL_DRW_FORM)) + + eKeyState = KS_PrevObject; + else + { + eKeyState = KS_End; + if( rSh.IsSttOfPara() && !rSh.HasReadonlySel() ) + { + SwTxtFmtColl* pColl = rSh.GetCurTxtFmtColl(); + if( pColl && + pColl->IsAssignedToListLevelOfOutlineStyle() && + 0 < pColl->GetAssignedOutlineStyleLevel()) + eKeyState = KS_OutlineUp; + } + } + } + break; + case KEY_TAB | KEY_MOD1: + case KEY_TAB | KEY_MOD2: + if( !rSh.HasReadonlySel() ) + { + if( aTmpQHD.HasCntnt() && !rSh.HasSelection() ) + { + // Next auto-complete suggestion + aTmpQHD.Next( pACorr && + pACorr->GetSwFlags().bAutoCmpltEndless ); + eKeyState = KS_NextPrevGlossary; + } + else if( rSh.GetTableFmt() ) + eKeyState = KS_InsTab; + else if((rSh.GetSelectionType() & + (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM| + nsSelectionType::SEL_FRM|nsSelectionType::SEL_OLE|nsSelectionType::SEL_GRF)) && + rSh.GetDrawView()->AreObjectsMarked()) + eKeyState = KS_EnterDrawHandleMode; + else + { + eKeyState = KS_InsTab; + } + } + break; + + case KEY_TAB | KEY_MOD1 | KEY_SHIFT: + { + if( aTmpQHD.HasCntnt() && !rSh.HasSelection() && + !rSh.HasReadonlySel() ) + { + // Previous auto-complete suggestion. + aTmpQHD.Previous( pACorr && + pACorr->GetSwFlags().bAutoCmpltEndless ); + eKeyState = KS_NextPrevGlossary; + } + else if((rSh.GetSelectionType() & (nsSelectionType::SEL_DRW|nsSelectionType::SEL_DRW_FORM| + nsSelectionType::SEL_FRM|nsSelectionType::SEL_OLE|nsSelectionType::SEL_GRF)) && + rSh.GetDrawView()->AreObjectsMarked()) + { + eKeyState = KS_EnterDrawHandleMode; + } + } + break; + case KEY_F2 : + if( !rSh.HasReadonlySel() ) + { + const int nSelectionType = rSh.GetSelectionType(); + if(nSelectionType & nsSelectionType::SEL_FRM) + eKeyState = KS_GoIntoFly; + else if((nSelectionType & nsSelectionType::SEL_DRW)) + eKeyState = KS_GoIntoDrawing; + } + break; + } + } + break; + case KS_CheckDocReadOnlyKeys: + { + eKeyState = KS_KeyToView; + switch( rKeyCode.GetModifier() | rKeyCode.GetCode() ) + { + case KEY_TAB: + case KEY_TAB | KEY_SHIFT: + bNormalChar = false; + eKeyState = KS_End; + if ( rSh.GetSelectionType() & + (nsSelectionType::SEL_GRF | + nsSelectionType::SEL_FRM | + nsSelectionType::SEL_OLE | + nsSelectionType::SEL_DRW | + nsSelectionType::SEL_DRW_FORM)) + + { + eKeyState = rKeyCode.GetModifier() & KEY_SHIFT ? + KS_PrevObject : KS_NextObject; + } + else if ( !rSh.IsMultiSelection() && rSh.CrsrInsideInputFld() ) + { + GetView().GetViewFrame()->GetDispatcher()->Execute( + KEY_SHIFT != rKeyCode.GetModifier() ? FN_GOTO_NEXT_INPUTFLD : FN_GOTO_PREV_INPUTFLD ); + } + else + { + rSh.SelectNextPrevHyperlink( KEY_SHIFT != rKeyCode.GetModifier() ); + } + break; + case KEY_RETURN: + { + const int nSelectionType = rSh.GetSelectionType(); + if(nSelectionType & nsSelectionType::SEL_FRM) + eKeyState = KS_GoIntoFly; + else + { + SfxItemSet aSet(rSh.GetAttrPool(), RES_TXTATR_INETFMT, RES_TXTATR_INETFMT); + rSh.GetCurAttr(aSet); + if(SFX_ITEM_SET == aSet.GetItemState(RES_TXTATR_INETFMT, false)) + { + const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT, true); + bNormalChar = false; + eKeyState = KS_End; + rSh.ClickToINetAttr((const SwFmtINetFmt&)rItem, URLLOAD_NOFILTER); + } + } + } + break; + } + } + break; + + case KS_EnterCharCell: + { + eKeyState = KS_KeyToView; + switch ( rKeyCode.GetModifier() | rKeyCode.GetCode() ) + { + case KEY_RIGHT | KEY_MOD2: + rSh.Right( CRSR_SKIP_CHARS, false, 1, false ); + eKeyState = KS_End; + FlushInBuffer(); + break; + case KEY_LEFT | KEY_MOD2: + rSh.Left( CRSR_SKIP_CHARS, false, 1, false ); + eKeyState = KS_End; + FlushInBuffer(); + break; + } + } + break; + + case KS_KeyToView: + { + eKeyState = KS_End; + bNormalChar = + !rKeyCode.IsMod2() && + rKeyCode.GetModifier() != (KEY_MOD1) && + rKeyCode.GetModifier() != (KEY_MOD1|KEY_SHIFT) && + SW_ISPRINTABLE( aCh ); + + if( bNormalChar && rSh.IsInFrontOfLabel() ) + { + rSh.NumOrNoNum(false); + } + + if( !m_aInBuffer.isEmpty() && ( !bNormalChar || bIsDocReadOnly )) + FlushInBuffer(); + + if( m_rView.KeyInput( aKeyEvent ) ) + bFlushBuffer = true, bNormalChar = false; + else + { + // Because Sfx accelerators are only called when they were + // enabled at the last status update, copy has to called + // 'forcefully' by us if necessary. + if( rKeyCode.GetFunction() == KEYFUNC_COPY ) + GetView().GetViewFrame()->GetBindings().Execute(SID_COPY); + + if( !bIsDocReadOnly && bNormalChar ) + { + const int nSelectionType = rSh.GetSelectionType(); + if((nSelectionType & nsSelectionType::SEL_DRW) && + 0 == (nSelectionType & nsSelectionType::SEL_DRW_TXT) && + rSh.GetDrawView()->GetMarkedObjectList().GetMarkCount() == 1) + { + SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + if(pObj) + { + EnterDrawTextMode(pObj->GetLogicRect().Center()); + if ( m_rView.GetCurShell()->ISA(SwDrawTextShell) ) + ((SwDrawTextShell*)m_rView.GetCurShell())->Init(); + rSh.GetDrawView()->KeyInput( rKEvt, this ); + } + } + else if(nSelectionType & nsSelectionType::SEL_FRM) + { + rSh.UnSelectFrm(); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + rSh.MoveSection( fnSectionCurr, fnSectionEnd ); + } + eKeyState = KS_InsChar; + } + else + { + bNormalChar = false; + Window::KeyInput( aKeyEvent ); + } + } + } + break; + case KS_LaunchOLEObject: + { + rSh.LaunchOLEObj(); + eKeyState = KS_End; + } + break; + case KS_GoIntoFly: + { + rSh.UnSelectFrm(); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + rSh.MoveSection( fnSectionCurr, fnSectionEnd ); + eKeyState = KS_End; + } + break; + case KS_GoIntoDrawing: + { + SdrObject* pObj = rSh.GetDrawView()->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj(); + if(pObj) + { + EnterDrawTextMode(pObj->GetLogicRect().Center()); + if ( m_rView.GetCurShell()->ISA(SwDrawTextShell) ) + ((SwDrawTextShell*)m_rView.GetCurShell())->Init(); + } + eKeyState = KS_End; + } + break; + case KS_EnterDrawHandleMode: + { + const SdrHdlList& rHdlList = rSh.GetDrawView()->GetHdlList(); + bool bForward(!aKeyEvent.GetKeyCode().IsShift()); + + ((SdrHdlList&)rHdlList).TravelFocusHdl(bForward); + eKeyState = KS_End; + } + break; + case KS_InsTab: + if( m_rView.ISA( SwWebView )) // no Tab for WebView + { + // then it should be passed along + Window::KeyInput( aKeyEvent ); + eKeyState = KS_End; + break; + } + aCh = '\t'; + // no break! + case KS_InsChar: + if (rSh.GetChar(false)==CH_TXT_ATR_FORMELEMENT) + { + ::sw::mark::ICheckboxFieldmark* pFieldmark = + dynamic_cast< ::sw::mark::ICheckboxFieldmark* > + (rSh.GetCurrentFieldmark()); + OSL_ENSURE(pFieldmark, + "Where is my FieldMark??"); + if(pFieldmark) + { + pFieldmark->SetChecked(!pFieldmark->IsChecked()); + OSL_ENSURE(pFieldmark->IsExpanded(), + "where is the otherpos?"); + if (pFieldmark->IsExpanded()) + { + rSh.CalcLayout(); + } + } + eKeyState = KS_End; + } + else if ( !rSh.HasReadonlySel() + || rSh.CrsrInsideInputFld() ) + { + const bool bIsNormalChar = + GetAppCharClass().isLetterNumeric( OUString( aCh ), 0 ); + if( bAppendSpace && bIsNormalChar && + (!m_aInBuffer.isEmpty() || !rSh.IsSttPara() || !rSh.IsEndPara() )) + { + // insert a blank ahead of the character. this ends up + // between the expanded text and the new "non-word-separator". + m_aInBuffer += " "; + } + + const bool bIsAutoCorrectChar = SvxAutoCorrect::IsAutoCorrectChar( aCh ); + const bool bRunNext = pACorr != NULL && pACorr->HasRunNext(); + if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || bRunNext ) && + pACfg->IsAutoFmtByInput() && + (( pACorr->IsAutoCorrFlag( ChgWeightUnderl ) && + ( '*' == aCh || '_' == aCh ) ) || + ( pACorr->IsAutoCorrFlag( ChgQuotes ) && ('\"' == aCh ))|| + ( pACorr->IsAutoCorrFlag( ChgSglQuotes ) && ( '\'' == aCh)))) + { + FlushInBuffer(); + rSh.AutoCorrect( *pACorr, aCh ); + if( '\"' != aCh && '\'' != aCh ) // only call when "*_"! + rSh.UpdateAttr(); + } + else if( !aKeyEvent.GetRepeat() && pACorr && ( bIsAutoCorrectChar || bRunNext ) && + pACfg->IsAutoFmtByInput() && + pACorr->IsAutoCorrFlag( CptlSttSntnc | CptlSttWrd | + ChgOrdinalNumber | AddNonBrkSpace | + ChgToEnEmDash | SetINetAttr | + Autocorrect ) && + '\"' != aCh && '\'' != aCh && '*' != aCh && '_' != aCh + ) + { + FlushInBuffer(); + rSh.AutoCorrect( *pACorr, aCh ); + } + else + { + OUStringBuffer aBuf(m_aInBuffer); + comphelper::string::padToLength(aBuf, + m_aInBuffer.getLength() + aKeyEvent.GetRepeat() + 1, aCh); + m_aInBuffer = aBuf.makeStringAndClear(); + bFlushCharBuffer = Application::AnyInput( VCL_INPUT_KEYBOARD ); + bFlushBuffer = !bFlushCharBuffer; + if( bFlushCharBuffer ) + m_aKeyInputFlushTimer.Start(); + } + eKeyState = KS_End; + } + else + { + MessageDialog(this, "InfoReadonlyDialog", + "modules/swriter/ui/inforeadonlydialog.ui").Execute(); + eKeyState = KS_End; + } + break; + + case KS_CheckAutoCorrect: + { + if( pACorr && pACfg->IsAutoFmtByInput() && + pACorr->IsAutoCorrFlag( CptlSttSntnc | CptlSttWrd | + ChgOrdinalNumber | + ChgToEnEmDash | SetINetAttr | + Autocorrect ) && + !rSh.HasReadonlySel() ) + { + FlushInBuffer(); + rSh.AutoCorrect( *pACorr, static_cast< sal_Unicode >('\0') ); + } + eKeyState = eNextKeyState; + } + break; + + default: + { + sal_uInt16 nSlotId = 0; + FlushInBuffer(); + switch( eKeyState ) + { + case KS_SpecialInsert: + rSh.DoSpecialInsert(); + break; + + case KS_NoNum: + rSh.NoNum(); + break; + + case KS_NumOff: + // shell change - so record in advance + rSh.DelNumRules(); + eKeyState = eNextKeyState; + break; + case KS_OutlineLvOff: // delete autofmt outlinelevel later + break; + + case KS_NumDown: + rSh.NumUpDown( true ); + m_nKS_NUMDOWN_Count = 2; + break; + case KS_NumUp: + rSh.NumUpDown( false ); + break; + + case KS_NumIndentInc: + rSh.ChangeIndentOfAllListLevels(360); + m_nKS_NUMINDENTINC_Count = 2; + break; + + case KS_GotoNextFieldMark: + { + ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkAfter(); + if(pFieldmark) rSh.GotoFieldmark(pFieldmark); + } + break; + + case KS_GotoPrevFieldMark: + { + ::sw::mark::IFieldmark const * const pFieldmark = rSh.GetFieldmarkBefore(); + if( pFieldmark ) + rSh.GotoFieldmark(pFieldmark); + } + break; + + case KS_NumIndentDec: + rSh.ChangeIndentOfAllListLevels(-360); + break; + + case KS_OutlineDown: + rSh.OutlineUpDown( 1 ); + break; + case KS_OutlineUp: + rSh.OutlineUpDown( -1 ); + break; + + case KS_NextCell: + // always 'flush' in tables + rSh.GoNextCell(); + nSlotId = FN_GOTO_NEXT_CELL; + break; + case KS_PrevCell: + rSh.GoPrevCell(); + nSlotId = FN_GOTO_PREV_CELL; + break; + case KS_AutoFmtByInput: + rSh.SplitNode( true ); + break; + + case KS_NextObject: + case KS_PrevObject: + if(rSh.GotoObj( KS_NextObject == eKeyState, GOTOOBJ_GOTO_ANY)) + { + if( rSh.IsFrmSelected() && + m_rView.GetDrawFuncPtr() ) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + } + rSh.HideCrsr(); + rSh.EnterSelFrmMode(); + } + break; + case KS_GlossaryExpand: + { + // replace the word or abbreviation with the auto text + rSh.StartUndo( UNDO_START ); + + OUString sFnd( aTmpQHD.m_aHelpStrings[ aTmpQHD.nCurArrPos ] ); + if( aTmpQHD.m_bIsAutoText ) + { + SwGlossaryList* pList = ::GetGlossaryList(); + OUString sShrtNm; + OUString sGroup; + if(pList->GetShortName( sFnd, sShrtNm, sGroup)) + { + rSh.SttSelect(); + rSh.ExtendSelection( false, aTmpQHD.nLen ); + SwGlossaryHdl* pGlosHdl = GetView().GetGlosHdl(); + pGlosHdl->SetCurGroup(sGroup, true); + pGlosHdl->InsertGlossary( sShrtNm); + m_pQuickHlpData->m_bAppendSpace = true; + } + } + else + { + sFnd = sFnd.copy( aTmpQHD.nLen ); + rSh.Insert( sFnd ); + m_pQuickHlpData->m_bAppendSpace = !pACorr || + pACorr->GetSwFlags().bAutoCmpltAppendBlanc; + } + rSh.EndUndo( UNDO_END ); + } + break; + + case KS_NextPrevGlossary: + m_pQuickHlpData->Move( aTmpQHD ); + m_pQuickHlpData->Start( rSh, USHRT_MAX ); + break; + + case KS_EditFormula: + { + const sal_uInt16 nId = SwInputChild::GetChildWindowId(); + + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + pVFrame->ToggleChildWindow( nId ); + SwInputChild* pChildWin = (SwInputChild*)pVFrame-> + GetChildWindow( nId ); + if( pChildWin ) + pChildWin->SetFormula( sFmlEntry ); + } + break; + + case KS_ColLeftBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_COL_LEFT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHMove() ); break; + case KS_ColRightBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_COL_RIGHT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHMove() ); break; + case KS_ColLeftSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_COL_LEFT, pModOpt->GetTblHMove() ); break; + case KS_ColRightSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_COL_RIGHT, pModOpt->GetTblHMove() ); break; + case KS_ColBottomBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_ROW_BOTTOM|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVMove() ); break; + case KS_ColBottomSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_ROW_BOTTOM, pModOpt->GetTblVMove() ); break; + case KS_CellLeftBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_LEFT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHMove() ); break; + case KS_CellRightBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_RIGHT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHMove() ); break; + case KS_CellLeftSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_LEFT, pModOpt->GetTblHMove() ); break; + case KS_CellRightSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_RIGHT, pModOpt->GetTblHMove() ); break; + case KS_CellTopBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_TOP|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVMove() ); break; + case KS_CellBottomBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_BOTTOM|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVMove() ); break; + case KS_CellTopSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_TOP, pModOpt->GetTblVMove() ); break; + case KS_CellBottomSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_CELL_BOTTOM, pModOpt->GetTblVMove() ); break; + + case KS_InsDel_ColLeftBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_COL_LEFT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_ColRightBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_COL_RIGHT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_ColLeftSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_COL_LEFT, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_ColRightSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_COL_RIGHT, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_ColTopBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_ROW_TOP|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_ColBottomBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_ROW_BOTTOM|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_ColTopSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_ROW_TOP, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_ColBottomSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_ROW_BOTTOM, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_CellLeftBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_LEFT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_CellRightBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_RIGHT|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_CellLeftSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_LEFT, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_CellRightSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_RIGHT, pModOpt->GetTblHInsert() ); break; + case KS_InsDel_CellTopBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_TOP|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_CellBottomBig: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_BOTTOM|nsTblChgWidthHeightType::WH_FLAG_BIGGER, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_CellTopSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_TOP, pModOpt->GetTblVInsert() ); break; + case KS_InsDel_CellBottomSmall: rSh.SetColRowWidthHeight( nsTblChgWidthHeightType::WH_FLAG_INSDEL|nsTblChgWidthHeightType::WH_CELL_BOTTOM, pModOpt->GetTblVInsert() ); break; + + case KS_TblColCellInsDel: + rSh.SetColRowWidthHeight( eTblChgMode, nTblChgSize ); + break; + case KS_Fly_Change: + { + SdrView *pSdrView = rSh.GetDrawView(); + const SdrHdlList& rHdlList = pSdrView->GetHdlList(); + if(rHdlList.GetFocusHdl()) + ChangeDrawing( nDir ); + else + ChangeFly( nDir, m_rView.ISA( SwWebView ) ); + } + break; + case KS_Draw_Change : + ChangeDrawing( nDir ); + break; + default: + break; + } + if( nSlotId && m_rView.GetViewFrame()->GetBindings().GetRecorder().is() ) + { + SfxRequest aReq(m_rView.GetViewFrame(), nSlotId ); + aReq.Done(); + } + eKeyState = KS_End; + } + } + } + + if( bStopKeyInputTimer ) + { + m_aKeyInputTimer.Stop(); + m_bTblInsDelMode = false; + } + + // in case the buffered characters are inserted + if( bFlushBuffer && !m_aInBuffer.isEmpty() ) + { + // bFlushCharBuffer was not resetted here + // why not? + bool bSave = bFlushCharBuffer; + FlushInBuffer(); + bFlushCharBuffer = bSave; + + // maybe show Tip-Help + OUString sWord; + if( bNormalChar && pACfg && pACorr && + ( pACfg->IsAutoTextTip() || + pACorr->GetSwFlags().bAutoCompleteWords ) && + rSh.GetPrevAutoCorrWord( *pACorr, sWord ) ) + { + ShowAutoTextCorrectQuickHelp(sWord, pACfg, pACorr); + } + } + + // get the word count dialog to update itself + SwWordCountWrapper *pWrdCnt = (SwWordCountWrapper*)GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()); + if( pWrdCnt ) + pWrdCnt->UpdateCounts(); + +} + +/** + * MouseEvents + */ +void SwEditWin::RstMBDownFlags() +{ + // Not on all systems a MouseButtonUp is used ahead + // of the modal dialog (like on WINDOWS). + // So reset the statuses here and release the mouse + // for the dialog. + m_bMBPressed = false; + bNoInterrupt = false; + EnterArea(); + ReleaseMouse(); +} + +/** + * Determines if the current position has a clickable url over a background + * frame. In that case, ctrl-click should select the url, not the frame. + */ +static bool lcl_urlOverBackground(SwWrtShell& rSh, const Point& rDocPos) +{ + SwContentAtPos aSwContentAtPos(SwContentAtPos::SW_INETATTR); + SdrObject* pSelectableObj = rSh.GetObjAt(rDocPos); + + return rSh.GetContentAtPos(rDocPos, aSwContentAtPos) && pSelectableObj->GetLayer() == rSh.GetDoc()->GetHellId(); +} + +#if !HAVE_FEATURE_DESKTOP + +// As such these two functions could be more or less anywhere, I have +// them now in this source file because the act of moving a selection +// end point is somewhat the same as what happens when one +// shift-clicks on either side of an existing selection. + +void touch_lo_selection_start_move_impl(const void *documentHandle, + int x, + int y) +{ + SwWrtShell *pWrtShell = reinterpret_cast<SwWrtShell*>(const_cast<void*>(documentHandle)); + + if (!pWrtShell) + return; + + const OutputDevice *pOut = pWrtShell->GetWin(); + if (!pOut) + pOut = pWrtShell->GetOut(); + + const Point aDocPos( pOut->PixelToLogic( Point(x, y) ) ); + + // Don't allow moving the start of the selection beyond the end + // (point) of the selection. + + SwRect startCharRect; + pWrtShell->GetCharRectAt(startCharRect, pWrtShell->GetCrsr()->GetPoint()); + const Point startCharPos = startCharRect.Center(); + + if (startCharPos.Y() < aDocPos.Y() || + (startCharPos.Y() == aDocPos.Y() && startCharPos.X() - startCharRect.Width() <= aDocPos.X())) + return; + + pWrtShell->ChgCurrPam( aDocPos ); + + // Keep mark normally at the start and point at the end, + // just exchange for the duration of moving the start. + pWrtShell->GetCrsr()->Exchange(); + { + SwMvContext aMvContext( pWrtShell ); + pWrtShell->SwCrsrShell::SetCrsr( aDocPos ); + } + pWrtShell->GetCrsr()->Exchange(); +} + +void touch_lo_selection_end_move_impl(const void *documentHandle, + int x, + int y) +{ + SwWrtShell *pWrtShell = reinterpret_cast<SwWrtShell*>(const_cast<void*>(documentHandle)); + + if (!pWrtShell) + return; + + const OutputDevice *pOut = pWrtShell->GetWin(); + if (!pOut) + pOut = pWrtShell->GetOut(); + + const Point aDocPos( pOut->PixelToLogic( Point(x, y) ) ); + + // Don't allow moving the end of the selection beyond the start + // (mark) of the selection. + + SwRect endCharRect; + pWrtShell->GetCharRectAt(endCharRect, pWrtShell->GetCrsr()->GetMark()); + const Point endCharPos = endCharRect.Center(); + + if (endCharPos.Y() > aDocPos.Y() || + (endCharPos.Y() == aDocPos.Y() && endCharPos.X() + endCharRect.Width() >= aDocPos.X())) + return; + + pWrtShell->ChgCurrPam( aDocPos ); + + { + SwMvContext aMvContext( pWrtShell ); + pWrtShell->SwCrsrShell::SetCrsr( aDocPos ); + } +} + +#endif + +void SwEditWin::MouseButtonDown(const MouseEvent& _rMEvt) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + // We have to check if a context menu is shown and we have an UI + // active inplace client. In that case we have to ignore the mouse + // button down event. Otherwise we would crash (context menu has been + // opened by inplace client and we would deactivate the inplace client, + // the contex menu is closed by VCL asynchronously which in the end + // would work on deleted objects or the context menu has no parent anymore) + SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient(); + bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() ); + + if ( bIsOleActive && PopupMenu::IsInExecute() ) + return; + + MouseEvent rMEvt(_rMEvt); + + if (m_rView.GetPostItMgr()->IsHit(rMEvt.GetPosPixel())) + return; + + m_rView.GetPostItMgr()->SetActiveSidebarWin(0); + + GrabFocus(); + + //ignore key modifiers for format paintbrush + { + bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard + && m_pApplyTempl->m_pFormatClipboard->HasContent(); + if( bExecFormatPaintbrush ) + rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(), + _rMEvt.GetMode(), _rMEvt.GetButtons() ); + } + + m_bWasShdwCrsr = 0 != m_pShadCrsr; + delete m_pShadCrsr, m_pShadCrsr = 0; + + const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) ); + + // How many clicks do we need to select a fly frame? + FrameControlType eControl; + bool bOverFly = false; + bool bPageAnchored = false; + bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored ); + + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly(); + if (bOverHeaderFooterFly && (!bIsDocReadOnly && rSh.GetCurFld())) + // We have a field here, that should have priority over header/footer fly. + bOverHeaderFooterFly = false; + + int nNbFlyClicks = 1; + // !bOverHeaderFooterFly doesn't mean we have a frame to select + if ( !bPageAnchored && ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) || + ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) ) + { + nNbFlyClicks = 2; + if ( _rMEvt.GetClicks( ) < nNbFlyClicks ) + return; + } + + // Are we clicking on a blank header/footer area? + if ( IsInHeaderFooter( aDocPos, eControl ) || bOverHeaderFooterFly ) + { + const SwPageFrm* pPageFrm = rSh.GetLayout()->GetPageAtPos( aDocPos ); + + // Is it active? + bool bActive = true; + const SwPageDesc* pDesc = pPageFrm->GetPageDesc(); + + const SwFrmFmt* pFmt = pDesc->GetLeftFmt(); + if ( pPageFrm->OnRightPage() ) + pFmt = pDesc->GetRightFmt(); + + if ( pFmt ) + { + if ( eControl == Header ) + bActive = pFmt->GetHeader().IsActive(); + else + bActive = pFmt->GetFooter().IsActive(); + } + + if ( !bActive ) + { + SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() ); + bool bWasInHeader = aPam.GetPoint( )->nNode.GetNode( ).FindHeaderStartNode( ) != NULL; + bool bWasInFooter = aPam.GetPoint( )->nNode.GetNode( ).FindFooterStartNode( ) != NULL; + + // Is the cursor in a part like similar to the one we clicked on? For example, + // if the cursor is in a header and we click on an empty header... don't change anything to + // keep consistent behaviour due to header edit mode (and the same for the footer as well). + + // Otherwise, we hide the header/footer control if a separator is shown, and vice versa. + if ( !( bWasInHeader && eControl == Header ) && + !( bWasInFooter && eControl == Footer ) ) + { + rSh.SetShowHeaderFooterSeparator( eControl, !rSh.IsShowHeaderFooterSeparator( eControl ) ); + } + + // Repaint everything + Invalidate(); + } + else + { + // Make sure we have the proper Header/Footer separators shown + // as these may be changed if clicking on an empty Header/Footer + rSh.SetShowHeaderFooterSeparator( Header, eControl == Header ); + rSh.SetShowHeaderFooterSeparator( Footer, eControl == Footer ); + + if ( !rSh.IsHeaderFooterEdit() ) + rSh.ToggleHeaderFooterEdit(); + + // Repaint everything + rSh.GetWin()->Invalidate(); + } + } + else + { + if ( rSh.IsHeaderFooterEdit( ) ) + rSh.ToggleHeaderFooterEdit( ); + else + { + // Make sure that the separators are hidden + rSh.SetShowHeaderFooterSeparator( Header, false ); + rSh.SetShowHeaderFooterSeparator( Footer, false ); + + // Repaint everything + // FIXME fdo#67358 for unknown reasons this causes painting + // problems when resizing table columns, so disable it +// rSh.GetWin()->Invalidate(); + } + } + + if ( IsChainMode() ) + { + SetChainMode( false ); + SwRect aDummy; + SwFlyFrmFmt *pFmt = (SwFlyFrmFmt*)rSh.GetFlyFrmFmt(); + if ( !rSh.Chainable( aDummy, *pFmt, aDocPos ) ) + rSh.Chain( *pFmt, aDocPos ); + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + return; + } + + // After GrabFocus a shell should be pushed. That should actually + // work but in practice ... + m_rView.SelectShellForDrop(); + + bool bCallBase = true; + + if( m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( rSh ); + m_pQuickHlpData->m_bAppendSpace = false; + + if( rSh.FinishOLEObj() ) + return; // end InPlace and the click doesn't count anymore + + SET_CURR_SHELL( &rSh ); + + SdrView *pSdrView = rSh.GetDrawView(); + if ( pSdrView ) + { + if (pSdrView->MouseButtonDown( rMEvt, this ) ) + { + rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); + return; // SdrView's event evaluated + } + } + + m_bIsInMove = false; + m_aStartPos = rMEvt.GetPosPixel(); + m_aRszMvHdlPt.X() = 0, m_aRszMvHdlPt.Y() = 0; + + sal_uInt8 nMouseTabCol = 0; + const bool bTmp = !rSh.IsDrawCreate() && !m_pApplyTempl && !rSh.IsInSelect() && + rMEvt.GetClicks() == 1 && MOUSE_LEFT == rMEvt.GetButtons(); + if ( bTmp && + 0 != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPos ) ) && + !rSh.IsObjSelectable( aDocPos ) ) + { + // Enhanced table selection + if ( SW_TABSEL_HORI <= nMouseTabCol && SW_TABCOLSEL_VERT >= nMouseTabCol ) + { + rSh.EnterStdMode(); + rSh.SelectTableRowCol( aDocPos ); + if( SW_TABSEL_HORI != nMouseTabCol && SW_TABSEL_HORI_RTL != nMouseTabCol) + { + m_pRowColumnSelectionStart = new Point( aDocPos ); + m_bIsRowDrag = SW_TABROWSEL_HORI == nMouseTabCol|| + SW_TABROWSEL_HORI_RTL == nMouseTabCol || + SW_TABCOLSEL_VERT == nMouseTabCol; + m_bMBPressed = true; + CaptureMouse(); + } + return; + } + + if ( !rSh.IsTableMode() ) + { + // comes from table columns out of the document. + if(SW_TABCOL_VERT == nMouseTabCol || SW_TABCOL_HORI == nMouseTabCol) + m_rView.SetTabColFromDoc( true ); + else + m_rView.SetTabRowFromDoc( true ); + + m_rView.SetTabColFromDocPos( aDocPos ); + m_rView.InvalidateRulerPos(); + SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); + rBind.Update(); + if ( RulerColumnDrag( rMEvt, + (SW_TABCOL_VERT == nMouseTabCol || SW_TABROW_HORI == nMouseTabCol)) ) + { + m_rView.SetTabColFromDoc( false ); + m_rView.SetTabRowFromDoc( false ); + m_rView.InvalidateRulerPos(); + rBind.Update(); + bCallBase = false; + } + else + { + return; + } + } + } + else if (bTmp && + rSh.IsNumLabel(aDocPos)) + { + SwTxtNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPos ); + m_rView.SetNumRuleNodeFromDoc( pNodeAtPos ); + m_rView.InvalidateRulerPos(); + SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); + rBind.Update(); + + if ( RulerMarginDrag( rMEvt, + rSh.IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPos ) ) ) + { + m_rView.SetNumRuleNodeFromDoc( NULL ); + m_rView.InvalidateRulerPos(); + rBind.Update(); + bCallBase = false; + } + else + { + // Make sure the pointer is set to 0, otherwise it may point to + // nowhere after deleting the corresponding text node. + m_rView.SetNumRuleNodeFromDoc( NULL ); + return; + } + } + + if ( rSh.IsInSelect() ) + rSh.EndSelect(); + + // query against LEFT because otherwise for example also a right + // click releases the selection. + if ( MOUSE_LEFT == rMEvt.GetButtons() ) + { + bool bOnlyText = false; + m_bMBPressed = true; + bNoInterrupt = true; + m_nKS_NUMDOWN_Count = 0; + + CaptureMouse(); + + // reset curor position if applicable + rSh.ResetCursorStack(); + + switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) + { + case MOUSE_LEFT: + case MOUSE_LEFT + KEY_SHIFT: + case MOUSE_LEFT + KEY_MOD2: + if( rSh.IsObjSelected() ) + { + SdrHdl* pHdl; + if( !bIsDocReadOnly && + !m_pAnchorMarker && + 0 != ( pHdl = pSdrView->PickHandle(aDocPos) ) && + ( pHdl->GetKind() == HDL_ANCHOR || + pHdl->GetKind() == HDL_ANCHOR_TR ) ) + { + // #i121463# Set selected during drag + pHdl->SetSelected(true); + m_pAnchorMarker = new SwAnchorMarker( pHdl ); + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + return; + } + } + if ( EnterDrawMode( rMEvt, aDocPos ) ) + { + bNoInterrupt = false; + return; + } + else if ( m_rView.GetDrawFuncPtr() && m_bInsFrm ) + { + StopInsFrm(); + rSh.Edit(); + } + + // Without SHIFT because otherwise Toggle doesn't work at selection + if (rMEvt.GetClicks() == 1) + { + if ( rSh.IsSelFrmMode()) + { + SdrHdl* pHdl = rSh.GetDrawView()->PickHandle(aDocPos); + bool bHitHandle = pHdl && pHdl->GetKind() != HDL_ANCHOR && + pHdl->GetKind() != HDL_ANCHOR_TR; + + if ((rSh.IsInsideSelectedObj(aDocPos) || bHitHandle) && + !(rMEvt.GetModifier() == KEY_SHIFT && !bHitHandle)) + { + rSh.EnterSelFrmMode( &aDocPos ); + if ( !m_pApplyTempl ) + { + // only if no position to size was hit. + if (!bHitHandle) + { + StartDDTimer(); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + } + bFrmDrag = true; + } + bNoInterrupt = false; + return; + } + } + } + } + + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK ); + if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) || + ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) ) + bExecHyperlinks = true; + } + + // Enhanced selection + sal_uInt8 nNumberOfClicks = static_cast< sal_uInt8 >(rMEvt.GetClicks() % 4); + if ( 0 == nNumberOfClicks && 0 < rMEvt.GetClicks() ) + nNumberOfClicks = 4; + + bool bExecDrawTextLink = false; + + switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) + { + case MOUSE_LEFT: + case MOUSE_LEFT + KEY_MOD1: + case MOUSE_LEFT + KEY_MOD2: + { + + bool bHandledFlyClick = false; + if ( nNumberOfClicks == nNbFlyClicks ) + { + bHandledFlyClick = true; + // only try to select frame, if pointer already was + // switched accordingly + if ( m_aActHitType != SDRHIT_NONE && !rSh.IsSelFrmMode() && + !GetView().GetViewFrame()->GetDispatcher()->IsLocked() && + !bExecDrawTextLink) + { + // Test if there is a draw object at that position and if it should be selected. + bool bShould = rSh.ShouldObjectBeSelected(aDocPos); + + if(bShould) + { + m_rView.NoRotate(); + rSh.HideCrsr(); + + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + bool bSelObj = rSh.SelectObj( aDocPos, + rMEvt.IsMod1() ? SW_ENTER_GROUP : 0); + if( bUnLockView ) + rSh.LockView( false ); + + if( bSelObj ) + { + // if the frame was deselected in the macro + // the cursor just has to be displayed again + if( FRMTYPE_NONE == rSh.GetSelFrmType() ) + rSh.ShowCrsr(); + else + { + if (rSh.IsFrmSelected() && m_rView.GetDrawFuncPtr()) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + } + + rSh.EnterSelFrmMode( &aDocPos ); + bFrmDrag = true; + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + } + return; + } + else + bOnlyText = rSh.IsObjSelectable( aDocPos ); + + if (!m_rView.GetDrawFuncPtr()) + rSh.ShowCrsr(); + } + else + bOnlyText = KEY_MOD1 != rMEvt.GetModifier(); + } + else if ( rSh.IsSelFrmMode() && + (m_aActHitType == SDRHIT_NONE || + !rSh.IsInsideSelectedObj( aDocPos ))) + { + m_rView.NoRotate(); + SdrHdl *pHdl; + if( !bIsDocReadOnly && !m_pAnchorMarker && 0 != + ( pHdl = pSdrView->PickHandle(aDocPos) ) && + ( pHdl->GetKind() == HDL_ANCHOR || + pHdl->GetKind() == HDL_ANCHOR_TR ) ) + { + m_pAnchorMarker = new SwAnchorMarker( pHdl ); + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + return; + } + else + { + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + sal_uInt8 nFlag = rMEvt.IsShift() ? SW_ADD_SELECT :0; + if( rMEvt.IsMod1() ) + nFlag = nFlag | SW_ENTER_GROUP; + + if ( rSh.IsSelFrmMode() ) + { + rSh.UnSelectFrm(); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + } + + bool bSelObj = rSh.SelectObj( aDocPos, nFlag ); + if( bUnLockView ) + rSh.LockView( false ); + + if( !bSelObj ) + { + // move cursor here so that it is not drawn in the + // frame first; ShowCrsr() happens in LeaveSelFrmMode() + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPos, false)); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify( &rSh ); + bCallBase = false; + } + else + { + rSh.HideCrsr(); + rSh.EnterSelFrmMode( &aDocPos ); + rSh.SelFlyGrabCrsr(); + rSh.MakeSelVisible(); + bFrmDrag = true; + if( rSh.IsFrmSelected() && + m_rView.GetDrawFuncPtr() ) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + } + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + return; + } + } + } + } + + switch ( nNumberOfClicks ) + { + case 1: + { + UpdatePointer( aDocPos, rMEvt.GetModifier() ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + + // hit an URL in DrawText object? + if (bExecHyperlinks && pSdrView) + { + SdrViewEvent aVEvt; + pSdrView->PickAnything(rMEvt, SDRMOUSEBUTTONDOWN, aVEvt); + + if (aVEvt.eEvent == SDREVENT_EXECUTEURL) + bExecDrawTextLink = true; + } + break; + } + case 2: + { + bFrmDrag = false; + if ( !bHandledFlyClick && !bIsDocReadOnly && rSh.IsInsideSelectedObj(aDocPos) && + 0 == rSh.IsSelObjProtected( FLYPROTECT_CONTENT|FLYPROTECT_PARENT ) ) + { + /* This is no good: on the one hand GetSelectionType is used as flag field + * (take a look into the GetSelectionType method) and on the other hand the + * return value is used in a switch without proper masking (very nice), this must lead to trouble + */ + switch ( rSh.GetSelectionType() &~ ( nsSelectionType::SEL_FONTWORK | nsSelectionType::SEL_EXTRUDED_CUSTOMSHAPE ) ) + { + case nsSelectionType::SEL_GRF: + RstMBDownFlags(); + GetView().GetViewFrame()->GetBindings().Execute( + FN_FORMAT_GRAFIC_DLG, 0, 0, + SFX_CALLMODE_RECORD|SFX_CALLMODE_SLOT); + return; + + // double click on OLE object --> OLE-InPlace + case nsSelectionType::SEL_OLE: + if (!rSh.IsSelObjProtected(FLYPROTECT_CONTENT)) + { + RstMBDownFlags(); + rSh.LaunchOLEObj(); + } + return; + + case nsSelectionType::SEL_FRM: + RstMBDownFlags(); + GetView().GetViewFrame()->GetBindings().Execute( + FN_FORMAT_FRAME_DLG, 0, 0, SFX_CALLMODE_RECORD|SFX_CALLMODE_SLOT); + return; + + case nsSelectionType::SEL_DRW: + RstMBDownFlags(); + EnterDrawTextMode(aDocPos); + if ( m_rView.GetCurShell()->ISA(SwDrawTextShell) ) + ((SwDrawTextShell*)m_rView.GetCurShell())->Init(); + return; + } + } + + // if the cursor position was corrected or if a Fly + // was selected in ReadOnlyMode, no word selection. + if ( !bValidCrsrPos || rSh.IsFrmSelected() ) + return; + + SwField *pFld; + bool bFtn = false; + + if( !bIsDocReadOnly && + ( 0 != ( pFld = rSh.GetCurFld() ) || + ( bFtn = rSh.GetCurFtn() ) ) ) + { + RstMBDownFlags(); + if( bFtn ) + GetView().GetViewFrame()->GetBindings().Execute( FN_EDIT_FOOTNOTE ); + else + { + sal_uInt16 nTypeId = pFld->GetTypeId(); + SfxViewFrame* pVFrame = GetView().GetViewFrame(); + switch( nTypeId ) + { + case TYP_POSTITFLD: + case TYP_SCRIPTFLD: + { + // if it's a Readonly region, status has to be enabled + sal_uInt16 nSlot = TYP_POSTITFLD == nTypeId ? FN_POSTIT : FN_JAVAEDIT; + SfxBoolItem aItem(nSlot, true); + pVFrame->GetBindings().SetState(aItem); + pVFrame->GetBindings().Execute(nSlot); + break; + } + case TYP_AUTHORITY : + pVFrame->GetBindings().Execute(FN_EDIT_AUTH_ENTRY_DLG); + break; + default: + pVFrame->GetBindings().Execute(FN_EDIT_FIELD); + } + } + return; + } + // in extended mode double and triple + // click has no effect. + if ( rSh.IsExtMode() || rSh.IsBlockMode() ) + return; + + // select work, AdditionalMode if applicable + if ( KEY_MOD1 == rMEvt.GetModifier() && !rSh.IsAddMode() ) + { + rSh.EnterAddMode(); + rSh.SelWrd( &aDocPos ); + rSh.LeaveAddMode(); + } + else + rSh.SelWrd( &aDocPos ); + bHoldSelection = true; + return; + } + case 3: + case 4: + { + bFrmDrag = false; + // in extended mode double and triple + // click has no effect. + if ( rSh.IsExtMode() ) + return; + + // if the cursor position was corrected or if a Fly + // was selected in ReadOnlyMode, no word selection. + if ( !bValidCrsrPos || rSh.IsFrmSelected() ) + return; + + // select line, AdditionalMode if applicable + const bool bMod = KEY_MOD1 == rMEvt.GetModifier() && + !rSh.IsAddMode(); + + if ( bMod ) + rSh.EnterAddMode(); + + // Enhanced selection + if ( 3 == nNumberOfClicks ) + rSh.SelSentence( &aDocPos ); + else + rSh.SelPara( &aDocPos ); + + if ( bMod ) + rSh.LeaveAddMode(); + + bHoldSelection = true; + return; + } + + default: + return; + } + } + /* no break */ + case MOUSE_LEFT + KEY_SHIFT: + case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: + { + bool bLockView = m_bWasShdwCrsr; + + switch ( rMEvt.GetModifier() ) + { + case KEY_MOD1 + KEY_SHIFT: + { + if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) ) + { + m_rView.NoRotate(); + rSh.HideCrsr(); + if ( rSh.IsSelFrmMode() ) + rSh.SelectObj(aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP); + else + { if ( rSh.SelectObj( aDocPos, SW_ADD_SELECT | SW_ENTER_GROUP ) ) + { + rSh.EnterSelFrmMode( &aDocPos ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + bFrmDrag = true; + return; + } + } + } + else if( rSh.IsSelFrmMode() && + rSh.GetDrawView()->PickHandle( aDocPos )) + { + bFrmDrag = true; + bNoInterrupt = false; + return; + } + } + break; + case KEY_MOD1: + if ( !bExecDrawTextLink ) + { + if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) && !lcl_urlOverBackground( rSh, aDocPos ) ) + { + m_rView.NoRotate(); + rSh.HideCrsr(); + if ( rSh.IsSelFrmMode() ) + rSh.SelectObj(aDocPos, SW_ENTER_GROUP); + else + { if ( rSh.SelectObj( aDocPos, SW_ENTER_GROUP ) ) + { + rSh.EnterSelFrmMode( &aDocPos ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + bFrmDrag = true; + return; + } + } + } + else if( rSh.IsSelFrmMode() && + rSh.GetDrawView()->PickHandle( aDocPos )) + { + bFrmDrag = true; + bNoInterrupt = false; + return; + } + else + { + if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() ) + { + rSh.PushMode(); + bModePushed = true; + + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + rSh.EnterAddMode(); + if( bUnLockView ) + rSh.LockView( false ); + } + bCallBase = false; + } + } + break; + case KEY_MOD2: + { + if ( !rSh.IsAddMode() && !rSh.IsExtMode() && !rSh.IsBlockMode() ) + { + rSh.PushMode(); + bModePushed = true; + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + rSh.EnterBlockMode(); + if( bUnLockView ) + rSh.LockView( false ); + } + bCallBase = false; + } + break; + case KEY_SHIFT: + { + if ( !m_bInsDraw && IsDrawObjSelectable( rSh, aDocPos ) ) + { + m_rView.NoRotate(); + rSh.HideCrsr(); + if ( rSh.IsSelFrmMode() ) + { + rSh.SelectObj(aDocPos, SW_ADD_SELECT); + + const SdrMarkList& rMarkList = pSdrView->GetMarkedObjectList(); + if (rMarkList.GetMark(0) == NULL) + { + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + bFrmDrag = false; + } + } + else + { if ( rSh.SelectObj( aDocPos ) ) + { + rSh.EnterSelFrmMode( &aDocPos ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + bFrmDrag = true; + return; + } + } + } + else + { + if ( rSh.IsSelFrmMode() && + rSh.IsInsideSelectedObj( aDocPos ) ) + { + rSh.EnterSelFrmMode( &aDocPos ); + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + bFrmDrag = true; + return; + } + if ( rSh.IsSelFrmMode() ) + { + rSh.UnSelectFrm(); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + bFrmDrag = false; + } + if ( !rSh.IsExtMode() ) + { + // don't start a selection when an + // URL field or a graphic is clicked + bool bSttSelect = rSh.HasSelection() || + Pointer(POINTER_REFHAND) != GetPointer(); + + if( !bSttSelect ) + { + bSttSelect = true; + if( bExecHyperlinks ) + { + SwContentAtPos aCntntAtPos( + SwContentAtPos::SW_FTN | + SwContentAtPos::SW_INETATTR ); + + if( rSh.GetContentAtPos( aDocPos, aCntntAtPos ) ) + { + if( !rSh.IsViewLocked() && + !rSh.IsReadOnlyAvailable() && + aCntntAtPos.IsInProtectSect() ) + bLockView = true; + + bSttSelect = false; + } + else if( rSh.IsURLGrfAtPos( aDocPos )) + bSttSelect = false; + } + } + + if( bSttSelect ) + rSh.SttSelect(); + } + } + bCallBase = false; + break; + } + default: + if( !rSh.IsViewLocked() ) + { + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_CLICKFIELD | + SwContentAtPos::SW_INETATTR ); + if( rSh.GetContentAtPos( aDocPos, aCntntAtPos, false ) && + !rSh.IsReadOnlyAvailable() && + aCntntAtPos.IsInProtectSect() ) + bLockView = true; + } + } + + if ( rSh.IsGCAttr() ) + { + rSh.GCAttr(); + rSh.ClearGCAttr(); + } + + SwContentAtPos aFieldAtPos(SwContentAtPos::SW_FIELD); + + // Are we clicking on a field? + if (rSh.GetContentAtPos(aDocPos, aFieldAtPos)) + { + bool bEditableField = (aFieldAtPos.pFndTxtAttr != NULL + && aFieldAtPos.pFndTxtAttr->Which() == RES_TXTATR_INPUTFIELD); + + if (!bEditableField) + { + rSh.SetCursor(&aDocPos, bOnlyText); + // Unfortunately the cursor may be on field + // position or on position after field depending on which + // half of the field was clicked on. + SwTxtAttr const*const pTxtFld(aFieldAtPos.pFndTxtAttr); + if (rSh.GetCurrentShellCursor().GetPoint()->nContent + .GetIndex() != *pTxtFld->GetStart()) + { + assert(rSh.GetCurrentShellCursor().GetPoint()->nContent + .GetIndex() == (*pTxtFld->GetStart() + 1)); + rSh.Left( CRSR_SKIP_CHARS, false, 1, false ); + } + // don't go into the !bOverSelect block below - it moves + // the cursor + break; + } + } + + bool bOverSelect = rSh.ChgCurrPam( aDocPos ), bOverURLGrf = false; + if( !bOverSelect ) + bOverURLGrf = bOverSelect = 0 != rSh.IsURLGrfAtPos( aDocPos ); + + if ( !bOverSelect ) + { + const bool bTmpNoInterrupt = bNoInterrupt; + bNoInterrupt = false; + + if( !rSh.IsViewLocked() && bLockView ) + rSh.LockView( true ); + else + bLockView = false; + + int nTmpSetCrsr = 0; + + { // only temporary generate Move-Kontext because otherwise + // the query to the content form doesn't work!!! + SwMvContext aMvContext( &rSh ); + nTmpSetCrsr = rSh.SetCursor(&aDocPos, bOnlyText); + bValidCrsrPos = !(CRSR_POSCHG & nTmpSetCrsr); + bCallBase = false; + } + + // notify the edit window that from now on we do not use the input language + if ( !(CRSR_POSOLD & nTmpSetCrsr) ) + SetUseInputLanguage( false ); + + if( bLockView ) + rSh.LockView( false ); + + bNoInterrupt = bTmpNoInterrupt; + } + if ( !bOverURLGrf && !bOnlyText ) + { + const int nSelType = rSh.GetSelectionType(); + // Check in general, if an object is selectable at given position. + // Thus, also text fly frames in background become selectable via Ctrl-Click. + if ( ( nSelType & nsSelectionType::SEL_OLE || + nSelType & nsSelectionType::SEL_GRF || + rSh.IsObjSelectable( aDocPos ) ) && !lcl_urlOverBackground( rSh, aDocPos ) ) + { + SwMvContext aMvContext( &rSh ); + if( !rSh.IsFrmSelected() ) + rSh.GotoNextFly(); + rSh.EnterSelFrmMode(); + bCallBase = false; + } + } + // don't reset here any longer so that, in case through MouseMove + // with pressed Ctrl key a multiple-selection should happen, + // the previous selection is not released in Drag. + break; + } + } + } + if (bCallBase) + Window::MouseButtonDown(rMEvt); +} + +void SwEditWin::MouseMove(const MouseEvent& _rMEvt) +{ + MouseEvent rMEvt(_rMEvt); + + //ignore key modifiers for format paintbrush + { + bool bExecFormatPaintbrush = m_pApplyTempl && m_pApplyTempl->m_pFormatClipboard + && m_pApplyTempl->m_pFormatClipboard->HasContent(); + if( bExecFormatPaintbrush ) + rMEvt = MouseEvent( _rMEvt.GetPosPixel(), _rMEvt.GetClicks(), + _rMEvt.GetMode(), _rMEvt.GetButtons() ); + } + + // as long as an action is running the MouseMove should be disconnected + // otherwise bug 40102 occurs + SwWrtShell &rSh = m_rView.GetWrtShell(); + if( rSh.ActionPend() ) + return ; + + if( m_pShadCrsr && 0 != (rMEvt.GetModifier() + rMEvt.GetButtons() ) ) + delete m_pShadCrsr, m_pShadCrsr = 0; + + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly(); + + SET_CURR_SHELL( &rSh ); + + //aPixPt == Point in Pixel, relative to ChildWin + //aDocPt == Point in Twips, document coordinates + const Point aPixPt( rMEvt.GetPosPixel() ); + const Point aDocPt( PixelToLogic( aPixPt ) ); + + if ( IsChainMode() ) + { + UpdatePointer( aDocPt, rMEvt.GetModifier() ); + return; + } + + SdrView *pSdrView = rSh.GetDrawView(); + + const SwCallMouseEvent aLastCallEvent( m_aSaveCallEvent ); + m_aSaveCallEvent.Clear(); + + if ( !bIsDocReadOnly && pSdrView && pSdrView->MouseMove(rMEvt,this) ) + { + SetPointer( POINTER_TEXT ); + return; // evaluate SdrView's event + } + + const Point aOldPt( rSh.VisArea().Pos() ); + const bool bInsWin = rSh.VisArea().IsInside( aDocPt ); + + if( m_pShadCrsr && !bInsWin ) + delete m_pShadCrsr, m_pShadCrsr = 0; + + if( bInsWin && m_pRowColumnSelectionStart ) + { + EnterArea(); + Point aPos( aDocPt ); + if( rSh.SelectTableRowCol( *m_pRowColumnSelectionStart, &aPos, m_bIsRowDrag )) + return; + } + + // position is necessary for OS/2 because obviously after a MB-Down + // a MB-Move is called immediately. + if( bDDTimerStarted ) + { + Point aDD( SwEditWin::m_nDDStartPosX, SwEditWin::m_nDDStartPosY ); + aDD = LogicToPixel( aDD ); + Rectangle aRect( aDD.X()-3, aDD.Y()-3, aDD.X()+3, aDD.Y()+3 ); + if ( !aRect.IsInside( aPixPt ) ) + StopDDTimer( &rSh, aDocPt ); + } + + if(m_rView.GetDrawFuncPtr()) + { + if( m_bInsDraw ) + { + m_rView.GetDrawFuncPtr()->MouseMove( rMEvt ); + if ( !bInsWin ) + { + Point aTmp( aDocPt ); + aTmp += rSh.VisArea().Pos() - aOldPt; + LeaveArea( aTmp ); + } + else + EnterArea(); + return; + } + else if(!rSh.IsFrmSelected() && !rSh.IsObjSelected()) + { + SfxBindings &rBnd = rSh.GetView().GetViewFrame()->GetBindings(); + Point aRelPos = rSh.GetRelativePagePosition(aDocPt); + if(aRelPos.X() >= 0) + { + FieldUnit eMetric = ::GetDfltMetric(0 != PTR_CAST(SwWebView, &GetView())); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + const SfxPointItem aTmp1( SID_ATTR_POSITION, aRelPos ); + rBnd.SetState( aTmp1 ); + } + else + { + rBnd.Invalidate(SID_ATTR_POSITION); + } + rBnd.Invalidate(SID_ATTR_SIZE); + const SfxStringItem aCell( SID_TABLE_CELL, OUString() ); + rBnd.SetState( aCell ); + } + } + + sal_uInt8 nMouseTabCol; + if( !bIsDocReadOnly && bInsWin && !m_pApplyTempl && !rSh.IsInSelect() ) + { + if ( SW_TABCOL_NONE != (nMouseTabCol = rSh.WhichMouseTabCol( aDocPt ) ) && + !rSh.IsObjSelectable( aDocPt ) ) + { + sal_uInt16 nPointer = USHRT_MAX; + bool bChkTblSel = false; + + switch ( nMouseTabCol ) + { + case SW_TABCOL_VERT : + case SW_TABROW_HORI : + nPointer = POINTER_VSIZEBAR; + bChkTblSel = true; + break; + case SW_TABROW_VERT : + case SW_TABCOL_HORI : + nPointer = POINTER_HSIZEBAR; + bChkTblSel = true; + break; + // Enhanced table selection + case SW_TABSEL_HORI : + nPointer = POINTER_TAB_SELECT_SE; + break; + case SW_TABSEL_HORI_RTL : + case SW_TABSEL_VERT : + nPointer = POINTER_TAB_SELECT_SW; + break; + case SW_TABCOLSEL_HORI : + case SW_TABROWSEL_VERT : + nPointer = POINTER_TAB_SELECT_S; + break; + case SW_TABROWSEL_HORI : + nPointer = POINTER_TAB_SELECT_E; + break; + case SW_TABROWSEL_HORI_RTL : + case SW_TABCOLSEL_VERT : + nPointer = POINTER_TAB_SELECT_W; + break; + } + + if ( USHRT_MAX != nPointer && + // i#35543 - Enhanced table selection is explicitly allowed in table mode + ( !bChkTblSel || !rSh.IsTableMode() ) ) + { + SetPointer( nPointer ); + } + + return; + } + else if (rSh.IsNumLabel(aDocPt, RULER_MOUSE_MARGINWIDTH)) + { + // i#42921 - consider vertical mode + SwTxtNode* pNodeAtPos = rSh.GetNumRuleNodeAtPos( aDocPt ); + const sal_uInt16 nPointer = + rSh.IsVerticalModeAtNdAndPos( *pNodeAtPos, aDocPt ) + ? POINTER_VSIZEBAR + : POINTER_HSIZEBAR; + SetPointer( nPointer ); + + return; + } + } + + bool bDelShadCrsr = true; + + switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) + { + case MOUSE_LEFT: + if( m_pAnchorMarker ) + { + // Now we need to refresh the SdrHdl pointer of m_pAnchorMarker. + // This looks a little bit tricky, but it solves the following + // problem: the m_pAnchorMarker contains a pointer to an SdrHdl, + // if the FindAnchorPos-call cause a scrolling of the visible + // area, it's possible that the SdrHdl will be destroyed and a + // new one will initialized at the original position(GetHdlPos). + // So the m_pAnchorMarker has to find the right SdrHdl, if it's + // the old one, it will find it with position aOld, if this one + // is destroyed, it will find a new one at position GetHdlPos(). + + const Point aOld = m_pAnchorMarker->GetPosForHitTest( *(rSh.GetOut()) ); + Point aNew = rSh.FindAnchorPos( aDocPt ); + SdrHdl* pHdl; + if( (0!=( pHdl = pSdrView->PickHandle( aOld ) )|| + 0 !=(pHdl = pSdrView->PickHandle( m_pAnchorMarker->GetHdlPos()) ) ) && + ( pHdl->GetKind() == HDL_ANCHOR || + pHdl->GetKind() == HDL_ANCHOR_TR ) ) + { + m_pAnchorMarker->ChgHdl( pHdl ); + if( aNew.X() || aNew.Y() ) + { + m_pAnchorMarker->SetPos( aNew ); + m_pAnchorMarker->SetLastPos( aDocPt ); + } + } + else + { + delete m_pAnchorMarker; + m_pAnchorMarker = NULL; + } + } + if ( m_bInsDraw ) + { + if ( !m_bMBPressed ) + break; + if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) ) + { + if ( !bInsWin ) + LeaveArea( aDocPt ); + else + EnterArea(); + if ( m_rView.GetDrawFuncPtr() ) + { + pSdrView->SetOrtho(false); + m_rView.GetDrawFuncPtr()->MouseMove( rMEvt ); + } + m_bIsInMove = true; + } + return; + } + + { + SwWordCountWrapper *pWrdCnt = (SwWordCountWrapper*)GetView().GetViewFrame()->GetChildWindow(SwWordCountWrapper::GetChildWindowId()); + if (pWrdCnt) + pWrdCnt->UpdateCounts(); + } + + case MOUSE_LEFT + KEY_SHIFT: + case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: + if ( !m_bMBPressed ) + break; + case MOUSE_LEFT + KEY_MOD1: + if ( bFrmDrag && rSh.IsSelFrmMode() ) + { + if( !m_bMBPressed ) + break; + + if ( m_bIsInMove || IsMinMove( m_aStartPos, aPixPt ) ) + { + // event processing for resizing + if( pSdrView->AreObjectsMarked() ) + { + const SwFrmFmt* pFlyFmt; + const SvxMacro* pMacro; + + const Point aSttPt( PixelToLogic( m_aStartPos ) ); + + // can we start? + if( HDL_USER == eSdrMoveHdl ) + { + SdrHdl* pHdl = pSdrView->PickHandle( aSttPt ); + eSdrMoveHdl = pHdl ? pHdl->GetKind() : HDL_MOVE; + } + + sal_uInt16 nEvent = HDL_MOVE == eSdrMoveHdl + ? SW_EVENT_FRM_MOVE + : SW_EVENT_FRM_RESIZE; + + if( 0 != ( pFlyFmt = rSh.GetFlyFrmFmt() ) && + 0 != ( pMacro = pFlyFmt->GetMacro().GetMacroTable(). + Get( nEvent )) && + // or notify only e.g. every 20 Twip? + m_aRszMvHdlPt != aDocPt ) + { + m_aRszMvHdlPt = aDocPt; + sal_uInt16 nPos = 0; + SbxArrayRef xArgs = new SbxArray; + SbxVariableRef xVar = new SbxVariable; + xVar->PutString( pFlyFmt->GetName() ); + xArgs->Put( &xVar, ++nPos ); + + if( SW_EVENT_FRM_RESIZE == nEvent ) + { + xVar = new SbxVariable; + xVar->PutUShort( static_cast< sal_uInt16 >(eSdrMoveHdl) ); + xArgs->Put( &xVar, ++nPos ); + } + + xVar = new SbxVariable; + xVar->PutLong( aDocPt.X() - aSttPt.X() ); + xArgs->Put( &xVar, ++nPos ); + xVar = new SbxVariable; + xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); + xArgs->Put( &xVar, ++nPos ); + + OUString sRet; + + ReleaseMouse(); + + rSh.ExecMacro( *pMacro, &sRet, &xArgs ); + + CaptureMouse(); + + if( !sRet.isEmpty() && sRet.toInt32()!=0 ) + return ; + } + } + // event processing for resizing + + if( bIsDocReadOnly ) + break; + + bool bIsSelectionGfx = rSh.GetSelectionType() & nsSelectionType::SEL_GRF; + bool bisResize = eSdrMoveHdl != HDL_MOVE; + + if ( rMEvt.IsShift() ) + { + pSdrView->SetAngleSnapEnabled(!bIsSelectionGfx); + if (bisResize) + pSdrView->SetOrtho(!bIsSelectionGfx); + else + pSdrView->SetOrtho(true); + } + else + { + pSdrView->SetAngleSnapEnabled(bIsSelectionGfx); + if (bisResize) + pSdrView->SetOrtho(bIsSelectionGfx); + else + pSdrView->SetOrtho(false); + } + + rSh.Drag( &aDocPt, rMEvt.IsShift() ); + m_bIsInMove = true; + } + else if( bIsDocReadOnly ) + break; + + if ( !bInsWin ) + { + Point aTmp( aDocPt ); + aTmp += rSh.VisArea().Pos() - aOldPt; + LeaveArea( aTmp ); + } + else if(m_bIsInMove) + EnterArea(); + return; + } + if ( !rSh.IsSelFrmMode() && !bDDINetAttr && + (IsMinMove( m_aStartPos,aPixPt ) || m_bIsInMove) && + (rSh.IsInSelect() || !rSh.ChgCurrPam( aDocPt )) ) + { + if ( pSdrView ) + { + if ( rMEvt.IsShift() ) + pSdrView->SetOrtho(true); + else + pSdrView->SetOrtho(false); + } + if ( !bInsWin ) + { + Point aTmp( aDocPt ); + aTmp += rSh.VisArea().Pos() - aOldPt; + LeaveArea( aTmp ); + } + else + { + if( !rMEvt.IsSynthetic() && + !(( MOUSE_LEFT + KEY_MOD1 == + rMEvt.GetModifier() + rMEvt.GetButtons() ) && + rSh.Is_FnDragEQBeginDrag() && !rSh.IsAddMode() )) + { + rSh.Drag( &aDocPt, false ); + + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPt, false)); + EnterArea(); + } + } + } + bDDINetAttr = false; + break; + case 0: + { + if ( m_pApplyTempl ) + { + UpdatePointer(aDocPt, 0); // maybe a frame has to be marked here + break; + } + // change ui if mouse is over SwPostItField + // TODO: do the same thing for redlines SW_REDLINE + SwRect aFldRect; + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_FIELD); + if( rSh.GetContentAtPos( aDocPt, aCntntAtPos, false, &aFldRect ) ) + { + const SwField* pFld = aCntntAtPos.aFnd.pFld; + if (pFld->Which()== RES_POSTITFLD) + { + m_rView.GetPostItMgr()->SetShadowState(reinterpret_cast<const SwPostItField*>(pFld),false); + } + else + m_rView.GetPostItMgr()->SetShadowState(0,false); + } + else + m_rView.GetPostItMgr()->SetShadowState(0,false); + } + // no break; + case KEY_SHIFT: + case KEY_MOD2: + case KEY_MOD1: + if ( !m_bInsDraw ) + { + bool bTstShdwCrsr = true; + + UpdatePointer( aDocPt, rMEvt.GetModifier() ); + + const SwFrmFmt* pFmt = 0; + const SwFmtINetFmt* pINet = 0; + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_INETATTR ); + if( rSh.GetContentAtPos( aDocPt, aCntntAtPos ) ) + pINet = (SwFmtINetFmt*)aCntntAtPos.aFnd.pAttr; + + const void* pTmp = pINet; + + if( pINet || + 0 != ( pTmp = pFmt = rSh.GetFmtFromAnyObj( aDocPt ))) + { + bTstShdwCrsr = false; + if( pTmp == pINet ) + m_aSaveCallEvent.Set( pINet ); + else + { + IMapObject* pIMapObj = pFmt->GetIMapObject( aDocPt ); + if( pIMapObj ) + m_aSaveCallEvent.Set( pFmt, pIMapObj ); + else + m_aSaveCallEvent.Set( EVENT_OBJECT_URLITEM, pFmt ); + } + + // should be be over a InternetField with an + // embedded macro? + if( m_aSaveCallEvent != aLastCallEvent ) + { + if( aLastCallEvent.HasEvent() ) + rSh.CallEvent( SFX_EVENT_MOUSEOUT_OBJECT, + aLastCallEvent, true ); + // 0 says that the object doesn't have any table + if( !rSh.CallEvent( SFX_EVENT_MOUSEOVER_OBJECT, + m_aSaveCallEvent )) + m_aSaveCallEvent.Clear(); + } + } + else if( aLastCallEvent.HasEvent() ) + { + // cursor was on an object + rSh.CallEvent( SFX_EVENT_MOUSEOUT_OBJECT, + aLastCallEvent, true ); + } + + if( bTstShdwCrsr && bInsWin && !bIsDocReadOnly && + !m_bInsFrm && + !rSh.GetViewOptions()->getBrowseMode() && + rSh.GetViewOptions()->IsShadowCursor() && + !(rMEvt.GetModifier() + rMEvt.GetButtons()) && + !rSh.HasSelection() && !GetConnectMetaFile() ) + { + SwRect aRect; + sal_Int16 eOrient; + SwFillMode eMode = (SwFillMode)rSh.GetViewOptions()->GetShdwCrsrFillMode(); + if( rSh.GetShadowCrsrPos( aDocPt, eMode, aRect, eOrient )) + { + if( !m_pShadCrsr ) + m_pShadCrsr = new SwShadowCursor( *this, + SwViewOption::GetDirectCursorColor() ); + if( text::HoriOrientation::RIGHT != eOrient && text::HoriOrientation::CENTER != eOrient ) + eOrient = text::HoriOrientation::LEFT; + m_pShadCrsr->SetPos( aRect.Pos(), aRect.Height(), static_cast< sal_uInt16 >(eOrient) ); + bDelShadCrsr = false; + } + } + } + break; + case MOUSE_LEFT + KEY_MOD2: + if( rSh.IsBlockMode() && !rMEvt.IsSynthetic() ) + { + rSh.Drag( &aDocPt, false ); + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPt, false)); + EnterArea(); + } + break; + } + + if( bDelShadCrsr && m_pShadCrsr ) + delete m_pShadCrsr, m_pShadCrsr = 0; + m_bWasShdwCrsr = false; +} + +/** + * Button Up + */ +void SwEditWin::MouseButtonUp(const MouseEvent& rMEvt) +{ + bool bCallBase = true; + + bool bCallShadowCrsr = m_bWasShdwCrsr; + m_bWasShdwCrsr = false; + if( m_pShadCrsr ) + delete m_pShadCrsr, m_pShadCrsr = 0; + + if( m_pRowColumnSelectionStart ) + DELETEZ( m_pRowColumnSelectionStart ); + + SdrHdlKind eOldSdrMoveHdl = eSdrMoveHdl; + eSdrMoveHdl = HDL_USER; // for MoveEvents - reset again + + // preventively reset + m_rView.SetTabColFromDoc( false ); + m_rView.SetNumRuleNodeFromDoc(NULL); + + SwWrtShell &rSh = m_rView.GetWrtShell(); + SET_CURR_SHELL( &rSh ); + SdrView *pSdrView = rSh.GetDrawView(); + if ( pSdrView ) + { + pSdrView->SetOrtho(false); + + if ( pSdrView->MouseButtonUp( rMEvt,this ) ) + { + rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); + return; // SdrView's event evaluated + } + } + // only process MouseButtonUp when the Down went to that windows as well. + if ( !m_bMBPressed ) + { + // Undo for the watering can is already in CommandHdl + // that's the way it should be! + + return; + } + + Point aDocPt( PixelToLogic( rMEvt.GetPosPixel() ) ); + + if ( bDDTimerStarted ) + { + StopDDTimer( &rSh, aDocPt ); + m_bMBPressed = false; + if ( rSh.IsSelFrmMode() ) + { + rSh.EndDrag( &aDocPt, false ); + bFrmDrag = false; + } + bNoInterrupt = false; + const Point aDocPos( PixelToLogic( rMEvt.GetPosPixel() ) ); + if ((PixelToLogic(m_aStartPos).Y() == (aDocPos.Y())) && (PixelToLogic(m_aStartPos).X() == (aDocPos.X())))//To make sure it was not moved + { + SdrObject* pObj; + SdrPageView* pPV; + if (pSdrView->PickObj(aDocPos, pSdrView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER )) + { + pSdrView->UnmarkAllObj(); + pSdrView->MarkObj(pObj,pPV,false,false); + } + } + ReleaseMouse(); + return; + } + + if( m_pAnchorMarker ) + { + if(m_pAnchorMarker->GetHdl()) + { + // #i121463# delete selected after drag + m_pAnchorMarker->GetHdl()->SetSelected(false); + } + + Point aPnt( m_pAnchorMarker->GetLastPos() ); + DELETEZ( m_pAnchorMarker ); + if( aPnt.X() || aPnt.Y() ) + rSh.FindAnchorPos( aPnt, true ); + } + if ( m_bInsDraw && m_rView.GetDrawFuncPtr() ) + { + if ( m_rView.GetDrawFuncPtr()->MouseButtonUp( rMEvt ) ) + { + if (m_rView.GetDrawFuncPtr()) // could have been destroyed in MouseButtonUp + { + m_rView.GetDrawFuncPtr()->Deactivate(); + + if (!m_rView.IsDrawMode()) + { + m_rView.SetDrawFuncPtr(NULL); + SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_ATTR_SIZE ); + rBind.Invalidate( SID_TABLE_CELL ); + } + } + + if ( rSh.IsObjSelected() ) + { + rSh.EnterSelFrmMode(); + if (!m_rView.GetDrawFuncPtr()) + StdDrawMode( OBJ_NONE, true ); + } + else if ( rSh.IsFrmSelected() ) + { + rSh.EnterSelFrmMode(); + StopInsFrm(); + } + else + { + const Point aDocPos( PixelToLogic( m_aStartPos ) ); + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPos, false)); + rSh.Edit(); + } + + m_rView.AttrChangedNotify( &rSh ); + } + else if (rMEvt.GetButtons() == MOUSE_RIGHT && rSh.IsDrawCreate()) + m_rView.GetDrawFuncPtr()->BreakCreate(); // abort drawing + + bNoInterrupt = false; + ReleaseMouse(); + return; + } + bool bPopMode = false; + switch ( rMEvt.GetModifier() + rMEvt.GetButtons() ) + { + case MOUSE_LEFT: + if ( m_bInsDraw && rSh.IsDrawCreate() ) + { + if ( m_rView.GetDrawFuncPtr() && m_rView.GetDrawFuncPtr()->MouseButtonUp(rMEvt) ) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.AttrChangedNotify( &rSh ); + if ( rSh.IsObjSelected() ) + rSh.EnterSelFrmMode(); + if ( m_rView.GetDrawFuncPtr() && m_bInsFrm ) + StopInsFrm(); + } + bCallBase = false; + break; + } + case MOUSE_LEFT + KEY_MOD1: + case MOUSE_LEFT + KEY_MOD2: + case MOUSE_LEFT + KEY_SHIFT + KEY_MOD1: + if ( bFrmDrag && rSh.IsSelFrmMode() ) + { + if ( rMEvt.IsMod1() ) // copy and don't move. + { + // abort drag, use internal Copy instead + Rectangle aRect; + rSh.GetDrawView()->TakeActionRect( aRect ); + if (!aRect.IsEmpty()) + { + rSh.BreakDrag(); + Point aEndPt, aSttPt; + if ( rSh.GetSelFrmType() & FRMTYPE_FLY_ATCNT ) + { + aEndPt = aRect.TopLeft(); + aSttPt = rSh.GetDrawView()->GetAllMarkedRect().TopLeft(); + } + else + { + aEndPt = aRect.Center(); + aSttPt = rSh.GetDrawView()->GetAllMarkedRect().Center(); + } + if ( aSttPt != aEndPt ) + { + rSh.StartUndo( UNDO_UI_DRAG_AND_COPY ); + rSh.Copy(&rSh, aSttPt, aEndPt, false); + rSh.EndUndo( UNDO_UI_DRAG_AND_COPY ); + } + } + else { + rSh.EndDrag( &aDocPt, false ); + } + } + else + { + { + const SwFrmFmt* pFlyFmt; + const SvxMacro* pMacro; + + sal_uInt16 nEvent = HDL_MOVE == eOldSdrMoveHdl + ? SW_EVENT_FRM_MOVE + : SW_EVENT_FRM_RESIZE; + + if( 0 != ( pFlyFmt = rSh.GetFlyFrmFmt() ) && + 0 != ( pMacro = pFlyFmt->GetMacro().GetMacroTable(). + Get( nEvent )) ) + { + const Point aSttPt( PixelToLogic( m_aStartPos ) ); + m_aRszMvHdlPt = aDocPt; + sal_uInt16 nPos = 0; + SbxArrayRef xArgs = new SbxArray; + SbxVariableRef xVar = new SbxVariable; + xVar->PutString( pFlyFmt->GetName() ); + xArgs->Put( &xVar, ++nPos ); + + if( SW_EVENT_FRM_RESIZE == nEvent ) + { + xVar = new SbxVariable; + xVar->PutUShort( static_cast< sal_uInt16 >(eOldSdrMoveHdl) ); + xArgs->Put( &xVar, ++nPos ); + } + + xVar = new SbxVariable; + xVar->PutLong( aDocPt.X() - aSttPt.X() ); + xArgs->Put( &xVar, ++nPos ); + xVar = new SbxVariable; + xVar->PutLong( aDocPt.Y() - aSttPt.Y() ); + xArgs->Put( &xVar, ++nPos ); + + xVar = new SbxVariable; + xVar->PutUShort( 1 ); + xArgs->Put( &xVar, ++nPos ); + + ReleaseMouse(); + + rSh.ExecMacro( *pMacro, 0, &xArgs ); + + CaptureMouse(); + } + } + rSh.EndDrag( &aDocPt, false ); + } + bFrmDrag = false; + bCallBase = false; + break; + } + bPopMode = true; + // no break + case MOUSE_LEFT + KEY_SHIFT: + if (rSh.IsSelFrmMode()) + { + + rSh.EndDrag( &aDocPt, false ); + bFrmDrag = false; + bCallBase = false; + break; + } + + if( bHoldSelection ) + { + // the EndDrag should be called in any case + bHoldSelection = false; + rSh.EndDrag( &aDocPt, false ); + } + else + { + SwContentAtPos aFieldAtPos ( SwContentAtPos::SW_FIELD ); + if ( !rSh.IsInSelect() && rSh.ChgCurrPam( aDocPt ) && !rSh.GetContentAtPos( aDocPt, aFieldAtPos ) ) + { + const bool bTmpNoInterrupt = bNoInterrupt; + bNoInterrupt = false; + { // create only temporary move context because otherwise + // the query to the content form doesn't work!!! + SwMvContext aMvContext( &rSh ); + const Point aDocPos( PixelToLogic( m_aStartPos ) ); + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPos, false)); + } + bNoInterrupt = bTmpNoInterrupt; + + } + else + { + bool bInSel = rSh.IsInSelect(); + rSh.EndDrag( &aDocPt, false ); + + // Internetfield? --> call link (load doc!!) + if( !bInSel ) + { + sal_uInt16 nFilter = URLLOAD_NOFILTER; + if( KEY_MOD1 == rMEvt.GetModifier() ) + nFilter |= URLLOAD_NEWVIEW; + + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + SvtSecurityOptions aSecOpts; + const bool bSecureOption = aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK ); + if ( ( bSecureOption && rMEvt.GetModifier() == KEY_MOD1 ) || + ( !bSecureOption && rMEvt.GetModifier() != KEY_MOD1 ) ) + bExecHyperlinks = true; + } + + const bool bExecSmarttags = rMEvt.GetModifier() == KEY_MOD1; + + if(m_pApplyTempl) + bExecHyperlinks = false; + + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_FIELD | + SwContentAtPos::SW_INETATTR | + SwContentAtPos::SW_SMARTTAG | SwContentAtPos::SW_FORMCTRL); + + if( rSh.GetContentAtPos( aDocPt, aCntntAtPos, false ) ) + { + // Do it again if we're not on a field/hyperlink to update the cursor accordingly + if ( SwContentAtPos::SW_FIELD != aCntntAtPos.eCntntAtPos + && SwContentAtPos::SW_INETATTR != aCntntAtPos.eCntntAtPos ) + rSh.GetContentAtPos( aDocPt, aCntntAtPos, true ); + + bool bViewLocked = rSh.IsViewLocked(); + if( !bViewLocked && !rSh.IsReadOnlyAvailable() && + aCntntAtPos.IsInProtectSect() ) + rSh.LockView( true ); + + ReleaseMouse(); + + if( SwContentAtPos::SW_FIELD == aCntntAtPos.eCntntAtPos ) + { + bool bAddMode(false); + // AdditionalMode if applicable + if (KEY_MOD1 == rMEvt.GetModifier() + && !rSh.IsAddMode()) + { + bAddMode = true; + rSh.EnterAddMode(); + } + if ( aCntntAtPos.pFndTxtAttr != NULL + && aCntntAtPos.pFndTxtAttr->Which() == RES_TXTATR_INPUTFIELD ) + { + // select content of Input Field, but exclude CH_TXT_ATR_INPUTFIELDSTART + // and CH_TXT_ATR_INPUTFIELDEND + rSh.SttSelect(); + rSh.SelectTxt( *(aCntntAtPos.pFndTxtAttr->GetStart()) + 1, + *(aCntntAtPos.pFndTxtAttr->End()) - 1 ); + } + else + { + rSh.ClickToField( *aCntntAtPos.aFnd.pFld ); + } + // a bit of a mystery what this is good for? + // in this case we assume it's valid since we + // just selected a field + bValidCrsrPos = true; + if (bAddMode) + { + rSh.LeaveAddMode(); + } + } + else if ( SwContentAtPos::SW_SMARTTAG == aCntntAtPos.eCntntAtPos ) + { + // execute smarttag menu + if ( bExecSmarttags && SwSmartTagMgr::Get().IsSmartTagsEnabled() ) + m_rView.ExecSmartTagPopup( aDocPt ); + } + else if ( SwContentAtPos::SW_FORMCTRL == aCntntAtPos.eCntntAtPos ) + { + OSL_ENSURE( aCntntAtPos.aFnd.pFldmark != NULL, "where is my field ptr???"); + if ( aCntntAtPos.aFnd.pFldmark != NULL) + { + IFieldmark *fieldBM = const_cast< IFieldmark* > ( aCntntAtPos.aFnd.pFldmark ); + if ( fieldBM->GetFieldname( ) == ODF_FORMCHECKBOX ) + { + ICheckboxFieldmark* pCheckboxFm = dynamic_cast<ICheckboxFieldmark*>(fieldBM); + pCheckboxFm->SetChecked(!pCheckboxFm->IsChecked()); + pCheckboxFm->Invalidate(); + rSh.InvalidateWindows( m_rView.GetVisArea() ); + } else if ( fieldBM->GetFieldname() == ODF_FORMDROPDOWN ) { + m_rView.ExecFieldPopup( aDocPt, fieldBM ); + fieldBM->Invalidate(); + rSh.InvalidateWindows( m_rView.GetVisArea() ); + } else { + // unknown type.. + } + } + } + else if ( SwContentAtPos::SW_INETATTR == aCntntAtPos.eCntntAtPos ) + { + if ( bExecHyperlinks && aCntntAtPos.aFnd.pAttr ) + rSh.ClickToINetAttr( *(SwFmtINetFmt*)aCntntAtPos.aFnd.pAttr, nFilter ); + } + + rSh.LockView( bViewLocked ); + bCallShadowCrsr = false; + } + else + { + aCntntAtPos = SwContentAtPos( SwContentAtPos::SW_FTN ); + if( !rSh.GetContentAtPos( aDocPt, aCntntAtPos, true ) && bExecHyperlinks ) + { + SdrViewEvent aVEvt; + + if (pSdrView) + pSdrView->PickAnything(rMEvt, SDRMOUSEBUTTONDOWN, aVEvt); + + if (pSdrView && aVEvt.eEvent == SDREVENT_EXECUTEURL) + { + // hit URL field + const SvxURLField *pField = aVEvt.pURLField; + if (pField) + { + OUString sURL(pField->GetURL()); + OUString sTarget(pField->GetTargetFrame()); + ::LoadURL(rSh, sURL, nFilter, sTarget); + } + bCallShadowCrsr = false; + } + else + { + // hit graphic + ReleaseMouse(); + if( rSh.ClickToINetGrf( aDocPt, nFilter )) + bCallShadowCrsr = false; + } + } + } + + if( bCallShadowCrsr && + rSh.GetViewOptions()->IsShadowCursor() && + MOUSE_LEFT == (rMEvt.GetModifier() + rMEvt.GetButtons()) && + !rSh.HasSelection() && + !GetConnectMetaFile() && + rSh.VisArea().IsInside( aDocPt )) + { + SwUndoId nLastUndoId(UNDO_EMPTY); + if (rSh.GetLastUndoInfo(0, & nLastUndoId)) + { + if (UNDO_INS_FROM_SHADOWCRSR == nLastUndoId) + { + rSh.Undo(); + } + } + SwFillMode eMode = (SwFillMode)rSh.GetViewOptions()->GetShdwCrsrFillMode(); + rSh.SetShadowCrsrPos( aDocPt, eMode ); + } + } + } + bCallBase = false; + + } + + // reset pushed mode in Down again if applicable + if ( bPopMode && bModePushed ) + { + rSh.PopMode(); + bModePushed = false; + bCallBase = false; + } + break; + + default: + ReleaseMouse(); + return; + } + + if( m_pApplyTempl ) + { + int eSelection = rSh.GetSelectionType(); + SwFormatClipboard* pFormatClipboard = m_pApplyTempl->m_pFormatClipboard; + if( pFormatClipboard )//apply format paintbrush + { + //get some parameters + SwWrtShell& rWrtShell = m_rView.GetWrtShell(); + SfxStyleSheetBasePool* pPool=0; + bool bNoCharacterFormats = false; + bool bNoParagraphFormats = true; + { + SwDocShell* pDocSh = m_rView.GetDocShell(); + if(pDocSh) + pPool = pDocSh->GetStyleSheetPool(); + if( (rMEvt.GetModifier()&KEY_MOD1) && (rMEvt.GetModifier()&KEY_SHIFT) ) + { + bNoCharacterFormats = true; + bNoParagraphFormats = false; + } + else if( rMEvt.GetModifier() & KEY_MOD1 ) + bNoParagraphFormats = false; + } + //execute paste + pFormatClipboard->Paste( rWrtShell, pPool, bNoCharacterFormats, bNoParagraphFormats ); + + //if the clipboard is empty after paste remove the ApplyTemplate + if(!pFormatClipboard->HasContent()) + SetApplyTemplate(SwApplyTemplate()); + } + else if( m_pApplyTempl->nColor ) + { + sal_uInt16 nId = 0; + switch( m_pApplyTempl->nColor ) + { + case SID_ATTR_CHAR_COLOR_EXT: + case SID_ATTR_CHAR_COLOR2: + nId = RES_CHRATR_COLOR; + break; + case SID_ATTR_CHAR_COLOR_BACKGROUND_EXT: + case SID_ATTR_CHAR_COLOR_BACKGROUND: + nId = RES_CHRATR_BACKGROUND; + break; + } + if( nId && (nsSelectionType::SEL_TXT|nsSelectionType::SEL_TBL) & eSelection) + { + if( rSh.IsSelection() && !rSh.HasReadonlySel() ) + { + if(nId == RES_CHRATR_BACKGROUND) + rSh.SetAttrItem( SvxBrushItem( SwEditWin::m_aTextBackColor, nId ) ); + else + rSh.SetAttrItem( SvxColorItem( SwEditWin::m_aTextColor, nId ) ); + rSh.UnSetVisCrsr(); + rSh.EnterStdMode(); + rSh.SetVisCrsr(aDocPt); + + m_pApplyTempl->bUndo = true; + bCallBase = false; + m_aTemplateTimer.Stop(); + } + else if(rMEvt.GetClicks() == 1) + { + // no selection -> so turn off watering can + m_aTemplateTimer.Start(); + } + } + } + else + { + OUString aStyleName; + switch ( m_pApplyTempl->eType ) + { + case SFX_STYLE_FAMILY_PARA: + if( (( nsSelectionType::SEL_TXT | nsSelectionType::SEL_TBL ) + & eSelection ) && !rSh.HasReadonlySel() ) + { + rSh.SetTxtFmtColl( m_pApplyTempl->aColl.pTxtColl ); + m_pApplyTempl->bUndo = true; + bCallBase = false; + if ( m_pApplyTempl->aColl.pTxtColl ) + aStyleName = m_pApplyTempl->aColl.pTxtColl->GetName(); + } + break; + case SFX_STYLE_FAMILY_CHAR: + if( (( nsSelectionType::SEL_TXT | nsSelectionType::SEL_TBL ) + & eSelection ) && !rSh.HasReadonlySel() ) + { + rSh.SetAttrItem( SwFmtCharFmt(m_pApplyTempl->aColl.pCharFmt) ); + rSh.UnSetVisCrsr(); + rSh.EnterStdMode(); + rSh.SetVisCrsr(aDocPt); + m_pApplyTempl->bUndo = true; + bCallBase = false; + if ( m_pApplyTempl->aColl.pCharFmt ) + aStyleName = m_pApplyTempl->aColl.pCharFmt->GetName(); + } + break; + case SFX_STYLE_FAMILY_FRAME : + { + const SwFrmFmt* pFmt = rSh.GetFmtFromObj( aDocPt ); + if(PTR_CAST(SwFlyFrmFmt, pFmt)) + { + rSh.SetFrmFmt( m_pApplyTempl->aColl.pFrmFmt, false, &aDocPt ); + m_pApplyTempl->bUndo = true; + bCallBase = false; + if( m_pApplyTempl->aColl.pFrmFmt ) + aStyleName = m_pApplyTempl->aColl.pFrmFmt->GetName(); + } + break; + } + case SFX_STYLE_FAMILY_PAGE: + // no Undo with page templates + rSh.ChgCurPageDesc( *m_pApplyTempl->aColl.pPageDesc ); + if ( m_pApplyTempl->aColl.pPageDesc ) + aStyleName = m_pApplyTempl->aColl.pPageDesc->GetName(); + bCallBase = false; + break; + case SFX_STYLE_FAMILY_PSEUDO: + if( !rSh.HasReadonlySel() ) + { + rSh.SetCurNumRule( *m_pApplyTempl->aColl.pNumRule, + false, + m_pApplyTempl->aColl.pNumRule->GetDefaultListId() ); + bCallBase = false; + m_pApplyTempl->bUndo = true; + if( m_pApplyTempl->aColl.pNumRule ) + aStyleName = m_pApplyTempl->aColl.pNumRule->GetName(); + } + break; + } + + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_rView.GetViewFrame()->GetBindings().GetRecorder(); + if ( !aStyleName.isEmpty() && xRecorder.is() ) + { + SfxShell *pSfxShell = lcl_GetShellFromDispatcher( m_rView, TYPE(SwTextShell) ); + if ( pSfxShell ) + { + SfxRequest aReq( m_rView.GetViewFrame(), SID_STYLE_APPLY ); + aReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aStyleName ) ); + aReq.AppendItem( SfxUInt16Item( SID_STYLE_FAMILY, (sal_uInt16) m_pApplyTempl->eType ) ); + aReq.Done(); + } + } + } + + } + ReleaseMouse(); + // Only processed MouseEvents arrive here; only at these the moduses can + // be resetted. + m_bMBPressed = false; + + // Make this call just to be sure. Selecting has finished surely by now. + // Otherwise the timeout's timer could give problems. + EnterArea(); + bNoInterrupt = false; + + if (bCallBase) + Window::MouseButtonUp(rMEvt); +} + +/** + * Apply template + */ +void SwEditWin::SetApplyTemplate(const SwApplyTemplate &rTempl) +{ + static bool bIdle = false; + DELETEZ(m_pApplyTempl); + SwWrtShell &rSh = m_rView.GetWrtShell(); + + if(rTempl.m_pFormatClipboard) + { + m_pApplyTempl = new SwApplyTemplate( rTempl ); + SetPointer( POINTER_FILL );//@todo #i20119# maybe better a new brush pointer here in future + rSh.NoEdit( false ); + bIdle = rSh.GetViewOptions()->IsIdle(); + ((SwViewOption *)rSh.GetViewOptions())->SetIdle( false ); + } + else if(rTempl.nColor) + { + m_pApplyTempl = new SwApplyTemplate( rTempl ); + SetPointer( POINTER_FILL ); + rSh.NoEdit( false ); + bIdle = rSh.GetViewOptions()->IsIdle(); + ((SwViewOption *)rSh.GetViewOptions())->SetIdle( false ); + } + else if( rTempl.eType ) + { + m_pApplyTempl = new SwApplyTemplate( rTempl ); + SetPointer( POINTER_FILL ); + rSh.NoEdit( false ); + bIdle = rSh.GetViewOptions()->IsIdle(); + ((SwViewOption *)rSh.GetViewOptions())->SetIdle( false ); + } + else + { + SetPointer( POINTER_TEXT ); + rSh.UnSetVisCrsr(); + + ((SwViewOption *)rSh.GetViewOptions())->SetIdle( bIdle ); + if ( !rSh.IsSelFrmMode() ) + rSh.Edit(); + } + + static sal_uInt16 aInva[] = + { + SID_STYLE_WATERCAN, + SID_ATTR_CHAR_COLOR_EXT, + SID_ATTR_CHAR_COLOR_BACKGROUND_EXT, + 0 + }; + m_rView.GetViewFrame()->GetBindings().Invalidate(aInva); +} + +/** + * Ctor + */ +SwEditWin::SwEditWin(Window *pParent, SwView &rMyView): + Window(pParent, WinBits(WB_CLIPCHILDREN | WB_DIALOGCONTROL)), + DropTargetHelper( this ), + DragSourceHelper( this ), + + m_eBufferLanguage(LANGUAGE_DONTKNOW), + m_pApplyTempl(0), + m_pAnchorMarker( 0 ), + m_pUserMarker( 0 ), + m_pUserMarkerObj( 0 ), + m_pShadCrsr( 0 ), + m_pRowColumnSelectionStart( 0 ), + + m_rView( rMyView ), + + m_aActHitType(SDRHIT_NONE), + m_nDropFormat( 0 ), + m_nDropAction( 0 ), + m_nDropDestination( 0 ), + + m_eBezierMode(SID_BEZIER_INSERT), + m_nInsFrmColCount( 1 ), + m_eDrawMode(OBJ_NONE), + + m_bMBPressed(false), + m_bInsDraw(false), + m_bInsFrm(false), + m_bIsInMove(false), + m_bIsInDrag(false), + m_bOldIdle(false), + m_bOldIdleSet(false), + m_bTblInsDelMode(false), + m_bTblIsInsMode(false), + m_bChainMode(false), + m_bWasShdwCrsr(false), + m_bLockInput(false), + m_bIsRowDrag(false), + m_bUseInputLanguage(false), + m_bObjectSelect(false), + m_nKS_NUMDOWN_Count(0), + m_nKS_NUMINDENTINC_Count(0), + m_aFrameControlsManager( this ) +{ + SetHelpId(HID_EDIT_WIN); + EnableChildTransparentMode(); + SetDialogControlFlags( WINDOW_DLGCTRL_RETURN | WINDOW_DLGCTRL_WANTFOCUS ); + + m_bMBPressed = m_bInsDraw = m_bInsFrm = + m_bIsInDrag = m_bOldIdle = m_bOldIdleSet = m_bChainMode = m_bWasShdwCrsr = false; + // initially use the input language + m_bUseInputLanguage = true; + + SetMapMode(MapMode(MAP_TWIP)); + + SetPointer( POINTER_TEXT ); + m_aTimer.SetTimeoutHdl(LINK(this, SwEditWin, TimerHandler)); + + m_bTblInsDelMode = false; + m_aKeyInputTimer.SetTimeout( 3000 ); + m_aKeyInputTimer.SetTimeoutHdl(LINK(this, SwEditWin, KeyInputTimerHandler)); + + m_aKeyInputFlushTimer.SetTimeout( 200 ); + m_aKeyInputFlushTimer.SetTimeoutHdl(LINK(this, SwEditWin, KeyInputFlushHandler)); + + // TemplatePointer for colors should be resetted without + // selection after single click + m_aTemplateTimer.SetTimeout(400); + m_aTemplateTimer.SetTimeoutHdl(LINK(this, SwEditWin, TemplateTimerHdl)); + + // temporary solution!!! Should set the font of the current + // insert position at every curor movement! + if( !rMyView.GetDocShell()->IsReadOnly() ) + { + Font aFont; + SetInputContext( InputContext( aFont, INPUTCONTEXT_TEXT | + INPUTCONTEXT_EXTTEXTINPUT ) ); + } +} + +SwEditWin::~SwEditWin() +{ + m_aKeyInputTimer.Stop(); + delete m_pShadCrsr; + delete m_pRowColumnSelectionStart; + if( m_pQuickHlpData->m_bIsDisplayed && m_rView.GetWrtShellPtr() ) + m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); + bExecuteDrag = false; + delete m_pApplyTempl; + m_rView.SetDrawFuncPtr(NULL); + + delete m_pUserMarker; + delete m_pAnchorMarker; +} + +/** + * Turn on DrawTextEditMode + */ +void SwEditWin::EnterDrawTextMode( const Point& aDocPos ) +{ + if ( m_rView.EnterDrawTextMode(aDocPos) ) + { + if (m_rView.GetDrawFuncPtr()) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + } + m_rView.NoRotate(); + m_rView.AttrChangedNotify( &m_rView.GetWrtShell() ); + } +} + +/** + * Turn on DrawMode + */ +bool SwEditWin::EnterDrawMode(const MouseEvent& rMEvt, const Point& aDocPos) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + SdrView *pSdrView = rSh.GetDrawView(); + + if ( m_rView.GetDrawFuncPtr() ) + { + if (rSh.IsDrawCreate()) + return true; + + bool bRet = m_rView.GetDrawFuncPtr()->MouseButtonDown( rMEvt ); + m_rView.AttrChangedNotify( &rSh ); + return bRet; + } + + if ( pSdrView && pSdrView->IsTextEdit() ) + { + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + + rSh.EndTextEdit(); // clicked aside, end Edit + rSh.SelectObj( aDocPos ); + if ( !rSh.IsObjSelected() && !rSh.IsFrmSelected() ) + rSh.LeaveSelFrmMode(); + else + { + SwEditWin::m_nDDStartPosY = aDocPos.Y(); + SwEditWin::m_nDDStartPosX = aDocPos.X(); + bFrmDrag = true; + } + if( bUnLockView ) + rSh.LockView( false ); + m_rView.AttrChangedNotify( &rSh ); + return true; + } + return false; +} + +bool SwEditWin::IsDrawSelMode() +{ + return IsObjectSelect(); +} + +void SwEditWin::GetFocus() +{ + if ( m_rView.GetPostItMgr()->HasActiveSidebarWin() ) + { + m_rView.GetPostItMgr()->GrabFocusOnActiveSidebarWin(); + } + else + { + m_rView.GotFocus(); + Window::GetFocus(); + m_rView.GetWrtShell().InvalidateAccessibleFocus(); + } +} + +void SwEditWin::LoseFocus() +{ + m_rView.GetWrtShell().InvalidateAccessibleFocus(); + Window::LoseFocus(); + if( m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); + m_rView.LostFocus(); +} + +void SwEditWin::Command( const CommandEvent& rCEvt ) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + + if ( !m_rView.GetViewFrame() ) + { + // If ViewFrame dies shortly, no popup anymore! + Window::Command(rCEvt); + return; + } + + // The command event is send to the window after a possible context + // menu from an inplace client has been closed. Now we have the chance + // to deactivate the inplace client without any problem regarding parent + // windows and code on the stack. + SfxInPlaceClient* pIPClient = rSh.GetSfxViewShell()->GetIPClient(); + bool bIsOleActive = ( pIPClient && pIPClient->IsObjectInPlaceActive() ); + if ( bIsOleActive && ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )) + { + rSh.FinishOLEObj(); + return; + } + + bool bCallBase = true; + + switch ( rCEvt.GetCommand() ) + { + case COMMAND_CONTEXTMENU: + { + const sal_uInt16 nId = SwInputChild::GetChildWindowId(); + SwInputChild* pChildWin = (SwInputChild*)GetView().GetViewFrame()-> + GetChildWindow( nId ); + + if (m_rView.GetPostItMgr()->IsHit(rCEvt.GetMousePosPixel())) + return; + + Point aDocPos( PixelToLogic( rCEvt.GetMousePosPixel() ) ); + if ( !rCEvt.IsMouseEvent() ) + aDocPos = rSh.GetCharRect().Center(); + + // Don't trigger the command on a frame anchored to header/footer is not editing it + FrameControlType eControl; + bool bOverFly = false; + bool bPageAnchored = false; + bool bOverHeaderFooterFly = IsOverHeaderFooterFly( aDocPos, eControl, bOverFly, bPageAnchored ); + // !bOverHeaderFooterFly doesn't mean we have a frame to select + if ( !bPageAnchored && rCEvt.IsMouseEvent( ) && + ( ( rSh.IsHeaderFooterEdit( ) && !bOverHeaderFooterFly && bOverFly ) || + ( !rSh.IsHeaderFooterEdit( ) && bOverHeaderFooterFly ) ) ) + { + return; + } + + if((!pChildWin || pChildWin->GetView() != &m_rView) && + !rSh.IsDrawCreate() && !IsDrawAction()) + { + SET_CURR_SHELL( &rSh ); + if (!m_pApplyTempl) + { + if (bNoInterrupt) + { + ReleaseMouse(); + bNoInterrupt = false; + m_bMBPressed = false; + } + if ( rCEvt.IsMouseEvent() ) + { + SelectMenuPosition(rSh, rCEvt.GetMousePosPixel()); + m_rView.StopShellTimer(); + } + const Point aPixPos = LogicToPixel( aDocPos ); + + if ( m_rView.GetDocShell()->IsReadOnly() ) + { + SwReadOnlyPopup* pROPopup = new SwReadOnlyPopup( aDocPos, m_rView ); + + ui::ContextMenuExecuteEvent aEvent; + aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); + aEvent.ExecutePosition.X = aPixPos.X(); + aEvent.ExecutePosition.Y = aPixPos.Y(); + Menu* pMenu = 0; + OUString sMenuName("private:resource/ReadonlyContextMenu"); + if( GetView().TryContextMenuInterception( *pROPopup, sMenuName, pMenu, aEvent ) ) + { + if ( pMenu ) + { + sal_uInt16 nExecId = ((PopupMenu*)pMenu)->Execute(this, aPixPos); + if( !::ExecuteMenuCommand( *static_cast<PopupMenu*>(pMenu), *m_rView.GetViewFrame(), nExecId )) + pROPopup->Execute(this, nExecId); + } + else + pROPopup->Execute(this, aPixPos); + } + delete pROPopup; + } + else if ( !m_rView.ExecSpellPopup( aDocPos ) ) + GetView().GetViewFrame()->GetDispatcher()->ExecutePopup( 0, this, &aPixPos); + } + else if (m_pApplyTempl->bUndo) + rSh.Do(SwWrtShell::UNDO); + bCallBase = false; + } + } + break; + + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + if( m_pShadCrsr ) + delete m_pShadCrsr, m_pShadCrsr = 0; + bCallBase = !m_rView.HandleWheelCommands( rCEvt ); + break; + + case COMMAND_STARTEXTTEXTINPUT: + { + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && + rSh.IsCrsrReadonly(); + if(!bIsDocReadOnly) + { + if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) + { + bCallBase = false; + rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); + } + else + { + if( rSh.HasSelection() ) + rSh.DelRight(); + + bCallBase = false; + LanguageType eInputLanguage = GetInputLanguage(); + rSh.CreateExtTextInput(eInputLanguage); + } + } + break; + } + case COMMAND_ENDEXTTEXTINPUT: + { + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && + rSh.IsCrsrReadonly(); + if(!bIsDocReadOnly) + { + if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) + { + bCallBase = false; + rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); + } + else + { + bCallBase = false; + OUString sRecord = rSh.DeleteExtTextInput(); + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_rView.GetViewFrame()->GetBindings().GetRecorder(); + + if ( !sRecord.isEmpty() ) + { + // convert quotes in IME text + // works on the last input character, this is escpecially in Korean text often done + // quotes that are inside of the string are not replaced! + const sal_Unicode aCh = sRecord[sRecord.getLength() - 1]; + SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); + SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect(); + if(pACorr && + (( pACorr->IsAutoCorrFlag( ChgQuotes ) && ('\"' == aCh ))|| + ( pACorr->IsAutoCorrFlag( ChgSglQuotes ) && ( '\'' == aCh)))) + { + rSh.DelLeft(); + rSh.AutoCorrect( *pACorr, aCh ); + } + + if ( xRecorder.is() ) + { + // determine Shell + SfxShell *pSfxShell = lcl_GetShellFromDispatcher( m_rView, TYPE(SwTextShell) ); + // generate request and record + if (pSfxShell) + { + SfxRequest aReq( m_rView.GetViewFrame(), FN_INSERT_STRING ); + aReq.AppendItem( SfxStringItem( FN_INSERT_STRING, sRecord ) ); + aReq.Done(); + } + } + } + } + } + } + break; + case COMMAND_EXTTEXTINPUT: + { + bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() && + rSh.IsCrsrReadonly(); + if(!bIsDocReadOnly) + { + if( m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( rSh ); + + OUString sWord; + if( rSh.HasDrawView() && rSh.GetDrawView()->IsTextEdit() ) + { + bCallBase = false; + rSh.GetDrawView()->GetTextEditOutlinerView()->Command( rCEvt ); + } + else + { + const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); + if( pData ) + { + sWord = pData->GetText(); + bCallBase = false; + rSh.SetExtTextInputData( *pData ); + } + } + uno::Reference< frame::XDispatchRecorder > xRecorder = + m_rView.GetViewFrame()->GetBindings().GetRecorder(); + if(!xRecorder.is()) + { + SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); + SvxAutoCorrect* pACorr = rACfg.GetAutoCorrect(); + if( pACorr && + // If autocompletion required... + ( rACfg.IsAutoTextTip() || + pACorr->GetSwFlags().bAutoCompleteWords ) && + // ... and extraction of last word from text input was successful... + rSh.GetPrevAutoCorrWord( *pACorr, sWord ) ) + { + // ... request for auto completion help to be shown. + ShowAutoTextCorrectQuickHelp(sWord, &rACfg, pACorr, true); + } + } + } + } + break; + case COMMAND_CURSORPOS: + // will be handled by the base class + break; + + case COMMAND_PASTESELECTION: + if( !m_rView.GetDocShell()->IsReadOnly() ) + { + TransferableDataHelper aDataHelper( + TransferableDataHelper::CreateFromSelection( this )); + if( !aDataHelper.GetXTransferable().is() ) + break; + + sal_uLong nDropFormat; + sal_uInt16 nEventAction, nDropAction, nDropDestination; + nDropDestination = GetDropDestination( rCEvt.GetMousePosPixel() ); + if( !nDropDestination ) + break; + + nDropAction = SotExchange::GetExchangeAction( + aDataHelper.GetDataFlavorExVector(), + nDropDestination, EXCHG_IN_ACTION_COPY, + EXCHG_IN_ACTION_COPY, nDropFormat, + nEventAction ); + if( EXCHG_INOUT_ACTION_NONE != nDropAction ) + { + const Point aDocPt( PixelToLogic( rCEvt.GetMousePosPixel() ) ); + SwTransferable::PasteData( aDataHelper, rSh, nDropAction, + nDropFormat, nDropDestination, false, + false, &aDocPt, EXCHG_IN_ACTION_COPY, + true ); + } + } + break; + case COMMAND_MODKEYCHANGE : + { + const CommandModKeyData* pCommandData = (const CommandModKeyData*)rCEvt.GetData(); + if(pCommandData->IsMod1() && !pCommandData->IsMod2()) + { + sal_uInt16 nSlot = 0; + if(pCommandData->IsLeftShift() && !pCommandData->IsRightShift()) + nSlot = SID_ATTR_PARA_LEFT_TO_RIGHT; + else if(!pCommandData->IsLeftShift() && pCommandData->IsRightShift()) + nSlot = SID_ATTR_PARA_RIGHT_TO_LEFT; + if(nSlot && SW_MOD()->GetCTLOptions().IsCTLFontEnabled()) + GetView().GetViewFrame()->GetDispatcher()->Execute(nSlot); + } + } + break; + case COMMAND_HANGUL_HANJA_CONVERSION : + GetView().GetViewFrame()->GetDispatcher()->Execute(SID_HANGUL_HANJA_CONVERSION); + break; + case COMMAND_INPUTLANGUAGECHANGE : + // i#42732 - update state of fontname if input language changes + bInputLanguageSwitched = true; + SetUseInputLanguage( true ); + break; + case COMMAND_SELECTIONCHANGE: + { + const CommandSelectionChangeData *pData = rCEvt.GetSelectionChangeData(); + rSh.SttCrsrMove(); + rSh.GoStartSentence(); + rSh.GetCrsr()->GetPoint()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetStart()); + rSh.SetMark(); + rSh.GetCrsr()->GetMark()->nContent += sal::static_int_cast<sal_uInt16, sal_uLong>(pData->GetEnd() - pData->GetStart()); + rSh.EndCrsrMove( true ); + } + break; + case COMMAND_PREPARERECONVERSION: + if( rSh.HasSelection() ) + { + SwPaM *pCrsr = (SwPaM*)rSh.GetCrsr(); + + if( rSh.IsMultiSelection() ) + { + if( pCrsr && !pCrsr->HasMark() && + pCrsr->GetPoint() == pCrsr->GetMark() ) + { + rSh.GoPrevCrsr(); + pCrsr = (SwPaM*)rSh.GetCrsr(); + } + + // Cancel all selections other than the last selected one. + while( rSh.GetCrsr()->GetNext() != rSh.GetCrsr() ) + delete rSh.GetCrsr()->GetNext(); + } + + if( pCrsr ) + { + sal_uLong nPosNodeIdx = pCrsr->GetPoint()->nNode.GetIndex(); + const sal_Int32 nPosIdx = pCrsr->GetPoint()->nContent.GetIndex(); + sal_uLong nMarkNodeIdx = pCrsr->GetMark()->nNode.GetIndex(); + const sal_Int32 nMarkIdx = pCrsr->GetMark()->nContent.GetIndex(); + + if( !rSh.GetCrsr()->HasMark() ) + rSh.GetCrsr()->SetMark(); + + rSh.SttCrsrMove(); + + if( nPosNodeIdx < nMarkNodeIdx ) + { + rSh.GetCrsr()->GetPoint()->nNode = nPosNodeIdx; + rSh.GetCrsr()->GetPoint()->nContent = nPosIdx; + rSh.GetCrsr()->GetMark()->nNode = nPosNodeIdx; + rSh.GetCrsr()->GetMark()->nContent = + rSh.GetCrsr()->GetCntntNode( true )->Len(); + } + else if( nPosNodeIdx == nMarkNodeIdx ) + { + rSh.GetCrsr()->GetPoint()->nNode = nPosNodeIdx; + rSh.GetCrsr()->GetPoint()->nContent = nPosIdx; + rSh.GetCrsr()->GetMark()->nNode = nMarkNodeIdx; + rSh.GetCrsr()->GetMark()->nContent = nMarkIdx; + } + else + { + rSh.GetCrsr()->GetMark()->nNode = nMarkNodeIdx; + rSh.GetCrsr()->GetMark()->nContent = nMarkIdx; + rSh.GetCrsr()->GetPoint()->nNode = nMarkNodeIdx; + rSh.GetCrsr()->GetPoint()->nContent = + rSh.GetCrsr()->GetCntntNode( false )->Len(); + } + + rSh.EndCrsrMove( true ); + } + } + break; + case COMMAND_QUERYCHARPOSITION: + { + bool bVertical = rSh.IsInVerticalText(); + const SwPosition& rPos = *rSh.GetCrsr()->GetPoint(); + SwDocShell* pDocSh = m_rView.GetDocShell(); + SwDoc *pDoc = pDocSh->GetDoc(); + SwExtTextInput* pInput = pDoc->GetExtTextInput( rPos.nNode.GetNode(), rPos.nContent.GetIndex() ); + if ( pInput ) + { + const SwPosition& rStart = *pInput->Start(); + const SwPosition& rEnd = *pInput->End(); + int nSize = 0; + for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) + { + ++nSize; + } + Window& rWin = rSh.GetView().GetEditWin(); + if ( nSize == 0 ) + { + // When the composition does not exist, use Caret rect instead. + SwRect aCaretRect ( rSh.GetCharRect() ); + Rectangle aRect( aCaretRect.Left(), aCaretRect.Top(), aCaretRect.Right(), aCaretRect.Bottom() ); + rWin.SetCompositionCharRect( &aRect, 1, bVertical ); + } + else + { + Rectangle* aRects = new Rectangle[ nSize ]; + int nRectIndex = 0; + for ( SwIndex nIndex = rStart.nContent; nIndex < rEnd.nContent; ++nIndex ) + { + const SwPosition aPos( rStart.nNode, nIndex ); + SwRect aRect ( rSh.GetCharRect() ); + rSh.GetCharRectAt( aRect, &aPos ); + aRects[ nRectIndex ] = Rectangle( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom() ); + ++nRectIndex; + } + rWin.SetCompositionCharRect( aRects, nSize, bVertical ); + delete[] aRects; + } + } + bCallBase = false; + } + break; +#if OSL_DEBUG_LEVEL > 0 + default: + OSL_ENSURE( !this, "unknown command." ); +#endif + } + if (bCallBase) + Window::Command(rCEvt); +} + +/* i#18686 select the object/cursor at the mouse + position of the context menu request */ +bool SwEditWin::SelectMenuPosition(SwWrtShell& rSh, const Point& rMousePos ) +{ + bool bRet = false; + const Point aDocPos( PixelToLogic( rMousePos ) ); + const bool bIsInsideSelectedObj( rSh.IsInsideSelectedObj( aDocPos ) ); + //create a synthetic mouse event out of the coordinates + MouseEvent aMEvt(rMousePos); + SdrView *pSdrView = rSh.GetDrawView(); + if ( pSdrView ) + { + // no close of insert_draw and reset of + // draw mode, if context menu position is inside a selected object. + if ( !bIsInsideSelectedObj && m_rView.GetDrawFuncPtr() ) + { + + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + SfxBindings& rBind = m_rView.GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_ATTR_SIZE ); + rBind.Invalidate( SID_TABLE_CELL ); + } + + // if draw text is active and there's a text selection + // at the mouse position then do nothing + if(rSh.GetSelectionType() & nsSelectionType::SEL_DRW_TXT) + { + OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView(); + ESelection aSelection = pOLV->GetSelection(); + if(!aSelection.IsZero()) + { + SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner(); + bool bVertical = pOutliner->IsVertical(); + const EditEngine& rEditEng = pOutliner->GetEditEngine(); + Point aEEPos(aDocPos); + const Rectangle& rOutputArea = pOLV->GetOutputArea(); + // regard vertical mode + if(bVertical) + { + aEEPos -= rOutputArea.TopRight(); + //invert the horizontal direction and exchange X and Y + long nTemp = -aEEPos.X(); + aEEPos.X() = aEEPos.Y(); + aEEPos.Y() = nTemp; + } + else + aEEPos -= rOutputArea.TopLeft(); + + EPosition aDocPosition = rEditEng.FindDocPosition(aEEPos); + ESelection aCompare(aDocPosition.nPara, aDocPosition.nIndex); + // make it a forward selection - otherwise the IsLess/IsGreater do not work :-( + aSelection.Adjust(); + if(!aCompare.IsLess(aSelection) && !aCompare.IsGreater(aSelection)) + { + return false; + } + } + + } + + if (pSdrView->MouseButtonDown( aMEvt, this ) ) + { + pSdrView->MouseButtonUp( aMEvt, this ); + rSh.GetView().GetViewFrame()->GetBindings().InvalidateAll(false); + return true; + } + } + rSh.ResetCursorStack(); + + if ( EnterDrawMode( aMEvt, aDocPos ) ) + { + return true; + } + if ( m_rView.GetDrawFuncPtr() && m_bInsFrm ) + { + StopInsFrm(); + rSh.Edit(); + } + + UpdatePointer( aDocPos, 0 ); + + if( !rSh.IsSelFrmMode() && + !GetView().GetViewFrame()->GetDispatcher()->IsLocked() ) + { + // Test if there is a draw object at that position and if it should be selected. + bool bShould = rSh.ShouldObjectBeSelected(aDocPos); + + if(bShould) + { + m_rView.NoRotate(); + rSh.HideCrsr(); + + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + bool bSelObj = rSh.SelectObj( aDocPos, 0); + if( bUnLockView ) + rSh.LockView( false ); + + if( bSelObj ) + { + bRet = true; + // in case the frame was deselected in the macro + // just the cursor has to be displayed again. + if( FRMTYPE_NONE == rSh.GetSelFrmType() ) + rSh.ShowCrsr(); + else + { + if (rSh.IsFrmSelected() && m_rView.GetDrawFuncPtr()) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + } + + rSh.EnterSelFrmMode( &aDocPos ); + bFrmDrag = true; + UpdatePointer( aDocPos, 0 ); + return bRet; + } + } + + if (!m_rView.GetDrawFuncPtr()) + rSh.ShowCrsr(); + } + } + else if ( rSh.IsSelFrmMode() && + (m_aActHitType == SDRHIT_NONE || + !bIsInsideSelectedObj)) + { + m_rView.NoRotate(); + bool bUnLockView = !rSh.IsViewLocked(); + rSh.LockView( true ); + sal_uInt8 nFlag = 0; + + if ( rSh.IsSelFrmMode() ) + { + rSh.UnSelectFrm(); + rSh.LeaveSelFrmMode(); + m_rView.AttrChangedNotify(&rSh); + bRet = true; + } + + bool bSelObj = rSh.SelectObj( aDocPos, nFlag ); + if( bUnLockView ) + rSh.LockView( false ); + + if( !bSelObj ) + { + // move cursor here so that it is not drawn in the + // frame at first; ShowCrsr() happens in LeaveSelFrmMode() + bValidCrsrPos = !(CRSR_POSCHG & rSh.SetCursor(&aDocPos, false)); + rSh.LeaveSelFrmMode(); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + bRet = true; + } + else + { + rSh.HideCrsr(); + rSh.EnterSelFrmMode( &aDocPos ); + rSh.SelFlyGrabCrsr(); + rSh.MakeSelVisible(); + bFrmDrag = true; + if( rSh.IsFrmSelected() && + m_rView.GetDrawFuncPtr() ) + { + m_rView.GetDrawFuncPtr()->Deactivate(); + m_rView.SetDrawFuncPtr(NULL); + m_rView.LeaveDrawCreate(); + m_rView.AttrChangedNotify( &rSh ); + } + UpdatePointer( aDocPos, 0 ); + bRet = true; + } + } + else if ( rSh.IsSelFrmMode() && bIsInsideSelectedObj ) + { + // Object at the mouse cursor is already selected - do nothing + return false; + } + + if ( rSh.IsGCAttr() ) + { + rSh.GCAttr(); + rSh.ClearGCAttr(); + } + + bool bOverSelect = rSh.ChgCurrPam( aDocPos ), bOverURLGrf = false; + if( !bOverSelect ) + bOverURLGrf = bOverSelect = 0 != rSh.IsURLGrfAtPos( aDocPos ); + + if ( !bOverSelect ) + { + { // create only temporary move context because otherwise + // the query against the content form doesn't work!!! + SwMvContext aMvContext( &rSh ); + rSh.SetCursor(&aDocPos, false); + bRet = true; + } + } + if( !bOverURLGrf ) + { + const int nSelType = rSh.GetSelectionType(); + if( nSelType == nsSelectionType::SEL_OLE || + nSelType == nsSelectionType::SEL_GRF ) + { + SwMvContext aMvContext( &rSh ); + if( !rSh.IsFrmSelected() ) + rSh.GotoNextFly(); + rSh.EnterSelFrmMode(); + bRet = true; + } + } + return bRet; +} + +static SfxShell* lcl_GetShellFromDispatcher( SwView& rView, TypeId nType ) +{ + // determine Shell + SfxShell* pShell; + SfxDispatcher* pDispatcher = rView.GetViewFrame()->GetDispatcher(); + for(sal_uInt16 i = 0; true; ++i ) + { + pShell = pDispatcher->GetShell( i ); + if( !pShell || pShell->IsA( nType ) ) + break; + } + return pShell; +} + +IMPL_LINK_NOARG(SwEditWin, KeyInputFlushHandler) +{ + FlushInBuffer(); + return 0; +} + +IMPL_LINK_NOARG(SwEditWin, KeyInputTimerHandler) +{ + m_bTblInsDelMode = false; + return 0; +} + +void SwEditWin::_InitStaticData() +{ + m_pQuickHlpData = new QuickHelpData(); +} + +void SwEditWin::_FinitStaticData() +{ + delete m_pQuickHlpData; +} +/* i#3370 - remove quick help to prevent saving + * of autocorrection suggestions */ +void SwEditWin::StopQuickHelp() +{ + if( HasFocus() && m_pQuickHlpData && m_pQuickHlpData->m_bIsDisplayed ) + m_pQuickHlpData->Stop( m_rView.GetWrtShell() ); +} + +IMPL_LINK_NOARG(SwEditWin, TemplateTimerHdl) +{ + SetApplyTemplate(SwApplyTemplate()); + return 0; +} + +void SwEditWin::SetChainMode( bool bOn ) +{ + if ( !m_bChainMode ) + StopInsFrm(); + + if ( m_pUserMarker ) + { + delete m_pUserMarker; + m_pUserMarker = 0L; + } + + m_bChainMode = bOn; + + static sal_uInt16 aInva[] = + { + FN_FRAME_CHAIN, FN_FRAME_UNCHAIN, 0 + }; + m_rView.GetViewFrame()->GetBindings().Invalidate(aInva); +} + +uno::Reference< ::com::sun::star::accessibility::XAccessible > SwEditWin::CreateAccessible() +{ + SolarMutexGuard aGuard; // this should have happened already!!! + SwWrtShell *pSh = m_rView.GetWrtShellPtr(); + OSL_ENSURE( pSh, "no writer shell, no accessible object" ); + uno::Reference< + ::com::sun::star::accessibility::XAccessible > xAcc; + if( pSh ) + xAcc = pSh->CreateAccessible(); + + return xAcc; +} + +void QuickHelpData::Move( QuickHelpData& rCpy ) +{ + m_aHelpStrings.clear(); + m_aHelpStrings.swap( rCpy.m_aHelpStrings ); + + m_bIsDisplayed = rCpy.m_bIsDisplayed; + nLen = rCpy.nLen; + nCurArrPos = rCpy.nCurArrPos; + m_bAppendSpace = rCpy.m_bAppendSpace; + m_bIsTip = rCpy.m_bIsTip; + m_bIsAutoText = rCpy.m_bIsAutoText; +} + +void QuickHelpData::ClearCntnt() +{ + nLen = nCurArrPos = 0; + m_bIsDisplayed = m_bAppendSpace = false; + nTipId = 0; + m_aHelpStrings.clear(); + m_bIsTip = true; + m_bIsAutoText = true; +} + +void QuickHelpData::Start( SwWrtShell& rSh, sal_uInt16 nWrdLen ) +{ + if( USHRT_MAX != nWrdLen ) + { + nLen = nWrdLen; + nCurArrPos = 0; + } + m_bIsDisplayed = true; + + Window& rWin = rSh.GetView().GetEditWin(); + if( m_bIsTip ) + { + Point aPt( rWin.OutputToScreenPixel( rWin.LogicToPixel( + rSh.GetCharRect().Pos() ))); + aPt.Y() -= 3; + nTipId = Help::ShowTip( &rWin, Rectangle( aPt, Size( 1, 1 )), + m_aHelpStrings[ nCurArrPos ], + QUICKHELP_LEFT | QUICKHELP_BOTTOM ); + } + else + { + OUString sStr( m_aHelpStrings[ nCurArrPos ] ); + sStr = sStr.copy( nLen ); + sal_uInt16 nL = sStr.getLength(); + const sal_uInt16 nVal = EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE | + EXTTEXTINPUT_ATTR_HIGHLIGHT; + const std::vector<sal_uInt16> aAttrs( nL, nVal ); + CommandExtTextInputData aCETID( sStr, &aAttrs[0], nL, + 0, false ); + + //fdo#33092. If the current input language is the default + //language that text would appear in if typed, then don't + //force a language on for the ExtTextInput. + LanguageType eInputLanguage = rWin.GetInputLanguage(); + if (lcl_isNonDefaultLanguage(eInputLanguage, + rSh.GetView(), sStr) == INVALID_HINT) + { + eInputLanguage = LANGUAGE_DONTKNOW; + } + + rSh.CreateExtTextInput(eInputLanguage); + rSh.SetExtTextInputData( aCETID ); + } +} + +void QuickHelpData::Stop( SwWrtShell& rSh ) +{ + if( !m_bIsTip ) + rSh.DeleteExtTextInput( 0, false ); + else if( nTipId ) + Help::HideTip( nTipId ); + ClearCntnt(); +} + +void QuickHelpData::FillStrArr( SwWrtShell& rSh, const OUString& rWord ) +{ + enum Capitalization { CASE_LOWER, CASE_UPPER, CASE_SENTENCE, CASE_OTHER }; + + // Determine word capitalization + const CharClass& rCC = GetAppCharClass(); + const OUString sWordLower = rCC.lowercase( rWord ); + Capitalization aWordCase = CASE_OTHER; + if ( !rWord.isEmpty() ) + { + if ( rWord[0] == sWordLower[0] ) + { + if ( rWord == sWordLower ) + aWordCase = CASE_LOWER; + } + else + { + // First character is not lower case i.e. assume upper or title case + OUString sWordSentence = sWordLower; + sWordSentence = sWordSentence.replaceAt( 0, 1, OUString(rWord[0]) ); + if ( rWord == sWordSentence ) + aWordCase = CASE_SENTENCE; + else + { + if ( rWord == rCC.uppercase( rWord ) ) + aWordCase = CASE_UPPER; + } + } + } + + salhelper::SingletonRef<SwCalendarWrapper>* pCalendar = s_getCalendarWrapper(); + (*pCalendar)->LoadDefaultCalendar( rSh.GetCurLang() ); + + // Add matching calendar month and day names + uno::Sequence< i18n::CalendarItem2 > aNames( (*pCalendar)->getMonths() ); + for ( sal_uInt16 i = 0; i < 2; ++i ) + { + for ( long n = 0; n < aNames.getLength(); ++n ) + { + const OUString& rStr( aNames[n].FullName ); + // Check string longer than word and case insensitive match + if( rStr.getLength() > rWord.getLength() && + rCC.lowercase( rStr, 0, rWord.getLength() ) == sWordLower ) + { + //fdo#61251 if it's an exact match, ensure unchanged replacement + //exists as a candidate + if (rStr.startsWith(rWord)) + m_aHelpStrings.push_back(rStr); + + if ( aWordCase == CASE_LOWER ) + m_aHelpStrings.push_back( rCC.lowercase( rStr ) ); + else if ( aWordCase == CASE_SENTENCE ) + { + OUString sTmp = rCC.lowercase( rStr ); + sTmp = sTmp.replaceAt( 0, 1, OUString(rStr[0]) ); + m_aHelpStrings.push_back( sTmp ); + } + else if ( aWordCase == CASE_UPPER ) + m_aHelpStrings.push_back( rCC.uppercase( rStr ) ); + else // CASE_OTHER - use retrieved capitalization + m_aHelpStrings.push_back( rStr ); + } + } + // Data for second loop iteration + if ( i == 0 ) + aNames = (*pCalendar)->getDays(); + } + + // Add matching words from AutoCompleteWord list + const SwAutoCompleteWord& rACList = rSh.GetAutoCompleteWords(); + std::vector<OUString> strings; + + if ( rACList.GetWordsMatching( rWord, strings ) ) + { + for (unsigned int i= 0; i<strings.size(); i++) + { + OUString aCompletedString = strings[i]; + //fdo#61251 if it's an exact match, ensure unchanged replacement + //exists as a candidate + if (aCompletedString.startsWith(rWord)) + m_aHelpStrings.push_back(aCompletedString); + if ( aWordCase == CASE_LOWER ) + m_aHelpStrings.push_back( rCC.lowercase( aCompletedString ) ); + else if ( aWordCase == CASE_SENTENCE ) + { + OUString sTmp = rCC.lowercase( aCompletedString ); + sTmp = sTmp.replaceAt( 0, 1, OUString(aCompletedString[0]) ); + m_aHelpStrings.push_back( sTmp ); + } + else if ( aWordCase == CASE_UPPER ) + m_aHelpStrings.push_back( rCC.uppercase( aCompletedString ) ); + else // CASE_OTHER - use retrieved capitalization + m_aHelpStrings.push_back( aCompletedString ); + } + } + +} + +namespace { + +class CompareIgnoreCaseAsciiFavorExact + : public std::binary_function<const OUString&, const OUString&, bool> +{ + const OUString &m_rOrigWord; +public: + CompareIgnoreCaseAsciiFavorExact(const OUString& rOrigWord) + : m_rOrigWord(rOrigWord) + { + } + + bool operator()(const OUString& s1, const OUString& s2) const + { + int nRet = s1.compareToIgnoreAsciiCase(s2); + if (nRet == 0) + { + //fdo#61251 sort stuff that starts with the exact rOrigWord before + //another ignore-case candidate + int n1StartsWithOrig = s1.startsWith(m_rOrigWord) ? 0 : 1; + int n2StartsWithOrig = s2.startsWith(m_rOrigWord) ? 0 : 1; + return n1StartsWithOrig < n2StartsWithOrig; + } + return nRet < 0; + } +}; + +struct EqualIgnoreCaseAscii +{ + bool operator()(const OUString& s1, const OUString& s2) const + { + return s1.equalsIgnoreAsciiCase(s2); + } +}; + +} // anonymous namespace + +// TODO Implement an i18n aware sort +void QuickHelpData::SortAndFilter(const OUString &rOrigWord) +{ + std::sort( m_aHelpStrings.begin(), + m_aHelpStrings.end(), + CompareIgnoreCaseAsciiFavorExact(rOrigWord) ); + + std::vector<OUString>::iterator it = std::unique( m_aHelpStrings.begin(), + m_aHelpStrings.end(), + EqualIgnoreCaseAscii() ); + m_aHelpStrings.erase( it, m_aHelpStrings.end() ); + + nCurArrPos = 0; +} + +void SwEditWin::ShowAutoTextCorrectQuickHelp( + const OUString& rWord, SvxAutoCorrCfg* pACfg, SvxAutoCorrect* pACorr, + bool bFromIME ) +{ + SwWrtShell& rSh = m_rView.GetWrtShell(); + m_pQuickHlpData->ClearCntnt(); + if( pACfg->IsAutoTextTip() ) + { + SwGlossaryList* pList = ::GetGlossaryList(); + pList->HasLongName( rWord, &m_pQuickHlpData->m_aHelpStrings ); + } + + if( m_pQuickHlpData->m_aHelpStrings.empty() && + pACorr->GetSwFlags().bAutoCompleteWords ) + { + m_pQuickHlpData->m_bIsAutoText = false; + m_pQuickHlpData->m_bIsTip = bFromIME || + !pACorr || + pACorr->GetSwFlags().bAutoCmpltShowAsTip; + + // Get the necessary data to show help text. + m_pQuickHlpData->FillStrArr( rSh, rWord ); + } + + if( !m_pQuickHlpData->m_aHelpStrings.empty() ) + { + m_pQuickHlpData->SortAndFilter(rWord); + m_pQuickHlpData->Start( rSh, rWord.getLength() ); + } +} + +bool SwEditWin::IsInHeaderFooter( const Point &rDocPt, FrameControlType &rControl ) const +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + const SwPageFrm* pPageFrm = rSh.GetLayout()->GetPageAtPos( rDocPt ); + + if ( pPageFrm && pPageFrm->IsOverHeaderFooterArea( rDocPt, rControl ) ) + return true; + + if ( rSh.IsShowHeaderFooterSeparator( Header ) || rSh.IsShowHeaderFooterSeparator( Footer ) ) + { + SwFrameControlsManager &rMgr = rSh.GetView().GetEditWin().GetFrameControlsManager(); + Point aPoint( LogicToPixel( rDocPt ) ); + + if ( rSh.IsShowHeaderFooterSeparator( Header ) ) + { + SwFrameControlPtr pControl = rMgr.GetControl( Header, pPageFrm ); + if ( pControl.get() && pControl->Contains( aPoint ) ) + { + rControl = Header; + return true; + } + } + + if ( rSh.IsShowHeaderFooterSeparator( Footer ) ) + { + SwFrameControlPtr pControl = rMgr.GetControl( Footer, pPageFrm ); + if ( pControl.get() && pControl->Contains( aPoint ) ) + { + rControl = Footer; + return true; + } + } + } + + return false; +} + +bool SwEditWin::IsOverHeaderFooterFly( const Point& rDocPos, FrameControlType& rControl, bool& bOverFly, bool& bPageAnchored ) const +{ + bool bRet = false; + Point aPt( rDocPos ); + SwWrtShell &rSh = m_rView.GetWrtShell(); + SwPaM aPam( *rSh.GetCurrentShellCursor().GetPoint() ); + rSh.GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt, NULL, true ); + + const SwStartNode* pStartFly = aPam.GetPoint()->nNode.GetNode().FindFlyStartNode(); + if ( pStartFly ) + { + bOverFly = true; + SwFrmFmt* pFlyFmt = pStartFly->GetFlyFmt( ); + if ( pFlyFmt ) + { + const SwPosition* pAnchor = pFlyFmt->GetAnchor( ).GetCntntAnchor( ); + if ( pAnchor ) + { + bool bInHeader = pAnchor->nNode.GetNode( ).FindHeaderStartNode( ) != NULL; + bool bInFooter = pAnchor->nNode.GetNode( ).FindFooterStartNode( ) != NULL; + + bRet = bInHeader || bInFooter; + if ( bInHeader ) + rControl = Header; + else if ( bInFooter ) + rControl = Footer; + } + else + bPageAnchored = pFlyFmt->GetAnchor( ).GetAnchorId( ) == FLY_AT_PAGE; + } + } + else + bOverFly = false; + return bRet; +} + +void SwEditWin::SetUseInputLanguage( bool bNew ) +{ + if ( bNew || m_bUseInputLanguage ) + { + SfxBindings& rBind = GetView().GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_ATTR_CHAR_FONT ); + rBind.Invalidate( SID_ATTR_CHAR_FONTHEIGHT ); + } + m_bUseInputLanguage = bNew; +} + +OUString SwEditWin::GetSurroundingText() const +{ + OUString sReturn; + SwWrtShell& rSh = m_rView.GetWrtShell(); + if( rSh.HasSelection() && !rSh.IsMultiSelection() && rSh.IsSelOnePara() ) + rSh.GetSelectedText( sReturn, GETSELTXT_PARABRK_TO_ONLYCR ); + else if( !rSh.HasSelection() ) + { + SwPosition *pPos = rSh.GetCrsr()->GetPoint(); + const sal_Int32 nPos = pPos->nContent.GetIndex(); + + // get the sentence around the cursor + rSh.HideCrsr(); + rSh.GoStartSentence(); + rSh.SetMark(); + rSh.GoEndSentence(); + rSh.GetSelectedText( sReturn, GETSELTXT_PARABRK_TO_ONLYCR ); + + pPos->nContent = nPos; + rSh.ClearMark(); + rSh.HideCrsr(); + } + + return sReturn; +} + +Selection SwEditWin::GetSurroundingTextSelection() const +{ + SwWrtShell& rSh = m_rView.GetWrtShell(); + if( rSh.HasSelection() ) + { + OUString sReturn; + rSh.GetSelectedText( sReturn, GETSELTXT_PARABRK_TO_ONLYCR ); + return Selection( 0, sReturn.getLength() ); + } + else + { + // Return the position of the visible cursor in the sentence + // around the visible cursor. + SwPosition *pPos = rSh.GetCrsr()->GetPoint(); + const sal_Int32 nPos = pPos->nContent.GetIndex(); + + rSh.HideCrsr(); + rSh.GoStartSentence(); + const sal_Int32 nStartPos = rSh.GetCrsr()->GetPoint()->nContent.GetIndex(); + + pPos->nContent = nPos; + rSh.ClearMark(); + rSh.ShowCrsr(); + + return Selection( nPos - nStartPos, nPos - nStartPos ); + } +} + +// MT: Removed Windows::SwitchView() introduced with IA2 CWS. +// There are other notifications for this when the active view has changed, so please update the code to use that event mechanism +void SwEditWin::SwitchView() +{ +#ifdef ACCESSIBLE_LAYOUT + if (!Application::IsAccessibilityEnabled()) + { + return ; + } + rView.GetWrtShell().InvalidateAccessibleFocus(); +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx new file mode 100644 index 000000000000..bbcaaf1a6399 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin2.cxx @@ -0,0 +1,465 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <comphelper/string.hxx> +#include <hintids.hxx> + +#include <doc.hxx> +#if OSL_DEBUG_LEVEL > 1 +#include <stdio.h> +#endif +#include <osl/thread.h> +#include <vcl/help.hxx> +#include <svl/stritem.hxx> +#include <unotools/securityoptions.hxx> +#include <tools/urlobj.hxx> +#include <txtrfmrk.hxx> +#include <fmtrfmrk.hxx> +#include <editeng/flditem.hxx> +#include <svl/urihelper.hxx> +#include <svx/svdotext.hxx> +#include <editeng/outliner.hxx> +#include <svl/itemiter.hxx> +#include <svx/svdview.hxx> +#include <svx/svdpagv.hxx> +#include <swmodule.hxx> +#include <modcfg.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <edtwin.hxx> +#include <dpage.hxx> +#include <shellres.hxx> +#include <docufld.hxx> +#include <dbfld.hxx> +#include <reffld.hxx> +#include <cellatr.hxx> +#include <shdwcrsr.hxx> +#include <fmtcol.hxx> +#include <charfmt.hxx> +#include <fmtftn.hxx> +#include <redline.hxx> +#include <tox.hxx> +#include <txttxmrk.hxx> +#include <uitool.hxx> +#include <viewopt.hxx> +#include <docvw.hrc> +#include <utlui.hrc> + +#include <PostItMgr.hxx> +#include <fmtfld.hxx> + +#include <IDocumentMarkAccess.hxx> +#include <ndtxt.hxx> + +static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon ) +{ + sal_uInt16 nResId = 0; + switch( rRedl.GetType() ) + { + case nsRedlineType_t::REDLINE_INSERT: nResId = STR_REDLINE_INSERT; break; + case nsRedlineType_t::REDLINE_DELETE: nResId = STR_REDLINE_DELETE; break; + case nsRedlineType_t::REDLINE_FORMAT: nResId = STR_REDLINE_FORMAT; break; + case nsRedlineType_t::REDLINE_TABLE: nResId = STR_REDLINE_TABLE; break; + case nsRedlineType_t::REDLINE_FMTCOLL: nResId = STR_REDLINE_FMTCOLL; break; + } + + OUStringBuffer sBuf; + if( nResId ) + { + sBuf.append(SW_RESSTR(nResId)); + sBuf.append(": "); + sBuf.append(rRedl.GetAuthorString()); + sBuf.append(" - "); + sBuf.append(GetAppLangDateTimeString(rRedl.GetTimeStamp())); + if( bBalloon && !rRedl.GetComment().isEmpty() ) + sBuf.append('\n').append(rRedl.GetComment()); + } + return sBuf.makeStringAndClear(); +} + +void SwEditWin::RequestHelp(const HelpEvent &rEvt) +{ + SwWrtShell &rSh = m_rView.GetWrtShell(); + bool bQuickBalloon = 0 != (rEvt.GetMode() & ( HELPMODE_QUICK | HELPMODE_BALLOON )); + if(bQuickBalloon && !rSh.GetViewOptions()->IsShowContentTips()) + return; + bool bContinue = true; + SET_CURR_SHELL(&rSh); + OUString sTxt; + Point aPos( PixelToLogic( ScreenToOutputPixel( rEvt.GetMousePosPixel() ) )); + bool bBalloon = static_cast< bool >(rEvt.GetMode() & HELPMODE_BALLOON); + + SdrView *pSdrView = rSh.GetDrawView(); + + if( bQuickBalloon ) + { + if( pSdrView ) + { + SdrPageView* pPV = pSdrView->GetSdrPageView(); + SwDPage* pPage = pPV ? ((SwDPage*)pPV->GetPage()) : 0; + bContinue = pPage && pPage->RequestHelp(this, pSdrView, rEvt); + } + } + + if( bContinue && bQuickBalloon) + { + SwRect aFldRect; + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_FIELD | + SwContentAtPos::SW_INETATTR | + SwContentAtPos::SW_FTN | + SwContentAtPos::SW_REDLINE | + SwContentAtPos::SW_TOXMARK | + SwContentAtPos::SW_REFMARK | + SwContentAtPos::SW_SMARTTAG | +#ifdef DBG_UTIL + SwContentAtPos::SW_TABLEBOXVALUE | + ( bBalloon ? SwContentAtPos::SW_CURR_ATTRS : 0) | +#endif + SwContentAtPos::SW_TABLEBOXFML ); + + if( rSh.GetContentAtPos( aPos, aCntntAtPos, false, &aFldRect ) ) + { + sal_uInt16 nStyle = 0; // style of quick help + switch( aCntntAtPos.eCntntAtPos ) + { + case SwContentAtPos::SW_TABLEBOXFML: + sTxt = "= "; + sTxt += ((SwTblBoxFormula*)aCntntAtPos.aFnd.pAttr)->GetFormula(); + break; +#ifdef DBG_UTIL + case SwContentAtPos::SW_TABLEBOXVALUE: + { + sTxt = OStringToOUString(OString::number( + ((SwTblBoxValue*)aCntntAtPos.aFnd.pAttr)->GetValue()), + osl_getThreadTextEncoding()); + } + break; + case SwContentAtPos::SW_CURR_ATTRS: + sTxt = aCntntAtPos.sStr; + break; +#endif + + case SwContentAtPos::SW_INETATTR: + { + sTxt = ((SfxStringItem*)aCntntAtPos.aFnd.pAttr)->GetValue(); + sTxt = URIHelper::removePassword( sTxt, + INetURLObject::WAS_ENCODED, + INetURLObject::DECODE_UNAMBIGUOUS); + //#i63832# remove the link target type + sal_Int32 nFound = sTxt.indexOf(cMarkSeparator); + if( nFound != -1 && (++nFound) < sTxt.getLength() ) + { + OUString sSuffix( sTxt.copy(nFound) ); + if( sSuffix == "table" || + sSuffix == "frame" || + sSuffix == "region" || + sSuffix == "outline" || + sSuffix == "text" || + sSuffix == "graphic" || + sSuffix == "ole" ) + sTxt = sTxt.copy( 0, nFound - 1); + } + // #i104300# + // special handling if target is a cross-reference bookmark + { + OUString sTmpSearchStr = sTxt.copy( 1 ); + IDocumentMarkAccess* const pMarkAccess = + rSh.getIDocumentMarkAccess(); + IDocumentMarkAccess::const_iterator_t ppBkmk = + pMarkAccess->findBookmark( sTmpSearchStr ); + if ( ppBkmk != pMarkAccess->getBookmarksEnd() && + IDocumentMarkAccess::GetType( *(ppBkmk->get()) ) + == IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK ) + { + SwTxtNode* pTxtNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTxtNode(); + if ( pTxtNode ) + { + sTxt = pTxtNode->GetExpandTxt( 0, pTxtNode->Len(), true, true ); + + if( !sTxt.isEmpty() ) + { + OUStringBuffer sTmp(comphelper::string::remove(sTxt, 0xad)); + for (sal_Int32 i = 0; i < sTmp.getLength(); ++i) + { + if (sTmp[i] < 0x20) + sTmp[i] = 0x20; + else if (sTmp[i] == 0x2011) + sTmp[i] = '-'; + } + sTxt = sTmp.makeStringAndClear(); + } + } + } + } + // #i80029# + bool bExecHyperlinks = m_rView.GetDocShell()->IsReadOnly(); + if ( !bExecHyperlinks ) + { + SvtSecurityOptions aSecOpts; + bExecHyperlinks = !aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK ); + + sTxt = ": " + sTxt; + if ( !bExecHyperlinks ) + sTxt = SwViewShell::GetShellRes()->aLinkCtrlClick + sTxt; + else + sTxt = SwViewShell::GetShellRes()->aLinkClick + sTxt; + } + break; + } + case SwContentAtPos::SW_SMARTTAG: + { + KeyCode aCode( KEY_SPACE ); + KeyCode aModifiedCode( KEY_SPACE, KEY_MOD1 ); + OUString aModStr( aModifiedCode.GetName() ); + aModStr = aModStr.replaceFirst(aCode.GetName(), OUString()); + aModStr = aModStr.replaceAll("+", OUString()); + sTxt = SW_RESSTR(STR_SMARTTAG_CLICK).replaceAll("%s", aModStr); + } + break; + + case SwContentAtPos::SW_FTN: + if( aCntntAtPos.pFndTxtAttr && aCntntAtPos.aFnd.pAttr ) + { + const SwFmtFtn* pFtn = (SwFmtFtn*)aCntntAtPos.aFnd.pAttr; + OUString sTmp; + pFtn->GetFtnText( sTmp ); + sTxt = SW_RESSTR( pFtn->IsEndNote() + ? STR_ENDNOTE : STR_FTNNOTE ) + sTmp; + bBalloon = true; + if( aCntntAtPos.IsInRTLText() ) + nStyle |= QUICKHELP_BIDI_RTL; + } + break; + + case SwContentAtPos::SW_REDLINE: + sTxt = lcl_GetRedlineHelp(*aCntntAtPos.aFnd.pRedl, bBalloon); + break; + + case SwContentAtPos::SW_TOXMARK: + sTxt = aCntntAtPos.sStr; + if( !sTxt.isEmpty() && aCntntAtPos.pFndTxtAttr ) + { + const SwTOXType* pTType = aCntntAtPos.pFndTxtAttr-> + GetTOXMark().GetTOXType(); + if( pTType && !pTType->GetTypeName().isEmpty() ) + { + sTxt = ": " + sTxt; + sTxt = pTType->GetTypeName() + sTxt; + } + } + break; + case SwContentAtPos::SW_REFMARK: + if(aCntntAtPos.aFnd.pAttr) + { + sTxt = SW_RESSTR(STR_CONTENT_TYPE_SINGLE_REFERENCE); + sTxt += ": "; + sTxt += ((const SwFmtRefMark*)aCntntAtPos.aFnd.pAttr)->GetRefName(); + } + break; + + default: + { + SwModuleOptions* pModOpt = SW_MOD()->GetModuleConfig(); + if(!pModOpt->IsHideFieldTips()) + { + const SwField* pFld = aCntntAtPos.aFnd.pFld; + switch( pFld->Which() ) + { + case RES_SETEXPFLD: + case RES_TABLEFLD: + case RES_GETEXPFLD: + { + sal_uInt16 nOldSubType = pFld->GetSubType(); + ((SwField*)pFld)->SetSubType(nsSwExtendedSubType::SUB_CMD); + sTxt = pFld->ExpandField(true); + ((SwField*)pFld)->SetSubType(nOldSubType); + } + break; + + case RES_POSTITFLD: + { + break; + } + case RES_INPUTFLD: // BubbleHelp, because the suggestion could be quite long + bBalloon = true; + /* no break */ + case RES_JUMPEDITFLD: + sTxt = pFld->GetPar2(); + break; + + case RES_DBFLD: + sTxt = pFld->GetFieldName(); + break; + + case RES_USERFLD: + case RES_HIDDENTXTFLD: + sTxt = pFld->GetPar1(); + break; + + case RES_DOCSTATFLD: + break; + + case RES_MACROFLD: + sTxt = ((const SwMacroField*)pFld)->GetMacro(); + break; + + case RES_GETREFFLD: + { + // #i85090# + const SwGetRefField* pRefFld( dynamic_cast<const SwGetRefField*>(pFld) ); + OSL_ENSURE( pRefFld, + "<SwEditWin::RequestHelp(..)> - unexpected type of <pFld>" ); + if ( pRefFld ) + { + if ( pRefFld->IsRefToHeadingCrossRefBookmark() || + pRefFld->IsRefToNumItemCrossRefBookmark() ) + { + sTxt = pRefFld->GetExpandedTxtOfReferencedTxtNode(); + if ( sTxt.getLength() > 80 ) + { + sTxt = sTxt.copy(0, 80) + "..."; + } + } + else + { + sTxt = ((SwGetRefField*)pFld)->GetSetRefName(); + } + } + } + break; + } + } + + if( sTxt.isEmpty() ) + { + aCntntAtPos.eCntntAtPos = SwContentAtPos::SW_REDLINE; + if( rSh.GetContentAtPos( aPos, aCntntAtPos, false, &aFldRect ) ) + sTxt = lcl_GetRedlineHelp(*aCntntAtPos.aFnd.pRedl, bBalloon); + } + } + } + if (!sTxt.isEmpty()) + { + if( bBalloon ) + Help::ShowBalloon( this, rEvt.GetMousePosPixel(), sTxt ); + else + { + // the show the help + Rectangle aRect( aFldRect.SVRect() ); + Point aPt( OutputToScreenPixel( LogicToPixel( aRect.TopLeft() ))); + aRect.Left() = aPt.X(); + aRect.Top() = aPt.Y(); + aPt = OutputToScreenPixel( LogicToPixel( aRect.BottomRight() )); + aRect.Right() = aPt.X(); + aRect.Bottom() = aPt.Y(); + Help::ShowQuickHelp( this, aRect, sTxt, nStyle ); + } + } + + bContinue = false; + } + if( bContinue ) + { + sal_uInt8 nTabCols = rSh.WhichMouseTabCol(aPos); + sal_uInt16 nTabRes = 0; + switch(nTabCols) + { + case SW_TABCOL_HORI: + case SW_TABCOL_VERT: + nTabRes = STR_TABLE_COL_ADJUST; + break; + case SW_TABROW_HORI: + case SW_TABROW_VERT: + nTabRes = STR_TABLE_ROW_ADJUST; + break; + // #i32329# Enhanced table selection + case SW_TABSEL_HORI: + case SW_TABSEL_HORI_RTL: + case SW_TABSEL_VERT: + nTabRes = STR_TABLE_SELECT_ALL; + break; + case SW_TABROWSEL_HORI: + case SW_TABROWSEL_HORI_RTL: + case SW_TABROWSEL_VERT: + nTabRes = STR_TABLE_SELECT_ROW; + break; + case SW_TABCOLSEL_HORI: + case SW_TABCOLSEL_VERT: + nTabRes = STR_TABLE_SELECT_COL; + break; + } + if(nTabRes) + { + sTxt = SW_RESSTR(nTabRes); + Size aTxtSize( GetTextWidth(sTxt), GetTextHeight()); + Rectangle aRect(rEvt.GetMousePosPixel(), aTxtSize); + Help::ShowQuickHelp(this, aRect, sTxt); + } + bContinue = false; + } + } + + if( bContinue ) + Window::RequestHelp( rEvt ); +} + +void SwEditWin::PrePaint() +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + + if(pWrtShell) + { + pWrtShell->PrePaint(); + } +} + +void SwEditWin::Paint(const Rectangle& rRect) +{ + SwWrtShell* pWrtShell = GetView().GetWrtShellPtr(); + if(!pWrtShell) + return; + bool bPaintShadowCrsr = false; + if( m_pShadCrsr ) + { + Rectangle aRect( m_pShadCrsr->GetRect()); + // fully resides inside? + if( rRect.IsInside( aRect ) ) + // dann aufheben + delete m_pShadCrsr, m_pShadCrsr = 0; + else if( rRect.IsOver( aRect )) + { + // resides somewhat above, then everything is clipped outside + // and we have to make the "inner part" at the end of the + // Paint visible again. Otherwise Paint errors occur! + bPaintShadowCrsr = true; + } + } + + if ( GetView().GetVisArea().GetWidth() <= 0 || + GetView().GetVisArea().GetHeight() <= 0 ) + Invalidate( rRect ); + else + pWrtShell->Paint( rRect ); + + if( bPaintShadowCrsr ) + m_pShadCrsr->Paint(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtwin3.cxx b/sw/source/uibase/docvw/edtwin3.cxx new file mode 100644 index 000000000000..c627b7772ef1 --- /dev/null +++ b/sw/source/uibase/docvw/edtwin3.cxx @@ -0,0 +1,166 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <hintids.hxx> +#include <vcl/settings.hxx> +#include <svx/ruler.hxx> +#include <viewopt.hxx> +#include "view.hxx" +#include "wrtsh.hxx" +#include "basesh.hxx" +#include "pview.hxx" +#include "mdiexp.hxx" +#include "edtwin.hxx" +#include "swmodule.hxx" +#include "modcfg.hxx" +#include "swtable.hxx" +#include "docsh.hxx" +#include "pagedesc.hxx" +#include <frmatr.hxx> +#include <editeng/frmdiritem.hxx> + +// Core-Notify +void ScrollMDI( SwViewShell* pVwSh, const SwRect &rRect, + sal_uInt16 nRangeX, sal_uInt16 nRangeY) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if (pSfxVwSh && pSfxVwSh->ISA(SwView)) + ((SwView *)pSfxVwSh)->Scroll( rRect.SVRect(), nRangeX, nRangeY ); +} + +// Docmdi - movable +bool IsScrollMDI( SwViewShell* pVwSh, const SwRect &rRect ) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if (pSfxVwSh && pSfxVwSh->ISA(SwView)) + return (((SwView *)pSfxVwSh)->IsScroll(rRect.SVRect())); + return false; +} + +// Notify for size change +void SizeNotify(SwViewShell* pVwSh, const Size &rSize) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if (pSfxVwSh) + { + if (pSfxVwSh->ISA(SwView)) + ((SwView *)pSfxVwSh)->DocSzChgd(rSize); + else if (pSfxVwSh->ISA(SwPagePreview)) + ((SwPagePreview *)pSfxVwSh)->DocSzChgd( rSize ); + } +} + +// Notify for page number update +void PageNumNotify( SwViewShell* pVwSh, sal_uInt16 nPhyNum, sal_uInt16 nVirtNum, + const OUString& rPgStr) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if ( pSfxVwSh && pSfxVwSh->ISA(SwView) && + ((SwView*)pSfxVwSh)->GetCurShell() ) + ((SwView *)pSfxVwSh)->UpdatePageNums(nPhyNum, nVirtNum, rPgStr); +} + +void FrameNotify( SwViewShell* pVwSh, FlyMode eMode ) +{ + if ( pVwSh->ISA(SwCrsrShell) ) + SwBaseShell::SetFrmMode( eMode, (SwWrtShell*)pVwSh ); +} + +// Notify for page number update +bool SwEditWin::RulerColumnDrag( const MouseEvent& rMEvt, bool bVerticalMode) +{ + SvxRuler& rRuler = bVerticalMode ? m_rView.GetVRuler() : m_rView.GetHRuler(); + return (!rRuler.StartDocDrag( rMEvt, RULER_TYPE_BORDER ) && + !rRuler.StartDocDrag( rMEvt, RULER_TYPE_MARGIN1) && + !rRuler.StartDocDrag( rMEvt, RULER_TYPE_MARGIN2)); +} + +// #i23726# +// #i42921# - add 3rd parameter <bVerticalMode> in order +// to consider vertical layout +bool SwEditWin::RulerMarginDrag( const MouseEvent& rMEvt, + const bool bVerticalMode ) +{ + SvxRuler& rRuler = bVerticalMode ? m_rView.GetVRuler() : m_rView.GetHRuler(); + return !rRuler.StartDocDrag( rMEvt, RULER_TYPE_INDENT); +} + +TblChgMode GetTblChgDefaultMode() +{ + SwModuleOptions* pOpt = SW_MOD()->GetModuleConfig(); + return pOpt ? pOpt->GetTblMode() : TBLVAR_CHGABS; +} + +void RepaintPagePreview( SwViewShell* pVwSh, const SwRect& rRect ) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if (pSfxVwSh && pSfxVwSh->ISA( SwPagePreview )) + ((SwPagePreview *)pSfxVwSh)->RepaintCoreRect( rRect ); +} + +bool JumpToSwMark( SwViewShell* pVwSh, const OUString& rMark ) +{ + SfxViewShell *pSfxVwSh = pVwSh->GetSfxViewShell(); + if( pSfxVwSh && pSfxVwSh->ISA( SwView ) ) + return ((SwView *)pSfxVwSh)->JumpToSwMark( rMark ); + return false; +} + +void SwEditWin::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + SwWrtShell* pSh = GetView().GetWrtShellPtr(); + // DataChanged() is sometimes called prior to creating + // the SwWrtShell + if(!pSh) + return; + bool bViewWasLocked = pSh->IsViewLocked(), bUnlockPaint = false; + pSh->LockView( true ); + switch( rDCEvt.GetType() ) + { + case DATACHANGED_SETTINGS: + // rearrange ScrollBars, respectively trigger resize, because + // the ScrollBar size can have change. For that, in the reset + // handler, the size of the ScrollBars also has to be queried + // from the settings. + if( rDCEvt.GetFlags() & SETTINGS_STYLE ) + { + pSh->LockPaint(); + bUnlockPaint = true; + SwViewShell::DeleteReplacementBitmaps(); + GetView().InvalidateBorder(); //Scrollbar work + } + break; + + case DATACHANGED_PRINTER: + case DATACHANGED_DISPLAY: + case DATACHANGED_FONTS: + case DATACHANGED_FONTSUBSTITUTION: + pSh->LockPaint(); + bUnlockPaint = true; + GetView().GetDocShell()->UpdateFontList(); //e.g. printer change + break; + } + pSh->LockView( bViewWasLocked ); + if( bUnlockPaint ) + pSh->UnlockPaint(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/frmsidebarwincontainer.cxx b/sw/source/uibase/docvw/frmsidebarwincontainer.cxx new file mode 100644 index 000000000000..3760f9778446 --- /dev/null +++ b/sw/source/uibase/docvw/frmsidebarwincontainer.cxx @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <frmsidebarwincontainer.hxx> + +#include <map> +#include <fmtfld.hxx> +#include <txtfld.hxx> +#include <SidebarWin.hxx> + +namespace { + struct SidebarWinKey + { + const sal_Int32 mnIndex; + + explicit SidebarWinKey( const sal_Int32 nIndex ) + : mnIndex( nIndex ) + {} + + bool operator < ( const SidebarWinKey& rSidebarWinKey ) const + { + return mnIndex < rSidebarWinKey.mnIndex; + } + }; + + struct SidebarWinOrder + { + bool operator()( const SidebarWinKey& rSidebarWinKeyA, + const SidebarWinKey& rSidebarWinKeyB ) const + { + return rSidebarWinKeyA < rSidebarWinKeyB; + } + }; + + typedef ::std::map < SidebarWinKey, sw::sidebarwindows::SwSidebarWin*, SidebarWinOrder > SidebarWinContainer; + + struct FrmKey + { + const SwFrm* mpFrm; + + explicit FrmKey( const SwFrm* pFrm ) + : mpFrm( pFrm ) + {} + + bool operator < ( const FrmKey& rFrmKey ) const + { + return mpFrm < rFrmKey.mpFrm; + } + }; + + struct FrmOrder + { + bool operator()( const FrmKey& rFrmKeyA, + const FrmKey& rFrmKeyB ) const + { + return rFrmKeyA < rFrmKeyB; + } + }; + + typedef ::std::map < FrmKey, SidebarWinContainer, FrmOrder > _FrmSidebarWinContainer; +} + +namespace sw { namespace sidebarwindows { + +class FrmSidebarWinContainer : public _FrmSidebarWinContainer +{ +}; + +SwFrmSidebarWinContainer::SwFrmSidebarWinContainer() + : mpFrmSidebarWinContainer( new FrmSidebarWinContainer() ) +{} + +SwFrmSidebarWinContainer::~SwFrmSidebarWinContainer() +{ + mpFrmSidebarWinContainer->clear(); + delete mpFrmSidebarWinContainer; +} + +bool SwFrmSidebarWinContainer::insert( const SwFrm& rFrm, + const SwFmtFld& rFmtFld, + SwSidebarWin& rSidebarWin ) +{ + bool bInserted( false ); + + FrmKey aFrmKey( &rFrm ); + SidebarWinContainer& rSidebarWinContainer = (*mpFrmSidebarWinContainer)[ aFrmKey ]; + + SidebarWinKey aSidebarWinKey( *(rFmtFld.GetTxtFld()->GetStart()) ); + if ( rSidebarWinContainer.empty() || + rSidebarWinContainer.find( aSidebarWinKey) == rSidebarWinContainer.end() ) + { + rSidebarWinContainer[ aSidebarWinKey ] = &rSidebarWin; + bInserted = true; + } + + return bInserted; +} + +bool SwFrmSidebarWinContainer::remove( const SwFrm& rFrm, + const SwSidebarWin& rSidebarWin ) +{ + bool bRemoved( false ); + + FrmKey aFrmKey( &rFrm ); + FrmSidebarWinContainer::iterator aFrmIter = mpFrmSidebarWinContainer->find( aFrmKey ); + if ( aFrmIter != mpFrmSidebarWinContainer->end() ) + { + SidebarWinContainer& rSidebarWinContainer = (*aFrmIter).second; + for ( SidebarWinContainer::iterator aIter = rSidebarWinContainer.begin(); + aIter != rSidebarWinContainer.end(); + ++aIter ) + { + if ( (*aIter).second == &rSidebarWin ) + { + rSidebarWinContainer.erase( aIter ); + bRemoved = true; + break; + } + } + } + + return bRemoved; +} + +bool SwFrmSidebarWinContainer::empty( const SwFrm& rFrm ) +{ + bool bEmpty( true ); + + FrmKey aFrmKey( &rFrm ); + FrmSidebarWinContainer::iterator aFrmIter = mpFrmSidebarWinContainer->find( aFrmKey ); + if ( aFrmIter != mpFrmSidebarWinContainer->end() ) + { + bEmpty = (*aFrmIter).second.empty(); + } + + return bEmpty; +} + +SwSidebarWin* SwFrmSidebarWinContainer::get( const SwFrm& rFrm, + const sal_Int32 nIndex ) +{ + SwSidebarWin* pRet( 0 ); + + FrmKey aFrmKey( &rFrm ); + FrmSidebarWinContainer::iterator aFrmIter = mpFrmSidebarWinContainer->find( aFrmKey ); + if ( aFrmIter != mpFrmSidebarWinContainer->end() ) + { + SidebarWinContainer& rSidebarWinContainer = (*aFrmIter).second; + sal_Int32 nCounter( nIndex ); + for ( SidebarWinContainer::iterator aIter = rSidebarWinContainer.begin(); + nCounter >= 0 && aIter != rSidebarWinContainer.end(); + ++aIter ) + { + if ( nCounter == 0 ) + { + pRet = (*aIter).second; + break; + } + + --nCounter; + } + } + + return pRet; +} + +void SwFrmSidebarWinContainer::getAll( const SwFrm& rFrm, + std::vector< Window* >* pSidebarWins ) +{ + pSidebarWins->clear(); + + FrmKey aFrmKey( &rFrm ); + FrmSidebarWinContainer::iterator aFrmIter = mpFrmSidebarWinContainer->find( aFrmKey ); + if ( aFrmIter != mpFrmSidebarWinContainer->end() ) + { + SidebarWinContainer& rSidebarWinContainer = (*aFrmIter).second; + for ( SidebarWinContainer::iterator aIter = rSidebarWinContainer.begin(); + aIter != rSidebarWinContainer.end(); + ++aIter ) + { + pSidebarWins->push_back( (*aIter).second ); + } + } +} + +} } // eof of namespace sw::sidebarwindows:: + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/frmsidebarwincontainer.hxx b/sw/source/uibase/docvw/frmsidebarwincontainer.hxx new file mode 100644 index 000000000000..225399360248 --- /dev/null +++ b/sw/source/uibase/docvw/frmsidebarwincontainer.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_FRMSIDEBARWINCONTAINER_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_FRMSIDEBARWINCONTAINER_HXX + +#include <sal/types.h> +#include <vector> + +class SwFrm; +class SwFmtFld; +class Window; + +namespace sw { namespace sidebarwindows { + +class SwSidebarWin; +class FrmSidebarWinContainer; + +class SwFrmSidebarWinContainer +{ + public: + SwFrmSidebarWinContainer(); + ~SwFrmSidebarWinContainer(); + + bool insert( const SwFrm& rFrm, + const SwFmtFld& rFmtFld, + SwSidebarWin& rSidebarWin ); + + bool remove( const SwFrm& rFrm, + const SwSidebarWin& rSidebarWin ); + + bool empty( const SwFrm& rFrm ); + + SwSidebarWin* get( const SwFrm& rFrm, + const sal_Int32 nIndex ); + + void getAll( const SwFrm& rFrm, + std::vector< Window* >* pSidebarWins ); + + private: + FrmSidebarWinContainer* mpFrmSidebarWinContainer; +}; + +} } // eof of namespace sw::sidebarwindows:: + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/romenu.cxx b/sw/source/uibase/docvw/romenu.cxx new file mode 100644 index 000000000000..37e6c32ea4d2 --- /dev/null +++ b/sw/source/uibase/docvw/romenu.cxx @@ -0,0 +1,368 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <hintids.hxx> + +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svtools/imap.hxx> +#include <svtools/inetimg.hxx> +#include <svtools/transfer.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/gallery.hxx> +#include <svx/graphichelper.hxx> +#include <editeng/brushitem.hxx> + +#include <frmatr.hxx> +#include <fmturl.hxx> +#include <fmtinfmt.hxx> +#include <docsh.hxx> +#include <view.hxx> +#include <wrtsh.hxx> +#include <viewopt.hxx> +#include <swmodule.hxx> +#include <romenu.hxx> +#include <pagedesc.hxx> +#include <modcfg.hxx> + +#include <cmdid.h> +#include <helpid.h> +#include <docvw.hrc> + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::sfx2; + +SwReadOnlyPopup::~SwReadOnlyPopup() +{ + delete pImageMap; + delete pTargetURL; +} + +void SwReadOnlyPopup::Check( sal_uInt16 nMID, sal_uInt16 nSID, SfxDispatcher &rDis ) +{ + SfxPoolItem *_pItem = 0; + SfxItemState eState = rDis.GetBindings()->QueryState( nSID, _pItem ); + if (eState >= SFX_ITEM_AVAILABLE) + { + EnableItem( nMID, true ); + if (_pItem) + { + CheckItem ( nMID, !_pItem->ISA(SfxVoidItem) && + _pItem->ISA(SfxBoolItem) && + ((SfxBoolItem*)_pItem)->GetValue()); + //remove full screen entry when not in full screen mode + if( SID_WIN_FULLSCREEN == nSID && !IsItemChecked(SID_WIN_FULLSCREEN) ) + EnableItem(nMID, false); + } + } + else + EnableItem( nMID, false ); + + delete _pItem; +} + +SwReadOnlyPopup::SwReadOnlyPopup( const Point &rDPos, SwView &rV ) : + PopupMenu( SW_RES(MN_READONLY_POPUP) ), + rView ( rV ), + rDocPos( rDPos ), + pImageMap( 0 ), + pTargetURL( 0 ) +{ + bGrfToGalleryAsLnk = SW_MOD()->GetModuleConfig()->IsGrfToGalleryAsLnk(); + SwWrtShell &rSh = rView.GetWrtShell(); + rSh.IsURLGrfAtPos( rDocPos, &sURL, &sTargetFrameName, &sDescription ); + if ( sURL.isEmpty() ) + { + SwContentAtPos aCntntAtPos( SwContentAtPos::SW_INETATTR ); + if( rSh.GetContentAtPos( rDocPos, aCntntAtPos, false)) + { + SwFmtINetFmt &rIItem = *(SwFmtINetFmt*)aCntntAtPos.aFnd.pAttr; + sURL = rIItem.GetValue(); + sTargetFrameName = rIItem.GetTargetFrame(); + sDescription = aCntntAtPos.sStr; + } + } + + bool bLink = false; + const Graphic *pGrf; + if ( 0 == (pGrf = rSh.GetGrfAtPos( rDocPos, sGrfName, bLink )) ) + { + EnableItem( MN_READONLY_SAVEGRAPHIC, false ); + EnableItem( MN_READONLY_COPYGRAPHIC, false ); + } + else + { + aGraphic = *pGrf; + const SwFrmFmt* pGrfFmt = rSh.GetFmtFromObj( rDocPos ); + const SfxPoolItem* pURLItem; + if( pGrfFmt && SFX_ITEM_SET == pGrfFmt->GetItemState( + RES_URL, true, &pURLItem )) + { + const SwFmtURL& rURL = *(SwFmtURL*)pURLItem; + if( rURL.GetMap() ) + pImageMap = new ImageMap( *rURL.GetMap() ); + else if( !rURL.GetURL().isEmpty() ) + pTargetURL = new INetImage( bLink ? sGrfName : OUString(), + rURL.GetURL(), + rURL.GetTargetFrameName(), + OUString(), Size() ); + } + } + + bool bEnableGraphicToGallery = bLink; + if ( bEnableGraphicToGallery ) + { + if (GalleryExplorer::FillThemeList( aThemeList )) + { + PopupMenu *pMenu = GetPopupMenu(MN_READONLY_GRAPHICTOGALLERY); + pMenu->CheckItem( MN_READONLY_TOGALLERYLINK, bGrfToGalleryAsLnk ); + pMenu->CheckItem( MN_READONLY_TOGALLERYCOPY, !bGrfToGalleryAsLnk ); + + for ( sal_uInt16 i=0; i < aThemeList.size(); ++i ) + pMenu->InsertItem( MN_READONLY_GRAPHICTOGALLERY+i + 3, aThemeList[ i ] ); + } + else + bEnableGraphicToGallery = false; + } + + EnableItem( MN_READONLY_GRAPHICTOGALLERY, bEnableGraphicToGallery ); + + SfxViewFrame * pVFrame = rV.GetViewFrame(); + SfxDispatcher &rDis = *pVFrame->GetDispatcher(); + const SwPageDesc &rDesc = rSh.GetPageDesc( rSh.GetCurPageDesc() ); + pItem = &rDesc.GetMaster().GetBackground(); + bool bEnableBackGallery = false, + bEnableBack = false; + + if ( GPOS_NONE != pItem->GetGraphicPos() ) + { + bEnableBack = true; + if ( !pItem->GetGraphicLink().isEmpty() ) + { + if ( aThemeList.empty() ) + GalleryExplorer::FillThemeList( aThemeList ); + + if ( !aThemeList.empty() ) + { + PopupMenu *pMenu = GetPopupMenu(MN_READONLY_BACKGROUNDTOGALLERY); + pMenu->CheckItem( MN_READONLY_TOGALLERYLINK, bGrfToGalleryAsLnk ); + pMenu->CheckItem( MN_READONLY_TOGALLERYCOPY, !bGrfToGalleryAsLnk ); + bEnableBackGallery = true; + + for ( sal_uInt16 i=0; i < aThemeList.size(); ++i ) + pMenu->InsertItem( MN_READONLY_GRAPHICTOGALLERY+i + 3, aThemeList[ i ] ); + } + } + } + EnableItem( MN_READONLY_SAVEBACKGROUND, bEnableBack ); + EnableItem( MN_READONLY_BACKGROUNDTOGALLERY, bEnableBackGallery ); + + if ( !rSh.GetViewOptions()->IsGraphic() ) + CheckItem( MN_READONLY_GRAPHICOFF ); + else + EnableItem( MN_READONLY_LOADGRAPHIC, false ); + + bool bReloadFrame = 0 != rSh.GetView().GetViewFrame()->GetFrame().GetParentFrame(); + EnableItem( MN_READONLY_RELOAD_FRAME, + bReloadFrame ); + EnableItem( MN_READONLY_RELOAD, !bReloadFrame); + + Check( MN_READONLY_EDITDOC, SID_EDITDOC, rDis ); + Check( MN_READONLY_SELECTION_MODE, FN_READONLY_SELECTION_MODE, rDis ); + Check( MN_READONLY_SOURCEVIEW, SID_SOURCEVIEW, rDis ); + Check( MN_READONLY_BROWSE_BACKWARD, SID_BROWSE_BACKWARD,rDis ); + Check( MN_READONLY_BROWSE_FORWARD, SID_BROWSE_FORWARD, rDis ); +#ifdef WNT + Check( MN_READONLY_PLUGINOFF, SID_PLUGINS_ACTIVE, rDis ); +#endif + Check( MN_READONLY_OPENURL, SID_OPENDOC, rDis ); + Check( MN_READONLY_OPENURLNEW, SID_OPENDOC, rDis ); + + SfxPoolItem* pState = NULL; + + SfxItemState eState = pVFrame->GetBindings().QueryState( SID_COPY, pState ); + Check( MN_READONLY_COPY, SID_COPY, rDis ); + if(eState < SFX_ITEM_AVAILABLE) + EnableItem( MN_READONLY_COPY, false ); + delete pState; + pState = NULL; + + eState = pVFrame->GetBindings().QueryState( SID_EDITDOC, pState ); + if ( + eState < SFX_ITEM_DEFAULT || + (rSh.IsGlobalDoc() && rView.GetDocShell()->IsReadOnlyUI()) + ) + { + EnableItem( MN_READONLY_EDITDOC, false ); + } + delete pState; + + if ( sURL.isEmpty() ) + { + EnableItem( MN_READONLY_OPENURL, false ); + EnableItem( MN_READONLY_OPENURLNEW, false ); + EnableItem( MN_READONLY_COPYLINK, false ); + } + Check( SID_WIN_FULLSCREEN, SID_WIN_FULLSCREEN, rDis ); + + RemoveDisabledEntries( true, true ); +} + +void SwReadOnlyPopup::Execute( Window* pWin, const Point &rPixPos ) +{ + sal_uInt16 nId = PopupMenu::Execute( + pWin, + rPixPos ); + Execute(pWin, nId); +} + +// execute the resulting ID only - necessary to support XContextMenuInterception +void SwReadOnlyPopup::Execute( Window* pWin, sal_uInt16 nId ) +{ + SwWrtShell &rSh = rView.GetWrtShell(); + SfxDispatcher &rDis = *rView.GetViewFrame()->GetDispatcher(); + if ( nId >= MN_READONLY_GRAPHICTOGALLERY ) + { + OUString sTmp; + sal_uInt16 nSaveId; + if ( nId >= MN_READONLY_BACKGROUNDTOGALLERY ) + { + nId -= MN_READONLY_BACKGROUNDTOGALLERY+3; + nSaveId = MN_READONLY_SAVEBACKGROUND; + sTmp = pItem->GetGraphicLink(); + } + else + { + nId -= MN_READONLY_GRAPHICTOGALLERY+3; + nSaveId = MN_READONLY_SAVEGRAPHIC; + sTmp = sGrfName; + } + if ( !bGrfToGalleryAsLnk ) + sTmp = SaveGraphic( nSaveId ); + + if ( !sTmp.isEmpty() ) + GalleryExplorer::InsertURL( aThemeList[nId], sTmp ); + + return; + } + + TransferDataContainer* pClipCntnr = 0; + + sal_uInt16 nExecId = USHRT_MAX; + sal_uInt16 nFilter = USHRT_MAX; + switch( nId ) + { + case SID_WIN_FULLSCREEN : nExecId = SID_WIN_FULLSCREEN; break; + case MN_READONLY_OPENURL: nFilter = URLLOAD_NOFILTER; break; + case MN_READONLY_OPENURLNEW: nFilter = URLLOAD_NEWVIEW; break; + case MN_READONLY_COPY: nExecId = SID_COPY; break; + + case MN_READONLY_EDITDOC: nExecId = SID_EDITDOC; break; + case MN_READONLY_SELECTION_MODE: nExecId = FN_READONLY_SELECTION_MODE; break; + case MN_READONLY_RELOAD: + case MN_READONLY_RELOAD_FRAME: + rSh.GetView().GetViewFrame()->GetDispatcher()->Execute(SID_RELOAD); + break; + + case MN_READONLY_BROWSE_BACKWARD: nExecId = SID_BROWSE_BACKWARD;break; + case MN_READONLY_BROWSE_FORWARD: nExecId = SID_BROWSE_FORWARD; break; + case MN_READONLY_SOURCEVIEW: nExecId = SID_SOURCEVIEW; break; + case MN_READONLY_SAVEGRAPHIC: + case MN_READONLY_SAVEBACKGROUND: + { + SaveGraphic( nId ); + break; + } + case MN_READONLY_COPYLINK: + pClipCntnr = new TransferDataContainer; + pClipCntnr->CopyString( sURL ); + break; + + case MN_READONLY_COPYGRAPHIC: + pClipCntnr = new TransferDataContainer; + pClipCntnr->CopyGraphic( aGraphic ); + + if( pImageMap ) + pClipCntnr->CopyImageMap( *pImageMap ); + if( pTargetURL ) + pClipCntnr->CopyINetImage( *pTargetURL ); + break; + + case MN_READONLY_LOADGRAPHIC: + { + bool bModified = rSh.IsModified(); + SwViewOption aOpt( *rSh.GetViewOptions() ); + aOpt.SetGraphic( true ); + rSh.ApplyViewOptions( aOpt ); + if(!bModified) + rSh.ResetModified(); + break; + } + case MN_READONLY_GRAPHICOFF: nExecId = FN_VIEW_GRAPHIC; break; +#ifdef WNT + case MN_READONLY_PLUGINOFF: nExecId = SID_PLUGINS_ACTIVE; break; +#endif + case MN_READONLY_TOGALLERYLINK: + SW_MOD()->GetModuleConfig()->SetGrfToGalleryAsLnk( true ); + break; + case MN_READONLY_TOGALLERYCOPY: + SW_MOD()->GetModuleConfig()->SetGrfToGalleryAsLnk( false ); + break; + + default: //forward the id to the SfxBindings + nExecId = nId; + } + if( USHRT_MAX != nExecId ) + rDis.GetBindings()->Execute( nExecId ); + if( USHRT_MAX != nFilter ) + ::LoadURL(rSh, sURL, nFilter, sTargetFrameName); + + if( pClipCntnr ) + { + ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > xRef( pClipCntnr ); + if( pClipCntnr->HasAnyData() ) + pClipCntnr->CopyToClipboard( pWin ); + } +} + +OUString SwReadOnlyPopup::SaveGraphic( sal_uInt16 nId ) +{ + // fish out the graphic's name + if ( MN_READONLY_SAVEBACKGROUND == nId ) + { + if ( !pItem->GetGraphicLink().isEmpty() ) + sGrfName = pItem->GetGraphicLink(); + ((SvxBrushItem*)pItem)->SetDoneLink( Link() ); + const Graphic *pGrf = pItem->GetGraphic(); + if ( pGrf ) + { + aGraphic = *pGrf; + if ( !pItem->GetGraphicLink().isEmpty() ) + sGrfName = pItem->GetGraphicLink(); + } + else + return OUString(); + } + return GraphicHelper::ExportGraphic( aGraphic, sGrfName ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/romenu.hxx b/sw/source/uibase/docvw/romenu.hxx new file mode 100644 index 000000000000..eae84d594181 --- /dev/null +++ b/sw/source/uibase/docvw/romenu.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ +#ifndef INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ROMENU_HXX +#define INCLUDED_SW_SOURCE_CORE_UIBASE_DOCVW_ROMENU_HXX + +#include <vcl/graph.hxx> +#include <vcl/menu.hxx> +#include <svl/stritem.hxx> + +class SwView; +class SfxDispatcher; +class SvxBrushItem; +class ImageMap; +class INetImage; + +class SwReadOnlyPopup : public PopupMenu +{ + SwView &rView; + const SvxBrushItem *pItem; + const Point &rDocPos; + Graphic aGraphic; + OUString sURL, + sTargetFrameName, + sDescription; + OUString sGrfName; + std::vector<OUString> aThemeList; + bool bGrfToGalleryAsLnk; + ImageMap* pImageMap; + INetImage* pTargetURL; + + void Check( sal_uInt16 nMID, sal_uInt16 nSID, SfxDispatcher &rDis ); + OUString SaveGraphic( sal_uInt16 nId ); + + using PopupMenu::Execute; + +public: + SwReadOnlyPopup( const Point &rDPos, SwView &rV ); + virtual ~SwReadOnlyPopup(); + + void Execute( Window* pWin, const Point &rPPos ); + void Execute( Window* pWin, sal_uInt16 nId ); +}; + +void GetPreferredExtension( OUString &rExt, const Graphic &rGrf ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/srcedtw.cxx b/sw/source/uibase/docvw/srcedtw.cxx new file mode 100644 index 000000000000..353780925449 --- /dev/null +++ b/sw/source/uibase/docvw/srcedtw.cxx @@ -0,0 +1,993 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <hintids.hxx> +#include <cmdid.h> + +#include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertiesChangeListener.hpp> +#include <cppuhelper/implbase1.hxx> +#include <officecfg/Office/Common.hxx> +#include <rtl/ustring.hxx> +#include <sal/log.hxx> +#include <vcl/textview.hxx> +#include <svx/svxids.hrc> +#include <vcl/scrbar.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/app.hxx> +#include <svtools/htmltokn.h> +#include <vcl/txtattr.hxx> +#include <vcl/settings.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/flstitem.hxx> +#include <vcl/metric.hxx> +#include <svtools/ctrltool.hxx> +#include <tools/time.hxx> +#include <swmodule.hxx> +#include <docsh.hxx> +#include <srcview.hxx> +#include <helpid.h> +#include <deque> + +struct SwTextPortion +{ + sal_uInt16 nLine; + sal_uInt16 nStart, nEnd; + svtools::ColorConfigEntry eType; +}; + +#define MAX_SYNTAX_HIGHLIGHT 20 +#define MAX_HIGHLIGHTTIME 200 +#define SYNTAX_HIGHLIGHT_TIMEOUT 200 + +typedef std::deque<SwTextPortion> SwTextPortions; + +static void lcl_Highlight(const OUString& rSource, SwTextPortions& aPortionList) +{ + const sal_Unicode cOpenBracket = '<'; + const sal_Unicode cCloseBracket= '>'; + const sal_Unicode cSlash = '/'; + const sal_Unicode cExclamation = '!'; + const sal_Unicode cMinus = '-'; + const sal_Unicode cSpace = ' '; + const sal_Unicode cTab = 0x09; + const sal_Unicode cLF = 0x0a; + const sal_Unicode cCR = 0x0d; + + const sal_uInt16 nStrLen = rSource.getLength(); + sal_uInt16 nInsert = 0; // number of inserted portions + sal_uInt16 nActPos = 0; // position, where '<' was found + sal_uInt16 nOffset = 0; // Offset of nActPos to '<' + sal_uInt16 nPortStart = USHRT_MAX; // for the TextPortion + sal_uInt16 nPortEnd = 0; + SwTextPortion aText; + while(nActPos < nStrLen) + { + svtools::ColorConfigEntry eFoundType = svtools::HTMLUNKNOWN; + if((nActPos < nStrLen - 2) && (rSource[nActPos] == cOpenBracket)) + { + // insert 'empty' portion + if(nPortEnd < nActPos - 1 ) + { + aText.nLine = 0; + // don't move at the beginning + aText.nStart = nPortEnd; + if(nInsert) + aText.nStart += 1; + aText.nEnd = nActPos - 1; + aText.eType = svtools::HTMLUNKNOWN; + aPortionList.push_back( aText ); + nInsert++; + } + sal_Unicode cFollowFirst = rSource[nActPos + 1]; + sal_Unicode cFollowNext = rSource[nActPos + 2]; + if(cExclamation == cFollowFirst) + { + // "<!" SGML or comment + if(cMinus == cFollowNext && + nActPos < nStrLen - 3 && cMinus == rSource[nActPos + 3]) + { + eFoundType = svtools::HTMLCOMMENT; + } + else + eFoundType = svtools::HTMLSGML; + nPortStart = nActPos; + nPortEnd = nActPos + 1; + } + else if(cSlash == cFollowFirst) + { + // "</" ignore slash + nPortStart = nActPos; + nActPos++; + nOffset++; + } + if(svtools::HTMLUNKNOWN == eFoundType) + { + // now here a keyword could follow + sal_uInt16 nSrchPos = nActPos; + while(++nSrchPos < nStrLen - 1) + { + sal_Unicode cNext = rSource[nSrchPos]; + if( cNext == cSpace || + cNext == cTab || + cNext == cLF || + cNext == cCR) + break; + else if(cNext == cCloseBracket) + { + break; + } + } + if(nSrchPos > nActPos + 1) + { + // some string was found + OUString sToken = rSource.copy(nActPos + 1, nSrchPos - nActPos - 1 ); + sToken = sToken.toAsciiUpperCase(); + int nToken = ::GetHTMLToken(sToken); + if(nToken) + { + // Token was found + eFoundType = svtools::HTMLKEYWORD; + nPortEnd = nSrchPos; + nPortStart = nActPos; + } + else + { + // what was that? + SAL_WARN( + "sw.level2", + "Token " << sToken + << " not recognised!"); + } + + } + } + // now we still have to look for '>' + if(svtools::HTMLUNKNOWN != eFoundType) + { + bool bFound = false; + for(sal_uInt16 i = nPortEnd; i < nStrLen; i++) + if(cCloseBracket == rSource[i]) + { + bFound = true; + nPortEnd = i; + break; + } + if(!bFound && (eFoundType == svtools::HTMLCOMMENT)) + { + // comment without ending in this line + bFound = true; + nPortEnd = nStrLen - 1; + } + + if(bFound ||(eFoundType == svtools::HTMLCOMMENT)) + { + SwTextPortion aTextPortion; + aTextPortion.nLine = 0; + aTextPortion.nStart = nPortStart + 1; + aTextPortion.nEnd = nPortEnd; + aTextPortion.eType = eFoundType; + aPortionList.push_back( aTextPortion ); + nInsert++; + eFoundType = svtools::HTMLUNKNOWN; + } + + } + } + nActPos++; + } + if(nInsert && nPortEnd < nActPos - 1) + { + aText.nLine = 0; + aText.nStart = nPortEnd + 1; + aText.nEnd = nActPos - 1; + aText.eType = svtools::HTMLUNKNOWN; + aPortionList.push_back( aText ); + nInsert++; + } +} + +class SwSrcEditWindow::ChangesListener: + public cppu::WeakImplHelper1< css::beans::XPropertiesChangeListener > +{ +public: + ChangesListener(SwSrcEditWindow & editor): editor_(editor) {} + +private: + virtual ~ChangesListener() {} + + virtual void SAL_CALL disposing(css::lang::EventObject const &) + throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + osl::MutexGuard g(editor_.mutex_); + editor_.notifier_.clear(); + } + + virtual void SAL_CALL propertiesChange( + css::uno::Sequence< css::beans::PropertyChangeEvent > const &) + throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE + { + SolarMutexGuard g; + editor_.SetFont(); + } + + SwSrcEditWindow & editor_; +}; + +SwSrcEditWindow::SwSrcEditWindow( Window* pParent, SwSrcView* pParentView ) : + Window( pParent, WB_BORDER|WB_CLIPCHILDREN ), + + pTextEngine(0), + + pOutWin(0), + pHScrollbar(0), + pVScrollbar(0), + + pSrcView(pParentView), + + nCurTextWidth(0), + nStartLine(USHRT_MAX), + eSourceEncoding(osl_getThreadTextEncoding()), + bDoSyntaxHighlight(true), + bHighlighting(false) +{ + SetHelpId(HID_SOURCE_EDITWIN); + CreateTextEngine(); + + // Using "this" in ctor is a little fishy, but should work here at least as + // long as there are no derivations: + listener_ = new ChangesListener(*this); + css::uno::Reference< css::beans::XMultiPropertySet > n( + officecfg::Office::Common::Font::SourceViewFont::get(), + css::uno::UNO_QUERY_THROW); + { + osl::MutexGuard g(mutex_); + notifier_ = n; + } + css::uno::Sequence< OUString > s(2); + s[0] = "FontHeight"; + s[1] = "FontName"; + n->addPropertiesChangeListener(s, listener_.get()); +} + + SwSrcEditWindow::~SwSrcEditWindow() +{ + css::uno::Reference< css::beans::XMultiPropertySet > n; + { + osl::MutexGuard g(mutex_); + n = notifier_; + } + if (n.is()) { + n->removePropertiesChangeListener(listener_.get()); + } + aSyntaxIdleTimer.Stop(); + if ( pTextEngine ) + { + EndListening( *pTextEngine ); + pTextEngine->RemoveView( pTextView ); + + delete pHScrollbar; + delete pVScrollbar; + + delete pTextView; + delete pTextEngine; + } + delete pOutWin; +} + +void SwSrcEditWindow::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + switch ( rDCEvt.GetType() ) + { + case DATACHANGED_SETTINGS: + // newly rearrange ScrollBars or trigger Resize, because + // ScrollBar size could have changed. For this, in the + // Resize handler the size of ScrollBars has to be queried + // from the settings as well. + if( rDCEvt.GetFlags() & SETTINGS_STYLE ) + Resize(); + break; + } +} + +void SwSrcEditWindow::Resize() +{ + // ScrollBars, etc. happens in Adjust... + if ( pTextView ) + { + long nVisY = pTextView->GetStartDocPos().Y(); + pTextView->ShowCursor(); + Size aOutSz( GetOutputSizePixel() ); + long nMaxVisAreaStart = pTextView->GetTextEngine()->GetTextHeight() - aOutSz.Height(); + if ( nMaxVisAreaStart < 0 ) + nMaxVisAreaStart = 0; + if ( pTextView->GetStartDocPos().Y() > nMaxVisAreaStart ) + { + Point aStartDocPos( pTextView->GetStartDocPos() ); + aStartDocPos.Y() = nMaxVisAreaStart; + pTextView->SetStartDocPos( aStartDocPos ); + pTextView->ShowCursor(); + } + long nScrollStd = GetSettings().GetStyleSettings().GetScrollBarSize(); + Size aScrollSz(aOutSz.Width() - nScrollStd, nScrollStd ); + Point aScrollPos(0, aOutSz.Height() - nScrollStd); + + pHScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); + + aScrollSz.Width() = aScrollSz.Height(); + aScrollSz.Height() = aOutSz.Height(); + aScrollPos = Point(aOutSz.Width() - nScrollStd, 0); + + pVScrollbar->SetPosSizePixel( aScrollPos, aScrollSz); + aOutSz.Width() -= nScrollStd; + aOutSz.Height() -= nScrollStd; + pOutWin->SetOutputSizePixel(aOutSz); + InitScrollBars(); + + // set line in first Resize + if(USHRT_MAX != nStartLine) + { + if(nStartLine < pTextEngine->GetParagraphCount()) + { + TextSelection aSel(TextPaM( nStartLine, 0 ), TextPaM( nStartLine, 0x0 )); + pTextView->SetSelection(aSel); + pTextView->ShowCursor(); + } + nStartLine = USHRT_MAX; + } + + if ( nVisY != pTextView->GetStartDocPos().Y() ) + Invalidate(); + } + +} + +void TextViewOutWin::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + + switch( rDCEvt.GetType() ) + { + case DATACHANGED_SETTINGS: + // query settings + if( rDCEvt.GetFlags() & SETTINGS_STYLE ) + { + const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); + SetBackground( rCol ); + Font aFont( pTextView->GetTextEngine()->GetFont() ); + aFont.SetFillColor( rCol ); + pTextView->GetTextEngine()->SetFont( aFont ); + } + break; + } +} + +void TextViewOutWin::MouseMove( const MouseEvent &rEvt ) +{ + if ( pTextView ) + pTextView->MouseMove( rEvt ); +} + +void TextViewOutWin::MouseButtonUp( const MouseEvent &rEvt ) +{ + if ( pTextView ) + { + pTextView->MouseButtonUp( rEvt ); + SfxBindings& rBindings = ((SwSrcEditWindow*)GetParent())->GetSrcView()->GetViewFrame()->GetBindings(); + rBindings.Invalidate( SID_TABLE_CELL ); + rBindings.Invalidate( SID_CUT ); + rBindings.Invalidate( SID_COPY ); + } +} + +void TextViewOutWin::MouseButtonDown( const MouseEvent &rEvt ) +{ + GrabFocus(); + if ( pTextView ) + pTextView->MouseButtonDown( rEvt ); +} + +void TextViewOutWin::Command( const CommandEvent& rCEvt ) +{ + switch(rCEvt.GetCommand()) + { + case COMMAND_CONTEXTMENU: + ((SwSrcEditWindow*)GetParent())->GetSrcView()->GetViewFrame()-> + GetDispatcher()->ExecutePopup(); + break; + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + { + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) + { + ((SwSrcEditWindow*)GetParent())->HandleWheelCommand( rCEvt ); + } + } + break; + + default: + if ( pTextView ) + pTextView->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +void TextViewOutWin::KeyInput( const KeyEvent& rKEvt ) +{ + bool bDone = false; + SwSrcEditWindow* pSrcEditWin = (SwSrcEditWindow*)GetParent(); + bool bChange = !pSrcEditWin->IsReadonly() || !TextEngine::DoesKeyChangeText( rKEvt ); + if(bChange) + bDone = pTextView->KeyInput( rKEvt ); + + SfxBindings& rBindings = ((SwSrcEditWindow*)GetParent())->GetSrcView()->GetViewFrame()->GetBindings(); + if ( !bDone ) + { + if ( !SfxViewShell::Current()->KeyInput( rKEvt ) ) + Window::KeyInput( rKEvt ); + } + else + { + rBindings.Invalidate( SID_TABLE_CELL ); + if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) + rBindings.Update( SID_BASICIDE_STAT_POS ); + if (pSrcEditWin->GetTextEngine()->IsModified() ) + { + rBindings.Invalidate( SID_SAVEDOC ); + rBindings.Invalidate( SID_DOC_MODIFIED ); + } + if( rKEvt.GetKeyCode().GetCode() == KEY_INSERT ) + rBindings.Invalidate( SID_ATTR_INSERT ); + } + + rBindings.Invalidate( SID_CUT ); + rBindings.Invalidate( SID_COPY ); + + SwDocShell* pDocShell = pSrcEditWin->GetSrcView()->GetDocShell(); + if(pSrcEditWin->GetTextEngine()->IsModified()) + { + pDocShell->SetModified(); + } +} + +void TextViewOutWin::Paint( const Rectangle& rRect ) +{ + pTextView->Paint( rRect ); +} + +void SwSrcEditWindow::CreateTextEngine() +{ + const Color &rCol = GetSettings().GetStyleSettings().GetWindowColor(); + pOutWin = new TextViewOutWin(this, 0); + pOutWin->SetBackground(Wallpaper(rCol)); + pOutWin->SetPointer(Pointer(POINTER_TEXT)); + pOutWin->Show(); + + // create Scrollbars + pHScrollbar = new ScrollBar(this, WB_3DLOOK |WB_HSCROLL|WB_DRAG); + pHScrollbar->EnableRTL( false ); // --- RTL --- no mirroring for scrollbars + pHScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + pHScrollbar->Show(); + + pVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); + pVScrollbar->EnableRTL( false ); // --- RTL --- no mirroring for scrollbars + pVScrollbar->SetScrollHdl(LINK(this, SwSrcEditWindow, ScrollHdl)); + pHScrollbar->EnableDrag(); + pVScrollbar->Show(); + + pTextEngine = new ExtTextEngine; + pTextView = new ExtTextView( pTextEngine, pOutWin ); + pTextView->SetAutoIndentMode(true); + pOutWin->SetTextView(pTextView); + + pTextEngine->SetUpdateMode( false ); + pTextEngine->InsertView( pTextView ); + + Font aFont; + aFont.SetTransparent( false ); + aFont.SetFillColor( rCol ); + SetPointFont( aFont ); + aFont = GetFont(); + aFont.SetFillColor( rCol ); + pOutWin->SetFont( aFont ); + pTextEngine->SetFont( aFont ); + + aSyntaxIdleTimer.SetTimeout( SYNTAX_HIGHLIGHT_TIMEOUT ); + aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, SwSrcEditWindow, SyntaxTimerHdl ) ); + + pTextEngine->EnableUndo( true ); + pTextEngine->SetUpdateMode( true ); + + pTextView->ShowCursor( true, true ); + InitScrollBars(); + StartListening( *pTextEngine ); + + SfxBindings& rBind = GetSrcView()->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_TABLE_CELL ); +} + +void SwSrcEditWindow::SetScrollBarRanges() +{ + // Extra method, not InitScrollBars, because also for TextEngine events. + + pHScrollbar->SetRange( Range( 0, nCurTextWidth-1 ) ); + pVScrollbar->SetRange( Range(0, pTextEngine->GetTextHeight()-1) ); +} + +void SwSrcEditWindow::InitScrollBars() +{ + SetScrollBarRanges(); + + Size aOutSz( pOutWin->GetOutputSizePixel() ); + pVScrollbar->SetVisibleSize( aOutSz.Height() ); + pVScrollbar->SetPageSize( aOutSz.Height() * 8 / 10 ); + pVScrollbar->SetLineSize( pOutWin->GetTextHeight() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + pHScrollbar->SetVisibleSize( aOutSz.Width() ); + pHScrollbar->SetPageSize( aOutSz.Width() * 8 / 10 ); + pHScrollbar->SetLineSize( pOutWin->GetTextWidth(OUString('x')) ); + pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); + +} + +IMPL_LINK(SwSrcEditWindow, ScrollHdl, ScrollBar*, pScroll) +{ + if(pScroll == pVScrollbar) + { + long nDiff = pTextView->GetStartDocPos().Y() - pScroll->GetThumbPos(); + GetTextView()->Scroll( 0, nDiff ); + pTextView->ShowCursor( false, true ); + pScroll->SetThumbPos( pTextView->GetStartDocPos().Y() ); + } + else + { + long nDiff = pTextView->GetStartDocPos().X() - pScroll->GetThumbPos(); + GetTextView()->Scroll( nDiff, 0 ); + pTextView->ShowCursor( false, true ); + pScroll->SetThumbPos( pTextView->GetStartDocPos().X() ); + } + GetSrcView()->GetViewFrame()->GetBindings().Invalidate( SID_TABLE_CELL ); + return 0; +} + +IMPL_LINK( SwSrcEditWindow, SyntaxTimerHdl, Timer *, pTimer ) +{ + Time aSyntaxCheckStart( Time::SYSTEM ); + SAL_WARN_IF(pTextView == 0, "sw", "No View yet, but syntax highlighting?!"); + + bHighlighting = true; + sal_uInt16 nCount = 0; + // at first the region around the cursor is processed + TextSelection aSel = pTextView->GetSelection(); + sal_uInt16 nCur = (sal_uInt16)aSel.GetStart().GetPara(); + if(nCur > 40) + nCur -= 40; + else + nCur = 0; + if(!aSyntaxLineTable.empty()) + for(sal_uInt16 i = 0; i < 80 && nCount < 40; i++, nCur++) + { + if(aSyntaxLineTable.find(nCur) != aSyntaxLineTable.end()) + { + DoSyntaxHighlight( nCur ); + aSyntaxLineTable.erase( nCur ); + nCount++; + if(aSyntaxLineTable.empty()) + break; + if((Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime()) > MAX_HIGHLIGHTTIME ) + { + pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); + break; + } + } + } + + // when there is still anything left by then, go on from the beginning + while ( !aSyntaxLineTable.empty() && nCount < MAX_SYNTAX_HIGHLIGHT) + { + sal_uInt16 nLine = *aSyntaxLineTable.begin(); + DoSyntaxHighlight( nLine ); + aSyntaxLineTable.erase(nLine); + nCount ++; + if(Time( Time::SYSTEM ).GetTime() - aSyntaxCheckStart.GetTime() > MAX_HIGHLIGHTTIME) + { + pTimer->SetTimeout( 2 * SYNTAX_HIGHLIGHT_TIMEOUT ); + break; + } + } + + if(!aSyntaxLineTable.empty() && !pTimer->IsActive()) + pTimer->Start(); + // SyntaxTimerHdl is called when text changed + // => good opportunity to determine text width! + long nPrevTextWidth = nCurTextWidth; + nCurTextWidth = pTextEngine->CalcTextWidth() + 25; // kleine Toleranz + if ( nCurTextWidth != nPrevTextWidth ) + SetScrollBarRanges(); + bHighlighting = false; + + return 0; +} + +void SwSrcEditWindow::DoSyntaxHighlight( sal_uInt16 nPara ) +{ + // Because of DelayedSyntaxHighlight it could happen, + // that the line doesn't exist anymore! + if ( nPara < pTextEngine->GetParagraphCount() ) + { + bool bTempModified = IsModified(); + pTextEngine->RemoveAttribs( nPara, true ); + OUString aSource( pTextEngine->GetText( nPara ) ); + pTextEngine->SetUpdateMode( false ); + ImpDoHighlight( aSource, nPara ); + TextView* pTmp = pTextEngine->GetActiveView(); + pTmp->SetAutoScroll(false); + pTextEngine->SetActiveView(0); + pTextEngine->SetUpdateMode( true ); + pTextEngine->SetActiveView(pTmp); + pTmp->SetAutoScroll(true); + pTmp->ShowCursor( false/*pTmp->IsAutoScroll()*/ ); + + if(!bTempModified) + ClearModifyFlag(); + } +} + +void SwSrcEditWindow::DoDelayedSyntaxHighlight( sal_uInt16 nPara ) +{ + if ( !bHighlighting && bDoSyntaxHighlight ) + { + aSyntaxLineTable.insert( nPara ); + aSyntaxIdleTimer.Start(); + } +} + +void SwSrcEditWindow::ImpDoHighlight( const OUString& rSource, sal_uInt16 nLineOff ) +{ + SwTextPortions aPortionList; + lcl_Highlight(rSource, aPortionList); + + size_t nCount = aPortionList.size(); + if ( !nCount ) + return; + + SwTextPortion& rLast = aPortionList[nCount-1]; + if ( rLast.nStart > rLast.nEnd ) // Only until Bug from MD is resolved + { + nCount--; + aPortionList.pop_back(); + if ( !nCount ) + return; + } + + { + // Only blanks and tabs have to be attributed along. + // When two identical attributes are placed consecutively, + // it optimises the TextEngine. + sal_uInt16 nLastEnd = 0; + + for ( size_t i = 0; i < nCount; i++ ) + { + SwTextPortion& r = aPortionList[i]; + SAL_WARN_IF( + r.nLine != aPortionList[0].nLine, "sw.level2", + "multiple lines after all?"); + if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved + continue; + + if ( r.nStart > nLastEnd ) + { + // Can I rely on the fact that all except blank and tab + // are being highlighted?! + r.nStart = nLastEnd; + } + nLastEnd = r.nEnd+1; + if ( ( i == (nCount-1) ) && ( r.nEnd < rSource.getLength() ) ) + r.nEnd = rSource.getLength(); + } + } + + for ( size_t i = 0; i < aPortionList.size(); i++ ) + { + SwTextPortion& r = aPortionList[i]; + if ( r.nStart > r.nEnd ) // only until Bug from MD is resolved + continue; + if(r.eType != svtools::HTMLSGML && + r.eType != svtools::HTMLCOMMENT && + r.eType != svtools::HTMLKEYWORD && + r.eType != svtools::HTMLUNKNOWN) + r.eType = svtools::HTMLUNKNOWN; + Color aColor((ColorData)SW_MOD()->GetColorConfig().GetColorValue((svtools::ColorConfigEntry)r.eType).nColor); + sal_uInt16 nLine = nLineOff+r.nLine; + pTextEngine->SetAttrib( TextAttribFontColor( aColor ), nLine, r.nStart, r.nEnd+1, true ); + } +} + +void SwSrcEditWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + if ( rHint.ISA( TextHint ) ) + { + const TextHint& rTextHint = (const TextHint&)rHint; + if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED ) + { + pHScrollbar->SetThumbPos( pTextView->GetStartDocPos().X() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + } + else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED ) + { + if ( (long)pTextEngine->GetTextHeight() < pOutWin->GetOutputSizePixel().Height() ) + pTextView->Scroll( 0, pTextView->GetStartDocPos().Y() ); + pVScrollbar->SetThumbPos( pTextView->GetStartDocPos().Y() ); + SetScrollBarRanges(); + } + else if( ( rTextHint.GetId() == TEXT_HINT_PARAINSERTED ) || + ( rTextHint.GetId() == TEXT_HINT_PARACONTENTCHANGED ) ) + { + DoDelayedSyntaxHighlight( (sal_uInt16)rTextHint.GetValue() ); + } + } +} + +void SwSrcEditWindow::Invalidate(sal_uInt16 ) +{ + pOutWin->Invalidate(); + Window::Invalidate(); + +} + +void SwSrcEditWindow::Command( const CommandEvent& rCEvt ) +{ + switch(rCEvt.GetCommand()) + { + case COMMAND_WHEEL: + case COMMAND_STARTAUTOSCROLL: + case COMMAND_AUTOSCROLL: + { + const CommandWheelData* pWData = rCEvt.GetWheelData(); + if( !pWData || COMMAND_WHEEL_ZOOM != pWData->GetMode() ) + HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); + } + break; + default: + Window::Command(rCEvt); + } +} + +void SwSrcEditWindow::HandleWheelCommand( const CommandEvent& rCEvt ) +{ + pTextView->Command(rCEvt); + HandleScrollCommand( rCEvt, pHScrollbar, pVScrollbar ); +} + +void SwSrcEditWindow::GetFocus() +{ + pOutWin->GrabFocus(); +} + +static bool lcl_GetLanguagesForEncoding(rtl_TextEncoding eEnc, LanguageType aLanguages[]) +{ + switch(eEnc) + { + case RTL_TEXTENCODING_UTF7 : + case RTL_TEXTENCODING_UTF8 : + // don#t fill - all LANGUAGE_SYSTEM means unicode font has to be used + break; + + case RTL_TEXTENCODING_ISO_8859_3: + case RTL_TEXTENCODING_ISO_8859_1 : + case RTL_TEXTENCODING_MS_1252 : + case RTL_TEXTENCODING_APPLE_ROMAN : + case RTL_TEXTENCODING_IBM_850 : + case RTL_TEXTENCODING_ISO_8859_14 : + case RTL_TEXTENCODING_ISO_8859_15 : + //fill with western languages + aLanguages[0] = LANGUAGE_GERMAN; + aLanguages[1] = LANGUAGE_FRENCH; + aLanguages[2] = LANGUAGE_ITALIAN; + aLanguages[3] = LANGUAGE_SPANISH; + break; + + case RTL_TEXTENCODING_IBM_865 : + //scandinavian + aLanguages[0] = LANGUAGE_FINNISH; + aLanguages[1] = LANGUAGE_NORWEGIAN; + aLanguages[2] = LANGUAGE_SWEDISH; + aLanguages[3] = LANGUAGE_DANISH; + break; + + case RTL_TEXTENCODING_ISO_8859_10 : + case RTL_TEXTENCODING_ISO_8859_13 : + case RTL_TEXTENCODING_ISO_8859_2 : + case RTL_TEXTENCODING_IBM_852 : + case RTL_TEXTENCODING_MS_1250 : + case RTL_TEXTENCODING_APPLE_CENTEURO : + aLanguages[0] = LANGUAGE_POLISH; + aLanguages[1] = LANGUAGE_CZECH; + aLanguages[2] = LANGUAGE_HUNGARIAN; + aLanguages[3] = LANGUAGE_SLOVAK; + break; + + case RTL_TEXTENCODING_ISO_8859_4 : + case RTL_TEXTENCODING_IBM_775 : + case RTL_TEXTENCODING_MS_1257 : + aLanguages[0] = LANGUAGE_LATVIAN ; + aLanguages[1] = LANGUAGE_LITHUANIAN; + aLanguages[2] = LANGUAGE_ESTONIAN ; + break; + + case RTL_TEXTENCODING_IBM_863 : aLanguages[0] = LANGUAGE_FRENCH_CANADIAN; break; + case RTL_TEXTENCODING_APPLE_FARSI : aLanguages[0] = LANGUAGE_FARSI; break; + case RTL_TEXTENCODING_APPLE_ROMANIAN:aLanguages[0] = LANGUAGE_ROMANIAN; break; + + case RTL_TEXTENCODING_IBM_861 : + case RTL_TEXTENCODING_APPLE_ICELAND : + aLanguages[0] = LANGUAGE_ICELANDIC; + break; + + case RTL_TEXTENCODING_APPLE_CROATIAN:aLanguages[0] = LANGUAGE_CROATIAN; break; + + case RTL_TEXTENCODING_IBM_437 : + case RTL_TEXTENCODING_ASCII_US : aLanguages[0] = LANGUAGE_ENGLISH; break; + + case RTL_TEXTENCODING_IBM_862 : + case RTL_TEXTENCODING_MS_1255 : + case RTL_TEXTENCODING_APPLE_HEBREW : + case RTL_TEXTENCODING_ISO_8859_8 : + aLanguages[0] = LANGUAGE_HEBREW; + break; + + case RTL_TEXTENCODING_IBM_857 : + case RTL_TEXTENCODING_MS_1254 : + case RTL_TEXTENCODING_APPLE_TURKISH: + case RTL_TEXTENCODING_ISO_8859_9 : + aLanguages[0] = LANGUAGE_TURKISH; + break; + + case RTL_TEXTENCODING_IBM_860 : + aLanguages[0] = LANGUAGE_PORTUGUESE; + break; + + case RTL_TEXTENCODING_IBM_869 : + case RTL_TEXTENCODING_MS_1253 : + case RTL_TEXTENCODING_APPLE_GREEK : + case RTL_TEXTENCODING_ISO_8859_7 : + case RTL_TEXTENCODING_IBM_737 : + aLanguages[0] = LANGUAGE_GREEK; + break; + + case RTL_TEXTENCODING_KOI8_R : + case RTL_TEXTENCODING_ISO_8859_5 : + case RTL_TEXTENCODING_IBM_855 : + case RTL_TEXTENCODING_MS_1251 : + case RTL_TEXTENCODING_IBM_866 : + case RTL_TEXTENCODING_APPLE_CYRILLIC : + aLanguages[0] = LANGUAGE_RUSSIAN; + break; + + case RTL_TEXTENCODING_APPLE_UKRAINIAN: + case RTL_TEXTENCODING_KOI8_U: + aLanguages[0] = LANGUAGE_UKRAINIAN; + break; + + case RTL_TEXTENCODING_IBM_864 : + case RTL_TEXTENCODING_MS_1256 : + case RTL_TEXTENCODING_ISO_8859_6 : + case RTL_TEXTENCODING_APPLE_ARABIC : + aLanguages[0] = LANGUAGE_ARABIC_SAUDI_ARABIA; + break; + + case RTL_TEXTENCODING_APPLE_CHINTRAD : + case RTL_TEXTENCODING_MS_950 : + case RTL_TEXTENCODING_GBT_12345 : + case RTL_TEXTENCODING_BIG5 : + case RTL_TEXTENCODING_EUC_TW : + case RTL_TEXTENCODING_BIG5_HKSCS : + aLanguages[0] = LANGUAGE_CHINESE_TRADITIONAL; + break; + + case RTL_TEXTENCODING_EUC_JP : + case RTL_TEXTENCODING_ISO_2022_JP : + case RTL_TEXTENCODING_JIS_X_0201 : + case RTL_TEXTENCODING_JIS_X_0208 : + case RTL_TEXTENCODING_JIS_X_0212 : + case RTL_TEXTENCODING_APPLE_JAPANESE : + case RTL_TEXTENCODING_MS_932 : + case RTL_TEXTENCODING_SHIFT_JIS : + aLanguages[0] = LANGUAGE_JAPANESE; + break; + + case RTL_TEXTENCODING_GB_2312 : + case RTL_TEXTENCODING_MS_936 : + case RTL_TEXTENCODING_GBK : + case RTL_TEXTENCODING_GB_18030 : + case RTL_TEXTENCODING_APPLE_CHINSIMP : + case RTL_TEXTENCODING_EUC_CN : + case RTL_TEXTENCODING_ISO_2022_CN : + aLanguages[0] = LANGUAGE_CHINESE_SIMPLIFIED; + break; + + case RTL_TEXTENCODING_APPLE_KOREAN : + case RTL_TEXTENCODING_MS_949 : + case RTL_TEXTENCODING_EUC_KR : + case RTL_TEXTENCODING_ISO_2022_KR : + case RTL_TEXTENCODING_MS_1361 : + aLanguages[0] = LANGUAGE_KOREAN; + break; + + case RTL_TEXTENCODING_APPLE_THAI : + case RTL_TEXTENCODING_MS_874 : + case RTL_TEXTENCODING_TIS_620 : + aLanguages[0] = LANGUAGE_THAI; + break; + default: aLanguages[0] = Application::GetSettings().GetUILanguageTag().getLanguageType(); + } + return aLanguages[0] != LANGUAGE_SYSTEM; +} +void SwSrcEditWindow::SetFont() +{ + OUString sFontName( + officecfg::Office::Common::Font::SourceViewFont::FontName::get(). + get_value_or(OUString())); + if(sFontName.isEmpty()) + { + LanguageType aLanguages[5] = + { + LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM, LANGUAGE_SYSTEM + }; + Font aFont; + if(lcl_GetLanguagesForEncoding(eSourceEncoding, aLanguages)) + { + //TODO: check for multiple languages + aFont = OutputDevice::GetDefaultFont(DEFAULTFONT_FIXED, aLanguages[0], 0, this); + } + else + aFont = OutputDevice::GetDefaultFont(DEFAULTFONT_SANS_UNICODE, + Application::GetSettings().GetLanguageTag().getLanguageType(), 0, this); + sFontName = aFont.GetName(); + } + const SvxFontListItem* pFontListItem = + (const SvxFontListItem* )pSrcView->GetDocShell()->GetItem( SID_ATTR_CHAR_FONTLIST ); + const FontList* pList = pFontListItem->GetFontList(); + FontInfo aInfo = pList->Get(sFontName,WEIGHT_NORMAL, ITALIC_NONE); + + const Font& rFont = GetTextEngine()->GetFont(); + Font aFont(aInfo); + Size aSize(rFont.GetSize()); + //font height is stored in point and set in twip + aSize.Height() = + officecfg::Office::Common::Font::SourceViewFont::FontHeight::get() * 20; + aFont.SetSize(pOutWin->LogicToPixel(aSize, MAP_TWIP)); + GetTextEngine()->SetFont( aFont ); + pOutWin->SetFont(aFont); +} + +void SwSrcEditWindow::SetTextEncoding(rtl_TextEncoding eEncoding) +{ + eSourceEncoding = eEncoding; + SetFont(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |