diff options
Diffstat (limited to 'sw/source/ui/docvw/postit.cxx')
-rw-r--r-- | sw/source/ui/docvw/postit.cxx | 2486 |
1 files changed, 2486 insertions, 0 deletions
diff --git a/sw/source/ui/docvw/postit.cxx b/sw/source/ui/docvw/postit.cxx new file mode 100644 index 000000000000..3079cc855c50 --- /dev/null +++ b/sw/source/ui/docvw/postit.cxx @@ -0,0 +1,2486 @@ +/************************************************************************* * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: postit.cxx,v $ + * $Revision: 1.8.42.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#include "precompiled_sw.hxx" +#include <postit.hxx> +#include <PostItMgr.hxx> + +#include <popup.hrc> +#include <docvw.hrc> +#include <app.hrc> + +#include <hintids.hxx> +#include "viewopt.hxx" +#include "cmdid.h" + +#include <tools/poly.hxx> // Polygon + +#include <svx/postitem.hxx> +#include <svx/fontitem.hxx> +#include <svx/eeitem.hxx> +#include <svx/fhgtitem.hxx> +#include <svx/bulitem.hxx> +#include <svx/udlnitem.hxx> +#include <svx/shdditem.hxx> +#include <svx/wghtitem.hxx> +#include <svx/colritem.hxx> +#include <svx/flditem.hxx> +#include <svx/frmdir.hxx> +#include <svx/frmdiritem.hxx> +#include <svx/langitem.hxx> +#include <svx/adjitem.hxx> +#include <svx/editview.hxx> +#include <svx/svdview.hxx> +#include <svx/sdrpaintwindow.hxx> +#include <svx/sdr/overlay/overlaymanager.hxx> +#include <svx/editstat.hxx> //EditEngine flags +#include <svx/outliner.hxx> +#include <svx/editeng.hxx> +#include <svx/editobj.hxx> +#include <svx/unolingu.hxx> + +#include <svtools/langtab.hxx> +#include <svl/slstitm.hxx> +#include <unotools/securityoptions.hxx> +#include <unotools/useroptions.hxx> +#include <svl/languageoptions.hxx> +#include <svl/zforlist.hxx> +#include <svtools/svmedit.hxx> + +#include <linguistic/lngprops.hxx> + +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/mnumgr.hxx> + +#include <vcl/vclenum.hxx> +#include <vcl/edit.hxx> +#include <vcl/help.hxx> +#include <vcl/scrbar.hxx> +#include <vcl/button.hxx> +#include <vcl/svapp.hxx> +#include <vcl/gradient.hxx> +#include <vcl/salbtype.hxx> // FRound +#include <vcl/msgbox.hxx> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + +#include <swrect.hxx> +#include <docufld.hxx> // SwPostItField +#include <edtwin.hxx> +#include <view.hxx> +#include <viewsh.hxx> +#include <docsh.hxx> +#include <shellres.hxx> +#include <fmtfld.hxx> +#include <wrtsh.hxx> +#include <textsh.hxx> +#include <doc.hxx> +#include <txtfld.hxx> +#include <redline.hxx> +#include <uitool.hxx> +#include <SwUndoField.hxx> +#include <editsh.hxx> +#include <swmodule.hxx> +#include <node.hxx> +#include <ndtxt.hxx> +#include <langhelper.hxx> + +#include <sw_primitivetypes2d.hxx> +#include <drawinglayer/primitive2d/primitivetools2d.hxx> +#include <drawinglayer/attribute/fillattribute.hxx> +#include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/shadowprimitive2d.hxx> + +using namespace ::com::sun::star; + +#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 + +#define POSTIT_SHADOW_BRIGHT Color(180,180,180) +#define POSTIT_SHADOW_DARK Color(83,83,83) + +#define LINEBREAK rtl::OUString::createFromAscii("\n") +#define EMPTYSTRING rtl::OUString::createFromAscii("") + +TYPEINIT0(SwMarginWin); +TYPEINIT1(SwPostIt,SwMarginWin); +//TYPEINIT1(SwRedComment,SwMarginWin); + +Color ColorFromAlphaColor(UINT8 aTransparency, Color &aFront, Color &aBack ) +{ + return Color((UINT8)(aFront.GetRed() * aTransparency/(double)255 + aBack.GetRed() * (1-aTransparency/(double)255)), + (UINT8)(aFront.GetGreen() * aTransparency/(double)255 + aBack.GetGreen() * (1-aTransparency/(double)255)), + (UINT8)(aFront.GetBlue() * aTransparency/(double)255 + aBack.GetBlue() * (1-aTransparency/(double)255))); +} + +/************ PostItTxt **************************************/ +PostItTxt::PostItTxt(Window* pParent, WinBits nBits) : Window(pParent, nBits), mpOutlinerView(0),mMouseOver(false),mbShowPopup(FALSE) +{ + SetHelpId(26276); + AddEventListener( LINK( this, PostItTxt, WindowEventListener ) ); + mpMarginWin = static_cast<SwMarginWin*>(GetParent()); +} + +PostItTxt::~PostItTxt() +{ + RemoveEventListener( LINK( this, PostItTxt, WindowEventListener ) ); +} + +void PostItTxt::GetFocus() +{ + BOOL bLockView = mpMarginWin->DocView()->GetWrtShell().IsViewLocked(); + mpMarginWin->DocView()->GetWrtShell().LockView( TRUE ); + + if(mpMarginWin && !mpMarginWin->IsPreview()) + mpMarginWin->Mgr()->SetActivePostIt(mpMarginWin); + Window::GetFocus(); + if (!mMouseOver) + Invalidate(); + + mpMarginWin->DocView()->GetWrtShell().LockView( bLockView ); + mpMarginWin->Mgr()->MakeVisible(mpMarginWin); +} + +void PostItTxt::LoseFocus() +{ + // write the visible text back into the SwField + if ( mpMarginWin ) + mpMarginWin->UpdateData(); + + Window::LoseFocus(); + if (!mMouseOver) + Invalidate(); +} + +void PostItTxt::RequestHelp(const HelpEvent &rEvt) +{ + USHORT nResId = 0; + switch( mpMarginWin->GetStatus() ) + { + 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 && mpMarginWin->DocView()->GetWrtShell().GetContentAtPos( mpMarginWin->GetAnkorRect().Pos(), aCntntAtPos ) ) + { + String sTxt; + sTxt = SW_RESSTR( nResId ); + sTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM(": " )); + sTxt += aCntntAtPos.aFnd.pRedl->GetAuthorString(); + sTxt.AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " )); + sTxt += GetAppLangDateTimeString( aCntntAtPos.aFnd.pRedl->GetTimeStamp() ); + Help::ShowQuickHelp( this,PixelToLogic(Rectangle(rEvt.GetMousePosPixel(),Size(50,10))),sTxt); + } +} + +void PostItTxt::Paint( const Rectangle& rRect) +{ + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + if (mMouseOver || HasFocus()) + DrawGradient(Rectangle(Point(0,0),PixelToLogic(GetSizePixel())), + Gradient(GRADIENT_LINEAR,mpMarginWin->ColorDark(),mpMarginWin->ColorDark())); + else + DrawGradient(Rectangle(Point(0,0),PixelToLogic(GetSizePixel())), + Gradient(GRADIENT_LINEAR,mpMarginWin->ColorLight(),mpMarginWin->ColorDark())); + } + + mpOutlinerView->Paint( rRect ); + + if (mpMarginWin->GetStatus()==SwPostItHelper::DELETED) + { + SetLineColor(static_cast<SwPostIt*>(mpMarginWin)->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 PostItTxt::KeyInput( const KeyEvent& rKeyEvt ) +{ + const KeyCode& rKeyCode = rKeyEvt.GetKeyCode(); + USHORT nKey = rKeyCode.GetCode(); + SwView* pView = mpMarginWin->DocView(); + if ((rKeyCode.IsMod1() && rKeyCode.IsMod2()) && ((nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN))) + mpMarginWin->SwitchToPostIt(nKey); + else + if ((nKey == KEY_ESCAPE) || (rKeyCode.IsMod1() && ((nKey == KEY_PAGEUP) || (nKey == KEY_PAGEDOWN)))) + mpMarginWin->SwitchToFieldPos(); + else + if (nKey == KEY_INSERT) + { + if (!rKeyCode.IsMod1() && !rKeyCode.IsMod2()) + mpMarginWin->ToggleInsMode(); + } + else + { + //let's make sure we see our note + mpMarginWin->Mgr()->MakeVisible(mpMarginWin); + + long aOldHeight = mpMarginWin->GetPostItTextHeight(); + bool bDone = false; + + /// HACK: need to switch off processing of Undo/Redo in Outliner + if ( !( (nKey == KEY_Z || nKey == KEY_Y) && rKeyCode.IsMod1()) ) + { + /* + SwPostItHelper::SwLayoutStatus aStatus = mpMarginWin->GetStatus(); + if ( (aStatus!=SwPostItHelper::DELETED) || + ( (aStatus==SwPostItHelper::DELETED) && (!mpMarginWin->Engine()->GetEditEngine().DoesKeyChangeText(rKeyEvt))) ) + */ + bool bIsProtected = mpMarginWin->IsProtected(); + if (!bIsProtected || (bIsProtected && !mpMarginWin->Engine()->GetEditEngine().DoesKeyChangeText(rKeyEvt)) ) + bDone = mpOutlinerView->PostKeyEvent( rKeyEvt ); + else + InfoBox( this, SW_RES( MSG_READONLY_CONTENT )).Execute(); + } + if (bDone) + mpMarginWin->ResizeIfNeccessary(aOldHeight,mpMarginWin->GetPostItTextHeight()); + else + { + // write back data first when showing navigator + if ( nKey==KEY_F5 ) + mpMarginWin->UpdateData(); + if (!pView->KeyInput(rKeyEvt)) + Window::KeyInput(rKeyEvt); + } + } + + pView->GetViewFrame()->GetBindings().InvalidateAll(FALSE); +} + +void PostItTxt::MouseMove( const MouseEvent& rMEvt ) +{ + if ( mpOutlinerView ) + { + mpOutlinerView->MouseMove( rMEvt ); + // mba: why does OutlinerView not handle the modifier setting?! + // this forces the postit to handle *all* pointer types + SetPointer( mpOutlinerView->GetPointer( rMEvt.GetPosPixel() ) ); + + const EditView& aEV = mpOutlinerView->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pFld = pItem->GetField(); + const SvxURLField* pURL = PTR_CAST( SvxURLField, pFld ); + if ( pURL ) + { + String sURL( pURL->GetURL() ); + SvtSecurityOptions aSecOpts; + if ( aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK) ) + { + sURL.InsertAscii( ": ", 0 ); + sURL.Insert( ViewShell::GetShellRes()->aHyperlinkClick, 0 ); + } + Help::ShowQuickHelp( this,PixelToLogic(Rectangle(GetPosPixel(),Size(50,10))),sURL); + } + } + } +} + +void PostItTxt::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (mpOutlinerView ) + { + SvtSecurityOptions aSecOpts; + bool bExecuteMod = aSecOpts.IsOptionSet( SvtSecurityOptions::E_CTRLCLICK_HYPERLINK); + + if ( !bExecuteMod || (bExecuteMod && rMEvt.GetModifier() == KEY_MOD1)) + { + const EditView& aEV = mpOutlinerView->GetEditView(); + const SvxFieldItem* pItem = aEV.GetFieldUnderMousePointer(); + if ( pItem ) + { + const SvxFieldData* pFld = pItem->GetField(); + const SvxURLField* pURL = PTR_CAST( SvxURLField, pFld ); + if ( pURL ) + { + mpOutlinerView->MouseButtonDown( rMEvt ); + SwWrtShell &rSh = mpMarginWin->DocView()->GetWrtShell(); + String sURL( pURL->GetURL() ); + String sTarget( pURL->GetTargetFrame() ); + ::LoadURL( sURL, &rSh, URLLOAD_NOFILTER, &sTarget); + return; + } + } + } + } + + GrabFocus(); + if ( mpOutlinerView ) + mpOutlinerView->MouseButtonDown( rMEvt ); + mpMarginWin->DocView()->GetViewFrame()->GetBindings().InvalidateAll(FALSE); +} + +void PostItTxt::MouseButtonUp( const MouseEvent& rMEvt ) +{ + if ( mpOutlinerView ) + mpOutlinerView->MouseButtonUp( rMEvt ); +} + +IMPL_LINK(PostItTxt, OnlineSpellCallback, SpellCallbackInfo*, pInfo) +{ + if ( mpMarginWin && (pInfo->nCommand == SPELLCMD_STARTSPELLDLG) ) + mpMarginWin->DocView()->GetViewFrame()->GetDispatcher()->Execute( FN_SPELL_GRAMMAR_DIALOG, SFX_CALLMODE_ASYNCHRON); + return 0; +} + +IMPL_LINK( PostItTxt, Select, Menu*, pSelMenu ) +{ + mpMarginWin->ExecuteCommand( pSelMenu->GetCurItemId() ); + return 0; +} + +void PostItTxt::Command( const CommandEvent& rCEvt ) +{ + if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU ) + { + if (!mpMarginWin->IsProtected() && + //if (!mpMarginWin->IsReadOnly() && (mpMarginWin->GetStatus()!=SwPostItHelper::DELETED) && + mpOutlinerView->IsWrongSpelledWordAtPos( rCEvt.GetMousePosPixel(),TRUE )) + { + Link aLink = LINK(this, PostItTxt, OnlineSpellCallback); + mpOutlinerView->ExecuteSpellPopup(rCEvt.GetMousePosPixel(),&aLink); + } + else + { + SfxPopupMenuManager* aMgr = mpMarginWin->DocView()->GetViewFrame()->GetDispatcher()->Popup(0, this,&rCEvt.GetMousePosPixel()); + XubString aText = ((PopupMenu*)aMgr->GetSVMenu())->GetItemText( FN_DELETE_NOTE_AUTHOR ); + SwRewriter aRewriter; + aRewriter.AddRule(UNDO_ARG1, mpMarginWin->GetAuthor()); + aText = aRewriter.Apply(aText); + ((PopupMenu*)aMgr->GetSVMenu())->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); + // SwPostItLinkForwarder_Impl aFwd( ((PopupMenu*)aMgr->GetSVMenu())->pSvMenu->GetSelectHdl(), mpPostIt ); + // ((PopupMenu*)aMgr->GetSVMenu())->pSvMenu->SetSelectHdl( LINK(&aFwd, SwPostItLinkForwarder_Impl, Select) ); + + ((PopupMenu*)aMgr->GetSVMenu())->SetSelectHdl( LINK(this, PostItTxt, Select) ); + + if (rCEvt.IsMouseEvent()) + ((PopupMenu*)aMgr->GetSVMenu())->Execute(this,rCEvt.GetMousePosPixel()); + else + { + const Size aSize = GetSizePixel(); + const Point aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 ); + ((PopupMenu*)aMgr->GetSVMenu())->Execute(this,aPos); + } + delete aMgr; + } + } + else + if (rCEvt.GetCommand() == COMMAND_WHEEL) + { + if (mpMarginWin->Scrollbar()->IsVisible()) + { + const CommandWheelData* pData = rCEvt.GetWheelData(); + if (pData->IsShift() || pData->IsMod1() || pData->IsMod2()) + { + mpMarginWin->DocView()->HandleWheelCommands(rCEvt); + } + else + { + HandleScrollCommand( rCEvt, 0 , mpMarginWin->Scrollbar()); + + /* + long nLines = pData->GetNotchDelta() * (long)pData->GetScrollLines(); + if ( ((mpMarginWin->Scrollbar()->GetRange().Min() == mpMarginWin->Scrollbar()->GetThumbPos()) && (nLines > 0)) || + ( (mpMarginWin->Scrollbar()->GetRange().Max() == mpMarginWin->Scrollbar()->GetThumbPos()+mpMarginWin->Scrollbar()->GetVisibleSize()) && (nLines < 0)) ) + { + mpMarginWin->DocView()->HandleWheelCommands(rCEvt); + } + else + { + HandleScrollCommand( rCEvt, 0 , mpMarginWin->Scrollbar()); + } + */ + } + } + else + { + mpMarginWin->DocView()->HandleWheelCommands(rCEvt); + } + } + else + { + if ( mpOutlinerView ) + mpOutlinerView->Command( rCEvt ); + else + Window::Command(rCEvt); + } +} + +void PostItTxt::DataChanged( const DataChangedEvent& aData) +{ + Window::DataChanged( aData ); +} + +IMPL_LINK( PostItTxt, WindowEventListener, VclSimpleEvent*, pWinEvent ) +{ + if ( pWinEvent && pWinEvent->ISA( VclWindowEvent ) ) + { + VclWindowEvent *pEvent = (VclWindowEvent*)pWinEvent; + if (pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE) + { + MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData(); + if ( pMouseEvt->IsEnterWindow() ) + { + mMouseOver = true; + if (!mbShowPopup && !HasFocus()) + { + mpMarginWin->SetViewState(SS_VIEW); + Invalidate(); + } + } + else if ( pMouseEvt->IsLeaveWindow()) + { + if (mpMarginWin->IsPreview()) + { + //mpMarginWin->doLazyDelete(); + } + else + { + mMouseOver = false; + if (!mbShowPopup && !HasFocus()) + { + mpMarginWin->SetViewState(SS_NORMAL); + Invalidate(); + } + } + } + } + } + return sal_True; +} + +XubString PostItTxt::GetSurroundingText() const +{ + if( mpOutlinerView ) + return mpOutlinerView->GetSurroundingText(); + else + return XubString::EmptyString(); +} + +Selection PostItTxt::GetSurroundingTextSelection() const +{ + if( mpOutlinerView ) + return mpOutlinerView->GetSurroundingTextSelection(); + else + return Selection( 0, 0 ); +} + +/************** SwMarginWin***********************************++*/ +SwMarginWin::SwMarginWin(Window* pParent, WinBits nBits,SwPostItMgr* aMgr,SwPostItBits aBits) +: Window(pParent, nBits), + mnEventId(0), + mpOutlinerView(0), + mpOutliner(0), + mpPostItTxt(0), + mpMeta(0), + mpVScrollbar(0), + mpAnkor(0), + mpShadow(0), + mpMgr(aMgr), + mbMeta(true), + nFlags(aBits), + mbMouseOverButton(false), + mpButtonPopup(0), + mbIsFollow(false) +{ + SwEditWin* aWin = static_cast<SwEditWin*>(GetParent()); + mpView = &aWin->GetView(); + + SdrPaintWindow* pPaintWindow = mpView->GetDrawView()->GetPaintWindow(0); + if(pPaintWindow) + { + pOverlayManager = pPaintWindow->GetOverlayManager(); + + mpShadow = new SwPostItShadow(basegfx::B2DPoint(0,0),basegfx::B2DPoint(0,0),Color(0,0,0),SS_NORMAL); + mpShadow->setVisible(false); + pOverlayManager->add(*mpShadow); + } +} + +SwMarginWin::~SwMarginWin() +{ + if (mpOutlinerView) + { + delete mpOutlinerView; + } + + if (mpOutliner) + { + delete mpOutliner; + } + + if (mpMeta) + { + mpMeta->RemoveEventListener( LINK( mpPostItTxt, PostItTxt, WindowEventListener ) ); + delete mpMeta; + } + + if (mpPostItTxt) + { + delete mpPostItTxt; + } + + if (mpVScrollbar) + { + delete mpVScrollbar; + } + + if (mpAnkor) + { + if (mpAnkor->getOverlayManager()) + { + // remove this object from the chain + mpAnkor->getOverlayManager()->remove(*mpAnkor); + } + delete mpAnkor; + } + + if (mpShadow) + { + if (mpShadow->getOverlayManager()) + { + mpShadow->getOverlayManager()->remove(*mpShadow); + } + delete mpShadow; + } + + if (mpButtonPopup) + { + delete mpButtonPopup; + } + + if (mnEventId) + Application::RemoveUserEvent( mnEventId ); +} + +void SwMarginWin::Paint( const Rectangle& rRect) +{ + Window::Paint(rRect); + + if (mpMeta->IsVisible() ) + { + //draw left over space + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + SetFillColor(COL_BLACK); + else + SetFillColor(mColorDark); + SetLineColor(); + DrawRect(PixelToLogic(Rectangle(Point(mpMeta->GetPosPixel().X()+mpMeta->GetSizePixel().Width(),mpMeta->GetPosPixel().Y()),Size(GetMetaButtonAreaWidth(),mpMeta->GetSizePixel().Height())))); + + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode()) + { + //draw rect around button + SetFillColor(COL_BLACK); + SetLineColor(COL_WHITE); + } + else + { + //draw button + Gradient aGradient; + if (mbMouseOverButton) + aGradient = Gradient(GRADIENT_LINEAR,ColorFromAlphaColor(80,mColorAnkor,mColorDark),ColorFromAlphaColor(15,mColorAnkor,mColorDark)); + else + aGradient = Gradient(GRADIENT_LINEAR,ColorFromAlphaColor(15,mColorAnkor,mColorDark),ColorFromAlphaColor(80,mColorAnkor,mColorDark)); + DrawGradient(mRectMetaButton,aGradient); + //draw rect around button + SetFillColor(); + SetLineColor(ColorFromAlphaColor(90,mColorAnkor,mColorDark)); + } + DrawRect(mRectMetaButton); + + if (IsPreview()) + { + Font aOldFont( GetFont()); + Font aFont(aOldFont); + Color aCol( COL_BLACK); + aFont.SetColor( aCol ); + aFont.SetHeight(200); + aFont.SetWeight(WEIGHT_MEDIUM); + SetFont( aFont ); + DrawText(mRectMetaButton,rtl::OUString::createFromAscii("Edit Note"),TEXT_DRAW_CENTER); + SetFont( aOldFont ); + } + else + { + //draw arrow + if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + SetFillColor(COL_WHITE); + else + SetFillColor(COL_BLACK); + SetLineColor(); + DrawPolygon(Polygon(aPopupTriangle)); + } + } +} + +void SwMarginWin::SetPosSizePixelRect(long nX, long nY,long nWidth, long nHeight,const SwRect &aRect, const long aPageBorder) +{ + mbMeta = true; + mPosSize = Rectangle(Point(nX,nY),Size(nWidth,nHeight)); + mAnkorRect = aRect; + mPageBorder = aPageBorder; +} + +void SwMarginWin::SetSize( const Size& rNewSize ) +{ + mPosSize.SetSize(rNewSize); +} + +void SwMarginWin::SetVirtualPosSize( const Point& aPoint, const Size& aSize) +{ + mPosSize = Rectangle(aPoint,aSize); +} + +void SwMarginWin::TranslateTopPosition(const long aAmount) +{ + mPosSize.Move(0,aAmount); +} + +void SwMarginWin::ShowAnkorOnly(const Point &aPoint) +{ + HideNote(); + SetPosAndSize(); + if (mpAnkor) + { + mpAnkor->SetSixthPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y())); + mpAnkor->SetSeventhPosition(basegfx::B2DPoint(aPoint.X(),aPoint.Y())); + mpAnkor->SetAnkorState(AS_ALL); + mpAnkor->setVisible(true); + } + if (mpShadow) + mpShadow->setVisible(false); +} + +SfxItemSet SwMarginWin::DefaultItem() +{ + SfxItemSet aItem( mpView->GetDocShell()->GetPool() ); + aItem.Put(SvxFontHeightItem(200,100,EE_CHAR_FONTHEIGHT)); + aItem.Put(SvxFontItem(FAMILY_SWISS,GetSettings().GetStyleSettings().GetFieldFont().GetName(), + EMPTYSTRING,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW,EE_CHAR_FONTINFO)); + return aItem; +} + +void SwMarginWin::InitControls() +{ + // actual window which holds the user text + mpPostItTxt = new PostItTxt(this, WB_NODIALOGCONTROL); + mpPostItTxt->SetPointer(Pointer(POINTER_TEXT)); + + // window control for author and date + mpMeta = new MultiLineEdit(this,0); + mpMeta->SetReadOnly(); + mpMeta->SetRightToLeft(Application::GetSettings().GetLayoutRTL()); + mpMeta->AlwaysDisableInput(true); + mpMeta->SetCallHandlersOnInputDisabled(true); + mpMeta->AddEventListener( LINK( mpPostItTxt, PostItTxt, WindowEventListener ) ); + AddEventListener( LINK( mpPostItTxt, PostItTxt, WindowEventListener ) ); + + // we should leave this setting alone, but for this we need a better layout algo + // with variable meta size height + AllSettings aSettings = mpMeta->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + Font aFont = aStyleSettings.GetFieldFont(); + aFont.SetHeight(8); + aStyleSettings.SetFieldFont(aFont); + aSettings.SetStyleSettings(aStyleSettings); + mpMeta->SetSettings(aSettings); + + SwDocShell* aShell = mpView->GetDocShell(); + mpOutliner = new Outliner(&aShell->GetPool(),OUTLINERMODE_TEXTOBJECT); + aShell->GetDoc()->SetCalcFieldValueHdl( mpOutliner ); + // mpOutliner->EnableUndo( FALSE ); + mpOutliner->SetUpdateMode( TRUE ); + Rescale(); + + OutputDevice* pDev = aShell->GetDoc()->getReferenceDevice(TRUE); + if ( pDev ) + { + mpOutliner->SetRefDevice( pDev ); + } + + mpOutlinerView = new OutlinerView ( mpOutliner, mpPostItTxt ); + mpOutlinerView->SetBackgroundColor(COL_TRANSPARENT); + mpOutliner->InsertView(mpOutlinerView ); + mpPostItTxt->SetTextView(mpOutlinerView); + mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,1,1) ) ); + + mpOutlinerView->SetAttribs(DefaultItem()); + + // TODO: ?? + EEHorizontalTextDirection aDefHoriTextDir = Application::GetSettings().GetLayoutRTL() ? EE_HTEXTDIR_R2L : EE_HTEXTDIR_L2R; + mpOutliner->SetDefaultHorizontalTextDirection( aDefHoriTextDir ); + + //create Scrollbars + mpVScrollbar = new ScrollBar(this, WB_3DLOOK |WB_VSCROLL|WB_DRAG); + mpVScrollbar->EnableNativeWidget(false); + mpVScrollbar->EnableRTL( false ); + mpVScrollbar->SetScrollHdl(LINK(this, SwMarginWin, ScrollHdl)); + mpVScrollbar->EnableDrag(); + mpVScrollbar->AddEventListener( LINK( mpPostItTxt, PostItTxt, WindowEventListener ) ); + + const SwViewOption* pVOpt = mpView->GetWrtShellPtr()->GetViewOptions(); + 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(mpMgr->GetColorDark(aIndex),mpMgr->GetColorLight(aIndex),mpMgr->GetColorAnkor(aIndex)); + + CheckMetaText(); + SetPopup(); + SetLanguage(GetLanguage()); + View()->StartSpeller(); + SetPostItText(); + Engine()->CompleteOnlineSpelling(); + + mpMeta->Show(); + mpVScrollbar->Show(); + mpPostItTxt->Show(); +} + +void SwMarginWin::CheckMetaText() +{ + const LocaleDataWrapper& rLocalData = SvtSysLocale().GetLocaleData(); + String sMeta = GetAuthor(); + if (sMeta==String(EMPTYSTRING)) + sMeta = String(SW_RES(STR_NOAUTHOR)); + if (sMeta.Len() > 22) + { + sMeta.Erase(20); + sMeta = sMeta + rtl::OUString::createFromAscii("..."); + } + Date aDate = GetDate(); + if (aDate==Date()) + sMeta = sMeta + LINEBREAK + String(SW_RES(STR_POSTIT_TODAY)); + else + if (aDate == Date(Date()-1)) + sMeta = sMeta + LINEBREAK + String(SW_RES(STR_POSTIT_YESTERDAY)); + else + if (aDate.IsValid() ) + sMeta = sMeta + LINEBREAK + rLocalData.getDate(aDate); + else + sMeta = sMeta + LINEBREAK + String(SW_RES(STR_NODATE)); + if (GetTime()!=0) + sMeta = sMeta + rtl::OUString::createFromAscii(" ") + rLocalData.getTime( GetTime(),false ); + if (mpMeta->GetText() != sMeta) + mpMeta->SetText(sMeta); +} + +void SwMarginWin::Rescale() +{ + MapMode aMode = GetParent()->GetMapMode(); + aMode.SetOrigin( Point() ); + //aMode.SetScaleX( aMode.GetScaleX() * Fraction( 8, 10 ) ); + //aMode.SetScaleY( aMode.GetScaleY() * Fraction( 8, 10 ) ); + mpOutliner->SetRefMapMode( aMode ); + SetMapMode( aMode ); + mpPostItTxt->SetMapMode( aMode ); + if ( mpMeta ) + { + Font aFont( mpMeta->GetSettings().GetStyleSettings().GetFieldFont() ); + sal_Int32 nHeight = aFont.GetHeight(); + nHeight = nHeight * aMode.GetScaleY().GetNumerator() / aMode.GetScaleY().GetDenominator(); + aFont.SetHeight( nHeight ); + mpMeta->SetControlFont( aFont ); + } +} + +void SwMarginWin::SetPosAndSize() +{ + bool bChange = false; + + if (GetSizePixel() != mPosSize.GetSize()) + { + bChange = true; + SetSizePixel(mPosSize.GetSize()); + DoResize(); + } + + if (GetPosPixel().X() != mPosSize.TopLeft().X() || (abs(GetPosPixel().Y() - mPosSize.TopLeft().Y()) > 5) ) + { + bChange = true; + SetPosPixel(mPosSize.TopLeft()); + + Point aLineStart; + Point aLineEnd ; + if (mbMarginSide) + { + aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) ); + aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) ); + } + else + { + aLineStart = EditWin()->PixelToLogic( Point(GetPosPixel().X(),GetPosPixel().Y()-1) ); + aLineEnd = EditWin()->PixelToLogic( Point(GetPosPixel().X()+GetSizePixel().Width(),GetPosPixel().Y()-1) ); + } + + if (!IsPreview()) + { + if (mpAnkor) + { + mpAnkor->SetAllPosition(basegfx::B2DPoint( mAnkorRect.Left() , mAnkorRect.Bottom() - 5* 15), + basegfx::B2DPoint( mAnkorRect.Left()-5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left()+5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left(), mAnkorRect.Bottom()+2*15), + basegfx::B2DPoint( mPageBorder ,mAnkorRect.Bottom()+2*15), + basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), + basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y())); + mpAnkor->SetHeight(mAnkorRect.Height()); + } + else + { + mpAnkor = new SwPostItAnkor(basegfx::B2DPoint( mAnkorRect.Left() , mAnkorRect.Bottom()-5*15), + basegfx::B2DPoint( mAnkorRect.Left()-5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left()+5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left(), mAnkorRect.Bottom()+2*15), + basegfx::B2DPoint( mPageBorder ,mAnkorRect.Bottom()+2*15), + basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()), + basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) , + mColorAnkor, + false, + false); + mpAnkor->SetHeight(mAnkorRect.Height()); + mpAnkor->setVisible(true); + mpAnkor->SetAnkorState(AS_TRI); + if (HasChildPathFocus()) + { + mpAnkor->setLineSolid(true); + } + pOverlayManager->add(*mpAnkor); + } + } + } + else + { + if ( mpAnkor && (mpAnkor->getBasePosition() != basegfx::B2DPoint( mAnkorRect.Left() , mAnkorRect.Bottom()-5*15)) ) + mpAnkor->SetTriPosition(basegfx::B2DPoint( mAnkorRect.Left() , mAnkorRect.Bottom() - 5* 15), + basegfx::B2DPoint( mAnkorRect.Left()-5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left()+5*15 , mAnkorRect.Bottom()+5*15), + basegfx::B2DPoint( mAnkorRect.Left(), mAnkorRect.Bottom()+2*15), + basegfx::B2DPoint( mPageBorder ,mAnkorRect.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 (mpMgr->ShowNotes()) + { + if (IsFollow() && !HasChildPathFocus()) + { + mpAnkor->SetAnkorState(AS_END); + } + else + { + mpAnkor->SetAnkorState(AS_ALL); + SwMarginWin* pWin = GetTopReplyNote(); + if (pWin) + pWin->Ankor()->SetAnkorState(AS_END); + } + } +} + +void SwMarginWin::DoResize() +{ + long aTextHeight = LogicToPixel( mpOutliner->CalcTextSize()).Height(); + long aHeight = GetSizePixel().Height(); + unsigned long aWidth = GetSizePixel().Width(); + + if (mbMeta) + { + aHeight -= GetMetaHeight(); + mpMeta->Show(); + mpPostItTxt->SetQuickHelpText(EMPTYSTRING); + } + else + { + mpMeta->Hide(); + mpPostItTxt->SetQuickHelpText(mpMeta->GetText()); + } + + if ((aTextHeight > aHeight) && !IsPreview()) + { // we need vertical scrollbars and have to reduce the width + aWidth -= GetScrollbarWidth(); + mpVScrollbar->Show(); + } + else + { + mpVScrollbar->Hide(); + } + + mpMeta->SetPosSizePixel(0,aHeight,GetSizePixel().Width()-GetMetaButtonAreaWidth(),GetMetaHeight()); + mpOutliner->SetPaperSize( PixelToLogic( Size(aWidth,aHeight) ) ) ; + mpOutlinerView->SetOutputArea( PixelToLogic( Rectangle(0,0,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) ) ); + } + + if (!Application::GetSettings().GetLayoutRTL()) + { + mpPostItTxt->SetPosSizePixel(0, 0, aWidth, aHeight); + mpVScrollbar->SetPosSizePixel( aWidth, 0, GetScrollbarWidth(), aHeight); + } + else + { + mpPostItTxt->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() ); + + Point aPos( mpMeta->GetPosPixel()); + Point aBase( aPos.X() + aPos.X() + GetSizePixel().Width(), aPos.Y() ); + Point aLeft = PixelToLogic( Point( aBase.X() - (METABUTTON_WIDTH+5)*fx.GetNumerator()/fx.GetDenominator(), aBase.Y()+17*fy.GetNumerator()/fx.GetDenominator() ) ); + Point aRight = PixelToLogic( Point( aBase.X() - (METABUTTON_WIDTH-1)*fx.GetNumerator()/fx.GetDenominator(), aBase.Y()+17*fy.GetNumerator()/fy.GetDenominator() ) ); + Point aBottom = PixelToLogic( Point( aBase.X() - (METABUTTON_WIDTH+2)*fx.GetNumerator()/fx.GetDenominator(), aBase.Y()+20*fy.GetNumerator()/fy.GetDenominator() ) ); + + aPopupTriangle.clear(); + aPopupTriangle.append(basegfx::B2DPoint(aLeft.X(),aLeft.Y())); + aPopupTriangle.append(basegfx::B2DPoint(aRight.X(),aRight.Y())); + aPopupTriangle.append(basegfx::B2DPoint(aBottom.X(),aBottom.Y())); + aPopupTriangle.setClosed(true); + if (IsPreview()) + mRectMetaButton = 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 + mRectMetaButton = 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() ) ) ); +} + +void SwMarginWin::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 SwMarginWin::SetScrollbar() +{ + mpVScrollbar->SetThumbPos( mpOutlinerView->GetVisArea().Top()+ mpOutlinerView->GetEditView().GetCursor()->GetOffsetY()); +} + +void SwMarginWin::ResizeIfNeccessary(long aOldHeight, long aNewHeight) +{ + if (aOldHeight != aNewHeight) + { + //check for lower border or next note + long aBorder = mpMgr->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 SwMarginWin::SetColor(Color aColorDark,Color aColorLight, Color aColorAnkor) +{ + mColorDark = aColorDark; + mColorLight = aColorLight; + mColorAnkor = aColorAnkor; + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + { + //Wallpaper aWall(Gradient(GRADIENT_LINEAR,mColorLight,mColorDark)); + //mpPostItTxt->SetBackground(aWall); + + mpMeta->SetControlBackground(mColorDark); + AllSettings aSettings = mpMeta->GetSettings(); + StyleSettings aStyleSettings = aSettings.GetStyleSettings(); + aStyleSettings.SetFieldTextColor(aColorAnkor); + aSettings.SetStyleSettings(aStyleSettings); + mpMeta->SetSettings(aSettings); + + AllSettings aSettings2 = mpVScrollbar->GetSettings(); + StyleSettings aStyleSettings2 = aSettings2.GetStyleSettings(); + aStyleSettings2.SetButtonTextColor(Color(0,0,0)); + //aStyleSettings2.SetLightColor(mColorAnkor); + aStyleSettings2.SetCheckedColor(mColorLight); //hintergund + //aStyleSettings2.SetLightBorderColor(mColorAnkor); + aStyleSettings2.SetShadowColor(mColorAnkor); + aStyleSettings2.SetFaceColor(mColorDark); + aSettings2.SetStyleSettings(aStyleSettings2); + mpVScrollbar->SetSettings(aSettings2); + } +} + +void SwMarginWin::SetMarginSide(bool aMarginSide) +{ + mbMarginSide = aMarginSide; +} + +void SwMarginWin::SetReadonly(BOOL bSet) +{ + mbReadonly = bSet; + View()->SetReadOnly(bSet); +} + +void SwMarginWin::SetLanguage(const SvxLanguageItem aNewItem) +{ + Engine()->SetModifyHdl( Link() ); + ESelection aOld = View()->GetSelection(); + + ESelection aNewSelection( 0, 0, (USHORT)Engine()->GetParagraphCount()-1, USHRT_MAX ); + View()->SetSelection( aNewSelection ); + SfxItemSet aEditAttr(View()->GetAttribs()); + aEditAttr.Put(aNewItem); + View()->SetAttribs( aEditAttr ); + + View()->SetSelection(aOld); + Engine()->SetModifyHdl( LINK( this, SwPostIt, ModifyHdl ) ); + + const SwViewOption* pVOpt = DocView()->GetWrtShellPtr()->GetViewOptions(); + ULONG nCntrl = Engine()->GetControlWord(); + // turn off + if (!pVOpt->IsOnlineSpell()) + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + else + 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 SwMarginWin::DataChanged( const DataChangedEvent& aEvent) +{ + Window::DataChanged( aEvent ); +} + +void SwMarginWin::GetFocus() +{ + if (mpPostItTxt) + mpPostItTxt->GrabFocus(); +} + +void SwMarginWin::LoseFocus() +{ +} + +void SwMarginWin::ShowNote() +{ + SetPosAndSize(); + if (!IsVisible()) + Window::Show(); + if (mpAnkor && !mpShadow->isVisible()) + mpShadow->setVisible(true); + if (mpAnkor && !mpAnkor->isVisible()) + mpAnkor->setVisible(true); +} + +void SwMarginWin::HideNote() +{ + if (IsVisible()) + Window::Hide(); + if (mpAnkor) + { + if (mpMgr->IsShowAnkor()) + mpAnkor->SetAnkorState(AS_TRI); + else + mpAnkor->setVisible(false); + } + if (mpShadow && mpShadow->isVisible()) + mpShadow->setVisible(false); +} + +void SwMarginWin::ActivatePostIt() +{ + mpMgr->AssureStdModeAtShell(); + + mpOutliner->ClearModifyFlag(); + mpOutliner->GetUndoManager().Clear(); + + CheckMetaText(); + SetViewState(SS_EDIT); + View()->ShowCursor(); + + mpOutlinerView->GetEditView().SetInsertMode(mpView->GetWrtShellPtr()->IsInsMode()); + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + View()->SetBackgroundColor(mColorDark); + + // mpPostItTxt->SetBackground(Wallpaper(mColorDark)); +} + +void SwMarginWin::DeactivatePostIt() +{ + // remove selection, #i87073# + if (View()->GetEditView().HasSelection()) + { + ESelection aSelection = View()->GetEditView().GetSelection(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos; + View()->GetEditView().SetSelection(aSelection); + } + + mpOutliner->CompleteOnlineSpelling(); + + SetViewState(SS_NORMAL); + // write the visible text back into the SwField + UpdateData(); + + if ( !Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) + View()->SetBackgroundColor(COL_TRANSPARENT); + + //mpPostItTxt->SetBackground(Gradient(GRADIENT_LINEAR,mColorLight,mColorDark)); + + if ( !IsProtected() && + //if (!IsReadOnly() && (GetStatus()!=SwPostItHelper::DELETED) && + Engine()->GetEditEngine().GetText()==String(EMPTYSTRING) ) + mnEventId = Application::PostUserEvent( LINK( this, SwMarginWin, DeleteHdl), 0 ); +} + +void SwMarginWin::ToggleInsMode() +{ + if (!mpView->GetWrtShell().IsRedlineOn()) + { + //change outliner + mpOutlinerView->GetEditView().SetInsertMode(!mpOutlinerView->GetEditView().IsInsertMode()); + //change documnet + mpView->GetWrtShell().ToggleInsMode(); + //update statusbar + SfxBindings &rBnd = mpView->GetViewFrame()->GetBindings(); + rBnd.Invalidate(SID_ATTR_INSERT); + rBnd.Update(SID_ATTR_INSERT); + } +} + +void SwMarginWin::ExecuteCommand(USHORT nSlot) +{ + mpMgr->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 + SwView* pView = DocView(); + if (Engine()->GetEditEngine().GetText() != String(EMPTYSTRING)) + { + OutlinerParaObject* pPara = new OutlinerParaObject(*View()->GetEditView().CreateTextObject()); + Mgr()->RegisterAnswer(pPara); + } + if (Mgr()->GetActivePostIt()) + Mgr()->SetActivePostIt(0); + SwitchToFieldPos(); + pView->GetViewFrame()->GetDispatcher()->Execute(FN_POSTIT); + break; + } + case FN_DELETE_COMMENT: + case FN_DELETE_NOTE: + + //Delete(); // do not kill the parent of our open popup menu + mnEventId = Application::PostUserEvent( LINK( this, SwMarginWin, DeleteHdl), 0 ); + break; + /* + case FN_HIDE_NOTE: + if ( Mgr()->GetActivePostIt() == this ) + { + Mgr()->SetActivePostIt(0); + // put the cursor back into the document + SwitchToFieldPos(); + } + Mgr()->Hide(mpFld); + break; + */ + case FN_DELETE_ALL_NOTES: + case FN_HIDE_ALL_NOTES: + // not possible as slot as this would require that "this" is the active postit + DocView()->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; + DocView()->GetViewFrame()->GetBindings().Execute( nSlot, aItems, 0, SFX_CALLMODE_ASYNCHRON ); + } + default: + mpView->GetViewFrame()->GetBindings().Execute( nSlot ); + break; + } +} + +bool SwMarginWin::CalcFollow() +{ + return false; +} + +SwEditWin* SwMarginWin::EditWin() +{ + return &mpView->GetEditWin(); +} + +String SwPostIt::GetAuthor() +{ + return mpFld->GetPar1(); +} + +Date SwPostIt::GetDate() +{ + return mpFld->GetDate(); +} + +Time SwPostIt::GetTime() +{ + return mpFld->GetTime(); +} + +long SwMarginWin::GetPostItTextHeight() +{ + return mpOutliner ? LogicToPixel(mpOutliner->CalcTextSize()).Height() : 0; +} + +void SwMarginWin::SwitchToPostIt(USHORT aDirection) +{ + if (mpMgr) + { + SwMarginWin* pPostIt = mpMgr->GetNextPostIt(aDirection, this); + if (pPostIt) + pPostIt->GrabFocus(); + } +} + +void SwMarginWin::MouseButtonDown( const MouseEvent& /*rMEvt */) +{ +} + +void SwMarginWin::MouseMove( const MouseEvent& rMEvt ) +{ + if (mRectMetaButton.IsInside(PixelToLogic(rMEvt.GetPosPixel()))) + { + if (!mbMouseOverButton) + { + Invalidate(mRectMetaButton); + mbMouseOverButton = true; + } + } + else + { + if (mbMouseOverButton) + { + Invalidate(mRectMetaButton); + mbMouseOverButton = false; + } + } +} + +void SwMarginWin::Delete() +{ + if ( Mgr()->GetActivePostIt() == this) + { + Mgr()->SetActivePostIt(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(SwMarginWin, ScrollHdl, ScrollBar*, pScroll) +{ + long nDiff = View()->GetEditView().GetVisArea().Top() - pScroll->GetThumbPos(); + View()->Scroll( 0, nDiff ); + return 0; +} + +IMPL_LINK(SwMarginWin, ModifyHdl, void*, pVoid) +{ + // no warnings, please + pVoid=0; + DocView()->GetDocShell()->SetModified(sal_True); + return 0; +} + +IMPL_LINK(SwMarginWin, DeleteHdl, void*, pVoid) +{ + // no warnings, please + pVoid=0; + mnEventId = 0; + Delete(); + return 0; +} + + +void SwMarginWin::ResetAttributes() +{ + mpOutlinerView->RemoveAttribsKeepLanguages(TRUE); + mpOutliner->RemoveFields(TRUE); + mpOutlinerView->SetAttribs(DefaultItem()); +} + +sal_Int32 SwMarginWin::GetScrollbarWidth() +{ + return mpView->GetWrtShell().GetViewOptions()->GetZoom() / 10; +} + +sal_Int32 SwMarginWin::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 SwMarginWin::GetMetaHeight() +{ + const Fraction& f( GetMapMode().GetScaleY() ); + return POSTIT_META_HEIGHT * f.GetNumerator() / f.GetDenominator(); +} + +sal_Int32 SwMarginWin::GetMinimumSizeWithMeta() +{ + return mpMgr->GetMinimumSizeWithMeta(); +} + +sal_Int32 SwMarginWin::GetMinimumSizeWithoutMeta() +{ + const Fraction& f( GetMapMode().GetScaleY() ); + return POSTIT_MINIMUMSIZE_WITHOUT_META * f.GetNumerator() / f.GetDenominator(); +} + +void SwMarginWin::SetSpellChecking() +{ + const SwViewOption* pVOpt = mpView->GetWrtShellPtr()->GetViewOptions(); + ULONG nCntrl = mpOutliner->GetControlWord(); + if (pVOpt->IsOnlineSpell()) + nCntrl |= EE_CNTRL_ONLINESPELLING; + else + nCntrl &= ~EE_CNTRL_ONLINESPELLING; + mpOutliner->SetControlWord(nCntrl); + + mpOutliner->CompleteOnlineSpelling(); + Invalidate(); +} + +void SwMarginWin::SetViewState(ShadowState bState) +{ + switch (bState) + { + case SS_EDIT: + { + if (mpAnkor) + { + mpAnkor->SetAnkorState(AS_ALL); + SwMarginWin* pWin = GetTopReplyNote(); + if (pWin) + pWin->Ankor()->SetAnkorState(AS_END); + mpAnkor->setLineSolid(true); + } + if (mpShadow) + mpShadow->SetShadowState(bState); + break; + } + case SS_VIEW: + { + if (mpAnkor) + mpAnkor->setLineSolid(true); + if (mpShadow) + mpShadow->SetShadowState(bState); + break; + } + case SS_NORMAL: + { + if (mpAnkor) + { + if (IsFollow()) + { + // if there is no visible parent note, we want to see the complete anchor ?? + //if (IsAnyStackParentVisible()) + mpAnkor->SetAnkorState(AS_END); + SwMarginWin* pTopWinSelf = GetTopReplyNote(); + SwMarginWin* pTopWinActive = mpMgr->GetActivePostIt() ? mpMgr->GetActivePostIt()->GetTopReplyNote() : 0; + if (pTopWinSelf && (pTopWinSelf!=pTopWinActive)) + { + if (pTopWinSelf!=mpMgr->GetActivePostIt()) + pTopWinSelf->Ankor()->setLineSolid(false); + pTopWinSelf->Ankor()->SetAnkorState(AS_ALL); + } + } + mpAnkor->setLineSolid(false); + } + if (mpShadow) + mpShadow->SetShadowState(bState); + break; + } + } +} + +bool SwMarginWin::IsAnyStackParentVisible() +{ + SwMarginWin* pMarginWin = mpMgr->GetNextPostIt(KEY_PAGEUP, this); + while (pMarginWin) + { + if (pMarginWin->IsFollow()) + { + pMarginWin = mpMgr->GetNextPostIt(KEY_PAGEUP, pMarginWin); + if (pMarginWin && pMarginWin->IsVisible()) + return true; + } + else + return pMarginWin && pMarginWin->IsVisible() ? true : false; + } + return false; +} + +SwMarginWin* SwMarginWin::GetTopReplyNote() +{ + SwMarginWin* pTopNote = 0; + SwMarginWin* pMarginWin = IsFollow() ? mpMgr->GetNextPostIt(KEY_PAGEUP, this) : 0; + while (pMarginWin) + { + pTopNote = pMarginWin; + pMarginWin = pMarginWin->IsFollow() ? mpMgr->GetNextPostIt(KEY_PAGEUP, pMarginWin) : 0; + } + return pTopNote; +} + +void SwMarginWin::SwitchToFieldPos() +{ + if ( Mgr()->GetActivePostIt() == this ) + Mgr()->SetActivePostIt(0); + GotoPos(); + sal_uInt32 aCount = MoveCaret(); + if (aCount) + DocView()->GetDocShell()->GetWrtShell()->SwCrsrShell::Right(aCount, 0, FALSE); + GrabFocusToDocument(); +} + +String SwMarginWin::GetAuthor() +{ + return String(EMPTYSTRING); +} + +Date SwMarginWin::GetDate() +{ + return Date(0); +} + +Time SwMarginWin::GetTime() +{ + return Time(0); +} + +SvxLanguageItem SwMarginWin::GetLanguage(void) +{ + return SvxLanguageItem(SwLangHelper::GetLanguage(DocView()->GetWrtShell(),RES_CHRATR_LANGUAGE),RES_CHRATR_LANGUAGE); +} + +/***** SwPostIt *********************************************/ +SwPostIt::SwPostIt( Window* pParent, WinBits nBits, SwFmtFld* aField,SwPostItMgr* aMgr,SwPostItBits aBits) + : SwMarginWin(pParent,nBits,aMgr,aBits), + mpFmtFld(aField), + mpFld( static_cast<SwPostItField*>(aField->GetFld())), + mStatus(SwPostItHelper::INVISIBLE) +{ +} + +void SwPostIt::SetPostItText() +{ + // get text from SwPostItField and insert into our textview + Engine()->SetModifyHdl( Link() ); + Engine()->EnableUndo( FALSE ); + mpFld = static_cast<SwPostItField*>(mpFmtFld->GetFld()); + if( mpFld->GetTextObject() ) + Engine()->SetText( *mpFld->GetTextObject() ); + else + { + Engine()->Clear(); + View()->SetAttribs(DefaultItem()); + View()->InsertText(mpFld->GetPar2(),false); + } + + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); + Engine()->EnableUndo( TRUE ); + Engine()->SetModifyHdl( LINK( this, SwPostIt, ModifyHdl ) ); + Invalidate(); +} + +void SwPostIt::UpdateData() +{ + if ( Engine()->IsModified() ) + { + SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + SwField* pOldField = mpFld->Copy(); + mpFld->SetPar2(Engine()->GetEditEngine().GetText()); + mpFld->SetTextObject(Engine()->CreateParaObject()); + DocView()->GetDocShell()->GetDoc()->AppendUndo(new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); + delete pOldField; + // 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 SwPostIt::SetChangeTracking(SwPostItHelper::SwLayoutStatus& aStatus,Color aColor) +{ + if ( (mStatus != aStatus) || (mChangeColor != aColor) ) + { + mStatus = aStatus; + mChangeColor = aColor; + Invalidate(); + } +} + +void SwPostIt::Delete() +{ + SwMarginWin::Delete(); + // we delete the field directly, the Mgr cleans up the PostIt by listening + DocView()->GetWrtShellPtr()->GotoField(*mpFmtFld); + GrabFocusToDocument(); + DocView()->GetWrtShellPtr()->DelRight(); +} + +void SwPostIt::GotoPos() +{ + DocView()->GetDocShell()->GetWrtShell()->GotoField(*mpFmtFld); +} + +sal_uInt32 SwPostIt::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 SwPostIt::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_FIELD ); + const SwField* pFld = pTxtAttr ? pTxtAttr->GetFld().GetFld() : 0; + return pFld && (pFld->Which()== RES_POSTITFLD); +} + +// counts how many SwPostItField we have right after the current one +sal_uInt32 SwPostIt::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_FIELD ); + SwField* pFld = pTxtAttr ? const_cast<SwField*>(pTxtAttr->GetFld().GetFld()) : 0; + while (pFld && (pFld->Which()== RES_POSTITFLD)) + { + aCount++; + pTxtAttr = pTxtFld->GetTxtNode().GetTxtAttrForCharAt( + aPosition.nContent.GetIndex() + aCount, RES_TXTATR_FIELD ); + pFld = pTxtAttr ? const_cast<SwField*>(pTxtAttr->GetFld().GetFld()) : 0; + } + return aCount - 1; +} + +void SwPostIt::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (mRectMetaButton.IsInside(PixelToLogic(rMEvt.GetPosPixel())) && rMEvt.IsLeft()) + { + if (IsPreview()) + { + doLazyDelete(); + if (Mgr()) + { + SwPostIt* pPostIt = dynamic_cast<SwPostIt*>(Mgr()->GetPostIt(mpFmtFld)); + if (pPostIt) + { + pPostIt->GrabFocus(); + Mgr()->MakeVisible(pPostIt); + } + } + + } + else + { + if ( mbReadonly ) + { + mpButtonPopup->EnableItem(FN_REPLY,false); + mpButtonPopup->EnableItem(FN_DELETE_NOTE,false); + mpButtonPopup->EnableItem(FN_DELETE_NOTE_AUTHOR,false); + mpButtonPopup->EnableItem(FN_DELETE_ALL_NOTES,false); + } + else + { + if (IsProtected()) + mpButtonPopup->EnableItem(FN_DELETE_NOTE,false); + else + mpButtonPopup->EnableItem(FN_DELETE_NOTE,true); + mpButtonPopup->EnableItem(FN_DELETE_NOTE_AUTHOR,true); + mpButtonPopup->EnableItem(FN_DELETE_ALL_NOTES,true); + } + SvtUserOptions aUserOpt; + String sAuthor; + if( !(sAuthor = aUserOpt.GetFullName()).Len()) + if( !(sAuthor = aUserOpt.GetID()).Len() ) + sAuthor = String( 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 == GetAuthor()) || (IsProtected())) + mpButtonPopup->EnableItem(FN_REPLY,false); + else + mpButtonPopup->EnableItem(FN_REPLY,true); + + // show the popup menu and execute the selected command + ExecuteCommand( mpButtonPopup->Execute( this,Rectangle(LogicToPixel(mRectMetaButton.BottomLeft()),LogicToPixel(mRectMetaButton.BottomLeft())),POPUPMENU_EXECUTE_DOWN | POPUPMENU_NOMOUSEUPCLOSE) ); + } + } +} + +void SwPostIt::SetPopup() +{ + mpButtonPopup = new PopupMenu(SW_RES(MN_ANNOTATION_BUTTON)); + //mpButtonPopup->SetMenuFlags(MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES); + XubString aText = mpButtonPopup->GetItemText( FN_DELETE_NOTE_AUTHOR ); + SwRewriter aRewriter; + aRewriter.AddRule(UNDO_ARG1,GetAuthor()); + aText = aRewriter.Apply(aText); + mpButtonPopup->SetItemText(FN_DELETE_NOTE_AUTHOR,aText); +} + +void SwPostIt::InitAnswer(OutlinerParaObject* pText) +{ + //collect our old meta data + SwMarginWin* pWin = Mgr()->GetNextPostIt(KEY_PAGEUP, this); + const LocaleDataWrapper& rLocalData = SvtSysLocale().GetLocaleData(); + String aText = String(SW_RES(STR_REPLY)); + SwRewriter aRewriter; + aRewriter.AddRule(UNDO_ARG1, pWin->GetAuthor()); + aText = aRewriter.Apply(aText); + aText.Append(String(rtl::OUString::createFromAscii(" (") + + String(rLocalData.getDate( pWin->GetDate())) + rtl::OUString::createFromAscii(", ") + + String(rLocalData.getTime( pWin->GetTime(),false)) + rtl::OUString::createFromAscii("): \""))); + View()->InsertText(aText,false); + + // insert old, selected text or "..." + // TOOD: iterate over all paragraphs, not only first one to find out if it is empty + if (pText->GetTextObject().GetText(0) != String(EMPTYSTRING)) + View()->GetEditView().InsertText(pText->GetTextObject()); + else + View()->InsertText(rtl::OUString::createFromAscii("..."),false); + View()->InsertText(rtl::OUString::createFromAscii("\"\n"),false); + + View()->SetSelection(ESelection(0x0,0x0,0xFFFF,0xFFFF)); + SfxItemSet aAnswerSet( DocView()->GetDocShell()->GetPool() ); + aAnswerSet.Put(SvxFontHeightItem(200,80,EE_CHAR_FONTHEIGHT)); + aAnswerSet.Put(SvxPostureItem(ITALIC_NORMAL,EE_CHAR_ITALIC)); + View()->SetAttribs(aAnswerSet); + View()->SetSelection(ESelection(0xFFFF,0xFFFF,0xFFFF,0xFFFF)); + + //remove all attributes and reset our standard ones + View()->GetEditView().RemoveAttribsKeepLanguages(true); + View()->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() ); + SwTxtFld* pTxtFld = mpFmtFld->GetTxtFld(); + SwPosition aPosition( pTxtFld->GetTxtNode() ); + aPosition.nContent = *pTxtFld->GetStart(); + SwField* pOldField = mpFld->Copy(); + mpFld->SetPar2(Engine()->GetEditEngine().GetText()); + mpFld->SetTextObject(Engine()->CreateParaObject()); + DocView()->GetDocShell()->GetDoc()->AppendUndo(new SwUndoFieldFromDoc(aPosition, *pOldField, *mpFld, 0, true)); + delete pOldField; + Engine()->SetModifyHdl( LINK( this, SwPostIt, ModifyHdl ) ); + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); +} + +SvxLanguageItem SwPostIt::GetLanguage(void) +{ + // set initial language for outliner + USHORT nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( mpFld->GetLanguage() ); + USHORT 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: DBG_ERROR("GetLanguage: wrong script tye"); + } + return SvxLanguageItem(mpFld->GetLanguage(),nLangWhichId); +} + +bool SwPostIt::IsProtected() +{ + bool aReturn; + aReturn = mpFmtFld ? (SwMarginWin::IsProtected() || (mStatus==SwPostItHelper::DELETED) || + mpFmtFld->IsProtect()) : (SwMarginWin::IsProtected() || (mStatus==SwPostItHelper::DELETED)); + return aReturn; +} + +/********** SwRedComment**************/ +/* +SwRedComment::SwRedComment( Window* pParent, WinBits nBits,SwPostItMgr* aMgr,SwPostItBits aBits,SwRedline* pRed) + : SwMarginWin(pParent,nBits,aMgr,aBits), + pRedline(pRed) +{ +} + +void SwRedComment::SetPopup() +{ + mpButtonPopup = new PopupMenu(SW_RES(MN_REDCOMMENT_BUTTON)); + //mpButtonPopup->SetMenuFlags(MENU_FLAG_ALWAYSSHOWDISABLEDENTRIES); +} + +void SwRedComment::UpdateData() +{ + if ( Engine()->IsModified() ) + { + // so we get a new layout of notes (ankor position is still the same and we would otherwise not get one) + Mgr()->SetLayout(); + // SetRedline is calling SetModified already + DocView()->GetWrtShell().SetRedlineComment(Engine()->GetEditEngine().GetText()); + } + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); +} + +void SwRedComment::SetPostItText() +{ + Engine()->SetModifyHdl( Link() ); + Engine()->EnableUndo( FALSE ); + + Engine()->Clear(); + View()->SetAttribs(DefaultItem()); + View()->InsertText(pRedline->GetComment(),false); + + Engine()->ClearModifyFlag(); + Engine()->GetUndoManager().Clear(); + Engine()->EnableUndo( TRUE ); + Engine()->SetModifyHdl( LINK( this, SwMarginWin, ModifyHdl ) ); + Invalidate(); +} + +void SwRedComment::DeactivatePostIt() +{ + SwMarginWin::DeactivatePostIt(); + // current Redline is still selected + DocView()->GetWrtShellPtr()->ClearMark(); +} + +void SwRedComment::ActivatePostIt() +{ + SwMarginWin::ActivatePostIt(); + + // do we want the redline selected? + // otherwise, SwRedComment::ActivatePostIt() as well as SwRedComment::DeactivatePostIt() + // can be thrown out completly + DocView()->GetDocShell()->GetWrtShell()->GotoRedline( + DocView()->GetDocShell()->GetWrtShell()->FindRedlineOfData(pRedline->GetRedlineData()),true); +} + +void SwRedComment::MouseButtonDown( const MouseEvent& rMEvt ) +{ + if (mRectMetaButton.IsInside(PixelToLogic(rMEvt.GetPosPixel())) && rMEvt.IsLeft()) + { + ExecuteCommand( mpButtonPopup->Execute( this,Rectangle(LogicToPixel(mRectMetaButton.BottomLeft()),LogicToPixel(mRectMetaButton.BottomLeft())),POPUPMENU_EXECUTE_DOWN | POPUPMENU_NOMOUSEUPCLOSE) ); + } +} + +void SwRedComment::Delete() +{ + SwMarginWin::Delete(); + // we are not neccessarily on our redline, so let's move there + GotoPos(); + DocView()->GetWrtShell().SetRedlineComment(EMPTYSTRING); + DocView()->GetWrtShell().ClearMark(); + // so we get a new layout of notes (ankor position is still the same and we would otherwise not get one) + Mgr()->SetLayout(); + Mgr()->RemoveItem(pRedline); +} + +void SwRedComment::GotoPos() +{ + DocView()->GetDocShell()->GetWrtShell()->GotoRedline( + DocView()->GetDocShell()->GetWrtShell()->FindRedlineOfData(pRedline->GetRedlineData())); +} + +String SwRedComment::GetAuthor() +{ + return pRedline->GetAuthorString(); +} + +Date SwRedComment::GetDate() +{ + return pRedline->GetTimeStamp().GetDate(); +} + +Time SwRedComment::GetTime() +{ + return pRedline->GetTimeStamp().GetTime(); +} + +bool SwRedComment::IsProtected() +{ + return SwMarginWin::IsProtected() || pRedline->Start()->nNode.GetNode().GetTxtNode()->IsInProtectSect(); +} +*/ + +////////////////////////////////////////////////////////////////////////////// +// 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 SwPostItShadowPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D +{ +private: + basegfx::B2DPoint maBasePosition; + basegfx::B2DPoint maSecondPosition; + ShadowState maShadowState; + +protected: + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition( + const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; + +public: + SwPostItShadowPrimitive( + 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; + + DeclPrimitrive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence SwPostItShadowPrimitive::createLocalDecomposition( + 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 SwPostItShadowPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const SwPostItShadowPrimitive& rCompare = static_cast< const SwPostItShadowPrimitive& >(rPrimitive); + + return (getBasePosition() == rCompare.getBasePosition() + && getSecondPosition() == rCompare.getSecondPosition() + && getShadowState() == rCompare.getShadowState()); + } + + return false; +} + +ImplPrimitrive2DIDBlock(SwPostItShadowPrimitive, PRIMITIVE2D_ID_SWPOSTITSHADOWPRIMITIVE) + +/****** SwPostItShadow ***********************************************************/ +SwPostItShadow::SwPostItShadow(const basegfx::B2DPoint& rBasePos,const basegfx::B2DPoint& rSecondPosition, + Color aBaseColor,ShadowState aState) + : OverlayObjectWithBasePosition(rBasePos, aBaseColor), + maSecondPosition(rSecondPosition), + mShadowState(aState) +{ +// mbAllowsAnimation = false; +} + +SwPostItShadow::~SwPostItShadow() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence SwPostItShadow::createOverlayObjectPrimitive2DSequence() +{ + const drawinglayer::primitive2d::Primitive2DReference aReference( + new SwPostItShadowPrimitive( + getBasePosition(), + GetSecondPosition(), + GetShadowState())); + return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); +} + +void SwPostItShadow::SetShadowState(ShadowState aState) +{ + if (mShadowState != aState) + { + mShadowState = aState; + + objectChange(); + } +} + +void SwPostItShadow::SetPosition(const basegfx::B2DPoint& rPoint1, + const basegfx::B2DPoint& rPoint2) +{ + if(!rPoint1.equal(getBasePosition()) || !rPoint2.equal(GetSecondPosition())) + { + maBasePosition = rPoint1; + maSecondPosition = rPoint2; + + objectChange(); + } +} + +////////////////////////////////////////////////////////////////////////////// +// helper class: Primitive for discrete visualisation + +class SwPostItAnkorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D +{ +private: + basegfx::B2DPolygon maTriangle; + basegfx::B2DPolygon maLine; + basegfx::B2DPolygon maLineTop; + AnkorState maAnkorState; + basegfx::BColor maColor; + + // discrete line width + double mfLogicLineWidth; + + // bitfield + bool mbShadow : 1; + bool mbLineSolid : 1; + +protected: + virtual drawinglayer::primitive2d::Primitive2DSequence createLocalDecomposition( + const drawinglayer::geometry::ViewInformation2D& rViewInformation) const; + +public: + SwPostItAnkorPrimitive( + const basegfx::B2DPolygon& rTriangle, + const basegfx::B2DPolygon& rLine, + const basegfx::B2DPolygon& rLineTop, + AnkorState aAnkorState, + const basegfx::BColor& rColor, + double fLogicLineWidth, + bool bShadow, + bool bLineSolid) + : drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D(), + maTriangle(rTriangle), + maLine(rLine), + maLineTop(rLineTop), + maAnkorState(aAnkorState), + maColor(rColor), + mfLogicLineWidth(fLogicLineWidth), + 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; } + AnkorState getAnkorState() const { return maAnkorState; } + const basegfx::BColor& getColor() const { return maColor; } + double getLogicLineWidth() const { return mfLogicLineWidth; } + bool getShadow() const { return mbShadow; } + bool getLineSolid() const { return mbLineSolid; } + + virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const; + + DeclPrimitrive2DIDBlock() +}; + +drawinglayer::primitive2d::Primitive2DSequence SwPostItAnkorPrimitive::createLocalDecomposition( + const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const +{ + drawinglayer::primitive2d::Primitive2DSequence aRetval; + + if(AS_TRI == getAnkorState() || AS_ALL == getAnkorState() || AS_START == getAnkorState()) + { + // create triangle + const drawinglayer::primitive2d::Primitive2DReference aTriangle( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(getTriangle()), + getColor())); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aTriangle); + } + + if(AS_ALL == getAnkorState() || AS_START == getAnkorState()) + { + // create line start + const drawinglayer::attribute::LineAttribute aLineAttribute( + getColor(), + getLogicLineWidth() / (basegfx::fTools::equalZero(getDiscreteUnit()) ? 1.0 : getDiscreteUnit())); + + 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 == getAnkorState() || AS_END == getAnkorState()) + { + // LineTop has to be created, too, but uses no shadow, so add after + // the other parts are created + const drawinglayer::attribute::LineAttribute aLineAttribute( + getColor(), + getLogicLineWidth() / (basegfx::fTools::equalZero(getDiscreteUnit()) ? 1.0 : getDiscreteUnit())); + + const drawinglayer::primitive2d::Primitive2DReference aLineTop( + new drawinglayer::primitive2d::PolygonStrokePrimitive2D( + getLineTop(), + aLineAttribute)); + + drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aLineTop); + } + + return aRetval; +} + +bool SwPostItAnkorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const +{ + if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive)) + { + const SwPostItAnkorPrimitive& rCompare = static_cast< const SwPostItAnkorPrimitive& >(rPrimitive); + + return (getTriangle() == rCompare.getTriangle() + && getLine() == rCompare.getLine() + && getLineTop() == rCompare.getLineTop() + && getAnkorState() == rCompare.getAnkorState() + && getColor() == rCompare.getColor() + && getLogicLineWidth() == rCompare.getLogicLineWidth() + && getShadow() == rCompare.getShadow() + && getLineSolid() == rCompare.getLineSolid()); + } + + return false; +} + +ImplPrimitrive2DIDBlock(SwPostItAnkorPrimitive, PRIMITIVE2D_ID_SWPOSTITANKORPRIMITIVE) + +/****** SwPostItAnkor ***********************************************************/ + +void SwPostItAnkor::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 SwPostItAnkor::implResetGeometry() +{ + maTriangle.clear(); + maLine.clear(); + maLineTop.clear(); +} + +SwPostItAnkor::SwPostItAnkor(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, + Color aBaseColor, + bool bShadowedEffect, + bool bLineSolid) + : OverlayObjectWithBasePosition(rBasePos, aBaseColor), + maSecondPosition(rSecondPos), + maThirdPosition(rThirdPos), + maFourthPosition(rFourthPos), + maFifthPosition(rFifthPos), + maSixthPosition(rSixthPos), + maSeventhPosition(rSeventhPos), + maTriangle(), + maLine(), + maLineTop(), + mHeight(0), + mAnkorState(AS_ALL), + mbShadowedEffect(bShadowedEffect), + mbLineSolid(bLineSolid) +{ + //mbAllowsAnimation = true; +} + +SwPostItAnkor::~SwPostItAnkor() +{ +} + +drawinglayer::primitive2d::Primitive2DSequence SwPostItAnkor::createOverlayObjectPrimitive2DSequence() +{ + implEnsureGeometry(); + + const drawinglayer::primitive2d::Primitive2DReference aReference( + new SwPostItAnkorPrimitive( + maTriangle, + maLine, + maLineTop, + GetAnkorState(), + getBaseColor().getBColor(), + ANKORLINE_WIDTH * 15.0, + getShadowedEffect(), + getLineSolid())); + + return drawinglayer::primitive2d::Primitive2DSequence(&aReference, 1); +} + +void SwPostItAnkor::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 SwPostItAnkor::SetSixthPosition(const basegfx::B2DPoint& rNew) +{ + if(rNew != maSixthPosition) + { + maSixthPosition = rNew; + implResetGeometry(); + objectChange(); + } +} + +void SwPostItAnkor::SetSeventhPosition(const basegfx::B2DPoint& rNew) +{ + if(rNew != maSeventhPosition) + { + maSeventhPosition = rNew; + implResetGeometry(); + objectChange(); + } +} + +void SwPostItAnkor::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 SwPostItAnkor::setLineSolid(bool bNew) +{ + if(bNew != getLineSolid()) + { + mbLineSolid = bNew; + objectChange(); + } +} + +void SwPostItAnkor::SetAnkorState(AnkorState aState) +{ + if (mAnkorState != aState) + { + mAnkorState = aState; + objectChange(); + } +} |