xref: /trunk/main/sw/source/ui/docvw/PostItMgr.cxx (revision 30b58845)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sw.hxx"
24 
25 #include "PostItMgr.hxx"
26 #include <postithelper.hxx>
27 
28 #include <SidebarWin.hxx>
29 #include <AnnotationWin.hxx>
30 #include <frmsidebarwincontainer.hxx>
31 #include <accmap.hxx>
32 
33 #include <SidebarWindowsConsts.hxx>
34 #include <AnchorOverlayObject.hxx>
35 #include <ShadowOverlayObject.hxx>
36 
37 #include <vcl/svapp.hxx>
38 #include <vcl/scrbar.hxx>
39 #include <vcl/outdev.hxx>
40 
41 #include <viewopt.hxx>
42 
43 #include <view.hxx>
44 #include <docsh.hxx>
45 #include <wrtsh.hxx>
46 #include <doc.hxx>
47 #include <fldbas.hxx>
48 #include <fmtfld.hxx>
49 #include <docufld.hxx>
50 #include <edtwin.hxx>
51 #include <txtfld.hxx>
52 #include <txtannotationfld.hxx>
53 #include <ndtxt.hxx>
54 #include <redline.hxx>
55 #include <docary.hxx>
56 #include <SwRewriter.hxx>
57 #include <tools/color.hxx>
58 
59 #include <swmodule.hxx>
60 #include <annotation.hrc>
61 #include "cmdid.h"
62 
63 #include <sfx2/request.hxx>
64 #include <sfx2/event.hxx>
65 #include <svl/srchitem.hxx>
66 
67 
68 #include <svl/languageoptions.hxx>
69 #include <svtools/langtab.hxx>
70 #include <svl/smplhint.hxx>
71 
72 #include <svx/svdview.hxx>
73 #include <editeng/eeitem.hxx>
74 #include <editeng/langitem.hxx>
75 #include <editeng/outliner.hxx>
76 
77 #include <i18npool/mslangid.hxx>
78 #include <i18npool/lang.h>
79 
80 #include "swevent.hxx"
81 #include "switerator.hxx"
82 
83 // distance between Anchor Y and initial note position
84 #define POSTIT_INITIAL_ANCHOR_DISTANCE      20
85 //distance between two postits
86 #define POSTIT_SPACE_BETWEEN				8
87 #define POSTIT_MINIMUMSIZE_WITH_META		60
88 #define POSTIT_SCROLL_SIDEBAR_HEIGHT		20
89 
90 // if we layout more often we stop, this should never happen
91 #define MAX_LOOP_COUNT						50
92 
93 using namespace sw::sidebarwindows;
94 
95 
comp_pos(const SwSidebarItem * a,const SwSidebarItem * b)96 bool comp_pos(const SwSidebarItem* a, const SwSidebarItem* b)
97 {
98     // sort by anchor position
99     return a->GetAnchorPosition() < b->GetAnchorPosition();
100 }
101 
SwPostItMgr(SwView * pView)102 SwPostItMgr::SwPostItMgr(SwView* pView)
103 	: mpView(pView)
104 	, mpWrtShell(mpView->GetDocShell()->GetWrtShell())
105 	, mpEditWin(&mpView->GetEditWin())
106 	, mnEventId(0)
107 	, mbWaitingForCalcRects(false)
108 	, mpActivePostIt(0)
109 	, mbLayout(false)
110 	, mbLayoutHeight(0)
111 	, mbLayouting(false)
112 	, mbReadOnly(mpView->GetDocShell()->IsReadOnly())
113 	, mbDeleteNote(true)
114 	, mpAnswer(0)
115     , mbIsShowAnchor( false )
116     , mpFrmSidebarWinContainer( 0 )
117 {
118 	if(!mpView->GetDrawView() )
119 		mpView->GetWrtShell().MakeDrawView();
120 
121 	SwNoteProps aProps;
122     mbIsShowAnchor = aProps.IsShowAnchor();
123 
124 	//make sure we get the color yellow always, even if not the first one of comments or redlining
125 	SW_MOD()->GetRedlineAuthor();
126 
127 	// collect all PostIts and redline comments that exist after loading the document
128 	// don't check for existence for any of them, don't focus them
129 	AddPostIts(false,false);
130     /*  this code can be used once we want redline comments in the Sidebar
131 	AddRedlineComments(false,false);
132 	*/
133 	// we want to receive stuff like SFX_HINT_DOCCHANGED
134 	StartListening(*mpView->GetDocShell());
135 	if (!mvPostItFlds.empty())
136 	{
137 		mbWaitingForCalcRects = true;
138 		mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 );
139 	}
140 }
141 
~SwPostItMgr()142 SwPostItMgr::~SwPostItMgr()
143 {
144 	if ( mnEventId )
145 		Application::RemoveUserEvent( mnEventId );
146     // forget about all our Sidebar windows
147     RemoveSidebarWin();
148 	EndListening( *mpView->GetDocShell() );
149 
150 	for(std::vector<SwPostItPageItem*>::iterator i = mPages.begin(); i!= mPages.end() ; i++)
151 		delete (*i);
152 	mPages.clear();
153 
154     delete mpFrmSidebarWinContainer;
155     mpFrmSidebarWinContainer = 0;
156 }
157 
CheckForRemovedPostIts()158 void SwPostItMgr::CheckForRemovedPostIts()
159 {
160 	bool bRemoved = false;
161     for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end(); )
162 	{
163         std::list<SwSidebarItem*>::iterator it = i++;
164 		if ( !(*it)->UseElement() )
165 		{
166             SwSidebarItem* p = (*it);
167 			mvPostItFlds.remove(*it);
168             if (GetActiveSidebarWin() == p->pPostIt)
169                 SetActiveSidebarWin(0);
170 			if (p->pPostIt)
171 				delete p->pPostIt;
172 			delete p;
173 			bRemoved = true;
174 		}
175 	}
176 
177 	if ( bRemoved )
178 	{
179 		// make sure that no deleted items remain in page lists
180 		// todo: only remove deleted ones?!
181 		if ( mvPostItFlds.empty() )
182 		{
183 			PreparePageContainer();
184 			PrepareView();
185 		}
186 		else
187 			// if postits are their make sure that page lists are not empty
188 			// otherwise sudden paints can cause pain (in BorderOverPageBorder)
189 			CalcRects();
190 	}
191 }
192 
InsertItem(SfxBroadcaster * pItem,bool bCheckExistance,bool bFocus)193 void SwPostItMgr::InsertItem(SfxBroadcaster* pItem, bool bCheckExistance, bool bFocus)
194 {
195 	if (bCheckExistance)
196 	{
197         for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
198 		{
199 			if ( (*i)->GetBroadCaster() == pItem )
200 				return;
201 		}
202 	}
203 	mbLayout = bFocus;
204 	if (pItem->ISA(SwFmtFld))
205         mvPostItFlds.push_back(new SwAnnotationItem(static_cast<SwFmtFld&>(*pItem), true, bFocus) );
206 	/*
207 	else
208 	if (pItem->ISA(SwRedline))
209 		mvPostItFlds.push_back(new SwRedCommentItem( static_cast<SwRedline*>(pItem), true, bFocus)) ;
210 	*/
211 	DBG_ASSERT(pItem->ISA(SwFmtFld) /*|| pItem->ISA(SwRedline)*/,"Mgr::InsertItem: seems like new stuff was added");
212 	StartListening(*pItem);
213 }
214 
RemoveItem(SfxBroadcaster * pBroadcast)215 void SwPostItMgr::RemoveItem( SfxBroadcaster* pBroadcast )
216 {
217 	EndListening(*pBroadcast);
218     for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
219 	{
220 		if ( (*i)->GetBroadCaster() == pBroadcast )
221 		{
222             SwSidebarItem* p = (*i);
223             if (GetActiveSidebarWin() == p->pPostIt)
224                 SetActiveSidebarWin(0);
225 			mvPostItFlds.remove(*i);
226 			delete p->pPostIt;
227 			delete p;
228 			break;
229 		}
230 	}
231 	mbLayout = true;
232 	PrepareView();
233 }
234 
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)235 void SwPostItMgr::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
236 {
237 	if ( rHint.IsA(TYPE(SfxEventHint) ) )
238 	{
239 		sal_uInt32 nId = ((SfxEventHint&)rHint).GetEventId();
240 		if ( nId == SW_EVENT_LAYOUT_FINISHED )
241 		{
242 			if ( !mbWaitingForCalcRects && !mvPostItFlds.empty())
243 			{
244 				mbWaitingForCalcRects = true;
245 				mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 );
246 			}
247 		}
248 	}
249 	else if ( rHint.IsA(TYPE(SfxSimpleHint)	) )
250 	{
251 		sal_uInt32 nId = ((SfxSimpleHint&)rHint).GetId();
252 		switch ( nId )
253 		{
254 			case SFX_HINT_MODECHANGED:
255 			{
256 				if ( mbReadOnly != !!(mpView->GetDocShell()->IsReadOnly()) )
257 				{
258 					mbReadOnly = !mbReadOnly;
259 					SetReadOnlyState();
260 					mbLayout = true;
261 				}
262 				break;
263 			}
264 			case SFX_HINT_DOCCHANGED:
265 			{
266 				if ( mpView->GetDocShell() == &rBC )
267 				{
268 					if ( !mbWaitingForCalcRects && !mvPostItFlds.empty())
269 					{
270 						mbWaitingForCalcRects = true;
271 						mnEventId = Application::PostUserEvent( LINK( this, SwPostItMgr, CalcHdl), 0 );
272 					}
273 				}
274 				break;
275 			}
276 			case SFX_HINT_USER04:
277 			{
278 				// if we are in a SplitNode/Cut operation, do not delete note and then add again, as this will flicker
279 				mbDeleteNote = !mbDeleteNote;
280 				break;
281 			}
282 			case SFX_HINT_DYING:
283 			{
284 				if ( mpView->GetDocShell() != &rBC )
285 				{
286 					// field to be removed is the broadcaster
287 					DBG_ERROR("Notification for removed SwFmtFld was not sent!");
288 					RemoveItem(&rBC);
289 				}
290 				break;
291 			}
292 		}
293 	}
294 	/*
295 	else if ( rHint.IsA(TYPE(SwRedlineHint) ) )
296 	{
297 		const SwRedlineHint rRedlineHint = static_cast<const SwRedlineHint&>(rHint);
298 	   	SwRedline* pRedline = const_cast<SwRedline*>(rRedlineHint.GetRedline());
299 		switch ( rRedlineHint.Which() )
300 		{
301 			case SWREDLINE_INSERTED :
302 			{
303 				bool bEmpty = !HasNotes();
304 				InsertItem( pRedline, true, false );
305 				if (bEmpty && !mvPostItFlds.empty())
306 					PrepareView(true);
307 				break;
308 			}
309 			case SWREDLINE_REMOVED:
310 			{
311 				RemoveItem(pRedline);
312 				break;
313 			}
314 			case SWREDLINE_FOCUS:
315 			{
316                                 if (rRedlineHint.GetView()== mpView)
317 					Focus(rBC);
318 				break;
319 			}
320 		}
321 	}
322 	*/
323 	else if ( rHint.IsA(TYPE(SwFmtFldHint) ) )
324 	{
325 		const SwFmtFldHint& rFmtHint = static_cast<const SwFmtFldHint&>(rHint);
326 		SwFmtFld* pFld = const_cast <SwFmtFld*>( rFmtHint.GetField() );
327 		switch ( rFmtHint.Which() )
328 		{
329 			case SWFMTFLD_INSERTED :
330 			{
331 				if (!pFld)
332 				{
333 					AddPostIts(true);
334 					break;
335 				}
336 				// get field to be inserted from hint
337 				if ( pFld->IsFldInDoc() )
338 				{
339 					bool bEmpty = !HasNotes();
340 					InsertItem( pFld, true, false );
341 					if (bEmpty && !mvPostItFlds.empty())
342 						PrepareView(true);
343 				}
344 				else
345 				{
346 					DBG_ERROR( "Inserted field not in document!" );
347                 		}
348 				break;
349 			}
350 			case SWFMTFLD_REMOVED:
351 			{
352 				if (mbDeleteNote)
353 				{
354 					if (!pFld)
355 					{
356 						CheckForRemovedPostIts();
357 						break;
358 					}
359 					RemoveItem(pFld);
360 				}
361 				break;
362 			}
363 			case SWFMTFLD_FOCUS:
364 			{
365        				if (rFmtHint.GetView()== mpView)
366 					Focus(rBC);
367 				break;
368 			}
369 			case SWFMTFLD_CHANGED:
370 			{
371 		                SwFmtFld* pFmtFld = dynamic_cast<SwFmtFld*>(&rBC);
372                 for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
373 				{
374                 			if ( pFmtFld == (*i)->GetBroadCaster() )
375 					{
376 						if ((*i)->pPostIt)
377 						{
378 							(*i)->pPostIt->SetPostItText();
379 							mbLayout = true;
380 						}
381 						break;
382 					}
383 				}
384 				break;
385 			}
386 
387             case SWFMTFLD_LANGUAGE:
388                 {
389                     SwFmtFld* pFmtFld = dynamic_cast<SwFmtFld*>(&rBC);
390                     for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
391                     {
392                         if ( pFmtFld == (*i)->GetBroadCaster() )
393                         {
394                             if ((*i)->pPostIt)
395                             {
396                                 const sal_uInt16 nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( (*i)->GetFmtFld().GetField()->GetLanguage() );
397                                 sal_uInt16 nLangWhichId = 0;
398                                 switch (nScriptType)
399                                 {
400                                 case SCRIPTTYPE_LATIN :    nLangWhichId = EE_CHAR_LANGUAGE ; break;
401                                 case SCRIPTTYPE_ASIAN :    nLangWhichId = EE_CHAR_LANGUAGE_CJK; break;
402                                 case SCRIPTTYPE_COMPLEX :  nLangWhichId = EE_CHAR_LANGUAGE_CTL; break;
403                                 }
404                                 (*i)->pPostIt->SetLanguage(
405                                     SvxLanguageItem(
406                                     (*i)->GetFmtFld().GetField()->GetLanguage(),
407                                     nLangWhichId) );
408                             }
409                             break;
410                         }
411                     }
412                     break;
413                 }
414         }
415     }
416 }
417 
Focus(SfxBroadcaster & rBC)418 void SwPostItMgr::Focus(SfxBroadcaster& rBC)
419 {
420 	if (!mpWrtShell->GetViewOptions()->IsPostIts())
421 	{
422 		SfxRequest aRequest(mpView->GetViewFrame(),FN_VIEW_NOTES);
423 		mpView->ExecViewOptions(aRequest);
424 	}
425 
426     for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
427 	{
428 		// field to get the focus is the broadcaster
429 		if ( &rBC == (*i)->GetBroadCaster() )
430 		{
431 			if ((*i)->pPostIt)
432 			{
433 				(*i)->pPostIt->GrabFocus();
434 				MakeVisible((*i)->pPostIt);
435 			}
436 			else
437 			{
438 				// when the layout algorithm starts, this postit is created and receives focus
439 				(*i)->bFocus = true;
440 			}
441 		}
442 	}
443 }
444 
CalcRects()445 bool SwPostItMgr::CalcRects()
446 {
447     if ( mnEventId )
448     {
449         // if CalcRects() was forced and an event is still pending: remove it
450         // it is superfluous and also may cause reentrance problems if triggered while layouting
451         Application::RemoveUserEvent( mnEventId );
452         mnEventId = 0;
453     }
454 
455     bool bChange = false;
456     bool bRepair = false;
457     PreparePageContainer();
458     if ( !mvPostItFlds.empty() )
459     {
460         for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
461         {
462             SwSidebarItem* pItem = (*i);
463             if ( !pItem->UseElement() )
464             {
465                 DBG_ERROR("PostIt is not in doc or other wrong use");
466                 bRepair = true;
467                 continue;
468             }
469 
470             const SwRect aOldAnchorRect( pItem->maLayoutInfo.mPosition );
471             const SwPostItHelper::SwLayoutStatus eOldLayoutStatus = pItem->mLayoutStatus;
472             const sal_uLong nOldStartNodeIdx( pItem->maLayoutInfo.mnStartNodeIdx );
473             const xub_StrLen nOldStartContent( pItem->maLayoutInfo.mnStartContent );
474 
475             {
476                 // update layout information
477                 const SwTxtAnnotationFld* pTxtAnnotationFld =
478                     dynamic_cast< const SwTxtAnnotationFld* >( pItem->GetFmtFld().GetTxtFld() );
479                 const ::sw::mark::IMark* pAnnotationMark =
480                     pTxtAnnotationFld != NULL ? pTxtAnnotationFld->GetAnnotationMark() : NULL;
481                 if ( pAnnotationMark != NULL )
482                 {
483                     pItem->mLayoutStatus =
484                         SwPostItHelper::getLayoutInfos(
485                             pItem->maLayoutInfo,
486                             pItem->GetAnchorPosition(),
487                             &pAnnotationMark->GetMarkStart() );
488                 }
489                 else
490                 {
491                     pItem->mLayoutStatus =
492                         SwPostItHelper::getLayoutInfos( pItem->maLayoutInfo, pItem->GetAnchorPosition() );
493                 }
494             }
495             bChange = bChange
496                       || pItem->maLayoutInfo.mPosition != aOldAnchorRect
497                       || pItem->mLayoutStatus != eOldLayoutStatus
498                       || pItem->maLayoutInfo.mnStartNodeIdx != nOldStartNodeIdx
499                       || pItem->maLayoutInfo.mnStartContent != nOldStartContent;
500         }
501 
502         // show notes in right order in navigator
503         // prevent Anchors during layout to overlap, e.g. when moving a frame
504         Sort(SORT_POS);
505 
506         // sort the items into the right page vector, so layout can be done by page
507         for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
508         {
509             SwSidebarItem* pItem = (*i);
510             if( SwPostItHelper::INVISIBLE == pItem->mLayoutStatus )
511             {
512                 if (pItem->pPostIt)
513                     pItem->pPostIt->HideNote();
514                 continue;
515             }
516 
517             if( SwPostItHelper::HIDDEN == pItem->mLayoutStatus )
518             {
519                 if (!mpWrtShell->GetViewOptions()->IsShowHiddenChar())
520                 {
521                     if (pItem->pPostIt)
522                         pItem->pPostIt->HideNote();
523                     continue;
524                 }
525             }
526 
527             const unsigned long aPageNum = pItem->maLayoutInfo.mnPageNumber;
528             if (aPageNum > mPages.size())
529             {
530                 const unsigned long nNumberOfPages = mPages.size();
531                 for (unsigned int j=0; j<aPageNum - nNumberOfPages; ++j)
532                     mPages.push_back( new SwPostItPageItem());
533             }
534             mPages[aPageNum-1]->mList->push_back(pItem);
535             mPages[aPageNum-1]->mPageRect = pItem->maLayoutInfo.mPageFrame;
536             mPages[aPageNum-1]->eSidebarPosition = pItem->maLayoutInfo.meSidebarPosition;
537         }
538 
539         if (!bChange && mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE))
540         {
541             long nLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() );
542             if( nLayoutHeight > mbLayoutHeight )
543             {
544                 if (mPages[0]->bScrollbar || HasScrollbars())
545                     bChange = true;
546             }
547             else if( nLayoutHeight < mbLayoutHeight )
548             {
549                 if (mPages[0]->bScrollbar || !BorderOverPageBorder(1))
550                     bChange = true;
551             }
552         }
553     }
554 
555     if ( bRepair )
556         CheckForRemovedPostIts();
557 
558     mbLayoutHeight = SwPostItHelper::getLayoutHeight( mpWrtShell->GetLayout() );
559     mbWaitingForCalcRects = false;
560     return bChange;
561 }
562 
HasScrollbars() const563 bool SwPostItMgr::HasScrollbars() const
564 {
565     for(std::list<SwSidebarItem*>::const_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
566 	{
567         if ((*i)->bShow && (*i)->pPostIt && (*i)->pPostIt->HasScrollbar())
568 			return true;
569 	}
570 	return false;
571 }
572 
PreparePageContainer()573 void SwPostItMgr::PreparePageContainer()
574 {
575 	// we do not just delete the SwPostItPageItem, so offset/scrollbar is not lost
576 	long lPageSize = mpWrtShell->GetNumPages();
577 	long lContainerSize = mPages.size();
578 
579 	if (lContainerSize < lPageSize)
580 	{
581 		for (int i=0; i<lPageSize - lContainerSize;i++)
582 			mPages.push_back( new SwPostItPageItem());
583 	}
584 	else
585 	if (lContainerSize > lPageSize)
586 	{
587 		for (int i=mPages.size()-1; i >= lPageSize;--i)
588 		{
589 			delete mPages[i];
590 			mPages.pop_back();
591 		}
592 	}
593 	// only clear the list, DO NOT delete the objects itself
594 	for(std::vector<SwPostItPageItem*>::iterator i = mPages.begin(); i!= mPages.end() ; i++)
595 	{
596 		(*i)->mList->clear();
597 		if (mvPostItFlds.empty())
598 			(*i)->bScrollbar = false;
599 
600 	}
601 }
602 
LayoutPostIts()603 void SwPostItMgr::LayoutPostIts()
604 {
605 	if ( !mvPostItFlds.empty() && !mbWaitingForCalcRects )
606 	{
607 		mbLayouting = true;
608 
609 			//loop over all pages and do the layout
610 			// - create SwPostIt if necessary
611 			// - place SwPostIts on their initial position
612 			// - calculate necessary height for all PostIts together
613 			bool bUpdate = false;
614 			for (unsigned long n=0;n<mPages.size();n++)
615 			{
616 				// only layout if there are notes on this page
617 				if (mPages[n]->mList->size()>0)
618 				{
619                     std::list<SwSidebarWin*>    aVisiblePostItList;
620 					unsigned long			lNeededHeight = 0;
621 					long					mlPageBorder = 0;
622 					long					mlPageEnd = 0;
623 
624                     for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i!= mPages[n]->mList->end(); i++)
625 					{
626                         SwSidebarItem* pItem = (*i);
627                         SwSidebarWin* pPostIt = pItem->pPostIt;
628 
629                         if (mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT )
630 						{
631 							// x value for notes positioning
632 							mlPageBorder = mpEditWin->LogicToPixel( Point( mPages[n]->mPageRect.Left(), 0)).X() - GetSidebarWidth(true);// - GetSidebarBorderWidth(true);
633 							//bending point
634                             mlPageEnd =
635                                 mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE)
636                                 ? pItem->maLayoutInfo.mPagePrtArea.Left()
637                                 : mPages[n]->mPageRect.Left() + 350;
638 						}
639                         else if (mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT )
640 						{
641 							// x value for notes positioning
642 							mlPageBorder = mpEditWin->LogicToPixel( Point(mPages[n]->mPageRect.Right(), 0)).X() + GetSidebarBorderWidth(true);
643 							//bending point
644                             mlPageEnd =
645                                 mpWrtShell->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE)
646                                 ? pItem->maLayoutInfo.mPagePrtArea.Right() :
647                                 mPages[n]->mPageRect.Right() - 350;
648 						}
649 
650 						if (pItem->bShow)
651 						{
652                             long Y = mpEditWin->LogicToPixel( Point(0,pItem->maLayoutInfo.mPosition.Bottom())).Y();
653 							long aPostItHeight = 0;
654 							if (!pPostIt)
655 							{
656                                 pPostIt = (*i)->GetSidebarWindow( mpView->GetEditWin(),
657                                                                   WB_DIALOGCONTROL,
658                                                                   *this,
659                                                                   0 );
660 								pPostIt->InitControls();
661 								pPostIt->SetReadonly(mbReadOnly);
662 								pItem->pPostIt = pPostIt;
663 								if (mpAnswer)
664 								{
665 									if (pPostIt->CalcFollow()) //do we really have another note in front of this one
666                                         static_cast<sw::annotation::SwAnnotationWin*>(pPostIt)->InitAnswer(mpAnswer);
667 									delete mpAnswer;
668 									mpAnswer = 0;
669 								}
670 							}
671 
672                             pPostIt->SetChangeTracking(
673                                 pItem->mLayoutStatus,
674                                 GetColorAnchor(pItem->maLayoutInfo.mRedlineAuthor));
675                             pPostIt->SetSidebarPosition(mPages[n]->eSidebarPosition);
676                             pPostIt->SetFollow(pPostIt->CalcFollow());
677                             aPostItHeight = ( pPostIt->GetPostItTextHeight() < pPostIt->GetMinimumSizeWithoutMeta()
678                                               ? pPostIt->GetMinimumSizeWithoutMeta()
679                                               : pPostIt->GetPostItTextHeight() )
680                                             + pPostIt->GetMetaHeight();
681                             pPostIt->SetPosSizePixelRect( mlPageBorder ,
682                                                           Y - GetInitialAnchorDistance(),
683                                                           GetNoteWidth() ,
684                                                           aPostItHeight,
685                                                           pItem->maLayoutInfo.mPosition,
686                                                           mlPageEnd );
687                             pPostIt->ChangeSidebarItem( *pItem );
688 
689 							if (pItem->bFocus)
690 							{
691 								mbLayout = true;
692                                 pPostIt->GrabFocus();
693 								pItem->bFocus = false;
694 							}
695 							// only the visible postits are used for the final layout
696 							aVisiblePostItList.push_back(pPostIt);
697 							lNeededHeight += pPostIt->IsFollow() ? aPostItHeight : aPostItHeight+GetSpaceBetween();
698 						}
699 						else // we don't want to see it
700 						{
701 							if (pPostIt)
702 								pPostIt->HideNote();
703 						}
704 					}
705 
706 					if ((aVisiblePostItList.size()>0) && ShowNotes())
707 					{
708 						bool bOldScrollbar = mPages[n]->bScrollbar;
709 						if (ShowNotes())
710 							mPages[n]->bScrollbar = LayoutByPage(aVisiblePostItList, mPages[n]->mPageRect.SVRect(), lNeededHeight);
711 						else
712 							mPages[n]->bScrollbar = false;
713 						if (!mPages[n]->bScrollbar)
714 						{
715 							mPages[n]->lOffset = 0;
716 						}
717 						else
718 						{
719 							// when we changed our zoom level, the offset value can be to big, so lets check for the largest possible zoom value
720 							long aAvailableHeight = mpEditWin->LogicToPixel(Size(0,mPages[n]->mPageRect.Height())).Height() - 2 * GetSidebarScrollerHeight();
721 							long lOffset = -1 * GetScrollSize() * (aVisiblePostItList.size() - aAvailableHeight / GetScrollSize());
722 							if (mPages[n]->lOffset < lOffset)
723 								mPages[n]->lOffset = lOffset;
724 						}
725 						bUpdate = (bOldScrollbar != mPages[n]->bScrollbar) || bUpdate;
726 						const long aSidebarheight = mPages[n]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
727 						/*
728                        					TODO
729                        					- enlarge all notes till GetNextBorder(), as we resized to average value before
730                        					*/
731 						// let's hide the ones which overlap the page
732                         for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
733 						{
734 							if (mPages[n]->lOffset != 0)
735 								(*i)->TranslateTopPosition(mPages[n]->lOffset);
736 
737 							bool bBottom  = mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y()+(*i)->VirtualSize().Height())).Y() <= (mPages[n]->mPageRect.Bottom()-aSidebarheight);
738 							bool bTop = mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y())).Y() >= (mPages[n]->mPageRect.Top()+aSidebarheight);
739 							if ( bBottom && bTop )
740 							{
741 								(*i)->ShowNote();
742 							}
743 							else
744 							{
745 								if (mpEditWin->PixelToLogic(Point(0,(*i)->VirtualPos().Y())).Y() < (mPages[n]->mPageRect.Top()+aSidebarheight))
746 								{
747                                     if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT )
748                                         (*i)->ShowAnchorOnly(Point( mPages[n]->mPageRect.Left(),
749                                                                     mPages[n]->mPageRect.Top()));
750                                     else if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT )
751                                         (*i)->ShowAnchorOnly(Point( mPages[n]->mPageRect.Right(),
752                                                                     mPages[n]->mPageRect.Top()));
753 								}
754 								else
755 								{
756                                     if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT )
757                                         (*i)->ShowAnchorOnly(Point(mPages[n]->mPageRect.Left(),
758                                                                    mPages[n]->mPageRect.Bottom()));
759                                     else if ( mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT )
760                                         (*i)->ShowAnchorOnly(Point(mPages[n]->mPageRect.Right(),
761                                                                    mPages[n]->mPageRect.Bottom()));
762 								}
763 								DBG_ASSERT(mPages[n]->bScrollbar,"SwPostItMgr::LayoutByPage(): note overlaps, but bScrollbar is not true");
764 							}
765 						}
766 
767 						// do some magic so we really see the focused note
768                         for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
769 						{
770                             				if ((*i)->HasChildPathFocus())
771 							{
772 								MakeVisible((*i),n+1);
773 								break;
774 							}
775 						}
776 					}
777 					else
778 					{
779                         for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
780                                                                 (*i)->SetPosAndSize();
781 
782                                                         bool bOldScrollbar = mPages[n]->bScrollbar;
783                                                         mPages[n]->bScrollbar = false;
784                                                         bUpdate = (bOldScrollbar != mPages[n]->bScrollbar) || bUpdate;
785 					}
786 					aVisiblePostItList.clear();
787 				}
788 				else
789 				{
790 					bUpdate = true;
791 					mPages[n]->bScrollbar = false;
792 				}
793 			}
794 
795 			if (!ShowNotes())
796 			{       // we do not want to see the notes anymore -> Options-Writer-View-Notes
797 				bool bRepair = false;
798                 for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
799 				{
800                     SwSidebarItem* pItem = (*i);
801 					if ( !pItem->UseElement() )
802 					{
803 						DBG_ERROR("PostIt is not in doc!");
804 						bRepair = true;
805 						continue;
806 					}
807 
808 					if ((*i)->pPostIt)
809 					{
810 						(*i)->pPostIt->HideNote();
811 						if ((*i)->pPostIt->HasChildPathFocus())
812 						{
813                             SetActiveSidebarWin(0);
814 							(*i)->pPostIt->GrabFocusToDocument();
815 						}
816 					}
817 				}
818 
819 				if ( bRepair )
820 					CheckForRemovedPostIts();
821 			}
822 
823 
824 			// notes scrollbar is otherwise not drawn correctly for some cases
825 			// scrollbar area is enough
826 			if (bUpdate)
827 				mpEditWin->Invalidate();
828 		mbLayouting = false;
829 	}
830 }
831 
BorderOverPageBorder(unsigned long aPage) const832 bool SwPostItMgr::BorderOverPageBorder(unsigned long aPage) const
833 {
834 	if ( mPages[aPage-1]->mList->empty() )
835 	{
836 		DBG_ERROR("Notes SidePane painted but no rects and page lists calculated!");
837 		return false;
838 	}
839 
840     SwSidebarItem_iterator aItem = mPages[aPage-1]->mList->end();
841 	--aItem;
842 	DBG_ASSERT ((*aItem)->pPostIt,"BorderOverPageBorder: NULL postIt, should never happen");
843 	if ((*aItem)->pPostIt)
844 	{
845 		const long aSidebarheight = mPages[aPage-1]->bScrollbar ? mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height() : 0;
846 		const long aEndValue = mpEditWin->PixelToLogic(Point(0,(*aItem)->pPostIt->GetPosPixel().Y()+(*aItem)->pPostIt->GetSizePixel().Height())).Y();
847 		return aEndValue <= mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight;
848 	}
849 	else
850 		return false;
851 }
852 
Scroll(const long lScroll,const unsigned long aPage)853 void SwPostItMgr::Scroll(const long lScroll,const unsigned long aPage)
854 {
855 	DBG_ASSERT((lScroll % GetScrollSize() )==0,"SwPostItMgr::Scroll: scrolling by wrong value");
856 	// do not scroll more than necessary up or down
857 	if ( ((mPages[aPage-1]->lOffset == 0) && (lScroll>0)) || ( BorderOverPageBorder(aPage) && (lScroll<0)) )
858 		return;
859 
860 	const bool bOldUp = ArrowEnabled(KEY_PAGEUP,aPage);
861 	const bool bOldDown = ArrowEnabled(KEY_PAGEDOWN,aPage);
862 	const long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
863     for(SwSidebarItem_iterator i = mPages[aPage-1]->mList->begin(); i!= mPages[aPage-1]->mList->end(); i++)
864 	{
865         SwSidebarWin* pPostIt = (*i)->pPostIt;
866 		// if this is an answer, we should take the normal position and not the real, slightly moved position
867 		pPostIt->SetVirtualPosSize(pPostIt->GetPosPixel(),pPostIt->GetSizePixel());
868 		pPostIt->TranslateTopPosition(lScroll);
869 
870 		if ((*i)->bShow)
871 		{
872 			bool bBottom  = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y()+pPostIt->VirtualSize().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
873 			bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() >=	 (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
874 			if ( bBottom && bTop)
875 			{
876 					pPostIt->ShowNote();
877 			}
878 			else
879 			{
880 				if ( mpEditWin->PixelToLogic(Point(0,pPostIt->VirtualPos().Y())).Y() < (mPages[aPage-1]->mPageRect.Top()+aSidebarheight))
881 				{
882                     if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT)
883                         pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Top()));
884                     else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT)
885                         pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Top()));
886 				}
887 				else
888 				{
889                     if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT)
890                         pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Left(),mPages[aPage-1]->mPageRect.Bottom()));
891                     else if (mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_RIGHT)
892                         pPostIt->ShowAnchorOnly(Point(mPages[aPage-1]->mPageRect.Right(),mPages[aPage-1]->mPageRect.Bottom()));
893 				}
894 			}
895 		}
896 	}
897 	mPages[aPage-1]->lOffset += lScroll;
898 	if ( (bOldUp != ArrowEnabled(KEY_PAGEUP,aPage)) ||(bOldDown != ArrowEnabled(KEY_PAGEDOWN,aPage)) )
899 	{
900 		mpEditWin->Invalidate(GetBottomScrollRect(aPage));
901 		mpEditWin->Invalidate(GetTopScrollRect(aPage));
902 	}
903 }
904 
AutoScroll(const SwSidebarWin * pPostIt,const unsigned long aPage)905 void SwPostItMgr::AutoScroll(const SwSidebarWin* pPostIt,const unsigned long aPage )
906 {
907 	// otherwise all notes are visible
908 	if (mPages[aPage-1]->bScrollbar)
909 	{
910 		const long aSidebarheight = mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height();
911 		const bool bBottom  = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height())).Y() <= (mPages[aPage-1]->mPageRect.Bottom()-aSidebarheight);
912 		const bool bTop = mpEditWin->PixelToLogic(Point(0,pPostIt->GetPosPixel().Y())).Y() >= (mPages[aPage-1]->mPageRect.Top()+aSidebarheight);
913 		if ( !(bBottom && bTop))
914 		{
915 			const long aDiff = bBottom ? mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Top() + aSidebarheight)).Y() - pPostIt->GetPosPixel().Y() :
916 											mpEditWin->LogicToPixel(Point(0,mPages[aPage-1]->mPageRect.Bottom() - aSidebarheight)).Y() - (pPostIt->GetPosPixel().Y()+pPostIt->GetSizePixel().Height());
917 			// this just adds the missing value to get the next a* GetScrollSize() after aDiff
918 			// e.g aDiff= 61 POSTIT_SCOLL=50 --> lScroll = 100
919 			const long lScroll = bBottom ? (aDiff + ( GetScrollSize() - (aDiff % GetScrollSize()))) : (aDiff - (GetScrollSize() + (aDiff % GetScrollSize())));
920 			Scroll(lScroll, aPage);
921 		}
922 	}
923 }
924 
MakeVisible(const SwSidebarWin * pPostIt,long aPage)925 void SwPostItMgr::MakeVisible(const SwSidebarWin* pPostIt,long aPage )
926 {
927 	if (aPage == -1)
928 	{
929 		// we don't know the page yet, let's find it ourselves
930 		for (unsigned long n=0;n<mPages.size();n++)
931 		{
932 			if (mPages[n]->mList->size()>0)
933 			{
934                 for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i!= mPages[n]->mList->end(); i++)
935 				{
936 					if ((*i)->pPostIt==pPostIt)
937 					{
938 						aPage = n+1;
939 						break;
940 					}
941 				}
942 			}
943 		}
944 	}
945 	if (aPage!=-1)
946 		AutoScroll(pPostIt,aPage);
947 	Rectangle aNoteRect (Point(pPostIt->GetPosPixel().X(),pPostIt->GetPosPixel().Y()-5),pPostIt->GetSizePixel());
948 	if (!aNoteRect.IsEmpty())
949 		mpWrtShell->MakeVisible(SwRect(mpEditWin->PixelToLogic(aNoteRect)));
950 }
951 
ArrowEnabled(sal_uInt16 aDirection,unsigned long aPage) const952 bool SwPostItMgr::ArrowEnabled(sal_uInt16 aDirection,unsigned long aPage) const
953 {
954 	switch (aDirection)
955 	{
956 		case KEY_PAGEUP:
957 			{
958 				return (mPages[aPage-1]->lOffset != 0);
959 			}
960 		case KEY_PAGEDOWN:
961 			{
962 				return (!BorderOverPageBorder(aPage));
963 			}
964 		default: return false;
965 	}
966 }
967 
GetArrowColor(sal_uInt16 aDirection,unsigned long aPage) const968 Color SwPostItMgr::GetArrowColor(sal_uInt16 aDirection,unsigned long aPage) const
969 {
970 	if (ArrowEnabled(aDirection,aPage))
971 	{
972 		if (Application::GetSettings().GetStyleSettings().GetHighContrastMode())
973 			return Color(COL_WHITE);
974 		else
975 			return COL_NOTES_SIDEPANE_ARROW_ENABLED;
976 	}
977 	else
978 	{
979 		return COL_NOTES_SIDEPANE_ARROW_DISABLED;
980 	}
981 }
982 
LayoutByPage(std::list<SwSidebarWin * > & aVisiblePostItList,const Rectangle aBorder,long lNeededHeight)983 bool SwPostItMgr::LayoutByPage(std::list<SwSidebarWin*> &aVisiblePostItList,const Rectangle aBorder, long lNeededHeight)
984 {
985 	/*** General layout idea:***/
986 	//  - if we have space left, we always move the current one up,
987 	//    otherwise the next one down
988 	//  - first all notes are resized
989 	//	- then the real layout starts
990 	/*************************************************************/
991 
992 	//rBorder is the page rect
993     const Rectangle	rBorder			= mpEditWin->LogicToPixel( aBorder);
994 	long			lTopBorder		= rBorder.Top() + 5;
995 	long			lBottomBorder	= rBorder.Bottom() - 5;
996 	const long		lVisibleHeight	= lBottomBorder - lTopBorder; //rBorder.GetHeight() ;
997 	long			lSpaceUsed		= 0;
998 	long			lTranslatePos	= 0;
999 	int				loop			= 0;
1000 	bool			bDone			= false;
1001 	bool			bScrollbars		= false;
1002 
1003 	// do all necessary resizings
1004 	if (lVisibleHeight < lNeededHeight)
1005 	{
1006 		// ok, now we have to really resize and adding scrollbars
1007 		const long lAverageHeight = (lVisibleHeight - aVisiblePostItList.size()*GetSpaceBetween()) / aVisiblePostItList.size();
1008 		if (lAverageHeight<GetMinimumSizeWithMeta())
1009 		{
1010 			bScrollbars = true;
1011 			lTopBorder += GetSidebarScrollerHeight() + 10;
1012 			lBottomBorder -= (GetSidebarScrollerHeight() + 10);
1013                 for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
1014 					(*i)->SetSize(Size((*i)->VirtualSize().getWidth(),(*i)->GetMinimumSizeWithMeta()));
1015 		}
1016 		else
1017 		{
1018             for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
1019 			{
1020 				if ( (*i)->VirtualSize().getHeight() > lAverageHeight)
1021 					(*i)->SetSize(Size((*i)->VirtualSize().getWidth(),lAverageHeight));
1022 			}
1023 		}
1024 	}
1025 
1026 	// start the real layout so nothing overlaps anymore
1027 	if (aVisiblePostItList.size()>1)
1028 	{
1029 		// if no window is moved anymore we are finished
1030 		while (!bDone)
1031 		{
1032 			loop++;
1033   			bDone = true;
1034 			lSpaceUsed = lTopBorder + GetSpaceBetween();
1035             for(SwSidebarWin_iterator i = aVisiblePostItList.begin(); i!= aVisiblePostItList.end() ; i++)
1036 			{
1037                 SwSidebarWin_iterator aNextPostIt = i;
1038 				++aNextPostIt;
1039 
1040 				if (aNextPostIt !=aVisiblePostItList.end())
1041 				{
1042 					lTranslatePos = ( (*i)->VirtualPos().Y() + (*i)->VirtualSize().Height()) - (*aNextPostIt)->VirtualPos().Y();
1043 					if (lTranslatePos > 0) // note windows overlaps the next one
1044 					{
1045 						// we are not done yet, loop at least once more
1046 						bDone = false;
1047 						// if there is space left, move the current note up
1048 						// it could also happen that there is no space left for the first note due to a scrollbar
1049 						// then we also jump into, so we move the current one up and the next one down
1050 						if ( (lSpaceUsed <= (*i)->VirtualPos().Y()) || (i==aVisiblePostItList.begin()))
1051 						{
1052 							// we have space left, so let's move the current one up
1053 							if ( ((*i)->VirtualPos().Y()- lTranslatePos - GetSpaceBetween()) > lTopBorder)
1054 							{
1055 								if ((*aNextPostIt)->IsFollow())
1056                                     (*i)->TranslateTopPosition(-1*(lTranslatePos+ANCHORLINE_WIDTH));
1057 								else
1058 									(*i)->TranslateTopPosition(-1*(lTranslatePos+GetSpaceBetween()));
1059 							}
1060 							else
1061 							{
1062 								long lMoveUp = (*i)->VirtualPos().Y() - lTopBorder;
1063 								(*i)->TranslateTopPosition(-1* lMoveUp);
1064 								if ((*aNextPostIt)->IsFollow())
1065                                     (*aNextPostIt)->TranslateTopPosition( (lTranslatePos+ANCHORLINE_WIDTH) - lMoveUp);
1066 								else
1067 									(*aNextPostIt)->TranslateTopPosition( (lTranslatePos+GetSpaceBetween()) - lMoveUp);
1068 							}
1069 						}
1070 						else
1071 						{
1072 							// no space left, left move the next one down
1073 							if ((*aNextPostIt)->IsFollow())
1074                                 (*aNextPostIt)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
1075 							else
1076 								(*aNextPostIt)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1077 						}
1078 					}
1079 					else
1080 					{
1081 						// the first one could overlap the topborder instead of a second note
1082 						if (i==aVisiblePostItList.begin())
1083 						{
1084 							long lMoveDown = lTopBorder - (*i)->VirtualPos().Y();
1085 							if (lMoveDown>0)
1086 							{
1087 								bDone = false;
1088 								(*i)->TranslateTopPosition( lMoveDown);
1089 							}
1090 						}
1091 					}
1092 					if (aNextPostIt !=aVisiblePostItList.end() && (*aNextPostIt)->IsFollow())
1093                         lSpaceUsed += (*i)->VirtualSize().Height() + ANCHORLINE_WIDTH;
1094 					else
1095 						lSpaceUsed += (*i)->VirtualSize().Height() + GetSpaceBetween();
1096 				}
1097 				else
1098 				{
1099 					//(*i) is the last visible item
1100                     SwSidebarWin_iterator aPrevPostIt = i;
1101 					--aPrevPostIt;
1102 					//lTranslatePos = ( (*aPrevPostIt)->VirtualPos().Y() + (*aPrevPostIt)->VirtualSize().Height() + GetSpaceBetween() ) - (*i)->VirtualPos().Y();
1103 					lTranslatePos = ( (*aPrevPostIt)->VirtualPos().Y() + (*aPrevPostIt)->VirtualSize().Height() ) - (*i)->VirtualPos().Y();
1104 					if (lTranslatePos > 0)
1105 					{
1106 						bDone = false;
1107 						if ( ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()+lTranslatePos) < lBottomBorder)
1108 						{
1109 							if ( (*i)->IsFollow() )
1110                                 (*i)->TranslateTopPosition(lTranslatePos+ANCHORLINE_WIDTH);
1111 							else
1112 								(*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1113 						}
1114 						else
1115 						{
1116 							(*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()) );
1117 						}
1118 					}
1119 					else
1120 					{
1121 						// note does not overlap, but we might be over the lower border
1122                         // only do this if there are no scrollbars, otherwise notes are supposed to overlap the border
1123 						if (!bScrollbars && ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height() > lBottomBorder) )
1124 						{
1125 							bDone = false;
1126 							(*i)->TranslateTopPosition(lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height()));
1127 						}
1128 					}
1129 				}
1130 			}
1131 			// security check so we don't loop forever
1132 			if (loop>MAX_LOOP_COUNT)
1133 			{
1134 				DBG_ERROR("PostItMgr::Layout(): We are looping forever");
1135 				break;
1136 			}
1137 		}
1138 	}
1139 	else
1140 	{
1141 		// only one left, make sure it is not hidden at the top or bottom
1142         SwSidebarWin_iterator i = aVisiblePostItList.begin();
1143 		lTranslatePos = lTopBorder - (*i)->VirtualPos().Y();
1144 		if (lTranslatePos>0)
1145 		{
1146 			(*i)->TranslateTopPosition(lTranslatePos+GetSpaceBetween());
1147 		}
1148 		lTranslatePos =	lBottomBorder - ((*i)->VirtualPos().Y()+ (*i)->VirtualSize().Height());
1149 		if (lTranslatePos<0)
1150 		{
1151 			(*i)->TranslateTopPosition(lTranslatePos);
1152 		}
1153 	}
1154 	return bScrollbars;
1155  }
1156 
1157 /*
1158 void SwPostItMgr::AddRedlineComments(bool bCheckExistance, bool bFocus)
1159 {
1160 	bool bEmpty = mvPostItFlds.empty();
1161 	const SwRedlineTbl& aTable = mpView->GetDocShell()->GetDoc()->GetRedlineTbl();
1162 	for( sal_uInt16 i = 0; i < aTable.Count(); ++i )
1163 	{
1164 		SwRedline* pRedline = const_cast<SwRedline*>((aTable)[i]);
1165 		if ( pRedline->GetComment() != String(rtl::OUString::createFromAscii("")) )
1166 			InsertItem(pRedline, bCheckExistance, bFocus);
1167 	}
1168 	if (bEmpty && !mvPostItFlds.empty())
1169 		PrepareView(true);
1170  }
1171  */
1172 
AddPostIts(bool bCheckExistance,bool bFocus)1173 void SwPostItMgr::AddPostIts(bool bCheckExistance, bool bFocus)
1174 {
1175 	bool bEmpty = mvPostItFlds.empty();
1176 	SwFieldType* pType = mpView->GetDocShell()->GetDoc()->GetFldType(RES_POSTITFLD, aEmptyStr,false);
1177 	SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
1178 	SwFmtFld* pSwFmtFld = aIter.First();
1179 	while(pSwFmtFld)
1180 	{
1181 		if ( pSwFmtFld->GetTxtFld())
1182 		{
1183 			if ( pSwFmtFld->IsFldInDoc() )
1184 				InsertItem(pSwFmtFld,bCheckExistance,bFocus);
1185 		}
1186 		pSwFmtFld = aIter.Next();
1187 	}
1188 
1189 	// if we just added the first one we have to update the view for centering
1190 	if (bEmpty && !mvPostItFlds.empty())
1191 		PrepareView(true);
1192 }
1193 
RemoveSidebarWin()1194 void SwPostItMgr::RemoveSidebarWin()
1195 {
1196 	if (!mvPostItFlds.empty())
1197 	{
1198         for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1199 		{
1200 			EndListening( *(const_cast<SfxBroadcaster*>((*i)->GetBroadCaster())) );
1201 			if ((*i)->pPostIt)
1202 				delete (*i)->pPostIt;
1203 			delete (*i);
1204 		}
1205 		mvPostItFlds.clear();
1206 	}
1207 
1208 	// all postits removed, no items should be left in pages
1209 	PreparePageContainer();
1210 }
1211 
1212 // copy to new vector, otherwise RemoveItem would operate and delete stuff on mvPostItFlds as well
1213 // RemoveItem will clean up the core field and visible postit if necessary
1214 // we cannot just delete everything as before, as postits could move into change tracking
Delete(String aAuthor)1215 void SwPostItMgr::Delete(String aAuthor)
1216 {
1217 	mpWrtShell->StartAllAction();
1218     if ( HasActiveSidebarWin() && (GetActiveSidebarWin()->GetAuthor()==aAuthor) )
1219     {
1220         SetActiveSidebarWin(0);
1221     }
1222 	SwRewriter aRewriter;
1223 	String aUndoString = SW_RES(STR_DELETE_AUTHOR_NOTES);
1224 	aUndoString += aAuthor;
1225 	aRewriter.AddRule(UNDO_ARG1, aUndoString);
1226 	mpWrtShell->StartUndo( UNDO_DELETE, &aRewriter );
1227 
1228 	std::vector<const SwFmtFld*> aTmp;
1229     aTmp.reserve( mvPostItFlds.size() );
1230     for(std::list<SwSidebarItem*>::iterator pPostIt = mvPostItFlds.begin(); pPostIt!= mvPostItFlds.end() ; pPostIt++)
1231 	{
1232 		if ( (*pPostIt)->pPostIt->GetAuthor() == aAuthor )
1233 			aTmp.push_back( &(*pPostIt)->GetFmtFld() );
1234 	}
1235 	for(std::vector<const SwFmtFld*>::iterator i = aTmp.begin(); i!= aTmp.end() ; i++)
1236 	{
1237 		mpWrtShell->GotoField( *(*i) );
1238 		mpWrtShell->DelRight();
1239 	}
1240     mpWrtShell->EndUndo();
1241 	PrepareView();
1242 	mpWrtShell->EndAllAction();
1243 	mbLayout = true;
1244 	CalcRects();
1245 	LayoutPostIts();
1246 }
1247 
Delete()1248 void SwPostItMgr::Delete()
1249 {
1250 	mpWrtShell->StartAllAction();
1251     SetActiveSidebarWin(0);
1252 	SwRewriter aRewriter;
1253 	aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_DELETE_ALL_NOTES) );
1254 	mpWrtShell->StartUndo( UNDO_DELETE, &aRewriter );
1255 
1256     std::vector<const SwFmtFld*> aTmp;
1257     aTmp.reserve( mvPostItFlds.size() );
1258     for(std::list<SwSidebarItem*>::iterator pPostIt = mvPostItFlds.begin(); pPostIt!= mvPostItFlds.end() ; pPostIt++)
1259     {
1260         aTmp.push_back( &(*pPostIt)->GetFmtFld() );
1261     }
1262 	for(std::vector<const SwFmtFld*>::iterator i = aTmp.begin(); i!= aTmp.end() ; i++)
1263 	{
1264 		mpWrtShell->GotoField( *(*i) );
1265 		mpWrtShell->DelRight();
1266 	}
1267 
1268 /*
1269 	for(std::list<SwPostItItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1270 	{
1271 		SwPostItItem* pItem = (*i);
1272 		// stop listening, we delete ourselves
1273 		EndListening( *(pItem->pFmtFld) );
1274 		// delete the actual SwPostItField
1275 		mpWrtShell->GotoField(*pItem->pFmtFld);
1276 		mpWrtShell->DelRight();
1277 		// delete visual representation
1278 		delete pItem->pPostIt;
1279 		// delete struct saving the pointers
1280 		delete pItem;
1281 	}
1282 	mvPostItFlds.clear();
1283 */
1284 
1285     mpWrtShell->EndUndo();
1286 	PrepareView();
1287 	mpWrtShell->EndAllAction();
1288 	mbLayout = true;
1289 	CalcRects();
1290 	LayoutPostIts();
1291 }
1292 #if 0
1293 void SwPostItMgr::Hide(SwPostItField* pPostItField )
1294 {
1295     for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1296 	{
1297 		if ((*i)->GetFmtFld())
1298 		{
1299 			SwPostItField* pField = static_cast<SwPostItField*>((*i)->GetFmtFld()->GetFld());
1300 			if (pPostItField==pField)
1301 			{
1302 				(*i)->bShow = false;
1303 				(*i)->pPostIt->HideNote();
1304 				break;
1305 			}
1306 		}
1307 	}
1308 
1309 	LayoutPostIts();
1310 }
1311 #endif
Hide(const String & rAuthor)1312 void SwPostItMgr::Hide( const String& rAuthor )
1313 {
1314     for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1315 	{
1316 		if ( (*i)->pPostIt && ((*i)->pPostIt->GetAuthor() == rAuthor) )
1317 		{
1318 			(*i)->bShow	 = false;
1319 			(*i)->pPostIt->HideNote();
1320 		}
1321 	}
1322 
1323 	LayoutPostIts();
1324 }
1325 
Hide()1326 void SwPostItMgr::Hide()
1327 {
1328     for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1329 	{
1330 		(*i)->bShow = false;
1331 		(*i)->pPostIt->HideNote();
1332 	}
1333 }
1334 
1335 
Show()1336 void SwPostItMgr::Show()
1337 {
1338     for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1339 	{
1340 		(*i)->bShow = true;
1341 	}
1342 	LayoutPostIts();
1343 }
1344 
Sort(const short aType)1345 void SwPostItMgr::Sort(const short aType)
1346 {
1347 	if (mvPostItFlds.size()>1 )
1348 	{
1349 		switch (aType)
1350 		{
1351 			case SORT_POS:
1352 				mvPostItFlds.sort(comp_pos);
1353 				break;
1354 			/*
1355 			case SORT_AUTHOR:
1356 				mvPostItFlds.sort(comp_author);
1357 				break;
1358 			case SORT_DATE:
1359 				mvPostItFlds.sort(comp_date);
1360 				break;
1361 			*/
1362 		}
1363 	}
1364 }
1365 
GetSidebarWin(const SfxBroadcaster * pBroadcaster) const1366 SwSidebarWin* SwPostItMgr::GetSidebarWin( const SfxBroadcaster* pBroadcaster) const
1367 {
1368 	for(const_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1369 	{
1370 		if ( (*i)->GetBroadCaster() == pBroadcaster)
1371 			return (*i)->pPostIt;
1372 	}
1373 	return NULL;
1374 }
1375 
GetAnnotationWin(const SwPostItField * pFld) const1376 sw::annotation::SwAnnotationWin* SwPostItMgr::GetAnnotationWin(const SwPostItField* pFld) const
1377 {
1378     for(const_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1379     {
1380         if ( (*i)->GetFmtFld().GetField() == pFld )
1381             return dynamic_cast<sw::annotation::SwAnnotationWin*>((*i)->pPostIt);
1382     }
1383     return NULL;
1384 }
1385 
GetNextPostIt(sal_uInt16 aDirection,SwSidebarWin * aPostIt)1386 SwSidebarWin* SwPostItMgr::GetNextPostIt( sal_uInt16 aDirection,
1387                                           SwSidebarWin* aPostIt )
1388 {
1389 	if (mvPostItFlds.size()>1)
1390 	{
1391         for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1392 		{
1393 			if ( (*i)->pPostIt ==aPostIt)
1394 			{
1395                 SwSidebarItem_iterator iNextPostIt  = i;
1396 				if (aDirection==KEY_PAGEUP)
1397 				{
1398 					if ( iNextPostIt==mvPostItFlds.begin() )
1399 					{
1400 						return NULL;
1401 					}
1402 					--iNextPostIt;
1403 				}
1404 				else
1405 				{
1406 					iNextPostIt++;
1407 					if ( iNextPostIt==mvPostItFlds.end() )
1408 					{
1409 						return NULL;
1410 					}
1411 				}
1412 				// let's quit, we are back at the beginning
1413 				if ( (*iNextPostIt)->pPostIt==aPostIt)
1414 					return NULL;
1415 				return (*iNextPostIt)->pPostIt;
1416 			}
1417 		}
1418 		return NULL;
1419 	}
1420 	else
1421 		return NULL;
1422 }
1423 
GetNextBorder()1424 long SwPostItMgr::GetNextBorder()
1425 {
1426 	for (unsigned long n=0;n<mPages.size();n++)
1427 	{
1428         for(SwSidebarItem_iterator b = mPages[n]->mList->begin(); b!= mPages[n]->mList->end(); b++)
1429 		{
1430 			if ((*b)->pPostIt == mpActivePostIt)
1431 			{
1432                 SwSidebarItem_iterator aNext = b;
1433 				aNext++;
1434 				bool bFollow = (aNext == mPages[n]->mList->end()) ? false : (*aNext)->pPostIt->IsFollow();
1435 				if ( mPages[n]->bScrollbar || bFollow )
1436 				{
1437 					return -1;
1438 				}
1439 				else
1440 				{
1441 					//if this is the last item, return the bottom border otherwise the next item
1442 					if (aNext == mPages[n]->mList->end())
1443 						return mpEditWin->LogicToPixel(Point(0,mPages[n]->mPageRect.Bottom())).Y() - GetSpaceBetween();
1444 					else
1445 						return (*aNext)->pPostIt->GetPosPixel().Y() - GetSpaceBetween();
1446 				}
1447 			}
1448 		}
1449 	}
1450 
1451 	DBG_ERROR("SwPostItMgr::GetNextBorder(): We have to find a next border here");
1452 	return -1;
1453 }
1454 
SetShadowState(const SwPostItField * pFld,bool bCursor)1455 void SwPostItMgr::SetShadowState(const SwPostItField* pFld,bool bCursor)
1456 {
1457 	if (pFld)
1458 	{
1459 		if (pFld !=mShadowState.mpShadowFld)
1460 		{
1461 			if (mShadowState.mpShadowFld)
1462 			{
1463 				// reset old one if still alive
1464 				// TODO: does not work properly if mouse and cursor was set
1465                 sw::annotation::SwAnnotationWin* pOldPostIt =
1466                                     GetAnnotationWin(mShadowState.mpShadowFld);
1467 				if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
1468                     pOldPostIt->SetViewState(VS_NORMAL);
1469 			}
1470 			//set new one, if it is not currently edited
1471             sw::annotation::SwAnnotationWin* pNewPostIt = GetAnnotationWin(pFld);
1472 			if (pNewPostIt && pNewPostIt->Shadow() && (pNewPostIt->Shadow()->GetShadowState() != SS_EDIT))
1473 			{
1474                 pNewPostIt->SetViewState(VS_VIEW);
1475 				//remember our new field
1476 				mShadowState.mpShadowFld = pFld;
1477 				mShadowState.bCursor = false;
1478 				mShadowState.bMouse = false;
1479 			}
1480 		}
1481 		if (bCursor)
1482 			mShadowState.bCursor = true;
1483 		else
1484 			mShadowState.bMouse = true;
1485 	}
1486 	else
1487 	{
1488 		if (mShadowState.mpShadowFld)
1489 		{
1490 			if (bCursor)
1491 				mShadowState.bCursor = false;
1492 			else
1493 				mShadowState.bMouse = false;
1494 			if (!mShadowState.bCursor && !mShadowState.bMouse)
1495 			{
1496 				// reset old one if still alive
1497                 sw::annotation::SwAnnotationWin* pOldPostIt = GetAnnotationWin(mShadowState.mpShadowFld);
1498 				if (pOldPostIt && pOldPostIt->Shadow() && (pOldPostIt->Shadow()->GetShadowState() != SS_EDIT))
1499 				{
1500                     pOldPostIt->SetViewState(VS_NORMAL);
1501 					mShadowState.mpShadowFld = 0;
1502 				}
1503 			}
1504 		}
1505 	}
1506 }
1507 
PrepareView(bool bIgnoreCount)1508 void SwPostItMgr::PrepareView(bool bIgnoreCount)
1509 {
1510 	if (!HasNotes() || bIgnoreCount)
1511 	{
1512 		mpWrtShell->StartAllAction();
1513 		//mpEditWin->Invalidate(); // really not needed anymore?
1514 		SwRootFrm* pLayout = mpWrtShell->GetLayout();
1515         if ( pLayout )
1516             SwPostItHelper::setSidebarChanged( pLayout,
1517                 mpWrtShell->getIDocumentSettingAccess()->get( IDocumentSettingAccess::BROWSE_MODE ) );
1518 		mpWrtShell->EndAllAction();
1519 	}
1520 }
1521 
ShowScrollbar(const unsigned long aPage) const1522 bool SwPostItMgr::ShowScrollbar(const unsigned long aPage) const
1523 {
1524 	if (mPages.size() > aPage-1)
1525 		return (mPages[aPage-1]->bScrollbar && !mbWaitingForCalcRects);
1526 	else
1527 		return false;
1528 }
1529 
IsHit(const Point & aPointPixel)1530 bool SwPostItMgr::IsHit(const Point &aPointPixel)
1531 {
1532 	if (HasNotes() && ShowNotes())
1533 	{
1534 		const Point aPoint = mpEditWin->PixelToLogic(aPointPixel);
1535         const SwRootFrm* pLayout = mpWrtShell->GetLayout();
1536         SwRect aPageFrm;
1537 		const unsigned long nPageNum = SwPostItHelper::getPageInfo( aPageFrm, pLayout, aPoint );
1538 	    if( nPageNum )
1539 		{
1540 			Rectangle aRect;
1541 			DBG_ASSERT(mPages.size()>nPageNum-1,"SwPostitMgr:: page container size wrong");
1542             aRect = mPages[nPageNum-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1543                     ? Rectangle(Point(aPageFrm.Left()-GetSidebarWidth()-GetSidebarBorderWidth(),aPageFrm.Top()),Size(GetSidebarWidth(),aPageFrm.Height()))
1544                     : Rectangle( Point(aPageFrm.Right()+GetSidebarBorderWidth(),aPageFrm.Top()) , Size(GetSidebarWidth(),aPageFrm.Height()));
1545 			if (aRect.IsInside(aPoint))
1546 			{
1547 				// we hit the note's sidebar
1548 				// let's now test for the arrow area
1549 				if (mPages[nPageNum-1]->bScrollbar)
1550 					return ScrollbarHit(nPageNum,aPoint);
1551 				else
1552 					return false;
1553 			}
1554 		}
1555 	}
1556 	return false;
1557 }
GetBottomScrollRect(const unsigned long aPage) const1558 Rectangle SwPostItMgr::GetBottomScrollRect(const unsigned long aPage) const
1559 {
1560 	SwRect aPageRect = mPages[aPage-1]->mPageRect;
1561     Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1562                          ? Point(aPageRect.Left() - GetSidebarWidth() - GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
1563                          : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
1564 	Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ;
1565 	return Rectangle(aPointBottom,aSize);
1566 
1567 }
1568 
GetTopScrollRect(const unsigned long aPage) const1569 Rectangle SwPostItMgr::GetTopScrollRect(const unsigned long aPage) const
1570 {
1571 	SwRect aPageRect = mPages[aPage-1]->mPageRect;
1572     Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1573                       ? Point(aPageRect.Left() - GetSidebarWidth() -GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
1574                       : Point(aPageRect.Right() + GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
1575 	Size aSize(GetSidebarWidth() - mpEditWin->PixelToLogic(Size(4,0)).Width(), mpEditWin->PixelToLogic(Size(0,GetSidebarScrollerHeight())).Height()) ;
1576 	return Rectangle(aPointTop,aSize);
1577 }
1578 
1579 
1580 //IMPORTANT: if you change the rects here, also change SwPageFrm::PaintNotesSidebar()
ScrollbarHit(const unsigned long aPage,const Point & aPoint)1581 bool SwPostItMgr::ScrollbarHit(const unsigned long aPage,const Point &aPoint)
1582 {
1583 	SwRect aPageRect = mPages[aPage-1]->mPageRect;
1584     Point aPointBottom = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1585                          ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth() + mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height())
1586                          : Point(aPageRect.Right() + GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Bottom()- mpEditWin->PixelToLogic(Size(0,2+GetSidebarScrollerHeight())).Height());
1587 
1588     Point aPointTop = mPages[aPage-1]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1589                       ? Point(aPageRect.Left() - GetSidebarWidth()-GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height())
1590                       : Point(aPageRect.Right()+GetSidebarBorderWidth()+ mpEditWin->PixelToLogic(Size(2,0)).Width(),aPageRect.Top() + mpEditWin->PixelToLogic(Size(0,2)).Height());
1591 
1592 	Rectangle aRectBottom(GetBottomScrollRect(aPage));
1593 	Rectangle aRectTop(GetTopScrollRect(aPage));
1594 
1595 	if (aRectBottom.IsInside(aPoint))
1596 	{
1597 		if (aPoint.X() < long((aPointBottom.X() + GetSidebarWidth()/3)))
1598 			Scroll( GetScrollSize(),aPage);
1599 		else
1600 			Scroll( -1*GetScrollSize(), aPage);
1601 		return true;
1602 	}
1603 	else
1604 	if (aRectTop.IsInside(aPoint))
1605 	{
1606 		if (aPoint.X() < long((aPointTop.X() + GetSidebarWidth()/3*2)))
1607 			Scroll(GetScrollSize(), aPage);
1608 		else
1609 			Scroll(-1*GetScrollSize(), aPage);
1610 		return true;
1611 	}
1612 	return false;
1613 }
1614 
CorrectPositions()1615 void SwPostItMgr::CorrectPositions()
1616 {
1617    if ( mbWaitingForCalcRects || mbLayouting || mvPostItFlds.empty() )
1618        return;
1619 
1620    // find first valid note
1621    SwSidebarWin *pFirstPostIt = 0;
1622    for(SwSidebarItem_iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1623    {
1624        pFirstPostIt = (*i)->pPostIt;
1625        if (pFirstPostIt)
1626            break;
1627    }
1628 
1629    //if we have not found a valid note, forget about it and leave
1630    if (!pFirstPostIt)
1631        return;
1632 
1633     // yeah, I know,    if this is a left page it could be wrong, but finding the page and the note is probably not even faster than just doing it
1634     // --> OD 2010-06-03 #i111964# - check, if anchor overlay object exists.
1635     const long aAnchorX = pFirstPostIt->Anchor()
1636                           ? mpEditWin->LogicToPixel( Point((long)(pFirstPostIt->Anchor()->GetSixthPosition().getX()),0)).X()
1637                           : 0;
1638     const long aAnchorY = pFirstPostIt->Anchor()
1639                           ? mpEditWin->LogicToPixel( Point(0,(long)(pFirstPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1
1640                           : 0;
1641     // <--
1642     if (Point(aAnchorX,aAnchorY) != pFirstPostIt->GetPosPixel())
1643     {
1644         long aAnchorPosX = 0;
1645         long aAnchorPosY = 0;
1646         for (unsigned long n=0;n<mPages.size();n++)
1647         {
1648             for(SwSidebarItem_iterator i = mPages[n]->mList->begin(); i!= mPages[n]->mList->end(); i++)
1649             {
1650                 if ( (*i)->bShow && (*i)->pPostIt && (*i)->pPostIt->Anchor() )
1651                 {
1652                     aAnchorPosX = mPages[n]->eSidebarPosition == sw::sidebarwindows::SIDEBAR_LEFT
1653                         ? mpEditWin->LogicToPixel( Point((long)((*i)->pPostIt->Anchor()->GetSeventhPosition().getX()),0)).X()
1654                         : mpEditWin->LogicToPixel( Point((long)((*i)->pPostIt->Anchor()->GetSixthPosition().getX()),0)).X();
1655                     aAnchorPosY = mpEditWin->LogicToPixel( Point(0,(long)((*i)->pPostIt->Anchor()->GetSixthPosition().getY()))).Y() + 1;
1656                     (*i)->pPostIt->SetPosPixel(Point(aAnchorPosX,aAnchorPosY));
1657                 }
1658             }
1659         }
1660     }
1661 }
1662 
1663 
ShowNotes() const1664 bool SwPostItMgr::ShowNotes() const
1665 {
1666 	// we only want to see notes if Options - Writer - View - Notes is ticked
1667 	return mpWrtShell->GetViewOptions()->IsPostIts();
1668 }
1669 
HasNotes() const1670 bool SwPostItMgr::HasNotes() const
1671 {
1672 	return !mvPostItFlds.empty();
1673 }
1674 
GetSidebarWidth(bool bPx) const1675 unsigned long SwPostItMgr::GetSidebarWidth(bool bPx) const
1676 {
1677 	unsigned long aWidth = (unsigned long)(mpWrtShell->GetViewOptions()->GetZoom() * 1.8);
1678 	if (bPx)
1679 		return aWidth;
1680 	else
1681 		return mpEditWin->PixelToLogic(Size( aWidth ,0)).Width();
1682 }
1683 
GetSidebarBorderWidth(bool bPx) const1684 unsigned long SwPostItMgr::GetSidebarBorderWidth(bool bPx) const
1685 {
1686 	if (bPx)
1687 		return 2;
1688 	else
1689 		return mpEditWin->PixelToLogic(Size(2,0)).Width();
1690 }
1691 
GetNoteWidth()1692 unsigned long SwPostItMgr::GetNoteWidth()
1693 {
1694 	return GetSidebarWidth(true);
1695 }
1696 
GetColorDark(sal_uInt16 aAuthorIndex)1697 Color SwPostItMgr::GetColorDark(sal_uInt16 aAuthorIndex)
1698 {
1699 	if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1700 	{
1701 		static const Color aArrayNormal[] = {
1702 			COL_AUTHOR1_NORMAL,		COL_AUTHOR2_NORMAL,		COL_AUTHOR3_NORMAL,
1703 			COL_AUTHOR4_NORMAL,		COL_AUTHOR5_NORMAL,		COL_AUTHOR6_NORMAL,
1704 			COL_AUTHOR7_NORMAL,		COL_AUTHOR8_NORMAL,		COL_AUTHOR9_NORMAL };
1705 
1706 		return Color( aArrayNormal[ aAuthorIndex % (sizeof( aArrayNormal )/ sizeof( aArrayNormal[0] ))]);
1707 	}
1708 	else
1709 		return Color(COL_WHITE);
1710 }
1711 
GetColorLight(sal_uInt16 aAuthorIndex)1712 Color SwPostItMgr::GetColorLight(sal_uInt16 aAuthorIndex)
1713 {
1714 	if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1715 	{
1716 		static const Color aArrayLight[] = {
1717 			COL_AUTHOR1_LIGHT,		COL_AUTHOR2_LIGHT,		COL_AUTHOR3_LIGHT,
1718 			COL_AUTHOR4_LIGHT,		COL_AUTHOR5_LIGHT,		COL_AUTHOR6_LIGHT,
1719 			COL_AUTHOR7_LIGHT,		COL_AUTHOR8_LIGHT,		COL_AUTHOR9_LIGHT };
1720 
1721 		return Color( aArrayLight[ aAuthorIndex % (sizeof( aArrayLight )/ sizeof( aArrayLight[0] ))]);
1722 	}
1723 	else
1724 		return Color(COL_WHITE);
1725 }
1726 
GetColorAnchor(sal_uInt16 aAuthorIndex)1727 Color SwPostItMgr::GetColorAnchor(sal_uInt16 aAuthorIndex)
1728 {
1729 	if (!Application::GetSettings().GetStyleSettings().GetHighContrastMode())
1730 	{
1731 		static const Color aArrayAnchor[] = {
1732 			COL_AUTHOR1_DARK,		COL_AUTHOR2_DARK,		COL_AUTHOR3_DARK,
1733 			COL_AUTHOR4_DARK,		COL_AUTHOR5_DARK,		COL_AUTHOR6_DARK,
1734 			COL_AUTHOR7_DARK,		COL_AUTHOR8_DARK,		COL_AUTHOR9_DARK };
1735 
1736 		return Color( aArrayAnchor[  aAuthorIndex % (sizeof( aArrayAnchor )  / sizeof( aArrayAnchor[0] ))]);
1737 	}
1738 	else
1739 		return Color(COL_WHITE);
1740 }
1741 
SetActiveSidebarWin(SwSidebarWin * p)1742 void SwPostItMgr::SetActiveSidebarWin( SwSidebarWin* p)
1743 {
1744 	if ( p != mpActivePostIt )
1745 	{
1746 		// we need the temp variable so we can set mpActivePostIt before we call DeactivatePostIt
1747 		// therefore we get a new layout in DOCCHANGED when switching from postit to document,
1748 		// otherwise, GetActivePostIt() would still hold our old postit
1749 		SwSidebarWin* pActive = mpActivePostIt;
1750 		mpActivePostIt = p;
1751 		if (pActive)
1752 		{
1753 			pActive->DeactivatePostIt();
1754 			mShadowState.mpShadowFld = 0;
1755 		}
1756 		if (mpActivePostIt)
1757 		{
1758 			mpActivePostIt->GotoPos();
1759 			mpView->AttrChangedNotify(0);
1760 			mpActivePostIt->ActivatePostIt();
1761 		}
1762 	}
1763 }
1764 
1765 IMPL_LINK( SwPostItMgr, CalcHdl, void*, /* pVoid*/  )
1766 {
1767 	mnEventId = 0;
1768 	if ( mbLayouting )
1769 	{
1770 		DBG_ERROR("Reentrance problem in Layout Manager!");
1771 		mbWaitingForCalcRects = false;
1772 		return 0;
1773 	}
1774 
1775 	// do not change order, even if it would seem so in the first place, we need the calcrects always
1776 	if (CalcRects() || mbLayout)
1777 	{
1778 		mbLayout = false;
1779 		LayoutPostIts();
1780 	}
1781 	return 0;
1782 }
1783 
Rescale()1784 void SwPostItMgr::Rescale()
1785 {
1786 	for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1787 		if ( (*i)->pPostIt )
1788 			(*i)->pPostIt->Rescale();
1789 }
1790 
GetInitialAnchorDistance() const1791 sal_Int32 SwPostItMgr::GetInitialAnchorDistance() const
1792 {
1793 	const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
1794 	return POSTIT_INITIAL_ANCHOR_DISTANCE * f.GetNumerator() / f.GetDenominator();
1795 }
1796 
GetSpaceBetween() const1797 sal_Int32 SwPostItMgr::GetSpaceBetween() const
1798 {
1799 	const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
1800 	return ( POSTIT_SPACE_BETWEEN ) * f.GetNumerator() / f.GetDenominator();
1801 }
1802 
GetScrollSize() const1803 sal_Int32 SwPostItMgr::GetScrollSize() const
1804 {
1805 	const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
1806 	return ( POSTIT_SPACE_BETWEEN + POSTIT_MINIMUMSIZE_WITH_META ) * f.GetNumerator() / f.GetDenominator();
1807 }
1808 
GetMinimumSizeWithMeta() const1809 sal_Int32 SwPostItMgr::GetMinimumSizeWithMeta() const
1810 {
1811 	const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
1812 	return POSTIT_MINIMUMSIZE_WITH_META * f.GetNumerator() / f.GetDenominator();
1813 }
1814 
GetSidebarScrollerHeight() const1815 sal_Int32 SwPostItMgr::GetSidebarScrollerHeight() const
1816 {
1817 	const Fraction& f( mpEditWin->GetMapMode().GetScaleY() );
1818 	return POSTIT_SCROLL_SIDEBAR_HEIGHT * f.GetNumerator() / f.GetDenominator();
1819 }
1820 
SetSpellChecking()1821 void SwPostItMgr::SetSpellChecking()
1822 {
1823 	for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1824 		if ( (*i)->pPostIt )
1825 			(*i)->pPostIt->SetSpellChecking();
1826 }
1827 
SetReadOnlyState()1828 void SwPostItMgr::SetReadOnlyState()
1829 {
1830 	for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1831 		if ( (*i)->pPostIt )
1832 			(*i)->pPostIt->SetReadonly( mbReadOnly );
1833 }
1834 
CheckMetaText()1835 void SwPostItMgr::CheckMetaText()
1836 {
1837         for(std::list<SwSidebarItem*>::iterator i = mvPostItFlds.begin(); i!= mvPostItFlds.end() ; i++)
1838                 if ( (*i)->pPostIt )
1839                        (*i)->pPostIt->CheckMetaText();
1840 
1841 }
1842 
Replace(SvxSearchItem * pItem)1843 sal_uInt16 SwPostItMgr::Replace(SvxSearchItem* pItem)
1844 {
1845     SwSidebarWin* pWin = GetActiveSidebarWin();
1846     sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( *pItem );
1847 	if (!aResult)
1848         SetActiveSidebarWin(0);
1849 	return aResult;
1850 }
1851 
FinishSearchReplace(const::com::sun::star::util::SearchOptions & rSearchOptions,bool bSrchForward)1852 sal_uInt16 SwPostItMgr::FinishSearchReplace(const ::com::sun::star::util::SearchOptions& rSearchOptions, bool bSrchForward)
1853 {
1854     SwSidebarWin* pWin = GetActiveSidebarWin();
1855 	SvxSearchItem aItem(SID_SEARCH_ITEM );
1856 	aItem.SetSearchOptions(rSearchOptions);
1857 	aItem.SetBackward(!bSrchForward);
1858     sal_uInt16 aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
1859 	if (!aResult)
1860         SetActiveSidebarWin(0);
1861 	return aResult;
1862 }
1863 
SearchReplace(const SwFmtFld & pFld,const::com::sun::star::util::SearchOptions & rSearchOptions,bool bSrchForward)1864 sal_uInt16 SwPostItMgr::SearchReplace(const SwFmtFld &pFld, const ::com::sun::star::util::SearchOptions& rSearchOptions, bool bSrchForward)
1865 {
1866 	sal_uInt16 aResult = 0;
1867     SwSidebarWin* pWin = GetSidebarWin(&pFld);
1868 	if (pWin)
1869 	{
1870         ESelection aOldSelection = pWin->GetOutlinerView()->GetSelection();
1871 		if (bSrchForward)
1872             pWin->GetOutlinerView()->SetSelection(ESelection(0,0,0,0));
1873 		else
1874             pWin->GetOutlinerView()->SetSelection(ESelection(EE_PARA_MAX, EE_INDEX_MAX));
1875 		SvxSearchItem aItem(SID_SEARCH_ITEM );
1876 		aItem.SetSearchOptions(rSearchOptions);
1877 		aItem.SetBackward(!bSrchForward);
1878         aResult = pWin->GetOutlinerView()->StartSearchAndReplace( aItem );
1879 		if (!aResult)
1880             pWin->GetOutlinerView()->SetSelection(aOldSelection);
1881 		else
1882 		{
1883             SetActiveSidebarWin(pWin);
1884 			MakeVisible(pWin);
1885 		}
1886 	}
1887 	return aResult;
1888 }
1889 
AssureStdModeAtShell()1890 void SwPostItMgr::AssureStdModeAtShell()
1891 {
1892 	//#i103373# #i103645#
1893         // deselect any drawing or frame and leave editing mode
1894       	SdrView* pSdrView = mpWrtShell->GetDrawView();
1895         if ( pSdrView && pSdrView->IsTextEdit() )
1896         {
1897         	sal_Bool bLockView = mpWrtShell->IsViewLocked();
1898        		mpWrtShell->LockView( sal_True );
1899         	mpWrtShell->EndTextEdit();
1900                 mpWrtShell->LockView( bLockView );
1901     	}
1902 
1903         if( mpWrtShell->IsSelFrmMode() || mpWrtShell->IsObjSelected())
1904         {
1905                 mpWrtShell->UnSelectFrm();
1906                 mpWrtShell->LeaveSelFrmMode();
1907                 mpWrtShell->GetView().LeaveDrawCreate();
1908                 mpWrtShell->EnterStdMode();
1909 
1910                 mpWrtShell->DrawSelChanged();
1911                 mpView->StopShellTimer();
1912         }
1913 }
1914 
HasActiveSidebarWin() const1915 bool SwPostItMgr::HasActiveSidebarWin() const
1916 {
1917     return mpActivePostIt != 0;
1918 }
1919 
HasActiveAnnotationWin() const1920 bool SwPostItMgr::HasActiveAnnotationWin() const
1921 {
1922     return HasActiveSidebarWin() &&
1923            dynamic_cast<sw::annotation::SwAnnotationWin*>(mpActivePostIt) != 0;
1924 }
1925 
GrabFocusOnActiveSidebarWin()1926 void SwPostItMgr::GrabFocusOnActiveSidebarWin()
1927 {
1928     if ( HasActiveSidebarWin() )
1929     {
1930         mpActivePostIt->GrabFocus();
1931     }
1932 }
1933 
UpdateDataOnActiveSidebarWin()1934 void SwPostItMgr::UpdateDataOnActiveSidebarWin()
1935 {
1936     if ( HasActiveSidebarWin() )
1937     {
1938         mpActivePostIt->UpdateData();
1939     }
1940 }
1941 
DeleteActiveSidebarWin()1942 void SwPostItMgr::DeleteActiveSidebarWin()
1943 {
1944     if ( HasActiveSidebarWin() )
1945     {
1946         mpActivePostIt->Delete();
1947     }
1948 }
1949 
HideActiveSidebarWin()1950 void SwPostItMgr::HideActiveSidebarWin()
1951 {
1952     if ( HasActiveSidebarWin() )
1953     {
1954         mpActivePostIt->Hide();
1955     }
1956 }
1957 
ToggleInsModeOnActiveSidebarWin()1958 void SwPostItMgr::ToggleInsModeOnActiveSidebarWin()
1959 {
1960     if ( HasActiveSidebarWin() )
1961     {
1962         mpActivePostIt->ToggleInsMode();
1963     }
1964 }
1965 
ConnectSidebarWinToFrm(const SwFrm & rFrm,const SwFmtFld & rFmtFld,SwSidebarWin & rSidebarWin)1966 void SwPostItMgr::ConnectSidebarWinToFrm( const SwFrm& rFrm,
1967                                           const SwFmtFld& rFmtFld,
1968                                           SwSidebarWin& rSidebarWin )
1969 {
1970     if ( mpFrmSidebarWinContainer == 0 )
1971     {
1972         mpFrmSidebarWinContainer = new SwFrmSidebarWinContainer();
1973     }
1974 
1975     const bool bInserted = mpFrmSidebarWinContainer->insert( rFrm, rFmtFld, rSidebarWin );
1976     if ( bInserted &&
1977          mpWrtShell->GetAccessibleMap() )
1978     {
1979         mpWrtShell->GetAccessibleMap()->InvalidatePosOrSize( 0, 0, &rSidebarWin, SwRect() );
1980     }
1981 }
1982 
DisconnectSidebarWinFromFrm(const SwFrm & rFrm,SwSidebarWin & rSidebarWin)1983 void SwPostItMgr::DisconnectSidebarWinFromFrm( const SwFrm& rFrm,
1984                                                SwSidebarWin& rSidebarWin )
1985 {
1986     if ( mpFrmSidebarWinContainer != 0 )
1987     {
1988         const bool bRemoved = mpFrmSidebarWinContainer->remove( rFrm, rSidebarWin );
1989         if ( bRemoved &&
1990              mpWrtShell->GetAccessibleMap() )
1991         {
1992             mpWrtShell->GetAccessibleMap()->Dispose( 0, 0, &rSidebarWin );
1993         }
1994     }
1995 }
1996 
HasFrmConnectedSidebarWins(const SwFrm & rFrm)1997 bool SwPostItMgr::HasFrmConnectedSidebarWins( const SwFrm& rFrm )
1998 {
1999     bool bRet( false );
2000 
2001     if ( mpFrmSidebarWinContainer != 0 )
2002     {
2003         bRet = !mpFrmSidebarWinContainer->empty( rFrm );
2004     }
2005 
2006     return bRet;
2007 }
2008 
GetSidebarWinForFrmByIndex(const SwFrm & rFrm,const sal_Int32 nIndex)2009 Window* SwPostItMgr::GetSidebarWinForFrmByIndex( const SwFrm& rFrm,
2010                                                  const sal_Int32 nIndex )
2011 {
2012     Window* pSidebarWin( 0 );
2013 
2014     if ( mpFrmSidebarWinContainer != 0 )
2015     {
2016         pSidebarWin = mpFrmSidebarWinContainer->get( rFrm, nIndex );
2017     }
2018 
2019     return pSidebarWin;
2020 }
2021 
GetAllSidebarWinForFrm(const SwFrm & rFrm,std::vector<Window * > * pChildren)2022 void SwPostItMgr::GetAllSidebarWinForFrm( const SwFrm& rFrm,
2023                                           std::vector< Window* >* pChildren )
2024 {
2025     if ( mpFrmSidebarWinContainer != 0 )
2026     {
2027         mpFrmSidebarWinContainer->getAll( rFrm, pChildren );
2028     }
2029 }
2030 
Commit()2031 void SwNoteProps::Commit() {}
Notify(const::com::sun::star::uno::Sequence<rtl::OUString> &)2032 void SwNoteProps::Notify( const ::com::sun::star::uno::Sequence< rtl::OUString >& ) {}
2033