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