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 
ImplInitTabDialogData()26 void TabDialog::ImplInitTabDialogData()
27 {
28     mpFixedLine     = nullptr;
29     mbPosControls   = true;
30 }
31 
ImplPosControls()32 void TabDialog::ImplPosControls()
33 {
34     if (isLayoutEnabled())
35         return;
36 
37     Size        aCtrlSize( IMPL_MINSIZE_BUTTON_WIDTH, IMPL_MINSIZE_BUTTON_HEIGHT );
38     long        nDownCtrl = 0;
39     long        nOffY = 0;
40     vcl::Window*     pTabControl = nullptr;
41 
42     vcl::Window* pChild = GetWindow( GetWindowType::FirstChild );
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 
104         vcl::Window* pChild2 = GetWindow( GetWindowType::FirstChild );
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 )
146             mpFixedLine = VclPtr<FixedLine>::Create( this );
147         mpFixedLine->SetPosSizePixel( Point( 0, nOffY ),
148                                       Size( aDlgSize.Width(), 2 ) );
149         mpFixedLine->Show();
150     }
151 
152     mbPosControls = false;
153 }
154 
TabDialog(vcl::Window * pParent,WinBits nStyle)155 TabDialog::TabDialog( vcl::Window* pParent, WinBits nStyle ) :
156     Dialog( WindowType::TABDIALOG )
157 {
158     ImplInitTabDialogData();
159     ImplInitDialog( pParent, nStyle );
160 }
161 
~TabDialog()162 TabDialog::~TabDialog()
163 {
164     disposeOnce();
165 }
166 
dispose()167 void TabDialog::dispose()
168 {
169     mpFixedLine.disposeAndClear();
170     Dialog::dispose();
171 }
172 
StateChanged(StateChangedType nType)173 void TabDialog::StateChanged( StateChangedType nType )
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 
184 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
185