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 + -
显示快捷键?