/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

// Created August 19, 1996 by Scott Putterman

#include "stdafx.h"
#include "tlbutton.h"
#include "mainfrm.h"
#include "ipframe.h"

#define TEXT_CHARACTERS_SHOWN 9
#define BORDERSIZE 2
#define TEXTVERTMARGIN 1
#define TEXTONLYVERTMARGIN 2
#define BITMAPVERTMARGIN 2
#define TEXT_BITMAPVERTMARGIN 1
#define HORIZMARGINSIZE 4

#define IDT_MENU		16383
#define MENU_DELAY_MS	500

#define IDT_BUTTONFOCUS 16410
#define BUTTONFOCUS_DELAY_MS 10

static CToolbarButton *pCurrentButton = NULL;

void WFE_ParseButtonString(UINT nID, CString &statusStr, CString &toolTipStr, CString &textStr)
{

		CString str1;

		str1.LoadString(nID);

		int nNewLineIndex = str1.Find('\n');
	
		if(nNewLineIndex == -1)
		{
			statusStr = str1;
			toolTipStr = statusStr;
			textStr = statusStr;
		}
		else
		{
			statusStr = str1.Left(nNewLineIndex);
			str1 = str1.Right( str1.GetLength() - (nNewLineIndex + 1));

			nNewLineIndex = str1.Find('\n');
			if( nNewLineIndex == -1)
			{
				toolTipStr = str1;
				textStr = toolTipStr;
			}
			else
			{
				toolTipStr = str1.Left(nNewLineIndex);
				textStr = str1.Right(str1.GetLength() - (nNewLineIndex + 1));
			}
		}



}

CButtonEditWnd::~CButtonEditWnd()
{

}


void CButtonEditWnd::SetToolbarButtonOwner(CToolbarButton *pOwner)
{
	m_pOwner = pOwner;
}

BOOL CButtonEditWnd::PreTranslateMessage ( MSG * msg )
{
   if ( msg->message == WM_KEYDOWN)
   {
      switch(msg->wParam)
      {
         case VK_RETURN:
         {
			m_pOwner->EditTextChanged(m_pOwner->GetTextEditText());
            return TRUE; // Bail out, since m_pOwner has been deleted.

         }
		 case VK_ESCAPE:
			 m_pOwner->RemoveTextEdit();
			 break;
	  }
   }
   
   return CEdit::PreTranslateMessage ( msg );
}

//////////////////////////////////////////////////////////////////////////
//					Messages for CButtonEditWnd
//////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CButtonEditWnd, CEdit)
	//{{AFX_MSG_MAP(CWnd)
 	ON_WM_DESTROY()
	ON_WM_KILLFOCUS()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CButtonEditWnd::OnDestroy( )
{
	delete this;

}
  
void CButtonEditWnd::OnKillFocus( CWnd* pNewWnd )
{
	 m_pOwner->RemoveTextEdit();
}

////////////////////////////////////////////////////

void CALLBACK EXPORT NSButtonMenuTimerProc(
    HWND hwnd,	// handle of window for timer messages 
    UINT uMsg,	// WM_TIMER message
    UINT idEvent,	// timer identifier
    ULONG dwTime 	// current system time
    );

void CToolbarButtonCmdUI::Enable(BOOL bOn)
{

	if(bOn != ((CToolbarButton*)m_pOther)->IsEnabled())
	{

		((CToolbarButton*)m_pOther)->Enable(bOn);

		m_pOther->Invalidate();
	}

	m_bEnableChanged = TRUE;
}

void CToolbarButtonCmdUI::SetCheck( int nCheck)
{


	if( nCheck != ((CToolbarButton*)m_pOther)->GetCheck())
	{
		((CToolbarButton*)m_pOther)->SetCheck(nCheck);
		m_pOther->Invalidate();

	}


}
 

DROPEFFECT CToolbarButtonDropTarget::OnDragEnter(CWnd * pWnd,
	COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
{
	DROPEFFECT deReturn;

	// Only interested in bookmarks
	deReturn = ProcessDragEnter(pWnd, pDataObject, dwKeyState, point);
	if(deReturn != DROPEFFECT_NONE)
		pWnd->SendMessage(NSDRAGGINGONBUTTON, 0, 0);

	return(deReturn);

} 


DROPEFFECT CToolbarButtonDropTarget::OnDragOver(CWnd * pWnd,
	COleDataObject * pDataObject, DWORD dwKeyState, CPoint point)
{
	
	return ProcessDragOver(pWnd, pDataObject, dwKeyState, point);
} 


BOOL CToolbarButtonDropTarget::OnDrop(CWnd * pWnd,
	COleDataObject * pDataObject, DROPEFFECT dropEffect, CPoint point)
{

	return ProcessDrop(pWnd, pDataObject, dropEffect, point);
	
} 

CToolbarButton::CToolbarButton()
{
	m_nIconType = BUILTIN_BITMAP;
	m_pBitmapFile = NULL;
	m_pButtonText = NULL;
	m_pToolTipText = NULL;
	m_pStatusText = NULL;
	m_bMenuShowing =FALSE;
	m_bButtonDown = FALSE;
	m_bHaveFocus = FALSE;
	m_bIsResourceID = TRUE;
	m_hFocusTimer = 0;
	m_pDropMenu = NULL;
	m_pDropTarget = NULL;
	m_bDraggingOnButton = FALSE;
	m_hBmpImg = NULL;
	m_nChecked = 0;
	m_bPicturesOnly = FALSE;
    m_bDoOnButtonDown = FALSE;
    m_dwButtonStyle = 0;
	m_bDepressed = FALSE;
	hasCustomTextColor = FALSE;
	hasCustomBGColor = FALSE;
}


CToolbarButton::~CToolbarButton()
{
	if(m_pButtonText != NULL)
	{
		XP_FREE(m_pButtonText);
	}

	if(m_pToolTipText != NULL)
	{
		XP_FREE(m_pToolTipText);
	}

	if(m_pStatusText != NULL)
	{
		XP_FREE(m_pStatusText);
	}

	if(m_pBitmapFile != NULL)
	{
		XP_FREE(m_pBitmapFile);
	}

	if(m_pDropMenu != NULL)
	{
		delete m_pDropMenu;
	}

	if(m_pDropTarget != NULL)
	{
		delete m_pDropTarget;
	}

	if(m_hBmpImg != NULL && !m_bBitmapFromParent)
		DeleteObject(m_hBmpImg);

	if(pCurrentButton == this)
		pCurrentButton = NULL;
}

int CToolbarButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize,
						   CSize advancedButtonSize,  LPCTSTR pButtonText, LPCTSTR pToolTipText,
						   LPCTSTR pStatusText, UINT nBitmapID, UINT nBitmapIndex, CSize bitmapSize, 
						   BOOL bNeedsUpdate, UINT nCommand, int nMaxTextChars, int nMinTextChars,
                           DWORD dwButtonStyle)
{
	


	m_nBitmapID = nBitmapID;
	m_nBitmapIndex = nBitmapIndex;
	m_nToolbarStyle = nToolbarStyle;
	m_noviceButtonSize = noviceButtonSize;
	m_advancedButtonSize = advancedButtonSize;
	m_bitmapSize = bitmapSize;
	m_bEnabled = TRUE;
	m_bNeedsUpdate = bNeedsUpdate;
	m_nCommand = nCommand;
	m_nMaxTextChars = nMaxTextChars;
    m_nMinTextChars = nMinTextChars;
    m_dwButtonStyle = dwButtonStyle;
    m_pTextEdit = NULL;

	CSize size = GetButtonSize();

	CRect rect(100, 100, size.cx, size.cy);
	CBrush brush;

	int bRtn = CWnd::Create( theApp.NSToolBarClass, NULL, 
					WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_PARENTDC,
					rect, pParent, nCommand, NULL);

	HINSTANCE hInst = AfxGetResourceHandle();

	CDC * pDC=GetDC();
	if(m_bIsResourceID)
	{
		// if we haven't been given a bitmap yet, we don't want to load this
		if(m_nBitmapID != 0)
		{
			WFE_InitializeUIPalette(pDC->m_hDC);
			HPALETTE hPalette= WFE_GetUIPalette(GetParentFrame());
			HPALETTE hOldPalette = SelectPalette(pDC->m_hDC, hPalette, FALSE);
			m_hBmpImg = WFE_LoadTransparentBitmap(hInst, pDC->m_hDC, sysInfo.m_clrBtnFace, RGB(255, 0, 255), hPalette, m_nBitmapID);
			SelectPalette(pDC->m_hDC, hOldPalette, TRUE);
		}
	}
	else
		m_hBmpImg = WFE_LoadBitmapFromFile(m_pBitmapFile);

	ReleaseDC(pDC);

	m_bBitmapFromParent = FALSE;

	SetText(pButtonText);

	if(pToolTipText != NULL)
	{
		m_pToolTipText = (LPTSTR)XP_ALLOC(XP_STRLEN(pToolTipText) + 1);
		XP_STRCPY(m_pToolTipText, pToolTipText);
	}


	m_pStatusText = (LPTSTR) XP_ALLOC(XP_STRLEN(pStatusText) + 1);
	XP_STRCPY(m_pStatusText, pStatusText);

    // Force initialization in SetStyle()
    m_dwButtonStyle = DWORD(-1);
    
    //Code moved to function so style can be set separately
    SetStyle(dwButtonStyle);

	m_eState = eNORMAL;

	return bRtn;
}

void CToolbarButton::SetStyle(DWORD dwButtonStyle)
{
    // If no change from current style, then do nothing
	if( m_dwButtonStyle == dwButtonStyle ){
        return;
    }
	m_dwButtonStyle = dwButtonStyle;
	CSize size = GetButtonSize();
    
    if(dwButtonStyle & TB_HAS_TIMED_MENU || dwButtonStyle & TB_HAS_IMMEDIATE_MENU)
	{
		// Create menu if not already done
        // Menu contents are appended and removed every time its used,
        //  so we don't need to delete items here
        if(!(dwButtonStyle & TB_HAS_DRAGABLE_MENU 
			&& m_menu.m_hMenu != NULL
			&& !IsMenu(m_menu.m_hMenu)))
			m_menu.CreatePopupMenu();
	}
    else if(dwButtonStyle & TB_HAS_DROPDOWN_TOOLBAR){
        // Even though the styles are bit flags,
        //    DROPDOWN_TOOLBAR style cannot be used with the MENU STYLES
        SetDoOnButtonDown(TRUE);   
    }

	// Create tooltip only if we have text and it wasn't created before
    if(m_pToolTipText != NULL && !IsWindow(m_ToolTip.m_hWnd))
	{
#ifdef WIN32
		m_ToolTip.Create(this, TTS_ALWAYSTIP);
#else
		m_ToolTip.Create(this);
#endif

		if(dwButtonStyle & TB_DYNAMIC_TOOLTIP)
		{
			CRect tipRect(0, 0, size.cx, size.cy);
			m_ToolTip.AddTool(this, LPSTR_TEXTCALLBACK, (m_nCommand == 0) ? NULL : &tipRect,
							  m_nCommand);
		}
		else
		{
			m_ToolTip.AddTool(this, m_pToolTipText);
		}

		m_ToolTip.Activate(TRUE);
		m_ToolTip.SetDelayTime(250);
	}
}

int CToolbarButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize, CSize advancedButtonSize,
			   LPCTSTR pButtonText, LPCTSTR pToolTipText, 
			   LPCTSTR pStatusText, LPCTSTR pBitmapFile,
			   CSize m_bitmapSize, BOOL bNeedsUpdate, UINT nCommand, int nMaxTextChars, int nMinTextChars,
               DWORD dwButtonStyle)
{

	m_bIsResourceID = FALSE;

	m_pBitmapFile = (LPTSTR) XP_ALLOC(XP_STRLEN(pBitmapFile) + 1);
	XP_STRCPY(m_pBitmapFile, pBitmapFile);

	return Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize, pButtonText, pToolTipText,
				  pStatusText, 0, 0, m_bitmapSize, bNeedsUpdate, nCommand, nMaxTextChars, nMinTextChars,
                  dwButtonStyle);


}

void CToolbarButton::SetText(LPCTSTR pButtonText)
{
	CSize oldSize = GetRequiredButtonSize();

	if(m_pButtonText != NULL)
	{
		XP_FREE(m_pButtonText);
	}

	m_pButtonText = (LPTSTR)XP_ALLOC(XP_STRLEN(pButtonText) +1);
	XP_STRCPY(m_pButtonText, pButtonText);

	CSize newSize = GetRequiredButtonSize();

	if((m_nToolbarStyle == TB_PICTURESANDTEXT || m_nToolbarStyle == TB_TEXT) && ::IsWindow(m_hWnd))
	{
		RedrawWindow();
	}

	if(oldSize != newSize)
		GetParent()->SendMessage(TB_SIZECHANGED, 0, (LPARAM)m_hWnd);

}

void CToolbarButton::SetButtonCommand(UINT nCommand)
{
#ifdef XP_WIN32
	CToolInfo ToolInfo;
    UINT nID =  (m_dwButtonStyle & TB_DYNAMIC_TOOLTIP) ? m_nCommand: 0;
	
	m_ToolTip.GetToolInfo(ToolInfo,this,nID);
	ToolInfo.uId =   (m_dwButtonStyle & TB_DYNAMIC_TOOLTIP) ? nCommand: 0;
	m_ToolTip.SetToolInfo(&ToolInfo);
	m_nCommand = nCommand;
#else
	TOOLINFO ToolInfo;
    UINT nID =  (m_dwButtonStyle & TB_DYNAMIC_TOOLTIP) ? m_nCommand: 0;
	
	m_ToolTip.GetToolInfo(&ToolInfo);
	ToolInfo.uId =   (m_dwButtonStyle & TB_DYNAMIC_TOOLTIP) ? nCommand: 0;
	m_ToolTip.SetToolInfo(&ToolInfo);
	m_nCommand = nCommand;
#endif
}

void CToolbarButton::SetToolTipText(LPCSTR pToolTipText)

{
    if (pToolTipText == NULL) 
        return;

	if(m_pToolTipText != NULL)
	{
	    XP_FREE(m_pToolTipText);
	}
	m_pToolTipText = (LPTSTR)XP_ALLOC(XP_STRLEN(pToolTipText) +1);
	XP_STRCPY(m_pToolTipText, pToolTipText);
    UINT nID = (m_dwButtonStyle & TB_DYNAMIC_TOOLTIP) ? m_nCommand: 0;
	m_ToolTip.UpdateTipText(m_pToolTipText, this, nID);
}

void CToolbarButton::SetStatusText(LPCSTR pStatusText)
{
    if (pStatusText == NULL)
        return;

    if(m_pStatusText != NULL)
    {
		XP_FREE(m_pStatusText);
	}
	m_pStatusText = (LPTSTR)XP_ALLOC(XP_STRLEN(pStatusText) +1);
	XP_STRCPY(m_pStatusText, pStatusText);
}

void CToolbarButton::SetBitmap(HBITMAP hBmpImg, BOOL bParentOwns)
{
	if(m_hBmpImg != NULL && !m_bBitmapFromParent)
		::DeleteObject(m_hBmpImg);

	m_hBmpImg = hBmpImg;
	m_bBitmapFromParent = bParentOwns;
}

void CToolbarButton::ReplaceBitmap(UINT nBitmapID, UINT nBitmapIndex)
{
	m_nBitmapID = nBitmapID;
	m_nBitmapIndex = nBitmapIndex;

	m_bIsResourceID = TRUE;
	RedrawWindow();
}

void CToolbarButton::ReplaceBitmap(LPCTSTR pBitmapFile)
{

	if(m_pBitmapFile != NULL)
	{
		XP_FREE(m_pBitmapFile);
	}

	m_pBitmapFile = (LPTSTR)XP_ALLOC(XP_STRLEN(pBitmapFile) +1);
	XP_STRCPY(m_pBitmapFile, pBitmapFile);

	m_bIsResourceID = FALSE;
	RedrawWindow();
}

void CToolbarButton::ReplaceBitmap(HBITMAP hBmpImg, UINT nBitmapIndex, BOOL bParentOwns)
{
	SetBitmap(hBmpImg, bParentOwns);
	ReplaceBitmap(0, nBitmapIndex);
}

void CToolbarButton::ReplaceBitmapIndex(UINT nBitmapIndex)
{
	if(m_nBitmapIndex != nBitmapIndex)
	{
		m_nBitmapIndex = nBitmapIndex;
		RedrawWindow();
	}
}

CSize CToolbarButton::GetButtonSize(void)
{
	return(m_nToolbarStyle == TB_PICTURESANDTEXT ? m_noviceButtonSize : m_advancedButtonSize);
}

CSize CToolbarButton::GetRequiredButtonSize(void)
{
    return GetButtonSizeFromChars(m_pButtonText, m_nMaxTextChars);
}

CSize CToolbarButton::GetButtonSizeFromChars(CString s, int c)
{
    CSize size;

	if(m_nToolbarStyle == TB_PICTURESANDTEXT)
	{
		size = GetBitmapOnTopSize(s, c);
	}
	else if (m_nToolbarStyle == TB_PICTURES)
	{
		size = GetBitmapOnlySize();
	}
	else if(m_nToolbarStyle == TB_TEXT)
	{
		size = GetTextOnlySize(s, c);
	}

	return size;
}

CSize CToolbarButton::GetMinimalButtonSize(void)
{
    return GetButtonSizeFromChars(m_pButtonText, m_nMinTextChars);
}

CSize CToolbarButton::GetMaximalButtonSize(void)
{
    return GetButtonSizeFromChars(m_pButtonText, m_nMaxTextChars);
}

void CToolbarButton::CheckForMinimalSize(void)
{
    // A button is at its minimal size if its
    // current horizontal extent is <= its minimal horizontal extent.
    atMinimalSize = (GetButtonSize().cx <= GetMinimalButtonSize().cx);
}

void CToolbarButton::CheckForMaximalSize(void)
{
    // A button is at its maximal size if its
    // current horizontal extent is >= its maximal horizontal extent.
    atMaximalSize = (GetButtonSize().cx >= GetMaximalButtonSize().cx);
}

BOOL CToolbarButton::AtMinimalSize(void)
{
    CheckForMinimalSize();
    return atMinimalSize;
}

BOOL CToolbarButton::AtMaximalSize(void)
{
    CheckForMaximalSize();
    return atMaximalSize;
}

void CToolbarButton::SetBitmapSize(CSize sizeImage)
{
	m_bitmapSize = sizeImage;
	RedrawWindow();
}

void CToolbarButton::SetButtonSize(CSize buttonSize)
{
	if(m_nToolbarStyle == TB_PICTURESANDTEXT)
	{
		m_noviceButtonSize  = buttonSize;
	}
	else
	{
		m_advancedButtonSize = buttonSize;
	}
}

void CToolbarButton::SetDropTarget(CToolbarButtonDropTarget *pDropTarget)
{

	m_pDropTarget = pDropTarget;

	m_pDropTarget->Register(this);
	m_pDropTarget->SetButton(this);
}

void CToolbarButton::SetCheck(int nCheck)
{
	m_nChecked = nCheck;
	switch(nCheck)
	{
		case 0: m_eState = eNORMAL;
				break;
		case 1: m_eState = eBUTTON_CHECKED; //eBUTTON_DOWN;
				break;
		case 2: m_eState = eDISABLED;
				break;
	}

}

int CToolbarButton::GetCheck(void)
{
	return m_nChecked;
}

void CToolbarButton::SetPicturesOnly(int bPicturesOnly)
{
	m_bPicturesOnly = bPicturesOnly;
	SetButtonMode(TB_PICTURES);
}

void CToolbarButton::SetButtonMode(int nToolbarStyle)
{
	if(m_bPicturesOnly)
		m_nToolbarStyle = TB_PICTURES;
	else
		m_nToolbarStyle = nToolbarStyle;
}

void CToolbarButton::FillInButtonData(LPBUTTONITEM pButton)
{
	pButton->button = m_hWnd;
	
}

void CToolbarButton::ButtonDragged(void)
{
	KillTimer(m_hMenuTimer);
	m_eState = eNORMAL;
	RedrawWindow();
}

void CToolbarButton::AddTextEdit(void)
{
	if(!m_pTextEdit)
	{
		m_pTextEdit = new CButtonEditWnd;

		if(m_pTextEdit)
		{
			CRect rect;
			HDC hDC = ::GetDC(m_hWnd);
			HFONT hFont = WFE_GetUIFont(hDC);
			HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
			TEXTMETRIC tm;

			GetTextMetrics(hDC, &tm);
			int height = tm.tmHeight;

			::SelectObject(hDC, hOldFont);
			::ReleaseDC(m_hWnd, hDC);

			GetTextRect(rect);
			if(rect.Height() > height)
			{
				rect.top += (rect.Height() - height) / 2;
				rect.bottom -= (rect.Height() - height) / 2;
			}

			BOOL bRtn = m_pTextEdit->Create(ES_AUTOHSCROLL, rect, this, 0);

			if(!bRtn)
			{
				delete m_pTextEdit;
				m_pTextEdit = NULL;
			}
			else
			{
				m_pTextEdit->ShowWindow(SW_SHOW);
				HDC hDC = ::GetDC(m_hWnd);

				HFONT hFont = WFE_GetUIFont(hDC);
				CFont *font = (CFont*) CFont::FromHandle(hFont);
				m_pTextEdit->SetFont(font);
				::ReleaseDC(m_hWnd, hDC);
				m_pTextEdit->SetFocus();
				m_pTextEdit->SetToolbarButtonOwner(this);
			}

		}

	}
}

void CToolbarButton::RemoveTextEdit(void)
{
	if(m_pTextEdit)
	{
		m_pTextEdit->PostMessage(WM_DESTROY, 0, 0);
		m_pTextEdit = NULL;

	}

}

void CToolbarButton::SetTextEditText(char *pText)
{
	if(m_pTextEdit)
	{
		m_pTextEdit->ReplaceSel(pText);
		m_pTextEdit->SetSel(0, strlen(pText), TRUE);
	}

}

// the string returned must be deleted
char * CToolbarButton::GetTextEditText(void)
{
	char str[1000];

	if(m_pTextEdit)
	{
		int size = m_pTextEdit->GetWindowText(str, 1000);
		if(size > 0)
		{
			char *newStr = new char[size + 1];
			strcpy(newStr, str);
			return newStr;
		}
	}

	return NULL;

}

void CToolbarButton::EditTextChanged(char *pText)
{
	SetText(pText);
}


//////////////////////////////////////////////////////////////////////////
//					Messages for CToolbarButton
//////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CToolbarButton, CWnd)
	//{{AFX_MSG_MAP(CWnd)
 	ON_WM_PAINT()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_SHOWWINDOW()
	ON_WM_ERASEBKGND()
#ifdef _WIN32
	ON_WM_CAPTURECHANGED()
#endif
	ON_WM_GETDLGCODE()
	ON_WM_KEYDOWN()
	ON_MESSAGE(TTN_NEEDTEXT, OnToolTipNeedText) 
	ON_WM_TIMER()
	ON_MESSAGE(NSDRAGMENUOPEN, OnDragMenuOpen)
	ON_MESSAGE(NSDRAGGINGONBUTTON, OnDraggingOnButton)
	ON_WM_PALETTECHANGED()
	ON_WM_SYSCOLORCHANGE()
    ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP

END_MESSAGE_MAP()

void CToolbarButton::OnLButtonDown(UINT nFlags, CPoint point)
{
	if(m_bEnabled)
	{
		// Show the button down look
		m_eState = eBUTTON_DOWN;
		m_bDraggingOnButton = FALSE;
		if(m_dwButtonStyle & TB_HAS_TIMED_MENU)
		{
			m_hMenuTimer = SetTimer(IDT_MENU, MENU_DELAY_MS, NULL);
		}
				
		RedrawWindow();
	}
	if(m_pToolTipText != NULL)
	{
		MSG msg = *(GetCurrentMessage());
		m_ToolTip.RelayEvent(&msg);
	}

    // Do action immediately if this is set
	if( m_bDoOnButtonDown )
	{
        if (m_dwButtonStyle & TB_HAS_IMMEDIATE_MENU)
		{
			m_hMenuTimer = SetTimer(IDT_MENU, 0, NULL);
		}
		else OnAction();
	}
    else 
        m_bButtonDown = TRUE;
}

void CToolbarButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// Make sure we're activated (button look)
	if (!m_bHaveFocus)
	{
			if(GetTopLevelFrame() == GetActiveWindow() || GetTopLevelFrame() == AfxGetMainWnd())
			{
				m_bHaveFocus = TRUE;
				if(m_hFocusTimer == 0)
				{
					if(pCurrentButton)
						pCurrentButton->RemoveButtonFocus();
					pCurrentButton = this;
					m_hFocusTimer = SetTimer(IDT_BUTTONFOCUS, BUTTONFOCUS_DELAY_MS, NULL);

					BOOL bStatusText = (strcmp(m_pStatusText, "") != 0);
					char status[1000];

					if(m_dwButtonStyle & TB_DYNAMIC_STATUS){
						WFE_GetOwnerFrame(this)->SendMessage(TB_FILLINSTATUS, (WPARAM)m_nCommand, (LPARAM) status);
						WFE_GetOwnerFrame(this)->SendMessage( WM_SETMESSAGESTRING,
														   (WPARAM) 0, (LPARAM) status );
					}
					else if ( bStatusText) {
						WFE_GetOwnerFrame(this)->SendMessage( WM_SETMESSAGESTRING,
														   (WPARAM)0, (LPARAM) m_pStatusText );
					}

				}

				if(m_pToolTipText != NULL)
				{
					m_ToolTip.Activate(TRUE);
					MSG msg = *(GetCurrentMessage());
					m_ToolTip.RelayEvent(&msg);
				}

				if(m_bEnabled)
				{
					m_eState = (nFlags & MK_LBUTTON) ? eBUTTON_DOWN : eBUTTON_UP;
					RedrawWindow();
					UpdateWindow();
				}
			}
	}

	if(GetTopLevelFrame() == GetActiveWindow() || GetTopLevelFrame() == AfxGetMainWnd())
	{
		if(m_pToolTipText!= NULL)
		{
			MSG msg = *(GetCurrentMessage());
			m_ToolTip.RelayEvent(&msg);
		}
	}



}

void CToolbarButton::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(m_bEnabled)
	{
		// Do action only if not done on button down
        if(!m_bDoOnButtonDown)
        {
            // Cursor is still over the button, so back to button up look
			m_eState = eBUTTON_UP;
			if(m_bButtonDown)
			{
				 if (m_dwButtonStyle & TB_HAS_IMMEDIATE_MENU)
				 {
					m_hMenuTimer = SetTimer(IDT_MENU, 0, NULL);
				 }
				 else OnAction();
			}
        }
		
		if (m_dwButtonStyle & TB_HAS_IMMEDIATE_MENU)
		{
			m_hMenuTimer = SetTimer(IDT_MENU, 0, NULL);
		}
		
		RedrawWindow();
	}
	if(m_dwButtonStyle & TB_HAS_TIMED_MENU)
	{
		KillTimer(m_hMenuTimer);
	}
	if(m_pToolTipText != NULL)
	{
		MSG msg = *(GetCurrentMessage());
		m_ToolTip.RelayEvent(&msg);
	}
	m_bButtonDown = FALSE;

}

void CToolbarButton::OnRButtonDown(UINT nFlags, CPoint point)
{
    if (CreateRightMouseMenu())
    {
        DisplayAndTrackMenu();
    }

	if(m_pToolTipText != NULL)
	{
		MSG msg = *(GetCurrentMessage());
		m_ToolTip.RelayEvent(&msg);
	}


}

void CToolbarButton::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
{
	int i = 0;
	i++;

}
  

BOOL CToolbarButton::OnCommand(UINT wParam,LONG lParam)
{
	return((BOOL)GetParentFrame()->SendMessage(WM_COMMAND, wParam, lParam));
}


BOOL CToolbarButton::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
	NMHDR *hdr = (NMHDR*)lParam;
	if(hdr->code == TTN_NEEDTEXT)
	{
		int command = (int) wParam;
		LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lParam; 

		GetParentFrame()->SendMessage(TB_FILLINTOOLTIP, WPARAM(m_hWnd), lParam);
		return TRUE;
	}
#ifdef _WIN32
	else
		return (CWnd::OnNotify(wParam, lParam, pResult));
#else
	return FALSE;
#endif
}

void CToolbarButton::OnPaint()
{
	CRect updateRect;

	GetUpdateRect(&updateRect);

	CPaintDC dcPaint(this);	// device context for painting
	CRect rcClient;
	GetClientRect(&rcClient);
	
	HDC hSrcDC = dcPaint.m_hDC;

	HPALETTE hPalette;
	HPALETTE hOldPalette;
	CFrameWnd* pParent = WFE_GetOwnerFrame(this); 
	hPalette = WFE_GetUIPalette(pParent);
	hOldPalette= ::SelectPalette(hSrcDC, hPalette, FALSE);
	
	CFrameGlue *pGlue = CFrameGlue::GetFrameGlue(pParent);
	if (pParent && pGlue && (pParent->IsKindOf(RUNTIME_CLASS(CGenericFrame)) ||
		pParent->IsKindOf(RUNTIME_CLASS(CInPlaceFrame)))) {
		CFrameGlue *pGlue = CFrameGlue::GetFrameGlue(pParent);
		if (pGlue && !pGlue->IsBackGroundPalette()) {
			hOldPalette= ::SelectPalette(hSrcDC, hPalette, TRUE);
			::RealizePalette(hSrcDC);
		}
		else {
			hOldPalette= ::SelectPalette(hSrcDC, hPalette, FALSE);
		}
	}
	else {
		hOldPalette= ::SelectPalette(hSrcDC, hPalette, TRUE);
		::RealizePalette(hSrcDC);
	}
	HDC hMemDC = ::CreateCompatibleDC(hSrcDC);
	if(hMemDC)
	{
		HPALETTE hOldMemPalette = ::SelectPalette(hMemDC, hPalette, FALSE);

		HBITMAP hbmMem = CreateCompatibleBitmap(hSrcDC,
										rcClient.Width(),
										rcClient.Height());

		//
		// Select the bitmap into the off-screen DC.
		//

		HBITMAP hbmOld = (HBITMAP)::SelectObject(hMemDC, hbmMem);

		COLORREF rgbOldBk;
		
		// Use the button face color as our background
		HBRUSH brFace = sysInfo.m_hbrBtnFace;
		
		if (hasCustomBGColor)
		{
			// Use the button's custom background
			brFace = ::CreateSolidBrush(customBGColor);
		}
		else ::SetBkColor(hMemDC, sysInfo.m_clrBtnFace); // Use button face color.

		::FillRect(hMemDC, rcClient, brFace);
		
		if (m_bDepressed)
		{
			::DeleteObject(brFace);
		}

		// if we are not enabled then must make sure that button state is normal
		if(!m_bEnabled)
		{
			m_eState = eNORMAL;
		}

		CRect innerRect = rcClient;

		innerRect.InflateRect(-BORDERSIZE, -BORDERSIZE);

		if(m_nToolbarStyle == TB_PICTURESANDTEXT)
		{
			DrawPicturesAndTextMode(hMemDC, innerRect);
		}
		else if(m_nToolbarStyle == TB_PICTURES)
		{
			DrawPicturesMode(hMemDC, innerRect);
		}
		else
		{
			DrawTextMode(hMemDC, innerRect);
		}

		// Now, draw 3d visual button effects, depending on our state
		switch (m_eState)
		{
			case eBUTTON_UP:
			{
                if( m_nChecked == 0 )
    				DrawUpButton(hMemDC, rcClient);
                else
    			    DrawDownButton(hMemDC, rcClient);
			}
			break;
			
			case eBUTTON_CHECKED:
			{
				// A checked button but NOT mousing over - no black border
                DrawCheckedButton(hMemDC, rcClient);
			}
			break;

			case eBUTTON_DOWN:
			{
				DrawDownButton(hMemDC, rcClient);
			}
			break;

			case eDISABLED:
			{
				if(m_nChecked == 2)
					DrawCheckedButton(hMemDC, rcClient);

			}
			break;

			case eNORMAL:
			{
				if (m_bDepressed)
					DrawDownButton(hMemDC, rcClient); // Looks like it's locked down.
			}
		}

		::SetBkColor(hMemDC, rgbOldBk);

		::BitBlt(hSrcDC, 0, 0, rcClient.Width(), rcClient.Height(), hMemDC, 0, 0,
						SRCCOPY);

		::SelectPalette(hMemDC, hOldMemPalette, FALSE);
		::SelectPalette(hSrcDC, hOldPalette, FALSE);

		::SelectObject(hMemDC, hbmOld);
		::DeleteObject(hbmMem);
 
		::DeleteDC(hMemDC);
	}
}

void CToolbarButton::OnShowWindow( BOOL bShow, UINT nStatus )
{
	m_bEraseBackground = bShow;
}

BOOL CToolbarButton::OnEraseBkgnd( CDC* pDC )
{
	if ( m_bEraseBackground ) {
		m_bEraseBackground = FALSE;
		return (BOOL) Default();
	} else {
		return TRUE;
	}
}

void CToolbarButton::OnCaptureChanged( CWnd* pWnd )
{
}
 
UINT CToolbarButton::OnGetDlgCode(void )
{
	return DLGC_WANTALLKEYS;

}

LRESULT CToolbarButton::OnToolTipNeedText(WPARAM wParam, LPARAM lParam)
{
	LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT) lParam;
	GetParentFrame()->SendMessage(TB_FILLINTOOLTIP, WPARAM(m_hWnd), lParam);

	return 1;
}

void CToolbarButton::OnTimer( UINT  nIDEvent )
{
	if(nIDEvent == IDT_MENU)
	{
		KillTimer( IDT_MENU );

		SetState(eBUTTON_DOWN);

		RedrawWindow();


		if(m_dwButtonStyle & TB_HAS_DRAGABLE_MENU)
		{
			CPoint point = RequestMenuPlacement();

			if(m_pDropMenu == NULL || !m_pDropMenu->IsOpen())
			{
				int nCount;
				if(m_pDropMenu != NULL)
				{
					nCount = m_pDropMenu->GetMenuItemCount();

					// clean out the menu before adding to it
					for(int i = nCount - 1; i >= 0; i--)
					{
						m_pDropMenu->DeleteMenu(i, MF_BYPOSITION);
					}
					m_pDropMenu->DestroyDropMenu();
					delete m_pDropMenu;
				}

				m_pDropMenu = new CDropMenu;

				SendMessage(NSDRAGMENUOPEN, (WPARAM)GetButtonCommand(), (LPARAM)m_pDropMenu);

				nCount = m_pDropMenu->GetMenuItemCount();

				if(nCount > 0)
				{
					CDropMenuDropTarget *dropTarget = new CDropMenuDropTarget(m_pDropMenu);

					m_pDropMenu->TrackDropMenu(this, point.x, point.y, m_bDraggingOnButton, dropTarget, m_bDraggingOnButton);
				}
			}
			
		}
		else
		{

			CPoint point(0, GetButtonSize().cy);
			ClientToScreen(&point);

			CMenu &pMenu = GetButtonMenu();

#ifdef _WIN32
			WFE_GetOwnerFrame(this)->SendMessage(NSBUTTONMENUOPEN, MAKEWPARAM(GetButtonCommand(), 0 ),(LPARAM)pMenu.m_hMenu);
#else
			WFE_GetOwnerFrame(this)->SendMessage(NSBUTTONMENUOPEN, (WPARAM) GetButtonCommand(), MAKELPARAM(pMenu.m_hMenu, 0));
#endif
			SetMenuShowing(TRUE);

			CWnd *pWnd = WFE_GetOwnerFrame(this);
			CRect rect;
			GetWindowRect(&rect);

			pMenu.TrackPopupMenu(TPM_LEFTALIGN,point.x, point.y, pWnd ? pWnd : this, &rect);
				
			SetMenuShowing(FALSE);

			int nCount = pMenu.GetMenuItemCount();

			for(int i = 0; i < nCount ; i++)
			{
				pMenu.DeleteMenu(0, MF_BYPOSITION);
			}

		}

		SetState( eNORMAL);
		RedrawWindow();
	}
	if(nIDEvent == IDT_BUTTONFOCUS)
	{
		RemoveButtonFocus();
	}


}

LRESULT CToolbarButton::OnDragMenuOpen(WPARAM wParam, LPARAM lParam)
{
	GetParentFrame()->SendMessage(NSDRAGMENUOPEN,wParam, lParam);

	return 1;
}

LRESULT CToolbarButton::OnDraggingOnButton(WPARAM wParam, LPARAM lParam)
{

	m_bDraggingOnButton = TRUE;
	if(m_dwButtonStyle & TB_HAS_TIMED_MENU)
	{
		m_hMenuTimer = SetTimer(IDT_MENU, MENU_DELAY_MS, NULL);
	}
	else if(m_dwButtonStyle & TB_HAS_IMMEDIATE_MENU)
	{
		m_hMenuTimer = SetTimer(IDT_MENU, 0, NULL);
	}

	return 1;
}

void CToolbarButton::OnPaletteChanged( CWnd* pFocusWnd )
{
	if (pFocusWnd != this ) {
		Invalidate();
		UpdateWindow();
	}

}

void CToolbarButton::OnSysColorChange( )
{
	if(!m_bBitmapFromParent)
	{
		if(m_bIsResourceID)
		{
			if(m_hBmpImg)
				::DeleteObject(m_hBmpImg);

			HINSTANCE hInst = AfxGetResourceHandle();
			HDC hDC = ::GetDC(m_hWnd);

			HPALETTE hPalette= WFE_GetUIPalette(GetParentFrame());
			m_hBmpImg = WFE_LoadTransparentBitmap(hInst, hDC, sysInfo.m_clrBtnFace, RGB(255, 0, 255), hPalette, m_nBitmapID);
			
			::ReleaseDC(m_hWnd, hDC);
			Invalidate();
		}
	}
}

HBRUSH CToolbarButton::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor )
{
	if(pWnd == m_pTextEdit && nCtlColor == CTLCOLOR_EDIT)
	{

		pDC->SetBkColor(sysInfo.m_clrBtnFace);
		pDC->SetTextColor(sysInfo.m_clrBtnText);
		return sysInfo.m_hbrBtnFace;
	}

	return NULL;
}

//////////////////////////////////////////////////////////////////////////
//					Helper Functions for CToolbarButton
//////////////////////////////////////////////////////////////////////////

void CToolbarButton::DrawPicturesAndTextMode(HDC hDC, CRect rect)
{

	DrawBitmapOnTop(hDC, rect);
}

void CToolbarButton::DrawPicturesMode(HDC hDC, CRect rect)
{

	DrawButtonBitmap(hDC, rect);

}

void CToolbarButton::DrawTextMode(HDC hDC, CRect rect)
{

	DrawTextOnly(hDC, rect);
}

void CToolbarButton::DrawBitmapOnTop(HDC hDC, CRect rect)
{
	CRect bitmapRect = rect;

	//goes 2 pixels from top
	bitmapRect.top += BITMAPVERTMARGIN;
	// Adjust the image rect
	bitmapRect.bottom = bitmapRect.top + m_bitmapSize.cy;
	
	DrawButtonBitmap(hDC, bitmapRect);

		// must make room for text . Note that our owner is
	// responsible for making sure our overall height is big enough to
	// hold both text and graphics.
	CString strTxt(m_pButtonText);

	if(m_nMaxTextChars != SHOW_ALL_CHARACTERS)
	{
		 strTxt = strTxt.Left(m_nMaxTextChars);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);

	SIZE sizeTxt;

	CRect sizeRect(0,0,150,0);
	::DrawText(hDC, strTxt, strTxt.GetLength(), &sizeRect, DT_CALCRECT | DT_WORDBREAK);
	sizeTxt.cx = sizeRect.Width();
	sizeTxt.cy = sizeRect.Height();

	// text's baseline should be 3 pixels from bottom
	CRect txtRect = rect;

	txtRect.top = bitmapRect.bottom +TEXT_BITMAPVERTMARGIN;
	
	DrawButtonText(hDC, txtRect, sizeTxt, strTxt);

	::SelectObject(hDC, hOldFont);

}

void CToolbarButton::DrawBitmapOnSide(HDC hDC, CRect rect)
{

	CRect bitmapRect = rect;

	bitmapRect.right = m_bitmapSize.cx + BORDERSIZE;

	DrawButtonBitmap(hDC, bitmapRect);

	CString strTxt(m_pButtonText);

	if(m_nMaxTextChars != SHOW_ALL_CHARACTERS)
	{
		 strTxt = strTxt.Left(m_nMaxTextChars);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);

	SIZE sizeTxt;
#if defined (WIN32)
	::GetTextExtentPoint32(hDC, (LPCSTR)strTxt, strTxt.GetLength(), &sizeTxt);
#else
	DWORD dwSize = ::GetTextExtent(hDC, (LPCSTR)strTxt, strTxt.GetLength());
	sizeTxt.cx = LOWORD(dwSize);
	sizeTxt.cy = HIWORD(dwSize);
#endif

	CRect txtRect = rect;

	txtRect.left = bitmapRect.right;

	DrawButtonText(hDC, txtRect, sizeTxt, strTxt);

	::SelectObject(hDC, hOldFont);
}

void CToolbarButton::DrawTextOnly(HDC hDC, CRect rect)
{

	CString strTxt(m_pButtonText);

	if(m_nMaxTextChars != SHOW_ALL_CHARACTERS)
	{
		 strTxt = strTxt.Left(m_nMaxTextChars);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);


	SIZE sizeTxt;

	CRect sizeRect(0,0,150,0);
	::DrawText(hDC, strTxt, strTxt.GetLength(), &sizeRect, DT_CALCRECT | DT_WORDBREAK);
	sizeTxt.cx = sizeRect.Width();
	sizeTxt.cy = sizeRect.Height();

	CRect txtRect = rect;

	DrawButtonText(hDC, txtRect, sizeTxt, strTxt);


	::SelectObject(hDC, hOldFont);
}

void CToolbarButton::DrawButtonText(HDC hDC, CRect rcTxt, CSize sizeTxt, CString strTxt)
{

	int nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);


	if(m_bEnabled)
	{
		UINT nFormat = strTxt.Find('\n') != -1 ? 0 : DT_SINGLELINE | DT_VCENTER;

		COLORREF oldColor;

		if (hasCustomTextColor)
		{
			oldColor = ::SetTextColor(hDC, customTextColor);
		}
		else if(m_eState == eNORMAL || m_eState == eBUTTON_CHECKED)
		{
			oldColor = ::SetTextColor(hDC, sysInfo.m_clrBtnText);
			if (m_bDepressed)
				oldColor = ::SetTextColor(hDC, RGB(255,255,255));
		}
		else if (m_eState == eBUTTON_DOWN)
		{
			oldColor = ::SetTextColor(hDC, RGB(0, 0, 128));
		}
		else if(m_eState == eBUTTON_UP)
		{
			oldColor = ::SetTextColor(hDC, RGB(0, 0, 255));
		}

		DrawText(hDC, (LPCSTR)strTxt, -1, &rcTxt, DT_CENTER | DT_EXTERNALLEADING | nFormat);

		::SetTextColor(hDC, oldColor);
	}
	else
	{
		CRect textRect = rcTxt;

		
		textRect.left = textRect.left + (textRect.Width() - sizeTxt.cx) / 2;
		textRect.top = textRect.top + (textRect.Height() - sizeTxt.cy) / 2;

		CRect textBackgroundRect = textRect;

#ifdef XP_WIN32
		if(sysInfo.m_bWin4)
		{
			
			TEXTMETRIC tm;
			
			GetTextMetrics(hDC, &tm);

			int descent = tm.tmDescent;
			int retVal = DrawState(hDC, NULL, NULL, (LPARAM)strTxt.LockBuffer(), 0, textRect.left, textRect.top, 0, 0, DST_TEXT | DSS_DISABLED);
			strTxt.UnlockBuffer();

		}
		else
#endif
		{
			UINT nFormat = strTxt.Find('\n') != -1 ? 0 : DT_SINGLELINE;

			textBackgroundRect.left +=1;
			textBackgroundRect.top +=1;
			
			COLORREF oldColor = ::SetTextColor(hDC,  GetSysColor(COLOR_BTNHIGHLIGHT )); // white
			::DrawText( hDC, (LPCSTR) strTxt, -1, &textBackgroundRect,   DT_EXTERNALLEADING | nFormat);
			::SetTextColor(hDC, GetSysColor( COLOR_GRAYTEXT ) );
			::DrawText(hDC, (LPCSTR) strTxt, -1, &textRect,   DT_EXTERNALLEADING | nFormat);
			::SetTextColor(hDC, oldColor );
		}
	}

	::SetBkMode(hDC, nOldBkMode);
}


void CToolbarButton::DrawButtonBitmap(HDC hDC, CRect rcImg)
{
	if(m_hBmpImg != NULL)
	{
		// Create a scratch DC and select our bitmap into it.
		HDC pBmpDC  = ::CreateCompatibleDC(hDC);
		HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());

		CBitmap BmpImg;

		CPoint ptDst;

		HINSTANCE hInst = AfxGetResourceHandle();


		HBITMAP hBmpImg;

		hBmpImg = m_hBmpImg;

		HBITMAP hOldBmp = (HBITMAP)::SelectObject(pBmpDC, hBmpImg);
		HPALETTE hOldPal = ::SelectPalette(pBmpDC, WFE_GetUIPalette(NULL), TRUE);
		::RealizePalette(pBmpDC);
		// Get the image dimensions
		CSize sizeImg;
		BITMAP bmp;

		::GetObject(hBmpImg, sizeof(bmp), &bmp);
		sizeImg.cx = bmp.bmWidth;
		sizeImg.cy = bmp.bmHeight;

		// Center the image within the button	
		ptDst.x = (rcImg.Width() >= m_bitmapSize.cx) ?
			rcImg.left + (((rcImg.Width() - m_bitmapSize.cx) + 1) / 2) : 0;
		
		ptDst.y = rcImg.top; 
		// If we're in the checked state, shift the image one pixel
		if (m_eState == eBUTTON_CHECKED || (m_eState == eBUTTON_UP && m_nChecked == 1))
		{
			ptDst.x += 1;
			ptDst.y += 1;
		}
	
		// Call the handy transparent blit function to paint the bitmap over
		// whatever colors exist.
		
		CPoint bitmapStart;

		BTN_STATE eState = m_eState;

		if(m_eState == eBUTTON_CHECKED)
			// A checked button has same bitmap as the normal state with no mouse-over
			eState = eNORMAL;
		else if(m_eState == eBUTTON_UP && m_nChecked == 2)
			// if we are in the mouse over mode, but indeterminate we want our bitmap to have a disabled look
			eState = eDISABLED;

        if(m_bIsResourceID)
			bitmapStart = CPoint(m_nBitmapIndex * m_bitmapSize.cx, m_bEnabled ? m_bitmapSize.cy * eState : m_bitmapSize.cy);

		if(m_bIsResourceID)  
		{
			UpdateIconInfo();
			if(m_nIconType == LOCAL_FILE)
			{
				DrawLocalIcon(hDC, ptDst.x, ptDst.y);
			}
			else if (m_nIconType == ARBITRARY_URL)
			{
				DrawCustomIcon(hDC, ptDst.x, ptDst.y);
			}
			else       
                ::BitBlt(hDC, ptDst.x, ptDst.y, m_bitmapSize.cx, m_bitmapSize.cy, 
					 pBmpDC, bitmapStart.x, bitmapStart.y, SRCCOPY);
		}
		else
		{
			CSize destSize;

			if(sizeImg.cx > sizeImg.cy)
			{
				destSize.cx = m_bitmapSize.cx;
				destSize.cy = (int)(m_bitmapSize.cy * ((double)sizeImg.cy / sizeImg.cx));
			}
			else
			{
				destSize.cx = (int)(m_bitmapSize.cx * ((double)sizeImg.cx/ sizeImg.cy));
				destSize.cy = m_bitmapSize.cy;
			}
			StretchBlt(hDC, ptDst.x, ptDst.y, destSize.cx, destSize.cy,
						pBmpDC, 0, 0, sizeImg.cx, sizeImg.cy, SRCCOPY);
		}

		// Cleanup

		::SelectObject(pBmpDC, hOldBmp);
		::SelectPalette(pBmpDC, hOldPal, TRUE);
		::DeleteDC(pBmpDC);

	}
}

/****************************************************************************
*
*	Function: DrawUpButton
*
*	PARAMETERS:
*		pDC		- pointer to DC to draw on
*		rect	- client rect to draw in
*
*	RETURNS:
*		void
*
*	DESCRIPTION:
*		Protected helper function for drawing the 3d "up button" look.
*		This is a static function so it may be called without instantiating
*		the object.
*
****************************************************************************/
void CToolbarButton::DrawUpButton(HDC hDC, CRect & rect)
{
	HBRUSH br = ::CreateSolidBrush(::GetSysColor(COLOR_BTNHIGHLIGHT));

	CRect rc(rect.left+1, rect.top+1, rect.right, 2);
	::FillRect(hDC, rc, br);
	rc.SetRect(rect.left+1, rect.top+1, rect.left+2, rect.bottom - 1);
	::FillRect(hDC, rc, br);
	::DeleteObject(br);
	
	br = ::CreateSolidBrush((RGB(0, 0, 0)));
    // Extra focus indication is solid black rect around outside
    // Looks more like "Win3.0" style buttons
	FrameRect(hDC, &rect, br );

	// Hilight
	// Shadow
	::DeleteObject(br);
	br = ::CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
	rc.SetRect(rect.left+1, rect.bottom - 2, rect.right - 1 , rect.bottom - 1);
	::FillRect(hDC, rc, br);
	rc.SetRect(rect.right - 2, rect.top, rect.right - 1, rect.bottom - 1);
	::FillRect(hDC, rc, br);
	::DeleteObject(br);
} 
/****************************************************************************
*
*	FUNCTION:  DrawDownButton
*
*	PARAMETERS:
*		pDC		- pointer to DC to draw on
*		rect	- client rect to draw in
*
*	RETURNS:
*		void
*
*	DESCRIPTION:
*		Protected helper function for drawing the 3d "down button" look.
*		This is a static function so it may be called without instantiating
*		the object.
*
****************************************************************************/

void CToolbarButton::DrawDownButton(HDC hDC, CRect & rect)
{
    DrawCheckedButton(hDC, rect);
	HBRUSH br = ::CreateSolidBrush((RGB(0, 0, 0)));

	::FrameRect(hDC, &rect, br );
	::DeleteObject(br);
}

/****************************************************************************
*
*	FUNCTION:  DrawCheckedButton
*
*	PARAMETERS:
*		pDC		- pointer to DC to draw on
*		rect	- client rect to draw in
*
*	RETURNS:
*		void
*
*	DESCRIPTION:
*		Protected helper function for drawing the 3d "down button" look.
*		This is a static function so it may be called without instantiating
*		the object.
*
****************************************************************************/

void CToolbarButton::DrawCheckedButton(HDC hDC, CRect & rect)
{
	// Hilight
	CRect rc(rect.left+1, rect.bottom - 2, rect.right - 1, rect.bottom - 1);
	HBRUSH br = ::CreateSolidBrush(::GetSysColor(COLOR_BTNHIGHLIGHT));
	::FillRect(hDC, rc, br);
	rc.SetRect(rect.right - 2, rect.top+1, rect.right - 1, rect.bottom - 1);
	::FillRect(hDC, rc, br);
	
	// Shadow
	::DeleteObject(br);
	br = ::CreateSolidBrush(::GetSysColor(COLOR_BTNSHADOW));
	rc.SetRect(rect.left+1, rect.top+1, rect.right - 1, 2);
	::FillRect(hDC, rc, br);
	rc.SetRect(rect.left+1, rect.top+1, rect.left+2, rect.bottom - 1);
	::FillRect(hDC, rc, br);
	::DeleteObject(br);
}

void CALLBACK EXPORT NSButtonMenuTimerProc(
    HWND hwnd,	// handle of window for timer messages 
    UINT uMsg,	// WM_TIMER message
    UINT idEvent,	// timer identifier
    ULONG dwTime 	// current system time
    )
{
}

CSize CToolbarButton::GetBitmapOnTopSize(CString strTxt, int c)
{

	HDC hDC = ::GetDC(m_hWnd);

	if (c == 0)
	{
		strTxt = "";
	}
	else if(c != SHOW_ALL_CHARACTERS)
	{
         if (strTxt.GetLength() > c)
             strTxt = strTxt.Left(c - 3) + "...";
         else strTxt = strTxt.Left(c);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);
	
	CRect textRect(0,0,150,0);

	CSize sizeTxt;

	if(strTxt.IsEmpty())
		sizeTxt.cx = sizeTxt.cy = 0;
	else
	{
		DrawText(hDC, strTxt, strTxt.GetLength(), &textRect, DT_CALCRECT | DT_WORDBREAK);
		sizeTxt.cx = textRect.Width();
		sizeTxt.cy = textRect.Height();
	}

	int nWidth, nHeight;

	::SelectObject(hDC, hOldFont);

	nWidth = ((m_bitmapSize.cx > sizeTxt.cx) ? m_bitmapSize.cx : sizeTxt.cx) + (2 * BORDERSIZE) + HORIZMARGINSIZE;
	nHeight = m_bitmapSize.cy + sizeTxt.cy + TEXTVERTMARGIN + TEXT_BITMAPVERTMARGIN + BITMAPVERTMARGIN + (2 *BORDERSIZE);

	::ReleaseDC(m_hWnd, hDC);


	return CSize(nWidth, nHeight);
}

CSize CToolbarButton::GetBitmapOnlySize(void)
{

	int nWidth, nHeight;


	nWidth = m_bitmapSize.cx + (2 * BORDERSIZE) + HORIZMARGINSIZE;
	nHeight = m_bitmapSize.cy + (2 * BORDERSIZE);

	return CSize(nWidth, nHeight);

}

CSize CToolbarButton::GetBitmapOnSideSize(CString strTxt, int c)
{

	HDC hDC = ::GetDC(m_hWnd);

	if(c != SHOW_ALL_CHARACTERS)
	{
         if (strTxt.GetLength() > c)
             strTxt = strTxt.Left(c - 3) + "...";
         else strTxt = strTxt.Left(c);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);
	
	SIZE sizeTxt;
#if defined (_WIN32)
	::GetTextExtentPoint32(hDC, (LPCSTR)strTxt, strTxt.GetLength(), &sizeTxt);
#else
	DWORD dwSize = ::GetTextExtent(hDC, (LPCSTR)strTxt, strTxt.GetLength());
	sizeTxt.cx = LOWORD(dwSize);
	sizeTxt.cy = HIWORD(dwSize);
#endif

	::SelectObject(hDC, hOldFont);

	int nWidth, nHeight;

	nWidth = sizeTxt.cx + m_bitmapSize.cx + (2 * BORDERSIZE) + HORIZMARGINSIZE;
	nHeight =((m_bitmapSize.cy > sizeTxt.cy) ? m_bitmapSize.cy : sizeTxt.cy) + (2 * BORDERSIZE);

	::ReleaseDC(m_hWnd, hDC);
	return CSize(nWidth, nHeight);
}

CSize CToolbarButton::GetTextOnlySize(CString strTxt, int c)
{

	HDC hDC = ::GetDC(m_hWnd);

	if(c != SHOW_ALL_CHARACTERS)
	{
         if (strTxt.GetLength() > c)
             strTxt = strTxt.Left(c - 3) + "...";
         else strTxt = strTxt.Left(c);
	}

	HFONT font = WFE_GetUIFont(hDC);

	HFONT hOldFont = (HFONT)::SelectObject(hDC, font);
	
	CRect textRect(0,0,150,0);

	CSize sizeTxt;

	if(strTxt.IsEmpty())
		sizeTxt.cx = sizeTxt.cy = 0;
	else
	{
		DrawText(hDC, strTxt, strTxt.GetLength(), &textRect, DT_CALCRECT | DT_WORDBREAK);

		sizeTxt.cx = textRect.Width();
		sizeTxt.cy = textRect.Height();
	}

	int nWidth, nHeight;

	::SelectObject(hDC, hOldFont);

	nWidth = sizeTxt.cx +  (2 * BORDERSIZE) + HORIZMARGINSIZE;
	nHeight = sizeTxt.cy + (2 * BORDERSIZE) + (2 * TEXTONLYVERTMARGIN);

	::ReleaseDC(m_hWnd, hDC);

	return CSize(nWidth, nHeight);

}

 void CToolbarButton::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
	m_state.m_pOther = this;

	m_state.m_nID = m_nCommand;

	m_state.DoUpdate(pTarget, bDisableIfNoHndler);
}

 void CToolbarButton::RemoveButtonFocus(void)
 {

	BOOL bStatusText = (strcmp(m_pStatusText, "") != 0);
	POINT point;

	KillTimer(IDT_BUTTONFOCUS);
	m_hFocusTimer = 0;
	GetCursorPos(&point);

	CRect rcClient;
	GetWindowRect(&rcClient);

	if (!rcClient.PtInRect(point))
	{
		m_bHaveFocus = FALSE;

		if ( bStatusText && WFE_GetOwnerFrame(this) != NULL) {
			WFE_GetOwnerFrame(this)->SendMessage( WM_SETMESSAGESTRING,
										   (WPARAM) 0, (LPARAM) "" );
		}

	
		//if we lose capture and we don't have a menu showing we just want to show
		//the normal state.  If we have a menu showing we want to show the button down
		//state
		if(m_nChecked == 1)
		{
			m_eState = eBUTTON_CHECKED;
			RedrawWindow();
		}
		else if(m_nChecked == 2)
		{
			m_eState = eDISABLED;
			RedrawWindow();
		}
		else if(m_eState != eNORMAL && !m_bMenuShowing)
		{
			if(m_nChecked == 0)
			{
				m_eState = eNORMAL;
				RedrawWindow();
			}
		}
		else if(m_bMenuShowing)
		{
			m_eState = eBUTTON_CHECKED; //eBUTTON_DOWN;
			RedrawWindow();
		}
		else if(m_bEnabled)
		{
			if(m_nChecked == 0)
			{
				m_eState = eNORMAL;
				RedrawWindow();
			}
		}
		UpdateWindow();
		pCurrentButton = NULL;
	}
	else
		m_hFocusTimer = SetTimer(IDT_BUTTONFOCUS, BUTTONFOCUS_DELAY_MS, NULL);
 }

 BOOL CToolbarButton::CreateRightMouseMenu(void)
 {
 	if((m_dwButtonStyle & TB_HAS_TIMED_MENU) && m_bEnabled)
	{

		#ifdef _WIN32
			GetParentFrame()->SendMessage(NSBUTTONMENUOPEN, MAKEWPARAM(m_nCommand, 0 ),(LPARAM)m_menu.m_hMenu);
		#else
			GetParentFrame()->SendMessage(NSBUTTONMENUOPEN, (WPARAM)m_nCommand, MAKELPARAM(m_menu.m_hMenu,0));
		#endif
		return TRUE;
	}

	return FALSE;
 }

 void CToolbarButton::DisplayAndTrackMenu(void)
 {

	m_eState = eBUTTON_DOWN;
	RedrawWindow();

	CPoint point = RequestMenuPlacement();
	
	CWnd *pWnd = GetMenuParent();
	CRect rect;
	GetWindowRect(&rect);
	KillTimer(IDT_BUTTONFOCUS);
	m_hFocusTimer = 0;

	m_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,point.x, point.y, pWnd ? pWnd : this, &rect);
	
	int nCount = m_menu.GetMenuItemCount();

	for(int i = 0; i < nCount ; i++)
	{
		m_menu.DeleteMenu(0, MF_BYPOSITION);
	}

	if(m_nChecked == 0)
		m_eState = eNORMAL;
	RedrawWindow();

 }

 CWnd* CToolbarButton::GetMenuParent(void)
 {
	return GetParentFrame();
 }

 void CToolbarButton::GetTextRect(CRect &rect)
 {
	GetClientRect(rect);

	rect.InflateRect(-BORDERSIZE, -BORDERSIZE);


	if(m_nToolbarStyle == TB_PICTURESANDTEXT)
	{
		GetPicturesAndTextModeTextRect(rect);
	}
	else if(m_nToolbarStyle == TB_PICTURES)
	{
		GetPicturesModeTextRect(rect);
	}
	else
	{
		GetTextModeTextRect(rect);
	}


 }

 void CToolbarButton::GetPicturesAndTextModeTextRect(CRect &rect)
 {
	GetBitmapOnTopTextRect(rect);
 }

 void CToolbarButton::GetPicturesModeTextRect(CRect &rect)
 {
	// there is no text
	rect.SetRect(0,0,0,0);

 }


 void CToolbarButton::GetTextModeTextRect(CRect &rect)
 {
	GetTextOnlyTextRect(rect);
 }

 void CToolbarButton::GetBitmapOnTopTextRect(CRect &rect)
 {
	CRect bitmapRect = rect;

	//goes 2 pixels from top
	bitmapRect.top += BITMAPVERTMARGIN;
	// Adjust the image rect
	bitmapRect.bottom = bitmapRect.top + m_bitmapSize.cy;
	
	rect.top = bitmapRect.bottom +TEXT_BITMAPVERTMARGIN;

 }

 void CToolbarButton::GetTextOnlyTextRect(CRect &rect)
 {
		
 }

 void CToolbarButton::GetBitmapOnSideTextRect(CRect &rect)
 {
	CRect bitmapRect = rect;

	bitmapRect.right = m_bitmapSize.cx + BORDERSIZE;

	rect.left = bitmapRect.right;

 }

// End CToolbar Implementation

//////////////////////////////////////////////////////////////////////////////////////
//							CDragableToolbarButton
//////////////////////////////////////////////////////////////////////////////////////

CDragableToolbarButton::CDragableToolbarButton()
{
	m_bDragging = FALSE;
}

//////////////////////////////////////////////////////////////////////////
//					Messages for CDragableToolbarButton
//////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CDragableToolbarButton, CToolbarButton)
	//{{AFX_MSG_MAP(CWnd)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP

END_MESSAGE_MAP()

void CDragableToolbarButton::OnLButtonUp(UINT nFlags, CPoint point)
{
	CToolbarButton::OnLButtonUp(nFlags, point);

	if(m_bDragging)
	{
		ReleaseCapture();
		m_bDragging = FALSE;
	}
}

void CDragableToolbarButton::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bDragging = TRUE;

	m_draggingPoint = point;

	CToolbarButton::OnLButtonDown(nFlags, point);

}

void CDragableToolbarButton::OnMouseMove(UINT nFlags, CPoint point)
{
	if(m_bDragging)
	{
		if((abs(point.x - m_draggingPoint.x) > 5)
             || (abs(point.y - m_draggingPoint.y) > 5))
		{
			ButtonDragged();
			m_bDragging = FALSE;

			GetParent()->PostMessage(NSBUTTONDRAGGING, 0,(LPARAM)m_hWnd);
			return;
		}
	}
	CToolbarButton::OnMouseMove(nFlags, point);
}

void CDragableToolbarButton::OnTimer( UINT  nIDEvent )
{
	CToolbarButton::OnTimer(nIDEvent);

	if(nIDEvent == IDT_MENU)
	{
		m_bDragging = FALSE;
	}
}
// End CDragableToolbarButton Implementation

//////////////////////////////////////////////////////////////////////////////////////
//							CStationaryToolbarButton
//////////////////////////////////////////////////////////////////////////////////////
int CStationaryToolbarButton::Create(CWnd *pParent, int nToolbarStyle, 
								CSize noviceButtonSize, CSize advancedButtonSize,
								LPCTSTR pButtonText, LPCTSTR pToolTipText, 
								LPCTSTR pStatusText, UINT nBitmapID, UINT nBitmapIndex,
								CSize bitmapSize, BOOL bNeedsUpdate, UINT nCommand, 
								int nMaxTextChars, DWORD dwButtonStyle, int nMinTextChars)
{
	
	return(CToolbarButton::Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize,
						   pButtonText, pToolTipText, pStatusText, nBitmapID, nBitmapIndex, 
						   bitmapSize, bNeedsUpdate,
						   nCommand, nMaxTextChars, nMinTextChars, dwButtonStyle));


}

int CStationaryToolbarButton::Create(CWnd *pParent, int nToolbarStyle, 
									CSize noviceButtonSize, CSize advancedButtonSize,
									LPCTSTR pButtonText, LPCTSTR pToolTipText, 
									LPCTSTR pStatusText, LPCTSTR pBitmapFile,
									CSize bitmapSize, BOOL bNeedsUpdate, UINT nCommand, 
									int nMaxTextChars, DWORD dwButtonStyle, int nMinTextChars)
{
	return(CToolbarButton::Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize,
						   pButtonText, pToolTipText, pStatusText, pBitmapFile, 
						   bitmapSize, bNeedsUpdate,
						   nCommand, nMaxTextChars, nMinTextChars, dwButtonStyle));

}


//////////////////////////////////////////////////////////////////////////
//					Messages for CStationaryToolbarButton
//////////////////////////////////////////////////////////////////////////

BEGIN_MESSAGE_MAP(CStationaryToolbarButton, CToolbarButton)
	//{{AFX_MSG_MAP(CWnd)
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP

END_MESSAGE_MAP()

void CStationaryToolbarButton::OnLButtonUp(UINT nFlags, CPoint point)
{
	CToolbarButton::OnLButtonUp(nFlags, point);
}

void CStationaryToolbarButton::OnLButtonDown(UINT nFlags, CPoint point)
{
	CToolbarButton::OnLButtonDown(nFlags, point);
}

void CStationaryToolbarButton::OnMouseMove(UINT nFlags, CPoint point)
{
	CToolbarButton::OnMouseMove(nFlags, point);
}
// End CStationaryToolbar Implementation





 //////////////////////////////////////////////////////////////////////////////////////
//							CCommandToolbarButton
//////////////////////////////////////////////////////////////////////////////////////

CCommandToolbarButton::CCommandToolbarButton()
{
	m_pActionOwner = NULL;
}

int CCommandToolbarButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize, CSize advancedButtonSize,
								LPCTSTR pButtonText, LPCTSTR pToolTipText, 
								LPCTSTR pStatusText, UINT nBitmapID, UINT nBitmapIndex,
								CSize bitmapSize, UINT nCommand, int nMaxTextChars, DWORD dwButtonStyle, int nMinTextChars)
{
	
	return(CStationaryToolbarButton::Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize,
						   pButtonText, pToolTipText, pStatusText, nBitmapID, nBitmapIndex, bitmapSize, TRUE,
						   nCommand, nMaxTextChars, dwButtonStyle, nMinTextChars));


}

int CCommandToolbarButton::Create(CWnd *pParent, int nToolbarStyle, CSize noviceButtonSize, CSize advancedButtonSize,
								  LPCTSTR pButtonText, LPCTSTR pToolTipText, 
								  LPCTSTR pStatusText, LPCTSTR pBitmapFile,
								  CSize bitmapSize, UINT nCommand, int nMaxTextChars, DWORD dwButtonStyle, int nMinTextChars)
{
	return(CStationaryToolbarButton::Create(pParent, nToolbarStyle, noviceButtonSize, advancedButtonSize,
						   pButtonText, pToolTipText, pStatusText, pBitmapFile, bitmapSize, TRUE,
						   nCommand, nMaxTextChars, dwButtonStyle, nMinTextChars));

}

void CCommandToolbarButton::OnAction(void)
{
	 CWnd *pActionOwner;

	 if(m_pActionOwner == NULL)
		pActionOwner = WFE_GetOwnerFrame(this);
	 else
		pActionOwner = m_pActionOwner;

#ifdef _WIN32
	pActionOwner->PostMessage(WM_COMMAND, MAKEWPARAM(m_nCommand, m_nCommand), 0);
#else
	pActionOwner->PostMessage(WM_COMMAND, (WPARAM) m_nCommand, MAKELPARAM(this->m_hWnd, 0));
#endif
}

 void CCommandToolbarButton::FillInOleDataSource(COleDataSource *pDataSource)
 {

	HGLOBAL hCommandButton = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(COMMANDBUTTONITEM));
    if(!hCommandButton) {
        return;
    }

    LPCOMMANDBUTTONITEM pCommandButton = (LPCOMMANDBUTTONITEM)GlobalLock(hCommandButton);
	
	CToolbarButton::FillInButtonData(&(pCommandButton->buttonInfo));

    GlobalUnlock(hCommandButton);

    // Create the DataSourceObject
    pDataSource->CacheGlobalData(RegisterClipboardFormat(NETSCAPE_COMMAND_BUTTON_FORMAT), hCommandButton);
  

 }

 void CCommandToolbarButton::SetActionMessageOwner(CWnd *pActionOwner)
 {
	 m_pActionOwner = pActionOwner;
 }
