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