LibreOffice Module vcl (master)  1
tabdlg.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <vcl/fixed.hxx>
21 #include <vcl/layout.hxx>
22 #include <vcl/tabctrl.hxx>
23 #include <vcl/toolkit/tabdlg.hxx>
24 #include <vcl/tabpage.hxx>
25 
27 {
28  mpFixedLine = nullptr;
29  mbPosControls = true;
30 }
31 
33 {
34  if (isLayoutEnabled())
35  return;
36 
38  long nDownCtrl = 0;
39  long nOffY = 0;
40  vcl::Window* pTabControl = nullptr;
41 
43  while ( pChild )
44  {
45  if ( pChild->IsVisible() )
46  {
47  if (pChild->GetType() == WindowType::TABCONTROL || isContainerWindow(*pChild))
48  pTabControl = pChild;
49  else if ( pTabControl )
50  {
51  Size aOptimalSize(pChild->get_preferred_size());
52  long nTxtWidth = aOptimalSize.Width();
53  if ( nTxtWidth > aCtrlSize.Width() )
54  aCtrlSize.setWidth( nTxtWidth );
55  long nTxtHeight = aOptimalSize.Height();
56  if ( nTxtHeight > aCtrlSize.Height() )
57  aCtrlSize.setHeight( nTxtHeight );
58  nDownCtrl++;
59  }
60  else
61  {
62  long nHeight = pChild->GetSizePixel().Height();
63  if ( nHeight > nOffY )
64  nOffY = nHeight;
65  }
66  }
67 
68  pChild = pChild->GetWindow( GetWindowType::Next );
69  }
70 
71  // do we have a TabControl ?
72  if ( pTabControl )
73  {
74  // adapt offset for other controls by an extra distance
75  if ( nOffY )
76  nOffY += IMPL_DIALOG_BAR_OFFSET*2 + 2;
77 
78  Point aTabOffset( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+nOffY );
79 
80  if (isContainerWindow(*pTabControl))
81  pTabControl->SetSizePixel(pTabControl->get_preferred_size());
82 
83  Size aTabSize = pTabControl->GetSizePixel();
84 
85  Size aDlgSize( aTabSize.Width() + IMPL_DIALOG_OFFSET*2,
86  aTabSize.Height() + IMPL_DIALOG_OFFSET*2 + nOffY );
87 
88  // adapt positioning
89  pTabControl->SetPosPixel( aTabOffset );
90 
91  // position all other Children
92  bool bTabCtrl = false;
93  int nLines = 0;
94  long nX;
95  long nY = aDlgSize.Height();
96  long nTopX = IMPL_DIALOG_OFFSET;
97 
98  // all buttons are right aligned under Windows 95
99  nX = IMPL_DIALOG_OFFSET;
100  long nCtrlBarWidth = ((aCtrlSize.Width()+IMPL_DIALOG_OFFSET)*nDownCtrl)-IMPL_DIALOG_OFFSET;
101  if ( nCtrlBarWidth <= aTabSize.Width() )
102  nX = aTabSize.Width() - nCtrlBarWidth + IMPL_DIALOG_OFFSET;
103 
105  while ( pChild2 )
106  {
107  if ( pChild2->IsVisible() )
108  {
109  if ( pChild2 == pTabControl )
110  bTabCtrl = true;
111  else if ( bTabCtrl )
112  {
113  if ( !nLines )
114  nLines = 1;
115 
116  if ( nX+aCtrlSize.Width()-IMPL_DIALOG_OFFSET > aTabSize.Width() )
117  {
118  nY += aCtrlSize.Height()+IMPL_DIALOG_OFFSET;
119  nX = IMPL_DIALOG_OFFSET;
120  nLines++;
121  }
122 
123  pChild2->SetPosSizePixel( Point( nX, nY ), aCtrlSize );
124  nX += aCtrlSize.Width()+IMPL_DIALOG_OFFSET;
125  }
126  else
127  {
128  Size aChildSize = pChild2->GetSizePixel();
129  pChild2->SetPosPixel( Point( nTopX, (nOffY-aChildSize.Height())/2 ) );
130  nTopX += aChildSize.Width()+2;
131  }
132  }
133 
134  pChild2 = pChild2->GetWindow( GetWindowType::Next );
135  }
136 
137  aDlgSize.AdjustHeight(nLines * (aCtrlSize.Height()+IMPL_DIALOG_OFFSET) );
138  SetOutputSizePixel( aDlgSize );
139  }
140 
141  // store offset
142  if ( nOffY )
143  {
144  Size aDlgSize = GetOutputSizePixel();
145  if ( !mpFixedLine )
147  mpFixedLine->SetPosSizePixel( Point( 0, nOffY ),
148  Size( aDlgSize.Width(), 2 ) );
149  mpFixedLine->Show();
150  }
151 
152  mbPosControls = false;
153 }
154 
157 {
159  ImplInit( pParent, nStyle );
160 }
161 
163 {
164  disposeOnce();
165 }
166 
168 {
170  Dialog::dispose();
171 }
172 
174 {
175  if ( nType == StateChangedType::InitShow )
176  {
177  // Calculate the Layout only for the initialized state
178  if ( mbPosControls )
179  ImplPosControls();
180  }
181  Dialog::StateChanged( nType );
182 }
183 
185 {
186  if (!pCurrent)
187  {
188  return nullptr;
189  }
190 
191  if (pCurrent->GetType() == WindowType::TABCONTROL)
192  {
193  return pCurrent;
194  }
195 
196  vcl::Window* pChild = pCurrent->GetWindow(GetWindowType::FirstChild);
197 
198  while (pChild)
199  {
200 
201  vcl::Window* pInorderChild = findTabControl(pChild);
202 
203  if (pInorderChild)
204  {
205  return pInorderChild;
206  }
207 
208  pChild = pChild->GetWindow(GetWindowType::Next);
209  }
210 
211  return nullptr;
212 }
213 
214 std::vector<OString> TabDialog::getAllPageUIXMLDescriptions() const
215 {
216  std::vector<OString> aRetval;
217 
218  const TabControl* pTabCtrl = dynamic_cast<TabControl*>(findTabControl(const_cast<TabDialog*>(this)));
219 
220  if (pTabCtrl)
221  {
222  for (sal_uInt16 a(0); a < pTabCtrl->GetPageCount(); a++)
223  {
224  const sal_uInt16 nPageId(pTabCtrl->GetPageId(a));
225 
226  if (TAB_PAGE_NOTFOUND != nPageId)
227  {
228  TabPage* pCandidate = pTabCtrl->GetTabPage(nPageId);
229 
230  if (pCandidate)
231  {
232  OString aNewName(pCandidate->getUIFile());
233 
234  if (!aNewName.isEmpty())
235  {
236  // we have to check for double entries, this may happen e.g.
237  // in the HeaderFooterDialog which has two times the same
238  // tabPage added. Add the PageID as hint to the name, separated
239  // by a token (using "|" here). Do not do this for 1st occurrence,
240  // that is used for detection and is not necessary.
241  // Use the UIXMLDescription without trailing '.ui', with one trailing '/'
242  bool bAlreadyAdded(false);
243 
244  for (auto const& elem : aRetval)
245  {
246  bAlreadyAdded = (elem == aNewName);
247  if (bAlreadyAdded)
248  break;
249  }
250 
251  if (bAlreadyAdded)
252  {
253  // add the PageId to be able to detect the correct tabPage in
254  // selectPageByUIXMLDescription below
255  aNewName += "|" + OString::number(nPageId);
256  }
257 
258  aRetval.push_back(aNewName);
259  }
260  }
261  }
262  }
263  }
264 
265  return aRetval;
266 }
267 
268 bool TabDialog::selectPageByUIXMLDescription(const OString& rUIXMLDescription)
269 {
270  TabControl* pTabCtrl = dynamic_cast<TabControl*>(findTabControl(this));
271 
272  if (pTabCtrl)
273  {
274  sal_uInt32 nTargetPageId(0);
275  OString aTargetName(rUIXMLDescription);
276  const sal_Int32 nIndexOfSeparator(rUIXMLDescription.indexOf("|"));
277 
278  if (-1 != nIndexOfSeparator)
279  {
280  // more than one tabPage with that UXMLDescription is added to this dialog,
281  // see getAllPageUIXMLDescriptions() above. Extract target PageId and
282  // strip the UXMLDescription name for comparison
283  nTargetPageId = rUIXMLDescription.copy(nIndexOfSeparator + 1).toUInt32();
284  aTargetName = rUIXMLDescription.copy(0, nIndexOfSeparator);
285  }
286 
287  for (sal_uInt16 a(0); a < pTabCtrl->GetPageCount(); a++)
288  {
289  const sal_uInt16 nPageId(pTabCtrl->GetPageId(a));
290 
291  if (TAB_PAGE_NOTFOUND != nPageId)
292  {
293  TabPage* pCandidate = pTabCtrl->GetTabPage(nPageId);
294 
295  if (pCandidate)
296  {
297  if (pCandidate->getUIFile() == aTargetName)
298  {
299  if (nTargetPageId)
300  {
301  // when multiple versions may exist, name is not sufficient. Also
302  // check for the given PageId to select the correct tabPage
303  // for cases where the same TabPage is used more than once
304  // in a tabDialog (e.g. HeaderFooterDialog)
305  if (nTargetPageId == nPageId)
306  {
307  pTabCtrl->SelectTabPage(nPageId);
308  return true;
309  }
310  }
311  else
312  {
313  // select that tabPage
314  pTabCtrl->SelectTabPage(nPageId);
315  return true;
316  }
317  }
318  }
319  }
320  }
321  }
322 
323  return false;
324 }
325 
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
SAL_DLLPRIVATE void ImplInitTabDialogData()
Definition: tabdlg.cxx:26
TabDialog(vcl::Window *pParent, WinBits nStyle)
Definition: tabdlg.cxx:155
virtual void StateChanged(StateChangedType nStateChange) override
Definition: tabdlg.cxx:173
long Height() const
void SelectTabPage(sal_uInt16 nPageId)
Definition: tabctrl.cxx:1871
virtual ~TabDialog() override
Definition: tabdlg.cxx:162
void disposeAndClear()
Definition: vclptr.hxx:200
virtual Size GetSizePixel() const
Definition: window.cxx:2364
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1256
TabPage * GetTabPage(sal_uInt16 nPageId) const
Definition: tabctrl.cxx:1919
#define IMPL_DIALOG_BAR_OFFSET
Definition: window.hxx:397
SAL_DLLPRIVATE void ImplPosControls()
Definition: tabdlg.cxx:32
StateChangedType
Definition: window.hxx:311
sal_Int64 WinBits
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: dialog.cxx:608
sal_uInt16 nPageId
virtual bool selectPageByUIXMLDescription(const OString &rUIXMLDescription) override
Definition: tabdlg.cxx:268
virtual void SetOutputSizePixel(const Size &rNewSize)
Definition: window2.cxx:1268
sal_uInt16 GetPageCount() const
Definition: tabctrl.cxx:1788
bool isContainerWindow(const vcl::Window &rWindow)
Definition: layout.hxx:804
virtual void dispose() override
This is intended to be used to clear any locally held references to other Window-subclass objects...
Definition: tabdlg.cxx:167
static vcl::Window * findTabControl(vcl::Window *pCurrent)
Definition: tabdlg.cxx:184
Size get_preferred_size() const
Definition: window2.cxx:1633
#define IMPL_MINSIZE_BUTTON_HEIGHT
Definition: window.hxx:390
Size GetOutputSizePixel() const
Definition: outdev.hxx:441
virtual void SetPosSizePixel(const Point &rNewPos, const Size &rNewSize)
Definition: window2.cxx:1262
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
#define TAB_PAGE_NOTFOUND
Definition: tabctrl.hxx:37
virtual void StateChanged(StateChangedType nStateChange) override
Definition: dialog.cxx:734
virtual std::vector< OString > getAllPageUIXMLDescriptions() const override
Definition: tabdlg.cxx:214
WindowType
bool IsVisible() const
Definition: window2.cxx:1096
sal_uInt16 GetPageId(sal_uInt16 nPos) const
Definition: tabctrl.cxx:1793
VclPtr< FixedLine > mpFixedLine
Definition: tabdlg.hxx:31
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
void ImplInit(vcl::Window *pParent, WinBits nStyle, InitFlag eFlag=InitFlag::Default)
Definition: dialog.cxx:431
WindowType GetType() const
Definition: window2.cxx:968
#define IMPL_MINSIZE_BUTTON_WIDTH
Definition: window.hxx:389
bool mbPosControls
Definition: tabdlg.hxx:32
void setWidth(long nWidth)
virtual void SetPosPixel(const Point &rNewPos)
Definition: window2.cxx:1251
bool isLayoutEnabled() const
Definition: syswin.cxx:1056
OString getUIFile() const
Definition: builder.hxx:491
#define IMPL_DIALOG_OFFSET
Definition: window.hxx:396
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2150
void setHeight(long nHeight)