Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/starmath/source/view.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 <com/sun/star/accessibility/AccessibleEventId.hpp>
23
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
24
#include <com/sun/star/frame/Desktop.hpp>
25
#include <com/sun/star/frame/XFramesSupplier.hpp>
26
#include <com/sun/star/frame/XModel.hpp>
27
#include <com/sun/star/container/XChild.hpp>
28
29
#include <comphelper/lok.hxx>
30
#include <comphelper/processfactory.hxx>
31
#include <comphelper/servicehelper.hxx>
32
#include <comphelper/storagehelper.hxx>
33
#include <comphelper/string.hxx>
34
#include <i18nutil/unicode.hxx>
35
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
36
#include <officecfg/Office/Common.hxx>
37
#include <sfx2/chalign.hxx>
38
#include <sfx2/dispatch.hxx>
39
#include <sfx2/docfile.hxx>
40
#include <sfx2/docfilt.hxx>
41
#include <sfx2/docinsert.hxx>
42
#include <sfx2/filedlghelper.hxx>
43
#include <sfx2/infobar.hxx>
44
#include <sfx2/lokcomponenthelpers.hxx>
45
#include <sfx2/lokhelper.hxx>
46
#include <sfx2/msg.hxx>
47
#include <sfx2/objface.hxx>
48
#include <sfx2/printer.hxx>
49
#include <sfx2/request.hxx>
50
#include <sfx2/sfxbasecontroller.hxx>
51
#include <sfx2/sidebar/Sidebar.hxx>
52
#include <sfx2/sidebar/SidebarChildWindow.hxx>
53
#include <sfx2/sidebar/SidebarController.hxx>
54
#include <sfx2/toolbarids.hxx>
55
#include <sfx2/viewfac.hxx>
56
#include <svl/eitem.hxx>
57
#include <svl/itemset.hxx>
58
#include <svl/poolitem.hxx>
59
#include <svl/stritem.hxx>
60
#include <svl/voiditem.hxx>
61
#include <vcl/transfer.hxx>
62
#include <svtools/colorcfg.hxx>
63
#include <svtools/dlgname.hxx>
64
#include <svl/whiter.hxx>
65
#include <svx/sidebar/SelectionChangeHandler.hxx>
66
#include <svx/zoomslideritem.hxx>
67
#include <editeng/editeng.hxx>
68
#include <editeng/editview.hxx>
69
#include <editeng/editund2.hxx>
70
#include <svx/svxdlg.hxx>
71
#include <sfx2/zoomitem.hxx>
72
#include <vcl/commandevent.hxx>
73
#include <vcl/event.hxx>
74
#include <vcl/help.hxx>
75
#include <vcl/settings.hxx>
76
#include <vcl/svapp.hxx>
77
#include <vcl/virdev.hxx>
78
#include <vcl/weld/MessageDialog.hxx>
79
#include <sal/log.hxx>
80
#include <tools/stream.hxx>
81
#include <tools/svborder.hxx>
82
#include <o3tl/string_view.hxx>
83
#include <o3tl/temporary.hxx>
84
85
#include <unotools/streamwrap.hxx>
86
87
#include <unomodel.hxx>
88
#include <view.hxx>
89
#include <cfgitem.hxx>
90
#include <dialog.hxx>
91
#include <document.hxx>
92
#include <starmath.hrc>
93
#include <strings.hrc>
94
#include <smmod.hxx>
95
#include <mathmlimport.hxx>
96
#include <cursor.hxx>
97
#include "accessibility.hxx"
98
#include <svl/hint.hxx>
99
#include <ElementsDockingWindow.hxx>
100
#include <helpids.h>
101
102
// space around the edit window, in pixels
103
// fdo#69111: Increased border on the top so that the window is
104
// easier to tear off.
105
0
#define CMD_BOX_PADDING 3
106
0
#define CMD_BOX_PADDING_TOP 11
107
108
#define ShellClass_SmViewShell
109
#include <smslots.hxx>
110
111
using namespace css;
112
using namespace css::accessibility;
113
using namespace css::uno;
114
115
static OUString GetScrollUIName(const SmViewShell& rShell)
116
0
{
117
0
    const SmDocShell* pShell = rShell.GetDoc();
118
0
    if (pShell && pShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
119
0
    {
120
        // This one has no border on the scrolledwindow, to maximize the space
121
        // available when in embedded mode and minimize the difference from
122
        // the ole preview to give a more seamless embedded editing experience.
123
0
        return "modules/smath/ui/embedwindow.ui";
124
0
    }
125
0
    return "modules/smath/ui/mathwindow.ui";
126
0
}
127
128
SmGraphicWindow::SmGraphicWindow(SmViewShell& rShell)
129
0
    : InterimItemWindow(&rShell.GetViewFrame().GetWindow(), GetScrollUIName(rShell), u"MathWindow"_ustr)
130
0
    , nLinePixH(GetSettings().GetStyleSettings().GetScrollBarSize())
131
0
    , nColumnPixW(nLinePixH)
132
0
    , nZoom(100)
133
    // continue to use user-scrolling to make this work equivalent to how it 'always' worked
134
0
    , mxScrolledWindow(m_xBuilder->weld_scrolled_window(u"scrolledwindow"_ustr, true))
135
0
    , mxGraphic(new SmGraphicWidget(rShell, *this))
136
0
    , mxGraphicWin(new weld::CustomWeld(*m_xBuilder, u"mathview"_ustr, *mxGraphic))
137
0
{
138
0
    InitControlBase(mxGraphic->GetDrawingArea());
139
140
0
    mxScrolledWindow->connect_hadjustment_value_changed(LINK(this, SmGraphicWindow, ScrollHdl));
141
0
    mxScrolledWindow->connect_vadjustment_value_changed(LINK(this, SmGraphicWindow, ScrollHdl));
142
143
    // docking windows are usually hidden (often already done in the
144
    // resource) and will be shown by the sfx framework.
145
0
    Hide();
146
0
}
Unexecuted instantiation: SmGraphicWindow::SmGraphicWindow(SmViewShell&)
Unexecuted instantiation: SmGraphicWindow::SmGraphicWindow(SmViewShell&)
147
148
void SmGraphicWindow::dispose()
149
0
{
150
0
    InitControlBase(nullptr);
151
0
    mxGraphicWin.reset();
152
0
    mxGraphic.reset();
153
0
    mxScrolledWindow.reset();
154
0
    InterimItemWindow::dispose();
155
0
}
156
157
SmGraphicWindow::~SmGraphicWindow()
158
0
{
159
0
    disposeOnce();
160
0
}
161
162
void SmGraphicWindow::Resize()
163
0
{
164
0
    InterimItemWindow::Resize();
165
166
    // get the new output-size in pixel
167
0
    Size aOutPixSz = GetOutputSizePixel();
168
169
    // determine the size of the output-area and if we need scrollbars
170
0
    const auto nScrSize = mxScrolledWindow->get_scroll_thickness();
171
0
    bool bVVisible = false; // by default no vertical-ScrollBar
172
0
    bool bHVisible = false; // by default no horizontal-ScrollBar
173
0
    bool bChanged;          // determines if a visibility was changed
174
0
    do
175
0
    {
176
0
        bChanged = false;
177
178
        // does we need a vertical ScrollBar
179
0
        if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
180
0
        {
181
0
            bHVisible = true;
182
0
            aOutPixSz.AdjustHeight( -nScrSize );
183
0
            bChanged = true;
184
0
        }
185
186
        // does we need a horizontal ScrollBar
187
0
        if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
188
0
        {
189
0
            bVVisible = true;
190
0
            aOutPixSz.AdjustWidth( -nScrSize );
191
0
            bChanged = true;
192
0
        }
193
194
0
    }
195
0
    while ( bChanged );   // until no visibility has changed
196
197
    // store the old offset and map-mode
198
0
    MapMode aMap(GetGraphicMapMode());
199
0
    Point aOldPixOffset(aPixOffset);
200
201
    // justify (right/bottom borders should never exceed the virtual window)
202
0
    Size aPixDelta;
203
0
    if ( aPixOffset.X() < 0 &&
204
0
         aPixOffset.X() + aTotPixSz.Width() < aOutPixSz.Width() )
205
0
        aPixDelta.setWidth(
206
0
            aOutPixSz.Width() - ( aPixOffset.X() + aTotPixSz.Width() ) );
207
0
    if ( aPixOffset.Y() < 0 &&
208
0
         aPixOffset.Y() + aTotPixSz.Height() < aOutPixSz.Height() )
209
0
        aPixDelta.setHeight(
210
0
            aOutPixSz.Height() - ( aPixOffset.Y() + aTotPixSz.Height() ) );
211
0
    if ( aPixDelta.Width() || aPixDelta.Height() )
212
0
    {
213
0
        aPixOffset.AdjustX(aPixDelta.Width() );
214
0
        aPixOffset.AdjustY(aPixDelta.Height() );
215
0
    }
216
217
    // for axis without scrollbar restore the origin
218
0
    if ( !bVVisible || !bHVisible )
219
0
    {
220
0
        aPixOffset = Point(
221
0
                     bHVisible
222
0
                     ? aPixOffset.X()
223
0
                     : (aOutPixSz.Width()-aTotPixSz.Width()) / 2,
224
0
                     bVVisible
225
0
                     ? aPixOffset.Y()
226
0
                     : (aOutPixSz.Height()-aTotPixSz.Height()) / 2 );
227
0
    }
228
0
    if (bHVisible && mxScrolledWindow->get_hpolicy() == VclPolicyType::NEVER)
229
0
        aPixOffset.setX( 0 );
230
0
    if (bVVisible && mxScrolledWindow->get_vpolicy() == VclPolicyType::NEVER)
231
0
        aPixOffset.setY( 0 );
232
233
    // select the shifted map-mode
234
0
    if (aPixOffset != aOldPixOffset)
235
0
        SetGraphicMapMode(aMap);
236
237
    // show or hide scrollbars
238
0
    mxScrolledWindow->set_vpolicy(bVVisible ? VclPolicyType::ALWAYS : VclPolicyType::NEVER);
239
0
    mxScrolledWindow->set_hpolicy(bHVisible ? VclPolicyType::ALWAYS : VclPolicyType::NEVER);
240
241
    // resize scrollbars and set their ranges
242
0
    if ( bHVisible )
243
0
    {
244
0
        mxScrolledWindow->hadjustment_configure(-aPixOffset.X(), aTotPixSz.Width(), nColumnPixW,
245
0
                                                aOutPixSz.Width(), aOutPixSz.Width());
246
0
    }
247
0
    if ( bVVisible )
248
0
    {
249
0
        mxScrolledWindow->vadjustment_configure(-aPixOffset.Y(), aTotPixSz.Height(), nLinePixH,
250
0
                                                aOutPixSz.Height(), aOutPixSz.Height());
251
0
    }
252
0
}
253
254
IMPL_LINK_NOARG(SmGraphicWindow, ScrollHdl, weld::ScrolledWindow&, void)
255
0
{
256
0
    MapMode aMap(GetGraphicMapMode());
257
0
    Point aNewPixOffset(aPixOffset);
258
259
    // scrolling horizontally?
260
0
    if (mxScrolledWindow->get_hpolicy() == VclPolicyType::ALWAYS)
261
0
        aNewPixOffset.setX(-mxScrolledWindow->hadjustment_get_value());
262
263
    // scrolling vertically?
264
0
    if (mxScrolledWindow->get_vpolicy() == VclPolicyType::ALWAYS)
265
0
        aNewPixOffset.setY(-mxScrolledWindow->vadjustment_get_value());
266
267
    // scrolling?
268
0
    if (aPixOffset == aNewPixOffset)
269
0
        return;
270
271
    // recompute the logical scroll units
272
0
    aPixOffset = aNewPixOffset;
273
274
0
    SetGraphicMapMode(aMap);
275
0
}
276
277
void SmGraphicWindow::SetGraphicMapMode(const MapMode& rNewMapMode)
278
0
{
279
0
    OutputDevice& rDevice = mxGraphic->GetOutputDevice();
280
0
    MapMode aMap( rNewMapMode );
281
0
    aMap.SetOrigin( aMap.GetOrigin() + rDevice.PixelToLogic( aPixOffset, aMap ) );
282
0
    rDevice.SetMapMode( aMap );
283
0
    mxGraphic->Invalidate();
284
0
}
285
286
MapMode SmGraphicWindow::GetGraphicMapMode() const
287
0
{
288
0
    OutputDevice& rDevice = mxGraphic->GetOutputDevice();
289
0
    MapMode aMap(rDevice.GetMapMode());
290
0
    aMap.SetOrigin( aMap.GetOrigin() - rDevice.PixelToLogic( aPixOffset ) );
291
0
    return aMap;
292
0
}
293
294
void SmGraphicWindow::SetTotalSize( const Size& rNewSize )
295
0
{
296
0
    aTotPixSz = mxGraphic->GetOutputDevice().LogicToPixel(rNewSize);
297
0
    Resize();
298
0
}
299
300
Size SmGraphicWindow::GetTotalSize() const
301
0
{
302
0
    return mxGraphic->GetOutputDevice().PixelToLogic(aTotPixSz);
303
0
}
304
305
void SmGraphicWindow::ShowContextMenu(const CommandEvent& rCEvt)
306
0
{
307
0
    GetParent()->ToTop();
308
0
    Point aPos(5, 5);
309
0
    if (rCEvt.IsMouseEvent())
310
0
        aPos = rCEvt.GetMousePosPixel();
311
312
    // added for replaceability of context menus
313
0
    SfxDispatcher::ExecutePopup( this, &aPos );
314
0
}
315
316
SmGraphicWidget::SmGraphicWidget(SmViewShell& rShell, SmGraphicWindow& rGraphicWindow)
317
0
    : mrGraphicWindow(rGraphicWindow)
318
0
    , bIsCursorVisible(false)
319
0
    , bIsLineVisible(false)
320
0
    , aCaretBlinkTimer("SmGraphicWidget aCaretBlinkTimer")
321
0
    , mrViewShell(rShell)
322
0
{
323
0
}
324
325
void SmGraphicWidget::SetDrawingArea(weld::DrawingArea* pDrawingArea)
326
0
{
327
0
    weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
328
329
0
    OutputDevice& rDevice = GetOutputDevice();
330
331
0
    rDevice.EnableRTL(GetDoc()->GetFormat().IsRightToLeft());
332
0
    rDevice.SetBackground(
333
0
        SmModule::get()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor);
334
335
0
    if (comphelper::LibreOfficeKit::isActive())
336
0
    {
337
        // Disable map mode, so that it's possible to send mouse event coordinates
338
        // directly in twips.
339
0
        rDevice.EnableMapMode(false);
340
0
    }
341
0
    else
342
0
    {
343
0
        rDevice.SetMapMode(MapMode(SmMapUnit(), Point(), 1.0, 1.0));
344
0
    }
345
346
0
    SetTotalSize();
347
348
0
    SetHelpId(HID_SMA_WIN_DOCUMENT);
349
350
0
    ShowLine(false);
351
0
    CaretBlinkInit();
352
0
}
353
354
SmGraphicWidget::~SmGraphicWidget()
355
0
{
356
0
    if (mxAccessible.is())
357
0
        mxAccessible->dispose();
358
0
    mxAccessible.clear();
359
0
    CaretBlinkStop();
360
0
}
361
362
0
SmDocShell* SmGraphicWidget::GetDoc() { return GetView().GetDoc(); }
363
364
SmCursor& SmGraphicWidget::GetCursor()
365
0
{
366
0
    assert(GetDoc());
367
0
    return GetDoc()->GetCursor();
368
0
}
369
370
bool SmGraphicWidget::MouseButtonDown(const MouseEvent& rMEvt)
371
0
{
372
0
    GrabFocus();
373
374
    // set formula-cursor and selection of edit window according to the
375
    // position clicked at
376
377
0
    SAL_WARN_IF( rMEvt.GetClicks() == 0, "starmath", "0 clicks" );
378
0
    if ( !rMEvt.IsLeft() )
379
0
        return true;
380
381
0
    OutputDevice& rDevice = GetOutputDevice();
382
    // get click position relative to formula
383
0
    Point aPos(rDevice.PixelToLogic(rMEvt.GetPosPixel()) - GetFormulaDrawPos());
384
385
0
    const SmNode *pTree = GetDoc()->GetFormulaTree();
386
0
    if (!pTree)
387
0
        return true;
388
389
0
    SmEditWindow* pEdit = GetView().GetEditWindow();
390
391
0
    if (SmViewShell::IsInlineEditEnabled()) {
392
0
        GetCursor().MoveTo(&rDevice, aPos, !rMEvt.IsShift());
393
0
        GetView().InvalidateSlots();
394
        // 'on grab' window events are missing in lok, do it explicitly
395
0
        if (comphelper::LibreOfficeKit::isActive())
396
0
            SetIsCursorVisible(true);
397
0
        return true;
398
0
    }
399
0
    const SmNode *pNode = nullptr;
400
    // if it was clicked inside the formula then get the appropriate node
401
0
    if (pTree->OrientedDist(aPos) <= 0)
402
0
        pNode = pTree->FindRectClosestTo(aPos);
403
404
0
    if (!pNode)
405
0
        return true;
406
407
0
    if (!pEdit)
408
0
        return true;
409
410
    // set selection to the beginning of the token
411
0
    pEdit->SetSelection(pNode->GetSelection());
412
0
    SetCursor(pNode);
413
414
    // allow for immediate editing and
415
    //! implicitly synchronize the cursor position mark in this window
416
0
    pEdit->GrabFocus();
417
418
0
    return true;
419
0
}
420
421
bool SmGraphicWidget::MouseMove(const MouseEvent &rMEvt)
422
0
{
423
0
    if (rMEvt.IsLeft() && SmViewShell::IsInlineEditEnabled())
424
0
    {
425
0
        OutputDevice& rDevice = GetOutputDevice();
426
0
        Point aPos(rDevice.PixelToLogic(rMEvt.GetPosPixel()) - GetFormulaDrawPos());
427
0
        GetCursor().MoveTo(&rDevice, aPos, false);
428
429
0
        CaretBlinkStop();
430
0
        SetIsCursorVisible(true);
431
0
        CaretBlinkStart();
432
0
        RepaintViewShellDoc();
433
0
    }
434
0
    return true;
435
0
}
436
437
void SmGraphicWidget::GetFocus()
438
0
{
439
0
    if (!SmViewShell::IsInlineEditEnabled())
440
0
        return;
441
0
    if (SmEditWindow* pEdit = GetView().GetEditWindow())
442
0
        pEdit->Flush();
443
0
    SetIsCursorVisible(true);
444
0
    ShowLine(true);
445
0
    CaretBlinkStart();
446
0
    RepaintViewShellDoc();
447
0
}
448
449
void SmGraphicWidget::LoseFocus()
450
0
{
451
0
    if (mxAccessible.is())
452
0
    {
453
0
        uno::Any aOldValue, aNewValue;
454
0
        aOldValue <<= AccessibleStateType::FOCUSED;
455
        // aNewValue remains empty
456
0
        mxAccessible->LaunchEvent( AccessibleEventId::STATE_CHANGED,
457
0
                aOldValue, aNewValue );
458
0
    }
459
0
    if (!SmViewShell::IsInlineEditEnabled())
460
0
        return;
461
0
    SetIsCursorVisible(false);
462
0
    ShowLine(false);
463
0
    CaretBlinkStop();
464
0
    RepaintViewShellDoc();
465
0
}
466
467
void SmGraphicWidget::RepaintViewShellDoc()
468
0
{
469
0
    if (SmDocShell* pDoc = GetDoc())
470
0
        pDoc->Repaint();
471
0
}
472
473
IMPL_LINK_NOARG(SmGraphicWidget, CaretBlinkTimerHdl, Timer *, void)
474
0
{
475
0
    if (IsCursorVisible())
476
0
        SetIsCursorVisible(false);
477
0
    else
478
0
        SetIsCursorVisible(true);
479
480
0
    RepaintViewShellDoc();
481
0
}
482
483
void SmGraphicWidget::CaretBlinkInit()
484
0
{
485
0
    if (comphelper::LibreOfficeKit::isActive())
486
0
        return; // No blinking in lok case
487
0
    aCaretBlinkTimer.SetInvokeHandler(LINK(this, SmGraphicWidget, CaretBlinkTimerHdl));
488
0
    aCaretBlinkTimer.SetTimeout(Application::GetSettings().GetStyleSettings().GetCursorBlinkTime());
489
0
}
490
491
void SmGraphicWidget::CaretBlinkStart()
492
0
{
493
0
    if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive())
494
0
        return;
495
0
    if (aCaretBlinkTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME)
496
0
        aCaretBlinkTimer.Start();
497
0
}
498
499
void SmGraphicWidget::CaretBlinkStop()
500
0
{
501
0
    if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive())
502
0
        return;
503
0
    aCaretBlinkTimer.Stop();
504
0
}
505
506
// shows or hides the formula-cursor depending on 'bShow' is true or not
507
void SmGraphicWidget::ShowCursor(bool bShow)
508
0
{
509
0
    if (SmViewShell::IsInlineEditEnabled())
510
0
        return;
511
512
0
    bool bInvert = bShow != IsCursorVisible();
513
0
    if (bInvert)
514
0
        InvertFocusRect(GetOutputDevice(), aCursorRect);
515
516
0
    SetIsCursorVisible(bShow);
517
0
}
518
519
void SmGraphicWidget::ShowLine(bool bShow)
520
0
{
521
0
    if (!SmViewShell::IsInlineEditEnabled())
522
0
        return;
523
524
0
    bIsLineVisible = bShow;
525
0
}
526
527
void SmGraphicWidget::SetIsCursorVisible(bool bVis)
528
0
{
529
0
    bIsCursorVisible = bVis;
530
0
    if (comphelper::LibreOfficeKit::isActive())
531
0
    {
532
0
        mrViewShell.SendCaretToLOK();
533
0
        mrViewShell.libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE,
534
0
                                               OString::boolean(bVis));
535
0
    }
536
0
}
537
538
void SmGraphicWidget::SetCursor(const SmNode *pNode)
539
0
{
540
0
    if (SmViewShell::IsInlineEditEnabled())
541
0
        return;
542
543
0
    const SmNode *pTree = GetDoc()->GetFormulaTree();
544
545
    // get appropriate rectangle
546
0
    Point aOffset (pNode->GetTopLeft() - pTree->GetTopLeft()),
547
0
          aTLPos  (GetFormulaDrawPos() + aOffset);
548
0
    aTLPos.AdjustX( -(pNode->GetItalicLeftSpace()) );
549
0
    Size  aSize   (pNode->GetItalicSize());
550
551
0
    SetCursor(tools::Rectangle(aTLPos, aSize));
552
0
}
553
554
void SmGraphicWidget::SetCursor(const tools::Rectangle &rRect)
555
    // sets cursor to new position (rectangle) 'rRect'.
556
    // The old cursor will be removed, and the new one will be shown if
557
    // that is activated in the ConfigItem
558
0
{
559
0
    if (SmViewShell::IsInlineEditEnabled())
560
0
        return;
561
562
0
    if (IsCursorVisible())
563
0
        ShowCursor(false);      // clean up remainings of old cursor
564
0
    aCursorRect = rRect;
565
0
    if (SmModule::get()->GetConfig()->IsShowFormulaCursor())
566
0
        ShowCursor(true);       // draw new cursor
567
0
}
568
569
const SmNode * SmGraphicWidget::SetCursorPos(sal_uInt16 nRow, sal_uInt16 nCol)
570
    // looks for a VISIBLE node in the formula tree with its token at
571
    // (or around) the position 'nRow', 'nCol' in the edit window
572
    // (row and column numbering starts with 1 there!).
573
    // If there is such a node the formula-cursor is set to cover that nodes
574
    // rectangle. If not the formula-cursor will be hidden.
575
    // In any case the search result is being returned.
