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 <sot/exchange.hxx>
23 #include <svx/strings.hrc>
24 #include <svx/svxids.hrc>
25
26 #include <sfx2/viewsh.hxx>
27 #include <sfx2/objsh.hxx>
28 #include <sfx2/dispatch.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <vcl/image.hxx>
31 #include <vcl/transfer.hxx>
32
33 #include <colrctrl.hxx>
34
35 #include <svx/svdview.hxx>
36 #include <svx/drawitem.hxx>
37 #include <svx/xfillit0.hxx>
38 #include <svx/xflclit.hxx>
39 #include <editeng/colritem.hxx>
40 #include <svx/xlineit0.hxx>
41 #include <svx/xlnclit.hxx>
42 #include <svx/xtable.hxx>
43 #include <svx/dialmgr.hxx>
44 #include <helpids.h>
45 #include <vcl/virdev.hxx>
46
47 #include <com/sun/star/beans/NamedValue.hpp>
48
49 using namespace com::sun::star;
50
51 class SvxColorValueSetData final : public TransferDataContainer
52 {
53 private:
54 uno::Sequence<beans::NamedValue> m_Data;
55
56 virtual void AddSupportedFormats() override;
57 virtual bool GetData(const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc) override;
58
59 public:
SvxColorValueSetData()60 SvxColorValueSetData()
61 {
62 }
63
SetData(const uno::Sequence<beans::NamedValue> & rData)64 void SetData(const uno::Sequence<beans::NamedValue>& rData)
65 {
66 m_Data = rData;
67 ClearFormats(); // invalidate m_aAny so new data will take effect
68 }
69 };
70
AddSupportedFormats()71 void SvxColorValueSetData::AddSupportedFormats()
72 {
73 AddFormat( SotClipboardFormatId::XFA );
74 }
75
GetData(const css::datatransfer::DataFlavor & rFlavor,const OUString &)76 bool SvxColorValueSetData::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
77 {
78 bool bRet = false;
79
80 if( SotExchange::GetFormat( rFlavor ) == SotClipboardFormatId::XFA )
81 {
82 SetAny(uno::makeAny(m_Data));
83 bRet = true;
84 }
85
86 return bRet;
87 }
88
SetDrawingArea(weld::DrawingArea * pDrawingArea)89 void SvxColorValueSet_docking::SetDrawingArea(weld::DrawingArea* pDrawingArea)
90 {
91 SvxColorValueSet::SetDrawingArea(pDrawingArea);
92 SetAccessibleName(SvxResId(STR_COLORTABLE));
93 SetStyle(GetStyle() | WB_ITEMBORDER);
94
95 m_xHelper.set(new SvxColorValueSetData);
96 rtl::Reference<TransferDataContainer> xHelper(m_xHelper);
97 SetDragDataTransferrable(xHelper, DND_ACTION_COPY);
98 }
99
SvxColorValueSet_docking(std::unique_ptr<weld::ScrolledWindow> xWindow)100 SvxColorValueSet_docking::SvxColorValueSet_docking(std::unique_ptr<weld::ScrolledWindow> xWindow)
101 : SvxColorValueSet(std::move(xWindow))
102 , mbLeftButton(true)
103 {
104 }
105
MouseButtonDown(const MouseEvent & rMEvt)106 bool SvxColorValueSet_docking::MouseButtonDown( const MouseEvent& rMEvt )
107 {
108 bool bRet;
109
110 // For Mac still handle differently!
111 if( rMEvt.IsLeft() )
112 {
113 mbLeftButton = true;
114 bRet = SvxColorValueSet::MouseButtonDown( rMEvt );
115 }
116 else
117 {
118 mbLeftButton = false;
119 MouseEvent aMEvt( rMEvt.GetPosPixel(),
120 rMEvt.GetClicks(),
121 rMEvt.GetMode(),
122 MOUSE_LEFT,
123 rMEvt.GetModifier() );
124 bRet = SvxColorValueSet::MouseButtonDown( aMEvt );
125 }
126
127 return bRet;
128 }
129
MouseButtonUp(const MouseEvent & rMEvt)130 bool SvxColorValueSet_docking::MouseButtonUp( const MouseEvent& rMEvt )
131 {
132 bool bRet;
133
134 // For Mac still handle differently!
135 if( rMEvt.IsLeft() )
136 {
137 mbLeftButton = true;
138 bRet = SvxColorValueSet::MouseButtonUp( rMEvt );
139 }
140 else
141 {
142 mbLeftButton = false;
143 MouseEvent aMEvt( rMEvt.GetPosPixel(),
144 rMEvt.GetClicks(),
145 rMEvt.GetMode(),
146 MOUSE_LEFT,
147 rMEvt.GetModifier() );
148 bRet = SvxColorValueSet::MouseButtonUp( aMEvt );
149 }
150 SetNoSelection();
151
152 return bRet;
153 }
154
StartDrag()155 bool SvxColorValueSet_docking::StartDrag()
156 {
157 sal_uInt16 nPos = GetSelectedItemId();
158 Color aItemColor( GetItemColor( nPos ) );
159 OUString sItemText( GetItemText( nPos ) );
160
161 drawing::FillStyle eStyle = ((1 == nPos)
162 ? drawing::FillStyle_NONE
163 : drawing::FillStyle_SOLID);
164
165 uno::Sequence<beans::NamedValue> props(2);
166 XFillColorItem const color(sItemText, aItemColor);
167 props[0].Name = "FillColor";
168 color.QueryValue(props[0].Value, 0);
169 XFillStyleItem const style(eStyle);
170 props[1].Name = "FillStyle";
171 style.QueryValue(props[1].Value, 0);
172
173 m_xHelper->SetData(props);
174
175 return false;
176 }
177
178 constexpr sal_uInt16 gnLeftSlot = SID_ATTR_FILL_COLOR;
179 constexpr sal_uInt16 gnRightSlot = SID_ATTR_LINE_COLOR;
180
SvxColorDockingWindow(SfxBindings * _pBindings,SfxChildWindow * pCW,vcl::Window * _pParent)181 SvxColorDockingWindow::SvxColorDockingWindow(SfxBindings* _pBindings, SfxChildWindow* pCW, vcl::Window* _pParent)
182 : SfxDockingWindow(_pBindings, pCW, _pParent,
183 "DockingColorWindow", "svx/ui/dockingcolorwindow.ui")
184 , pColorList()
185 , xColorSet(new SvxColorValueSet_docking(m_xBuilder->weld_scrolled_window("valuesetwin", true)))
186 , xColorSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *xColorSet))
187 {
188 SetText(SvxResId(STR_COLORTABLE));
189 SetQuickHelpText(SvxResId(RID_SVXSTR_COLORBAR));
190 SetSizePixel(LogicToPixel(Size(150, 22), MapMode(MapUnit::MapAppFont)));
191 SetHelpId(HID_CTRL_COLOR);
192
193 xColorSet->SetSelectHdl( LINK( this, SvxColorDockingWindow, SelectHdl ) );
194 xColorSet->SetHelpId(HID_COLOR_CTL_COLORS);
195
196 // Get the model from the view shell. Using SfxObjectShell::Current()
197 // is unreliable when called at the wrong times.
198 SfxObjectShell* pDocSh = nullptr;
199 if (_pBindings != nullptr)
200 {
201 SfxDispatcher* pDispatcher = _pBindings->GetDispatcher();
202 if (pDispatcher != nullptr)
203 {
204 SfxViewFrame* pFrame = pDispatcher->GetFrame();
205 if (pFrame != nullptr)
206 {
207 SfxViewShell* pViewShell = pFrame->GetViewShell();
208 if (pViewShell != nullptr)
209 pDocSh = pViewShell->GetObjectShell();
210 }
211 }
212 }
213
214 if ( pDocSh )
215 {
216 const SfxPoolItem* pItem = pDocSh->GetItem( SID_COLOR_TABLE );
217 if( pItem )
218 {
219 pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
220 FillValueSet();
221 }
222 }
223
224 Size aItemSize = xColorSet->CalcItemSizePixel(Size(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength()));
225 aItemSize.setWidth( aItemSize.Width() + SvxColorValueSet::getEntryEdgeLength() );
226 aItemSize.setWidth( aItemSize.Width() / 2 );
227 aItemSize.setHeight( aItemSize.Height() + SvxColorValueSet::getEntryEdgeLength() );
228 aItemSize.setHeight( aItemSize.Height() / 2 );
229
230 if (_pBindings != nullptr)
231 StartListening(*_pBindings, DuplicateHandling::Prevent);
232 }
233
~SvxColorDockingWindow()234 SvxColorDockingWindow::~SvxColorDockingWindow()
235 {
236 disposeOnce();
237 }
238
dispose()239 void SvxColorDockingWindow::dispose()
240 {
241 EndListening( GetBindings() );
242 xColorSetWin.reset();
243 xColorSet.reset();
244 SfxDockingWindow::dispose();
245 }
246
Notify(SfxBroadcaster &,const SfxHint & rHint)247 void SvxColorDockingWindow::Notify( SfxBroadcaster& , const SfxHint& rHint )
248 {
249 const SfxPoolItemHint* pPoolItemHint = dynamic_cast<const SfxPoolItemHint*>(&rHint);
250 if ( pPoolItemHint )
251 if (auto pColorListItem = dynamic_cast<const SvxColorListItem*>(pPoolItemHint->GetObject()))
252 {
253 // The list of colors has changed
254 pColorList = pColorListItem->GetColorList();
255 FillValueSet();
256 }
257 }
258
FillValueSet()259 void SvxColorDockingWindow::FillValueSet()
260 {
261 if( !pColorList.is() )
262 return;
263
264 xColorSet->Clear();
265
266 xColorSet->addEntriesForXColorList(*pColorList, 2);
267
268 // create the last entry for 'invisible/none'
269 const Size aColorSize(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength());
270 tools::Long nPtX = aColorSize.Width() - 1;
271 tools::Long nPtY = aColorSize.Height() - 1;
272 ScopedVclPtrInstance< VirtualDevice > pVD;
273
274 pVD->SetOutputSizePixel( aColorSize );
275 pVD->SetLineColor( COL_BLACK );
276 pVD->SetBackground( Wallpaper( COL_WHITE ) );
277 pVD->DrawLine( Point(), Point( nPtX, nPtY ) );
278 pVD->DrawLine( Point( 0, nPtY ), Point( nPtX, 0 ) );
279
280 BitmapEx aBmp( pVD->GetBitmapEx( Point(), aColorSize ) );
281
282 xColorSet->InsertItem( sal_uInt16(1), Image(aBmp), SvxResId( RID_SVXSTR_INVISIBLE ) );
283 }
284
Close()285 bool SvxColorDockingWindow::Close()
286 {
287 SfxBoolItem aItem( SID_COLOR_CONTROL, false );
288 GetBindings().GetDispatcher()->ExecuteList(SID_COLOR_CONTROL,
289 SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem });
290 SfxDockingWindow::Close();
291 return true;
292 }
293
IMPL_LINK_NOARG(SvxColorDockingWindow,SelectHdl,ValueSet *,void)294 IMPL_LINK_NOARG(SvxColorDockingWindow, SelectHdl, ValueSet*, void)
295 {
296 SfxDispatcher* pDispatcher = GetBindings().GetDispatcher();
297 sal_uInt16 nPos = xColorSet->GetSelectedItemId();
298 Color aColor( xColorSet->GetItemColor( nPos ) );
299 OUString aStr( xColorSet->GetItemText( nPos ) );
300
301 if (xColorSet->IsLeftButton())
302 {
303 if ( gnLeftSlot == SID_ATTR_FILL_COLOR )
304 {
305 if ( nPos == 1 ) // invisible
306 {
307 XFillStyleItem aXFillStyleItem( drawing::FillStyle_NONE );
308 pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
309 { &aXFillStyleItem });
310 }
311 else
312 {
313 bool bDone = false;
314
315 // If we have a DrawView and we are in TextEdit mode, then
316 // not the area color but the text color is assigned
317 SfxViewShell* pViewSh = SfxViewShell::Current();
318 if ( pViewSh )
319 {
320 SdrView* pView = pViewSh->GetDrawView();
321 if ( pView && pView->IsTextEdit() )
322 {
323 SvxColorItem aTextColorItem( aColor, SID_ATTR_CHAR_COLOR );
324 pDispatcher->ExecuteList(SID_ATTR_CHAR_COLOR,
325 SfxCallMode::RECORD, { &aTextColorItem });
326 bDone = true;
327 }
328 }
329 if ( !bDone )
330 {
331 XFillStyleItem aXFillStyleItem( drawing::FillStyle_SOLID );
332 XFillColorItem aXFillColorItem( aStr, aColor );
333 pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
334 { &aXFillColorItem, &aXFillStyleItem });
335 }
336 }
337 }
338 else if ( nPos != 1 ) // invisible
339 {
340 SvxColorItem aLeftColorItem( aColor, gnLeftSlot );
341 pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
342 { &aLeftColorItem });
343 }
344 }
345 else
346 {
347 if ( gnRightSlot == SID_ATTR_LINE_COLOR )
348 {
349 if( nPos == 1 ) // invisible
350 {
351 XLineStyleItem aXLineStyleItem( drawing::LineStyle_NONE );
352 pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
353 { &aXLineStyleItem });
354 }
355 else
356 {
357 // If the LineStyle is invisible, it is set to SOLID
358 SfxViewShell* pViewSh = SfxViewShell::Current();
359 if ( pViewSh )
360 {
361 SdrView* pView = pViewSh->GetDrawView();
362 if ( pView )
363 {
364 SfxItemSet aAttrSet( pView->GetModel()->GetItemPool() );
365 pView->GetAttributes( aAttrSet );
366 if ( aAttrSet.GetItemState( XATTR_LINESTYLE ) != SfxItemState::DONTCARE )
367 {
368 drawing::LineStyle eXLS =
369 aAttrSet.Get( XATTR_LINESTYLE ).GetValue();
370 if ( eXLS == drawing::LineStyle_NONE )
371 {
372 XLineStyleItem aXLineStyleItem( drawing::LineStyle_SOLID );
373 pDispatcher->ExecuteList(gnRightSlot,
374 SfxCallMode::RECORD, { &aXLineStyleItem });
375 }
376 }
377 }
378 }
379
380 XLineColorItem aXLineColorItem( aStr, aColor );
381 pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
382 { &aXLineColorItem });
383 }
384 }
385 else if ( nPos != 1 ) // invisible
386 {
387 SvxColorItem aRightColorItem( aColor, gnRightSlot );
388 pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
389 { &aRightColorItem });
390 }
391 }
392 }
393
GetFocus()394 void SvxColorDockingWindow::GetFocus()
395 {
396 SfxDockingWindow::GetFocus();
397 if (xColorSet)
398 {
399 // Grab the focus to the color value set so that it can be controlled
400 // with the keyboard.
401 xColorSet->GrabFocus();
402 }
403 }
404
EventNotify(NotifyEvent & rNEvt)405 bool SvxColorDockingWindow::EventNotify( NotifyEvent& rNEvt )
406 {
407 bool bRet = false;
408 if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
409 {
410 KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
411 sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode();
412 switch( nKeyCode )
413 {
414 case KEY_ESCAPE:
415 GrabFocusToDocument();
416 bRet = true;
417 break;
418 }
419 }
420
421 return bRet || SfxDockingWindow::EventNotify(rNEvt);
422 }
423
424 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
425