Bump version to 5.0-14
[LibreOffice.git] / svtools / source / dialogs / wizdlg.cxx
blob39d63906d5c54941389fc30890282f67ca55cc38
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
46 long mnOffset;
51 void WizardDialog::ImplInitData()
53 mpFirstPage = NULL;
54 mpFirstBtn = NULL;
55 mpCurTabPage = NULL;
56 mpPrevBtn = NULL;
57 mpNextBtn = NULL;
58 mpViewWindow = NULL;
59 mnCurLevel = 0;
60 meViewAlign = WINDOWALIGN_LEFT;
61 mbEmptyViewMargin = false;
62 mnLeftAlignCount = 0;
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
86 long nMaxHeight = 0;
87 ImplWizButtonData* pBtnData = mpFirstBtn;
88 while ( pBtnData )
90 long nBtnHeight = pBtnData->mpButton->GetSizePixel().Height();
91 if ( nBtnHeight > nMaxHeight )
92 nMaxHeight = nBtnHeight;
93 pBtnData = pBtnData->mpNext;
95 if ( nMaxHeight )
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())
122 return;
123 if (IsInClose())
124 return;
125 maWizardLayoutIdle.Start();
128 IMPL_LINK_NOARG_TYPED( WizardDialog, ImplHandleWizardLayoutTimerHdl, Idle*, void )
130 ImplPosCtrls();
131 ImplPosTabPage();
134 void WizardDialog::ImplPosCtrls()
136 Size aDlgSize = GetOutputSizePixel();
137 long nBtnWidth = 0;
138 long nMaxHeight = 0;
139 long nOffY = aDlgSize.Height();
141 ImplWizButtonData* pBtnData = mpFirstBtn;
142 int j = 0;
143 while ( pBtnData )
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;
155 j++;
158 if ( nMaxHeight )
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;
165 int i = 0;
166 while ( pBtnData )
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;
176 else
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;
185 i++;
188 nOffY -= WIZARDDIALOG_BUTTON_OFFSET_Y;
191 if ( mpViewWindow && mpViewWindow->IsVisible() )
193 long nViewOffX = 0;
194 long nViewOffY = 0;
195 long nViewWidth = 0;
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 )
210 nViewOffX = 0;
211 nViewOffY = 0;
212 nViewHeight = nDlgHeight;
214 else
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,
238 nViewPosFlags );
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()
254 if ( !mpCurTabPage )
255 return;
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() )
262 return;
265 // calculate height of ButtonBar
266 long nMaxHeight = 0;
267 ImplWizButtonData* pBtnData = mpFirstBtn;
268 while ( pBtnData )
270 long nBtnHeight = pBtnData->mpButton->GetSizePixel().Height();
271 if ( nBtnHeight > nMaxHeight )
272 nMaxHeight = nBtnHeight;
273 pBtnData = pBtnData->mpNext;
275 if ( nMaxHeight )
276 nMaxHeight += WIZARDDIALOG_BUTTON_OFFSET_Y*2;
278 // position TabPage
279 Size aDlgSize = GetOutputSizePixel();
280 aDlgSize.Height() -= nMaxHeight;
281 long nOffX = 0;
282 long nOffY = 0;
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 )
311 return;
313 TabPage* pOldTabPage = mpCurTabPage;
314 if ( pOldTabPage )
315 pOldTabPage->DeactivatePage();
317 mpCurTabPage = pTabPage;
318 if ( pTabPage )
320 ImplPosTabPage();
321 pTabPage->ActivatePage();
322 pTabPage->Show();
325 if ( pOldTabPage )
326 pOldTabPage->Hide();
331 TabPage* WizardDialog::ImplGetPage( sal_uInt16 nLevel ) const
333 sal_uInt16 nTempLevel = 0;
334 ImplWizPageData* pPageData = mpFirstPage;
335 while ( pPageData )
337 if ( (nTempLevel == nLevel) || !pPageData->mpNext )
338 break;
340 nTempLevel++;
341 pPageData = pPageData->mpNext;
344 if ( pPageData )
345 return pPageData->mpPage;
346 return NULL;
349 WizardDialog::WizardDialog( vcl::Window* pParent, WinBits nStyle ) :
350 ModalDialog( pParent, nStyle )
352 ImplInitData();
357 WizardDialog::WizardDialog( vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription ) :
358 ModalDialog( pParent, rID, rUIXMLDescription )
360 ImplInitData();
363 WizardDialog::~WizardDialog()
365 disposeOnce();
368 void WizardDialog::dispose()
370 maWizardLayoutIdle.Stop();
372 // Remove all buttons
373 while ( mpFirstBtn )
374 RemoveButton( mpFirstBtn->mpButton );
376 // Remove all pages
377 while ( mpFirstPage )
378 RemovePage( mpFirstPage->mpPage );
380 mpCurTabPage.clear();
381 mpPrevBtn.clear();
382 mpNextBtn.clear();
383 mpViewWindow.clear();
384 ModalDialog::dispose();
389 void WizardDialog::Resize()
391 if ( IsReallyShown() && !IsInInitShow() )
393 ImplPosCtrls();
394 ImplPosTabPage();
397 Dialog::Resize();
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;
412 while ( pPageData )
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 );
430 ImplPosCtrls();
431 ImplPosTabPage();
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 );
459 mpPrevBtn->Click();
461 return true;
464 else
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 );
473 mpNextBtn->Click();
475 return true;
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 );
497 else
498 return true;
503 bool WizardDialog::ShowNextPage()
505 return ShowPage( mnCurLevel+1 );
510 bool WizardDialog::ShowPrevPage()
512 if ( !mnCurLevel )
513 return false;
514 return ShowPage( mnCurLevel-1 );
519 bool WizardDialog::ShowPage( sal_uInt16 nLevel )
521 if ( DeactivatePage() )
523 mnCurLevel = nLevel;
524 ActivatePage();
525 ImplShowTabPage( ImplGetPage( mnCurLevel ) );
526 return true;
528 else
529 return false;
534 bool WizardDialog::Finish( long nResult )
536 if ( DeactivatePage() )
538 if ( mpCurTabPage )
539 mpCurTabPage->DeactivatePage();
541 if ( IsInExecute() )
542 EndDialog( nResult );
543 else if ( GetStyle() & WB_CLOSEABLE )
544 Close();
545 return true;
547 else
548 return false;
553 void WizardDialog::AddPage( TabPage* pPage )
555 ImplWizPageData* pNewPageData = new ImplWizPageData;
556 pNewPageData->mpNext = NULL;
557 pNewPageData->mpPage = pPage;
559 if ( !mpFirstPage )
560 mpFirstPage = pNewPageData;
561 else
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;
576 while ( pPageData )
578 if ( pPageData->mpPage == pPage )
580 if ( pPrevPageData )
581 pPrevPageData->mpNext = pPageData->mpNext;
582 else
583 mpFirstPage = pPageData->mpNext;
584 if ( pPage == mpCurTabPage )
585 mpCurTabPage = NULL;
586 delete pPageData;
587 return;
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;
603 while ( pPageData )
605 if ( (nTempLevel == nLevel) || !pPageData->mpNext )
606 break;
608 nTempLevel++;
609 pPageData = pPageData->mpNext;
612 if ( pPageData )
614 if ( pPageData->mpPage == mpCurTabPage )
615 mpCurTabPage = NULL;
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;
631 nTempLevel++;
634 return NULL;
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;
646 if ( !mpFirstBtn )
647 mpFirstBtn = pNewBtnData;
648 else
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;
663 while ( pBtnData )
665 if ( pBtnData->mpButton == pButton )
667 if ( pPrevBtnData )
668 pPrevBtnData->mpNext = pBtnData->mpNext;
669 else
670 mpFirstBtn = pBtnData->mpNext;
671 delete pBtnData;
672 return;
675 pPrevBtnData = pBtnData;
676 pBtnData = pBtnData->mpNext;
679 OSL_FAIL( "WizardDialog::RemoveButton() - Button not in list" );
682 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */