Add a comment to clarify what kind of inputs the class handles
[LibreOffice.git] / sw / source / uibase / utlui / unotools.cxx
blob94c8853b642c53cb4889caf8a9d7f2b61b83f037
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 <sal/config.h>
22 #include <string_view>
24 #include <swtypes.hxx>
26 #include <strings.hrc>
27 #include <unotools.hxx>
28 #include <unoprnms.hxx>
29 #include <unotextcursor.hxx>
30 #include <unotxdoc.hxx>
31 #include <i18nutil/unicode.hxx>
32 #include <o3tl/string_view.hxx>
33 #include <rtl/string.h>
34 #include <svtools/colorcfg.hxx>
35 #include <vcl/commandevent.hxx>
36 #include <vcl/jobset.hxx>
37 #include <vcl/settings.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/virdev.hxx>
40 #include <vcl/weld.hxx>
41 #include <com/sun/star/frame/Desktop.hpp>
42 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
43 #include <com/sun/star/view/XScreenCursor.hpp>
44 #include <com/sun/star/view/DocumentZoomType.hpp>
45 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
46 #include <com/sun/star/style/XStyle.hpp>
47 #include <com/sun/star/text/XTextDocument.hpp>
48 #include <com/sun/star/awt/PosSize.hpp>
49 #include <com/sun/star/view/XViewSettingsSupplier.hpp>
50 #include <com/sun/star/container/XNameContainer.hpp>
51 #include <com/sun/star/frame/XLayoutManager.hpp>
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/propertysequence.hxx>
54 #include <comphelper/servicehelper.hxx>
55 #include <comphelper/string.hxx>
56 #include <docsh.hxx>
57 #include <editsh.hxx>
58 #include <wrtsh.hxx>
59 #include <swmodule.hxx>
60 #include <TextCursorHelper.hxx>
61 #include <doc.hxx>
63 using namespace ::com::sun::star;
65 constexpr OUStringLiteral cFactory = u"private:factory/swriter";
67 static void disableScrollBars(uno::Reference< beans::XPropertySet > const & xViewProps,
68 bool bEnableOnlineMode)
70 //the scrollbar logic is kind of busted looking in writer, when the hori scrollbar
71 //property is changed then the hori scrollbar is enabled if the property is
72 //true or browse (online) mode is enabled. So...
73 //disable online mode
74 //turn off scrollbars
75 //turn back on online mode if that's what we want
76 //which subverts the (dodgy/buggy) scrollbar setting
78 //To reproduce this problem, in edit->autotext and click through
79 //the examples and see if the preview gets a horizontal scrollbar
80 uno::Any aFalseSet(uno::Any(false));
81 xViewProps->setPropertyValue(UNO_NAME_SHOW_ONLINE_LAYOUT, aFalseSet);
83 xViewProps->setPropertyValue(UNO_NAME_SHOW_HORI_SCROLL_BAR, aFalseSet);
84 xViewProps->setPropertyValue(UNO_NAME_SHOW_VERT_SCROLL_BAR, aFalseSet);
86 if (bEnableOnlineMode)
88 xViewProps->setPropertyValue(UNO_NAME_SHOW_ONLINE_LAYOUT, uno::Any(true));
92 SwOneExampleFrame::SwOneExampleFrame(sal_uInt32 nFlags,
93 const Link<SwOneExampleFrame&,void>* pInitializedLink,
94 const OUString* pURL)
95 : m_aLoadedIdle("sw uibase SwOneExampleFrame Loaded")
96 , m_pModuleView(SwModule::get()->GetView())
97 , m_nStyleFlags(nFlags)
98 , m_bIsInitialized(false)
100 if (pURL && !pURL->isEmpty())
101 m_sArgumentURL = *pURL;
103 if( pInitializedLink )
104 m_aInitializedLink = *pInitializedLink;
106 // the controller is asynchronously set
107 m_aLoadedIdle.SetInvokeHandler(LINK(this, SwOneExampleFrame, TimeoutHdl));
108 m_aLoadedIdle.SetPriority(TaskPriority::HIGH_IDLE);
111 void SwOneExampleFrame::SetDrawingArea(weld::DrawingArea* pDrawingArea)
113 CustomWidgetController::SetDrawingArea(pDrawingArea);
114 m_xVirDev = VclPtr<VirtualDevice>::Create();
115 Size aSize(m_xVirDev->LogicToPixel(Size(150, 188), MapMode(MapUnit::MapAppFont)));
116 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
117 SetOutputSizePixel(aSize);
118 CreateControl();
121 bool SwOneExampleFrame::Command(const CommandEvent& rCEvt)
123 switch (rCEvt.GetCommand())
125 case CommandEventId::ContextMenu:
127 //#125881# quickly clicking crashes because the control is not fully initialized
128 if (m_xController.is())
129 return CreatePopup(rCEvt.GetMousePosPixel());
131 break;
132 default:;
133 break;
135 return CustomWidgetController::Command(rCEvt);
138 void SwOneExampleFrame::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
140 Size aSize(GetOutputSizePixel());
141 // m_xVirDev instead of rRenderContext just to avoid overlays in writer re-triggering
142 // invalidate on rRenderContext if it is a vcl::Window, which is the "classic" gen mode
143 m_xVirDev->SetOutputSizePixel(aSize);
145 Color aBgColor = SwModule::get()->GetColorConfig().GetColorValue(::svtools::DOCCOLOR).nColor;
146 m_xVirDev->DrawWallpaper(tools::Rectangle(Point(), aSize), aBgColor);
148 if (m_xCursor)
150 uno::Reference<view::XViewSettingsSupplier> xSettings(m_xController, uno::UNO_QUERY);
151 uno::Reference<beans::XPropertySet> xViewProps = xSettings->getViewSettings();
152 uno::Any aZoom = xViewProps->getPropertyValue(UNO_NAME_ZOOM_VALUE);
153 sal_Int16 nZoom = 100;
154 aZoom >>= nZoom;
156 double fZoom = 100.0 / nZoom;
158 m_xVirDev->Push(vcl::PushFlags::ALL);
159 m_xVirDev->SetMapMode(MapMode(MapUnit::MapTwip));
160 SwDoc *pDoc = m_xCursor->GetDoc();
161 SwDocShell* pShell = pDoc->GetDocShell();
162 tools::Rectangle aRect(Point(), m_xVirDev->PixelToLogic(aSize));
163 pShell->SetVisArea(tools::Rectangle(Point(), Size(aRect.GetWidth() * fZoom,
164 aRect.GetHeight() * fZoom)));
165 pShell->DoDraw(m_xVirDev.get(), aRect.TopLeft(), aRect.GetSize(), JobSetup(), ASPECT_CONTENT, true);
166 m_xVirDev->Pop();
169 rRenderContext.DrawOutDev(Point(), aSize, Point(), aSize, *m_xVirDev);
172 SwOneExampleFrame::~SwOneExampleFrame()
174 DisposeControl();
177 void SwOneExampleFrame::CreateControl()
179 // create new doc
180 OUString sTempURL(cFactory);
181 if(!m_sArgumentURL.isEmpty())
182 sTempURL = m_sArgumentURL;
184 uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(::comphelper::getProcessComponentContext());
185 uno::Sequence<beans::PropertyValue> args( comphelper::InitPropertySequence({
186 { "DocumentService", uno::Any(u"com.sun.star.text.TextDocument"_ustr) },
187 { "OpenFlags", uno::Any(u"-RB"_ustr) },
188 { "Referer", uno::Any(u"private:user"_ustr) },
189 { "ReadOnly", uno::Any(true) },
190 { "Hidden", uno::Any(true) }
191 }));
193 m_xModel = dynamic_cast<SwXTextDocument*>(xDesktop->loadComponentFromURL(sTempURL, u"_blank"_ustr, 0, args).get());
195 m_aLoadedIdle.Start();
198 void SwOneExampleFrame::DisposeControl()
200 m_aLoadedIdle.Stop();
201 m_xCursor = nullptr;
202 if (m_xModel)
204 m_xModel->dispose();
205 m_xModel = nullptr;
207 m_xController = nullptr;
210 IMPL_LINK( SwOneExampleFrame, TimeoutHdl, Timer*, pTimer, void )
212 if (!m_xModel.is())
213 return;
215 m_xController = m_xModel->getCurrentController();
217 if (m_xController.is())
219 uno::Reference<frame::XFrame> xFrame = m_xController->getFrame();
220 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
221 if ( xPropSet.is() )
225 uno::Reference< frame::XLayoutManager > xLayoutManager;
226 uno::Any aValue = xPropSet->getPropertyValue(u"LayoutManager"_ustr);
227 aValue >>= xLayoutManager;
228 if ( xLayoutManager.is() )
229 xLayoutManager->setVisible( false );
231 catch (const uno::Exception&)
236 //now the ViewOptions should be set properly
237 uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
238 uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
240 const uno::Any aTrueSet( true );
241 const uno::Any aFalseSet( false );
243 if( !m_bIsInitialized )
245 xViewProps->setPropertyValue(UNO_NAME_SHOW_BREAKS, aFalseSet);
246 xViewProps->setPropertyValue(UNO_NAME_SHOW_DRAWINGS, aTrueSet);
247 xViewProps->setPropertyValue(UNO_NAME_SHOW_FIELD_COMMANDS, aFalseSet);
248 xViewProps->setPropertyValue(UNO_NAME_SHOW_GRAPHICS, aTrueSet);
249 xViewProps->setPropertyValue(UNO_NAME_HIDE_WHITESPACE, aFalseSet);
250 xViewProps->setPropertyValue(UNO_NAME_SHOW_HIDDEN_PARAGRAPHS, aFalseSet);
251 xViewProps->setPropertyValue(UNO_NAME_SHOW_HIDDEN_TEXT, aFalseSet);
252 xViewProps->setPropertyValue(UNO_NAME_SHOW_HORI_RULER, aFalseSet);
253 xViewProps->setPropertyValue(UNO_NAME_SHOW_PARA_BREAKS, aFalseSet);
254 xViewProps->setPropertyValue(UNO_NAME_SHOW_PROTECTED_SPACES, aFalseSet);
255 xViewProps->setPropertyValue(UNO_NAME_SHOW_SOFT_HYPHENS, aFalseSet);
256 xViewProps->setPropertyValue(UNO_NAME_SHOW_SPACES, aFalseSet);
257 xViewProps->setPropertyValue(UNO_NAME_SHOW_TABLES, aTrueSet);
258 xViewProps->setPropertyValue(UNO_NAME_SHOW_TABSTOPS, aFalseSet);
259 xViewProps->setPropertyValue(UNO_NAME_SHOW_VERT_RULER, aFalseSet);
261 if(0 ==(m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT))
263 uno::Any aZoom;
264 aZoom <<= sal_Int16(view::DocumentZoomType::PAGE_WIDTH_EXACT);
265 xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
267 else
269 uno::Any aZoom;
270 aZoom <<= sal_Int16(view::DocumentZoomType::BY_VALUE);
271 xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
273 sal_Int16 nZoomValue = 75;
274 if(EX_SHOW_BUSINESS_CARDS == m_nStyleFlags)
276 nZoomValue = 80;
278 aZoom <<= nZoomValue;
279 xViewProps->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
282 // set onlinelayout property after setting the zoom
283 disableScrollBars(xViewProps, (m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT) != 0);
284 m_bIsInitialized = true;
287 uno::Reference< text::XText > xText = m_xModel->getText();
288 uno::Reference< text::XTextCursor > xTextCursor = xText->createTextCursor();
289 m_xCursor = dynamic_cast<SwXTextCursor*>(xTextCursor.get());
290 assert(bool(xTextCursor) == bool(m_xCursor) && "expect to get SwXTextCursor type here");
292 //From here, a cursor is defined, which goes through the template,
293 //and overwrites the template words where it is necessary.
295 SwDoc *pDoc = m_xCursor ? m_xCursor->GetDoc() : nullptr;
296 if (pDoc && (m_nStyleFlags & EX_LOCALIZE_TOC_STRINGS))
298 SwEditShell* pSh = pDoc->GetEditShell();
302 if (pSh->GetCurWord() == "HEADING1")
304 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING1));
306 else if (pSh->GetCurWord() == "ENTRY1")
308 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY1));
310 else if (pSh->GetCurWord() == "HEADING11")
312 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING11));
314 else if (pSh->GetCurWord() == "ENTRY11")
316 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY11));
318 else if (pSh->GetCurWord() == "HEADING12")
320 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_HEADING12));
322 else if (pSh->GetCurWord() == "ENTRY12")
324 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_ENTRY12));
326 else if (pSh->GetCurWord() == "TABLE1")
328 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_TABLE1));
330 else if (pSh->GetCurWord() == "IMAGE1")
332 pSh->Overwrite(SwResId(STR_IDXEXAMPLE_IDXTXT_IMAGE1));
335 while(pSh->Right(sal_uInt16(1), SwCursorSkipMode::Cells, true));
337 TOXTypes eTypes[] = { TOX_INDEX, TOX_USER, TOX_CONTENT };
338 for (auto eType : eTypes)
340 const SwTOXType* pTOXType = pDoc->GetTOXType(eType, 0);
341 SwTOXMarks aMarks;
342 pTOXType->CollectTextMarks(aMarks);
343 for (auto pMark : aMarks)
345 if (pMark->GetAlternativeText() == "Chapter")
346 pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_CHAPTER));
347 else if (pMark->GetAlternativeText() == "Keyword")
348 pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_KEYWORD));
349 else if (pMark->GetAlternativeText() == "this")
350 pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_THIS));
351 else if (pMark->GetAlternativeText() == "User Directory Entry")
352 pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_USER_DIR_ENTRY));
353 else if (pMark->GetAlternativeText() == "Entry")
354 pMark->SetAlternativeText(SwResId(STR_IDXEXAMPLE_IDXMARK_ENTRY));
356 if (pMark->GetPrimaryKey() == "Primary key")
357 pMark->SetPrimaryKey(SwResId(STR_IDXEXAMPLE_IDXMARK_PRIMARY_KEY));
359 if (pMark->GetSecondaryKey() == "Secondary key")
360 pMark->SetSecondaryKey(SwResId(STR_IDXEXAMPLE_IDXMARK_SECONDARY_KEY));
365 uno::Any aPageStyle = m_xCursor->getPropertyValue(UNO_NAME_PAGE_STYLE_NAME);
366 OUString sPageStyle;
367 aPageStyle >>= sPageStyle;
369 uno::Reference< container::XNameAccess > xStyles = m_xModel->getStyleFamilies();
370 uno::Any aPFamily = xStyles->getByName( u"PageStyles"_ustr );
371 uno::Reference< container::XNameContainer > xPFamily;
373 if( EX_SHOW_DEFAULT_PAGE != m_nStyleFlags
374 && (aPFamily >>= xPFamily) && !sPageStyle.isEmpty() )
376 uno::Any aPStyle = xPFamily->getByName( sPageStyle );
377 uno::Reference< style::XStyle > xPStyle;
378 aPStyle >>= xPStyle;
379 uno::Reference< beans::XPropertySet > xPProp(xPStyle, uno::UNO_QUERY);
380 uno::Any aSize = xPProp->getPropertyValue(UNO_NAME_SIZE);
381 awt::Size aPSize;
382 aSize >>= aPSize;
383 //TODO: set page width to card width
384 aPSize.Width = 10000;
385 aSize <<= aPSize;
386 xPProp->setPropertyValue(UNO_NAME_SIZE, aSize);
388 uno::Any aZero; aZero <<= sal_Int32(0);
389 xPProp->setPropertyValue(UNO_NAME_LEFT_MARGIN, aZero);
390 xPProp->setPropertyValue(UNO_NAME_RIGHT_MARGIN, aZero);
393 uno::Reference<awt::XWindow> xWin = xFrame->getContainerWindow();
394 Size aWinSize(GetOutputSizePixel());
395 xWin->setPosSize(0, 0, aWinSize.Width(), aWinSize.Height(), awt::PosSize::SIZE);
397 // can only be done here - the SFX changes the ScrollBar values
398 disableScrollBars(xViewProps, (m_nStyleFlags&EX_SHOW_ONLINE_LAYOUT) != 0);
400 m_aInitializedLink.Call(*this);
402 uno::Reference< text::XTextViewCursorSupplier > xCursorSupp(m_xController, uno::UNO_QUERY);
403 uno::Reference< view::XScreenCursor > xScrCursor(xCursorSupp->getViewCursor(), uno::UNO_QUERY);
404 if(xScrCursor.is())
405 xScrCursor->screenUp();
407 if (pDoc)
409 SwEditShell* pSh = pDoc->GetEditShell();
410 if( pSh && pSh->ActionCount() )
412 pSh->EndAllAction();
413 pSh->UnlockPaint();
417 SwModule::get()->SetView(m_pModuleView);
419 Invalidate();
421 else
422 pTimer->Start();
425 void SwOneExampleFrame::ClearDocument()
427 if( !m_xCursor )
428 return;
430 SwDoc* pDoc = m_xCursor->GetDoc();
431 SwEditShell* pSh = pDoc->GetEditShell();
432 pSh->LockPaint(LockPaintReason::ExampleFrame);
433 pSh->StartAllAction();
434 pSh->KillPams();
435 pSh->ClearMark();
436 pDoc->ClearDoc();
437 pSh->ClearUpCursors();
439 if( m_aLoadedIdle.IsActive())
441 pSh->EndAllAction();
442 pSh->UnlockPaint();
444 m_aLoadedIdle.Start();
447 bool SwOneExampleFrame::CreatePopup(const Point& rPt)
449 if (EX_SHOW_ONLINE_LAYOUT != m_nStyleFlags)
450 return false;
452 std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/previewmenu.ui"_ustr));
453 std::unique_ptr<weld::Menu> xPop(xBuilder->weld_menu(u"previewmenu"_ustr));
455 uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
456 uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
458 uno::Any aZoom = xViewProps->getPropertyValue(UNO_NAME_ZOOM_VALUE);
459 sal_Int16 nZoom = 0;
460 aZoom >>= nZoom;
462 for (auto const nZoomPreset : { 20, 40, 50, 75, 100 })
464 OUString sTemp = unicode::formatPercent(nZoomPreset,
465 Application::GetSettings().GetUILanguageTag());
466 OUString sIdent = "zoom" + OUString::number(nZoomPreset);
467 xPop->set_label(sIdent, sTemp);
468 if (nZoom == nZoomPreset)
469 xPop->set_active(sIdent, true);
472 PopupHdl(xPop->popup_at_rect(GetDrawingArea(), tools::Rectangle(rPt, Size(1, 1))));
474 return true;
477 void SwOneExampleFrame::PopupHdl(std::u16string_view rId)
479 std::u16string_view sZoomValue;
480 if (o3tl::starts_with(rId, u"zoom", &sZoomValue))
482 sal_Int16 nZoom = o3tl::toInt32(sZoomValue);
483 uno::Reference< view::XViewSettingsSupplier > xSettings(m_xController, uno::UNO_QUERY);
484 uno::Reference< beans::XPropertySet > xViewProps = xSettings->getViewSettings();
486 uno::Any aZoom;
487 aZoom <<= nZoom;
488 xViewProps->setPropertyValue(UNO_NAME_ZOOM_VALUE, aZoom);
489 aZoom <<= sal_Int16(view::DocumentZoomType::BY_VALUE);
490 xViewProps->setPropertyValue(UNO_NAME_ZOOM_TYPE, aZoom);
492 Invalidate();
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */