diff --git a/Src/xWorks/XhtmlDocView.cs b/Src/xWorks/XhtmlDocView.cs
index db86a52338..f3c1b8848e 100644
--- a/Src/xWorks/XhtmlDocView.cs
+++ b/Src/xWorks/XhtmlDocView.cs
@@ -1123,8 +1123,7 @@ public void OnPropertyChanged(string name)
switch (name)
{
case "SelectedPublication":
- var validConfiguration = SetCurrentDictionaryPublicationLayout();
- UpdateContent(validConfiguration);
+ ShowSelectedPublication();
break;
case "DictionaryPublicationLayout":
case "ReversalIndexPublicationLayout":
@@ -1422,15 +1421,39 @@ private void RefreshAllContent(object _)
// The Configure dialog sets the layout silently, so sync the guid.
SyncReversalIndexGuidToConfiguration();
}
+ // Force a refresh.
+ m_loadedConfig = null;
+ ShowConfiguration(currentConfig);
+ }
+
+ ///
+ /// Loads a configuration. When it excludes the selected publication, the publication
+ /// first moves, without broadcasting, to one the configuration includes, or to All
+ /// Entries when it includes none, and the load is then of the configuration valid for
+ /// that publication. All Entries never moves.
+ ///
+ internal void ShowConfiguration(string configuration)
+ {
var currentPublication = GetCurrentPublication();
- var validPublication = GetValidPublicationForConfiguration(currentConfig) ?? xWorksStrings.AllEntriesPublication;
+ var validPublication = GetValidPublicationForConfiguration(configuration) ?? xWorksStrings.AllEntriesPublication;
if (currentPublication != xWorksStrings.AllEntriesPublication && currentPublication != validPublication)
{
- m_propertyTable.SetProperty("SelectedPublication", validPublication, true);
+ m_propertyTable.SetProperty("SelectedPublication", validPublication, false);
+ ShowSelectedPublication();
}
- // Force a refresh.
- m_loadedConfig = null;
- UpdateContent(currentConfig);
+ else
+ {
+ UpdateContent(configuration);
+ }
+ }
+
+ ///
+ /// Stores the configuration valid for the selected publication, without broadcasting,
+ /// and loads it.
+ ///
+ private void ShowSelectedPublication()
+ {
+ UpdateContent(SetCurrentDictionaryPublicationLayout());
}
public bool RefreshDisplay()
@@ -1603,13 +1626,20 @@ public virtual bool OnDisplayFindAndReplaceText(object commandObject, ref UIItem
return true; //we've handled this
}
+ ///
+ /// Mediator handler for the Show All Entries command: selects All Entries and shows it.
+ /// Choosing it again changes nothing.
+ ///
public bool OnShowAllEntries(object args)
{
- m_propertyTable.SetProperty("SelectedPublication", xWorksStrings.AllEntriesPublication, true);
+ if (GetCurrentPublication() == xWorksStrings.AllEntriesPublication)
+ return true;
+ m_propertyTable.SetProperty("SelectedPublication", xWorksStrings.AllEntriesPublication, false);
+ ShowSelectedPublication();
return true;
}
- private void UpdateContent(string configurationFile, bool allOnOnePage = false)
+ protected virtual void UpdateContent(string configurationFile, bool allOnOnePage = false)
{
SetInfoBarText();
var htmlErrorMessage = xWorksStrings.ksErrorDisplayingPublication;
diff --git a/Src/xWorks/xWorksTests/XhtmlDocViewTests.cs b/Src/xWorks/xWorksTests/XhtmlDocViewTests.cs
index 2019234ac0..69802c06e4 100644
--- a/Src/xWorks/xWorksTests/XhtmlDocViewTests.cs
+++ b/Src/xWorks/xWorksTests/XhtmlDocViewTests.cs
@@ -655,8 +655,185 @@ public void SilentLayoutChange_SyncingGuidThenValidating_KeepsTheChosenConfigura
#endregion
+ #region Direct publication selection
+
+ [Test]
+ public void OnShowAllEntries_SelectsAllEntriesAndLoadsTheCurrentConfigurationOnce()
+ {
+ using (new UndoableUnitOfWorkHelper(Cache.ActionHandlerAccessor, "doit", "undoit"))
+ {
+ CreatePublication("TestPub");
+ using (var scenario = new PublicationScenario(Cache, "TestPub", "TestPub"))
+ {
+ // SUT
+ scenario.View.OnShowAllEntries(null);
+
+ Assert.That(scenario.SelectedPublication, Is.EqualTo(xWorksStrings.AllEntriesPublication));
+ Assert.That(scenario.View.LoadedConfigurations, Is.EqualTo(new[] { scenario.ConfigurationPath }));
+ Assert.That(scenario.Mediator.JobItems, Is.Zero, "the publication must change without a broadcast");
+ }
+ }
+ }
+
+ [Test]
+ public void OnShowAllEntries_WhenAllEntriesIsSelected_LoadsNothing()
+ {
+ using (new UndoableUnitOfWorkHelper(Cache.ActionHandlerAccessor, "doit", "undoit"))
+ {
+ CreatePublication("TestPub");
+ using (var scenario = new PublicationScenario(Cache, "TestPub", xWorksStrings.AllEntriesPublication))
+ {
+ // SUT
+ scenario.View.OnShowAllEntries(null);
+
+ Assert.That(scenario.View.LoadedConfigurations, Is.Empty);
+ Assert.That(scenario.Mediator.JobItems, Is.Zero);
+ }
+ }
+ }
+
+ [Test]
+ public void ShowConfiguration_ExcludedPublicationSelected_MovesToAnIncludedOneAndLoadsOnce()
+ {
+ using (new UndoableUnitOfWorkHelper(Cache.ActionHandlerAccessor, "doit", "undoit"))
+ {
+ CreatePublication("TestPub");
+ CreatePublication("OtherPub");
+ using (var scenario = new PublicationScenario(Cache, "TestPub", "OtherPub"))
+ {
+ // SUT
+ scenario.View.ShowConfiguration(scenario.ConfigurationPath);
+
+ Assert.That(scenario.SelectedPublication, Is.EqualTo("TestPub"));
+ Assert.That(scenario.View.LoadedConfigurations, Is.EqualTo(new[] { scenario.ConfigurationPath }),
+ "one load, of the configuration valid for the publication moved to");
+ Assert.That(scenario.Mediator.JobItems, Is.Zero, "the publication must change without a broadcast");
+ }
+ }
+ }
+
+ [Test]
+ public void ShowConfiguration_ValidConfigurationIsAnotherFile_LoadsOnlyTheValidOne()
+ {
+ using (new UndoableUnitOfWorkHelper(Cache.ActionHandlerAccessor, "doit", "undoit"))
+ {
+ CreatePublication("TestPub");
+ CreatePublication("OtherPub");
+ using (var scenario = new PublicationScenario(Cache, "TestPub", "OtherPub"))
+ using (var outsideConfig = TempFile.WithFilename(Path.Combine(Path.GetTempPath(),
+ "OutsideTheProject" + DictionaryConfigurationModel.FileExtension)))
+ {
+ // Outside the project folder, so the publication's valid configuration is the
+ // project one, not this file
+ File.WriteAllText(outsideConfig.Path, ConfigurationTemplate.Replace("",
+ "TestPub"));
+ scenario.PropertyTable.SetProperty("DictionaryPublicationLayout", outsideConfig.Path, false);
+
+ // SUT
+ scenario.View.ShowConfiguration(outsideConfig.Path);
+
+ Assert.That(scenario.SelectedPublication, Is.EqualTo("TestPub"));
+ Assert.That(scenario.View.LoadedConfigurations, Is.EqualTo(new[] { scenario.ConfigurationPath }),
+ "the configuration passed in must not be loaded when the publication moved");
+ Assert.That(scenario.PropertyTable.GetStringProperty("DictionaryPublicationLayout", null),
+ Is.EqualTo(scenario.ConfigurationPath));
+ }
+ }
+ }
+
+ [Test]
+ public void ShowConfiguration_AllEntriesSelected_KeepsAllEntriesAndLoadsOnce()
+ {
+ using (new UndoableUnitOfWorkHelper(Cache.ActionHandlerAccessor, "doit", "undoit"))
+ {
+ CreatePublication("TestPub");
+ using (var scenario = new PublicationScenario(Cache, "TestPub", xWorksStrings.AllEntriesPublication))
+ {
+ // SUT
+ scenario.View.ShowConfiguration(scenario.ConfigurationPath);
+
+ Assert.That(scenario.SelectedPublication, Is.EqualTo(xWorksStrings.AllEntriesPublication));
+ Assert.That(scenario.View.LoadedConfigurations, Is.EqualTo(new[] { scenario.ConfigurationPath }));
+ }
+ }
+ }
+
+ private void CreatePublication(string name)
+ {
+ var publication = Cache.ServiceLocator.GetInstance().Create();
+ var enId = Cache.WritingSystemFactory.GetWsFromStr("en");
+ Cache.LangProject.LexDbOA.PublicationTypesOA.PossibilitiesOS.Add(publication);
+ publication.Name.set_String(enId, TsStringUtils.MakeString(name, enId));
+ }
+
+ ///
+ /// A colleague registered so the Mediator queues broadcasts: with no colleague it
+ /// discards them before queueing, and the job count would prove nothing.
+ ///
+ private sealed class ListeningColleague : IxCoreColleague
+ {
+ public void Init(Mediator mediator, PropertyTable propertyTable, XmlNode configurationParameters) { }
+ public IxCoreColleague[] GetMessageTargets() => new IxCoreColleague[] { this };
+ public bool ShouldNotCall => false;
+ public int Priority => (int)ColleaguePriority.High;
+ }
+
+ ///
+ /// A Dictionary-tool view on its own Mediator and PropertyTable, whose current
+ /// configuration is a user configuration listing only the publication named at
+ /// creation. Disposing it removes that configuration file.
+ ///
+ private sealed class PublicationScenario : IDisposable
+ {
+ public Mediator Mediator { get; }
+ public PropertyTable PropertyTable { get; }
+ public TestXhtmlDocView View { get; }
+ public string ConfigurationPath => m_configuration.Path;
+ public string SelectedPublication => PropertyTable.GetStringProperty("SelectedPublication", null);
+ private readonly TempFile m_configuration;
+
+ public PublicationScenario(LcmCache cache, string publicationInConfiguration, string selectedPublication)
+ {
+ Mediator = new Mediator();
+ Mediator.AddColleague(new ListeningColleague());
+ PropertyTable = new PropertyTable(Mediator);
+ PropertyTable.SetProperty("cache", cache, false);
+ var configDirectory = Path.Combine(LcmFileHelper.GetConfigSettingsDir(cache.ProjectId.ProjectFolder), "Dictionary");
+ Directory.CreateDirectory(configDirectory);
+ m_configuration = TempFile.WithFilename(Path.Combine(configDirectory,
+ "OnlyOnePublication" + DictionaryConfigurationModel.FileExtension));
+ File.WriteAllText(m_configuration.Path, ConfigurationTemplate.Replace("",
+ "" + publicationInConfiguration + ""));
+ PropertyTable.SetProperty("currentContentControl", "lexiconDictionary", false);
+ PropertyTable.SetProperty("DictionaryPublicationLayout", m_configuration.Path, false);
+ PropertyTable.SetProperty("SelectedPublication", selectedPublication, false);
+ View = new TestXhtmlDocView();
+ View.SetConfigObjectName("Dictionary");
+ View.SetMediator(Mediator);
+ View.SetPropertyTable(PropertyTable);
+ }
+
+ public void Dispose()
+ {
+ View.Dispose();
+ m_configuration.Dispose();
+ PropertyTable.Dispose();
+ Mediator.Dispose();
+ }
+ }
+
+ #endregion
+
private class TestXhtmlDocView : XhtmlDocView
{
+ /// The configurations handed to UpdateContent, in call order.
+ internal readonly List LoadedConfigurations = new List();
+
+ protected override void UpdateContent(string configurationFile, bool allOnOnePage = false)
+ {
+ LoadedConfigurations.Add(configurationFile);
+ }
+
internal void SetConfigObjectName(string name)
{
m_configObjectName = name;