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