1 // Dialog.cpp
2
3 #include "StdAfx.h"
4
5 // For compilers that support precompilation, includes "wx/wx.h".
6 #include "wx/wxprec.h"
7
8 #ifdef __BORLANDC__
9 #pragma hdrstop
10 #endif
11
12 // for all others, include the necessary headers (this file is usually all you
13 // need because it includes almost all "standard" wxWidgets headers)
14 #ifndef WX_PRECOMP
15 #include "wx/wx.h"
16 #endif
17
18 #include "Windows/Control/DialogImpl.h"
19 #include "Windows/Synchronization.h"
20
21 // #include "../GUI/p7zip_32.xpm"
22 extern const char * p7zip_32_xpm[];
23
nameWindowToUnix(const TCHAR * lpFileName)24 const TCHAR * nameWindowToUnix(const TCHAR * lpFileName) {
25 if ((lpFileName[0] == wxT('c')) && (lpFileName[1] == wxT(':'))) return lpFileName+2;
26 return lpFileName;
27 }
28
29
30 extern time_t g_T0; // FIXME
31
32 extern wxWindow * g_window;
33
34 enum { // FIXME - duplicate
35 WORKER_EVENT=100 // this one gets sent from the worker thread
36 };
37
38 #define DIALOG_ID_MESSAGEBOX 8100
39 #define DIALOG_ID_DIR_DIALOG 8101
40 #define DIALOG_ID_FILE_DIALOG 8102
41 #define DIALOG_ID_POST_DIALOG 8190
42 #define DIALOG_ID_END_DIALOG 8199
43
44 static struct
45 {
46 bool busy;
47
48 int id;
49 wxWindow *parentWindow;
50
51 // CreateDialog
52 NWindows::NControl::CModalDialog * dialog;
53
54 // EndModal
55 int value;
56 NWindows::NControl::CModalDialogImpl * window;
57
58 // MessageBox
59 const TCHAR * msg;
60 const TCHAR * title;
61 int flag;
62
63 //
64 LPCWSTR initialFolderOrFile;
65
66 wxSemaphore * sem;
67 int ret;
68
69 UString resultPath;
70
71 #define MAX_CREATE 16
72 } g_tabCreate[MAX_CREATE];
73
74 static int myCreateHandle2(int n);
75
findFreeInd()76 static int findFreeInd()
77 {
78 static NWindows::NSynchronization::CCriticalSection g_CriticalSection;
79
80 g_CriticalSection.Enter();
81 int ind = 0;
82 while (ind < MAX_CREATE)
83 {
84 if (g_tabCreate[ind].busy == false)
85 {
86 g_tabCreate[ind].busy = true;
87 break;
88 }
89 ind++;
90 }
91 g_CriticalSection.Leave();
92
93 return ind;
94 }
95
WaitInd(int ind,int id,wxWindow * parent,UString & resultPath)96 static int WaitInd(int ind,int id,wxWindow * parent,UString &resultPath)
97 {
98 int ret = 0;
99
100 g_tabCreate[ind].id = id;
101 g_tabCreate[ind].parentWindow = parent;
102 g_tabCreate[ind].ret = 0;
103 g_tabCreate[ind].resultPath = wxEmptyString;
104
105 if (wxThread::IsMain())
106 {
107 ret = myCreateHandle2(ind);
108 resultPath = g_tabCreate[ind].resultPath;
109 }
110 else
111 {
112 g_tabCreate[ind].sem = new wxSemaphore(0);
113
114 // create any type of command event here
115 wxCommandEvent event( wxEVT_COMMAND_MENU_SELECTED, WORKER_EVENT );
116 event.SetInt( ind );
117
118 // send in a thread-safe way
119 // DEBUG printf("T=0x%lx - %d : WaitInd(%d,%p): BEGIN\n", wxThread::GetCurrentId(),time(0)-g_T0,g_tabCreate[ind].id,g_tabCreate[ind].parentWindow);
120 wxPostEvent( g_window, event );
121
122 g_tabCreate[ind].sem->Wait();
123
124 ret = g_tabCreate[ind].ret;
125 resultPath = g_tabCreate[ind].resultPath;
126 // DEBUG printf("T=0x%lx - %d : WaitInd(%d,%p): ret=%d\n", wxThread::GetCurrentId(),time(0)-g_T0,g_tabCreate[ind].id,g_tabCreate[ind].parentWindow,ret);
127 delete g_tabCreate[ind].sem;
128 g_tabCreate[ind].sem = 0;
129 }
130
131 g_tabCreate[ind].busy = false;
132
133 return ret;
134 }
135
WaitInd(int ind,int id,wxWindow * parent)136 static int WaitInd(int ind,int id,wxWindow * parent)
137 {
138 UString resultPath;
139 return WaitInd(ind,id,parent,resultPath);
140 }
141
142 class LockGUI
143 {
144 bool _IsMain;
145 public:
LockGUI()146 LockGUI() {
147 _IsMain = wxThread::IsMain();
148 if (!_IsMain) {
149 // DEBUG printf("GuiEnter(0x%lx)\n",wxThread::GetCurrentId());
150 wxMutexGuiEnter();
151 }
152 }
~LockGUI()153 ~LockGUI() {
154 if (!_IsMain) {
155 wxMutexGuiLeave();
156 // DEBUG printf("GuiLeave(0x%lx)\n",wxThread::GetCurrentId());
157 }
158 }
159 };
160
161 static const unsigned int kNumDialogsMax = 32;
162 static unsigned int g_NumDialogs = 0;
163 static const CDialogInfo *g_Dialogs[kNumDialogsMax];
164
RegisterDialog(const CDialogInfo * dialogInfo)165 void RegisterDialog(const CDialogInfo *dialogInfo)
166 {
167 // DEBUG printf("RegisterDialog : %d\n",dialogInfo->id);
168 if (g_NumDialogs < kNumDialogsMax)
169 g_Dialogs[g_NumDialogs++] = dialogInfo;
170 }
171
172 namespace NWindows {
173
MyLoadString(unsigned int resourceID)174 CSysString MyLoadString(unsigned int resourceID)
175 {
176 for(int i=0; i < g_NumDialogs; i++) {
177 if (g_Dialogs[i]->stringTable) {
178 int j = 0;
179 while(g_Dialogs[i]->stringTable[j].str) {
180 if (resourceID == g_Dialogs[i]->stringTable[j].id) {
181 return g_Dialogs[i]->stringTable[j].str;
182 }
183
184 j++;
185 }
186 }
187 }
188 return L"FIXME-MyLoadStringW-";
189 }
190
191 namespace NControl {
192
193 /////////////////////////////////////////// CModalDialog //////////////////////////////////
194
CheckButton(int buttonID,UINT checkState)195 bool CModalDialog::CheckButton(int buttonID, UINT checkState)
196 {
197 LockGUI lock;
198 wxCheckBox* w = (wxCheckBox*)_window->FindWindow(buttonID);
199 if (w)
200 {
201 w->SetValue(checkState == BST_CHECKED);
202 return true;
203 }
204 return false;
205 }
206
IsButtonChecked(int buttonID) const207 UINT CModalDialog::IsButtonChecked(int buttonID) const
208 {
209 LockGUI lock;
210 wxCheckBox* w = (wxCheckBox*)_window->FindWindow(buttonID);
211 if (w)
212 {
213 bool bret = w->GetValue();
214 if (bret) return BST_CHECKED;
215 }
216 return BST_UNCHECKED;
217 }
218
EnableItem(int id,bool state)219 void CModalDialog::EnableItem(int id, bool state)
220 {
221 LockGUI lock;
222 wxWindow* w = _window->FindWindow(id);
223 if (w) w->Enable(state);
224 }
225
SetItemText(int id,const TCHAR * txt)226 void CModalDialog::SetItemText(int id, const TCHAR *txt)
227 {
228 LockGUI lock;
229 wxWindow* w = _window->FindWindow(id);
230 if (w)
231 {
232 wxString label(txt);
233 w->SetLabel(label);
234 }
235 }
236
GetItem(long id) const237 wxWindow * CModalDialog::GetItem(long id) const
238 {
239 LockGUI lock;
240 return _window->FindWindow(id);
241 }
242
ShowItem(int itemID,int cmdShow) const243 void CModalDialog::ShowItem(int itemID, int cmdShow) const
244 {
245 LockGUI lock;
246 // cmdShow = SW_HIDE or SW_SHOW (sometimes false or true !)
247 wxWindow* w = _window->FindWindow(itemID);
248 if (w)
249 {
250 // FIXME w->Show(cmdShow != SW_HIDE);
251 w->Enable(cmdShow != SW_HIDE);
252 }
253 }
254
SetTimer(UINT_PTR idEvent,unsigned milliseconds)255 UINT_PTR CModalDialog::SetTimer(UINT_PTR idEvent , unsigned milliseconds)
256 {
257 LockGUI lock;
258 return _window->SetTimer(idEvent , milliseconds);
259 }
260
KillTimer(UINT_PTR idEvent)261 void CModalDialog::KillTimer(UINT_PTR idEvent)
262 {
263 LockGUI lock;
264 _window->KillTimer(idEvent);
265 }
266
SetText(const TCHAR * _title)267 void CModalDialog::SetText(const TCHAR *_title) {
268 LockGUI lock;
269 _window->SetTitle(_title);
270 }
271
272
GetText(CSysString & s)273 bool CModalDialog::GetText(CSysString &s) {
274 wxString str;
275 {
276 LockGUI lock;
277 str = _window->GetTitle();
278 }
279 s = str;
280 return true;
281 }
282
Create(int id,HWND parentWindow)283 INT_PTR CModalDialog::Create(int id , HWND parentWindow)
284 {
285 int ind = findFreeInd();
286
287 g_tabCreate[ind].dialog = this;
288
289 return WaitInd(ind,id,parentWindow);
290 }
291
End(int result)292 void CModalDialog::End(int result)
293 {
294 int ind = findFreeInd();
295
296 g_tabCreate[ind].window = _window;
297 g_tabCreate[ind].value = result;
298
299 WaitInd(ind,DIALOG_ID_END_DIALOG,0);
300 }
301
PostMessage(UINT message)302 void CModalDialog::PostMessage(UINT message)
303 {
304 int ind = findFreeInd();
305
306 g_tabCreate[ind].dialog = this;
307 g_tabCreate[ind].value = message;
308
309 WaitInd(ind,DIALOG_ID_POST_DIALOG,0);
310 }
311
312 /////////////////////////////////////////// CModalDialogImpl ///////////////////////////////////////
313
CModalDialogImpl(CDialog * dialog,wxWindow * parent,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style)314 CModalDialogImpl::CModalDialogImpl(CDialog *dialog, wxWindow* parent, wxWindowID id,
315 const wxString& title, const wxPoint& pos,
316 const wxSize& size, long style) :
317 wxDialog(parent, id, title , pos , size, style /* | wxDIALOG_NO_PARENT */ ) ,
318 _timer(this, TIMER_ID_IMPL), _dialog(dialog)
319 {
320 // set the frame icon
321 this->SetIcon(wxICON(p7zip_32));
322 }
323
OnAnyButton(wxCommandEvent & event)324 void CModalDialogImpl::OnAnyButton(wxCommandEvent& event)
325 {
326 int id = event.GetId();
327 if (id == wxID_OK)
328 {
329 if (_dialog) _dialog->OnOK();
330 // event.Skip(true);
331 }
332 else if (id == wxID_CANCEL)
333 {
334 if (_dialog) _dialog->OnCancel();
335 // event.Skip(true);
336 }
337 else if (id == wxID_HELP)
338 {
339 if (_dialog) _dialog->OnHelp();
340 }
341 else
342 {
343 if (_dialog)
344 {
345 bool bret = _dialog->OnButtonClicked(id, FindWindow(id) );
346 }
347 }
348 }
349
OnAnyChoice(wxCommandEvent & event)350 void CModalDialogImpl::OnAnyChoice(wxCommandEvent &event)
351 {
352 int itemID = event.GetId();
353 if (_dialog) _dialog->OnCommand(CBN_SELCHANGE, itemID, 0);
354 }
355
OnAnyTimer(wxTimerEvent & event)356 void CModalDialogImpl::OnAnyTimer(wxTimerEvent &event)
357 {
358 int timerID = event.GetId();
359 if (_dialog) _dialog->OnTimer(timerID , 0);
360 }
361 }
362 }
363
364 ///////////////////////// myCreateHandle
365
366
myCreateHandle2(int n)367 static int myCreateHandle2(int n)
368 {
369 int id = g_tabCreate[n].id;
370 wxWindow * parentWindow = g_tabCreate[n].parentWindow;
371 NWindows::NControl::CModalDialogImpl * window = 0;
372
373 // DEBUG printf("T=0x%lx - %d : myCreateHandle(%d): BEGIN\n", wxThread::GetCurrentId(),time(0)-g_T0,n);
374
375 if (id == DIALOG_ID_END_DIALOG)
376 {
377 /* FIXME : the dialog must be shown before ending it ?
378 while (!_window->IsShownOnScreen()) Sleep(200);
379 Sleep(200);
380 */
381 g_tabCreate[n].window->EndModal(g_tabCreate[n].value);
382 return 0;
383 }
384
385 if (id == DIALOG_ID_POST_DIALOG)
386 {
387 g_tabCreate[n].dialog->OnMessage(g_tabCreate[n].value, 0, 0);
388 return 0;
389 }
390
391 if (id == DIALOG_ID_MESSAGEBOX)
392 {
393 long style = g_tabCreate[n].flag;
394 long decorated_style = style;
395 if ( ( style & ( wxICON_EXCLAMATION | wxICON_HAND | wxICON_INFORMATION |
396 wxICON_QUESTION ) ) == 0 )
397 {
398 decorated_style |= ( style & wxYES ) ? wxICON_QUESTION : wxICON_INFORMATION ;
399 }
400 wxMessageDialog dialog(parentWindow, g_tabCreate[n].msg, g_tabCreate[n].title, decorated_style);
401 dialog.SetIcon(wxICON(p7zip_32));
402 int ret = dialog.ShowModal();
403
404 return ret;
405 }
406
407 if (id == DIALOG_ID_DIR_DIALOG)
408 {
409 wxString defaultDir = g_tabCreate[n].initialFolderOrFile;
410 wxDirDialog dirDialog(g_tabCreate[n].parentWindow,
411 g_tabCreate[n].title, defaultDir);
412 dirDialog.SetIcon(wxICON(p7zip_32));
413 int ret = dirDialog.ShowModal();
414 if (ret == wxID_OK) g_tabCreate[n].resultPath = dirDialog.GetPath();
415 return ret;
416 }
417
418 if (id == DIALOG_ID_FILE_DIALOG)
419 {
420 wxString defaultFilename = g_tabCreate[n].initialFolderOrFile;
421 wxFileDialog fileDialog(g_tabCreate[n].parentWindow, g_tabCreate[n].title,
422 wxEmptyString, defaultFilename,
423 wxT("All Files (*.*)|*.*"), wxSAVE|wxOVERWRITE_PROMPT);
424 fileDialog.SetIcon(wxICON(p7zip_32));
425 int ret = fileDialog.ShowModal();
426 if (ret == wxID_OK) g_tabCreate[n].resultPath = fileDialog.GetPath();
427 return ret;
428 }
429
430 for(int i=0; i < g_NumDialogs; i++) {
431 if (id == g_Dialogs[i]->id) {
432 // DEBUG printf("%d : Create(%d,%p): CreateDialog-1\n",time(0)-g_T0,id,parentWindow);
433 window = (g_Dialogs[i]->createDialog)(g_tabCreate[n].dialog,g_tabCreate[n].parentWindow);
434 // DEBUG printf("%d : Create(%d,%p): CreateDialog-2\n",time(0)-g_T0,id,parentWindow);
435 break;
436 }
437 }
438
439 if (window) {
440
441 // DEBUG printf("%d : Create(%d,%p): %p->ShowModal()\n",time(0)-g_T0,id,parentWindow,window);
442
443 INT_PTR ret = window->ShowModal();
444
445 // DEBUG printf("%d : Create(%d,%p): %p->ShowModal() - ret=%d\n",time(0)-g_T0,id,parentWindow,window,ret);
446 window->Detach();
447 window->Destroy();
448
449 // DEBUG printf("%d : Create(%d,%p): END\n",time(0)-g_T0,id,parentWindow,window);
450
451 return ret;
452 }
453
454 // FIXME
455 printf("INTERNAL ERROR : cannot find dialog %d\n",id);
456
457 return 0;
458 }
459
myCreateHandle(int n)460 void myCreateHandle(int n)
461 {
462 int ret = myCreateHandle2(n);
463 g_tabCreate[n].ret = ret;
464 g_tabCreate[n].sem->Post();
465 }
466
MessageBoxW(wxWindow * parent,const TCHAR * msg,const TCHAR * title,int flag)467 int MessageBoxW(wxWindow * parent, const TCHAR * msg, const TCHAR * title,int flag)
468 {
469 int ind = findFreeInd();
470
471 g_tabCreate[ind].msg = msg;
472 g_tabCreate[ind].title = title;
473 g_tabCreate[ind].flag = flag;
474
475 return WaitInd(ind,DIALOG_ID_MESSAGEBOX,parent);
476 }
477
478
479
480 // FIXME : should be in Windows/Shell.cpp
481
482 namespace NWindows{
483 namespace NShell{
484
BrowseForFolder(HWND owner,LPCWSTR title,LPCWSTR initialFolder,UString & resultPath)485 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
486 {
487 int ind = findFreeInd();
488
489 g_tabCreate[ind].title = title;
490 g_tabCreate[ind].initialFolderOrFile = nameWindowToUnix(initialFolder);
491
492 UString resTmp;
493 int ret = WaitInd(ind,DIALOG_ID_DIR_DIALOG,owner,resTmp);
494 if(ret == wxID_OK)
495 {
496 resultPath = resTmp;
497 return true;
498 }
499 return false;
500 }
501
502 }}
503
504 /////////////////////////// CPP/Windows/CommonDialog.cpp
505 namespace NWindows
506 {
507
MyGetOpenFileName(HWND hwnd,LPCWSTR title,LPCWSTR fullFileName,LPCWSTR s,UString & resPath)508 bool MyGetOpenFileName(HWND hwnd, LPCWSTR title, LPCWSTR fullFileName, LPCWSTR s, UString &resPath)
509 {
510 int ind = findFreeInd();
511
512 g_tabCreate[ind].title = title;
513 g_tabCreate[ind].initialFolderOrFile = nameWindowToUnix(fullFileName);
514
515 UString resTmp;
516 int ret = WaitInd(ind,DIALOG_ID_FILE_DIALOG,hwnd,resTmp);
517 if(ret == wxID_OK)
518 {
519 resPath = resTmp;
520 return true;
521 }
522 return false;
523 }
524 }
525
526