android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / ui / vba / vbalistformat.cxx
blobefcbf2dbe874ae60194557816e2e70704bdd34a3
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 .
19 #include "vbalistformat.hxx"
20 #include <utility>
21 #include <vbahelper/vbahelper.hxx>
22 #include <ooo/vba/word/WdListApplyTo.hpp>
23 #include <ooo/vba/word/WdDefaultListBehavior.hpp>
24 #include <com/sun/star/awt/FontDescriptor.hpp>
25 #include <com/sun/star/container/XEnumerationAccess.hpp>
26 #include <com/sun/star/container/XEnumeration.hpp>
27 #include <com/sun/star/document/XUndoManagerSupplier.hpp>
28 #include <com/sun/star/beans/XMultiPropertySet.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/style/TabStop.hpp>
31 #include <com/sun/star/text/PositionAndSpaceMode.hpp>
32 #include <com/sun/star/text/XTextTable.hpp>
33 #include <com/sun/star/util/Color.hpp>
34 #include <comphelper/sequence.hxx>
35 #include <comphelper/sequenceashashmap.hxx>
36 #include <comphelper/scopeguard.hxx>
37 #include <editeng/numitem.hxx>
38 #include "vbalisttemplate.hxx"
40 #include <vector>
42 using namespace ::ooo::vba;
43 using namespace ::com::sun::star;
45 SwVbaListFormat::SwVbaListFormat( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, uno::Reference< text::XTextRange > xTextRange ) : SwVbaListFormat_BASE( rParent, rContext ), mxTextRange(std::move( xTextRange ))
49 SwVbaListFormat::~SwVbaListFormat()
53 void SAL_CALL SwVbaListFormat::ApplyListTemplate( const css::uno::Reference< word::XListTemplate >& ListTemplate, const css::uno::Any& ContinuePreviousList, const css::uno::Any& ApplyTo, const css::uno::Any& DefaultListBehavior )
55 bool bContinuePreviousList = true;
56 if( ContinuePreviousList.hasValue() )
57 ContinuePreviousList >>= bContinuePreviousList;
59 // "applyto" must be current selection
60 sal_Int32 bApplyTo = word::WdListApplyTo::wdListApplyToSelection;
61 if( ApplyTo.hasValue() )
62 ApplyTo >>= bApplyTo;
63 if( bApplyTo != word::WdListApplyTo::wdListApplyToSelection )
64 throw uno::RuntimeException();
66 // default behaviour must be wdWord8ListBehavior
67 sal_Int32 nDefaultListBehavior = word::WdDefaultListBehavior::wdWord8ListBehavior;
68 if( DefaultListBehavior.hasValue() )
69 DefaultListBehavior >>= nDefaultListBehavior;
70 if( nDefaultListBehavior != word::WdDefaultListBehavior::wdWord8ListBehavior )
71 throw uno::RuntimeException();
73 uno::Reference< container::XEnumerationAccess > xEnumAccess( mxTextRange, uno::UNO_QUERY_THROW );
74 uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
75 if (!xEnum->hasMoreElements())
76 return;
78 SwVbaListTemplate& rListTemplate = dynamic_cast<SwVbaListTemplate&>(*ListTemplate);
80 bool isFirstElement = true;
83 uno::Reference< beans::XPropertySet > xProps( xEnum->nextElement(), uno::UNO_QUERY_THROW );
84 if( isFirstElement )
86 bool isNumberingRestart = !bContinuePreviousList;
87 xProps->setPropertyValue("ParaIsNumberingRestart", uno::Any( isNumberingRestart ) );
88 if( isNumberingRestart )
90 xProps->setPropertyValue("NumberingStartValue", uno::Any( sal_Int16(1) ) );
92 isFirstElement = false;
94 else
96 xProps->setPropertyValue("ParaIsNumberingRestart", uno::Any( false ) );
98 rListTemplate.applyListTemplate( xProps );
100 while( xEnum->hasMoreElements() );
103 template <class Ref>
104 static void addParagraphsToList(const Ref& a,
105 std::vector<css::uno::Reference<css::beans::XPropertySet>>& rList)
107 if (css::uno::Reference<css::lang::XServiceInfo> xInfo{ a, css::uno::UNO_QUERY })
109 if (xInfo->supportsService("com.sun.star.text.Paragraph"))
111 rList.emplace_back(xInfo, css::uno::UNO_QUERY_THROW);
113 else if (xInfo->supportsService("com.sun.star.text.TextTable"))
115 css::uno::Reference<css::text::XTextTable> xTable(xInfo, css::uno::UNO_QUERY_THROW);
116 const auto aNames = xTable->getCellNames();
117 for (const auto& rName : aNames)
119 addParagraphsToList(xTable->getCellByName(rName), rList);
123 if (css::uno::Reference<css::container::XEnumerationAccess> xEnumAccess{ a,
124 css::uno::UNO_QUERY })
126 auto xEnum = xEnumAccess->createEnumeration();
127 while (xEnum->hasMoreElements())
128 addParagraphsToList(xEnum->nextElement(), rList);
132 void SAL_CALL SwVbaListFormat::ConvertNumbersToText( )
134 css::uno::Reference<css::frame::XModel> xModel(getThisWordDoc(mxContext));
135 css::uno::Reference<css::document::XUndoManagerSupplier> xUndoSupplier(
136 xModel, css::uno::UNO_QUERY_THROW);
137 css::uno::Reference<css::document::XUndoManager> xUndoManager(xUndoSupplier->getUndoManager());
138 xUndoManager->enterUndoContext("ConvertNumbersToText");
139 xModel->lockControllers();
140 comphelper::ScopeGuard g([xModel, xUndoManager]() {
141 xModel->unlockControllers();
142 xUndoManager->leaveUndoContext();
145 std::vector<css::uno::Reference<css::beans::XPropertySet>> aParagraphs;
146 addParagraphsToList(mxTextRange, aParagraphs);
148 // in reverse order, to get proper label strings
149 for (auto iter = aParagraphs.rbegin(); iter != aParagraphs.rend(); ++iter)
151 auto& rPropertySet = *iter;
152 if (bool bNumber; (rPropertySet->getPropertyValue("NumberingIsNumber") >>= bNumber) && bNumber)
154 css::uno::Reference<css::text::XTextRange> xRange(rPropertySet, css::uno::UNO_QUERY_THROW);
155 OUString sLabelString;
156 rPropertySet->getPropertyValue("ListLabelString") >>= sLabelString;
157 // sal_Int16 nAdjust = SAL_MAX_INT16; // TODO?
158 sal_Int16 nNumberingType = SAL_MAX_INT16; // css::style::NumberingType
159 sal_Int16 nPositionAndSpaceMode = SAL_MAX_INT16;
160 sal_Int16 nLabelFollowedBy = SAL_MAX_INT16;
161 sal_Int32 nListtabStopPosition = SAL_MAX_INT32;
162 sal_Int32 nFirstLineIndent = SAL_MAX_INT32;
163 sal_Int32 nIndentAt = SAL_MAX_INT32;
164 sal_Int32 nLeftMargin = SAL_MAX_INT32;
165 sal_Int32 nSymbolTextDistance = SAL_MAX_INT32;
166 sal_Int32 nFirstLineOffset = SAL_MAX_INT32;
167 OUString sCharStyleName, sBulletChar;
168 css::awt::FontDescriptor aBulletFont;
169 bool bHasFont;
170 css::util::Color aBulletColor = css::util::Color(COL_AUTO);
171 bool bHasColor;
174 sal_uInt16 nLevel = SAL_MAX_UINT16;
175 rPropertySet->getPropertyValue("NumberingLevel") >>= nLevel;
176 css::uno::Reference<css::container::XIndexAccess> xNumberingRules;
177 rPropertySet->getPropertyValue("NumberingRules") >>= xNumberingRules;
178 comphelper::SequenceAsHashMap aLevelRule(xNumberingRules->getByIndex(nLevel));
180 // See offapi/com/sun/star/text/NumberingLevel.idl
181 aLevelRule["CharStyleName"] >>= sCharStyleName;
182 aLevelRule["NumberingType"] >>= nNumberingType;
183 // TODO: aLevelRule["Adjust"] >>= nAdjust; // HoriOrientation::LEFT/RIGHT/CENTER
184 aLevelRule["PositionAndSpaceMode"] >>= nPositionAndSpaceMode;
186 // for css::text::PositionAndSpaceMode::LABEL_ALIGNMENT
187 aLevelRule["LabelFollowedBy"] >>= nLabelFollowedBy;
188 aLevelRule["ListtabStopPosition"] >>= nListtabStopPosition;
189 aLevelRule["FirstLineIndent"] >>= nFirstLineIndent;
190 aLevelRule["IndentAt"] >>= nIndentAt;
192 // for css::text::PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION
193 aLevelRule["LeftMargin"] >>= nLeftMargin;
194 aLevelRule["SymbolTextDistance"] >>= nSymbolTextDistance;
195 aLevelRule["FirstLineOffset"] >>= nFirstLineOffset;
197 aLevelRule["BulletChar"] >>= sBulletChar;
198 bHasFont = (aLevelRule["BulletFont"] >>= aBulletFont);
199 bHasColor = (aLevelRule["BulletColor"] >>= aBulletColor);
202 if (nNumberingType != css::style::NumberingType::BITMAP) // TODO
204 if (nPositionAndSpaceMode
205 == css::text::PositionAndSpaceMode::LABEL_WIDTH_AND_POSITION)
207 nIndentAt = nLeftMargin;
208 nFirstLineIndent = nFirstLineOffset;
209 nListtabStopPosition = nSymbolTextDistance;
210 nLabelFollowedBy = SvxNumberFormat::LabelFollowedBy::LISTTAB;
213 switch (nLabelFollowedBy)
215 case SvxNumberFormat::LabelFollowedBy::LISTTAB:
216 sLabelString += "\t";
217 break;
218 case SvxNumberFormat::LabelFollowedBy::SPACE:
219 sLabelString += " ";
220 break;
221 case SvxNumberFormat::LabelFollowedBy::NEWLINE:
222 sLabelString += "\n";
223 break;
226 css::uno::Reference<css::text::XTextRange> xNumberText(xRange->getStart());
227 xNumberText->setString(sLabelString);
228 css::uno::Reference<css::beans::XPropertySet> xNumberProps(
229 xNumberText, css::uno::UNO_QUERY_THROW);
230 if (!sCharStyleName.isEmpty())
231 xNumberProps->setPropertyValue("CharStyleName", css::uno::Any(sCharStyleName));
233 if (nNumberingType == css::style::NumberingType::CHAR_SPECIAL)
235 css::uno::Reference<css::text::XTextRange> xBulletText(xNumberText->getStart());
236 xBulletText->setString(sBulletChar);
238 std::unordered_map<OUString, css::uno::Any> aNameValues;
239 if (bHasFont)
241 aNameValues.insert({
242 { "CharFontName", css::uno::Any(aBulletFont.Name) },
243 { "CharFontStyleName", css::uno::Any(aBulletFont.StyleName) },
244 { "CharFontFamily", css::uno::Any(aBulletFont.Family) },
245 { "CharFontCharSet", css::uno::Any(aBulletFont.CharSet) },
246 { "CharWeight", css::uno::Any(aBulletFont.Weight) },
247 { "CharUnderline", css::uno::Any(aBulletFont.Underline) },
248 { "CharStrikeout", css::uno::Any(aBulletFont.Strikeout) },
249 { "CharAutoKerning", css::uno::Any(aBulletFont.Kerning) },
250 { "CharFontPitch", css::uno::Any(aBulletFont.Pitch) },
251 { "CharWordMode", css::uno::Any(aBulletFont.WordLineMode) },
252 { "CharRotation", css::uno::Any(static_cast<sal_Int16>(
253 std::round(aBulletFont.Orientation * 10))) },
255 if (aBulletFont.Height)
256 aNameValues["CharHeight"] <<= aBulletFont.Height;
258 if (bHasColor)
260 aNameValues["CharColor"] <<= aBulletColor;
263 if (css::uno::Reference<css::beans::XMultiPropertySet> xBulletMultiProps{
264 xBulletText, css::uno::UNO_QUERY })
266 xBulletMultiProps->setPropertyValues(
267 comphelper::mapKeysToSequence(aNameValues),
268 comphelper::mapValuesToSequence(aNameValues));
270 else
272 css::uno::Reference<css::beans::XPropertySet> xBulletProps(
273 xBulletText, css::uno::UNO_QUERY_THROW);
274 for (const auto& [rName, rVal] : aNameValues)
275 xBulletProps->setPropertyValue(rName, rVal);
278 else
280 // TODO: css::style::NumberingType::BITMAP
283 rPropertySet->setPropertyValue("ParaLeftMargin", css::uno::Any(nIndentAt));
284 rPropertySet->setPropertyValue("ParaFirstLineIndent", css::uno::Any(nFirstLineIndent));
285 if (nLabelFollowedBy == SvxNumberFormat::LabelFollowedBy::LISTTAB)
287 css::uno::Sequence<css::style::TabStop> stops;
288 rPropertySet->getPropertyValue("ParaTabStops") >>= stops;
289 css::style::TabStop tabStop{};
290 tabStop.Position = nListtabStopPosition;
291 tabStop.Alignment = com::sun::star::style::TabAlign::TabAlign_LEFT;
292 tabStop.FillChar = ' ';
293 rPropertySet->setPropertyValue("ParaTabStops",
294 css::uno::Any(comphelper::combineSequences({ tabStop }, stops)));
295 // FIXME: What if added tap stop is greater than already defined ones?
298 else
300 continue; // for now, keep such lists as is
303 // In case of higher outline levels, each assignment of empty value just sets level 1
304 while (rPropertySet->getPropertyValue("NumberingRules") != css::uno::Any())
306 rPropertySet->setPropertyValue("NumberingRules", css::uno::Any());
312 OUString
313 SwVbaListFormat::getServiceImplName()
315 return "SwVbaListFormat";
318 uno::Sequence< OUString >
319 SwVbaListFormat::getServiceNames()
321 static uno::Sequence< OUString > const aServiceNames
323 "ooo.vba.word.ListFormat"
325 return aServiceNames;
328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */