Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/controller/main/ChartController_TextEdit.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_wasm_strip.h>
21
22
#include <ChartController.hxx>
23
24
#include <ResId.hxx>
25
#include "UndoGuard.hxx"
26
#include <DrawViewWrapper.hxx>
27
#include <ChartWindow.hxx>
28
#include <ChartModel.hxx>
29
#include <ChartView.hxx>
30
#include <TitleHelper.hxx>
31
#include <ObjectIdentifier.hxx>
32
#include <ControllerLockGuard.hxx>
33
#include <comphelper/diagnose_ex.hxx>
34
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
35
#include <AccessibleTextHelper.hxx>
36
#endif
37
#include <strings.hrc>
38
#include <chartview/DrawModelWrapper.hxx>
39
#include <osl/diagnose.h>
40
41
#include <svx/svdoutl.hxx>
42
#include <svx/svxdlg.hxx>
43
#include <svx/svxids.hrc>
44
#include <editeng/editids.hrc>
45
#include <vcl/svapp.hxx>
46
#include <com/sun/star/beans/XPropertySet.hpp>
47
#include <com/sun/star/beans/XPropertySetInfo.hpp>
48
#include <com/sun/star/text/XTextCursor.hpp>
49
#include <com/sun/star/chart2/FormattedString.hpp>
50
#include <svl/stritem.hxx>
51
#include <editeng/fontitem.hxx>
52
#include <editeng/section.hxx>
53
#include <memory>
54
55
namespace chart
56
{
57
using namespace ::com::sun::star;
58
59
void ChartController::executeDispatch_EditText( const Point* pMousePixel )
60
0
{
61
0
    StartTextEdit( pMousePixel );
62
0
}
63
64
void ChartController::StartTextEdit( const Point* pMousePixel )
65
0
{
66
    //the first marked object will be edited
67
68
0
    SolarMutexGuard aGuard;
69
0
    SdrObject* pTextObj = m_pDrawViewWrapper->getTextEditObject();
70
0
    if(!pTextObj)
71
0
        return;
72
73
0
    OSL_PRECOND(!m_pTextActionUndoGuard,
74
0
                "ChartController::StartTextEdit: already have a TextUndoGuard!?");
75
0
    m_pTextActionUndoGuard.reset( new UndoGuard(
76
0
        SchResId( STR_ACTION_EDIT_TEXT ), m_xUndoManager ) );
77
0
    SdrOutliner* pOutliner = m_pDrawViewWrapper->getOutliner();
78
79
    //#i77362 change notification for changes on additional shapes are missing
80
0
    if( m_xChartView.is() )
81
0
        m_xChartView->setPropertyValue( u"SdrViewIsInEditMode"_ustr, uno::Any(true) );
82
83
0
    auto pChartWindow(GetChartWindow());
84
85
0
    bool bEdit = m_pDrawViewWrapper->SdrBeginTextEdit( pTextObj
86
0
                    , m_pDrawViewWrapper->GetPageView()
87
0
                    , pChartWindow
88
0
                    , false //bIsNewObj
89
0
                    , pOutliner
90
0
                    , nullptr //pOutlinerView
91
0
                    , true //bDontDeleteOutliner
92
0
                    , true //bOnlyOneView
93
0
                    );
94
0
    if(!bEdit)
95
0
        return;
96
97
0
    m_pDrawViewWrapper->SetEditMode();
98
99
    // #i12587# support for shapes in chart
100
0
    if ( pMousePixel )
101
0
    {
102
0
        OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
103
0
        if ( pOutlinerView )
104
0
        {
105
0
            MouseEvent aEditEvt( *pMousePixel, 1, MouseEventModifiers::SYNTHETIC, MOUSE_LEFT, 0 );
106
0
            pOutlinerView->MouseButtonDown( aEditEvt );
107
0
            pOutlinerView->MouseButtonUp( aEditEvt );
108
0
        }
109
0
    }
110
111
0
    if (pChartWindow)
112
0
    {
113
        //we invalidate the outliner region because the outliner has some
114
        //paint problems (some characters are painted twice a little bit shifted)
115
0
        pChartWindow->Invalidate( m_pDrawViewWrapper->GetMarkedObjBoundRect() );
116
0
    }
117
0
}
118
119
bool ChartController::EndTextEdit()
120
0
{
121
0
    m_pDrawViewWrapper->SdrEndTextEdit();
122
123
    //#i77362 change notification for changes on additional shapes are missing
124
0
    if( m_xChartView.is() )
125
0
        m_xChartView->setPropertyValue( u"SdrViewIsInEditMode"_ustr, uno::Any(false) );
126
127
0
    SdrObject* pTextObject = m_pDrawViewWrapper->getTextEditObject();
128
0
    if(!pTextObject)
129
0
        return false;
130
131
0
    OutlinerParaObject* pParaObj = pTextObject->GetOutlinerParaObject();
132
0
    if( !pParaObj )
133
0
        return true;
134
135
0
    OUString aObjectCID = m_aSelection.getSelectedCID();
136
0
    if ( !aObjectCID.isEmpty() )
137
0
    {
138
0
        uno::Reference< beans::XPropertySet > xPropSet =
139
0
            ObjectIdentifier::getObjectPropertySet( aObjectCID, getChartModel() );
140
141
        // lock controllers till end of block
142
0
        ControllerLockGuardUNO aCLGuard( getChartModel() );
143
144
0
        uno::Sequence< uno::Reference< chart2::XFormattedString > > aNewFormattedTitle =
145
0
            GetFormattedTitle(pParaObj->GetTextObject(), pTextObject->getUnoShape());
146
147
0
        Title* pTitle = dynamic_cast<Title*>(xPropSet.get());
148
0
        TitleHelper::setFormattedString(pTitle, aNewFormattedTitle);
149
150
0
        OSL_ENSURE(m_pTextActionUndoGuard, "ChartController::EndTextEdit: no TextUndoGuard!");
151
0
        if (m_pTextActionUndoGuard)
152
0
            m_pTextActionUndoGuard->commit();
153
0
    }
154
0
    m_pTextActionUndoGuard.reset();
155
0
    return true;
156
0
}
157
158
uno::Sequence< uno::Reference< chart2::XFormattedString > > ChartController::GetFormattedTitle(
159
    const EditTextObject& aEdit, const uno::Reference< drawing::XShape >& xShape )
160
0
{
161
0
    std::vector < uno::Reference< chart2::XFormattedString > > aNewStrings;
162
0
    if (!xShape.is())
163
0
        return comphelper::containerToSequence(aNewStrings);
164
165
0
    uno::Reference< text::XText > xText(xShape, uno::UNO_QUERY);
166
0
    if (!xText.is())
167
0
        return comphelper::containerToSequence(aNewStrings);
168
169
0
    uno::Reference< text::XTextCursor > xSelectionCursor(xText->createTextCursor());
170
0
    if (!xSelectionCursor.is())
171
0
        return comphelper::containerToSequence(aNewStrings);
172
173
0
    xSelectionCursor->gotoStart(false);
174
175
0
    std::vector<editeng::Section> aSecAttrs;
176
0
    aEdit.GetAllSections(aSecAttrs);
177
178
0
    for (editeng::Section const& rSection : aSecAttrs)
179
0
    {
180
0
        if (!xSelectionCursor->isCollapsed())
181
0
            xSelectionCursor->collapseToEnd();
182
183
0
        xSelectionCursor->goRight(rSection.mnEnd - rSection.mnStart, true);
184
185
0
        OUString aNewString = xSelectionCursor->getString();
186
187
0
        bool bNextPara = (aEdit.GetParagraphCount() > 1 && rSection.mnParagraph != aEdit.GetParagraphCount() - 1 &&
188
0
            aEdit.GetTextLen(rSection.mnParagraph) <= rSection.mnEnd);
189
190
0
        uno::Reference< chart2::XFormattedString2 > xFmtStr = chart2::FormattedString::create(m_xCC);
191
0
        if (bNextPara)
192
0
            aNewString += OUStringChar('\n');
193
0
        xFmtStr->setString(aNewString);
194
0
        aNewStrings.emplace_back(xFmtStr);
195
196
0
        uno::Reference< beans::XPropertySetInfo > xInfo = xFmtStr->getPropertySetInfo();
197
0
        uno::Reference< beans::XPropertySet > xSelectionProp(xSelectionCursor, uno::UNO_QUERY);
198
0
        try
199
0
        {
200
0
            for (const beans::Property& rProp : xSelectionProp->getPropertySetInfo()->getProperties())
201
0
            {
202
0
                if (xInfo.is() && xInfo->hasPropertyByName(rProp.Name))
203
0
                {
204
0
                    const uno::Any aValue = xSelectionProp->getPropertyValue(rProp.Name);
205
0
                    xFmtStr->setPropertyValue(rProp.Name, aValue);
206
0
                }
207
0
            }
208
0
        }
209
0
        catch ( const uno::Exception& )
210
0
        {
211
0
            DBG_UNHANDLED_EXCEPTION("chart2");
212
0
            aNewStrings.clear();
213
0
        }
214
215
0
        if (bNextPara)
216
0
            xSelectionCursor->goRight(1, false); // next paragraph
217
0
    }
218
219
0
    return comphelper::containerToSequence(aNewStrings);
220
0
}
221
222
void ChartController::executeDispatch_InsertSpecialCharacter()
223
0
{
224
0
    SolarMutexGuard aGuard;
225
0
    if( !m_pDrawViewWrapper)
226
0
    {
227
0
        OSL_ENSURE( m_pDrawViewWrapper, "No DrawViewWrapper for ChartController" );
228
0
        return;
229
0
    }
230
0
    if( !m_pDrawViewWrapper->IsTextEdit() )
231
0
        StartTextEdit();
232
233
0
    SvxAbstractDialogFactory * pFact = SvxAbstractDialogFactory::Create();
234
235
0
    SfxAllItemSet aSet( m_pDrawModelWrapper->GetItemPool() );
236
0
    aSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
237
238
    //set fixed current font
239
0
    aSet.Put( SfxBoolItem( FN_PARAM_2, true ) ); //maybe not necessary in future
240
241
0
    vcl::Font aCurFont = m_pDrawViewWrapper->getOutliner()->GetRefDevice()->GetFont();
242
0
    aSet.Put( SvxFontItem( aCurFont.GetFamilyTypeMaybeAskConfig(), aCurFont.GetFamilyName(), aCurFont.GetStyleName(), aCurFont.GetPitchMaybeAskConfig(), aCurFont.GetCharSet(), SID_ATTR_CHAR_FONT ) );
243
244
0
    VclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(GetChartFrame(), aSet, nullptr));
245
0
    pDlg->StartExecuteAsync(
246
0
        [this, pDlg] (sal_Int32 nResult)->void
247
0
        {
248
0
            if (nResult == RET_OK)
249
0
            {
250
0
                const SfxItemSet* pSet = pDlg->GetOutputItemSet();
251
0
                OUString aString;
252
0
                if (pSet)
253
0
                    if (const SfxStringItem* pCharMapItem = pSet->GetItemIfSet(SID_CHARMAP))
254
0
                        aString = pCharMapItem->GetValue();
255
256
0
                OutlinerView* pOutlinerView = m_pDrawViewWrapper->GetTextEditOutlinerView();
257
0
                SdrOutliner*  pOutliner = m_pDrawViewWrapper->getOutliner();
258
259
0
                if(pOutliner && pOutlinerView)
260
0
                {
261
                    // insert string to outliner
262
263
                    // prevent flicker
264
0
                    pOutlinerView->HideCursor();
265
0
                    pOutliner->SetUpdateLayout(false);
266
267
                    // delete current selection by inserting empty String, so current
268
                    // attributes become unique (sel. has to be erased anyway)
269
0
                    pOutlinerView->InsertText(OUString());
270
271
0
                    pOutlinerView->InsertText(aString, true);
272
273
0
                    ESelection aSel = pOutlinerView->GetSelection();
274
0
                    aSel.CollapseToEnd();
275
0
                    pOutlinerView->SetSelection(aSel);
276
277
                    // show changes
278
0
                    pOutliner->SetUpdateLayout(true);
279
0
                    pOutlinerView->ShowCursor();
280
0
                }
281
0
            }
282
0
            pDlg->disposeOnce();
283
0
        }
284
0
    );
285
286
0
}
287
288
rtl::Reference< ::chart::AccessibleTextHelper >
289
    ChartController::createAccessibleTextContext()
290
0
{
291
0
#if !ENABLE_WASM_STRIP_ACCESSIBILITY
292
0
    return new AccessibleTextHelper( m_pDrawViewWrapper.get() );
293
#else
294
    return {};
295
#endif
296
0
}
297
298
} //namespace chart
299
300
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */