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