576
0
{
577
0
    if (SmViewShell::IsInlineEditEnabled())
578
0
        return nullptr;
579
580
    // find visible node with token at nRow, nCol
581
0
    const SmNode *pTree = GetDoc()->GetFormulaTree(),
582
0
                 *pNode = nullptr;
583
0
    if (pTree)
584
0
        pNode = pTree->FindTokenAt(nRow, nCol);
585
586
0
    if (pNode)
587
0
        SetCursor(pNode);
588
0
    else
589
0
        ShowCursor(false);
590
591
0
    return pNode;
592
0
}
593
594
void SmGraphicWidget::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
595
0
{
596
0
    assert(GetDoc());
597
0
    SmDocShell& rDoc = *GetDoc();
598
0
    Point aPoint;
599
600
0
    rDoc.DrawFormula(rRenderContext, aPoint, true);  //! modifies aPoint to be the topleft
601
                                                     //! corner of the formula
602
0
    aFormulaDrawPos = aPoint;
603
0
    if (SmViewShell::IsInlineEditEnabled())
604
0
    {
605
        //Draw cursor if any...
606
0
        if (rDoc.HasCursor() && IsLineVisible())
607
0
            rDoc.GetCursor().Draw(rRenderContext, aPoint, IsCursorVisible());
608
0
    }
609
0
    else
610
0
    {
611
0
        SetIsCursorVisible(false);  // (old) cursor must be drawn again
612
613
0
        if (const SmEditWindow* pEdit = GetView().GetEditWindow())
614
0
        {   // get new position for formula-cursor (for possible altered formula)
615
0
            sal_Int32  nRow;
616
0
            sal_uInt16 nCol;
617
0
            SmGetLeftSelectionPart(pEdit->GetSelection(), nRow, nCol);
618
0
            const SmNode *pFound = SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
619
620
0
            if (pFound && SmModule::get()->GetConfig()->IsShowFormulaCursor())
621
0
                ShowCursor(true);
622
0
        }
623
0
    }
624
0
}
625
626
void SmGraphicWidget::SetTotalSize()
627
0
{
628
0
    assert(GetDoc());
629
0
    OutputDevice& rDevice = GetOutputDevice();
630
0
    const Size aTmp(rDevice.PixelToLogic(rDevice.LogicToPixel(GetDoc()->GetSize())));
631
0
    if (aTmp != mrGraphicWindow.GetTotalSize())
632
0
        mrGraphicWindow.SetTotalSize(aTmp);
633
0
}
634
635
namespace
636
{
637
SmBracketType BracketTypeOf(sal_uInt32 c)
638
0
{
639
0
    switch (c)
640
0
    {
641
0
        case '(':
642
0
        case ')':
643
0
            return SmBracketType::Round;
644
0
        case '[':
645
0
        case ']':
646
0
            return SmBracketType::Square;
647
0
        case '{':
648
0
        case '}':
649
0
            return SmBracketType::Curly;
650
0
    }
651
0
    assert(false); // Unreachable
652
0
    return SmBracketType::Round;
653
0
}
654
655
bool CharInput(sal_uInt32 c, SmCursor& rCursor, OutputDevice& rDevice)
656
0
{
657
0
    switch (c)
658
0
    {
659
0
        case 0:
660
0
            return false;
661
0
        case ' ':
662
0
            rCursor.InsertElement(BlankElement);
663
0
            break;
664
0
        case '!':
665
0
            rCursor.InsertElement(FactorialElement);
666
0
            break;
667
0
        case '%':
668
0
            rCursor.InsertElement(PercentElement);
669
0
            break;
670
0
        case '*':
671
0
            rCursor.InsertElement(CDotElement);
672
0
            break;
673
0
        case '+':
674
0
            rCursor.InsertElement(PlusElement);
675
0
            break;
676
0
        case '-':
677
0
            rCursor.InsertElement(MinusElement);
678
0
            break;
679
0
        case '<':
680
0
            rCursor.InsertElement(LessThanElement);
681
0
            break;
682
0
        case '=':
683
0
            rCursor.InsertElement(EqualElement);
684
0
            break;
685
0
        case '>':
686
0
            rCursor.InsertElement(GreaterThanElement);
687
0
            break;
688
0
        case '^':
689
0
            rCursor.InsertSubSup(RSUP);
690
0
            break;
691
0
        case '_':
692
0
            rCursor.InsertSubSup(RSUB);
693
0
            break;
694
0
        case '/':
695
0
            rCursor.InsertFraction();
696
0
            break;
697
0
        case '(':
698
0
        case '[':
699
0
        case '{':
700
0
            rCursor.InsertBrackets(BracketTypeOf(c));
701
0
            break;
702
0
        case ')':
703
0
        case ']':
704
0
        case '}':
705
0
            if (rCursor.IsAtTailOfBracket(BracketTypeOf(c)))
706
0
            {
707
0
                rCursor.Move(&rDevice, MoveRight);
708
0
                break;
709
0
            }
710
0
            [[fallthrough]];
711
0
        default:
712
0
            rCursor.InsertText(OUString(&c, 1));
713
0
            break;
714
0
    }
715
0
    return true;
716
0
}
717
}
718
719
bool SmGraphicWidget::KeyInput(const KeyEvent& rKEvt)
720
0
{
721
0
    if (rKEvt.GetKeyCode().GetCode() == KEY_F1)
722
0
    {
723
0
        GetView().StartMainHelp();
724
0
        return true;
725
0
    }
726
727
0
    if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
728
0
    {
729
        // Terminate possible InPlace mode
730
0
        return GetView().Escape();
731
0
    }
732
733
0
    if (!SmViewShell::IsInlineEditEnabled())
734
0
        return GetView().KeyInput(rKEvt);
735
736
0
    bool bConsumed = true;
737
738
0
    SmCursor& rCursor = GetCursor();
739
0
    switch (rKEvt.GetKeyCode().GetFunction())
740
0
    {
741
0
    case KeyFuncType::COPY:
742
0
        rCursor.Copy(&mrGraphicWindow);
743
0
        break;
744
0
    case KeyFuncType::CUT:
745
0
        rCursor.Cut(&mrGraphicWindow);
746
0
        break;
747
0
    case KeyFuncType::PASTE:
748
0
        rCursor.Paste(&mrGraphicWindow);
749
0
        break;
750
0
    case KeyFuncType::UNDO:
751
0
        GetDoc()->Execute(o3tl::temporary(SfxRequest(*GetView().GetFrame(), SID_UNDO)));
752
0
        break;
753
0
    case KeyFuncType::REDO:
754
0
        GetDoc()->Execute(o3tl::temporary(SfxRequest(*GetView().GetFrame(), SID_REDO)));
755
0
        break;
756
0
    default:
757
0
        switch (rKEvt.GetKeyCode().GetCode())
758
0
        {
759
0
            case KEY_LEFT:
760
0
                rCursor.Move(&GetOutputDevice(), MoveLeft, !rKEvt.GetKeyCode().IsShift());
761
0
                break;
762
0
            case KEY_RIGHT:
763
0
                rCursor.Move(&GetOutputDevice(), MoveRight, !rKEvt.GetKeyCode().IsShift());
764
0
                break;
765
0
            case KEY_UP:
766
0
                rCursor.Move(&GetOutputDevice(), MoveUp, !rKEvt.GetKeyCode().IsShift());
767
0
                break;
768
0
            case KEY_DOWN:
769
0
                rCursor.Move(&GetOutputDevice(), MoveDown, !rKEvt.GetKeyCode().IsShift());
770
0
                break;
771
0
            case KEY_RETURN:
772
0
                if (!rKEvt.GetKeyCode().IsShift())
773
0
                    rCursor.InsertRow();
774
0
                break;
775
0
            case KEY_DELETE:
776
0
                if (!rCursor.HasSelection())
777
0
                {
778
0
                    rCursor.Move(&GetOutputDevice(), MoveRight, false);
779
0
                    if (rCursor.HasComplexSelection())
780
0
                        break;
781
0
                }
782
0
                rCursor.Delete();
783
0
                break;
784
0
            case KEY_BACKSPACE:
785
0
                rCursor.DeletePrev(&GetOutputDevice());
786
0
                break;
787
0
            default:
788
0
                if (!CharInput(rKEvt.GetCharCode(), rCursor, GetOutputDevice()))
789
0
                    bConsumed = GetView().KeyInput(rKEvt);
790
0
        }
791
0
    }
792
793
0
    GetView().InvalidateSlots();
794
0
    CaretBlinkStop();
795
0
    CaretBlinkStart();
796
0
    SetIsCursorVisible(true);
797
0
    RepaintViewShellDoc();
798
799
0
    return bConsumed;
800
0
}
801
802
bool SmGraphicWidget::Command(const CommandEvent& rCEvt)
803
0
{
804
0
    bool bCallBase = true;
805
0
    if (!GetView().GetViewFrame().GetFrame().IsInPlace())
806
0
    {
807
0
        switch ( rCEvt.GetCommand() )
808
0
        {
809
0
            case CommandEventId::ContextMenu:
810
                // purely for "ExecutePopup" taking a vcl::Window and
811
                // we assume SmGraphicWindow 0,0 is at SmEditWindow 0,0
812
0
                mrGraphicWindow.ShowContextMenu(rCEvt);
813
0
                bCallBase = false;
814
0
            break;
815
816
0
            case CommandEventId::Wheel:
817
0
            {
818
0
                const CommandWheelData* pWData = rCEvt.GetWheelData();
819
0
                if  ( pWData && CommandWheelMode::ZOOM == pWData->GetMode() )
820
0
                {
821
0
                    sal_uInt16 nTmpZoom = mrGraphicWindow.GetZoom();
822
0
                    if( 0 > pWData->GetDelta() )
823
0
                        nTmpZoom -= 10;
824
0
                    else
825
0
                        nTmpZoom += 10;
826
0
                    mrGraphicWindow.SetZoom(nTmpZoom);
827
0
                    bCallBase = false;
828
0
                }
829
0
                break;
830
0
            }
831
0
            case CommandEventId::GestureZoom:
832
0
            {
833
0
                const CommandGestureZoomData* pData = rCEvt.GetGestureZoomData();
834
0
                if (pData)
835
0
                {
836
0
                    if (pData->meEventType == GestureEventZoomType::Begin)
837
0
                    {
838
0
                        mfLastZoomScale = pData->mfScaleDelta;
839
0
                    }
840
0
                    else if (pData->meEventType == GestureEventZoomType::Update)
841
0
                    {
842
0
                        double deltaBetweenEvents = (pData->mfScaleDelta - mfLastZoomScale) / mfLastZoomScale;
843
0
                        mfLastZoomScale = pData->mfScaleDelta;
844
845
                        // Accumulate fractional zoom to avoid small zoom changes from being ignored
846
0
                        mfAccumulatedZoom += deltaBetweenEvents;
847
0
                        int nZoomChangePercent = mfAccumulatedZoom * 100;
848
0
                        mfAccumulatedZoom -= nZoomChangePercent / 100.0;
849
850
0
                        sal_uInt16 nZoom = mrGraphicWindow.GetZoom();
851
0
                        nZoom += nZoomChangePercent;
852
0
                        mrGraphicWindow.SetZoom(nZoom);
853
0
                    }
854
0
                    bCallBase = false;
855
0
                }
856
0
                break;
857
0
            }
858
859
0
            default: break;
860
0
        }
861
0
    }
862
863
0
    switch (rCEvt.GetCommand())
864
0
    {
865
0
        case CommandEventId::ExtTextInput:
866
0
            if (SmViewShell::IsInlineEditEnabled())
867
0
            {
868
0
                const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData();
869
0
                assert(pData);
870
0
                const OUString& rText = pData->GetText();
871
0
                SmCursor& rCursor = GetCursor();
872
0
                OutputDevice& rDevice = GetOutputDevice();
873
0
                for (sal_Int32 i = 0; i < rText.getLength();)
874
0
                    CharInput(rText.iterateCodePoints(&i), rCursor, rDevice);
875
0
                bCallBase = false;
876
0
            }
877
0
            break;
878
0
        default:
879
0
            break;
880
0
    }
881
0
    return !bCallBase;
882
0
}
883
884
void SmGraphicWindow::SetZoom(sal_uInt16 Factor)
885
0
{
886
0
    if (comphelper::LibreOfficeKit::isActive())
887
0
        return;
888
0
    nZoom = std::clamp(Factor, MINZOOM, MAXZOOM);
889
0
    double fFraction = nZoom / 100.0;
890
0
    SetGraphicMapMode(MapMode(SmMapUnit(), Point(), fFraction, fFraction));
891
0
    mxGraphic->SetTotalSize();
892
0
    SmViewShell& rViewSh = mxGraphic->GetView();
893
0
    rViewSh.GetViewFrame().GetBindings().Invalidate(SID_ATTR_ZOOM);
894
0
    rViewSh.GetViewFrame().GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER);
895
0
}
896
897
void SmGraphicWindow::ZoomToFitInWindow()
898
0
{
899
    // set defined mapmode before calling 'LogicToPixel' below
900
0
    SetGraphicMapMode(MapMode(SmMapUnit()));
901
902
0
    assert(mxGraphic->GetDoc());
903
0
    Size aSize(mxGraphic->GetOutputDevice().LogicToPixel(mxGraphic->GetDoc()->GetSize()));
904
0
    Size aWindowSize(GetSizePixel());
905
906
0
    if (!aSize.IsEmpty())
907
0
    {
908
0
        tools::Long nVal = std::min ((85 * aWindowSize.Width())  / aSize.Width(),
909
0
                      (85 * aWindowSize.Height()) / aSize.Height());
910
0
        SetZoom ( sal::static_int_cast< sal_uInt16 >(nVal) );
911
0
    }
912
0
}
913
914
rtl::Reference<comphelper::OAccessible> SmGraphicWidget::CreateAccessible()
915
0
{
916
0
    if (!mxAccessible.is())
917
0
    {
918
0
        mxAccessible = new SmGraphicAccessible( this );
919
0
    }
920
0
    return mxAccessible;
921
0
}
922
923
/**************************************************************************/
924
SmGraphicController::SmGraphicController(SmGraphicWidget &rSmGraphic,
925
                        sal_uInt16          nId_,
926
                        SfxBindings     &rBindings) :
927
0
    SfxControllerItem(nId_, rBindings),
928
0
    rGraphic(rSmGraphic)
929
0
{
930
0
}
931
932
void SmGraphicController::StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
933
0
{
934
0
    rGraphic.SetTotalSize();
935
0
    rGraphic.Invalidate();
936
0
    SfxControllerItem::StateChangedAtToolBoxControl (nSID, eState, pState);
937
0
}
938
939
/**************************************************************************/
940
SmEditController::SmEditController(SmEditWindow &rSmEdit,
941
                     sal_uInt16       nId_,
942
                     SfxBindings  &rBindings) :
943
0
    SfxControllerItem(nId_, rBindings),
944
0
    rEdit(rSmEdit)
945
0
{
946
0
}
947
948
void SmEditController::StateChangedAtToolBoxControl(sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState)
949
0
{
950
0
    const SfxStringItem *pItem =  dynamic_cast<const SfxStringItem*>( pState);
951
952
0
    if ((pItem != nullptr) && (rEdit.GetText() != pItem->GetValue()))
953
0
        rEdit.SetText(pItem->GetValue());
954
0
    SfxControllerItem::StateChangedAtToolBoxControl (nSID, eState, pState);
955
0
}
956
957
/**************************************************************************/
958
SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings& rBindings_, SfxChildWindow* pChildWindow,
959
                               vcl::Window* pParent)
960
0
    : SfxDockingWindow(rBindings_, pChildWindow, pParent, u"EditWindow"_ustr,
961
0
                       u"modules/smath/ui/editwindow.ui"_ustr)
962
0
    , m_xEdit(new SmEditWindow(*this, *m_xBuilder))
963
0
    , aController(*m_xEdit, SID_TEXT, rBindings_)
964
0
    , bExiting(false)
965
0
    , aInitialFocusTimer("SmCmdBoxWindow aInitialFocusTimer")
966
0
{
967
0
    set_id(u"math_edit"_ustr);
968
969
0
    SetHelpId( HID_SMA_COMMAND_WIN );
970
0
    SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont)));
971
0
    SetText(SmResId(STR_CMDBOXWINDOW));
972
973
0
    Hide();
974
975
    // Don't try to grab focus in inline edit mode
976
0
    if (!SmViewShell::IsInlineEditEnabled())
977
0
    {
978
0
        aInitialFocusTimer.SetInvokeHandler(LINK(this, SmCmdBoxWindow, InitialFocusTimerHdl));
979
0
        aInitialFocusTimer.SetTimeout(100);
980
0
    }
981
0
}
Unexecuted instantiation: SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings&, SfxChildWindow*, vcl::Window*)
Unexecuted instantiation: SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings&, SfxChildWindow*, vcl::Window*)
982
983
Point SmCmdBoxWindow::WidgetToWindowPos(const weld::Widget& rWidget, const Point& rPos)
984
0
{
985
0
    Point aRet(rPos);
986
0
    int x(0), y(0), width(0), height(0);
987
0
    rWidget.get_extents_relative_to(*m_xContainer, x, y, width, height);
988
0
    aRet.Move(x, y);
989
0
    aRet.Move(m_xBox->GetPosPixel().X(), m_xBox->GetPosPixel().Y());
990
0
    return aRet;
991
0
}
992
993
void SmCmdBoxWindow::ShowContextMenu(const Point& rPos)
994
0
{
995
0
    ToTop();
996
0
    SmViewShell *pViewSh = GetView();
997
0
    if (pViewSh)
998
0
        pViewSh->GetViewFrame().GetDispatcher()->ExecutePopup(u"edit"_ustr, this, &rPos);
999
0
}
1000
1001
void SmCmdBoxWindow::Command(const CommandEvent& rCEvt)
1002
0
{
1003
0
    if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
1004
0
    {
1005
0
        ShowContextMenu(rCEvt.GetMousePosPixel());
1006
0
        return;
1007
0
    }
1008
1009
0
    SfxDockingWindow::Command(rCEvt);
1010
0
}
1011
1012
SmCmdBoxWindow::~SmCmdBoxWindow ()
1013
0
{
1014
0
    disposeOnce();
1015
0
}
1016
1017
void SmCmdBoxWindow::dispose()
1018
0
{
1019
0
    aInitialFocusTimer.Stop();
1020
0
    bExiting = true;
1021
0
    aController.dispose();
1022
0
    m_xEdit.reset();
1023
0
    SfxDockingWindow::dispose();
1024
0
}
1025
1026
SmViewShell * SmCmdBoxWindow::GetView()
1027
0
{
1028
0
    SfxDispatcher *pDispatcher = GetBindings().GetDispatcher();
1029
0
    SfxViewShell *pView = pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr;
1030
0
    return  dynamic_cast<SmViewShell*>( pView);
1031
0
}
1032
1033
Size SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign)
1034
0
{
1035
0
    switch (eAlign)
1036
0
    {
1037
0
        case SfxChildAlignment::LEFT:
1038
0
        case SfxChildAlignment::RIGHT:
1039
0
            return Size();
1040
0
        default:
1041
0
            break;
1042
0
    }
1043
0
    return SfxDockingWindow::CalcDockingSize(eAlign);
1044
0
}
1045
1046
SfxChildAlignment SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual,
1047
                                             SfxChildAlignment eWish)
1048
0
{
1049
0
    switch (eWish)
1050
0
    {
1051
0
        case SfxChildAlignment::TOP:
1052
0
        case SfxChildAlignment::BOTTOM:
1053
0
        case SfxChildAlignment::NOALIGNMENT:
1054
0
            return eWish;
1055
0
        default:
1056
0
            break;
1057
0
    }
1058
1059
0
    return eActual;
1060
0
}
1061
1062
void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange )
1063
0
{
1064
0
    if (StateChangedType::InitShow == nStateChange)
1065
0
    {
1066
0
        Resize();   // avoid SmEditWindow not being painted correctly
1067
1068
        // set initial position of window in floating mode
1069
0
        if (IsFloatingMode())
1070
0
            AdjustPosition();   //! don't change pos in docking-mode !
1071
1072
0
        aInitialFocusTimer.Start();
1073
0
    }
1074
1075
0
    SfxDockingWindow::StateChanged( nStateChange );
1076
0
}
1077
1078
IMPL_LINK_NOARG( SmCmdBoxWindow, InitialFocusTimerHdl, Timer *, void )
1079
0
{
1080
    // We want to have the focus in the edit window once Math has been opened
1081
    // to allow for immediate typing.
1082
    // Problem: There is no proper way to do this
1083
    // Thus: this timer based solution has been implemented (see GrabFocus below)
1084
1085
    // Follow-up problem (#i114910): grabbing the focus may bust the help system since
1086
    // it relies on getting the current frame which conflicts with grabbing the focus.
1087
    // Thus aside from the 'GrabFocus' call everything else is to get the
1088
    // help reliably working despite using 'GrabFocus'.
1089
1090
0
    try
1091
0
    {
1092
0
        uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( comphelper::getProcessComponentContext() );
1093
1094
0
        m_xEdit->GrabFocus();
1095
1096
0
        SmViewShell* pView = GetView();
1097
0
        assert(pView);
1098
0
        bool bInPlace = pView->GetViewFrame().GetFrame().IsInPlace();
1099
0
        uno::Reference< frame::XFrame > xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
1100
0
        if ( bInPlace )
1101
0
        {
1102
0
            uno::Reference<container::XChild> xModel(pView->GetDoc()->GetModel(),
1103
0
                                                     uno::UNO_QUERY_THROW);
1104
0
            uno::Reference< frame::XModel > xParent( xModel->getParent(), uno::UNO_QUERY_THROW );
1105
0
            uno::Reference< frame::XController > xParentCtrler( xParent->getCurrentController() );
1106
0
            uno::Reference< frame::XFramesSupplier > xParentFrame( xParentCtrler->getFrame(), uno::UNO_QUERY_THROW );
1107
0
            xParentFrame->setActiveFrame( xFrame );
1108
0
        }
1109
0
        else
1110
0
        {
1111
0
            xDesktop->setActiveFrame( xFrame );
1112
0
        }
1113
0
    }
1114
0
    catch (uno::Exception &)
1115
0
    {
1116
0
        SAL_WARN( "starmath", "failed to properly set initial focus to edit window" );
1117
0
    }
1118
0
}
1119
1120
void SmCmdBoxWindow::AdjustPosition()
1121
0
{
1122
0
    const tools::Rectangle aRect( Point(), GetParent()->GetOutputSizePixel() );
1123
0
    Point aTopLeft( Point( aRect.Left(),
1124
0
                           aRect.Bottom() - GetSizePixel().Height() ) );
1125
0
    Point aPos( GetParent()->OutputToScreenPixel( aTopLeft ) );
1126
0
    if (aPos.X() < 0)
1127
0
        aPos.setX( 0 );
1128
0
    if (aPos.Y() < 0)
1129
0
        aPos.setY( 0 );
1130
0
    SetPosPixel( aPos );
1131
0
}
1132
1133
void SmCmdBoxWindow::ToggleFloatingMode()
1134
0
{
1135
0
    SfxDockingWindow::ToggleFloatingMode();
1136
1137
0
    if (GetFloatingWindow())
1138
0
        GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
1139
0
}
1140
1141
void SmCmdBoxWindow::GetFocus()
1142
0
{
1143
0
    if (!bExiting)
1144
0
        m_xEdit->GrabFocus();
1145
0
}
1146
1147
SFX_IMPL_DOCKINGWINDOW_WITHID(SmCmdBoxWrapper, SID_CMDBOXWINDOW);
1148
1149
SmCmdBoxWrapper::SmCmdBoxWrapper(vcl::Window* pParentWindow, sal_uInt16 nId, SfxBindings& rBindings,
1150
                                 SfxChildWinInfo& rInfo)
1151
0
    : SfxChildWindow(pParentWindow, nId)
1152
0
{
1153
0
    VclPtrInstance<SmCmdBoxWindow> pDialog(rBindings, this, pParentWindow);
1154
0
    SetWindow(pDialog);
1155
    // make window docked to the bottom initially (after first start)
1156
0
    SetAlignment(SfxChildAlignment::BOTTOM);
1157
0
    pDialog->setDeferredProperties();
1158
0
    pDialog->set_border_width(CMD_BOX_PADDING);
1159
0
    pDialog->set_margin_top(CMD_BOX_PADDING_TOP);
1160
0
    pDialog->Initialize(rInfo);
1161
0
}
1162
1163
SFX_IMPL_SUPERCLASS_INTERFACE(SmViewShell, SfxViewShell)
1164
1165
void SmViewShell::InitInterface_Impl()
1166
1
{
1167
1
    GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS,
1168
1
                                            SfxVisibilityFlags::Standard | SfxVisibilityFlags::FullScreen | SfxVisibilityFlags::Server,
1169
1
                                            ToolbarId::Math_Toolbox);
1170
    //Dummy-Objectbar, to avoid quiver while activating
1171
1172
1
    GetStaticInterface()->RegisterChildWindow(SmCmdBoxWrapper::GetChildWindowId());
1173
1
    GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
1174
1175
1
    GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
1176
1
}
1177
1178
1
SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell, "Default")
1179
1
{
1180
1
    SFX_VIEW_REGISTRATION(SmDocShell);
1181
1
}
1182
1183
void SmViewShell::InnerResizePixel(const Point &rOfs, const Size &rSize, bool)
1184
0
{
1185
0
    Size aObjSize = GetObjectShell()->GetVisArea().GetSize();
1186
0
    if ( !aObjSize.IsEmpty() )
1187
0
    {
1188
0
        Size aProvidedSize = GetWindow()->PixelToLogic(rSize, MapMode(SmMapUnit()));
1189
0
        double fZoomX = double(aProvidedSize.Width()) / aObjSize.Width();
1190
0
        double fZoomY = double(aProvidedSize.Height()) / aObjSize.Height();
1191
0
        MapMode aMap(mxGraphicWindow->GetGraphicMapMode());
1192
0
        aMap.SetScaleX(fZoomX);
1193
0
        aMap.SetScaleY(fZoomY);
1194
0
        mxGraphicWindow->SetGraphicMapMode(aMap);
1195
0
    }
1196
1197
0
    SetBorderPixel( SvBorder() );
1198
0
    mxGraphicWindow->SetPosSizePixel(rOfs, rSize);
1199
0
    GetGraphicWidget().SetTotalSize();
1200
0
}
1201
1202
void SmViewShell::OuterResizePixel(const Point &rOfs, const Size &rSize)
1203
0
{
1204
0
    mxGraphicWindow->SetPosSizePixel(rOfs, rSize);
1205
0
    if (GetDoc()->IsPreview())
1206
0
        mxGraphicWindow->ZoomToFitInWindow();
1207
0
}
1208
1209
void SmViewShell::QueryObjAreaPixel( tools::Rectangle& rRect ) const
1210
0
{
1211
0
    rRect.SetSize(mxGraphicWindow->GetSizePixel());
1212
0
}
1213
1214
void SmViewShell::SetZoomFactor( double fX, double fY )
1215
0
{
1216
0
    double fFrac = std::min(fX, fY);
1217
0
    mxGraphicWindow->SetZoom(sal::static_int_cast<sal_uInt16>(tools::Long(fFrac * 100)));
1218
1219
    //To avoid rounding errors base class regulates crooked values too
1220
    //if necessary
1221
0
    SfxViewShell::SetZoomFactor( fX, fY );
1222
0
}
1223
1224
SfxPrinter* SmViewShell::GetPrinter(bool bCreate)
1225
0
{
1226
0
    SmDocShell* pDoc = GetDoc();
1227
0
    if (pDoc->HasPrinter() || bCreate)
1228
0
        return pDoc->GetPrinter();
1229
0
    return nullptr;
1230
0
}
1231
1232
sal_uInt16 SmViewShell::SetPrinter(SfxPrinter *pNewPrinter, SfxPrinterChangeFlags nDiffFlags )
1233
0
{
1234
0
    SfxPrinter *pOld = GetDoc()->GetPrinter();
1235
0
    if ( pOld && pOld->IsPrinting() )
1236
0
        return SFX_PRINTERROR_BUSY;
1237
1238
0
    if ((nDiffFlags & SfxPrinterChangeFlags::PRINTER) == SfxPrinterChangeFlags::PRINTER)
1239
0
        GetDoc()->SetPrinter( pNewPrinter );
1240
1241
0
    if ((nDiffFlags & SfxPrinterChangeFlags::OPTIONS) == SfxPrinterChangeFlags::OPTIONS)
1242
0
    {
1243
0
        SmModule::get()->GetConfig()->ItemSetToConfig(pNewPrinter->GetOptions());
1244
0
    }
1245
0
    return 0;
1246
0
}
1247
1248
bool SmViewShell::HasPrintOptionsPage() const
1249
0
{
1250
0
    return true;
1251
0
}
1252
1253
std::unique_ptr<SfxTabPage> SmViewShell::CreatePrintOptionsPage(weld::Container* pPage, weld::DialogController* pController,
1254
                                                       const SfxItemSet &rOptions)
1255
0
{
1256
0
    return SmPrintOptionsTabPage::Create(pPage, pController, rOptions);
1257
0
}
1258
1259
SmEditWindow *SmViewShell::GetEditWindow()
1260
0
{
1261
0
    SmCmdBoxWrapper* pWrapper = static_cast<SmCmdBoxWrapper*>(
1262
0
                                    GetViewFrame().GetChildWindow(SmCmdBoxWrapper::GetChildWindowId()));
1263
1264
0
    if (pWrapper != nullptr)
1265
0
    {
1266
0
        SmEditWindow& rEditWin = pWrapper->GetEditWindow();
1267
0
        return &rEditWin;
1268
0
    }
1269
1270
0
    return nullptr;
1271
0
}
1272
1273
void SmViewShell::SetStatusText(const OUString& rText)
1274
0
{
1275
0
    maStatusText = rText;
1276
0
    GetViewFrame().GetBindings().Invalidate(SID_TEXTSTATUS);
1277
0
}
1278
1279
void SmViewShell::ShowError(const SmErrorDesc* pErrorDesc)
1280
0
{
1281
0
    assert(GetDoc());
1282
0
    if (pErrorDesc || nullptr != (pErrorDesc = GetDoc()->GetParser()->GetError()) )
1283
0
    {
1284
0
        SetStatusText( pErrorDesc->m_aText );
1285
0
        if (SmEditWindow* pEdit = GetEditWindow())
1286
0
            pEdit->MarkError( Point( pErrorDesc->m_pNode->GetColumn(),
1287
0
                                               pErrorDesc->m_pNode->GetRow()));
1288
0
    }
1289
0
}
1290
1291
void SmViewShell::NextError()
1292
0
{
1293
0
    assert(GetDoc());
1294
0
    const SmErrorDesc   *pErrorDesc = GetDoc()->GetParser()->NextError();
1295
1296
0
    if (pErrorDesc)
1297
0
        ShowError( pErrorDesc );
1298
0
}
1299
1300
void SmViewShell::PrevError()
1301
0
{
1302
0
    assert(GetDoc());
1303
0
    const SmErrorDesc   *pErrorDesc = GetDoc()->GetParser()->PrevError();
1304
1305
0
    if (pErrorDesc)
1306
0
        ShowError( pErrorDesc );
1307
0
}
1308
1309
void SmViewShell::Insert( SfxMedium& rMedium )
1310
0
{
1311
0
    SmDocShell *pDoc = GetDoc();
1312
0
    bool bRet = false;
1313
1314
0
    uno::Reference <embed::XStorage> xStorage = rMedium.GetStorage();
1315
0
    if (xStorage.is() && xStorage->getElementNames().hasElements())
1316
0
    {
1317
0
        if (xStorage->hasByName(u"content.xml"_ustr))
1318
0
        {
1319
            // is this a fabulous math package ?
1320
0
            rtl::Reference<SmModel> xModel(dynamic_cast<SmModel*>(pDoc->GetModel().get()));
1321
0
            SmXMLImportWrapper aEquation(xModel);    //!! modifies the result of pDoc->GetText() !!
1322
0
            bRet = ERRCODE_NONE == aEquation.Import(rMedium);
1323
0
        }
1324
0
    }
1325
1326
0
    if (!bRet)
1327
0
        return;
1328
1329
0
    OUString aText = pDoc->GetText();
1330
0
    if (SmEditWindow *pEditWin = GetEditWindow())
1331
0
        pEditWin->InsertText( aText );
1332
0
    else
1333
0
    {
1334
0
        SAL_WARN( "starmath", "EditWindow missing" );
1335
0
    }
1336
1337
0
    pDoc->Parse();
1338
0
    pDoc->SetModified();
1339
1340
0
    SfxBindings &rBnd = GetViewFrame().GetBindings();
1341
0
    rBnd.Invalidate(SID_GRAPHIC_SM);
1342
0
    rBnd.Invalidate(SID_TEXT);
1343
0
}
1344
1345
void SmViewShell::InsertFrom(SfxMedium &rMedium)
1346
0
{
1347
0
    bool bSuccess = false;
1348
0
    SmDocShell* pDoc = GetDoc();
1349
0
    SvStream* pStream = rMedium.GetInStream();
1350
1351
0
    if (pStream)
1352
0
    {
1353
0
        const OUString& rFltName = rMedium.GetFilter()->GetFilterName();
1354
0
        if ( rFltName == MATHML_XML )
1355
0
        {
1356
0
            rtl::Reference<SmModel> xModel(dynamic_cast<SmModel*>(pDoc->GetModel().get()));
1357
0
            SmXMLImportWrapper aEquation(xModel);    //!! modifies the result of pDoc->GetText() !!
1358
0
            bSuccess = ERRCODE_NONE == aEquation.Import(rMedium);
1359
0
        }
1360
0
    }
1361
1362
0
    if (!bSuccess)
1363
0
        return;
1364
1365
0
    OUString aText = pDoc->GetText();
1366
0
    if (SmEditWindow *pEditWin = GetEditWindow())
1367
0
        pEditWin->InsertText(aText);
1368
0
    else
1369
0
        SAL_WARN( "starmath", "EditWindow missing" );
1370
1371
0
    pDoc->Parse();
1372
0
    pDoc->SetModified();
1373
1374
0
    SfxBindings& rBnd = GetViewFrame().GetBindings();
1375
0
    rBnd.Invalidate(SID_GRAPHIC_SM);
1376
0
    rBnd.Invalidate(SID_TEXT);
1377
0
}
1378
1379
void SmViewShell::Execute(SfxRequest& rReq)
1380
0
{
1381
0
    SmEditWindow *pWin = GetEditWindow();
1382
1383
0
    switch (rReq.GetSlot())
1384
0
    {
1385
0
        case SID_FORMULACURSOR:
1386
0
        {
1387
0
            auto* config = SmModule::get()->GetConfig();
1388
1389
0
            const SfxItemSet  *pArgs = rReq.GetArgs();
1390
0
            const SfxPoolItem *pItem;
1391
1392
0
            bool  bVal;
1393
0
            if ( pArgs &&
1394
0
                 SfxItemState::SET == pArgs->GetItemState( SID_FORMULACURSOR, false, &pItem))
1395
0
                bVal = static_cast<const SfxBoolItem *>(pItem)->GetValue();
1396
0
            else
1397
0
                bVal = !config->IsShowFormulaCursor();
1398
1399
0
            config->SetShowFormulaCursor(bVal);
1400
0
            if (!IsInlineEditEnabled())
1401
0
                GetGraphicWidget().ShowCursor(bVal);
1402
0
            break;
1403
0
        }
1404
0
        case SID_DRAW:
1405
0
            if (pWin)
1406
0
            {
1407
0
                GetDoc()->SetText( pWin->GetText() );
1408
0
                SetStatusText(OUString());
1409
0
                ShowError( nullptr );
1410
0
                GetDoc()->Repaint();
1411
0
            }
1412
0
            break;
1413
1414
0
        case SID_ZOOM_OPTIMAL:
1415
0
            mxGraphicWindow->ZoomToFitInWindow();
1416
0
            break;
1417
1418
0
        case SID_ZOOMIN:
1419
0
            mxGraphicWindow->SetZoom(mxGraphicWindow->GetZoom() + 25);
1420
0
            break;
1421
1422
0
        case SID_ZOOMOUT:
1423
0
            SAL_WARN_IF( mxGraphicWindow->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1424
0
            mxGraphicWindow->SetZoom(mxGraphicWindow->GetZoom() - 25);
1425
0
            break;
1426
1427
0
        case SID_COPYOBJECT:
1428
0
        {
1429
            //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
1430
0
            Reference< datatransfer::XTransferable > xTrans( GetDoc()->GetModel(), uno::UNO_QUERY );
1431
0
            if( xTrans.is() )
1432
0
            {
1433
0
                auto pTrans = dynamic_cast<TransferableHelper*>(xTrans.get());
1434
0
                if (pTrans)
1435
0
                {
1436
0
                    if (pWin)
1437
0
                        pTrans->CopyToClipboard(pWin->GetClipboard());
1438
0
                }
1439
0
            }
1440
0
        }
1441
0
        break;
1442
1443
0
        case SID_PASTEOBJECT:
1444
0
        {
1445
0
            uno::Reference < io::XInputStream > xStrm;
1446
0
            if (pWin)
1447
0
            {
1448
0
                TransferableDataHelper aData(TransferableDataHelper::CreateFromClipboard(pWin->GetClipboard()));
1449
0
                SotClipboardFormatId nId;
1450
0
                if( aData.GetTransferable().is() &&
1451
0
                    ( aData.HasFormat( nId = SotClipboardFormatId::EMBEDDED_OBJ ) ||
1452
0
                      (aData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) &&
1453
0
                       aData.HasFormat( nId = SotClipboardFormatId::EMBED_SOURCE ))))
1454
0
                    xStrm = aData.GetInputStream(nId, OUString());
1455
0
            }
1456
1457
0
            if (xStrm.is())
1458
0
            {
1459
0
                try
1460
0
                {
1461
0
                    uno::Reference < embed::XStorage > xStorage =
1462
0
                            ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm, ::comphelper::getProcessComponentContext() );
1463
0
                    SfxMedium aMedium( xStorage, OUString() );
1464
0
                    Insert( aMedium );
1465
0
                    GetDoc()->UpdateText();
1466
0
                }
1467
0
                catch (uno::Exception &)
1468
0
                {
1469
0
                    SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1470
0
                }
1471
0
            }
1472
0
        }
1473
0
        break;
1474
1475
1476
0
        case SID_CUT:
1477
0
            if (IsInlineEditEnabled())
1478
0
            {
1479
0
                GetDoc()->GetCursor().Cut(&GetGraphicWindow());
1480
0
                GetGraphicWidget().GrabFocus();
1481
0
            }
1482
0
            else if (pWin)
1483
0
                pWin->Cut();
1484
0
            break;
1485
1486
0
        case SID_COPY:
1487
0
            if (IsInlineEditEnabled())
1488
0
            {
1489
0
                GetDoc()->GetCursor().Copy(&GetGraphicWindow());
1490
0
                GetGraphicWidget().GrabFocus();
1491
0
            }
1492
0
            else if (pWin)
1493
0
            {
1494
0
                if (pWin->IsAllSelected())
1495
0
                {
1496
0
                    GetViewFrame().GetDispatcher()->ExecuteList(
1497
0
                                SID_COPYOBJECT, SfxCallMode::RECORD,
1498
0
                                { new SfxVoidItem(SID_COPYOBJECT) });
1499
0
                }
1500
0
                else
1501
0
                    pWin->Copy();
1502
0
            }
1503
0
            break;
1504
1505
0
        case SID_PASTE:
1506
0
            {
1507
0
                if (IsInlineEditEnabled())
1508
0
                {
1509
0
                    GetDoc()->GetCursor().Paste(&GetGraphicWindow());
1510
0
                    GetGraphicWidget().GrabFocus();
1511
0
                    break;
1512
0
                }
1513
1514
0
                if( pWin )
1515
0
                {
1516
0
                    TransferableDataHelper aDataHelper(
1517
0
                        TransferableDataHelper::CreateFromClipboard(
1518
0
                                                    pWin->GetClipboard()));
1519
1520
0
                    if( aDataHelper.GetTransferable().is() &&
1521
0
                        aDataHelper.HasFormat( SotClipboardFormatId::STRING ))
1522
0
                        pWin->Paste();
1523
0
                    else
1524
0
                    {
1525
0
                        GetViewFrame().GetDispatcher()->ExecuteList(
1526
0
                                SID_PASTEOBJECT, SfxCallMode::RECORD,
1527
0
                                { new SfxVoidItem(SID_PASTEOBJECT) });
1528
0
                    }
1529
0
                }
1530
0
            }
1531
0
            break;
1532
1533
0
        case SID_MATRIXEDITOR:
1534
0
            if (pWin)
1535
0
            {
1536
0
                auto pMatrixCreatorDialog = std::make_unique<MatrixCreatorDialog>(rReq.GetFrameWeld());
1537
1538
0
                if (pMatrixCreatorDialog->run() == RET_OK)
1539
0
                {
1540
0
                    OUString result = pMatrixCreatorDialog->getMatrix();
1541
1542
0
                    ESelection eSelection = pWin->GetSelection();
1543
0
                    eSelection.Adjust();
1544
1545
0
                    auto pEngine = pWin->GetEditEngine();
1546
0
                    OUString sText;
1547
1548
0
                    for (sal_Int32 p = 0; p < pEngine->GetParagraphCount(); ++p)
1549
0
                    {
1550
0
                        if (p == eSelection.start.nPara)
1551
0
                        {
1552
0
                            OUString pText = pEngine->GetText(p);
1553
0
                            sText += pText.replaceAt(eSelection.start.nIndex,
1554
0
                                                     eSelection.end.nIndex - eSelection.start.nIndex,
1555
0
                                                     result)
1556
0
                                     + "\n";
1557
0
                        }
1558
0
                        else
1559
0
                            sText += pEngine->GetText(p) + "\n";
1560
0
                    }
1561
1562
0
                    GetDoc()->SetText(sText);
1563
0
                    SetStatusText(OUString());
1564
0
                    ShowError(nullptr);
1565
0
                    GetDoc()->Repaint();
1566
0
                }
1567
0
            }
1568
0
        break;
1569
1570
0
        case SID_DELETE:
1571
0
            if (IsInlineEditEnabled())
1572
0
            {
1573
0
                if (!GetDoc()->GetCursor().HasSelection())
1574
0
                {
1575
0
                    GetDoc()->GetCursor().Move(&GetGraphicWindow().GetGraphicWidget().GetOutputDevice(), MoveRight, false);
1576
0
                    if (!GetDoc()->GetCursor().HasComplexSelection())
1577
0
                        GetDoc()->GetCursor().Delete();
1578
0
                }
1579
0
                else
1580
0
                    GetDoc()->GetCursor().Delete();
1581
0
                GetGraphicWidget().GrabFocus();
1582
0
            }
1583
0
            else if (pWin)
1584
0
                pWin->Delete();
1585
0
            break;
1586
1587
0
        case SID_SELECT:
1588
0
            if (pWin)
1589
0
                pWin->SelectAll();
1590
0
            break;
1591
1592
0
        case SID_INSERTCOMMANDTEXT:
1593
0
        {
1594
0
            const SfxStringItem& rItem = rReq.GetArgs()->Get(SID_INSERTCOMMANDTEXT);
1595
1596
0
            if (IsInlineEditEnabled())
1597
0
            {
1598
0
                GetDoc()->GetCursor().InsertCommandText(rItem.GetValue());
1599
0
                GetGraphicWidget().GrabFocus();
1600
0
            }
1601
0
            else if (pWin)
1602
0
            {
1603
0
                pWin->InsertText(rItem.GetValue());
1604
0
            }
1605
0
            break;
1606
1607
0
        }
1608
1609
0
        case SID_INSERTSPECIAL:
1610
0
        {
1611
0
            const SfxStringItem& rItem = rReq.GetArgs()->Get(SID_INSERTSPECIAL);
1612
1613
0
            if (IsInlineEditEnabled())
1614
0
                GetDoc()->GetCursor().InsertSpecial(rItem.GetValue());
1615
0
            else if (pWin)
1616
0
                pWin->InsertText(rItem.GetValue());
1617
0
            break;
1618
0
        }
1619
1620
0
        case SID_IMPORT_FORMULA:
1621
0
        {
1622
0
            mpRequest.reset(new SfxRequest( rReq ));
1623
0
            mpDocInserter.reset(new ::sfx2::DocumentInserter(pWin ? pWin->GetFrameWeld() : nullptr,
1624
0
                              GetDoc()->GetFactory().GetFactoryName()));
1625
0
            mpDocInserter->StartExecuteModal( LINK( this, SmViewShell, DialogClosedHdl ) );
1626
0
            break;
1627
0
        }
1628
1629
0
        case SID_IMPORT_MATHML_CLIPBOARD:
1630
0
        {
1631
0
            if (pWin)
1632
0
            {
1633
0
                TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromClipboard(pWin->GetClipboard()));
1634
0
                uno::Reference < io::XInputStream > xStrm;
1635
0
                if  ( aDataHelper.GetTransferable().is() )
1636
0
                {
1637
0
                    SotClipboardFormatId nId = SotClipboardFormatId::MATHML;
1638
0
                    if (aDataHelper.HasFormat(nId))
1639
0
                    {
1640
0
                        xStrm = aDataHelper.GetInputStream(nId, u""_ustr);
1641
0
                        if (xStrm.is())
1642
0
                        {
1643
0
                            SfxMedium aClipboardMedium;
1644
0
                            aClipboardMedium.GetItemSet(); //generate initial itemset, not sure if necessary
1645
0
                            std::shared_ptr<const SfxFilter> pMathFilter =
1646
0
                                SfxFilter::GetFilterByName(MATHML_XML);
1647
0
                            aClipboardMedium.SetFilter(pMathFilter);
1648
0
                            aClipboardMedium.setStreamToLoadFrom(xStrm, true /*bIsReadOnly*/);
1649
0
                            InsertFrom(aClipboardMedium);
1650
0
                            GetDoc()->UpdateText();
1651
0
                        }
1652
0
                    }
1653
0
                    else
1654
0
                    {
1655
0
                        nId = SotClipboardFormatId::STRING;
1656
0
                        if (aDataHelper.HasFormat(nId))
1657
0
                        {
1658
                            // In case of FORMAT_STRING no stream exists, need to generate one
1659
0
                            OUString aString;
1660
0
                            if (aDataHelper.GetString( nId, aString))
1661
0
                            {
1662
                                // tdf#117091 force xml declaration to exist
1663
0
                                if (!aString.startsWith("<?xml"))
1664
0
                                    aString = "<?xml version=\"1.0\"?>\n" + aString;
1665
1666
0
                                SfxMedium aClipboardMedium;
1667
0
                                aClipboardMedium.GetItemSet(); //generates initial itemset, not sure if necessary
1668
0
                                std::shared_ptr<const SfxFilter> pMathFilter =
1669
0
                                    SfxFilter::GetFilterByName(MATHML_XML);
1670
0
                                aClipboardMedium.SetFilter(pMathFilter);
1671
1672
0
                                SvMemoryStream aStrm( const_cast<sal_Unicode *>(aString.getStr()), aString.getLength() * sizeof(sal_Unicode), StreamMode::READ);
1673
0
                                uno::Reference<io::XInputStream> xStrm2( new ::utl::OInputStreamWrapper(aStrm) );
1674
0
                                aClipboardMedium.setStreamToLoadFrom(xStrm2, true /*bIsReadOnly*/);
1675
0
                                InsertFrom(aClipboardMedium);
1676
0
                                GetDoc()->UpdateText();
1677
0
                            }
1678
0
                        }
1679
0
                    }
1680
0
                }
1681
0
            }
1682
0
            break;
1683
0
        }
1684
1685
0
        case SID_NEXTERR:
1686
0
            NextError();
1687
0
            if (pWin)
1688
0
                pWin->GrabFocus();
1689
0
            break;
1690
1691
0
        case SID_PREVERR:
1692
0
            PrevError();
1693
0
            if (pWin)
1694
0
                pWin->GrabFocus();
1695
0
            break;
1696
1697
0
        case SID_NEXTMARK:
1698
0
            if (pWin)
1699
0
            {
1700
0
                pWin->SelNextMark();
1701
0
                pWin->GrabFocus();
1702
0
            }
1703
0
            break;
1704
1705
0
        case SID_PREVMARK:
1706
0
            if (pWin)
1707
0
            {
1708
0
                pWin->SelPrevMark();
1709
0
                pWin->GrabFocus();
1710
0
            }
1711
0
            break;
1712
1713
0
        case SID_TEXTSTATUS:
1714
0
        {
1715
0
            if (rReq.GetArgs() != nullptr)
1716
0
            {
1717
0
                const SfxStringItem& rItem = rReq.GetArgs()->Get(SID_TEXTSTATUS);
1718
1719
0
                SetStatusText(rItem.GetValue());
1720
0
            }
1721
1722
0
            break;
1723
0
        }
1724
1725
0
        case SID_GETEDITTEXT:
1726
0
            if (pWin && !pWin->GetText().isEmpty())
1727
0
                GetDoc()->SetText( pWin->GetText() );
1728
0
            break;
1729
1730
0
        case SID_ATTR_ZOOM:
1731
0
        {
1732
0
            if ( !GetViewFrame().GetFrame().IsInPlace() )
1733
0
            {
1734
0
                const SfxItemSet *pSet = rReq.GetArgs();
1735
0
                if ( pSet )
1736
0
                {
1737
0
                    ZoomByItemSet(pSet);
1738
0
                }
1739
0
                else
1740
0
                {
1741
0
                    SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<SID_ATTR_ZOOM, SID_ATTR_ZOOM>( SmDocShell::GetPool() ));
1742
0
                    aSet.Put( SvxZoomItem( SvxZoomType::PERCENT, mxGraphicWindow->GetZoom()));
1743
0
                    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1744
0
                    ScopedVclPtr<AbstractSvxZoomDialog> xDlg(pFact->CreateSvxZoomDialog(GetViewFrame().GetWindow().GetFrameWeld(), aSet));
1745
0
                    xDlg->SetLimits( MINZOOM, MAXZOOM );
1746
0
                    if (xDlg->Execute() != RET_CANCEL)
1747
0
                        ZoomByItemSet(xDlg->GetOutputItemSet());
1748
0
                }
1749
0
            }
1750
0
        }
1751
0
        break;
1752
1753
0
        case SID_ATTR_ZOOMSLIDER:
1754
0
        {
1755
0
            const SfxItemSet *pArgs = rReq.GetArgs();
1756
0
            const SfxPoolItem* pItem;
1757
1758
0
            if ( pArgs && SfxItemState::SET == pArgs->GetItemState(SID_ATTR_ZOOMSLIDER, true, &pItem ) )
1759
0
            {
1760
0
                const sal_uInt16 nCurrentZoom = static_cast<const SvxZoomSliderItem *>(pItem)->GetValue();
1761
0
                mxGraphicWindow->SetZoom(nCurrentZoom);
1762
0
            }
1763
0
        }
1764
0
        break;
1765
1766
0
        case SID_ELEMENTSDOCKINGWINDOW:
1767
0
        {
1768
            // First make sure that the sidebar is visible
1769
0
            GetViewFrame().ShowChildWindow(SID_SIDEBAR);
1770
1771
0
            sfx2::sidebar::Sidebar::TogglePanel(u"MathElementsPanel",
1772
0
                                                GetViewFrame().GetFrame().GetFrameInterface());
1773
0
            GetViewFrame().GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW );
1774
1775
0
            rReq.Ignore ();
1776
0
        }
1777
0
        break;
1778
1779
0
        case SID_CMDBOXWINDOW:
1780
0
        {
1781
0
            GetViewFrame().ToggleChildWindow(SID_CMDBOXWINDOW);
1782
0
            GetViewFrame().GetBindings().Invalidate(SID_CMDBOXWINDOW);
1783
0
        }
1784
0
        break;
1785
1786
0
        case SID_UNICODE_NOTATION_TOGGLE:
1787
0
        {
1788
0
            EditEngine* pEditEngine = nullptr;
1789
0
            if( pWin )
1790
0
                pEditEngine = pWin->GetEditEngine();
1791
1792
0
            EditView* pEditView = nullptr;
1793
0
            if( pEditEngine )
1794
0
                pEditView = pEditEngine->GetView();
1795
1796
0
            if( pEditView )
1797
0
            {
1798
0
                const OUString sInput = pEditView->GetSurroundingText();
1799
0
                ESelection aSel(  pWin->GetSelection() );
1800
1801
0
                if (aSel.start.nIndex > aSel.end.nIndex)
1802
0
                    aSel.end.nIndex = aSel.start.nIndex;
1803
1804
                //calculate a valid end-position by reading logical characters
1805
0
                sal_Int32 nUtf16Pos=0;
1806
0
                while ((nUtf16Pos < sInput.getLength()) && (nUtf16Pos < aSel.end.nIndex))
1807
0
                {
1808
0
                    sInput.iterateCodePoints(&nUtf16Pos);
1809
0
                    if (nUtf16Pos > aSel.end.nIndex)
1810
0
                        aSel.end.nIndex = nUtf16Pos;
1811
0
                }
1812
1813
0
                ToggleUnicodeCodepoint aToggle;
1814
0
                while( nUtf16Pos && aToggle.AllowMoreInput( sInput[nUtf16Pos-1]) )
1815
0
                    --nUtf16Pos;
1816
0
                const OUString sReplacement = aToggle.ReplacementString();
1817
0
                if( !sReplacement.isEmpty() )
1818
0
                {
1819
0
                    pEditView->SetSelection( aSel );
1820
0
                    pEditEngine->UndoActionStart(EDITUNDO_REPLACEALL);
1821
0
                    aSel.start.nIndex = aSel.end.nIndex - aToggle.StringToReplace().getLength();
1822
0
                    pWin->SetSelection( aSel );
1823
0
                    pEditView->InsertText( sReplacement, true );
1824
0
                    pEditEngine->UndoActionEnd();
1825
0
                    pWin->Flush();
1826
0
                }
1827
0
            }
1828
0
        }
1829
0
        break;
1830
1831
0
        case SID_SYMBOLS_CATALOGUE:
1832
0
        {
1833
0
            SmModule* pp = SmModule::get();
1834
1835
            // get device used to retrieve the FontList
1836
0
            SmDocShell *pDoc = GetDoc();
1837
0
            OutputDevice *pDev = pDoc->GetPrinter();
1838
0
            if (!pDev || pDev->GetFontFaceCollectionCount() == 0)
1839
0
                pDev = &pp->GetDefaultVirtualDev();
1840
0
            SAL_WARN_IF( !pDev, "starmath", "device for font list missing" );
1841
1842
0
            SmSymbolDialog aDialog(pWin ? pWin->GetFrameWeld() : nullptr, pDev, pp->GetSymbolManager(), *this);
1843
0
            aDialog.run();
1844
0
        }
1845
0
        break;
1846
1847
0
        case SID_CHARMAP:
1848
0
        {
1849
0
            const SfxItemSet* pArgs = rReq.GetArgs();
1850
0
            const SfxStringItem* pItem = nullptr;
1851
0
            if (pArgs && SfxItemState::SET == pArgs->GetItemState(SID_CHARMAP, true, &pItem))
1852
0
            {
1853
0
                if (IsInlineEditEnabled())
1854
0
                    GetDoc()->GetCursor().InsertText(pItem->GetValue());
1855
0
                else if (pWin)
1856
0
                    pWin->InsertText(pItem->GetValue());
1857
0
                break;
1858
0
            }
1859
1860
0
            SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
1861
0
            SfxAllItemSet aSet(GetViewFrame().GetObjectShell()->GetPool());
1862
0
            aSet.Put(SfxBoolItem(FN_PARAM_1, false));
1863
0
            aSet.Put(SfxStringItem(SID_FONT_NAME,
1864
0
                                   GetDoc()->GetFormat().GetFont(FNT_VARIABLE).GetFamilyName()));
1865
0
            VclPtr<SfxAbstractDialog> pDialog(
1866
0
                pFact->CreateCharMapDialog(pWin ? pWin->GetFrameWeld() : nullptr, aSet,
1867
0
                                           GetViewFrame().GetFrame().GetFrameInterface()));
1868
0
            pDialog->StartExecuteAsync(
1869
0
                [pDialog] (sal_Int32 /*nResult*/)->void
1870
0
                {
1871
0
                    pDialog->disposeOnce();
1872
0
                }
1873
0
            );
1874
0
        }
1875
0
        break;
1876
1877
0
        case SID_ATTR_PARA_LEFT_TO_RIGHT:
1878
0
        case SID_ATTR_PARA_RIGHT_TO_LEFT:
1879
0
        {
1880
0
            bool bRTL = rReq.GetSlot() == SID_ATTR_PARA_RIGHT_TO_LEFT;
1881
0
            GetDoc()->SetRightToLeft(bRTL);
1882
0
            GetGraphicWindow().GetGraphicWidget().GetOutputDevice().EnableRTL(bRTL);
1883
0
            GetViewFrame().GetBindings().Invalidate(bRTL ? SID_ATTR_PARA_LEFT_TO_RIGHT : SID_ATTR_PARA_RIGHT_TO_LEFT);
1884
0
        }
1885
0
        break;
1886
0
        case SID_SAVE_FORMULA:
1887
0
        {
1888
0
            OUString aName = "My Formula 1";
1889
0
            OUString aDesc(SmResId(STR_USER_DEFINED_FORMULA));
1890
0
            SvxNameDialog aDlg(GetFrameWeld(), aName, aDesc);
1891
1892
0
            if (aDlg.run() == RET_OK)
1893
0
            {
1894
0
                aName = aDlg.GetName();
1895
0
                if (SmModule::get()->GetConfig()->HasUserDefinedFormula(aName))
1896
0
                {
1897
0
                    std::unique_ptr<weld::MessageDialog> xQuery(Application::CreateMessageDialog(
1898
0
                        GetFrameWeld(), VclMessageType::Question, VclButtonsType::YesNo,
1899
0
                        SmResId(STR_USER_DEFINED_FORMULA_EXISTS).replaceAll("%1", aName)));
1900
0
                    if (xQuery->run() == RET_NO)
1901
0
                        break;
1902
0
                }
1903
0
                if (SmEditWindow* pEditWin = GetEditWindow())
1904
0
                    SmModule::get()->GetConfig()->SaveUserDefinedFormula(aName, pEditWin->GetText());
1905
1906
                // Show the Elements sidebar with the "User-defined" entry selected
1907
0
                GetViewFrame().ShowChildWindow(SID_SIDEBAR);
1908
0
                sfx2::sidebar::Sidebar::ShowPanel(u"MathElementsPanel",
1909
0
                                                  GetViewFrame().GetFrame().GetFrameInterface());
1910
0
                GetViewFrame().GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW );
1911
0
                Broadcast(SfxHint(SfxHintId::SmNewUserFormula));
1912
0
                rReq.Ignore ();
1913
0
            }
1914
0
        }
1915
0
        break;
1916
0
    }
1917
0
    rReq.Done();
1918
0
}
1919
1920
1921
void SmViewShell::GetState(SfxItemSet &rSet)
1922
0
{
1923
0
    SfxWhichIter aIter(rSet);
1924
1925
0
    SmEditWindow *pEditWin = GetEditWindow();
1926
0
    for (sal_uInt16 nWh = aIter.FirstWhich(); nWh != 0; nWh = aIter.NextWhich())
1927
0
    {
1928
0
        switch (nWh)
1929
0
        {
1930
0
        case SID_CUT:
1931
0
        case SID_COPY:
1932
0
        case SID_DELETE:
1933
0
            if (IsInlineEditEnabled())
1934
0
            {
1935
0
                if (!GetDoc()->GetCursor().HasSelection())
1936
0
                    rSet.DisableItem(nWh);
1937
0
            }
1938
0
            else if (! pEditWin || ! pEditWin->IsSelected())
1939
0
                rSet.DisableItem(nWh);
1940
0
            break;
1941
1942
0
        case SID_PASTE:
1943
0
            if (pEditWin)
1944
0
            {
1945
0
                TransferableDataHelper aDataHelper(
1946
0
                        TransferableDataHelper::CreateFromClipboard(
1947
0
                                                        pEditWin->GetClipboard()) );
1948
1949
0
                mbPasteState = aDataHelper.GetTransferable().is() &&
1950
0
                 ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) ||
1951
0
                   aDataHelper.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ ) ||
1952
0
                   (aDataHelper.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR )
1953
0
                      && aDataHelper.HasFormat( SotClipboardFormatId::EMBED_SOURCE )));
1954
0
            }
1955
0
            if( !mbPasteState )
1956
0
                rSet.DisableItem( nWh );
1957
0
            break;
1958
1959
0
        case SID_ATTR_ZOOM:
1960
0
            rSet.Put(SvxZoomItem( SvxZoomType::PERCENT, mxGraphicWindow->GetZoom()));
1961
0
            [[fallthrough]];
1962
0
        case SID_ZOOMIN:
1963
0
        case SID_ZOOMOUT:
1964
0
        case SID_ZOOM_OPTIMAL:
1965
0
            if ( GetViewFrame().GetFrame().IsInPlace() )
1966
0
                rSet.DisableItem( nWh );
1967
0
            break;
1968
1969
0
        case SID_ATTR_ZOOMSLIDER :
1970
0
            {
1971
0
                const sal_uInt16 nCurrentZoom = mxGraphicWindow->GetZoom();
1972
0
                SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM );
1973
0
                aZoomSliderItem.AddSnappingPoint( 100 );
1974
0
                rSet.Put( aZoomSliderItem );
1975
0
            }
1976
0
        break;
1977
1978
0
        case SID_NEXTERR:
1979
0
        case SID_PREVERR:
1980
0
        case SID_NEXTMARK:
1981
0
        case SID_PREVMARK:
1982
0
        case SID_DRAW:
1983
0
        case SID_SELECT:
1984
0
            if (! pEditWin || pEditWin->IsEmpty())
1985
0
                rSet.DisableItem(nWh);
1986
0
            break;
1987
1988
0
        case SID_TEXTSTATUS:
1989
0
            {
1990
0
                rSet.Put(SfxStringItem(nWh, maStatusText));
1991
0
            }
1992
0
            break;
1993
1994
0
        case SID_FORMULACURSOR:
1995
0
            {
1996
0
                if (IsInlineEditEnabled())
1997
0
                    rSet.DisableItem(nWh);
1998
0
                else
1999
0
                    rSet.Put(SfxBoolItem(nWh, SmModule::get()->GetConfig()->IsShowFormulaCursor()));
2000
0
            }
2001
0
            break;
2002
0
        case SID_ELEMENTSDOCKINGWINDOW:
2003
0
            {
2004
0
                const bool bState = sfx2::sidebar::Sidebar::IsPanelVisible(
2005
0
                    u"MathElementsPanel", GetViewFrame().GetFrame().GetFrameInterface());
2006
0
                rSet.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW, bState));
2007
0
            }
2008
0
            break;
2009
0
        case SID_CMDBOXWINDOW:
2010
0
            {
2011
0
                bool bState = false;
2012
0
                auto pCmdWin = GetViewFrame().GetChildWindow(SID_CMDBOXWINDOW);
2013
0
                if (pCmdWin)
2014
0
                    bState = pCmdWin->IsVisible();
2015
0
                rSet.Put(SfxBoolItem(SID_CMDBOXWINDOW, bState));
2016
0
            }
2017
0
            break;
2018
0
        case SID_ATTR_PARA_LEFT_TO_RIGHT:
2019
0
            rSet.Put(SfxBoolItem(nWh, !GetDoc()->GetFormat().IsRightToLeft()));
2020
0
            break;
2021
2022
0
        case SID_ATTR_PARA_RIGHT_TO_LEFT:
2023
0
            rSet.Put(SfxBoolItem(nWh, GetDoc()->GetFormat().IsRightToLeft()));
2024
0
            break;
2025
0
        case SID_SAVE_FORMULA:
2026
0
            if (!pEditWin || pEditWin->IsEmpty())
2027
0
                rSet.DisableItem(nWh);
2028
0
            break;
2029
0
        }
2030
0
    }
2031
0
}
2032
2033
namespace
2034
{
2035
css::uno::Reference<css::ui::XSidebar>
2036
getSidebarFromModel(const css::uno::Reference<css::frame::XModel>& xModel)
2037
0
{
2038
0
    css::uno::Reference<css::container::XChild> xChild(xModel, css::uno::UNO_QUERY);
2039
0
    if (!xChild.is())
2040
0
        return nullptr;
2041
0
    css::uno::Reference<css::frame::XModel> xParent(xChild->getParent(), css::uno::UNO_QUERY);
2042
0
    if (!xParent.is())
2043
0
        return nullptr;
2044
0
    css::uno::Reference<css::frame::XController2> xController(xParent->getCurrentController(),
2045
0
                                                              css::uno::UNO_QUERY);
2046
0
    if (!xController.is())
2047
0
        return nullptr;
2048
0
    css::uno::Reference<css::ui::XSidebarProvider> xSidebarProvider = xController->getSidebar();
2049
0
    if (!xSidebarProvider.is())
2050
0
        return nullptr;
2051
0
    return xSidebarProvider->getSidebar();
2052
0
}
2053
class SmController : public SfxBaseController
2054
{
2055
public:
2056
    SmController(SfxViewShell& rViewShell)
2057
0
        : SfxBaseController(&rViewShell)
2058
0
        , mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
2059
0
              GetContextName, this, vcl::EnumContext::Context::Math))
2060
0
    {
2061
0
        rViewShell.SetContextName(GetContextName());
2062
0
    }
2063
    // No need to call mpSelectionChangeHandler->Disconnect() unless SmController implements XSelectionSupplier
2064
    // ~SmController() { mpSelectionChangeHandler->Disconnect(); }
2065
2066
    // css::frame::XController
2067
    void SAL_CALL attachFrame(const css::uno::Reference<css::frame::XFrame>& xFrame) override
2068
0
    {
2069
0
        SfxBaseController::attachFrame(xFrame);
2070
2071
0
        if (comphelper::LibreOfficeKit::isActive())
2072
0
        {
2073
0
            CopyLokViewCallbackFromFrameCreator();
2074
            // In lok mode, DocumentHolder::ShowUI is not called on OLE in-place activation,
2075
            // because respective code is skipped in OCommonEmbeddedObject::SwitchStateTo_Impl,
2076
            // so sidebar controller does not get registered properly; do it here
2077
0
            if (auto xSidebar = getSidebarFromModel(getModel()))
2078
0
            {
2079
0
                auto pSidebar = dynamic_cast<sfx2::sidebar::SidebarController*>(xSidebar.get());
2080
0
                assert(pSidebar);
2081
0
                pSidebar->registerSidebarForFrame(this);
2082
0
                pSidebar->updateModel(getModel());
2083
0
            }
2084
0
        }
2085
2086
        // No need to call mpSelectionChangeHandler->Connect() unless SmController implements XSelectionSupplier
2087
0
        mpSelectionChangeHandler->selectionChanged({}); // Installs the correct context
2088
0
    }
2089
2090
    virtual void SAL_CALL dispose() override
2091
0
    {
2092
0
        if (comphelper::LibreOfficeKit::isActive())
2093
0
            if (auto pViewShell = GetViewShell_Impl())
2094
0
                pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE,
2095
0
                                                       OString::boolean(false));
2096
2097
0
        SfxBaseController::dispose();
2098
0
    }
2099
2100
private:
2101
0
    static OUString GetContextName() { return u"Math"_ustr; } // Static constant for now
2102
2103
    rtl::Reference<svx::sidebar::SelectionChangeHandler> mpSelectionChangeHandler;
2104
};
2105
}
2106
2107
SmViewShell::SmViewShell(SfxViewFrame& rFrame_, SfxViewShell *)
2108
0
    : SfxViewShell(rFrame_, SfxViewShellFlags::HAS_PRINTOPTIONS)
2109
0
    , mxGraphicWindow(VclPtr<SmGraphicWindow>::Create(*this))
2110
0
    , maGraphicController(mxGraphicWindow->GetGraphicWidget(), SID_GRAPHIC_SM, rFrame_.GetBindings())
2111
0
    , mbPasteState(false)
2112
0
{
2113
0
    SetStatusText(OUString());
2114
0
    SetWindow(mxGraphicWindow.get());
2115
0
    SfxShell::SetName(u"SmView"_ustr);
2116
0
    SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() );
2117
0
    SetController(new SmController(*this));
2118
0
}
2119
2120
SmViewShell::~SmViewShell()
2121
0
{
2122
    //!! this view shell is not active anymore !!
2123
    // Thus 'SmGetActiveView' will give a 0 pointer.
2124
    // Thus we need to supply this view as argument
2125
0
    if (SmEditWindow *pEditWin = GetEditWindow())
2126
0
        pEditWin->DeleteEditView();
2127
0
    mxGraphicWindow.disposeAndClear();
2128
0
}
2129
2130
void SmViewShell::Deactivate( bool bIsMDIActivate )
2131
0
{
2132
0
    if (SmEditWindow *pEdit = GetEditWindow())
2133
0
        pEdit->Flush();
2134
2135
0
    SfxViewShell::Deactivate( bIsMDIActivate );
2136
0
}
2137
2138
void SmViewShell::Activate( bool bIsMDIActivate )
2139
0
{
2140
0
    SfxViewShell::Activate( bIsMDIActivate );
2141
2142
0
    if (IsInlineEditEnabled())
2143
0
    {
2144
        // In LOK, activate in-place editing
2145
0
        GetGraphicWidget().GrabFocus();
2146
0
    }
2147
0
    else if (SmEditWindow *pEdit = GetEditWindow())
2148
0
    {
2149
        //! Since there is no way to be informed if a "drag and drop"
2150
        //! event has taken place, we call SetText here in order to
2151
        //! synchronize the GraphicWindow display with the text in the
2152
        //! EditEngine.
2153
0
        SmDocShell *pDoc = GetDoc();
2154
0
        pDoc->SetText( pDoc->GetEditEngine().GetText() );
2155
2156
0
        if ( bIsMDIActivate )
2157
0
            pEdit->GrabFocus();
2158
0
    }
2159
0
}
2160
2161
IMPL_LINK( SmViewShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
2162
0
{
2163
0
    assert(_pFileDlg && "SmViewShell::DialogClosedHdl(): no file dialog");
2164
0
    assert(mpDocInserter && "ScDocShell::DialogClosedHdl(): no document inserter");
2165
2166
0
    if ( ERRCODE_NONE == _pFileDlg->GetError() )
2167
0
    {
2168
0
        std::unique_ptr<SfxMedium> pMedium = mpDocInserter->CreateMedium();
2169
2170
0
        if ( pMedium )
2171
0
        {
2172
0
            if ( pMedium->IsStorage() )
2173
0
                Insert( *pMedium );
2174
0
            else
2175
0
                InsertFrom( *pMedium );
2176
0
            pMedium.reset();
2177
2178
0
            SmDocShell* pDoc = GetDoc();
2179
0
            pDoc->UpdateText();
2180
0
            pDoc->ArrangeFormula();
2181
0
            pDoc->Repaint();
2182
            // adjust window, repaint, increment ModifyCount,...
2183
0
            GetViewFrame().GetBindings().Invalidate(SID_GRAPHIC_SM);
2184
0
        }
2185
0
    }
2186
2187
0
    mpRequest->SetReturnValue( SfxBoolItem( mpRequest->GetSlot(), true ) );
2188
0
    mpRequest->Done();
2189
0
}
2190
2191
void SmViewShell::Notify( SfxBroadcaster& , const SfxHint& rHint )
2192
0
{
2193
0
    switch( rHint.GetId() )
2194
0
    {
2195
0
        case SfxHintId::ModeChanged:
2196
0
        case SfxHintId::DocChanged:
2197
0
            GetViewFrame().GetBindings().InvalidateAll(false);
2198
0
        break;
2199
0
        default:
2200
0
        break;
2201
0
    }
2202
0
}
2203
2204
bool SmViewShell::IsInlineEditEnabled()
2205
0
{
2206
0
    return comphelper::LibreOfficeKit::isActive()
2207
0
           || SmModule::get()->GetConfig()->IsInlineEditEnable();
2208
0
}
2209
2210
void SmViewShell::StartMainHelp()
2211
0
{
2212
0
    Help* pHelp = Application::GetHelp();
2213
0
    if (pHelp)
2214
0
        pHelp->Start(HID_SMA_MAIN_HELP, GetViewFrame().GetFrameWeld());
2215
0
}
2216
2217
void SmViewShell::ZoomByItemSet(const SfxItemSet *pSet)
2218
0
{
2219
0
    assert(pSet);
2220
0
    const SvxZoomItem &rZoom = pSet->Get(SID_ATTR_ZOOM);
2221
0
    switch( rZoom.GetType() )
2222
0
    {
2223
0
        case SvxZoomType::PERCENT:
2224
0
            mxGraphicWindow->SetZoom(sal::static_int_cast<sal_uInt16>(rZoom.GetValue ()));
2225
0
            break;
2226
2227
0
        case SvxZoomType::OPTIMAL:
2228
0
            mxGraphicWindow->ZoomToFitInWindow();
2229
0
            break;
2230
2231
0
        case SvxZoomType::PAGEWIDTH:
2232
0
        case SvxZoomType::WHOLEPAGE:
2233
0
        {
2234
0
            const MapMode aMap( SmMapUnit() );
2235
0
            SfxPrinter *pPrinter = GetPrinter( true );
2236
0
            tools::Rectangle  OutputRect(Point(), pPrinter->GetOutputSize());
2237
0
            Size       OutputSize(pPrinter->LogicToPixel(Size(OutputRect.GetWidth(),
2238
0
                                                              OutputRect.GetHeight()), aMap));
2239
0
            Size       GraphicSize(pPrinter->LogicToPixel(GetDoc()->GetSize(), aMap));
2240
0
            if (GraphicSize.Width() <= 0 || GraphicSize.Height() <= 0)
2241
0
                break;
2242
0
            sal_uInt16 nZ = std::min(o3tl::convert(OutputSize.Width(), 100, GraphicSize.Width()),
2243
0
                                     o3tl::convert(OutputSize.Height(), 100, GraphicSize.Height()));
2244
0
            mxGraphicWindow->SetZoom(nZ);
2245
0
            break;
2246
0
        }
2247
0
        default:
2248
0
            break;
2249
0
    }
2250
0
}
2251
2252
std::optional<OString> SmViewShell::getLOKPayload(int nType, int nViewId) const
2253
0
{
2254
0
    switch (nType)
2255
0
    {
2256
0
        case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR:
2257
0
        {
2258
0
            OString sRectangle;
2259
0
            if (const SmGraphicWidget& widget = GetGraphicWidget(); widget.IsCursorVisible())
2260
0
            {
2261
0
                SmCursor& rCursor = GetDoc()->GetCursor();
2262
0
                OutputDevice& rOutDev = const_cast<SmGraphicWidget&>(widget).GetOutputDevice();
2263
0
                tools::Rectangle aCaret = rCursor.GetCaretRectangle(rOutDev);
2264
0
                Point aFormulaDrawPos = widget.GetFormulaDrawPos();
2265
0
                aCaret.Move(aFormulaDrawPos.X(), aFormulaDrawPos.Y());
2266
0
                LokStarMathHelper helper(SfxViewShell::Current());
2267
0
                tools::Rectangle aBounds = helper.GetBoundingBox();
2268
0
                aCaret.Move(aBounds.Left(), aBounds.Top());
2269
0
                sRectangle = aCaret.toString();
2270
0
            }
2271
0
            return SfxLokHelper::makeVisCursorInvalidation(nViewId, sRectangle, false, {});
2272
0
        }
2273
0
        case LOK_CALLBACK_TEXT_SELECTION:
2274
0
        {
2275
0
            OString sRectangle;
2276
0
            if (const SmGraphicWidget& widget = GetGraphicWidget(); widget.IsCursorVisible())
2277
0
            {
2278
0
                SmCursor& rCursor = GetDoc()->GetCursor();
2279
0
                OutputDevice& rOutDev = const_cast<SmGraphicWidget&>(widget).GetOutputDevice();
2280
0
                tools::Rectangle aSelection = rCursor.GetSelectionRectangle(rOutDev);
2281
0
                if (!aSelection.IsEmpty())
2282
0
                {
2283
0
                    Point aFormulaDrawPos = widget.GetFormulaDrawPos();
2284
0
                    aSelection.Move(aFormulaDrawPos.X(), aFormulaDrawPos.Y());
2285
0
                    LokStarMathHelper helper(SfxViewShell::Current());
2286
0
                    tools::Rectangle aBounds = helper.GetBoundingBox();
2287
2288
0
                    aSelection.Move(aBounds.Left(), aBounds.Top());
2289
0
                    sRectangle = aSelection.toString();
2290
0
                }
2291
0
            }
2292
0
            return sRectangle;
2293
0
        }
2294
0
        case LOK_CALLBACK_TEXT_SELECTION_START:
2295
0
        case LOK_CALLBACK_TEXT_SELECTION_END:
2296
0
        case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
2297
0
        case LOK_CALLBACK_TEXT_VIEW_SELECTION:
2298
0
            return {};
2299
0
    }
2300
0
    return SfxViewShell::getLOKPayload(nType, nViewId); // aborts
2301
0
}
2302
2303
void SmViewShell::SendCaretToLOK() const
2304
0
{
2305
0
    const int nViewId = sal_Int32(GetViewShellId());
2306
0
    if (const auto payload = getLOKPayload(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, nViewId))
2307
0
    {
2308
0
        libreOfficeKitViewCallbackWithViewId(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR,
2309
0
                                             *payload, nViewId);
2310
0
    }
2311
0
    if (const auto payload = getLOKPayload(LOK_CALLBACK_TEXT_SELECTION, nViewId))
2312
0
    {
2313
0
        libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, *payload);
2314
0
    }
2315
0
}
2316
2317
void SmViewShell::InvalidateSlots()
2318
0
{
2319
0
    auto& rBind = GetViewFrame().GetBindings();
2320
0
    rBind.Invalidate(SID_COPY);
2321
0
    rBind.Invalidate(SID_CUT);
2322
0
    rBind.Invalidate(SID_DELETE);
2323
0
}
2324
2325
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */