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