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/func/futext.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 <futext.hxx>
21
#include <editeng/eeitem.hxx>
22
#include <svx/sdrpagewindow.hxx>
23
#include <svx/sdrpaintwindow.hxx>
24
#include <tools/urlobj.hxx>
25
#include <vcl/help.hxx>
26
#include <editeng/fhgtitem.hxx>
27
#include <svl/intitem.hxx>
28
#include <svl/stritem.hxx>
29
#include <svx/svdotext.hxx>
30
#include <editeng/flditem.hxx>
31
#include <svl/style.hxx>
32
#include <svx/svdpagv.hxx>
33
#include <svx/sdtmfitm.hxx>
34
#include <svx/sdtagitm.hxx>
35
#include <svx/sdtfsitm.hxx>
36
#include <sfx2/viewfrm.hxx>
37
#include <sfx2/dispatch.hxx>
38
#include <sfx2/bindings.hxx>
39
#include <sfx2/request.hxx>
40
#include <editeng/editeng.hxx>
41
#include <svx/svdoutl.hxx>
42
#include <svx/svxids.hrc>
43
#include <sfx2/docfile.hxx>
44
#include <editeng/outlobj.hxx>
45
#include <osl/diagnose.h>
46
47
#include <editeng/frmdiritem.hxx>
48
49
#include <svx/svdetc.hxx>
50
#include <editeng/editview.hxx>
51
52
#include <sdresid.hxx>
53
#include <app.hrc>
54
55
#include <ViewShell.hxx>
56
#include <ViewShellBase.hxx>
57
#include <View.hxx>
58
#include <Window.hxx>
59
#include <drawdoc.hxx>
60
#include <sdpage.hxx>
61
#include <FrameView.hxx>
62
#include <ToolBarManager.hxx>
63
#include <DrawDocShell.hxx>
64
#include <strings.hrc>
65
#include <pres.hxx>
66
67
using namespace ::com::sun::star;
68
using namespace ::com::sun::star::uno;
69
70
namespace sd {
71
72
const sal_uInt16 SidArray[] = {
73
    SID_STYLE_FAMILY2,                //    5542
74
    SID_STYLE_FAMILY5,                //    5545
75
    SID_REDO,                         //    5700
76
    SID_UNDO,                         //    5701
77
    SID_CUT,                          //    5710
78
    SID_COPY,                         //    5711
79
    SID_ATTR_TABSTOP,                 //   10002
80
    SID_ATTR_CHAR_FONT,               //   10007
81
    SID_ATTR_CHAR_POSTURE,            //   10008
82
    SID_ATTR_CHAR_WEIGHT,             //   10009
83
    SID_ATTR_CHAR_SHADOWED,           //   10010
84
    SID_ATTR_CHAR_STRIKEOUT,          //   10013
85
    SID_ATTR_CHAR_UNDERLINE,          //   10014
86
    SID_ATTR_CHAR_FONTHEIGHT,         //   10015
87
    SID_ATTR_CHAR_COLOR,              //   10017
88
    SID_ATTR_CHAR_KERNING,            //   10018
89
    SID_ATTR_CHAR_CASEMAP,            //   10019
90
    SID_ATTR_PARA_ADJUST_LEFT,        //   10028
91
    SID_ATTR_PARA_ADJUST_RIGHT,       //   10029
92
    SID_ATTR_PARA_ADJUST_CENTER,      //   10030
93
    SID_ATTR_PARA_ADJUST_BLOCK,       //   10031
94
    SID_ATTR_PARA_LINESPACE_10,       //   10034
95
    SID_ATTR_PARA_LINESPACE_15,       //   10035
96
    SID_ATTR_PARA_LINESPACE_20,       //   10036
97
    SID_ATTR_PARA_ULSPACE,            //   10042
98
    SID_ATTR_PARA_LRSPACE,            //   10043
99
    SID_ATTR_TRANSFORM_POS_X,         //   10088
100
    SID_ATTR_TRANSFORM_POS_Y,         //   10089
101
    SID_ATTR_TRANSFORM_WIDTH,         //   10090
102
    SID_ATTR_TRANSFORM_HEIGHT,        //   10091
103
    SID_ATTR_TRANSFORM_ROT_X,         //   10093
104
    SID_ATTR_TRANSFORM_ROT_Y,         //   10094
105
    SID_ATTR_TRANSFORM_ANGLE,         //   10095 //Added
106
    SID_OUTLINE_UP,                   //   10150
107
    SID_OUTLINE_DOWN,                 //   10151
108
    SID_OUTLINE_LEFT,                 //   10152
109
    SID_OUTLINE_RIGHT,                //   10153
110
    SID_ATTR_TRANSFORM_PROTECT_POS,   //   10236
111
    SID_ATTR_TRANSFORM_PROTECT_SIZE,  //   10237 //Added
112
    SID_FORMTEXT_STYLE,               //   10257
113
    SID_SET_SUPER_SCRIPT,             //   10294
114
    SID_SET_SUB_SCRIPT,               //   10295
115
    SID_ATTR_TRANSFORM_AUTOWIDTH,     //   10310
116
    SID_ATTR_TRANSFORM_AUTOHEIGHT,    //   10311 //Added
117
    SID_HYPERLINK_GETLINK,            //   10361
118
    SID_DEC_INDENT,                   //   10461
119
    SID_INC_INDENT,                   //   10462
120
    SID_CHARMAP,                      //   10503
121
    SID_TEXTDIRECTION_LEFT_TO_RIGHT,  //   10907
122
    SID_TEXTDIRECTION_TOP_TO_BOTTOM,  //   10908
123
    SID_ATTR_PARA_LEFT_TO_RIGHT,      //   10950
124
    SID_ATTR_PARA_RIGHT_TO_LEFT,      //   10951
125
    SID_PARASPACE_INCREASE,           //   11145
126
    SID_PARASPACE_DECREASE,           //   11146
127
    SID_ATTR_PARA_ADJUST_START,       //   11579
128
    SID_ATTR_PARA_ADJUST_END,         //   11580
129
    FN_NUM_BULLET_ON,                 //   20138
130
    FN_NUM_NUMBERING_ON,              //   20144
131
                            0 };
132
133
134
/**
135
 * base class for text functions
136
 */
137
FuText::FuText( ViewShell& rViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument& rDoc, SfxRequest& rReq )
138
0
: FuConstruct(rViewSh, pWin, pView, rDoc, rReq)
139
0
, bFirstObjCreated(false)
140
0
, bJustEndedEdit(false)
141
0
, rRequest (rReq)
142
0
{
143
0
}
144
145
rtl::Reference<FuPoor> FuText::Create( ViewShell& rViewSh, ::sd::Window* pWin, ::sd::View* pView, SdDrawDocument& rDoc, SfxRequest& rReq )
146
0
{
147
0
    rtl::Reference<FuPoor> xFunc( new FuText( rViewSh, pWin, pView, rDoc, rReq ) );
148
0
    return xFunc;
149
0
}
150
151
void FuText::disposing()
152
0
{
153
0
    if(mpView)
154
0
    {
155
0
        if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
156
0
            mxTextObj = nullptr;
157
158
        // reset the RequestHandler of the used Outliner to the handler of the document
159
0
        ::Outliner* pOutliner = mpView->GetTextEditOutliner();
160
161
0
        if (pOutliner)
162
0
            pOutliner->SetStyleSheetPool(static_cast<SfxStyleSheetPool*>(mrDoc.GetStyleSheetPool()));
163
0
    }
164
0
}
165
166
/*************************************************************************
167
|*
168
|* Execute functionality of this class:
169
|*
170
|* #71422: Start the functionality of this class in this method
171
|* and not in the ctor.
172
|* If you construct an object of this class and you put the
173
|* address of this object to pFuActual you've got a problem,
174
|* because some methods inside DoExecute use the pFuActual-Pointer.
175
|* If the code inside DoExecute is executed inside the ctor,
176
|* the value of pFuActual is not right. And the value will not
177
|* be right until the ctor finished !!!
178
|*
179
\************************************************************************/
180
void FuText::DoExecute( SfxRequest& )
181
0
{
182
0
    mrViewShell.GetViewShellBase().GetToolBarManager()->SetToolBarShell(
183
0
        ToolBarManager::ToolBarGroup::Function,
184
0
        ToolbarId::Draw_Text_Toolbox_Sd);
185
186
0
    mpView->SetCurrentObj(SdrObjKind::Text);
187
0
    mpView->SetEditMode(SdrViewEditMode::Edit);
188
189
0
    MouseEvent aMEvt(mpWindow->GetPointerPosPixel());
190
191
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
192
0
    if (nSlotId == SID_TEXTEDIT)
193
0
    {
194
        // Try to select an object
195
0
        SdrPageView* pPV = mpView->GetSdrPageView();
196
0
        SdrViewEvent aVEvt;
197
0
        mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
198
0
        mpView->MarkObj(aVEvt.mpRootObj, pPV);
199
200
0
        mxTextObj = DynCastSdrTextObj( aVEvt.mpObj );
201
0
    }
202
0
    else if (rMarkList.GetMarkCount() != 0)
203
0
    {
204
0
        if (rMarkList.GetMarkCount() == 1)
205
0
        {
206
0
            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
207
0
            mxTextObj = DynCastSdrTextObj( pObj );
208
0
        }
209
0
    }
210
211
    // check for table
212
0
    if (rMarkList.GetMarkCount() != 0)
213
0
    {
214
0
        if (rMarkList.GetMarkCount() == 1)
215
0
        {
216
0
            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
217
0
            if( pObj && (pObj->GetObjInventor() == SdrInventor::Default ) && (pObj->GetObjIdentifier() == SdrObjKind::Table) )
218
0
            {
219
0
                mrViewShell.GetViewShellBase().GetToolBarManager()->AddToolBarShell(ToolBarManager::ToolBarGroup::Function, ToolbarId::Draw_Table_Toolbox);
220
0
            }
221
0
        }
222
0
    }
223
224
0
    bool bQuickDrag = true;
225
226
0
    const SfxItemSet* pArgs = rRequest.GetArgs();
227
228
0
    if (pArgs
229
230
        // test for type before using
231
0
        && SID_TEXTEDIT == nSlotId
232
0
        && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT)
233
234
0
        && pArgs->Get(SID_TEXTEDIT).GetValue() == 2)
235
0
    {
236
        // Selection by doubleclick -> don't allow QuickDrag
237
0
        bQuickDrag = false;
238
0
    }
239
240
0
    SetInEditMode(aMEvt, bQuickDrag);
241
0
}
242
243
bool FuText::MouseButtonDown(const MouseEvent& rMEvt)
244
0
{
245
0
    bMBDown = true;
246
0
    bJustEndedEdit = false;
247
248
0
    bool bReturn = FuDraw::MouseButtonDown(rMEvt);
249
250
0
    SdrViewEvent aVEvt;
251
0
    SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
252
253
    // handle URL also during the text editing
254
0
    if (rMEvt.GetClicks() == 1 && rMEvt.IsLeft() && rMEvt.IsMod1())
255
0
    {
256
0
        OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
257
258
0
        if (mxTextObj.get().is() && pOLV && pOLV->GetFieldUnderMousePointer())
259
0
        {
260
0
            const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer();
261
0
            if (pFieldItem)
262
0
            {
263
0
                const SvxFieldData* pField = pFieldItem->GetField();
264
265
0
                if (auto pURLField = dynamic_cast< const SvxURLField *>( pField ))
266
0
                {
267
0
                    eHit = SdrHitKind::MarkedObject;
268
0
                    aVEvt.meEvent = SdrEventKind::ExecuteUrl;
269
0
                    aVEvt.mpURLField = pURLField;
270
0
                }
271
0
            }
272
0
        }
273
0
    }
274
275
0
    if (eHit == SdrHitKind::TextEdit)
276
0
    {
277
        // hit text -> SdrView handles event
278
0
        if (mpView->MouseButtonDown(rMEvt, mpWindow->GetOutDev()))
279
0
            return true;
280
0
    }
281
282
0
    if (rMEvt.GetClicks() == 1)
283
0
    {
284
0
        if (mpView->IsTextEdit() && eHit != SdrHitKind::MarkedObject && eHit != SdrHitKind::Handle)
285
0
        {
286
            // finish text input
287
0
            if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
288
0
            {
289
                /* Bugfix from MBA: during a double click onto the unused? area
290
                   in text mode, we get with the second click eHit =
291
                   SdrHitKind::TextEditObj since it goes to the TextObject which was
292
                   created with the first click. But this is removed by
293
                   SdrEndTextEdit since it is empty. But it is still in the mark
294
                   list. The call MarkObj further below accesses then the dead
295
                   object. As a simple fix, we determine eHit after
296
                   SdrEndTextEdit again, this returns then SdrHitKind::NONE. */
297
0
                mxTextObj = nullptr;
298
0
                eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
299
0
            }
300
301
0
            mpView->SetCurrentObj(SdrObjKind::Text);
302
0
            mpView->SetEditMode(SdrViewEditMode::Edit);
303
0
        }
304
305
0
        if (rMEvt.IsLeft() || rMEvt.IsRight())
306
0
        {
307
0
            mpWindow->CaptureMouse();
308
0
            SdrPageView* pPV = mpView->GetSdrPageView();
309
310
0
            if (eHit == SdrHitKind::TextEdit)
311
0
            {
312
0
                SetInEditMode(rMEvt, false);
313
0
            }
314
0
            else
315
0
            {
316
                // Don't remark table when clicking in it, mark change triggers a lot of updating
317
0
                bool bMarkChanges = true;
318
0
                rtl::Reference< sdr::SelectionController > xSelectionController(mpView->getSelectionController());
319
0
                if (eHit == SdrHitKind::TextEditObj && xSelectionController.is())
320
0
                {
321
0
                    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
322
0
                    if (rMarkList.GetMarkCount() == 1 && rMarkList.GetMark(0)->GetMarkedSdrObj() == aVEvt.mpRootObj)
323
0
                        bMarkChanges = false;
324
0
                }
325
326
0
                if (eHit != SdrHitKind::Handle)
327
0
                {
328
                    // deselect selection
329
0
                    if (!rMEvt.IsShift() && eHit == SdrHitKind::TextEditObj)
330
0
                    {
331
0
                        if(bMarkChanges)
332
0
                        {
333
0
                            mpView->UnmarkAll();
334
0
                            mpView->SetDragMode(SdrDragMode::Move);
335
0
                        }
336
0
                    }
337
0
                }
338
339
0
                if ( aVEvt.meEvent == SdrEventKind::ExecuteUrl                   ||
340
0
                     eHit == SdrHitKind::Handle                                 ||
341
0
                     eHit == SdrHitKind::MarkedObject                           ||
342
0
                     eHit == SdrHitKind::TextEditObj                            ||
343
0
                     ( eHit == SdrHitKind::UnmarkedObject && bFirstObjCreated &&
344
0
                       !bPermanent ) )
345
0
                {
346
                    // Handle, hit marked or unmarked object
347
0
                    if (eHit == SdrHitKind::TextEditObj)
348
0
                    {
349
                        /* hit text of unmarked object:
350
                           select object and set to EditMode */
351
0
                        if (bMarkChanges)
352
0
                            mpView->MarkObj(aVEvt.mpRootObj, pPV);
353
354
0
                        if (auto pSdrTextObj = DynCastSdrTextObj(aVEvt.mpObj))
355
0
                        {
356
0
                            mxTextObj = pSdrTextObj;
357
0
                        }
358
359
0
                        SetInEditMode(rMEvt, true);
360
0
                    }
361
0
                    else if (aVEvt.meEvent == SdrEventKind::ExecuteUrl && !rMEvt.IsMod2())
362
0
                    {
363
                        // execute URL
364
0
                        mpWindow->ReleaseMouse();
365
366
0
                        if (aVEvt.mpURLField)
367
0
                        {
368
0
                            SfxStringItem aStrItem(SID_FILE_NAME, aVEvt.mpURLField->GetURL());
369
0
                            SfxStringItem aReferer(SID_REFERER, mpDocSh->GetMedium()->GetName());
370
0
                            SfxBoolItem aBrowseItem( SID_BROWSE, true );
371
0
                            SfxViewFrame* pFrame = mrViewShell.GetViewFrame();
372
373
0
                            if (rMEvt.IsMod1())
374
0
                            {
375
                                // open in new frame
376
0
                                pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC,
377
0
                                    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
378
0
                                    { &aStrItem, &aBrowseItem, &aReferer });
379
0
                            }
380
0
                            else
381
0
                            {
382
                                // open in current frame
383
0
                                SfxFrameItem aFrameItem(SID_DOCFRAME, pFrame);
384
0
                                pFrame->GetDispatcher()->ExecuteList(SID_OPENDOC,
385
0
                                    SfxCallMode::ASYNCHRON | SfxCallMode::RECORD,
386
0
                                    { &aStrItem, &aFrameItem, &aBrowseItem, &aReferer });
387
0
                            }
388
0
                        }
389
0
                    }
390
0
                    else
391
0
                    {
392
                        // drag object or handle
393
394
                        // #i78748#
395
                        // do the EndTextEdit first, it will delete the handles and force a
396
                        // recreation. This will make aVEvt.mpHdl to point to a deleted handle,
397
                        // thus it is necessary to reset it and to get it again.
398
399
                        // #i112855#
400
                        // cl: I'm not sure why we checked here also for mxTextObj->GetOutlinerParaObject
401
                        // this caused SdrEndTextEdit() to be called also when not in text editing and
402
                        // this does not make sense and caused troubles. (see issue 112855)
403
404
0
                        if( mpView->IsTextEdit() )
405
0
                        {
406
0
                            mpView->SdrEndTextEdit();
407
0
                            bJustEndedEdit = true;
408
409
0
                            if(aVEvt.mpHdl)
410
0
                            {
411
                                // force new handle identification, the pointer will be dead here
412
                                // since SdrEndTextEdit has reset (deleted) the handles.
413
0
                                aVEvt.mpHdl = nullptr;
414
0
                                mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
415
0
                            }
416
0
                        }
417
418
0
                        if (!aVEvt.mpHdl)
419
0
                        {
420
0
                            if( eHit == SdrHitKind::UnmarkedObject )
421
0
                            {
422
0
                                if ( !rMEvt.IsShift() )
423
0
                                    mpView->UnmarkAll();
424
425
0
                                mpView->MarkObj(aVEvt.mpRootObj, pPV);
426
0
                            }
427
428
                            // Drag object
429
0
                            bFirstMouseMove = true;
430
0
                            aDragTimer.Start();
431
0
                        }
432
433
0
                        if ( ! rMEvt.IsRight())
434
0
                        {
435
                            // we need to pick again since SdrEndTextEdit can rebuild the handles list
436
0
                            eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
437
0
                            if( (eHit == SdrHitKind::Handle) || (eHit == SdrHitKind::MarkedObject) )
438
0
                            {
439
0
                                sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
440
0
                                mpView->BegDragObj(aMDPos, nullptr, aVEvt.mpHdl, nDrgLog);
441
0
                            }
442
0
                        }
443
0
                        bReturn = true;
444
0
                    }
445
0
                }
446
0
                else if ( nSlotId != SID_TEXTEDIT &&
447
0
                          (bPermanent || !bFirstObjCreated) )
448
0
                {
449
                    // create object
450
0
                    mpView->SetCurrentObj(SdrObjKind::Text);
451
0
                    mpView->SetEditMode(SdrViewEditMode::Create);
452
0
                    sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
453
0
                    mpView->BegCreateObj(aMDPos, nullptr, nDrgLog);
454
0
                }
455
0
                else
456
0
                {
457
                    // select
458
0
                    if( !rMEvt.IsShift() )
459
0
                        mpView->UnmarkAll();
460
461
0
                    mpView->BegMarkObj( aMDPos );
462
0
                }
463
0
            }
464
0
        }
465
0
    }
466
0
    else if ( rMEvt.GetClicks() == 2 && !mpView->IsTextEdit() )
467
0
    {
468
0
        MouseEvent aMEvt( mpWindow->GetPointerPosPixel() );
469
0
        SetInEditMode( aMEvt, false );
470
0
    }
471
472
0
    if (!bIsInDragMode)
473
0
    {
474
0
        ForcePointer(&rMEvt);
475
0
        mrViewShell.GetViewFrame()->GetBindings().Invalidate(SidArray);
476
0
    }
477
478
0
    return bReturn;
479
0
}
480
481
bool FuText::MouseMove(const MouseEvent& rMEvt)
482
0
{
483
0
    bool bReturn = FuDraw::MouseMove(rMEvt);
484
485
0
    if (aDragTimer.IsActive() )
486
0
    {
487
0
        if( bFirstMouseMove )
488
0
            bFirstMouseMove = false;
489
0
        else
490
0
            aDragTimer.Stop();
491
0
    }
492
493
0
    if (!bReturn && mpView->IsAction() && !mpDocSh->IsReadOnly())
494
0
    {
495
0
        Point aPix(rMEvt.GetPosPixel());
496
0
        Point aPnt(mpWindow->PixelToLogic(aPix));
497
498
0
        ForceScroll(aPix);
499
0
        mpView->MovAction(aPnt);
500
0
    }
501
502
0
    ForcePointer(&rMEvt);
503
504
0
    return bReturn;
505
0
}
506
507
void FuText::ImpSetAttributesForNewTextObject(SdrTextObj* pTxtObj)
508
0
{
509
0
    if( nSlotId == SID_ATTR_CHAR )
510
0
    {
511
0
        SfxItemSet aSet(mrViewShell.GetPool());
512
0
        aSet.Put(makeSdrTextAutoGrowWidthItem(false));
513
0
        aSet.Put(makeSdrTextAutoGrowHeightItem(true));
514
0
        pTxtObj->SetMergedItemSet(aSet);
515
0
        pTxtObj->AdjustTextFrameWidthAndHeight();
516
0
        const SfxViewShell* pCurrentViewShell = SfxViewShell::Current();
517
0
        if (pCurrentViewShell && (pCurrentViewShell->isLOKMobilePhone() || pCurrentViewShell->isLOKTablet()))
518
0
            pTxtObj->SetText(SdResId(STR_PRESOBJ_TEXT_EDIT_MOBILE));
519
0
    }
520
0
    else if( nSlotId == SID_ATTR_CHAR_VERTICAL )
521
0
    {
522
        // draw text object, needs to be initialized when vertical text is used
523
0
        SfxItemSet aSet(mrViewShell.GetPool());
524
525
0
        aSet.Put(makeSdrTextAutoGrowWidthItem(true));
526
0
        aSet.Put(makeSdrTextAutoGrowHeightItem(false));
527
528
        // Set defaults for vertical click-n'drag text object, pool defaults are:
529
        // SdrTextVertAdjustItem: SDRTEXTVERTADJUST_TOP
530
        // SdrTextHorzAdjustItem: SDRTEXTHORZADJUST_BLOCK
531
        // Analog to that:
532
0
        aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK));
533
0
        aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
534
535
0
        pTxtObj->SetMergedItemSet(aSet);
536
0
        pTxtObj->AdjustTextFrameWidthAndHeight();
537
0
    }
538
0
}
539
540
void FuText::ImpSetAttributesFitToSize(SdrTextObj* pTxtObj)
541
0
{
542
    // FitToSize (fit to frame)
543
0
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>(mrViewShell.GetPool()));
544
0
    aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL));
545
0
    aSet.Put(makeSdrTextAutoGrowHeightItem(false));
546
0
    aSet.Put(makeSdrTextAutoGrowWidthItem(false));
547
0
    pTxtObj->SetMergedItemSet(aSet);
548
0
    pTxtObj->AdjustTextFrameWidthAndHeight();
549
0
}
550
551
void FuText::ImpSetAttributesFitToSizeVertical(SdrTextObj* pTxtObj)
552
0
{
553
0
    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWWIDTH>(mrViewShell.GetPool()));
554
0
    aSet.Put(SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_PROPORTIONAL));
555
0
    aSet.Put(makeSdrTextAutoGrowHeightItem(false));
556
0
    aSet.Put(makeSdrTextAutoGrowWidthItem(false));
557
0
    pTxtObj->SetMergedItemSet(aSet);
558
0
    pTxtObj->AdjustTextFrameWidthAndHeight();
559
0
}
560
561
bool FuText::MouseButtonUp(const MouseEvent& rMEvt)
562
0
{
563
0
    bool bReturn = false;
564
0
    if (aDragTimer.IsActive())
565
0
    {
566
0
        aDragTimer.Stop();
567
0
        bIsInDragMode = false;
568
0
    }
569
570
0
    mrViewShell.GetViewFrame()->GetBindings().Invalidate( SidArray );
571
572
0
    Point aPnt( mpWindow->PixelToLogic( rMEvt.GetPosPixel() ) );
573
574
0
    if( (mpView && mpView->MouseButtonUp(rMEvt, mpWindow->GetOutDev())) || rMEvt.GetClicks() == 2 )
575
0
        return true; // handle event from SdrView
576
577
0
    bool bEmptyTextObj = false;
578
579
0
    if (mxTextObj.get().is())
580
0
    {
581
0
        bool bReset = true;
582
583
0
        if (mpView)
584
0
        {
585
0
            const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
586
587
0
            if (rMarkList.GetMarkCount() == 1
588
0
                && ( rMarkList.GetMark(0)->GetMarkedSdrObj() == mxTextObj.get().get()) )
589
0
            {
590
0
                if (!GetTextObj()->GetOutlinerParaObject() )
591
0
                    bEmptyTextObj = true;
592
0
                else
593
0
                    bFirstObjCreated = true;
594
0
                bReset = false;
595
0
            }
596
0
        }
597
598
0
        if (bReset)
599
0
        {
600
0
            mxTextObj = nullptr;
601
0
        }
602
0
    }
603
604
0
    if (rMEvt.IsLeft() && !mxTextObj.get().is() && IsIgnoreUnexpectedMouseButtonUp())
605
0
        return false;
606
607
0
    if( mpView && mpView->IsDragObj())
608
0
    {
609
        // object was moved
610
0
        FrameView* pFrameView = mrViewShell.GetFrameView();
611
0
        bool bDragWithCopy = (rMEvt.IsMod1() && pFrameView->IsDragWithCopy());
612
613
0
        if (bDragWithCopy)
614
0
        {
615
0
            bDragWithCopy = !mpView->IsPresObjSelected(false);
616
0
        }
617
618
0
        mpView->SetDragWithCopy(bDragWithCopy);
619
0
        mpView->EndDragObj( mpView->IsDragWithCopy() );
620
0
        mpView->ForceMarkedToAnotherPage();
621
0
        mpView->SetCurrentObj(SdrObjKind::Text);
622
623
0
        sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
624
625
0
        if (bJustEndedEdit)
626
0
        {
627
0
            bJustEndedEdit = false;
628
0
            FuPoor::cancel();
629
0
        }
630
0
        if ((rMEvt.GetClicks() != 2) &&
631
0
            !rMEvt.IsShift() && !rMEvt.IsMod1() && !rMEvt.IsMod2() && !rMEvt.IsRight() &&
632
0
            std::abs(aPnt.X() - aMDPos.X()) < nDrgLog &&
633
0
            std::abs(aPnt.Y() - aMDPos.Y()) < nDrgLog)
634
0
        {
635
            /*************************************************************
636
            * From text mode, you don't want to rotate immediately.
637
            **************************************************************/
638
0
            SdrPageView* pPV;
639
0
            SdrObject* pObj = mpView->PickObj(aMDPos, mpView->getHitTolLog(), pPV, SdrSearchOptions::ALSOONMASTER | SdrSearchOptions::BEFOREMARK);
640
0
            if (pObj && pPV->IsObjMarkable(pObj))
641
0
            {
642
0
                mpView->UnmarkAllObj();
643
0
                mpView->MarkObj(pObj,pPV);
644
0
                return bReturn;
645
0
            }
646
0
        }
647
0
    }
648
0
    else if( mpView && mpView->IsCreateObj() && rMEvt.IsLeft())
649
0
    {
650
        // object was created
651
0
        rtl::Reference<SdrTextObj> pTextObj = DynCastSdrTextObj( mpView->GetCreateObj() );
652
0
        mxTextObj = pTextObj.get();
653
654
0
        if( pTextObj )
655
0
        {
656
            //AW outliner needs to be set to vertical when there is no
657
            // outliner object up to now; also it needs to be set back to not
658
            // vertical when there was a vertical one used last time.
659
0
            OutlinerParaObject* pOPO = GetTextObj()->GetOutlinerParaObject();
660
0
            SdrOutliner& rOutl(pTextObj->getSdrModelFromSdrObject().GetDrawOutliner(GetTextObj()));
661
0
            bool bVertical((pOPO && pOPO->IsEffectivelyVertical())
662
0
                || nSlotId == SID_ATTR_CHAR_VERTICAL
663
0
                || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL);
664
0
            rOutl.SetVertical(bVertical);
665
666
            // Before ImpSetAttributesForNewTextObject the vertical writing mode
667
            // needs to be set at the object. This is done here at the OutlinerParaObject
668
            // directly to not mirror the layout text items involved. These items will be set
669
            // from ImpSetAttributesForNewTextObject and below.
670
0
            OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject();
671
672
0
            if(!pPara)
673
0
            {
674
0
                GetTextObj()->ForceOutlinerParaObject();
675
0
                pPara = GetTextObj()->GetOutlinerParaObject();
676
0
            }
677
678
0
            if(pPara && bVertical != pPara->IsEffectivelyVertical())
679
0
            {
680
                // set ParaObject orientation accordingly
681
0
                pPara->SetVertical(bVertical);
682
0
            }
683
684
0
            ImpSetAttributesForNewTextObject(GetTextObj());
685
0
        }
686
687
0
        if (!mpView->EndCreateObj(SdrCreateCmd::ForceEnd))
688
0
        {
689
            // it was not possible to create text object
690
0
            mxTextObj = nullptr;
691
0
            pTextObj = nullptr;
692
0
        }
693
0
        else if (nSlotId == SID_TEXT_FITTOSIZE)
694
0
        {
695
0
            ImpSetAttributesFitToSize(GetTextObj());
696
697
0
            SetInEditMode(rMEvt, false);
698
0
        }
699
0
        else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL )
700
0
        {
701
0
            ImpSetAttributesFitToSizeVertical(GetTextObj());
702
703
0
            SetInEditMode(rMEvt, false);
704
0
        }
705
0
        else
706
0
        {
707
            // thereby the handles and the gray frame are correct
708
0
            mpView->AdjustMarkHdl();
709
0
            mpView->PickHandle(aPnt);
710
0
            SetInEditMode(rMEvt, false);
711
0
        }
712
0
    }
713
0
    else if ( mpView && mpView->IsAction())
714
0
    {
715
0
        mpView->EndAction();
716
0
    }
717
718
0
    ForcePointer(&rMEvt);
719
0
    mpWindow->ReleaseMouse();
720
721
0
    if (mpView)
722
0
    {
723
0
        const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
724
0
        if ( rMarkList.GetMarkCount() == 0 )
725
0
        {
726
0
            sal_uInt16 nDrgLog1 = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
727
0
            if ( std::abs(aMDPos.X() - aPnt.X()) < nDrgLog1 &&
728
0
                 std::abs(aMDPos.Y() - aPnt.Y()) < nDrgLog1 &&
729
0
                 !rMEvt.IsShift() && !rMEvt.IsMod2() )
730
0
            {
731
0
                SdrPageView* pPV2 = mpView->GetSdrPageView();
732
0
                SdrViewEvent aVEvt;
733
0
                mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
734
0
                mpView->MarkObj(aVEvt.mpRootObj, pPV2);
735
0
            }
736
0
        }
737
0
    }
738
739
0
    if ( !mxTextObj.get().is() && mpView )
740
0
    {
741
0
        if ( ( (!bEmptyTextObj   &&  bPermanent) ||
742
0
             (!bFirstObjCreated && !bPermanent) ) &&
743
0
              !mpDocSh->IsReadOnly()               &&
744
0
              nSlotId != SID_TEXTEDIT )
745
0
        {
746
            // text body (left-justified AutoGrow)
747
0
            mpView->SetCurrentObj(SdrObjKind::Text);
748
0
            mpView->SetEditMode(SdrViewEditMode::Create);
749
0
            sal_uInt16 nDrgLog = sal_uInt16 ( mpWindow->PixelToLogic(Size(mpView->GetDragThresholdPixels(),0)).Width() );
750
0
            mpView->BegCreateObj(aMDPos, nullptr, nDrgLog);
751
752
0
            bool bSnapEnabled = mpView->IsSnapEnabled();
753
754
0
            if (bSnapEnabled)
755
0
                mpView->SetSnapEnabled(false);
756
757
0
            aPnt.AdjustX(nDrgLog + nDrgLog );
758
0
            aPnt.AdjustY(nDrgLog + nDrgLog );
759
0
            mpView->MovAction(aPnt);
760
761
0
            mxTextObj = DynCastSdrTextObj( mpView->GetCreateObj() );
762
763
0
            if(mxTextObj.get().is())
764
0
            {
765
0
                GetTextObj()->SetDisableAutoWidthOnDragging(true);
766
0
            }
767
768
0
            if(!mpView->EndCreateObj(SdrCreateCmd::ForceEnd))
769
0
            {
770
0
                mxTextObj.clear();
771
0
            }
772
773
0
            if(bSnapEnabled)
774
0
                mpView->SetSnapEnabled(bSnapEnabled);
775
776
0
            if(mxTextObj.get().is())
777
0
            {
778
0
                SfxItemSet aSet(mrViewShell.GetPool());
779
0
                aSet.Put(makeSdrTextMinFrameHeightItem(0));
780
0
                aSet.Put(makeSdrTextMinFrameWidthItem(0));
781
0
                aSet.Put(makeSdrTextAutoGrowHeightItem(true));
782
0
                aSet.Put(makeSdrTextAutoGrowWidthItem(true));
783
784
0
                if(nSlotId == SID_ATTR_CHAR_VERTICAL)
785
0
                {
786
                    // Here, all items which need to be different from pool default need to be set
787
                    // again on the newly created text object.
788
                    // Since this is a simple click text object, it is first created, then SetVertical()
789
                    // is used, then ImpSetAttributesForNewTextObject is called and then the object is
790
                    // deleted again since not the minimum drag distance was travelled. Then, a new
791
                    // click text object is created and thus all that stuff needs to be set again here.
792
793
                    // Before using the new object the vertical writing mode
794
                    // needs to be set. This is done here at the OutlinerParaObject
795
                    // directly to not mirror the layout text items involved. These items will be set
796
                    // below.
797
0
                    OutlinerParaObject* pPara = GetTextObj()->GetOutlinerParaObject();
798
799
0
                    if(!pPara)
800
0
                    {
801
0
                        GetTextObj()->ForceOutlinerParaObject();
802
0
                        pPara = GetTextObj()->GetOutlinerParaObject();
803
0
                    }
804
805
0
                    if(pPara && !pPara->IsEffectivelyVertical())
806
0
                    {
807
                        // set ParaObject orientation accordingly
808
0
                        pPara->SetVertical(true);
809
0
                    }
810
811
0
                    aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
812
813
                    // Analog to the else case below, for vertical simple click texts
814
                    // one of the default set items from ImpSetAttributesForNewTextObject
815
                    // needs to be adapted to non-block mode.
816
0
                    const SfxItemSet& rSet = mpView->GetDefaultAttr();
817
0
                    SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue();
818
819
0
                    if(SvxFrameDirection::Horizontal_RL_TB == eDirection || SvxFrameDirection::Vertical_RL_TB == eDirection)
820
0
                    {
821
0
                        aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM));
822
0
                    }
823
0
                    else
824
0
                    {
825
0
                        aSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP));
826
0
                    }
827
0
                }
828
0
                else
829
0
                {
830
                    // This is for Format/Page settings. Since this also leads
831
                    // to the object defaults to be changed, i think this code can be
832
                    // removed. CL. wanted to take a look before adding this.
833
834
                    // Look in the object defaults if left-to-right is wanted. If
835
                    // yes, set text anchoring to right to let the box grow to left.
836
0
                    const SfxItemSet& rSet = mpView->GetDefaultAttr();
837
0
                    SvxFrameDirection eDirection = rSet.Get(EE_PARA_WRITINGDIR).GetValue();
838
839
0
                    if(SvxFrameDirection::Horizontal_RL_TB == eDirection)
840
0
                    {
841
0
                        aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT));
842
0
                    }
843
0
                    else
844
0
                    {
845
0
                        aSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT));
846
0
                    }
847
0
                }
848
849
0
                GetTextObj()->SetMergedItemSet(aSet);
850
0
                GetTextObj()->SetDisableAutoWidthOnDragging(true);
851
0
                SetInEditMode(rMEvt, false);
852
0
            }
853
854
0
            bFirstObjCreated = true;
855
0
        }
856
0
        else
857
0
        {
858
            // switch to selection
859
0
            if (mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
860
0
            {
861
0
                mxTextObj = nullptr;
862
0
            }
863
864
0
            mrViewShell.GetViewFrame()->GetDispatcher()->Execute( SID_OBJECT_SELECT,
865
0
                                      SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
866
0
        }
867
0
    }
868
0
    if (bJustEndedEdit)
869
0
    {
870
0
        bJustEndedEdit = false;
871
0
        FuPoor::cancel();
872
0
    }
873
0
    bMBDown = false;
874
0
    FuConstruct::MouseButtonUp(rMEvt);
875
0
    return bReturn;
876
0
}
877
878
/**
879
 * handle keyboard events
880
 * @returns sal_True if the event was handled, sal_False otherwise
881
 */
882
bool FuText::KeyInput(const KeyEvent& rKEvt)
883
0
{
884
0
    bool bReturn = false;
885
886
0
    vcl::KeyCode nCode = rKEvt.GetKeyCode();
887
0
    bool bShift = nCode.IsShift();
888
889
0
    if(mxTextObj.get().is())
890
0
    {
891
        // maybe object is deleted, test if it's equal to the selected object
892
0
        const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
893
0
        SdrObject* pSelectedObj = nullptr;
894
895
0
        if(1 == rMarkList.GetMarkCount())
896
0
        {
897
0
            SdrMark* pMark = rMarkList.GetMark(0);
898
0
            pSelectedObj = pMark->GetMarkedSdrObj();
899
0
        }
900
901
0
        if(mxTextObj.get().get() != pSelectedObj)
902
0
        {
903
0
            mxTextObj = nullptr;
904
0
        }
905
0
    }
906
907
0
    if (auto pTextObj = mxTextObj.get())
908
0
        if ( pTextObj->GetObjInventor() == SdrInventor::Default && pTextObj->GetObjIdentifier() == SdrObjKind::TitleText && rKEvt.GetKeyCode().GetCode() == KEY_RETURN )
909
0
        {
910
            // title text object: always soft breaks
911
0
            bShift = true;
912
0
        }
913
914
0
    sal_uInt16 nKey = nCode.GetCode();
915
0
    vcl::KeyCode aKeyCode (nKey, bShift, nCode.IsMod1(), nCode.IsMod2(), nCode.IsMod3() );
916
0
    KeyEvent aKEvt(rKEvt.GetCharCode(), aKeyCode);
917
918
0
    bool bOK = true;
919
920
0
    if (mpDocSh->IsReadOnly())
921
0
    {
922
0
        bOK = !EditEngine::DoesKeyChangeText(aKEvt);
923
0
    }
924
0
    if( aKeyCode.GetCode() == KEY_PAGEUP || aKeyCode.GetCode() == KEY_PAGEDOWN )
925
0
    {
926
0
        bOK = false;   // default handling in base class
927
0
    }
928
929
0
    if (bOK && mpView->KeyInput(aKEvt, mpWindow) )
930
0
    {
931
0
        bReturn = true;
932
933
0
        mrViewShell.GetViewFrame()->GetBindings().Invalidate( SidArray );
934
935
0
    }
936
0
    else if (aKeyCode == KEY_ESCAPE)
937
0
    {
938
0
        bReturn = cancel();
939
0
    }
940
941
0
    if( bPermanent )
942
0
    {
943
0
        mpView->SetCurrentObj(SdrObjKind::Text);
944
0
        mpView->SetEditMode(SdrViewEditMode::Create);
945
0
    }
946
947
0
    if (!bReturn)
948
0
    {
949
0
        bReturn = FuDraw::KeyInput(aKEvt);
950
0
    }
951
952
0
    return bReturn;
953
0
}
954
955
void FuText::Activate()
956
0
{
957
0
    mpView->SetQuickTextEditMode(mrViewShell.GetFrameView()->IsQuickEdit());
958
959
    // #i89661# it's no longer necessary to make it so big here, it's fine tuned
960
    // for text objects in SdrMarkView::CheckSingleSdrObjectHit
961
0
    mpView->SetHitTolerancePixel( 2 * HITPIX );
962
963
0
    OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
964
965
0
    if (pOLV)
966
0
        pOLV->ShowCursor(/*bGotoCursor=*/true, /*bActivate=*/true);
967
968
0
    FuConstruct::Activate();
969
970
0
    if( pOLV )
971
0
        mpView->SetEditMode(SdrViewEditMode::Edit);
972
0
}
973
974
void FuText::Deactivate()
975
0
{
976
0
    OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
977
978
0
    if (pOLV)
979
0
        pOLV->HideCursor(/*bDeactivate=*/true);
980
981
0
    mpView->SetHitTolerancePixel( HITPIX );
982
983
0
    FuConstruct::Deactivate();
984
0
}
985
986
/**
987
 * Sets the object into the edit mode.
988
 */
989
void FuText::SetInEditMode(const MouseEvent& rMEvt, bool bQuickDrag)
990
0
{
991
0
    SdrPageView* pPV = mpView->GetSdrPageView();
992
0
    if( mxTextObj.get().is() && (mxTextObj.get()->getSdrPageFromSdrObject() == pPV->GetPage()) )
993
0
    {
994
0
        mpView->SetCurrentObj(SdrObjKind::Text);
995
996
0
        if( bPermanent )
997
0
            mpView->SetEditMode(SdrViewEditMode::Create);
998
0
        else
999
0
            mpView->SetEditMode(SdrViewEditMode::Edit);
1000
1001
0
        bool bEmptyOutliner = false;
1002
1003
0
        if (!GetTextObj()->GetOutlinerParaObject() && mpView->GetTextEditOutliner())
1004
0
        {
1005
0
            ::Outliner* pOutl = mpView->GetTextEditOutliner();
1006
0
            sal_Int32 nParagraphCnt = pOutl->GetParagraphCount();
1007
0
            Paragraph* p1stPara = pOutl->GetParagraph( 0 );
1008
1009
0
            if (nParagraphCnt==1 && p1stPara)
1010
0
            {
1011
                // with only one paragraph
1012
0
                if (pOutl->GetText(p1stPara).isEmpty())
1013
0
                {
1014
0
                    bEmptyOutliner = true;
1015
0
                }
1016
0
            }
1017
0
        }
1018
1019
0
        if (GetTextObj() != mpView->GetTextEditObject() || bEmptyOutliner)
1020
0
        {
1021
0
            rtl::Reference<SdrTextObj> pTextObj = mxTextObj.get();
1022
0
            SdrInventor nInv = pTextObj->GetObjInventor();
1023
0
            SdrObjKind  nSdrObjKind = pTextObj->GetObjIdentifier();
1024
1025
0
            if (nInv == SdrInventor::Default && GetTextObj()->HasTextEdit() &&
1026
0
                (nSdrObjKind == SdrObjKind::Text ||
1027
0
                 nSdrObjKind == SdrObjKind::TitleText ||
1028
0
                 nSdrObjKind == SdrObjKind::OutlineText || !pTextObj->IsEmptyPresObj() ) )
1029
0
            {
1030
                // create new outliner (owned by SdrObjEditView)
1031
0
                std::unique_ptr<SdrOutliner> pOutl = SdrMakeOutliner(OutlinerMode::OutlineObject, mrDoc);
1032
1033
0
                if (bEmptyOutliner)
1034
0
                    mpView->SdrEndTextEdit(true);
1035
1036
0
                pTextObj = GetTextObj();
1037
0
                if( pTextObj )
1038
0
                {
1039
0
                    OutlinerParaObject* pOPO = pTextObj->GetOutlinerParaObject();
1040
0
                    if( pOPO && pOPO->IsEffectivelyVertical() )
1041
0
                    {
1042
0
                        pOutl->SetVertical(pOPO->GetVertical());
1043
0
                        pOutl->SetRotation(pOPO->GetRotation());
1044
0
                    }
1045
0
                    else if (nSlotId == SID_ATTR_CHAR_VERTICAL || nSlotId == SID_TEXT_FITTOSIZE_VERTICAL)
1046
0
                        pOutl->SetVertical( true );
1047
1048
0
                    if( pTextObj->getTextCount() > 1 )
1049
0
                    {
1050
0
                        Point aPix(rMEvt.GetPosPixel());
1051
0
                        Point aPnt(mpWindow->PixelToLogic(aPix));
1052
0
                        pTextObj->setActiveText( pTextObj->CheckTextHit(aPnt ) );
1053
0
                    }
1054
1055
0
                    if (mpView->SdrBeginTextEdit(pTextObj.get(), pPV, mpWindow, true, pOutl.release()) && mxTextObj.get()->GetObjInventor() == SdrInventor::Default)
1056
0
                    {
1057
0
                        bFirstObjCreated = true;
1058
0
                        DeleteDefaultText();
1059
1060
0
                        OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1061
1062
0
                        nSdrObjKind = mxTextObj.get()->GetObjIdentifier();
1063
1064
0
                        SdrViewEvent aVEvt;
1065
0
                        SdrHitKind eHit = mpView->PickAnything(rMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
1066
1067
0
                        if (eHit == SdrHitKind::TextEdit)
1068
0
                        {
1069
                            // hit text
1070
0
                            if (nSdrObjKind == SdrObjKind::Text ||
1071
0
                                nSdrObjKind == SdrObjKind::TitleText ||
1072
0
                                nSdrObjKind == SdrObjKind::OutlineText ||
1073
0
                                nSdrObjKind == SdrObjKind::Table ||
1074
0
                                nSlotId == SID_TEXTEDIT ||
1075
0
                                !bQuickDrag)
1076
0
                            {
1077
0
                                pOLV->MouseButtonDown(rMEvt);
1078
0
                                pOLV->MouseMove(rMEvt);
1079
0
                                pOLV->MouseButtonUp(rMEvt);
1080
0
                            }
1081
1082
0
                            if (mrViewShell.GetFrameView()->IsQuickEdit() && bQuickDrag && GetTextObj()->GetOutlinerParaObject())
1083
0
                            {
1084
0
                                pOLV->MouseButtonDown(rMEvt);
1085
0
                            }
1086
0
                        }
1087
0
                        else
1088
0
                        {
1089
                            // Move cursor to end of text
1090
0
                            if (pOLV != nullptr)
1091
0
                                pOLV->SetSelection(ESelection::AtEnd());
1092
0
                        }
1093
0
                    }
1094
0
                    else
1095
0
                    {
1096
0
                        mpView->RestoreDefaultText( mxTextObj.get().get() );
1097
0
                    }
1098
0
                }
1099
0
            }
1100
0
        }
1101
0
    }
1102
0
    else
1103
0
    {
1104
0
        mxTextObj = nullptr;
1105
0
    }
1106
0
}
1107
1108
/**
1109
 * Text entry is started, if necessary delete the default text.
1110
 */
1111
void FuText::DeleteDefaultText()
1112
0
{
1113
0
    if ( !(mxTextObj.get().is() && mxTextObj.get()->IsEmptyPresObj()) )
1114
0
        return;
1115
1116
0
    SdPage* pPage = static_cast<SdPage*>( mxTextObj.get()->getSdrPageFromSdrObject() );
1117
1118
0
    if (!pPage)
1119
0
        return;
1120
1121
0
    PresObjKind ePresObjKind = pPage->GetPresObjKind(mxTextObj.get().get());
1122
1123
0
    if ( !(ePresObjKind == PresObjKind::Title   ||
1124
0
           ePresObjKind == PresObjKind::Outline ||
1125
0
           ePresObjKind == PresObjKind::Notes   ||
1126
0
           ePresObjKind == PresObjKind::Text      ) ||
1127
0
          pPage->IsMasterPage() )
1128
0
        return;
1129
1130
0
    ::Outliner* pOutliner = mpView->GetTextEditOutliner();
1131
0
    SfxStyleSheet* pSheet = pOutliner->GetStyleSheet( 0 );
1132
0
    bool bIsUndoEnabled = pOutliner->IsUndoEnabled();
1133
0
    if( bIsUndoEnabled )
1134
0
        pOutliner->EnableUndo(false);
1135
1136
0
    pOutliner->SetText( OUString(), pOutliner->GetParagraph( 0 ) );
1137
1138
0
    if( bIsUndoEnabled )
1139
0
        pOutliner->EnableUndo(true);
1140
1141
0
    if (pSheet &&
1142
0
        (ePresObjKind == PresObjKind::Notes || ePresObjKind == PresObjKind::Text))
1143
0
        pOutliner->SetStyleSheet(0, pSheet);
1144
1145
0
    mxTextObj.get()->SetEmptyPresObj(true);
1146
0
}
1147
1148
bool FuText::RequestHelp(const HelpEvent& rHEvt)
1149
0
{
1150
0
    bool bReturn = false;
1151
1152
0
    OutlinerView* pOLV = mpView->GetTextEditOutlinerView();
1153
1154
0
    if ((Help::IsBalloonHelpEnabled() || Help::IsQuickHelpEnabled()) &&
1155
0
        mxTextObj.get().is() && pOLV && pOLV->GetFieldUnderMousePointer())
1156
0
    {
1157
0
        OUString aHelpText;
1158
0
        const SvxFieldItem* pFieldItem = pOLV->GetFieldUnderMousePointer();
1159
0
        const SvxFieldData* pField = pFieldItem->GetField();
1160
1161
0
        if (auto pURLField = dynamic_cast< const SvxURLField *>( pField ))
1162
0
        {
1163
            // URL-Field
1164
0
            aHelpText = INetURLObject::decode( pURLField->GetURL(), INetURLObject::DecodeMechanism::WithCharset );
1165
0
        }
1166
0
        if (!aHelpText.isEmpty())
1167
0
        {
1168
0
            ::tools::Rectangle aLogicPix = mpWindow->LogicToPixel(mxTextObj.get()->GetLogicRect());
1169
0
            ::tools::Rectangle aScreenRect(mpWindow->OutputToScreenPixel(aLogicPix.TopLeft()),
1170
0
                                  mpWindow->OutputToScreenPixel(aLogicPix.BottomRight()));
1171
1172
0
            if (Help::IsBalloonHelpEnabled())
1173
0
            {
1174
0
                Help::ShowBalloon( static_cast<vcl::Window*>(mpWindow), rHEvt.GetMousePosPixel(), aScreenRect, aHelpText);
1175
0
                bReturn = true;
1176
0
            }
1177
0
            else if (Help::IsQuickHelpEnabled())
1178
0
            {
1179
0
                Help::ShowQuickHelp( static_cast<vcl::Window*>(mpWindow), aScreenRect, aHelpText);
1180
0
                bReturn = true;
1181
0
            }
1182
0
        }
1183
0
    }
1184
1185
0
    if (!bReturn)
1186
0
    {
1187
0
        bReturn = FuConstruct::RequestHelp(rHEvt);
1188
0
    }
1189
1190
0
    return bReturn;
1191
0
}
1192
1193
void FuText::ReceiveRequest(SfxRequest& rReq)
1194
0
{
1195
0
    nSlotId = rReq.GetSlot();
1196
1197
    // then we call the base class (besides others, nSlotId is NOT set there)
1198
0
    FuPoor::ReceiveRequest(rReq);
1199
1200
0
    if (!(nSlotId == SID_TEXTEDIT || mrViewShell.GetFrameView()->IsQuickEdit() || SID_ATTR_CHAR == nSlotId))
1201
0
        return;
1202
1203
0
    MouseEvent aMEvt(mpWindow->GetPointerPosPixel());
1204
1205
0
    mxTextObj = nullptr;
1206
0
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
1207
1208
0
    if (nSlotId == SID_TEXTEDIT)
1209
0
    {
1210
        // are we currently editing?
1211
0
        mxTextObj = mpView->GetTextEditObject();
1212
1213
0
        if (!mxTextObj.get().is())
1214
0
        {
1215
            // Try to select an object
1216
0
            SdrPageView* pPV = mpView->GetSdrPageView();
1217
0
            SdrViewEvent aVEvt;
1218
0
            mpView->PickAnything(aMEvt, SdrMouseEventKind::BUTTONDOWN, aVEvt);
1219
0
            mpView->MarkObj(aVEvt.mpRootObj, pPV);
1220
1221
0
            if (auto pSdrTextObj = DynCastSdrTextObj(aVEvt.mpObj))
1222
0
            {
1223
0
                mxTextObj = pSdrTextObj;
1224
0
            }
1225
0
        }
1226
0
    }
1227
0
    else if (rMarkList.GetMarkCount() != 0)
1228
0
    {
1229
1230
0
        if (rMarkList.GetMarkCount() == 1)
1231
0
        {
1232
0
            SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
1233
1234
0
            if( auto pTextObj = DynCastSdrTextObj( pObj ))
1235
0
            {
1236
0
                mxTextObj = pTextObj;
1237
0
            }
1238
0
        }
1239
0
    }
1240
1241
0
    bool bQuickDrag = true;
1242
1243
0
    const SfxItemSet* pArgs = rReq.GetArgs();
1244
1245
0
    if (pArgs
1246
1247
        // test for type before using
1248
0
        && SID_TEXTEDIT == nSlotId
1249
0
        && SfxItemState::SET == pArgs->GetItemState(SID_TEXTEDIT)
1250
1251
0
        && pArgs->Get(SID_TEXTEDIT).GetValue() == 2)
1252
0
    {
1253
        // selection with double click -> do not allow QuickDrag
1254
0
        bQuickDrag = false;
1255
0
    }
1256
1257
0
    SetInEditMode(aMEvt, bQuickDrag);
1258
0
}
1259
1260
void FuText::DoubleClick(const MouseEvent& )
1261
0
{
1262
    // Nothing to do
1263
0
}
1264
1265
/** Removed the insertion of default text and putting a new text
1266
    object directly into edit mode.
1267
*/
1268
rtl::Reference<SdrObject> FuText::CreateDefaultObject(const sal_uInt16 nID, const ::tools::Rectangle& rRectangle)
1269
0
{
1270
0
    rtl::Reference<SdrObject> pObj( SdrObjFactory::MakeNewObject(
1271
0
        mpView->getSdrModelFromSdrView(),
1272
0
        mpView->GetCurrentObjInventor(),
1273
0
        mpView->GetCurrentObjIdentifier(),
1274
0
        nullptr) );
1275
1276
0
    if(pObj)
1277
0
    {
1278
0
        if( auto pText = DynCastSdrTextObj( pObj.get() ) )
1279
0
        {
1280
0
            pText->SetLogicRect(rRectangle);
1281
1282
0
            bool bVertical = (SID_ATTR_CHAR_VERTICAL == nID || SID_TEXT_FITTOSIZE_VERTICAL == nID);
1283
0
            pText->SetVerticalWriting(bVertical);
1284
1285
0
            ImpSetAttributesForNewTextObject(pText);
1286
1287
0
            if (nSlotId == SID_TEXT_FITTOSIZE)
1288
0
            {
1289
0
                ImpSetAttributesFitToSize(pText);
1290
0
            }
1291
0
            else if ( nSlotId == SID_TEXT_FITTOSIZE_VERTICAL )
1292
0
            {
1293
0
                ImpSetAttributesFitToSizeVertical(pText);
1294
0
            }
1295
1296
            // Put text object into edit mode.
1297
0
            SdrPageView* pPV = mpView->GetSdrPageView();
1298
0
            mpView->SdrBeginTextEdit(pText, pPV);
1299
0
        }
1300
0
        else
1301
0
        {
1302
0
            OSL_FAIL("Object is NO text object");
1303
0
        }
1304
0
    }
1305
1306
0
    return pObj;
1307
0
}
1308
1309
/** is called when the current function should be aborted. <p>
1310
    This is used when a function gets a KEY_ESCAPE but can also
1311
    be called directly.
1312
1313
    @returns true if an active function was aborted
1314
*/
1315
bool FuText::cancel()
1316
0
{
1317
0
    if ( mpView->IsTextEdit() )
1318
0
    {
1319
0
        if(mpView->SdrEndTextEdit() == SdrEndTextEditKind::Deleted)
1320
0
            mxTextObj = nullptr;
1321
1322
0
        mpView->SetCurrentObj(SdrObjKind::Text);
1323
0
        mpView->SetEditMode(SdrViewEditMode::Edit);
1324
0
        return true;
1325
0
    }
1326
0
    else
1327
0
    {
1328
0
        return false;
1329
0
    }
1330
0
}
1331
1332
void FuText::ChangeFontSize( bool bGrow, OutlinerView* pOLV, const FontList* pFontList, ::sd::View* pView )
1333
0
{
1334
0
    if( !pFontList || !pView )
1335
0
        return;
1336
1337
0
    if( pOLV )
1338
0
    {
1339
0
        pOLV->GetEditView().ChangeFontSize( bGrow, pFontList );
1340
0
    }
1341
0
    else
1342
0
    {
1343
1344
0
        pView->BegUndo(SdResId(bGrow ? STR_GROW_FONT_SIZE : STR_SHRINK_FONT_SIZE));
1345
0
        const SdrMarkList& rMarkList = pView->GetMarkedObjectList();
1346
0
        for( size_t nMark = 0; nMark < rMarkList.GetMarkCount(); ++nMark )
1347
0
        {
1348
0
            SdrTextObj* pTextObj = DynCastSdrTextObj( rMarkList.GetMark(nMark)->GetMarkedSdrObj() );
1349
0
            if( pTextObj )
1350
0
            {
1351
0
                rtl::Reference<sdr::SelectionController> xSelectionController(pView->getSelectionController());
1352
0
                if (xSelectionController.is() && xSelectionController->ChangeFontSize(bGrow, pFontList))
1353
0
                {
1354
0
                    continue;
1355
0
                }
1356
0
                for( sal_Int32 nText = 0; nText < pTextObj->getTextCount(); nText++ )
1357
0
                {
1358
0
                    pTextObj->setActiveText( nText );
1359
1360
                    // Put text object into edit mode.
1361
0
                    SdrPageView* pPV = pView->GetSdrPageView();
1362
0
                    pView->SdrBeginTextEdit(pTextObj, pPV);
1363
1364
0
                    pOLV = pView->GetTextEditOutlinerView();
1365
0
                    if( pOLV )
1366
0
                    {
1367
0
                        pOLV->SetSelection(ESelection::All());
1368
1369
0
                        ChangeFontSize( bGrow, pOLV, pFontList, pView );
1370
0
                    }
1371
1372
0
                    pView->SdrEndTextEdit();
1373
0
                }
1374
1375
0
                SfxItemSet aShapeSet( pTextObj->GetMergedItemSet() );
1376
0
                if( EditView::ChangeFontSize( bGrow, aShapeSet, pFontList ) )
1377
0
                {
1378
0
                    pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT ) );
1379
0
                    pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CJK ) );
1380
0
                    pTextObj->SetObjectItemNoBroadcast( aShapeSet.Get( EE_CHAR_FONTHEIGHT_CTL ) );
1381
0
                }
1382
0
            }
1383
0
        }
1384
0
        pView->EndUndo();
1385
0
    }
1386
0
}
1387
1388
void FuText::InvalidateBindings()
1389
0
{
1390
0
    mrViewShell.GetViewFrame()->GetBindings().Invalidate(SidArray);
1391
0
}
1392
1393
1394
} // end of namespace sd
1395
1396
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */