Serious-Engine/Sources/SeriousSkaStudio/ColoredButton.cpp
2016-03-11 18:20:51 -06:00

403 lines
12 KiB
C++

/* Copyright (c) 2002-2012 Croteam Ltd.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as published by
the Free Software Foundation
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
// ColoredButton.cpp : implementation file
//
#include "stdafx.h"
#include "seriousskastudio.h"
#include "ColoredButton.h"
#ifdef _DEBUG
#undef new
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CColoredButton
COLOR _colColorClipboard = 0xFFFFFFFF;
void CColoredButton::OnColorChange()
{
theApp.m_dlgBarTreeView.ChangeColorOnSelectedSurfaces(m_strID,m_colColor);
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
pDoc->MarkAsChanged();
}
CColoredButton::CColoredButton()
{
m_colColor = 0xFFFFFFFF;
m_colLastColor = 0xFFFFFFFF;
m_ptPickerType = PT_MFC;
m_pwndParentDialog = NULL;
m_bMixedColor = FALSE;
UBYTE ubR, ubG, ubB;
UBYTE ubH, ubS, ubV;
ColorToRGB( m_colColor, ubR, ubG, ubB);
ColorToHSV( m_colColor, ubH, ubS, ubV);
UBYTE ubA = (UBYTE) (m_colColor&255);
m_ubComponents[0][0] = ubH;
m_ubComponents[0][1] = ubS;
m_ubComponents[0][2] = ubV;
m_ubComponents[0][3] = ubA;
m_ubComponents[1][0] = ubR;
m_ubComponents[1][1] = ubG;
m_ubComponents[1][2] = ubB;
}
CColoredButton::~CColoredButton()
{
}
BEGIN_MESSAGE_MAP(CColoredButton, CButton)
//{{AFX_MSG_MAP(CColoredButton)
ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_CONTEXTMENU()
/*
ON_COMMAND(ID_COPY_COLOR, OnCopyColor)
ON_COMMAND(ID_PASTE_COLOR, OnPasteColor)
ON_COMMAND(ID_NUMERIC_ALPHA, OnNumericAlpha)
*/
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CColoredButton message handlers
void CColoredButton::SetColor(COLOR clrNew)
{
m_colColor = clrNew;
m_bMixedColor = FALSE;
if( ::IsWindow(m_hWnd)) Invalidate( FALSE);
// OnColorChange();
}
void CColoredButton::ColorToComponents(void)
{
if( m_colColor == m_colLastColor) return;
UBYTE ubR, ubG, ubB;
UBYTE ubH, ubS, ubV;
ColorToRGB( m_colColor, ubR, ubG, ubB);
ColorToHSV( m_colColor, ubH, ubS, ubV);
UBYTE ubA = (UBYTE) (m_colColor&255);
m_ubComponents[0][0] = ubH;
m_ubComponents[0][1] = ubS;
m_ubComponents[0][2] = ubV;
m_ubComponents[0][3] = ubA;
m_ubComponents[1][0] = ubR;
m_ubComponents[1][1] = ubG;
m_ubComponents[1][2] = ubB;
m_colLastColor = m_colColor;
}
// CColoredButton message handlers
void CColoredButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
EnableToolTips( TRUE);
CDC *pDC = GetDC();
m_rectButton = lpDrawItemStruct->rcItem;
m_rectButton.top+=2;
m_rectButton.bottom-=2;
m_dx = (m_rectButton.right-m_rectButton.left)/6;
m_dy = (m_rectButton.top-m_rectButton.bottom)/2;
if( m_bMixedColor && IsWindowEnabled())
{
CBrush brush;
brush.CreateHatchBrush(HS_BDIAGONAL, CLRF_CLR( RGBToColor(100,100,100)));
pDC->FillRect( &m_rectButton, &brush);
}
else
{
ColorToComponents();
UBYTE ubR, ubG, ubB;
UBYTE ubH, ubS, ubV, ubA;
ubH = m_ubComponents[0][0];
ubS = m_ubComponents[0][1];
ubV = m_ubComponents[0][2];
ubA = m_ubComponents[0][3];
ubR = m_ubComponents[1][0];
ubG = m_ubComponents[1][1];
ubB = m_ubComponents[1][2];
#define FILL_RECT( col, x, y, w, h) {\
RECT rectToFill;\
rectToFill.left = m_rectButton.left+m_dx*x;\
if( w<0) rectToFill.right = m_rectButton.right-2;\
else rectToFill.right = m_rectButton.left+rectToFill.left+m_dx*w;\
rectToFill.top = m_rectButton.top-m_dy*y;\
rectToFill.bottom = m_rectButton.top+rectToFill.top-m_dy*h;\
COLORREF clrfColor = CLRF_CLR( col);\
if( !IsWindowEnabled()) clrfColor = CLRF_CLR( 0xBBBBBBBB);\
pDC->FillSolidRect( &rectToFill, clrfColor);\
pDC->DrawEdge( &rectToFill, EDGE_SUNKEN, BF_RECT);}
FILL_RECT( HSVToColor( ubH, 255, 255), 0, 0, 1, 1);
FILL_RECT( HSVToColor( ubH, ubS, 255), 1, 0, 1, 1);
FILL_RECT( HSVToColor( ubH, 0, ubV), 2, 0, 1, 1);
FILL_RECT( RGBToColor( ubA, ubA, ubA), 3, 0, 1, 2);
FILL_RECT( RGBToColor( ubR, 0, 0), 0, 1, 1, 1);
FILL_RECT( RGBToColor( 0, ubG, 0), 1, 1, 1, 1);
FILL_RECT( RGBToColor( 0, 0, ubB), 2, 1, 1, 1);
FILL_RECT( m_colColor, 4, 0, 2, 2);
}
pDC->DrawEdge( &lpDrawItemStruct->rcItem, EDGE_BUMP, BF_RECT);
ReleaseDC( pDC);
}
BOOL MyChooseColor( COLORREF &clrNewColor, CWnd &wndOwner)
{
COLORREF MyCustColors[ 16];
CHOOSECOLOR ccInit;
ASSERT( &wndOwner != NULL);
MyCustColors[ 0] = CLRF_CLR(C_BLACK);
MyCustColors[ 1] = CLRF_CLR(C_WHITE);
MyCustColors[ 2] = CLRF_CLR(C_dGRAY);
MyCustColors[ 3] = CLRF_CLR(C_GRAY);
MyCustColors[ 4] = CLRF_CLR(C_lGRAY);
MyCustColors[ 5] = CLRF_CLR(C_dRED);
MyCustColors[ 6] = CLRF_CLR(C_dGREEN);
MyCustColors[ 7] = CLRF_CLR(C_dBLUE);
MyCustColors[ 8] = CLRF_CLR(C_dCYAN);
MyCustColors[ 9] = CLRF_CLR(C_dMAGENTA);
MyCustColors[10] = CLRF_CLR(C_dYELLOW);
MyCustColors[11] = CLRF_CLR(C_dORANGE);
MyCustColors[12] = CLRF_CLR(C_dBROWN);
MyCustColors[13] = CLRF_CLR(C_dPINK);
MyCustColors[14] = CLRF_CLR(C_lORANGE);
MyCustColors[15] = CLRF_CLR(C_lBROWN);
memset(&ccInit, 0, sizeof(CHOOSECOLOR));
ccInit.lStructSize = sizeof(CHOOSECOLOR);
ccInit.Flags = CC_RGBINIT | CC_FULLOPEN;
ccInit.rgbResult = clrNewColor;
ccInit.lpCustColors = &MyCustColors[ 0];
ccInit.hwndOwner = wndOwner.m_hWnd;
if( !ChooseColor( &ccInit))
return FALSE;
clrNewColor = ccInit.rgbResult;
return TRUE;
}
void CColoredButton::OnClicked()
{
if( m_iColorIndex != -1) return;
// colored button can call eather custom palette window for choosing colors (where variable
// to receive result color is pointed with _pcolColorToSet) eather trough MFC-provided
// color picker
ASSERT( m_ptPickerType != PT_CUSTOM);
COLORREF TmpColor = CLRF_CLR( m_colColor);
if( MyChooseColor( TmpColor, *GetParent()))
{
m_bMixedColor = FALSE;
// restore alpha value
m_colColor = CLR_CLRF( TmpColor) | m_colColor&0x000000FF;
OnColorChange();
Invalidate( FALSE);
}
// invalidate parent dialog
if( m_pwndParentDialog != NULL) m_pwndParentDialog->UpdateData( TRUE);
}
void CColoredButton::SetOverButtonInfo( CPoint point)
{
#define SET_OVER_BUTTON_INFO( x, y, w, h, color_index, component_index) {\
RECT rectToClick;\
rectToClick.left = m_rectButton.left+m_dx*x;\
if( w<0) rectToClick.right = m_rectButton.right-2;\
else rectToClick.right = m_rectButton.left+rectToClick.left+m_dx*w;\
rectToClick.top = m_rectButton.top-m_dy*y;\
rectToClick.bottom = m_rectButton.top+rectToClick.top-m_dy*h;\
if( PtInRect( &rectToClick, point)) {\
m_iColorIndex = color_index; m_iComponentIndex = component_index;}}
SET_OVER_BUTTON_INFO( 0, 0, 1, 1, 0, 0); // H
SET_OVER_BUTTON_INFO( 1, 0, 1, 1, 0, 1); // S
SET_OVER_BUTTON_INFO( 2, 0, 1, 1, 0, 2); // V
SET_OVER_BUTTON_INFO( 3, 0, 1, 2, 0, 3); // A
SET_OVER_BUTTON_INFO( 0, 1, 1, 1, 1, 0); // R
SET_OVER_BUTTON_INFO( 1, 1, 1, 1, 1, 1); // G
SET_OVER_BUTTON_INFO( 2, 1, 1, 1, 1, 2); // B
SET_OVER_BUTTON_INFO( 4, 0, 2, 2,-1,-1); // Color
}
static BOOL _bMouseMoveEnabled;
void CColoredButton::OnLButtonDown(UINT nFlags, CPoint point)
{
m_ptCenter.x = ::GetSystemMetrics(SM_CXSCREEN)/2;
m_ptCenter.y = ::GetSystemMetrics(SM_CYSCREEN)/2;
GetCursorPos( &m_ptStarting);
SetOverButtonInfo( point);
if( m_bMixedColor)
m_iColorIndex = -1;
if( m_iColorIndex != -1)
{
_bMouseMoveEnabled = TRUE;
ShowCursor(FALSE);
SetCursorPos(m_ptCenter.x, m_ptCenter.y);
}
CButton::OnLButtonDown(nFlags, point);
}
void CColoredButton::OnLButtonUp(UINT nFlags, CPoint point)
{
if( m_iColorIndex != -1)
{
ShowCursor(TRUE);
_bMouseMoveEnabled = FALSE;
SetCursorPos(m_ptStarting.x, m_ptStarting.y);
}
CButton::OnLButtonUp(nFlags, point);
}
void CColoredButton::OnMouseMove(UINT nFlags, CPoint point)
{
SetOverButtonInfo( point);
EnableToolTips( TRUE);
if( (m_iColorIndex != -1) && (nFlags & MK_LBUTTON) && _bMouseMoveEnabled)
{
CPoint ptCurrent;
GetCursorPos( &ptCurrent);
ColorToComponents();
SLONG slResult = m_ubComponents[ m_iColorIndex][m_iComponentIndex];
slResult += ptCurrent.x-m_ptCenter.x;
slResult = Min(Max(slResult,0L), 255L);
m_ubComponents[ m_iColorIndex][m_iComponentIndex] = UBYTE( slResult);
COLOR colResult;
if( m_iColorIndex == 0) {
colResult = HSVToColor( m_ubComponents[0][0], m_ubComponents[0][1], m_ubComponents[0][2]);
ColorToRGB(colResult, m_ubComponents[1][0], m_ubComponents[1][1], m_ubComponents[1][2]);
} else {
colResult = RGBToColor( m_ubComponents[1][0], m_ubComponents[1][1], m_ubComponents[1][2]);
ColorToHSV(colResult, m_ubComponents[0][0], m_ubComponents[0][1], m_ubComponents[0][2]);
}
// add alpha
colResult |= m_ubComponents[0][3];
m_colColor = colResult;
OnColorChange();
m_colLastColor = colResult;
m_bMixedColor = FALSE;
Invalidate( FALSE);
SendMessage( WM_PAINT);
// invalidate parent dialog
if( m_pwndParentDialog != NULL) m_pwndParentDialog->UpdateData( TRUE);
if(ptCurrent != m_ptCenter)
{
SetCursorPos( m_ptCenter.x, m_ptCenter.y);
}
}
CButton::OnMouseMove(nFlags, point);
}
int CColoredButton::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
UBYTE ubR, ubG, ubB;
UBYTE ubH, ubS, ubV, ubA;
ubH = m_ubComponents[0][0];
ubS = m_ubComponents[0][1];
ubV = m_ubComponents[0][2];
ubA = m_ubComponents[0][3];
ubR = m_ubComponents[1][0];
ubG = m_ubComponents[1][1];
ubB = m_ubComponents[1][2];
CTString strColor;
strColor.PrintF( "HSV=(%d,%d,%d), RGB=(%d,%d,%d), Alpha=%d", ubH, ubS, ubV, ubR, ubG, ubB, ubA);
pTI->lpszText = (wchar_t *)malloc(sizeof(wchar_t) * (strlen(strColor)+1));
wcscpy( pTI->lpszText, CString(strColor));
RECT rectToolTip;
rectToolTip.left = 50;
rectToolTip.right = 60;
rectToolTip.top = 50;
rectToolTip.bottom = 60;
pTI->hwnd = GetParent()->m_hWnd;
pTI->uId = (UINT) m_hWnd;
pTI->rect = rectToolTip;
pTI->uFlags = TTF_IDISHWND;
return 1;
}
void CColoredButton::OnContextMenu(CWnd* pWnd, CPoint point)
{
/*
CMenu menu;
if( menu.LoadMenu(IDR_COLOR_BUTTON))
{
CMenu* pPopup = menu.GetSubMenu(0);
pPopup->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
point.x, point.y, this);
}
*/
}
void CColoredButton::OnCopyColor()
{
_colColorClipboard = m_colColor;
}
void CColoredButton::OnPasteColor()
{
SetColor( _colColorClipboard);
CSeriousSkaStudioDoc *pDoc = theApp.GetDocument();
pDoc->MarkAsChanged();
// invalidate parent dialog
if( m_pwndParentDialog != NULL) m_pwndParentDialog->UpdateData( TRUE);
}
void CColoredButton::OnNumericAlpha()
{
/*
CDlgNumericAlpha dlgNumericAlpha( GetColor()&0xFF);
if( dlgNumericAlpha.DoModal() == IDOK)
{
m_ubComponents[0][3] = dlgNumericAlpha.m_iAlpha;
m_colColor &= 0xFFFFFF00;
m_colColor |= (dlgNumericAlpha.m_iAlpha & 0xFF);
m_colLastColor = m_colColor;
if( ::IsWindow(m_hWnd)) Invalidate( FALSE);
// invalidate parent dialog
if( m_pwndParentDialog != NULL) m_pwndParentDialog->UpdateData( TRUE);
}
*/
}
void CColoredButton::OnLButtonDblClk(UINT nFlags, CPoint point)
{
OnNumericAlpha();
CButton::OnLButtonDblClk(nFlags, point);
}