// ListRow.cpp : implementation file
//

#include "stdafx.h"
#include "certmap.h"
#include "ListRow.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


#define SZ_RES_COLOR_PREFS      "Control Panel\\Colors"
#define SZ_RES_COLOR_HILITE     "Hilight"
#define SZ_RES_COLOR_HILITETEXT "HilightText"


/////////////////////////////////////////////////////////////////////////////
// CListSelRowCtrl
//-----------------------------------------------------------------------------------
CListSelRowCtrl::CListSelRowCtrl():
        m_StartDrawingCol( 0 )
    {
    }

//-----------------------------------------------------------------------------------
CListSelRowCtrl::~CListSelRowCtrl()
    {
    }


//-----------------------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CListSelRowCtrl, CListCtrl)
    //{{AFX_MSG_MAP(CListSelRowCtrl)
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONDBLCLK()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//-----------------------------------------------------------------------------------
void CListSelRowCtrl::GetHiliteColors()
    {
    // get the hilite color
    m_colorHilite = GetSysColor( COLOR_HIGHLIGHT );

    // get the hilited text color
    m_colorHiliteText = GetSysColor( COLOR_HIGHLIGHTTEXT );
    }



/////////////////////////////////////////////////////////////////////////////
// CListSelRowCtrl message handlers

//-----------------------------------------------------------------------------------
void CListSelRowCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    CRect       rcItem = lpDrawItemStruct->rcItem;
    CRect       rcSection;
    UINT        itemID = lpDrawItemStruct->itemID;
    UINT        cpLeft = rcItem.left;
    CString     sz;
    LV_COLUMN   colData;
    COLORREF    colorTextOld;
    COLORREF    colorBackOld;

    // setup the CDC object
    CDC         cdc;
    cdc.Attach( lpDrawItemStruct->hDC );

#ifdef _DEBUG
    if ( m_StartDrawingCol == 0 )
        sz.Empty();
#endif

    // clear the columnd buffer
    ZeroMemory( &colData, sizeof(colData) );
    colData.mask = LVCF_WIDTH;

    // if this is the selected item, prepare the background and the text color
    BOOL fSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
    if ( fSelected )
        {
        GetHiliteColors();
        colorTextOld = cdc.SetTextColor( m_colorHiliteText );
        colorBackOld = cdc.SetBkColor( m_colorHilite );
        }

    // starting with the m_StartDrawingCol column, draw the columns
    // do it in a loop, just skipping until we hit m_StartDrawingCol
    DWORD iCol = 0;
    while ( GetColumn(iCol, &colData) )
        {
        // see if we are ready yet
        if ( iCol < m_StartDrawingCol )
            {
            // set the new left.
            cpLeft += colData.cx;
            // increment the column counter
            iCol++;
            continue;
            }

        // prepare the background but once
        if ( iCol == m_StartDrawingCol )
            {
            // prepare the background
            rcSection = rcItem;
            rcSection.left = cpLeft;
            rcSection.right--;
            CBrush  brush;
            if ( lpDrawItemStruct->itemState & ODS_SELECTED )
                brush.CreateSolidBrush( m_colorHilite );
            else
                brush.CreateSolidBrush( GetSysColor( COLOR_WINDOW ) );
            cdc.FillRect( &rcSection, &brush );
            }


        // display the name
        sz = GetItemText( itemID, iCol );
        if ( !sz.IsEmpty() )
            {
            // figure out the sectional rect
            rcSection = rcItem;
            rcSection.left = cpLeft + 2;
            rcSection.right = cpLeft + colData.cx - 1;
            
            // fit the string into the required space
            FitString( sz, rcSection.right - rcSection.left, &cdc );

            //draw the string
            cdc.DrawText( sz, &rcSection, DT_SINGLELINE|DT_LEFT|DT_BOTTOM|DT_NOPREFIX );
            }

        // set the new left.
        cpLeft += colData.cx;
        // increment the column counter
        iCol++;
        }

    // if this is the selected item, restore the colors
    if ( fSelected )
        {
        cdc.SetTextColor( colorTextOld );
        cdc.SetBkColor( colorBackOld );
        }

    // cleanup the CDC object
    cdc.Detach();
    }


//------------------------------------------------------------------------
void CListSelRowCtrl::FitString( CString &sz, int cpWidth, CDC* pcdc )
    {
    CSize       size;
    UINT        cch;
    CString     szEllipsis;

    // start by testing the existing width
    size = pcdc->GetTextExtent( sz );
    if ( size.cx <= cpWidth ) return;

    // initialize szTrunc and szEllipsis
    cch = sz.GetLength();

    szEllipsis.LoadString(IDS_ELLIPSIS);

    // while we are too big, truncate one letter and add an ellipsis
    while( (size.cx > cpWidth) && (cch > 1) )
        {
        // chop off the last letter of the string - not counting the ...
        cch--;
        sz = sz.Left( cch );

        // add the elipsis (spelling?)
        sz += szEllipsis;

        // get the length
        size = pcdc->GetTextExtent( sz );
        }
    }







//------------------------------------------------------------------------
void CListSelRowCtrl::HiliteSelectedCells()
    {
    int iList = -1;
    while( (iList = GetNextItem( iList, LVNI_SELECTED )) >= 0 )
        HiliteSelectedCell( iList );
    }

//------------------------------------------------------------------------
void CListSelRowCtrl::HiliteSelectedCell( int iCell, BOOL fHilite )
    {
    // if there is no selected cell, do nothing
    if ( iCell < 0 )
        return;

    // get the rect to draw
    CRect   rect;
    if ( !FGetCellRect(iCell, -1, &rect) )
        {
        ASSERT(FALSE);
        return;
        }

    // get the client rect
    CRect   rectClient;
    GetClientRect( rectClient );

    // make sure it fits ok (problems can occur here when scrolled)
    // don't want it to draw in the column titles
    if ( rect.top < (rect.bottom - rect.top) )
        return;

    // now prepare to draw
    CDC *pdc = GetDC();

    // clip to the client area
    pdc->IntersectClipRect( rectClient );

    // set up the brush
    CBrush  cbrush;
    if ( fHilite )
        cbrush.CreateSolidBrush( RGB(192,192,192) );
    else
        cbrush.CreateSolidBrush( RGB(0xFF,0xFF,0xFF) );

    // draw the hilite rect
    pdc->FrameRect( rect, &cbrush );

    // cleanup
    ReleaseDC( pdc );
    }

//------------------------------------------------------------------------
BOOL    CListSelRowCtrl::FGetCellRect( LONG iRow, LONG iCol, CRect *pcrect )
    {
    // first, get the rect that the list thinks is appropriate
    if ( !GetItemRect(iRow, pcrect, LVIR_BOUNDS) )
        return FALSE;

    // if iCol < 0, then return the total size of the row
    if ( iCol < 0 )
        return TRUE;

    // trim the horizontal dimension to the correct column positioning
    LONG    cpLeft;
    LONG    cpRight = 0;
    for ( WORD i = 0; i <= iCol; i++ )
        {
        // set the left side
        cpLeft = cpRight;

        // get the right
        LONG cpWidth = GetColumnWidth(i);
        if ( cpWidth < 0 ) return FALSE;
        cpRight += cpWidth;
        }

    // well, now trim it seeing as we have the right values
    pcrect->left = cpLeft;
    pcrect->right = cpRight;
    
    // success!
    return TRUE;
    }

#define MAKE_LPARAM(x,y) ( ((unsigned long)(y)<<16) | ((unsigned long)(x)) )

//------------------------------------------------------------------------
void CListSelRowCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
    {
    // force the point to be in the right place
    point.x = 6;
    LPARAM lp = MAKE_LPARAM(point.x, point.y);
//  DefWindowProc(WM_LBUTTONDBLCLK, nFlags, lp );
    CListCtrl::OnLButtonDblClk( nFlags, point);
    }

//------------------------------------------------------------------------
void CListSelRowCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    point.x = 6;
    LPARAM lp = MAKE_LPARAM(point.x, point.y);
//  DefWindowProc(WM_LBUTTONDOWN, nFlags, lp );
    CListCtrl::OnLButtonDown( nFlags, point);
    }