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 <com/sun/star/accessibility/AccessibleEventId.hpp>
21 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
22 #include <com/sun/star/frame/Desktop.hpp>
23 #include <com/sun/star/frame/XFramesSupplier.hpp>
24 #include <com/sun/star/container/XChild.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/servicehelper.hxx>
28 #include <comphelper/storagehelper.hxx>
29 #include <comphelper/string.hxx>
30 #include <i18nutil/unicode.hxx>
31 #include <officecfg/Office/Common.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/docfilt.hxx>
35 #include <sfx2/docinsert.hxx>
36 #include <sfx2/filedlghelper.hxx>
37 #include <sfx2/infobar.hxx>
38 #include <sfx2/msg.hxx>
39 #include <sfx2/objface.hxx>
40 #include <sfx2/printer.hxx>
41 #include <sfx2/request.hxx>
42 #include <sfx2/viewfac.hxx>
43 #include <svl/eitem.hxx>
44 #include <svl/itemset.hxx>
45 #include <svl/poolitem.hxx>
46 #include <svl/stritem.hxx>
47 #include <vcl/transfer.hxx>
48 #include <svtools/colorcfg.hxx>
49 #include <svl/whiter.hxx>
50 #include <svx/zoomslideritem.hxx>
51 #include <editeng/editeng.hxx>
52 #include <editeng/editview.hxx>
53 #include <svx/svxdlg.hxx>
54 #include <sfx2/zoomitem.hxx>
55 #include <vcl/commandevent.hxx>
56 #include <vcl/event.hxx>
57 #include <vcl/decoview.hxx>
58 #include <vcl/menu.hxx>
59 #include <vcl/settings.hxx>
60 #include <vcl/virdev.hxx>
61 #include <sal/log.hxx>
62 #include <tools/svborder.hxx>
64 #include <unotools/streamwrap.hxx>
66 #include <unomodel.hxx>
68 #include "cfgitem.hxx"
70 #include <document.hxx>
71 #include <starmath.hrc>
72 #include <strings.hrc>
74 #include "mathmlimport.hxx"
76 #include "accessibility.hxx"
77 #include <ElementsDockingWindow.hxx>
82 #define MINZOOM sal_uInt16(25)
83 #define MAXZOOM sal_uInt16(800)
85 // space around the edit window, in pixels
86 // fdo#69111: Increased border on the top so that the window is
87 // easier to tear off.
88 #define CMD_BOX_PADDING 4
89 #define CMD_BOX_PADDING_TOP 10
91 #define ShellClass_SmViewShell
92 #include <smslots.hxx>
95 using namespace css::accessibility
;
96 using namespace css::uno
;
98 SmGraphicWindow::SmGraphicWindow(SmViewShell
* pShell
)
99 : ScrollableWindow(&pShell
->GetViewFrame()->GetWindow())
104 // docking windows are usually hidden (often already done in the
105 // resource) and will be shown by the sfx framework.
108 const Fraction
aFraction(1, 1);
109 SetMapMode(MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
));
113 SetHelpId(HID_SMA_WIN_DOCUMENT
);
119 SmGraphicWindow::~SmGraphicWindow()
124 void SmGraphicWindow::dispose()
126 if (mxAccessible
.is())
127 mxAccessible
->ClearWin(); // make Accessible nonfunctional
128 mxAccessible
.clear();
130 ScrollableWindow::dispose();
133 void SmGraphicWindow::StateChanged(StateChangedType eType
)
135 if (eType
== StateChangedType::InitShow
)
137 ScrollableWindow::StateChanged(eType
);
140 void SmGraphicWindow::MouseButtonDown(const MouseEvent
& rMEvt
)
142 ScrollableWindow::MouseButtonDown(rMEvt
);
146 // set formula-cursor and selection of edit window according to the
147 // position clicked at
149 SAL_WARN_IF( rMEvt
.GetClicks() == 0, "starmath", "0 clicks" );
150 if ( !rMEvt
.IsLeft() )
153 // get click position relative to formula
154 Point
aPos (PixelToLogic(rMEvt
.GetPosPixel())
155 - GetFormulaDrawPos());
157 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
161 if (IsInlineEditEnabled()) {
162 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, !rMEvt
.IsShift());
165 const SmNode
*pNode
= nullptr;
166 // if it was clicked inside the formula then get the appropriate node
167 if (pTree
->OrientedDist(aPos
) <= 0)
168 pNode
= pTree
->FindRectClosestTo(aPos
);
173 SmEditWindow
*pEdit
= pViewShell
->GetEditWindow();
176 const SmToken
aToken (pNode
->GetToken());
178 // set selection to the beginning of the token
179 ESelection
aSel (aToken
.nRow
- 1, aToken
.nCol
- 1);
181 if (rMEvt
.GetClicks() != 1 || aToken
.eType
== TPLACE
)
182 aSel
.nEndPos
= aSel
.nEndPos
+ sal::static_int_cast
< sal_uInt16
>(aToken
.aText
.getLength());
184 pEdit
->SetSelection(aSel
);
187 // allow for immediate editing and
188 //! implicitly synchronize the cursor position mark in this window
192 void SmGraphicWindow::MouseMove(const MouseEvent
&rMEvt
)
194 ScrollableWindow::MouseMove(rMEvt
);
196 if (rMEvt
.IsLeft() && IsInlineEditEnabled())
198 Point
aPos(PixelToLogic(rMEvt
.GetPosPixel()) - GetFormulaDrawPos());
199 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, false);
202 SetIsCursorVisible(true);
204 RepaintViewShellDoc();
208 bool SmGraphicWindow::IsInlineEditEnabled()
210 return SmViewShell::IsInlineEditEnabled();
213 void SmGraphicWindow::GetFocus()
215 if (!IsInlineEditEnabled())
217 if (pViewShell
->GetEditWindow())
218 pViewShell
->GetEditWindow()->Flush();
219 //Let view shell know what insertions should be done in visual editor
220 pViewShell
->SetInsertIntoEditWindow(false);
221 SetIsCursorVisible(true);
224 RepaintViewShellDoc();
227 void SmGraphicWindow::LoseFocus()
229 ScrollableWindow::LoseFocus();
230 if (mxAccessible
.is())
232 uno::Any aOldValue
, aNewValue
;
233 aOldValue
<<= AccessibleStateType::FOCUSED
;
234 // aNewValue remains empty
235 mxAccessible
->LaunchEvent( AccessibleEventId::STATE_CHANGED
,
236 aOldValue
, aNewValue
);
238 if (!IsInlineEditEnabled())
240 SetIsCursorVisible(false);
243 RepaintViewShellDoc();
246 void SmGraphicWindow::RepaintViewShellDoc()
248 SmDocShell
* pDoc
= pViewShell
->GetDoc();
253 IMPL_LINK_NOARG(SmGraphicWindow
, CaretBlinkTimerHdl
, Timer
*, void)
255 if (IsCursorVisible())
256 SetIsCursorVisible(false);
258 SetIsCursorVisible(true);
260 RepaintViewShellDoc();
263 void SmGraphicWindow::CaretBlinkInit()
265 aCaretBlinkTimer
.SetInvokeHandler(LINK(this, SmGraphicWindow
, CaretBlinkTimerHdl
));
266 aCaretBlinkTimer
.SetTimeout( ScrollableWindow::GetSettings().GetStyleSettings().GetCursorBlinkTime() );
269 void SmGraphicWindow::CaretBlinkStart()
271 if (!IsInlineEditEnabled())
273 if (aCaretBlinkTimer
.GetTimeout() != STYLE_CURSOR_NOBLINKTIME
)
274 aCaretBlinkTimer
.Start();
277 void SmGraphicWindow::CaretBlinkStop()
279 if (!IsInlineEditEnabled())
281 aCaretBlinkTimer
.Stop();
284 void SmGraphicWindow::ShowCursor(bool bShow
)
285 // shows or hides the formula-cursor depending on 'bShow' is true or not
287 if (IsInlineEditEnabled())
290 bool bInvert
= bShow
!= IsCursorVisible();
293 InvertTracking(aCursorRect
, ShowTrackFlags::Small
| ShowTrackFlags::TrackWindow
);
295 SetIsCursorVisible(bShow
);
298 void SmGraphicWindow::ShowLine(bool bShow
)
300 if (!IsInlineEditEnabled())
303 bIsLineVisible
= bShow
;
306 void SmGraphicWindow::SetCursor(const SmNode
*pNode
)
308 if (IsInlineEditEnabled())
311 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
313 // get appropriate rectangle
314 Point
aOffset (pNode
->GetTopLeft() - pTree
->GetTopLeft()),
315 aTLPos (GetFormulaDrawPos() + aOffset
);
316 aTLPos
.AdjustX( -(pNode
->GetItalicLeftSpace()) );
317 Size
aSize (pNode
->GetItalicSize());
319 SetCursor(tools::Rectangle(aTLPos
, aSize
));
322 void SmGraphicWindow::SetCursor(const tools::Rectangle
&rRect
)
323 // sets cursor to new position (rectangle) 'rRect'.
324 // The old cursor will be removed, and the new one will be shown if
325 // that is activated in the ConfigItem
327 if (IsInlineEditEnabled())
330 SmModule
*pp
= SM_MOD();
332 if (IsCursorVisible())
333 ShowCursor(false); // clean up remainings of old cursor
335 if (pp
->GetConfig()->IsShowFormulaCursor())
336 ShowCursor(true); // draw new cursor
339 const SmNode
* SmGraphicWindow::SetCursorPos(sal_uInt16 nRow
, sal_uInt16 nCol
)
340 // looks for a VISIBLE node in the formula tree with its token at
341 // (or around) the position 'nRow', 'nCol' in the edit window
342 // (row and column numbering starts with 1 there!).
343 // If there is such a node the formula-cursor is set to cover that nodes
344 // rectangle. If not the formula-cursor will be hidden.
345 // In any case the search result is being returned.
347 if (IsInlineEditEnabled())
350 // find visible node with token at nRow, nCol
351 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree(),
354 pNode
= pTree
->FindTokenAt(nRow
, nCol
);
364 void SmGraphicWindow::ApplySettings(vcl::RenderContext
& rRenderContext
)
366 rRenderContext
.SetBackground(SM_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
);
369 void SmGraphicWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
371 SmDocShell
& rDoc
= *pViewShell
->GetDoc();
374 rDoc
.DrawFormula(rRenderContext
, aPoint
, true); //! modifies aPoint to be the topleft
375 //! corner of the formula
376 aFormulaDrawPos
= aPoint
;
377 if (IsInlineEditEnabled())
379 //Draw cursor if any...
380 if (pViewShell
->GetDoc()->HasCursor() && IsLineVisible())
381 pViewShell
->GetDoc()->GetCursor().Draw(rRenderContext
, aPoint
, IsCursorVisible());
385 SetIsCursorVisible(false); // (old) cursor must be drawn again
387 const SmEditWindow
* pEdit
= pViewShell
->GetEditWindow();
389 { // get new position for formula-cursor (for possible altered formula)
392 SmGetLeftSelectionPart(pEdit
->GetSelection(), nRow
, nCol
);
395 const SmNode
*pFound
= SetCursorPos(static_cast<sal_uInt16
>(nRow
), nCol
);
397 SmModule
*pp
= SM_MOD();
398 if (pFound
&& pp
->GetConfig()->IsShowFormulaCursor())
405 void SmGraphicWindow::SetTotalSize ()
407 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
408 const Size
aTmp( PixelToLogic( LogicToPixel( rDoc
.GetSize() )));
409 if ( aTmp
!= ScrollableWindow::GetTotalSize() )
410 ScrollableWindow::SetTotalSize( aTmp
);
413 void SmGraphicWindow::KeyInput(const KeyEvent
& rKEvt
)
415 if (!IsInlineEditEnabled()) {
416 if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
417 ScrollableWindow::KeyInput(rKEvt
);
421 SmCursor
& rCursor
= pViewShell
->GetDoc()->GetCursor();
422 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
423 if (eFunc
== KeyFuncType::COPY
)
425 else if (eFunc
== KeyFuncType::CUT
)
427 else if (eFunc
== KeyFuncType::PASTE
)
430 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
435 rCursor
.Move(this, MoveLeft
, !rKEvt
.GetKeyCode().IsShift());
439 rCursor
.Move(this, MoveRight
, !rKEvt
.GetKeyCode().IsShift());
443 rCursor
.Move(this, MoveUp
, !rKEvt
.GetKeyCode().IsShift());
447 rCursor
.Move(this, MoveDown
, !rKEvt
.GetKeyCode().IsShift());
451 if(!rKEvt
.GetKeyCode().IsShift())
456 if(!rCursor
.HasSelection()){
457 rCursor
.Move(this, MoveRight
, false);
458 if(rCursor
.HasComplexSelection()) break;
464 rCursor
.DeletePrev(this);
467 rCursor
.InsertElement(PlusElement
);
470 if(rKEvt
.GetKeyCode().IsShift())
471 rCursor
.InsertSubSup(RSUB
);
473 rCursor
.InsertElement(MinusElement
);
476 rCursor
.InsertElement(CDotElement
);
479 rCursor
.InsertFraction();
482 rCursor
.InsertElement(LessThanElement
);
485 rCursor
.InsertElement(GreaterThanElement
);
488 rCursor
.InsertElement(EqualElement
);
492 sal_Unicode code
= rKEvt
.GetCharCode();
495 rCursor
.InsertElement(BlankElement
);
496 }else if(code
== '^') {
497 rCursor
.InsertSubSup(RSUP
);
498 }else if(code
== '(') {
499 rCursor
.InsertBrackets(SmBracketType::Round
);
500 }else if(code
== '[') {
501 rCursor
.InsertBrackets(SmBracketType::Square
);
502 }else if(code
== '{') {
503 rCursor
.InsertBrackets(SmBracketType::Curly
);
504 }else if(code
== '!') {
505 rCursor
.InsertElement(FactorialElement
);
506 }else if(code
== '%') {
507 rCursor
.InsertElement(PercentElement
);
509 else if ((code
== ')' && rCursor
.IsAtTailOfBracket(SmBracketType::Round
))
510 || (code
== ']' && rCursor
.IsAtTailOfBracket(SmBracketType::Square
))
511 || (code
== '}' && rCursor
.IsAtTailOfBracket(SmBracketType::Curly
)))
513 rCursor
.Move(this, MoveRight
);
517 rCursor
.InsertText(OUString(code
));
518 }else if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
519 ScrollableWindow::KeyInput(rKEvt
);
526 SetIsCursorVisible(true);
527 RepaintViewShellDoc();
531 void SmGraphicWindow::Command(const CommandEvent
& rCEvt
)
533 bool bCallBase
= true;
534 if ( !pViewShell
->GetViewFrame()->GetFrame().IsInPlace() )
536 switch ( rCEvt
.GetCommand() )
538 case CommandEventId::ContextMenu
:
540 GetParent()->ToTop();
542 if (rCEvt
.IsMouseEvent())
543 aPos
= rCEvt
.GetMousePosPixel();
545 // added for replaceability of context menus
546 SfxDispatcher::ExecutePopup( this, &aPos
);
552 case CommandEventId::Wheel
:
554 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
555 if ( pWData
&& CommandWheelMode::ZOOM
== pWData
->GetMode() )
557 sal_uInt16 nTmpZoom
= GetZoom();
558 if( 0 > pWData
->GetDelta() )
572 ScrollableWindow::Command (rCEvt
);
576 void SmGraphicWindow::SetZoom(sal_uInt16 Factor
)
578 nZoom
= std::clamp(Factor
, MINZOOM
, MAXZOOM
);
579 Fraction
aFraction (nZoom
, 100);
580 SetMapMode( MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
) );
582 SmViewShell
*pViewSh
= GetView();
585 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM
);
586 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER
);
592 void SmGraphicWindow::ZoomToFitInWindow()
594 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
596 // set defined mapmode before calling 'LogicToPixel' below
597 SetMapMode(MapMode(MapUnit::Map100thMM
));
599 Size
aSize (LogicToPixel(rDoc
.GetSize()));
600 Size
aWindowSize (GetSizePixel());
602 if (!aSize
.IsEmpty())
604 tools::Long nVal
= std::min ((85 * aWindowSize
.Width()) / aSize
.Width(),
605 (85 * aWindowSize
.Height()) / aSize
.Height());
606 SetZoom ( sal::static_int_cast
< sal_uInt16
>(nVal
) );
610 uno::Reference
< XAccessible
> SmGraphicWindow::CreateAccessible()
612 if (!mxAccessible
.is())
614 mxAccessible
= new SmGraphicAccessible( this );
616 return mxAccessible
.get();
619 /**************************************************************************/
622 SmGraphicController::SmGraphicController(SmGraphicWindow
&rSmGraphic
,
624 SfxBindings
&rBindings
) :
625 SfxControllerItem(nId_
, rBindings
),
631 void SmGraphicController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
633 rGraphic
.SetTotalSize();
634 rGraphic
.Invalidate();
635 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
639 /**************************************************************************/
642 SmEditController::SmEditController(SmEditWindow
&rSmEdit
,
644 SfxBindings
&rBindings
) :
645 SfxControllerItem(nId_
, rBindings
),
652 void SmEditController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
654 const SfxStringItem
*pItem
= dynamic_cast<const SfxStringItem
*>( pState
);
656 if ((pItem
!= nullptr) && (rEdit
.GetText() != pItem
->GetValue()))
657 rEdit
.SetText(pItem
->GetValue());
658 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
661 /**************************************************************************/
662 SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings
*pBindings_
, SfxChildWindow
*pChildWindow
,
663 vcl::Window
*pParent
) :
664 SfxDockingWindow(pBindings_
, pChildWindow
, pParent
, WB_MOVEABLE
|WB_CLOSEABLE
|WB_SIZEABLE
|WB_DOCKABLE
),
665 aEdit (VclPtr
<SmEditWindow
>::Create(*this)),
666 aController (*aEdit
, SID_TEXT
, *pBindings_
),
669 SetHelpId( HID_SMA_COMMAND_WIN
);
670 SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont
)));
671 SetText(SmResId(STR_CMDBOXWINDOW
));
675 aInitialFocusTimer
.SetInvokeHandler(LINK(this, SmCmdBoxWindow
, InitialFocusTimerHdl
));
676 aInitialFocusTimer
.SetTimeout(100);
679 SmCmdBoxWindow::~SmCmdBoxWindow ()
684 void SmCmdBoxWindow::dispose()
686 aInitialFocusTimer
.Stop();
688 aController
.dispose();
689 aEdit
.disposeAndClear();
690 SfxDockingWindow::dispose();
693 SmViewShell
* SmCmdBoxWindow::GetView()
695 SfxDispatcher
*pDispatcher
= GetBindings().GetDispatcher();
696 SfxViewShell
*pView
= pDispatcher
? pDispatcher
->GetFrame()->GetViewShell() : nullptr;
697 return dynamic_cast<SmViewShell
*>( pView
);
700 void SmCmdBoxWindow::Resize()
702 tools::Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
703 aRect
.AdjustLeft(CMD_BOX_PADDING
);
704 aRect
.AdjustTop(CMD_BOX_PADDING_TOP
);
705 aRect
.AdjustRight( -(CMD_BOX_PADDING
) );
706 aRect
.AdjustBottom( -(CMD_BOX_PADDING
) );
708 DecorationView
aView(this);
709 aRect
= aView
.DrawFrame(aRect
, DrawFrameStyle::In
, DrawFrameFlags::NoDraw
);
711 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
712 SfxDockingWindow::Resize();
716 void SmCmdBoxWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
718 tools::Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
719 aRect
.AdjustLeft(CMD_BOX_PADDING
);
720 aRect
.AdjustTop(CMD_BOX_PADDING_TOP
);
721 aRect
.AdjustRight( -(CMD_BOX_PADDING
) );
722 aRect
.AdjustBottom( -(CMD_BOX_PADDING
) );
724 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
726 DecorationView
aView(&rRenderContext
);
727 aView
.DrawFrame( aRect
, DrawFrameStyle::In
);
730 Size
SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign
)
734 case SfxChildAlignment::LEFT
:
735 case SfxChildAlignment::RIGHT
:
740 return SfxDockingWindow::CalcDockingSize(eAlign
);
743 SfxChildAlignment
SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual
,
744 SfxChildAlignment eWish
)
748 case SfxChildAlignment::TOP
:
749 case SfxChildAlignment::BOTTOM
:
750 case SfxChildAlignment::NOALIGNMENT
:
759 void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange
)
761 if (StateChangedType::InitShow
== nStateChange
)
763 Resize(); // avoid SmEditWindow not being painted correctly
765 // set initial position of window in floating mode
766 if (IsFloatingMode())
767 AdjustPosition(); //! don't change pos in docking-mode !
769 aInitialFocusTimer
.Start();
772 SfxDockingWindow::StateChanged( nStateChange
);
775 IMPL_LINK_NOARG( SmCmdBoxWindow
, InitialFocusTimerHdl
, Timer
*, void )
777 // We want to have the focus in the edit window once Math has been opened
778 // to allow for immediate typing.
779 // Problem: There is no proper way to do this
780 // Thus: this timer based solution has been implemented (see GrabFocus below)
782 // Follow-up problem (#i114910): grabbing the focus may bust the help system since
783 // it relies on getting the current frame which conflicts with grabbing the focus.
784 // Thus aside from the 'GrabFocus' call everything else is to get the
785 // help reliably working despite using 'GrabFocus'.
789 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( comphelper::getProcessComponentContext() );
793 SmViewShell
* pView
= GetView();
795 bool bInPlace
= pView
->GetViewFrame()->GetFrame().IsInPlace();
796 uno::Reference
< frame::XFrame
> xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
799 uno::Reference
<container::XChild
> xModel(pView
->GetDoc()->GetModel(),
800 uno::UNO_QUERY_THROW
);
801 uno::Reference
< frame::XModel
> xParent( xModel
->getParent(), uno::UNO_QUERY_THROW
);
802 uno::Reference
< frame::XController
> xParentCtrler( xParent
->getCurrentController() );
803 uno::Reference
< frame::XFramesSupplier
> xParentFrame( xParentCtrler
->getFrame(), uno::UNO_QUERY_THROW
);
804 xParentFrame
->setActiveFrame( xFrame
);
808 xDesktop
->setActiveFrame( xFrame
);
811 catch (uno::Exception
&)
813 SAL_WARN( "starmath", "failed to properly set initial focus to edit window" );
817 void SmCmdBoxWindow::AdjustPosition()
819 const tools::Rectangle
aRect( Point(), GetParent()->GetOutputSizePixel() );
820 Point
aTopLeft( Point( aRect
.Left(),
821 aRect
.Bottom() - GetSizePixel().Height() ) );
822 Point
aPos( GetParent()->OutputToScreenPixel( aTopLeft
) );
830 void SmCmdBoxWindow::ToggleFloatingMode()
832 SfxDockingWindow::ToggleFloatingMode();
834 if (GetFloatingWindow())
835 GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
838 void SmCmdBoxWindow::GetFocus()
844 SFX_IMPL_DOCKINGWINDOW_WITHID(SmCmdBoxWrapper
, SID_CMDBOXWINDOW
);
846 SmCmdBoxWrapper::SmCmdBoxWrapper(vcl::Window
*pParentWindow
, sal_uInt16 nId
,
847 SfxBindings
*pBindings
,
848 SfxChildWinInfo
*pInfo
) :
849 SfxChildWindow(pParentWindow
, nId
)
851 SetWindow(VclPtr
<SmCmdBoxWindow
>::Create(pBindings
, this, pParentWindow
));
853 // make window docked to the bottom initially (after first start)
854 SetAlignment(SfxChildAlignment::BOTTOM
);
855 static_cast<SfxDockingWindow
*>(GetWindow())->Initialize(pInfo
);
858 SFX_IMPL_SUPERCLASS_INTERFACE(SmViewShell
, SfxViewShell
)
860 void SmViewShell::InitInterface_Impl()
862 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS
,
863 SfxVisibilityFlags::Standard
| SfxVisibilityFlags::FullScreen
| SfxVisibilityFlags::Server
,
864 ToolbarId::Math_Toolbox
);
865 //Dummy-Objectbar, to avoid quiver while activating
867 GetStaticInterface()->RegisterChildWindow(SmCmdBoxWrapper::GetChildWindowId());
868 GetStaticInterface()->RegisterChildWindow(SmElementsDockingWindowWrapper::GetChildWindowId());
869 GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
872 SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell
, "Default")
874 SFX_VIEW_REGISTRATION(SmDocShell
);
877 void SmViewShell::InnerResizePixel(const Point
&rOfs
, const Size
&rSize
, bool)
879 Size aObjSize
= GetObjectShell()->GetVisArea().GetSize();
880 if ( !aObjSize
.IsEmpty() )
882 Size aProvidedSize
= GetWindow()->PixelToLogic(rSize
, MapMode(MapUnit::Map100thMM
));
883 SfxViewShell::SetZoomFactor( Fraction( aProvidedSize
.Width(), aObjSize
.Width() ),
884 Fraction( aProvidedSize
.Height(), aObjSize
.Height() ) );
887 SetBorderPixel( SvBorder() );
888 GetGraphicWindow().SetPosSizePixel(rOfs
, rSize
);
889 GetGraphicWindow().SetTotalSize();
892 void SmViewShell::OuterResizePixel(const Point
&rOfs
, const Size
&rSize
)
894 SmGraphicWindow
&rWin
= GetGraphicWindow();
895 rWin
.SetPosSizePixel(rOfs
, rSize
);
896 if (GetDoc()->IsPreview())
897 rWin
.ZoomToFitInWindow();
898 rWin
.PaintImmediately();
901 void SmViewShell::QueryObjAreaPixel( tools::Rectangle
& rRect
) const
903 rRect
.SetSize( GetGraphicWindow().GetSizePixel() );
906 void SmViewShell::SetZoomFactor( const Fraction
&rX
, const Fraction
&rY
)
908 const Fraction
&rFrac
= std::min(rX
, rY
);
909 GetGraphicWindow().SetZoom(sal::static_int_cast
<sal_uInt16
>(tools::Long(rFrac
* Fraction( 100, 1 ))));
911 //To avoid rounding errors base class regulates crooked values too
913 SfxViewShell::SetZoomFactor( rX
, rY
);
916 Size
SmViewShell::GetTextLineSize(OutputDevice
const & rDevice
, const OUString
& rLine
)
918 Size
aSize(rDevice
.GetTextWidth(rLine
), rDevice
.GetTextHeight());
919 const tools::Long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_digit_width() * 8;
928 aSize
.setWidth( ((aSize
.Width() / nTabPos
) + 1) * nTabPos
);
930 const OUString aText
= rLine
.getToken(0, '\t', nPos
);
931 aSize
.AdjustWidth(rDevice
.GetTextWidth(aText
) );
939 Size
SmViewShell::GetTextSize(OutputDevice
const & rDevice
, const OUString
& rText
, tools::Long MaxWidth
)
949 OUString aLine
= rText
.getToken(0, '\n', nPos
);
950 aLine
= aLine
.replaceAll("\r", "");
952 aSize
= GetTextLineSize(rDevice
, aLine
);
954 if (aSize
.Width() > MaxWidth
)
959 sal_Int32 m
= aLine
.getLength();
962 for (sal_Int32 n
= 0; n
< nLen
; n
++)
964 sal_Unicode cLineChar
= aLine
[n
];
965 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
967 aText
= aLine
.copy(0, n
);
968 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
975 aText
= aLine
.copy(0, m
);
976 aLine
= aLine
.replaceAt(0, m
, "");
977 aSize
= GetTextLineSize(rDevice
, aText
);
978 aTextSize
.AdjustHeight(aSize
.Height() );
979 aTextSize
.setWidth( std::clamp(aSize
.Width(), aTextSize
.Width(), MaxWidth
) );
981 aLine
= comphelper::string::stripStart(aLine
, ' ');
982 aLine
= comphelper::string::stripStart(aLine
, '\t');
983 aLine
= comphelper::string::stripStart(aLine
, ' ');
985 while (!aLine
.isEmpty());
989 aTextSize
.AdjustHeight(aSize
.Height() );
990 aTextSize
.setWidth( std::max(aTextSize
.Width(), aSize
.Width()) );
998 void SmViewShell::DrawTextLine(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rLine
)
1000 Point
aPoint(rPosition
);
1001 const tools::Long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_digit_width() * 8;
1009 aPoint
.setX( ((aPoint
.X() / nTabPos
) + 1) * nTabPos
);
1011 OUString aText
= rLine
.getToken(0, '\t', nPos
);
1012 rDevice
.DrawText(aPoint
, aText
);
1013 aPoint
.AdjustX(rDevice
.GetTextWidth(aText
) );
1015 while ( nPos
>= 0 );
1018 rDevice
.DrawText(aPoint
, rLine
);
1022 void SmViewShell::DrawText(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rText
, sal_uInt16 MaxWidth
)
1024 if (rText
.isEmpty())
1027 Point
aPoint(rPosition
);
1033 OUString aLine
= rText
.getToken(0, '\n', nPos
);
1034 aLine
= aLine
.replaceAll("\r", "");
1035 aSize
= GetTextLineSize(rDevice
, aLine
);
1036 if (aSize
.Width() > MaxWidth
)
1041 sal_Int32 m
= aLine
.getLength();
1044 for (sal_Int32 n
= 0; n
< nLen
; n
++)
1046 sal_Unicode cLineChar
= aLine
[n
];
1047 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
1049 aText
= aLine
.copy(0, n
);
1050 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
1056 aText
= aLine
.copy(0, m
);
1057 aLine
= aLine
.replaceAt(0, m
, "");
1059 DrawTextLine(rDevice
, aPoint
, aText
);
1060 aPoint
.AdjustY(aSize
.Height() );
1062 aLine
= comphelper::string::stripStart(aLine
, ' ');
1063 aLine
= comphelper::string::stripStart(aLine
, '\t');
1064 aLine
= comphelper::string::stripStart(aLine
, ' ');
1066 while (GetTextLineSize(rDevice
, aLine
).Width() > MaxWidth
);
1068 // print the remaining text
1069 if (!aLine
.isEmpty())
1071 DrawTextLine(rDevice
, aPoint
, aLine
);
1072 aPoint
.AdjustY(aSize
.Height() );
1077 DrawTextLine(rDevice
, aPoint
, aLine
);
1078 aPoint
.AdjustY(aSize
.Height() );
1081 while ( nPos
>= 0 );
1084 void SmViewShell::Impl_Print(OutputDevice
&rOutDev
, const SmPrintUIOptions
&rPrintUIOptions
, tools::Rectangle aOutRect
)
1086 const bool bIsPrintTitle
= rPrintUIOptions
.getBoolValue( PRTUIOPT_TITLE_ROW
, true );
1087 const bool bIsPrintFrame
= rPrintUIOptions
.getBoolValue( PRTUIOPT_BORDER
, true );
1088 const bool bIsPrintFormulaText
= rPrintUIOptions
.getBoolValue( PRTUIOPT_FORMULA_TEXT
, true );
1089 SmPrintSize
ePrintSize( static_cast< SmPrintSize
>( rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_FORMAT
, PRINT_SIZE_NORMAL
) ));
1090 const sal_uInt16 nZoomFactor
= static_cast< sal_uInt16
>(rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_SCALE
, 100 ));
1093 rOutDev
.SetLineColor( COL_BLACK
);
1095 // output text on top
1098 Size
aSize600 (0, 600);
1099 Size
aSize650 (0, 650);
1100 vcl::Font
aFont(FAMILY_DONTKNOW
, aSize600
);
1102 aFont
.SetAlignment(ALIGN_TOP
);
1103 aFont
.SetWeight(WEIGHT_BOLD
);
1104 aFont
.SetFontSize(aSize650
);
1105 aFont
.SetColor( COL_BLACK
);
1106 rOutDev
.SetFont(aFont
);
1108 Size
aTitleSize (GetTextSize(rOutDev
, GetDoc()->GetTitle(), aOutRect
.GetWidth() - 200));
1110 aFont
.SetWeight(WEIGHT_NORMAL
);
1111 aFont
.SetFontSize(aSize600
);
1112 rOutDev
.SetFont(aFont
);
1114 Size
aDescSize (GetTextSize(rOutDev
, GetDoc()->GetComment(), aOutRect
.GetWidth() - 200));
1117 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.TopLeft(),
1118 Size(aOutRect
.GetWidth(), 100 + aTitleSize
.Height() + 200 + aDescSize
.Height() + 100)));
1119 aOutRect
.AdjustTop(200 );
1122 aFont
.SetWeight(WEIGHT_BOLD
);
1123 aFont
.SetFontSize(aSize650
);
1124 rOutDev
.SetFont(aFont
);
1125 Point
aPoint(aOutRect
.Left() + (aOutRect
.GetWidth() - aTitleSize
.Width()) / 2,
1127 DrawText(rOutDev
, aPoint
, GetDoc()->GetTitle(),
1128 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1129 aOutRect
.AdjustTop(aTitleSize
.Height() + 200 );
1131 // output description
1132 aFont
.SetWeight(WEIGHT_NORMAL
);
1133 aFont
.SetFontSize(aSize600
);
1134 rOutDev
.SetFont(aFont
);
1135 aPoint
.setX( aOutRect
.Left() + (aOutRect
.GetWidth() - aDescSize
.Width()) / 2 );
1136 aPoint
.setY( aOutRect
.Top() );
1137 DrawText(rOutDev
, aPoint
, GetDoc()->GetComment(),
1138 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1139 aOutRect
.AdjustTop(aDescSize
.Height() + 300 );
1142 // output text on bottom
1143 if (bIsPrintFormulaText
)
1145 vcl::Font
aFont(FAMILY_DONTKNOW
, Size(0, 600));
1146 aFont
.SetAlignment(ALIGN_TOP
);
1147 aFont
.SetColor( COL_BLACK
);
1150 rOutDev
.SetFont(aFont
);
1152 Size
aSize (GetTextSize(rOutDev
, GetDoc()->GetText(), aOutRect
.GetWidth() - 200));
1154 aOutRect
.AdjustBottom( -(aSize
.Height() + 600) );
1157 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.BottomLeft(),
1158 Size(aOutRect
.GetWidth(), 200 + aSize
.Height() + 200)));
1160 Point
aPoint (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1161 aOutRect
.Bottom() + 300);
1162 DrawText(rOutDev
, aPoint
, GetDoc()->GetText(),
1163 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1164 aOutRect
.AdjustBottom( -200 );
1168 rOutDev
.DrawRect(aOutRect
);
1170 aOutRect
.AdjustTop(100 );
1171 aOutRect
.AdjustLeft(100 );
1172 aOutRect
.AdjustBottom( -100 );
1173 aOutRect
.AdjustRight( -100 );
1175 Size
aSize (GetDoc()->GetSize());
1177 MapMode OutputMapMode
;
1178 // PDF export should always use PRINT_SIZE_NORMAL ...
1179 if (!rPrintUIOptions
.getBoolValue( "IsPrinter" ) )
1180 ePrintSize
= PRINT_SIZE_NORMAL
;
1183 case PRINT_SIZE_NORMAL
:
1184 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1187 case PRINT_SIZE_SCALED
:
1188 if (!aSize
.IsEmpty())
1190 Size
OutputSize (rOutDev
.LogicToPixel(Size(aOutRect
.GetWidth(),
1191 aOutRect
.GetHeight()), MapMode(MapUnit::Map100thMM
)));
1192 Size
GraphicSize (rOutDev
.LogicToPixel(aSize
, MapMode(MapUnit::Map100thMM
)));
1193 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(tools::Long(Fraction(OutputSize
.Width() * 100, GraphicSize
.Width())),
1194 tools::Long(Fraction(OutputSize
.Height() * 100, GraphicSize
.Height()))));
1196 Fraction
aFraction (std::clamp(nZ
, MINZOOM
, sal_uInt16(100)));
1198 OutputMapMode
= MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
);
1201 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1204 case PRINT_SIZE_ZOOMED
:
1206 Fraction
aFraction( nZoomFactor
, 100 );
1208 OutputMapMode
= MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
);
1213 aSize
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aSize
, OutputMapMode
),
1214 MapMode(MapUnit::Map100thMM
));
1216 Point
aPos (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1217 aOutRect
.Top() + (aOutRect
.GetHeight() - aSize
.Height()) / 2);
1219 aPos
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aPos
, MapMode(MapUnit::Map100thMM
)),
1221 aOutRect
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aOutRect
, MapMode(MapUnit::Map100thMM
)),
1224 rOutDev
.SetMapMode(OutputMapMode
);
1225 rOutDev
.SetClipRegion(vcl::Region(aOutRect
));
1226 GetDoc()->DrawFormula(rOutDev
, aPos
);
1227 rOutDev
.SetClipRegion();
1232 SfxPrinter
* SmViewShell::GetPrinter(bool bCreate
)
1234 SmDocShell
* pDoc
= GetDoc();
1235 if (pDoc
->HasPrinter() || bCreate
)
1236 return pDoc
->GetPrinter();
1240 sal_uInt16
SmViewShell::SetPrinter(SfxPrinter
*pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
1242 SfxPrinter
*pOld
= GetDoc()->GetPrinter();
1243 if ( pOld
&& pOld
->IsPrinting() )
1244 return SFX_PRINTERROR_BUSY
;
1246 if ((nDiffFlags
& SfxPrinterChangeFlags::PRINTER
) == SfxPrinterChangeFlags::PRINTER
)
1247 GetDoc()->SetPrinter( pNewPrinter
);
1249 if ((nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
) == SfxPrinterChangeFlags::OPTIONS
)
1251 SmModule
*pp
= SM_MOD();
1252 pp
->GetConfig()->ItemSetToConfig(pNewPrinter
->GetOptions());
1257 bool SmViewShell::HasPrintOptionsPage() const
1262 std::unique_ptr
<SfxTabPage
> SmViewShell::CreatePrintOptionsPage(weld::Container
* pPage
, weld::DialogController
* pController
,
1263 const SfxItemSet
&rOptions
)
1265 return SmPrintOptionsTabPage::Create(pPage
, pController
, rOptions
);
1268 SmEditWindow
*SmViewShell::GetEditWindow()
1270 SmCmdBoxWrapper
* pWrapper
= static_cast<SmCmdBoxWrapper
*>(
1271 GetViewFrame()->GetChildWindow(SmCmdBoxWrapper::GetChildWindowId()));
1273 if (pWrapper
!= nullptr)
1275 SmEditWindow
& rEditWin
= pWrapper
->GetEditWindow();
1282 void SmViewShell::SetStatusText(const OUString
& rText
)
1284 maStatusText
= rText
;
1285 GetViewFrame()->GetBindings().Invalidate(SID_TEXTSTATUS
);
1288 void SmViewShell::ShowError(const SmErrorDesc
* pErrorDesc
)
1291 if (pErrorDesc
|| nullptr != (pErrorDesc
= GetDoc()->GetParser().GetError()) )
1293 SetStatusText( pErrorDesc
->m_aText
);
1294 GetEditWindow()->MarkError( Point( pErrorDesc
->m_pNode
->GetColumn(),
1295 pErrorDesc
->m_pNode
->GetRow()));
1299 void SmViewShell::NextError()
1302 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().NextError();
1305 ShowError( pErrorDesc
);
1308 void SmViewShell::PrevError()
1311 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().PrevError();
1314 ShowError( pErrorDesc
);
1317 void SmViewShell::Insert( SfxMedium
& rMedium
)
1319 SmDocShell
*pDoc
= GetDoc();
1322 uno::Reference
<embed::XStorage
> xStorage
= rMedium
.GetStorage();
1323 if (xStorage
.is() && xStorage
->getElementNames().hasElements())
1325 if (xStorage
->hasByName("content.xml"))
1327 // is this a fabulous math package ?
1328 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1329 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1330 bRet
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1337 OUString aText
= pDoc
->GetText();
1338 SmEditWindow
*pEditWin
= GetEditWindow();
1340 pEditWin
->InsertText( aText
);
1343 SAL_WARN( "starmath", "EditWindow missing" );
1347 pDoc
->SetModified();
1349 SfxBindings
&rBnd
= GetViewFrame()->GetBindings();
1350 rBnd
.Invalidate(SID_GAPHIC_SM
);
1351 rBnd
.Invalidate(SID_TEXT
);
1354 void SmViewShell::InsertFrom(SfxMedium
&rMedium
)
1356 bool bSuccess
= false;
1357 SmDocShell
* pDoc
= GetDoc();
1358 SvStream
* pStream
= rMedium
.GetInStream();
1362 const OUString
& rFltName
= rMedium
.GetFilter()->GetFilterName();
1363 if ( rFltName
== MATHML_XML
)
1365 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1366 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1367 bSuccess
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1374 OUString aText
= pDoc
->GetText();
1375 SmEditWindow
*pEditWin
= GetEditWindow();
1377 pEditWin
->InsertText(aText
);
1379 SAL_WARN( "starmath", "EditWindow missing" );
1382 pDoc
->SetModified();
1384 SfxBindings
& rBnd
= GetViewFrame()->GetBindings();
1385 rBnd
.Invalidate(SID_GAPHIC_SM
);
1386 rBnd
.Invalidate(SID_TEXT
);
1389 void SmViewShell::Execute(SfxRequest
& rReq
)
1391 SmEditWindow
*pWin
= GetEditWindow();
1393 switch (rReq
.GetSlot())
1395 case SID_FORMULACURSOR
:
1397 SmModule
*pp
= SM_MOD();
1399 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1400 const SfxPoolItem
*pItem
;
1404 SfxItemState::SET
== pArgs
->GetItemState( SID_FORMULACURSOR
, false, &pItem
))
1405 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1407 bVal
= !pp
->GetConfig()->IsShowFormulaCursor();
1409 pp
->GetConfig()->SetShowFormulaCursor(bVal
);
1410 if (!IsInlineEditEnabled())
1411 GetGraphicWindow().ShowCursor(bVal
);
1417 GetDoc()->SetText( pWin
->GetText() );
1418 SetStatusText(OUString());
1419 ShowError( nullptr );
1420 GetDoc()->Repaint();
1424 case SID_ZOOM_OPTIMAL
:
1425 mpGraphic
->ZoomToFitInWindow();
1429 mpGraphic
->SetZoom(mpGraphic
->GetZoom() + 25);
1433 SAL_WARN_IF( mpGraphic
->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1434 mpGraphic
->SetZoom(mpGraphic
->GetZoom() - 25);
1437 case SID_COPYOBJECT
:
1439 //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
1440 Reference
< datatransfer::XTransferable
> xTrans( GetDoc()->GetModel(), uno::UNO_QUERY
);
1443 auto pTrans
= comphelper::getUnoTunnelImplementation
<TransferableHelper
>(xTrans
);
1445 pTrans
->CopyToClipboard(GetEditWindow());
1450 case SID_PASTEOBJECT
:
1452 TransferableDataHelper
aData( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1453 uno::Reference
< io::XInputStream
> xStrm
;
1454 SotClipboardFormatId nId
;
1455 if( aData
.GetTransferable().is() &&
1456 ( aData
.HasFormat( nId
= SotClipboardFormatId::EMBEDDED_OBJ
) ||
1457 (aData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
1458 aData
.HasFormat( nId
= SotClipboardFormatId::EMBED_SOURCE
))))
1459 xStrm
= aData
.GetInputStream(nId
, OUString());
1465 uno::Reference
< embed::XStorage
> xStorage
=
1466 ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
, ::comphelper::getProcessComponentContext() );
1467 SfxMedium
aMedium( xStorage
, OUString() );
1469 GetDoc()->UpdateText();
1471 catch (uno::Exception
&)
1473 SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1488 if (pWin
->IsAllSelected())
1490 GetViewFrame()->GetDispatcher()->ExecuteList(
1491 SID_COPYOBJECT
, SfxCallMode::RECORD
,
1492 { new SfxVoidItem(SID_COPYOBJECT
) });
1501 bool bCallExec
= nullptr == pWin
;
1504 TransferableDataHelper
aDataHelper(
1505 TransferableDataHelper::CreateFromSystemClipboard(
1508 if( aDataHelper
.GetTransferable().is() &&
1509 aDataHelper
.HasFormat( SotClipboardFormatId::STRING
))
1516 GetViewFrame()->GetDispatcher()->ExecuteList(
1517 SID_PASTEOBJECT
, SfxCallMode::RECORD
,
1518 { new SfxVoidItem(SID_PASTEOBJECT
) });
1533 case SID_INSERTCOMMANDTEXT
:
1535 const SfxStringItem
& rItem
= static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTCOMMANDTEXT
));
1537 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1539 pWin
->InsertText(rItem
.GetValue());
1541 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1543 GetDoc()->GetCursor().InsertCommandText(rItem
.GetValue());
1544 GetGraphicWindow().GrabFocus();
1550 case SID_INSERTSPECIAL
:
1552 const SfxStringItem
& rItem
=
1553 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTSPECIAL
));
1555 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1556 pWin
->InsertText(rItem
.GetValue());
1557 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1558 GetDoc()->GetCursor().InsertSpecial(rItem
.GetValue());
1562 case SID_IMPORT_FORMULA
:
1564 mpRequest
.reset(new SfxRequest( rReq
));
1565 mpDocInserter
.reset(new ::sfx2::DocumentInserter(pWin
? pWin
->GetFrameWeld() : nullptr,
1566 GetDoc()->GetFactory().GetFactoryName()));
1567 mpDocInserter
->StartExecuteModal( LINK( this, SmViewShell
, DialogClosedHdl
) );
1571 case SID_IMPORT_MATHML_CLIPBOARD
:
1573 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1574 uno::Reference
< io::XInputStream
> xStrm
;
1575 if ( aDataHelper
.GetTransferable().is() )
1577 SotClipboardFormatId nId
= SotClipboardFormatId::MATHML
;
1578 if (aDataHelper
.HasFormat(nId
))
1580 xStrm
= aDataHelper
.GetInputStream(nId
, "");
1583 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1584 pClipboardMedium
->GetItemSet(); //generate initial itemset, not sure if necessary
1585 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1586 SfxFilter::GetFilterByName(MATHML_XML
);
1587 pClipboardMedium
->SetFilter(pMathFilter
);
1588 pClipboardMedium
->setStreamToLoadFrom(xStrm
, true /*bIsReadOnly*/);
1589 InsertFrom(*pClipboardMedium
);
1590 GetDoc()->UpdateText();
1595 nId
= SotClipboardFormatId::STRING
;
1596 if (aDataHelper
.HasFormat(nId
))
1598 // In case of FORMAT_STRING no stream exists, need to generate one
1600 if (aDataHelper
.GetString( nId
, aString
))
1602 // tdf#117091 force xml declaration to exist
1603 if (!aString
.startsWith("<?xml"))
1604 aString
= "<?xml version=\"1.0\"?>\n" + aString
;
1606 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1607 pClipboardMedium
->GetItemSet(); //generates initial itemset, not sure if necessary
1608 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1609 SfxFilter::GetFilterByName(MATHML_XML
);
1610 pClipboardMedium
->SetFilter(pMathFilter
);
1612 std::unique_ptr
<SvMemoryStream
> pStrm
;
1613 // The text to be imported might asserts encoding like 'encoding="utf-8"' but FORMAT_STRING is UTF-16.
1614 // Force encoding to UTF-16, if encoding exists.
1615 bool bForceUTF16
= false;
1616 sal_Int32 nPosL
= aString
.indexOf("encoding=\"");
1617 sal_Int32 nPosU
= -1;
1618 if ( nPosL
>= 0 && nPosL
+10 < aString
.getLength() )
1621 nPosU
= aString
.indexOf( '"',nPosL
);
1629 OUString aNewString
= aString
.replaceAt( nPosL
,nPosU
-nPosL
,"UTF-16");
1630 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aNewString
.getStr()), aNewString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1634 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aString
.getStr()), aString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1636 uno::Reference
<io::XInputStream
> xStrm2( new ::utl::OInputStreamWrapper(*pStrm
) );
1637 pClipboardMedium
->setStreamToLoadFrom(xStrm2
, true /*bIsReadOnly*/);
1638 InsertFrom(*pClipboardMedium
);
1639 GetDoc()->UpdateText();
1662 pWin
->SelNextMark();
1670 pWin
->SelPrevMark();
1675 case SID_TEXTSTATUS
:
1677 if (rReq
.GetArgs() != nullptr)
1679 const SfxStringItem
& rItem
=
1680 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_TEXTSTATUS
));
1682 SetStatusText(rItem
.GetValue());
1688 case SID_GETEDITTEXT
:
1689 if (pWin
&& !pWin
->GetText().isEmpty())
1690 GetDoc()->SetText( pWin
->GetText() );
1695 if ( !GetViewFrame()->GetFrame().IsInPlace() )
1697 const SfxItemSet
*pSet
= rReq
.GetArgs();
1700 ZoomByItemSet(pSet
);
1704 SfxItemSet
aSet( SmDocShell::GetPool(), svl::Items
<SID_ATTR_ZOOM
, SID_ATTR_ZOOM
>{});
1705 aSet
.Put( SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1706 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1707 ScopedVclPtr
<AbstractSvxZoomDialog
> xDlg(pFact
->CreateSvxZoomDialog(GetViewFrame()->GetWindow().GetFrameWeld(), aSet
));
1708 xDlg
->SetLimits( MINZOOM
, MAXZOOM
);
1709 if (xDlg
->Execute() != RET_CANCEL
)
1710 ZoomByItemSet(xDlg
->GetOutputItemSet());
1716 case SID_ATTR_ZOOMSLIDER
:
1718 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1719 const SfxPoolItem
* pItem
;
1721 if ( pArgs
&& SfxItemState::SET
== pArgs
->GetItemState(SID_ATTR_ZOOMSLIDER
, true, &pItem
) )
1723 const sal_uInt16 nCurrentZoom
= static_cast<const SvxZoomSliderItem
*>(pItem
)->GetValue();
1724 mpGraphic
->SetZoom( nCurrentZoom
);
1729 case SID_ELEMENTSDOCKINGWINDOW
:
1731 GetViewFrame()->ToggleChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1732 GetViewFrame()->GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW
);
1738 case SID_UNICODE_NOTATION_TOGGLE
:
1740 EditEngine
* pEditEngine
= nullptr;
1742 pEditEngine
= pWin
->GetEditEngine();
1744 EditView
* pEditView
= nullptr;
1746 pEditView
= pEditEngine
->GetView();
1750 const OUString sInput
= pEditView
->GetSurroundingText();
1751 ESelection
aSel( pWin
->GetSelection() );
1753 if ( aSel
.nStartPos
> aSel
.nEndPos
)
1754 aSel
.nEndPos
= aSel
.nStartPos
;
1756 //calculate a valid end-position by reading logical characters
1757 sal_Int32 nUtf16Pos
=0;
1758 while( (nUtf16Pos
< sInput
.getLength()) && (nUtf16Pos
< aSel
.nEndPos
) )
1760 sInput
.iterateCodePoints(&nUtf16Pos
);
1761 if( nUtf16Pos
> aSel
.nEndPos
)
1762 aSel
.nEndPos
= nUtf16Pos
;
1765 ToggleUnicodeCodepoint aToggle
;
1766 while( nUtf16Pos
&& aToggle
.AllowMoreInput( sInput
[nUtf16Pos
-1]) )
1768 const OUString sReplacement
= aToggle
.ReplacementString();
1769 if( !sReplacement
.isEmpty() )
1771 pEditView
->SetSelection( aSel
);
1772 pEditEngine
->UndoActionStart(EDITUNDO_REPLACEALL
);
1773 aSel
.nStartPos
= aSel
.nEndPos
- aToggle
.StringToReplace().getLength();
1774 pWin
->SetSelection( aSel
);
1775 pEditView
->InsertText( sReplacement
, true );
1776 pEditEngine
->UndoActionEnd();
1783 case SID_SYMBOLS_CATALOGUE
:
1786 // get device used to retrieve the FontList
1787 SmDocShell
*pDoc
= GetDoc();
1788 OutputDevice
*pDev
= pDoc
->GetPrinter();
1789 if (!pDev
|| pDev
->GetDevFontCount() == 0)
1790 pDev
= &SM_MOD()->GetDefaultVirtualDev();
1791 SAL_WARN_IF( !pDev
, "starmath", "device for font list missing" );
1793 SmModule
*pp
= SM_MOD();
1794 SmSymbolDialog
aDialog(pWin
? pWin
->GetFrameWeld() : nullptr, pDev
, pp
->GetSymbolManager(), *this);
1803 void SmViewShell::GetState(SfxItemSet
&rSet
)
1805 SfxWhichIter
aIter(rSet
);
1807 SmEditWindow
*pEditWin
= GetEditWindow();
1808 for (sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
!= 0; nWh
= aIter
.NextWhich())
1815 if (! pEditWin
|| ! pEditWin
->IsSelected())
1816 rSet
.DisableItem(nWh
);
1822 TransferableDataHelper
aDataHelper(
1823 TransferableDataHelper::CreateFromSystemClipboard(
1826 mbPasteState
= aDataHelper
.GetTransferable().is() &&
1827 ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) ||
1828 aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) ||
1829 (aDataHelper
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
)
1830 && aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
)));
1833 rSet
.DisableItem( nWh
);
1837 rSet
.Put(SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1841 case SID_ZOOM_OPTIMAL
:
1842 if ( GetViewFrame()->GetFrame().IsInPlace() )
1843 rSet
.DisableItem( nWh
);
1846 case SID_ATTR_ZOOMSLIDER
:
1848 const sal_uInt16 nCurrentZoom
= mpGraphic
->GetZoom();
1849 SvxZoomSliderItem
aZoomSliderItem( nCurrentZoom
, MINZOOM
, MAXZOOM
);
1850 aZoomSliderItem
.AddSnappingPoint( 100 );
1851 rSet
.Put( aZoomSliderItem
);
1861 if (! pEditWin
|| pEditWin
->IsEmpty())
1862 rSet
.DisableItem(nWh
);
1865 case SID_TEXTSTATUS
:
1867 rSet
.Put(SfxStringItem(nWh
, maStatusText
));
1871 case SID_FORMULACURSOR
:
1873 SmModule
*pp
= SM_MOD();
1874 rSet
.Put(SfxBoolItem(nWh
, pp
->GetConfig()->IsShowFormulaCursor()));
1877 case SID_ELEMENTSDOCKINGWINDOW
:
1879 bool bState
= false;
1880 SfxChildWindow
*pChildWnd
= GetViewFrame()->
1881 GetChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1882 if (pChildWnd
&& pChildWnd
->GetWindow()->IsVisible())
1884 rSet
.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW
, bState
));
1891 SmViewShell::SmViewShell(SfxViewFrame
*pFrame_
, SfxViewShell
*)
1892 : SfxViewShell(pFrame_
, SfxViewShellFlags::HAS_PRINTOPTIONS
)
1893 , mpGraphic(VclPtr
<SmGraphicWindow
>::Create(this))
1894 , maGraphicController(*mpGraphic
, SID_GAPHIC_SM
, pFrame_
->GetBindings())
1895 , mbPasteState(false)
1896 , mbInsertIntoEditWindow(false)
1898 SetStatusText(OUString());
1899 SetWindow(mpGraphic
.get());
1900 SfxShell::SetName("SmView");
1901 SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() );
1905 SmViewShell::~SmViewShell()
1907 //!! this view shell is not active anymore !!
1908 // Thus 'SmGetActiveView' will give a 0 pointer.
1909 // Thus we need to supply this view as argument
1910 SmEditWindow
*pEditWin
= GetEditWindow();
1912 pEditWin
->DeleteEditView();
1913 mpGraphic
.disposeAndClear();
1916 void SmViewShell::Deactivate( bool bIsMDIActivate
)
1918 SmEditWindow
*pEdit
= GetEditWindow();
1922 SfxViewShell::Deactivate( bIsMDIActivate
);
1925 void SmViewShell::Activate( bool bIsMDIActivate
)
1927 SfxViewShell::Activate( bIsMDIActivate
);
1929 SmEditWindow
*pEdit
= GetEditWindow();
1932 //! Since there is no way to be informed if a "drag and drop"
1933 //! event has taken place, we call SetText here in order to
1934 //! synchronize the GraphicWindow display with the text in the
1936 SmDocShell
*pDoc
= GetDoc();
1937 pDoc
->SetText( pDoc
->GetEditEngine().GetText() );
1939 if ( bIsMDIActivate
)
1944 IMPL_LINK( SmViewShell
, DialogClosedHdl
, sfx2::FileDialogHelper
*, _pFileDlg
, void )
1946 assert(_pFileDlg
&& "SmViewShell::DialogClosedHdl(): no file dialog");
1947 assert(mpDocInserter
&& "ScDocShell::DialogClosedHdl(): no document inserter");
1949 if ( ERRCODE_NONE
== _pFileDlg
->GetError() )
1951 std::unique_ptr
<SfxMedium
> pMedium
= mpDocInserter
->CreateMedium();
1955 if ( pMedium
->IsStorage() )
1958 InsertFrom( *pMedium
);
1961 SmDocShell
* pDoc
= GetDoc();
1963 pDoc
->ArrangeFormula();
1965 // adjust window, repaint, increment ModifyCount,...
1966 GetViewFrame()->GetBindings().Invalidate(SID_GAPHIC_SM
);
1970 mpRequest
->SetReturnValue( SfxBoolItem( mpRequest
->GetSlot(), true ) );
1974 void SmViewShell::Notify( SfxBroadcaster
& , const SfxHint
& rHint
)
1976 switch( rHint
.GetId() )
1978 case SfxHintId::ModeChanged
:
1979 case SfxHintId::DocChanged
:
1980 GetViewFrame()->GetBindings().InvalidateAll(false);
1987 bool SmViewShell::IsInlineEditEnabled()
1989 return officecfg::Office::Common::Misc::ExperimentalMode::get();
1992 void SmViewShell::ZoomByItemSet(const SfxItemSet
*pSet
)
1995 const SvxZoomItem
&rZoom
= pSet
->Get(SID_ATTR_ZOOM
);
1996 switch( rZoom
.GetType() )
1998 case SvxZoomType::PERCENT
:
1999 mpGraphic
->SetZoom(sal::static_int_cast
<sal_uInt16
>(rZoom
.GetValue ()));
2002 case SvxZoomType::OPTIMAL
:
2003 mpGraphic
->ZoomToFitInWindow();
2006 case SvxZoomType::PAGEWIDTH
:
2007 case SvxZoomType::WHOLEPAGE
:
2009 const MapMode
aMap( MapUnit::Map100thMM
);
2010 SfxPrinter
*pPrinter
= GetPrinter( true );
2011 tools::Rectangle
OutputRect(Point(), pPrinter
->GetOutputSize());
2012 Size
OutputSize(pPrinter
->LogicToPixel(Size(OutputRect
.GetWidth(),
2013 OutputRect
.GetHeight()), aMap
));
2014 Size
GraphicSize(pPrinter
->LogicToPixel(GetDoc()->GetSize(), aMap
));
2015 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(tools::Long(Fraction(OutputSize
.Width() * 100, GraphicSize
.Width())),
2016 tools::Long(Fraction(OutputSize
.Height() * 100, GraphicSize
.Height()))));
2017 mpGraphic
->SetZoom (nZ
);
2025 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */