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 <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>
59 #include <swmodule.hxx>
60 #include <TextCursorHelper.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...
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
,
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
);
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());
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
);
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;
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);
169 rRenderContext
.DrawOutDev(Point(), aSize
, Point(), aSize
, *m_xVirDev
);
172 SwOneExampleFrame::~SwOneExampleFrame()
177 void SwOneExampleFrame::CreateControl()
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) }
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();
207 m_xController
= nullptr;
210 IMPL_LINK( SwOneExampleFrame
, TimeoutHdl
, Timer
*, pTimer
, void )
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
);
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
))
264 aZoom
<<= sal_Int16(view::DocumentZoomType::PAGE_WIDTH_EXACT
);
265 xViewProps
->setPropertyValue(UNO_NAME_ZOOM_TYPE
, 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
)
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);
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
);
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
;
379 uno::Reference
< beans::XPropertySet
> xPProp(xPStyle
, uno::UNO_QUERY
);
380 uno::Any aSize
= xPProp
->getPropertyValue(UNO_NAME_SIZE
);
383 //TODO: set page width to card width
384 aPSize
.Width
= 10000;
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
);
405 xScrCursor
->screenUp();
409 SwEditShell
* pSh
= pDoc
->GetEditShell();
410 if( pSh
&& pSh
->ActionCount() )
417 SwModule::get()->SetView(m_pModuleView
);
425 void SwOneExampleFrame::ClearDocument()
430 SwDoc
* pDoc
= m_xCursor
->GetDoc();
431 SwEditShell
* pSh
= pDoc
->GetEditShell();
432 pSh
->LockPaint(LockPaintReason::ExampleFrame
);
433 pSh
->StartAllAction();
437 pSh
->ClearUpCursors();
439 if( m_aLoadedIdle
.IsActive())
444 m_aLoadedIdle
.Start();
447 bool SwOneExampleFrame::CreatePopup(const Point
& rPt
)
449 if (EX_SHOW_ONLINE_LAYOUT
!= m_nStyleFlags
)
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
);
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))));
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();
488 xViewProps
->setPropertyValue(UNO_NAME_ZOOM_VALUE
, aZoom
);
489 aZoom
<<= sal_Int16(view::DocumentZoomType::BY_VALUE
);
490 xViewProps
->setPropertyValue(UNO_NAME_ZOOM_TYPE
, aZoom
);
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */