public SComboBox(Stream <IMaybe <T> > setSelectedItem, IMaybe <T> initSelectedItem, IEnumerable <T> items) { Action <IMaybe <T> > setSelectedItemImpl = m => base.SelectedItem = m.Match <object>(v => v, () => null); this.ItemsSource = items ?? new T[0]; setSelectedItemImpl(initSelectedItem); List <IListener> listeners = new List <IListener>(); StreamSink <int> sDecrement = new StreamSink <int>(); Cell <bool> allow = setSelectedItem.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); Func <IMaybe <T> > getSelectedItem = () => { object sel = base.SelectedItem; return(sel == null?Maybe.Nothing <T>() : Maybe.Just((T)sel)); }; StreamSink <IMaybe <T> > sUserSelectedItem = new StreamSink <IMaybe <T> >(); this.SUserSelectedItem = sUserSelectedItem; this.SelectedItem = sUserSelectedItem.Gate(allow).OrElse(setSelectedItem).Hold(initSelectedItem); SelectionChangedEventHandler selectionChangedEventHandler = (sender, args) => { IMaybe <T> selectedItem = getSelectedItem(); this.Dispatcher.InvokeAsync(() => sUserSelectedItem.Send(selectedItem)); }; this.SelectionChanged += selectionChangedEventHandler; listeners.Add(setSelectedItem.Listen(m => { this.Dispatcher.InvokeAsync(() => { this.SelectionChanged -= selectionChangedEventHandler; setSelectedItemImpl(m); this.SelectionChanged += selectionChangedEventHandler; sDecrement.Send(-1); }); })); this.disposeListeners = () => { foreach (IListener l in listeners) { using (l) { } } }; }
public SComboBox(Stream <Maybe <T> > setSelectedItem, Maybe <T> initSelectedItem, IEnumerable <T> items) { void SetSelectedItemImpl(Maybe <T> m) => base.SelectedItem = m.Match <object>(v => v, () => null); this.ItemsSource = items ?? new T[0]; SetSelectedItemImpl(initSelectedItem); List <IListener> listeners = new List <IListener>(); StreamSink <int> sDecrement = Stream.CreateSink <int>(); Cell <bool> allow = setSelectedItem.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); Maybe <T> GetSelectedItem() { object sel = base.SelectedItem; return(sel == null ? Maybe.None : Maybe.Some((T)sel)); } StreamSink <Maybe <T> > sUserSelectedItem = Stream.CreateSink <Maybe <T> >(); this.SUserSelectedItem = sUserSelectedItem; this.SelectedItem = sUserSelectedItem.Gate(allow).OrElse(setSelectedItem).Hold(initSelectedItem); void SelectionChangedEventHandler(object sender, SelectionChangedEventArgs args) { Maybe <T> selectedItem = GetSelectedItem(); this.Dispatcher.InvokeAsync(() => sUserSelectedItem.Send(selectedItem)); } this.SelectionChanged += SelectionChangedEventHandler; listeners.Add(setSelectedItem.Listen(m => { this.Dispatcher.InvokeAsync(() => { this.SelectionChanged -= SelectionChangedEventHandler; SetSelectedItemImpl(m); this.SelectionChanged += SelectionChangedEventHandler; sDecrement.Send(-1); }); })); this.disposeListeners = () => { foreach (IListener l in listeners) { l.Unlisten(); } }; }
public void TestGate() { StreamSink <char?> sc = Stream.CreateSink <char?>(); BehaviorSink <bool> cGate = Behavior.CreateSink(true); List <char?> @out = new List <char?>(); IListener l = sc.Gate(cGate).Listen(@out.Add); sc.Send('H'); cGate.Send(false); sc.Send('O'); cGate.Send(true); sc.Send('I'); l.Unlisten(); CollectionAssert.AreEqual(new[] { 'H', 'I' }, @out); }
public STextBox(Stream <string> setText, string initText, Cell <bool> enabled) { base.Text = initText; List <IListener> listeners = new List <IListener>(); StreamSink <int> sDecrement = new StreamSink <int>(); Cell <bool> allow = setText.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); StreamSink <string> sUserChanges = new StreamSink <string>(); this.SUserChanges = sUserChanges; this.Text = sUserChanges.Gate(allow).OrElse(setText).Hold(initText); TextChangedEventHandler textChangedEventHandler = (sender, args) => { string text = base.Text; this.Dispatcher.InvokeAsync(() => sUserChanges.Send(text)); }; this.TextChanged += textChangedEventHandler; // Set the initial value at the end of the transaction so it works with CellLoops. Transaction.Post(() => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = enabled.Sample())); listeners.Add(setText.Listen(t => { this.Dispatcher.InvokeAsync(() => { this.TextChanged -= textChangedEventHandler; base.Text = t; this.TextChanged += textChangedEventHandler; sDecrement.Send(-1); }); })); listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e))); this.disposeListeners = () => { foreach (IListener l in listeners) { using (l) { } } }; }
public void TestGate() { StreamSink <char?> sc = new StreamSink <char?>(); CellSink <bool> cGate = new CellSink <bool>(true); List <char?> @out = new List <char?>(); using (sc.Gate(cGate).Listen(@out.Add)) { sc.Send('H'); cGate.Send(false); sc.Send('O'); cGate.Send(true); sc.Send('I'); } CollectionAssert.AreEqual(new[] { 'H', 'I' }, @out); }
public void TestGate() { StreamSink<char?> sc = new StreamSink<char?>(); CellSink<bool> cGate = new CellSink<bool>(true); List<char?> @out = new List<char?>(); using (sc.Gate(cGate).Listen(@out.Add)) { sc.Send('H'); cGate.Send(false); sc.Send('O'); cGate.Send(true); sc.Send('I'); } CollectionAssert.AreEqual(new[] { 'H', 'I' }, @out); }
public STextBox(Stream<string> setText, string initText, Cell<bool> enabled) { base.Text = initText; List<IListener> listeners = new List<IListener>(); StreamSink<int> sDecrement = new StreamSink<int>(); Cell<bool> allow = setText.Map(_ => 1).OrElse(sDecrement).Accum(0, (b, d) => b + d).Map(b => b == 0); StreamSink<string> sUserChanges = new StreamSink<string>(); this.SUserChanges = sUserChanges; this.Text = sUserChanges.Gate(allow).OrElse(setText).Hold(initText); TextChangedEventHandler textChangedEventHandler = (sender, args) => { string text = base.Text; this.Dispatcher.InvokeAsync(() => sUserChanges.Send(text)); }; this.TextChanged += textChangedEventHandler; // Set the initial value at the end of the transaction so it works with CellLoops. Transaction.Post(() => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = enabled.Sample())); listeners.Add(setText.Listen(t => { this.Dispatcher.InvokeAsync(() => { this.TextChanged -= textChangedEventHandler; base.Text = t; this.TextChanged += textChangedEventHandler; sDecrement.Send(-1); }); })); listeners.Add(Operational.Updates(enabled).Listen(e => this.Dispatcher.InvokeIfNecessary(() => this.IsEnabled = e))); this.disposeListeners = () => { foreach (IListener l in listeners) { using (l) { } } }; }