/*
 * Xailer source code:
 *
 * ColorComboBox.prg
 * Clase TColorComboBox
 *
 * Copyright 2003, 2007 Jose Lalin
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"


//--------------------------------------------------------------------------

CLASS XColorComboBox FROM TComboBox

PUBLISHED:
   PROPERTY lShowText      INIT .F.
   PROPERTY nColorBoxSize  INIT 18  EDITOR PE_Scale
   PROPERTY nLineHeight    INIT 18  EDITOR PE_Scale
   PROPERTY lAddColor      INIT .T.

PROTECTED:
   DATA nCtlStyle    INIT nOr(   WS_CHILD, WS_CLIPSIBLINGS, ;
                                 WS_BORDER, WS_VSCROLL, ;
                                 CBS_DROPDOWNLIST, CBS_OWNERDRAWFIXED )

PUBLIC:
   PROPERTY aColors     INIT {   clWhite, clYellow, clMagenta, ;
                                 clRed, clAqua, clLime, clBlue, ;
                                 clGray, clSilver, clOlive, clPurple, ;
                                 clMaroon, clTeal, clGreen, clNavy, ;
                                 clBlack } ;
                        WRITE METHOD SetColors

   PROPERTY nColor      INIT clBlack READ METHOD GetColor WRITE METHOD SetColor
   PROPERTY nStyle      INIT csDROPDOWNLIST
   PROPERTY aItems
   PROPERTY cText
   PROPERTY lSort
   PROPERTY nMaxLength
   PROPERTY nClrPane
   PROPERTY nClrText
   PROPERTY lAutoHScroll
   PROPERTY nHorzExtent
   PROPERTY oBrush      AS TBrush

   METHOD New( oParent ) CONSTRUCTOR
   METHOD Scale( nScale )

RESERVED:
   METHOD SetColors( aColors )
   METHOD GetColor()
   METHOD SetColor( nColor )

   METHOD DrawItem( lpDIS )
   METHOD MeasureItem( lpMIS )

ENDCLASS

//--------------------------------------------------------------------------

METHOD New( oParent ) CLASS XColorComboBox

   ::Super:New( oParent )

   IF Empty( ::aItems )
      ::SetColors()
   ENDIF

RETURN Self

//--------------------------------------------------------------------------

METHOD Scale( nScale ) CLASS XColorComboBox

   DEFAULT nScale TO Application:nScale

   IF nScale != 100
      ::Super:Scale( nScale )
      ::nColorBoxSize := MulDiv( ::nColorBoxSize, nScale, 100 )
      ::nLineHeight := MulDiv( ::nLineHeight, nScale, 100 )
   ENDIF

RETURN Nil

//----------------------------------------------------------------------------

METHOD GetColor() CLASS XColorComboBox

   LOCAL nClr  := ::FnColor

   IF ::nIndex > 0
      nClr := ::aColors[ ::nIndex ]
   ENDIF

RETURN nClr

//--------------------------------------------------------------------------

METHOD SetColor( nColor ) CLASS XColorComboBox

   LOCAL nPos := AScan( ::aColors, nColor )

   IF nPos > 0
      ::nIndex := nPos
      ::Refresh()
   ELSE
      IF ::lAddColor
         AAdd( ::aColors, nColor )
         ::SetColors()
         ::nIndex := Len( ::aColors )
         ::Refresh()
      ENDIF
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD SetColors( aColors ) CLASS XColorComboBox

   LOCAL aClrs := ::aColors

   UPDATE ::FaColors TO aColors

   ::aItems := {}
   AEval( ::aColors, {|nClr| ::AddItem( "RGB( " + ;
                              Str( GetRValue( nClr ), 3 ) + ", " + ;
                              Str( GetGValue( nClr ), 3 ) + ", " + ;
                              Str( GetBValue( nClr ), 3 ) + ")" ) } )

RETURN aClrs

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#include <windows.h>
#include <xailer.h>
#include <colors.ch>

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XCOLORCOMBOBOX_MEASUREITEM )
{
   PHB_ITEM Self = hb_stackSelfItem();
   LPMEASUREITEMSTRUCT lpmis = (LPVOID) hb_parnl( 1 );

   lpmis->itemHeight = XA_ObjGetNL( Self, "nLineHeight" );

   hb_retl( TRUE );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XCOLORCOMBOBOX_DRAWITEM )
{
   PHB_ITEM Self = hb_stackSelfItem();
   LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT) hb_parnl( 1 );

   if( lpdis->CtlType == ODT_COMBOBOX )
   {
      HDC hDC = lpdis->hDC;
      PHB_ITEM pColors = XA_ObjGetItemCopy( Self, "aColors" );
      INT iItem = lpdis->itemID;
      INT iIndex;
      COLORREF nClr;
      HBRUSH hBrush;
      RECT rc = lpdis->rcItem;
      COLORREF nClrBack;
      BOOL bText = XA_ObjGetL( Self, "lShowText" );
      INT iColorBoxSize = XA_ObjGetNL( Self, "nColorBoxSize" );

      if( iItem == -1 )
         iIndex = XA_ObjGetNL( Self, "FnIndex" );
      else
         iIndex = iItem + 1;

      nClr = hb_arrayGetNL( pColors, iIndex );

      if( lpdis->itemState & ODS_SELECTED )
         nClrBack = GetSysColor( COLOR_HIGHLIGHT );
      else
         nClrBack = GetSysColor( COLOR_WINDOW );

      hBrush = CreateSolidBrush( nClrBack );
      FillRect( hDC, &rc, hBrush );
      DeleteObject( hBrush );

      InflateRect( &rc, -2, -2 );

      if( bText )
         rc.right = iColorBoxSize ? iColorBoxSize : 25;

      if( nClr & 0x80000000 )  // Transparente o ninguno
         {
         HPEN hPen, hOldPen;

         hBrush = CreateSolidBrush( clWhite );
         FillRect( hDC, &rc, hBrush );
         hOldPen = SelectObject( hDC, GetStockObject( BLACK_PEN ) );
         MoveToEx( hDC, rc.left, rc.top, NULL );
         LineTo( hDC, rc.right - 1, rc.top );
         LineTo( hDC, rc.right - 1, rc.bottom - 1 );
         LineTo( hDC, rc.left, rc.bottom - 1 );
         LineTo( hDC, rc.left, rc.top );
         hPen = CreatePen( PS_SOLID, 2, clRed );
         SelectObject( hDC, hPen );
         MoveToEx( hDC, rc.left + 1, rc.top + 1, NULL );
         LineTo( hDC, rc.right - 2, rc.bottom - 2 );
         MoveToEx( hDC, rc.right - 2, rc.top + 1, NULL );
         LineTo( hDC, rc.left + 1, rc.bottom - 2 );
         SelectObject( hDC, hOldPen );
         DeleteObject( hPen );
         }
      else
         {
         hBrush = CreateSolidBrush( nClr );
         FillRect( hDC, &rc, hBrush );
         }

      DeleteObject( hBrush );

      if( bText )
      {
         PHB_ITEM aItems = XA_ObjGetItem( Self, "aItems" );
         PHB_ITEM pText = hb_itemArrayGet( aItems, iIndex );
         COLORREF nOldClr;
         int iBkMode;

         rc.left = iColorBoxSize ? iColorBoxSize + 5 : 30;
         rc.right = lpdis->rcItem.right;

         //SetBkColor( hDC, XA_ObjGetNL( Self, "nClrPane" ) ) ;

         if( lpdis->itemState & ODS_SELECTED )
            nOldClr = SetTextColor( hDC, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
         else if( lpdis->itemState & ODS_DISABLED )
            nOldClr = SetTextColor( hDC, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
         else
            nOldClr = SetTextColor( hDC, GetSysColor( COLOR_WINDOWTEXT ) );

         iBkMode = SetBkMode( hDC, TRANSPARENT );
         DrawText( hDC, hb_itemGetCPtr( pText ), hb_itemGetCLen( pText ),
                     &rc, DT_VCENTER | DT_SINGLELINE );
         SetBkMode( hDC, iBkMode );
         SetTextColor( hDC, nOldClr );

         hb_itemRelease( pText );
      }

      hb_itemRelease( pColors );
      hb_retl( TRUE );
   }
   else
      hb_retl( FALSE );
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
