Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/docshell/sdclient.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 <Client.hxx>
21
#include <svx/svdoole2.hxx>
22
#include <tools/debug.hxx>
23
24
#include <ViewShell.hxx>
25
#include <View.hxx>
26
#include <vcl/svapp.hxx>
27
28
using namespace com::sun::star;
29
30
namespace sd {
31
32
Client::Client(SdrOle2Obj* pObj, ViewShell& rViewShell, vcl::Window* pWindow) :
33
0
    SfxInPlaceClient(rViewShell.GetViewShell(), pWindow, pObj->GetAspect() ),
34
0
    mrViewShell(rViewShell),
35
0
    pSdrOle2Obj(pObj)
36
0
{
37
0
    SetObject( pObj->GetObjRef() );
38
0
    DBG_ASSERT( GetObject().is(), "No object connected!" );
39
0
}
40
41
Client::~Client()
42
0
{
43
0
}
44
45
/**
46
 * If IP active, then we get this request to increase the visible section of the
47
 * object.
48
 */
49
void Client::RequestNewObjectArea( ::tools::Rectangle& aObjRect )
50
0
{
51
0
    ::sd::View* pView = mrViewShell.GetView();
52
53
0
    bool bSizeProtect = false;
54
0
    bool bPosProtect = false;
55
56
0
    const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
57
0
    if (rMarkList.GetMarkCount() == 1)
58
0
    {
59
0
        SdrMark* pMark = rMarkList.GetMark(0);
60
0
        SdrObject* pObj = pMark->GetMarkedSdrObj();
61
62
        // no need to check for changes, this method is called only if the area really changed
63
0
        bSizeProtect = pObj->IsResizeProtect();
64
0
        bPosProtect = pObj->IsMoveProtect();
65
0
    }
66
67
0
    ::tools::Rectangle aOldRect = GetObjArea();
68
0
    if ( bPosProtect )
69
0
        aObjRect.SetPos( aOldRect.TopLeft() );
70
71
0
    if ( bSizeProtect )
72
0
        aObjRect.SetSize( aOldRect.GetSize() );
73
74
0
    ::tools::Rectangle aWorkArea( pView->GetWorkArea() );
75
0
    if ( aWorkArea.Contains(aObjRect) || bPosProtect || aObjRect == aOldRect )
76
0
        return;
77
78
    // correct position
79
0
    Point aPos = aObjRect.TopLeft();
80
0
    Size  aSize = aObjRect.GetSize();
81
0
    Point aWorkAreaTL = aWorkArea.TopLeft();
82
0
    Point aWorkAreaBR = aWorkArea.BottomRight();
83
84
0
    aPos.setX( std::max(aPos.X(), aWorkAreaTL.X()) );
85
0
    aPos.setX( std::min(aPos.X(), aWorkAreaBR.X()-aSize.Width()) );
86
0
    aPos.setY( std::max(aPos.Y(), aWorkAreaTL.Y()) );
87
0
    aPos.setY( std::min(aPos.Y(), aWorkAreaBR.Y()-aSize.Height()) );
88
89
0
    aObjRect.SetPos(aPos);
90
0
}
91
92
void Client::ObjectAreaChanged()
93
0
{
94
0
    ::sd::View* pView = mrViewShell.GetView();
95
0
    const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
96
0
    if (rMarkList.GetMarkCount() != 1)
97
0
        return;
98
99
0
    SdrMark* pMark = rMarkList.GetMark(0);
100
0
    SdrOle2Obj* pObj = dynamic_cast< SdrOle2Obj* >(pMark->GetMarkedSdrObj());
101
102
0
    if(!pObj)
103
0
        return;
104
105
    // no need to check for changes, this method is called only if the area really changed
106
0
    ::tools::Rectangle aNewRectangle(GetScaledObjArea());
107
108
    // #i118524# if sheared/rotated, center to non-rotated LogicRect
109
0
    pObj->setSuppressSetVisAreaSize(true);
110
111
0
    if(pObj->GetGeoStat().m_nRotationAngle || pObj->GetGeoStat().m_nShearAngle)
112
0
    {
113
0
        pObj->SetLogicRect( aNewRectangle );
114
115
0
        const ::tools::Rectangle& rBoundRect = pObj->GetCurrentBoundRect();
116
0
        const Point aDelta(aNewRectangle.Center() - rBoundRect.Center());
117
118
0
        aNewRectangle.Move(aDelta.X(), aDelta.Y());
119
0
    }
120
121
0
    pObj->SetLogicRect( aNewRectangle );
122
0
    pObj->setSuppressSetVisAreaSize(false);
123
0
}
124
125
void Client::ViewChanged()
126
0
{
127
0
    if ( GetAspect() == embed::Aspects::MSOLE_ICON )
128
0
    {
129
        // the iconified object seems not to need such a scaling handling
130
        // since the replacement image and the size a completely controlled by the container
131
        // TODO/LATER: when the icon exchange is implemented the scaling handling might be required again here
132
133
0
        pSdrOle2Obj->ActionChanged(); // draw needs it to remove lines in slide preview
134
0
        return;
135
0
    }
136
137
    //TODO/LATER: should we try to avoid the recalculation of the visareasize
138
    //if we know that it didn't change?
139
0
    if (!mrViewShell.GetActiveWindow())
140
0
        return;
141
142
0
    ::sd::View* pView = mrViewShell.GetView();
143
0
    if (!pView)
144
0
        return;
145
146
    // Do not recalculate the visareasize if the embedded object is opening in a new window.
147
0
    if (!IsObjectInPlaceActive())
148
0
    {
149
0
        pSdrOle2Obj->BroadcastObjectChange();
150
0
        return;
151
0
    }
152
153
0
    ::tools::Rectangle aLogicRect( pSdrOle2Obj->GetLogicRect() );
154
0
    Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() );
155
156
0
    if( pSdrOle2Obj->IsChart() )
157
0
    {
158
        //charts never should be stretched see #i84323# for example
159
0
        pSdrOle2Obj->SetLogicRect( ::tools::Rectangle( aLogicRect.TopLeft(), aLogicSize ) );
160
0
        pSdrOle2Obj->BroadcastObjectChange();
161
0
        return;
162
0
    }
163
164
    // TODO/LEAN: maybe we can do this without requesting the VisualArea?
165
    // working with the visual area might need running state, so the object may switch itself to this state
166
0
    MapMode             aMap100( MapUnit::Map100thMM );
167
0
    ::tools::Rectangle           aVisArea;
168
0
    Size aSize = pSdrOle2Obj->GetOrigObjSize( &aMap100 );
169
170
0
    aVisArea.SetSize( aSize );
171
0
    Size                aScaledSize( static_cast< ::tools::Long >( GetScaleWidth() * Fraction( aVisArea.GetWidth() ) ),
172
0
                                        static_cast< ::tools::Long >( GetScaleHeight() * Fraction( aVisArea.GetHeight() ) ) );
173
174
    // react to the change if the difference is bigger than one pixel
175
0
    Size aPixelDiff =
176
0
        Application::GetDefaultDevice()->LogicToPixel(
177
0
            Size( aLogicRect.GetWidth() - aScaledSize.Width(),
178
0
                  aLogicRect.GetHeight() - aScaledSize.Height() ),
179
0
            aMap100 );
180
0
    if( aPixelDiff.Width() || aPixelDiff.Height() )
181
0
    {
182
0
        pSdrOle2Obj->SetLogicRect( ::tools::Rectangle( aLogicRect.TopLeft(), aScaledSize ) );
183
0
        pSdrOle2Obj->BroadcastObjectChange();
184
0
    }
185
0
    else
186
0
        pSdrOle2Obj->ActionChanged();
187
0
}
188
189
} // end of namespace sd
190
191
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */