Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / starmath / source / view.cxx
blob346ea88400f3be0a0b3e2b05a5673977c7184e5e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
60 #include <view.hxx>
61 #include "cfgitem.hxx"
62 #include <dialog.hxx>
63 #include <document.hxx>
64 #include <starmath.hrc>
65 #include <strings.hrc>
66 #include "mathmlimport.hxx"
67 #include <cursor.hxx>
68 #include "accessibility.hxx"
69 #include <ElementsDockingWindow.hxx>
70 #include <helpids.h>
71 #include <cassert>
72 #include <memory>
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>
86 using namespace css;
87 using namespace css::accessibility;
88 using namespace css::uno;
90 SmGraphicWindow::SmGraphicWindow(SmViewShell* pShell)
91 : ScrollableWindow(&pShell->GetViewFrame()->GetWindow())
92 , pViewShell(pShell)
93 , nZoom(100)
95 assert(pViewShell);
96 // docking windows are usually hidden (often already done in the
97 // resource) and will be shown by the sfx framework.
98 Hide();
100 const Fraction aFraction(1, 1);
101 SetMapMode(MapMode(MapUnit::Map100thMM, Point(), aFraction, aFraction));
103 SetTotalSize();
105 SetHelpId(HID_SMA_WIN_DOCUMENT);
107 ShowLine(false);
108 CaretBlinkInit();
111 SmGraphicWindow::~SmGraphicWindow()
113 disposeOnce();
116 void SmGraphicWindow::dispose()
118 if (mxAccessible.is())
119 mxAccessible->ClearWin(); // make Accessible nonfunctional
120 CaretBlinkStop();
121 ScrollableWindow::dispose();
124 void SmGraphicWindow::StateChanged(StateChangedType eType)
126 if (eType == StateChangedType::InitShow)
127 Show();
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);
144 GrabFocus();
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();
157 if (!pTree)
158 return;
160 if (IsInlineEditEnabled()) {
161 pViewShell->GetDoc()->GetCursor().MoveTo(this, aPos, !rMEvt.IsShift());
162 return;
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);
169 if (pNode)
170 { SmEditWindow *pEdit = pViewShell->GetEditWindow();
171 if (!pEdit)
172 return;
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);
182 SetCursor(pNode);
184 // allow for immediate editing and
185 //! implicitly synchronize the cursor position mark in this window
186 pEdit->GrabFocus();
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);
200 CaretBlinkStop();
201 SetIsCursorVisible(true);
202 CaretBlinkStart();
203 RepaintViewShellDoc();
207 bool SmGraphicWindow::IsInlineEditEnabled() const
209 return pViewShell->IsInlineEditEnabled();
212 void SmGraphicWindow::GetFocus()
214 if (!IsInlineEditEnabled())
215 return;
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);
221 ShowLine(true);
222 CaretBlinkStart();
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())
238 return;
239 SetIsCursorVisible(false);
240 ShowLine(false);
241 CaretBlinkStop();
242 RepaintViewShellDoc();
245 void SmGraphicWindow::RepaintViewShellDoc()
247 SmDocShell* pDoc = pViewShell->GetDoc();
248 if (pDoc)
249 pDoc->Repaint();
252 IMPL_LINK_NOARG(SmGraphicWindow, CaretBlinkTimerHdl, Timer *, void)
254 if (IsCursorVisible())
255 SetIsCursorVisible(false);
256 else
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())
271 return;
272 if (aCaretBlinkTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME)
273 aCaretBlinkTimer.Start();
276 void SmGraphicWindow::CaretBlinkStop()
278 if (!IsInlineEditEnabled())
279 return;
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())
287 return;
289 bool bInvert = bShow != IsCursorVisible();
291 if (bInvert)
292 InvertTracking(aCursorRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow);
294 SetIsCursorVisible(bShow);
297 void SmGraphicWindow::ShowLine(bool bShow)
299 if (!IsInlineEditEnabled())
300 return;
302 bIsLineVisible = bShow;
305 void SmGraphicWindow::SetCursor(const SmNode *pNode)
307 if (IsInlineEditEnabled())
308 return;
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())
327 return;
329 SmModule *pp = SM_MOD();
331 if (IsCursorVisible())
332 ShowCursor(false); // clean up remainings of old cursor
333 aCursorRect = rRect;
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())
347 return nullptr;
349 // find visible node with token at nRow, nCol
350 const SmNode *pTree = pViewShell->GetDoc()->GetFormulaTree(),
351 *pNode = nullptr;
352 if (pTree)
353 pNode = pTree->FindTokenAt(nRow, nCol);
355 if (pNode)
356 SetCursor(pNode);
357 else
358 ShowCursor(false);
360 return pNode;
363 void SmGraphicWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
365 ApplyColorConfigValues(SM_MOD()->GetColorConfig());
367 SmDocShell& rDoc = *pViewShell->GetDoc();
368 Point aPoint;
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());
379 else
381 SetIsCursorVisible(false); // (old) cursor must be drawn again
383 const SmEditWindow* pEdit = pViewShell->GetEditWindow();
384 if (pEdit)
385 { // get new position for formula-cursor (for possible altered formula)
386 sal_Int32 nRow;
387 sal_uInt16 nCol;
388 SmGetLeftSelectionPart(pEdit->GetSelection(), nRow, nCol);
389 nRow++;
390 nCol++;
391 const SmNode *pFound = SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
393 SmModule *pp = SM_MOD();
394 if (pFound && pp->GetConfig()->IsShowFormulaCursor())
395 ShowCursor(true);
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);
414 return;
417 SmCursor& rCursor = pViewShell->GetDoc()->GetCursor();
418 KeyFuncType eFunc = rKEvt.GetKeyCode().GetFunction();
419 if (eFunc == KeyFuncType::COPY)
420 rCursor.Copy();
421 else if (eFunc == KeyFuncType::CUT)
422 rCursor.Cut();
423 else if (eFunc == KeyFuncType::PASTE)
424 rCursor.Paste();
425 else {
426 sal_uInt16 nCode = rKEvt.GetKeyCode().GetCode();
427 switch(nCode)
429 case KEY_LEFT:
431 rCursor.Move(this, MoveLeft, !rKEvt.GetKeyCode().IsShift());
432 }break;
433 case KEY_RIGHT:
435 rCursor.Move(this, MoveRight, !rKEvt.GetKeyCode().IsShift());
436 }break;
437 case KEY_UP:
439 rCursor.Move(this, MoveUp, !rKEvt.GetKeyCode().IsShift());
440 }break;
441 case KEY_DOWN:
443 rCursor.Move(this, MoveDown, !rKEvt.GetKeyCode().IsShift());
444 }break;
445 case KEY_RETURN:
447 if(!rKEvt.GetKeyCode().IsShift())
448 rCursor.InsertRow();
449 }break;
450 case KEY_DELETE:
452 if(!rCursor.HasSelection()){
453 rCursor.Move(this, MoveRight, false);
454 if(rCursor.HasComplexSelection()) break;
456 rCursor.Delete();
457 }break;
458 case KEY_BACKSPACE:
460 rCursor.DeletePrev(this);
461 }break;
462 case KEY_ADD:
463 rCursor.InsertElement(PlusElement);
464 break;
465 case KEY_SUBTRACT:
466 if(rKEvt.GetKeyCode().IsShift())
467 rCursor.InsertSubSup(RSUB);
468 else
469 rCursor.InsertElement(MinusElement);
470 break;
471 case KEY_MULTIPLY:
472 rCursor.InsertElement(CDotElement);
473 break;
474 case KEY_DIVIDE:
475 rCursor.InsertFraction();
476 break;
477 case KEY_LESS:
478 rCursor.InsertElement(LessThanElement);
479 break;
480 case KEY_GREATER:
481 rCursor.InsertElement(GreaterThanElement);
482 break;
483 case KEY_EQUAL:
484 rCursor.InsertElement(EqualElement);
485 break;
486 default:
488 sal_Unicode code = rKEvt.GetCharCode();
489 SmBraceNode* pBraceNode = nullptr;
491 if(code == ' ') {
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);
511 }else{
512 if(code != 0){
513 rCursor.InsertText(OUString(code));
514 }else if (! (GetView() && GetView()->KeyInput(rKEvt)) )
515 ScrollableWindow::KeyInput(rKEvt);
520 CaretBlinkStop();
521 CaretBlinkStart();
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();
537 Point aPos(5, 5);
538 if (rCEvt.IsMouseEvent())
539 aPos = rCEvt.GetMousePosPixel();
541 // added for replaceability of context menus
542 SfxDispatcher::ExecutePopup( this, &aPos );
544 bCallBase = false;
546 break;
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() )
555 nTmpZoom -= 10;
556 else
557 nTmpZoom += 10;
558 SetZoom( nTmpZoom );
559 bCallBase = false;
562 break;
564 default: break;
567 if ( bCallBase )
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) );
577 SetTotalSize();
578 SmViewShell *pViewSh = GetView();
579 if (pViewSh)
581 pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOM);
582 pViewSh->GetViewFrame()->GetBindings().Invalidate(SID_ATTR_ZOOMSLIDER);
584 Invalidate();
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,
619 sal_uInt16 nId_,
620 SfxBindings &rBindings) :
621 SfxControllerItem(nId_, rBindings),
622 rGraphic(rSmGraphic)
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,
639 sal_uInt16 nId_,
640 SfxBindings &rBindings) :
641 SfxControllerItem(nId_, rBindings),
642 rEdit(rSmEdit)
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_),
663 bExiting (false)
665 SetHelpId( HID_SMA_COMMAND_WIN );
666 SetSizePixel(LogicToPixel(Size(292 , 94), MapMode(MapUnit::MapAppFont)));
667 SetText(SmResId(STR_CMDBOXWINDOW));
669 Hide();
671 aInitialFocusTimer.SetInvokeHandler(LINK(this, SmCmdBoxWindow, InitialFocusTimerHdl));
672 aInitialFocusTimer.SetTimeout(100);
675 SmCmdBoxWindow::~SmCmdBoxWindow ()
677 disposeOnce();
680 void SmCmdBoxWindow::dispose()
682 aInitialFocusTimer.Stop();
683 bExiting = true;
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();
709 Invalidate();
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)
728 switch (eAlign)
730 case SfxChildAlignment::LEFT:
731 case SfxChildAlignment::RIGHT:
732 return Size();
733 default:
734 break;
736 return SfxDockingWindow::CalcDockingSize(eAlign);
739 SfxChildAlignment SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual,
740 SfxChildAlignment eWish)
742 switch (eWish)
744 case SfxChildAlignment::TOP:
745 case SfxChildAlignment::BOTTOM:
746 case SfxChildAlignment::NOALIGNMENT:
747 return eWish;
748 default:
749 break;
752 return eActual;
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() );
787 aEdit->GrabFocus();
789 bool bInPlace = GetView()->GetViewFrame()->GetFrame().IsInPlace();
790 uno::Reference< frame::XFrame > xFrame( GetBindings().GetDispatcher()->GetFrame()->GetFrame().GetFrameInterface());
791 if ( bInPlace )
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 );
799 else
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 ) );
816 if (aPos.X() < 0)
817 aPos.setX( 0 );
818 if (aPos.Y() < 0)
819 aPos.setY( 0 );
820 SetPosPixel( aPos );
823 void SmCmdBoxWindow::ToggleFloatingMode()
825 SfxDockingWindow::ToggleFloatingMode();
827 if (GetFloatingWindow())
828 GetFloatingWindow()->SetMinOutputSizePixel(Size (200, 50));
831 void SmCmdBoxWindow::GetFocus()
833 if (!bExiting)
834 aEdit->GrabFocus();
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();
899 rWin.Update();
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
913 //if necessary
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;
922 if (nTabPos)
924 aSize.setWidth( 0 );
925 sal_Int32 nPos = 0;
928 if (nPos > 0)
929 aSize.setWidth( ((aSize.Width() / nTabPos) + 1) * nTabPos );
931 const OUString aText = rLine.getToken(0, '\t', nPos);
932 aSize.AdjustWidth(rDevice.GetTextWidth(aText) );
934 while (nPos >= 0);
937 return aSize;
940 Size SmViewShell::GetTextSize(OutputDevice const & rDevice, const OUString& rText, long MaxWidth)
942 Size aSize;
943 Size aTextSize;
944 if (rText.isEmpty())
945 return aTextSize;
947 sal_Int32 nPos = 0;
950 OUString aLine = rText.getToken(0, '\n', nPos);
951 aLine = aLine.replaceAll("\r", "");
953 aSize = GetTextLineSize(rDevice, aLine);
955 if (aSize.Width() > MaxWidth)
959 OUString aText;
960 sal_Int32 m = aLine.getLength();
961 sal_Int32 nLen = m;
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)
970 m = n;
971 else
972 break;
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());
988 else
990 aTextSize.AdjustHeight(aSize.Height() );
991 aTextSize.setWidth( std::max(aTextSize.Width(), aSize.Width()) );
994 while (nPos >= 0);
996 return aTextSize;
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;
1004 if (nTabPos)
1006 sal_Int32 nPos = 0;
1009 if (nPos > 0)
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 );
1018 else
1019 rDevice.DrawText(aPoint, rLine);
1023 void SmViewShell::DrawText(OutputDevice& rDevice, const Point& rPosition, const OUString& rText, sal_uInt16 MaxWidth)
1025 if (rText.isEmpty())
1026 return;
1028 Point aPoint(rPosition);
1029 Size aSize;
1031 sal_Int32 nPos = 0;
1034 OUString aLine = rText.getToken(0, '\n', nPos);
1035 aLine = aLine.replaceAll("\r", "");
1036 aSize = GetTextLineSize(rDevice, aLine);
1037 if (aSize.Width() > MaxWidth)
1041 OUString aText;
1042 sal_Int32 m = aLine.getLength();
1043 sal_Int32 nLen = m;
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)
1052 m = n;
1053 else
1054 break;
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() );
1076 else
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 ));
1093 rOutDev.Push();
1094 rOutDev.SetLineColor( COL_BLACK );
1096 // output text on top
1097 if (bIsPrintTitle)
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));
1117 if (bIsPrintFrame)
1118 rOutDev.DrawRect(tools::Rectangle(aOutRect.TopLeft(),
1119 Size(aOutRect.GetWidth(), 100 + aTitleSize.Height() + 200 + aDescSize.Height() + 100)));
1120 aOutRect.AdjustTop(200 );
1122 // output title
1123 aFont.SetWeight(WEIGHT_BOLD);
1124 aFont.SetFontSize(aSize650);
1125 rOutDev.SetFont(aFont);
1126 Point aPoint(aOutRect.Left() + (aOutRect.GetWidth() - aTitleSize.Width()) / 2,
1127 aOutRect.Top());
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 );
1150 // get size
1151 rOutDev.SetFont(aFont);
1153 Size aSize (GetTextSize(rOutDev, GetDoc()->GetText(), aOutRect.GetWidth() - 200));
1155 aOutRect.AdjustBottom( -(aSize.Height() + 600) );
1157 if (bIsPrintFrame)
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 );
1168 if (bIsPrintFrame)
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;
1182 switch (ePrintSize)
1184 case PRINT_SIZE_NORMAL:
1185 OutputMapMode = MapMode(MapUnit::Map100thMM);
1186 break;
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()))));
1196 nZ -= 10;
1197 Fraction aFraction (std::max(MINZOOM, std::min(MAXZOOM, nZ)), 100);
1199 OutputMapMode = MapMode(MapUnit::Map100thMM, Point(), aFraction, aFraction);
1201 else
1202 OutputMapMode = MapMode(MapUnit::Map100thMM);
1203 break;
1205 case PRINT_SIZE_ZOOMED:
1207 Fraction aFraction( nZoomFactor, 100 );
1209 OutputMapMode = MapMode(MapUnit::Map100thMM, Point(), aFraction, aFraction);
1210 break;
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)),
1221 OutputMapMode);
1222 aOutRect = rOutDev.PixelToLogic(rOutDev.LogicToPixel(aOutRect, MapMode(MapUnit::Map100thMM)),
1223 OutputMapMode);
1225 rOutDev.SetMapMode(OutputMapMode);
1226 rOutDev.SetClipRegion(vcl::Region(aOutRect));
1227 GetDoc()->DrawFormula(rOutDev, aPos);
1228 rOutDev.SetClipRegion();
1230 rOutDev.Pop();
1233 SfxPrinter* SmViewShell::GetPrinter(bool bCreate)
1235 SmDocShell* pDoc = GetDoc();
1236 if (pDoc->HasPrinter() || bCreate)
1237 return pDoc->GetPrinter();
1238 return nullptr;
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());
1255 return 0;
1258 bool SmViewShell::HasPrintOptionsPage() const
1260 return true;
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();
1277 return &rEditWin;
1280 return nullptr;
1283 void SmViewShell::SetStatusText(const OUString& rText)
1285 maStatusText = rText;
1286 GetViewFrame()->GetBindings().Invalidate(SID_TEXTSTATUS);
1289 void SmViewShell::ShowError(const SmErrorDesc* pErrorDesc)
1291 assert(GetDoc());
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()
1302 assert(GetDoc());
1303 const SmErrorDesc *pErrorDesc = GetDoc()->GetParser().NextError();
1305 if (pErrorDesc)
1306 ShowError( pErrorDesc );
1309 void SmViewShell::PrevError()
1311 assert(GetDoc());
1312 const SmErrorDesc *pErrorDesc = GetDoc()->GetParser().PrevError();
1314 if (pErrorDesc)
1315 ShowError( pErrorDesc );
1318 void SmViewShell::Insert( SfxMedium& rMedium )
1320 SmDocShell *pDoc = GetDoc();
1321 bool bRet = false;
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);
1336 if (bRet)
1338 OUString aText = pDoc->GetText();
1339 SmEditWindow *pEditWin = GetEditWindow();
1340 if (pEditWin)
1341 pEditWin->InsertText( aText );
1342 else
1344 SAL_WARN( "starmath", "EditWindow missing" );
1347 pDoc->Parse();
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();
1362 if (pStream)
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);
1373 if (bSuccess)
1375 OUString aText = pDoc->GetText();
1376 SmEditWindow *pEditWin = GetEditWindow();
1377 if (pEditWin)
1378 pEditWin->InsertText(aText);
1379 else
1380 SAL_WARN( "starmath", "EditWindow missing" );
1382 pDoc->Parse();
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;
1404 bool bVal;
1405 if ( pArgs &&
1406 SfxItemState::SET == pArgs->GetItemState( SID_FORMULACURSOR, false, &pItem))
1407 bVal = static_cast<const SfxBoolItem *>(pItem)->GetValue();
1408 else
1409 bVal = !pp->GetConfig()->IsShowFormulaCursor();
1411 pp->GetConfig()->SetShowFormulaCursor(bVal);
1412 if (!IsInlineEditEnabled())
1413 GetGraphicWindow().ShowCursor(bVal);
1414 break;
1416 case SID_DRAW:
1417 if (pWin)
1419 GetDoc()->SetText( pWin->GetText() );
1420 SetStatusText(OUString());
1421 ShowError( nullptr );
1422 GetDoc()->Repaint();
1424 break;
1426 case SID_ZOOM_OPTIMAL:
1427 mpGraphic->ZoomToFitInWindow();
1428 break;
1430 case SID_ZOOMIN:
1431 mpGraphic->SetZoom(mpGraphic->GetZoom() + 25);
1432 break;
1434 case SID_ZOOMOUT:
1435 SAL_WARN_IF( mpGraphic->GetZoom() < 25, "starmath", "incorrect sal_uInt16 argument" );
1436 mpGraphic->SetZoom(mpGraphic->GetZoom() - 25);
1437 break;
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 );
1443 if( xTrans.is() )
1445 Reference< lang::XUnoTunnel> xTnnl( xTrans, uno::UNO_QUERY);
1446 if( xTnnl.is() )
1448 TransferableHelper* pTrans = reinterpret_cast< TransferableHelper * >(
1449 sal::static_int_cast< sal_uIntPtr >(
1450 xTnnl->getSomething( TransferableHelper::getUnoTunnelId() )));
1451 if( pTrans )
1452 pTrans->CopyToClipboard(GetEditWindow());
1456 break;
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());
1469 if (xStrm.is())
1473 uno::Reference < embed::XStorage > xStorage =
1474 ::comphelper::OStorageHelper::GetStorageFromInputStream( xStrm, ::comphelper::getProcessComponentContext() );
1475 SfxMedium aMedium( xStorage, OUString() );
1476 Insert( aMedium );
1477 GetDoc()->UpdateText();
1479 catch (uno::Exception &)
1481 SAL_WARN( "starmath", "SmViewShell::Execute (SID_PASTEOBJECT): failed to get storage from input stream" );
1485 break;
1488 case SID_CUT:
1489 if (pWin)
1490 pWin->Cut();
1491 break;
1493 case SID_COPY:
1494 if (pWin)
1496 if (pWin->IsAllSelected())
1498 GetViewFrame()->GetDispatcher()->ExecuteList(
1499 SID_COPYOBJECT, SfxCallMode::RECORD,
1500 { new SfxVoidItem(SID_COPYOBJECT) });
1502 else
1503 pWin->Copy();
1505 break;
1507 case SID_PASTE:
1509 bool bCallExec = nullptr == pWin;
1510 if( !bCallExec )
1512 TransferableDataHelper aDataHelper(
1513 TransferableDataHelper::CreateFromSystemClipboard(
1514 GetEditWindow()) );
1516 if( aDataHelper.GetTransferable().is() &&
1517 aDataHelper.HasFormat( SotClipboardFormatId::STRING ))
1518 pWin->Paste();
1519 else
1520 bCallExec = true;
1522 if( bCallExec )
1524 GetViewFrame()->GetDispatcher()->ExecuteList(
1525 SID_PASTEOBJECT, SfxCallMode::RECORD,
1526 { new SfxVoidItem(SID_PASTEOBJECT) });
1529 break;
1531 case SID_DELETE:
1532 if (pWin)
1533 pWin->Delete();
1534 break;
1536 case SID_SELECT:
1537 if (pWin)
1538 pWin->SelectAll();
1539 break;
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();
1554 break;
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());
1567 break;
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 ) );
1576 break;
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, "");
1589 if (xStrm.is())
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();
1601 else
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() )
1623 nPosL += 10;
1624 nPosU = aString.indexOf( '"',nPosL);
1625 if (nPosU > nPosL)
1627 bForceUTF16 = true;
1630 if ( bForceUTF16 )
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));
1635 else
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();
1647 break;
1650 case SID_NEXTERR:
1651 NextError();
1652 if (pWin)
1653 pWin->GrabFocus();
1654 break;
1656 case SID_PREVERR:
1657 PrevError();
1658 if (pWin)
1659 pWin->GrabFocus();
1660 break;
1662 case SID_NEXTMARK:
1663 if (pWin)
1665 pWin->SelNextMark();
1666 pWin->GrabFocus();
1668 break;
1670 case SID_PREVMARK:
1671 if (pWin)
1673 pWin->SelPrevMark();
1674 pWin->GrabFocus();
1676 break;
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());
1688 break;
1691 case SID_GETEDITTEXT:
1692 if (pWin)
1693 if (!pWin->GetText().isEmpty()) GetDoc()->SetText( pWin->GetText() );
1694 break;
1696 case SID_ATTR_ZOOM:
1698 if ( !GetViewFrame()->GetFrame().IsInPlace() )
1700 const SfxItemSet *pSet = rReq.GetArgs();
1701 if ( pSet )
1703 ZoomByItemSet(pSet);
1705 else
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();
1710 if(pFact)
1712 ScopedVclPtr<AbstractSvxZoomDialog> xDlg(pFact->CreateSvxZoomDialog(GetViewFrame()->GetWindow().GetFrameWeld(), aSet));
1713 assert(xDlg);
1714 xDlg->SetLimits( MINZOOM, MAXZOOM );
1715 if (xDlg->Execute() != RET_CANCEL)
1716 ZoomByItemSet(xDlg->GetOutputItemSet());
1721 break;
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 );
1734 break;
1736 case SID_ELEMENTSDOCKINGWINDOW:
1738 GetViewFrame()->ToggleChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1739 GetViewFrame()->GetBindings().Invalidate( SID_ELEMENTSDOCKINGWINDOW );
1741 rReq.Ignore ();
1743 break;
1745 case SID_UNICODE_NOTATION_TOGGLE:
1747 EditEngine* pEditEngine = nullptr;
1748 if( pWin )
1749 pEditEngine = pWin->GetEditEngine();
1751 EditView* pEditView = nullptr;
1752 if( pEditEngine )
1753 pEditView = pEditEngine->GetView();
1755 if( pEditView )
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]) )
1774 --nUtf16Pos;
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();
1784 pWin->Flush();
1788 break;
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);
1802 aDialog.run();
1804 break;
1806 rReq.Done();
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())
1817 switch (nWh)
1819 case SID_CUT:
1820 case SID_COPY:
1821 case SID_DELETE:
1822 if (! pEditWin || ! pEditWin->IsSelected())
1823 rSet.DisableItem(nWh);
1824 break;
1826 case SID_PASTE:
1827 if (pEditWin)
1829 TransferableDataHelper aDataHelper(
1830 TransferableDataHelper::CreateFromSystemClipboard(
1831 pEditWin) );
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 )));
1839 if( !mbPasteState )
1840 rSet.DisableItem( nWh );
1841 break;
1843 case SID_ATTR_ZOOM:
1844 rSet.Put(SvxZoomItem( SvxZoomType::PERCENT, mpGraphic->GetZoom()));
1845 SAL_FALLTHROUGH;
1846 case SID_ZOOMIN:
1847 case SID_ZOOMOUT:
1848 case SID_ZOOM_OPTIMAL:
1849 if ( GetViewFrame()->GetFrame().IsInPlace() )
1850 rSet.DisableItem( nWh );
1851 break;
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 );
1860 break;
1862 case SID_NEXTERR:
1863 case SID_PREVERR:
1864 case SID_NEXTMARK:
1865 case SID_PREVMARK:
1866 case SID_DRAW:
1867 case SID_SELECT:
1868 if (! pEditWin || pEditWin->IsEmpty())
1869 rSet.DisableItem(nWh);
1870 break;
1872 case SID_TEXTSTATUS:
1874 rSet.Put(SfxStringItem(nWh, maStatusText));
1876 break;
1878 case SID_FORMULACURSOR:
1880 SmModule *pp = SM_MOD();
1881 rSet.Put(SfxBoolItem(nWh, pp->GetConfig()->IsShowFormulaCursor()));
1883 break;
1884 case SID_ELEMENTSDOCKINGWINDOW:
1886 bool bState = false;
1887 SfxChildWindow *pChildWnd = GetViewFrame()->
1888 GetChildWindow( SmElementsDockingWindowWrapper::GetChildWindowId() );
1889 if (pChildWnd && pChildWnd->GetWindow()->IsVisible())
1890 bState = true;
1891 rSet.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW, bState));
1893 break;
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();
1919 if (pEditWin)
1920 pEditWin->DeleteEditView();
1921 mpGraphic.disposeAndClear();
1924 void SmViewShell::Deactivate( bool bIsMDIActivate )
1926 SmEditWindow *pEdit = GetEditWindow();
1927 if ( pEdit )
1928 pEdit->Flush();
1930 SfxViewShell::Deactivate( bIsMDIActivate );
1933 void SmViewShell::Activate( bool bIsMDIActivate )
1935 SfxViewShell::Activate( bIsMDIActivate );
1937 SmEditWindow *pEdit = GetEditWindow();
1938 if ( pEdit )
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
1943 //! EditEngine.
1944 SmDocShell *pDoc = GetDoc();
1945 pDoc->SetText( pDoc->GetEditEngine().GetText() );
1947 if ( bIsMDIActivate )
1948 pEdit->GrabFocus();
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() )
1964 Insert( *pMedium );
1965 else
1966 InsertFrom( *pMedium );
1967 delete pMedium;
1969 SmDocShell* pDoc = GetDoc();
1970 pDoc->UpdateText();
1971 pDoc->ArrangeFormula();
1972 pDoc->Repaint();
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);
1989 break;
1990 default:
1991 break;
1995 bool SmViewShell::IsInlineEditEnabled() const
1997 return mpImpl->aOpts.IsExperimentalMode();
2000 void SmViewShell::ZoomByItemSet(const SfxItemSet *pSet)
2002 assert(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 ()));
2008 break;
2010 case SvxZoomType::OPTIMAL:
2011 mpGraphic->ZoomToFitInWindow();
2012 break;
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);
2026 break;
2028 default:
2029 break;
2033 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */