Files
libreoffice/sw/source/ui/docvw/postit.cxx
2009-12-21 20:40:13 +01:00

2487 lines
83 KiB
C++

/************************************************************************* *
*
* 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 create2DDecomposition(
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::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 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 create2DDecomposition(
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::create2DDecomposition(
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();
}
}