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