/src/libreoffice/sd/source/ui/table/TableDesignPane.cxx
Line | Count | Source |
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 <sal/config.h> |
21 | | |
22 | | #include <string_view> |
23 | | |
24 | | #include <com/sun/star/beans/XPropertySet.hpp> |
25 | | #include <com/sun/star/drawing/XDrawView.hpp> |
26 | | #include <com/sun/star/frame/XController.hpp> |
27 | | #include <com/sun/star/lang/XSingleServiceFactory.hpp> |
28 | | #include <com/sun/star/util/XModifiable.hpp> |
29 | | #include <com/sun/star/view/XSelectionSupplier.hpp> |
30 | | #include <com/sun/star/style/XStyle.hpp> |
31 | | #include <com/sun/star/style/XStyleFamiliesSupplier.hpp> |
32 | | |
33 | | #include <comphelper/sequence.hxx> |
34 | | #include <sfx2/viewfrm.hxx> |
35 | | #include <vcl/commandevent.hxx> |
36 | | #include <vcl/image.hxx> |
37 | | #include <vcl/settings.hxx> |
38 | | #include <vcl/svapp.hxx> |
39 | | #include <vcl/virdev.hxx> |
40 | | #include <vcl/weld/Menu.hxx> |
41 | | #include <vcl/weld/ScrolledWindow.hxx> |
42 | | #include <vcl/weld/MessageDialog.hxx> |
43 | | |
44 | | #include <tools/debug.hxx> |
45 | | #include <comphelper/diagnose_ex.hxx> |
46 | | #include <svl/style.hxx> |
47 | | #include <svl/stritem.hxx> |
48 | | #include <sfx2/bindings.hxx> |
49 | | #include <sfx2/app.hxx> |
50 | | #include <sfx2/request.hxx> |
51 | | #include <sfx2/dispatch.hxx> |
52 | | #include <svx/svxids.hrc> |
53 | | #include <svx/svdetc.hxx> |
54 | | #include <svx/svxdlg.hxx> |
55 | | #include <editeng/boxitem.hxx> |
56 | | #include <editeng/borderline.hxx> |
57 | | #include <editeng/colritem.hxx> |
58 | | #include <editeng/eeitem.hxx> |
59 | | #include <svx/sdr/table/tabledesign.hxx> |
60 | | #include <svx/sdr/table/tablecontroller.hxx> |
61 | | #include <o3tl/enumrange.hxx> |
62 | | |
63 | | #include <TableDesignPane.hxx> |
64 | | |
65 | | #include <stlsheet.hxx> |
66 | | #include <strings.hrc> |
67 | | #include <sdresid.hxx> |
68 | | #include <bitmaps.hlst> |
69 | | #include <ViewShell.hxx> |
70 | | #include <ViewShellBase.hxx> |
71 | | #include <EventMultiplexer.hxx> |
72 | | #include <DrawController.hxx> |
73 | | |
74 | | using namespace ::com::sun::star; |
75 | | using namespace ::com::sun::star::uno; |
76 | | using namespace ::com::sun::star::drawing; |
77 | | using namespace ::com::sun::star::container; |
78 | | using namespace ::com::sun::star::beans; |
79 | | using namespace ::com::sun::star::view; |
80 | | using namespace ::com::sun::star::style; |
81 | | using namespace ::com::sun::star::frame; |
82 | | using namespace ::com::sun::star::lang; |
83 | | |
84 | | namespace sd { |
85 | | |
86 | | const sal_Int32 nPreviewColumns = 5; |
87 | | const sal_Int32 nPreviewRows = 5; |
88 | | const sal_Int32 nCellWidth = 12; // one pixel is shared with the next cell! |
89 | | const sal_Int32 nCellHeight = 7; // one pixel is shared with the next cell! |
90 | | const sal_Int32 nBitmapWidth = (nCellWidth * nPreviewColumns) - (nPreviewColumns - 1); |
91 | | const sal_Int32 nBitmapHeight = (nCellHeight * nPreviewRows) - (nPreviewRows - 1); |
92 | | |
93 | | const std::u16string_view gPropNames[CB_COUNT] = |
94 | | { |
95 | | u"UseFirstRowStyle", |
96 | | u"UseLastRowStyle", |
97 | | u"UseBandingRowStyle", |
98 | | u"UseFirstColumnStyle", |
99 | | u"UseLastColumnStyle", |
100 | | u"UseBandingColumnStyle" |
101 | | }; |
102 | | |
103 | | constexpr std::u16string_view aTableStyleBaseName = u"table"; |
104 | | |
105 | | TableDesignWidget::TableDesignWidget(weld::Builder& rBuilder, ViewShellBase& rBase) |
106 | 0 | : mrBase(rBase) |
107 | 0 | , m_xMenu(rBuilder.weld_menu(u"menu"_ustr)) |
108 | 0 | , m_xValueSet(new TableValueSet(rBuilder.weld_scrolled_window(u"previewswin"_ustr, true))) |
109 | 0 | , m_xValueSetWin(new weld::CustomWeld(rBuilder, u"previews"_ustr, *m_xValueSet)) |
110 | 0 | { |
111 | 0 | m_xValueSet->SetStyle(m_xValueSet->GetStyle() | WB_NO_DIRECTSELECT | WB_FLATVALUESET | WB_ITEMBORDER); |
112 | 0 | m_xValueSet->SetExtraSpacing(8); |
113 | 0 | m_xValueSet->setModal(false); |
114 | 0 | m_xValueSet->SetColor(); |
115 | 0 | m_xValueSet->SetSelectHdl(LINK(this, TableDesignWidget, implValueSetHdl)); |
116 | 0 | m_xValueSet->SetContextMenuHandler(LINK(this, TableDesignWidget, implContextMenuHandler)); |
117 | |
|
118 | 0 | for (sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i) |
119 | 0 | { |
120 | 0 | m_aCheckBoxes[i] = rBuilder.weld_check_button(OUString(gPropNames[i])); |
121 | 0 | m_aCheckBoxes[i]->connect_toggled(LINK(this, TableDesignWidget, implCheckBoxHdl)); |
122 | 0 | } |
123 | | |
124 | | // get current controller and initialize listeners |
125 | 0 | try |
126 | 0 | { |
127 | 0 | mxView = mrBase.GetDrawController(); |
128 | 0 | addListener(); |
129 | |
|
130 | 0 | DrawController* pController = mrBase.GetDrawController(); |
131 | 0 | if (pController) |
132 | 0 | { |
133 | 0 | Reference< XStyleFamiliesSupplier > xFamiliesSupp( pController->getModel(), UNO_QUERY_THROW ); |
134 | 0 | Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() ); |
135 | 0 | mxTableFamily.set( xFamilies->getByName( u"table"_ustr ), UNO_QUERY_THROW ); |
136 | 0 | mxCellFamily.set( xFamilies->getByName( u"cell"_ustr ), UNO_QUERY_THROW ); |
137 | 0 | } |
138 | 0 | } |
139 | 0 | catch (const Exception&) |
140 | 0 | { |
141 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::CustomAnimationPane()" ); |
142 | 0 | } |
143 | | |
144 | 0 | onSelectionChanged(); |
145 | 0 | updateControls(); |
146 | 0 | } |
147 | | |
148 | | TableDesignWidget::~TableDesignWidget() |
149 | 0 | { |
150 | 0 | removeListener(); |
151 | 0 | } |
152 | | |
153 | | void TableDesignWidget::setDocumentModified() |
154 | 0 | { |
155 | 0 | try |
156 | 0 | { |
157 | 0 | Reference<XController> xController(mrBase.GetController(), UNO_SET_THROW); |
158 | 0 | Reference<util::XModifiable> xModifiable(xController->getModel(), UNO_QUERY_THROW); |
159 | 0 | xModifiable->setModified(true); |
160 | 0 | } |
161 | 0 | catch (Exception&) |
162 | 0 | { |
163 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::setDocumentModified()"); |
164 | 0 | } |
165 | 0 | } |
166 | | |
167 | | IMPL_LINK(TableDesignWidget, implContextMenuHandler, const Point*, pPoint, void) |
168 | 0 | { |
169 | 0 | auto nClickedItemId = pPoint ? m_xValueSet->GetItemId(*pPoint) : m_xValueSet->GetSelectedItemId(); |
170 | |
|
171 | 0 | try |
172 | 0 | { |
173 | 0 | if (nClickedItemId > mxTableFamily->getCount()) |
174 | 0 | return; |
175 | | |
176 | 0 | if (nClickedItemId) |
177 | 0 | { |
178 | 0 | Reference<XStyle> xStyle(mxTableFamily->getByIndex(nClickedItemId - 1), UNO_QUERY_THROW); |
179 | |
|
180 | 0 | m_xMenu->set_visible(u"clone"_ustr, true); |
181 | 0 | m_xMenu->set_visible(u"format"_ustr, true); |
182 | 0 | m_xMenu->set_visible(u"delete"_ustr, xStyle->isUserDefined()); |
183 | 0 | m_xMenu->set_visible(u"reset"_ustr, !xStyle->isUserDefined()); |
184 | 0 | m_xMenu->set_sensitive(u"reset"_ustr, Reference<util::XModifiable>(xStyle, UNO_QUERY_THROW)->isModified()); |
185 | 0 | } |
186 | 0 | else |
187 | 0 | { |
188 | 0 | m_xMenu->set_visible(u"clone"_ustr, false); |
189 | 0 | m_xMenu->set_visible(u"format"_ustr, false); |
190 | 0 | m_xMenu->set_visible(u"delete"_ustr, false); |
191 | 0 | m_xMenu->set_visible(u"reset"_ustr, false); |
192 | 0 | } |
193 | 0 | } |
194 | 0 | catch (Exception&) |
195 | 0 | { |
196 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::implContextMenuHandler()"); |
197 | 0 | } |
198 | | |
199 | 0 | m_xValueSet->SelectItem(nClickedItemId); |
200 | |
|
201 | 0 | Point aPosition = pPoint ? *pPoint : m_xValueSet->GetItemRect(nClickedItemId).Center(); |
202 | 0 | OUString aCommand = m_xMenu->popup_at_rect(m_xValueSet->GetDrawingArea(), ::tools::Rectangle(aPosition, Size(1,1))); |
203 | |
|
204 | 0 | if (aCommand == "new") |
205 | 0 | InsertStyle(); |
206 | 0 | else if (aCommand == "clone") |
207 | 0 | CloneStyle(); |
208 | 0 | else if (aCommand == "delete") |
209 | 0 | DeleteStyle(); |
210 | 0 | else if (aCommand == "reset") |
211 | 0 | ResetStyle(); |
212 | 0 | else if (!aCommand.isEmpty()) |
213 | 0 | EditStyle(aCommand); |
214 | 0 | } |
215 | | |
216 | | namespace |
217 | | { |
218 | | OUString getNewStyleName(const Reference<XNameContainer>& rFamily, std::u16string_view rBaseName) |
219 | 0 | { |
220 | 0 | OUString aName(rBaseName); |
221 | 0 | sal_Int32 nIndex = 1; |
222 | 0 | while(rFamily->hasByName(aName)) |
223 | 0 | { |
224 | 0 | aName = rBaseName + OUString::number(nIndex++); |
225 | 0 | } |
226 | |
|
227 | 0 | return aName; |
228 | 0 | } |
229 | | } |
230 | | |
231 | | void TableDesignWidget::InsertStyle() |
232 | 0 | { |
233 | 0 | try |
234 | 0 | { |
235 | 0 | Reference<XSingleServiceFactory> xFactory(mxTableFamily, UNO_QUERY_THROW); |
236 | 0 | Reference<XNameContainer> xTableFamily(mxTableFamily, UNO_QUERY_THROW); |
237 | 0 | Reference<XNameReplace> xTableStyle(xFactory->createInstance(), UNO_QUERY_THROW); |
238 | 0 | const OUString aName(getNewStyleName(xTableFamily, aTableStyleBaseName)); |
239 | 0 | xTableFamily->insertByName(aName, Any(xTableStyle)); |
240 | |
|
241 | 0 | Reference<XStyle> xCellStyle(mxCellFamily->getByName(u"default"_ustr), UNO_QUERY_THROW); |
242 | |
|
243 | 0 | xTableStyle->replaceByName(u"body"_ustr, Any(xCellStyle)); |
244 | 0 | xTableStyle->replaceByName(u"odd-rows"_ustr , Any(xCellStyle)); |
245 | 0 | xTableStyle->replaceByName(u"odd-columns"_ustr , Any(xCellStyle)); |
246 | 0 | xTableStyle->replaceByName(u"first-row"_ustr , Any(xCellStyle)); |
247 | 0 | xTableStyle->replaceByName(u"first-column"_ustr , Any(xCellStyle)); |
248 | 0 | xTableStyle->replaceByName(u"last-row"_ustr , Any(xCellStyle)); |
249 | 0 | xTableStyle->replaceByName(u"last-column"_ustr , Any(xCellStyle)); |
250 | |
|
251 | 0 | updateControls(); |
252 | 0 | selectStyle(aName); |
253 | 0 | setDocumentModified(); |
254 | 0 | } |
255 | 0 | catch (Exception&) |
256 | 0 | { |
257 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::InsertStyle()"); |
258 | 0 | } |
259 | 0 | } |
260 | | |
261 | | void TableDesignWidget::CloneStyle() |
262 | 0 | { |
263 | 0 | try |
264 | 0 | { |
265 | 0 | Reference<XNameAccess> xSrcTableStyle(mxTableFamily->getByIndex(m_xValueSet->GetSelectedItemId() - 1), UNO_QUERY_THROW); |
266 | |
|
267 | 0 | Reference<XSingleServiceFactory> xFactory(mxTableFamily, UNO_QUERY_THROW); |
268 | 0 | Reference<XNameContainer> xTableFamily(mxTableFamily, UNO_QUERY_THROW); |
269 | 0 | Reference<XNameReplace> xDestTableStyle(xFactory->createInstance(), UNO_QUERY_THROW); |
270 | 0 | const OUString aName(getNewStyleName(xTableFamily, aTableStyleBaseName)); |
271 | 0 | xTableFamily->insertByName(aName, Any(xDestTableStyle)); |
272 | |
|
273 | 0 | auto aNames(xSrcTableStyle->getElementNames()); |
274 | 0 | for (const auto& name : aNames) |
275 | 0 | { |
276 | 0 | Reference<XStyle> xSrcCellStyle(xSrcTableStyle->getByName(name), UNO_QUERY); |
277 | 0 | if (xSrcCellStyle && xSrcCellStyle->isUserDefined()) |
278 | 0 | { |
279 | 0 | Reference<XSingleServiceFactory> xCellFactory(mxCellFamily, UNO_QUERY_THROW); |
280 | 0 | Reference<XStyle> xDestCellStyle(xCellFactory->createInstance(), UNO_QUERY_THROW); |
281 | 0 | xDestCellStyle->setParentStyle(xSrcCellStyle->getParentStyle()); |
282 | 0 | const OUString aStyleName(getNewStyleName(mxCellFamily, Concat2View(aName + "-" + name))); |
283 | 0 | mxCellFamily->insertByName(aStyleName, Any(xDestCellStyle)); |
284 | |
|
285 | 0 | rtl::Reference xSrcStyleSheet = static_cast<SdStyleSheet*>(xSrcCellStyle.get()); |
286 | 0 | rtl::Reference xDestStyleSheet = static_cast<SdStyleSheet*>(xDestCellStyle.get()); |
287 | |
|
288 | 0 | xDestStyleSheet->GetItemSet().Put(xSrcStyleSheet->GetItemSet()); |
289 | |
|
290 | 0 | xDestTableStyle->replaceByName(name, Any(xDestCellStyle)); |
291 | 0 | } |
292 | 0 | else |
293 | 0 | xDestTableStyle->replaceByName(name, Any(xSrcCellStyle)); |
294 | 0 | } |
295 | |
|
296 | 0 | updateControls(); |
297 | 0 | selectStyle(aName); |
298 | 0 | setDocumentModified(); |
299 | 0 | } |
300 | 0 | catch (Exception&) |
301 | 0 | { |
302 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::CloneStyle()"); |
303 | 0 | } |
304 | 0 | } |
305 | | |
306 | | void TableDesignWidget::ResetStyle() |
307 | 0 | { |
308 | 0 | try |
309 | 0 | { |
310 | 0 | Reference<XIndexReplace> xTableStyle(mxTableFamily->getByIndex(m_xValueSet->GetSelectedItemId() - 1), UNO_QUERY_THROW); |
311 | |
|
312 | 0 | for (sal_Int32 i = 0; i < xTableStyle->getCount(); ++i) |
313 | 0 | { |
314 | 0 | Reference<XStyle> xCellStyle(xTableStyle->getByIndex(i), UNO_QUERY); |
315 | 0 | while (xCellStyle && xCellStyle->isUserDefined() && !xCellStyle->getParentStyle().isEmpty()) |
316 | 0 | xCellStyle.set(mxCellFamily->getByName(xCellStyle->getParentStyle()), UNO_QUERY); |
317 | |
|
318 | 0 | xTableStyle->replaceByIndex(i, Any(xCellStyle)); |
319 | 0 | } |
320 | |
|
321 | 0 | endTextEditForStyle(xTableStyle); |
322 | 0 | Reference<util::XModifiable>(xTableStyle, UNO_QUERY_THROW)->setModified(false); |
323 | |
|
324 | 0 | updateControls(); |
325 | 0 | setDocumentModified(); |
326 | 0 | } |
327 | 0 | catch (Exception&) |
328 | 0 | { |
329 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::ResetStyle()"); |
330 | 0 | } |
331 | 0 | } |
332 | | |
333 | | void TableDesignWidget::DeleteStyle() |
334 | 0 | { |
335 | 0 | try |
336 | 0 | { |
337 | 0 | Reference<XStyle> xTableStyle(mxTableFamily->getByIndex(m_xValueSet->GetSelectedItemId() - 1), UNO_QUERY_THROW); |
338 | |
|
339 | 0 | if (xTableStyle->isInUse()) |
340 | 0 | { |
341 | 0 | std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog( |
342 | 0 | m_xValueSet->GetDrawingArea(), VclMessageType::Question, VclButtonsType::YesNo, SdResId(STR_REMOVE_TABLESTYLE))); |
343 | |
|
344 | 0 | if (xBox->run() != RET_YES) |
345 | 0 | return; |
346 | | |
347 | 0 | endTextEditForStyle(xTableStyle); |
348 | 0 | } |
349 | | |
350 | 0 | Reference<XNameContainer>(mxTableFamily, UNO_QUERY_THROW)->removeByName(xTableStyle->getName()); |
351 | |
|
352 | 0 | updateControls(); |
353 | 0 | setDocumentModified(); |
354 | 0 | } |
355 | 0 | catch (Exception&) |
356 | 0 | { |
357 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::DeleteStyle()"); |
358 | 0 | } |
359 | 0 | } |
360 | | |
361 | | void TableDesignWidget::EditStyle(const OUString& rCommand) |
362 | 0 | { |
363 | 0 | try |
364 | 0 | { |
365 | 0 | Reference<XNameReplace> xTableStyle(mxTableFamily->getByIndex(m_xValueSet->GetSelectedItemId() - 1), UNO_QUERY_THROW); |
366 | 0 | Reference<XStyle> xCellStyle(xTableStyle->getByName(rCommand), UNO_QUERY_THROW); |
367 | 0 | rtl::Reference xStyleSheet = static_cast<SdStyleSheet*>(xCellStyle.get()); |
368 | |
|
369 | 0 | bool bUserDefined = xStyleSheet->IsEditable(); |
370 | 0 | if (!bUserDefined) |
371 | 0 | { |
372 | 0 | Reference<XSingleServiceFactory> xFactory(mxCellFamily, UNO_QUERY_THROW); |
373 | 0 | xCellStyle.set(xFactory->createInstance(), UNO_QUERY_THROW); |
374 | 0 | xCellStyle->setParentStyle(xStyleSheet->getName()); |
375 | 0 | xStyleSheet = static_cast<SdStyleSheet*>(xCellStyle.get()); |
376 | 0 | } |
377 | |
|
378 | 0 | SfxItemSet aNewAttr(xStyleSheet->GetItemSet()); |
379 | | |
380 | | // merge drawing layer text distance items into SvxBoxItem used by the dialog |
381 | 0 | SvxBoxItem aBoxItem(sdr::table::SvxTableController::TextDistancesToSvxBoxItem(aNewAttr)); |
382 | 0 | aNewAttr.Put(aBoxItem); |
383 | | |
384 | | // inner borders do not apply to a cell style |
385 | 0 | SvxBoxInfoItem aBoxInfoItem(aNewAttr.Get(SDRATTR_TABLE_BORDER_INNER)); |
386 | 0 | aBoxInfoItem.SetTable(false); |
387 | 0 | aNewAttr.Put(aBoxInfoItem); |
388 | |
|
389 | 0 | SdrView* pDrawView = mrBase.GetDrawView(); |
390 | 0 | if (!pDrawView) |
391 | 0 | return; |
392 | | |
393 | 0 | SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); |
394 | 0 | ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact ? pFact->CreateSvxFormatCellsDialog( |
395 | 0 | mrBase.GetFrameWeld(), aNewAttr, pDrawView->GetModel(), true) : nullptr); |
396 | 0 | if (pDlg && pDlg->Execute() == RET_OK) |
397 | 0 | { |
398 | 0 | endTextEditForStyle(xTableStyle); |
399 | |
|
400 | 0 | if (!bUserDefined) |
401 | 0 | { |
402 | 0 | Reference<XNamed> xNamed(xTableStyle, UNO_QUERY_THROW); |
403 | 0 | const OUString aStyleName(getNewStyleName(mxCellFamily, Concat2View(xNamed->getName() + "-" + rCommand))); |
404 | 0 | mxCellFamily->insertByName(aStyleName, Any(xCellStyle)); |
405 | 0 | xTableStyle->replaceByName(rCommand, Any(xCellStyle)); |
406 | 0 | } |
407 | |
|
408 | 0 | SfxItemSet aNewSet(*pDlg->GetOutputItemSet()); |
409 | 0 | sdr::table::SvxTableController::SvxBoxItemToTextDistances(aBoxItem, aNewSet); |
410 | 0 | sdr::properties::CleanupFillProperties(aNewSet); |
411 | 0 | xStyleSheet->GetItemSet().Put(aNewSet); |
412 | 0 | xStyleSheet->Broadcast(SfxHint(SfxHintId::DataChanged)); |
413 | |
|
414 | 0 | updateControls(); |
415 | 0 | setDocumentModified(); |
416 | 0 | } |
417 | 0 | } |
418 | 0 | catch (Exception&) |
419 | 0 | { |
420 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::EditStyle()"); |
421 | 0 | } |
422 | 0 | } |
423 | | |
424 | | static SfxBindings* getBindings( ViewShellBase const & rBase ) |
425 | 0 | { |
426 | 0 | auto pViewShell = rBase.GetMainViewShell().get(); |
427 | 0 | if( !pViewShell ) |
428 | 0 | return nullptr; |
429 | 0 | auto pViewFrame = pViewShell->GetViewFrame(); |
430 | 0 | if( !pViewFrame ) |
431 | 0 | return nullptr; |
432 | 0 | return &pViewFrame->GetBindings(); |
433 | 0 | } |
434 | | |
435 | | static SfxDispatcher* getDispatcher( ViewShellBase const & rBase ) |
436 | 0 | { |
437 | 0 | auto pViewShell = rBase.GetMainViewShell().get(); |
438 | 0 | if( !pViewShell ) |
439 | 0 | return nullptr; |
440 | 0 | auto pViewFrame = pViewShell->GetViewFrame(); |
441 | 0 | if( !pViewFrame ) |
442 | 0 | return nullptr; |
443 | 0 | return pViewFrame->GetDispatcher(); |
444 | 0 | } |
445 | | |
446 | | IMPL_LINK_NOARG(TableDesignWidget, implValueSetHdl, ValueSet*, void) |
447 | 0 | { |
448 | 0 | ApplyStyle(); |
449 | 0 | } |
450 | | |
451 | | void TableDesignWidget::ApplyStyle() |
452 | 0 | { |
453 | 0 | try |
454 | 0 | { |
455 | 0 | OUString sStyleName; |
456 | 0 | sal_Int32 nIndex = static_cast< sal_Int32 >( m_xValueSet->GetSelectedItemId() ) - 1; |
457 | |
|
458 | 0 | if( (nIndex >= 0) && (nIndex < mxTableFamily->getCount()) ) |
459 | 0 | { |
460 | 0 | Reference< XNameAccess > xNames( mxTableFamily, UNO_QUERY_THROW ); |
461 | 0 | sStyleName = xNames->getElementNames()[nIndex]; |
462 | 0 | } |
463 | 0 | else if (nIndex == mxTableFamily->getCount()) |
464 | 0 | { |
465 | 0 | InsertStyle(); |
466 | 0 | return; |
467 | 0 | } |
468 | | |
469 | 0 | if( sStyleName.isEmpty() ) |
470 | 0 | return; |
471 | | |
472 | 0 | if( mxSelectedTable.is() ) |
473 | 0 | { |
474 | 0 | if (SdrView* pView = mrBase.GetDrawView()) |
475 | 0 | { |
476 | 0 | if (pView->IsTextEdit()) |
477 | 0 | pView->SdrEndTextEdit(); |
478 | |
|
479 | 0 | SfxRequest aReq( SID_TABLE_STYLE, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() ); |
480 | 0 | aReq.AppendItem( SfxStringItem( SID_TABLE_STYLE, sStyleName ) ); |
481 | |
|
482 | 0 | const rtl::Reference< sdr::SelectionController >& xController( pView->getSelectionController() ); |
483 | 0 | if( xController.is() ) |
484 | 0 | xController->Execute( aReq ); |
485 | |
|
486 | 0 | SfxBindings* pBindings = getBindings( mrBase ); |
487 | 0 | if( pBindings ) |
488 | 0 | { |
489 | 0 | pBindings->Invalidate( SID_UNDO ); |
490 | 0 | pBindings->Invalidate( SID_REDO ); |
491 | 0 | } |
492 | 0 | } |
493 | 0 | setDocumentModified(); |
494 | 0 | } |
495 | 0 | else |
496 | 0 | { |
497 | 0 | SfxDispatcher* pDispatcher = getDispatcher( mrBase ); |
498 | 0 | SfxStringItem aArg( SID_TABLE_STYLE, sStyleName ); |
499 | 0 | pDispatcher->ExecuteList(SID_INSERT_TABLE, SfxCallMode::ASYNCHRON, |
500 | 0 | { &aArg }); |
501 | 0 | } |
502 | 0 | } |
503 | 0 | catch( Exception& ) |
504 | 0 | { |
505 | 0 | TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::implValueSetHdl()"); |
506 | 0 | } |
507 | 0 | } |
508 | | |
509 | | IMPL_LINK_NOARG(TableDesignWidget, implCheckBoxHdl, weld::Toggleable&, void) |
510 | 0 | { |
511 | 0 | ApplyOptions(); |
512 | 0 | FillDesignPreviewControl(); |
513 | 0 | } |
514 | | |
515 | | void TableDesignWidget::ApplyOptions() |
516 | 0 | { |
517 | 0 | static const sal_uInt16 gParamIds[CB_COUNT] = |
518 | 0 | { |
519 | 0 | ID_VAL_USEFIRSTROWSTYLE, ID_VAL_USELASTROWSTYLE, ID_VAL_USEBANDINGROWSTYLE, |
520 | 0 | ID_VAL_USEFIRSTCOLUMNSTYLE, ID_VAL_USELASTCOLUMNSTYLE, ID_VAL_USEBANDINGCOLUMNSTYLE |
521 | 0 | }; |
522 | |
|
523 | 0 | if( !mxSelectedTable.is() ) |
524 | 0 | return; |
525 | | |
526 | 0 | SfxRequest aReq( SID_TABLE_STYLE_SETTINGS, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() ); |
527 | |
|
528 | 0 | for( sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i ) |
529 | 0 | { |
530 | 0 | aReq.AppendItem( SfxBoolItem( gParamIds[i], m_aCheckBoxes[i]->get_active() ) ); |
531 | 0 | } |
532 | |
|
533 | 0 | SdrView* pView = mrBase.GetDrawView(); |
534 | 0 | if( !pView ) |
535 | 0 | return; |
536 | | |
537 | 0 | const rtl::Reference< sdr::SelectionController >& xController( pView->getSelectionController() ); |
538 | 0 | if( xController.is() ) |
539 | 0 | { |
540 | 0 | xController->Execute( aReq ); |
541 | |
|
542 | 0 | SfxBindings* pBindings = getBindings( mrBase ); |
543 | 0 | if( pBindings ) |
544 | 0 | { |
545 | 0 | pBindings->Invalidate( SID_UNDO ); |
546 | 0 | pBindings->Invalidate( SID_REDO ); |
547 | 0 | } |
548 | 0 | } |
549 | 0 | setDocumentModified(); |
550 | 0 | } |
551 | | |
552 | | void TableDesignWidget::onSelectionChanged() |
553 | 0 | { |
554 | 0 | Reference< XPropertySet > xNewSelection; |
555 | |
|
556 | 0 | if( mxView.is() ) try |
557 | 0 | { |
558 | 0 | Any aSel( mxView->getSelection() ); |
559 | 0 | Sequence< XShape > xShapeSeq; |
560 | 0 | if( aSel >>= xShapeSeq ) |
561 | 0 | { |
562 | 0 | if( xShapeSeq.getLength() == 1 ) |
563 | 0 | aSel <<= xShapeSeq[0]; |
564 | 0 | } |
565 | 0 | else |
566 | 0 | { |
567 | 0 | Reference< XShapes > xShapes( aSel, UNO_QUERY ); |
568 | 0 | if( xShapes.is() && (xShapes->getCount() == 1) ) |
569 | 0 | aSel = xShapes->getByIndex(0); |
570 | 0 | } |
571 | |
|
572 | 0 | Reference< XShapeDescriptor > xDesc( aSel, UNO_QUERY ); |
573 | 0 | if( xDesc.is() && ( xDesc->getShapeType() == "com.sun.star.drawing.TableShape" || xDesc->getShapeType() == "com.sun.star.presentation.TableShape" ) ) |
574 | 0 | { |
575 | 0 | xNewSelection.set( xDesc, UNO_QUERY ); |
576 | 0 | } |
577 | 0 | } |
578 | 0 | catch( Exception& ) |
579 | 0 | { |
580 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::onSelectionChanged()" ); |
581 | 0 | } |
582 | | |
583 | 0 | if( mxSelectedTable != xNewSelection ) |
584 | 0 | { |
585 | 0 | mxSelectedTable = std::move(xNewSelection); |
586 | 0 | updateControls(); |
587 | 0 | } |
588 | 0 | } |
589 | | |
590 | | bool TableValueSet::Command(const CommandEvent& rEvent) |
591 | 0 | { |
592 | 0 | if (rEvent.GetCommand() != CommandEventId::ContextMenu) |
593 | 0 | return ValueSet::Command(rEvent); |
594 | | |
595 | 0 | maContextMenuHandler.Call(rEvent.IsMouseEvent() ? &rEvent.GetMousePosPixel() : nullptr); |
596 | 0 | return true; |
597 | 0 | } |
598 | | |
599 | | void TableValueSet::Resize() |
600 | 0 | { |
601 | 0 | ValueSet::Resize(); |
602 | | // Calculate the number of rows and columns. |
603 | 0 | if( GetItemCount() <= 0 ) |
604 | 0 | return; |
605 | | |
606 | 0 | Size aValueSetSize = GetOutputSizePixel(); |
607 | |
|
608 | 0 | Image aImage = GetItemImage(GetItemId(0)); |
609 | 0 | Size aItemSize = aImage.GetSizePixel(); |
610 | |
|
611 | 0 | aItemSize.AdjustHeight(10 ); |
612 | 0 | int nColumnCount = (aValueSetSize.Width() - GetScrollWidth()) / aItemSize.Width(); |
613 | 0 | if (nColumnCount < 1) |
614 | 0 | nColumnCount = 1; |
615 | |
|
616 | 0 | int nRowCount = (GetItemCount() + nColumnCount - 1) / nColumnCount; |
617 | 0 | if (nRowCount < 1) |
618 | 0 | nRowCount = 1; |
619 | |
|
620 | 0 | int nVisibleRowCount = std::min(nRowCount, getMaxRowCount()); |
621 | |
|
622 | 0 | SetColCount (static_cast<sal_uInt16>(nColumnCount)); |
623 | 0 | SetLineCount (static_cast<sal_uInt16>(nVisibleRowCount)); |
624 | |
|
625 | 0 | if( !m_bModal ) |
626 | 0 | { |
627 | 0 | WinBits nStyle = GetStyle() & ~WB_VSCROLL; |
628 | 0 | if( nRowCount > nVisibleRowCount ) |
629 | 0 | { |
630 | 0 | nStyle |= WB_VSCROLL; |
631 | 0 | } |
632 | 0 | SetStyle( nStyle ); |
633 | 0 | } |
634 | 0 | } |
635 | | |
636 | | TableValueSet::TableValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow) |
637 | 0 | : ValueSet(std::move(pScrolledWindow)) |
638 | 0 | , m_bModal(false) |
639 | 0 | { |
640 | 0 | } |
641 | | |
642 | | void TableValueSet::StyleUpdated() |
643 | 0 | { |
644 | 0 | updateSettings(); |
645 | 0 | } |
646 | | |
647 | | void TableValueSet::updateSettings() |
648 | 0 | { |
649 | 0 | if( !m_bModal ) |
650 | 0 | { |
651 | 0 | Color aColor = Application::GetSettings().GetStyleSettings().GetWindowColor(); |
652 | 0 | SetColor(aColor); |
653 | 0 | SetExtraSpacing(8); |
654 | 0 | } |
655 | 0 | } |
656 | | |
657 | | void TableDesignWidget::updateControls() |
658 | 0 | { |
659 | 0 | static const bool gDefaults[CB_COUNT] = { true, false, true, false, false, false }; |
660 | |
|
661 | 0 | const bool bHasTable = mxSelectedTable.is(); |
662 | |
|
663 | 0 | for (sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i) |
664 | 0 | { |
665 | 0 | bool bUse = gDefaults[i]; |
666 | 0 | if( bHasTable ) try |
667 | 0 | { |
668 | 0 | mxSelectedTable->getPropertyValue( OUString(gPropNames[i]) ) >>= bUse; |
669 | 0 | } |
670 | 0 | catch( Exception& ) |
671 | 0 | { |
672 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::updateControls()"); |
673 | 0 | } |
674 | 0 | m_aCheckBoxes[i]->set_active(bUse); |
675 | 0 | m_aCheckBoxes[i]->set_sensitive(bHasTable); |
676 | 0 | } |
677 | | |
678 | 0 | FillDesignPreviewControl(); |
679 | 0 | m_xValueSet->updateSettings(); |
680 | 0 | m_xValueSet->Resize(); |
681 | |
|
682 | 0 | if( mxSelectedTable.is() ) |
683 | 0 | { |
684 | 0 | Reference< XNamed > xNamed( mxSelectedTable->getPropertyValue( u"TableTemplate"_ustr ), UNO_QUERY ); |
685 | 0 | if( xNamed.is() ) |
686 | 0 | selectStyle(xNamed->getName()); |
687 | 0 | } |
688 | 0 | } |
689 | | |
690 | | void TableDesignWidget::selectStyle(std::u16string_view rStyle) |
691 | 0 | { |
692 | 0 | Reference< XNameAccess > xNames( mxTableFamily, UNO_QUERY ); |
693 | 0 | if( xNames.is() ) |
694 | 0 | { |
695 | 0 | Sequence< OUString > aNames( xNames->getElementNames() ); |
696 | 0 | sal_Int32 nIndex = comphelper::findValue(aNames, rStyle); |
697 | 0 | if (nIndex != -1) |
698 | 0 | m_xValueSet->SelectItem(static_cast<sal_uInt16>(nIndex) + 1); |
699 | 0 | } |
700 | 0 | } |
701 | | |
702 | | void TableDesignWidget::endTextEditForStyle(const Reference<XInterface>& rStyle) |
703 | 0 | { |
704 | 0 | if (!mxSelectedTable) |
705 | 0 | return; |
706 | | |
707 | 0 | Reference<XInterface> xTableStyle(mxSelectedTable->getPropertyValue(u"TableTemplate"_ustr), UNO_QUERY); |
708 | 0 | if (xTableStyle != rStyle) |
709 | 0 | return; |
710 | | |
711 | 0 | SdrView* pDrawView = mrBase.GetDrawView(); |
712 | 0 | if (pDrawView && pDrawView->IsTextEdit()) |
713 | 0 | pDrawView->SdrEndTextEdit(); |
714 | 0 | } |
715 | | |
716 | | void TableDesignWidget::addListener() |
717 | 0 | { |
718 | 0 | Link<sdtools::EventMultiplexerEvent&,void> aLink( LINK(this,TableDesignWidget,EventMultiplexerListener) ); |
719 | 0 | mrBase.GetEventMultiplexer()->AddEventListener( aLink ); |
720 | 0 | } |
721 | | |
722 | | void TableDesignWidget::removeListener() |
723 | 0 | { |
724 | 0 | Link<sdtools::EventMultiplexerEvent&,void> aLink( LINK(this,TableDesignWidget,EventMultiplexerListener) ); |
725 | 0 | mrBase.GetEventMultiplexer()->RemoveEventListener( aLink ); |
726 | 0 | } |
727 | | |
728 | | IMPL_LINK(TableDesignWidget,EventMultiplexerListener, |
729 | | sdtools::EventMultiplexerEvent&, rEvent, void) |
730 | 0 | { |
731 | 0 | switch (rEvent.meEventId) |
732 | 0 | { |
733 | 0 | case EventMultiplexerEventId::CurrentPageChanged: |
734 | 0 | case EventMultiplexerEventId::EditViewSelection: |
735 | 0 | onSelectionChanged(); |
736 | 0 | break; |
737 | | |
738 | 0 | case EventMultiplexerEventId::MainViewRemoved: |
739 | 0 | mxView.clear(); |
740 | 0 | onSelectionChanged(); |
741 | 0 | break; |
742 | | |
743 | 0 | case EventMultiplexerEventId::MainViewAdded: |
744 | 0 | mxView = mrBase.GetDrawController(); |
745 | 0 | onSelectionChanged(); |
746 | 0 | break; |
747 | | |
748 | 0 | default: break; |
749 | 0 | } |
750 | 0 | } |
751 | | |
752 | | namespace { |
753 | | |
754 | | struct CellInfo |
755 | | { |
756 | | Color maCellColor; |
757 | | Color maTextColor; |
758 | | std::shared_ptr<SvxBoxItem> maBorder; |
759 | | |
760 | | explicit CellInfo( const Reference< XStyle >& xStyle ); |
761 | | }; |
762 | | |
763 | | } |
764 | | |
765 | | CellInfo::CellInfo( const Reference< XStyle >& xStyle ) |
766 | 0 | : maBorder(std::make_shared<SvxBoxItem>(SDRATTR_TABLE_BORDER)) |
767 | 0 | { |
768 | 0 | SfxStyleSheet* pStyleSheet = SfxUnoStyleSheet::getUnoStyleSheet( xStyle ); |
769 | 0 | if( !pStyleSheet ) |
770 | 0 | return; |
771 | | |
772 | 0 | SfxItemSet& rSet = pStyleSheet->GetItemSet(); |
773 | | |
774 | | // get style fill color |
775 | 0 | maCellColor = GetDraftFillColor(rSet).value_or(COL_TRANSPARENT); |
776 | | |
777 | | // get style text color |
778 | 0 | const SvxColorItem* pTextColor = rSet.GetItem(EE_CHAR_COLOR); |
779 | 0 | if( pTextColor ) |
780 | 0 | maTextColor = pTextColor->GetValue(); |
781 | 0 | else |
782 | 0 | maTextColor = COL_TRANSPARENT; |
783 | | |
784 | | // get border |
785 | 0 | const SvxBoxItem* pBoxItem = rSet.GetItem( SDRATTR_TABLE_BORDER ); |
786 | 0 | if( pBoxItem ) |
787 | 0 | maBorder.reset(pBoxItem->Clone()); |
788 | 0 | } |
789 | | |
790 | | typedef std::vector< std::shared_ptr< CellInfo > > CellInfoVector; |
791 | | typedef std::shared_ptr< CellInfo > CellInfoMatrix[nPreviewColumns * nPreviewRows]; |
792 | | |
793 | | namespace { |
794 | | |
795 | | struct TableStyleSettings |
796 | | { |
797 | | bool mbUseFirstRow; |
798 | | bool mbUseLastRow; |
799 | | bool mbUseFirstColumn; |
800 | | bool mbUseLastColumn; |
801 | | bool mbUseRowBanding; |
802 | | bool mbUseColumnBanding; |
803 | | |
804 | | TableStyleSettings() |
805 | 0 | : mbUseFirstRow(true) |
806 | 0 | , mbUseLastRow(false) |
807 | 0 | , mbUseFirstColumn(false) |
808 | 0 | , mbUseLastColumn(false) |
809 | 0 | , mbUseRowBanding(true) |
810 | 0 | , mbUseColumnBanding(false) {} |
811 | | }; |
812 | | |
813 | | } |
814 | | |
815 | | static void FillCellInfoVector( const Reference< XIndexAccess >& xTableStyle, CellInfoVector& rVector ) |
816 | 0 | { |
817 | 0 | DBG_ASSERT( xTableStyle.is() && (xTableStyle->getCount() == sdr::table::style_count ), "sd::FillCellInfoVector(), invalid table style!" ); |
818 | 0 | if( !xTableStyle.is() ) |
819 | 0 | return; |
820 | | |
821 | 0 | try |
822 | 0 | { |
823 | 0 | rVector.resize( sdr::table::style_count ); |
824 | |
|
825 | 0 | for( sal_Int32 nStyle = 0; nStyle < sdr::table::style_count; ++nStyle ) |
826 | 0 | { |
827 | 0 | Reference< XStyle > xStyle( xTableStyle->getByIndex( nStyle ), UNO_QUERY ); |
828 | 0 | if( xStyle.is() ) |
829 | 0 | rVector[nStyle] = std::make_shared<CellInfo>( xStyle ); |
830 | 0 | } |
831 | 0 | } |
832 | 0 | catch(Exception&) |
833 | 0 | { |
834 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::FillCellInfoVector()"); |
835 | 0 | } |
836 | 0 | } |
837 | | |
838 | | static void FillCellInfoMatrix( const CellInfoVector& rStyle, const TableStyleSettings& rSettings, CellInfoMatrix& rMatrix ) |
839 | 0 | { |
840 | 0 | for( sal_Int32 nRow = 0; nRow < nPreviewColumns; ++nRow ) |
841 | 0 | { |
842 | 0 | const bool bFirstRow = rSettings.mbUseFirstRow && (nRow == 0); |
843 | 0 | const bool bLastRow = rSettings.mbUseLastRow && (nRow == nPreviewColumns - 1); |
844 | |
|
845 | 0 | for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol ) |
846 | 0 | { |
847 | 0 | std::shared_ptr< CellInfo > xCellInfo; |
848 | | |
849 | | // first and last row win first, if used and available |
850 | 0 | if( bFirstRow ) |
851 | 0 | { |
852 | 0 | xCellInfo = rStyle[sdr::table::first_row_style]; |
853 | 0 | } |
854 | 0 | else if( bLastRow ) |
855 | 0 | { |
856 | 0 | xCellInfo = rStyle[sdr::table::last_row_style]; |
857 | 0 | } |
858 | |
|
859 | 0 | if( !xCellInfo ) |
860 | 0 | { |
861 | | // next come first and last column, if used and available |
862 | 0 | if( rSettings.mbUseFirstColumn && (nCol == 0) ) |
863 | 0 | { |
864 | 0 | xCellInfo = rStyle[sdr::table::first_column_style]; |
865 | 0 | } |
866 | 0 | else if( rSettings.mbUseLastColumn && (nCol == nPreviewColumns-1) ) |
867 | 0 | { |
868 | 0 | xCellInfo = rStyle[sdr::table::last_column_style]; |
869 | 0 | } |
870 | 0 | } |
871 | |
|
872 | 0 | if( !xCellInfo ) |
873 | 0 | { |
874 | 0 | if( rSettings.mbUseRowBanding ) |
875 | 0 | { |
876 | 0 | if( (nRow & 1) == 0 ) |
877 | 0 | { |
878 | 0 | xCellInfo = rStyle[sdr::table::even_rows_style]; |
879 | 0 | } |
880 | 0 | else |
881 | 0 | { |
882 | 0 | xCellInfo = rStyle[sdr::table::odd_rows_style]; |
883 | 0 | } |
884 | 0 | } |
885 | 0 | } |
886 | |
|
887 | 0 | if( !xCellInfo ) |
888 | 0 | { |
889 | 0 | if( rSettings.mbUseColumnBanding ) |
890 | 0 | { |
891 | 0 | if( (nCol & 1) == 0 ) |
892 | 0 | { |
893 | 0 | xCellInfo = rStyle[sdr::table::even_columns_style]; |
894 | 0 | } |
895 | 0 | else |
896 | 0 | { |
897 | 0 | xCellInfo = rStyle[sdr::table::odd_columns_style]; |
898 | 0 | } |
899 | 0 | } |
900 | 0 | } |
901 | |
|
902 | 0 | if( !xCellInfo ) |
903 | 0 | { |
904 | | // use default cell style if non found yet |
905 | 0 | xCellInfo = rStyle[sdr::table::body_style]; |
906 | 0 | } |
907 | |
|
908 | 0 | rMatrix[(nCol * nPreviewColumns) + nRow] = std::move(xCellInfo); |
909 | 0 | } |
910 | 0 | } |
911 | 0 | } |
912 | | |
913 | | static Bitmap CreateDesignPreview( const Reference< XIndexAccess >& xTableStyle, const TableStyleSettings& rSettings, bool bIsPageDark ) |
914 | 0 | { |
915 | 0 | CellInfoVector aCellInfoVector(sdr::table::style_count); |
916 | 0 | FillCellInfoVector( xTableStyle, aCellInfoVector ); |
917 | |
|
918 | 0 | CellInfoMatrix aMatrix; |
919 | 0 | FillCellInfoMatrix( aCellInfoVector, rSettings, aMatrix ); |
920 | | |
921 | | // bbbbbbbbbbbb w = 12 pixel |
922 | | // bccccccccccb h = 7 pixel |
923 | | // bccccccccccb b = border color |
924 | | // bcttttttttcb c = cell color |
925 | | // bccccccccccb t = text color |
926 | | // bccccccccccb |
927 | | // bbbbbbbbbbbb |
928 | |
|
929 | 0 | ScopedVclPtr<VirtualDevice> pVirDev(VclPtr<VirtualDevice>::Create()); |
930 | 0 | Size aBmpSize(nBitmapWidth, nBitmapHeight); |
931 | 0 | pVirDev->SetOutputSizePixel(aBmpSize); |
932 | |
|
933 | 0 | pVirDev->SetBackground( bIsPageDark ? COL_BLACK : COL_WHITE ); |
934 | 0 | pVirDev->Erase(); |
935 | | |
936 | | // first draw cell background and text line previews |
937 | 0 | sal_Int32 nY = 0; |
938 | 0 | sal_Int32 nRow; |
939 | 0 | for( nRow = 0; nRow < nPreviewRows; ++nRow, nY += nCellHeight-1 ) |
940 | 0 | { |
941 | 0 | sal_Int32 nX = 0; |
942 | 0 | for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol, nX += nCellWidth-1 ) |
943 | 0 | { |
944 | 0 | std::shared_ptr< CellInfo > xCellInfo(aMatrix[(nCol * nPreviewColumns) + nRow]); |
945 | |
|
946 | 0 | Color aTextColor( COL_AUTO ); |
947 | 0 | if( xCellInfo ) |
948 | 0 | { |
949 | | // fill cell background |
950 | 0 | const ::tools::Rectangle aRect( nX, nY, nX + nCellWidth - 1, nY + nCellHeight - 1 ); |
951 | |
|
952 | 0 | if( xCellInfo->maCellColor != COL_TRANSPARENT ) |
953 | 0 | { |
954 | 0 | pVirDev->SetFillColor( xCellInfo->maCellColor ); |
955 | 0 | pVirDev->DrawRect( aRect ); |
956 | 0 | } |
957 | |
|
958 | 0 | aTextColor = xCellInfo->maTextColor; |
959 | 0 | } |
960 | | |
961 | | // draw text preview line |
962 | 0 | if( aTextColor == COL_AUTO ) |
963 | 0 | aTextColor = bIsPageDark ? COL_WHITE : COL_BLACK; |
964 | 0 | pVirDev->SetLineColor( aTextColor ); |
965 | 0 | const Point aPnt1( nX + 2, nY + ((nCellHeight - 1 ) >> 1) ); |
966 | 0 | const Point aPnt2( nX + nCellWidth - 3, aPnt1.Y() ); |
967 | 0 | pVirDev->DrawLine( aPnt1, aPnt2 ); |
968 | 0 | } |
969 | 0 | } |
970 | | |
971 | | // second draw border lines |
972 | 0 | nY = 0; |
973 | 0 | for( nRow = 0; nRow < nPreviewRows; ++nRow, nY += nCellHeight-1 ) |
974 | 0 | { |
975 | 0 | sal_Int32 nX = 0; |
976 | 0 | for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol, nX += nCellWidth-1 ) |
977 | 0 | { |
978 | 0 | std::shared_ptr< CellInfo > xCellInfo(aMatrix[(nCol * nPreviewColumns) + nRow]); |
979 | |
|
980 | 0 | if( xCellInfo ) |
981 | 0 | { |
982 | 0 | const Point aPntTL( nX, nY ); |
983 | 0 | const Point aPntTR( nX + nCellWidth - 1, nY ); |
984 | 0 | const Point aPntBL( nX, nY + nCellHeight - 1 ); |
985 | 0 | const Point aPntBR( nX + nCellWidth - 1, nY + nCellHeight - 1 ); |
986 | |
|
987 | 0 | sal_Int32 border_diffs[8] = { 0,-1, 0,1, -1,0, 1,0 }; |
988 | 0 | sal_Int32* pDiff = &border_diffs[0]; |
989 | | |
990 | | // draw top border |
991 | 0 | for( SvxBoxItemLine nLine : o3tl::enumrange<SvxBoxItemLine>() ) |
992 | 0 | { |
993 | 0 | const ::editeng::SvxBorderLine* pBorderLine = xCellInfo->maBorder->GetLine(nLine); |
994 | 0 | if( !pBorderLine || ((pBorderLine->GetOutWidth() == 0) && (pBorderLine->GetInWidth()==0)) ) |
995 | 0 | continue; |
996 | | |
997 | 0 | sal_Int32 nBorderCol = nCol + *pDiff++; |
998 | 0 | sal_Int32 nBorderRow = nRow + *pDiff++; |
999 | 0 | if( (nBorderCol >= 0) && (nBorderCol < nPreviewColumns) && (nBorderRow >= 0) && (nBorderRow < nPreviewRows) ) |
1000 | 0 | { |
1001 | | // check border |
1002 | 0 | std::shared_ptr< CellInfo > xBorderInfo(aMatrix[(nBorderCol * nPreviewColumns) + nBorderRow]); |
1003 | 0 | if( xBorderInfo ) |
1004 | 0 | { |
1005 | 0 | const ::editeng::SvxBorderLine* pBorderLine2 = xBorderInfo->maBorder->GetLine(static_cast<SvxBoxItemLine>(static_cast<int>(nLine)^1)); |
1006 | 0 | if( pBorderLine2 && pBorderLine2->HasPriority(*pBorderLine) ) |
1007 | 0 | continue; // other border line wins |
1008 | 0 | } |
1009 | 0 | } |
1010 | | |
1011 | 0 | pVirDev->SetLineColor( pBorderLine->GetColor() ); |
1012 | 0 | switch( nLine ) |
1013 | 0 | { |
1014 | 0 | case SvxBoxItemLine::TOP: pVirDev->DrawLine( aPntTL, aPntTR ); break; |
1015 | 0 | case SvxBoxItemLine::BOTTOM: pVirDev->DrawLine( aPntBL, aPntBR ); break; |
1016 | 0 | case SvxBoxItemLine::LEFT: pVirDev->DrawLine( aPntTL, aPntBL ); break; |
1017 | 0 | case SvxBoxItemLine::RIGHT: pVirDev->DrawLine( aPntTR, aPntBR ); break; |
1018 | 0 | } |
1019 | 0 | } |
1020 | 0 | } |
1021 | 0 | } |
1022 | 0 | } |
1023 | | |
1024 | 0 | return pVirDev->GetBitmap(Point(0,0), aBmpSize); |
1025 | 0 | } |
1026 | | |
1027 | | void TableDesignWidget::FillDesignPreviewControl() |
1028 | 0 | { |
1029 | 0 | sal_uInt16 nSelectedItem = m_xValueSet->GetSelectedItemId(); |
1030 | 0 | m_xValueSet->Clear(); |
1031 | 0 | try |
1032 | 0 | { |
1033 | 0 | TableStyleSettings aSettings; |
1034 | 0 | if( mxSelectedTable.is() ) |
1035 | 0 | { |
1036 | 0 | aSettings.mbUseFirstRow = m_aCheckBoxes[CB_HEADER_ROW]->get_active(); |
1037 | 0 | aSettings.mbUseLastRow = m_aCheckBoxes[CB_TOTAL_ROW]->get_active(); |
1038 | 0 | aSettings.mbUseRowBanding = m_aCheckBoxes[CB_BANDED_ROWS]->get_active(); |
1039 | 0 | aSettings.mbUseFirstColumn = m_aCheckBoxes[CB_FIRST_COLUMN]->get_active(); |
1040 | 0 | aSettings.mbUseLastColumn = m_aCheckBoxes[CB_LAST_COLUMN]->get_active(); |
1041 | 0 | aSettings.mbUseColumnBanding = m_aCheckBoxes[CB_BANDED_COLUMNS]->get_active(); |
1042 | 0 | } |
1043 | |
|
1044 | 0 | bool bIsPageDark = false; |
1045 | 0 | if( mxView.is() ) |
1046 | 0 | { |
1047 | 0 | Reference< XPropertySet > xPageSet( mxView->getCurrentPage(), UNO_QUERY ); |
1048 | 0 | if( xPageSet.is() ) |
1049 | 0 | { |
1050 | 0 | xPageSet->getPropertyValue(u"IsBackgroundDark"_ustr) >>= bIsPageDark; |
1051 | 0 | } |
1052 | 0 | } |
1053 | |
|
1054 | 0 | sal_Int32 nCount = mxTableFamily->getCount(); |
1055 | 0 | for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) try |
1056 | 0 | { |
1057 | 0 | Reference< XIndexAccess > xTableStyle( mxTableFamily->getByIndex( nIndex ), UNO_QUERY ); |
1058 | 0 | if( xTableStyle.is() ) |
1059 | 0 | m_xValueSet->InsertItem( sal::static_int_cast<sal_uInt16>( nIndex + 1 ), Image( CreateDesignPreview( xTableStyle, aSettings, bIsPageDark ) ) ); |
1060 | 0 | } |
1061 | 0 | catch( Exception& ) |
1062 | 0 | { |
1063 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::FillDesignPreviewControl()"); |
1064 | 0 | } |
1065 | 0 | m_xValueSet->InsertItem(++nCount, Image(StockImage::Yes, BMP_INSERT_TABLESTYLE), SdResId(STR_INSERT_TABLESTYLE)); |
1066 | |
|
1067 | 0 | sal_Int32 nCols = 3; |
1068 | 0 | sal_Int32 nRows = std::min<sal_Int32>((nCount+2)/3, TableValueSet::getMaxRowCount()); |
1069 | 0 | m_xValueSet->SetColCount(nCols); |
1070 | 0 | m_xValueSet->SetLineCount(nRows); |
1071 | 0 | WinBits nStyle = m_xValueSet->GetStyle() & ~WB_VSCROLL; |
1072 | 0 | m_xValueSet->SetStyle(nStyle); |
1073 | |
|
1074 | 0 | m_xValueSet->SetOptimalSize(); |
1075 | 0 | weld::DrawingArea* pDrawingArea = m_xValueSet->GetDrawingArea(); |
1076 | 0 | Size aSize = pDrawingArea->get_preferred_size(); |
1077 | 0 | aSize.AdjustWidth(10 * nCols); |
1078 | 0 | aSize.AdjustHeight(10 * nRows); |
1079 | 0 | pDrawingArea->set_size_request(aSize.Width(), aSize.Height()); |
1080 | |
|
1081 | 0 | m_xValueSet->Resize(); |
1082 | 0 | } |
1083 | 0 | catch( Exception& ) |
1084 | 0 | { |
1085 | 0 | TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::FillDesignPreviewControl()"); |
1086 | 0 | } |
1087 | 0 | m_xValueSet->SelectItem(nSelectedItem); |
1088 | 0 | } |
1089 | | |
1090 | | } |
1091 | | |
1092 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |