xref: /aoo41x/main/svx/source/tbxctrls/colrctrl.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <svx/dialogs.hrc>
28 
29 
30 #include <tools/list.hxx>
31 #include <sfx2/viewsh.hxx>
32 #include <sfx2/objsh.hxx>
33 #include <sfx2/dispatch.hxx>
34 #include <vcl/image.hxx>
35 
36 #include <svx/colrctrl.hxx>
37 
38 #include <svx/svdview.hxx>
39 #include "svx/drawitem.hxx"
40 #include <editeng/colritem.hxx>
41 #include "svx/xattr.hxx"
42 #include <svx/xtable.hxx>
43 #include <svx/dialmgr.hxx>
44 #include "svx/xexch.hxx"
45 #include <vcl/svapp.hxx>
46 
47 SFX_IMPL_DOCKINGWINDOW( SvxColorChildWindow, SID_COLOR_CONTROL )
48 
49 // ------------------------
50 // - SvxColorValueSetData -
51 // ------------------------
52 
53 class SvxColorValueSetData : public TransferableHelper
54 {
55 private:
56 
57 	XFillExchangeData		maData;
58 
59 protected:
60 
61 	virtual void			AddSupportedFormats();
62 	virtual sal_Bool		GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
63 	virtual sal_Bool		WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId, const ::com::sun::star::datatransfer::DataFlavor& rFlavor );
64 
65 public:
66 
67 							SvxColorValueSetData( const XFillAttrSetItem& rSetItem ) :
68 								maData( rSetItem ) {}
69 };
70 
71 // -----------------------------------------------------------------------------
72 
73 void SvxColorValueSetData::AddSupportedFormats()
74 {
75 	AddFormat( SOT_FORMATSTR_ID_XFA );
76 }
77 
78 // -----------------------------------------------------------------------------
79 
80 sal_Bool SvxColorValueSetData::GetData( const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
81 {
82 	sal_Bool bRet = sal_False;
83 
84 	if( SotExchange::GetFormat( rFlavor ) == SOT_FORMATSTR_ID_XFA )
85 	{
86 		SetObject( &maData, 0, rFlavor );
87 		bRet = sal_True;
88 	}
89 
90 	return bRet;
91 }
92 
93 // -----------------------------------------------------------------------------
94 
95 sal_Bool SvxColorValueSetData::WriteObject( SotStorageStreamRef& rxOStm, void*, sal_uInt32 , const ::com::sun::star::datatransfer::DataFlavor&  )
96 {
97 	*rxOStm << maData;
98 	return( rxOStm->GetError() == ERRCODE_NONE );
99 }
100 
101 /*************************************************************************
102 |*
103 |* SvxColorValueSet: Ctor
104 |*
105 \************************************************************************/
106 
107 SvxColorValueSet::SvxColorValueSet( Window* _pParent, WinBits nWinStyle ) :
108 	ValueSet( _pParent, nWinStyle ),
109 	DragSourceHelper( this ),
110     bLeft (sal_True)
111 {
112 	SetAccessibleName(String( SVX_RES( STR_COLORTABLE ) ) );
113 }
114 
115 /*************************************************************************
116 |*
117 |* SvxColorValueSet: Ctor
118 |*
119 \************************************************************************/
120 
121 SvxColorValueSet::SvxColorValueSet( Window* _pParent, const ResId& rResId ) :
122 	ValueSet( _pParent, rResId ),
123 	DragSourceHelper( this ),
124     bLeft (sal_True)
125 {
126 	SetAccessibleName(String( SVX_RES( STR_COLORTABLE )  ));
127 }
128 
129 /*************************************************************************
130 |*
131 |* SvxColorValueSet: MouseButtonDown
132 |*
133 \************************************************************************/
134 
135 void SvxColorValueSet::MouseButtonDown( const MouseEvent& rMEvt )
136 {
137 	// Fuer Mac noch anders handlen !
138 	if( rMEvt.IsLeft() )
139 	{
140 		bLeft = sal_True;
141 		ValueSet::MouseButtonDown( rMEvt );
142 	}
143 	else
144 	{
145 		bLeft = sal_False;
146 		MouseEvent aMEvt( rMEvt.GetPosPixel(),
147 						  rMEvt.GetClicks(),
148 						  rMEvt.GetMode(),
149 						  MOUSE_LEFT,
150 						  rMEvt.GetModifier() );
151 		ValueSet::MouseButtonDown( aMEvt );
152 	}
153 
154 	aDragPosPixel = GetPointerPosPixel();
155 }
156 
157 /*************************************************************************
158 |*
159 |* SvxColorValueSet: MouseButtonUp
160 |*
161 \************************************************************************/
162 
163 void SvxColorValueSet::MouseButtonUp( const MouseEvent& rMEvt )
164 {
165 	// Fuer Mac noch anders handlen !
166 	if( rMEvt.IsLeft() )
167 	{
168 		bLeft = sal_True;
169 		ValueSet::MouseButtonUp( rMEvt );
170 	}
171 	else
172 	{
173 		bLeft = sal_False;
174 		MouseEvent aMEvt( rMEvt.GetPosPixel(),
175 						  rMEvt.GetClicks(),
176 						  rMEvt.GetMode(),
177 						  MOUSE_LEFT,
178 						  rMEvt.GetModifier() );
179 		ValueSet::MouseButtonUp( aMEvt );
180 	}
181 	SetNoSelection();
182 }
183 
184 /*************************************************************************
185 |*
186 |* Command-Event
187 |*
188 \************************************************************************/
189 
190 void SvxColorValueSet::Command(const CommandEvent& rCEvt)
191 {
192 	// Basisklasse
193 	ValueSet::Command(rCEvt);
194 }
195 
196 /*************************************************************************
197 |*
198 |* StartDrag
199 |*
200 \************************************************************************/
201 
202 void SvxColorValueSet::StartDrag( sal_Int8 , const Point&  )
203 {
204 	Application::PostUserEvent(STATIC_LINK(this, SvxColorValueSet, ExecDragHdl));
205 }
206 
207 /*************************************************************************
208 |*
209 |* Drag&Drop asynchron ausfuehren
210 |*
211 \************************************************************************/
212 
213 void SvxColorValueSet::DoDrag()
214 {
215 	SfxObjectShell* pDocSh = SfxObjectShell::Current();
216 	sal_uInt16			nItemId = GetItemId( aDragPosPixel );
217 
218 	if( pDocSh && nItemId )
219 	{
220 		XFillAttrSetItem	aXFillSetItem( &pDocSh->GetPool() );
221 		SfxItemSet&			rSet = aXFillSetItem.GetItemSet();
222 
223 		rSet.Put( XFillColorItem( GetItemText( nItemId ), GetItemColor( nItemId ) ) );
224 		rSet.Put(XFillStyleItem( ( 1 == nItemId ) ? XFILL_NONE : XFILL_SOLID ) );
225 
226 		EndSelection();
227 		( new SvxColorValueSetData( aXFillSetItem ) )->StartDrag( this, DND_ACTION_COPY );
228 		ReleaseMouse();
229 	}
230 }
231 
232 /*************************************************************************
233 |*
234 |*
235 |*
236 \************************************************************************/
237 
238 IMPL_STATIC_LINK(SvxColorValueSet, ExecDragHdl, void*, EMPTYARG)
239 {
240 	// Als Link, damit asynchron ohne ImpMouseMoveMsg auf dem Stack auch die
241 	// Farbleiste geloescht werden darf
242 	pThis->DoDrag();
243 	return(0);
244 }
245 
246 /*************************************************************************
247 |*
248 |* Ableitung vom SfxChildWindow als "Behaelter" fuer Animator
249 |*
250 \************************************************************************/
251 
252 SvxColorChildWindow::SvxColorChildWindow( Window* _pParent,
253     									  sal_uInt16 nId,
254 										  SfxBindings* pBindings,
255 										  SfxChildWinInfo* pInfo ) :
256 	SfxChildWindow( _pParent, nId )
257 {
258 	SvxColorDockingWindow* pWin = new SvxColorDockingWindow( pBindings, this,
259 										_pParent, SVX_RES( RID_SVXCTRL_COLOR ) );
260 	pWindow = pWin;
261 
262 	eChildAlignment = SFX_ALIGN_BOTTOM;
263 
264 	pWin->Initialize( pInfo );
265 }
266 
267 
268 
269 /*************************************************************************
270 |*
271 |* Ctor: SvxColorDockingWindow
272 |*
273 \************************************************************************/
274 
275 SvxColorDockingWindow::SvxColorDockingWindow
276 (
277 	SfxBindings* _pBindings,
278 	SfxChildWindow* pCW,
279 	Window* _pParent,
280 	const ResId& rResId
281 ) :
282 
283 	SfxDockingWindow( _pBindings, pCW, _pParent, rResId ),
284 
285 	pColorTable 	( NULL ),
286 	aColorSet		( this, ResId( 1, *rResId.GetResMgr() ) ),
287 	nLeftSlot		( SID_ATTR_FILL_COLOR ),
288 	nRightSlot		( SID_ATTR_LINE_COLOR ),
289 	nCols			( 20 ),
290 	nLines			( 1 ),
291 	aColorSize		( 14, 14 )
292 
293 {
294 	FreeResource();
295 
296 	aColorSet.SetStyle( aColorSet.GetStyle() | WB_ITEMBORDER );
297 	aColorSet.SetSelectHdl( LINK( this, SvxColorDockingWindow, SelectHdl ) );
298 
299     // Get the model from the view shell.  Using SfxObjectShell::Current()
300     // is unreliable when called at the wrong times.
301     SfxObjectShell*	pDocSh = NULL;
302     if (_pBindings != NULL)
303     {
304         SfxDispatcher* pDispatcher = _pBindings->GetDispatcher();
305         if (pDispatcher != NULL)
306         {
307             SfxViewFrame* pFrame = pDispatcher->GetFrame();
308             if (pFrame != NULL)
309             {
310                 SfxViewShell* pViewShell = pFrame->GetViewShell();
311                 if (pViewShell != NULL)
312                     pDocSh = pViewShell->GetObjectShell();
313             }
314         }
315     }
316 
317 	if ( pDocSh )
318 	{
319 		const SfxPoolItem*	pItem = pDocSh->GetItem( SID_COLOR_TABLE );
320 		if( pItem )
321 		{
322 			pColorTable = ( (SvxColorTableItem*) pItem )->GetColorTable();
323 			FillValueSet();
324 		}
325 	}
326 	aItemSize = aColorSet.CalcItemSizePixel( aColorSize );
327 	aItemSize.Width() = aItemSize.Width() + aColorSize.Width();
328 	aItemSize.Width() /= 2;
329 	aItemSize.Height() = aItemSize.Height() + aColorSize.Height();
330 	aItemSize.Height() /= 2;
331 
332 	SetSize();
333 	aColorSet.Show();
334 	StartListening( *_pBindings, sal_True );
335 }
336 
337 
338 /*************************************************************************
339 |*
340 |* Dtor: SvxColorDockingWindow
341 |*
342 \************************************************************************/
343 
344 SvxColorDockingWindow::~SvxColorDockingWindow()
345 {
346 	EndListening( GetBindings() );
347 }
348 
349 /*************************************************************************
350 |*
351 |* Notify
352 |*
353 \************************************************************************/
354 
355 void SvxColorDockingWindow::Notify( SfxBroadcaster& , const SfxHint& rHint )
356 {
357 	const SfxPoolItemHint *pPoolItemHint = PTR_CAST(SfxPoolItemHint, &rHint);
358 	if ( pPoolItemHint
359 		 && ( pPoolItemHint->GetObject()->ISA( SvxColorTableItem ) ) )
360 	{
361 		// Die Liste der Farben hat sich geaendert
362 		pColorTable = ( (SvxColorTableItem*) pPoolItemHint->GetObject() )->GetColorTable();
363 		FillValueSet();
364 	}
365 }
366 
367 /*************************************************************************
368 |*
369 |* FillValueSet
370 |*
371 \************************************************************************/
372 
373 void SvxColorDockingWindow::FillValueSet()
374 {
375 	if( pColorTable )
376 	{
377 		aColorSet.Clear();
378 
379 		// Erster Eintrag: unsichtbar
380 		long nPtX = aColorSize.Width() - 1;
381 		long nPtY = aColorSize.Height() - 1;
382 		VirtualDevice aVD;
383 		aVD.SetOutputSizePixel( aColorSize );
384 		aVD.SetLineColor( Color( COL_BLACK ) );
385 		aVD.SetBackground( Wallpaper( Color( COL_WHITE ) ) );
386 		aVD.DrawLine( Point(), Point( nPtX, nPtY ) );
387 		aVD.DrawLine( Point( 0, nPtY ), Point( nPtX, 0 ) );
388 
389 		Bitmap aBmp( aVD.GetBitmap( Point(), aColorSize ) );
390 
391 		aColorSet.InsertItem( (sal_uInt16)1, Image(aBmp), SVX_RESSTR( RID_SVXSTR_INVISIBLE ) );
392 
393 		XColorEntry* pEntry;
394 		nCount = pColorTable->Count();
395 
396 		for( long i = 0; i < nCount; i++ )
397 		{
398 			pEntry = pColorTable->GetColor( i );
399 			aColorSet.InsertItem( (sal_uInt16)i+2,
400 							pEntry->GetColor(), pEntry->GetName() );
401 		}
402 	}
403 }
404 
405 /*************************************************************************
406 |*
407 |* SetSize
408 |*
409 \************************************************************************/
410 
411 void SvxColorDockingWindow::SetSize()
412 {
413 	// Groesse fuer ValueSet berechnen
414 	Size aSize = GetOutputSizePixel();
415 	aSize.Width()  -= 4;
416 	aSize.Height() -= 4;
417 
418 	// Zeilen und Spalten berechnen
419 	nCols = (sal_uInt16) ( aSize.Width() / aItemSize.Width() );
420 	nLines = (sal_uInt16) ( (float) aSize.Height() / (float) aItemSize.Height() /*+ 0.35*/ );
421 	if( nLines == 0 )
422 		nLines++;
423 
424 	// Scrollbar setzen/entfernen
425 	WinBits nBits = aColorSet.GetStyle();
426 	if ( nLines * nCols >= nCount )
427 		nBits &= ~WB_VSCROLL;
428 	else
429 		nBits |= WB_VSCROLL;
430 	aColorSet.SetStyle( nBits );
431 
432 	// ScrollBar ?
433 	long nScrollWidth = aColorSet.GetScrollWidth();
434 	if( nScrollWidth > 0 )
435 	{
436 		// Spalten mit ScrollBar berechnen
437 		nCols = (sal_uInt16) ( ( aSize.Width() - nScrollWidth ) / aItemSize.Width() );
438 	}
439 	aColorSet.SetColCount( nCols );
440 
441 	if( IsFloatingMode() )
442 		aColorSet.SetLineCount( nLines );
443 	else
444 	{
445 		aColorSet.SetLineCount( 0 ); // sonst wird LineHeight ignoriert
446 		aColorSet.SetItemHeight( aItemSize.Height() );
447 	}
448 
449 	aColorSet.SetPosSizePixel( Point( 2, 2 ), aSize );
450 }
451 
452 /*************************************************************************
453 |*
454 |* SvxColorDockingWindow: Close
455 |*
456 \************************************************************************/
457 
458 sal_Bool SvxColorDockingWindow::Close()
459 {
460 	SfxBoolItem aItem( SID_COLOR_CONTROL, sal_False );
461 	GetBindings().GetDispatcher()->Execute(
462 		SID_COLOR_CONTROL, SFX_CALLMODE_ASYNCHRON | SFX_CALLMODE_RECORD, &aItem, 0L );
463 	SfxDockingWindow::Close();
464 	return( sal_True );
465 }
466 
467 /*************************************************************************
468 |*
469 |* SelectHdl
470 |*
471 \************************************************************************/
472 
473 IMPL_LINK( SvxColorDockingWindow, SelectHdl, void *, EMPTYARG )
474 {
475 	SfxDispatcher* pDispatcher = GetBindings().GetDispatcher();
476 	sal_uInt16 nPos = aColorSet.GetSelectItemId();
477 	Color  aColor( aColorSet.GetItemColor( nPos ) );
478 	String aStr( aColorSet.GetItemText( nPos ) );
479 
480     if (aColorSet.IsLeftButton())
481     {
482 		if ( nLeftSlot == SID_ATTR_FILL_COLOR )
483 		{
484 			if ( nPos == 1 )		// unsichtbar
485 			{
486 				XFillStyleItem aXFillStyleItem( XFILL_NONE );
487 				pDispatcher->Execute( nLeftSlot, SFX_CALLMODE_RECORD, &aXFillStyleItem, 0L );
488 			}
489 			else
490 			{
491 				sal_Bool bDone = sal_False;
492 
493 				// Wenn wir eine DrawView haben und uns im TextEdit-Modus befinden,
494 				// wird nicht die Flaechen-, sondern die Textfarbe zugewiesen
495 				SfxViewShell* pViewSh = SfxViewShell::Current();
496 				if ( pViewSh )
497 				{
498 					SdrView* pView = pViewSh->GetDrawView();
499 					if ( pView && pView->IsTextEdit() )
500 					{
501 						SvxColorItem aTextColorItem( aColor, SID_ATTR_CHAR_COLOR );
502 						pDispatcher->Execute(
503 							SID_ATTR_CHAR_COLOR, SFX_CALLMODE_RECORD, &aTextColorItem, 0L );
504 						bDone = sal_True;
505 					}
506 				}
507 				if ( !bDone )
508 				{
509 					XFillStyleItem aXFillStyleItem( XFILL_SOLID );
510 					XFillColorItem aXFillColorItem( aStr, aColor );
511 					pDispatcher->Execute(
512 						nLeftSlot, SFX_CALLMODE_RECORD, &aXFillColorItem, &aXFillStyleItem, 0L );
513 				}
514 			}
515 		}
516 		else if ( nPos != 1 )		// unsichtbar
517 		{
518 			SvxColorItem aLeftColorItem( aColor, nLeftSlot );
519 			pDispatcher->Execute( nLeftSlot, SFX_CALLMODE_RECORD, &aLeftColorItem, 0L );
520 		}
521     }
522     else
523 	{
524 		if ( nRightSlot == SID_ATTR_LINE_COLOR )
525 		{
526 			if( nPos == 1 )		// unsichtbar
527 			{
528 				XLineStyleItem aXLineStyleItem( XLINE_NONE );
529 				pDispatcher->Execute( nRightSlot, SFX_CALLMODE_RECORD, &aXLineStyleItem, 0L );
530 			}
531 			else
532 			{
533 				// Sollte der LineStyle unsichtbar sein, so wird er auf SOLID gesetzt
534 				SfxViewShell* pViewSh = SfxViewShell::Current();
535 				if ( pViewSh )
536 				{
537 					SdrView* pView = pViewSh->GetDrawView();
538 					if ( pView )
539 					{
540 						SfxItemSet aAttrSet( pView->GetModel()->GetItemPool() );
541 						pView->GetAttributes( aAttrSet );
542 						if ( aAttrSet.GetItemState( XATTR_LINESTYLE ) != SFX_ITEM_DONTCARE )
543 						{
544 							XLineStyle eXLS = (XLineStyle)
545 								( (const XLineStyleItem&)aAttrSet.Get( XATTR_LINESTYLE ) ).GetValue();
546 							if ( eXLS == XLINE_NONE )
547 							{
548 								XLineStyleItem aXLineStyleItem( XLINE_SOLID );
549 								pDispatcher->Execute( nRightSlot, SFX_CALLMODE_RECORD, &aXLineStyleItem, 0L );
550 							}
551 						}
552 					}
553 				}
554 
555 				XLineColorItem aXLineColorItem( aStr, aColor );
556 				pDispatcher->Execute( nRightSlot, SFX_CALLMODE_RECORD, &aXLineColorItem, 0L );
557 			}
558 		}
559 		else if ( nPos != 1 )		// unsichtbar
560 		{
561 			SvxColorItem aRightColorItem( aColor, nRightSlot );
562 			pDispatcher->Execute( nRightSlot, SFX_CALLMODE_RECORD, &aRightColorItem, 0L );
563 		}
564 	}
565 
566 	return 0;
567 }
568 
569 /*************************************************************************
570 |*
571 |* Resizing
572 |*
573 \************************************************************************/
574 
575 
576 void SvxColorDockingWindow::Resizing( Size& rNewSize )
577 {
578 	rNewSize.Width()  -= 4;
579 	rNewSize.Height() -= 4;
580 
581 	// Spalten und Reihen ermitteln
582 	nCols = (sal_uInt16) ( (float) rNewSize.Width() / (float) aItemSize.Width() + 0.5 );
583 	nLines = (sal_uInt16) ( (float) rNewSize.Height() / (float) aItemSize.Height() + 0.5 );
584 	if( nLines == 0 )
585 		nLines = 1;
586 
587 	// Scrollbar setzen/entfernen
588 	WinBits nBits = aColorSet.GetStyle();
589 	if ( nLines * nCols >= nCount )
590 		nBits &= ~WB_VSCROLL;
591 	else
592 		nBits |= WB_VSCROLL;
593 	aColorSet.SetStyle( nBits );
594 
595 	// ScrollBar ?
596 	long nScrollWidth = aColorSet.GetScrollWidth();
597 	if( nScrollWidth > 0 )
598 	{
599 		// Spalten mit ScrollBar berechnen
600 		nCols = (sal_uInt16) ( ( ( (float) rNewSize.Width() - (float) nScrollWidth ) )
601 							/ (float) aItemSize.Width() + 0.5 );
602 	}
603 	if( nCols <= 1 )
604 		nCols = 2;
605 
606 	// Max. Reihen anhand der gegebenen Spalten berechnen
607 	long nMaxLines = nCount / nCols;
608 	if( nCount %  nCols )
609 		nMaxLines++;
610 
611 	nLines = sal::static_int_cast< sal_uInt16 >(
612         std::min< long >( nLines, nMaxLines ) );
613 
614 	// Groesse des Windows setzen
615 	rNewSize.Width()  = nCols * aItemSize.Width() + nScrollWidth + 4;
616 	rNewSize.Height() = nLines * aItemSize.Height() + 4;
617 }
618 
619 /*************************************************************************
620 |*
621 |* Resize
622 |*
623 \************************************************************************/
624 
625 void SvxColorDockingWindow::Resize()
626 {
627 	if ( !IsFloatingMode() || !GetFloatingWindow()->IsRollUp() )
628 		SetSize();
629 	SfxDockingWindow::Resize();
630 }
631 
632 
633 
634 void SvxColorDockingWindow::GetFocus (void)
635 {
636 	SfxDockingWindow::GetFocus();
637     // Grab the focus to the color value set so that it can be controlled
638     // with the keyboard.
639 	aColorSet.GrabFocus();
640 }
641 
642 long SvxColorDockingWindow::Notify( NotifyEvent& rNEvt )
643 {
644 	long nRet = 0;
645 	if( ( rNEvt.GetType() == EVENT_KEYINPUT ) )
646 	{
647 		KeyEvent aKeyEvt = *rNEvt.GetKeyEvent();
648 		sal_uInt16	 nKeyCode = aKeyEvt.GetKeyCode().GetCode();
649 		switch( nKeyCode )
650 		{
651 			case KEY_ESCAPE:
652 				GrabFocusToDocument();
653 				nRet = 1;
654 				break;
655 		}
656 	}
657 
658 	return nRet ? nRet : SfxDockingWindow::Notify( rNEvt );
659 }
660