gwidgets.cpp

来自「一个由Mike Gashler完成的机器学习方面的includes neural」· C++ 代码 · 共 2,638 行 · 第 1/5 页

CPP
2,638
字号
/*	Copyright (C) 2006, Mike Gashler	This library is free software; you can redistribute it and/or	modify it under the terms of the GNU Lesser General Public	License as published by the Free Software Foundation; either	version 2.1 of the License, or (at your option) any later version.	see http://www.gnu.org/copyleft/lesser.html*/#include "GWidgets.h"#include "GImage.h"#include "GArray.h"#include "GDirList.h"#ifdef WIN32#include <direct.h>#else // WIN32#include <unistd.h>#endif // !WIN32#include "GFile.h"#include <math.h>#include "GTime.h"#include "GBits.h"GWidgetStyle::GWidgetStyle(){	m_nButtonFontSize = 14;	m_nLabelFontSize = 14;	m_fButtonFontWidth = (float).8;	m_fLabelFontWidth = (float)1;	m_cButtonTextColor = 0xff000000;	m_cLabelTextColor = 0xff8888ff;	m_cButtonPressedTextColor = gRGB(255, 255, 255);	m_cTextBoxBorderColor = gRGB(255, 255, 255);	m_cTextBoxTextColor = gRGB(255, 255, 255);}GWidgetStyle::~GWidgetStyle(){}void GWidgetStyle::DrawButtonText(GImage* pImage, int x, int y, int w, int h, GString* pString, bool pressed){	int nTempBufLen = pString->GetLength() + 1;	GTEMPBUF(char, szText, nTempBufLen);	pString->GetAnsi(szText);	int nButtonFontSize = m_nButtonFontSize;	if(h < nButtonFontSize)		nButtonFontSize = h;	int wid = pImage->MeasureHardTextWidth(nButtonFontSize, szText, m_fButtonFontWidth);	GRect r;	r.x = x + (w - wid) / 2;	if(r.x < x)		r.x = x;	r.y = y + (h - nButtonFontSize) / 2;	if(r.y < y)		r.y = y;	r.w = w - (r.x - x);	r.h = nButtonFontSize;	pImage->DrawHardText(&r, szText, pressed ? m_cButtonPressedTextColor : m_cButtonTextColor, m_fButtonFontWidth);}void GWidgetStyle::DrawLabelText(GImage* pImage, int x, int y, int w, int h, GString* pString, bool alignLeft, GColor c){	int nTempBufLen = pString->GetLength() + 1;	GTEMPBUF(char, szText, nTempBufLen);	pString->GetAnsi(szText);	//int nLabelFontSize = m_nLabelFontSize;	//if(h < nLabelFontSize)	//	nLabelFontSize = h;	int wid = pImage->MeasureHardTextWidth(h/*nLabelFontSize*/, szText, m_fLabelFontWidth);	GRect r;	if(alignLeft)		r.x = x;	else	{		r.x = x + w - wid;		if(r.x < x)			r.x = x;	}	r.y = y; // + (h - nLabelFontSize) / 2;	if(r.y < y)		r.y = y;	r.w = w - (r.x - x);	r.h = h; //nLabelFontSize;	pImage->DrawHardText(&r, szText, c, m_fLabelFontWidth);}void GWidgetStyle::DrawHorizCurvedOutSurface(GImage* pImage, int x, int y, int w, int h, GColor col){	if(w <= 0 || h <= 0)		return;	float fac = (float)1.1 / w;	int n;	for(n = 0; n < w; n++)	{		float t = (float)n * fac - (float).1;		int shade = (int)(255 * (1 - (t * t)));		pImage->DrawLine(x, y, x, y + h - 1, MixColors(0xffffffff, col, shade));		x++;	}}void GWidgetStyle::DrawHorizCurvedInSurface(GImage* pImage, int x, int y, int w, int h, GColor col){	if(w <= 0 || h <= 0)		return;	int n;	for(n = 0; n < w; n++)	{		float t = (float)(n + n) / w - 1;		int shade = (int)(64 + 191 * ((t * t)));		pImage->DrawLine(x, y, x, y + h - 1, MixColors(col, 0xff000000, shade));		x++;	}}void GWidgetStyle::DrawVertCurvedOutSurface(GImage* pImage, int x, int y, int w, int h, GColor col){	float fac = (float)1.1 / h;	int yStart = 0;	if(y < 0)		yStart = -y;	if(y + h > (int)pImage->GetHeight())		h = pImage->GetHeight() - y;	int n;	for(n = yStart; n < h; n++)	{		float t = (float)n * fac - (float).1;		int shade = (int)(255 * (1 - (t * t)));		pImage->DrawLine(x, y, x + w - 1, y, MixColors(0xffffffff, col, shade));		y++;	}}void GWidgetStyle::DrawVertCurvedInSurface(GImage* pImage, int x, int y, int w, int h, GColor col){	int n;	for(n = 0; n < h; n++)	{		float t = (float)(n + n) / h - 1;		int shade = (int)(64 + 191 * ((t * t)));		pImage->DrawLine(x, y, x + w - 1, y, MixColors(col, 0xff000000, shade));		y++;	}}void GWidgetStyle::DrawCursor(GImage* pImage, int x, int y, int w, int h){	pImage->DrawBox(x, y, x + w, y + h, m_cTextBoxTextColor);}void GWidgetStyle::DrawClipped(GImage* pCanvas, int x, int y, GWidget* pWidget, GRect* pClipRect){	// See if we can do it without clipping	GRect* pWidgetRect = pWidget->GetRect();	if(	x >= pClipRect->x &&		y >= pClipRect->y &&		x + pWidgetRect->w <= pClipRect->x + pClipRect->w &&		y + pWidgetRect->h <= pClipRect->y + pClipRect->h)	{		pWidget->Draw(pCanvas, x, y);		return;	}	// Draw onto the buffer image, then copy the clipped part	if(m_bufferImage.GetWidth() < pWidgetRect->w || m_bufferImage.GetHeight() < pWidgetRect->h)		m_bufferImage.SetSize(MAX(m_bufferImage.GetWidth(), pWidgetRect->w), MAX(m_bufferImage.GetHeight(), pWidgetRect->h));	pWidget->Draw(&m_bufferImage, 0, 0);	GRect r;	r.x = MAX(0, pClipRect->x - x);	r.y = MAX(0, pClipRect->y - y);	r.w = MIN(pWidgetRect->w, pClipRect->x + pClipRect->w - x) - r.x;	r.h = MIN(pWidgetRect->h, pClipRect->y + pClipRect->h - y) - r.y;	pCanvas->Blit(x + r.x, y + r.y, &m_bufferImage, &r);}// ----------------------------------------------------------------------GWidget::GWidget(GWidgetGroup* pParent, int x, int y, int w, int h){	m_pParent = pParent;	m_pStyle = pParent ? pParent->GetStyle() : NULL;	m_rect.Set(x, y, w, h);	if(pParent)		pParent->AddWidget(this);	else		m_nID = -1;	GAssert(m_nDebugCheck = 0x600df00d, "");}/*virtual*/ GWidget::~GWidget(){	GAssert(DebugCheck(), "corruption!");	//GAssert(m_pParent || GetType() == Dialog, "Unexpected root widget");	if(m_pParent)		m_pParent->OnDestroyWidget(this);}#ifdef _DEBUGbool GWidget::DebugCheck(){	GAssert(m_nDebugCheck == 0x600df00d, "corruption!");	return true;}#endif // _DEBUGvoid GWidget::SetPos(int x, int y){	m_rect.x = x;	m_rect.y = y;	// todo: dirty the parent?}// ----------------------------------------------------------------------GWidgetAtomic::GWidgetAtomic(GWidgetGroup* pParent, int x, int y, int w, int h) : GWidget(pParent, x, y, w, h){	GAssert(pParent, "atomic widgets require a parent");}/*virtual*/ GWidgetAtomic::~GWidgetAtomic(){}/*virtual*/ void GWidgetAtomic::OnChar(char c){	if(m_pParent)		m_pParent->OnChar(c);}/*virtual*/ void GWidgetAtomic::OnMouseMove(int dx, int dy){}// ----------------------------------------------------------------------GWidgetGroup::GWidgetGroup(GWidgetGroup* pParent, int x, int y, int w, int h) : GWidget(pParent, x, y, w, h){	m_pWidgets = new GPointerArray(16);	m_pDirtyChildren = new GPointerArray(16);	m_pDirtyBits = new GIntArray(2);	m_pDirtyBits->AddInt(0);}/*virtual*/ GWidgetGroup::~GWidgetGroup(){	GWidget* pWidget;	while(m_pWidgets->GetSize() > 0)	{		pWidget = (GWidget*)m_pWidgets->GetPointer(0);		delete(pWidget);	}	delete(m_pWidgets);	delete(m_pDirtyChildren);	delete(m_pDirtyBits);}bool GWidgetGroup::GetDirtyBit(int nBit){	unsigned int n = (unsigned int)m_pDirtyBits->GetInt(nBit / 32);	return (((1 << (nBit % 32)) & n) != 0);}void GWidgetGroup::SetDirtyBit(int nBit, bool bValue){	int index = nBit / 32;	int offset = nBit % 32;	unsigned int n = (unsigned int)m_pDirtyBits->GetInt(index);	if(bValue)		n = (n | (1 << offset));	else		n = (n & (~(1 << offset)));	m_pDirtyBits->SetInt(index, n);}void GWidgetGroup::Tattle(GWidget* pChild){	if(pChild)	{		GAssert(GetChildWidget(pChild->m_nID) == pChild, "that's not my child");		if(GetDirtyBit(pChild->m_nID))			return; // we already know this child is dirty		//GAssert(m_pDirtyChildren->GetSize() == 0 || m_pDirtyChildren->GetPointer(m_pDirtyChildren->GetSize() - 1) != pChild, "dirty bits aren't working");		m_pDirtyChildren->AddPointer(pChild);		SetDirtyBit(pChild->m_nID, true);	}	else		SetDirtyBit(m_pWidgets->GetSize(), true);	if(m_pParent)		m_pParent->Tattle(this);}void GWidgetGroup::AddWidget(GWidget* pWidget){	pWidget->m_nID = m_pWidgets->GetSize();	m_pWidgets->AddPointer(pWidget);	if((m_pWidgets->GetSize() + 33) / 32 > m_pDirtyBits->GetSize())		m_pDirtyBits->AddInt(0);	SetDirtyBit(m_pWidgets->GetSize(), GetDirtyBit(m_pWidgets->GetSize() - 1));	Tattle(pWidget);}// todo: use a divide-and-conquer technique to improve performance/*virtual*/ GWidgetAtomic* GWidgetGroup::FindAtomicWidget(int x, int y){	int n;	int nCount = m_pWidgets->GetSize();	GWidget* pWidget;	for(n = 0; n < nCount; n++)	{		pWidget = (GWidget*)m_pWidgets->GetPointer(n);		if(pWidget->GetRect()->DoesInclude(x, y))		{			if(pWidget->IsAtomicWidget())				return (GWidgetAtomic*)pWidget;			else			{				GRect* pRect = pWidget->GetRect();				return ((GWidgetGroup*)pWidget)->FindAtomicWidget(x - pRect->x, y - pRect->y);			}		}	}	return NULL;}int GWidgetGroup::GetChildWidgetCount(){	return m_pWidgets->GetSize();}GWidget* GWidgetGroup::GetChildWidget(int n){	return (GWidget*)m_pWidgets->GetPointer(n);}/*virtual*/ void GWidgetGroup::OnDestroyWidget(GWidget* pWidget){	if(pWidget->m_nID >= 0)	{		// Remove the widget from my list		GAssert(GetChildWidget(pWidget->m_nID) == pWidget, "bad id");		int nLast = m_pWidgets->GetSize() - 1;		GWidget* pLast = (GWidget*)m_pWidgets->GetPointer(nLast);		pLast->m_nID = pWidget->m_nID;		m_pWidgets->SetPointer(pWidget->m_nID, pLast);		m_pWidgets->DeleteCell(nLast);		SetDirtyBit(m_pWidgets->GetSize(), GetDirtyBit(m_pWidgets->GetSize() + 1));		pWidget->m_nID = -1;		// todo: erase the dead widget	}	if(m_pParent)		m_pParent->OnDestroyWidget(pWidget);}void GWidgetGroup::SetClean(){	m_pDirtyChildren->Clear();	int nCount = m_pDirtyBits->GetSize();	int i;	for(i = 0; i < nCount; i++)		m_pDirtyBits->SetInt(i, 0);}// ----------------------------------------------------------------------GWidgetDialog::GWidgetDialog(int w, int h, GColor cBackground) : GWidgetGroup(NULL, 0, 0, w, h){	m_cBackground = cBackground;	m_image.SetSize(w, h);	m_image.Clear(cBackground);	m_pStyle = new GWidgetStyle();	m_pGrabbedWidget = NULL;	m_pFocusWidget = NULL;	m_prevMouseX = 0;	m_prevMouseY = 0;}/*virtual*/ GWidgetDialog::~GWidgetDialog(){	ReleaseWidget(1);	delete(m_pStyle);}// virtualvoid GWidgetDialog::Draw(GImage* pCanvas, int x, int y){	GPointerArray* pDirtyChildren = m_pDirtyChildren;	if(GetDirtyBit(m_pWidgets->GetSize()))	{		SetDirtyBit(m_pWidgets->GetSize(), false);		pDirtyChildren = m_pWidgets;		//m_image.Clear(m_cBackground);	}	int n;	int nCount = pDirtyChildren->GetSize();	GRect* pRect;	GWidget* pChild;	for(n = 0; n < nCount; n++)	{		pChild = (GWidget*)pDirtyChildren->GetPointer(n);		pRect = pChild->GetRect();		GAssert(x + pRect->x >= 0 && y + pRect->y >= 0 && x + pRect->x + pRect->w <= pCanvas->GetWidth() && y + pRect->y + pRect->h <= pCanvas->GetHeight(), "out of range");		pChild->Draw(pCanvas, x + pRect->x, y + pRect->y);	}	SetClean();}void GWidgetDialog::SetFocusWidget(GWidgetAtomic* pWidget){	if(m_pFocusWidget != pWidget)	{		if(m_pFocusWidget)			m_pFocusWidget->OnLoseFocus();		m_pFocusWidget = pWidget;		if(pWidget)			pWidget->OnGetFocus();	}}void GWidgetDialog::GrabWidget(GWidgetAtomic* pWidget, int button, int mouseX, int mouseY){	ReleaseWidget(button);	m_pGrabbedWidget = pWidget;	SetFocusWidget(pWidget);	if(pWidget)	{		GWidget* pTmp;		GRect* pRect;		for(pTmp = pWidget; pTmp; pTmp = pTmp->GetParent())		{			pRect = pTmp->GetRect();			mouseX -= pRect->x;			mouseY -= pRect->y;		}		pWidget->Grab(button, mouseX, mouseY);	}}void GWidgetDialog::ReleaseWidget(int button){	if(!m_pGrabbedWidget)		return;	// Use a local var in case the handler destroys this dialog	GWidgetAtomic* pGrabbedWidget = m_pGrabbedWidget;	m_pGrabbedWidget = NULL;	pGrabbedWidget->Release(button);}/*virtual*/ void GWidgetDialog::OnDestroyWidget(GWidget* pWidget){	if(pWidget->GetParent() == this)	{		GRect* pRect = pWidget->GetRect();		m_image.FillBox(pRect->x, pRect->y, pRect->w, pRect->h, m_cBackground);		m_pDirtyChildren->Clear();		Tattle(NULL);	}	if(pWidget == m_pGrabbedWidget)		m_pGrabbedWidget = NULL;	if(pWidget == m_pFocusWidget)		m_pFocusWidget = NULL;	GWidgetGroup::OnDestroyWidget(pWidget);}void GWidgetDialog::HandleChar(char c){	if(!m_pFocusWidget)		return;	m_pFocusWidget->OnChar(c);}bool GWidgetDialog::HandleMousePos(int x, int y){	x -= m_prevMouseX;	y -= m_prevMouseY;	if(x == 0 && y == 0)		return false;	m_prevMouseX += x;	m_prevMouseY += y;	if(!m_pGrabbedWidget)		return false;	m_pGrabbedWidget->OnMouseMove(x, y);	return true;}GImage* GWidgetDialog::GetImage(){	Draw(&m_image, 0, 0);	return &m_image;}// ----------------------------------------------------------------------GWidgetTextButton::GWidgetTextButton(GWidgetGroup* pParent, int x, int y, int w, int h, GString* pText): GWidgetAtomic(pParent, x, y, w, h){	m_text.Copy(pText);	m_pressed = false;}GWidgetTextButton::GWidgetTextButton(GWidgetGroup* pParent, int x, int y, int w, int h, const char* szText): GWidgetAtomic(pParent, x, y, w, h){	m_text.Copy(szText);	m_pressed = false;}/*virtual*/ GWidgetTextButton::~GWidgetTextButton(){}/*virtual*/ void GWidgetTextButton::Grab(int button, int x, int y){	m_pressed = true;	m_pParent->Tattle(this);	m_pParent->OnPushTextButton(this);}/*virtual*/ void GWidgetTextButton::Release(int button){	m_pressed = false;	m_pParent->Tattle(this);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?