/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// space around the edit window, in pixels // fdo#69111: Increased border on the top so that the window is // easier to tear off. #define CMD_BOX_PADDING 3 #define CMD_BOX_PADDING_TOP 11
static OUString GetScrollUIName(const SmViewShell& rShell)
{ const SmDocShell* pShell = rShell.GetDoc(); if (pShell && pShell->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)
{ // This one has no border on the scrolledwindow, to maximize the space // available when in embedded mode and minimize the difference from // the ole preview to give a more seamless embedded editing experience. return"modules/smath/ui/embedwindow.ui";
} return"modules/smath/ui/mathwindow.ui";
}
SmGraphicWindow::SmGraphicWindow(SmViewShell& rShell)
: InterimItemWindow(&rShell.GetViewFrame().GetWindow(), GetScrollUIName(rShell), u"MathWindow"_ustr)
, nLinePixH(GetSettings().GetStyleSettings().GetScrollBarSize())
, nColumnPixW(nLinePixH)
, nZoom(100) // continue to use user-scrolling to make this work equivalent to how it 'always' worked
, mxScrolledWindow(m_xBuilder->weld_scrolled_window(u"scrolledwindow"_ustr, true))
, mxGraphic(new SmGraphicWidget(rShell, *this))
, mxGraphicWin(new weld::CustomWeld(*m_xBuilder, u"mathview"_ustr, *mxGraphic))
{
InitControlBase(mxGraphic->GetDrawingArea());
// get the new output-size in pixel
Size aOutPixSz = GetOutputSizePixel();
// determine the size of the output-area and if we need scrollbars constauto nScrSize = mxScrolledWindow->get_scroll_thickness(); bool bVVisible = false; // by default no vertical-ScrollBar bool bHVisible = false; // by default no horizontal-ScrollBar bool bChanged; // determines if a visibility was changed do
{
bChanged = false;
// does we need a vertical ScrollBar if ( aOutPixSz.Width() < aTotPixSz.Width() && !bHVisible )
{
bHVisible = true;
aOutPixSz.AdjustHeight( -nScrSize );
bChanged = true;
}
// does we need a horizontal ScrollBar if ( aOutPixSz.Height() < aTotPixSz.Height() && !bVVisible )
{
bVVisible = true;
aOutPixSz.AdjustWidth( -nScrSize );
bChanged = true;
}
} while ( bChanged ); // until no visibility has changed
// store the old offset and map-mode
MapMode aMap(GetGraphicMapMode());
Point aOldPixOffset(aPixOffset);
OutputDevice& rDevice = GetOutputDevice(); // get click position relative to formula
Point aPos(rDevice.PixelToLogic(rMEvt.GetPosPixel()) - GetFormulaDrawPos());
const SmNode *pTree = GetDoc()->GetFormulaTree(); if (!pTree) returntrue;
SmEditWindow* pEdit = GetView().GetEditWindow();
if (SmViewShell::IsInlineEditEnabled()) {
GetCursor().MoveTo(&rDevice, aPos, !rMEvt.IsShift());
GetView().InvalidateSlots(); // 'on grab' window events are missing in lok, do it explicitly if (comphelper::LibreOfficeKit::isActive())
SetIsCursorVisible(true); returntrue;
} const SmNode *pNode = nullptr; // if it was clicked inside the formula then get the appropriate node if (pTree->OrientedDist(aPos) <= 0)
pNode = pTree->FindRectClosestTo(aPos);
if (!pNode) returntrue;
if (!pEdit) returntrue;
// set selection to the beginning of the token
pEdit->SetSelection(pNode->GetSelection());
SetCursor(pNode);
// allow for immediate editing and //! implicitly synchronize the cursor position mark in this window
pEdit->GrabFocus();
void SmGraphicWidget::CaretBlinkInit()
{ if (comphelper::LibreOfficeKit::isActive()) return; // No blinking in lok case
aCaretBlinkTimer.SetInvokeHandler(LINK(this, SmGraphicWidget, CaretBlinkTimerHdl));
aCaretBlinkTimer.SetTimeout(Application::GetSettings().GetStyleSettings().GetCursorBlinkTime());
}
void SmGraphicWidget::CaretBlinkStart()
{ if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive()) return; if (aCaretBlinkTimer.GetTimeout() != STYLE_CURSOR_NOBLINKTIME)
aCaretBlinkTimer.Start();
}
void SmGraphicWidget::CaretBlinkStop()
{ if (!SmViewShell::IsInlineEditEnabled() || comphelper::LibreOfficeKit::isActive()) return;
aCaretBlinkTimer.Stop();
}
// shows or hides the formula-cursor depending on 'bShow' is true or not void SmGraphicWidget::ShowCursor(bool bShow)
{ if (SmViewShell::IsInlineEditEnabled()) return;
bool bInvert = bShow != IsCursorVisible(); if (bInvert)
InvertFocusRect(GetOutputDevice(), aCursorRect);
SetIsCursorVisible(bShow);
}
void SmGraphicWidget::ShowLine(bool bShow)
{ if (!SmViewShell::IsInlineEditEnabled()) return;
void SmGraphicWidget::SetCursor(const SmNode *pNode)
{ if (SmViewShell::IsInlineEditEnabled()) return;
const SmNode *pTree = GetDoc()->GetFormulaTree();
// get appropriate rectangle
Point aOffset (pNode->GetTopLeft() - pTree->GetTopLeft()),
aTLPos (GetFormulaDrawPos() + aOffset);
aTLPos.AdjustX( -(pNode->GetItalicLeftSpace()) );
Size aSize (pNode->GetItalicSize());
SetCursor(tools::Rectangle(aTLPos, aSize));
}
void SmGraphicWidget::SetCursor(const tools::Rectangle &rRect) // sets cursor to new position (rectangle) 'rRect'. // The old cursor will be removed, and the new one will be shown if // that is activated in the ConfigItem
{ if (SmViewShell::IsInlineEditEnabled()) return;
if (IsCursorVisible())
ShowCursor(false); // clean up remainings of old cursor
aCursorRect = rRect; if (SmModule::get()->GetConfig()->IsShowFormulaCursor())
ShowCursor(true); // draw new cursor
}
const SmNode * SmGraphicWidget::SetCursorPos(sal_uInt16 nRow, sal_uInt16 nCol) // looks for a VISIBLE node in the formula tree with its token at // (or around) the position 'nRow', 'nCol' in the edit window // (row and column numbering starts with 1 there!). // If there is such a node the formula-cursor is set to cover that nodes // rectangle. If not the formula-cursor will be hidden. // In any case the search result is being returned.
{ if (SmViewShell::IsInlineEditEnabled()) return nullptr;
// find visible node with token at nRow, nCol const SmNode *pTree = GetDoc()->GetFormulaTree(),
*pNode = nullptr; if (pTree)
pNode = pTree->FindTokenAt(nRow, nCol);
if (pNode)
SetCursor(pNode); else
ShowCursor(false);
rDoc.DrawFormula(rRenderContext, aPoint, true); //! modifies aPoint to be the topleft //! corner of the formula
aFormulaDrawPos = aPoint; if (SmViewShell::IsInlineEditEnabled())
{ //Draw cursor if any... if (rDoc.HasCursor() && IsLineVisible())
rDoc.GetCursor().Draw(rRenderContext, aPoint, IsCursorVisible());
} else
{
SetIsCursorVisible(false); // (old) cursor must be drawn again
if (const SmEditWindow* pEdit = GetView().GetEditWindow())
{ // get new position for formula-cursor (for possible altered formula)
sal_Int32 nRow;
sal_uInt16 nCol;
SmGetLeftSelectionPart(pEdit->GetSelection(), nRow, nCol); const SmNode *pFound = SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
if (pFound && SmModule::get()->GetConfig()->IsShowFormulaCursor())
ShowCursor(true);
}
}
}
Size SmCmdBoxWindow::CalcDockingSize(SfxChildAlignment eAlign)
{ switch (eAlign)
{ case SfxChildAlignment::LEFT: case SfxChildAlignment::RIGHT: return Size(); default: break;
} return SfxDockingWindow::CalcDockingSize(eAlign);
}
SfxChildAlignment SmCmdBoxWindow::CheckAlignment(SfxChildAlignment eActual,
SfxChildAlignment eWish)
{ switch (eWish)
{ case SfxChildAlignment::TOP: case SfxChildAlignment::BOTTOM: case SfxChildAlignment::NOALIGNMENT: return eWish; default: break;
}
return eActual;
}
void SmCmdBoxWindow::StateChanged( StateChangedType nStateChange )
{ if (StateChangedType::InitShow == nStateChange)
{
Resize(); // avoid SmEditWindow not being painted correctly
// set initial position of window in floating mode if (IsFloatingMode())
AdjustPosition(); //! don't change pos in docking-mode !
aInitialFocusTimer.Start();
}
SfxDockingWindow::StateChanged( nStateChange );
}
IMPL_LINK_NOARG( SmCmdBoxWindow, InitialFocusTimerHdl, Timer *, void )
{ // We want to have the focus in the edit window once Math has been opened // to allow for immediate typing. // Problem: There is no proper way to do this // Thus: this timer based solution has been implemented (see GrabFocus below)
// Follow-up problem (#i114910): grabbing the focus may bust the help system since // it relies on getting the current frame which conflicts with grabbing the focus. // Thus aside from the 'GrabFocus' call everything else is to get the // help reliably working despite using 'GrabFocus'.
uno::Reference <embed::XStorage> xStorage = rMedium.GetStorage(); if (xStorage.is() && xStorage->getElementNames().hasElements())
{ if (xStorage->hasByName(u"content.xml"_ustr))
{ // is this a fabulous math package ?
rtl::Reference<SmModel> xModel(dynamic_cast<SmModel*>(pDoc->GetModel().get()));
SmXMLImportWrapper aEquation(xModel); //!! modifies the result of pDoc->GetText() !!
bRet = ERRCODE_NONE == aEquation.Import(rMedium);
}
}
case SID_COPYOBJECT:
{ //TODO/LATER: does not work because of UNO Tunneling - will be fixed later
Reference< datatransfer::XTransferable > xTrans( GetDoc()->GetModel(), uno::UNO_QUERY ); if( xTrans.is() )
{ auto pTrans = dynamic_cast<TransferableHelper*>(xTrans.get()); if (pTrans)
{ if (pWin)
pTrans->CopyToClipboard(pWin->GetClipboard());
}
}
} break;
case SID_PASTEOBJECT:
{
uno::Reference < io::XInputStream > xStrm; if (pWin)
{
TransferableDataHelper aData(TransferableDataHelper::CreateFromClipboard(pWin->GetClipboard()));
SotClipboardFormatId nId; if( aData.GetTransferable().is() &&
( aData.HasFormat( nId = SotClipboardFormatId::EMBEDDED_OBJ ) ||
(aData.HasFormat( SotClipboardFormatId::OBJECTDESCRIPTOR ) &&
aData.HasFormat( nId = SotClipboardFormatId::EMBED_SOURCE ))))
xStrm = aData.GetInputStream(nId, OUString());
}
case SID_IMPORT_MATHML_CLIPBOARD:
{ if (pWin)
{
TransferableDataHelper aDataHelper(TransferableDataHelper::CreateFromClipboard(pWin->GetClipboard()));
uno::Reference < io::XInputStream > xStrm; if ( aDataHelper.GetTransferable().is() )
{
SotClipboardFormatId nId = SotClipboardFormatId::MATHML; if (aDataHelper.HasFormat(nId))
{
xStrm = aDataHelper.GetInputStream(nId, u""_ustr); if (xStrm.is())
{
SfxMedium aClipboardMedium;
aClipboardMedium.GetItemSet(); //generate initial itemset, not sure if necessary
std::shared_ptr<const SfxFilter> pMathFilter =
SfxFilter::GetFilterByName(MATHML_XML);
aClipboardMedium.SetFilter(pMathFilter);
aClipboardMedium.setStreamToLoadFrom(xStrm, true/*bIsReadOnly*/);
InsertFrom(aClipboardMedium);
GetDoc()->UpdateText();
}
} else
{
nId = SotClipboardFormatId::STRING; if (aDataHelper.HasFormat(nId))
{ // In case of FORMAT_STRING no stream exists, need to generate one
OUString aString; if (aDataHelper.GetString( nId, aString))
{ // tdf#117091 force xml declaration to exist if (!aString.startsWith("))
aString = "1.0\"?>\n" + aString;
SfxMedium aClipboardMedium;
aClipboardMedium.GetItemSet(); //generates initial itemset, not sure if necessary
std::shared_ptr<const SfxFilter> pMathFilter =
SfxFilter::GetFilterByName(MATHML_XML);
aClipboardMedium.SetFilter(pMathFilter);
case SID_SYMBOLS_CATALOGUE:
{
SmModule* pp = SmModule::get();
// get device used to retrieve the FontList
SmDocShell *pDoc = GetDoc();
OutputDevice *pDev = pDoc->GetPrinter(); if (!pDev || pDev->GetFontFaceCollectionCount() == 0)
pDev = &pp->GetDefaultVirtualDev();
SAL_WARN_IF( !pDev, "starmath", "device for font list missing" );
case SID_ATTR_ZOOM:
rSet.Put(SvxZoomItem( SvxZoomType::PERCENT, mxGraphicWindow->GetZoom()));
[[fallthrough]]; case SID_ZOOMIN: case SID_ZOOMOUT: case SID_ZOOM_OPTIMAL: if ( GetViewFrame().GetFrame().IsInPlace() )
rSet.DisableItem( nWh ); break;
case SID_NEXTERR: case SID_PREVERR: case SID_NEXTMARK: case SID_PREVMARK: case SID_DRAW: case SID_SELECT: if (! pEditWin || pEditWin->IsEmpty())
rSet.DisableItem(nWh); break;
case SID_TEXTSTATUS:
{
rSet.Put(SfxStringItem(nWh, maStatusText));
} break;
case SID_FORMULACURSOR:
{ if (IsInlineEditEnabled())
rSet.DisableItem(nWh); else
rSet.Put(SfxBoolItem(nWh, SmModule::get()->GetConfig()->IsShowFormulaCursor()));
} break; case SID_ELEMENTSDOCKINGWINDOW:
{ constbool bState = sfx2::sidebar::Sidebar::IsPanelVisible(
u"MathElementsPanel", GetViewFrame().GetFrame().GetFrameInterface());
rSet.Put(SfxBoolItem(SID_ELEMENTSDOCKINGWINDOW, bState));
} break; case SID_CMDBOXWINDOW:
{ bool bState = false; auto pCmdWin = GetViewFrame().GetChildWindow(SID_CMDBOXWINDOW); if (pCmdWin)
bState = pCmdWin->IsVisible();
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.