Import Geant4 10.6.0 source tree

This commit is contained in:
Gabriele Cosmo
2019-12-06 15:12:28 +01:00
parent b2a62ae692
commit 5baee230e9
2997 changed files with 141580 additions and 98673 deletions
@@ -0,0 +1,810 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_Windows_WinTk
#define tools_Windows_WinTk
#include "../Windows/tools" //and not "tools", because this fancy VisualC++ will not find the file!
#include <tools/touplow>
#include <tools/words>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
#include <vector>
namespace tools {
namespace WinTk {
class Component;
class CallbackData {
public:
CallbackData():x(0),y(0),wparam(0),lparam(0){}
public:
std::string value;
int x;
int y;
WPARAM wparam;
LPARAM lparam;
};
typedef void (*Callback)(Component&,CallbackData&,void*);
class Component {
typedef std::vector< std::pair<Callback,void*> > Callbacks;
typedef std::pair<std::string,Callbacks> NamedCallbacks;
#ifdef TOOLS_MEM
TOOLS_SCLASS(exlib::WinTk::Component)
#endif
public:
Component(const std::string& aType):fType(aType),fWindow(0),fParent(0){
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
Component(const std::string& aType,Component& aParent):fType(aType),fWindow(0),fParent(&aParent) {
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
virtual ~Component() {
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
Component(Component&) {
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
Component& operator=(Component&) {return *this;}
public:
std::string name() const {return fName;}
void setName(const std::string& aName) {fName = aName;}
const std::string& type() const {return fType;}
HWND nativeWindow() {return fWindow;}
Component* parent() const {return fParent;}
virtual void show() {
//if(!fWindow) return;
//::ShowWindow(fWindow,SW_SHOWDEFAULT);
}
void hide() {
if(!fWindow) return;
::ShowWindow(fWindow,SW_HIDE);
}
virtual bool size(unsigned int& aWidth,unsigned int& aHeight) {
aWidth = 0;
aHeight = 0;
if(!fWindow) return false;
RECT rect;
::GetClientRect(fWindow,&rect);
aWidth = rect.right-rect.left;
aHeight = rect.bottom-rect.top;
return true;
}
virtual bool position(int& aX,int& aY) {
aX = 0;
aY = 0;
if(!fWindow) return false;
RECT rect;
::GetClientRect(fWindow,&rect);
aX = rect.left;
aY = rect.top;
return true;
}
Component* findFather(const std::string& aType) {
if(aType==type()) return this;
Component* parent = fParent;
while(parent) {
if(aType==parent->type()) return parent;
parent = parent->fParent;
}
return 0;
}
bool setBackground(double aR,double aG,double aB){
if(!fWindow) return false;
int r = int(aR*255.0);
if((r<0)||(r>255)) return false;
int g = int(aG*255.0);
if((g<0)||(g>255)) return false;
int b = int(aB*255.0);
if((b<0)||(b>255)) return false;
/*
//COLORREF cr = RGB(r,g,b);
HBRUSH brush = ::CreateSolidBrush(RGB(r,g,b));
::printf("debug : WinTk::Component::setBackground : brush %lu\n",brush);
HBRUSH prev = (HBRUSH)::GetClassLongPtr(fWindow,GCLP_HBRBACKGROUND);
::printf("debug : WinTk::Component::setBackground : prev brush %lu\n",prev);
{WNDCLASSEX wc;
::GetClassInfoEx(::GetModuleHandle(NULL),WC_STATIC,&wc);
::printf("debug : prev brush xxx %lu\n",wc.hbrBackground);}
ULONG_PTR stat =
::SetClassLongPtr(fWindow,GCLP_HBRBACKGROUND,(LONG_PTR)brush);
if(prev && !stat) {
::printf("debug : WinTk::Component::setBackground : SetClassLongPtr failed.\n");
return false;
}
{ULONG_PTR stat =
::SetClassLongPtr(fWindow,GCLP_HBRBACKGROUND,(LONG_PTR)brush);
::printf("debug : WinTk::Component::setBackground : SetClassLongPtr failed.yyy %lu.\n",stat);}
{WNDCLASSEX wc;
::GetClassInfoEx(::GetModuleHandle(NULL),WC_STATIC,&wc);
::printf("debug : prev brush yyy %lu\n",wc.hbrBackground);}
if(!::InvalidateRect(fWindow,NULL,TRUE)) {
::printf("debug : WinTk::Component::setBackground : InvalidateRect failed.\n");
return false;
}
//::DeleteObject(brush);
return true;
*/
return false;
}
public:
void addCallback(const std::string& aName,Callback aFunction,void* aTag) {
NamedCallbacks* cbks = 0;
std::vector<NamedCallbacks>::iterator it;
for(it=fCallbacks.begin();it!=fCallbacks.end();++it) {
if(aName==(*it).first) {
cbks = &(*it);
break;
}
}
if(!cbks) {
fCallbacks.push_back(std::pair<std::string,Callbacks>(aName,Callbacks()));
cbks = &(fCallbacks.back());
}
cbks->second.push_back(std::pair<Callback,void*>(aFunction,aTag));
}
void removeCallback(const std::string& aName,Callback aFunction,void* aTag) {
NamedCallbacks* cbks = 0;
std::vector<NamedCallbacks>::iterator it;
for(it=fCallbacks.begin();it!=fCallbacks.end();++it) {
if(aName==(*it).first) {
cbks = &(*it);
break;
}
}
if(cbks) {
Callbacks::iterator it;
for(it=cbks->second.begin();it!=cbks->second.end();++it) {
if( (aFunction==(*it).first) && (aTag==(*it).second) ) {
cbks->second.erase(it);
return;
}
}
}
}
bool executeCallbacks(const std::string& aName,CallbackData& aData) {
std::vector<NamedCallbacks>::const_iterator it;
for(it=fCallbacks.begin();it!=fCallbacks.end();++it) {
if(aName==(*it).first) {
const Callbacks& cbks = (*it).second;
Callbacks::const_iterator it2;
for(it2=cbks.begin();it2!=cbks.end();++it2) {
Callback cbk = (*it2).first;
if(cbk) {
HWND back_fWindow = fWindow;
cbk(*this,aData,(*it2).second);
// The callback may have destroyed the Component and
// the native HWND. The below checks that.
// In a proc, it is better to not use the HWND
// (or the Component) after calling executeCallbacks.
if(back_fWindow && !::GetWindowLongPtr(back_fWindow,GWLP_USERDATA)) {
//::printf("WinTk::Component::executeCallbacks : WARNING : A callback destroyed the native HWND window !\n");
return false;
}
}
}
return true;
}
}
return false;
}
bool hasCallbacks(const std::string& aName) const {
std::vector<NamedCallbacks>::const_iterator it;
for(it=fCallbacks.begin();it!=fCallbacks.end();++it) {
if(aName==(*it).first) return true;
}
return false;
}
protected:
static void wm__destroy(HWND aWindow) {
Component* This = (Component*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) { //How to be sure that we have a Component* ???
if(This->fWindow!=aWindow) {
::printf("WinTk::Component::wm_destroy : HWND mismatch !\n");
}
if(This->hasCallbacks("WM_DESTROY")) {
CallbackData data;
This->executeCallbacks("WM_DESTROY",data);
}
This->fWindow = 0;
}
::SetWindowLongPtr(aWindow,GWLP_USERDATA,LONG_PTR(NULL));
}
protected:
// WM_PARENTNOTIFY is sent within the CreateWindow of the child.
// When received by the parent, the parent Post (not Send) to itself
// a WM_TK_CHILDCREATED in order to be notify of the child creation
// out of any CreateWindow.
#define WM_TK_CHILDCREATED ((WM_USER)+888)
#define WM_TK_CHILDDELETED ((WM_USER)+889)
#define TK_KEY 127 // To be sure that it is a message of our own.
static LRESULT CALLBACK containerProc(HWND aWindow,UINT aMessage,WPARAM aWParam,LPARAM aLParam) {
//////////////////////////////////////////////////////////////////////////////
// Some child send notification message to their parent (instead of sending
// the message to themselves !). This procedure is used by containers
// to forward these messages to the child.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
switch(aMessage) {
case WM_PARENTNOTIFY:{
if(aWParam==WM_CREATE) {
::PostMessage(aWindow,WM_TK_CHILDCREATED,TK_KEY,0);
return 0;
} else if(aWParam==WM_DESTROY) {
::PostMessage(aWindow,WM_TK_CHILDDELETED,TK_KEY,0);
return 0;
}
}break;
case WM_TK_CHILDCREATED:{
if(aWParam==TK_KEY) {
RECT rect;
::GetClientRect(aWindow,&rect);
LPARAM size = MAKELPARAM(rect.right-rect.left,rect.bottom-rect.top);
::SendMessage(aWindow,WM_SIZE,(WPARAM)0,size);
return 0;
}
}break;
case WM_TK_CHILDDELETED:{
if(aWParam==TK_KEY) {
}
}break;
case WM_NOTIFY:{ //Coming from a child (combobox, scrollbar, toolbar).
NMHDR* nmhdr = (NMHDR*)aLParam;
HWND from_win = nmhdr->hwndFrom;
if(from_win!=aWindow) {
::SendMessage(from_win,aMessage,aWParam,aLParam);
}
}return 0;
case WM_COMMAND:
case WM_VSCROLL:
case WM_HSCROLL:{
::SendMessage((HWND)aLParam,aMessage,aWParam,(LPARAM)0);
}return 0;
}
return TRUE; //Not handled.
}
#undef WM_TK_CHILDCREATED
#undef WM_TK_CHILDDELETED
#undef TK_KEY
protected:
void destroy() {
if(hasCallbacks("delete")) {
CallbackData data;
executeCallbacks("delete",data);
}
if(fWindow) {
::SetWindowLongPtr(fWindow,GWLP_USERDATA,LONG_PTR(NULL));
::DestroyWindow(fWindow);
fWindow = 0;
}
}
void rubberDrawLine(POINT& aBegin,POINT& aEnd) {
if(!fWindow) return;
HPEN pen = ::CreatePen(PS_SOLID,5,RGB(0,0,0));
HDC hdc = ::GetWindowDC(fWindow);
HPEN oldPen = SelectPen(hdc,pen);
int oldROP = ::SetROP2(hdc,R2_NOT);
POINT pt;
::MoveToEx(hdc,aBegin.x,aBegin.y,&pt);
::LineTo(hdc,aEnd.x,aEnd.y);
::SetROP2(hdc,oldROP);
SelectPen(hdc,oldPen);
::ReleaseDC(fWindow,hdc);
::DeletePen(pen);
}
void rubberDrawRect(POINT& aBegin,POINT& aEnd) {
if(!fWindow) return;
HPEN pen = ::CreatePen(PS_SOLID,0,RGB(0,0,0));
HDC hdc = ::GetWindowDC(fWindow);
HPEN oldPen = SelectPen(hdc,pen);
int oldROP = ::SetROP2(hdc,R2_NOT);
POINT pt;
::MoveToEx(hdc,aBegin.x,aBegin.y,&pt);
::LineTo(hdc,aBegin.x,aEnd.y);
::LineTo(hdc,aEnd.x,aEnd.y);
::LineTo(hdc,aEnd.x,aBegin.y);
::LineTo(hdc,aBegin.x,aBegin.y);
::SetROP2(hdc,oldROP);
SelectPen(hdc,oldPen);
::ReleaseDC(fWindow,hdc);
::DeletePen(pen);
}
private:
std::string fType;
protected:
HWND fWindow;
Component* fParent;
std::vector<NamedCallbacks> fCallbacks;
std::string fName;
};
class Shell;
typedef void(*SetFocusCallback)(Shell*,void*);
class Shell : public Component {
public:
Shell(unsigned int aMask)
:Component("Shell")
,fFocusWindow(0)
,fSetFocusCallback(0)
,fSetFocusTag(0)
,fAcceleratorTable(0)
{
static char sWindowClassName[] = "WinTk::Shell";
static bool done = false;
if(!done) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)Shell::proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ::GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
wc.lpszMenuName = sWindowClassName;
wc.lpszClassName = sWindowClassName;
::RegisterClass(&wc);
done = true;
}
fWindow = ::CreateWindow(sWindowClassName,
NULL,
aMask, //WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,
400,400,
NULL,NULL,
::GetModuleHandle(NULL),
NULL);
if(!fWindow) return;
::SetWindowLongPtr(fWindow,GWLP_USERDATA,LONG_PTR(this));
}
virtual ~Shell() {
if(fAcceleratorTable) {
::DestroyAcceleratorTable(fAcceleratorTable);
fAcceleratorTable = 0;
}
destroy();
}
protected:
Shell(Shell& a_from):Component(a_from) {}
Shell& operator=(Shell&) {return *this;}
public:
virtual void show() {
if(!fWindow) return;
::SetForegroundWindow(fWindow);
::ShowWindow(fWindow,SW_SHOWDEFAULT);
::UpdateWindow(fWindow);
::DrawMenuBar(fWindow);
}
void setTitle(const std::string& aString) {
if(!fWindow) return;
::SetWindowText(fWindow,aString.c_str());
}
void setGeometry(int aX,int aY,unsigned int aWidth,unsigned int aHeight) {
//////////////////////////////////////////////////////////////////////////////
// Given width, height is the desired client area.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
if(!fWindow) return;
int hborder = ::GetSystemMetrics(SM_CYCAPTION);
if(::GetWindowLongPtr(fWindow,GWLP_ID)) // Has a menubar.
hborder += ::GetSystemMetrics(SM_CYMENU);
::MoveWindow(fWindow,aX,aY,aWidth,hborder + aHeight,TRUE);
}
void setSize(unsigned int aWidth,unsigned int aHeight) {
//////////////////////////////////////////////////////////////////////////////
// Given width, height is the desired client area.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
if(!fWindow) return;
int hborder = ::GetSystemMetrics(SM_CYCAPTION);
RECT rect;
::GetWindowRect(fWindow,&rect);
::MoveWindow(fWindow,rect.left,rect.top,aWidth,hborder + aHeight,TRUE);
}
void setFocusWindow(HWND aWindow) {fFocusWindow = aWindow;}
HWND focusWindow() {return fFocusWindow;}
void setSetFocusCallback(SetFocusCallback aCallback,void* aTag) {
fSetFocusCallback = aCallback;
fSetFocusTag = aTag;
}
void callSetFocusCallback() {
if(!fSetFocusCallback) return;
fSetFocusCallback(this,fSetFocusTag);
}
HACCEL nativeAcceleratorTable() {return fAcceleratorTable;}
bool addAccelerator(const std::string& aString,int aID) {
//printf("debug : accel : %s %d\n",aString.c_str(),aID);
// aString should be of the form : "a" or "Ctrl+a".
ACCEL acc;
//acc.fVirt : FALT, FCONTROL, FNOINVERT, FSHIFT, FVIRTKEY
{acc.cmd = aID;
std::vector<std::string> words;
std::string s(aString);
tools::touppercase(s);
tools::words(s,"+",false,words);
if(words.size()==1) {
acc.fVirt = FVIRTKEY;
if(!string_to_VK(words[0],acc.key)) return false;
} else if((words.size()==2)&&(words[1].size())) {
if(words[0]=="CTRL") {
acc.fVirt = FCONTROL;
} else if(words[0]=="ALT") {
acc.fVirt = FALT;
} else if(words[0]=="SHIFT") {
acc.fVirt = FSHIFT;
} else {
return false;
}
acc.fVirt |= FVIRTKEY;
if(!string_to_VK(words[1],acc.key)) return false;
} else {
return false;
}}
if(!fAcceleratorTable) {
fAcceleratorTable = ::CreateAcceleratorTable(&acc,1);
} else {
int n = ::CopyAcceleratorTable(fAcceleratorTable,NULL,0);
ACCEL* tbl = new ACCEL[n+1];
::CopyAcceleratorTable(fAcceleratorTable,tbl,n);
ACCEL& tacc = tbl[n];
tacc.fVirt = acc.fVirt;
tacc.key = acc.key;
tacc.cmd = acc.cmd;
::DestroyAcceleratorTable(fAcceleratorTable);
fAcceleratorTable = ::CreateAcceleratorTable(tbl,n+1);
delete [] tbl;
}
return true;
}
private:
static bool string_to_VK(const std::string& aString,WORD& a_VK) {
//VK_xxx are defined in WinUser.h
if(aString.size()==1) { a_VK = aString[0];return true;} //WM_W is 'W'
#define S_VK(aWhat) \
if(!::strcmp(aString.c_str(),#aWhat)) { a_VK = VK_##aWhat;return true;}
S_VK(BACK)
S_VK(TAB)
S_VK(CLEAR)
S_VK(RETURN)
S_VK(ESCAPE)
S_VK(SPACE)
S_VK(UP)
S_VK(DOWN)
S_VK(LEFT)
S_VK(RIGHT)
S_VK(F1)
S_VK(F2)
S_VK(F3)
S_VK(F4)
S_VK(F5)
S_VK(F6)
S_VK(F7)
S_VK(F8)
S_VK(F9)
S_VK(F10)
S_VK(F11)
S_VK(F12)
S_VK(F13)
S_VK(F14)
S_VK(F15)
S_VK(F16)
S_VK(F17)
S_VK(F18)
S_VK(F19)
S_VK(F20)
S_VK(F21)
S_VK(F22)
S_VK(F23)
S_VK(F24)
//FIXME : handle other keys ? NUMPAD[0-9]
#undef S_VK
return false;
}
static LRESULT CALLBACK proc(HWND aWindow,UINT aMessage,WPARAM aWParam,LPARAM aLParam) {
switch (aMessage) {
// Same logic as containerProc :
case WM_NOTIFY:{ //Coming from a child (combobox, scrollbar, toolbar).
NMHDR* nmhdr = (NMHDR*)aLParam;
HWND from_win = nmhdr->hwndFrom;
if(from_win!=aWindow) {
::SendMessage(from_win,aMessage,aWParam,aLParam);
}
}return 0;
// Else :
case WM_SIZE:{ // Assume one child window ! FIXME : have a message if not.
int width = LOWORD(aLParam);
int height = HIWORD(aLParam);
HWND hwnd = GetFirstChild(aWindow);
if(hwnd) {
//FIXME : have to treat the case of TOOLBAR not being the first.
if(GetClassName(hwnd)==std::string(TOOLBARCLASSNAME)) {
HWND next = GetNextSibling(hwnd);
// Share area between toolbar and second child :
RECT rect;
::GetWindowRect(hwnd,&rect);
int htb = rect.bottom-rect.top;
SetGeometry(next,0,htb,width,height-htb);
} else {
SetGeometry(hwnd,0,0,width,height);
}
}
}return 0;
case WM_SETFOCUS:{
Shell* This = (Shell*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
This->callSetFocusCallback();
HWND win = This->focusWindow();
if(win) ::SetFocus(win);
}
}return 0;
case WM_INITMENUPOPUP:{ //0x0117
//aWParam is the HMENU (from CreatePopupMenu)
//aLParam is the MenuItemCount
Shell* This = (Shell*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
CallbackData data;
data.wparam = aWParam;
This->executeCallbacks("cascading",data);
}
} return 0;
case WM_COMMAND:{ //Coming from a menu item, a toolbar !
if(aLParam) {
// From a toolbar ; send it back to it :
::SendMessage((HWND)aLParam,aMessage,aWParam,0);
} else {
//if(HIWORD(aWParam)==1) { //From an accelerator.
//}
// From a menu item :
Shell* This = (Shell*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
CallbackData data;
data.wparam = LOWORD(aWParam);
This->executeCallbacks("activate",data);
}
}
}return 0;
case WM_CLOSE:{
Shell* This = (Shell*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
if(This->hasCallbacks("close")) {
CallbackData data;
This->executeCallbacks("close",data);
}
}
}break; //NOTE : can't be return 0.
case WM_DESTROY:wm__destroy(aWindow);return 0;
}
return (DefWindowProc(aWindow,aMessage,aWParam,aLParam));
}
private:
HWND fFocusWindow;
SetFocusCallback fSetFocusCallback;
void* fSetFocusTag;
HACCEL fAcceleratorTable;
};
class OpenGLArea : public Component {
public:
OpenGLArea(Component& aParent)
:Component("OpenGLArea",aParent)
,fContext(0)
,fHDC(0)
{
if(!fParent || !fParent->nativeWindow()) return;
HWND parent = fParent->nativeWindow();
static char sOpenGLAreaClassName[] = "WinTk::OpenGLArea";
static bool done = false;
if(!done) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)OpenGLArea::proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetWindowInstance(parent),
wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
wc.lpszMenuName = sOpenGLAreaClassName;
wc.lpszClassName = sOpenGLAreaClassName;
::RegisterClass(&wc);
done = true;
}
// The WS_BORDER is needed. Else probleme of size at startup.
RECT rect;
::GetClientRect(parent,&rect);
fWindow = ::CreateWindow(sOpenGLAreaClassName,
NULL,
WS_CHILD | WS_VISIBLE,
0,0,
rect.right-rect.left,
rect.bottom-rect.top,
parent,NULL,
GetWindowInstance(parent),
NULL);
if(!fWindow) return;
::SetWindowLongPtr(fWindow,GWLP_USERDATA,LONG_PTR(this));
// initialize OpenGL rendering :
fHDC = ::GetDC(fWindow);
if( fHDC && SetWindowPixelFormat(fHDC) ) {
fContext = ::wglCreateContext(fHDC);
}
}
virtual ~OpenGLArea() {
if(wglGetCurrentContext()!=NULL) wglMakeCurrent(NULL,NULL);
if(fContext) {
wglDeleteContext(fContext);
fContext = 0;
}
destroy();
}
protected:
OpenGLArea(OpenGLArea& a_from):Component(a_from) {}
OpenGLArea& operator=(OpenGLArea&) {return *this;}
public:
bool write_gl2ps(const std::string&,const std::string&);
private:
static LRESULT CALLBACK proc(HWND aWindow,UINT aMessage,WPARAM aWParam,LPARAM aLParam) {
switch (aMessage) {
case WM_PAINT:{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(aWindow,&ps);
OpenGLArea* This = (OpenGLArea*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
HDC hdc = This->fHDC;
HGLRC context = This->fContext;
if(hdc && context) {
::wglMakeCurrent(hdc,context);
// User OpenGL paint code :
CallbackData data;
data.wparam = aWParam;
data.lparam = aLParam;
This->executeCallbacks("paint",data);
::SwapBuffers(hdc);
}
}
EndPaint(aWindow,&ps);
}return 0;
case WM_LBUTTONDOWN:{
OpenGLArea* This = (OpenGLArea*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
CallbackData data;
data.wparam = aWParam;
data.lparam = aLParam;
data.value = "ButtonPress";
data.x = LOWORD(aLParam);
data.y = HIWORD(aLParam);
This->executeCallbacks("event",data);
}
}return 0;
case WM_LBUTTONUP:{
OpenGLArea* This = (OpenGLArea*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
CallbackData data;
data.wparam = aWParam;
data.lparam = aLParam;
data.value = "ButtonRelease";
data.x = LOWORD(aLParam);
data.y = HIWORD(aLParam);
This->executeCallbacks("event",data);
}
} return 0;
case WM_MOUSEMOVE:{
unsigned int state = aWParam;
if((state & MK_LBUTTON)==MK_LBUTTON) {
OpenGLArea* This = (OpenGLArea*)::GetWindowLongPtr(aWindow,GWLP_USERDATA);
if(This) {
CallbackData data;
data.wparam = aWParam;
data.lparam = aLParam;
data.value = "MotionNotify";
data.x = LOWORD(aLParam);
data.y = HIWORD(aLParam);
This->executeCallbacks("event",data);
}
}
}return 0;
case WM_DESTROY:wm__destroy(aWindow);return 0;
}
return (DefWindowProc(aWindow,aMessage,aWParam,aLParam));
}
static bool SetWindowPixelFormat(HDC aHdc) {
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags =
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER |
PFD_STEREO_DONTCARE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 8;
pfd.cRedShift = 16;
pfd.cGreenBits = 8;
pfd.cGreenShift = 8;
pfd.cBlueBits = 8;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 64;
pfd.cAccumRedBits = 16;
pfd.cAccumGreenBits = 16;
pfd.cAccumBlueBits = 16;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 32;
pfd.cStencilBits = 8;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
int pixelIndex = ::ChoosePixelFormat(aHdc,&pfd);
if (pixelIndex==0) {
// Let's choose a default index.
pixelIndex = 1;
if (::DescribePixelFormat(aHdc,
pixelIndex,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd)==0) {
return false;
}
}
if (::SetPixelFormat(aHdc,pixelIndex,&pfd)==FALSE) return false;
return true;
}
private:
HGLRC fContext;
HDC fHDC;
};
}}
#endif
@@ -0,0 +1,601 @@
// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_Windows_tools
#define tools_Windows_tools
#include <windows.h>
#include <windowsx.h>
#include <string>
namespace tools {
namespace WinTk {
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline bool GetClassName(HWND aWindow,std::string& a_value) {
if(!aWindow) {a_value.clear();return false;}
char className[256];
::GetClassName(aWindow,className,128);
a_value = std::string(className);
return true;
}
inline HWND GetChildByClassName(HWND aWindow,const std::string& aClassName) {
// A CBS_SIMPLE has two children of class ComboLBox and Edit.
// At creation, a CBS_DROPDOWN has one child of class Edit.
if(!aWindow) return NULL;
HWND child = GetFirstChild(aWindow);
std::string ss;
while(child) {
GetClassName(child,ss);
if(ss==aClassName) return child;
child = GetNextSibling(child);
}
return NULL;
}
inline void SetGeometry(HWND aWindow,int aX,int aY,unsigned int aWidth,unsigned int aHeight) {
if(!aWindow) return;
std::string className;
GetClassName(aWindow,className);
if(className=="ComboBox") {
// For a Combo the height is the visible part + the height of the list !
// (A combo may have no edit control).
::MoveWindow(aWindow,aX,aY,aWidth,200,TRUE);
} else {
::MoveWindow(aWindow,aX,aY,aWidth,aHeight,TRUE);
}
}
inline void GetSize(HWND aWindow,int& aWidth,int& aHeight) {
RECT rect;
::GetWindowRect(aWindow,&rect);
aWidth = rect.right-rect.left;
aHeight = rect.bottom-rect.top;
}
inline unsigned int GetNumberOfChildren(HWND aWindow) {
unsigned int number = 0;
HWND child = GetFirstChild(aWindow);
while(child) {
number++;
child = GetNextSibling(child);
}
return number;
}
inline HWND GetLastChild(HWND aWindow) {
HWND child = GetFirstChild(aWindow);
while(child) {
HWND next = GetNextSibling(child);
if(!next) return child;
child = next;
}
return 0;
}
inline void GetText(HWND aWindow,std::string& a_value) {
int l = ::GetWindowTextLength(aWindow);
a_value.resize(l);
::GetWindowText(aWindow,(char*)a_value.c_str(),l+1);
}
/*
inline void PrintChildren(HWND aWindow) {
// A CBS_SIMPLE has two children of class ComboLBox and Edit.
// At creation, a CBS_DROPDOWN has one child of class Edit.
if(!aWindow) return;
HWND child = GetFirstChild(aWindow);
while(child) {
//printf("debug : window : %ld, child : %ld class \"%s\"\n",
// aWindow,child,ClassName(child).c_str());
child = GetNextSibling(child);
}
}
*/
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline bool IsStyle(HWND aWindow,LONG aStyle) {
LONG_PTR style = ::GetWindowLongPtr(aWindow,GWL_STYLE);
return ( ((style & aStyle ) == aStyle) ? true : false);
}
inline void ChangeStyle(HWND aWindow,LONG aStyle,bool aValue) {
LONG_PTR style = ::GetWindowLongPtr(aWindow,GWL_STYLE);
if(aValue) { //Enable style.
style = style | aStyle;
} else { //Disbale style.
style = style & ~aStyle;
}
::SetWindowLongPtr(aWindow,GWL_STYLE,style);
}
inline bool IsShell(HWND aWindow) {
if(IsStyle(aWindow,WS_OVERLAPPEDWINDOW)) return true;
if(IsStyle(aWindow,WS_POPUP)) return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline HWND GetShell(HWND aWindow) {
HWND window = aWindow;
if(IsShell(window)) return window;
while(true) {
HWND parent = GetParent(window);
if(!parent) return window;
if(IsShell(parent)) return parent;
window = parent;
}
return 0;
}
inline bool Show(HWND aWindow) {
HWND shell = GetShell(aWindow);
if(!shell) return false;
::SetForegroundWindow(shell);
::ShowWindow(shell,SW_SHOWDEFAULT);
::UpdateWindow(shell);
::DrawMenuBar(shell);
return true;
}
inline bool Hide(HWND aWindow) {
HWND shell = GetShell(aWindow);
if(!shell) return false;
::ShowWindow(shell,SW_HIDE);
return true;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline bool IsTabStop(HWND aWindow) {
LONG_PTR style = ::GetWindowLongPtr(aWindow,GWL_STYLE);
return ((style & WS_TABSTOP ) == WS_TABSTOP ? true : false);
}
inline HWND GetTabStopInTree(HWND aWindow,bool aForward) {
if(IsTabStop(aWindow)) return aWindow;
HWND child = aForward ? GetFirstChild(aWindow) : GetLastChild(aWindow);
while(child) {
HWND tabStop = GetTabStopInTree(child,aForward);
if(tabStop) return tabStop;
child = aForward ? GetNextSibling(child) : GetPrevSibling(child);
}
return NULL;
}
inline HWND GetTabStopInSibling(HWND aWindow,bool aForward) {
if(!aWindow) return NULL;
HWND child = aForward ? GetNextSibling(aWindow) : GetPrevSibling(aWindow);
while(child) {
HWND tabStop = GetTabStopInTree(child,aForward);
if(tabStop) return tabStop;
child = aForward ? GetNextSibling(child) : GetPrevSibling(child);
}
return NULL;
}
inline HWND GetTabStop(HWND aDialog,HWND aWindow,bool aForward = true) {
if(!aWindow) return NULL;
HWND window = aWindow;
while(window && (window!=aDialog) ) {
HWND tabStop = GetTabStopInSibling(window,aForward);
if(tabStop) return tabStop;
window = GetParent(window);
}
return GetTabStopInTree(aDialog,aForward);
}
inline HBITMAP CreateDIB(HDC aDC,int aWidth,int aHeight,int aBPP /*16||24||32*/,void** aBits) {
if((aBPP!=24) && (aBPP!=32)) return 0;
BITMAPINFO format;
BITMAPINFOHEADER* header = (BITMAPINFOHEADER*)&format;
header->biSize = sizeof(BITMAPINFOHEADER);
header->biWidth = aWidth;
header->biHeight = -aHeight;
header->biPlanes = 1;
header->biBitCount = aBPP;
header->biCompression = BI_RGB;
header->biSizeImage = 0;
header->biXPelsPerMeter = 0;
header->biYPelsPerMeter = 0;
header->biClrUsed = 0;
header->biClrImportant = 0;
UINT flag = DIB_RGB_COLORS;
HBITMAP bitmap = ::CreateDIBSection(aDC,&format,flag,(void**)aBits,NULL,0);
if(!(*aBits)) return 0;
return bitmap;
}
}}
#include <commctrl.h>
namespace tools {
namespace WinTk {
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline bool TreeGetItemLabel(HWND aWindow,HTREEITEM aItem,std::string& a_value) {
TCHAR text[256];
TV_ITEM item;
item.hItem = aItem;
item.mask = TVIF_TEXT;
item.pszText = text;
item.cchTextMax = 256;
if(!TreeView_GetItem(aWindow,&item)) {a_value.clear();return false;}
a_value = std::string(text);
return true;
}
inline bool TreeIsItemBranch(HWND aWindow,HTREEITEM aItem) {
TV_ITEM item;
item.hItem = aItem;
item.mask = TVIF_CHILDREN;
if(!TreeView_GetItem(aWindow,&item)) return 0;
return item.cChildren?true:false;
}
inline bool TreeIsItemExpanded(HWND aWindow,HTREEITEM aItem) {
TV_ITEM item;
item.hItem = aItem;
item.mask = TVIS_EXPANDED;
if(!TreeView_GetItem(aWindow,&item)) return 0;
return ((item.state & TVIS_EXPANDED)== TVIS_EXPANDED) ? true : false;
}
inline void TreeGetItemPath(HWND aWindow,HTREEITEM aItem,std::string& a_value) {
HTREEITEM item = aItem;
a_value.clear();
std::string ss;
while(item && (item!=TVI_ROOT)) {
TreeGetItemLabel(aWindow,item,ss);
std::string opath = a_value;
a_value = "\n";
a_value += ss;
a_value += opath;
item = TreeView_GetParent(aWindow,item);
}
// Remove the leading \n
if(a_value.size()) a_value = a_value.substr(1,a_value.size()-1);
}
inline void TreeGetItemXML(HWND aWindow,HTREEITEM aItem,std::string& a_value) {
//return a XML string representing this tree
std::string spaceItem = "";
std::string spaceRoot = "";
std::string ss;
a_value.clear();
do {
a_value += spaceRoot + "<treeItem>";
a_value += spaceItem + "<label>";
TreeGetItemLabel(aWindow,aItem,ss);
a_value.append(ss);
a_value += "</label>";
a_value += spaceItem + "<opened>";
if (TreeIsItemExpanded(aWindow,aItem)) a_value.append("true");
else a_value.append("false");
a_value += "</opened>";
if (TreeView_GetChild(aWindow,aItem)) {
TreeGetItemXML(aWindow,TreeView_GetChild(aWindow,aItem),ss);
a_value += ss;
}
a_value += spaceRoot + "</treeItem>";
aItem = TreeView_GetNextSibling(aWindow,aItem);
}
while (aItem);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
inline int smanip_axtoi(const std::string& a_string) {
// convert from ASCII hex to int
// Exa : "FF" -> 256.
int x = 0;
size_t n = a_string.size();
// convert n nibbles
for (size_t i = 0; i < n; i++) {
char c = a_string[i];
// numbers 0 - 9
if ((c > 0x2F) && (c < 0x3A))
x += ((c - 0x30) << ((n - i - 1) * 4));
// capital letters A - F
if ((c > 0x40) && (c < 0x47))
x += ((c - 0x41 + 0x0A) << ((n - i - 1) * 4));
// lower case letters a - f
if ((c > 0x60) && (c < 0x67))
x += ((c - 0x61 + 0x0A) << ((n - i - 1) * 4));
}
return x;
}
}}
#include <tools/svalues>
namespace tools {
namespace WinTk {
inline HBITMAP ConvertXpmToDIB(HDC aDC,const std::vector<std::string>& aXPM,int& aWidth,int& aHeight) {
// Convert from xpm to DIB (demands hex colors).
// From CoinWin/widgets/SoWinBitmapButton.cpp.
aWidth = 0;
aHeight = 0;
if(!aXPM.size()) return 0;
std::vector<int> vals;
tools::values<int>(aXPM[0]," ",false,vals);
if(vals.size()!=4) return 0;
int width = vals[0];
int height = vals[1];
int numcol = vals[2];
int numchars = vals[3];
if(width<=0) return 0;
if(height<=0) return 0;
if(numcol<=0) return 0;
if(numchars<=0) return 0;
// Check consistency :
if((height+numcol)!=aXPM.size()-1) return 0;
size_t lcolor = 0;
int i;
for (i = 0; i < numcol; i++) {
std::string::size_type pos = aXPM[i+1].rfind("c #");
if(pos==std::string::npos) continue; // May be "c None"
lcolor = aXPM[i+1].size()-(pos+3);
break;
}
//printf("debug : xpm : numcol %d (%d)\n",numcol,lcolor);
if( (lcolor!=6) && (lcolor!=12) ) return 0;
// create color lookup table
char* charlookuptable = new char[numcol * numchars];
//long* colorlookuptable = new long[numcol];
int* rlookuptable = new int[numcol];
int* glookuptable = new int[numcol];
int* blookuptable = new int[numcol];
bool done = true;
// get colors
for (i = 0; i < numcol; i++) {
const std::string& line = aXPM[i+1];
// Check consistency :
if((int)line.size()<numchars) {
done = false;
break;
}
for (int j = 0; j < numchars; j ++) {
charlookuptable[(i * numchars) + j] = line[j];
}
// Find color by value :
std::string::size_type pos = line.find("c #",numchars);
if(pos!=std::string::npos) {
size_t lc = line.size()-(pos+3);
if(lc!=lcolor) {
done = false;
//printf("debug : xpm : error in \"%s\" %d %d\n",
//line.c_str(),lc,lcolor);
break;
}
if(lcolor==6) {
rlookuptable[i] = smanip_axtoi(line.substr(pos+3+0,2));
glookuptable[i] = smanip_axtoi(line.substr(pos+3+2,2));
blookuptable[i] = smanip_axtoi(line.substr(pos+3+4,2));
} else { //lcolor 12
rlookuptable[i] = smanip_axtoi(line.substr(pos+3+0,2));
glookuptable[i] = smanip_axtoi(line.substr(pos+3+4,2));
blookuptable[i] = smanip_axtoi(line.substr(pos+3+8,2));
}
//printf("debug : xpm : color %d : (%x,%x,%x)\n",
// i,rlookuptable[i],glookuptable[i],blookuptable[i]);
} else { // Could be "c None"
rlookuptable[i] = -1;
glookuptable[i] = -1;
blookuptable[i] = -1;
}
}
//printf("debug : xpm : read color %d\n",done);
//WARNING : pixelsize 3 does not work with button in a toolbar.
// unsigned char pixelsize = 3;
unsigned char pixelsize = 4;
if(!done) pixelsize = 0; // Will induce a clean exit.
// create bitmap
void* dest;
HBITMAP hbmp = CreateDIB(aDC,width,height,pixelsize * 8,&dest);
if(hbmp) {
int noneColor = ::GetSysColor(COLOR_3DFACE);
done = true;
// put pixels
for (i = 0; i < height; i++) {
const std::string& line = aXPM[i + 1 + numcol];
// Check consistency :
if((int)line.size()!=(numchars*width)) {
done = false;
break;
}
int y = i * width * pixelsize;
for (int j = 0; j < width; j++) {
int x = j * pixelsize;
// for every color
for (int k = 0; k < numcol; k++) {
bool found = true;
for (int l = 0; l < numchars; l++) {
if (charlookuptable[(k * numchars) + l]
!= line[(j * numchars) + l]) {
found = false;
break;
}
}
if(found) {
unsigned char r,g,b;
if (rlookuptable[k] == -1) {
r = (noneColor & 0x00FF0000)>>16;
g = (noneColor & 0x0000FF00)>>8;
b = noneColor & 0x000000FF;
} else {
r = rlookuptable[k];
g = glookuptable[k];
b = blookuptable[k];
}
if(pixelsize==4) {
((unsigned char*)dest)[y + x + 0] = b;
((unsigned char*)dest)[y + x + 1] = g;
((unsigned char*)dest)[y + x + 2] = r;
((unsigned char*)dest)[y + x + 3] = 0;
} else {
((unsigned char*)dest)[y + x + 0] = b;
((unsigned char*)dest)[y + x + 1] = g;
((unsigned char*)dest)[y + x + 2] = r;
}
// next pixel
break;
}
}
}
}
if(!done) {
//printf("debug : xpm : can'tread pixels.\n");
::DeleteObject(hbmp);
hbmp = 0;
}
}
// cleanup
delete [] charlookuptable;
delete [] rlookuptable;
delete [] glookuptable;
delete [] blookuptable;
if(hbmp) {
aWidth = width;
aHeight = height;
}
return hbmp;
}
}}
#include <tools/file>
namespace tools {
namespace WinTk {
inline HBITMAP Read_Xpm(HDC aDC,const std::string& aFileName,int& aWidth,int& aHeight) {
aWidth = 0;
aHeight = 0;
std::vector<std::string> text;
//std::string name;
//tools::file_name(aFileName,name);
if(!tools::file::read(aFileName,text)) return 0;
std::vector<std::string> xpm;
{for(size_t index=0;index<text.size();index++) {
if(text[index][0]!='"') continue;
std::string::size_type l = text[index].size();
std::string line = text[index].substr(1,l-1);
std::string::size_type pos = line.find("\"");
if(pos==std::string::npos) return 0;
xpm.push_back(line.substr(0,pos));
}}
if(!xpm.size()) return 0;
return ConvertXpmToDIB(aDC,xpm,aWidth,aHeight);
}
inline std::string TreeGetItemLabel(HWND aWindow,HTREEITEM aItem) {
std::string ss;
TreeGetItemLabel(aWindow,aItem,ss);
return ss;
}
inline std::string TreeGetItemPath(HWND aWindow,HTREEITEM aItem) {
std::string ss;
TreeGetItemPath(aWindow,aItem,ss);
return ss;
}
inline std::string TreeGetItemXML(HWND aWindow,HTREEITEM aItem) {
std::string ss;
TreeGetItemXML(aWindow,aItem,ss);
return ss;
}
inline std::string GetText(HWND aWindow) {
std::string ss;
GetText(aWindow,ss);
return ss;
}
inline std::string GetClassName(HWND aWindow) {
std::string ss;
GetClassName(aWindow,ss);
return ss;
}
}}
#include <tools/system> //backcomp
namespace tools {
namespace WinTk {
inline HBITMAP ReadXpm(HDC aDC,const std::string& aFileName,int& aWidth,int& aHeight) {
std::string name;
tools::file_name(aFileName,name);
return Read_Xpm(aDC,name,aWidth,aHeight);
}
}}
#endif