@@ -40,10 +40,21 @@ define(function (require, exports, module) {
40
40
PreferencesManager = require ( "preferences/PreferencesManager" ) ,
41
41
StatusBar = require ( "widgets/StatusBar" ) ,
42
42
Strings = require ( "strings" ) ,
43
+ FileUtils = require ( "file/FileUtils" ) ,
44
+ InMemoryFile = require ( "document/InMemoryFile" ) ,
45
+ Dialogs = require ( "widgets/Dialogs" ) ,
46
+ DefaultDialogs = require ( "widgets/DefaultDialogs" ) ,
47
+ ProjectManager = require ( "project/ProjectManager" ) ,
48
+ Async = require ( "utils/Async" ) ,
49
+ FileSystem = require ( "filesystem/FileSystem" ) ,
43
50
StringUtils = require ( "utils/StringUtils" ) ;
51
+
52
+ var SupportedEncodingsText = require ( "text!supported-encodings.json" ) ,
53
+ SupportedEncodings = JSON . parse ( SupportedEncodingsText ) ;
44
54
45
55
/* StatusBar indicators */
46
56
var languageSelect , // this is a DropdownButton instance
57
+ encodingSelect , // this is a DropdownButton instance
47
58
$cursorInfo ,
48
59
$fileInfo ,
49
60
$indentType ,
@@ -74,12 +85,24 @@ define(function (require, exports, module) {
74
85
var doc = editor . document ,
75
86
lang = doc . getLanguage ( ) ;
76
87
77
- // Ensure width isn't left locked by a previous click of the dropdown (which may not have resulted in a "change" event at the time)
78
- languageSelect . $button . css ( "width" , "auto" ) ;
79
88
// Show the current language as button title
80
89
languageSelect . $button . text ( lang . getName ( ) ) ;
81
90
}
82
91
92
+ /**
93
+ * Update encoding
94
+ * @param {Editor } editor Current editor
95
+ */
96
+ function _updateEncodingInfo ( editor ) {
97
+ var doc = editor . document ;
98
+
99
+ // Show the current encoding as button title
100
+ if ( ! doc . file . _encoding ) {
101
+ doc . file . _encoding = "UTF-8" ;
102
+ }
103
+ encodingSelect . $button . text ( doc . file . _encoding ) ;
104
+ }
105
+
83
106
/**
84
107
* Update file information
85
108
* @param {Editor } editor Current editor
@@ -277,6 +300,7 @@ define(function (require, exports, module) {
277
300
278
301
_updateCursorInfo ( null , current ) ;
279
302
_updateLanguageInfo ( current ) ;
303
+ _updateEncodingInfo ( current ) ;
280
304
_updateFileInfo ( current ) ;
281
305
_initOverwriteMode ( current ) ;
282
306
_updateIndentType ( fullPath ) ;
@@ -305,6 +329,40 @@ define(function (require, exports, module) {
305
329
languageSelect . items . unshift ( LANGUAGE_SET_AS_DEFAULT ) ;
306
330
}
307
331
332
+ /**
333
+ * Change the encoding and reload the current document.
334
+ * If passed then save the preferred encoding in state.
335
+ */
336
+ function _changeEncodingAndReloadDoc ( document ) {
337
+ var promise = document . reload ( ) ;
338
+ promise . done ( function ( text , readTimestamp ) {
339
+ encodingSelect . $button . text ( document . file . _encoding ) ;
340
+ // Store the preferred encoding in the state
341
+ var projectRoot = ProjectManager . getProjectRoot ( ) ,
342
+ context = {
343
+ location : {
344
+ scope : "user" ,
345
+ layer : "project" ,
346
+ layerID : projectRoot . fullPath
347
+ }
348
+ } ;
349
+ var encoding = PreferencesManager . getViewState ( "encoding" , context ) ;
350
+ encoding [ document . file . fullPath ] = document . file . _encoding ;
351
+ PreferencesManager . setViewState ( "encoding" , encoding , context ) ;
352
+ } ) ;
353
+ promise . fail ( function ( error ) {
354
+ console . log ( "Error reloading contents of " + document . file . fullPath , error ) ;
355
+ } ) ;
356
+ }
357
+
358
+
359
+ /**
360
+ * Populate the encodingSelect DropdownButton's menu with all registered encodings
361
+ */
362
+ function _populateEncodingDropdown ( ) {
363
+ encodingSelect . items = SupportedEncodings ;
364
+ }
365
+
308
366
/**
309
367
* Initialize
310
368
*/
@@ -343,6 +401,27 @@ define(function (require, exports, module) {
343
401
$ ( "#status-language" ) . append ( languageSelect . $button ) ;
344
402
languageSelect . $button . attr ( "title" , Strings . STATUSBAR_LANG_TOOLTIP ) ;
345
403
404
+
405
+ encodingSelect = new DropdownButton ( "" , [ ] , function ( item , index ) {
406
+ var document = EditorManager . getActiveEditor ( ) . document ;
407
+ var html = _ . escape ( item ) ;
408
+
409
+ // Show indicators for currently selected & default languages for the current file
410
+ if ( item === "UTF-8" ) {
411
+ html += " <span class='default-language'>" + Strings . STATUSBAR_DEFAULT_LANG + "</span>" ;
412
+ }
413
+ if ( item === document . file . _encoding ) {
414
+ html = "<span class='checked-language'></span>" + html ;
415
+ }
416
+ return html ;
417
+ } ) ;
418
+
419
+ encodingSelect . dropdownExtraClasses = "dropdown-status-bar" ;
420
+ encodingSelect . $button . addClass ( "btn-status-bar" ) ;
421
+ $ ( "#status-encoding" ) . append ( encodingSelect . $button ) ;
422
+ encodingSelect . $button . attr ( "title" , Strings . STATUSBAR_ENCODING_TOOLTIP ) ;
423
+
424
+
346
425
// indentation event handlers
347
426
$indentType . on ( "click" , _toggleIndentType ) ;
348
427
$indentWidthLabel
@@ -389,16 +468,96 @@ define(function (require, exports, module) {
389
468
}
390
469
} ) ;
391
470
471
+ // Encoding select change handler
472
+ encodingSelect . on ( "select" , function ( e , encoding ) {
473
+ var document = EditorManager . getActiveEditor ( ) . document ,
474
+ fullPath = document . file . fullPath ;
475
+
476
+ document . file . _encoding = encoding ;
477
+
478
+
479
+ if ( ! ( document . file instanceof InMemoryFile ) && document . isDirty ) {
480
+ var dialogId = DefaultDialogs . DIALOG_ID_EXT_CHANGED ,
481
+ message = StringUtils . format (
482
+ Strings . DIRTY_FILE_ENCODING_CHANGE_WARN ,
483
+ StringUtils . breakableUrl (
484
+ ProjectManager . makeProjectRelativeIfPossible ( document . file . fullPath )
485
+ )
486
+ ) ,
487
+ buttons = [
488
+ {
489
+ className : Dialogs . DIALOG_BTN_CLASS_LEFT ,
490
+ id : Dialogs . DIALOG_BTN_DONTSAVE ,
491
+ text : Strings . IGNORE_RELOAD_FROM_DISK
492
+ } ,
493
+ {
494
+ className : Dialogs . DIALOG_BTN_CLASS_PRIMARY ,
495
+ id : Dialogs . DIALOG_BTN_CANCEL ,
496
+ text : Strings . CANCEL
497
+ }
498
+ ] ;
499
+
500
+ Dialogs . showModalDialog ( dialogId , Strings . SAVE_FILE_ENCODING_CHANGE_WARN , message , buttons )
501
+ . done ( function ( id ) {
502
+ if ( id === Dialogs . DIALOG_BTN_DONTSAVE ) {
503
+ _changeEncodingAndReloadDoc ( document ) ;
504
+ }
505
+ } ) ;
506
+ } else if ( document . file instanceof InMemoryFile ) {
507
+ encodingSelect . $button . text ( encoding ) ;
508
+ } else if ( ! document . isDirty ) {
509
+ _changeEncodingAndReloadDoc ( document ) ;
510
+ }
511
+ } ) ;
512
+
392
513
$statusOverwrite . on ( "click" , _updateEditorOverwriteMode ) ;
393
514
}
394
515
395
516
// Initialize: status bar focused listener
396
517
EditorManager . on ( "activeEditorChange" , _onActiveEditorChange ) ;
397
518
519
+ function _checkFileExistance ( filePath , index , encoding ) {
520
+ var deferred = new $ . Deferred ( ) ,
521
+ fileEntry = FileSystem . getFileForPath ( filePath ) ;
522
+
523
+ fileEntry . exists ( function ( err , exists ) {
524
+ if ( ! err && exists ) {
525
+ deferred . resolve ( ) ;
526
+ } else {
527
+ delete encoding [ filePath ] ;
528
+ deferred . reject ( ) ;
529
+ }
530
+ } ) ;
531
+
532
+ return deferred . promise ( ) ;
533
+ }
534
+
535
+ ProjectManager . on ( "projectOpen" , function ( ) {
536
+ var projectRoot = ProjectManager . getProjectRoot ( ) ,
537
+ context = {
538
+ location : {
539
+ scope : "user" ,
540
+ layer : "project" ,
541
+ layerID : projectRoot . fullPath
542
+ }
543
+ } ;
544
+ var encoding = PreferencesManager . getViewState ( "encoding" , context ) ;
545
+ if ( ! encoding ) {
546
+ PreferencesManager . setViewState ( "encoding" , { } , context ) ;
547
+ }
548
+ Async . doSequentially ( Object . keys ( encoding ) , function ( filePath , index ) {
549
+ return _checkFileExistance ( filePath , index , encoding ) ;
550
+ } , false )
551
+ . always ( function ( ) {
552
+ PreferencesManager . setViewState ( "encoding" , encoding , context ) ;
553
+ } ) ;
554
+ } ) ;
555
+
398
556
AppInit . htmlReady ( _init ) ;
399
557
AppInit . appReady ( function ( ) {
400
558
// Populate language switcher with all languages after startup; update it later if this set changes
401
559
_populateLanguageDropdown ( ) ;
560
+ _populateEncodingDropdown ( ) ;
402
561
LanguageManager . on ( "languageAdded languageModified" , _populateLanguageDropdown ) ;
403
562
_onActiveEditorChange ( null , EditorManager . getActiveEditor ( ) , null ) ;
404
563
StatusBar . show ( ) ;
0 commit comments