00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifdef G4UI_BUILD_WIN32_SESSION
00035
00036
00037 #include "G4UIWin32.hh"
00038
00039 #include <string.h>
00040
00041 #include <windows.h>
00042 #include <windowsx.h>
00043 #include <wingdi.h>
00044
00045 #include <strstream>
00046
00047 #include "G4UImanager.hh"
00048 #include "G4StateManager.hh"
00049 #include "G4UIcommandTree.hh"
00050 #include "G4UIcommandStatus.hh"
00051 #include "G4Win32.hh"
00052
00053 #define TEXT_MAX_LINES 300
00054
00055 class TextBuffer
00056 {
00057 public:
00058 TextBuffer();
00059 ~TextBuffer();
00060
00061 int GetNumberOfLines () { return linei;}
00062 void SetHeightOfPage (int a_height) { heightOfPage = a_height; }
00063 void SetEndOfPage (int a_value);
00064 int GetEndOfPage () { return endOfPage; }
00065
00066 void IncrementEndOfPage ();
00067 void DecrementEndOfPage ();
00068 void JumpDownEndOfPage ();
00069 void JumpUpEndOfPage ();
00070 G4bool AppendString (char* a_string);
00071 void Draw (HDC a_hdc,RECT* a_rect);
00072
00073 private:
00074 G4String* lines;
00075 int linen;
00076 int linei;
00077 int endOfPage,heightOfPage;
00078 char spaces[256];
00079 };
00080
00081 TextBuffer::TextBuffer()
00082 : linei(0),linen(TEXT_MAX_LINES),endOfPage(0),heightOfPage(12)
00083 {
00084 lines = new G4String[linen];
00085 for(int count=0;count<256;count++) spaces[count] = ' ';
00086 }
00087
00088 TextBuffer::~TextBuffer()
00089 {
00090 delete [] lines;
00091 }
00092
00093 void TextBuffer::SetEndOfPage (int a_value)
00094 {
00095 if( (a_value<0) || (a_value>=linei)) {
00096 endOfPage = linei-1;
00097 } else {
00098 endOfPage = a_value;
00099 }
00100 }
00101
00102 void TextBuffer::IncrementEndOfPage ()
00103 {
00104 endOfPage++;
00105 if(endOfPage>=linei) endOfPage = linei-1;
00106 }
00107
00108 void TextBuffer::DecrementEndOfPage ()
00109 {
00110 endOfPage--;
00111 if(endOfPage<0) endOfPage = 0;
00112 }
00113
00114 void TextBuffer::JumpDownEndOfPage ()
00115 {
00116 endOfPage += heightOfPage;
00117 if(endOfPage>=linei) endOfPage = linei-1;
00118 }
00119
00120 void TextBuffer::JumpUpEndOfPage ()
00121 {
00122 endOfPage -= heightOfPage;
00123 if(endOfPage<0) endOfPage = 0;
00124 }
00125
00126 G4bool TextBuffer::AppendString (char* a_string)
00127 {
00128 G4bool value = false;
00129 if( (a_string==NULL) || (a_string[0]=='\0') ) return value;
00130 int length = strlen(a_string);
00131 if(a_string[length-1]=='\n') {
00132 lines[linei] += a_string;
00133 lines[linei] = lines[linei].strip(G4String::trailing,'\n');
00134 linei++;
00135 value = true;
00136 } else {
00137 lines[linei] += a_string;
00138 }
00139 if(linei>=linen) {
00140 for(int count=0;count<linen;count++) {
00141 lines[count] = "";
00142 }
00143 linei = 0;
00144 }
00145 if(value==true) endOfPage = linei-1;
00146 return value;
00147 }
00148
00149 void TextBuffer::Draw (HDC a_hdc,RECT* a_rect)
00150 {
00151 TEXTMETRIC tm;
00152 GetTextMetrics (a_hdc,&tm);
00153 short charWidth = (short)tm.tmAveCharWidth;
00154 short charHeight = (short)(tm.tmHeight + tm.tmExternalLeading);
00155 for(int row=0;row<heightOfPage;row++) {
00156 int rowi = endOfPage - row;
00157 short y = (short)(a_rect->bottom - charHeight * (row + 1));
00158 if((rowi>=0)&&(rowi<linei)) {
00159 TextOut (a_hdc,0,y,(char*)spaces,256);
00160 const char* string = lines[rowi].data();
00161 if(string!=NULL) {
00162 TextOut (a_hdc,0,y,(char*)string,strlen((char*)string));
00163 }
00164 }
00165 }
00166 }
00167
00168
00169 static char mainClassName[] = "G4UIWin32";
00170 static char textClassName[] = "G4UIWin32/Text";
00171 static G4bool exitSession = true;
00172 static G4bool exitPause = true;
00173 static G4bool exitHelp = true;
00174 static G4UIsession* tmpSession = NULL;
00175
00176 static WNDPROC oldEditWindowProc;
00177 static G4bool ConvertStringToInt(const char*,int&);
00178
00179 static int actionIdentifier = 0;
00180
00181
00182 G4UIWin32::G4UIWin32 (
00183 )
00184 :mainWindow(NULL)
00185 ,textWindow(NULL)
00186 ,editWindow(NULL)
00187 ,menuBar(NULL)
00188 ,textBuffer(NULL)
00189 ,textCols(80)
00190 ,textRows(12)
00191 ,fHelp(false)
00192 ,fHelpChoice(0)
00193 ,fHistoryPos(-1)
00194
00196 {
00197 G4UImanager* UI = G4UImanager::GetUIpointer();
00198 if(UI!=NULL) UI->SetSession(this);
00199
00200 interactorManager = G4Win32::getInstance ();
00201 static G4bool Done = FALSE;
00202 if(Done==FALSE) {
00203 WNDCLASS wc;
00204 wc.style = CS_HREDRAW | CS_VREDRAW;
00205 wc.lpfnWndProc = (WNDPROC)G4UIWin32::MainWindowProc;
00206 wc.cbClsExtra = 0;
00207 wc.cbWndExtra = 0;
00208 wc.hInstance = ::GetModuleHandle(NULL);
00209 wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
00210 wc.hCursor = LoadCursor(NULL,IDC_ARROW);
00211 wc.hbrBackground = GetStockBrush(WHITE_BRUSH);
00212 wc.lpszMenuName = mainClassName;
00213 wc.lpszClassName = mainClassName;
00214 ::RegisterClass (&wc);
00215
00216 wc.style = CS_HREDRAW | CS_VREDRAW;
00217 wc.lpfnWndProc = (WNDPROC)G4UIWin32::TextWindowProc;
00218 wc.cbClsExtra = 0;
00219 wc.cbWndExtra = 0;
00220 wc.hInstance = ::GetModuleHandle(NULL);
00221 wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
00222 wc.hCursor = LoadCursor(NULL,IDC_ARROW);
00223 wc.hbrBackground = GetStockBrush(WHITE_BRUSH);
00224 wc.lpszMenuName = textClassName;
00225 wc.lpszClassName = textClassName;
00226 ::RegisterClass (&wc);
00227 Done = TRUE;
00228 }
00229
00230 menuBar = CreateMenu();
00231 defaultMenu = CreatePopupMenu();
00232 AppendMenu(menuBar,MF_POPUP,(UINT)defaultMenu,"Geant4");
00233
00234 textBuffer = new TextBuffer();
00235
00236 tmpSession = this;
00237 mainWindow = ::CreateWindow(mainClassName,mainClassName,
00238 WS_OVERLAPPEDWINDOW,
00239 CW_USEDEFAULT,CW_USEDEFAULT,
00240 0,0,
00241 NULL,menuBar,
00242 ::GetModuleHandle(NULL),
00243 NULL);
00244 tmpSession = NULL;
00245 ::SetWindowLong(mainWindow,GWL_USERDATA,LONG(this));
00246
00247 ::SetForegroundWindow(mainWindow);
00248 ::ShowWindow(mainWindow,SW_SHOWDEFAULT);
00249 ::UpdateWindow(mainWindow);
00250
00251 if(UI!=NULL) UI->SetCoutDestination(this);
00252 }
00253
00254 G4UIWin32::~G4UIWin32 (
00255 )
00256
00258 {
00259 G4UImanager* UI = G4UImanager::GetUIpointer();
00260 if(UI!=NULL) {
00261 UI->SetSession(NULL);
00262 UI->SetCoutDestination(NULL);
00263 }
00264 delete textBuffer;
00265 if(textWindow!=NULL) ::SetWindowLong(textWindow,GWL_USERDATA,LONG(NULL));
00266 if(mainWindow!=NULL) {
00267 ::SetWindowLong(mainWindow,GWL_USERDATA,LONG(NULL));
00268 ::DestroyWindow(mainWindow);
00269 }
00270 }
00271
00272 G4UIsession* G4UIWin32::SessionStart (
00273 )
00274
00276 {
00277 if(interactorManager==NULL) return this;
00278 Prompt ("session");
00279 exitSession = false;
00280 interactorManager->DisableSecondaryLoop ();
00281 void* event;
00282 while((event = interactorManager->GetEvent())!=NULL) {
00283 interactorManager->DispatchEvent(event);
00284 if(exitSession==true) break;
00285 }
00286 interactorManager->EnableSecondaryLoop ();
00287 return this;
00288 }
00289
00290 void G4UIWin32::Prompt (
00291 G4String a_prompt
00292 )
00293
00295 {
00296 }
00297
00298 void G4UIWin32::SessionTerminate (
00299 )
00300
00302 {
00303 }
00304
00305 void G4UIWin32::PauseSessionStart (
00306 G4String a_state
00307 )
00308
00310 {
00311 if(a_state=="G4_pause> ") {
00312 SecondaryLoop ("Pause, type continue to exit this state");
00313 }
00314
00315 if(a_state=="EndOfEvent") {
00316
00317 SecondaryLoop ("End of event, type continue to exit this state");
00318 }
00319 }
00320
00321 void G4UIWin32::SecondaryLoop (
00322 G4String a_prompt
00323 )
00324
00326 {
00327 if(interactorManager==NULL) return;
00328 Prompt(a_prompt);
00329 exitPause = false;
00330 void* event;
00331 while((event = interactorManager->GetEvent())!=NULL) {
00332 interactorManager->DispatchEvent(event);
00333 if(exitPause==true) break;
00334 }
00335 Prompt("session");
00336 }
00337
00338 G4int G4UIWin32::ReceiveG4cout (
00339 G4String a_string
00340 )
00341
00343 {
00344 TextAppendString((char*)a_string.data());
00345 return 0;
00346 }
00347
00348 G4int G4UIWin32::ReceiveG4cerr (
00349 G4String a_string
00350 )
00351
00353 {
00354 TextAppendString((char*)a_string.data());
00355 return 0;
00356 }
00357
00358 G4bool G4UIWin32::GetHelpChoice(
00359 G4int& aInt
00360 )
00361
00363 {
00364 fHelp = true;
00365
00366 if(interactorManager==NULL) return false;
00367 Prompt("Help");
00368 exitHelp = false;
00369 void* event;
00370 while((event = interactorManager->GetEvent())!=NULL) {
00371 interactorManager->DispatchEvent(event);
00372 if(exitHelp==true) break;
00373 }
00374 Prompt("session");
00375
00376 if(fHelp==false) return false;
00377 aInt = fHelpChoice;
00378 fHelp = false;
00379 return true;
00380 }
00381
00382 void G4UIWin32::ExitHelp(
00383 )
00384
00386 {
00387 }
00388
00389 void G4UIWin32::AddMenu (
00390 const char* a_name
00391 ,const char* a_label
00392 )
00393
00395 {
00396 if(a_name==NULL) return;
00397 if(defaultMenu!=NULL) {
00398 DeleteMenu (menuBar,0,MF_BYPOSITION);
00399 defaultMenu = NULL;
00400 }
00401 HMENU hMenu = CreatePopupMenu();
00402 AppendMenu(menuBar,MF_POPUP,(UINT)hMenu,a_label);
00403 AddInteractor(a_name,(G4Interactor)hMenu);
00404 DrawMenuBar(mainWindow);
00405 }
00406
00407 void G4UIWin32::AddButton (
00408 const char* a_menu
00409 ,const char* a_label
00410 ,const char* a_command
00411 )
00412
00414 {
00415 if(a_menu==NULL) return;
00416 if(a_label==NULL) return;
00417 if(a_command==NULL) return;
00418 HMENU hMenu = (HMENU)GetInteractor(a_menu);
00419 actionIdentifier++;
00420 commands[actionIdentifier] = a_command;
00421 AppendMenu (hMenu,MF_STRING,actionIdentifier,a_label);
00422 }
00423
00424 G4String G4UIWin32::GetCommand (
00425 int a_id
00426 )
00427
00429 {
00430 return commands[a_id];
00431 }
00432
00433
00434
00435 LRESULT CALLBACK G4UIWin32::MainWindowProc (
00436 HWND a_window
00437 ,UINT a_message
00438 ,WPARAM a_wParam
00439 ,LPARAM a_lParam
00440 )
00441
00443 {
00444 static short charWidth,charHeight;
00445
00446 switch (a_message) {
00447 case WM_CREATE:{
00448 HDC hdc;
00449 TEXTMETRIC tm;
00450 RECT rect;
00451 GetWindowRect (a_window,&rect);
00452
00453 hdc = GetDC (a_window);
00454 GetTextMetrics (hdc,&tm);
00455 charWidth = (short)tm.tmAveCharWidth;
00456 charHeight = (short)(tm.tmHeight + tm.tmExternalLeading);
00457 ReleaseDC (a_window,hdc);
00458
00459 G4UIWin32* This = (G4UIWin32*)tmpSession;
00460 if(This!=NULL) {
00461 This->textWindow = CreateWindow (textClassName,NULL,
00462 WS_CHILD | WS_VISIBLE | WS_VSCROLL,
00463 0,0,
00464 This->textCols * charWidth,
00465 This->textRows * charHeight,
00466 a_window,NULL,
00467 GetWindowInstance(a_window),
00468 NULL);
00469 ::SetWindowLong (This->textWindow,GWL_USERDATA,LONG(This));
00470
00471 This->editWindow = CreateWindow ("edit",NULL,
00472 WS_CHILD | WS_VISIBLE | WS_BORDER,
00473 0,This->textRows * charHeight,
00474 This->textCols * charWidth,charHeight,
00475 a_window,(HMENU)1,
00476 GetWindowInstance(a_window),
00477 NULL);
00478 oldEditWindowProc = (WNDPROC)GetWindowLong(This->editWindow,GWL_WNDPROC);
00479 SetWindowLong (This->editWindow,GWL_WNDPROC,(LONG)EditWindowProc);
00480
00481 MoveWindow (a_window,
00482 rect.left,rect.top,
00483 2 * GetSystemMetrics(SM_CXFRAME) +
00484 This->textCols * charWidth,
00485 GetSystemMetrics(SM_CYCAPTION) +
00486 2 * GetSystemMetrics(SM_CYFRAME) +
00487 This->textRows * charHeight + charHeight,
00488 TRUE);
00489 }
00490 }return 0;
00491 case WM_SIZE:{
00492 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(a_window,GWL_USERDATA);
00493 if(This!=NULL) {
00494
00495 int width = LOWORD(a_lParam);
00496 int height = HIWORD(a_lParam);
00497 int editHeight = charHeight;
00498 MoveWindow (This->textWindow,
00499 0,0,
00500 width,height - editHeight,
00501 FALSE);
00502 MoveWindow (This->editWindow,
00503 0,height - editHeight,
00504 width,charHeight,
00505 FALSE);
00506 ((TextBuffer*)This->textBuffer)->SetHeightOfPage(height/charHeight);
00507 }
00508 }return 0;
00509 case WM_SETFOCUS:{
00510 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(a_window,GWL_USERDATA);
00511 if(This!=NULL) SetFocus (This->editWindow);
00512 }return 0;
00513 case WM_COMMAND:{
00514 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(a_window,GWL_USERDATA);
00515 if(This!=NULL) {
00516 if(This->fHelp==false) {
00517 G4String command = This->GetCommand(a_wParam);
00518 This->ApplyShellCommand (command,exitSession,exitPause);
00519 }
00520 }
00521 }return 0;
00522 case WM_DESTROY:
00523 PostQuitMessage(0);
00524 return 0;
00525 }
00526 return (DefWindowProc(a_window,a_message,a_wParam,a_lParam));
00527 }
00528
00529 LRESULT CALLBACK G4UIWin32::TextWindowProc (
00530 HWND a_window
00531 ,UINT a_message
00532 ,WPARAM a_wParam
00533 ,LPARAM a_lParam
00534 )
00535
00537 {
00538 switch (a_message) {
00539 case WM_PAINT:{
00540 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(a_window,GWL_USERDATA);
00541 if(This!=NULL) {
00542 TextBuffer* textBuffer = (TextBuffer*)This->textBuffer;
00543 RECT rect;
00544 GetClientRect (a_window,&rect);
00545 PAINTSTRUCT ps;
00546 HDC hdc = BeginPaint(a_window,&ps);
00547 textBuffer->Draw(hdc,&rect);
00548 EndPaint(a_window,&ps);
00549 }
00550 }return 0;
00551 case WM_VSCROLL:{
00552 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(a_window,GWL_USERDATA);
00553 if(This!=NULL) {
00554 TextBuffer* textBuffer = (TextBuffer*)This->textBuffer;
00555 int what = LOWORD(a_wParam);
00556 switch(what) {
00557 case SB_LINEUP:
00558 textBuffer->DecrementEndOfPage();
00559 break;
00560 case SB_LINEDOWN:
00561 textBuffer->IncrementEndOfPage();
00562 break;
00563 case SB_PAGEUP:
00564 textBuffer->JumpUpEndOfPage();
00565 break;
00566 case SB_PAGEDOWN:
00567 textBuffer->JumpDownEndOfPage();
00568 break;
00569 case SB_THUMBPOSITION:
00570 case SB_THUMBTRACK:
00571 textBuffer->SetEndOfPage(HIWORD(a_wParam));
00572 break;
00573 default:
00574 return 0;
00575 }
00576 int eop = textBuffer->GetEndOfPage();
00577 SetScrollPos(a_window,SB_VERT,eop,TRUE);
00578 InvalidateRect(a_window,NULL,TRUE);
00579 }}return 0;
00580 case WM_DESTROY:
00581 PostQuitMessage(0);
00582 return 0;
00583 }
00584 return (DefWindowProc(a_window,a_message,a_wParam,a_lParam));
00585 }
00586
00587 LRESULT CALLBACK G4UIWin32::EditWindowProc (
00588 HWND a_window
00589 ,UINT a_message
00590 ,WPARAM a_wParam
00591 ,LPARAM a_lParam
00592 )
00593
00595 {
00596 switch (a_message) {
00597 case WM_KEYDOWN:
00598 switch(a_wParam){
00599 case VK_RETURN:{
00600 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(
00601 GetParent(a_window),GWL_USERDATA);
00602 char buffer[128];
00603 GetWindowText (a_window,buffer,128);
00604 G4String command (buffer);
00605
00606 Edit_SetText(a_window,"");
00607 Edit_SetSel(a_window,0,0);
00608
00609 if(This!=NULL) {
00610 if(This->fHelp==true) {
00611 exitHelp = true;
00612 This->fHelp = ConvertStringToInt(command.data(),This->fHelpChoice);
00613 } else {
00614 This->fHistory.push_back(command);
00615 This->fHistoryPos = -1;
00616 This->ApplyShellCommand (command,exitSession,exitPause);
00617 }
00618 }
00619
00620 }break;
00621 case VK_TAB:{
00622 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(
00623 GetParent(a_window),GWL_USERDATA);
00624 if( (This!=NULL) && (This->fHelp==true) ) break;
00625 char buffer[128];
00626 Edit_GetText(a_window,buffer,128);
00627
00628 G4String command(buffer);
00629
00630 if(This!=NULL) {
00631 G4String cmd = This->Complete(command);
00632 const char* d = cmd.data();
00633 int l = strlen(d);
00634 Edit_SetText(a_window,d);
00635 Edit_SetSel(a_window,l,l);
00636 }
00637
00638 }break;
00639 case VK_UP:{
00640 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(
00641 GetParent(a_window),GWL_USERDATA);
00642 if(This!=NULL) {
00643 int pos = This->fHistoryPos== -1 ?
00644 This->fHistory.size()-1 : This->fHistoryPos-1;
00645 if((pos>=0)&&(pos<(int)This->fHistory.size())) {
00646 G4String command = This->fHistory[pos];
00647 const char* d = command.data();
00648 int l = strlen(d);
00649 Edit_SetText(a_window,d);
00650 Edit_SetSel(a_window,l,l);
00651
00652 This->fHistoryPos = pos;
00653 }
00654 }
00655 }return 0;
00656 case VK_DOWN:{
00657 G4UIWin32* This = (G4UIWin32*)::GetWindowLong(
00658 GetParent(a_window),GWL_USERDATA);
00659 if(This!=NULL) {
00660 int pos = This->fHistoryPos + 1;
00661 if((pos>=0)&&(pos<(int)This->fHistory.size())) {
00662 G4String command = This->fHistory[pos];
00663 const char* d = command.data();
00664 int l = strlen(d);
00665 Edit_SetText(a_window,d);
00666 Edit_SetSel(a_window,l,l);
00667
00668 This->fHistoryPos = pos;
00669 } else if(pos>=(int)This->fHistory.size()) {
00670 Edit_SetText(a_window,"");
00671 Edit_SetSel(a_window,0,0);
00672
00673 This->fHistoryPos = -1;
00674 }
00675 }
00676 }return 0;
00677 }
00678 }
00679 return CallWindowProc(oldEditWindowProc,
00680 a_window,a_message,
00681 a_wParam,a_lParam);
00682 }
00683
00684 void G4UIWin32::TextAppendString (
00685 char* a_string
00686 )
00687
00689 {
00690 if( (a_string==NULL) || (a_string[0]=='\0') ) return;
00691 if(textWindow==NULL) return;
00692 if(((TextBuffer*)textBuffer)->AppendString(a_string)==true) {
00693
00694 RECT rect;
00695 GetClientRect(textWindow,&rect);
00696 InvalidateRect(textWindow,NULL,TRUE);
00697 HDC hdc = GetDC(textWindow);
00698 ((TextBuffer*)textBuffer)->Draw(hdc,&rect);
00699 ReleaseDC (textWindow,hdc);
00700 int linen = ((TextBuffer*)textBuffer)->GetNumberOfLines();
00701 SetScrollRange(textWindow,SB_VERT,0,linen-1,TRUE);
00702 SetScrollPos(textWindow,SB_VERT,linen-1,TRUE);
00703 }
00704 }
00706 G4bool ConvertStringToInt(
00707 const char* aString
00708 ,int& aInt
00709 )
00712 {
00713 aInt = 0;
00714 if(aString==NULL) return false;
00715 char* s;
00716 long value = strtol(aString,&s,10);
00717 if(s==aString) return false;
00718 aInt = value;
00719 return true;
00720 }
00721
00722
00723 #endif