1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/fixed.hxx>
21 #include <vcl/button.hxx>
22 #include <vcl/tabpage.hxx>
23 #include <svtools/wizdlg.hxx>
27 #define WIZARDDIALOG_BUTTON_OFFSET_Y 6
28 #define WIZARDDIALOG_BUTTON_DLGOFFSET_X 6
29 #define WIZARDDIALOG_VIEW_DLGOFFSET_X 6
30 #define WIZARDDIALOG_VIEW_DLGOFFSET_Y 6
34 struct ImplWizPageData
36 ImplWizPageData
* mpNext
;
37 VclPtr
<TabPage
> mpPage
;
42 struct ImplWizButtonData
44 ImplWizButtonData
* mpNext
;
45 VclPtr
<Button
> mpButton
;
51 void WizardDialog::ImplInitData()
60 meViewAlign
= WINDOWALIGN_LEFT
;
61 mbEmptyViewMargin
= false;
64 maWizardLayoutIdle
.SetPriority(SchedulerPriority::RESIZE
);
65 maWizardLayoutIdle
.SetIdleHdl( LINK( this, WizardDialog
, ImplHandleWizardLayoutTimerHdl
) );
69 void WizardDialog::SetLeftAlignedButtonCount( sal_Int16 _nCount
)
71 mnLeftAlignCount
= _nCount
;
76 void WizardDialog::SetEmptyViewMargin()
78 mbEmptyViewMargin
= true;
83 void WizardDialog::ImplCalcSize( Size
& rSize
)
85 // ButtonBar-Hoehe berechnen
87 ImplWizButtonData
* pBtnData
= mpFirstBtn
;
90 long nBtnHeight
= pBtnData
->mpButton
->GetSizePixel().Height();
91 if ( nBtnHeight
> nMaxHeight
)
92 nMaxHeight
= nBtnHeight
;
93 pBtnData
= pBtnData
->mpNext
;
96 nMaxHeight
+= WIZARDDIALOG_BUTTON_OFFSET_Y
*2;
97 rSize
.Height() += nMaxHeight
;
99 // View-Window-Groesse dazurechnen
100 if ( mpViewWindow
&& mpViewWindow
->IsVisible() )
102 Size aViewSize
= mpViewWindow
->GetSizePixel();
103 if ( meViewAlign
== WINDOWALIGN_TOP
)
104 rSize
.Height() += aViewSize
.Height();
105 else if ( meViewAlign
== WINDOWALIGN_LEFT
)
106 rSize
.Width() += aViewSize
.Width();
107 else if ( meViewAlign
== WINDOWALIGN_BOTTOM
)
108 rSize
.Height() += aViewSize
.Height();
109 else if ( meViewAlign
== WINDOWALIGN_RIGHT
)
110 rSize
.Width() += aViewSize
.Width();
114 bool WizardDialog::hasWizardPendingLayout() const
116 return maWizardLayoutIdle
.IsActive();
119 void WizardDialog::queue_resize(StateChangedType
/*eReason*/)
121 if (hasWizardPendingLayout())
125 maWizardLayoutIdle
.Start();
128 IMPL_LINK_NOARG_TYPED( WizardDialog
, ImplHandleWizardLayoutTimerHdl
, Idle
*, void )
134 void WizardDialog::ImplPosCtrls()
136 Size aDlgSize
= GetOutputSizePixel();
139 long nOffY
= aDlgSize
.Height();
141 ImplWizButtonData
* pBtnData
= mpFirstBtn
;
145 if (j
>= mnLeftAlignCount
)
147 Size aBtnSize
= pBtnData
->mpButton
->GetSizePixel();
148 long nBtnHeight
= aBtnSize
.Height();
149 if ( nBtnHeight
> nMaxHeight
)
150 nMaxHeight
= nBtnHeight
;
151 nBtnWidth
+= aBtnSize
.Width();
152 nBtnWidth
+= pBtnData
->mnOffset
;
154 pBtnData
= pBtnData
->mpNext
;
160 long nOffX
= aDlgSize
.Width()-nBtnWidth
-WIZARDDIALOG_BUTTON_DLGOFFSET_X
;
161 long nOffLeftAlignX
= LogicalCoordinateToPixel(6);
162 nOffY
-= WIZARDDIALOG_BUTTON_OFFSET_Y
+nMaxHeight
;
164 pBtnData
= mpFirstBtn
;
168 Size aBtnSize
= pBtnData
->mpButton
->GetSizePixel();
169 if (i
>= mnLeftAlignCount
)
171 Point
aPos( nOffX
, nOffY
+((nMaxHeight
-aBtnSize
.Height())/2) );
172 pBtnData
->mpButton
->SetPosPixel( aPos
);
173 nOffX
+= aBtnSize
.Width();
174 nOffX
+= pBtnData
->mnOffset
;
178 Point
aPos( nOffLeftAlignX
, nOffY
+((nMaxHeight
-aBtnSize
.Height())/2) );
179 pBtnData
->mpButton
->SetPosPixel( aPos
);
180 nOffLeftAlignX
+= aBtnSize
.Width();
181 nOffLeftAlignX
+= pBtnData
->mnOffset
;
184 pBtnData
= pBtnData
->mpNext
;
188 nOffY
-= WIZARDDIALOG_BUTTON_OFFSET_Y
;
191 if ( mpViewWindow
&& mpViewWindow
->IsVisible() )
196 long nViewHeight
= 0;
197 long nDlgHeight
= nOffY
;
198 PosSizeFlags nViewPosFlags
= PosSizeFlags::Pos
;
199 if ( meViewAlign
== WINDOWALIGN_TOP
)
201 nViewOffX
= WIZARDDIALOG_VIEW_DLGOFFSET_X
;
202 nViewOffY
= WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
203 nViewWidth
= aDlgSize
.Width()-(WIZARDDIALOG_VIEW_DLGOFFSET_X
*2);
204 nViewPosFlags
|= PosSizeFlags::Width
;
206 else if ( meViewAlign
== WINDOWALIGN_LEFT
)
208 if ( mbEmptyViewMargin
)
212 nViewHeight
= nDlgHeight
;
216 nViewOffX
= WIZARDDIALOG_VIEW_DLGOFFSET_X
;
217 nViewOffY
= WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
218 nViewHeight
= nDlgHeight
-(WIZARDDIALOG_VIEW_DLGOFFSET_Y
*2);
220 nViewPosFlags
|= PosSizeFlags::Height
;
222 else if ( meViewAlign
== WINDOWALIGN_BOTTOM
)
224 nViewOffX
= WIZARDDIALOG_VIEW_DLGOFFSET_X
;
225 nViewOffY
= nDlgHeight
-mpViewWindow
->GetSizePixel().Height()-WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
226 nViewWidth
= aDlgSize
.Width()-(WIZARDDIALOG_VIEW_DLGOFFSET_X
*2);
227 nViewPosFlags
|= PosSizeFlags::Width
;
229 else if ( meViewAlign
== WINDOWALIGN_RIGHT
)
231 nViewOffX
= aDlgSize
.Width()-mpViewWindow
->GetSizePixel().Width()-WIZARDDIALOG_VIEW_DLGOFFSET_X
;
232 nViewOffY
= WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
233 nViewHeight
= nDlgHeight
-(WIZARDDIALOG_VIEW_DLGOFFSET_Y
*2);
234 nViewPosFlags
|= PosSizeFlags::Height
;
236 mpViewWindow
->setPosSizePixel( nViewOffX
, nViewOffY
,
237 nViewWidth
, nViewHeight
,
243 long WizardDialog::LogicalCoordinateToPixel(int iCoordinate
){
244 Size aLocSize
= LogicToPixel(Size( iCoordinate
, 0 ), MAP_APPFONT
);
245 int iPixelCoordinate
= aLocSize
.Width();
246 return iPixelCoordinate
;
252 void WizardDialog::ImplPosTabPage()
257 if ( !IsInInitShow() )
259 // #100199# - On Unix initial size is equal to screen size, on Windows
260 // it's 0,0. One cannot calculate the size unless dialog is visible.
261 if ( !IsReallyVisible() )
265 // calculate height of ButtonBar
267 ImplWizButtonData
* pBtnData
= mpFirstBtn
;
270 long nBtnHeight
= pBtnData
->mpButton
->GetSizePixel().Height();
271 if ( nBtnHeight
> nMaxHeight
)
272 nMaxHeight
= nBtnHeight
;
273 pBtnData
= pBtnData
->mpNext
;
276 nMaxHeight
+= WIZARDDIALOG_BUTTON_OFFSET_Y
*2;
279 Size aDlgSize
= GetOutputSizePixel();
280 aDlgSize
.Height() -= nMaxHeight
;
283 if ( mpViewWindow
&& mpViewWindow
->IsVisible() )
285 Size aViewSize
= mpViewWindow
->GetSizePixel();
286 if ( meViewAlign
== WINDOWALIGN_TOP
)
288 nOffY
+= aViewSize
.Height()+WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
289 aDlgSize
.Height() -= aViewSize
.Height()+WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
291 else if ( meViewAlign
== WINDOWALIGN_LEFT
)
293 long nViewOffset
= mbEmptyViewMargin
? 0 : WIZARDDIALOG_VIEW_DLGOFFSET_X
;
294 nOffX
+= aViewSize
.Width() + nViewOffset
;
295 aDlgSize
.Width() -= nOffX
;
297 else if ( meViewAlign
== WINDOWALIGN_BOTTOM
)
298 aDlgSize
.Height() -= aViewSize
.Height()+WIZARDDIALOG_VIEW_DLGOFFSET_Y
;
299 else if ( meViewAlign
== WINDOWALIGN_RIGHT
)
300 aDlgSize
.Width() -= aViewSize
.Width()+WIZARDDIALOG_VIEW_DLGOFFSET_X
;
302 Point
aPos( nOffX
, nOffY
);
303 mpCurTabPage
->SetPosSizePixel( aPos
, aDlgSize
);
308 void WizardDialog::ImplShowTabPage( TabPage
* pTabPage
)
310 if ( mpCurTabPage
== pTabPage
)
313 TabPage
* pOldTabPage
= mpCurTabPage
;
315 pOldTabPage
->DeactivatePage();
317 mpCurTabPage
= pTabPage
;
321 pTabPage
->ActivatePage();
331 TabPage
* WizardDialog::ImplGetPage( sal_uInt16 nLevel
) const
333 sal_uInt16 nTempLevel
= 0;
334 ImplWizPageData
* pPageData
= mpFirstPage
;
337 if ( (nTempLevel
== nLevel
) || !pPageData
->mpNext
)
341 pPageData
= pPageData
->mpNext
;
345 return pPageData
->mpPage
;
349 WizardDialog::WizardDialog( vcl::Window
* pParent
, WinBits nStyle
) :
350 ModalDialog( pParent
, nStyle
)
357 WizardDialog::WizardDialog( vcl::Window
* pParent
, const OUString
& rID
, const OUString
& rUIXMLDescription
) :
358 ModalDialog( pParent
, rID
, rUIXMLDescription
)
363 WizardDialog::~WizardDialog()
368 void WizardDialog::dispose()
370 maWizardLayoutIdle
.Stop();
372 // Remove all buttons
374 RemoveButton( mpFirstBtn
->mpButton
);
377 while ( mpFirstPage
)
378 RemovePage( mpFirstPage
->mpPage
);
380 mpCurTabPage
.clear();
383 mpViewWindow
.clear();
384 ModalDialog::dispose();
389 void WizardDialog::Resize()
391 if ( IsReallyShown() && !IsInInitShow() )
402 void WizardDialog::StateChanged( StateChangedType nType
)
404 if ( nType
== StateChangedType::InitShow
)
406 if ( IsDefaultSize() )
408 Size aDlgSize
= GetPageSizePixel();
409 if ( !aDlgSize
.Width() || !aDlgSize
.Height() )
411 ImplWizPageData
* pPageData
= mpFirstPage
;
414 if ( pPageData
->mpPage
)
416 Size aPageSize
= pPageData
->mpPage
->GetSizePixel();
417 if ( aPageSize
.Width() > aDlgSize
.Width() )
418 aDlgSize
.Width() = aPageSize
.Width();
419 if ( aPageSize
.Height() > aDlgSize
.Height() )
420 aDlgSize
.Height() = aPageSize
.Height();
423 pPageData
= pPageData
->mpNext
;
426 ImplCalcSize( aDlgSize
);
427 SetOutputSizePixel( aDlgSize
);
432 ImplShowTabPage( ImplGetPage( mnCurLevel
) );
435 Dialog::StateChanged( nType
);
440 bool WizardDialog::Notify( NotifyEvent
& rNEvt
)
442 if ( (rNEvt
.GetType() == MouseNotifyEvent::KEYINPUT
) && mpPrevBtn
&& mpNextBtn
)
444 const KeyEvent
* pKEvt
= rNEvt
.GetKeyEvent();
445 vcl::KeyCode aKeyCode
= pKEvt
->GetKeyCode();
446 sal_uInt16 nKeyCode
= aKeyCode
.GetCode();
448 if ( aKeyCode
.IsMod1() )
450 if ( aKeyCode
.IsShift() || (nKeyCode
== KEY_PAGEUP
) )
452 if ( (nKeyCode
== KEY_TAB
) || (nKeyCode
== KEY_PAGEUP
) )
454 if ( mpPrevBtn
->IsVisible() &&
455 mpPrevBtn
->IsEnabled() && mpPrevBtn
->IsInputEnabled() )
457 mpPrevBtn
->SetPressed( true );
458 mpPrevBtn
->SetPressed( false );
466 if ( (nKeyCode
== KEY_TAB
) || (nKeyCode
== KEY_PAGEDOWN
) )
468 if ( mpNextBtn
->IsVisible() &&
469 mpNextBtn
->IsEnabled() && mpNextBtn
->IsInputEnabled() )
471 mpNextBtn
->SetPressed( true );
472 mpNextBtn
->SetPressed( false );
481 return Dialog::Notify( rNEvt
);
486 void WizardDialog::ActivatePage()
488 maActivateHdl
.Call( this );
493 bool WizardDialog::DeactivatePage()
495 if ( maDeactivateHdl
.IsSet() )
496 return maDeactivateHdl
.Call( this );
503 bool WizardDialog::ShowNextPage()
505 return ShowPage( mnCurLevel
+1 );
510 bool WizardDialog::ShowPrevPage()
514 return ShowPage( mnCurLevel
-1 );
519 bool WizardDialog::ShowPage( sal_uInt16 nLevel
)
521 if ( DeactivatePage() )
525 ImplShowTabPage( ImplGetPage( mnCurLevel
) );
534 bool WizardDialog::Finish( long nResult
)
536 if ( DeactivatePage() )
539 mpCurTabPage
->DeactivatePage();
542 EndDialog( nResult
);
543 else if ( GetStyle() & WB_CLOSEABLE
)
553 void WizardDialog::AddPage( TabPage
* pPage
)
555 ImplWizPageData
* pNewPageData
= new ImplWizPageData
;
556 pNewPageData
->mpNext
= NULL
;
557 pNewPageData
->mpPage
= pPage
;
560 mpFirstPage
= pNewPageData
;
563 ImplWizPageData
* pPageData
= mpFirstPage
;
564 while ( pPageData
->mpNext
)
565 pPageData
= pPageData
->mpNext
;
566 pPageData
->mpNext
= pNewPageData
;
572 void WizardDialog::RemovePage( TabPage
* pPage
)
574 ImplWizPageData
* pPrevPageData
= NULL
;
575 ImplWizPageData
* pPageData
= mpFirstPage
;
578 if ( pPageData
->mpPage
== pPage
)
581 pPrevPageData
->mpNext
= pPageData
->mpNext
;
583 mpFirstPage
= pPageData
->mpNext
;
584 if ( pPage
== mpCurTabPage
)
590 pPrevPageData
= pPageData
;
591 pPageData
= pPageData
->mpNext
;
594 OSL_FAIL( "WizardDialog::RemovePage() - Page not in list" );
599 void WizardDialog::SetPage( sal_uInt16 nLevel
, TabPage
* pPage
)
601 sal_uInt16 nTempLevel
= 0;
602 ImplWizPageData
* pPageData
= mpFirstPage
;
605 if ( (nTempLevel
== nLevel
) || !pPageData
->mpNext
)
609 pPageData
= pPageData
->mpNext
;
614 if ( pPageData
->mpPage
== mpCurTabPage
)
616 pPageData
->mpPage
= pPage
;
622 TabPage
* WizardDialog::GetPage( sal_uInt16 nLevel
) const
624 sal_uInt16 nTempLevel
= 0;
626 for (ImplWizPageData
* pPageData
= mpFirstPage
; pPageData
;
627 pPageData
= pPageData
->mpNext
)
629 if ( nTempLevel
== nLevel
)
630 return pPageData
->mpPage
;
639 void WizardDialog::AddButton( Button
* pButton
, long nOffset
)
641 ImplWizButtonData
* pNewBtnData
= new ImplWizButtonData
;
642 pNewBtnData
->mpNext
= NULL
;
643 pNewBtnData
->mpButton
= pButton
;
644 pNewBtnData
->mnOffset
= nOffset
;
647 mpFirstBtn
= pNewBtnData
;
650 ImplWizButtonData
* pBtnData
= mpFirstBtn
;
651 while ( pBtnData
->mpNext
)
652 pBtnData
= pBtnData
->mpNext
;
653 pBtnData
->mpNext
= pNewBtnData
;
659 void WizardDialog::RemoveButton( Button
* pButton
)
661 ImplWizButtonData
* pPrevBtnData
= NULL
;
662 ImplWizButtonData
* pBtnData
= mpFirstBtn
;
665 if ( pBtnData
->mpButton
== pButton
)
668 pPrevBtnData
->mpNext
= pBtnData
->mpNext
;
670 mpFirstBtn
= pBtnData
->mpNext
;
675 pPrevBtnData
= pBtnData
;
676 pBtnData
= pBtnData
->mpNext
;
679 OSL_FAIL( "WizardDialog::RemoveButton() - Button not in list" );
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */