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 .
21 #include <DrawDocShell.hxx>
22 #include <svx/svdpagv.hxx>
23 #include <svx/svxdlg.hxx>
24 #include <o3tl/string_view.hxx>
27 #include <ViewShell.hxx>
28 #include <FrameView.hxx>
29 #include <drawdoc.hxx>
31 #include <ClientView.hxx>
33 #include <strings.hrc>
35 #include <sdresid.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/virdev.hxx>
39 #include <rtl/character.hxx>
40 #include <tools/debug.hxx>
45 * Drawing of DocShell (with the helper class SdDrawViewShell)
47 void DrawDocShell::Draw(OutputDevice
* pOut
, const JobSetup
&, sal_uInt16 nAspect
, bool /*bOutputForScreen*/)
49 if (nAspect
== ASPECT_THUMBNAIL
)
51 // THUMBNAIL: here we may can set the draft mode
54 std::optional
<ClientView
> pView( std::in_place
, this, pOut
);
56 pView
->SetHlplVisible(false);
57 pView
->SetGridVisible(false);
58 pView
->SetBordVisible(false);
59 pView
->SetPageVisible(false);
60 pView
->SetGlueVisible(false);
62 SdPage
* pSelectedPage
= nullptr;
64 const std::vector
<std::unique_ptr
<sd::FrameView
>> &rViews
= mpDoc
->GetFrameViewList();
67 sd::FrameView
* pFrameView
= rViews
[0].get();
68 if( pFrameView
->GetPageKind() == PageKind::Standard
)
70 sal_uInt16 nSelectedPage
= pFrameView
->GetSelectedPage();
71 pSelectedPage
= mpDoc
->GetSdPage(nSelectedPage
, PageKind::Standard
);
75 if( nullptr == pSelectedPage
)
77 SdPage
* pPage
= nullptr;
78 sal_uInt16 nPageCnt
= mpDoc
->GetSdPageCount(PageKind::Standard
);
80 for (sal_uInt16 i
= 0; i
< nPageCnt
; i
++)
82 pPage
= mpDoc
->GetSdPage(i
, PageKind::Standard
);
84 if ( pPage
->IsSelected() )
85 pSelectedPage
= pPage
;
88 if( nullptr == pSelectedPage
)
89 pSelectedPage
= mpDoc
->GetSdPage(0, PageKind::Standard
);
92 ::tools::Rectangle aVisArea
= GetVisArea(nAspect
);
93 pOut
->IntersectClipRegion(aVisArea
);
94 pView
->ShowSdrPage(pSelectedPage
);
96 if (pOut
->GetOutDevType() == OUTDEV_WINDOW
)
99 MapMode aOldMapMode
= pOut
->GetMapMode();
101 if (pOut
->GetOutDevType() == OUTDEV_PRINTER
)
103 MapMode aMapMode
= aOldMapMode
;
104 Point aOrigin
= aMapMode
.GetOrigin();
107 aMapMode
.SetOrigin(aOrigin
);
108 pOut
->SetMapMode(aMapMode
);
111 vcl::Region
aRegion(aVisArea
);
112 pView
->CompleteRedraw(pOut
, aRegion
);
114 if (pOut
->GetOutDevType() == OUTDEV_PRINTER
)
116 pOut
->SetMapMode(aOldMapMode
);
120 ::tools::Rectangle
DrawDocShell::GetVisArea(sal_uInt16 nAspect
) const
122 ::tools::Rectangle aVisArea
;
124 if( ( ASPECT_THUMBNAIL
== nAspect
) || ( ASPECT_DOCPRINT
== nAspect
) )
126 // provide size of first page
127 aVisArea
.SetSize(mpDoc
->GetSdPage(0, PageKind::Standard
)->GetSize());
131 aVisArea
= SfxObjectShell::GetVisArea(nAspect
);
134 if (aVisArea
.IsEmpty() && mpViewShell
)
136 vcl::Window
* pWin
= mpViewShell
->GetActiveWindow();
140 aVisArea
= pWin
->PixelToLogic(::tools::Rectangle(Point(0,0), pWin
->GetOutputSizePixel()));
147 void DrawDocShell::Connect(ViewShell
* pViewSh
)
149 mpViewShell
= pViewSh
;
152 void DrawDocShell::Disconnect(ViewShell
const * pViewSh
)
154 if (mpViewShell
== pViewSh
)
156 mpViewShell
= nullptr;
160 FrameView
* DrawDocShell::GetFrameView()
162 FrameView
* pFrameView
= nullptr;
166 pFrameView
= mpViewShell
->GetFrameView();
173 * Creates a bitmap of an arbitrary page
175 BitmapEx
DrawDocShell::GetPagePreviewBitmap(SdPage
* pPage
)
177 const sal_uInt16 nMaxEdgePixel
= 90;
178 MapMode
aMapMode( MapUnit::Map100thMM
);
179 const Size
aSize( pPage
->GetSize() );
181 ScopedVclPtrInstance
< VirtualDevice
> pVDev( *Application::GetDefaultDevice() );
183 pVDev
->SetMapMode( aMapMode
);
185 const Size
aPixSize( pVDev
->LogicToPixel( aSize
) );
186 const sal_uLong nMaxEdgePix
= std::max( aPixSize
.Width(), aPixSize
.Height() );
187 Fraction
aFrac( nMaxEdgePixel
, nMaxEdgePix
);
189 aMapMode
.SetScaleX( aFrac
);
190 aMapMode
.SetScaleY( aFrac
);
191 pVDev
->SetMapMode( aMapMode
);
192 pVDev
->SetOutputSize( aSize
);
194 // that we also get the dark lines at the right and bottom page margin
195 aFrac
= Fraction( nMaxEdgePixel
- 1, nMaxEdgePix
);
196 aMapMode
.SetScaleX( aFrac
);
197 aMapMode
.SetScaleY( aFrac
);
198 pVDev
->SetMapMode( aMapMode
);
200 std::optional
<ClientView
> pView( std::in_place
, this, pVDev
);
201 FrameView
* pFrameView
= GetFrameView();
202 pView
->ShowSdrPage( pPage
);
204 if ( GetFrameView() )
206 // initialize the drawing-(screen) attributes
207 pView
->SetGridCoarse( pFrameView
->GetGridCoarse() );
208 pView
->SetGridFine( pFrameView
->GetGridFine() );
209 pView
->SetSnapGridWidth(pFrameView
->GetSnapGridWidthX(), pFrameView
->GetSnapGridWidthY());
210 pView
->SetGridVisible( pFrameView
->IsGridVisible() );
211 pView
->SetGridFront( pFrameView
->IsGridFront() );
212 pView
->SetSnapAngle( pFrameView
->GetSnapAngle() );
213 pView
->SetGridSnap( pFrameView
->IsGridSnap() );
214 pView
->SetBordSnap( pFrameView
->IsBordSnap() );
215 pView
->SetHlplSnap( pFrameView
->IsHlplSnap() );
216 pView
->SetOFrmSnap( pFrameView
->IsOFrmSnap() );
217 pView
->SetOPntSnap( pFrameView
->IsOPntSnap() );
218 pView
->SetOConSnap( pFrameView
->IsOConSnap() );
219 pView
->SetDragStripes( pFrameView
->IsDragStripes() );
220 pView
->SetFrameDragSingles( pFrameView
->IsFrameDragSingles() );
221 pView
->SetSnapMagneticPixel( pFrameView
->GetSnapMagneticPixel() );
222 pView
->SetMarkedHitMovesAlways( pFrameView
->IsMarkedHitMovesAlways() );
223 pView
->SetMoveOnlyDragging( pFrameView
->IsMoveOnlyDragging() );
224 pView
->SetSlantButShear( pFrameView
->IsSlantButShear() );
225 pView
->SetNoDragXorPolys( pFrameView
->IsNoDragXorPolys() );
226 pView
->SetCrookNoContortion( pFrameView
->IsCrookNoContortion() );
227 pView
->SetAngleSnapEnabled( pFrameView
->IsAngleSnapEnabled() );
228 pView
->SetBigOrtho( pFrameView
->IsBigOrtho() );
229 pView
->SetOrtho( pFrameView
->IsOrtho() );
231 SdrPageView
* pPageView
= pView
->GetSdrPageView();
235 if ( pPageView
->GetVisibleLayers() != pFrameView
->GetVisibleLayers() )
236 pPageView
->SetVisibleLayers( pFrameView
->GetVisibleLayers() );
238 if ( pPageView
->GetPrintableLayers() != pFrameView
->GetPrintableLayers() )
239 pPageView
->SetPrintableLayers( pFrameView
->GetPrintableLayers() );
241 if ( pPageView
->GetLockedLayers() != pFrameView
->GetLockedLayers() )
242 pPageView
->SetLockedLayers( pFrameView
->GetLockedLayers() );
244 pPageView
->SetHelpLines( pFrameView
->GetStandardHelpLines() );
247 if ( pView
->GetActiveLayer() != pFrameView
->GetActiveLayer() )
248 pView
->SetActiveLayer( pFrameView
->GetActiveLayer() );
251 pView
->CompleteRedraw( pVDev
, vcl::Region(::tools::Rectangle(aNullPt
, aSize
)) );
253 // IsRedrawReady() always gives sal_True while ( !pView->IsRedrawReady() ) {}
256 pVDev
->SetMapMode( MapMode() );
258 BitmapEx
aPreview( pVDev
->GetBitmapEx( aNullPt
, pVDev
->GetOutputSizePixel() ) );
260 DBG_ASSERT(!aPreview
.IsEmpty(), "Preview-Bitmap could not be generated");
266 * Checks if the page exists. If so, we force the user to enter a not yet used
268 * @return sal_False if the user cancels the action.
270 bool DrawDocShell::CheckPageName(weld::Window
* pWin
, OUString
& rName
)
272 const OUString
aStrForDlg( rName
);
273 bool bIsNameValid
= IsNewPageNameValid( rName
, true );
278 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
280 if (GetDocumentType() == DocumentType::Draw
)
281 aDesc
= SdResId( STR_WARN_PAGE_EXISTS_DRAW
);
283 aDesc
= SdResId( STR_WARN_PAGE_EXISTS
);
285 ScopedVclPtr
<AbstractSvxNameDialog
> aNameDlg(pFact
->CreateSvxNameDialog(pWin
, aStrForDlg
, aDesc
));
286 aNameDlg
->SetEditHelpId( HID_SD_NAMEDIALOG_PAGE
);
288 aNameDlg
->SetCheckNameHdl( LINK( this, DrawDocShell
, RenameSlideHdl
) );
290 rtl::Reference
<FuPoor
> xFunc( mpViewShell
->GetCurrentFunction() );
294 if( aNameDlg
->Execute() == RET_OK
)
296 rName
= aNameDlg
->GetName();
297 bIsNameValid
= IsNewPageNameValid( rName
);
304 bool DrawDocShell::IsNewPageNameValid( OUString
& rInOutPageName
, bool bResetStringIfStandardName
/* = false */ )
306 bool bCanUseNewName
= false;
308 // check if name is something like 'Slide/Page n'
310 if (GetDoc()->GetDocumentType() == DocumentType::Draw
)
311 aStrPage
= SdResId(STR_PAGE_NAME
) + " ";
313 // using the same strings as SdPage::GetName
314 aStrPage
= SdResId(STR_PAGE
) + " ";
316 bool bIsStandardName
= false;
318 // prevent also _future_ slide names of the form "'STR_PAGE' + ' ' + '[0-9]+|[a-z]|[A-Z]|[CDILMVX]+|[cdilmvx]+'"
319 // (arabic, lower- and upper case single letter, lower- and upper case roman numbers)
320 if (rInOutPageName
.startsWith(aStrPage
) &&
321 rInOutPageName
.getLength() > aStrPage
.getLength())
323 sal_Int32 nIdx
{ aStrPage
.getLength() };
324 std::u16string_view sRemainder
= o3tl::getToken(rInOutPageName
, 0, ' ', nIdx
);
325 if (!sRemainder
.empty() && sRemainder
[0] >= '0' && sRemainder
[0] <= '9')
327 // check for arabic numbering
330 // skip all following numbers
331 while (nIndex
< sRemainder
.size() &&
332 sRemainder
[nIndex
] >= '0' && sRemainder
[nIndex
] <= '9')
337 // EOL? Reserved name!
338 if (nIndex
>= sRemainder
.size())
340 bIsStandardName
= true;
343 else if (sRemainder
.size() == 1 &&
344 rtl::isAsciiLowerCase(sRemainder
[0]))
346 // lower case, single character: reserved
347 bIsStandardName
= true;
349 else if (sRemainder
.size() == 1 &&
350 rtl::isAsciiUpperCase(sRemainder
[0]))
352 // upper case, single character: reserved
353 bIsStandardName
= true;
357 // check for upper/lower case roman numbering
358 OUString
sReserved(u
"cdilmvx"_ustr
);
360 // skip all following characters contained in one reserved class
361 if (sReserved
.indexOf(sRemainder
[0]) == -1)
362 sReserved
= sReserved
.toAsciiUpperCase();
365 while (nIndex
< sRemainder
.size() &&
366 sReserved
.indexOf(sRemainder
[nIndex
]) != -1)
371 // EOL? Reserved name!
372 if (nIndex
>= sRemainder
.size())
374 bIsStandardName
= true;
379 if( bIsStandardName
)
381 if( bResetStringIfStandardName
)
383 // this is for insertion of slides from other files with standard
384 // name. They get a new standard name, if the string is set to an
386 rInOutPageName
.clear();
387 bCanUseNewName
= true;
390 bCanUseNewName
= false;
394 if (!rInOutPageName
.isEmpty())
397 sal_uInt16 nExistingPageNum
= mpDoc
->GetPageByName( rInOutPageName
, bOutDummy
);
398 bCanUseNewName
= ( nExistingPageNum
== SDRPAGE_NOTFOUND
);
401 bCanUseNewName
= false;
404 return bCanUseNewName
;
407 bool DrawDocShell::IsPageNameUnique( std::u16string_view rPageName
) const
409 return mpDoc
->IsPageNameUnique(rPageName
);
412 IMPL_LINK( DrawDocShell
, RenameSlideHdl
, AbstractSvxNameDialog
&, rDialog
, bool )
414 OUString aNewName
= rDialog
.GetName();
415 return IsNewPageNameValid( aNewName
);
418 } // end of namespace sd
420 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */