Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/gallery2/galctrl.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 <config_features.h>
21
22
#include <sfx2/viewfrm.hxx>
23
#include <sfx2/dispatch.hxx>
24
#include <sfx2/sfxsids.hrc>
25
#include <tools/mapunit.hxx>
26
#include <avmedia/mediaplayer.hxx>
27
#include <galbrws1.hxx>
28
#include <svx/galtheme.hxx>
29
#include <svx/galmisc.hxx>
30
#include <svx/galctrl.hxx>
31
#include <galobj.hxx>
32
#include <avmedia/mediawindow.hxx>
33
#include <vcl/event.hxx>
34
#include <vcl/commandevent.hxx>
35
#include <vcl/graphicfilter.hxx>
36
#include <vcl/svapp.hxx>
37
#include <vcl/themecolors.hxx>
38
#include <bitmaps.hlst>
39
#include <svl/itemset.hxx>
40
41
GalleryPreview::GalleryPreview(GalleryBrowser* pParent, std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
42
0
    : mxScrolledWindow(std::move(xScrolledWindow))
43
0
    , mpParent(pParent)
44
0
    , mpTheme(nullptr)
45
0
{
46
0
}
47
48
void GalleryPreview::Show()
49
0
{
50
0
    mxScrolledWindow->show();
51
0
    weld::CustomWidgetController::Show();
52
0
}
53
54
void GalleryPreview::Hide()
55
0
{
56
0
    weld::CustomWidgetController::Hide();
57
0
    mxScrolledWindow->hide();
58
0
}
59
60
GalleryPreview::~GalleryPreview()
61
0
{
62
0
}
63
64
void GalleryPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea)
65
0
{
66
0
    CustomWidgetController::SetDrawingArea(pDrawingArea);
67
0
    Size aSize = pDrawingArea->get_ref_device().LogicToPixel(Size(70, 88), MapMode(MapUnit::MapAppFont));
68
0
    pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
69
0
    SetOutputSizePixel(aSize);
70
71
0
    mxDragDropTargetHelper.reset(new GalleryDragDrop(mpParent, pDrawingArea->get_drop_target()));
72
0
}
73
74
namespace
75
{
76
    bool ImplGetGraphicCenterRect(const weld::CustomWidgetController& rWidget, const Graphic& rGraphic, tools::Rectangle& rResultRect)
77
0
    {
78
0
        const Size  aWinSize(rWidget.GetOutputSizePixel());
79
0
        Size        aNewSize(rWidget.GetDrawingArea()->get_ref_device().LogicToPixel(rGraphic.GetPrefSize(), rGraphic.GetPrefMapMode()));
80
0
        bool        bRet = false;
81
82
0
        if( aNewSize.Width() && aNewSize.Height() )
83
0
        {
84
            // scale to fit window
85
0
            const double fGrfWH = static_cast<double>(aNewSize.Width()) / aNewSize.Height();
86
0
            const double fWinWH = static_cast<double>(aWinSize.Width()) / aWinSize.Height();
87
88
0
            if ( fGrfWH < fWinWH )
89
0
            {
90
0
                aNewSize.setWidth( static_cast<tools::Long>( aWinSize.Height() * fGrfWH ) );
91
0
                aNewSize.setHeight( aWinSize.Height() );
92
0
            }
93
0
            else
94
0
            {
95
0
                aNewSize.setWidth( aWinSize.Width() );
96
0
                aNewSize.setHeight( static_cast<tools::Long>( aWinSize.Width() / fGrfWH) );
97
0
            }
98
99
0
            const Point aNewPos( ( aWinSize.Width()  - aNewSize.Width() ) >> 1,
100
0
                                 ( aWinSize.Height() - aNewSize.Height() ) >> 1 );
101
102
0
            rResultRect = tools::Rectangle( aNewPos, aNewSize );
103
0
            bRet = true;
104
0
        }
105
106
0
        return bRet;
107
0
    }
108
}
109
110
bool GalleryPreview::ImplGetGraphicCenterRect( const Graphic& rGraphic, tools::Rectangle& rResultRect ) const
111
0
{
112
0
    return ::ImplGetGraphicCenterRect(*this, rGraphic, rResultRect);
113
0
}
114
115
void GalleryPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& /*rRect*/)
116
0
{
117
0
    rRenderContext.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetWindowColor()));
118
0
    rRenderContext.Erase();
119
120
0
    if (ImplGetGraphicCenterRect(m_aGraphicObj.GetGraphic(), m_aPreviewRect))
121
0
    {
122
0
        const Point aPos( m_aPreviewRect.TopLeft() );
123
0
        const Size  aSize( m_aPreviewRect.GetSize() );
124
125
0
        if( m_aGraphicObj.IsAnimated() )
126
0
            m_aGraphicObj.StartAnimation(rRenderContext, aPos, aSize);
127
0
        else
128
0
            m_aGraphicObj.Draw(rRenderContext, aPos, aSize);
129
0
    }
130
0
}
131
132
bool GalleryPreview::MouseButtonDown(const MouseEvent& rMEvt)
133
0
{
134
0
    if (mpTheme && (rMEvt.GetClicks() == 2))
135
0
        mpParent->TogglePreview();
136
0
    return true;
137
0
}
138
139
bool GalleryPreview::Command(const CommandEvent& rCEvt)
140
0
{
141
0
    if (mpTheme && (rCEvt.GetCommand() == CommandEventId::ContextMenu))
142
0
    {
143
0
        mpParent->ShowContextMenu(rCEvt);
144
0
        return true;
145
0
    }
146
0
    return false;
147
0
}
148
149
bool GalleryPreview::KeyInput(const KeyEvent& rKEvt)
150
0
{
151
0
    if(mpTheme)
152
0
    {
153
0
        GalleryBrowser* pBrowser = mpParent;
154
155
0
        switch( rKEvt.GetKeyCode().GetCode() )
156
0
        {
157
0
            case KEY_BACKSPACE:
158
0
                pBrowser->TogglePreview();
159
0
            break;
160
161
0
            case KEY_HOME:
162
0
                pBrowser->Travel( GalleryBrowserTravel::First );
163
0
            break;
164
165
0
            case KEY_END:
166
0
                pBrowser->Travel( GalleryBrowserTravel::Last );
167
0
            break;
168
169
0
            case KEY_LEFT:
170
0
            case KEY_UP:
171
0
                pBrowser->Travel( GalleryBrowserTravel::Previous );
172
0
            break;
173
174
0
            case KEY_RIGHT:
175
0
            case KEY_DOWN:
176
0
                pBrowser->Travel( GalleryBrowserTravel::Next );
177
0
            break;
178
179
0
            default:
180
0
            {
181
0
                if (!pBrowser->KeyInput(rKEvt))
182
0
                    return false;
183
0
            }
184
0
            break;
185
0
        }
186
187
0
        return true;
188
0
    }
189
0
    return false;
190
0
}
191
192
bool GalleryPreview::StartDrag()
193
0
{
194
0
    if (mpTheme)
195
0
        return mpParent->StartDrag();
196
0
    return true;
197
0
}
198
199
void GalleryPreview::PreviewMedia( const INetURLObject& rURL )
200
0
{
201
0
#if HAVE_FEATURE_AVMEDIA
202
0
    if (rURL.GetProtocol() == INetProtocol::NotValid)
203
0
        return;
204
205
0
    ::avmedia::MediaFloater* pFloater = avmedia::getMediaFloater();
206
207
0
    if (!pFloater)
208
0
    {
209
0
        if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
210
0
            pViewFrm->GetBindings().GetDispatcher()->Execute( SID_AVMEDIA_PLAYER, SfxCallMode::SYNCHRON );
211
0
        pFloater = avmedia::getMediaFloater();
212
0
    }
213
214
0
    if (pFloater)
215
0
        pFloater->setURL( rURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ), u""_ustr, true );
216
#else
217
    (void) rURL;
218
#endif
219
0
}
220
221
DialogGalleryPreview::DialogGalleryPreview()
222
0
{
223
0
}
224
225
void DialogGalleryPreview::SetDrawingArea(weld::DrawingArea* pDrawingArea)
226
0
{
227
0
    CustomWidgetController::SetDrawingArea(pDrawingArea);
228
0
    Size aSize(pDrawingArea->get_ref_device().LogicToPixel(Size(70, 88), MapMode(MapUnit::MapAppFont)));
229
0
    pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
230
0
}
231
232
bool DialogGalleryPreview::SetGraphic( const INetURLObject& _aURL )
233
0
{
234
0
    bool bRet = true;
235
0
    Graphic aGraphic;
236
0
#if HAVE_FEATURE_AVMEDIA
237
0
    if( ::avmedia::MediaWindow::isMediaURL( _aURL.GetMainURL( INetURLObject::DecodeMechanism::Unambiguous ), u""_ustr ) )
238
0
    {
239
0
        aGraphic = Bitmap(RID_SVXBMP_GALLERY_MEDIA);
240
0
    }
241
0
    else
242
0
#endif
243
0
    {
244
0
        GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
245
0
        GalleryProgress aProgress( &rFilter );
246
0
        if( rFilter.ImportGraphic( aGraphic, _aURL ) )
247
0
            bRet = false;
248
0
    }
249
250
0
    SetGraphic( aGraphic );
251
0
    Invalidate();
252
0
    return bRet;
253
0
}
254
255
bool DialogGalleryPreview::ImplGetGraphicCenterRect( const Graphic& rGraphic, tools::Rectangle& rResultRect ) const
256
0
{
257
0
    return ::ImplGetGraphicCenterRect(*this, rGraphic, rResultRect);
258
0
}
259
260
void DialogGalleryPreview::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
261
0
{
262
0
    rRenderContext.SetBackground(Wallpaper(Application::GetSettings().GetStyleSettings().GetWindowColor()));
263
264
0
    if (ImplGetGraphicCenterRect(maGraphicObj.GetGraphic(), maPreviewRect))
265
0
    {
266
0
        const Point aPos( maPreviewRect.TopLeft() );
267
0
        const Size  aSize( maPreviewRect.GetSize() );
268
269
0
        if( maGraphicObj.IsAnimated() )
270
0
            maGraphicObj.StartAnimation(rRenderContext, aPos, aSize);
271
0
        else
272
0
            maGraphicObj.Draw(rRenderContext, aPos, aSize);
273
0
    }
274
0
}
275
276
void GalleryIconView::drawTransparenceBackground(vcl::RenderContext& rOut, const Point& rPos, const Size& rSize)
277
0
{
278
    // draw checkered background
279
0
    static const sal_uInt32 nLen(8);
280
0
    static Color aW(COL_WHITE);
281
0
    static Color aG(0xef, 0xef, 0xef);
282
0
    static bool bCheckedAppearanceMode = false;
283
0
    static bool bIsDarkMode = false;
284
285
0
    if (!bCheckedAppearanceMode)
286
0
    {
287
0
        bIsDarkMode = MiscSettings::GetAppColorMode() == AppearanceMode::DARK
288
0
                      || (MiscSettings::GetAppColorMode() == AppearanceMode::AUTO
289
0
                          && MiscSettings::GetUseDarkMode());
290
0
        bCheckedAppearanceMode = true;
291
0
    }
292
293
0
    if (bIsDarkMode)
294
0
    {
295
0
        aW = COL_BLACK;
296
0
        aW.SetAlpha(90); // 90 looks good, no fancy logic otherwise to use 90 here.
297
0
        aG = COL_TRANSPARENT;
298
0
    }
299
300
0
    rOut.DrawCheckered(rPos, rSize, nLen, aW, aG);
301
0
}
302
303
GalleryIconView::GalleryIconView(GalleryBrowser* pParent, std::unique_ptr<weld::ScrolledWindow> xScrolledWindow)
304
0
    : ValueSet(std::move(xScrolledWindow))
305
0
    , mpParent(pParent)
306
0
    , mpTheme(nullptr)
307
0
{
308
0
}
309
310
GalleryIconView::~GalleryIconView()
311
0
{
312
0
}
313
314
void GalleryIconView::SetDrawingArea(weld::DrawingArea* pDrawingArea)
315
0
{
316
0
    ValueSet::SetDrawingArea(pDrawingArea);
317
318
0
    SetStyle(GetStyle() | WB_TABSTOP | WB_3DLOOK | WB_BORDER | WB_ITEMBORDER | WB_DOUBLEBORDER | WB_VSCROLL | WB_FLATVALUESET);
319
0
    EnableFullItemMode( false );
320
321
0
    SetExtraSpacing( 2 );
322
0
    SetItemWidth( S_THUMB + 6 );
323
0
    SetItemHeight( S_THUMB + 6 );
324
325
0
    mxDragDropTargetHelper.reset(new GalleryDragDrop(mpParent, pDrawingArea->get_drop_target()));
326
0
}
327
328
void GalleryIconView::UserDraw(const UserDrawEvent& rUDEvt)
329
0
{
330
0
    const sal_uInt16 nId = rUDEvt.GetItemId();
331
332
0
    if (!nId || !mpTheme)
333
0
        return;
334
335
0
    const tools::Rectangle& rRect = rUDEvt.GetRect();
336
0
    const Size aSize(rRect.GetWidth(), rRect.GetHeight());
337
0
    Bitmap aBitmap;
338
0
    Size aPreparedSize;
339
0
    OUString aItemTextTitle;
340
0
    OUString aItemTextPath;
341
342
0
    mpTheme->GetPreviewBitmapAndStrings(nId - 1, aBitmap, aPreparedSize, aItemTextTitle, aItemTextPath);
343
344
0
    bool bNeedToCreate(aBitmap.IsEmpty());
345
346
0
    if (!bNeedToCreate && aItemTextTitle.isEmpty())
347
0
    {
348
0
        bNeedToCreate = true;
349
0
    }
350
351
0
    if (!bNeedToCreate && aPreparedSize != aSize)
352
0
    {
353
0
        bNeedToCreate = true;
354
0
    }
355
356
0
    if (bNeedToCreate)
357
0
    {
358
0
        std::unique_ptr<SgaObject> pObj = mpTheme->AcquireObject(nId - 1);
359
360
0
        if(pObj)
361
0
        {
362
0
            aBitmap = pObj->createPreviewBitmap(aSize);
363
0
            aItemTextTitle = GalleryBrowser::GetItemText(*pObj, GalleryItemFlags::Title);
364
365
0
            mpTheme->SetPreviewBitmapAndStrings(nId - 1, aBitmap, aSize, aItemTextTitle, aItemTextPath);
366
0
        }
367
0
    }
368
369
0
    if (!aBitmap.IsEmpty())
370
0
    {
371
0
        const Size aBitmapExSizePixel(aBitmap.GetSizePixel());
372
0
        const Point aPos(
373
0
            ((aSize.Width() - aBitmapExSizePixel.Width()) >> 1) + rRect.Left(),
374
0
            ((aSize.Height() - aBitmapExSizePixel.Height()) >> 1) + rRect.Top());
375
0
        OutputDevice* pDev = rUDEvt.GetRenderContext();
376
377
0
        if(aBitmap.HasAlpha())
378
0
        {
379
            // draw checkered background for full rectangle.
380
0
            GalleryIconView::drawTransparenceBackground(*pDev, rRect.TopLeft(), rRect.GetSize());
381
0
        }
382
383
0
        pDev->DrawBitmap(aPos, aBitmap);
384
0
    }
385
386
0
    SetItemText(nId, aItemTextTitle);
387
0
}
388
389
bool GalleryIconView::MouseButtonDown(const MouseEvent& rMEvt)
390
0
{
391
0
    bool bRet = ValueSet::MouseButtonDown(rMEvt);
392
393
0
    if (rMEvt.GetClicks() == 2)
394
0
        mpParent->TogglePreview();
395
396
0
    return bRet;
397
0
}
398
399
bool GalleryIconView::Command(const CommandEvent& rCEvt)
400
0
{
401
0
    bool bRet = ValueSet::Command(rCEvt);
402
403
0
    if (!bRet && rCEvt.GetCommand() == CommandEventId::ContextMenu)
404
0
    {
405
0
        bRet = mpParent->ShowContextMenu(rCEvt);
406
0
    }
407
408
0
    return bRet;
409
0
}
410
411
bool GalleryIconView::KeyInput(const KeyEvent& rKEvt)
412
0
{
413
0
    if (!mpTheme || !mpParent->KeyInput(rKEvt))
414
0
        return ValueSet::KeyInput(rKEvt);
415
0
    return true;
416
0
}
417
418
bool GalleryIconView::StartDrag()
419
0
{
420
0
    Select();
421
0
    return mpParent->StartDrag();
422
0
}
423
424
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */