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/view/XSelectionSupplier.hpp>
28 #include <com/sun/star/style/XStyle.hpp>
29 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
30
31 #include <comphelper/sequence.hxx>
32 #include <sfx2/viewfrm.hxx>
33 #include <vcl/image.hxx>
34 #include <vcl/settings.hxx>
35 #include <vcl/virdev.hxx>
36
37 #include <tools/debug.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <svl/style.hxx>
40 #include <svl/stritem.hxx>
41 #include <sfx2/bindings.hxx>
42 #include <sfx2/app.hxx>
43 #include <sfx2/request.hxx>
44 #include <sfx2/dispatch.hxx>
45 #include <svx/svxids.hrc>
46 #include <svx/svdetc.hxx>
47 #include <editeng/boxitem.hxx>
48 #include <editeng/borderline.hxx>
49 #include <editeng/colritem.hxx>
50 #include <editeng/eeitem.hxx>
51 #include <svx/sdr/table/tabledesign.hxx>
52 #include <o3tl/enumrange.hxx>
53
54 #include <TableDesignPane.hxx>
55
56 #include <ViewShell.hxx>
57 #include <ViewShellBase.hxx>
58 #include <EventMultiplexer.hxx>
59
60 using namespace ::com::sun::star;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::drawing;
63 using namespace ::com::sun::star::container;
64 using namespace ::com::sun::star::beans;
65 using namespace ::com::sun::star::view;
66 using namespace ::com::sun::star::style;
67 using namespace ::com::sun::star::frame;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::ui;
70
71 namespace sd {
72
73 const sal_Int32 nPreviewColumns = 5;
74 const sal_Int32 nPreviewRows = 5;
75 const sal_Int32 nCellWidth = 12; // one pixel is shared with the next cell!
76 const sal_Int32 nCellHeight = 7; // one pixel is shared with the next cell!
77 const sal_Int32 nBitmapWidth = (nCellWidth * nPreviewColumns) - (nPreviewColumns - 1);
78 const sal_Int32 nBitmapHeight = (nCellHeight * nPreviewRows) - (nPreviewRows - 1);
79
80 const std::string_view gPropNames[CB_COUNT] =
81 {
82 "UseFirstRowStyle",
83 "UseLastRowStyle",
84 "UseBandingRowStyle",
85 "UseFirstColumnStyle",
86 "UseLastColumnStyle",
87 "UseBandingColumnStyle"
88 };
89
TableDesignWidget(weld::Builder & rBuilder,ViewShellBase & rBase)90 TableDesignWidget::TableDesignWidget(weld::Builder& rBuilder, ViewShellBase& rBase)
91 : mrBase(rBase)
92 , m_xValueSet(new TableValueSet(rBuilder.weld_scrolled_window("previewswin", true)))
93 , m_xValueSetWin(new weld::CustomWeld(rBuilder, "previews", *m_xValueSet))
94 {
95 m_xValueSet->SetStyle(m_xValueSet->GetStyle() | WB_NO_DIRECTSELECT | WB_FLATVALUESET | WB_ITEMBORDER);
96 m_xValueSet->SetExtraSpacing(8);
97 m_xValueSet->setModal(false);
98 m_xValueSet->SetColor();
99 m_xValueSet->SetSelectHdl(LINK(this, TableDesignWidget, implValueSetHdl));
100
101 for (sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i)
102 {
103 m_aCheckBoxes[i] = rBuilder.weld_check_button(OString(gPropNames[i].data(), gPropNames[i].size()));
104 m_aCheckBoxes[i]->connect_toggled(LINK(this, TableDesignWidget, implCheckBoxHdl));
105 }
106
107 // get current controller and initialize listeners
108 try
109 {
110 mxView.set(mrBase.GetController(), UNO_QUERY);
111 addListener();
112
113 Reference< XController > xController( mrBase.GetController(), UNO_SET_THROW );
114 Reference< XStyleFamiliesSupplier > xFamiliesSupp( xController->getModel(), UNO_QUERY_THROW );
115 Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
116 mxTableFamily.set( xFamilies->getByName( "table" ), UNO_QUERY_THROW );
117 }
118 catch (const Exception&)
119 {
120 TOOLS_WARN_EXCEPTION( "sd", "sd::CustomAnimationPane::CustomAnimationPane()" );
121 }
122
123 onSelectionChanged();
124 updateControls();
125 }
126
~TableDesignWidget()127 TableDesignWidget::~TableDesignWidget()
128 {
129 removeListener();
130 }
131
getBindings(ViewShellBase const & rBase)132 static SfxBindings* getBindings( ViewShellBase const & rBase )
133 {
134 if( rBase.GetMainViewShell() && rBase.GetMainViewShell()->GetViewFrame() )
135 return &rBase.GetMainViewShell()->GetViewFrame()->GetBindings();
136 else
137 return nullptr;
138 }
139
getDispatcher(ViewShellBase const & rBase)140 static SfxDispatcher* getDispatcher( ViewShellBase const & rBase )
141 {
142 if( rBase.GetMainViewShell() && rBase.GetMainViewShell()->GetViewFrame() )
143 return rBase.GetMainViewShell()->GetViewFrame()->GetDispatcher();
144 else
145 return nullptr;
146 }
147
IMPL_LINK_NOARG(TableDesignWidget,implValueSetHdl,ValueSet *,void)148 IMPL_LINK_NOARG(TableDesignWidget, implValueSetHdl, ValueSet*, void)
149 {
150 ApplyStyle();
151 }
152
ApplyStyle()153 void TableDesignWidget::ApplyStyle()
154 {
155 try
156 {
157 OUString sStyleName;
158 sal_Int32 nIndex = static_cast< sal_Int32 >( m_xValueSet->GetSelectedItemId() ) - 1;
159
160 if( (nIndex >= 0) && (nIndex < mxTableFamily->getCount()) )
161 {
162 Reference< XNameAccess > xNames( mxTableFamily, UNO_QUERY_THROW );
163 sStyleName = xNames->getElementNames()[nIndex];
164 }
165
166 if( sStyleName.isEmpty() )
167 return;
168
169 SdrView* pView = mrBase.GetDrawView();
170 if( mxSelectedTable.is() )
171 {
172 if( pView )
173 {
174 SfxRequest aReq( SID_TABLE_STYLE, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() );
175 aReq.AppendItem( SfxStringItem( SID_TABLE_STYLE, sStyleName ) );
176
177 const rtl::Reference< sdr::SelectionController >& xController( pView->getSelectionController() );
178 if( xController.is() )
179 xController->Execute( aReq );
180
181 SfxBindings* pBindings = getBindings( mrBase );
182 if( pBindings )
183 {
184 pBindings->Invalidate( SID_UNDO );
185 pBindings->Invalidate( SID_REDO );
186 }
187 }
188 }
189 else
190 {
191 SfxDispatcher* pDispatcher = getDispatcher( mrBase );
192 SfxStringItem aArg( SID_TABLE_STYLE, sStyleName );
193 pDispatcher->ExecuteList(SID_INSERT_TABLE, SfxCallMode::ASYNCHRON,
194 { &aArg });
195 }
196 }
197 catch( Exception& )
198 {
199 TOOLS_WARN_EXCEPTION( "sd", "TableDesignWidget::implValueSetHdl()");
200 }
201 }
202
IMPL_LINK_NOARG(TableDesignWidget,implCheckBoxHdl,weld::Toggleable &,void)203 IMPL_LINK_NOARG(TableDesignWidget, implCheckBoxHdl, weld::Toggleable&, void)
204 {
205 ApplyOptions();
206 FillDesignPreviewControl();
207 }
208
ApplyOptions()209 void TableDesignWidget::ApplyOptions()
210 {
211 static const sal_uInt16 gParamIds[CB_COUNT] =
212 {
213 ID_VAL_USEFIRSTROWSTYLE, ID_VAL_USELASTROWSTYLE, ID_VAL_USEBANDINGROWSTYLE,
214 ID_VAL_USEFIRSTCOLUMNSTYLE, ID_VAL_USELASTCOLUMNSTYLE, ID_VAL_USEBANDINGCOLUMNSTYLE
215 };
216
217 if( !mxSelectedTable.is() )
218 return;
219
220 SfxRequest aReq( SID_TABLE_STYLE_SETTINGS, SfxCallMode::SYNCHRON, SfxGetpApp()->GetPool() );
221
222 for( sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i )
223 {
224 aReq.AppendItem( SfxBoolItem( gParamIds[i], m_aCheckBoxes[i]->get_active() ) );
225 }
226
227 SdrView* pView = mrBase.GetDrawView();
228 if( !pView )
229 return;
230
231 const rtl::Reference< sdr::SelectionController >& xController( pView->getSelectionController() );
232 if( xController.is() )
233 {
234 xController->Execute( aReq );
235
236 SfxBindings* pBindings = getBindings( mrBase );
237 if( pBindings )
238 {
239 pBindings->Invalidate( SID_UNDO );
240 pBindings->Invalidate( SID_REDO );
241 }
242 }
243 }
244
onSelectionChanged()245 void TableDesignWidget::onSelectionChanged()
246 {
247 Reference< XPropertySet > xNewSelection;
248
249 if( mxView.is() ) try
250 {
251 Reference< XSelectionSupplier > xSel( mxView, UNO_QUERY_THROW );
252 Any aSel( xSel->getSelection() );
253 Sequence< XShape > xShapeSeq;
254 if( aSel >>= xShapeSeq )
255 {
256 if( xShapeSeq.getLength() == 1 )
257 aSel <<= xShapeSeq[0];
258 }
259 else
260 {
261 Reference< XShapes > xShapes( aSel, UNO_QUERY );
262 if( xShapes.is() && (xShapes->getCount() == 1) )
263 aSel = xShapes->getByIndex(0);
264 }
265
266 Reference< XShapeDescriptor > xDesc( aSel, UNO_QUERY );
267 if( xDesc.is() && ( xDesc->getShapeType() == "com.sun.star.drawing.TableShape" || xDesc->getShapeType() == "com.sun.star.presentation.TableShape" ) )
268 {
269 xNewSelection.set( xDesc, UNO_QUERY );
270 }
271 }
272 catch( Exception& )
273 {
274 TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::onSelectionChanged()" );
275 }
276
277 if( mxSelectedTable != xNewSelection )
278 {
279 mxSelectedTable = xNewSelection;
280 updateControls();
281 }
282 }
283
Resize()284 void TableValueSet::Resize()
285 {
286 ValueSet::Resize();
287 // Calculate the number of rows and columns.
288 if( GetItemCount() <= 0 )
289 return;
290
291 Size aValueSetSize = GetOutputSizePixel();
292
293 Image aImage = GetItemImage(GetItemId(0));
294 Size aItemSize = aImage.GetSizePixel();
295
296 aItemSize.AdjustHeight(10 );
297 int nColumnCount = (aValueSetSize.Width() - GetScrollWidth()) / aItemSize.Width();
298 if (nColumnCount < 1)
299 nColumnCount = 1;
300
301 int nRowCount = (GetItemCount() + nColumnCount - 1) / nColumnCount;
302 if (nRowCount < 1)
303 nRowCount = 1;
304
305 int nVisibleRowCount = (aValueSetSize.Height()+2) / aItemSize.Height();
306
307 SetColCount (static_cast<sal_uInt16>(nColumnCount));
308 SetLineCount (static_cast<sal_uInt16>(nRowCount));
309
310 if( !m_bModal )
311 {
312 WinBits nStyle = GetStyle() & ~WB_VSCROLL;
313 if( nRowCount > nVisibleRowCount )
314 {
315 nStyle |= WB_VSCROLL;
316 }
317 SetStyle( nStyle );
318 }
319 }
320
TableValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)321 TableValueSet::TableValueSet(std::unique_ptr<weld::ScrolledWindow> pScrolledWindow)
322 : ValueSet(std::move(pScrolledWindow))
323 , m_bModal(false)
324 {
325 }
326
StyleUpdated()327 void TableValueSet::StyleUpdated()
328 {
329 updateSettings();
330 }
331
updateSettings()332 void TableValueSet::updateSettings()
333 {
334 if( !m_bModal )
335 {
336 Color aColor = Application::GetSettings().GetStyleSettings().GetWindowColor();
337 SetColor(aColor);
338 SetExtraSpacing(8);
339 }
340 }
341
updateControls()342 void TableDesignWidget::updateControls()
343 {
344 static const bool gDefaults[CB_COUNT] = { true, false, true, false, false, false };
345
346 const bool bHasTable = mxSelectedTable.is();
347
348 for (sal_uInt16 i = CB_HEADER_ROW; i <= CB_BANDED_COLUMNS; ++i)
349 {
350 bool bUse = gDefaults[i];
351 if( bHasTable ) try
352 {
353 mxSelectedTable->getPropertyValue( OUString::createFromAscii(gPropNames[i]) ) >>= bUse;
354 }
355 catch( Exception& )
356 {
357 TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::updateControls()");
358 }
359 m_aCheckBoxes[i]->set_active(bUse);
360 m_aCheckBoxes[i]->set_sensitive(bHasTable);
361 }
362
363 FillDesignPreviewControl();
364 m_xValueSet->updateSettings();
365 m_xValueSet->Resize();
366
367 sal_uInt16 nSelection = 0;
368 if( mxSelectedTable.is() )
369 {
370 Reference< XNamed > xNamed( mxSelectedTable->getPropertyValue( "TableTemplate" ), UNO_QUERY );
371 if( xNamed.is() )
372 {
373 const OUString sStyleName( xNamed->getName() );
374
375 Reference< XNameAccess > xNames( mxTableFamily, UNO_QUERY );
376 if( xNames.is() )
377 {
378 Sequence< OUString > aNames( xNames->getElementNames() );
379 sal_Int32 nIndex = comphelper::findValue(aNames, sStyleName);
380 if (nIndex != -1)
381 nSelection = static_cast<sal_uInt16>(nIndex) + 1;
382 }
383 }
384 }
385 m_xValueSet->SelectItem( nSelection );
386 }
387
addListener()388 void TableDesignWidget::addListener()
389 {
390 Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,TableDesignWidget,EventMultiplexerListener) );
391 mrBase.GetEventMultiplexer()->AddEventListener( aLink );
392 }
393
removeListener()394 void TableDesignWidget::removeListener()
395 {
396 Link<tools::EventMultiplexerEvent&,void> aLink( LINK(this,TableDesignWidget,EventMultiplexerListener) );
397 mrBase.GetEventMultiplexer()->RemoveEventListener( aLink );
398 }
399
IMPL_LINK(TableDesignWidget,EventMultiplexerListener,tools::EventMultiplexerEvent &,rEvent,void)400 IMPL_LINK(TableDesignWidget,EventMultiplexerListener,
401 tools::EventMultiplexerEvent&, rEvent, void)
402 {
403 switch (rEvent.meEventId)
404 {
405 case EventMultiplexerEventId::CurrentPageChanged:
406 case EventMultiplexerEventId::EditViewSelection:
407 onSelectionChanged();
408 break;
409
410 case EventMultiplexerEventId::MainViewRemoved:
411 mxView.clear();
412 onSelectionChanged();
413 break;
414
415 case EventMultiplexerEventId::MainViewAdded:
416 mxView.set( mrBase.GetController(), UNO_QUERY );
417 onSelectionChanged();
418 break;
419
420 default: break;
421 }
422 }
423
424 namespace {
425
426 struct CellInfo
427 {
428 Color maCellColor;
429 Color maTextColor;
430 std::shared_ptr<SvxBoxItem> maBorder;
431
432 explicit CellInfo( const Reference< XStyle >& xStyle );
433 };
434
435 }
436
CellInfo(const Reference<XStyle> & xStyle)437 CellInfo::CellInfo( const Reference< XStyle >& xStyle )
438 : maBorder(std::make_shared<SvxBoxItem>(SDRATTR_TABLE_BORDER))
439 {
440 SfxStyleSheet* pStyleSheet = SfxUnoStyleSheet::getUnoStyleSheet( xStyle );
441 if( !pStyleSheet )
442 return;
443
444 SfxItemSet& rSet = pStyleSheet->GetItemSet();
445
446 // get style fill color
447 if( !GetDraftFillColor(rSet, maCellColor) )
448 maCellColor = COL_TRANSPARENT;
449
450 // get style text color
451 const SvxColorItem* pTextColor = rSet.GetItem(EE_CHAR_COLOR);
452 if( pTextColor )
453 maTextColor = pTextColor->GetValue();
454 else
455 maTextColor = COL_TRANSPARENT;
456
457 // get border
458 const SvxBoxItem* pBoxItem = rSet.GetItem( SDRATTR_TABLE_BORDER );
459 if( pBoxItem )
460 maBorder.reset(pBoxItem->Clone());
461 }
462
463 typedef std::vector< std::shared_ptr< CellInfo > > CellInfoVector;
464 typedef std::shared_ptr< CellInfo > CellInfoMatrix[nPreviewColumns * nPreviewRows];
465
466 namespace {
467
468 struct TableStyleSettings
469 {
470 bool mbUseFirstRow;
471 bool mbUseLastRow;
472 bool mbUseFirstColumn;
473 bool mbUseLastColumn;
474 bool mbUseRowBanding;
475 bool mbUseColumnBanding;
476
TableStyleSettingssd::__anon9d4f505e0211::TableStyleSettings477 TableStyleSettings()
478 : mbUseFirstRow(true)
479 , mbUseLastRow(false)
480 , mbUseFirstColumn(false)
481 , mbUseLastColumn(false)
482 , mbUseRowBanding(true)
483 , mbUseColumnBanding(false) {}
484 };
485
486 }
487
FillCellInfoVector(const Reference<XIndexAccess> & xTableStyle,CellInfoVector & rVector)488 static void FillCellInfoVector( const Reference< XIndexAccess >& xTableStyle, CellInfoVector& rVector )
489 {
490 DBG_ASSERT( xTableStyle.is() && (xTableStyle->getCount() == sdr::table::style_count ), "sd::FillCellInfoVector(), invalid table style!" );
491 if( !xTableStyle.is() )
492 return;
493
494 try
495 {
496 rVector.resize( sdr::table::style_count );
497
498 for( sal_Int32 nStyle = 0; nStyle < sdr::table::style_count; ++nStyle )
499 {
500 Reference< XStyle > xStyle( xTableStyle->getByIndex( nStyle ), UNO_QUERY );
501 if( xStyle.is() )
502 rVector[nStyle] = std::make_shared<CellInfo>( xStyle );
503 }
504 }
505 catch(Exception&)
506 {
507 TOOLS_WARN_EXCEPTION( "sd", "sd::FillCellInfoVector()");
508 }
509 }
510
FillCellInfoMatrix(const CellInfoVector & rStyle,const TableStyleSettings & rSettings,CellInfoMatrix & rMatrix)511 static void FillCellInfoMatrix( const CellInfoVector& rStyle, const TableStyleSettings& rSettings, CellInfoMatrix& rMatrix )
512 {
513 for( sal_Int32 nRow = 0; nRow < nPreviewColumns; ++nRow )
514 {
515 const bool bFirstRow = rSettings.mbUseFirstRow && (nRow == 0);
516 const bool bLastRow = rSettings.mbUseLastRow && (nRow == nPreviewColumns - 1);
517
518 for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol )
519 {
520 std::shared_ptr< CellInfo > xCellInfo;
521
522 // first and last row win first, if used and available
523 if( bFirstRow )
524 {
525 xCellInfo = rStyle[sdr::table::first_row_style];
526 }
527 else if( bLastRow )
528 {
529 xCellInfo = rStyle[sdr::table::last_row_style];
530 }
531
532 if( !xCellInfo )
533 {
534 // next come first and last column, if used and available
535 if( rSettings.mbUseFirstColumn && (nCol == 0) )
536 {
537 xCellInfo = rStyle[sdr::table::first_column_style];
538 }
539 else if( rSettings.mbUseLastColumn && (nCol == nPreviewColumns-1) )
540 {
541 xCellInfo = rStyle[sdr::table::last_column_style];
542 }
543 }
544
545 if( !xCellInfo )
546 {
547 if( rSettings.mbUseRowBanding )
548 {
549 if( (nRow & 1) == 0 )
550 {
551 xCellInfo = rStyle[sdr::table::even_rows_style];
552 }
553 else
554 {
555 xCellInfo = rStyle[sdr::table::odd_rows_style];
556 }
557 }
558 }
559
560 if( !xCellInfo )
561 {
562 if( rSettings.mbUseColumnBanding )
563 {
564 if( (nCol & 1) == 0 )
565 {
566 xCellInfo = rStyle[sdr::table::even_columns_style];
567 }
568 else
569 {
570 xCellInfo = rStyle[sdr::table::odd_columns_style];
571 }
572 }
573 }
574
575 if( !xCellInfo )
576 {
577 // use default cell style if non found yet
578 xCellInfo = rStyle[sdr::table::body_style];
579 }
580
581 rMatrix[(nCol * nPreviewColumns) + nRow] = xCellInfo;
582 }
583 }
584 }
585
CreateDesignPreview(const Reference<XIndexAccess> & xTableStyle,const TableStyleSettings & rSettings,bool bIsPageDark)586 static BitmapEx CreateDesignPreview( const Reference< XIndexAccess >& xTableStyle, const TableStyleSettings& rSettings, bool bIsPageDark )
587 {
588 CellInfoVector aCellInfoVector(sdr::table::style_count);
589 FillCellInfoVector( xTableStyle, aCellInfoVector );
590
591 CellInfoMatrix aMatrix;
592 FillCellInfoMatrix( aCellInfoVector, rSettings, aMatrix );
593
594 // bbbbbbbbbbbb w = 12 pixel
595 // bccccccccccb h = 7 pixel
596 // bccccccccccb b = border color
597 // bcttttttttcb c = cell color
598 // bccccccccccb t = text color
599 // bccccccccccb
600 // bbbbbbbbbbbb
601
602 ScopedVclPtr<VirtualDevice> pVirDev(VclPtr<VirtualDevice>::Create());
603 Size aBmpSize(nBitmapWidth, nBitmapHeight);
604 pVirDev->SetOutputSizePixel(aBmpSize);
605
606 pVirDev->SetBackground( bIsPageDark ? COL_BLACK : COL_WHITE );
607 pVirDev->Erase();
608
609 // first draw cell background and text line previews
610 sal_Int32 nY = 0;
611 sal_Int32 nRow;
612 for( nRow = 0; nRow < nPreviewRows; ++nRow, nY += nCellHeight-1 )
613 {
614 sal_Int32 nX = 0;
615 for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol, nX += nCellWidth-1 )
616 {
617 std::shared_ptr< CellInfo > xCellInfo(aMatrix[(nCol * nPreviewColumns) + nRow]);
618
619 Color aTextColor( COL_AUTO );
620 if( xCellInfo )
621 {
622 // fill cell background
623 const ::tools::Rectangle aRect( nX, nY, nX + nCellWidth - 1, nY + nCellHeight - 1 );
624
625 if( xCellInfo->maCellColor != COL_TRANSPARENT )
626 {
627 pVirDev->SetFillColor( xCellInfo->maCellColor );
628 pVirDev->DrawRect( aRect );
629 }
630
631 aTextColor = xCellInfo->maTextColor;
632 }
633
634 // draw text preview line
635 if( aTextColor == COL_AUTO )
636 aTextColor = bIsPageDark ? COL_WHITE : COL_BLACK;
637 pVirDev->SetLineColor( aTextColor );
638 const Point aPnt1( nX + 2, nY + ((nCellHeight - 1 ) >> 1) );
639 const Point aPnt2( nX + nCellWidth - 3, aPnt1.Y() );
640 pVirDev->DrawLine( aPnt1, aPnt2 );
641 }
642 }
643
644 // second draw border lines
645 nY = 0;
646 for( nRow = 0; nRow < nPreviewRows; ++nRow, nY += nCellHeight-1 )
647 {
648 sal_Int32 nX = 0;
649 for( sal_Int32 nCol = 0; nCol < nPreviewColumns; ++nCol, nX += nCellWidth-1 )
650 {
651 std::shared_ptr< CellInfo > xCellInfo(aMatrix[(nCol * nPreviewColumns) + nRow]);
652
653 if( xCellInfo )
654 {
655 const Point aPntTL( nX, nY );
656 const Point aPntTR( nX + nCellWidth - 1, nY );
657 const Point aPntBL( nX, nY + nCellHeight - 1 );
658 const Point aPntBR( nX + nCellWidth - 1, nY + nCellHeight - 1 );
659
660 sal_Int32 border_diffs[8] = { 0,-1, 0,1, -1,0, 1,0 };
661 sal_Int32* pDiff = &border_diffs[0];
662
663 // draw top border
664 for( SvxBoxItemLine nLine : o3tl::enumrange<SvxBoxItemLine>() )
665 {
666 const ::editeng::SvxBorderLine* pBorderLine = xCellInfo->maBorder->GetLine(nLine);
667 if( !pBorderLine || ((pBorderLine->GetOutWidth() == 0) && (pBorderLine->GetInWidth()==0)) )
668 continue;
669
670 sal_Int32 nBorderCol = nCol + *pDiff++;
671 sal_Int32 nBorderRow = nRow + *pDiff++;
672 if( (nBorderCol >= 0) && (nBorderCol < nPreviewColumns) && (nBorderRow >= 0) && (nBorderRow < nPreviewRows) )
673 {
674 // check border
675 std::shared_ptr< CellInfo > xBorderInfo(aMatrix[(nBorderCol * nPreviewColumns) + nBorderRow]);
676 if( xBorderInfo )
677 {
678 const ::editeng::SvxBorderLine* pBorderLine2 = xBorderInfo->maBorder->GetLine(static_cast<SvxBoxItemLine>(static_cast<int>(nLine)^1));
679 if( pBorderLine2 && pBorderLine2->HasPriority(*pBorderLine) )
680 continue; // other border line wins
681 }
682 }
683
684 pVirDev->SetLineColor( pBorderLine->GetColor() );
685 switch( nLine )
686 {
687 case SvxBoxItemLine::TOP: pVirDev->DrawLine( aPntTL, aPntTR ); break;
688 case SvxBoxItemLine::BOTTOM: pVirDev->DrawLine( aPntBL, aPntBR ); break;
689 case SvxBoxItemLine::LEFT: pVirDev->DrawLine( aPntTL, aPntBL ); break;
690 case SvxBoxItemLine::RIGHT: pVirDev->DrawLine( aPntTR, aPntBR ); break;
691 }
692 }
693 }
694 }
695 }
696
697 return pVirDev->GetBitmapEx(Point(0,0), aBmpSize);
698 }
699
FillDesignPreviewControl()700 void TableDesignWidget::FillDesignPreviewControl()
701 {
702 sal_uInt16 nSelectedItem = m_xValueSet->GetSelectedItemId();
703 m_xValueSet->Clear();
704 try
705 {
706 TableStyleSettings aSettings;
707 if( mxSelectedTable.is() )
708 {
709 aSettings.mbUseFirstRow = m_aCheckBoxes[CB_HEADER_ROW]->get_active();
710 aSettings.mbUseLastRow = m_aCheckBoxes[CB_TOTAL_ROW]->get_active();
711 aSettings.mbUseRowBanding = m_aCheckBoxes[CB_BANDED_ROWS]->get_active();
712 aSettings.mbUseFirstColumn = m_aCheckBoxes[CB_FIRST_COLUMN]->get_active();
713 aSettings.mbUseLastColumn = m_aCheckBoxes[CB_LAST_COLUMN]->get_active();
714 aSettings.mbUseColumnBanding = m_aCheckBoxes[CB_BANDED_COLUMNS]->get_active();
715 }
716
717 bool bIsPageDark = false;
718 if( mxView.is() )
719 {
720 Reference< XPropertySet > xPageSet( mxView->getCurrentPage(), UNO_QUERY );
721 if( xPageSet.is() )
722 {
723 xPageSet->getPropertyValue("IsBackgroundDark") >>= bIsPageDark;
724 }
725 }
726
727 sal_Int32 nCount = mxTableFamily->getCount();
728 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) try
729 {
730 Reference< XIndexAccess > xTableStyle( mxTableFamily->getByIndex( nIndex ), UNO_QUERY );
731 if( xTableStyle.is() )
732 m_xValueSet->InsertItem( sal::static_int_cast<sal_uInt16>( nIndex + 1 ), Image( CreateDesignPreview( xTableStyle, aSettings, bIsPageDark ) ) );
733 }
734 catch( Exception& )
735 {
736 TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::FillDesignPreviewControl()");
737 }
738 sal_Int32 nCols = 3;
739 sal_Int32 nRows = (nCount+2)/3;
740 m_xValueSet->SetColCount(nCols);
741 m_xValueSet->SetLineCount(nRows);
742 WinBits nStyle = m_xValueSet->GetStyle() & ~WB_VSCROLL;
743 m_xValueSet->SetStyle(nStyle);
744
745 m_xValueSet->SetOptimalSize();
746 weld::DrawingArea* pDrawingArea = m_xValueSet->GetDrawingArea();
747 Size aSize = pDrawingArea->get_preferred_size();
748 aSize.AdjustWidth(10 * nCols);
749 aSize.AdjustHeight(10 * nRows);
750 pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
751
752 m_xValueSet->Resize();
753 }
754 catch( Exception& )
755 {
756 TOOLS_WARN_EXCEPTION( "sd", "sd::TableDesignWidget::FillDesignPreviewControl()");
757 }
758 m_xValueSet->SelectItem(nSelectedItem);
759 }
760
761 }
762
763 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
764