You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
CrowdControl/Assets/3rd/StompyRobot/SRDebugger/Scripts/Services/Implementation/OptionsServiceImpl.cs

186 lines
6.0 KiB
C#

namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Internal;
using SRF.Service;
using SRF.Helpers;
using UnityEngine;
[Service(typeof (IOptionsService))]
public partial class OptionsServiceImpl : IOptionsService
{
public event EventHandler OptionsUpdated;
public ICollection<OptionDefinition> Options
{
get { return _optionsReadonly; }
}
private void OptionsContainerOnOptionAdded(IOptionContainer container, OptionDefinition optionDefinition)
{
List<OptionDefinition> options;
if(!_optionContainerLookup.TryGetValue(container, out options))
{
Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
return;
}
if (options.Contains(optionDefinition))
{
Debug.LogWarning("[SRDebugger] Received option added event from option container, but option has already been added.");
return;
}
options.Add(optionDefinition);
_options.Add(optionDefinition);
OnOptionsUpdated();
}
private void OptionsContainerOnOptionRemoved(IOptionContainer container, OptionDefinition optionDefinition)
{
List<OptionDefinition> options;
if (!_optionContainerLookup.TryGetValue(container, out options))
{
Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
return;
}
if (options.Remove(optionDefinition))
{
_options.Remove(optionDefinition);
OnOptionsUpdated();
}
else
{
Debug.LogWarning("[SRDebugger] Received option removed event from option container, but option does not exist.");
}
}
private readonly Dictionary<IOptionContainer, List<OptionDefinition>> _optionContainerLookup = new Dictionary<IOptionContainer, List<OptionDefinition>>();
private readonly Dictionary<IOptionContainer, OptionContainerEventHandler> _optionContainerEventHandlerLookup = new Dictionary<IOptionContainer, OptionContainerEventHandler>();
private readonly List<OptionDefinition> _options = new List<OptionDefinition>();
private readonly IList<OptionDefinition> _optionsReadonly;
public OptionsServiceImpl()
{
_optionsReadonly = new ReadOnlyCollection<OptionDefinition>(_options);
}
public void Scan(object obj)
{
AddContainer(obj);
}
public void AddContainer(object obj)
{
var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
AddContainer(container);
}
public void AddContainer(IOptionContainer optionContainer)
{
if (_optionContainerLookup.ContainsKey(optionContainer))
{
throw new Exception("An options container should only be added once.");
}
List<OptionDefinition> options = new List<OptionDefinition>();
options.AddRange(optionContainer.GetOptions());
_optionContainerLookup.Add(optionContainer, options);
if (optionContainer.IsDynamic)
{
var handler = new OptionContainerEventHandler(this, optionContainer);
_optionContainerEventHandlerLookup.Add(optionContainer, handler);
}
if (options.Count > 0)
{
_options.AddRange(options);
OnOptionsUpdated();
}
}
public void RemoveContainer(object obj)
{
var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
RemoveContainer(container);
}
public void RemoveContainer(IOptionContainer optionContainer)
{
if (!_optionContainerLookup.ContainsKey(optionContainer))
{
return;
}
bool isDirty = false;
var list = _optionContainerLookup[optionContainer];
_optionContainerLookup.Remove(optionContainer);
foreach (var op in list)
{
_options.Remove(op);
isDirty = true;
}
OptionContainerEventHandler handler;
if (_optionContainerEventHandlerLookup.TryGetValue(optionContainer,
out handler))
{
handler.Dispose();
_optionContainerEventHandlerLookup.Remove(optionContainer);
}
if (isDirty)
{
OnOptionsUpdated();
}
}
private void OnOptionsUpdated()
{
if (OptionsUpdated != null)
{
OptionsUpdated(this, EventArgs.Empty);
}
}
class OptionContainerEventHandler : IDisposable
{
private readonly OptionsServiceImpl _service;
private readonly IOptionContainer _container;
public OptionContainerEventHandler(OptionsServiceImpl service, IOptionContainer container)
{
_container = container;
_service = service;
container.OptionAdded += ContainerOnOptionAdded;
container.OptionRemoved += ContainerOnOptionRemoved;
}
private void ContainerOnOptionAdded(OptionDefinition obj)
{
_service.OptionsContainerOnOptionAdded(_container, obj);
}
private void ContainerOnOptionRemoved(OptionDefinition obj)
{
_service.OptionsContainerOnOptionRemoved(_container, obj);
}
public void Dispose()
{
_container.OptionAdded -= ContainerOnOptionAdded;
_container.OptionRemoved -= ContainerOnOptionRemoved;
}
}
}
}