merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / dialogs / colctrl.cxx
blob3f70bc9cd3c486565bc75cfc4fe878a4870b97e6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: colctrl.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
35 #include <vcl/salbtype.hxx>
36 #include <vcl/bmpacc.hxx>
38 #include <svtools/colctrl.hxx>
40 // ----------------
41 // - ColorControl -
42 // ----------------
44 SvColorControl::SvColorControl( Window* pParent, WinBits nStyle ) :
45 Control ( pParent, nStyle ),
46 mpBitmap ( NULL ),
47 mpReadAccess ( NULL ),
48 mnLuminance ( 50 )
50 Initialize();
53 // -----------------------------------------------------------------------
54 SvColorControl::SvColorControl( Window* pParent, const ResId& rResId ) :
55 Control ( pParent, rResId ),
56 mpBitmap ( NULL ),
57 mpReadAccess ( NULL ),
58 mnLuminance ( 50 )
60 Initialize();
64 // -----------------------------------------------------------------------
65 SvColorControl::~SvColorControl()
67 delete mpBitmap;
70 // -----------------------------------------------------------------------
71 void SvColorControl::Initialize()
73 SetLineColor( Color( COL_BLACK ) );
76 // -----------------------------------------------------------------------
77 void SvColorControl::CreateBitmap()
79 const Size aSize( GetOutputSizePixel() );
81 if( mpBitmap && mpBitmap->GetSizePixel() != aSize )
82 delete mpBitmap, mpBitmap = NULL;
84 if( !mpBitmap )
85 mpBitmap = new Bitmap( aSize, 24 );
87 BitmapWriteAccess* pWriteAccess = mpBitmap->AcquireWriteAccess();
89 if( pWriteAccess )
91 USHORT nX = (USHORT) aSize.Width();
92 USHORT nY = (USHORT) aSize.Height();
94 UINT16 nHue, nSat;
95 ColorHSB aColHSB( 0, 0, mnLuminance );
97 for( USHORT i = 0; i < nY; i++ )
99 nSat = (UINT16) FRound( 100 - ( 100.0 * i + 0.5 ) / nY );
101 for( USHORT j = 0; j < nX; j++ )
103 nHue = (UINT16) FRound( ( 360.0 * j + 0.5 ) / nX );
105 aColHSB.SetHue( nHue );
106 aColHSB.SetSat( nSat );
108 // mpBitmap always has a bit count of 24 => use of SetPixel(...) is safe
109 pWriteAccess->SetPixel( i, j, BitmapColor( aColHSB.GetRGB() ) );
113 mpBitmap->ReleaseAccess( pWriteAccess );
116 SetColor( maColor );
119 // -----------------------------------------------------------------------
120 void SvColorControl::ShowPosition( const Point& rPos )
122 // Explizites Abfragen des Bereichs, da schon mal ein Wert < 0 vorhanden ist
123 if( mpBitmap )
125 long nX = rPos.X();
126 long nY = rPos.Y();
127 if( nX < 0L )
128 nX = 0L;
129 else if( nX >= mpBitmap->GetSizePixel().Width() )
130 nX = mpBitmap->GetSizePixel().Width() - 1L;
132 if( nY < 0L )
133 nY= 0L;
134 else if( nY >= mpBitmap->GetSizePixel().Height() )
135 nY = mpBitmap->GetSizePixel().Height() - 1L;
137 Point aPos = maPosition;
138 maPosition.X() = nX - 2;
139 maPosition.Y() = nY - 2;
140 Invalidate( Rectangle( aPos, Size( 5, 5) ) );
141 Invalidate( Rectangle( maPosition, Size( 5, 5) ) );
143 if( ( mpReadAccess = mpBitmap->AcquireReadAccess() ) != NULL )
145 // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe
146 maColor = mpReadAccess->GetPixel( nY, nX );
147 mpBitmap->ReleaseAccess( mpReadAccess );
148 mpReadAccess = NULL;
152 // -----------------------------------------------------------------------
153 void SvColorControl::MouseMove( const MouseEvent& rMEvt )
155 if( rMEvt.IsLeft() )
157 ShowPosition( rMEvt.GetPosPixel() );
158 Modify();
162 // -----------------------------------------------------------------------
163 void SvColorControl::MouseButtonDown( const MouseEvent& rMEvt )
165 if( rMEvt.IsLeft() && !rMEvt.IsShift() )
167 //ShowPointer( FALSE );
168 CaptureMouse();
169 ShowPosition( rMEvt.GetPosPixel() );
170 Modify();
174 // -----------------------------------------------------------------------
175 void SvColorControl::MouseButtonUp( const MouseEvent& )
177 //ShowPointer( TRUE );
178 if( IsMouseCaptured() )
179 ReleaseMouse();
182 // -----------------------------------------------------------------------
183 void SvColorControl::Paint( const Rectangle& rRect )
185 if( !mpBitmap )
186 CreateBitmap();
188 Bitmap aOutputBitmap( *mpBitmap );
190 if( GetBitCount() <= 8 )
191 aOutputBitmap.Dither();
193 DrawBitmap( rRect.TopLeft(), rRect.GetSize(), rRect.TopLeft(), rRect.GetSize(), aOutputBitmap );
195 // Positions-Control (Fadenkreuz oder Aehnliches)
196 Point aPos1( maPosition );
197 Point aPos2( maPosition );
198 aPos2.X() += 4;
199 DrawLine( aPos1, aPos2 );
200 aPos2.X() -= 4;
201 aPos2.Y() += 4;
202 DrawLine( aPos1, aPos2 );
203 aPos1.Y() += 4;
204 aPos2.X() += 4;
205 DrawLine( aPos1, aPos2 );
206 aPos1.X() += 4;
207 aPos2.Y() -= 4;
208 DrawLine( aPos1, aPos2 );
211 // -----------------------------------------------------------------------
212 void SvColorControl::Resize()
214 CreateBitmap();
215 Control::Resize();
218 // -----------------------------------------------------------------------
219 void SvColorControl::Modify()
221 maModifyHdl.Call( this );
224 // -----------------------------------------------------------------------
225 void SvColorControl::SetColor( const ColorHSB& rCol, BOOL bSetColor )
227 if( bSetColor )
228 maColor = rCol.GetRGB();
230 if( mpBitmap )
232 USHORT nX = (USHORT) mpBitmap->GetSizePixel().Width();
233 USHORT nY = (USHORT) mpBitmap->GetSizePixel().Height();
234 INT16 nZ = rCol.GetBri();
236 SetLuminance( nZ );
237 nX = rCol.GetHue() * nX / 360; // Farbe
238 nY = nY - rCol.GetSat() * nY / 100; // Saettigung
239 ShowPosition( Point( nX, nY ) );
243 // -----------------------------------------------------------------------
244 void SvColorControl::SetColor( const Color& rCol )
246 maColor = rCol;
248 if( mpBitmap )
250 ColorHSB aColHsb( rCol );
251 SetColor( aColHsb, FALSE );
255 // -----------------------------------------------------------------------
256 void SvColorControl::SetLuminance( short nLum )
258 if( nLum != mnLuminance && nLum >= 0 && nLum <= 100 )
260 mnLuminance = nLum;
262 if( mnLuminance < 40 )
263 SetLineColor( Color( COL_WHITE ) );
264 else
265 SetLineColor( Color( COL_BLACK ) );
267 CreateBitmap();
269 long nX = maPosition.X() + 2;
270 long nY = maPosition.Y() + 2;
272 if( mpBitmap && ( ( mpReadAccess = mpBitmap->AcquireReadAccess() ) != NULL ) )
274 // mpBitmap always has a bit count of 24 => use of GetPixel(...) is safe
275 maColor = mpReadAccess->GetPixel( nY, nX );
276 mpBitmap->ReleaseAccess( mpReadAccess );
277 mpReadAccess = NULL;
280 Invalidate();
285 // -----------------------
286 // - ColorPreviewControl -
287 // -----------------------
290 // -----------------------------------------------------------------------
291 ColorPreviewControl::ColorPreviewControl( Window* pParent, WinBits nStyle ) :
292 Control ( pParent, nStyle )
294 SetFillColor( maColor );
295 SetLineColor( maColor );
298 // -----------------------------------------------------------------------
299 ColorPreviewControl::ColorPreviewControl( Window* pParent, const ResId& rResId ) :
300 Control ( pParent, rResId )
302 SetFillColor( maColor );
303 SetLineColor( maColor );
307 // -----------------------------------------------------------------------
308 ColorPreviewControl::~ColorPreviewControl()
312 // -----------------------------------------------------------------------
313 void ColorPreviewControl::Paint( const Rectangle& rRect )
315 DrawRect( rRect );
318 // -----------------------------------------------------------------------
319 void ColorPreviewControl::SetColor( const Color& rCol )
321 if( rCol != maColor )
323 maColor = rCol;
324 SetFillColor( maColor );
325 SetLineColor( maColor );
326 Invalidate();
331 // -----------------------
332 // - ColorMixingControl -
333 // -----------------------
336 // -----------------------------------------------------------------------
337 ColorMixingControl::ColorMixingControl( Window* pParent, WinBits nStyle,
338 USHORT nRows, USHORT nColumns ) :
339 ValueSet ( pParent, nStyle ),
340 mnRows ( nRows ),
341 mnColumns ( nColumns )
343 Initialize();
346 // -----------------------------------------------------------------------
347 ColorMixingControl::ColorMixingControl( Window* pParent, const ResId& rResId,
348 USHORT nRows, USHORT nColumns ) :
349 ValueSet ( pParent, rResId ),
350 mnRows ( nRows ),
351 mnColumns ( nColumns )
353 Initialize();
357 // -----------------------------------------------------------------------
358 ColorMixingControl::~ColorMixingControl()
362 // -----------------------------------------------------------------------
363 void ColorMixingControl::Initialize()
365 SetColCount( mnColumns );
367 Color aColor;
368 String aStr;
369 for( USHORT i = 1; i <= mnRows * mnColumns; i++ )
371 InsertItem( i, aColor, aStr );
374 /*maColor[ 0 ] = Color( COL_LIGHTRED );
375 maColor[ 1 ] = Color( COL_LIGHTGREEN );
376 maColor[ 2 ] = Color( COL_YELLOW );
377 maColor[ 3 ] = Color( COL_LIGHTBLUE );*/
379 SetColor( CMC_TOPLEFT, Color( COL_LIGHTRED ) );
380 SetColor( CMC_BOTTOMRIGHT, Color( COL_LIGHTBLUE ) );
382 SetColor( CMC_TOPRIGHT, Color( COL_LIGHTGREEN ) );
383 SetColor( CMC_BOTTOMLEFT, Color( COL_YELLOW ) );
385 /*FillColumn( 0 );
386 FillColumn( mnColumns - 1 );
387 for( i = 0; i < mnRows; i++ )
388 FillRow( i );*/
391 // -----------------------------------------------------------------------
392 Color ColorMixingControl::CalcDifferenceColor( USHORT nCol1, USHORT nCol2,
393 USHORT nSteps )
395 // Die Berechnung ist noch etwas ungenau, daher sollte besser mit floats
396 // gearbeitet werden... (muss !!!)
397 Color aColor( GetItemColor( nCol1 ) );
398 Color aColor2( GetItemColor( nCol2 ) );
400 aColor.SetRed( (UINT8) ( ( aColor2.GetRed() - aColor.GetRed() ) / nSteps ) );
401 aColor.SetGreen( (UINT8) ( ( aColor2.GetGreen() - aColor.GetGreen() ) / nSteps ) );
402 aColor.SetBlue( (UINT8) ( ( aColor2.GetBlue() - aColor.GetBlue() ) / nSteps ) );
404 return( aColor );
407 // -----------------------------------------------------------------------
408 void ColorMixingControl::FillRow( USHORT nRow )
410 USHORT nCol1 = nRow * mnColumns + 1;
411 USHORT nCol2 = ( nRow + 1 ) * mnColumns;
412 Color aColor( GetItemColor( nCol1 ) );
413 Color aDiffColor( CalcDifferenceColor( nCol1, nCol2, mnColumns - 1 ) );
415 for( USHORT i = nCol1 + 1; i < nCol2; i++ )
417 aColor.SetRed( aColor.GetRed() + aDiffColor.GetRed() );
418 aColor.SetGreen( aColor.GetGreen() + aDiffColor.GetGreen() );
419 aColor.SetBlue( aColor.GetBlue() + aDiffColor.GetBlue() );
421 SetItemColor( i, aColor );
422 SetItemText( i, GetRGBString( aColor ) );
426 // -----------------------------------------------------------------------
427 void ColorMixingControl::FillColumn( USHORT nColumn )
429 USHORT nCol1 = nColumn + 1;
430 USHORT nCol2 = nColumn + ( mnRows - 1 ) * mnColumns + 1;
431 Color aColor( GetItemColor( nCol1 ) );
432 Color aDiffColor( CalcDifferenceColor( nCol1, nCol2, mnRows - 1 ) );
434 for( USHORT i = nCol1 + mnColumns; i < nCol2; i = i + mnColumns )
436 aColor.SetRed( aColor.GetRed() + aDiffColor.GetRed() );
437 aColor.SetGreen( aColor.GetGreen() + aDiffColor.GetGreen() );
438 aColor.SetBlue( aColor.GetBlue() + aDiffColor.GetBlue() );
440 SetItemColor( i, aColor );
441 SetItemText( i, GetRGBString( aColor ) );
445 // -----------------------------------------------------------------------
446 void ColorMixingControl::SetRows( USHORT nRows )
448 mnRows = nRows;
451 // -----------------------------------------------------------------------
452 void ColorMixingControl::SetColumns( USHORT nColumns )
454 mnColumns = nColumns;
457 // -----------------------------------------------------------------------
458 void ColorMixingControl::SetColor( CMCPosition ePos, const Color& rCol )
460 if( rCol != maColor[ ePos ] )
462 maColor[ ePos ] = rCol;
463 USHORT nPos = 0;
464 USHORT nColumn = 0;
465 String aStr( GetRGBString( rCol ) );
467 switch( ePos )
469 case CMC_TOPLEFT:
470 nPos = 1;
471 nColumn = 0;
472 break;
474 case CMC_TOPRIGHT:
475 nPos = mnColumns;
476 nColumn = mnColumns - 1;
477 break;
479 case CMC_BOTTOMLEFT:
480 nPos = ( mnRows - 1 ) * mnColumns + 1;
481 nColumn = 0;
482 break;
484 case CMC_BOTTOMRIGHT:
485 nPos = mnRows * mnColumns;
486 nColumn = mnColumns - 1;
487 break;
488 case CMC_OTHER:
489 break; // -Wall not handled.
491 SetItemColor( nPos, rCol );
492 SetItemText( nPos, aStr );
493 FillColumn( nColumn );
495 for( USHORT i = 0; i < mnRows; i++ )
496 FillRow( i );
500 // -----------------------------------------------------------------------
501 String ColorMixingControl::GetRGBString( const Color& rColor )
503 String aStr( String::CreateFromInt32(rColor.GetRed()) );
504 aStr += ' ';
505 aStr += String::CreateFromInt32(rColor.GetGreen());
506 aStr += ' ';
507 aStr += String::CreateFromInt32(rColor.GetBlue());
509 return aStr;
511 // -----------------------------------------------------------------------
512 CMCPosition ColorMixingControl::GetCMCPosition() const
514 CMCPosition ePos = CMC_OTHER;
515 USHORT nPos = GetSelectItemId();
517 if( nPos == 1 )
518 ePos = CMC_TOPLEFT;
519 else if( nPos == mnColumns )
520 ePos = CMC_TOPRIGHT;
521 else if( nPos == ( mnRows - 1 ) * mnColumns + 1 )
522 ePos = CMC_BOTTOMLEFT;
523 else if( nPos == mnRows * mnColumns )
524 ePos = CMC_BOTTOMRIGHT;
526 return( ePos );
530 // ------------
531 // - ColorHSB -
532 // ------------
534 // Erste Ansaetze gingen auf die Berechnung von Sven Hannover zurueck
535 // Der jetzige Algorithmus stammt im weitesten Sinne aus dem Foley/VanDam
538 /**************************************************************************
540 |* ColorHSB::ColorHSB()
542 |* Beschreibung RGB nach HSB
543 |* Ersterstellung SOH 02.10.97
545 **************************************************************************/
547 ColorHSB::ColorHSB( const Color& rColor )
549 UINT8 c[3];
550 UINT8 cMax, cMin;
552 c[0] = rColor.GetRed();
553 c[1] = rColor.GetGreen();
554 c[2] = rColor.GetBlue();
556 cMax = c[0];
557 if( c[1] > cMax )
558 cMax = c[1];
559 if( c[2] > cMax )
560 cMax = c[2];
562 // Brightness = max(R, G, B);
563 mnBri = cMax * 100 / 255;
565 cMin = c[0];
566 if( c[1] < cMin )
567 cMin = c[1];
568 if( c[2] < cMin )
569 cMin = c[2];
571 UINT8 cDelta = cMax - cMin;
573 // Saturation = max - min / max
574 if( mnBri > 0 )
575 mnSat = cDelta * 100 / cMax;
576 else
577 mnSat = 0;
579 if( mnSat == 0 )
580 mnHue = 0; // Default = undefined
581 else
583 double dHue = 0;
585 if( c[0] == cMax )
587 dHue = (double)( c[1] - c[2] ) / (double)cDelta;
589 else if( c[1] == cMax )
591 dHue = 2.0 + (double)( c[2] - c[0] ) / (double)cDelta;
593 else if ( c[2] == cMax )
595 dHue = 4.0 + (double)( c[0] - c[1] ) / (double)cDelta;
597 // else dHue = ??? -Wall FIXME
598 dHue *= 60.0;
600 if( dHue < 0.0 )
601 dHue += 360.0;
603 mnHue = (UINT16) dHue;
607 /**************************************************************************
609 |* ColorHSB::GetRGB()
611 |* Beschreibung HSB nach RGB
612 |* Ersterstellung SOH 02.10.97
614 **************************************************************************/
616 Color ColorHSB::GetRGB() const
618 UINT8 cR,cG,cB;
619 UINT8 nB = (UINT8) ( mnBri * 255 / 100 );
621 if( mnSat == 0 )
623 cR = nB;
624 cG = nB;
625 cB = nB;
627 else
629 double dH = mnHue;
630 double f;
631 UINT16 n;
632 if( dH == 360.0 )
633 dH = 0.0;
635 dH /= 60.0;
636 n = (UINT16) dH;
637 f = dH - n;
639 // #107375# Doing the calculation completely in floating
640 // point, the former optimization gave sometimes negative
641 // results for c and was pointless anyway
642 UINT8 a = static_cast<UINT8>( nB * ( 100.0 - mnSat ) / 100.0 );
643 UINT8 b = static_cast<UINT8>( nB * ( 100.0 - mnSat * f ) / 100.0 );
644 UINT8 c = static_cast<UINT8>( nB * ( 100.0 - mnSat * ( 1.0 - f ) ) / 100.0 );
646 switch( n )
648 case 0: cR = nB; cG = c; cB = a; break;
649 case 1: cR = b; cG = nB; cB = a; break;
650 case 2: cR = a; cG = nB; cB = c; break;
651 case 3: cR = a; cG = b; cB = nB; break;
652 case 4: cR = c; cG = a; cB = nB; break;
653 case 5: cR = nB; cG = a; cB = b; break;
654 default: cR = 0; cG = 0; cB = 0; break; // -Wall ????
658 return( Color( cR, cG, cB ) );
661 // ------------
662 // - ColorCMYK -
663 // ------------
666 // -----------------------------------------------------------------------
667 ColorCMYK::ColorCMYK( const Color& rColor )
669 mnCyan = 255 - rColor.GetRed();
670 mnMagenta = 255 - rColor.GetGreen();
671 mnYellow = 255 - rColor.GetBlue();
673 mnKey = Min( Min( mnCyan, mnMagenta ), mnYellow );
675 mnCyan = mnCyan - mnKey;
676 mnMagenta = mnMagenta - mnKey;
677 mnYellow = mnYellow - mnKey;
680 // -----------------------------------------------------------------------
681 Color ColorCMYK::GetRGB() const
683 int nTmp = Max( 0, 255 - ( mnCyan + mnKey ) );
684 UINT8 cR = (UINT8) nTmp;
685 nTmp = Max( 0, 255 - ( mnMagenta + mnKey ) );
686 UINT8 cG = (UINT8) nTmp;
687 nTmp = Max( 0, 255 - ( mnYellow + mnKey ) );
688 UINT8 cB = (UINT8) nTmp;
690 return( Color( cR, cG, cB ) );