1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
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>
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/dispatch.hxx>
38 #include <sfx2/docfile.hxx>
39 #include <sfx2/docfilt.hxx>
40 #include <sfx2/docinsert.hxx>
41 #include <sfx2/filedlghelper.hxx>
42 #include <sfx2/infobar.hxx>
43 #include <sfx2/lokcomponenthelpers.hxx>
44 #include <sfx2/lokhelper.hxx>
45 #include <sfx2/msg.hxx>
46 #include <sfx2/objface.hxx>
47 #include <sfx2/printer.hxx>
48 #include <sfx2/request.hxx>
49 #include <sfx2/sfxbasecontroller.hxx>
50 #include <sfx2/sidebar/Sidebar.hxx>
51 #include <sfx2/sidebar/SidebarChildWindow.hxx>
52 #include <sfx2/sidebar/SidebarController.hxx>
53 #include <sfx2/viewfac.hxx>
54 #include <svl/eitem.hxx>
55 #include <svl/itemset.hxx>
56 #include <svl/poolitem.hxx>
57 #include <svl/stritem.hxx>
58 #include <vcl/transfer.hxx>
59 #include <svtools/colorcfg.hxx>
60 #include <svl/whiter.hxx>
61 #include <svx/sidebar/SelectionChangeHandler.hxx>
62 #include <svx/zoomslideritem.hxx>
63 #include <editeng/editeng.hxx>
64 #include <editeng/editview.hxx>
65 #include <svx/svxdlg.hxx>
66 #include <sfx2/zoomitem.hxx>
67 #include <vcl/commandevent.hxx>
68 #include <vcl/event.hxx>
69 #include <vcl/settings.hxx>
70 #include <vcl/virdev.hxx>
71 #include <sal/log.hxx>
72 #include <tools/svborder.hxx>
73 #include <o3tl/string_view.hxx>
74 #include <o3tl/temporary.hxx>
76 #include <unotools/streamwrap.hxx>
78 #include <unomodel.hxx>
80 #include <cfgitem.hxx>
82 #include <document.hxx>
83 #include <starmath.hrc>
84 #include <strings.hrc>
86 #include <mathmlimport.hxx>
88 #include "accessibility.hxx"
89 #include <ElementsDockingWindow.hxx>
92 #define MINZOOM sal_uInt16(25)
93 #define MAXZOOM sal_uInt16(800)
95 // space around the edit window, in pixels
96 // fdo#69111: Increased border on the top so that the window is
97 // easier to tear off.
98 #define CMD_BOX_PADDING 3
99 #define CMD_BOX_PADDING_TOP 11
101 #define ShellClass_SmViewShell
102 #include <smslots.hxx>
105 using namespace css::accessibility
;
106 using namespace css::uno
;
108 SmGraphicWindow::SmGraphicWindow(SmViewShell
& rShell
)
109 : InterimItemWindow(&rShell
.GetViewFrame().GetWindow(), "modules/smath/ui/mathwindow.ui", "MathWindow")
110 , nLinePixH(GetSettings().GetStyleSettings().GetScrollBarSize())
111 , nColumnPixW(nLinePixH
)
113 // continue to use user-scrolling to make this work equivalent to how it 'always' worked
114 , mxScrolledWindow(m_xBuilder
->weld_scrolled_window("scrolledwindow", true))
115 , mxGraphic(new SmGraphicWidget(rShell
, *this))
116 , mxGraphicWin(new weld::CustomWeld(*m_xBuilder
, "mathview", *mxGraphic
))
118 InitControlBase(mxGraphic
->GetDrawingArea());
120 mxScrolledWindow
->connect_hadjustment_changed(LINK(this, SmGraphicWindow
, ScrollHdl
));
121 mxScrolledWindow
->connect_vadjustment_changed(LINK(this, SmGraphicWindow
, ScrollHdl
));
123 // docking windows are usually hidden (often already done in the
124 // resource) and will be shown by the sfx framework.
128 void SmGraphicWindow::dispose()
130 InitControlBase(nullptr);
131 mxGraphicWin
.reset();
133 mxScrolledWindow
.reset();
134 InterimItemWindow::dispose();
137 SmGraphicWindow::~SmGraphicWindow()
142 void SmGraphicWindow::Resize()
144 InterimItemWindow::Resize();
146 // get the new output-size in pixel
147 Size aOutPixSz
= GetOutputSizePixel();
149 // determine the size of the output-area and if we need scrollbars
150 const auto nScrSize
= mxScrolledWindow
->get_scroll_thickness();
151 bool bVVisible
= false; // by default no vertical-ScrollBar
152 bool bHVisible
= false; // by default no horizontal-ScrollBar
153 bool bChanged
; // determines if a visiblility was changed
158 // does we need a vertical ScrollBar
159 if ( aOutPixSz
.Width() < aTotPixSz
.Width() && !bHVisible
)
162 aOutPixSz
.AdjustHeight( -nScrSize
);
166 // does we need a horizontal ScrollBar
167 if ( aOutPixSz
.Height() < aTotPixSz
.Height() && !bVVisible
)
170 aOutPixSz
.AdjustWidth( -nScrSize
);
175 while ( bChanged
); // until no visibility has changed
177 // store the old offset and map-mode
178 MapMode
aMap(GetGraphicMapMode());
179 Point
aOldPixOffset(aPixOffset
);
181 // justify (right/bottom borders should never exceed the virtual window)
183 if ( aPixOffset
.X() < 0 &&
184 aPixOffset
.X() + aTotPixSz
.Width() < aOutPixSz
.Width() )
186 aOutPixSz
.Width() - ( aPixOffset
.X() + aTotPixSz
.Width() ) );
187 if ( aPixOffset
.Y() < 0 &&
188 aPixOffset
.Y() + aTotPixSz
.Height() < aOutPixSz
.Height() )
190 aOutPixSz
.Height() - ( aPixOffset
.Y() + aTotPixSz
.Height() ) );
191 if ( aPixDelta
.Width() || aPixDelta
.Height() )
193 aPixOffset
.AdjustX(aPixDelta
.Width() );
194 aPixOffset
.AdjustY(aPixDelta
.Height() );
197 // for axis without scrollbar restore the origin
198 if ( !bVVisible
|| !bHVisible
)
203 : (aOutPixSz
.Width()-aTotPixSz
.Width()) / 2,
206 : (aOutPixSz
.Height()-aTotPixSz
.Height()) / 2 );
208 if (bHVisible
&& mxScrolledWindow
->get_hpolicy() == VclPolicyType::NEVER
)
209 aPixOffset
.setX( 0 );
210 if (bVVisible
&& mxScrolledWindow
->get_vpolicy() == VclPolicyType::NEVER
)
211 aPixOffset
.setY( 0 );
213 // select the shifted map-mode
214 if (aPixOffset
!= aOldPixOffset
)
215 SetGraphicMapMode(aMap
);
217 // show or hide scrollbars
218 mxScrolledWindow
->set_vpolicy(bVVisible
? VclPolicyType::ALWAYS
: VclPolicyType::NEVER
);
219 mxScrolledWindow
->set_hpolicy(bHVisible
? VclPolicyType::ALWAYS
: VclPolicyType::NEVER
);
221 // resize scrollbars and set their ranges
224 mxScrolledWindow
->hadjustment_configure(-aPixOffset
.X(), 0, aTotPixSz
.Width(), nColumnPixW
,
225 aOutPixSz
.Width(), aOutPixSz
.Width());
229 mxScrolledWindow
->vadjustment_configure(-aPixOffset
.Y(), 0, aTotPixSz
.Height(), nLinePixH
,
230 aOutPixSz
.Height(), aOutPixSz
.Height());
234 IMPL_LINK_NOARG(SmGraphicWindow
, ScrollHdl
, weld::ScrolledWindow
&, void)
236 MapMode
aMap(GetGraphicMapMode());
237 Point
aNewPixOffset(aPixOffset
);
239 // scrolling horizontally?
240 if (mxScrolledWindow
->get_hpolicy() == VclPolicyType::ALWAYS
)
241 aNewPixOffset
.setX(-mxScrolledWindow
->hadjustment_get_value());
243 // scrolling vertically?
244 if (mxScrolledWindow
->get_vpolicy() == VclPolicyType::ALWAYS
)
245 aNewPixOffset
.setY(-mxScrolledWindow
->vadjustment_get_value());
248 if (aPixOffset
== aNewPixOffset
)
251 // recompute the logical scroll units
252 aPixOffset
= aNewPixOffset
;
254 SetGraphicMapMode(aMap
);
257 void SmGraphicWindow::SetGraphicMapMode(const MapMode
& rNewMapMode
)
259 OutputDevice
& rDevice
= mxGraphic
->GetOutputDevice();
260 MapMode
aMap( rNewMapMode
);
261 aMap
.SetOrigin( aMap
.GetOrigin() + rDevice
.PixelToLogic( aPixOffset
, aMap
) );
262 rDevice
.SetMapMode( aMap
);
263 mxGraphic
->Invalidate();
266 MapMode
SmGraphicWindow::GetGraphicMapMode() const
268 OutputDevice
& rDevice
= mxGraphic
->GetOutputDevice();
269 MapMode
aMap(rDevice
.GetMapMode());
270 aMap
.SetOrigin( aMap
.GetOrigin() - rDevice
.PixelToLogic( aPixOffset
) );
274 void SmGraphicWindow::SetTotalSize( const Size
& rNewSize
)
276 aTotPixSz
= mxGraphic
->GetOutputDevice().LogicToPixel(rNewSize
);
280 Size
SmGraphicWindow::GetTotalSize() const
282 return mxGraphic
->GetOutputDevice().PixelToLogic(aTotPixSz
);
285 void SmGraphicWindow::ShowContextMenu(const CommandEvent
& rCEvt
)
287 GetParent()->ToTop();
289 if (rCEvt
.IsMouseEvent())
290 aPos
= rCEvt
.GetMousePosPixel();
292 // added for replaceability of context menus
293 SfxDispatcher::ExecutePopup( this, &aPos
);
296 SmGraphicWidget::SmGraphicWidget(SmViewShell
& rShell
, SmGraphicWindow
& rGraphicWindow
)
297 : mrGraphicWindow(rGraphicWindow
)
298 , bIsCursorVisible(false)
299 , bIsLineVisible(false)
300 , aCaretBlinkTimer("SmGraphicWidget aCaretBlinkTimer")
301 , mrViewShell(rShell
)
305 void SmGraphicWidget::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
307 weld::CustomWidgetController::SetDrawingArea(pDrawingArea
);
309 OutputDevice
& rDevice
= GetOutputDevice();
311 rDevice
.SetBackground(SM_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
313 if (comphelper::LibreOfficeKit::isActive())
315 // Disable map mode, so that it's possible to send mouse event coordinates
316 // directly in twips.
317 rDevice
.EnableMapMode(false);
321 const Fraction
aFraction(1, 1);
322 rDevice
.SetMapMode(MapMode(SmMapUnit(), Point(), aFraction
, aFraction
));
327 SetHelpId(HID_SMA_WIN_DOCUMENT
);
333 SmGraphicWidget::~SmGraphicWidget()
335 if (mxAccessible
.is())
336 mxAccessible
->ClearWin(); // make Accessible nonfunctional
337 mxAccessible
.clear();
341 SmDocShell
* SmGraphicWidget::GetDoc() { return GetView().GetDoc(); }
343 SmCursor
& SmGraphicWidget::GetCursor()
346 return GetDoc()->GetCursor();
349 bool SmGraphicWidget::MouseButtonDown(const MouseEvent
& rMEvt
)
353 // set formula-cursor and selection of edit window according to the
354 // position clicked at
356 SAL_WARN_IF( rMEvt
.GetClicks() == 0, "starmath", "0 clicks" );
357 if ( !rMEvt
.IsLeft() )
360 OutputDevice
& rDevice
= GetOutputDevice();
361 // get click position relative to formula
362 Point
aPos(rDevice
.PixelToLogic(rMEvt
.GetPosPixel()) - GetFormulaDrawPos());
364 const SmNode
*pTree
= GetDoc()->GetFormulaTree();
368 if (SmViewShell::IsInlineEditEnabled()) {
369 GetCursor().MoveTo(&rDevice
, aPos
, !rMEvt
.IsShift());
370 // 'on grab' window events are missing in lok, do it explicitly
371 if (comphelper::LibreOfficeKit::isActive())
372 SetIsCursorVisible(true);
375 const SmNode
*pNode
= nullptr;
376 // if it was clicked inside the formula then get the appropriate node
377 if (pTree
->OrientedDist(aPos
) <= 0)
378 pNode
= pTree
->FindRectClosestTo(aPos
);
383 SmEditWindow
* pEdit
= GetView().GetEditWindow();
387 // set selection to the beginning of the token
388 pEdit
->SetSelection(pNode
->GetSelection());
391 // allow for immediate editing and
392 //! implicitly synchronize the cursor position mark in this window
398 bool SmGraphicWidget::MouseMove(const MouseEvent
&rMEvt
)
400 if (rMEvt
.IsLeft() && SmViewShell::IsInlineEditEnabled())
402 OutputDevice
& rDevice
= GetOutputDevice();
403 Point
aPos(rDevice
.PixelToLogic(rMEvt
.GetPosPixel()) - GetFormulaDrawPos());
404 GetCursor().MoveTo(&rDevice
, aPos
, false);
407 SetIsCursorVisible(true);
409 RepaintViewShellDoc();
414 void SmGraphicWidget::GetFocus()
416 if (!SmViewShell::IsInlineEditEnabled())
418 if (SmEditWindow
* pEdit
= GetView().GetEditWindow())
420 //Let view shell know what insertions should be done in visual editor
421 GetView().SetInsertIntoEditWindow(false);
422 SetIsCursorVisible(true);
425 RepaintViewShellDoc();
428 void SmGraphicWidget::LoseFocus()
430 if (mxAccessible
.is())
432 uno::Any aOldValue
, aNewValue
;
433 aOldValue
<<= AccessibleStateType::FOCUSED
;
434 // aNewValue remains empty
435 mxAccessible
->LaunchEvent( AccessibleEventId::STATE_CHANGED
,
436 aOldValue
, aNewValue
);
438 if (!SmViewShell::IsInlineEditEnabled())
440 SetIsCursorVisible(false);
443 RepaintViewShellDoc();
446 void SmGraphicWidget::RepaintViewShellDoc()
448 if (SmDocShell
* pDoc
= GetDoc())
452 IMPL_LINK_NOARG(SmGraphicWidget
, CaretBlinkTimerHdl
, Timer
*, void)
454 if (IsCursorVisible())
455 SetIsCursorVisible(false);
457 SetIsCursorVisible(true);
459 RepaintViewShellDoc();
462 void SmGraphicWidget::CaretBlinkInit()
464 if (comphelper::LibreOfficeKit::isActive())
465 return; // No blinking in lok case
466 aCaretBlinkTimer
.SetInvokeHandler(LINK(this, SmGraphicWidget
, CaretBlinkTimerHdl
));
467 aCaretBlinkTimer
.SetTimeout(Application::GetSettings().GetStyleSettings().GetCursorBlinkTime());
470 void SmGraphicWidget::CaretBlinkStart()
472 if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive())
474 if (aCaretBlinkTimer
.GetTimeout() != STYLE_CURSOR_NOBLINKTIME
)
475 aCaretBlinkTimer
.Start();
478 void SmGraphicWidget::CaretBlinkStop()
480 if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive())
482 aCaretBlinkTimer
.Stop();
485 // shows or hides the formula-cursor depending on 'bShow' is true or not
486 void SmGraphicWidget::ShowCursor(bool bShow
)
488 if (SmViewShell::IsInlineEditEnabled())
491 bool bInvert
= bShow
!= IsCursorVisible();
493 InvertFocusRect(GetOutputDevice(), aCursorRect
);
495 SetIsCursorVisible(bShow
);
498 void SmGraphicWidget::ShowLine(bool bShow
)
500 if (!SmViewShell::IsInlineEditEnabled())
503 bIsLineVisible
= bShow
;
506 void SmGraphicWidget::SetIsCursorVisible(bool bVis
)
508 bIsCursorVisible
= bVis
;
509 if (comphelper::LibreOfficeKit::isActive())
511 mrViewShell
.SendCaretToLOK();
512 mrViewShell
.libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE
,
513 OString::boolean(bVis
));
517 void SmGraphicWidget::SetCursor(const SmNode
*pNode
)
519 if (SmViewShell::IsInlineEditEnabled())
522 const SmNode
*pTree
= GetDoc()->GetFormulaTree();
524 // get appropriate rectangle
525 Point
aOffset (pNode
->GetTopLeft() - pTree
->GetTopLeft()),
526 aTLPos (GetFormulaDrawPos() + aOffset
);
527 aTLPos
.AdjustX( -(pNode
->GetItalicLeftSpace()) );
528 Size
aSize (pNode
->GetItalicSize());
530 SetCursor(tools::Rectangle(aTLPos
, aSize
));
533 void SmGraphicWidget::SetCursor(const tools::Rectangle
&rRect
)
534 // sets cursor to new position (rectangle) 'rRect'.
535 // The old cursor will be removed, and the new one will be shown if
536 // that is activated in the ConfigItem
538 if (SmViewShell::IsInlineEditEnabled())
541 SmModule
*pp
= SM_MOD();
543 if (IsCursorVisible())
544 ShowCursor(false); // clean up remainings of old cursor
546 if (pp
->GetConfig()->IsShowFormulaCursor())
547 ShowCursor(true); // draw new cursor
550 const SmNode
* SmGraphicWidget::SetCursorPos(sal_uInt16 nRow
, sal_uInt16 nCol
)
551 // looks for a VISIBLE node in the formula tree with its token at
552 // (or around) the position 'nRow', 'nCol' in the edit window
553 // (row and column numbering starts with 1 there!).
554 // If there is such a node the formula-cursor is set to cover that nodes
555 // rectangle. If not the formula-cursor will be hidden.
556 // In any case the search result is being returned.
558 if (SmViewShell::IsInlineEditEnabled())
561 // find visible node with token at nRow, nCol
562 const SmNode
*pTree
= GetDoc()->GetFormulaTree(),
565 pNode
= pTree
->FindTokenAt(nRow
, nCol
);
575 void SmGraphicWidget::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
578 SmDocShell
& rDoc
= *GetDoc();
581 rDoc
.DrawFormula(rRenderContext
, aPoint
, true); //! modifies aPoint to be the topleft
582 //! corner of the formula
583 aFormulaDrawPos
= aPoint
;
584 if (SmViewShell::IsInlineEditEnabled())
586 //Draw cursor if any...
587 if (rDoc
.HasCursor() && IsLineVisible())
588 rDoc
.GetCursor().Draw(rRenderContext
, aPoint
, IsCursorVisible());
592 SetIsCursorVisible(false); // (old) cursor must be drawn again
594 if (const SmEditWindow
* pEdit
= GetView().GetEditWindow())
595 { // get new position for formula-cursor (for possible altered formula)
598 SmGetLeftSelectionPart(pEdit
->GetSelection(), nRow
, nCol
);
599 const SmNode
*pFound
= SetCursorPos(static_cast<sal_uInt16
>(nRow
), nCol
);
601 SmModule
*pp
= SM_MOD();
602 if (pFound
&& pp
->GetConfig()->IsShowFormulaCursor())
608 void SmGraphicWidget::SetTotalSize()
611 OutputDevice
& rDevice
= GetOutputDevice();
612 const Size
aTmp(rDevice
.PixelToLogic(rDevice
.LogicToPixel(GetDoc()->GetSize())));
613 if (aTmp
!= mrGraphicWindow
.GetTotalSize())
614 mrGraphicWindow
.SetTotalSize(aTmp
);
619 SmBracketType
BracketTypeOf(sal_uInt32 c
)
625 return SmBracketType::Round
;
628 return SmBracketType::Square
;
631 return SmBracketType::Curly
;
633 assert(false); // Unreachable
634 return SmBracketType::Round
;
637 bool CharInput(sal_uInt32 c
, SmCursor
& rCursor
, OutputDevice
& rDevice
)
644 rCursor
.InsertElement(BlankElement
);
647 rCursor
.InsertElement(FactorialElement
);
650 rCursor
.InsertElement(PercentElement
);
653 rCursor
.InsertElement(CDotElement
);
656 rCursor
.InsertElement(PlusElement
);
659 rCursor
.InsertElement(MinusElement
);
662 rCursor
.InsertElement(LessThanElement
);
665 rCursor
.InsertElement(EqualElement
);
668 rCursor
.InsertElement(GreaterThanElement
);
671 rCursor
.InsertSubSup(RSUP
);
674 rCursor
.InsertSubSup(RSUB
);
677 rCursor
.InsertFraction();
682 rCursor
.InsertBrackets(BracketTypeOf(c
));
687 if (rCursor
.IsAtTailOfBracket(BracketTypeOf(c
)))
689 rCursor
.Move(&rDevice
, MoveRight
);
694 rCursor
.InsertText(OUString(&c
, 1));
701 bool SmGraphicWidget::KeyInput(const KeyEvent
& rKEvt
)
703 if (!SmViewShell::IsInlineEditEnabled())
704 return GetView().KeyInput(rKEvt
);
706 bool bConsumed
= true;
708 SmCursor
& rCursor
= GetCursor();
709 switch (rKEvt
.GetKeyCode().GetFunction())
711 case KeyFuncType::COPY
:
714 case KeyFuncType::CUT
:
717 case KeyFuncType::PASTE
:
720 case KeyFuncType::UNDO
:
721 GetDoc()->Execute(o3tl::temporary(SfxRequest(*GetView().GetFrame(), SID_UNDO
)));
723 case KeyFuncType::REDO
:
724 GetDoc()->Execute(o3tl::temporary(SfxRequest(*GetView().GetFrame(), SID_REDO
)));
727 switch (rKEvt
.GetKeyCode().GetCode())
730 rCursor
.Move(&GetOutputDevice(), MoveLeft
, !rKEvt
.GetKeyCode().IsShift());
733 rCursor
.Move(&GetOutputDevice(), MoveRight
, !rKEvt
.GetKeyCode().IsShift());
736 rCursor
.Move(&GetOutputDevice(), MoveUp
, !rKEvt
.GetKeyCode().IsShift());
739 rCursor
.Move(&GetOutputDevice(), MoveDown
, !rKEvt
.GetKeyCode().IsShift());
742 if (!rKEvt
.GetKeyCode().IsShift())
746 if (!rCursor
.HasSelection())
748 rCursor
.Move(&GetOutputDevice(), MoveRight
, false);
749 if (rCursor
.HasComplexSelection())
755 rCursor
.DeletePrev(&GetOutputDevice());
758 if (!CharInput(rKEvt
.GetCharCode(), rCursor
, GetOutputDevice()))
759 bConsumed
= GetView().KeyInput(rKEvt
);
764 SetIsCursorVisible(true);
765 RepaintViewShellDoc();
770 bool SmGraphicWidget::Command(const CommandEvent
& rCEvt
)
772 bool bCallBase
= true;
773 if (!GetView().GetViewFrame().GetFrame().IsInPlace())
775 switch ( rCEvt
.GetCommand() )
777 case CommandEventId::ContextMenu
:
778 // purely for "ExecutePopup" taking a vcl::Window and
779 // we assume SmGraphicWindow 0,0 is at SmEditWindow 0,0
780 mrGraphicWindow
.ShowContextMenu(rCEvt
);
784 case CommandEventId::Wheel
:
786 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
787 if ( pWData
&& CommandWheelMode::ZOOM
== pWData
->GetMode() )
789 sal_uInt16 nTmpZoom
= mrGraphicWindow
.GetZoom();
790 if( 0 > pWData
->GetDelta() )
794 mrGraphicWindow
.SetZoom(nTmpZoom
);
799 case CommandEventId::GestureZoom
:
801 const CommandGestureZoomData
* pData
= rCEvt
.GetGestureZoomData();
804 if (pData
->meEventType
== GestureEventZoomType::Begin
)
806 mfLastZoomScale
= pData
->mfScaleDelta
;
808 else if (pData
->meEventType
== GestureEventZoomType::Update
)
810 double deltaBetweenEvents
= (pData
->mfScaleDelta
- mfLastZoomScale
) / mfLastZoomScale
;
811 mfLastZoomScale
= pData
->mfScaleDelta
;
813 // Accumulate fractional zoom to avoid small zoom changes from being ignored
814 mfAccumulatedZoom
+= deltaBetweenEvents
;
815 int nZoomChangePercent
= mfAccumulatedZoom
* 100;
816 mfAccumulatedZoom
-= nZoomChangePercent
/ 100.0;
818 sal_uInt16 nZoom
= mrGraphicWindow
.GetZoom();
819 nZoom
+= nZoomChangePercent
;
820 mrGraphicWindow
.SetZoom(nZoom
);
832 switch (rCEvt
.GetCommand())
834 case CommandEventId::ExtTextInput
:
835 if (comphelper::LibreOfficeKit::isActive())
837 const CommandExtTextInputData
* pData
= rCEvt
.GetExtTextInputData();
839 const OUString
& rText
= pData
->GetText();
840 SmCursor
& rCursor
= GetCursor();
841 OutputDevice
& rDevice
= GetOutputDevice();
842 for (sal_Int32 i
= 0; i
< rText
.getLength();)
843 CharInput(rText
.iterateCodePoints(&i
), rCursor
, rDevice
);
854 void SmGraphicWindow::SetZoom(sal_uInt16 Factor
)
856 if (comphelper::LibreOfficeKit::isActive())
858 nZoom
= std::clamp(Factor
, MINZOOM
, MAXZOOM
);
859 Fraction
aFraction(nZoom
, 100);
860 SetGraphicMapMode(MapMode(SmMapUnit(), Point(), aFraction
, aFraction
));
861 mxGraphic
->SetTotalSize();
862 SmViewShell
& rViewSh
= mxGraphic
->GetView();
863 rViewSh
.GetViewFrame().GetBindings().Invalidate(SID_ATTR_ZOOM
);
864 rViewSh
.GetViewFrame().GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER
);
867 void SmGraphicWindow::ZoomToFitInWindow()
869 // set defined mapmode before calling 'LogicToPixel' below
870 SetGraphicMapMode(MapMode(SmMapUnit()));
872 assert(mxGraphic
->GetDoc());
873 Size
aSize(mxGraphic
->GetOutputDevice().LogicToPixel(mxGraphic
->GetDoc()->GetSize()));
874 Size
aWindowSize(GetSizePixel());
876 if (!aSize
.IsEmpty())
878 tools::Long nVal
= std::min ((85 * aWindowSize
.Width()) / aSize
.Width(),
879 (85 * aWindowSize
.Height()) / aSize
.Height());
880 SetZoom ( sal::static_int_cast
< sal_uInt16
>(nVal
) );
884 uno::Reference
< XAccessible
> SmGraphicWidget::CreateAccessible()
886 if (!mxAccessible
.is())
888 mxAccessible
= new SmGraphicAccessible( this );
893 /**************************************************************************/
894 SmGraphicController::SmGraphicController(SmGraphicWidget
&rSmGraphic
,
896 SfxBindings
&rBindings
) :
897 SfxControllerItem(nId_
, rBindings
),
902 void SmGraphicController::StateChangedAtToolBoxControl(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
904 rGraphic
.SetTotalSize();
905 rGraphic
.Invalidate();
906 SfxControllerItem::StateChangedAtToolBoxControl (nSID
, eState
, pState
);
909 /**************************************************************************/
910 SmEditController::SmEditController(SmEditWindow
&rSmEdit
,
912 SfxBindings
&rBindings
) :
913 SfxControllerItem(nId_
, rBindings
),
918 void SmEditController::StateChangedAtToolBoxControl(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
920 const SfxStringItem
*pItem
= dynamic_cast<const SfxStringItem
*>( pState
);
922 if ((pItem
!= nullptr) && (rEdit
.GetText() != pItem
->GetValue()))
923 rEdit
.SetText(pItem
->GetValue());
924 SfxControllerItem::StateChangedAtToolBoxControl (nSID
, eState
, pState
);
927 /**************************************************************************/
928 SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings
*pBindings_
, SfxChildWindow
*pChildWindow
,
929 vcl::Window
*pParent
)
930 : SfxDockingWindow(pBindings_
, pChildWindow
, pParent
, "EditWindow", "modules/smath/ui/editwindow.ui")
931 , m_xEdit(new SmEditWindow(*this, *m_xBuilder
))
932 , aController(*m_xEdit
, SID_TEXT
, *pBindings_
)
934 , aInitialFocusTimer("SmCmdBoxWindow aInitialFocusTimer")
938 SetHelpId( HID_SMA_COMMAND_WIN
);
939 SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont
)));
940 SetText(SmResId(STR_CMDBOXWINDOW
));
944 // Don't try to grab focus in LOK inline edit mode
945 if (!comphelper::LibreOfficeKit::isActive())
947 aInitialFocusTimer
.SetInvokeHandler(LINK(this, SmCmdBoxWindow
, InitialFocusTimerHdl
));
948 aInitialFocusTimer
.SetTimeout(100);
952 Point
SmCmdBoxWindow::WidgetToWindowPos(const weld::Widget
& rWidget
, const Point
& rPos
)
955 int x(0), y(0), width(0), height(0);
956 rWidget
.get_extents_relative_to(*m_xContainer
, x
, y
, width
, height
);
958 aRet
.Move(m_xBox
->GetPosPixel().X(), m_xBox
->GetPosPixel().Y());
962 void SmCmdBoxWindow::ShowContextMenu(const Point
& rPos
)
965 SmViewShell
*pViewSh
= GetView();
967 pViewSh
->GetViewFrame().GetDispatcher()->ExecutePopup("edit", this, &rPos
);
970 void SmCmdBoxWindow::Command(const CommandEvent
& rCEvt
)
972 if (rCEvt
.GetCommand() == CommandEventId::ContextMenu
)
974 ShowContextMenu(rCEvt
.GetMousePosPixel());
978 SfxDockingWindow::Command(rCEvt
);
981 SmCmdBoxWindow::~SmCmdBoxWindow ()
986 void SmCmdBoxWindow::dispose()
988 aInitialFocusTimer
.Stop();
990 aController
.dispose();
992 SfxDockingWindow::dispose();
995 SmViewShell
* SmCmdBoxWindow::GetView()
997 SfxDispatcher
*pDispatcher
= GetBindings().GetDispatcher();
998 SfxViewShell
*pView
= pDispatcher
? pDispatcher
->GetFrame()->GetViewShell() : nullptr;
999 return dynamic_cast<SmViewShell
*>( pView
);
1002 Size
SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign
)
1006 case SfxChildAlignment::LEFT
:
1007 case SfxChildAlignment::RIGHT
:
1012 return SfxDockingWindow::CalcDockingSize(eAlign
);
1015 SfxChildAlignment
SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual
,
1016 SfxChildAlignment eWish
)
1020 case SfxChildAlignment::TOP
:
1021 case SfxChildAlignment::BOTTOM
:
1022 case SfxChildAlignment::NOALIGNMENT
:
1031 void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange
)
1033 if (StateChangedType::InitShow
== nStateChange
)
1035 Resize(); // avoid SmEditWindow not being painted correctly
1037 // set initial position of window in floating mode
1038 if (IsFloatingMode())
1039 AdjustPosition(); //! don't change pos in docking-mode !
1041 aInitialFocusTimer
.Start();
1044 SfxDockingWindow::StateChanged( nStateChange
);
1047 IMPL_LINK_NOARG( SmCmdBoxWindow
, InitialFocusTimerHdl
, Timer
*, void )
1049 // We want to have the focus in the edit window once Math has been opened
1050 // to allow for immediate typing.
1051 // Problem: There is no proper way to do this
1052 // Thus: this timer based solution has been implemented (see GrabFocus below)
1054 // Follow-up problem (#i114910): grabbing the focus may bust the help system since
1055 // it relies on getting the current frame which conflicts with grabbing the focus.
1056 // Thus aside from the 'GrabFocus' call everything else is to get the
1057 // help reliably working despite using 'GrabFocus'.
1061 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( comphelper::getProcessComponentContext() );
1063 m_xEdit
->GrabFocus();
1065 SmViewShell
* pView
= GetView();
1067 bool bInPlace
= pView
->GetViewFrame().GetFrame().IsInPlace();
1068 uno::Reference
< frame::XFrame
> xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
1071 uno::Reference
<container::XChild
> xModel(pView
->GetDoc()->GetModel(),
1072 uno::UNO_QUERY_THROW
);
1073 uno::Reference
< frame::XModel
> xParent( xModel
->getParent(), uno::UNO_QUERY_THROW
);
1074 uno::Reference
< frame::XController
> xParentCtrler( xParent
->getCurrentController() );
1075 uno::Reference
< frame::XFramesSupplier
> xParentFrame( xParentCtrler
->getFrame(), uno::UNO_QUERY_THROW
);
1076 xParentFrame
->setActiveFrame( xFrame
);
1080 xDesktop
->setActiveFrame( xFrame
);
1083 catch (uno::Exception
&)
1085 SAL_WARN( "starmath", "failed to properly set initial focus to edit window" );
1089 void SmCmdBoxWindow::AdjustPosition()
1091 const tools::Rectangle
aRect( Point(), GetParent()->GetOutputSizePixel() );
1092 Point
aTopLeft( Point( aRect
.Left(),
1093 aRect
.Bottom() - GetSizePixel().Height() ) );
1094 Point
aPos( GetParent()->OutputToScreenPixel( aTopLeft
) );
1099 SetPosPixel( aPos
);
1102 void SmCmdBoxWindow::ToggleFloatingMode()
1104 SfxDockingWindow::ToggleFloatingMode();
1106 if (GetFloatingWindow())
1107 GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
1110 void SmCmdBoxWindow::GetFocus()
1113 m_xEdit
->GrabFocus();
1116 SFX_IMPL_DOCKINGWINDOW_WITHID(SmCmdBoxWrapper
, SID_CMDBOXWINDOW
);
1118 SmCmdBoxWrapper::SmCmdBoxWrapper(vcl::Window
*pParentWindow
, sal_uInt16 nId
,
1119 SfxBindings
*pBindings
,
1120 SfxChildWinInfo
*pInfo
) :
1121 SfxChildWindow(pParentWindow
, nId
)
1123 VclPtrInstance
<SmCmdBoxWindow
> pDialog(pBindings
, this, pParentWindow
);
1125 // make window docked to the bottom initially (after first start)
1126 SetAlignment(SfxChildAlignment::BOTTOM
);
1127 pDialog
->setDeferredProperties();
1128 pDialog
->set_border_width(CMD_BOX_PADDING
);
1129 pDialog
->set_margin_top(CMD_BOX_PADDING_TOP
);
1130 pDialog
->Initialize(pInfo
);
1133 SFX_IMPL_SUPERCLASS_INTERFACE(SmViewShell
, SfxViewShell
)
1135 void SmViewShell::InitInterface_Impl()
1137 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS
,
1138 SfxVisibilityFlags::Standard
| SfxVisibilityFlags::FullScreen
| SfxVisibilityFlags::Server
,
1139 ToolbarId::Math_Toolbox
);
1140 //Dummy-Objectbar, to avoid quiver while activating
1142 GetStaticInterface()->RegisterChildWindow(SmCmdBoxWrapper::GetChildWindowId());
1143 GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
1145 GetStaticInterface()->RegisterChildWindow(::sfx2::sidebar::SidebarChildWindow::GetChildWindowId());
1148 SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell
, "Default")
1150 SFX_VIEW_REGISTRATION(SmDocShell
);
1153 void SmViewShell::InnerResizePixel(const Point
&rOfs
, const Size
&rSize
, bool)
1155 Size aObjSize
= GetObjectShell()->GetVisArea().GetSize();
1156 if ( !aObjSize
.IsEmpty() )
1158 Size aProvidedSize
= GetWindow()->PixelToLogic(rSize
, MapMode(SmMapUnit()));
1159 Fraction
aZoomX(aProvidedSize
.Width(), aObjSize
.Width());
1160 Fraction
aZoomY(aProvidedSize
.Height(), aObjSize
.Height());
1161 MapMode
aMap(mxGraphicWindow
->GetGraphicMapMode());
1162 aMap
.SetScaleX(aZoomX
);
1163 aMap
.SetScaleY(aZoomY
);
1164 mxGraphicWindow
->SetGraphicMapMode(aMap
);
1167 SetBorderPixel( SvBorder() );
1168 mxGraphicWindow
->SetPosSizePixel(rOfs
, rSize
);
1169 GetGraphicWidget().SetTotalSize();
1172 void SmViewShell::OuterResizePixel(const Point
&rOfs
, const Size
&rSize
)
1174 mxGraphicWindow
->SetPosSizePixel(rOfs
, rSize
);
1175 if (GetDoc()->IsPreview())
1176 mxGraphicWindow
->ZoomToFitInWindow();
1179 void SmViewShell::QueryObjAreaPixel( tools::Rectangle
& rRect
) const
1181 rRect
.SetSize(mxGraphicWindow
->GetSizePixel());
1184 void SmViewShell::SetZoomFactor( const Fraction
&rX
, const Fraction
&rY
)
1186 const Fraction
&rFrac
= std::min(rX
, rY
);
1187 mxGraphicWindow
->SetZoom(sal::static_int_cast
<sal_uInt16
>(tools::Long(rFrac
* Fraction( 100, 1 ))));
1189 //To avoid rounding errors base class regulates crooked values too
1191 SfxViewShell::SetZoomFactor( rX
, rY
);
1194 Size
SmViewShell::GetTextLineSize(OutputDevice
const & rDevice
, const OUString
& rLine
)
1196 Size
aSize(rDevice
.GetTextWidth(rLine
), rDevice
.GetTextHeight());
1197 const tools::Long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_digit_width() * 8;
1201 aSize
.setWidth( 0 );
1206 aSize
.setWidth( ((aSize
.Width() / nTabPos
) + 1) * nTabPos
);
1208 const OUString aText
= rLine
.getToken(0, '\t', nPos
);
1209 aSize
.AdjustWidth(rDevice
.GetTextWidth(aText
) );
1217 Size
SmViewShell::GetTextSize(OutputDevice
const & rDevice
, std::u16string_view rText
, tools::Long MaxWidth
)
1227 OUString
aLine( o3tl::getToken(rText
, 0, '\n', nPos
) );
1228 aLine
= aLine
.replaceAll("\r", "");
1230 aSize
= GetTextLineSize(rDevice
, aLine
);
1232 if (aSize
.Width() > MaxWidth
)
1237 sal_Int32 m
= aLine
.getLength();
1240 for (sal_Int32 n
= 0; n
< nLen
; n
++)
1242 sal_Unicode cLineChar
= aLine
[n
];
1243 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
1245 aText
= aLine
.copy(0, n
);
1246 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
1253 aText
= aLine
.copy(0, m
);
1254 aLine
= aLine
.replaceAt(0, m
, u
"");
1255 aSize
= GetTextLineSize(rDevice
, aText
);
1256 aTextSize
.AdjustHeight(aSize
.Height() );
1257 aTextSize
.setWidth( std::clamp(aSize
.Width(), aTextSize
.Width(), MaxWidth
) );
1259 aLine
= comphelper::string::stripStart(aLine
, ' ');
1260 aLine
= comphelper::string::stripStart(aLine
, '\t');
1261 aLine
= comphelper::string::stripStart(aLine
, ' ');
1263 while (!aLine
.isEmpty());
1267 aTextSize
.AdjustHeight(aSize
.Height() );
1268 aTextSize
.setWidth( std::max(aTextSize
.Width(), aSize
.Width()) );
1276 void SmViewShell::DrawTextLine(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rLine
)
1278 Point
aPoint(rPosition
);
1279 const tools::Long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_digit_width() * 8;
1287 aPoint
.setX( ((aPoint
.X() / nTabPos
) + 1) * nTabPos
);
1289 OUString aText
= rLine
.getToken(0, '\t', nPos
);
1290 rDevice
.DrawText(aPoint
, aText
);
1291 aPoint
.AdjustX(rDevice
.GetTextWidth(aText
) );
1293 while ( nPos
>= 0 );
1296 rDevice
.DrawText(aPoint
, rLine
);
1299 void SmViewShell::DrawText(OutputDevice
& rDevice
, const Point
& rPosition
, std::u16string_view rText
, sal_uInt16 MaxWidth
)
1304 Point
aPoint(rPosition
);
1310 OUString
aLine( o3tl::getToken(rText
, 0, '\n', nPos
) );
1311 aLine
= aLine
.replaceAll("\r", "");
1312 aSize
= GetTextLineSize(rDevice
, aLine
);
1313 if (aSize
.Width() > MaxWidth
)
1318 sal_Int32 m
= aLine
.getLength();
1321 for (sal_Int32 n
= 0; n
< nLen
; n
++)
1323 sal_Unicode cLineChar
= aLine
[n
];
1324 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
1326 aText
= aLine
.copy(0, n
);
1327 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
1333 aText
= aLine
.copy(0, m
);
1334 aLine
= aLine
.replaceAt(0, m
, u
"");
1336 DrawTextLine(rDevice
, aPoint
, aText
);
1337 aPoint
.AdjustY(aSize
.Height() );
1339 aLine
= comphelper::string::stripStart(aLine
, ' ');
1340 aLine
= comphelper::string::stripStart(aLine
, '\t');
1341 aLine
= comphelper::string::stripStart(aLine
, ' ');
1343 while (GetTextLineSize(rDevice
, aLine
).Width() > MaxWidth
);
1345 // print the remaining text
1346 if (!aLine
.isEmpty())
1348 DrawTextLine(rDevice
, aPoint
, aLine
);
1349 aPoint
.AdjustY(aSize
.Height() );
1354 DrawTextLine(rDevice
, aPoint
, aLine
);
1355 aPoint
.AdjustY(aSize
.Height() );
1358 while ( nPos
>= 0 );
1361 void SmViewShell::Impl_Print(OutputDevice
&rOutDev
, const SmPrintUIOptions
&rPrintUIOptions
, tools::Rectangle aOutRect
)
1363 const bool bIsPrintTitle
= rPrintUIOptions
.getBoolValue( PRTUIOPT_TITLE_ROW
, true );
1364 const bool bIsPrintFrame
= rPrintUIOptions
.getBoolValue( PRTUIOPT_BORDER
, true );
1365 const bool bIsPrintFormulaText
= rPrintUIOptions
.getBoolValue( PRTUIOPT_FORMULA_TEXT
, true );
1366 SmPrintSize
ePrintSize( static_cast< SmPrintSize
>( rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_FORMAT
, PRINT_SIZE_NORMAL
) ));
1367 const sal_uInt16 nZoomFactor
= static_cast< sal_uInt16
>(rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_SCALE
, 100 ));
1370 rOutDev
.SetLineColor( COL_BLACK
);
1372 // output text on top
1375 Size
aSize600 (0, 600);
1376 Size
aSize650 (0, 650);
1377 vcl::Font
aFont(FAMILY_DONTKNOW
, aSize600
);
1379 aFont
.SetAlignment(ALIGN_TOP
);
1380 aFont
.SetWeight(WEIGHT_BOLD
);
1381 aFont
.SetFontSize(aSize650
);
1382 aFont
.SetColor( COL_BLACK
);
1383 rOutDev
.SetFont(aFont
);
1385 Size
aTitleSize (GetTextSize(rOutDev
, GetDoc()->GetTitle(), aOutRect
.GetWidth() - 200));
1387 aFont
.SetWeight(WEIGHT_NORMAL
);
1388 aFont
.SetFontSize(aSize600
);
1389 rOutDev
.SetFont(aFont
);
1391 Size
aDescSize (GetTextSize(rOutDev
, GetDoc()->GetComment(), aOutRect
.GetWidth() - 200));
1394 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.TopLeft(),
1395 Size(aOutRect
.GetWidth(), 100 + aTitleSize
.Height() + 200 + aDescSize
.Height() + 100)));
1396 aOutRect
.AdjustTop(200 );
1399 aFont
.SetWeight(WEIGHT_BOLD
);
1400 aFont
.SetFontSize(aSize650
);
1401 rOutDev
.SetFont(aFont
);
1402 Point
aPoint(aOutRect
.Left() + (aOutRect
.GetWidth() - aTitleSize
.Width()) / 2,
1404 DrawText(rOutDev
, aPoint
, GetDoc()->GetTitle(),
1405 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1406 aOutRect
.AdjustTop(aTitleSize
.Height() + 200 );
1408 // output description
1409 aFont
.SetWeight(WEIGHT_NORMAL
);
1410 aFont
.SetFontSize(aSize600
);
1411 rOutDev
.SetFont(aFont
);
1412 aPoint
.setX( aOutRect
.Left() + (aOutRect
.GetWidth() - aDescSize
.Width()) / 2 );
1413 aPoint
.setY( aOutRect
.Top() );
1414 DrawText(rOutDev
, aPoint
, GetDoc()->GetComment(),
1415 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1416 aOutRect
.AdjustTop(aDescSize
.Height() + 300 );
1419 // output text on bottom
1420 if (bIsPrintFormulaText
)
1422 vcl::Font
aFont(FAMILY_DONTKNOW
, Size(0, 600));
1423 aFont
.SetAlignment(ALIGN_TOP
);
1424 aFont
.SetColor( COL_BLACK
);
1427 rOutDev
.SetFont(aFont
);
1429 Size
aSize (GetTextSize(rOutDev
, GetDoc()->GetText(), aOutRect
.GetWidth() - 200));
1431 aOutRect
.AdjustBottom( -(aSize
.Height() + 600) );
1434 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.BottomLeft(),
1435 Size(aOutRect
.GetWidth(), 200 + aSize
.Height() + 200)));
1437 Point
aPoint (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1438 aOutRect
.Bottom() + 300);
1439 DrawText(rOutDev
, aPoint
, GetDoc()->GetText(),
1440 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1441 aOutRect
.AdjustBottom( -200 );
1445 rOutDev
.DrawRect(aOutRect
);
1447 aOutRect
.AdjustTop(100 );
1448 aOutRect
.AdjustLeft(100 );
1449 aOutRect
.AdjustBottom( -100 );
1450 aOutRect
.AdjustRight( -100 );
1452 Size
aSize (GetDoc()->GetSize());
1454 MapMode OutputMapMode
;
1455 // PDF export should always use PRINT_SIZE_NORMAL ...
1456 if (!rPrintUIOptions
.getBoolValue( "IsPrinter" ) )
1457 ePrintSize
= PRINT_SIZE_NORMAL
;
1460 case PRINT_SIZE_NORMAL
:
1461 OutputMapMode
= MapMode(SmMapUnit());
1464 case PRINT_SIZE_SCALED
:
1465 if (!aSize
.IsEmpty())
1467 Size
OutputSize(rOutDev
.LogicToPixel(aOutRect
.GetSize(), MapMode(SmMapUnit())));
1468 Size
GraphicSize(rOutDev
.LogicToPixel(aSize
, MapMode(SmMapUnit())));
1469 sal_uInt16 nZ
= std::min(o3tl::convert(OutputSize
.Width(), 100, GraphicSize
.Width()),
1470 o3tl::convert(OutputSize
.Height(), 100, GraphicSize
.Height()));
1472 Fraction
aFraction(std::clamp(nZ
, MINZOOM
, MAXZOOM
), 100);
1474 OutputMapMode
= MapMode(SmMapUnit(), Point(), aFraction
, aFraction
);
1477 OutputMapMode
= MapMode(SmMapUnit());
1480 case PRINT_SIZE_ZOOMED
:
1482 Fraction
aFraction( nZoomFactor
, 100 );
1484 OutputMapMode
= MapMode(SmMapUnit(), Point(), aFraction
, aFraction
);
1489 aSize
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aSize
, OutputMapMode
),
1490 MapMode(SmMapUnit()));
1492 Point
aPos (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1493 aOutRect
.Top() + (aOutRect
.GetHeight() - aSize
.Height()) / 2);
1495 aPos
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aPos
, MapMode(SmMapUnit())),
1497 aOutRect
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aOutRect
, MapMode(SmMapUnit())),
1500 rOutDev
.SetMapMode(OutputMapMode
);
1501 rOutDev
.SetClipRegion(vcl::Region(aOutRect
));
1502 GetDoc()->DrawFormula(rOutDev
, aPos
);
1503 rOutDev
.SetClipRegion();
1508 SfxPrinter
* SmViewShell::GetPrinter(bool bCreate
)
1510 SmDocShell
* pDoc
= GetDoc();
1511 if (pDoc
->HasPrinter() || bCreate
)
1512 return pDoc
->GetPrinter();
1516 sal_uInt16
SmViewShell::SetPrinter(SfxPrinter
*pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
1518 SfxPrinter
*pOld
= GetDoc()->GetPrinter();
1519 if ( pOld
&& pOld
->IsPrinting() )
1520 return SFX_PRINTERROR_BUSY
;
1522 if ((nDiffFlags
& SfxPrinterChangeFlags::PRINTER
) == SfxPrinterChangeFlags::PRINTER
)
1523 GetDoc()->SetPrinter( pNewPrinter
);
1525 if ((nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
) == SfxPrinterChangeFlags::OPTIONS
)
1527 SmModule
*pp
= SM_MOD();
1528 pp
->GetConfig()->ItemSetToConfig(pNewPrinter
->GetOptions());
1533 bool SmViewShell::HasPrintOptionsPage() const
1538 std::unique_ptr
<SfxTabPage
> SmViewShell::CreatePrintOptionsPage(weld::Container
* pPage
, weld::DialogController
* pController
,
1539 const SfxItemSet
&rOptions
)
1541 return SmPrintOptionsTabPage::Create(pPage
, pController
, rOptions
);
1544 SmEditWindow
*SmViewShell::GetEditWindow()
1546 SmCmdBoxWrapper
* pWrapper
= static_cast<SmCmdBoxWrapper
*>(
1547 GetViewFrame().GetChildWindow(SmCmdBoxWrapper::GetChildWindowId()));
1549 if (pWrapper
!= nullptr)
1551 SmEditWindow
& rEditWin
= pWrapper
->GetEditWindow();
1558 void SmViewShell::SetStatusText(const OUString
& rText
)
1560 maStatusText
= rText
;
1561 GetViewFrame().GetBindings().Invalidate(SID_TEXTSTATUS
);
1564 void SmViewShell::ShowError(const SmErrorDesc
* pErrorDesc
)
1567 if (pErrorDesc
|| nullptr != (pErrorDesc
= GetDoc()->GetParser()->GetError()) )
1569 SetStatusText( pErrorDesc
->m_aText
);
1570 if (SmEditWindow
* pEdit
= GetEditWindow())
1571 pEdit
->MarkError( Point( pErrorDesc
->m_pNode
->GetColumn(),
1572 pErrorDesc
->m_pNode
->GetRow()));
1576 void SmViewShell::NextError()
1579 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser()->NextError();
1582 ShowError( pErrorDesc
);
1585 void SmViewShell::PrevError()
1588 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser()->PrevError();
1591 ShowError( pErrorDesc
);
1594 void SmViewShell::Insert( SfxMedium
& rMedium
)
1596 SmDocShell
*pDoc
= GetDoc();
1599 uno::Reference
<embed::XStorage
> xStorage
= rMedium
.GetStorage();
1600 if (xStorage
.is() && xStorage
->getElementNames().hasElements())
1602 if (xStorage
->hasByName("content.xml"))
1604 // is this a fabulous math package ?
1605 rtl::Reference
<SmModel
> xModel(dynamic_cast<SmModel
*>(pDoc
->GetModel().get()));
1606 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1607 bRet
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1614 OUString aText
= pDoc
->GetText();
1615 if (SmEditWindow
*pEditWin
= GetEditWindow())
1616 pEditWin
->InsertText( aText
);
1619 SAL_WARN( "starmath", "EditWindow missing" );
1623 pDoc
->SetModified();
1625 SfxBindings
&rBnd
= GetViewFrame().GetBindings();
1626 rBnd
.Invalidate(SID_GRAPHIC_SM
);
1627 rBnd
.Invalidate(SID_TEXT
);
1630 void SmViewShell::InsertFrom(SfxMedium
&rMedium
)
1632 bool bSuccess
= false;
1633 SmDocShell
* pDoc
= GetDoc();
1634 SvStream
* pStream
= rMedium
.GetInStream();
1638 const OUString
& rFltName
= rMedium
.GetFilter()->GetFilterName();
1639 if ( rFltName
== MATHML_XML
)
1641 rtl::Reference
<SmModel
> xModel(dynamic_cast<SmModel
*>(pDoc
->GetModel().get()));
1642 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1643 bSuccess
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1650 OUString aText
= pDoc
->GetText();
1651 if (SmEditWindow
*pEditWin
= GetEditWindow())
1652 pEditWin
->InsertText(aText
);
1654 SAL_WARN( "starmath", "EditWindow missing" );
1657 pDoc
->SetModified();
1659 SfxBindings
& rBnd
= GetViewFrame().GetBindings();
1660 rBnd
.Invalidate(SID_GRAPHIC_SM
);
1661 rBnd
.Invalidate(SID_TEXT
);
1664 void SmViewShell::Execute(SfxRequest
& rReq
)
1666 SmEditWindow
*pWin
= GetEditWindow();
1668 switch (rReq
.GetSlot())
1670 case SID_FORMULACURSOR
:
1672 SmModule
*pp
= SM_MOD();
1674 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1675 const SfxPoolItem
*pItem
;
1679 SfxItemState::SET
== pArgs
->GetItemState( SID_FORMULACURSOR
, false, &pItem
))
1680 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1682 bVal
= !pp
->GetConfig()->IsShowFormulaCursor();
1684 pp
->GetConfig()->SetShowFormulaCursor(bVal
);
1685 if (!IsInlineEditEnabled())
1686 GetGraphicWidget().ShowCursor(bVal
);
1692 GetDoc()->SetText( pWin
->GetText() );
1693 SetStatusText(OUString());
1694 ShowError( nullptr );
1695 GetDoc()->Repaint();
1699 case SID_ZOOM_OPTIMAL
:
1700 mxGraphicWindow
->ZoomToFitInWindow();
1704 mxGraphicWindow
->SetZoom(mxGraphicWindow
->GetZoom() + 25);
1708 SAL_WARN_IF( mxGraphicWindow
->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1709 mxGraphicWindow
->SetZoom(mxGraphicWindow
->GetZoom() - 25);
1712 case SID_COPYOBJECT
:
1714 //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
1715 Reference
< datatransfer::XTransferable
> xTrans( GetDoc()->GetModel(), uno::UNO_QUERY
);
1718 auto pTrans
= dynamic_cast<TransferableHelper
*>(xTrans
.get());
1722 pTrans
->CopyToClipboard(pWin
->GetClipboard());
1728 case SID_PASTEOBJECT
:
1730 uno::Reference
< io::XInputStream
> xStrm
;
1733 TransferableDataHelper
aData(TransferableDataHelper::CreateFromClipboard(pWin
->GetClipboard()));
1734 SotClipboardFormatId nId
;
1735 if( aData
.GetTransferable().is() &&
1736 ( aData
.HasFormat( nId
= SotClipboardFormatId::EMBEDDED_OBJ
) ||
1737 (aData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
1738 aData
.HasFormat( nId
= SotClipboardFormatId::EMBED_SOURCE
))))
1739 xStrm
= aData
.GetInputStream(nId
, OUString());
1746 uno::Reference
< embed::XStorage
> xStorage
=
1747 ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
, ::comphelper::getProcessComponentContext() );
1748 SfxMedium
aMedium( xStorage
, OUString() );
1750 GetDoc()->UpdateText();
1752 catch (uno::Exception
&)
1754 SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1769 if (pWin
->IsAllSelected())
1771 GetViewFrame().GetDispatcher()->ExecuteList(
1772 SID_COPYOBJECT
, SfxCallMode::RECORD
,
1773 { new SfxVoidItem(SID_COPYOBJECT
) });
1782 bool bCallExec
= nullptr == pWin
;
1787 TransferableDataHelper
aDataHelper(
1788 TransferableDataHelper::CreateFromClipboard(
1789 pWin
->GetClipboard()));
1791 if( aDataHelper
.GetTransferable().is() &&
1792 aDataHelper
.HasFormat( SotClipboardFormatId::STRING
))
1800 GetViewFrame().GetDispatcher()->ExecuteList(
1801 SID_PASTEOBJECT
, SfxCallMode::RECORD
,
1802 { new SfxVoidItem(SID_PASTEOBJECT
) });
1817 case SID_INSERTCOMMANDTEXT
:
1819 const SfxStringItem
& rItem
= rReq
.GetArgs()->Get(SID_INSERTCOMMANDTEXT
);
1821 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1823 pWin
->InsertText(rItem
.GetValue());
1825 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1827 GetDoc()->GetCursor().InsertCommandText(rItem
.GetValue());
1828 GetGraphicWidget().GrabFocus();
1834 case SID_INSERTSPECIAL
:
1836 const SfxStringItem
& rItem
= rReq
.GetArgs()->Get(SID_INSERTSPECIAL
);
1838 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1839 pWin
->InsertText(rItem
.GetValue());
1840 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1841 GetDoc()->GetCursor().InsertSpecial(rItem
.GetValue());
1845 case SID_IMPORT_FORMULA
:
1847 mpRequest
.reset(new SfxRequest( rReq
));
1848 mpDocInserter
.reset(new ::sfx2::DocumentInserter(pWin
? pWin
->GetFrameWeld() : nullptr,
1849 GetDoc()->GetFactory().GetFactoryName()));
1850 mpDocInserter
->StartExecuteModal( LINK( this, SmViewShell
, DialogClosedHdl
) );
1854 case SID_IMPORT_MATHML_CLIPBOARD
:
1858 TransferableDataHelper
aDataHelper(TransferableDataHelper::CreateFromClipboard(pWin
->GetClipboard()));
1859 uno::Reference
< io::XInputStream
> xStrm
;
1860 if ( aDataHelper
.GetTransferable().is() )
1862 SotClipboardFormatId nId
= SotClipboardFormatId::MATHML
;
1863 if (aDataHelper
.HasFormat(nId
))
1865 xStrm
= aDataHelper
.GetInputStream(nId
, "");
1868 SfxMedium aClipboardMedium
;
1869 aClipboardMedium
.GetItemSet(); //generate initial itemset, not sure if necessary
1870 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1871 SfxFilter::GetFilterByName(MATHML_XML
);
1872 aClipboardMedium
.SetFilter(pMathFilter
);
1873 aClipboardMedium
.setStreamToLoadFrom(xStrm
, true /*bIsReadOnly*/);
1874 InsertFrom(aClipboardMedium
);
1875 GetDoc()->UpdateText();
1880 nId
= SotClipboardFormatId::STRING
;
1881 if (aDataHelper
.HasFormat(nId
))
1883 // In case of FORMAT_STRING no stream exists, need to generate one
1885 if (aDataHelper
.GetString( nId
, aString
))
1887 // tdf#117091 force xml declaration to exist
1888 if (!aString
.startsWith("<?xml"))
1889 aString
= "<?xml version=\"1.0\"?>\n" + aString
;
1891 SfxMedium aClipboardMedium
;
1892 aClipboardMedium
.GetItemSet(); //generates initial itemset, not sure if necessary
1893 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1894 SfxFilter::GetFilterByName(MATHML_XML
);
1895 aClipboardMedium
.SetFilter(pMathFilter
);
1897 SvMemoryStream
aStrm( const_cast<sal_Unicode
*>(aString
.getStr()), aString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
);
1898 uno::Reference
<io::XInputStream
> xStrm2( new ::utl::OInputStreamWrapper(aStrm
) );
1899 aClipboardMedium
.setStreamToLoadFrom(xStrm2
, true /*bIsReadOnly*/);
1900 InsertFrom(aClipboardMedium
);
1901 GetDoc()->UpdateText();
1925 pWin
->SelNextMark();
1933 pWin
->SelPrevMark();
1938 case SID_TEXTSTATUS
:
1940 if (rReq
.GetArgs() != nullptr)
1942 const SfxStringItem
& rItem
= rReq
.GetArgs()->Get(SID_TEXTSTATUS
);
1944 SetStatusText(rItem
.GetValue());
1950 case SID_GETEDITTEXT
:
1951 if (pWin
&& !pWin
->GetText().isEmpty())
1952 GetDoc()->SetText( pWin
->GetText() );
1957 if ( !GetViewFrame().GetFrame().IsInPlace() )
1959 const SfxItemSet
*pSet
= rReq
.GetArgs();
1962 ZoomByItemSet(pSet
);
1966 SfxItemSetFixed
<SID_ATTR_ZOOM
, SID_ATTR_ZOOM
> aSet( SmDocShell::GetPool() );
1967 aSet
.Put( SvxZoomItem( SvxZoomType::PERCENT
, mxGraphicWindow
->GetZoom()));
1968 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1969 ScopedVclPtr
<AbstractSvxZoomDialog
> xDlg(pFact
->CreateSvxZoomDialog(GetViewFrame().GetWindow().GetFrameWeld(), aSet
));
1970 xDlg
->SetLimits( MINZOOM
, MAXZOOM
);
1971 if (xDlg
->Execute() != RET_CANCEL
)
1972 ZoomByItemSet(xDlg
->GetOutputItemSet());
1978 case SID_ATTR_ZOOMSLIDER
:
1980 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1981 const SfxPoolItem
* pItem
;
1983 if ( pArgs
&& SfxItemState::SET
== pArgs
->GetItemState(SID_ATTR_ZOOMSLIDER
, true, &pItem
) )
1985 const sal_uInt16 nCurrentZoom
= static_cast<const SvxZoomSliderItem
*>(pItem
)->GetValue();
1986 mxGraphicWindow
->SetZoom(nCurrentZoom
);
1991 case SID_ELEMENTSDOCKINGWINDOW
:
1993 // First make sure that the sidebar is visible
1994 GetViewFrame().ShowChildWindow(SID_SIDEBAR
);
1996 sfx2::sidebar::Sidebar::TogglePanel(u
"MathElementsPanel",
1997 GetViewFrame().GetFrame().GetFrameInterface());
1998 GetViewFrame().GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW
);
2004 case SID_UNICODE_NOTATION_TOGGLE
:
2006 EditEngine
* pEditEngine
= nullptr;
2008 pEditEngine
= pWin
->GetEditEngine();
2010 EditView
* pEditView
= nullptr;
2012 pEditView
= pEditEngine
->GetView();
2016 const OUString sInput
= pEditView
->GetSurroundingText();
2017 ESelection
aSel( pWin
->GetSelection() );
2019 if ( aSel
.nStartPos
> aSel
.nEndPos
)
2020 aSel
.nEndPos
= aSel
.nStartPos
;
2022 //calculate a valid end-position by reading logical characters
2023 sal_Int32 nUtf16Pos
=0;
2024 while( (nUtf16Pos
< sInput
.getLength()) && (nUtf16Pos
< aSel
.nEndPos
) )
2026 sInput
.iterateCodePoints(&nUtf16Pos
);
2027 if( nUtf16Pos
> aSel
.nEndPos
)
2028 aSel
.nEndPos
= nUtf16Pos
;
2031 ToggleUnicodeCodepoint aToggle
;
2032 while( nUtf16Pos
&& aToggle
.AllowMoreInput( sInput
[nUtf16Pos
-1]) )
2034 const OUString sReplacement
= aToggle
.ReplacementString();
2035 if( !sReplacement
.isEmpty() )
2037 pEditView
->SetSelection( aSel
);
2038 pEditEngine
->UndoActionStart(EDITUNDO_REPLACEALL
);
2039 aSel
.nStartPos
= aSel
.nEndPos
- aToggle
.StringToReplace().getLength();
2040 pWin
->SetSelection( aSel
);
2041 pEditView
->InsertText( sReplacement
, true );
2042 pEditEngine
->UndoActionEnd();
2049 case SID_SYMBOLS_CATALOGUE
:
2052 // get device used to retrieve the FontList
2053 SmDocShell
*pDoc
= GetDoc();
2054 OutputDevice
*pDev
= pDoc
->GetPrinter();
2055 if (!pDev
|| pDev
->GetFontFaceCollectionCount() == 0)
2056 pDev
= &SM_MOD()->GetDefaultVirtualDev();
2057 SAL_WARN_IF( !pDev
, "starmath", "device for font list missing" );
2059 SmModule
*pp
= SM_MOD();
2060 SmSymbolDialog
aDialog(pWin
? pWin
->GetFrameWeld() : nullptr, pDev
, pp
->GetSymbolManager(), *this);
2069 void SmViewShell::GetState(SfxItemSet
&rSet
)
2071 SfxWhichIter
aIter(rSet
);
2073 SmEditWindow
*pEditWin
= GetEditWindow();
2074 for (sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
!= 0; nWh
= aIter
.NextWhich())
2081 if (! pEditWin
|| ! pEditWin
->IsSelected())
2082 rSet
.DisableItem(nWh
);
2088 TransferableDataHelper
aDataHelper(
2089 TransferableDataHelper::CreateFromClipboard(
2090 pEditWin
->GetClipboard()) );
2092 mbPasteState
= aDataHelper
.GetTransferable().is() &&
2093 ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) ||
2094 aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) ||
2095 (aDataHelper
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
)
2096 && aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
)));
2099 rSet
.DisableItem( nWh
);
2103 rSet
.Put(SvxZoomItem( SvxZoomType::PERCENT
, mxGraphicWindow
->GetZoom()));
2107 case SID_ZOOM_OPTIMAL
:
2108 if ( GetViewFrame().GetFrame().IsInPlace() )
2109 rSet
.DisableItem( nWh
);
2112 case SID_ATTR_ZOOMSLIDER
:
2114 const sal_uInt16 nCurrentZoom
= mxGraphicWindow
->GetZoom();
2115 SvxZoomSliderItem
aZoomSliderItem( nCurrentZoom
, MINZOOM
, MAXZOOM
);
2116 aZoomSliderItem
.AddSnappingPoint( 100 );
2117 rSet
.Put( aZoomSliderItem
);
2127 if (! pEditWin
|| pEditWin
->IsEmpty())
2128 rSet
.DisableItem(nWh
);
2131 case SID_TEXTSTATUS
:
2133 rSet
.Put(SfxStringItem(nWh
, maStatusText
));
2137 case SID_FORMULACURSOR
:
2139 SmModule
*pp
= SM_MOD();
2140 rSet
.Put(SfxBoolItem(nWh
, pp
->GetConfig()->IsShowFormulaCursor()));
2143 case SID_ELEMENTSDOCKINGWINDOW
:
2145 const bool bState
= sfx2::sidebar::Sidebar::IsPanelVisible(
2146 u
"MathElementsPanel", GetViewFrame().GetFrame().GetFrameInterface());
2147 rSet
.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW
, bState
));
2156 class SmController
: public SfxBaseController
2159 SmController(SfxViewShell
& rViewShell
)
2160 : SfxBaseController(&rViewShell
)
2161 , mpSelectionChangeHandler(new svx::sidebar::SelectionChangeHandler(
2162 GetContextName
, this, vcl::EnumContext::Context::Math
))
2164 rViewShell
.SetContextName(GetContextName());
2166 // No need to call mpSelectionChangeHandler->Disconnect() unless SmController implements XSelectionSupplier
2167 // ~SmController() { mpSelectionChangeHandler->Disconnect(); }
2169 // css::frame::XController
2170 void SAL_CALL
attachFrame(const css::uno::Reference
<css::frame::XFrame
>& xFrame
) override
2172 SfxBaseController::attachFrame(xFrame
);
2174 if (comphelper::LibreOfficeKit::isActive())
2175 CopyLokViewCallbackFromFrameCreator();
2177 // No need to call mpSelectionChangeHandler->Connect() unless SmController implements XSelectionSupplier
2178 mpSelectionChangeHandler
->selectionChanged({}); // Installs the correct context
2181 virtual void SAL_CALL
dispose() override
2183 if (comphelper::LibreOfficeKit::isActive())
2184 if (auto pViewShell
= GetViewShell_Impl())
2185 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE
,
2186 OString::boolean(false));
2188 SfxBaseController::dispose();
2192 static OUString
GetContextName() { return "Math"; } // Static constant for now
2194 rtl::Reference
<svx::sidebar::SelectionChangeHandler
> mpSelectionChangeHandler
;
2198 SmViewShell::SmViewShell(SfxViewFrame
& rFrame_
, SfxViewShell
*)
2199 : SfxViewShell(rFrame_
, SfxViewShellFlags::HAS_PRINTOPTIONS
)
2200 , mxGraphicWindow(VclPtr
<SmGraphicWindow
>::Create(*this))
2201 , maGraphicController(mxGraphicWindow
->GetGraphicWidget(), SID_GRAPHIC_SM
, rFrame_
.GetBindings())
2202 , mbPasteState(false)
2203 , mbInsertIntoEditWindow(false)
2205 SetStatusText(OUString());
2206 SetWindow(mxGraphicWindow
.get());
2207 SfxShell::SetName("SmView");
2208 SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() );
2209 SetController(new SmController(*this));
2212 SmViewShell::~SmViewShell()
2214 //!! this view shell is not active anymore !!
2215 // Thus 'SmGetActiveView' will give a 0 pointer.
2216 // Thus we need to supply this view as argument
2217 if (SmEditWindow
*pEditWin
= GetEditWindow())
2218 pEditWin
->DeleteEditView();
2219 mxGraphicWindow
.disposeAndClear();
2222 void SmViewShell::Deactivate( bool bIsMDIActivate
)
2224 if (SmEditWindow
*pEdit
= GetEditWindow())
2227 SfxViewShell::Deactivate( bIsMDIActivate
);
2230 void SmViewShell::Activate( bool bIsMDIActivate
)
2232 SfxViewShell::Activate( bIsMDIActivate
);
2234 if (comphelper::LibreOfficeKit::isActive())
2236 // In LOK, activate in-place editing
2237 GetGraphicWidget().GrabFocus();
2239 else if (SmEditWindow
*pEdit
= GetEditWindow())
2241 //! Since there is no way to be informed if a "drag and drop"
2242 //! event has taken place, we call SetText here in order to
2243 //! synchronize the GraphicWindow display with the text in the
2245 SmDocShell
*pDoc
= GetDoc();
2246 pDoc
->SetText( pDoc
->GetEditEngine().GetText() );
2248 if ( bIsMDIActivate
)
2253 IMPL_LINK( SmViewShell
, DialogClosedHdl
, sfx2::FileDialogHelper
*, _pFileDlg
, void )
2255 assert(_pFileDlg
&& "SmViewShell::DialogClosedHdl(): no file dialog");
2256 assert(mpDocInserter
&& "ScDocShell::DialogClosedHdl(): no document inserter");
2258 if ( ERRCODE_NONE
== _pFileDlg
->GetError() )
2260 std::unique_ptr
<SfxMedium
> pMedium
= mpDocInserter
->CreateMedium();
2264 if ( pMedium
->IsStorage() )
2267 InsertFrom( *pMedium
);
2270 SmDocShell
* pDoc
= GetDoc();
2272 pDoc
->ArrangeFormula();
2274 // adjust window, repaint, increment ModifyCount,...
2275 GetViewFrame().GetBindings().Invalidate(SID_GRAPHIC_SM
);
2279 mpRequest
->SetReturnValue( SfxBoolItem( mpRequest
->GetSlot(), true ) );
2283 void SmViewShell::Notify( SfxBroadcaster
& , const SfxHint
& rHint
)
2285 switch( rHint
.GetId() )
2287 case SfxHintId::ModeChanged
:
2288 case SfxHintId::DocChanged
:
2289 GetViewFrame().GetBindings().InvalidateAll(false);
2296 bool SmViewShell::IsInlineEditEnabled()
2298 return comphelper::LibreOfficeKit::isActive()
2299 || officecfg::Office::Common::Misc::ExperimentalMode::get();
2302 void SmViewShell::ZoomByItemSet(const SfxItemSet
*pSet
)
2305 const SvxZoomItem
&rZoom
= pSet
->Get(SID_ATTR_ZOOM
);
2306 switch( rZoom
.GetType() )
2308 case SvxZoomType::PERCENT
:
2309 mxGraphicWindow
->SetZoom(sal::static_int_cast
<sal_uInt16
>(rZoom
.GetValue ()));
2312 case SvxZoomType::OPTIMAL
:
2313 mxGraphicWindow
->ZoomToFitInWindow();
2316 case SvxZoomType::PAGEWIDTH
:
2317 case SvxZoomType::WHOLEPAGE
:
2319 const MapMode
aMap( SmMapUnit() );
2320 SfxPrinter
*pPrinter
= GetPrinter( true );
2321 tools::Rectangle
OutputRect(Point(), pPrinter
->GetOutputSize());
2322 Size
OutputSize(pPrinter
->LogicToPixel(Size(OutputRect
.GetWidth(),
2323 OutputRect
.GetHeight()), aMap
));
2324 Size
GraphicSize(pPrinter
->LogicToPixel(GetDoc()->GetSize(), aMap
));
2325 if (GraphicSize
.Width() <= 0 || GraphicSize
.Height() <= 0)
2327 sal_uInt16 nZ
= std::min(o3tl::convert(OutputSize
.Width(), 100, GraphicSize
.Width()),
2328 o3tl::convert(OutputSize
.Height(), 100, GraphicSize
.Height()));
2329 mxGraphicWindow
->SetZoom(nZ
);
2337 std::optional
<OString
> SmViewShell::getLOKPayload(int nType
, int nViewId
) const
2341 case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
:
2344 if (const SmGraphicWidget
& widget
= GetGraphicWidget(); widget
.IsCursorVisible())
2346 SmCursor
& rCursor
= GetDoc()->GetCursor();
2347 OutputDevice
& rOutDev
= const_cast<SmGraphicWidget
&>(widget
).GetOutputDevice();
2348 tools::Rectangle aCaret
= rCursor
.GetCaretRectangle(rOutDev
);
2349 Point aFormulaDrawPos
= widget
.GetFormulaDrawPos();
2350 aCaret
.Move(aFormulaDrawPos
.X(), aFormulaDrawPos
.Y());
2351 LokStarMathHelper
helper(SfxViewShell::Current());
2352 tools::Rectangle aBounds
= helper
.GetBoundingBox();
2353 aCaret
.Move(aBounds
.Left(), aBounds
.Top());
2354 sRectangle
= aCaret
.toString();
2356 return SfxLokHelper::makeVisCursorInvalidation(nViewId
, sRectangle
, false, {});
2358 case LOK_CALLBACK_TEXT_SELECTION
:
2361 if (const SmGraphicWidget
& widget
= GetGraphicWidget(); widget
.IsCursorVisible())
2363 SmCursor
& rCursor
= GetDoc()->GetCursor();
2364 OutputDevice
& rOutDev
= const_cast<SmGraphicWidget
&>(widget
).GetOutputDevice();
2365 tools::Rectangle aSelection
= rCursor
.GetSelectionRectangle(rOutDev
);
2366 if (!aSelection
.IsEmpty())
2368 Point aFormulaDrawPos
= widget
.GetFormulaDrawPos();
2369 aSelection
.Move(aFormulaDrawPos
.X(), aFormulaDrawPos
.Y());
2370 LokStarMathHelper
helper(SfxViewShell::Current());
2371 tools::Rectangle aBounds
= helper
.GetBoundingBox();
2373 aSelection
.Move(aBounds
.Left(), aBounds
.Top());
2374 sRectangle
= aSelection
.toString();
2379 case LOK_CALLBACK_TEXT_SELECTION_START
:
2380 case LOK_CALLBACK_TEXT_SELECTION_END
:
2381 case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR
:
2382 case LOK_CALLBACK_TEXT_VIEW_SELECTION
:
2385 return SfxViewShell::getLOKPayload(nType
, nViewId
); // aborts
2388 void SmViewShell::SendCaretToLOK() const
2390 const int nViewId
= sal_Int32(GetViewShellId());
2391 if (const auto& payload
= getLOKPayload(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
, nViewId
))
2393 libreOfficeKitViewCallbackWithViewId(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR
,
2396 if (const auto& payload
= getLOKPayload(LOK_CALLBACK_TEXT_SELECTION
, nViewId
))
2398 libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION
, *payload
);
2402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */