Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/dialog/_contdlg.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 <sal/config.h>
21
22
#include <tools/helpers.hxx>
23
#include <svl/eitem.hxx>
24
#include <sfx2/ctrlitem.hxx>
25
#include <sfx2/dispatch.hxx>
26
#include <sfx2/module.hxx>
27
#include <o3tl/untaint.hxx>
28
#include <unotools/localedatawrapper.hxx>
29
30
#include <svx/svxids.hrc>
31
#include <svx/contdlg.hxx>
32
#include "contimp.hxx"
33
#include "contwnd.hxx"
34
#include <svx/svdopath.hxx>
35
#include <vcl/alpha.hxx>
36
#include <vcl/animate/Animation.hxx>
37
#include <vcl/animate/AnimationFrame.hxx>
38
#include <vcl/svapp.hxx>
39
#include <vcl/settings.hxx>
40
#include <vcl/virdev.hxx>
41
#include "dlgunit.hxx"
42
#include <vcl/weld/Builder.hxx>
43
#include <vcl/weld/Dialog.hxx>
44
#include <vcl/weld/MessageDialog.hxx>
45
#include <vcl/weld/weld.hxx>
46
47
SFX_IMPL_MODELESSDIALOGCONTOLLER_WITHID(SvxContourDlgChildWindow, SID_CONTOUR_DLG);
48
49
SvxContourDlgItem::SvxContourDlgItem( SvxSuperContourDlg& rContourDlg, SfxBindings& rBindings ) :
50
0
            SfxControllerItem   ( SID_CONTOUR_EXEC, rBindings ),
51
0
            rDlg                ( rContourDlg )
52
0
{
53
0
}
54
55
void SvxContourDlgItem::StateChangedAtToolBoxControl( sal_uInt16 nSID, SfxItemState /*eState*/, const SfxPoolItem* pItem )
56
0
{
57
0
    if ( pItem && ( SID_CONTOUR_EXEC == nSID ) )
58
0
    {
59
0
        const SfxBoolItem* pStateItem = dynamic_cast<const SfxBoolItem*>( pItem  );
60
0
        assert(pStateItem); //SfxBoolItem expected
61
0
        if (pStateItem)
62
0
            rDlg.SetExecState(!pStateItem->GetValue());
63
0
    }
64
0
}
65
66
SvxContourDlgChildWindow::SvxContourDlgChildWindow(vcl::Window* _pParent, sal_uInt16 nId,
67
                                                   SfxBindings* pBindings, SfxChildWinInfo const * pInfo)
68
0
    : SfxChildWindow( _pParent, nId )
69
0
{
70
0
    SetController(std::make_shared<SvxContourDlg>(pBindings, this, _pParent->GetFrameWeld()));
71
0
    SvxContourDlg* pDlg = static_cast<SvxContourDlg*>(GetController().get());
72
0
    pDlg->Initialize( pInfo );
73
0
}
74
75
SvxContourDlg::SvxContourDlg(SfxBindings* _pBindings, SfxChildWindow* pCW,
76
                             weld::Window* _pParent)
77
0
    : SfxModelessDialogController(_pBindings, pCW, _pParent, u"svx/ui/floatingcontour.ui"_ustr, u"FloatingContour"_ustr)
78
0
    , m_xImpl(std::make_unique<SvxSuperContourDlg>(*m_xBuilder, *m_xDialog, _pBindings))
79
0
{
80
0
}
81
82
SvxContourDlg::~SvxContourDlg()
83
0
{
84
0
}
85
86
tools::PolyPolygon SvxContourDlg::CreateAutoContour( const Graphic& rGraphic,
87
                                                     const tools::Rectangle* pRect )
88
0
{
89
0
    Bitmap  aBmp;
90
0
    bool bContourEdgeDetect = false;
91
92
0
    if ( rGraphic.GetType() == GraphicType::Bitmap )
93
0
    {
94
0
        if( rGraphic.IsAnimated() )
95
0
        {
96
0
            ScopedVclPtrInstance< VirtualDevice > pVDev;
97
0
            MapMode             aTransMap;
98
0
            const Animation     aAnim( rGraphic.GetAnimation() );
99
0
            const Size&         rSizePix = aAnim.GetDisplaySizePixel();
100
0
            const sal_uInt16        nCount = aAnim.Count();
101
102
0
            if ( pVDev->SetOutputSizePixel( rSizePix ) )
103
0
            {
104
0
                pVDev->SetLineColor( COL_BLACK );
105
0
                pVDev->SetFillColor( COL_BLACK );
106
107
0
                for( sal_uInt16 i = 0; i < nCount; i++ )
108
0
                {
109
0
                    const AnimationFrame& rStepBmp = aAnim.Get( i );
110
111
                    // Push Polygon output to the right place; this is the
112
                    // offset of the sub-image within the total animation
113
0
                    aTransMap.SetOrigin( Point( rStepBmp.maPositionPixel.X(), rStepBmp.maPositionPixel.Y() ) );
114
0
                    pVDev->SetMapMode( aTransMap );
115
0
                    pVDev->DrawPolyPolygon( CreateAutoContour( rStepBmp.maBitmap, pRect ) );
116
0
                }
117
118
0
                aTransMap.SetOrigin( Point() );
119
0
                pVDev->SetMapMode( aTransMap );
120
0
                aBmp = pVDev->GetBitmap( Point(), rSizePix );
121
0
                aBmp.Convert( BmpConversion::N1BitThreshold );
122
0
            }
123
0
        }
124
0
        else
125
0
        {
126
0
            Bitmap aTmpBmp = rGraphic.GetBitmap();
127
0
            if (aTmpBmp.HasAlpha())
128
0
                aBmp = aTmpBmp.CreateAlphaMask().GetBitmap();
129
0
            else
130
0
            {
131
132
0
                aBmp = std::move(aTmpBmp);
133
0
                bContourEdgeDetect = true;
134
0
            }
135
0
        }
136
0
    }
137
0
    else if( rGraphic.GetType() != GraphicType::NONE )
138
0
    {
139
0
        const Graphic   aTmpGrf( rGraphic.GetGDIMetaFile().GetMonochromeMtf( COL_BLACK ) );
140
0
        ScopedVclPtrInstance< VirtualDevice > pVDev;
141
0
        Size            aSizePix( pVDev->LogicToPixel( aTmpGrf.GetPrefSize(), aTmpGrf.GetPrefMapMode() ) );
142
143
0
        if( aSizePix.Width() && aSizePix.Height() && ( aSizePix.Width() > 512 || aSizePix.Height() > 512 ) )
144
0
        {
145
0
            double fWH = static_cast<double>(aSizePix.Width()) / aSizePix.Height();
146
147
0
            if( fWH <= 1.0 )
148
0
            {
149
0
                aSizePix.setHeight(512);
150
0
                aSizePix.setWidth(basegfx::fround<tools::Long>(aSizePix.Height() * fWH));
151
0
            }
152
0
            else
153
0
            {
154
0
                aSizePix.setWidth(512);
155
0
                aSizePix.setHeight(basegfx::fround<tools::Long>(aSizePix.Width() / fWH));
156
0
            }
157
0
        }
158
159
0
        if( pVDev->SetOutputSizePixel( aSizePix ) )
160
0
        {
161
0
            const Point aPt;
162
0
            aTmpGrf.Draw(*pVDev, aPt, aSizePix);
163
0
            aBmp = pVDev->GetBitmap( aPt, aSizePix );
164
0
        }
165
166
0
        bContourEdgeDetect = true;
167
0
    }
168
169
0
    aBmp.SetPrefSize( rGraphic.GetPrefSize() );
170
0
    aBmp.SetPrefMapMode( rGraphic.GetPrefMapMode() );
171
172
0
    return tools::PolyPolygon( aBmp.GetContour( bContourEdgeDetect, pRect ) );
173
0
}
174
175
// Loop through to super class, no virtual Methods to not become incompatible
176
// due to IF changes
177
178
const Graphic& SvxContourDlg::GetGraphic() const
179
0
{
180
0
    return m_xImpl->GetGraphic();
181
0
}
182
183
bool SvxContourDlg::IsGraphicChanged() const
184
0
{
185
0
    return m_xImpl->IsGraphicChanged();
186
0
}
187
188
tools::PolyPolygon SvxContourDlg::GetPolyPolygon()
189
0
{
190
0
    return m_xImpl->GetPolyPolygon();
191
0
}
192
193
const void* SvxContourDlg::GetEditingObject() const
194
0
{
195
0
    return m_xImpl->GetEditingObject();
196
0
}
197
198
void SvxContourDlg::Update( const Graphic& rGraphic, bool bGraphicLinked,
199
                            const tools::PolyPolygon* pPolyPoly, void* pEditingObj )
200
0
{
201
0
    m_xImpl->UpdateGraphic( rGraphic, bGraphicLinked, pPolyPoly, pEditingObj );
202
0
}
203
204
SvxSuperContourDlg::SvxSuperContourDlg(weld::Builder& rBuilder,
205
    weld::Dialog& rDialog, SfxBindings* pBindings)
206
0
    : aUpdateIdle( "SvxSuperContourDlg UpdateIdle" )
207
0
    , aCreateIdle( "SvxSuperContourDlg CreateIdle" )
208
0
    , mpBindings(pBindings)
209
0
    , pUpdateEditingObject( nullptr )
210
0
    , pCheckObj( nullptr )
211
0
    , aContourItem( *this, *pBindings )
212
0
    , mnGrfChanged( 0 )
213
0
    , bExecState( false )
214
0
    , bUpdateGraphicLinked( false )
215
0
    , bGraphicLinked( false )
216
0
    , m_rDialog(rDialog)
217
0
    , m_xContourWnd(new ContourWindow(&rDialog))
218
0
    , m_xStbStatusColor(new StatusColor(*m_xContourWnd))
219
0
    , m_xTbx1(rBuilder.weld_toolbar(u"toolbar"_ustr))
220
0
    , m_xMtfTolerance(rBuilder.weld_metric_spin_button(u"spinbutton"_ustr, FieldUnit::PERCENT))
221
0
    , m_xStbStatus2(rBuilder.weld_label(u"statuspos"_ustr))
222
0
    , m_xStbStatus3(rBuilder.weld_label(u"statussize"_ustr))
223
0
    , m_xCancelBtn(rBuilder.weld_button(u"cancel"_ustr))
224
0
    , m_xStbStatusColorWeld(new weld::CustomWeld(rBuilder, u"statuscolor"_ustr, *m_xStbStatusColor))
225
0
    , m_xContourWndWeld(new weld::CustomWeld(rBuilder, u"container"_ustr, *m_xContourWnd))
226
0
{
227
0
    m_xCancelBtn->connect_clicked(LINK(this, SvxSuperContourDlg, CancelHdl));
228
229
0
    m_xContourWnd->SetMousePosLink( LINK( this, SvxSuperContourDlg, MousePosHdl ) );
230
0
    m_xContourWnd->SetGraphSizeLink( LINK( this, SvxSuperContourDlg, GraphSizeHdl ) );
231
0
    m_xContourWnd->SetUpdateLink( LINK( this, SvxSuperContourDlg, StateHdl ) );
232
0
    m_xContourWnd->SetPipetteHdl( LINK( this, SvxSuperContourDlg, PipetteHdl ) );
233
0
    m_xContourWnd->SetPipetteClickHdl( LINK( this, SvxSuperContourDlg, PipetteClickHdl ) );
234
0
    m_xContourWnd->SetWorkplaceClickHdl( LINK( this, SvxSuperContourDlg, WorkplaceClickHdl ) );
235
236
0
    m_xTbx1->connect_clicked( LINK( this, SvxSuperContourDlg, Tbx1ClickHdl ) );
237
238
0
    m_xMtfTolerance->set_value(10, FieldUnit::PERCENT);
239
240
0
    aUpdateIdle.SetInvokeHandler( LINK( this, SvxSuperContourDlg, UpdateHdl ) );
241
242
0
    aCreateIdle.SetPriority( TaskPriority::RESIZE );
243
0
    aCreateIdle.SetInvokeHandler( LINK( this, SvxSuperContourDlg, CreateHdl ) );
244
0
}
245
246
SvxSuperContourDlg::~SvxSuperContourDlg()
247
0
{
248
0
    m_xContourWnd->SetUpdateLink( Link<GraphCtrl*,void>() );
249
0
    m_xContourWnd.reset();
250
0
}
251
252
IMPL_LINK_NOARG(SvxSuperContourDlg, CancelHdl, weld::Button&, void)
253
0
{
254
0
    bool bRet = true;
255
256
0
    if (m_xTbx1->get_item_sensitive(u"TBI_APPLY"_ustr))
257
0
    {
258
0
        std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(&m_rDialog, u"svx/ui/querysavecontchangesdialog.ui"_ustr));
259
0
        std::unique_ptr<weld::MessageDialog> xQBox(xBuilder->weld_message_dialog(u"QuerySaveContourChangesDialog"_ustr));
260
0
        const short nRet = xQBox->run();
261
262
0
        if ( nRet == RET_YES )
263
0
        {
264
0
            SfxBoolItem aBoolItem( SID_CONTOUR_EXEC, true );
265
0
            GetBindings().GetDispatcher()->ExecuteList(
266
0
                SID_CONTOUR_EXEC, SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
267
0
                { &aBoolItem });
268
0
        }
269
0
        else if ( nRet == RET_CANCEL )
270
0
            bRet = false;
271
0
    }
272
273
0
    if (bRet)
274
0
        m_rDialog.response(RET_CANCEL);
275
0
}
276
277
// Enabled or disabled all Controls
278
279
void SvxSuperContourDlg::SetExecState( bool bEnable )
280
0
{
281
0
    bExecState = bEnable;
282
0
}
283
284
void SvxSuperContourDlg::SetGraphic( const Graphic& rGraphic )
285
0
{
286
0
    aUndoGraphic = aRedoGraphic = Graphic();
287
0
    aGraphic = rGraphic;
288
0
    mnGrfChanged = 0;
289
0
    m_xContourWnd->SetGraphic( aGraphic );
290
0
}
291
292
void SvxSuperContourDlg::SetPolyPolygon( const tools::PolyPolygon& rPolyPoly )
293
0
{
294
0
    DBG_ASSERT(  m_xContourWnd->GetGraphic().GetType() != GraphicType::NONE, "Graphic must've been set first!" );
295
296
0
    tools::PolyPolygon aPolyPoly( rPolyPoly );
297
0
    const MapMode   aMap100( MapUnit::Map100thMM );
298
0
    const MapMode   aGrfMap( aGraphic.GetPrefMapMode() );
299
0
    OutputDevice*   pOutDev = Application::GetDefaultDevice();
300
0
    bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
301
302
0
    for ( sal_uInt16 j = 0, nPolyCount = aPolyPoly.Count(); j < nPolyCount; j++ )
303
0
    {
304
0
        tools::Polygon& rPoly = aPolyPoly[ j ];
305
306
0
        for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
307
0
        {
308
0
            Point& rPt = rPoly[ i ];
309
310
0
            if ( !bPixelMap )
311
0
                rPt = pOutDev->LogicToPixel( rPt, aGrfMap );
312
313
0
            rPt = pOutDev->PixelToLogic( rPt, aMap100 );
314
0
        }
315
0
    }
316
317
0
    m_xContourWnd->SetPolyPolygon( aPolyPoly );
318
0
    m_xContourWnd->GetSdrModel()->SetChanged();
319
0
}
320
321
tools::PolyPolygon SvxSuperContourDlg::GetPolyPolygon()
322
0
{
323
0
    tools::PolyPolygon aRetPolyPoly( m_xContourWnd->GetPolyPolygon() );
324
325
0
    const MapMode   aMap100( MapUnit::Map100thMM );
326
0
    const MapMode   aGrfMap( aGraphic.GetPrefMapMode() );
327
0
    OutputDevice*   pOutDev = Application::GetDefaultDevice();
328
0
    bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;
329
330
0
    for ( sal_uInt16 j = 0, nPolyCount = aRetPolyPoly.Count(); j < nPolyCount; j++ )
331
0
    {
332
0
        tools::Polygon& rPoly = aRetPolyPoly[ j ];
333
334
0
        for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
335
0
        {
336
0
            Point& rPt = rPoly[ i ];
337
338
0
            rPt = pOutDev->LogicToPixel( rPt, aMap100  );
339
340
0
            if ( !bPixelMap )
341
0
                rPt = pOutDev->PixelToLogic( rPt, aGrfMap  );
342
0
        }
343
0
    }
344
345
0
    return aRetPolyPoly;
346
0
}
347
348
void SvxSuperContourDlg::UpdateGraphic( const Graphic& rGraphic, bool _bGraphicLinked,
349
                                 const tools::PolyPolygon* pPolyPoly, void* pEditingObj )
350
0
{
351
0
    aUpdateGraphic = rGraphic;
352
0
    bUpdateGraphicLinked = _bGraphicLinked;
353
0
    pUpdateEditingObject = pEditingObj;
354
355
0
    if ( pPolyPoly )
356
0
        aUpdatePolyPoly = *pPolyPoly;
357
0
    else
358
0
        aUpdatePolyPoly = tools::PolyPolygon();
359
360
0
    aUpdateIdle.Start();
361
0
}
362
363
// Click handler for ToolBox
364
365
IMPL_LINK(SvxSuperContourDlg, Tbx1ClickHdl, const OUString&, rId, void)
366
0
{
367
0
    if (rId == "TBI_APPLY")
368
0
    {
369
0
        SfxBoolItem aBoolItem( SID_CONTOUR_EXEC, true );
370
0
        GetBindings().GetDispatcher()->ExecuteList(
371
0
            SID_CONTOUR_EXEC, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
372
0
            { &aBoolItem });
373
0
    }
374
0
    else if (rId == "TBI_WORKPLACE")
375
0
    {
376
0
        if (m_xTbx1->get_item_active(u"TBI_WORKPLACE"_ustr))
377
0
        {
378
0
            std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(&m_rDialog, u"svx/ui/querydeletecontourdialog.ui"_ustr));
379
0
            std::unique_ptr<weld::MessageDialog> xQBox(xBuilder->weld_message_dialog(u"QueryDeleteContourDialog"_ustr));
380
381
0
            if (!m_xContourWnd->IsContourChanged() || (xQBox->run() == RET_YES))
382
0
                m_xContourWnd->SetWorkplaceMode( true );
383
0
            else
384
0
                m_xTbx1->set_item_active(u"TBI_WORKPLACE"_ustr, false);
385
0
        }
386
0
        else
387
0
            m_xContourWnd->SetWorkplaceMode( false );
388
0
    }
389
0
    else if (rId == "TBI_SELECT")
390
0
    {
391
0
        SetActiveTool(rId);
392
0
        m_xContourWnd->SetEditMode( true );
393
0
    }
394
0
    else if (rId == "TBI_RECT")
395
0
    {
396
0
        SetActiveTool(rId);
397
0
        m_xContourWnd->SetObjKind( SdrObjKind::Rectangle );
398
0
    }
399
0
    else if (rId == "TBI_CIRCLE")
400
0
    {
401
0
        SetActiveTool(rId);
402
0
        m_xContourWnd->SetObjKind( SdrObjKind::CircleOrEllipse );
403
0
    }
404
0
    else if (rId == "TBI_POLY")
405
0
    {
406
0
        SetActiveTool(rId);
407
0
        m_xContourWnd->SetObjKind( SdrObjKind::Polygon );
408
0
    }
409
0
    else if (rId == "TBI_POLYEDIT")
410
0
    {
411
0
        m_xContourWnd->SetPolyEditMode(m_xTbx1->get_item_active(u"TBI_POLYEDIT"_ustr) ? SID_BEZIER_MOVE : 0);
412
0
    }
413
0
    else if (rId == "TBI_POLYMOVE")
414
0
    {
415
0
        SetActivePoly(rId);
416
0
        m_xContourWnd->SetPolyEditMode( SID_BEZIER_MOVE );
417
0
    }
418
0
    else if (rId == "TBI_POLYINSERT")
419
0
    {
420
0
        SetActivePoly(rId);
421
0
        m_xContourWnd->SetPolyEditMode( SID_BEZIER_INSERT );
422
0
    }
423
0
    else if (rId == "TBI_POLYDELETE")
424
0
    {
425
0
        m_xContourWnd->GetSdrView()->DeleteMarkedPoints();
426
0
    }
427
0
    else if (rId == "TBI_UNDO")
428
0
    {
429
0
        mnGrfChanged = mnGrfChanged ? mnGrfChanged - 1 : 0;
430
0
        aRedoGraphic = aGraphic;
431
0
        aGraphic = aUndoGraphic;
432
0
        aUndoGraphic = Graphic();
433
0
        m_xContourWnd->SetGraphic( aGraphic, false );
434
0
    }
435
0
    else if (rId == "TBI_REDO")
436
0
    {
437
0
        mnGrfChanged++;
438
0
        aUndoGraphic = aGraphic;
439
0
        aGraphic = aRedoGraphic;
440
0
        aRedoGraphic = Graphic();
441
0
        m_xContourWnd->SetGraphic( aGraphic, false );
442
0
    }
443
0
    else if (rId == "TBI_AUTOCONTOUR")
444
0
    {
445
0
        aCreateIdle.Start();
446
0
    }
447
0
    else if (rId == "TBI_PIPETTE")
448
0
    {
449
0
        bool bPipette = m_xTbx1->get_item_active(u"TBI_PIPETTE"_ustr);
450
451
0
        if ( !bPipette )
452
0
            m_xStbStatusColor->Invalidate();
453
0
        else if ( bGraphicLinked )
454
0
        {
455
0
            std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(&m_rDialog, u"svx/ui/queryunlinkgraphicsdialog.ui"_ustr));
456
0
            std::unique_ptr<weld::MessageDialog> xQBox(xBuilder->weld_message_dialog(u"QueryUnlinkGraphicsDialog"_ustr));
457
458
0
            if (xQBox->run() != RET_YES)
459
0
            {
460
0
                bPipette = false;
461
0
                m_xTbx1->set_item_active(u"TBI_PIPETTE"_ustr, bPipette);
462
0
                m_xStbStatusColor->Invalidate();
463
0
            }
464
0
        }
465
466
0
        m_xContourWnd->SetPipetteMode( bPipette );
467
0
    }
468
0
    m_xContourWnd->QueueIdleUpdate();
469
0
}
470
471
void SvxSuperContourDlg::SetActiveTool(std::u16string_view rId)
472
0
{
473
0
    m_xTbx1->set_item_active(u"TBI_SELECT"_ustr, rId == u"TBI_SELECT");
474
0
    m_xTbx1->set_item_active(u"TBI_RECT"_ustr, rId == u"TBI_RECT");
475
0
    m_xTbx1->set_item_active(u"TBI_CIRCLE"_ustr, rId == u"TBI_CIRCLE");
476
0
    m_xTbx1->set_item_active(u"TBI_POLY"_ustr, rId == u"TBI_POLY");
477
0
}
478
479
void SvxSuperContourDlg::SetActivePoly(std::u16string_view rId)
480
0
{
481
0
    m_xTbx1->set_item_active(u"TBI_POLYMOVE"_ustr, rId == u"TBI_POLYMOVE");
482
0
    m_xTbx1->set_item_active(u"TBI_POLYINSERT"_ustr, rId == u"TBI_POLYINSERT");
483
0
}
484
485
IMPL_LINK( SvxSuperContourDlg, MousePosHdl, GraphCtrl*, pWnd, void )
486
0
{
487
0
    OUString aStr;
488
0
    const FieldUnit eFieldUnit = GetBindings().GetDispatcher()->GetModule()->GetFieldUnit();
489
0
    const Point& rMousePos = pWnd->GetMousePos();
490
0
    const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
491
0
    const sal_Unicode cSep = rLocaleWrapper.getNumDecimalSep()[0];
492
493
0
    aStr = GetUnitString( rMousePos.X(), eFieldUnit, cSep )
494
0
         + " / "
495
0
         + GetUnitString( rMousePos.Y(), eFieldUnit, cSep );
496
497
0
    m_xStbStatus2->set_label( aStr );
498
0
}
499
500
IMPL_LINK( SvxSuperContourDlg, GraphSizeHdl, GraphCtrl*, pWnd, void )
501
0
{
502
0
    OUString aStr;
503
0
    const FieldUnit eFieldUnit = GetBindings().GetDispatcher()->GetModule()->GetFieldUnit();
504
0
    const Size& rSize = pWnd->GetGraphicSize();
505
0
    const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
506
0
    const sal_Unicode cSep = rLocaleWrapper.getNumDecimalSep()[0];
507
508
0
    aStr = GetUnitString( rSize.Width(), eFieldUnit, cSep )
509
0
         + " x "
510
0
         + GetUnitString( rSize.Height(), eFieldUnit, cSep );
511
512
0
    m_xStbStatus3->set_label( aStr );
513
0
}
514
515
IMPL_LINK_NOARG(SvxSuperContourDlg, UpdateHdl, Timer *, void)
516
0
{
517
0
    aUpdateIdle.Stop();
518
519
0
    if ( pUpdateEditingObject != pCheckObj )
520
0
    {
521
0
        if( !GetEditingObject() )
522
0
            m_xContourWnd->GrabFocus();
523
524
0
        SetGraphic( aUpdateGraphic );
525
0
        SetPolyPolygon( aUpdatePolyPoly );
526
0
        pCheckObj = pUpdateEditingObject;
527
0
        bGraphicLinked = bUpdateGraphicLinked;
528
529
0
        aUpdateGraphic = Graphic();
530
0
        aUpdatePolyPoly = tools::PolyPolygon();
531
0
        bUpdateGraphicLinked = false;
532
533
0
        m_xContourWnd->GetSdrModel()->SetChanged( false );
534
0
    }
535
536
0
    GetBindings().Invalidate( SID_CONTOUR_EXEC );
537
0
    m_xContourWnd->QueueIdleUpdate();
538
0
}
539
540
IMPL_LINK_NOARG(SvxSuperContourDlg, CreateHdl, Timer *, void)
541
0
{
542
0
    aCreateIdle.Stop();
543
544
0
    const tools::Rectangle aWorkRect = m_xContourWnd->GetDrawingArea()->get_ref_device().LogicToPixel(
545
0
        m_xContourWnd->GetWorkRect(), MapMode( MapUnit::Map100thMM));
546
547
0
    const Graphic&  rGraphic = m_xContourWnd->GetGraphic();
548
0
    const bool      bValid = aWorkRect.Left() != aWorkRect.Right() && aWorkRect.Top() != aWorkRect.Bottom();
549
550
0
    weld::WaitObject aWaitObj(&m_rDialog);
551
0
    SetPolyPolygon( SvxContourDlg::CreateAutoContour( rGraphic, bValid ? &aWorkRect : nullptr ) );
552
0
}
553
554
IMPL_LINK( SvxSuperContourDlg, StateHdl, GraphCtrl*, pWnd, void )
555
0
{
556
0
    const SdrObject*    pObj = pWnd->GetSelectedSdrObject();
557
0
    const SdrView*      pView = pWnd->GetSdrView();
558
0
    const bool          bPolyEdit = ( pObj != nullptr ) && dynamic_cast<const SdrPathObj*>( pObj) !=  nullptr;
559
0
    const bool          bDrawEnabled = !(bPolyEdit && m_xTbx1->get_item_active(u"TBI_POLYEDIT"_ustr));
560
0
    const bool          bPipette = m_xTbx1->get_item_active(u"TBI_PIPETTE"_ustr);
561
0
    const bool          bWorkplace = m_xTbx1->get_item_active(u"TBI_WORKPLACE"_ustr);
562
0
    const bool          bDontHide = !( bPipette || bWorkplace );
563
0
    const bool          bBitmap = pWnd->GetGraphic().GetType() == GraphicType::Bitmap;
564
565
0
    m_xTbx1->set_item_sensitive(u"TBI_APPLY"_ustr, bDontHide && bExecState && pWnd->IsChanged());
566
567
0
    m_xTbx1->set_item_sensitive(u"TBI_WORKPLACE"_ustr, !bPipette && bDrawEnabled);
568
569
0
    m_xTbx1->set_item_sensitive(u"TBI_SELECT"_ustr, bDontHide && bDrawEnabled);
570
0
    m_xTbx1->set_item_sensitive(u"TBI_RECT"_ustr, bDontHide && bDrawEnabled);
571
0
    m_xTbx1->set_item_sensitive(u"TBI_CIRCLE"_ustr, bDontHide && bDrawEnabled);
572
0
    m_xTbx1->set_item_sensitive(u"TBI_POLY"_ustr, bDontHide && bDrawEnabled);
573
574
0
    m_xTbx1->set_item_sensitive(u"TBI_POLYEDIT"_ustr, bDontHide && bPolyEdit);
575
0
    m_xTbx1->set_item_sensitive(u"TBI_POLYMOVE"_ustr, bDontHide && !bDrawEnabled);
576
0
    m_xTbx1->set_item_sensitive(u"TBI_POLYINSERT"_ustr, bDontHide && !bDrawEnabled);
577
0
    m_xTbx1->set_item_sensitive(u"TBI_POLYDELETE"_ustr, bDontHide && !bDrawEnabled && pView->IsDeleteMarkedPointsPossible());
578
579
0
    m_xTbx1->set_item_sensitive(u"TBI_AUTOCONTOUR"_ustr, bDontHide && bDrawEnabled);
580
0
    m_xTbx1->set_item_sensitive(u"TBI_PIPETTE"_ustr, !bWorkplace && bDrawEnabled && bBitmap);
581
582
0
    m_xTbx1->set_item_sensitive(u"TBI_UNDO"_ustr, bDontHide && aUndoGraphic.GetType() != GraphicType::NONE);
583
0
    m_xTbx1->set_item_sensitive(u"TBI_REDO"_ustr, bDontHide && aRedoGraphic.GetType() != GraphicType::NONE);
584
585
0
    if ( bPolyEdit )
586
0
    {
587
0
        switch( pWnd->GetPolyEditMode() )
588
0
        {
589
0
            case SID_BEZIER_MOVE:
590
0
                SetActivePoly(u"TBI_POLYMOVE");
591
0
                break;
592
0
            case SID_BEZIER_INSERT:
593
0
                SetActivePoly(u"TBI_POLYINSERT");
594
0
                break;
595
0
            default:
596
0
                break;
597
0
        }
598
0
    }
599
0
    else
600
0
    {
601
0
        m_xTbx1->set_item_active(u"TBI_POLYEDIT"_ustr, false);
602
0
        SetActivePoly(u"TBI_POLYMOVE");
603
0
        pWnd->SetPolyEditMode( 0 );
604
0
    }
605
0
}
606
607
IMPL_LINK_NOARG(SvxSuperContourDlg, PipetteHdl, ContourWindow&, void)
608
0
{
609
0
    m_xStbStatusColor->Invalidate();
610
0
}
611
612
void StatusColor::Paint(vcl::RenderContext& rDevice, const tools::Rectangle&)
613
0
{
614
0
    const Color& rOldLineColor = rDevice.GetLineColor();
615
0
    const Color& rOldFillColor = rDevice.GetFillColor();
616
617
0
    tools::Rectangle aRect(Point(), GetOutputSizePixel());
618
0
    const Color& rColor = m_rWnd.GetPipetteColor();
619
620
0
    rDevice.SetLineColor(rColor);
621
0
    rDevice.SetFillColor(rColor);
622
623
0
    aRect.AdjustLeft(4 );
624
0
    aRect.AdjustTop(4 );
625
0
    aRect.AdjustRight( -4 );
626
0
    aRect.AdjustBottom( -4 );
627
628
0
    rDevice.DrawRect( aRect );
629
630
0
    rDevice.SetLineColor(rOldLineColor);
631
0
    rDevice.SetFillColor(rOldFillColor);
632
0
}
633
634
IMPL_LINK( SvxSuperContourDlg, PipetteClickHdl, ContourWindow&, rWnd, void )
635
0
{
636
0
    if ( rWnd.IsClickValid() )
637
0
    {
638
0
        const Color&    rColor = rWnd.GetPipetteColor();
639
640
0
        weld::WaitObject aWaitObj(&m_rDialog);
641
642
0
        if( aGraphic.GetType() == GraphicType::Bitmap )
643
0
        {
644
0
            const auto nPercentage = o3tl::sanitizing_cast<sal_uInt16>(m_xMtfTolerance->get_value(FieldUnit::PERCENT));
645
0
            const auto nTol = nPercentage * 255 / 100;
646
647
0
            AlphaMask aMask = aGraphic.GetBitmap().CreateColorBitmap().CreateAlphaMask( rColor, nTol );
648
649
0
            if( aGraphic.IsTransparent() )
650
0
                aMask.AlphaCombineOr( aGraphic.GetBitmap().CreateAlphaMask() );
651
652
0
            if( !aMask.IsEmpty() )
653
0
            {
654
0
                std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(&m_rDialog, u"svx/ui/querynewcontourdialog.ui"_ustr));
655
0
                std::unique_ptr<weld::MessageDialog> xQBox(xBuilder->weld_message_dialog(u"QueryNewContourDialog"_ustr));
656
657
0
                bool        bNewContour;
658
659
0
                aRedoGraphic = Graphic();
660
0
                aUndoGraphic = aGraphic;
661
0
                Bitmap aBmp = aGraphic.GetBitmap().CreateColorBitmap();
662
0
                aGraphic = Graphic( Bitmap( aBmp, aMask ) );
663
0
                mnGrfChanged++;
664
665
0
                bNewContour = (xQBox->run() == RET_YES);
666
0
                rWnd.SetGraphic( aGraphic, bNewContour );
667
668
0
                if( bNewContour )
669
0
                    aCreateIdle.Start();
670
0
            }
671
0
        }
672
0
    }
673
674
0
    m_xTbx1->set_item_active(u"TBI_PIPETTE"_ustr, false);
675
0
    rWnd.SetPipetteMode( false );
676
0
    m_xStbStatusColor->Invalidate();
677
0
}
678
679
IMPL_LINK( SvxSuperContourDlg, WorkplaceClickHdl, ContourWindow&, rWnd, void )
680
0
{
681
0
    m_xTbx1->set_item_active(u"TBI_WORKPLACE"_ustr, false);
682
0
    m_xTbx1->set_item_active(u"TBI_SELECT"_ustr, true);
683
0
    rWnd.SetWorkplaceMode( false );
684
685
0
    m_xContourWnd->QueueIdleUpdate();
686
0
}
687
688
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */