Coverage Report

Created: 2025-11-16 09:57

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