Coverage Report

Created: 2025-12-31 10:39

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