@@ -40,6 +40,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
4040 INITIALIZE_BINDABLE_ENUM_SETTING_REVERSE_ORDER (CloseOnExitMode, CloseOnExitMode, winrt::Microsoft::Terminal::Settings::Model::CloseOnExitMode, L" Profile_CloseOnExit" , L" Content" );
4141 INITIALIZE_BINDABLE_ENUM_SETTING (ScrollState, ScrollbarState, winrt::Microsoft::Terminal::Control::ScrollbarState, L" Profile_ScrollbarVisibility" , L" Content" );
4242
43+ _InitializeCurrentBellSounds ();
44+
4345 // Add a property changed handler to our own property changed event.
4446 // This propagates changes from the settings model to anybody listening to our
4547 // unique view model members.
@@ -76,6 +78,21 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
7678 {
7779 _NotifyChanges (L" HideIcon" );
7880 }
81+ else if (viewModelProperty == L" CurrentBellSounds" )
82+ {
83+ // we already have infrastructure in place to
84+ // propagate changes from the CurrentBellSounds
85+ // to the model. Refer to...
86+ // - _InitializeCurrentBellSounds() --> _CurrentBellSounds.VectorChanged()
87+ // - RequestAddBellSound()
88+ // - RequestDeleteBellSound()
89+
90+ _NotifyChanges (L" BellSoundPreview" , L" HasBellSound" );
91+ }
92+ else if (viewModelProperty == L" BellSound" )
93+ {
94+ _InitializeCurrentBellSounds ();
95+ }
7996 });
8097
8198 // Do the same for the starting directory
@@ -374,6 +391,145 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
374391 BellStyle (currentStyle);
375392 }
376393
394+ // Method Description:
395+ // - Construct _CurrentBellSounds by importing the _inherited_ value from the model
396+ // - Adds a PropertyChanged handler to each BellSoundViewModel to propagate changes to the model
397+ void ProfileViewModel::_InitializeCurrentBellSounds ()
398+ {
399+ _CurrentBellSounds = winrt::single_threaded_observable_vector<Editor::BellSoundViewModel>();
400+ if (const auto soundList = _profile.BellSound ())
401+ {
402+ for (const auto && bellSound : soundList)
403+ {
404+ auto vm = winrt::make<BellSoundViewModel>(bellSound);
405+ vm.PropertyChanged ({ this , &ProfileViewModel::_BellSoundVMPropertyChanged });
406+ _CurrentBellSounds.Append (vm);
407+ }
408+ }
409+ _CurrentBellSounds.VectorChanged ([this ](auto &&, const IVectorChangedEventArgs& args) {
410+ switch (args.CollectionChange ())
411+ {
412+ case CollectionChange::ItemInserted:
413+ {
414+ const auto index = args.Index ();
415+ const auto & newSound = _CurrentBellSounds.GetAt (index);
416+
417+ if (!_profile.BellSound ())
418+ {
419+ _profile.BellSound (winrt::single_threaded_vector<winrt::hstring>());
420+ }
421+ _profile.BellSound ().InsertAt (index, newSound.Path ());
422+ break ;
423+ }
424+ case CollectionChange::ItemRemoved:
425+ {
426+ _profile.BellSound ().RemoveAt (args.Index ());
427+ break ;
428+ }
429+ case CollectionChange::ItemChanged:
430+ {
431+ // I've never been able to get this one to hit,
432+ // but if it ever does, propagate change to model
433+ const auto index = args.Index ();
434+ const auto & newSound = _CurrentBellSounds.GetAt (index);
435+ _profile.BellSound ().SetAt (index, newSound.Path ());
436+ break ;
437+ }
438+ case CollectionChange::Reset:
439+ default :
440+ {
441+ // propagate changes to model
442+ auto list = winrt::single_threaded_vector<winrt::hstring>();
443+ for (const auto & sound : _CurrentBellSounds)
444+ {
445+ list.Append (sound.Path ());
446+ }
447+ _profile.BellSound (list);
448+ break ;
449+ }
450+ }
451+ });
452+ _NotifyChanges (L" CurrentBellSounds" );
453+ }
454+
455+ // Method Description:
456+ // - If the current layer is inheriting the bell sound from its parent,
457+ // we need to copy the _inherited_ bell sound list to the current layer
458+ // so that we can then apply modifications to it
459+ void ProfileViewModel::_PrepareModelForBellSoundModification ()
460+ {
461+ if (const auto inheritedSounds = _profile.BellSound (); !_profile.HasBellSound () && inheritedSounds)
462+ {
463+ auto newSounds{ winrt::single_threaded_vector<winrt::hstring>() };
464+ for (const auto sound : inheritedSounds)
465+ {
466+ newSounds.Append (sound);
467+ }
468+ _profile.BellSound (newSounds);
469+ }
470+ }
471+
472+ hstring ProfileViewModel::BellSoundPreview ()
473+ {
474+ const auto & currentSound = BellSound ();
475+ if (!currentSound || currentSound.Size () == 0 )
476+ {
477+ return RS_ (L" Profile_BellSoundPreviewDefault" );
478+ }
479+ else if (currentSound.Size () == 1 )
480+ {
481+ std::filesystem::path filePath{ std::wstring_view{ currentSound.GetAt (0 ) } };
482+ return hstring{ filePath.filename ().wstring () };
483+ }
484+ return RS_ (L" Profile_BellSoundPreviewMultiple" );
485+ }
486+
487+ void ProfileViewModel::_BellSoundVMPropertyChanged (const IInspectable& sender, const PropertyChangedEventArgs& args)
488+ {
489+ if (args.PropertyName () == L" Path" )
490+ {
491+ auto senderVM = sender.as <Editor::BellSoundViewModel>();
492+
493+ // propagate changes to model
494+ uint32_t index;
495+ if (_CurrentBellSounds.IndexOf (senderVM, index))
496+ {
497+ // if current layer is inheriting,
498+ // we should copy the bell sound then apply changes
499+ _PrepareModelForBellSoundModification ();
500+
501+ _profile.BellSound ().SetAt (index, senderVM.Path ());
502+ _NotifyChanges (L" CurrentBellSounds" );
503+ }
504+ }
505+ }
506+
507+ void ProfileViewModel::RequestAddBellSound ()
508+ {
509+ // If we were inheriting our bell sound,
510+ // copy it over to the current layer and apply modifications
511+ _PrepareModelForBellSoundModification ();
512+
513+ auto vm = winrt::make<BellSoundViewModel>();
514+ vm.PropertyChanged ({ this , &ProfileViewModel::_BellSoundVMPropertyChanged });
515+ _CurrentBellSounds.Append (vm);
516+ _NotifyChanges (L" CurrentBellSounds" );
517+ }
518+
519+ void ProfileViewModel::RequestDeleteBellSound (const Editor::BellSoundViewModel& vm)
520+ {
521+ uint32_t index;
522+ if (_CurrentBellSounds.IndexOf (vm, index))
523+ {
524+ // If we were inheriting our bell sound,
525+ // copy it over to the current layer and apply modifications
526+ _PrepareModelForBellSoundModification ();
527+
528+ _CurrentBellSounds.RemoveAt (index);
529+ _NotifyChanges (L" CurrentBellSounds" );
530+ }
531+ }
532+
377533 void ProfileViewModel::DeleteProfile ()
378534 {
379535 auto deleteProfileArgs{ winrt::make_self<DeleteProfileEventArgs>(Guid ()) };
0 commit comments