LibreOffice Module svx (master)  1
colrctrl.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 <sot/exchange.hxx>
23 #include <sot/storage.hxx>
24 #include <svx/strings.hrc>
25 #include <svx/svxids.hrc>
26 
27 #include <sfx2/viewsh.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/dispatch.hxx>
30 #include <sfx2/viewfrm.hxx>
31 #include <vcl/image.hxx>
32 
33 #include <svx/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/svapp.hxx>
46 #include <vcl/virdev.hxx>
47 
48 #include <com/sun/star/beans/NamedValue.hpp>
49 
50 using namespace com::sun::star;
51 
52 namespace {
53 
54 class SvxColorValueSetData : public TransferableHelper
55 {
56 private:
57 
58  uno::Sequence<beans::NamedValue> m_Data;
59 
60 protected:
61 
62  virtual void AddSupportedFormats() override;
63  virtual bool GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& rDestDoc ) override;
64 
65 public:
66 
67  explicit SvxColorValueSetData(const uno::Sequence<beans::NamedValue>& rProps)
68  : m_Data(rProps)
69  {}
70 };
71 
72 }
73 
74 void SvxColorValueSetData::AddSupportedFormats()
75 {
76  AddFormat( SotClipboardFormatId::XFA );
77 }
78 
79 bool SvxColorValueSetData::GetData( const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
80 {
81  bool bRet = false;
82 
83  if( SotExchange::GetFormat( rFlavor ) == SotClipboardFormatId::XFA )
84  {
85  SetAny(uno::makeAny(m_Data));
86  bRet = true;
87  }
88 
89  return bRet;
90 }
91 
93  SvxColorValueSet( _pParent, WB_ITEMBORDER ),
94  DragSourceHelper( this ),
95  mbLeftButton(true)
96 {
97  SetAccessibleName(SvxResId(STR_COLORTABLE));
98 }
99 
101 {
102  // For Mac still handle differently!
103  if( rMEvt.IsLeft() )
104  {
105  mbLeftButton = true;
107  }
108  else
109  {
110  mbLeftButton = false;
111  MouseEvent aMEvt( rMEvt.GetPosPixel(),
112  rMEvt.GetClicks(),
113  rMEvt.GetMode(),
114  MOUSE_LEFT,
115  rMEvt.GetModifier() );
117  }
118 
119  aDragPosPixel = GetPointerPosPixel();
120 }
121 
123 {
124  // For Mac still handle differently!
125  if( rMEvt.IsLeft() )
126  {
127  mbLeftButton = true;
129  }
130  else
131  {
132  mbLeftButton = false;
133  MouseEvent aMEvt( rMEvt.GetPosPixel(),
134  rMEvt.GetClicks(),
135  rMEvt.GetMode(),
136  MOUSE_LEFT,
137  rMEvt.GetModifier() );
139  }
140  SetNoSelection();
141 }
142 
144 {
145  Application::PostUserEvent(LINK(this, SvxColorValueSet_docking, ExecDragHdl), nullptr, true);
146 }
147 
149 {
151  sal_uInt16 nItemId = GetItemId( aDragPosPixel );
152 
153  if( pDocSh && nItemId )
154  {
155  uno::Sequence<beans::NamedValue> props(2);
156  XFillColorItem const color(GetItemText(nItemId), GetItemColor(nItemId));
157  props[0].Name = "FillColor";
158  color.QueryValue(props[0].Value, 0);
159  XFillStyleItem const style((1 == nItemId)
160  ? drawing::FillStyle_NONE
161  : drawing::FillStyle_SOLID);
162  props[1].Name = "FillStyle";
163  style.QueryValue(props[1].Value, 0);
164 
165  EndSelection();
166  ( new SvxColorValueSetData(props) )->StartDrag( this, DND_ACTION_COPY );
167  ReleaseMouse();
168  }
169 }
170 
171 IMPL_LINK_NOARG(SvxColorValueSet_docking, ExecDragHdl, void*, void)
172 {
173  // As a link, so that asynchronously without ImpMouseMoveMsg on the
174  // stack the color bar may also be deleted
175  DoDrag();
176 }
177 
178 static constexpr sal_uInt16 gnLeftSlot = SID_ATTR_FILL_COLOR;
179 static constexpr sal_uInt16 gnRightSlot = SID_ATTR_LINE_COLOR;
180 
182 (
183  SfxBindings* _pBindings,
184  SfxChildWindow* pCW,
185  vcl::Window* _pParent
186 ) :
187 
188  SfxDockingWindow( _pBindings, pCW, _pParent, WB_MOVEABLE|WB_CLOSEABLE|WB_SIZEABLE|WB_DOCKABLE ),
189  pColorList (),
190  aColorSet ( VclPtr<SvxColorValueSet_docking>::Create(this) ),
191  nCols ( 20 ),
192  nLines ( 1 ),
193  nCount ( 0 )
194 {
195  SetText(SvxResId(STR_COLORTABLE));
196  SetQuickHelpText(SvxResId(RID_SVXSTR_COLORBAR));
197  SetSizePixel(LogicToPixel(Size(150, 22), MapMode(MapUnit::MapAppFont)));
198  SetHelpId(HID_CTRL_COLOR);
199 
200  aColorSet->SetSelectHdl( LINK( this, SvxColorDockingWindow, SelectHdl ) );
201  aColorSet->SetHelpId(HID_COLOR_CTL_COLORS);
202  aColorSet->SetPosSizePixel(LogicToPixel(Point(2, 2), MapMode(MapUnit::MapAppFont)),
203  LogicToPixel(Size(146, 18), MapMode(MapUnit::MapAppFont)));
204 
205  // Get the model from the view shell. Using SfxObjectShell::Current()
206  // is unreliable when called at the wrong times.
207  SfxObjectShell* pDocSh = nullptr;
208  if (_pBindings != nullptr)
209  {
210  SfxDispatcher* pDispatcher = _pBindings->GetDispatcher();
211  if (pDispatcher != nullptr)
212  {
213  SfxViewFrame* pFrame = pDispatcher->GetFrame();
214  if (pFrame != nullptr)
215  {
216  SfxViewShell* pViewShell = pFrame->GetViewShell();
217  if (pViewShell != nullptr)
218  pDocSh = pViewShell->GetObjectShell();
219  }
220  }
221  }
222 
223  if ( pDocSh )
224  {
225  const SfxPoolItem* pItem = pDocSh->GetItem( SID_COLOR_TABLE );
226  if( pItem )
227  {
228  pColorList = static_cast<const SvxColorListItem*>(pItem)->GetColorList();
229  FillValueSet();
230  }
231  }
232 
233  aItemSize = aColorSet->CalcItemSizePixel(Size(SvxColorValueSet::getEntryEdgeLength(), SvxColorValueSet::getEntryEdgeLength()));
234  aItemSize.setWidth( aItemSize.Width() + SvxColorValueSet::getEntryEdgeLength() );
235  aItemSize.setWidth( aItemSize.Width() / 2 );
236  aItemSize.setHeight( aItemSize.Height() + SvxColorValueSet::getEntryEdgeLength() );
237  aItemSize.setHeight( aItemSize.Height() / 2 );
238 
239  SetSize();
240  aColorSet->Show();
241  if (_pBindings != nullptr)
242  StartListening(*_pBindings, DuplicateHandling::Prevent);
243 }
244 
246 {
247  disposeOnce();
248 }
249 
251 {
255 }
256 
258 {
259  const SfxPoolItemHint* pPoolItemHint = dynamic_cast<const SfxPoolItemHint*>(&rHint);
260  if ( pPoolItemHint
261  && ( dynamic_cast<const SvxColorListItem*>(pPoolItemHint->GetObject()) != nullptr ) )
262  {
263  // The list of colors has changed
264  pColorList = static_cast<SvxColorListItem*>( pPoolItemHint->GetObject() )->GetColorList();
265  FillValueSet();
266  }
267 }
268 
270 {
271  if( !pColorList.is() )
272  return;
273 
274  nCount = pColorList->Count();
275  aColorSet->Clear();
276 
278 
279  // create the last entry for 'invisible/none'
281  long nPtX = aColorSize.Width() - 1;
282  long nPtY = aColorSize.Height() - 1;
284 
285  pVD->SetOutputSizePixel( aColorSize );
286  pVD->SetLineColor( COL_BLACK );
287  pVD->SetBackground( Wallpaper( COL_WHITE ) );
288  pVD->DrawLine( Point(), Point( nPtX, nPtY ) );
289  pVD->DrawLine( Point( 0, nPtY ), Point( nPtX, 0 ) );
290 
291  BitmapEx aBmp( pVD->GetBitmapEx( Point(), aColorSize ) );
292 
293  aColorSet->InsertItem( sal_uInt16(1), Image(aBmp), SvxResId( RID_SVXSTR_INVISIBLE ) );
294 
295 }
296 
298 {
299  // calculate the size for ValueSet
300  Size aSize = GetOutputSizePixel();
301  aSize.AdjustWidth( -4 );
302  aSize.AdjustHeight( -4 );
303 
304  // calculate rows and columns
305  nCols = static_cast<sal_uInt16>( aSize.Width() / aItemSize.Width() );
306  nLines = static_cast<sal_uInt16>( static_cast<float>(aSize.Height()) / static_cast<float>(aItemSize.Height()) /*+ 0.35*/ );
307  if( nLines == 0 )
308  nLines++;
309 
310  // set/remove scroll bar
311  WinBits nBits = aColorSet->GetStyle();
312  if ( static_cast<long>(nLines) * nCols >= nCount )
313  nBits &= ~WB_VSCROLL;
314  else
315  nBits |= WB_VSCROLL;
316  aColorSet->SetStyle( nBits );
317 
318  // scroll bar?
319  long nScrollWidth = aColorSet->GetScrollWidth();
320  if( nScrollWidth > 0 )
321  {
322  // calculate columns with scroll bar
323  nCols = static_cast<sal_uInt16>( ( aSize.Width() - nScrollWidth ) / aItemSize.Width() );
324  }
326 
327  if( IsFloatingMode() )
329  else
330  {
331  aColorSet->SetLineCount(); // otherwise line height is ignored
333  }
334 
335  aColorSet->SetPosSizePixel( Point( 2, 2 ), aSize );
336 }
337 
339 {
340  SfxBoolItem aItem( SID_COLOR_CONTROL, false );
341  GetBindings().GetDispatcher()->ExecuteList(SID_COLOR_CONTROL,
342  SfxCallMode::ASYNCHRON | SfxCallMode::RECORD, { &aItem });
344  return true;
345 }
346 
348 {
349  SfxDispatcher* pDispatcher = GetBindings().GetDispatcher();
350  sal_uInt16 nPos = aColorSet->GetSelectedItemId();
351  Color aColor( aColorSet->GetItemColor( nPos ) );
352  OUString aStr( aColorSet->GetItemText( nPos ) );
353 
354  if (aColorSet->IsLeftButton())
355  {
356  if ( gnLeftSlot == SID_ATTR_FILL_COLOR )
357  {
358  if ( nPos == 1 ) // invisible
359  {
360  XFillStyleItem aXFillStyleItem( drawing::FillStyle_NONE );
361  pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
362  { &aXFillStyleItem });
363  }
364  else
365  {
366  bool bDone = false;
367 
368  // If we have a DrawView and we are in TextEdit mode, then
369  // not the area color but the text color is assigned
370  SfxViewShell* pViewSh = SfxViewShell::Current();
371  if ( pViewSh )
372  {
373  SdrView* pView = pViewSh->GetDrawView();
374  if ( pView && pView->IsTextEdit() )
375  {
376  SvxColorItem aTextColorItem( aColor, SID_ATTR_CHAR_COLOR );
377  pDispatcher->ExecuteList(SID_ATTR_CHAR_COLOR,
378  SfxCallMode::RECORD, { &aTextColorItem });
379  bDone = true;
380  }
381  }
382  if ( !bDone )
383  {
384  XFillStyleItem aXFillStyleItem( drawing::FillStyle_SOLID );
385  XFillColorItem aXFillColorItem( aStr, aColor );
386  pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
387  { &aXFillColorItem, &aXFillStyleItem });
388  }
389  }
390  }
391  else if ( nPos != 1 ) // invisible
392  {
393  SvxColorItem aLeftColorItem( aColor, gnLeftSlot );
394  pDispatcher->ExecuteList(gnLeftSlot, SfxCallMode::RECORD,
395  { &aLeftColorItem });
396  }
397  }
398  else
399  {
400  if ( gnRightSlot == SID_ATTR_LINE_COLOR )
401  {
402  if( nPos == 1 ) // invisible
403  {
404  XLineStyleItem aXLineStyleItem( drawing::LineStyle_NONE );
405  pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
406  { &aXLineStyleItem });
407  }
408  else
409  {
410  // If the LineStyle is invisible, it is set to SOLID
411  SfxViewShell* pViewSh = SfxViewShell::Current();
412  if ( pViewSh )
413  {
414  SdrView* pView = pViewSh->GetDrawView();
415  if ( pView )
416  {
417  SfxItemSet aAttrSet( pView->GetModel()->GetItemPool() );
418  pView->GetAttributes( aAttrSet );
419  if ( aAttrSet.GetItemState( XATTR_LINESTYLE ) != SfxItemState::DONTCARE )
420  {
421  drawing::LineStyle eXLS =
422  aAttrSet.Get( XATTR_LINESTYLE ).GetValue();
423  if ( eXLS == drawing::LineStyle_NONE )
424  {
425  XLineStyleItem aXLineStyleItem( drawing::LineStyle_SOLID );
426  pDispatcher->ExecuteList(gnRightSlot,
427  SfxCallMode::RECORD, { &aXLineStyleItem });
428  }
429  }
430  }
431  }
432 
433  XLineColorItem aXLineColorItem( aStr, aColor );
434  pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
435  { &aXLineColorItem });
436  }
437  }
438  else if ( nPos != 1 ) // invisible
439  {
440  SvxColorItem aRightColorItem( aColor, gnRightSlot );
441  pDispatcher->ExecuteList(gnRightSlot, SfxCallMode::RECORD,
442  { &aRightColorItem });
443  }
444  }
445 }
446 
448 {
449  rNewSize.AdjustWidth( -4 );
450  rNewSize.AdjustHeight( -4 );
451 
452  // determine columns and rows
453  nCols = static_cast<sal_uInt16>( static_cast<float>(rNewSize.Width()) / static_cast<float>(aItemSize.Width()) + 0.5 );
454  nLines = static_cast<sal_uInt16>( static_cast<float>(rNewSize.Height()) / static_cast<float>(aItemSize.Height()) + 0.5 );
455  if( nLines == 0 )
456  nLines = 1;
457 
458  // set/remove scroll bar
459  WinBits nBits = aColorSet->GetStyle();
460  if ( static_cast<long>(nLines) * nCols >= nCount )
461  nBits &= ~WB_VSCROLL;
462  else
463  nBits |= WB_VSCROLL;
464  aColorSet->SetStyle( nBits );
465 
466  // scroll bar?
467  long nScrollWidth = aColorSet->GetScrollWidth();
468  if( nScrollWidth > 0 )
469  {
470  // calculate columns with scroll bar
471  nCols = static_cast<sal_uInt16>( ( static_cast<float>(rNewSize.Width()) - static_cast<float>(nScrollWidth) )
472  / static_cast<float>(aItemSize.Width()) + 0.5 );
473  }
474  if( nCols <= 1 )
475  nCols = 2;
476 
477  // calculate max. rows using the given columns
478  long nMaxLines = nCount / nCols;
479  if( nCount % nCols )
480  nMaxLines++;
481 
482  nLines = sal::static_int_cast< sal_uInt16 >(
483  std::min< long >( nLines, nMaxLines ) );
484 
485  // set size of the window
486  rNewSize.setWidth( nCols * aItemSize.Width() + nScrollWidth + 4 );
487  rNewSize.setHeight( nLines * aItemSize.Height() + 4 );
488 }
489 
491 {
492  if ( !IsFloatingMode() || !GetFloatingWindow()->IsRollUp() )
493  SetSize();
495 }
496 
498 {
499  SfxDockingWindow::GetFocus();
500  if (aColorSet)
501  {
502  // Grab the focus to the color value set so that it can be controlled
503  // with the keyboard.
504  aColorSet->GrabFocus();
505  }
506 }
507 
509 {
510  bool bRet = false;
511  if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
512  {
513  KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
514  sal_uInt16 nKeyCode = aKeyEvt.GetKeyCode().GetCode();
515  switch( nKeyCode )
516  {
517  case KEY_ESCAPE:
518  GrabFocusToDocument();
519  bRet = true;
520  break;
521  }
522  }
523 
524  return bRet || SfxDockingWindow::EventNotify(rNEvt);
525 }
526 
527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
long Width() const
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 * >())
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
virtual bool Close() override
Definition: colrctrl.cxx:338
long AdjustWidth(long n)
#define DND_ACTION_COPY
long Height() const
signed char sal_Int8
MouseEventModifiers GetMode() const
void EndSelection()
void disposeAndClear()
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
sal_uInt16 GetCode() const
const KeyEvent * GetKeyEvent() const
virtual void GetFocus() override
This function is called when the window gets the focus.
Definition: colrctrl.cxx:497
static SfxObjectShell * Current()
WinBits const WB_VSCROLL
virtual void Resize() override
Definition: colrctrl.cxx:490
static sal_uInt32 getEntryEdgeLength()
long AdjustHeight(long n)
void SetLineCount(sal_uInt16 nNewLines=0)
void Clear()
virtual ~SvxColorDockingWindow() override
Definition: colrctrl.cxx:245
#define HID_COLOR_CTL_COLORS
Definition: helpids.h:23
virtual bool EventNotify(NotifyEvent &rNEvt) override
Definition: colrctrl.cxx:508
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Value
sal_uInt16 GetClicks() const
sal_Int64 WinBits
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: colrctrl.cxx:257
OUString SvxResId(const char *pId)
Definition: dialmgr.cxx:28
#define WB_ITEMBORDER
int nCount
static SfxViewShell * Current()
void SetItemHeight(long nLineHeight)
virtual bool Close() override
static constexpr sal_uInt16 gnRightSlot
Definition: colrctrl.cxx:179
#define MOUSE_LEFT
virtual bool EventNotify(NotifyEvent &rNEvt) override
virtual void MouseButtonUp(const MouseEvent &rMEvt) override
Definition: colrctrl.cxx:122
const SfxPoolItem * GetItem(sal_uInt16 nSlotId) const
virtual void dispose() override
Definition: colrctrl.cxx:250
SvxColorDockingWindow(SfxBindings *pBindings, SfxChildWindow *pCW, vcl::Window *pParent)
Definition: colrctrl.cxx:182
SfxPoolItem * GetObject() const
static constexpr sal_uInt16 gnLeftSlot
Definition: colrctrl.cxx:178
XColorListRef pColorList
Definition: colrctrl.hxx:80
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
Definition: xattr.cxx:1902
virtual void StartDrag(sal_Int8 nAction, const Point &rPtPixel) override
Definition: colrctrl.cxx:143
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
VclPtr< SvxColorValueSet_docking > aColorSet
Definition: colrctrl.hxx:81
#define KEY_ESCAPE
void InsertItem(sal_uInt16 nItemId, const Image &rImage)
OUString GetItemText(sal_uInt16 nItemId) const
MouseNotifyEvent GetType() const
#define XATTR_LINESTYLE
Definition: xdef.hxx:90
sal_uInt16 GetModifier() const
#define HID_CTRL_COLOR
Definition: helpids.h:27
SfxViewShell * GetViewShell() const
virtual bool QueryValue(css::uno::Any &rVal, sal_uInt8 nMemberId=0) const override
Definition: xattr.cxx:1798
virtual void Resizing(Size &rSize) override
Definition: colrctrl.cxx:447
const vcl::KeyCode & GetKeyCode() const
static SotClipboardFormatId GetFormat(const css::datatransfer::DataFlavor &rFlavor)
virtual bool IsTextEdit() const final override
Definition: svdedxv.cxx:1664
long GetScrollWidth() const
Any makeAny(Color const &value)
void SetNoSelection()
void SetColCount(sal_uInt16 nNewCols=1)
SvxColorValueSet_docking(vcl::Window *pParent)
Definition: colrctrl.cxx:92
void GetAttributes(SfxItemSet &rTargetSet, bool bOnlyHardAttr=false) const
Definition: svdview.cxx:251
bool IsLeft() const
SfxViewFrame * GetFrame() const
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
void addEntriesForXColorList(const XColorList &rXColorList, sal_uInt32 nStartIndex=1)
SfxBindings & GetBindings() const
const Point & GetPosPixel() const
constexpr::Color COL_WHITE(0xFF, 0xFF, 0xFF)
virtual SdrView * GetDrawView() const
virtual SfxObjectShell * GetObjectShell() override
SfxDispatcher * GetDispatcher() const
IMPL_LINK_NOARG(SvxColorValueSet_docking, ExecDragHdl, void *, void)
Definition: colrctrl.cxx:171
const SfxItemPool & GetItemPool() const
Definition: svdmodel.hxx:314
virtual void Resize() override
virtual void MouseButtonDown(const MouseEvent &rMEvt) override
Definition: colrctrl.cxx:100
sal_uInt16 GetItemId(size_t nPos) const
virtual void dispose() override
void setWidth(long nWidth)
SdrModel * GetModel() const
Definition: svdpntv.hxx:271
aStr
Color GetItemColor(sal_uInt16 nItemId) const
sal_uInt16 nPos
void setHeight(long nHeight)