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/accessibility/XAccessible.hpp>
23 #include <com/sun/star/frame/Desktop.hpp>
24 #include <com/sun/star/frame/XFramesSupplier.hpp>
25 #include <com/sun/star/container/XChild.hpp>
27 #include <comphelper/processfactory.hxx>
28 #include <comphelper/storagehelper.hxx>
29 #include <comphelper/string.hxx>
30 #include <i18nutil/unicode.hxx>
31 #include <sfx2/dispatch.hxx>
32 #include <sfx2/docfile.hxx>
33 #include <sfx2/docfilt.hxx>
34 #include <sfx2/docinsert.hxx>
35 #include <sfx2/filedlghelper.hxx>
36 #include <sfx2/infobar.hxx>
37 #include <sfx2/msg.hxx>
38 #include <sfx2/objface.hxx>
39 #include <sfx2/printer.hxx>
40 #include <sfx2/request.hxx>
41 #include <svl/eitem.hxx>
42 #include <svl/itemset.hxx>
43 #include <svl/poolitem.hxx>
44 #include <svl/stritem.hxx>
45 #include <svtools/transfer.hxx>
46 #include <svtools/miscopt.hxx>
47 #include <svl/whiter.hxx>
48 #include <svx/zoomslideritem.hxx>
49 #include <editeng/editeng.hxx>
50 #include <editeng/editview.hxx>
51 #include <svx/svxdlg.hxx>
52 #include <sfx2/zoomitem.hxx>
53 #include <vcl/decoview.hxx>
54 #include <vcl/menu.hxx>
55 #include <vcl/settings.hxx>
57 #include <unotools/streamwrap.hxx>
59 #include <unomodel.hxx>
61 #include "cfgitem.hxx"
63 #include <document.hxx>
64 #include <starmath.hrc>
65 #include <strings.hrc>
66 #include "mathmlimport.hxx"
68 #include "accessibility.hxx"
69 #include <ElementsDockingWindow.hxx>
74 #define MINZOOM sal_uInt16(25)
75 #define MAXZOOM sal_uInt16(800)
77 // space around the edit window, in pixels
78 // fdo#69111: Increased border on the top so that the window is
79 // easier to tear off.
80 #define CMD_BOX_PADDING 4
81 #define CMD_BOX_PADDING_TOP 10
83 #define ShellClass_SmViewShell
84 #include <smslots.hxx>
87 using namespace css::accessibility
;
88 using namespace css::uno
;
90 SmGraphicWindow::SmGraphicWindow(SmViewShell
* pShell
)
91 : ScrollableWindow(&pShell
->GetViewFrame()->GetWindow())
96 // docking windows are usually hidden (often already done in the
97 // resource) and will be shown by the sfx framework.
100 const Fraction
aFraction(1, 1);
101 SetMapMode(MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
));
105 SetHelpId(HID_SMA_WIN_DOCUMENT
);
111 SmGraphicWindow::~SmGraphicWindow()
116 void SmGraphicWindow::dispose()
118 if (mxAccessible
.is())
119 mxAccessible
->ClearWin(); // make Accessible nonfunctional
121 ScrollableWindow::dispose();
124 void SmGraphicWindow::StateChanged(StateChangedType eType
)
126 if (eType
== StateChangedType::InitShow
)
128 ScrollableWindow::StateChanged(eType
);
132 void SmGraphicWindow::ApplyColorConfigValues(const svtools::ColorConfig
&rColorCfg
)
134 // Note: SetTextColor not necessary since the nodes that
135 // get painted have the color information.
136 SetBackground(rColorCfg
.GetColorValue(svtools::DOCCOLOR
).nColor
);
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() )
152 // get click position relative to formula
153 Point
aPos (PixelToLogic(rMEvt
.GetPosPixel())
154 - GetFormulaDrawPos());
156 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
160 if (IsInlineEditEnabled()) {
161 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, !rMEvt
.IsShift());
164 const SmNode
*pNode
= nullptr;
165 // if it was clicked inside the formula then get the appropriate node
166 if (pTree
->OrientedDist(aPos
) <= 0)
167 pNode
= pTree
->FindRectClosestTo(aPos
);
170 { SmEditWindow
*pEdit
= pViewShell
->GetEditWindow();
173 const SmToken
aToken (pNode
->GetToken());
175 // set selection to the beginning of the token
176 ESelection
aSel (aToken
.nRow
- 1, aToken
.nCol
- 1);
178 if (rMEvt
.GetClicks() != 1 || aToken
.eType
== TPLACE
)
179 aSel
.nEndPos
= aSel
.nEndPos
+ sal::static_int_cast
< sal_uInt16
>(aToken
.aText
.getLength());
181 pEdit
->SetSelection(aSel
);
184 // allow for immediate editing and
185 //! implicitly synchronize the cursor position mark in this window
191 void SmGraphicWindow::MouseMove(const MouseEvent
&rMEvt
)
193 ScrollableWindow::MouseMove(rMEvt
);
195 if (rMEvt
.IsLeft() && IsInlineEditEnabled())
197 Point
aPos(PixelToLogic(rMEvt
.GetPosPixel()) - GetFormulaDrawPos());
198 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, false);
201 SetIsCursorVisible(true);
203 RepaintViewShellDoc();
207 bool SmGraphicWindow::IsInlineEditEnabled() const
209 return pViewShell
->IsInlineEditEnabled();
212 void SmGraphicWindow::GetFocus()
214 if (!IsInlineEditEnabled())
216 if (pViewShell
->GetEditWindow())
217 pViewShell
->GetEditWindow()->Flush();
218 //Let view shell know what insertions should be done in visual editor
219 pViewShell
->SetInsertIntoEditWindow(false);
220 SetIsCursorVisible(true);
223 RepaintViewShellDoc();
226 void SmGraphicWindow::LoseFocus()
228 ScrollableWindow::LoseFocus();
229 if (mxAccessible
.is())
231 uno::Any aOldValue
, aNewValue
;
232 aOldValue
<<= AccessibleStateType::FOCUSED
;
233 // aNewValue remains empty
234 mxAccessible
->LaunchEvent( AccessibleEventId::STATE_CHANGED
,
235 aOldValue
, aNewValue
);
237 if (!IsInlineEditEnabled())
239 SetIsCursorVisible(false);
242 RepaintViewShellDoc();
245 void SmGraphicWindow::RepaintViewShellDoc()
247 SmDocShell
* pDoc
= pViewShell
->GetDoc();
252 IMPL_LINK_NOARG(SmGraphicWindow
, CaretBlinkTimerHdl
, Timer
*, void)
254 if (IsCursorVisible())
255 SetIsCursorVisible(false);
257 SetIsCursorVisible(true);
259 RepaintViewShellDoc();
262 void SmGraphicWindow::CaretBlinkInit()
264 aCaretBlinkTimer
.SetInvokeHandler(LINK(this, SmGraphicWindow
, CaretBlinkTimerHdl
));
265 aCaretBlinkTimer
.SetTimeout( ScrollableWindow::GetSettings().GetStyleSettings().GetCursorBlinkTime() );
268 void SmGraphicWindow::CaretBlinkStart()
270 if (!IsInlineEditEnabled())
272 if (aCaretBlinkTimer
.GetTimeout() != STYLE_CURSOR_NOBLINKTIME
)
273 aCaretBlinkTimer
.Start();
276 void SmGraphicWindow::CaretBlinkStop()
278 if (!IsInlineEditEnabled())
280 aCaretBlinkTimer
.Stop();
283 void SmGraphicWindow::ShowCursor(bool bShow
)
284 // shows or hides the formula-cursor depending on 'bShow' is true or not
286 if (IsInlineEditEnabled())
289 bool bInvert
= bShow
!= IsCursorVisible();
292 InvertTracking(aCursorRect
, ShowTrackFlags::Small
| ShowTrackFlags::TrackWindow
);
294 SetIsCursorVisible(bShow
);
297 void SmGraphicWindow::ShowLine(bool bShow
)
299 if (!IsInlineEditEnabled())
302 bIsLineVisible
= bShow
;
305 void SmGraphicWindow::SetCursor(const SmNode
*pNode
)
307 if (IsInlineEditEnabled())
310 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
312 // get appropriate rectangle
313 Point
aOffset (pNode
->GetTopLeft() - pTree
->GetTopLeft()),
314 aTLPos (GetFormulaDrawPos() + aOffset
);
315 aTLPos
.AdjustX( -(pNode
->GetItalicLeftSpace()) );
316 Size
aSize (pNode
->GetItalicSize());
318 SetCursor(tools::Rectangle(aTLPos
, aSize
));
321 void SmGraphicWindow::SetCursor(const tools::Rectangle
&rRect
)
322 // sets cursor to new position (rectangle) 'rRect'.
323 // The old cursor will be removed, and the new one will be shown if
324 // that is activated in the ConfigItem
326 if (IsInlineEditEnabled())
329 SmModule
*pp
= SM_MOD();
331 if (IsCursorVisible())
332 ShowCursor(false); // clean up remainings of old cursor
334 if (pp
->GetConfig()->IsShowFormulaCursor())
335 ShowCursor(true); // draw new cursor
338 const SmNode
* SmGraphicWindow::SetCursorPos(sal_uInt16 nRow
, sal_uInt16 nCol
)
339 // looks for a VISIBLE node in the formula tree with its token at
340 // (or around) the position 'nRow', 'nCol' in the edit window
341 // (row and column numbering starts with 1 there!).
342 // If there is such a node the formula-cursor is set to cover that nodes
343 // rectangle. If not the formula-cursor will be hidden.
344 // In any case the search result is being returned.
346 if (IsInlineEditEnabled())
349 // find visible node with token at nRow, nCol
350 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree(),
353 pNode
= pTree
->FindTokenAt(nRow
, nCol
);
363 void SmGraphicWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
365 ApplyColorConfigValues(SM_MOD()->GetColorConfig());
367 SmDocShell
& rDoc
= *pViewShell
->GetDoc();
370 rDoc
.DrawFormula(rRenderContext
, aPoint
, true); //! modifies aPoint to be the topleft
371 //! corner of the formula
372 aFormulaDrawPos
= aPoint
;
373 if (IsInlineEditEnabled())
375 //Draw cursor if any...
376 if (pViewShell
->GetDoc()->HasCursor() && IsLineVisible())
377 pViewShell
->GetDoc()->GetCursor().Draw(rRenderContext
, aPoint
, IsCursorVisible());
381 SetIsCursorVisible(false); // (old) cursor must be drawn again
383 const SmEditWindow
* pEdit
= pViewShell
->GetEditWindow();
385 { // get new position for formula-cursor (for possible altered formula)
388 SmGetLeftSelectionPart(pEdit
->GetSelection(), nRow
, nCol
);
391 const SmNode
*pFound
= SetCursorPos(static_cast<sal_uInt16
>(nRow
), nCol
);
393 SmModule
*pp
= SM_MOD();
394 if (pFound
&& pp
->GetConfig()->IsShowFormulaCursor())
401 void SmGraphicWindow::SetTotalSize ()
403 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
404 const Size
aTmp( PixelToLogic( LogicToPixel( rDoc
.GetSize() )));
405 if ( aTmp
!= ScrollableWindow::GetTotalSize() )
406 ScrollableWindow::SetTotalSize( aTmp
);
409 void SmGraphicWindow::KeyInput(const KeyEvent
& rKEvt
)
411 if (!IsInlineEditEnabled()) {
412 if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
413 ScrollableWindow::KeyInput(rKEvt
);
417 SmCursor
& rCursor
= pViewShell
->GetDoc()->GetCursor();
418 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
419 if (eFunc
== KeyFuncType::COPY
)
421 else if (eFunc
== KeyFuncType::CUT
)
423 else if (eFunc
== KeyFuncType::PASTE
)
426 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
431 rCursor
.Move(this, MoveLeft
, !rKEvt
.GetKeyCode().IsShift());
435 rCursor
.Move(this, MoveRight
, !rKEvt
.GetKeyCode().IsShift());
439 rCursor
.Move(this, MoveUp
, !rKEvt
.GetKeyCode().IsShift());
443 rCursor
.Move(this, MoveDown
, !rKEvt
.GetKeyCode().IsShift());
447 if(!rKEvt
.GetKeyCode().IsShift())
452 if(!rCursor
.HasSelection()){
453 rCursor
.Move(this, MoveRight
, false);
454 if(rCursor
.HasComplexSelection()) break;
460 rCursor
.DeletePrev(this);
463 rCursor
.InsertElement(PlusElement
);
466 if(rKEvt
.GetKeyCode().IsShift())
467 rCursor
.InsertSubSup(RSUB
);
469 rCursor
.InsertElement(MinusElement
);
472 rCursor
.InsertElement(CDotElement
);
475 rCursor
.InsertFraction();
478 rCursor
.InsertElement(LessThanElement
);
481 rCursor
.InsertElement(GreaterThanElement
);
484 rCursor
.InsertElement(EqualElement
);
488 sal_Unicode code
= rKEvt
.GetCharCode();
489 SmBraceNode
* pBraceNode
= nullptr;
492 rCursor
.InsertElement(BlankElement
);
493 }else if(code
== '^') {
494 rCursor
.InsertSubSup(RSUP
);
495 }else if(code
== '(') {
496 rCursor
.InsertBrackets(SmBracketType::Round
);
497 }else if(code
== '[') {
498 rCursor
.InsertBrackets(SmBracketType::Square
);
499 }else if(code
== '{') {
500 rCursor
.InsertBrackets(SmBracketType::Curly
);
501 }else if(code
== '!') {
502 rCursor
.InsertElement(FactorialElement
);
503 }else if(code
== '%') {
504 rCursor
.InsertElement(PercentElement
);
505 }else if(code
== ')' && rCursor
.IsAtTailOfBracket(SmBracketType::Round
, &pBraceNode
)) {
506 rCursor
.MoveAfterBracket(pBraceNode
);
507 }else if(code
== ']' && rCursor
.IsAtTailOfBracket(SmBracketType::Square
, &pBraceNode
)) {
508 rCursor
.MoveAfterBracket(pBraceNode
);
509 }else if(code
== '}' && rCursor
.IsAtTailOfBracket(SmBracketType::Curly
, &pBraceNode
)) {
510 rCursor
.MoveAfterBracket(pBraceNode
);
513 rCursor
.InsertText(OUString(code
));
514 }else if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
515 ScrollableWindow::KeyInput(rKEvt
);
522 SetIsCursorVisible(true);
523 RepaintViewShellDoc();
527 void SmGraphicWindow::Command(const CommandEvent
& rCEvt
)
529 bool bCallBase
= true;
530 if ( !pViewShell
->GetViewFrame()->GetFrame().IsInPlace() )
532 switch ( rCEvt
.GetCommand() )
534 case CommandEventId::ContextMenu
:
536 GetParent()->ToTop();
538 if (rCEvt
.IsMouseEvent())
539 aPos
= rCEvt
.GetMousePosPixel();
541 // added for replaceability of context menus
542 SfxDispatcher::ExecutePopup( this, &aPos
);
548 case CommandEventId::Wheel
:
550 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
551 if ( pWData
&& CommandWheelMode::ZOOM
== pWData
->GetMode() )
553 sal_uInt16 nTmpZoom
= GetZoom();
554 if( 0 > pWData
->GetDelta() )
568 ScrollableWindow::Command (rCEvt
);
572 void SmGraphicWindow::SetZoom(sal_uInt16 Factor
)
574 nZoom
= std::min(std::max(Factor
, MINZOOM
), MAXZOOM
);
575 Fraction
aFraction (nZoom
, 100);
576 SetMapMode( MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
) );
578 SmViewShell
*pViewSh
= GetView();
581 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM
);
582 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER
);
588 void SmGraphicWindow::ZoomToFitInWindow()
590 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
592 // set defined mapmode before calling 'LogicToPixel' below
593 SetMapMode(MapMode(MapUnit::Map100thMM
));
595 Size
aSize (LogicToPixel(rDoc
.GetSize()));
596 Size
aWindowSize (GetSizePixel());
598 if (aSize
.Width() > 0 && aSize
.Height() > 0)
600 long nVal
= std::min ((85 * aWindowSize
.Width()) / aSize
.Width(),
601 (85 * aWindowSize
.Height()) / aSize
.Height());
602 SetZoom ( sal::static_int_cast
< sal_uInt16
>(nVal
) );
606 uno::Reference
< XAccessible
> SmGraphicWindow::CreateAccessible()
608 if (!mxAccessible
.is())
610 mxAccessible
= new SmGraphicAccessible( this );
612 return mxAccessible
.get();
615 /**************************************************************************/
618 SmGraphicController::SmGraphicController(SmGraphicWindow
&rSmGraphic
,
620 SfxBindings
&rBindings
) :
621 SfxControllerItem(nId_
, rBindings
),
627 void SmGraphicController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
629 rGraphic
.SetTotalSize();
630 rGraphic
.Invalidate();
631 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
635 /**************************************************************************/
638 SmEditController::SmEditController(SmEditWindow
&rSmEdit
,
640 SfxBindings
&rBindings
) :
641 SfxControllerItem(nId_
, rBindings
),
648 void SmEditController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
650 const SfxStringItem
*pItem
= dynamic_cast<const SfxStringItem
*>( pState
);
652 if ((pItem
!= nullptr) && (rEdit
.GetText() != pItem
->GetValue()))
653 rEdit
.SetText(pItem
->GetValue());
654 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
657 /**************************************************************************/
658 SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings
*pBindings_
, SfxChildWindow
*pChildWindow
,
659 vcl::Window
*pParent
) :
660 SfxDockingWindow(pBindings_
, pChildWindow
, pParent
, WB_MOVEABLE
|WB_CLOSEABLE
|WB_SIZEABLE
|WB_DOCKABLE
),
661 aEdit (VclPtr
<SmEditWindow
>::Create(*this)),
662 aController (*(aEdit
.get()), SID_TEXT
, *pBindings_
),
665 SetHelpId( HID_SMA_COMMAND_WIN
);
666 SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont
)));
667 SetText(SmResId(STR_CMDBOXWINDOW
));
671 aInitialFocusTimer
.SetInvokeHandler(LINK(this, SmCmdBoxWindow
, InitialFocusTimerHdl
));
672 aInitialFocusTimer
.SetTimeout(100);
675 SmCmdBoxWindow::~SmCmdBoxWindow ()
680 void SmCmdBoxWindow::dispose()
682 aInitialFocusTimer
.Stop();
684 aController
.dispose();
685 aEdit
.disposeAndClear();
686 SfxDockingWindow::dispose();
689 SmViewShell
* SmCmdBoxWindow::GetView()
691 SfxDispatcher
*pDispatcher
= GetBindings().GetDispatcher();
692 SfxViewShell
*pView
= pDispatcher
? pDispatcher
->GetFrame()->GetViewShell() : nullptr;
693 return dynamic_cast<SmViewShell
*>( pView
);
696 void SmCmdBoxWindow::Resize()
698 tools::Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
699 aRect
.AdjustLeft(CMD_BOX_PADDING
);
700 aRect
.AdjustTop(CMD_BOX_PADDING_TOP
);
701 aRect
.AdjustRight( -(CMD_BOX_PADDING
) );
702 aRect
.AdjustBottom( -(CMD_BOX_PADDING
) );
704 DecorationView
aView(this);
705 aRect
= aView
.DrawFrame(aRect
, DrawFrameStyle::In
, DrawFrameFlags::NoDraw
);
707 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
708 SfxDockingWindow::Resize();
712 void SmCmdBoxWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
& /*rRect*/)
714 tools::Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
715 aRect
.AdjustLeft(CMD_BOX_PADDING
);
716 aRect
.AdjustTop(CMD_BOX_PADDING_TOP
);
717 aRect
.AdjustRight( -(CMD_BOX_PADDING
) );
718 aRect
.AdjustBottom( -(CMD_BOX_PADDING
) );
720 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
722 DecorationView
aView(&rRenderContext
);
723 aView
.DrawFrame( aRect
, DrawFrameStyle::In
);
726 Size
SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign
)
730 case SfxChildAlignment::LEFT
:
731 case SfxChildAlignment::RIGHT
:
736 return SfxDockingWindow::CalcDockingSize(eAlign
);
739 SfxChildAlignment
SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual
,
740 SfxChildAlignment eWish
)
744 case SfxChildAlignment::TOP
:
745 case SfxChildAlignment::BOTTOM
:
746 case SfxChildAlignment::NOALIGNMENT
:
755 void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange
)
757 if (StateChangedType::InitShow
== nStateChange
)
759 Resize(); // avoid SmEditWindow not being painted correctly
761 // set initial position of window in floating mode
762 if (IsFloatingMode())
763 AdjustPosition(); //! don't change pos in docking-mode !
765 aInitialFocusTimer
.Start();
768 SfxDockingWindow::StateChanged( nStateChange
);
771 IMPL_LINK_NOARG( SmCmdBoxWindow
, InitialFocusTimerHdl
, Timer
*, void )
773 // We want to have the focus in the edit window once Math has been opened
774 // to allow for immediate typing.
775 // Problem: There is no proper way to do this
776 // Thus: this timer based solution has been implemented (see GrabFocus below)
778 // Follow-up problem (#i114910): grabbing the focus may bust the help system since
779 // it relies on getting the current frame which conflicts with grabbing the focus.
780 // Thus aside from the 'GrabFocus' call everything else is to get the
781 // help reliably working despite using 'GrabFocus'.
785 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( comphelper::getProcessComponentContext() );
789 bool bInPlace
= GetView()->GetViewFrame()->GetFrame().IsInPlace();
790 uno::Reference
< frame::XFrame
> xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
793 uno::Reference
< container::XChild
> xModel( GetView()->GetDoc()->GetModel(), uno::UNO_QUERY_THROW
);
794 uno::Reference
< frame::XModel
> xParent( xModel
->getParent(), uno::UNO_QUERY_THROW
);
795 uno::Reference
< frame::XController
> xParentCtrler( xParent
->getCurrentController() );
796 uno::Reference
< frame::XFramesSupplier
> xParentFrame( xParentCtrler
->getFrame(), uno::UNO_QUERY_THROW
);
797 xParentFrame
->setActiveFrame( xFrame
);
801 xDesktop
->setActiveFrame( xFrame
);
804 catch (uno::Exception
&)
806 SAL_WARN( "starmath", "failed to properly set initial focus to edit window" );
810 void SmCmdBoxWindow::AdjustPosition()
812 const tools::Rectangle
aRect( Point(), GetParent()->GetOutputSizePixel() );
813 Point
aTopLeft( Point( aRect
.Left(),
814 aRect
.Bottom() - GetSizePixel().Height() ) );
815 Point
aPos( GetParent()->OutputToScreenPixel( aTopLeft
) );
823 void SmCmdBoxWindow::ToggleFloatingMode()
825 SfxDockingWindow::ToggleFloatingMode();
827 if (GetFloatingWindow())
828 GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
831 void SmCmdBoxWindow::GetFocus()
837 SFX_IMPL_DOCKINGWINDOW_WITHID(SmCmdBoxWrapper
, SID_CMDBOXWINDOW
);
839 SmCmdBoxWrapper::SmCmdBoxWrapper(vcl::Window
*pParentWindow
, sal_uInt16 nId
,
840 SfxBindings
*pBindings
,
841 SfxChildWinInfo
*pInfo
) :
842 SfxChildWindow(pParentWindow
, nId
)
844 SetWindow(VclPtr
<SmCmdBoxWindow
>::Create(pBindings
, this, pParentWindow
));
846 // make window docked to the bottom initially (after first start)
847 SetAlignment(SfxChildAlignment::BOTTOM
);
848 static_cast<SfxDockingWindow
*>(GetWindow())->Initialize(pInfo
);
851 struct SmViewShell_Impl
853 std::unique_ptr
<sfx2::DocumentInserter
> pDocInserter
;
854 std::unique_ptr
<SfxRequest
> pRequest
;
855 SvtMiscOptions aOpts
;
859 SFX_IMPL_SUPERCLASS_INTERFACE(SmViewShell
, SfxViewShell
)
861 void SmViewShell::InitInterface_Impl()
863 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS
,
864 SfxVisibilityFlags::Standard
| SfxVisibilityFlags::FullScreen
| SfxVisibilityFlags::Server
,
865 ToolbarId::Math_Toolbox
);
866 //Dummy-Objectbar, to avoid quiver while activating
868 GetStaticInterface()->RegisterChildWindow(SmCmdBoxWrapper::GetChildWindowId());
869 GetStaticInterface()->RegisterChildWindow(SmElementsDockingWindowWrapper::GetChildWindowId());
870 GetStaticInterface()->RegisterChildWindow(SfxInfoBarContainerChild::GetChildWindowId());
873 SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell
, "Default")
875 SFX_VIEW_REGISTRATION(SmDocShell
);
878 void SmViewShell::InnerResizePixel(const Point
&rOfs
, const Size
&rSize
, bool)
880 Size aObjSize
= GetObjectShell()->GetVisArea().GetSize();
881 if ( aObjSize
.Width() > 0 && aObjSize
.Height() > 0 )
883 Size aProvidedSize
= GetWindow()->PixelToLogic(rSize
, MapMode(MapUnit::Map100thMM
));
884 SfxViewShell::SetZoomFactor( Fraction( aProvidedSize
.Width(), aObjSize
.Width() ),
885 Fraction( aProvidedSize
.Height(), aObjSize
.Height() ) );
888 SetBorderPixel( SvBorder() );
889 GetGraphicWindow().SetPosSizePixel(rOfs
, rSize
);
890 GetGraphicWindow().SetTotalSize();
893 void SmViewShell::OuterResizePixel(const Point
&rOfs
, const Size
&rSize
)
895 SmGraphicWindow
&rWin
= GetGraphicWindow();
896 rWin
.SetPosSizePixel(rOfs
, rSize
);
897 if (GetDoc()->IsPreview())
898 rWin
.ZoomToFitInWindow();
902 void SmViewShell::QueryObjAreaPixel( tools::Rectangle
& rRect
) const
904 rRect
.SetSize( GetGraphicWindow().GetSizePixel() );
907 void SmViewShell::SetZoomFactor( const Fraction
&rX
, const Fraction
&rY
)
909 const Fraction
&rFrac
= std::min(rX
, rY
);
910 GetGraphicWindow().SetZoom(sal::static_int_cast
<sal_uInt16
>(long(rFrac
* Fraction( 100, 1 ))));
912 //To avoid rounding errors base class regulates crooked values too
914 SfxViewShell::SetZoomFactor( rX
, rY
);
917 Size
SmViewShell::GetTextLineSize(OutputDevice
const & rDevice
, const OUString
& rLine
)
919 Size
aSize(rDevice
.GetTextWidth(rLine
), rDevice
.GetTextHeight());
920 const long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_char_width() * 8;
929 aSize
.setWidth( ((aSize
.Width() / nTabPos
) + 1) * nTabPos
);
931 const OUString aText
= rLine
.getToken(0, '\t', nPos
);
932 aSize
.AdjustWidth(rDevice
.GetTextWidth(aText
) );
940 Size
SmViewShell::GetTextSize(OutputDevice
const & rDevice
, const OUString
& rText
, long MaxWidth
)
950 OUString aLine
= rText
.getToken(0, '\n', nPos
);
951 aLine
= aLine
.replaceAll("\r", "");
953 aSize
= GetTextLineSize(rDevice
, aLine
);
955 if (aSize
.Width() > MaxWidth
)
960 sal_Int32 m
= aLine
.getLength();
963 for (sal_Int32 n
= 0; n
< nLen
; n
++)
965 sal_Unicode cLineChar
= aLine
[n
];
966 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
968 aText
= aLine
.copy(0, n
);
969 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
976 aText
= aLine
.copy(0, m
);
977 aLine
= aLine
.replaceAt(0, m
, "");
978 aSize
= GetTextLineSize(rDevice
, aText
);
979 aTextSize
.AdjustHeight(aSize
.Height() );
980 aTextSize
.setWidth( std::max(aTextSize
.Width(), std::min(aSize
.Width(), MaxWidth
)) );
982 aLine
= comphelper::string::stripStart(aLine
, ' ');
983 aLine
= comphelper::string::stripStart(aLine
, '\t');
984 aLine
= comphelper::string::stripStart(aLine
, ' ');
986 while (!aLine
.isEmpty());
990 aTextSize
.AdjustHeight(aSize
.Height() );
991 aTextSize
.setWidth( std::max(aTextSize
.Width(), aSize
.Width()) );
999 void SmViewShell::DrawTextLine(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rLine
)
1001 Point
aPoint(rPosition
);
1002 const long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_char_width() * 8;
1010 aPoint
.setX( ((aPoint
.X() / nTabPos
) + 1) * nTabPos
);
1012 OUString aText
= rLine
.getToken(0, '\t', nPos
);
1013 rDevice
.DrawText(aPoint
, aText
);
1014 aPoint
.AdjustX(rDevice
.GetTextWidth(aText
) );
1016 while ( nPos
>= 0 );
1019 rDevice
.DrawText(aPoint
, rLine
);
1023 void SmViewShell::DrawText(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rText
, sal_uInt16 MaxWidth
)
1025 if (rText
.isEmpty())
1028 Point
aPoint(rPosition
);
1034 OUString aLine
= rText
.getToken(0, '\n', nPos
);
1035 aLine
= aLine
.replaceAll("\r", "");
1036 aSize
= GetTextLineSize(rDevice
, aLine
);
1037 if (aSize
.Width() > MaxWidth
)
1042 sal_Int32 m
= aLine
.getLength();
1045 for (sal_Int32 n
= 0; n
< nLen
; n
++)
1047 sal_Unicode cLineChar
= aLine
[n
];
1048 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
1050 aText
= aLine
.copy(0, n
);
1051 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
1057 aText
= aLine
.copy(0, m
);
1058 aLine
= aLine
.replaceAt(0, m
, "");
1060 DrawTextLine(rDevice
, aPoint
, aText
);
1061 aPoint
.AdjustY(aSize
.Height() );
1063 aLine
= comphelper::string::stripStart(aLine
, ' ');
1064 aLine
= comphelper::string::stripStart(aLine
, '\t');
1065 aLine
= comphelper::string::stripStart(aLine
, ' ');
1067 while (GetTextLineSize(rDevice
, aLine
).Width() > MaxWidth
);
1069 // print the remaining text
1070 if (!aLine
.isEmpty())
1072 DrawTextLine(rDevice
, aPoint
, aLine
);
1073 aPoint
.AdjustY(aSize
.Height() );
1078 DrawTextLine(rDevice
, aPoint
, aLine
);
1079 aPoint
.AdjustY(aSize
.Height() );
1082 while ( nPos
>= 0 );
1085 void SmViewShell::Impl_Print(OutputDevice
&rOutDev
, const SmPrintUIOptions
&rPrintUIOptions
, tools::Rectangle aOutRect
)
1087 const bool bIsPrintTitle
= rPrintUIOptions
.getBoolValue( PRTUIOPT_TITLE_ROW
, true );
1088 const bool bIsPrintFrame
= rPrintUIOptions
.getBoolValue( PRTUIOPT_BORDER
, true );
1089 const bool bIsPrintFormulaText
= rPrintUIOptions
.getBoolValue( PRTUIOPT_FORMULA_TEXT
, true );
1090 SmPrintSize
ePrintSize( static_cast< SmPrintSize
>( rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_FORMAT
, PRINT_SIZE_NORMAL
) ));
1091 const sal_uInt16 nZoomFactor
= static_cast< sal_uInt16
>(rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_SCALE
, 100 ));
1094 rOutDev
.SetLineColor( COL_BLACK
);
1096 // output text on top
1099 Size
aSize600 (0, 600);
1100 Size
aSize650 (0, 650);
1101 vcl::Font
aFont(FAMILY_DONTKNOW
, aSize600
);
1103 aFont
.SetAlignment(ALIGN_TOP
);
1104 aFont
.SetWeight(WEIGHT_BOLD
);
1105 aFont
.SetFontSize(aSize650
);
1106 aFont
.SetColor( COL_BLACK
);
1107 rOutDev
.SetFont(aFont
);
1109 Size
aTitleSize (GetTextSize(rOutDev
, GetDoc()->GetTitle(), aOutRect
.GetWidth() - 200));
1111 aFont
.SetWeight(WEIGHT_NORMAL
);
1112 aFont
.SetFontSize(aSize600
);
1113 rOutDev
.SetFont(aFont
);
1115 Size
aDescSize (GetTextSize(rOutDev
, GetDoc()->GetComment(), aOutRect
.GetWidth() - 200));
1118 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.TopLeft(),
1119 Size(aOutRect
.GetWidth(), 100 + aTitleSize
.Height() + 200 + aDescSize
.Height() + 100)));
1120 aOutRect
.AdjustTop(200 );
1123 aFont
.SetWeight(WEIGHT_BOLD
);
1124 aFont
.SetFontSize(aSize650
);
1125 rOutDev
.SetFont(aFont
);
1126 Point
aPoint(aOutRect
.Left() + (aOutRect
.GetWidth() - aTitleSize
.Width()) / 2,
1128 DrawText(rOutDev
, aPoint
, GetDoc()->GetTitle(),
1129 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1130 aOutRect
.AdjustTop(aTitleSize
.Height() + 200 );
1132 // output description
1133 aFont
.SetWeight(WEIGHT_NORMAL
);
1134 aFont
.SetFontSize(aSize600
);
1135 rOutDev
.SetFont(aFont
);
1136 aPoint
.setX( aOutRect
.Left() + (aOutRect
.GetWidth() - aDescSize
.Width()) / 2 );
1137 aPoint
.setY( aOutRect
.Top() );
1138 DrawText(rOutDev
, aPoint
, GetDoc()->GetComment(),
1139 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1140 aOutRect
.AdjustTop(aDescSize
.Height() + 300 );
1143 // output text on bottom
1144 if (bIsPrintFormulaText
)
1146 vcl::Font
aFont(FAMILY_DONTKNOW
, Size(0, 600));
1147 aFont
.SetAlignment(ALIGN_TOP
);
1148 aFont
.SetColor( COL_BLACK
);
1151 rOutDev
.SetFont(aFont
);
1153 Size
aSize (GetTextSize(rOutDev
, GetDoc()->GetText(), aOutRect
.GetWidth() - 200));
1155 aOutRect
.AdjustBottom( -(aSize
.Height() + 600) );
1158 rOutDev
.DrawRect(tools::Rectangle(aOutRect
.BottomLeft(),
1159 Size(aOutRect
.GetWidth(), 200 + aSize
.Height() + 200)));
1161 Point
aPoint (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1162 aOutRect
.Bottom() + 300);
1163 DrawText(rOutDev
, aPoint
, GetDoc()->GetText(),
1164 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1165 aOutRect
.AdjustBottom( -200 );
1169 rOutDev
.DrawRect(aOutRect
);
1171 aOutRect
.AdjustTop(100 );
1172 aOutRect
.AdjustLeft(100 );
1173 aOutRect
.AdjustBottom( -100 );
1174 aOutRect
.AdjustRight( -100 );
1176 Size
aSize (GetDoc()->GetSize());
1178 MapMode OutputMapMode
;
1179 // PDF export should always use PRINT_SIZE_NORMAL ...
1180 if (!rPrintUIOptions
.getBoolValue( "IsPrinter" ) )
1181 ePrintSize
= PRINT_SIZE_NORMAL
;
1184 case PRINT_SIZE_NORMAL
:
1185 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1188 case PRINT_SIZE_SCALED
:
1189 if ((aSize
.Width() > 0) && (aSize
.Height() > 0))
1191 Size
OutputSize (rOutDev
.LogicToPixel(Size(aOutRect
.GetWidth(),
1192 aOutRect
.GetHeight()), MapMode(MapUnit::Map100thMM
)));
1193 Size
GraphicSize (rOutDev
.LogicToPixel(aSize
, MapMode(MapUnit::Map100thMM
)));
1194 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(long(Fraction(OutputSize
.Width() * 100L, GraphicSize
.Width())),
1195 long(Fraction(OutputSize
.Height() * 100L, GraphicSize
.Height()))));
1197 Fraction
aFraction (std::max(MINZOOM
, std::min(MAXZOOM
, nZ
)), 100);
1199 OutputMapMode
= MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
);
1202 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1205 case PRINT_SIZE_ZOOMED
:
1207 Fraction
aFraction( nZoomFactor
, 100 );
1209 OutputMapMode
= MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
);
1214 aSize
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aSize
, OutputMapMode
),
1215 MapMode(MapUnit::Map100thMM
));
1217 Point
aPos (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1218 aOutRect
.Top() + (aOutRect
.GetHeight() - aSize
.Height()) / 2);
1220 aPos
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aPos
, MapMode(MapUnit::Map100thMM
)),
1222 aOutRect
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aOutRect
, MapMode(MapUnit::Map100thMM
)),
1225 rOutDev
.SetMapMode(OutputMapMode
);
1226 rOutDev
.SetClipRegion(vcl::Region(aOutRect
));
1227 GetDoc()->DrawFormula(rOutDev
, aPos
);
1228 rOutDev
.SetClipRegion();
1233 SfxPrinter
* SmViewShell::GetPrinter(bool bCreate
)
1235 SmDocShell
* pDoc
= GetDoc();
1236 if (pDoc
->HasPrinter() || bCreate
)
1237 return pDoc
->GetPrinter();
1241 sal_uInt16
SmViewShell::SetPrinter(SfxPrinter
*pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
1243 SfxPrinter
*pOld
= GetDoc()->GetPrinter();
1244 if ( pOld
&& pOld
->IsPrinting() )
1245 return SFX_PRINTERROR_BUSY
;
1247 if ((nDiffFlags
& SfxPrinterChangeFlags::PRINTER
) == SfxPrinterChangeFlags::PRINTER
)
1248 GetDoc()->SetPrinter( pNewPrinter
);
1250 if ((nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
) == SfxPrinterChangeFlags::OPTIONS
)
1252 SmModule
*pp
= SM_MOD();
1253 pp
->GetConfig()->ItemSetToConfig(pNewPrinter
->GetOptions());
1258 bool SmViewShell::HasPrintOptionsPage() const
1263 VclPtr
<SfxTabPage
> SmViewShell::CreatePrintOptionsPage(weld::Container
* pPage
,
1264 const SfxItemSet
&rOptions
)
1266 return SmPrintOptionsTabPage::Create(pPage
, rOptions
);
1269 SmEditWindow
*SmViewShell::GetEditWindow()
1271 SmCmdBoxWrapper
* pWrapper
= static_cast<SmCmdBoxWrapper
*>(
1272 GetViewFrame()->GetChildWindow(SmCmdBoxWrapper::GetChildWindowId()));
1274 if (pWrapper
!= nullptr)
1276 SmEditWindow
& rEditWin
= pWrapper
->GetEditWindow();
1283 void SmViewShell::SetStatusText(const OUString
& rText
)
1285 maStatusText
= rText
;
1286 GetViewFrame()->GetBindings().Invalidate(SID_TEXTSTATUS
);
1289 void SmViewShell::ShowError(const SmErrorDesc
* pErrorDesc
)
1292 if (pErrorDesc
|| nullptr != (pErrorDesc
= GetDoc()->GetParser().GetError()) )
1294 SetStatusText( pErrorDesc
->m_aText
);
1295 GetEditWindow()->MarkError( Point( pErrorDesc
->m_pNode
->GetColumn(),
1296 pErrorDesc
->m_pNode
->GetRow()));
1300 void SmViewShell::NextError()
1303 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().NextError();
1306 ShowError( pErrorDesc
);
1309 void SmViewShell::PrevError()
1312 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().PrevError();
1315 ShowError( pErrorDesc
);
1318 void SmViewShell::Insert( SfxMedium
& rMedium
)
1320 SmDocShell
*pDoc
= GetDoc();
1323 uno::Reference
<embed::XStorage
> xStorage
= rMedium
.GetStorage();
1324 uno::Reference
<container::XNameAccess
> xNameAccess(xStorage
, uno::UNO_QUERY
);
1325 if (xNameAccess
.is() && xNameAccess
->getElementNames().getLength())
1327 if (xNameAccess
->hasByName("content.xml") || xNameAccess
->hasByName("Content.xml"))
1329 // is this a fabulous math package ?
1330 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1331 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1332 bRet
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1338 OUString aText
= pDoc
->GetText();
1339 SmEditWindow
*pEditWin
= GetEditWindow();
1341 pEditWin
->InsertText( aText
);
1344 SAL_WARN( "starmath", "EditWindow missing" );
1348 pDoc
->SetModified();
1350 SfxBindings
&rBnd
= GetViewFrame()->GetBindings();
1351 rBnd
.Invalidate(SID_GAPHIC_SM
);
1352 rBnd
.Invalidate(SID_TEXT
);
1356 void SmViewShell::InsertFrom(SfxMedium
&rMedium
)
1358 bool bSuccess
= false;
1359 SmDocShell
* pDoc
= GetDoc();
1360 SvStream
* pStream
= rMedium
.GetInStream();
1364 const OUString
& rFltName
= rMedium
.GetFilter()->GetFilterName();
1365 if ( rFltName
== MATHML_XML
)
1367 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1368 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1369 bSuccess
= ERRCODE_NONE
== aEquation
.Import(rMedium
);
1375 OUString aText
= pDoc
->GetText();
1376 SmEditWindow
*pEditWin
= GetEditWindow();
1378 pEditWin
->InsertText(aText
);
1380 SAL_WARN( "starmath", "EditWindow missing" );
1383 pDoc
->SetModified();
1385 SfxBindings
& rBnd
= GetViewFrame()->GetBindings();
1386 rBnd
.Invalidate(SID_GAPHIC_SM
);
1387 rBnd
.Invalidate(SID_TEXT
);
1391 void SmViewShell::Execute(SfxRequest
& rReq
)
1393 SmEditWindow
*pWin
= GetEditWindow();
1395 switch (rReq
.GetSlot())
1397 case SID_FORMULACURSOR
:
1399 SmModule
*pp
= SM_MOD();
1401 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1402 const SfxPoolItem
*pItem
;
1406 SfxItemState::SET
== pArgs
->GetItemState( SID_FORMULACURSOR
, false, &pItem
))
1407 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1409 bVal
= !pp
->GetConfig()->IsShowFormulaCursor();
1411 pp
->GetConfig()->SetShowFormulaCursor(bVal
);
1412 if (!IsInlineEditEnabled())
1413 GetGraphicWindow().ShowCursor(bVal
);
1419 GetDoc()->SetText( pWin
->GetText() );
1420 SetStatusText(OUString());
1421 ShowError( nullptr );
1422 GetDoc()->Repaint();
1426 case SID_ZOOM_OPTIMAL
:
1427 mpGraphic
->ZoomToFitInWindow();
1431 mpGraphic
->SetZoom(mpGraphic
->GetZoom() + 25);
1435 SAL_WARN_IF( mpGraphic
->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1436 mpGraphic
->SetZoom(mpGraphic
->GetZoom() - 25);
1439 case SID_COPYOBJECT
:
1441 //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
1442 Reference
< datatransfer::XTransferable
> xTrans( GetDoc()->GetModel(), uno::UNO_QUERY
);
1445 Reference
< lang::XUnoTunnel
> xTnnl( xTrans
, uno::UNO_QUERY
);
1448 TransferableHelper
* pTrans
= reinterpret_cast< TransferableHelper
* >(
1449 sal::static_int_cast
< sal_uIntPtr
>(
1450 xTnnl
->getSomething( TransferableHelper::getUnoTunnelId() )));
1452 pTrans
->CopyToClipboard(GetEditWindow());
1458 case SID_PASTEOBJECT
:
1460 TransferableDataHelper
aData( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1461 uno::Reference
< io::XInputStream
> xStrm
;
1462 SotClipboardFormatId nId
;
1463 if( aData
.GetTransferable().is() &&
1464 ( aData
.HasFormat( nId
= SotClipboardFormatId::EMBEDDED_OBJ
) ||
1465 (aData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
1466 aData
.HasFormat( nId
= SotClipboardFormatId::EMBED_SOURCE
))))
1467 xStrm
= aData
.GetInputStream(nId
, OUString());
1473 uno::Reference
< embed::XStorage
> xStorage
=
1474 ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
, ::comphelper::getProcessComponentContext() );
1475 SfxMedium
aMedium( xStorage
, OUString() );
1477 GetDoc()->UpdateText();
1479 catch (uno::Exception
&)
1481 SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1496 if (pWin
->IsAllSelected())
1498 GetViewFrame()->GetDispatcher()->ExecuteList(
1499 SID_COPYOBJECT
, SfxCallMode::RECORD
,
1500 { new SfxVoidItem(SID_COPYOBJECT
) });
1509 bool bCallExec
= nullptr == pWin
;
1512 TransferableDataHelper
aDataHelper(
1513 TransferableDataHelper::CreateFromSystemClipboard(
1516 if( aDataHelper
.GetTransferable().is() &&
1517 aDataHelper
.HasFormat( SotClipboardFormatId::STRING
))
1524 GetViewFrame()->GetDispatcher()->ExecuteList(
1525 SID_PASTEOBJECT
, SfxCallMode::RECORD
,
1526 { new SfxVoidItem(SID_PASTEOBJECT
) });
1541 case SID_INSERTCOMMANDTEXT
:
1543 const SfxStringItem
& rItem
= static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTCOMMANDTEXT
));
1545 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1547 pWin
->InsertText(rItem
.GetValue());
1549 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1551 GetDoc()->GetCursor().InsertCommandText(rItem
.GetValue());
1552 GetGraphicWindow().GrabFocus();
1558 case SID_INSERTSPECIAL
:
1560 const SfxStringItem
& rItem
=
1561 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTSPECIAL
));
1563 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1564 pWin
->InsertText(rItem
.GetValue());
1565 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1566 GetDoc()->GetCursor().InsertSpecial(rItem
.GetValue());
1570 case SID_IMPORT_FORMULA
:
1572 mpImpl
->pRequest
.reset(new SfxRequest( rReq
));
1573 mpImpl
->pDocInserter
.reset(new ::sfx2::DocumentInserter(pWin
? pWin
->GetFrameWeld() : nullptr,
1574 GetDoc()->GetFactory().GetFactoryName()));
1575 mpImpl
->pDocInserter
->StartExecuteModal( LINK( this, SmViewShell
, DialogClosedHdl
) );
1579 case SID_IMPORT_MATHML_CLIPBOARD
:
1581 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1582 uno::Reference
< io::XInputStream
> xStrm
;
1583 SotClipboardFormatId nId
= SOT_FORMAT_SYSTEM_START
; //dummy initialize to avoid warning
1584 if ( aDataHelper
.GetTransferable().is() )
1586 if (aDataHelper
.HasFormat(nId
= SotClipboardFormatId::MATHML
))
1588 xStrm
= aDataHelper
.GetInputStream(nId
, "");
1591 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1592 pClipboardMedium
->GetItemSet(); //generate initial itemset, not sure if necessary
1593 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1594 SfxFilter::GetFilterByName(MATHML_XML
);
1595 pClipboardMedium
->SetFilter(pMathFilter
);
1596 pClipboardMedium
->setStreamToLoadFrom(xStrm
, true /*bIsReadOnly*/);
1597 InsertFrom(*pClipboardMedium
);
1598 GetDoc()->UpdateText();
1603 if (aDataHelper
.HasFormat(nId
= SotClipboardFormatId::STRING
))
1605 // In case of FORMAT_STRING no stream exists, need to generate one
1606 ::rtl::OUString aString
;
1607 if (aDataHelper
.GetString( nId
, aString
))
1609 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1610 pClipboardMedium
->GetItemSet(); //generates initial itemset, not sure if necessary
1611 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1612 SfxFilter::GetFilterByName(MATHML_XML
);
1613 pClipboardMedium
->SetFilter(pMathFilter
);
1615 std::unique_ptr
<SvMemoryStream
> pStrm
;
1616 // The text to be imported might asserts encoding like 'encoding="utf-8"' but FORMAT_STRING is UTF-16.
1617 // Force encoding to UTF-16, if encoding exists.
1618 bool bForceUTF16
= false;
1619 sal_Int32 nPosL
= aString
.indexOf("encoding=\"");
1620 sal_Int32 nPosU
= -1;
1621 if ( nPosL
>= 0 && nPosL
+10 < aString
.getLength() )
1624 nPosU
= aString
.indexOf( '"',nPosL
);
1632 OUString aNewString
= aString
.replaceAt( nPosL
,nPosU
-nPosL
,"UTF-16");
1633 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aNewString
.getStr()), aNewString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1637 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aString
.getStr()), aString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1639 uno::Reference
<io::XInputStream
> xStrm2( new ::utl::OInputStreamWrapper(*pStrm
) );
1640 pClipboardMedium
->setStreamToLoadFrom(xStrm2
, true /*bIsReadOnly*/);
1641 InsertFrom(*pClipboardMedium
);
1642 GetDoc()->UpdateText();
1665 pWin
->SelNextMark();
1673 pWin
->SelPrevMark();
1678 case SID_TEXTSTATUS
:
1680 if (rReq
.GetArgs() != nullptr)
1682 const SfxStringItem
& rItem
=
1683 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_TEXTSTATUS
));
1685 SetStatusText(rItem
.GetValue());
1691 case SID_GETEDITTEXT
:
1693 if (!pWin
->GetText().isEmpty()) GetDoc()->SetText( pWin
->GetText() );
1698 if ( !GetViewFrame()->GetFrame().IsInPlace() )
1700 const SfxItemSet
*pSet
= rReq
.GetArgs();
1703 ZoomByItemSet(pSet
);
1707 SfxItemSet
aSet( SmDocShell::GetPool(), svl::Items
<SID_ATTR_ZOOM
, SID_ATTR_ZOOM
>{});
1708 aSet
.Put( SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1709 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1712 ScopedVclPtr
<AbstractSvxZoomDialog
> xDlg(pFact
->CreateSvxZoomDialog(GetViewFrame()->GetWindow().GetFrameWeld(), aSet
));
1714 xDlg
->SetLimits( MINZOOM
, MAXZOOM
);
1715 if (xDlg
->Execute() != RET_CANCEL
)
1716 ZoomByItemSet(xDlg
->GetOutputItemSet());
1723 case SID_ATTR_ZOOMSLIDER
:
1725 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1726 const SfxPoolItem
* pItem
;
1728 if ( pArgs
&& SfxItemState::SET
== pArgs
->GetItemState(SID_ATTR_ZOOMSLIDER
, true, &pItem
) )
1730 const sal_uInt16 nCurrentZoom
= static_cast<const SvxZoomSliderItem
*>(pItem
)->GetValue();
1731 mpGraphic
->SetZoom( nCurrentZoom
);
1736 case SID_ELEMENTSDOCKINGWINDOW
:
1738 GetViewFrame()->ToggleChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1739 GetViewFrame()->GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW
);
1745 case SID_UNICODE_NOTATION_TOGGLE
:
1747 EditEngine
* pEditEngine
= nullptr;
1749 pEditEngine
= pWin
->GetEditEngine();
1751 EditView
* pEditView
= nullptr;
1753 pEditView
= pEditEngine
->GetView();
1757 const OUString sInput
= pEditView
->GetSurroundingText();
1758 ESelection
aSel( pWin
->GetSelection() );
1760 if ( aSel
.nStartPos
> aSel
.nEndPos
)
1761 aSel
.nEndPos
= aSel
.nStartPos
;
1763 //calculate a valid end-position by reading logical characters
1764 sal_Int32 nUtf16Pos
=0;
1765 while( (nUtf16Pos
< sInput
.getLength()) && (nUtf16Pos
< aSel
.nEndPos
) )
1767 sInput
.iterateCodePoints(&nUtf16Pos
);
1768 if( nUtf16Pos
> aSel
.nEndPos
)
1769 aSel
.nEndPos
= nUtf16Pos
;
1772 ToggleUnicodeCodepoint aToggle
;
1773 while( nUtf16Pos
&& aToggle
.AllowMoreInput( sInput
[nUtf16Pos
-1]) )
1775 const OUString sReplacement
= aToggle
.ReplacementString();
1776 if( !sReplacement
.isEmpty() )
1778 pEditView
->SetSelection( aSel
);
1779 pEditEngine
->UndoActionStart(EDITUNDO_REPLACEALL
);
1780 aSel
.nStartPos
= aSel
.nEndPos
- aToggle
.StringToReplace().getLength();
1781 pWin
->SetSelection( aSel
);
1782 pEditView
->InsertText( sReplacement
, true );
1783 pEditEngine
->UndoActionEnd();
1790 case SID_SYMBOLS_CATALOGUE
:
1793 // get device used to retrieve the FontList
1794 SmDocShell
*pDoc
= GetDoc();
1795 OutputDevice
*pDev
= pDoc
->GetPrinter();
1796 if (!pDev
|| pDev
->GetDevFontCount() == 0)
1797 pDev
= &SM_MOD()->GetDefaultVirtualDev();
1798 SAL_WARN_IF( !pDev
, "starmath", "device for font list missing" );
1800 SmModule
*pp
= SM_MOD();
1801 SmSymbolDialog
aDialog(pWin
? pWin
->GetFrameWeld() : nullptr, pDev
, pp
->GetSymbolManager(), *this);
1810 void SmViewShell::GetState(SfxItemSet
&rSet
)
1812 SfxWhichIter
aIter(rSet
);
1814 SmEditWindow
*pEditWin
= GetEditWindow();
1815 for (sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
!= 0; nWh
= aIter
.NextWhich())
1822 if (! pEditWin
|| ! pEditWin
->IsSelected())
1823 rSet
.DisableItem(nWh
);
1829 TransferableDataHelper
aDataHelper(
1830 TransferableDataHelper::CreateFromSystemClipboard(
1833 mbPasteState
= aDataHelper
.GetTransferable().is() &&
1834 ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) ||
1835 aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) ||
1836 (aDataHelper
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
)
1837 && aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
)));
1840 rSet
.DisableItem( nWh
);
1844 rSet
.Put(SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1848 case SID_ZOOM_OPTIMAL
:
1849 if ( GetViewFrame()->GetFrame().IsInPlace() )
1850 rSet
.DisableItem( nWh
);
1853 case SID_ATTR_ZOOMSLIDER
:
1855 const sal_uInt16 nCurrentZoom
= mpGraphic
->GetZoom();
1856 SvxZoomSliderItem
aZoomSliderItem( nCurrentZoom
, MINZOOM
, MAXZOOM
);
1857 aZoomSliderItem
.AddSnappingPoint( 100 );
1858 rSet
.Put( aZoomSliderItem
);
1868 if (! pEditWin
|| pEditWin
->IsEmpty())
1869 rSet
.DisableItem(nWh
);
1872 case SID_TEXTSTATUS
:
1874 rSet
.Put(SfxStringItem(nWh
, maStatusText
));
1878 case SID_FORMULACURSOR
:
1880 SmModule
*pp
= SM_MOD();
1881 rSet
.Put(SfxBoolItem(nWh
, pp
->GetConfig()->IsShowFormulaCursor()));
1884 case SID_ELEMENTSDOCKINGWINDOW
:
1886 bool bState
= false;
1887 SfxChildWindow
*pChildWnd
= GetViewFrame()->
1888 GetChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1889 if (pChildWnd
&& pChildWnd
->GetWindow()->IsVisible())
1891 rSet
.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW
, bState
));
1898 SmViewShell::SmViewShell(SfxViewFrame
*pFrame_
, SfxViewShell
*)
1899 : SfxViewShell(pFrame_
, SfxViewShellFlags::HAS_PRINTOPTIONS
)
1900 , mpImpl(new SmViewShell_Impl
)
1901 , mpGraphic(VclPtr
<SmGraphicWindow
>::Create(this))
1902 , maGraphicController(*mpGraphic
.get(), SID_GAPHIC_SM
, pFrame_
->GetBindings())
1903 , mbPasteState(false)
1904 , mbInsertIntoEditWindow(false)
1906 SetStatusText(OUString());
1907 SetWindow(mpGraphic
.get());
1908 SfxShell::SetName("SmView");
1909 SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() );
1913 SmViewShell::~SmViewShell()
1915 //!! this view shell is not active anymore !!
1916 // Thus 'SmGetActiveView' will give a 0 pointer.
1917 // Thus we need to supply this view as argument
1918 SmEditWindow
*pEditWin
= GetEditWindow();
1920 pEditWin
->DeleteEditView();
1921 mpGraphic
.disposeAndClear();
1924 void SmViewShell::Deactivate( bool bIsMDIActivate
)
1926 SmEditWindow
*pEdit
= GetEditWindow();
1930 SfxViewShell::Deactivate( bIsMDIActivate
);
1933 void SmViewShell::Activate( bool bIsMDIActivate
)
1935 SfxViewShell::Activate( bIsMDIActivate
);
1937 SmEditWindow
*pEdit
= GetEditWindow();
1940 //! Since there is no way to be informed if a "drag and drop"
1941 //! event has taken place, we call SetText here in order to
1942 //! synchronize the GraphicWindow display with the text in the
1944 SmDocShell
*pDoc
= GetDoc();
1945 pDoc
->SetText( pDoc
->GetEditEngine().GetText() );
1947 if ( bIsMDIActivate
)
1952 IMPL_LINK( SmViewShell
, DialogClosedHdl
, sfx2::FileDialogHelper
*, _pFileDlg
, void )
1954 assert(_pFileDlg
&& "SmViewShell::DialogClosedHdl(): no file dialog");
1955 assert(mpImpl
->pDocInserter
&& "ScDocShell::DialogClosedHdl(): no document inserter");
1957 if ( ERRCODE_NONE
== _pFileDlg
->GetError() )
1959 SfxMedium
* pMedium
= mpImpl
->pDocInserter
->CreateMedium();
1961 if ( pMedium
!= nullptr )
1963 if ( pMedium
->IsStorage() )
1966 InsertFrom( *pMedium
);
1969 SmDocShell
* pDoc
= GetDoc();
1971 pDoc
->ArrangeFormula();
1973 // adjust window, repaint, increment ModifyCount,...
1974 GetViewFrame()->GetBindings().Invalidate(SID_GAPHIC_SM
);
1978 mpImpl
->pRequest
->SetReturnValue( SfxBoolItem( mpImpl
->pRequest
->GetSlot(), true ) );
1979 mpImpl
->pRequest
->Done();
1982 void SmViewShell::Notify( SfxBroadcaster
& , const SfxHint
& rHint
)
1984 switch( rHint
.GetId() )
1986 case SfxHintId::ModeChanged
:
1987 case SfxHintId::DocChanged
:
1988 GetViewFrame()->GetBindings().InvalidateAll(false);
1995 bool SmViewShell::IsInlineEditEnabled() const
1997 return mpImpl
->aOpts
.IsExperimentalMode();
2000 void SmViewShell::ZoomByItemSet(const SfxItemSet
*pSet
)
2003 const SvxZoomItem
&rZoom
= pSet
->Get(SID_ATTR_ZOOM
);
2004 switch( rZoom
.GetType() )
2006 case SvxZoomType::PERCENT
:
2007 mpGraphic
->SetZoom(sal::static_int_cast
<sal_uInt16
>(rZoom
.GetValue ()));
2010 case SvxZoomType::OPTIMAL
:
2011 mpGraphic
->ZoomToFitInWindow();
2014 case SvxZoomType::PAGEWIDTH
:
2015 case SvxZoomType::WHOLEPAGE
:
2017 const MapMode
aMap( MapUnit::Map100thMM
);
2018 SfxPrinter
*pPrinter
= GetPrinter( true );
2019 tools::Rectangle
OutputRect(Point(), pPrinter
->GetOutputSize());
2020 Size
OutputSize(pPrinter
->LogicToPixel(Size(OutputRect
.GetWidth(),
2021 OutputRect
.GetHeight()), aMap
));
2022 Size
GraphicSize(pPrinter
->LogicToPixel(GetDoc()->GetSize(), aMap
));
2023 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(long(Fraction(OutputSize
.Width() * 100L, GraphicSize
.Width())),
2024 long(Fraction(OutputSize
.Height() * 100L, GraphicSize
.Height()))));
2025 mpGraphic
->SetZoom (nZ
);
2033 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */