public FrFlow(Orientation dir, IEnumerable <Fridget> fridgets) : base((size, sMouse, sKey, focus, idSupply) => { DiscreteCell <Size> desiredSize = DiscreteCell.Constant(new Size(0, 0)); DiscreteCell <DrawableDelegate> drawable = DiscreteCell.Constant(new DrawableDelegate(d => { })); Stream <long> sChangeFocus = Stream.Never <long>(); foreach (Fridget fridget in fridgets) { DiscreteCellLoop <Maybe <Size> > childSz = new DiscreteCellLoop <Maybe <Size> >(); Output fo = new FrTranslate(fridget, dir == Orientation.Horizontal ? desiredSize.Map(dsz => new Point(dsz.Width, 0)) : desiredSize.Map(dsz => new Point(0, dsz.Height))) .Reify(childSz, sMouse, sKey, focus, idSupply.Child1()); idSupply = idSupply.Child2(); childSz.Loop( size.Lift(fo.DesiredSize, (mSize, foDsz) => mSize.Map(s => dir == Orientation.Horizontal ? new Size(foDsz.Width, s.Height) : new Size(s.Width, foDsz.Height)))); Size LiftDesiredSizeHorizontal(Size dsz, Size foDsz) => new Size(dsz.Width + foDsz.Width, dsz.Height > foDsz.Height ? dsz.Height : foDsz.Height); Size LiftDesiredSizeVertical(Size dsz, Size foDsz) => new Size(dsz.Width > foDsz.Width ? dsz.Width : foDsz.Width, dsz.Height + foDsz.Height); desiredSize = desiredSize.Lift(fo.DesiredSize, dir == Orientation.Horizontal ? LiftDesiredSizeHorizontal : (Func <Size, Size, Size>)LiftDesiredSizeVertical); drawable = drawable.Lift(fo.Drawable, (drA, drB) => drA.Append(drB)); sChangeFocus = sChangeFocus.OrElse(fo.SChangeFocus); } return(new Output(drawable, desiredSize, sChangeFocus)); }) { }
public void Test_Constant_TestCase() { DiscreteCell <char> c = DiscreteCell.Constant('a'); List <char> @out = RunSimulation <char>(c.Listen); CollectionAssert.AreEqual(new[] { 'a' }, @out); }
public MainWindow() { this.InitializeComponent(); this.Container.Children.Add(Transaction.Run(() => { FrButton b = new FrButton(DiscreteCell.Constant("OK")); IListener l = b.SClicked.Listen(_ => this.AddMessage("clicked!")); return(new FrView(this, b, l)); })); }
public Outputs() { this.Delivery = DiscreteCell.Constant(PetrolPump.Delivery.Off); this.PresetLcd = DiscreteCell.Constant(string.Empty); this.SaleCostLcd = DiscreteCell.Constant(string.Empty); this.SaleQuantityLcd = DiscreteCell.Constant(string.Empty); this.PriceLcd1 = DiscreteCell.Constant(string.Empty); this.PriceLcd2 = DiscreteCell.Constant(string.Empty); this.PriceLcd3 = DiscreteCell.Constant(string.Empty); this.SBeep = Stream.Never <Unit>(); this.SSaleComplete = Stream.Never <Sale>(); }
public MainWindow() { this.InitializeComponent(); this.Container.Children.Add(Transaction.Run(() => { FrButton ok = new FrButton(DiscreteCell.Constant("OK")); FrButton cancel = new FrButton(DiscreteCell.Constant("Cancel")); IReadOnlyList <Fridget> fridgets = new[] { ok, cancel }; Fridget dialog = new FrFlow(Orientation.Horizontal, fridgets); IListener lOk = ok.SClicked.Listen(_ => this.AddMessage("OK")); IListener lCancel = cancel.SClicked.Listen(_ => this.AddMessage("Cancel")); return(new FrView(this, dialog, new CompositeListener(new[] { lOk, lCancel }))); })); }
public MainWindow() { this.InitializeComponent(); this.Container.Children.Add(Transaction.Run(() => { FrTextField firstName = new FrTextField("Joe"); FrTextField lastName = new FrTextField("Bloggs"); FrButton ok = new FrButton(DiscreteCell.Constant("OK")); FrButton cancel = new FrButton(DiscreteCell.Constant("Cancel")); IReadOnlyList <Fridget> buttons = new[] { ok, cancel }; Fridget buttonPanel = new FrFlow(Orientation.Horizontal, buttons); IReadOnlyList <Fridget> fridgets = new[] { buttonPanel, firstName, lastName }; Fridget dialog = new FrFlow(Orientation.Vertical, fridgets); IListener lOk = ok.SClicked.Snapshot(firstName.Text, lastName.Text, (_, f, l) => f + " " + l).Listen(n => this.AddMessage("OK: " + n)); IListener lCancel = cancel.SClicked.Listen(_ => this.AddMessage("Cancel")); return(new FrView(this, dialog, new CompositeListener(new[] { lOk, lCancel }))); })); }
public Implementation(PetrolPumpWindow petrolPump) { SComboBox <IPump> logic = new SComboBox <IPump>( new IPump[] { new LifeCyclePump(), new AccumulatePulsesPump(), new ShowDollarsPump(), new ClearSalePump(), new KeypadPump(), new PresetAmountPump() }, p => p.GetType().FullName); petrolPump.LogicComboBoxPlaceholder.Children.Add(logic); STextField textPrice1 = new STextField("2.149") { Width = 100 }; petrolPump.Price1Placeholder.Children.Add(textPrice1); STextField textPrice2 = new STextField("2.341") { Width = 100 }; petrolPump.Price2Placeholder.Children.Add(textPrice2); STextField textPrice3 = new STextField("1.499") { Width = 100 }; petrolPump.Price3Placeholder.Children.Add(textPrice3); Func <string, double> parseDoubleSafe = s => { double n; if (double.TryParse(s, out n)) { return(n); } return(0.0); }; StreamSink <Key> sKey = new StreamSink <Key>(); Dictionary <Key, FrameworkElement> containersByKey = new Dictionary <Key, FrameworkElement> { { Key.One, petrolPump.Keypad1Button }, { Key.Two, petrolPump.Keypad2Button }, { Key.Three, petrolPump.Keypad3Button }, { Key.Four, petrolPump.Keypad4Button }, { Key.Five, petrolPump.Keypad5Button }, { Key.Six, petrolPump.Keypad6Button }, { Key.Seven, petrolPump.Keypad7Button }, { Key.Eight, petrolPump.Keypad8Button }, { Key.Nine, petrolPump.Keypad9Button }, { Key.Zero, petrolPump.Keypad0Button }, { Key.Clear, petrolPump.KeypadClearButton } }; foreach (KeyValuePair <Key, FrameworkElement> containerAndKey in containersByKey) { containerAndKey.Value.MouseDown += async(sender, args) => { if (args.LeftButton == MouseButtonState.Pressed) { await Task.Run(() => sKey.Send(containerAndKey.Key)); } }; } DiscreteCellLoop <UpDown> nozzle1 = new DiscreteCellLoop <UpDown>(); DiscreteCellLoop <UpDown> nozzle2 = new DiscreteCellLoop <UpDown>(); DiscreteCellLoop <UpDown> nozzle3 = new DiscreteCellLoop <UpDown>(); DiscreteCell <double> calibration = DiscreteCell.Constant(0.001); DiscreteCell <double> price1 = textPrice1.Text.Map(parseDoubleSafe); DiscreteCell <double> price2 = textPrice2.Text.Map(parseDoubleSafe); DiscreteCell <double> price3 = textPrice3.Text.Map(parseDoubleSafe); DiscreteCellSink <Stream <Unit> > csClearSale = new DiscreteCellSink <Stream <Unit> >(Sodium.Stream.Never <Unit>()); Stream <Unit> sClearSale = csClearSale.SwitchS(); StreamSink <int> sFuelPulses = new StreamSink <int>(); Cell <Outputs> outputs = logic.SelectedItem.Map( pump => pump.Create(new Inputs( nozzle1.Updates, nozzle2.Updates, nozzle3.Updates, sKey, sFuelPulses, calibration, price1, price2, price3, sClearSale))); DiscreteCell <Delivery> delivery = outputs.Map(o => o.Delivery).SwitchC(); DiscreteCell <string> presetLcd = outputs.Map(o => o.PresetLcd).SwitchC(); DiscreteCell <string> saleCostLcd = outputs.Map(o => o.SaleCostLcd).SwitchC(); DiscreteCell <string> saleQuantityLcd = outputs.Map(o => o.SaleQuantityLcd).SwitchC(); DiscreteCell <string> priceLcd1 = outputs.Map(o => o.PriceLcd1).SwitchC(); DiscreteCell <string> priceLcd2 = outputs.Map(o => o.PriceLcd2).SwitchC(); DiscreteCell <string> priceLcd3 = outputs.Map(o => o.PriceLcd3).SwitchC(); Stream <Unit> sBeep = outputs.Map(o => o.SBeep).SwitchS(); Stream <Sale> sSaleComplete = outputs.Map(o => o.SSaleComplete).SwitchS(); SoundPlayer beepPlayer = new SoundPlayer(GetResourceStream(@"sounds\beep.wav")); this.listeners.Add(sBeep.Listen(_ => new Thread(() => beepPlayer.PlaySync()) { IsBackground = true }.Start())); SoundPlayer fastRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\fast.wav")); Action stopFast = () => { }; void PlayFast() { ManualResetEvent mre = new ManualResetEvent(false); new Thread(() => { fastRumblePlayer.PlayLooping(); mre.WaitOne(); fastRumblePlayer.Stop(); }) { IsBackground = true }.Start(); stopFast = () => { mre.Set(); stopFast = () => { }; }; } SoundPlayer slowRumblePlayer = new SoundPlayer(GetResourceStream(@"sounds\slow.wav")); Action stopSlow = () => { }; void PlaySlow() { ManualResetEvent mre = new ManualResetEvent(false); new Thread(() => { slowRumblePlayer.PlayLooping(); mre.WaitOne(); slowRumblePlayer.Stop(); }) { IsBackground = true }.Start(); stopSlow = () => { mre.Set(); stopSlow = () => { }; }; } this.listeners.Add(delivery.Changes().Listen(d => { petrolPump.Dispatcher.InvokeIfNecessary(() => { if (d == Delivery.Fast1 || d == Delivery.Fast2 || d == Delivery.Fast3) { PlayFast(); } else { stopFast(); } if (d == Delivery.Slow1 || d == Delivery.Slow2 || d == Delivery.Slow3) { PlaySlow(); } else { stopSlow(); } }); })); StackPanel presetLcdStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.PresetPlaceholder.Children.Add(presetLcdStackPanel); this.listeners.Add(presetLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(presetLcdStackPanel, t, 5, true)))); StackPanel saleCostStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.DollarsPlaceholder.Children.Add(saleCostStackPanel); this.listeners.Add(saleCostLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleCostStackPanel, t, 5, true)))); StackPanel saleQuantityLcdStackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.LitersPlaceholder.Children.Add(saleQuantityLcdStackPanel); this.listeners.Add(saleQuantityLcd.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(saleQuantityLcdStackPanel, t, 5, true)))); StackPanel priceLcd1StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel1Placeholder.Children.Add(priceLcd1StackPanel); this.listeners.Add(priceLcd1.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd1StackPanel, t, 5, false)))); StackPanel priceLcd2StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel2Placeholder.Children.Add(priceLcd2StackPanel); this.listeners.Add(priceLcd2.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd2StackPanel, t, 5, false)))); StackPanel priceLcd3StackPanel = new StackPanel { Orientation = Orientation.Horizontal }; petrolPump.Fuel3Placeholder.Children.Add(priceLcd3StackPanel); this.listeners.Add(priceLcd3.Listen(t => petrolPump.Dispatcher.InvokeIfNecessary(() => petrolPump.SetLcdDigits(priceLcd3StackPanel, t, 5, false)))); Dictionary <DiscreteCellLoop <UpDown>, Image> nozzles = new Dictionary <DiscreteCellLoop <UpDown>, Image> { { nozzle1, petrolPump.Nozzle1Image }, { nozzle2, petrolPump.Nozzle2Image }, { nozzle3, petrolPump.Nozzle3Image } }; this.listeners.AddRange(nozzles.Select(nozzle => nozzle.Key.Listen(p => petrolPump.Dispatcher.InvokeIfNecessary(() => nozzle.Value.Margin = p == UpDown.Up ? new Thickness(0, 0, 0, 0) : new Thickness(0, 30, 0, 0))))); foreach (KeyValuePair <DiscreteCellLoop <UpDown>, Image> nozzle in nozzles) { StreamSink <Unit> nozzleClicks = new StreamSink <Unit>(); nozzle.Value.MouseDown += async(sender, args) => { if (args.LeftButton == MouseButtonState.Pressed) { await Task.Run(() => nozzleClicks.Send(Unit.Value)); } }; nozzle.Key.Loop(nozzleClicks.Snapshot(nozzle.Key, (_, n) => n == UpDown.Down ? UpDown.Up : UpDown.Down).Hold(UpDown.Down)); } this.listeners.Add(sSaleComplete.Listen(sale => { Task.Run(() => { petrolPump.Dispatcher.InvokeIfNecessary(() => { SaleCompleteDialog dialog = new SaleCompleteDialog( sale.Fuel.ToString(), Formatters.FormatPrice(sale.Price, null), Formatters.FormatSaleCost(sale.Cost), Formatters.FormatSaleQuantity(sale.Quantity)); dialog.Owner = petrolPump; csClearSale.Send(dialog.SOkClicked); dialog.Show(); IListener l = null; // ReSharper disable once RedundantAssignment l = dialog.SOkClicked.Listen(_ => { petrolPump.Dispatcher.InvokeIfNecessary(() => dialog.Close()); // ReSharper disable once AccessToModifiedClosure l?.Unlisten(); }); }); }); })); Task.Run(async() => { while (true) { Transaction.RunVoid(() => { switch (delivery.Cell.Sample()) { case Delivery.Fast1: case Delivery.Fast2: case Delivery.Fast3: sFuelPulses.Send(40); break; case Delivery.Slow1: case Delivery.Slow2: case Delivery.Slow3: sFuelPulses.Send(2); break; } }); await Task.Delay(200).ConfigureAwait(false); } // ReSharper disable once FunctionNeverReturns }); }
public Frp(Action <string> addMessage) { this.listener = Transaction.Run(() => { DiscreteCell <Maybe <DragInfo> > dragInfo = this.sMouseDown.Map(me => Maybe.Some(new DragInfo(me, Canvas.GetLeft(me.Element.Polygon).ZeroIfNaN(), Canvas.GetTop(me.Element.Polygon).ZeroIfNaN()))) .OrElse(this.sMouseUp.Map(_ => Maybe <DragInfo> .None)).Hold(Maybe.None); DiscreteCell <bool> axisLock = this.sShift.Hold(false); DiscreteCell <Maybe <Tuple <MouseEvt, bool> > > mouseMoveAndAxisLock = dragInfo.Map(md => md.Match( d => this.sMouseMove.Hold(d.Me).Lift(axisLock, Tuple.Create).Map(Maybe.Some), () => DiscreteCell.Constant(Maybe <Tuple <MouseEvt, bool> > .None))).SwitchC(); IListener listener1 = dragInfo.Values.FilterMaybe().Listen(d => addMessage("FRP dragging " + d.Me.Element.Name)); IListener listener2 = mouseMoveAndAxisLock .Values .FilterMaybe() .Snapshot(dragInfo, (ma, md) => md.Match(d => Maybe.Some(new Reposition(d, ma.Item1, ma.Item2)), () => Maybe.None)) .FilterMaybe() .Listen(p => { Canvas.SetLeft(p.Polygon, p.Left); Canvas.SetTop(p.Polygon, p.Top); }); return(new CompositeListener(new[] { listener1, listener2 })); }); }
public STextBox(Stream <string> setText, string initText) : this(setText, initText, DiscreteCell.Constant(true)) { }
public SButton() : this(DiscreteCell.Constant(true)) { }