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/AccessibleEventObject.hpp>
22 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
23 #include <com/sun/star/accessibility/XAccessible.hpp>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/frame/Desktop.hpp>
26 #include <com/sun/star/frame/XFramesSupplier.hpp>
27 #include <com/sun/star/container/XChild.hpp>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/storagehelper.hxx>
31 #include <comphelper/string.hxx>
32 #include <i18nutil/unicode.hxx>
33 #include <sfx2/app.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <sfx2/docfile.hxx>
36 #include <sfx2/docfilt.hxx>
37 #include <sfx2/docinsert.hxx>
38 #include <sfx2/filedlghelper.hxx>
39 #include <sfx2/msg.hxx>
40 #include <sfx2/objface.hxx>
41 #include <sfx2/printer.hxx>
42 #include <sfx2/request.hxx>
43 #include <svl/eitem.hxx>
44 #include <svl/intitem.hxx>
45 #include <svl/itemset.hxx>
46 #include <svl/poolitem.hxx>
47 #include <svl/ptitem.hxx>
48 #include <svl/stritem.hxx>
49 #include <svtools/transfer.hxx>
50 #include <svtools/miscopt.hxx>
51 #include <svl/undo.hxx>
52 #include <svl/whiter.hxx>
53 #include <svx/dialogs.hrc>
54 #include <svx/zoomslideritem.hxx>
55 #include <editeng/editeng.hxx>
56 #include <editeng/editview.hxx>
57 #include <svx/svxdlg.hxx>
58 #include <sfx2/zoomitem.hxx>
59 #include <vcl/decoview.hxx>
60 #include <vcl/menu.hxx>
61 #include <vcl/msgbox.hxx>
62 #include <vcl/wrkwin.hxx>
63 #include <vcl/settings.hxx>
65 #include <unotools/streamwrap.hxx>
67 #include "unomodel.hxx"
69 #include "cfgitem.hxx"
71 #include "document.hxx"
72 #include "starmath.hrc"
73 #include "mathmlimport.hxx"
75 #include "accessibility.hxx"
76 #include "ElementsDockingWindow.hxx"
80 #define MINZOOM sal_uInt16(25)
81 #define MAXZOOM sal_uInt16(800)
83 // space around the edit window, in pixels
84 // fdo#69111: Increased border on the top so that the window is
85 // easier to tear off.
86 #define CMD_BOX_PADDING 4
87 #define CMD_BOX_PADDING_TOP 10
90 #include "smslots.hxx"
93 using namespace css::accessibility
;
94 using namespace css::uno
;
96 SmGraphicWindow::SmGraphicWindow(SmViewShell
* pShell
)
97 : ScrollableWindow(&pShell
->GetViewFrame()->GetWindow())
98 , pAccessible(nullptr)
103 // docking windows are usually hidden (often already done in the
104 // resource) and will be shown by the sfx framework.
107 const Fraction
aFraction(1, 1);
108 SetMapMode(MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
));
112 SetHelpId(HID_SMA_WIN_DOCUMENT
);
118 SmGraphicWindow::~SmGraphicWindow()
123 void SmGraphicWindow::dispose()
126 pAccessible
->ClearWin(); // make Accessible defunctional
127 // Note: memory for pAccessible will be freed when the reference
128 // xAccessible is released.
130 ScrollableWindow::dispose();
133 void SmGraphicWindow::StateChanged(StateChangedType eType
)
135 if (eType
== StateChangedType::InitShow
)
137 ScrollableWindow::StateChanged(eType
);
141 void SmGraphicWindow::ApplyColorConfigValues(const svtools::ColorConfig
&rColorCfg
)
143 // Note: SetTextColor not necessary since the nodes that
144 // get painted have the color information.
145 SetBackground(Color(static_cast<ColorData
>(rColorCfg
.GetColorValue(svtools::DOCCOLOR
).nColor
)));
149 void SmGraphicWindow::MouseButtonDown(const MouseEvent
& rMEvt
)
151 ScrollableWindow::MouseButtonDown(rMEvt
);
155 // set formula-cursor and selection of edit window according to the
156 // position clicked at
158 SAL_WARN_IF( rMEvt
.GetClicks() == 0, "starmath", "0 clicks" );
159 if ( rMEvt
.IsLeft() )
161 // get click position relativ to formula
162 Point
aPos (PixelToLogic(rMEvt
.GetPosPixel())
163 - GetFormulaDrawPos());
165 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
169 if (IsInlineEditEnabled()) {
170 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, !rMEvt
.IsShift());
173 const SmNode
*pNode
= nullptr;
174 // if it was clicked inside the formula then get the appropriate node
175 if (pTree
->OrientedDist(aPos
) <= 0)
176 pNode
= pTree
->FindRectClosestTo(aPos
);
179 { SmEditWindow
*pEdit
= pViewShell
->GetEditWindow();
182 const SmToken
aToken (pNode
->GetToken());
184 // set selection to the beginning of the token
185 ESelection
aSel (aToken
.nRow
- 1, aToken
.nCol
- 1);
187 if (rMEvt
.GetClicks() != 1 || aToken
.eType
== TPLACE
)
188 aSel
.nEndPos
= aSel
.nEndPos
+ sal::static_int_cast
< sal_uInt16
>(aToken
.aText
.getLength());
190 pEdit
->SetSelection(aSel
);
193 // allow for immediate editing and
194 //! implicitly synchronize the cursor position mark in this window
200 void SmGraphicWindow::MouseMove(const MouseEvent
&rMEvt
)
202 ScrollableWindow::MouseMove(rMEvt
);
204 if (rMEvt
.IsLeft() && IsInlineEditEnabled())
206 Point
aPos(PixelToLogic(rMEvt
.GetPosPixel()) - GetFormulaDrawPos());
207 pViewShell
->GetDoc()->GetCursor().MoveTo(this, aPos
, false);
210 SetIsCursorVisible(true);
212 RepaintViewShellDoc();
216 bool SmGraphicWindow::IsInlineEditEnabled() const
218 return pViewShell
->IsInlineEditEnabled();
221 void SmGraphicWindow::GetFocus()
223 if (!IsInlineEditEnabled())
225 if (pViewShell
->GetEditWindow())
226 pViewShell
->GetEditWindow()->Flush();
227 //Let view shell know what insertions should be done in visual editor
228 pViewShell
->SetInsertIntoEditWindow(false);
229 SetIsCursorVisible(true);
232 RepaintViewShellDoc();
235 void SmGraphicWindow::LoseFocus()
237 ScrollableWindow::LoseFocus();
238 if (xAccessible
.is())
240 uno::Any aOldValue
, aNewValue
;
241 aOldValue
<<= AccessibleStateType::FOCUSED
;
242 // aNewValue remains empty
243 pAccessible
->LaunchEvent( AccessibleEventId::STATE_CHANGED
,
244 aOldValue
, aNewValue
);
246 if (!IsInlineEditEnabled())
248 SetIsCursorVisible(false);
251 RepaintViewShellDoc();
254 void SmGraphicWindow::RepaintViewShellDoc()
256 SmDocShell
* pDoc
= pViewShell
->GetDoc();
261 IMPL_LINK_NOARG(SmGraphicWindow
, CaretBlinkTimerHdl
, Timer
*, void)
263 if (IsCursorVisible())
264 SetIsCursorVisible(false);
266 SetIsCursorVisible(true);
268 RepaintViewShellDoc();
271 void SmGraphicWindow::CaretBlinkInit()
273 aCaretBlinkTimer
.SetTimeoutHdl(LINK(this, SmGraphicWindow
, CaretBlinkTimerHdl
));
274 aCaretBlinkTimer
.SetTimeout( ScrollableWindow::GetSettings().GetStyleSettings().GetCursorBlinkTime() );
277 void SmGraphicWindow::CaretBlinkStart()
279 if (!IsInlineEditEnabled())
281 if (aCaretBlinkTimer
.GetTimeout() != STYLE_CURSOR_NOBLINKTIME
)
282 aCaretBlinkTimer
.Start();
285 void SmGraphicWindow::CaretBlinkStop()
287 if (!IsInlineEditEnabled())
289 aCaretBlinkTimer
.Stop();
292 void SmGraphicWindow::ShowCursor(bool bShow
)
293 // shows or hides the formula-cursor depending on 'bShow' is true or not
295 if (IsInlineEditEnabled())
298 bool bInvert
= bShow
!= IsCursorVisible();
301 InvertTracking(aCursorRect
, ShowTrackFlags::Small
| ShowTrackFlags::TrackWindow
);
303 SetIsCursorVisible(bShow
);
306 void SmGraphicWindow::ShowLine(bool bShow
)
308 if (!IsInlineEditEnabled())
311 bIsLineVisible
= bShow
;
314 void SmGraphicWindow::SetCursor(const SmNode
*pNode
)
316 if (IsInlineEditEnabled())
319 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree();
321 // get appropriate rectangle
322 Point
aOffset (pNode
->GetTopLeft() - pTree
->GetTopLeft()),
323 aTLPos (GetFormulaDrawPos() + aOffset
);
324 aTLPos
.X() -= pNode
->GetItalicLeftSpace();
325 Size
aSize (pNode
->GetItalicSize());
327 SetCursor(Rectangle(aTLPos
, aSize
));
330 void SmGraphicWindow::SetCursor(const Rectangle
&rRect
)
331 // sets cursor to new position (rectangle) 'rRect'.
332 // The old cursor will be removed, and the new one will be shown if
333 // that is activated in the ConfigItem
335 if (IsInlineEditEnabled())
338 SmModule
*pp
= SM_MOD();
340 if (IsCursorVisible())
341 ShowCursor(false); // clean up remainings of old cursor
343 if (pp
->GetConfig()->IsShowFormulaCursor())
344 ShowCursor(true); // draw new cursor
347 const SmNode
* SmGraphicWindow::SetCursorPos(sal_uInt16 nRow
, sal_uInt16 nCol
)
348 // looks for a VISIBLE node in the formula tree with its token at
349 // (or around) the position 'nRow', 'nCol' in the edit window
350 // (row and column numbering starts with 1 there!).
351 // If there is such a node the formula-cursor is set to cover that nodes
352 // rectangle. If not the formula-cursor will be hidden.
353 // In any case the search result is being returned.
355 if (IsInlineEditEnabled())
358 // find visible node with token at nRow, nCol
359 const SmNode
*pTree
= pViewShell
->GetDoc()->GetFormulaTree(),
362 pNode
= pTree
->FindTokenAt(nRow
, nCol
);
372 void SmGraphicWindow::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
&)
374 ApplyColorConfigValues(SM_MOD()->GetColorConfig());
376 SmDocShell
& rDoc
= *pViewShell
->GetDoc();
379 rDoc
.DrawFormula(rRenderContext
, aPoint
, true); //! modifies aPoint to be the topleft
380 //! corner of the formula
381 aFormulaDrawPos
= aPoint
;
382 if (IsInlineEditEnabled())
384 //Draw cursor if any...
385 if (pViewShell
->GetDoc()->HasCursor() && IsLineVisible())
386 pViewShell
->GetDoc()->GetCursor().Draw(rRenderContext
, aPoint
, IsCursorVisible());
390 SetIsCursorVisible(false); // (old) cursor must be drawn again
392 const SmEditWindow
* pEdit
= pViewShell
->GetEditWindow();
394 { // get new position for formula-cursor (for possible altered formula)
397 SmGetLeftSelectionPart(pEdit
->GetSelection(), nRow
, nCol
);
400 const SmNode
*pFound
= SetCursorPos(static_cast<sal_uInt16
>(nRow
), nCol
);
402 SmModule
*pp
= SM_MOD();
403 if (pFound
&& pp
->GetConfig()->IsShowFormulaCursor())
410 void SmGraphicWindow::SetTotalSize ()
412 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
413 const Size
aTmp( PixelToLogic( LogicToPixel( rDoc
.GetSize() )));
414 if ( aTmp
!= ScrollableWindow::GetTotalSize() )
415 ScrollableWindow::SetTotalSize( aTmp
);
418 void SmGraphicWindow::KeyInput(const KeyEvent
& rKEvt
)
420 if (!IsInlineEditEnabled()) {
421 if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
422 ScrollableWindow::KeyInput(rKEvt
);
426 SmCursor
& rCursor
= pViewShell
->GetDoc()->GetCursor();
427 KeyFuncType eFunc
= rKEvt
.GetKeyCode().GetFunction();
428 if (eFunc
== KeyFuncType::COPY
)
430 else if (eFunc
== KeyFuncType::CUT
)
432 else if (eFunc
== KeyFuncType::PASTE
)
435 sal_uInt16 nCode
= rKEvt
.GetKeyCode().GetCode();
440 rCursor
.Move(this, MoveLeft
, !rKEvt
.GetKeyCode().IsShift());
444 rCursor
.Move(this, MoveRight
, !rKEvt
.GetKeyCode().IsShift());
448 rCursor
.Move(this, MoveUp
, !rKEvt
.GetKeyCode().IsShift());
452 rCursor
.Move(this, MoveDown
, !rKEvt
.GetKeyCode().IsShift());
456 if(!rKEvt
.GetKeyCode().IsShift())
461 if(!rCursor
.HasSelection()){
462 rCursor
.Move(this, MoveRight
, false);
463 if(rCursor
.HasComplexSelection()) break;
469 rCursor
.DeletePrev(this);
472 rCursor
.InsertElement(PlusElement
);
475 if(rKEvt
.GetKeyCode().IsShift())
476 rCursor
.InsertSubSup(RSUB
);
478 rCursor
.InsertElement(MinusElement
);
481 rCursor
.InsertElement(CDotElement
);
484 rCursor
.InsertFraction();
487 rCursor
.InsertElement(LessThanElement
);
490 rCursor
.InsertElement(GreaterThanElement
);
493 rCursor
.InsertElement(EqualElement
);
497 sal_Unicode code
= rKEvt
.GetCharCode();
498 SmBraceNode
* pBraceNode
= nullptr;
501 rCursor
.InsertElement(BlankElement
);
502 }else if(code
== '^') {
503 rCursor
.InsertSubSup(RSUP
);
504 }else if(code
== '(') {
505 rCursor
.InsertBrackets(RoundBrackets
);
506 }else if(code
== '[') {
507 rCursor
.InsertBrackets(SquareBrackets
);
508 }else if(code
== '{') {
509 rCursor
.InsertBrackets(CurlyBrackets
);
510 }else if(code
== '!') {
511 rCursor
.InsertElement(FactorialElement
);
512 }else if(code
== '%') {
513 rCursor
.InsertElement(PercentElement
);
514 }else if(code
== ')' && rCursor
.IsAtTailOfBracket(RoundBrackets
, &pBraceNode
)) {
515 rCursor
.MoveAfterBracket(pBraceNode
);
516 }else if(code
== ']' && rCursor
.IsAtTailOfBracket(SquareBrackets
, &pBraceNode
)) {
517 rCursor
.MoveAfterBracket(pBraceNode
);
518 }else if(code
== '}' && rCursor
.IsAtTailOfBracket(CurlyBrackets
, &pBraceNode
)) {
519 rCursor
.MoveAfterBracket(pBraceNode
);
522 rCursor
.InsertText(OUString(code
));
523 }else if (! (GetView() && GetView()->KeyInput(rKEvt
)) )
524 ScrollableWindow::KeyInput(rKEvt
);
531 SetIsCursorVisible(true);
532 RepaintViewShellDoc();
536 void SmGraphicWindow::Command(const CommandEvent
& rCEvt
)
538 bool bCallBase
= true;
539 if ( !pViewShell
->GetViewFrame()->GetFrame().IsInPlace() )
541 switch ( rCEvt
.GetCommand() )
543 case CommandEventId::ContextMenu
:
545 GetParent()->ToTop();
547 if (rCEvt
.IsMouseEvent())
548 aPos
= rCEvt
.GetMousePosPixel();
550 // added for replaceability of context menus
551 SfxDispatcher::ExecutePopup( this, &aPos
);
557 case CommandEventId::Wheel
:
559 const CommandWheelData
* pWData
= rCEvt
.GetWheelData();
560 if ( pWData
&& CommandWheelMode::ZOOM
== pWData
->GetMode() )
562 sal_uInt16 nTmpZoom
= GetZoom();
563 if( 0 > pWData
->GetDelta() )
577 ScrollableWindow::Command (rCEvt
);
581 void SmGraphicWindow::SetZoom(sal_uInt16 Factor
)
583 nZoom
= std::min(std::max(Factor
, MINZOOM
), MAXZOOM
);
584 Fraction
aFraction (nZoom
, 100);
585 SetMapMode( MapMode(MapUnit::Map100thMM
, Point(), aFraction
, aFraction
) );
587 SmViewShell
*pViewSh
= GetView();
590 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM
);
591 pViewSh
->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER
);
597 void SmGraphicWindow::ZoomToFitInWindow()
599 SmDocShell
&rDoc
= *pViewShell
->GetDoc();
601 // set defined mapmode before calling 'LogicToPixel' below
602 SetMapMode(MapMode(MapUnit::Map100thMM
));
604 Size
aSize (LogicToPixel(rDoc
.GetSize()));
605 Size
aWindowSize (GetSizePixel());
607 if (aSize
.Width() > 0 && aSize
.Height() > 0)
609 long nVal
= std::min ((85 * aWindowSize
.Width()) / aSize
.Width(),
610 (85 * aWindowSize
.Height()) / aSize
.Height());
611 SetZoom ( sal::static_int_cast
< sal_uInt16
>(nVal
) );
615 uno::Reference
< XAccessible
> SmGraphicWindow::CreateAccessible()
619 pAccessible
= new SmGraphicAccessible( this );
620 xAccessible
= pAccessible
;
625 /**************************************************************************/
628 SmGraphicController::SmGraphicController(SmGraphicWindow
&rSmGraphic
,
630 SfxBindings
&rBindings
) :
631 SfxControllerItem(nId_
, rBindings
),
637 void SmGraphicController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
639 rGraphic
.SetTotalSize();
640 rGraphic
.Invalidate();
641 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
645 /**************************************************************************/
648 SmEditController::SmEditController(SmEditWindow
&rSmEdit
,
650 SfxBindings
&rBindings
) :
651 SfxControllerItem(nId_
, rBindings
),
658 void SmEditController::StateChanged(sal_uInt16 nSID
, SfxItemState eState
, const SfxPoolItem
* pState
)
660 const SfxStringItem
*pItem
= dynamic_cast<const SfxStringItem
*>( pState
);
662 if ((pItem
!= nullptr) && (rEdit
.GetText() != OUString(pItem
->GetValue())))
663 rEdit
.SetText(pItem
->GetValue());
664 SfxControllerItem::StateChanged (nSID
, eState
, pState
);
667 /**************************************************************************/
668 SmCmdBoxWindow::SmCmdBoxWindow(SfxBindings
*pBindings_
, SfxChildWindow
*pChildWindow
,
669 vcl::Window
*pParent
) :
670 SfxDockingWindow(pBindings_
, pChildWindow
, pParent
, WB_MOVEABLE
|WB_CLOSEABLE
|WB_SIZEABLE
|WB_DOCKABLE
),
671 aEdit (VclPtr
<SmEditWindow
>::Create(*this)),
672 aController (*(aEdit
.get()), SID_TEXT
, *pBindings_
),
675 SetHelpId( HID_SMA_COMMAND_WIN
);
676 SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont
)));
677 SetText(SM_RESSTR(STR_CMDBOXWINDOW
));
681 aInitialFocusTimer
.SetTimeoutHdl(LINK(this, SmCmdBoxWindow
, InitialFocusTimerHdl
));
682 aInitialFocusTimer
.SetTimeout(100);
685 SmCmdBoxWindow::~SmCmdBoxWindow ()
690 void SmCmdBoxWindow::dispose()
692 aInitialFocusTimer
.Stop();
694 aController
.dispose();
695 aEdit
.disposeAndClear();
696 SfxDockingWindow::dispose();
699 SmViewShell
* SmCmdBoxWindow::GetView()
701 SfxDispatcher
*pDispatcher
= GetBindings().GetDispatcher();
702 SfxViewShell
*pView
= pDispatcher
? pDispatcher
->GetFrame()->GetViewShell() : nullptr;
703 return dynamic_cast<SmViewShell
*>( pView
);
706 void SmCmdBoxWindow::Resize()
708 Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
709 aRect
.Left() += CMD_BOX_PADDING
;
710 aRect
.Top() += CMD_BOX_PADDING_TOP
;
711 aRect
.Right() -= CMD_BOX_PADDING
;
712 aRect
.Bottom() -= CMD_BOX_PADDING
;
714 DecorationView
aView(this);
715 aRect
= aView
.DrawFrame(aRect
, DrawFrameStyle::In
, DrawFrameFlags::NoDraw
);
717 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
718 SfxDockingWindow::Resize();
722 void SmCmdBoxWindow::Paint(vcl::RenderContext
& rRenderContext
, const Rectangle
& /*rRect*/)
724 Rectangle
aRect(Point(0, 0), GetOutputSizePixel());
725 aRect
.Left() += CMD_BOX_PADDING
;
726 aRect
.Top() += CMD_BOX_PADDING_TOP
;
727 aRect
.Right() -= CMD_BOX_PADDING
;
728 aRect
.Bottom() -= CMD_BOX_PADDING
;
730 aEdit
->SetPosSizePixel(aRect
.TopLeft(), aRect
.GetSize());
732 DecorationView
aView(&rRenderContext
);
733 aView
.DrawFrame( aRect
, DrawFrameStyle::In
);
736 Size
SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign
)
740 case SfxChildAlignment::LEFT
:
741 case SfxChildAlignment::RIGHT
:
746 return SfxDockingWindow::CalcDockingSize(eAlign
);
749 SfxChildAlignment
SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual
,
750 SfxChildAlignment eWish
)
754 case SfxChildAlignment::TOP
:
755 case SfxChildAlignment::BOTTOM
:
756 case SfxChildAlignment::NOALIGNMENT
:
765 void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange
)
767 if (StateChangedType::InitShow
== nStateChange
)
769 Resize(); // avoid SmEditWindow not being painted correctly
771 // set initial position of window in floating mode
772 if (IsFloatingMode())
773 AdjustPosition(); //! don't change pos in docking-mode !
775 aInitialFocusTimer
.Start();
778 SfxDockingWindow::StateChanged( nStateChange
);
781 IMPL_LINK_NOARG( SmCmdBoxWindow
, InitialFocusTimerHdl
, Timer
*, void )
783 // We want to have the focus in the edit window once Math has been opened
784 // to allow for immediate typing.
785 // Problem: There is no proper way to do this
786 // Thus: this timer based solution has been implemented (see GrabFocus below)
788 // Follow-up problem (#i114910): grabbing the focus may bust the help system since
789 // it relies on getting the current frame which conflicts with grabbing the focus.
790 // Thus aside from the 'GrabFocus' call everything else is to get the
791 // help reliably working despite using 'GrabFocus'.
795 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( comphelper::getProcessComponentContext() );
799 bool bInPlace
= GetView()->GetViewFrame()->GetFrame().IsInPlace();
800 uno::Reference
< frame::XFrame
> xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
803 uno::Reference
< container::XChild
> xModel( GetView()->GetDoc()->GetModel(), uno::UNO_QUERY_THROW
);
804 uno::Reference
< frame::XModel
> xParent( xModel
->getParent(), uno::UNO_QUERY_THROW
);
805 uno::Reference
< frame::XController
> xParentCtrler( xParent
->getCurrentController() );
806 uno::Reference
< frame::XFramesSupplier
> xParentFrame( xParentCtrler
->getFrame(), uno::UNO_QUERY_THROW
);
807 xParentFrame
->setActiveFrame( xFrame
);
811 xDesktop
->setActiveFrame( xFrame
);
814 catch (uno::Exception
&)
816 SAL_WARN( "starmath", "failed to properly set initial focus to edit window" );
820 void SmCmdBoxWindow::AdjustPosition()
823 const Rectangle
aRect( aPt
, GetParent()->GetOutputSizePixel() );
824 Point
aTopLeft( Point( aRect
.Left(),
825 aRect
.Bottom() - GetSizePixel().Height() ) );
826 Point
aPos( GetParent()->OutputToScreenPixel( aTopLeft
) );
834 void SmCmdBoxWindow::ToggleFloatingMode()
836 SfxDockingWindow::ToggleFloatingMode();
838 if (GetFloatingWindow())
839 GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
842 void SmCmdBoxWindow::GetFocus()
848 SFX_IMPL_DOCKINGWINDOW_WITHID(SmCmdBoxWrapper
, SID_CMDBOXWINDOW
);
850 SmCmdBoxWrapper::SmCmdBoxWrapper(vcl::Window
*pParentWindow
, sal_uInt16 nId
,
851 SfxBindings
*pBindings
,
852 SfxChildWinInfo
*pInfo
) :
853 SfxChildWindow(pParentWindow
, nId
)
855 SetWindow(VclPtr
<SmCmdBoxWindow
>::Create(pBindings
, this, pParentWindow
));
857 // make window docked to the bottom initially (after first start)
858 SetAlignment(SfxChildAlignment::BOTTOM
);
859 static_cast<SfxDockingWindow
*>(GetWindow())->Initialize(pInfo
);
862 struct SmViewShell_Impl
864 std::unique_ptr
<sfx2::DocumentInserter
> pDocInserter
;
865 std::unique_ptr
<SfxRequest
> pRequest
;
866 SvtMiscOptions aOpts
;
870 SFX_IMPL_SUPERCLASS_INTERFACE(SmViewShell
, SfxViewShell
)
872 void SmViewShell::InitInterface_Impl()
874 GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_TOOLS
,
875 SfxVisibilityFlags::Standard
| SfxVisibilityFlags::FullScreen
| SfxVisibilityFlags::Server
,
877 //Dummy-Objectbar, to avoid quiver while activating
879 GetStaticInterface()->RegisterChildWindow(SmCmdBoxWrapper::GetChildWindowId());
880 GetStaticInterface()->RegisterChildWindow(SmElementsDockingWindowWrapper::GetChildWindowId());
883 SFX_IMPL_NAMED_VIEWFACTORY(SmViewShell
, "Default")
885 SFX_VIEW_REGISTRATION(SmDocShell
);
888 void SmViewShell::AdjustPosSizePixel(const Point
&rPos
, const Size
&rSize
)
890 mpGraphic
->SetPosSizePixel(rPos
, rSize
);
893 void SmViewShell::InnerResizePixel(const Point
&rOfs
, const Size
&rSize
, bool)
895 Size aObjSize
= GetObjectShell()->GetVisArea().GetSize();
896 if ( aObjSize
.Width() > 0 && aObjSize
.Height() > 0 )
898 Size aProvidedSize
= GetWindow()->PixelToLogic( rSize
, MapUnit::Map100thMM
);
899 SfxViewShell::SetZoomFactor( Fraction( aProvidedSize
.Width(), aObjSize
.Width() ),
900 Fraction( aProvidedSize
.Height(), aObjSize
.Height() ) );
903 SetBorderPixel( SvBorder() );
904 GetGraphicWindow().SetPosSizePixel(rOfs
, rSize
);
905 GetGraphicWindow().SetTotalSize();
908 void SmViewShell::OuterResizePixel(const Point
&rOfs
, const Size
&rSize
)
910 SmGraphicWindow
&rWin
= GetGraphicWindow();
911 rWin
.SetPosSizePixel(rOfs
, rSize
);
912 if (GetDoc()->IsPreview())
913 rWin
.ZoomToFitInWindow();
917 void SmViewShell::QueryObjAreaPixel( Rectangle
& rRect
) const
919 rRect
.SetSize( GetGraphicWindow().GetSizePixel() );
922 void SmViewShell::SetZoomFactor( const Fraction
&rX
, const Fraction
&rY
)
924 const Fraction
&rFrac
= rX
< rY
? rX
: rY
;
925 GetGraphicWindow().SetZoom(sal::static_int_cast
<sal_uInt16
>(long(rFrac
* Fraction( 100, 1 ))));
927 //To avoid rounding errors base class regulates crooked values too
929 SfxViewShell::SetZoomFactor( rX
, rY
);
932 Size
SmViewShell::GetTextLineSize(OutputDevice
& rDevice
, const OUString
& rLine
)
934 Size
aSize(rDevice
.GetTextWidth(rLine
), rDevice
.GetTextHeight());
935 const long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_char_width() * 8;
944 aSize
.Width() = ((aSize
.Width() / nTabPos
) + 1) * nTabPos
;
946 const OUString aText
= rLine
.getToken(0, '\t', nPos
);
947 aSize
.Width() += rDevice
.GetTextWidth(aText
);
955 Size
SmViewShell::GetTextSize(OutputDevice
& rDevice
, const OUString
& rText
, long MaxWidth
)
965 OUString aLine
= rText
.getToken(0, '\n', nPos
);
966 aLine
= aLine
.replaceAll("\r", "");
968 aSize
= GetTextLineSize(rDevice
, aLine
);
970 if (aSize
.Width() > MaxWidth
)
975 sal_Int32 m
= aLine
.getLength();
978 for (sal_Int32 n
= 0; n
< nLen
; n
++)
980 sal_Unicode cLineChar
= aLine
[n
];
981 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
983 aText
= aLine
.copy(0, n
);
984 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
991 aText
= aLine
.copy(0, m
);
992 aLine
= aLine
.replaceAt(0, m
, "");
993 aSize
= GetTextLineSize(rDevice
, aText
);
994 aTextSize
.Height() += aSize
.Height();
995 aTextSize
.Width() = std::max(aTextSize
.Width(), std::min(aSize
.Width(), MaxWidth
));
997 aLine
= comphelper::string::stripStart(aLine
, ' ');
998 aLine
= comphelper::string::stripStart(aLine
, '\t');
999 aLine
= comphelper::string::stripStart(aLine
, ' ');
1001 while (!aLine
.isEmpty());
1005 aTextSize
.Height() += aSize
.Height();
1006 aTextSize
.Width() = std::max(aTextSize
.Width(), aSize
.Width());
1014 void SmViewShell::DrawTextLine(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rLine
)
1016 Point
aPoint(rPosition
);
1017 const long nTabPos
= rLine
.isEmpty() ? 0 : rDevice
.approximate_char_width() * 8;
1025 aPoint
.X() = ((aPoint
.X() / nTabPos
) + 1) * nTabPos
;
1027 OUString aText
= rLine
.getToken(0, '\t', nPos
);
1028 rDevice
.DrawText(aPoint
, aText
);
1029 aPoint
.X() += rDevice
.GetTextWidth(aText
);
1031 while ( nPos
>= 0 );
1034 rDevice
.DrawText(aPoint
, rLine
);
1038 void SmViewShell::DrawText(OutputDevice
& rDevice
, const Point
& rPosition
, const OUString
& rText
, sal_uInt16 MaxWidth
)
1040 if (rText
.isEmpty())
1043 Point
aPoint(rPosition
);
1049 OUString aLine
= rText
.getToken(0, '\n', nPos
);
1050 aLine
= aLine
.replaceAll("\r", "");
1051 aSize
= GetTextLineSize(rDevice
, aLine
);
1052 if (aSize
.Width() > MaxWidth
)
1057 sal_Int32 m
= aLine
.getLength();
1060 for (sal_Int32 n
= 0; n
< nLen
; n
++)
1062 sal_Unicode cLineChar
= aLine
[n
];
1063 if ((cLineChar
== ' ') || (cLineChar
== '\t'))
1065 aText
= aLine
.copy(0, n
);
1066 if (GetTextLineSize(rDevice
, aText
).Width() < MaxWidth
)
1072 aText
= aLine
.copy(0, m
);
1073 aLine
= aLine
.replaceAt(0, m
, "");
1075 DrawTextLine(rDevice
, aPoint
, aText
);
1076 aPoint
.Y() += aSize
.Height();
1078 aLine
= comphelper::string::stripStart(aLine
, ' ');
1079 aLine
= comphelper::string::stripStart(aLine
, '\t');
1080 aLine
= comphelper::string::stripStart(aLine
, ' ');
1082 while (GetTextLineSize(rDevice
, aLine
).Width() > MaxWidth
);
1084 // print the remaining text
1085 if (!aLine
.isEmpty())
1087 DrawTextLine(rDevice
, aPoint
, aLine
);
1088 aPoint
.Y() += aSize
.Height();
1093 DrawTextLine(rDevice
, aPoint
, aLine
);
1094 aPoint
.Y() += aSize
.Height();
1097 while ( nPos
>= 0 );
1100 void SmViewShell::Impl_Print(OutputDevice
&rOutDev
, const SmPrintUIOptions
&rPrintUIOptions
, Rectangle aOutRect
, Point aZeroPoint
)
1102 const bool bIsPrintTitle
= rPrintUIOptions
.getBoolValue( PRTUIOPT_TITLE_ROW
, true );
1103 const bool bIsPrintFrame
= rPrintUIOptions
.getBoolValue( PRTUIOPT_BORDER
, true );
1104 const bool bIsPrintFormulaText
= rPrintUIOptions
.getBoolValue( PRTUIOPT_FORMULA_TEXT
, true );
1105 SmPrintSize
ePrintSize( static_cast< SmPrintSize
>( rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_FORMAT
, PRINT_SIZE_NORMAL
) ));
1106 const sal_uInt16 nZoomFactor
= static_cast< sal_uInt16
>(rPrintUIOptions
.getIntValue( PRTUIOPT_PRINT_SCALE
, 100 ));
1109 rOutDev
.SetLineColor( Color(COL_BLACK
) );
1111 // output text on top
1114 Size
aSize600 (0, 600);
1115 Size
aSize650 (0, 650);
1116 vcl::Font
aFont(FAMILY_DONTKNOW
, aSize600
);
1118 aFont
.SetAlignment(ALIGN_TOP
);
1119 aFont
.SetWeight(WEIGHT_BOLD
);
1120 aFont
.SetFontSize(aSize650
);
1121 aFont
.SetColor( Color(COL_BLACK
) );
1122 rOutDev
.SetFont(aFont
);
1124 Size
aTitleSize (GetTextSize(rOutDev
, GetDoc()->GetTitle(), aOutRect
.GetWidth() - 200));
1126 aFont
.SetWeight(WEIGHT_NORMAL
);
1127 aFont
.SetFontSize(aSize600
);
1128 rOutDev
.SetFont(aFont
);
1130 Size
aDescSize (GetTextSize(rOutDev
, GetDoc()->GetComment(), aOutRect
.GetWidth() - 200));
1133 rOutDev
.DrawRect(Rectangle(aOutRect
.TopLeft(),
1134 Size(aOutRect
.GetWidth(), 100 + aTitleSize
.Height() + 200 + aDescSize
.Height() + 100)));
1135 aOutRect
.Top() += 200;
1138 aFont
.SetWeight(WEIGHT_BOLD
);
1139 aFont
.SetFontSize(aSize650
);
1140 rOutDev
.SetFont(aFont
);
1141 Point
aPoint(aOutRect
.Left() + (aOutRect
.GetWidth() - aTitleSize
.Width()) / 2,
1143 DrawText(rOutDev
, aPoint
, GetDoc()->GetTitle(),
1144 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1145 aOutRect
.Top() += aTitleSize
.Height() + 200;
1147 // output description
1148 aFont
.SetWeight(WEIGHT_NORMAL
);
1149 aFont
.SetFontSize(aSize600
);
1150 rOutDev
.SetFont(aFont
);
1151 aPoint
.X() = aOutRect
.Left() + (aOutRect
.GetWidth() - aDescSize
.Width()) / 2;
1152 aPoint
.Y() = aOutRect
.Top();
1153 DrawText(rOutDev
, aPoint
, GetDoc()->GetComment(),
1154 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1155 aOutRect
.Top() += aDescSize
.Height() + 300;
1158 // output text on bottom
1159 if (bIsPrintFormulaText
)
1161 vcl::Font
aFont(FAMILY_DONTKNOW
, Size(0, 600));
1162 aFont
.SetAlignment(ALIGN_TOP
);
1163 aFont
.SetColor( Color(COL_BLACK
) );
1166 rOutDev
.SetFont(aFont
);
1168 Size
aSize (GetTextSize(rOutDev
, GetDoc()->GetText(), aOutRect
.GetWidth() - 200));
1170 aOutRect
.Bottom() -= aSize
.Height() + 600;
1173 rOutDev
.DrawRect(Rectangle(aOutRect
.BottomLeft(),
1174 Size(aOutRect
.GetWidth(), 200 + aSize
.Height() + 200)));
1176 Point
aPoint (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1177 aOutRect
.Bottom() + 300);
1178 DrawText(rOutDev
, aPoint
, GetDoc()->GetText(),
1179 sal::static_int_cast
< sal_uInt16
>(aOutRect
.GetWidth() - 200));
1180 aOutRect
.Bottom() -= 200;
1184 rOutDev
.DrawRect(aOutRect
);
1186 aOutRect
.Top() += 100;
1187 aOutRect
.Left() += 100;
1188 aOutRect
.Bottom() -= 100;
1189 aOutRect
.Right() -= 100;
1191 Size
aSize (GetDoc()->GetSize());
1193 MapMode OutputMapMode
;
1194 // PDF export should always use PRINT_SIZE_NORMAL ...
1195 if (!rPrintUIOptions
.getBoolValue( "IsPrinter" ) )
1196 ePrintSize
= PRINT_SIZE_NORMAL
;
1199 case PRINT_SIZE_NORMAL
:
1200 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1203 case PRINT_SIZE_SCALED
:
1204 if ((aSize
.Width() > 0) && (aSize
.Height() > 0))
1206 Size
OutputSize (rOutDev
.LogicToPixel(Size(aOutRect
.GetWidth(),
1207 aOutRect
.GetHeight()), MapMode(MapUnit::Map100thMM
)));
1208 Size
GraphicSize (rOutDev
.LogicToPixel(aSize
, MapMode(MapUnit::Map100thMM
)));
1209 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(long(Fraction(OutputSize
.Width() * 100L, GraphicSize
.Width())),
1210 long(Fraction(OutputSize
.Height() * 100L, GraphicSize
.Height()))));
1212 Fraction
aFraction (std::max(MINZOOM
, std::min(MAXZOOM
, nZ
)), 100);
1214 OutputMapMode
= MapMode(MapUnit::Map100thMM
, aZeroPoint
, aFraction
, aFraction
);
1217 OutputMapMode
= MapMode(MapUnit::Map100thMM
);
1220 case PRINT_SIZE_ZOOMED
:
1222 Fraction
aFraction( nZoomFactor
, 100 );
1224 OutputMapMode
= MapMode(MapUnit::Map100thMM
, aZeroPoint
, aFraction
, aFraction
);
1229 aSize
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aSize
, OutputMapMode
),
1230 MapMode(MapUnit::Map100thMM
));
1232 Point
aPos (aOutRect
.Left() + (aOutRect
.GetWidth() - aSize
.Width()) / 2,
1233 aOutRect
.Top() + (aOutRect
.GetHeight() - aSize
.Height()) / 2);
1235 aPos
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aPos
, MapMode(MapUnit::Map100thMM
)),
1237 aOutRect
= rOutDev
.PixelToLogic(rOutDev
.LogicToPixel(aOutRect
, MapMode(MapUnit::Map100thMM
)),
1240 rOutDev
.SetMapMode(OutputMapMode
);
1241 rOutDev
.SetClipRegion(vcl::Region(aOutRect
));
1242 GetDoc()->DrawFormula(rOutDev
, aPos
);
1243 rOutDev
.SetClipRegion();
1248 SfxPrinter
* SmViewShell::GetPrinter(bool bCreate
)
1250 SmDocShell
* pDoc
= GetDoc();
1251 if (pDoc
->HasPrinter() || bCreate
)
1252 return pDoc
->GetPrinter();
1256 sal_uInt16
SmViewShell::SetPrinter(SfxPrinter
*pNewPrinter
, SfxPrinterChangeFlags nDiffFlags
)
1258 SfxPrinter
*pOld
= GetDoc()->GetPrinter();
1259 if ( pOld
&& pOld
->IsPrinting() )
1260 return SFX_PRINTERROR_BUSY
;
1262 if ((nDiffFlags
& SfxPrinterChangeFlags::PRINTER
) == SfxPrinterChangeFlags::PRINTER
)
1263 GetDoc()->SetPrinter( pNewPrinter
);
1265 if ((nDiffFlags
& SfxPrinterChangeFlags::OPTIONS
) == SfxPrinterChangeFlags::OPTIONS
)
1267 SmModule
*pp
= SM_MOD();
1268 pp
->GetConfig()->ItemSetToConfig(pNewPrinter
->GetOptions());
1273 bool SmViewShell::HasPrintOptionsPage() const
1278 VclPtr
<SfxTabPage
> SmViewShell::CreatePrintOptionsPage(vcl::Window
*pParent
,
1279 const SfxItemSet
&rOptions
)
1281 return SmPrintOptionsTabPage::Create(pParent
, rOptions
);
1284 SmEditWindow
*SmViewShell::GetEditWindow()
1286 SmCmdBoxWrapper
* pWrapper
= static_cast<SmCmdBoxWrapper
*>(
1287 GetViewFrame()->GetChildWindow(SmCmdBoxWrapper::GetChildWindowId()));
1289 if (pWrapper
!= nullptr)
1291 SmEditWindow
& rEditWin
= pWrapper
->GetEditWindow();
1298 void SmViewShell::SetStatusText(const OUString
& rText
)
1300 maStatusText
= rText
;
1301 GetViewFrame()->GetBindings().Invalidate(SID_TEXTSTATUS
);
1304 void SmViewShell::ShowError(const SmErrorDesc
* pErrorDesc
)
1307 if (pErrorDesc
|| nullptr != (pErrorDesc
= GetDoc()->GetParser().GetError(0)) )
1309 SetStatusText( pErrorDesc
->m_aText
);
1310 GetEditWindow()->MarkError( Point( pErrorDesc
->m_pNode
->GetColumn(),
1311 pErrorDesc
->m_pNode
->GetRow()));
1315 void SmViewShell::NextError()
1318 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().NextError();
1321 ShowError( pErrorDesc
);
1324 void SmViewShell::PrevError()
1327 const SmErrorDesc
*pErrorDesc
= GetDoc()->GetParser().PrevError();
1330 ShowError( pErrorDesc
);
1333 void SmViewShell::Insert( SfxMedium
& rMedium
)
1335 SmDocShell
*pDoc
= GetDoc();
1338 uno::Reference
<embed::XStorage
> xStorage
= rMedium
.GetStorage();
1339 uno::Reference
<container::XNameAccess
> xNameAccess(xStorage
, uno::UNO_QUERY
);
1340 if (xNameAccess
.is() && xNameAccess
->getElementNames().getLength())
1342 if (xNameAccess
->hasByName("content.xml") || xNameAccess
->hasByName("Content.xml"))
1344 // is this a fabulous math package ?
1345 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1346 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1347 bRet
= 0 == aEquation
.Import(rMedium
);
1353 OUString aText
= pDoc
->GetText();
1354 SmEditWindow
*pEditWin
= GetEditWindow();
1356 pEditWin
->InsertText( aText
);
1359 SAL_WARN( "starmath", "EditWindow missing" );
1363 pDoc
->SetModified();
1365 SfxBindings
&rBnd
= GetViewFrame()->GetBindings();
1366 rBnd
.Invalidate(SID_GAPHIC_SM
);
1367 rBnd
.Invalidate(SID_TEXT
);
1371 void SmViewShell::InsertFrom(SfxMedium
&rMedium
)
1373 bool bSuccess
= false;
1374 SmDocShell
* pDoc
= GetDoc();
1375 SvStream
* pStream
= rMedium
.GetInStream();
1379 const OUString
& rFltName
= rMedium
.GetFilter()->GetFilterName();
1380 if ( rFltName
== MATHML_XML
)
1382 Reference
<css::frame::XModel
> xModel(pDoc
->GetModel());
1383 SmXMLImportWrapper
aEquation(xModel
); //!! modifies the result of pDoc->GetText() !!
1384 bSuccess
= 0 == aEquation
.Import(rMedium
);
1390 OUString aText
= pDoc
->GetText();
1391 SmEditWindow
*pEditWin
= GetEditWindow();
1393 pEditWin
->InsertText(aText
);
1395 SAL_WARN( "starmath", "EditWindow missing" );
1398 pDoc
->SetModified();
1400 SfxBindings
& rBnd
= GetViewFrame()->GetBindings();
1401 rBnd
.Invalidate(SID_GAPHIC_SM
);
1402 rBnd
.Invalidate(SID_TEXT
);
1406 void SmViewShell::Execute(SfxRequest
& rReq
)
1408 SmEditWindow
*pWin
= GetEditWindow();
1410 switch (rReq
.GetSlot())
1412 case SID_FORMULACURSOR
:
1414 SmModule
*pp
= SM_MOD();
1416 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1417 const SfxPoolItem
*pItem
;
1421 SfxItemState::SET
== pArgs
->GetItemState( SID_FORMULACURSOR
, false, &pItem
))
1422 bVal
= static_cast<const SfxBoolItem
*>(pItem
)->GetValue();
1424 bVal
= !pp
->GetConfig()->IsShowFormulaCursor();
1426 pp
->GetConfig()->SetShowFormulaCursor(bVal
);
1427 if (!IsInlineEditEnabled())
1428 GetGraphicWindow().ShowCursor(bVal
);
1434 GetDoc()->SetText( pWin
->GetText() );
1435 SetStatusText(OUString());
1436 ShowError( nullptr );
1437 GetDoc()->Repaint();
1441 case SID_ZOOM_OPTIMAL
:
1442 mpGraphic
->ZoomToFitInWindow();
1446 mpGraphic
->SetZoom(mpGraphic
->GetZoom() + 25);
1450 SAL_WARN_IF( mpGraphic
->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1451 mpGraphic
->SetZoom(mpGraphic
->GetZoom() - 25);
1454 case SID_COPYOBJECT
:
1456 //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
1457 Reference
< datatransfer::XTransferable
> xTrans( GetDoc()->GetModel(), uno::UNO_QUERY
);
1460 Reference
< lang::XUnoTunnel
> xTnnl( xTrans
, uno::UNO_QUERY
);
1463 TransferableHelper
* pTrans
= reinterpret_cast< TransferableHelper
* >(
1464 sal::static_int_cast
< sal_uIntPtr
>(
1465 xTnnl
->getSomething( TransferableHelper::getUnoTunnelId() )));
1467 pTrans
->CopyToClipboard(GetEditWindow());
1473 case SID_PASTEOBJECT
:
1475 TransferableDataHelper
aData( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1476 uno::Reference
< io::XInputStream
> xStrm
;
1477 SotClipboardFormatId nId
;
1478 if( aData
.GetTransferable().is() &&
1479 ( aData
.HasFormat( nId
= SotClipboardFormatId::EMBEDDED_OBJ
) ||
1480 (aData
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
) &&
1481 aData
.HasFormat( nId
= SotClipboardFormatId::EMBED_SOURCE
))))
1482 xStrm
= aData
.GetInputStream(nId
, OUString());
1488 uno::Reference
< embed::XStorage
> xStorage
=
1489 ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm
, ::comphelper::getProcessComponentContext() );
1490 uno::Reference
< beans::XPropertySet
> xProps( xStorage
, uno::UNO_QUERY
);
1491 SfxMedium
aMedium( xStorage
, OUString() );
1493 GetDoc()->UpdateText();
1495 catch (uno::Exception
&)
1497 SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1512 if (pWin
->IsAllSelected())
1514 GetViewFrame()->GetDispatcher()->ExecuteList(
1515 SID_COPYOBJECT
, SfxCallMode::RECORD
,
1516 { new SfxVoidItem(SID_COPYOBJECT
) });
1525 bool bCallExec
= nullptr == pWin
;
1528 TransferableDataHelper
aDataHelper(
1529 TransferableDataHelper::CreateFromSystemClipboard(
1532 if( aDataHelper
.GetTransferable().is() &&
1533 aDataHelper
.HasFormat( SotClipboardFormatId::STRING
))
1540 GetViewFrame()->GetDispatcher()->ExecuteList(
1541 SID_PASTEOBJECT
, SfxCallMode::RECORD
,
1542 { new SfxVoidItem(SID_PASTEOBJECT
) });
1557 case SID_INSERTCOMMAND
:
1559 const SfxInt16Item
& rItem
=
1560 static_cast<const SfxInt16Item
&>(rReq
.GetArgs()->Get(SID_INSERTCOMMAND
));
1562 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1563 pWin
->InsertCommand(rItem
.GetValue());
1564 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
)) {
1565 GetDoc()->GetCursor().InsertCommand(rItem
.GetValue());
1566 GetGraphicWindow().GrabFocus();
1571 case SID_INSERTCOMMANDTEXT
:
1573 const SfxStringItem
& rItem
= static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTCOMMANDTEXT
));
1575 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1577 pWin
->InsertText(rItem
.GetValue());
1579 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1581 GetDoc()->GetCursor().InsertCommandText(rItem
.GetValue());
1582 GetGraphicWindow().GrabFocus();
1588 case SID_INSERTSYMBOL
:
1590 const SfxStringItem
& rItem
=
1591 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_INSERTSYMBOL
));
1593 if (pWin
&& (mbInsertIntoEditWindow
|| !IsInlineEditEnabled()))
1594 pWin
->InsertText(rItem
.GetValue());
1595 if (IsInlineEditEnabled() && (GetDoc() && !mbInsertIntoEditWindow
))
1596 GetDoc()->GetCursor().InsertSpecial(rItem
.GetValue());
1600 case SID_IMPORT_FORMULA
:
1602 mpImpl
->pRequest
.reset(new SfxRequest( rReq
));
1603 mpImpl
->pDocInserter
.reset(new ::sfx2::DocumentInserter(
1604 GetDoc()->GetFactory().GetFactoryName(), false ));
1605 mpImpl
->pDocInserter
->StartExecuteModal( LINK( this, SmViewShell
, DialogClosedHdl
) );
1609 case SID_IMPORT_MATHML_CLIPBOARD
:
1611 TransferableDataHelper
aDataHelper( TransferableDataHelper::CreateFromSystemClipboard(GetEditWindow()) );
1612 uno::Reference
< io::XInputStream
> xStrm
;
1613 SotClipboardFormatId nId
= SOT_FORMAT_SYSTEM_START
; //dummy initialize to avoid warning
1614 if ( aDataHelper
.GetTransferable().is() )
1616 if (aDataHelper
.HasFormat(nId
= SotClipboardFormatId::MATHML
))
1618 xStrm
= aDataHelper
.GetInputStream(nId
, "");
1621 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1622 pClipboardMedium
->GetItemSet(); //generate initial itemset, not sure if necessary
1623 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1624 SfxFilter::GetFilterByName(MATHML_XML
);
1625 pClipboardMedium
->SetFilter(pMathFilter
);
1626 pClipboardMedium
->setStreamToLoadFrom(xStrm
, true /*bIsReadOnly*/);
1627 InsertFrom(*pClipboardMedium
);
1628 GetDoc()->UpdateText();
1633 if (aDataHelper
.HasFormat(nId
= SotClipboardFormatId::STRING
))
1635 // In case of FORMAT_STRING no stream exists, need to generate one
1636 ::rtl::OUString aString
;
1637 if (aDataHelper
.GetString( nId
, aString
))
1639 std::unique_ptr
<SfxMedium
> pClipboardMedium(new SfxMedium());
1640 pClipboardMedium
->GetItemSet(); //generates initial itemset, not sure if necessary
1641 std::shared_ptr
<const SfxFilter
> pMathFilter
=
1642 SfxFilter::GetFilterByName(MATHML_XML
);
1643 pClipboardMedium
->SetFilter(pMathFilter
);
1645 std::unique_ptr
<SvMemoryStream
> pStrm
;
1646 // The text to be imported might asserts encoding like 'encoding="utf-8"' but FORMAT_STRING is UTF-16.
1647 // Force encoding to UTF-16, if encoding exists.
1648 bool bForceUTF16
= false;
1649 sal_Int32 nPosL
= aString
.indexOf("encoding=\"");
1650 sal_Int32 nPosU
= -1;
1651 if ( nPosL
>= 0 && nPosL
+10 < aString
.getLength() )
1654 nPosU
= aString
.indexOf( '"',nPosL
);
1662 OUString aNewString
= aString
.replaceAt( nPosL
,nPosU
-nPosL
,"UTF-16");
1663 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aNewString
.getStr()), aNewString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1667 pStrm
.reset(new SvMemoryStream( const_cast<sal_Unicode
*>(aString
.getStr()), aString
.getLength() * sizeof(sal_Unicode
), StreamMode::READ
));
1669 uno::Reference
<io::XInputStream
> xStrm2( new ::utl::OInputStreamWrapper(*pStrm
) );
1670 pClipboardMedium
->setStreamToLoadFrom(xStrm2
, true /*bIsReadOnly*/);
1671 InsertFrom(*pClipboardMedium
);
1672 GetDoc()->UpdateText();
1695 pWin
->SelNextMark();
1703 pWin
->SelPrevMark();
1708 case SID_TEXTSTATUS
:
1710 if (rReq
.GetArgs() != nullptr)
1712 const SfxStringItem
& rItem
=
1713 static_cast<const SfxStringItem
&>(rReq
.GetArgs()->Get(SID_TEXTSTATUS
));
1715 SetStatusText(rItem
.GetValue());
1721 case SID_GETEDITTEXT
:
1723 if (!pWin
->GetText().isEmpty()) GetDoc()->SetText( pWin
->GetText() );
1728 if ( !GetViewFrame()->GetFrame().IsInPlace() )
1730 const SfxItemSet
*pSet
= rReq
.GetArgs();
1733 ZoomByItemSet(pSet
);
1737 SfxItemSet
aSet( SmDocShell::GetPool(), SID_ATTR_ZOOM
, SID_ATTR_ZOOM
);
1738 aSet
.Put( SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1739 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
1742 ScopedVclPtr
<AbstractSvxZoomDialog
> xDlg(pFact
->CreateSvxZoomDialog(&GetViewFrame()->GetWindow(), aSet
));
1744 xDlg
->SetLimits( MINZOOM
, MAXZOOM
);
1745 if (xDlg
->Execute() != RET_CANCEL
)
1746 ZoomByItemSet(xDlg
->GetOutputItemSet());
1753 case SID_ATTR_ZOOMSLIDER
:
1755 const SfxItemSet
*pArgs
= rReq
.GetArgs();
1756 const SfxPoolItem
* pItem
;
1758 if ( pArgs
&& SfxItemState::SET
== pArgs
->GetItemState(SID_ATTR_ZOOMSLIDER
, true, &pItem
) )
1760 const sal_uInt16 nCurrentZoom
= static_cast<const SvxZoomSliderItem
*>(pItem
)->GetValue();
1761 mpGraphic
->SetZoom( nCurrentZoom
);
1766 case SID_ELEMENTSDOCKINGWINDOW
:
1768 GetViewFrame()->ToggleChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1769 GetViewFrame()->GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW
);
1775 case SID_UNICODE_NOTATION_TOGGLE
:
1777 EditEngine
* pEditEngine
= nullptr;
1779 pEditEngine
= pWin
->GetEditEngine();
1781 EditView
* pEditView
= nullptr;
1783 pEditView
= pEditEngine
->GetView();
1787 const OUString sInput
= pEditView
->GetSurroundingText();
1788 ESelection
aSel( pWin
->GetSelection() );
1790 if ( aSel
.nStartPos
> aSel
.nEndPos
)
1791 aSel
.nEndPos
= aSel
.nStartPos
;
1793 //calculate a valid end-position by reading logical characters
1794 sal_Int32 nUtf16Pos
=0;
1795 while( (nUtf16Pos
< sInput
.getLength()) && (nUtf16Pos
< aSel
.nEndPos
) )
1797 sInput
.iterateCodePoints(&nUtf16Pos
);
1798 if( nUtf16Pos
> aSel
.nEndPos
)
1799 aSel
.nEndPos
= nUtf16Pos
;
1802 ToggleUnicodeCodepoint aToggle
;
1803 while( nUtf16Pos
&& aToggle
.AllowMoreInput( sInput
[nUtf16Pos
-1]) )
1805 const OUString sReplacement
= aToggle
.ReplacementString();
1806 if( !sReplacement
.isEmpty() )
1808 pEditView
->SetSelection( aSel
);
1809 pEditEngine
->UndoActionStart(EDITUNDO_REPLACEALL
);
1810 aSel
.nStartPos
= aSel
.nEndPos
- aToggle
.StringToReplace().getLength();
1811 pWin
->SetSelection( aSel
);
1812 pEditView
->InsertText( sReplacement
, true );
1813 pEditEngine
->UndoActionEnd(EDITUNDO_REPLACEALL
);
1820 case SID_SYMBOLS_CATALOGUE
:
1823 // get device used to retrieve the FontList
1824 SmDocShell
*pDoc
= GetDoc();
1825 OutputDevice
*pDev
= pDoc
->GetPrinter();
1826 if (!pDev
|| pDev
->GetDevFontCount() == 0)
1827 pDev
= &SM_MOD()->GetDefaultVirtualDev();
1828 SAL_WARN_IF( !pDev
, "starmath", "device for font list missing" );
1830 SmModule
*pp
= SM_MOD();
1831 ScopedVclPtrInstance
<SmSymbolDialog
>( nullptr, pDev
, pp
->GetSymbolManager(), *this )->Execute();
1839 void SmViewShell::GetState(SfxItemSet
&rSet
)
1841 SfxWhichIter
aIter(rSet
);
1843 SmEditWindow
*pEditWin
= GetEditWindow();
1844 for (sal_uInt16 nWh
= aIter
.FirstWhich(); nWh
!= 0; nWh
= aIter
.NextWhich())
1851 if (! pEditWin
|| ! pEditWin
->IsSelected())
1852 rSet
.DisableItem(nWh
);
1858 TransferableDataHelper
aDataHelper(
1859 TransferableDataHelper::CreateFromSystemClipboard(
1862 mbPasteState
= aDataHelper
.GetTransferable().is() &&
1863 ( aDataHelper
.HasFormat( SotClipboardFormatId::STRING
) ||
1864 aDataHelper
.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ
) ||
1865 (aDataHelper
.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR
)
1866 && aDataHelper
.HasFormat( SotClipboardFormatId::EMBED_SOURCE
)));
1869 rSet
.DisableItem( nWh
);
1873 rSet
.Put(SvxZoomItem( SvxZoomType::PERCENT
, mpGraphic
->GetZoom()));
1877 case SID_ZOOM_OPTIMAL
:
1878 if ( GetViewFrame()->GetFrame().IsInPlace() )
1879 rSet
.DisableItem( nWh
);
1882 case SID_ATTR_ZOOMSLIDER
:
1884 const sal_uInt16 nCurrentZoom
= mpGraphic
->GetZoom();
1885 SvxZoomSliderItem
aZoomSliderItem( nCurrentZoom
, MINZOOM
, MAXZOOM
);
1886 aZoomSliderItem
.AddSnappingPoint( 100 );
1887 rSet
.Put( aZoomSliderItem
);
1897 if (! pEditWin
|| pEditWin
->IsEmpty())
1898 rSet
.DisableItem(nWh
);
1901 case SID_TEXTSTATUS
:
1903 rSet
.Put(SfxStringItem(nWh
, maStatusText
));
1907 case SID_FORMULACURSOR
:
1909 SmModule
*pp
= SM_MOD();
1910 rSet
.Put(SfxBoolItem(nWh
, pp
->GetConfig()->IsShowFormulaCursor()));
1913 case SID_ELEMENTSDOCKINGWINDOW
:
1915 bool bState
= false;
1916 SfxChildWindow
*pChildWnd
= GetViewFrame()->
1917 GetChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1918 if (pChildWnd
&& pChildWnd
->GetWindow()->IsVisible())
1920 rSet
.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW
, bState
));
1927 SmViewShell::SmViewShell(SfxViewFrame
*pFrame_
, SfxViewShell
*)
1928 : SfxViewShell(pFrame_
, SfxViewShellFlags::HAS_PRINTOPTIONS
| SfxViewShellFlags::CAN_PRINT
)
1929 , mpImpl(new SmViewShell_Impl
)
1930 , mpGraphic(VclPtr
<SmGraphicWindow
>::Create(this))
1931 , maGraphicController(*mpGraphic
.get(), SID_GAPHIC_SM
, pFrame_
->GetBindings())
1932 , mbPasteState(false)
1933 , mbInsertIntoEditWindow(false)
1935 SetStatusText(OUString());
1936 SetWindow(mpGraphic
.get());
1937 SfxShell::SetName("SmView");
1938 SfxShell::SetUndoManager( &GetDoc()->GetEditEngine().GetUndoManager() );
1939 SetHelpId( HID_SMA_VIEWSHELL_DOCUMENT
);
1943 SmViewShell::~SmViewShell()
1945 //!! this view shell is not active anymore !!
1946 // Thus 'SmGetActiveView' will give a 0 pointer.
1947 // Thus we need to supply this view as argument
1948 SmEditWindow
*pEditWin
= GetEditWindow();
1950 pEditWin
->DeleteEditView( *this );
1951 mpGraphic
.disposeAndClear();
1954 void SmViewShell::Deactivate( bool bIsMDIActivate
)
1956 SmEditWindow
*pEdit
= GetEditWindow();
1960 SfxViewShell::Deactivate( bIsMDIActivate
);
1963 void SmViewShell::Activate( bool bIsMDIActivate
)
1965 SfxViewShell::Activate( bIsMDIActivate
);
1967 SmEditWindow
*pEdit
= GetEditWindow();
1970 //! Since there is no way to be informed if a "drag and drop"
1971 //! event has taken place, we call SetText here in order to
1972 //! synchronize the GraphicWindow display with the text in the
1974 SmDocShell
*pDoc
= GetDoc();
1975 pDoc
->SetText( pDoc
->GetEditEngine().GetText() );
1977 if ( bIsMDIActivate
)
1982 IMPL_LINK( SmViewShell
, DialogClosedHdl
, sfx2::FileDialogHelper
*, _pFileDlg
, void )
1984 assert(_pFileDlg
&& "SmViewShell::DialogClosedHdl(): no file dialog");
1985 assert(mpImpl
->pDocInserter
&& "ScDocShell::DialogClosedHdl(): no document inserter");
1987 if ( ERRCODE_NONE
== _pFileDlg
->GetError() )
1989 SfxMedium
* pMedium
= mpImpl
->pDocInserter
->CreateMedium();
1991 if ( pMedium
!= nullptr )
1993 if ( pMedium
->IsStorage() )
1996 InsertFrom( *pMedium
);
1999 SmDocShell
* pDoc
= GetDoc();
2001 pDoc
->ArrangeFormula();
2003 // adjust window, repaint, increment ModifyCount,...
2004 GetViewFrame()->GetBindings().Invalidate(SID_GAPHIC_SM
);
2008 mpImpl
->pRequest
->SetReturnValue( SfxBoolItem( mpImpl
->pRequest
->GetSlot(), true ) );
2009 mpImpl
->pRequest
->Done();
2012 void SmViewShell::Notify( SfxBroadcaster
& , const SfxHint
& rHint
)
2014 switch( rHint
.GetId() )
2016 case SfxHintId::ModeChanged
:
2017 case SfxHintId::DocChanged
:
2018 GetViewFrame()->GetBindings().InvalidateAll(false);
2025 bool SmViewShell::IsInlineEditEnabled() const
2027 return mpImpl
->aOpts
.IsExperimentalMode();
2030 void SmViewShell::ZoomByItemSet(const SfxItemSet
*pSet
)
2033 const SvxZoomItem
&rZoom
= static_cast<const SvxZoomItem
&>(pSet
->Get(SID_ATTR_ZOOM
));
2034 switch( rZoom
.GetType() )
2036 case SvxZoomType::PERCENT
:
2037 mpGraphic
->SetZoom(sal::static_int_cast
<sal_uInt16
>(rZoom
.GetValue ()));
2040 case SvxZoomType::OPTIMAL
:
2041 mpGraphic
->ZoomToFitInWindow();
2044 case SvxZoomType::PAGEWIDTH
:
2045 case SvxZoomType::WHOLEPAGE
:
2047 const MapMode
aMap( MapUnit::Map100thMM
);
2048 SfxPrinter
*pPrinter
= GetPrinter( true );
2050 Rectangle
OutputRect(aPoint
, pPrinter
->GetOutputSize());
2051 Size
OutputSize(pPrinter
->LogicToPixel(Size(OutputRect
.GetWidth(),
2052 OutputRect
.GetHeight()), aMap
));
2053 Size
GraphicSize(pPrinter
->LogicToPixel(GetDoc()->GetSize(), aMap
));
2054 sal_uInt16 nZ
= sal::static_int_cast
<sal_uInt16
>(std::min(long(Fraction(OutputSize
.Width() * 100L, GraphicSize
.Width())),
2055 long(Fraction(OutputSize
.Height() * 100L, GraphicSize
.Height()))));
2056 mpGraphic
->SetZoom (nZ
);
2064 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */