framework2

Форк
0
777 строк · 24.4 Кб
1

2
#include "ofSystemUtils.h"
3
#include "ofFileUtils.h"
4
#include "ofLog.h"
5
#include "ofUtils.h"
6
#include "ofConstants.h"
7

8
#include <condition_variable>
9
#include <mutex>
10

11
#ifdef TARGET_OSX
12
	// ofSystemUtils.cpp is configured to build as
13
	// objective-c++ so as able to use Cocoa dialog panels
14
	// This is done with this compiler flag
15
	//		-x objective-c++
16
	// http://www.yakyak.org/viewtopic.php?p=1475838&sid=1e9dcb5c9fd652a6695ac00c5e957822#p1475838
17

18
	#include <Cocoa/Cocoa.h>
19
	#include "ofAppRunner.h"
20
#endif
21

22
#ifdef TARGET_WIN32
23

24
#define _WIN32_DCOM
25
#include <winuser.h>
26
#include <commdlg.h>
27
#include <windows.h>
28
#include <shlobj.h>
29
#include <tchar.h>
30
#include <stdio.h>
31
#include <locale>
32
#include <sstream>
33
#include <string>
34

35
std::string convertWideToNarrow( const wchar_t *s, char dfault = '?',
36
                      const std::locale& loc = std::locale() )
37
{
38
  std::ostringstream stm;
39

40
  while( *s != L'\0' ) {
41
    stm << std::use_facet< std::ctype<wchar_t> >( loc ).narrow( *s++, dfault );
42
  }
43
  return stm.str();
44
}
45

46
std::wstring convertNarrowToWide( const std::string& as ){
47
    // deal with trivial case of empty string
48
    if( as.empty() )    return std::wstring();
49

50
    // determine required length of new string
51
    size_t reqLength = ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), 0, 0 );
52

53
    // construct new string of required length
54
    std::wstring ret( reqLength, L'\0' );
55

56
    // convert old string to new string
57
    ::MultiByteToWideChar( CP_UTF8, 0, as.c_str(), (int)as.length(), &ret[0], (int)ret.length() );
58

59
    // return new string ( compiler should optimize this away )
60
    return ret;
61
}
62

63
#endif
64

65
#if defined( TARGET_OSX )
66
static void restoreAppWindowFocus(){
67
	NSWindow * appWindow = (__bridge NSWindow *)ofGetCocoaWindow();
68
	if(appWindow) {
69
		[appWindow makeKeyAndOrderFront:nil];
70
	}
71
}
72
#endif
73

74
#if defined( TARGET_LINUX ) && defined (OF_USING_GTK)
75
#include <gtk/gtk.h>
76
#include "ofGstUtils.h"
77
#include <thread>
78
#include <X11/Xlib.h>
79

80
#if GTK_MAJOR_VERSION>=3
81
#define OPEN_BUTTON "_Open"
82
#define SELECT_BUTTON "_Select All"
83
#define SAVE_BUTTON "_Save"
84
#define CANCEL_BUTTON "_Cancel"
85
#else
86
#define OPEN_BUTTON GTK_STOCK_OPEN
87
#define SELECT_BUTTON GTK_STOCK_SELECT_ALL
88
#define SAVE_BUTTON GTK_STOCK_SAVE
89
#define CANCEL_BUTTON GTK_STOCK_CANCEL
90
#endif
91

92

93
gboolean init_gtk(gpointer userdata){
94
	int argc=0; char **argv = nullptr;
95
	gtk_init (&argc, &argv);
96

97
	return FALSE;
98
}
99

100
struct FileDialogData{
101
	GtkFileChooserAction action;
102
	std::string windowTitle;
103
	std::string defaultName;
104
	std::string results;
105
	bool done;
106
	std::condition_variable condition;
107
	std::mutex mutex;
108
};
109

110
gboolean file_dialog_gtk(gpointer userdata){
111
	FileDialogData * dialogData = (FileDialogData*)userdata;
112
	const gchar* button_name = nullptr;
113
	switch(dialogData->action){
114
	case GTK_FILE_CHOOSER_ACTION_OPEN:
115
		button_name = OPEN_BUTTON;
116
		break;
117
	case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
118
		button_name = SELECT_BUTTON;
119
		break;
120
	case GTK_FILE_CHOOSER_ACTION_SAVE:
121
		button_name = SAVE_BUTTON;
122
		break;
123
	default:
124
		break;
125
	}
126

127
	if(button_name!=nullptr){
128
		GtkWidget *dialog = gtk_file_chooser_dialog_new (dialogData->windowTitle.c_str(),
129
							  nullptr,
130
							  dialogData->action,
131
							  button_name, GTK_RESPONSE_ACCEPT,
132
							  CANCEL_BUTTON, GTK_RESPONSE_CANCEL,
133
							  nullptr);
134

135
		if(ofFile(dialogData->defaultName, ofFile::Reference).isDirectory()){
136
			gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dialogData->defaultName.c_str());
137
		}else{
138
			gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), dialogData->defaultName.c_str());
139
		}
140

141
		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
142
			dialogData->results = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
143
		}
144
		gtk_widget_destroy (dialog);
145
	}
146

147
	std::unique_lock<std::mutex> lck(dialogData->mutex);
148
	dialogData->condition.notify_all();
149
	dialogData->done = true;
150
	return G_SOURCE_REMOVE;
151
}
152

153
struct TextDialogData{
154
	std::string text;
155
	std::string question;
156
	bool done;
157
	std::condition_variable condition;
158
	std::mutex mutex;
159
};
160

161
gboolean alert_dialog_gtk(gpointer userdata){
162
	TextDialogData * dialogData = (TextDialogData*)userdata;
163
	GtkWidget* dialog = gtk_message_dialog_new (nullptr, (GtkDialogFlags) 0, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "%s", dialogData->text.c_str());
164
	gtk_widget_grab_focus(gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK));
165
	gtk_dialog_run (GTK_DIALOG (dialog));
166
	gtk_widget_destroy (dialog);
167
	dialogData->mutex.lock();
168
	dialogData->condition.notify_all();
169
	dialogData->done = true;
170
	dialogData->mutex.unlock();
171

172
	return G_SOURCE_REMOVE;
173
}
174

175
gboolean text_dialog_gtk(gpointer userdata){
176
	TextDialogData * dialogData = (TextDialogData*)userdata;
177
	GtkWidget* dialog = gtk_message_dialog_new (nullptr, (GtkDialogFlags) 0, GTK_MESSAGE_QUESTION, (GtkButtonsType) GTK_BUTTONS_OK_CANCEL, "%s", dialogData->question.c_str() );
178
	GtkWidget* content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
179
	GtkWidget* textbox = gtk_entry_new();
180
	gtk_entry_set_text(GTK_ENTRY(textbox),dialogData->text.c_str());
181
	gtk_container_add (GTK_CONTAINER (content_area), textbox);
182
	gtk_widget_show_all (dialog);
183
	if(gtk_dialog_run (GTK_DIALOG (dialog))==GTK_RESPONSE_OK){
184
		dialogData->text = gtk_entry_get_text(GTK_ENTRY(textbox));
185
	} else {
186
    dialogData->text = "";
187
  }
188
	gtk_widget_destroy (dialog);
189
	dialogData->mutex.lock();
190
	dialogData->condition.notify_all();
191
	dialogData->done = true;
192
	dialogData->mutex.unlock();
193

194
	return G_SOURCE_REMOVE;
195
}
196

197
static void initGTK(){
198
	static bool initialized = false;
199
	if(!initialized){
200
		#if !defined(TARGET_RASPBERRY_PI_LEGACY)
201
		XInitThreads();
202
		#endif
203
		int argc=0; char **argv = nullptr;
204
		gtk_init (&argc, &argv);
205
		ofGstUtils::startGstMainLoop();
206
		initialized = true;
207
	}
208

209
}
210

211
static std::string gtkFileDialog(GtkFileChooserAction action,std::string windowTitle,std::string defaultName=""){
212
	initGTK();
213
	FileDialogData dialogData;
214
	dialogData.action = action;
215
	dialogData.windowTitle = windowTitle;
216
	dialogData.defaultName = defaultName;
217
	dialogData.done = false;
218

219
	g_main_context_invoke(g_main_loop_get_context(ofGstUtils::getGstMainLoop()), &file_dialog_gtk, &dialogData);
220
	if(!dialogData.done){
221
		std::unique_lock<std::mutex> lck(dialogData.mutex);
222
		dialogData.condition.wait(lck);
223
	}
224

225
	return dialogData.results;
226
}
227

228
void resetLocale(std::locale locale){
229
	try{
230
		std::locale::global(locale);
231
	}catch(...){
232
		if(ofToLower(std::locale("").name()).find("utf-8")==std::string::npos){
233
			ofLogWarning("ofSystemUtils") << "GTK changes the locale when opening a dialog which can "
234
				 "break number parsing. We tried to change back to " <<
235
				 locale.name() <<
236
				 "but failed some string parsing functions might behave differently "
237
				 "after this";
238
		}
239
	}
240
}
241
#endif
242

243
#ifdef TARGET_ANDROID
244
#include "ofxAndroidUtils.h"
245
#endif
246

247
#ifdef TARGET_EMSCRIPTEN
248
#include <emscripten/emscripten.h>
249
#endif
250

251

252
//------------------------------------------------------------------------------
253
ofFileDialogResult::ofFileDialogResult(){
254
	filePath = "";
255
	fileName = "";
256
	bSuccess = false;
257
}
258

259
//------------------------------------------------------------------------------
260
std::string ofFileDialogResult::getName(){
261
	return fileName;
262
}
263

264
//------------------------------------------------------------------------------
265
std::string ofFileDialogResult::getPath(){
266
	return filePath;
267
}
268

269

270
//------------------------------------------------------------------------------
271
void ofSystemAlertDialog(std::string errorMessage){
272
	#ifdef TARGET_WIN32
273
		// we need to convert error message to a wide char message.
274
		std::wstring errorMessageW{errorMessage.begin(),errorMessage.end()};
275
		// launch the alert:
276
		MessageBoxW(nullptr, errorMessageW.c_str(), L"alert", MB_OK);
277
	#endif
278

279
	#ifdef TARGET_OSX
280
		@autoreleasepool {
281
			NSAlert* alertDialog = [[NSAlert alloc] init];
282
			alertDialog.messageText = [NSString stringWithUTF8String:errorMessage.c_str()];
283
			[alertDialog runModal];
284
			restoreAppWindowFocus();
285
		}
286
	#endif
287

288
	#if defined( TARGET_LINUX ) && defined (OF_USING_GTK)
289
		auto locale = std::locale();
290
		initGTK();
291
		TextDialogData dialogData;
292
		dialogData.text = errorMessage;
293
		dialogData.done = false;
294
		g_main_context_invoke(g_main_loop_get_context(ofGstUtils::getGstMainLoop()), &alert_dialog_gtk, &dialogData);
295
		if(!dialogData.done){
296
			std::unique_lock<std::mutex> lock(dialogData.mutex);
297
			dialogData.condition.wait(lock);
298
		}
299
		resetLocale(locale);
300
	#endif
301

302
	#ifdef TARGET_ANDROID
303
		ofxAndroidAlertBox(errorMessage);
304
	#endif
305

306
	#ifdef TARGET_EMSCRIPTEN
307
		emscripten_run_script((std::string("alert(")+errorMessage+");").c_str());
308
	#endif
309
}
310

311
//----------------------------------------------------------------------------------------
312
#ifdef TARGET_WIN32
313
//---------------------------------------------------------------------
314
static int CALLBACK loadDialogBrowseCallback(
315
  HWND hwnd,
316
  UINT uMsg,
317
  LPARAM lParam,
318
  LPARAM lpData
319
){
320
    std::string defaultPath = *(std::string*)lpData;
321
    if(defaultPath!="" && uMsg==BFFM_INITIALIZED){
322
		wchar_t         wideCharacterBuffer[MAX_PATH];
323
		wcscpy(wideCharacterBuffer, convertNarrowToWide(ofToDataPath(defaultPath)).c_str());
324
        SendMessage(hwnd,BFFM_SETSELECTION,1,(LPARAM)wideCharacterBuffer);
325
    }
326

327
	return 0;
328
}
329
//----------------------------------------------------------------------------------------
330
#endif
331
//---------------------------------------------------------------------
332

333
// OS specific results here.  "" = cancel or something bad like can't load, can't save, etc...
334
ofFileDialogResult ofSystemLoadDialog(std::string windowTitle, bool bFolderSelection, std::string defaultPath){
335

336
	ofFileDialogResult results;
337

338
	//----------------------------------------------------------------------------------------
339
	//------------------------------------------------------------------------------       OSX
340
	//----------------------------------------------------------------------------------------
341
#ifdef TARGET_OSX
342
	@autoreleasepool {
343
		NSOpenGLContext *context = [NSOpenGLContext currentContext];
344

345
		NSOpenPanel * loadDialog = [NSOpenPanel openPanel];
346
		[loadDialog setAllowsMultipleSelection:NO];
347
		[loadDialog setCanChooseDirectories:bFolderSelection];
348
		[loadDialog setCanChooseFiles:!bFolderSelection];
349
		[loadDialog setResolvesAliases:YES];
350

351
		if(!windowTitle.empty()) {
352
			// changed from setTitle to setMessage
353
			// https://stackoverflow.com/questions/36879212/title-bar-missing-in-nsopenpanel
354
			[loadDialog setMessage:[NSString stringWithUTF8String:windowTitle.c_str()]];
355
		}
356

357
		if(!defaultPath.empty()) {
358
			NSString * s = [NSString stringWithUTF8String:defaultPath.c_str()];
359
			s = [[s stringByExpandingTildeInPath] stringByResolvingSymlinksInPath];
360
			NSURL * defaultPathUrl = [NSURL fileURLWithPath:s];
361
			[loadDialog setDirectoryURL:defaultPathUrl];
362
		}
363

364
		NSInteger buttonClicked = [loadDialog runModal];
365
		[context makeCurrentContext];
366
		restoreAppWindowFocus();
367

368
		if(buttonClicked == NSModalResponseOK) {
369
			NSURL * selectedFileURL = [[loadDialog URLs] objectAtIndex:0];
370
			results.filePath = std::string([[selectedFileURL path] UTF8String]);
371
		}
372
	}
373
#endif
374
	//----------------------------------------------------------------------------------------
375
	//----------------------------------------------------------------------------------------
376
	//----------------------------------------------------------------------------------------
377

378
	//----------------------------------------------------------------------------------------
379
	//------------------------------------------------------------------------------   windoze
380
	//----------------------------------------------------------------------------------------
381
#ifdef TARGET_WIN32
382
	std::wstring windowTitleW{windowTitle.begin(), windowTitle.end()};
383

384
	if (bFolderSelection == false){
385

386
        OPENFILENAME ofn;
387

388
		ZeroMemory(&ofn, sizeof(ofn));
389
		ofn.lStructSize = sizeof(ofn);
390
		HWND hwnd = WindowFromDC(wglGetCurrentDC());
391
		ofn.hwndOwner = hwnd;
392

393
		//the file name and path
394
		wchar_t szFileName[MAX_PATH];
395
		memset(szFileName, 0, sizeof(szFileName));
396

397
		//the dir, if specified
398
		wchar_t szDir[MAX_PATH];
399

400
		//the title if specified
401
		wchar_t szTitle[MAX_PATH];
402
		if(defaultPath!=""){
403
			wcscpy(szDir,convertNarrowToWide(ofToDataPath(defaultPath)).c_str());
404
			ofn.lpstrInitialDir = szDir;
405
		}
406

407
		if (windowTitle != "") {
408
			wcscpy(szTitle, convertNarrowToWide(windowTitle).c_str());
409
			ofn.lpstrTitle = szTitle;
410
		} else {
411
			ofn.lpstrTitle = nullptr;
412
		}
413

414
		ofn.lpstrFilter = L"All\0";
415
		ofn.lpstrFile = szFileName;
416
		ofn.nMaxFile = MAX_PATH;
417
		ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
418
		ofn.lpstrDefExt = 0;
419
		ofn.lpstrTitle = windowTitleW.c_str();
420

421
		if(GetOpenFileName(&ofn)) {
422
			results.filePath = convertWideToNarrow(szFileName);
423
		}
424
		else {
425
			//this should throw an error on failure unless its just the user canceling out
426
			//DWORD err = CommDlgExtendedError();
427
		}
428

429
	} else {
430

431
		BROWSEINFOW      bi;
432
		wchar_t         wideCharacterBuffer[MAX_PATH];
433
		wchar_t			wideWindowTitle[MAX_PATH];
434
		LPITEMIDLIST    pidl;
435
		LPMALLOC		lpMalloc;
436

437
		if (windowTitle != "") {
438
			wcscpy(wideWindowTitle, convertNarrowToWide(windowTitle).c_str());
439
		} else {
440
			wcscpy(wideWindowTitle, L"Select Directory");
441
		}
442

443
		// Get a pointer to the shell memory allocator
444
		if(SHGetMalloc(&lpMalloc) != S_OK){
445
			//TODO: deal with some sort of error here?
446
		}
447
		bi.hwndOwner        =   nullptr;
448
		bi.pidlRoot         =   nullptr;
449
		bi.pszDisplayName   =   wideCharacterBuffer;
450
		bi.lpszTitle        =   wideWindowTitle;
451
		bi.ulFlags          =   BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
452
		bi.lpfn             =   &loadDialogBrowseCallback;
453
		bi.lParam           =   (LPARAM) &defaultPath;
454
		bi.lpszTitle        =   windowTitleW.c_str();
455

456
		if( (pidl = SHBrowseForFolderW(&bi)) ){
457
			// Copy the path directory to the buffer
458
			if(SHGetPathFromIDListW(pidl,wideCharacterBuffer)){
459
				results.filePath = convertWideToNarrow(wideCharacterBuffer);
460
			}
461
			lpMalloc->Free(pidl);
462
		}
463
		lpMalloc->Release();
464
	}
465

466
	//----------------------------------------------------------------------------------------
467
	//------------------------------------------------------------------------------   windoze
468
	//----------------------------------------------------------------------------------------
469
#endif
470

471

472

473

474
	//----------------------------------------------------------------------------------------
475
	//------------------------------------------------------------------------------   linux
476
	//----------------------------------------------------------------------------------------
477
#if defined( TARGET_LINUX ) && defined (OF_USING_GTK)
478
		auto locale = std::locale();
479
		if(bFolderSelection)
480
			results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, windowTitle, ofToDataPath(defaultPath).c_str());
481
		else
482
			results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_OPEN, windowTitle, ofToDataPath(defaultPath).c_str());
483
		resetLocale(locale);
484
#endif
485
	//----------------------------------------------------------------------------------------
486
	//----------------------------------------------------------------------------------------
487
	//----------------------------------------------------------------------------------------
488

489

490

491
	if( results.filePath.length() > 0 ){
492
		results.bSuccess = true;
493
		results.fileName = ofFilePath::getFileName(results.filePath);
494
	}
495

496
	return results;
497
}
498

499

500

501
ofFileDialogResult ofSystemSaveDialog(std::string defaultName, std::string messageName){
502

503
	ofFileDialogResult results;
504

505
	//----------------------------------------------------------------------------------------
506
	//------------------------------------------------------------------------------       OSX
507
	//----------------------------------------------------------------------------------------
508
#ifdef TARGET_OSX
509
	@autoreleasepool {
510
		NSSavePanel * saveDialog = [NSSavePanel savePanel];
511
		NSOpenGLContext *context = [NSOpenGLContext currentContext];
512
		[saveDialog setMessage:[NSString stringWithUTF8String:messageName.c_str()]];
513
		[saveDialog setNameFieldStringValue:[NSString stringWithUTF8String:defaultName.c_str()]];
514

515
		NSInteger buttonClicked = [saveDialog runModal];
516
		restoreAppWindowFocus();
517
		[context makeCurrentContext];
518

519
		if(buttonClicked == NSModalResponseOK){
520
			results.filePath = std::string([[[saveDialog URL] path] UTF8String]);
521
		}
522
	}
523
#endif
524
	//----------------------------------------------------------------------------------------
525
	//----------------------------------------------------------------------------------------
526
	//----------------------------------------------------------------------------------------
527

528
	//----------------------------------------------------------------------------------------
529
	//------------------------------------------------------------------------------   windoze
530
	//----------------------------------------------------------------------------------------
531
#ifdef TARGET_WIN32
532

533

534
	wchar_t fileName[MAX_PATH] = L"";
535
	OPENFILENAMEW ofn;
536
    memset(&ofn, 0, sizeof(OPENFILENAME));
537
	ofn.lStructSize = sizeof(OPENFILENAME);
538
	HWND hwnd = WindowFromDC(wglGetCurrentDC());
539
	ofn.hwndOwner = hwnd;
540
	ofn.hInstance = GetModuleHandle(0);
541
	ofn.nMaxFileTitle = 31;
542
	ofn.lpstrFile = fileName;
543
	ofn.nMaxFile = MAX_PATH;
544
	ofn.lpstrFilter = L"All Files (*.*)\0*.*\0";
545
	ofn.lpstrDefExt = L"";	// we could do .rxml here?
546
	ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
547
	ofn.lpstrTitle = L"Select Output File";
548

549
	if (GetSaveFileNameW(&ofn)){
550
		results.filePath = convertWideToNarrow(fileName);
551
	}
552

553
#endif
554
	//----------------------------------------------------------------------------------------
555
	//----------------------------------------------------------------------------------------
556
	//----------------------------------------------------------------------------------------
557

558

559
	//----------------------------------------------------------------------------------------
560
	//------------------------------------------------------------------------------   linux
561
	//----------------------------------------------------------------------------------------
562
#if defined( TARGET_LINUX ) && defined (OF_USING_GTK)
563
	auto locale = std::locale();
564
	// results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_SAVE, messageName, ofToDataPath(defaultName).string());
565
	results.filePath = gtkFileDialog(GTK_FILE_CHOOSER_ACTION_SAVE, messageName, ofToDataPath(defaultName));
566
	resetLocale(locale);
567
#endif
568
	//----------------------------------------------------------------------------------------
569
	//----------------------------------------------------------------------------------------
570
	//----------------------------------------------------------------------------------------
571

572
	if( results.filePath.length() > 0 ){
573
		results.bSuccess = true;
574
		results.fileName = ofFilePath::getFileName(results.filePath);
575
	}
576

577
	return results;
578
}
579

580
#ifdef TARGET_WIN32
581
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
582
{
583
    //switch(msg)
584
    //{
585
    //    case WM_CLOSE:
586
    //        DestroyWindow(hwnd);
587
    //    break;
588
    //    case WM_DESTROY:
589
    //        PostQuitMessage(0);
590
    //    break;
591
    //    default:
592
            return DefWindowProc(hwnd, msg, wParam, lParam);
593
    //}
594
}
595
#endif
596

597

598
std::string ofSystemTextBoxDialog(std::string question, std::string text){
599
#if defined( TARGET_LINUX ) && defined (OF_USING_GTK)
600
	auto locale = std::locale();
601
	initGTK();
602
	TextDialogData dialogData;
603
	dialogData.text = text;
604
	dialogData.done = false;
605
	dialogData.question = question;
606
	g_main_context_invoke(g_main_loop_get_context(ofGstUtils::getGstMainLoop()), &text_dialog_gtk, &dialogData);
607
	if(!dialogData.done){
608
		std::unique_lock<std::mutex> lock(dialogData.mutex);
609
		dialogData.condition.wait(lock);
610
	}
611
	resetLocale(locale);
612
	text = dialogData.text;
613
#endif
614

615
#ifdef TARGET_OSX
616
	@autoreleasepool {
617
		// create alert dialog
618
		NSAlert *alert = [[NSAlert alloc] init];
619
		[alert addButtonWithTitle:@"OK"];
620
		[alert addButtonWithTitle:@"Cancel"];
621
		[alert setMessageText:[NSString stringWithCString:question.c_str()
622
												 encoding:NSUTF8StringEncoding]];
623
		// create text field
624
		NSTextField* label = [[NSTextField alloc] initWithFrame:NSRectFromCGRect(CGRectMake(0,0,300,40))];
625
		[label setStringValue:[NSString stringWithCString:text.c_str()
626
												 encoding:NSUTF8StringEncoding]];
627
		// add text field to alert dialog
628
		[alert setAccessoryView:label];
629
		[[alert window] setInitialFirstResponder: label];
630

631
		NSInteger returnCode = [alert runModal];
632
		restoreAppWindowFocus();
633
		// if OK was clicked, assign value to text
634
		if ( returnCode == NSAlertFirstButtonReturn )
635
			text = [[label stringValue] UTF8String];
636
    else
637
      text = "";
638
	}
639
#endif
640

641
#ifdef TARGET_WIN32
642
    // we need to convert error message to a wide char message.
643
    // first, figure out the length and allocate a wchar_t at that length + 1 (the +1 is for a terminating character)
644

645
	WNDCLASSEX wc;
646
	MSG Msg;
647

648
        #define TMP_STR_CONVERT LPCWSTR
649

650
		const LPCWSTR g_szClassName = L"myWindowClass\0";
651

652
		//Step 1: Registering the Window Class
653
		wc.cbSize        = sizeof(WNDCLASSEX);
654
		wc.style         = CS_HREDRAW | CS_VREDRAW;
655
		wc.lpfnWndProc   = WndProc;
656
		wc.cbClsExtra    = 0;
657
		wc.cbWndExtra    = 0;
658
		wc.hInstance     = GetModuleHandle(0);
659
		wc.lpszClassName = g_szClassName;
660
		wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
661
		wc.lpszMenuName  = nullptr;
662
		wc.hCursor       = LoadCursor(nullptr, IDC_ARROW);
663
		wc.hIcon         = LoadIcon(nullptr, IDI_APPLICATION);
664
		wc.hIconSm       = LoadIcon(nullptr, IDI_APPLICATION);
665
		if(!RegisterClassEx(&wc)){
666
			DWORD err=GetLastError();
667
			if ((err==ERROR_CLASS_ALREADY_EXISTS)){
668
                ; // we are ok
669
                // http://stackoverflow.com/questions/5791996/re-registering-user-defined-window-class-c
670
            } else {
671
			MessageBox(nullptr, L"Window Registration Failed!\0", L"Error!\0",
672
				MB_ICONEXCLAMATION | MB_OK);
673
			return text;
674
		}
675
		}
676

677
		HWND dialog = CreateWindowEx(WS_EX_DLGMODALFRAME,
678
			g_szClassName,
679
			convertNarrowToWide(question).c_str(),
680
			WS_POPUP | WS_CAPTION | DS_MODALFRAME | WS_SYSMENU,
681
			CW_USEDEFAULT, CW_USEDEFAULT, 240, 140,
682
			WindowFromDC(wglGetCurrentDC()), nullptr, GetModuleHandle(0),nullptr);
683

684
		if(dialog == nullptr)
685
		{
686

687
			MessageBox(nullptr,L"Window Creation Failed!\0", L"Error!\0",
688
				MB_ICONEXCLAMATION | MB_OK);
689
			return text;
690

691
		}
692

693
		EnableWindow(WindowFromDC(wglGetCurrentDC()), FALSE);
694
		HWND hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT\0", convertNarrowToWide(text).c_str(),
695
			WS_CHILD | WS_VISIBLE | WS_TABSTOP,
696
			10, 10, 210, 40, dialog, (HMENU)101, GetModuleHandle(nullptr), nullptr);
697

698

699
		HWND okButton = CreateWindowEx(WS_EX_CLIENTEDGE, L"BUTTON\0", L"OK\0",
700
			WS_CHILD | WS_VISIBLE | WS_TABSTOP,
701
			10, 60, 60, 30, dialog, (HMENU)IDOK, GetModuleHandle(nullptr), nullptr);
702

703
		HWND cancelButton = CreateWindowEx(WS_EX_CLIENTEDGE, L"BUTTON\0", L"Cancel\0",
704
			WS_CHILD | WS_VISIBLE,
705
			80, 60, 60, 30, dialog, (HMENU)IDCANCEL, GetModuleHandle(nullptr), nullptr);
706

707
		SetFocus( hEdit );
708

709
		ShowWindow(dialog, SW_SHOWNORMAL);
710
		bool bFirstEmpty = true;
711
		while (true){
712
			 if (!PeekMessageW( &Msg, 0, 0, 0, PM_REMOVE )){
713
				 if (bFirstEmpty){
714
					 // ShowWindow the first time the queue goes empty
715
					 ShowWindow( dialog, SW_SHOWNORMAL );
716
					 bFirstEmpty = FALSE;
717
				 }
718
				 if (!(GetWindowLongW( dialog, GWL_STYLE ) & DS_NOIDLEMSG)){
719
					 // No message present -> send ENTERIDLE and wait
720
					 SendMessageW( WindowFromDC(wglGetCurrentDC()), WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)dialog );
721
				 }
722
				 GetMessageW( &Msg, 0, 0, 0 );
723
			 }
724

725
			 if (Msg.message == WM_QUIT){
726
				 PostQuitMessage( Msg.wParam );
727
				 if (!IsWindow( dialog )){
728
					EnableWindow(WindowFromDC(wglGetCurrentDC()), TRUE);
729
					return text;
730
				 }
731
				 break;
732
			 }
733

734
			 if (!IsWindow( dialog )){
735
				EnableWindow(WindowFromDC(wglGetCurrentDC()), TRUE);
736
				return text;
737
			 }
738

739
			 TranslateMessage( &Msg );
740
			 DispatchMessageW( &Msg );
741

742
			 if((Msg.hwnd == okButton && Msg.message==WM_LBUTTONUP) || (Msg.message==WM_KEYUP && Msg.wParam==13)){
743
				 break;
744
			 }else if((Msg.hwnd == cancelButton && Msg.message==WM_LBUTTONUP) ||  (Msg.message==WM_KEYUP && Msg.wParam==27)){
745
				 EnableWindow(WindowFromDC(wglGetCurrentDC()), TRUE);
746
				 DestroyWindow(dialog);
747
				 return "";
748
			 }
749

750
			 if (!IsWindow( dialog )){
751
				EnableWindow(WindowFromDC(wglGetCurrentDC()), TRUE);
752
				return text;
753
			 }
754

755
			 if (bFirstEmpty && Msg.message == WM_TIMER){
756
				 ShowWindow( dialog, SW_SHOWNORMAL );
757
				 bFirstEmpty = FALSE;
758
			 }
759
		 }
760

761
		 char buf[16384];
762
		 GetDlgItemTextA( dialog, 101, buf, 16384 );
763
		 text = buf;
764

765
		 DestroyWindow(dialog);
766
		 EnableWindow(WindowFromDC(wglGetCurrentDC()), TRUE);
767

768
#endif
769

770
#ifdef TARGET_ANDROID
771
     ofxAndroidAlertTextBox(question,text);
772
#endif
773

774
#ifdef TARGET_EMSCRIPTEN
775
     text = emscripten_run_script_string((std::string("prompt('") + question + "','')").c_str());
776
#endif
777
	return text;
778
}
779

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.