1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include "PageOrientationControl.hxx"
21 #include "PageMarginControl.hxx"
22 #include <PageOrientationPopup.hxx>
23 #include <com/sun/star/document/XUndoManager.hpp>
24 #include <com/sun/star/document/XUndoManagerSupplier.hpp>
25 #include <com/sun/star/frame/XFrame.hpp>
26
27 #include <sfx2/viewsh.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <cmdid.h>
31
32 namespace {
getUndoManager(const css::uno::Reference<css::frame::XFrame> & rxFrame)33 css::uno::Reference< css::document::XUndoManager > getUndoManager( const css::uno::Reference< css::frame::XFrame >& rxFrame )
34 {
35 const css::uno::Reference< css::frame::XController > xController = rxFrame->getController();
36 if ( xController.is() )
37 {
38 const css::uno::Reference< css::frame::XModel > xModel = xController->getModel();
39 if ( xModel.is() )
40 {
41 const css::uno::Reference< css::document::XUndoManagerSupplier > xSuppUndo( xModel, css::uno::UNO_QUERY_THROW );
42 return css::uno::Reference< css::document::XUndoManager >( xSuppUndo->getUndoManager(), css::uno::UNO_SET_THROW );
43 }
44 }
45
46 return css::uno::Reference< css::document::XUndoManager > ();
47 }
48 }
49
50 namespace sw::sidebar {
51
PageOrientationControl(PageOrientationPopup * pControl,weld::Widget * pParent)52 PageOrientationControl::PageOrientationControl(PageOrientationPopup* pControl, weld::Widget* pParent)
53 : WeldToolbarPopup(pControl->getFrameInterface(), pParent, u"modules/swriter/ui/pageorientationcontrol.ui"_ustr, u"PageOrientationControl"_ustr)
54 , m_xPortrait(m_xBuilder->weld_button(u"portrait"_ustr))
55 , m_xLandscape(m_xBuilder->weld_button(u"landscape"_ustr))
56 , m_xControl(pControl)
57 , mpPageItem( new SvxPageItem(SID_ATTR_PAGE) )
58 , mpPageSizeItem( new SvxSizeItem(SID_ATTR_PAGE_SIZE) )
59 , mpPageLRMarginItem( new SvxLongLRSpaceItem( 0, 0, SID_ATTR_PAGE_LRSPACE ) )
60 , mpPageULMarginItem( new SvxLongULSpaceItem( 0, 0, SID_ATTR_PAGE_ULSPACE ) )
61 {
62 m_xPortrait->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) );
63 m_xLandscape->connect_clicked( LINK( this, PageOrientationControl,ImplOrientationHdl ) );
64 }
65
GrabFocus()66 void PageOrientationControl::GrabFocus()
67 {
68 m_xPortrait->grab_focus();
69 }
70
~PageOrientationControl()71 PageOrientationControl::~PageOrientationControl()
72 {
73 }
74
ExecuteMarginLRChange(const tools::Long nPageLeftMargin,const tools::Long nPageRightMargin)75 void PageOrientationControl::ExecuteMarginLRChange(
76 const tools::Long nPageLeftMargin,
77 const tools::Long nPageRightMargin )
78 {
79 mpPageLRMarginItem->SetLeft( nPageLeftMargin );
80 mpPageLRMarginItem->SetRight( nPageRightMargin );
81 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
82 pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_LRSPACE,
83 SfxCallMode::RECORD, { mpPageLRMarginItem.get() });
84 }
85
ExecuteMarginULChange(const tools::Long nPageTopMargin,const tools::Long nPageBottomMargin)86 void PageOrientationControl::ExecuteMarginULChange(
87 const tools::Long nPageTopMargin,
88 const tools::Long nPageBottomMargin )
89 {
90 mpPageULMarginItem->SetUpper( nPageTopMargin );
91 mpPageULMarginItem->SetLower( nPageBottomMargin );
92 if (SfxViewFrame* pViewFrm = SfxViewFrame::Current())
93 pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_ULSPACE,
94 SfxCallMode::RECORD, { mpPageULMarginItem.get() });
95 }
96
ExecuteOrientationChange(const bool bLandscape)97 void PageOrientationControl::ExecuteOrientationChange( const bool bLandscape )
98 {
99 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
100 if (!pViewFrm)
101 return;
102
103 css::uno::Reference< css::document::XUndoManager > mxUndoManager(
104 getUndoManager( pViewFrm->GetFrame().GetFrameInterface() ) );
105
106 if ( mxUndoManager.is() )
107 mxUndoManager->enterUndoContext( u""_ustr );
108
109 SfxPoolItemHolder aResult;
110 pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_SIZE, aResult);
111 mpPageSizeItem.reset(static_cast<const SvxSizeItem*>(aResult.getItem())->Clone());
112
113 // Prevent accidental toggling of page orientation
114 if ((mpPageSizeItem->GetWidth() > mpPageSizeItem->GetHeight()) == bLandscape)
115 {
116 if ( mxUndoManager.is() )
117 mxUndoManager->leaveUndoContext();
118 return;
119 }
120
121 pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_LRSPACE, aResult);
122 mpPageLRMarginItem.reset(static_cast<const SvxLongLRSpaceItem*>(aResult.getItem())->Clone());
123
124 pViewFrm->GetBindings().GetDispatcher()->QueryState(SID_ATTR_PAGE_ULSPACE, aResult);
125 mpPageULMarginItem.reset(static_cast<const SvxLongULSpaceItem*>(aResult.getItem())->Clone());
126
127 {
128 // set new page orientation
129 mpPageItem->SetLandscape( bLandscape );
130
131 // swap the width and height of the page size
132 const tools::Long nRotatedWidth = mpPageSizeItem->GetSize().Height();
133 const tools::Long nRotatedHeight = mpPageSizeItem->GetSize().Width();
134 mpPageSizeItem->SetSize(Size(nRotatedWidth, nRotatedHeight));
135
136 // apply changed attributes
137 pViewFrm->GetDispatcher()->ExecuteList(SID_ATTR_PAGE_SIZE,
138 SfxCallMode::RECORD, { mpPageSizeItem.get(), mpPageItem.get() });
139 }
140
141 // check, if margin values still fit to the changed page size.
142 // if not, adjust margin values
143 {
144 const tools::Long nML = mpPageLRMarginItem->GetLeft();
145 const tools::Long nMR = mpPageLRMarginItem->GetRight();
146 const tools::Long nTmpPW = nML + nMR + MINBODY;
147
148 const tools::Long nPW = mpPageSizeItem->GetSize().Width();
149
150 if ( nTmpPW > nPW )
151 {
152 if ( nML <= nMR )
153 {
154 ExecuteMarginLRChange( mpPageLRMarginItem->GetLeft(), nMR - (nTmpPW - nPW ) );
155 }
156 else
157 {
158 ExecuteMarginLRChange( nML - (nTmpPW - nPW ), mpPageLRMarginItem->GetRight() );
159 }
160 }
161
162 const tools::Long nMT = mpPageULMarginItem->GetUpper();
163 const tools::Long nMB = mpPageULMarginItem->GetLower();
164 const tools::Long nTmpPH = nMT + nMB + MINBODY;
165
166 const tools::Long nPH = mpPageSizeItem->GetSize().Height();
167
168 if ( nTmpPH > nPH )
169 {
170 if ( nMT <= nMB )
171 {
172 ExecuteMarginULChange( mpPageULMarginItem->GetUpper(), nMB - ( nTmpPH - nPH ) );
173 }
174 else
175 {
176 ExecuteMarginULChange( nMT - ( nTmpPH - nPH ), mpPageULMarginItem->GetLower() );
177 }
178 }
179 }
180
181 if ( mxUndoManager.is() )
182 mxUndoManager->leaveUndoContext();
183 }
184
IMPL_LINK(PageOrientationControl,ImplOrientationHdl,weld::Button &,rControl,void)185 IMPL_LINK(PageOrientationControl, ImplOrientationHdl, weld::Button&, rControl, void)
186 {
187 if (&rControl == m_xPortrait.get())
188 ExecuteOrientationChange( false );
189 else
190 ExecuteOrientationChange( true );
191
192 m_xControl->EndPopupMode();
193 }
194
195 } // end of namespace sw::sidebar
196
197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
198