Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/window/tabpage.cxx
Line
Count
Source
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/event.hxx>
21
#include <vcl/layout.hxx>
22
#include <vcl/tabpage.hxx>
23
#include <vcl/bitmap.hxx>
24
#include <vcl/salnativewidgets.hxx>
25
#include <vcl/settings.hxx>
26
#include <vcl/toolkit/scrbar.hxx>
27
#include <svdata.hxx>
28
29
void TabPage::ImplInit( vcl::Window* pParent, WinBits nStyle )
30
0
{
31
0
    if ( !(nStyle & WB_NODIALOGCONTROL) )
32
0
        nStyle |= WB_DIALOGCONTROL;
33
34
0
    Window::ImplInit( pParent, nStyle, nullptr );
35
36
0
    bool bHasHoriBar = false;
37
0
    bool bHasVertBar = false;
38
39
0
    Link<ScrollBar*,void> aLink( LINK( this, TabPage, ScrollBarHdl ) );
40
41
0
    if ( nStyle & ( WB_AUTOHSCROLL | WB_AUTOVSCROLL ) )
42
0
    {
43
0
        if ( nStyle & WB_AUTOHSCROLL )
44
0
        {
45
0
            bHasHoriBar = true;
46
0
            m_pHScroll.reset(VclPtr<ScrollBar>::Create(this, (WB_HSCROLL | WB_DRAG)));
47
0
            m_pHScroll->Show();
48
0
            m_pHScroll->SetScrollHdl(aLink);
49
0
        }
50
0
        if ( nStyle &  WB_AUTOVSCROLL )
51
0
        {
52
0
            bHasVertBar = true;
53
0
            m_pVScroll.reset(VclPtr<ScrollBar>::Create(this, (WB_VSCROLL | WB_DRAG)));
54
0
            m_pVScroll->Show();
55
0
            m_pVScroll->SetScrollHdl(aLink);
56
0
        }
57
0
    }
58
59
0
    if ( bHasHoriBar || bHasVertBar )
60
0
    {
61
0
        SetStyle( GetStyle() | WB_CLIPCHILDREN );
62
0
    }
63
64
0
    mnScrWidth = Application::GetSettings().GetStyleSettings().GetScrollBarSize();
65
66
0
    ImplInitSettings();
67
68
    // if the tabpage is drawn (ie filled) by a native widget, make sure all controls will have transparent background
69
    // otherwise they will paint with a wrong background
70
0
    if( IsNativeControlSupported(ControlType::TabBody, ControlPart::Entire) && GetParent() && (GetParent()->GetType() == WindowType::TABCONTROL) )
71
0
        EnableChildTransparentMode();
72
0
}
73
74
void TabPage::ImplInitSettings()
75
0
{
76
0
    vcl::Window* pParent = GetParent();
77
0
    if (pParent && pParent->IsChildTransparentModeEnabled() && !IsControlBackground())
78
0
    {
79
0
        EnableChildTransparentMode();
80
0
        SetParentClipMode( ParentClipMode::NoClip );
81
0
        SetPaintTransparent( true );
82
0
        SetBackground();
83
0
    }
84
0
    else
85
0
    {
86
0
        EnableChildTransparentMode( false );
87
0
        SetParentClipMode();
88
0
        SetPaintTransparent( false );
89
90
0
        if (IsControlBackground() || !pParent)
91
0
            SetBackground( GetControlBackground() );
92
0
        else
93
0
            SetBackground( pParent->GetBackground() );
94
0
    }
95
0
}
96
97
TabPage::TabPage( vcl::Window* pParent, WinBits nStyle ) :
98
0
    Window( WindowType::TABPAGE )
99
0
{
100
0
    ImplInit( pParent, nStyle );
101
0
}
Unexecuted instantiation: TabPage::TabPage(vcl::Window*, long)
Unexecuted instantiation: TabPage::TabPage(vcl::Window*, long)
102
103
TabPage::~TabPage()
104
0
{
105
0
    disposeOnce();
106
0
}
107
108
void TabPage::dispose()
109
0
{
110
0
    m_pVScroll.disposeAndClear();
111
0
    m_pHScroll.disposeAndClear();
112
0
    vcl::Window::dispose();
113
0
}
114
115
void TabPage::StateChanged( StateChangedType nType )
116
0
{
117
0
    Window::StateChanged( nType );
118
119
0
    if ( nType == StateChangedType::InitShow )
120
0
    {
121
0
        if (GetSettings().GetStyleSettings().GetAutoMnemonic())
122
0
            GenerateAutoMnemonicsOnHierarchy(this);
123
        // FIXME: no layouting, workaround some clipping issues
124
0
        ImplAdjustNWFSizes();
125
0
    }
126
0
    else if ( nType == StateChangedType::ControlBackground )
127
0
    {
128
0
        ImplInitSettings();
129
0
        Invalidate();
130
0
    }
131
0
}
132
133
void TabPage::DataChanged( const DataChangedEvent& rDCEvt )
134
0
{
135
0
    Window::DataChanged( rDCEvt );
136
137
0
    if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
138
0
         (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
139
0
    {
140
0
        ImplInitSettings();
141
0
        Invalidate();
142
0
    }
143
0
}
144
145
void TabPage::Paint( vcl::RenderContext& rRenderContext, const tools::Rectangle& )
146
0
{
147
    // draw native tabpage only inside tabcontrols, standalone tabpages look ugly (due to bad dialog design)
148
0
    if( !(IsNativeControlSupported(ControlType::TabBody, ControlPart::Entire) && GetParent() && (GetParent()->GetType() == WindowType::TABCONTROL)) )
149
0
        return;
150
151
0
    const ImplControlValue aControlValue;
152
153
0
    ControlState nState = ControlState::ENABLED;
154
0
    if ( !IsEnabled() )
155
0
        nState &= ~ControlState::ENABLED;
156
0
    if ( HasFocus() )
157
0
        nState |= ControlState::FOCUSED;
158
    // pass the whole window region to NWF as the tab body might be a gradient or bitmap
159
    // that has to be scaled properly, clipping makes sure that we do not paint too much
160
0
    tools::Rectangle aCtrlRegion( Point(), GetOutputSizePixel() );
161
0
    rRenderContext.DrawNativeControl( ControlType::TabBody, ControlPart::Entire, aCtrlRegion, nState,
162
0
            aControlValue, OUString() );
163
0
}
164
165
void TabPage::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags )
166
0
{
167
0
    Point aPos = pDev->LogicToPixel( rPos );
168
0
    Size aSize = GetSizePixel();
169
170
0
    Wallpaper aWallpaper = GetBackground();
171
0
    if ( !aWallpaper.IsBitmap() )
172
0
        ImplInitSettings();
173
174
0
    auto popIt = pDev->ScopedPush();
175
0
    pDev->SetMapMode();
176
0
    pDev->SetLineColor();
177
178
0
    if ( aWallpaper.IsBitmap() )
179
0
        pDev->DrawBitmap( aPos, aSize, aWallpaper.GetBitmap() );
180
0
    else
181
0
    {
182
0
        if( aWallpaper.GetColor() == COL_AUTO )
183
0
            pDev->SetFillColor( GetSettings().GetStyleSettings().GetDialogColor() );
184
0
        else
185
0
            pDev->SetFillColor( aWallpaper.GetColor() );
186
0
        pDev->DrawRect( tools::Rectangle( aPos, aSize ) );
187
0
    }
188
0
}
189
190
Size TabPage::GetOptimalSize() const
191
0
{
192
0
    if (isLayoutEnabled(this))
193
0
        return VclContainer::getLayoutRequisition(*GetWindow(GetWindowType::FirstChild));
194
0
    return getLegacyBestSizeForChildren(*this);
195
0
}
196
197
void TabPage::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation)
198
0
{
199
0
    Window::SetPosSizePixel(rAllocPos, rAllocation);
200
0
    if (isLayoutEnabled(this) && rAllocation.Width() && rAllocation.Height())
201
0
        VclContainer::setLayoutAllocation(*GetWindow(GetWindowType::FirstChild), Point(0, 0), rAllocation);
202
0
}
203
204
void TabPage::SetSizePixel(const Size& rAllocation)
205
0
{
206
0
    Window::SetSizePixel(rAllocation);
207
0
    if (isLayoutEnabled(this) && rAllocation.Width() && rAllocation.Height())
208
0
        VclContainer::setLayoutAllocation(*GetWindow(GetWindowType::FirstChild), Point(0, 0), rAllocation);
209
0
}
210
211
void TabPage::SetPosPixel(const Point& rAllocPos)
212
0
{
213
0
    Window::SetPosPixel(rAllocPos);
214
0
    Size aAllocation(GetOutputSizePixel());
215
0
    if (isLayoutEnabled(this) && aAllocation.Width() && aAllocation.Height())
216
0
    {
217
0
        VclContainer::setLayoutAllocation(*GetWindow(GetWindowType::FirstChild), Point(0, 0), aAllocation);
218
0
    }
219
0
}
220
221
void TabPage::lcl_Scroll( tools::Long nX, tools::Long nY )
222
0
{
223
0
    tools::Long nXScroll = mnScrollPos.X() - nX;
224
0
    tools::Long nYScroll = mnScrollPos.Y() - nY;
225
0
    mnScrollPos = Point( nX, nY );
226
227
0
    tools::Rectangle aScrollableArea( 0, 0, maScrollArea.Width(), maScrollArea.Height() );
228
0
    Scroll(nXScroll, nYScroll, aScrollableArea );
229
    // Manually scroll all children ( except the scrollbars )
230
0
    for ( int index = 0; index < GetChildCount(); ++index )
231
0
    {
232
0
        vcl::Window* pChild = GetChild( index );
233
0
        if ( pChild && pChild != m_pVScroll.get() && pChild != m_pHScroll.get() )
234
0
        {
235
0
            Point aPos = pChild->GetPosPixel();
236
0
            aPos += Point( nXScroll, nYScroll );
237
0
            pChild->SetPosPixel( aPos );
238
0
        }
239
0
    }
240
0
}
241
242
IMPL_LINK( TabPage, ScrollBarHdl, ScrollBar*, pSB, void )
243
0
{
244
0
    sal_uInt16 nPos = static_cast<sal_uInt16>(pSB->GetThumbPos());
245
0
    if( pSB == m_pVScroll.get() )
246
0
        lcl_Scroll(mnScrollPos.X(), nPos );
247
0
    else if( pSB == m_pHScroll.get() )
248
0
        lcl_Scroll(nPos, mnScrollPos.Y() );
249
0
}
250
251
void TabPage::SetScrollTop( tools::Long nTop )
252
0
{
253
0
    Point aOld = mnScrollPos;
254
0
    lcl_Scroll( mnScrollPos.X() , mnScrollPos.Y() - nTop );
255
0
    if( m_pHScroll )
256
0
        m_pHScroll->SetThumbPos( 0 );
257
    // new pos is 0,0
258
0
    mnScrollPos = aOld;
259
0
}
260
void TabPage::SetScrollLeft( tools::Long nLeft )
261
0
{
262
0
    Point aOld = mnScrollPos;
263
0
    lcl_Scroll( mnScrollPos.X() - nLeft , mnScrollPos.Y() );
264
0
    if( m_pVScroll )
265
0
        m_pVScroll->SetThumbPos( 0 );
266
    // new pos is 0,0
267
0
    mnScrollPos = aOld;
268
0
}
269
270
void TabPage::SetScrollWidth( tools::Long nWidth )
271
0
{
272
0
    maScrollArea.setWidth( nWidth );
273
0
    ResetScrollBars();
274
0
}
275
276
void TabPage::SetScrollHeight( tools::Long nHeight )
277
0
{
278
0
    maScrollArea.setHeight( nHeight );
279
0
    ResetScrollBars();
280
0
}
281
282
void TabPage::Resize()
283
0
{
284
0
    ResetScrollBars();
285
0
}
286
287
void TabPage::ResetScrollBars()
288
0
{
289
0
    Size aOutSz = GetOutputSizePixel();
290
291
0
    Point aVPos( aOutSz.Width() - mnScrWidth, 0 );
292
0
    Point aHPos( 0, aOutSz.Height() - mnScrWidth );
293
294
0
    if( m_pVScroll )
295
0
    {
296
0
        m_pVScroll->SetPosSizePixel( aVPos, Size( mnScrWidth,  GetSizePixel().Height() - mnScrWidth ) );
297
0
        m_pVScroll->SetRangeMax( maScrollArea.Height() + mnScrWidth );
298
0
        m_pVScroll->SetVisibleSize( GetSizePixel().Height() );
299
0
    }
300
301
0
    if( m_pHScroll )
302
0
    {
303
0
        m_pHScroll->SetPosSizePixel( aHPos, Size(  GetSizePixel().Width() - mnScrWidth, mnScrWidth ) );
304
0
        m_pHScroll->SetRangeMax( maScrollArea.Width() + mnScrWidth  );
305
0
        m_pHScroll->SetVisibleSize( GetSizePixel().Width() );
306
0
    }
307
0
}
308
309
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */