xref: /AOO41X/main/svx/source/tbxctrls/colrctrl.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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