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