1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License or as specified alternatively below. You may obtain a copy of
8 * the License at http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * Major Contributor(s):
16 * [ Copyright (C) 2011 SUSE <cbosdonnat@suse.com> (initial developer) ]
18 * All Rights Reserved.
20 * For minor contributions see the git repository.
22 * Alternatively, the contents of this file may be used under the terms of
23 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 * instead of those above.
28 #include <globals.hrc>
34 #include <DashedLine.hxx>
37 #include <fmtpdsc.hxx>
38 #include <IDocumentUndoRedo.hxx>
39 #include <PageBreakWin.hxx>
40 #include <pagefrm.hxx>
41 #include <PostItMgr.hxx>
42 #include <uiitems.hxx>
44 #include <viewopt.hxx>
47 #include <basegfx/color/bcolortools.hxx>
48 #include <basegfx/matrix/b2dhommatrixtools.hxx>
49 #include <basegfx/polygon/b2dpolygon.hxx>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
51 #include <basegfx/range/b2drectangle.hxx>
52 #include <drawinglayer/primitive2d/discretebitmapprimitive2d.hxx>
53 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
54 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
55 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
56 #include <editeng/brkitem.hxx>
57 #include <sfx2/dispatch.hxx>
58 #include <svx/sdr/contact/objectcontacttools.hxx>
59 #include <vcl/svapp.hxx>
61 #define BUTTON_WIDTH 30
62 #define BUTTON_HEIGHT 19
65 using namespace basegfx
;
66 using namespace basegfx::tools
;
67 using namespace drawinglayer::primitive2d
;
71 class SwBreakDashedLine
: public SwDashedLine
74 SwPageBreakWin
* m_pWin
;
77 SwBreakDashedLine( Window
* pParent
, Color
& ( *pColorFn
)(), SwPageBreakWin
* pWin
) :
78 SwDashedLine( pParent
, pColorFn
),
81 virtual void MouseMove( const MouseEvent
& rMEvt
);
84 void SwBreakDashedLine::MouseMove( const MouseEvent
& rMEvt
)
86 Point
aEventPos( GetPosPixel() + rMEvt
.GetPosPixel() );
87 if ( !m_pWin
->Contains( aEventPos
) )
88 m_pWin
->Fade( false );
89 else if ( !m_pWin
->IsVisible() )
92 if ( !rMEvt
.IsSynthetic() )
94 Point
* pPtr
= new Point( rMEvt
.GetPosPixel() );
95 m_pWin
->UpdatePosition( pPtr
);
100 SwPageBreakWin::SwPageBreakWin( SwEditWin
* pEditWin
, const SwPageFrm
* pPageFrm
) :
101 MenuButton( pEditWin
, WB_DIALOGCONTROL
),
102 SwFrameControl( pEditWin
, pPageFrm
),
103 m_pPopupMenu( NULL
),
105 m_bIsAppearing( false ),
107 m_nDelayAppearing( 0 ),
108 m_bDestroyed( false ),
111 // Use pixels for the rest of the drawing
112 SetMapMode( MapMode ( MAP_PIXEL
) );
114 // Create the line control
115 m_pLine
= new SwBreakDashedLine( GetEditWin(), &SwViewOption::GetPageBreakColor
, this );
117 // Create the popup menu
118 m_pPopupMenu
= new PopupMenu( SW_RES( MN_PAGEBREAK_BUTTON
) );
119 m_pPopupMenu
->SetDeactivateHdl( LINK( this, SwPageBreakWin
, HideHandler
) );
120 SetPopupMenu( m_pPopupMenu
);
122 m_aFadeTimer
.SetTimeout( 50 );
123 m_aFadeTimer
.SetTimeoutHdl( LINK( this, SwPageBreakWin
, FadeHandler
) );
126 SwPageBreakWin::~SwPageBreakWin( )
136 void SwPageBreakWin::Paint( const Rectangle
& )
138 const Rectangle
aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) );
140 // Properly paint the control
141 BColor aColor
= SwViewOption::GetPageBreakColor().getBColor();
143 BColor aHslLine
= rgb2hsl( aColor
);
144 double nLuminance
= aHslLine
.getZ();
145 nLuminance
+= ( 1.0 - nLuminance
) * 0.75;
146 if ( aHslLine
.getZ() > 0.7 )
147 nLuminance
= aHslLine
.getZ() * 0.7;
148 aHslLine
.setZ( nLuminance
);
149 BColor aOtherColor
= hsl2rgb( aHslLine
);
151 const StyleSettings
& rSettings
= Application::GetSettings().GetStyleSettings();
152 if ( rSettings
.GetHighContrastMode( ) )
154 aColor
= rSettings
.GetDialogTextColor().getBColor();
155 aOtherColor
= rSettings
.GetDialogColor( ).getBColor();
158 bool bRtl
= Application::GetSettings().GetLayoutRTL();
160 Primitive2DSequence
aSeq( 3 );
161 B2DRectangle
aBRect( double( aRect
.Left() ), double( aRect
.Top( ) ),
162 double( aRect
.Right() ), double( aRect
.Bottom( ) ) );
163 B2DPolygon aPolygon
= createPolygonFromRect( aBRect
, 3.0 / BUTTON_WIDTH
, 3.0 / BUTTON_HEIGHT
);
165 // Create the polygon primitives
166 aSeq
[0] = Primitive2DReference( new PolyPolygonColorPrimitive2D(
167 B2DPolyPolygon( aPolygon
), aOtherColor
) );
168 aSeq
[1] = Primitive2DReference( new PolygonHairlinePrimitive2D(
169 aPolygon
, aColor
) );
171 // Create the primitive for the image
172 Image
aImg( SW_RES( IMG_PAGE_BREAK
) );
173 double nImgOfstX
= 3.0;
175 nImgOfstX
= aRect
.Right() - aImg
.GetSizePixel().Width() - 3.0;
176 aSeq
[2] = Primitive2DReference( new DiscreteBitmapPrimitive2D(
177 aImg
.GetBitmapEx(), B2DPoint( nImgOfstX
, 1.0 ) ) );
179 // Paint the symbol if not readonly button
182 double nTop
= double( aRect
.getHeight() ) / 2.0;
183 double nBottom
= nTop
+ 4.0;
184 double nLeft
= aRect
.getWidth( ) - ARROW_WIDTH
- 6.0;
186 nLeft
= ARROW_WIDTH
- 2.0;
187 double nRight
= nLeft
+ 8.0;
189 B2DPolygon aTriangle
;
190 aTriangle
.append( B2DPoint( nLeft
, nTop
) );
191 aTriangle
.append( B2DPoint( nRight
, nTop
) );
192 aTriangle
.append( B2DPoint( ( nLeft
+ nRight
) / 2.0, nBottom
) );
193 aTriangle
.setClosed( true );
195 BColor aTriangleColor
= Color( COL_BLACK
).getBColor( );
196 if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() )
197 aTriangleColor
= Color( COL_WHITE
).getBColor( );
199 aSeq
.realloc( aSeq
.getLength() + 1 );
200 aSeq
[ aSeq
.getLength() - 1 ] = Primitive2DReference( new PolyPolygonColorPrimitive2D(
201 B2DPolyPolygon( aTriangle
), aTriangleColor
) );
204 Primitive2DSequence
aGhostedSeq( 1 );
205 double nFadeRate
= double( m_nFadeRate
) / 100.0;
206 aGhostedSeq
[0] = Primitive2DReference( new ModifiedColorPrimitive2D(
207 aSeq
, BColorModifier( Color( COL_WHITE
).getBColor(), 1.0 - nFadeRate
, BCOLORMODIFYMODE_INTERPOLATE
) ) );
209 // Create the processor and process the primitives
210 const drawinglayer::geometry::ViewInformation2D aNewViewInfos
;
211 drawinglayer::processor2d::BaseProcessor2D
* pProcessor
=
212 sdr::contact::createBaseProcessor2DFromOutputDevice(
213 *this, aNewViewInfos
);
215 pProcessor
->process( aGhostedSeq
);
218 void SwPageBreakWin::Select( )
220 SwFrameControlPtr pThis
= GetEditWin()->GetFrameControlsManager( ).GetControl( PageBreak
, GetFrame() );
222 switch( GetCurItemId( ) )
224 case FN_PAGEBREAK_EDIT
:
226 const SwLayoutFrm
* pBodyFrm
= static_cast< const SwLayoutFrm
* >( GetPageFrame()->Lower() );
227 while ( pBodyFrm
&& !pBodyFrm
->IsBodyFrm() )
228 pBodyFrm
= static_cast< const SwLayoutFrm
* >( pBodyFrm
->GetNext() );
230 SwEditWin
* pEditWin
= GetEditWin();
234 SwWrtShell
& rSh
= pEditWin
->GetView().GetWrtShell();
235 sal_Bool bOldLock
= rSh
.IsViewLocked();
236 rSh
.LockView( sal_True
);
238 if ( pBodyFrm
->Lower()->IsTabFrm() )
243 SwCntntFrm
*pCnt
= const_cast< SwCntntFrm
* >( pBodyFrm
->ContainsCntnt() );
244 SwCntntNode
* pNd
= pCnt
->GetNode();
245 rSh
.SetSelection( *pNd
);
247 SfxUInt16Item
aItem( pEditWin
->GetView().GetPool( ).GetWhich( FN_FORMAT_TABLE_DLG
), TP_TABLE_TEXTFLOW
);
248 pEditWin
->GetView().GetViewFrame()->GetDispatcher()->Execute(
249 FN_FORMAT_TABLE_DLG
, SFX_CALLMODE_SYNCHRON
|SFX_CALLMODE_RECORD
, &aItem
, NULL
);
251 rSh
.Pop( sal_False
);
255 SwCntntFrm
*pCnt
= const_cast< SwCntntFrm
* >( pBodyFrm
->ContainsCntnt() );
256 SwCntntNode
* pNd
= pCnt
->GetNode();
259 SwPaMItem
aPaMItem( pEditWin
->GetView().GetPool( ).GetWhich( FN_PARAM_PAM
), &aPaM
);
260 SfxUInt16Item
aItem( pEditWin
->GetView().GetPool( ).GetWhich( SID_PARA_DLG
), TP_PARA_EXT
);
261 pEditWin
->GetView().GetViewFrame()->GetDispatcher()->Execute(
262 SID_PARA_DLG
, SFX_CALLMODE_SYNCHRON
|SFX_CALLMODE_RECORD
, &aItem
, &aPaMItem
, NULL
);
264 rSh
.LockView( bOldLock
);
265 pEditWin
->GrabFocus( );
269 case FN_PAGEBREAK_DELETE
:
271 const SwLayoutFrm
* pBodyFrm
= static_cast< const SwLayoutFrm
* >( GetPageFrame()->Lower() );
272 while ( pBodyFrm
&& !pBodyFrm
->IsBodyFrm() )
273 pBodyFrm
= static_cast< const SwLayoutFrm
* >( pBodyFrm
->GetNext() );
277 SwCntntFrm
*pCnt
= const_cast< SwCntntFrm
* >( pBodyFrm
->ContainsCntnt() );
278 SwCntntNode
* pNd
= pCnt
->GetNode();
280 pNd
->GetDoc()->GetIDocumentUndoRedo( ).StartUndo( UNDO_UI_DELETE_PAGE_BREAK
, NULL
);
282 SfxItemSet
aSet( GetEditWin()->GetView().GetWrtShell().GetAttrPool(),
283 RES_PAGEDESC
, RES_PAGEDESC
,
284 RES_BREAK
, RES_BREAK
,
286 aSet
.Put( SvxFmtBreakItem( SVX_BREAK_NONE
, RES_BREAK
) );
287 aSet
.Put( SwFmtPageDesc( NULL
) );
290 pNd
->GetDoc()->InsertItemSet( aPaM
, aSet
, nsSetAttrMode::SETATTR_DEFAULT
);
292 pNd
->GetDoc()->GetIDocumentUndoRedo( ).EndUndo( UNDO_UI_DELETE_PAGE_BREAK
, NULL
);
298 // Only fade if there is more than this temporary shared pointer:
299 // The main reference has been deleted due to a page break removal
300 if ( pThis
.use_count() > 1 )
304 void SwPageBreakWin::MouseMove( const MouseEvent
& rMEvt
)
306 Point
aEventPos( rMEvt
.GetPosPixel() + rMEvt
.GetPosPixel() );
307 if ( !Contains( aEventPos
) && !PopupMenu::IsInExecute() )
309 else if ( !IsVisible() )
313 void SwPageBreakWin::Activate( )
316 MenuButton::Activate();
319 void SwPageBreakWin::UpdatePosition( const Point
* pEvtPt
)
321 if ( pEvtPt
!= NULL
)
323 if ( pEvtPt
== m_pMousePt
)
329 const SwPageFrm
* pPageFrm
= GetPageFrame();
330 const SwFrm
* pPrevPage
= pPageFrm
->GetPrev();
331 while ( pPrevPage
&& ( pPrevPage
->Frm().Top( ) == pPageFrm
->Frm().Top( ) ) )
332 pPrevPage
= pPrevPage
->GetPrev();
334 Rectangle aBoundRect
= GetEditWin()->LogicToPixel( pPageFrm
->GetBoundRect().SVRect() );
335 Rectangle aFrmRect
= GetEditWin()->LogicToPixel( pPageFrm
->Frm().SVRect() );
337 long nYLineOffset
= ( aBoundRect
.Top() + aFrmRect
.Top() ) / 2;
340 Rectangle aPrevFrmRect
= GetEditWin()->LogicToPixel( pPrevPage
->Frm().SVRect() );
341 nYLineOffset
= ( aPrevFrmRect
.Bottom() + aFrmRect
.Top() ) / 2;
344 // Get the page + sidebar coords
345 long nPgLeft
= aFrmRect
.Left();
346 long nPgRight
= aFrmRect
.Right();
348 unsigned long nSidebarWidth
= 0;
349 const SwPostItMgr
* pPostItMngr
= GetEditWin()->GetView().GetWrtShell().GetPostItMgr();
350 if ( pPostItMngr
&& pPostItMngr
->HasNotes() && pPostItMngr
->ShowNotes() )
351 nSidebarWidth
= pPostItMngr
->GetSidebarBorderWidth( true ) + pPostItMngr
->GetSidebarWidth( true );
353 if ( pPageFrm
->SidebarPosition( ) == sw::sidebarwindows::SIDEBAR_LEFT
)
354 nPgLeft
-= nSidebarWidth
;
355 else if ( pPageFrm
->SidebarPosition( ) == sw::sidebarwindows::SIDEBAR_RIGHT
)
356 nPgRight
+= nSidebarWidth
;
358 Size
aBtnSize( BUTTON_WIDTH
+ ARROW_WIDTH
, BUTTON_HEIGHT
);
360 // Place the button on the left or right?
361 Rectangle aVisArea
= GetEditWin()->LogicToPixel( GetEditWin()->GetView().GetVisArea() );
363 long nLineLeft
= std::max( nPgLeft
, aVisArea
.Left() );
364 long nLineRight
= std::min( nPgRight
, aVisArea
.Right() );
365 long nBtnLeft
= nLineLeft
;
369 nBtnLeft
= nLineLeft
+ m_pMousePt
->X() - aBtnSize
.getWidth() / 2;
371 if ( nBtnLeft
< nLineLeft
)
372 nBtnLeft
= nLineLeft
;
373 else if ( ( nBtnLeft
+ aBtnSize
.getWidth() ) > nLineRight
)
374 nBtnLeft
= nLineRight
- aBtnSize
.getWidth();
377 // Set the button position
378 Point
aBtnPos( nBtnLeft
, nYLineOffset
- BUTTON_HEIGHT
/ 2 );
379 SetPosSizePixel( aBtnPos
, aBtnSize
);
381 // Set the line position
382 Point
aLinePos( nLineLeft
, nYLineOffset
- 5 );
383 Size
aLineSize( nLineRight
- nLineLeft
, 10 );
384 m_pLine
->SetPosSizePixel( aLinePos
, aLineSize
);
387 void SwPageBreakWin::ShowAll( bool bShow
)
389 m_pLine
->Show( bShow
);
392 bool SwPageBreakWin::Contains( const Point
&rDocPt
) const
394 Rectangle
aRect( GetPosPixel(), GetSizePixel() );
395 if ( aRect
.IsInside( rDocPt
) )
398 Rectangle
aLineRect( m_pLine
->GetPosPixel(), m_pLine
->GetSizePixel() );
399 if ( aLineRect
.IsInside( rDocPt
) )
405 const SwPageFrm
* SwPageBreakWin::GetPageFrame( )
407 return static_cast< const SwPageFrm
* >( GetFrame( ) );
410 void SwPageBreakWin::SetReadonly( bool bReadonly
)
412 Enable( !bReadonly
);
415 void SwPageBreakWin::Fade( bool bFadeIn
)
417 m_bIsAppearing
= bFadeIn
;
419 m_nDelayAppearing
= 0;
421 if ( !m_bDestroyed
&& m_aFadeTimer
.IsActive( ) )
424 m_aFadeTimer
.Start( );
427 IMPL_LINK( SwPageBreakWin
, HideHandler
, void *, EMPTYARG
)
434 IMPL_LINK( SwPageBreakWin
, FadeHandler
, Timer
*, EMPTYARG
)
436 const int TICKS_BEFORE_WE_APPEAR
= 10;
437 if ( m_bIsAppearing
&& m_nDelayAppearing
< TICKS_BEFORE_WE_APPEAR
)
440 m_aFadeTimer
.Start();
444 if ( m_bIsAppearing
&& m_nFadeRate
> 0 )
446 else if ( !m_bIsAppearing
&& m_nFadeRate
< 100 )
449 if ( m_nFadeRate
!= 100 && !IsVisible() )
451 else if ( m_nFadeRate
== 100 && IsVisible( ) )
459 if ( IsVisible( ) && m_nFadeRate
> 0 && m_nFadeRate
< 100 )
460 m_aFadeTimer
.Start();
465 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */