Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="newFormular"></param>
        /// <param name="append"></param>
        ///
        private void UpdateWindow(MessageFormular newFormular, bool append = false)
        {
            if (newFormular == null)
            {
                return;
            }

            var old = LayoutPanel.Formular;                       // retrieve copy

            newFormular = newFormular.Clone() as MessageFormular; // act on copy

            if (append)
            {
                // overwrite all existing fields, and hand back the result
                foreach (var field in newFormular.FieldDescriptors)
                {
                    old[field.Name] = field; // hard overwrite
                }
                old.Require(RequireEnum.NoneButBoth, newFormular);
                old.Name    = newFormular.Name;
                newFormular = old;
            }
            else
            {
                newFormular.Require(RequireEnum.NoneButBoth, old);
            }

            LayoutPanel.Changed -= ReadLayoutPanel;
            LayoutPanel.Formular = newFormular;
            LayoutPanel.Changed += ReadLayoutPanel;

            LayoutPanel.CanEditFields = newFormular.IsDynamic;
        }
Example #2
0
        private void OnConfig(IDiffSpread <string> spread)
        {
            if (!SkippedFirst)
            {
                // usually just the Default of the pin, any saved data will come next
                SkippedFirst = true;
                return;
                // default of the pin already mimmicks default Formular for this node
            }

            var formular = Formular;

            formular.Require(RequireEnum.None);

            if (FFormularSelection.IsAnyInvalid())
            {
                formular.Name = MessageFormular.DYNAMIC;
            }
            else
            {
                formular.Name = FFormularSelection[0].Name;
            }

            // overwrite fiels that occur in FConfig
            var config = new MessageFormular(MessageFormular.DYNAMIC, FConfig[0]);

            foreach (var field in config.FieldDescriptors)
            {
                formular[field.Name] = field;
            }

            Formular = formular;
        }
        /// <summary>
        /// This will be called when a Formular is changed in the registry, to make all affected nodes comply with potential re-configuration
        /// </summary>
        /// <param name="sender">Usually Context</param>
        /// <param name="e">Contains the new Formular</param>
        protected virtual void FormularRemotelyChanged(MessageFormularRegistry sender, MessageFormular formular)
        {
            if (FFormularSelection.IsAnyInvalid())
            {
                return;                                     // before and during first frame input pins might not be valid yet
            }
            if (formular.IsDynamic)
            {
                return;
            }

            if (FFormularSelection[0] == formular.Name)
            {
                formular = formular.Clone() as MessageFormular; // keep a copy

                if (CustomizeFormular)
                {
                    formular.Require(RequireEnum.NoneBut, Formular); // never automatically add anything. e.g never add pins without user consent
                }
                else
                {
                    formular.Require(RequireEnum.All);  // always add all.
                }
                Formular = formular;
            }
        }
Example #4
0
        /// <summary>
        /// Will try to apply the formular to the current pin layout
        /// </summary>
        /// <param name="newFormular"></param>
        /// <remarks>
        /// If any pin in the new formular is already present, it will preserve the pin.
        /// If any current pin is not contained in the new Formular, but is linked in the patch, it will force the node to raise exceptions every frame, until the link is manually deleted.
        /// </remarks>
        protected void TryDefinePins(object sender, MessageFormular newFormular)
        {
            // reject formular, deferring it to application later on.
            if (HasEndangeredLinks(newFormular))
            {
                RemovePinsFirst = true;
                return;
            }
            else
            {
                RemovePinsFirst = false;
            }

            List <string> invalidPins = FPins.Keys.ToList();

            foreach (FormularFieldDescriptor field in newFormular.FieldDescriptors.Where(field => field.IsRequired))
            {
                if (FPins.ContainsKey(field.Name) && FPins[field.Name] != null)
                {
                    invalidPins.Remove(field.Name);

                    // same name, but types don't match
                    // todo: in fact eg float does match double from vvvv side, conversion useful for patching speed?
                    if (FPins[field.Name].GetInnerMostType() != field.Type)
                    {
                        FPins[field.Name].Dispose();
                        var pin = CreatePin(field);
                        if (pin != null)
                        {
                            FPins[field.Name] = pin;
                        }
                    }
                }
                else
                {
                    var pin = CreatePin(field);
                    if (pin != null)
                    {
                        FPins[field.Name] = pin;
                    }
                }
            }

            // cleanup
            foreach (string name in invalidPins)
            {
                FPins[name].Dispose();
                FPins.Remove(name);
            }

            // reorder - does not work right now, sdk offers only read-only access
            //var names = Formular.FieldNames.ToArray();

            //int counter = 0;
            //foreach (var name in newFormular.FieldNames)
            //{
            //    if (FPins[name] != null)
            //        FPins[name].GetPluginIO().Order = counter * 2 + 5;
            //}
        }
Example #5
0
        protected virtual void OnSelectFormular(IDiffSpread <EnumEntry> spread)
        {
            if (FFormularSelection.IsAnyInvalid() || string.IsNullOrWhiteSpace(FFormularSelection[0].Name))
            {
                FLogger.Log(LogType.Warning, "[\"" + this.GetType().Name + "\"] - Select a Formular. ID = " + PluginHost.GetNodePath(false));
                return;
            }

            var formularName = FFormularSelection[0].Name;

            if (Formular.Name == formularName)
            {
                return;
            }

            if (formularName != MessageFormular.DYNAMIC)
            {
                Formular = RetrieveAdoptedFormular(formularName);
            }
            else
            {
                // fallback to what's been known to the node
                // so a switch to DYNAMIC keeps the old entries (but makes them editable)
                Formular.Name = MessageFormular.DYNAMIC;
                Formular      = Formular;
            }
        }
        public void MultipleDefinitions()
        {
            var reg = MessageFormularRegistry.Context;

            var formular = new MessageFormular("A38", "string[3] Field");

            string lastChangedFormular = "";
            reg.FormularChanged += (sender, newFormular) => lastChangedFormular = newFormular.Name;

            Assert.AreEqual("", lastChangedFormular);
            var success = reg.Define("AddFormular", formular);

            Assert.IsTrue(success);
            Assert.AreEqual("A38", lastChangedFormular);

            try
            {
                reg.Define("Clash", formular);
                Assert.Fail("Formular by that name already exists from a different definer.");
            } catch (RegistryException) {}

            success = reg.Undefine("AddFormular", formular);
            Assert.IsTrue(success);

            success = reg.Define("NoClash", formular);
            Assert.IsTrue(success);

            var definitions = reg.AllFormularNames.Where(x => x != MessageFormular.DYNAMIC);

            Assert.AreEqual(1, definitions.Count());
            Assert.AreEqual("A38", definitions.First());
        }
        public void MultipleDefinitions()
        {
            var reg = MessageFormularRegistry.Context;

            var formular = new MessageFormular("A38", "string[3] Field");

            string lastChangedFormular = "";

            reg.FormularChanged += (sender, newFormular) => lastChangedFormular = newFormular.Name;

            Assert.AreEqual("", lastChangedFormular);
            var success = reg.Define("AddFormular", formular);

            Assert.IsTrue(success);
            Assert.AreEqual("A38", lastChangedFormular);

            try
            {
                reg.Define("Clash", formular);
                Assert.Fail("Formular by that name already exists from a different definer.");
            } catch (RegistryException) {}

            success = reg.Undefine("AddFormular", formular);
            Assert.IsTrue(success);

            success = reg.Define("NoClash", formular);
            Assert.IsTrue(success);

            var definitions = reg.AllFormularNames.Where(x => x != MessageFormular.DYNAMIC);

            Assert.AreEqual(1, definitions.Count());
            Assert.AreEqual("A38", definitions.First());
        }
        internal MessageFormularRegistry()
        {
            var formular = new MessageFormular(MessageFormular.DYNAMIC, null as Message); // empty message

            Data["_dyn"] = new List<MessageFormular>();
            Data["_dyn"].Add(formular);
        }
Example #9
0
        //called when data for any output pin is requested
        public override void Evaluate(int SpreadMax)
        {
            var FieldCount = Getters.Count;

            if (FLearn[0] && FInput.SliceCount > 0 && FInput[0] != null)
            {
                var type = FInput[0].GetType();

                FLogger.Log(LogType.Debug, "Learning Type... " + type.FullName);

                FieldInfo[] fields = type.GetFields();

                FieldCount       = fields.Length;
                FName.SliceCount = FieldCount;

                Getters.Clear();
                var formular = new MessageFormular(type.FullName, "");
                for (var i = 0; i < FieldCount; i++)
                {
                    var name = fields[i].Name;
                    FName[i] = name;

                    var fieldInfo = type.GetField(name);

                    try
                    {
                        formular.Append(new FormularFieldDescriptor(fieldInfo.FieldType, name, 1), true);

                        var getter = fieldInfo.CompileGetter();
                        Getters.Add(name, getter);

                        FLogger.Log(LogType.Debug, "Success: " + fieldInfo.FieldType.Name + " " + name);
                    }
                    catch (Exception)
                    {
                        FLogger.Log(LogType.Debug, "Failed: " + fieldInfo.FieldType.Name + " " + name);
                        //FLogger.Log(ex, LogType.Debug);
                    }
                }
                Formular = formular;
            }

            SpreadMax          = FInput.SliceCount;
            FOutput.SliceCount = SpreadMax;

            for (int i = 0; i < SpreadMax; i++)
            {
                var m = new Message(Formular.Name);
                foreach (var fieldName in Formular.FieldNames)
                {
                    var getter = Getters[fieldName];

                    var bin = BinFactory.New(Formular[fieldName].Type);
                    bin.Add(getter(FInput[i]));
                    m[fieldName] = bin;
                }
                FOutput[i] = m;
            }
        }
Example #10
0
        //called when data for any output pin is requested
        public override void Evaluate(int SpreadMax)
        {
            var FieldCount = Getters.Count;
            if (FLearn[0] && FInput.SliceCount > 0 && FInput[0] != null)
            {
                var type = FInput[0].GetType();

                FLogger.Log(LogType.Debug, "Learning Type... "+type.FullName);

                FieldInfo[] fields = type.GetFields();

                FieldCount = fields.Length;
                FName.SliceCount = FieldCount;

                Getters.Clear();
                var formular = new MessageFormular(type.FullName, "");
                for (var i = 0; i < FieldCount; i++)
                {
                    var name = fields[i].Name;
                    FName[i] = name;

                    var fieldInfo = type.GetField(name);

                    try
                    {
                        formular.Append(new FormularFieldDescriptor(fieldInfo.FieldType, name, 1), true);

                        var getter = fieldInfo.CompileGetter();
                        Getters.Add(name, getter);

                        FLogger.Log(LogType.Debug, "Success: " + fieldInfo.FieldType.Name + " " + name);
                    }
                    catch (Exception)
                    {
                        FLogger.Log(LogType.Debug, "Failed: " + fieldInfo.FieldType.Name + " " + name);
                        //FLogger.Log(ex, LogType.Debug);
                    }
                }
                Formular = formular;
            }

            SpreadMax = FInput.SliceCount;
            FOutput.SliceCount = SpreadMax;

            for (int i = 0; i < SpreadMax; i++)
            {
                var m = new Message(Formular.Name);
                foreach (var fieldName in Formular.FieldNames)
                {
                    var getter = Getters[fieldName];

                    var bin = BinFactory.New(Formular[fieldName].Type);
                    bin.Add(getter(FInput[i]));
                    m[fieldName] = bin;

                }
                FOutput[i] = m;
            }
        }
Example #11
0
        public override void Evaluate(int SpreadMax)
        {
            // graceful fallback when being fed bad data
            if (FNew.IsAnyInvalid() || FTopic.IsAnyInvalid() || FSpreadCount.IsAnyInvalid())
            {
                FOutput.FlushNil();
                return;
            }

            if (!FNew.Any() && !ForceNewDefaults)
            {
                FOutput.FlushNil();
                return;
            }

            SpreadMax          = FFormularSelection.SliceCount; // numbers of supported Formulars
            FOutput.SliceCount = SpreadMax;

            var counter = 0;

            for (int i = 0; i < SpreadMax; i++)
            {
                var             formularName = FFormularSelection[i].Name;
                MessageFormular formular;
                try
                {
                    formular = RetrieveRegisteredFormular(formularName);
                } catch (RegistryException)
                {
                    formular = null;
                }

                if (formular == null || formular.IsDynamic)
                {
                    formular = new MessageFormular(formularName, ""); // empty fallback, in case not available or dynamic
                }
                FOutput[i].SliceCount = 0;

                var count = FSpreadCount[i];
                for (int j = 0; j < count; j++)
                {
                    if (FNew[counter] || ForceNewDefaults)
                    {
                        Message message = new Message(formular);
                        message.Topic = FTopic[counter];
                        FOutput[i].Add(message);
                    }
                    counter++;
                }
            }
            FOutput.Flush();

            ForceNewDefaults = false;
        }
Example #12
0
        /// <summary>
        /// Will try to apply the formular to the current pin layout
        /// </summary>
        /// <param name="newFormular"></param>
        /// <remarks>
        /// If any pin in the new formular is already present, it will preserve the pin.
        /// If any current pin is not contained in the new Formular, but is linked in the patch, it will force the node to raise exceptions every frame, until the link is manually deleted.
        /// </remarks>
        protected void TryDefinePins(object sender, MessageFormular newFormular)
        {
            // reject formular, deferring it to application later on.
            if (HasEndangeredLinks(newFormular))
            {
                RemovePinsFirst = true;
                return;
            }
            else
            {
                RemovePinsFirst = false;
            }

            List <string> invalidPins = FPins.Keys.ToList();

            foreach (FormularFieldDescriptor field in newFormular.FieldDescriptors.Where(field => field.IsRequired))
            {
                if (FPins.ContainsKey(field.Name) && FPins[field.Name] != null)
                {
                    invalidPins.Remove(field.Name);

                    // same name, but types don't match
                    // todo: in fact eg float does match double from vvvv side, conversion useful for patching speed?
                    if (FPins[field.Name].GetTypeRecord().Type != field.Type)
                    {
                        FPins[field.Name].Dispose();
                        var pin = CreatePin(field);
                        if (pin != null)
                        {
                            FPins[field.Name] = pin;
                        }
                    }
                }
                else
                {
                    var pin = CreatePin(field);
                    if (pin != null)
                    {
                        FPins[field.Name] = pin;
                    }
                }
            }

            // cleanup
            foreach (string name in invalidPins)
            {
                FPins[name].Dispose();
                FPins.Remove(name);
            }

            ReOrder();
        }
Example #13
0
        protected virtual void OnConfigChange(IDiffSpread<string> configSpread)
        {
            var formular = new MessageFormular(MessageFormular.DYNAMIC, configSpread[0] ?? "string Value");
            if (formular.FieldNames.Count() < 1) return;

            if (FValue != null)
            {
                FValue.Dispose();
            }

            var name = formular.FieldNames.First();
            TargetDynamicType = formular[name].Type;

            IOAttribute attr = DefinePin(formular[name]); // each implementation of DynamicNode must create its own InputAttribute or OutputAttribute
            Type pinType = typeof(ISpread<>).MakeGenericType((typeof(ISpread<>)).MakeGenericType(TargetDynamicType)); // the Pin is always a binsized one

               FValue = FIOFactory.CreateIOContainer(pinType, attr);
        }
Example #14
0
        /// <summary>
        /// This will be called when a Formular is changed in the registry, to make all affected nodes comply with potential re-configuration
        /// </summary>
        /// <param name="sender">Usually Context</param>
        /// <param name="e">Contains the new Formular</param>
        protected virtual void FormularRemotelyChanged(MessageFormularRegistry sender, MessageFormular formular)
        {
            if (FFormularSelection.IsAnyInvalid())
            {
                return;                                     // before and during first frame input pins might not be valid yet
            }
            if (formular.IsDynamic)
            {
                return;
            }

            if (FFormularSelection[0] == formular.Name)
            {
                formular = RetrieveAdoptedFormular(formular.Name);
                if (!CustomizeFormular)
                {
                    formular.Require(RequireEnum.All);                     // always add all.
                }
                Formular = formular;
            }
        }
        protected virtual void OnSelectFormular(IDiffSpread <EnumEntry> spread)
        {
            if (FFormularSelection.IsAnyInvalid() || string.IsNullOrWhiteSpace(FFormularSelection[0].Name))
            {
                FLogger.Log(LogType.Warning, "[\"" + this.GetType().Name + "\"] - Select a Formular. ID = " + PluginHost.GetNodePath(false));
                return;
            }

            var formularName = FFormularSelection[0].Name;

            if (Formular.Name == formularName)
            {
                return;
            }

            var backup = new MessageFormular(formularName, FConfig[0]); // local backup

            try
            {
                MessageFormular formular;
                if (formularName != MessageFormular.DYNAMIC)
                {
                    formular = RetrieveFormular(formularName);
                    formular.Require(RequireEnum.NoneBut, backup);
                }
                else
                {
                    formular      = backup; // fallback to what's been known to the node
                    formular.Name = formularName;
                }

                Formular = formular;
            }
            catch (RegistryException)
            {
                // i.e. not found. might happen during first frame
                Formular = backup;
            }
        }
Example #16
0
        /// <summary>
        /// Detects link breaking action, that would occur when disposing a now unneeded pin, or resetting its type.
        /// </summary>
        /// <param name="newFormular">Includes the changes to be done.</param>
        /// <returns>True, if no linkbreaking conflict of type or linkbreaking pin elimination</returns>
        /// <remarks>Compares the existing dynamic pins with the required fields in the given Formular</remarks>
        protected bool HasEndangeredLinks(MessageFormular newFormular)
        {
            // pin removals
            var danger = from pinName in FPins.Keys
                         where HasLink(FPins[pinName])
                         where !(newFormular.FieldNames.Contains(pinName) &&
                                 newFormular[pinName].IsRequired)
                         select pinName;

            // type changes - removal and recreate new
            var typeDanger = from pinName in FPins.Keys
                             where HasLink(FPins[pinName]) // first frame pin will not be initialized
                             where newFormular.FieldNames.Contains(pinName)
                             where newFormular[pinName].IsRequired
                             let innerType = FPins[pinName].GetTypeRecord().Type          // ISpread<ISpread< ??? >>
                                             where newFormular[pinName].Type != innerType // rather ask for conversion? see actual pin creation for more comments
                                             select pinName;

            // ignore changes to binsize for now

            return(danger.Count() > 0 || typeDanger.Count() > 0);
        }
Example #17
0
        private MessageFormular RetrieveAdoptedFormular(string formularName)
        {
            MessageFormular reg;

            try
            {
                reg = RetrieveRegisteredFormular(formularName);
            }
            catch (RegistryException)
            {
                reg = new MessageFormular(MessageFormular.DYNAMIC, FConfig[0]);
                // i.e. not found. might happen during first frame
            }
            reg.Require(RequireEnum.NoneBut, Formular);

            var formular = new MessageFormular(formularName, "");

            // all required fields, in order as the old one
            // overwrites any type differences, or sizes
            var oldNames = Formular.FieldNames.ToList();
            var required = reg.FieldDescriptors.Where(f => f.IsRequired).OrderBy(f => oldNames.IndexOf(f.Name));

            foreach (var field in required)
            {
                formular.Append(field, true);
            }

            // all non-required fields, in order as from registry
            var extraNames = reg.FieldNames.ToList();
            var extra      = reg.FieldDescriptors.Where(f => !f.IsRequired).OrderBy(f => extraNames.IndexOf(f.Name));

            foreach (var field in extra)
            {
                formular.Append(field, false);
            }

            return(formular);
        }
        protected virtual void OnConfigChange(IDiffSpread <string> configSpread)
        {
            var formular = new MessageFormular(MessageFormular.DYNAMIC, configSpread[0] ?? "string Value");

            if (formular.FieldNames.Count() < 1)
            {
                return;
            }

            if (FValue != null)
            {
                FValue.Dispose();
            }

            var name = formular.FieldNames.First();

            TargetDynamicType = formular[name].Type;

            IOAttribute attr    = DefinePin(formular[name]);                                                                   // each implementation of DynamicNode must create its own InputAttribute or OutputAttribute
            Type        pinType = typeof(ISpread <>).MakeGenericType((typeof(ISpread <>)).MakeGenericType(TargetDynamicType)); // the Pin is always a binsized one

            FValue = FIOFactory.CreateIOContainer(pinType, attr);
        }
        protected virtual void OnSelectFormular(IDiffSpread<EnumEntry> spread)
        {
            if (FFormularSelection.IsAnyInvalid()  || string.IsNullOrWhiteSpace( FFormularSelection[0].Name) )
            {
                FLogger.Log(LogType.Warning, "[\""+ this.GetType().Name + "\"] - Select a Formular. ID = " + PluginHost.GetNodePath(false));
                return;
            }

            var formularName = FFormularSelection[0].Name;
            if (Formular.Name == formularName) return;

            var backup = new MessageFormular(formularName, FConfig[0]); // local backup
            try
            {
                MessageFormular formular;
                if (formularName != MessageFormular.DYNAMIC)
                {
                    formular = RetrieveFormular(formularName);
                    formular.Require(RequireEnum.NoneBut, backup);
                }
                else {
                    formular = backup; // fallback to what's been known to the node
                    formular.Name = formularName;
                }

                Formular = formular;
            }
            catch (RegistryException)
            {
                // i.e. not found. might happen during first frame
                Formular = backup;
            }
        }
Example #20
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="newFormular"></param>
        /// <param name="append"></param>
        /// 
        private void UpdateWindow(MessageFormular newFormular, bool append = false)
        {
            if (newFormular == null) return;

            var old = LayoutPanel.Formular; // retrieve copy
            newFormular = newFormular.Clone() as MessageFormular; // act on copy

            if (append)
            {
                // overwrite all existing fields, and hand back the result
                foreach (var field in newFormular.FieldDescriptors)
                {
                    old[field.Name] = field; // hard overwrite
                }
                old.Require(RequireEnum.NoneButBoth, newFormular);
                old.Name = newFormular.Name;
                newFormular = old;
            }
            else
            {
                newFormular.Require(RequireEnum.NoneButBoth, old);
            }

            LayoutPanel.Changed -= ReadLayoutPanel;
            LayoutPanel.Formular = newFormular;
            LayoutPanel.Changed += ReadLayoutPanel;

            LayoutPanel.CanEditFields = newFormular.IsDynamic;
        }
Example #21
0
 private void ReadLayoutPanel(object sender, MessageFormular formular)
 {
     Formular = formular;
 }
Example #22
0
        /// <summary>
        /// Will try to apply the formular to the current pin layout
        /// </summary>
        /// <param name="newFormular"></param>
        /// <remarks>
        /// If any pin in the new formular is already present, it will preserve the pin.
        /// If any current pin is not contained in the new Formular, but is linked in the patch, it will force the node to raise exceptions every frame, until the link is manually deleted.
        /// </remarks>
        protected void TryDefinePins(object sender, MessageFormular newFormular)
        {
            // reject formular, deferring it to application later on.
            if (HasEndangeredLinks(newFormular))
            {
                RemovePinsFirst = true;
                return;
            }
            else RemovePinsFirst = false;

            List<string> invalidPins = FPins.Keys.ToList();
            foreach (FormularFieldDescriptor field in newFormular.FieldDescriptors.Where(field => field.IsRequired))
            {
                if (FPins.ContainsKey(field.Name) && FPins[field.Name] != null)
                {
                    invalidPins.Remove(field.Name);

                    // same name, but types don't match
                    // todo: in fact eg float does match double from vvvv side, conversion useful for patching speed?
                    if (FPins[field.Name].GetTypeRecord().Type != field.Type)
                    {
                        FPins[field.Name].Dispose();
                        var pin = CreatePin(field);
                        if (pin != null) FPins[field.Name] = pin;
                    }
                }
                else
                {
                    var pin = CreatePin(field);
                    if (pin != null) FPins[field.Name] = pin;
                }
            }

            // cleanup
            foreach (string name in invalidPins)
            {
                FPins[name].Dispose();
                FPins.Remove(name);
            }

            ReOrder();
        }
Example #23
0
        /// <summary>
        /// Detects link breaking action, that would occur when disposing a now unneeded pin, or resetting its type.
        /// </summary>
        /// <param name="newFormular">Includes the changes to be done.</param>
        /// <returns>True, if no linkbreaking conflict of type or linkbreaking pin elimination</returns>
        /// <remarks>Compares the existing dynamic pins with the required fields in the given Formular</remarks>
        protected bool HasEndangeredLinks(MessageFormular newFormular)
        {
            // pin removals
            var danger = from pinName in FPins.Keys
                         where HasLink(FPins[pinName])
                         where !(    newFormular.FieldNames.Contains(pinName)
                                  && newFormular[pinName].IsRequired)
                         select pinName;

            // type changes - removal and recreate new
            var typeDanger = from pinName in FPins.Keys
                             where HasLink(FPins[pinName]) // first frame pin will not be initialized
                             where newFormular.FieldNames.Contains(pinName)
                             where newFormular[pinName].IsRequired
                             let innerType = FPins[pinName].GetTypeRecord().Type // ISpread<ISpread< ??? >>
                             where newFormular[pinName].Type != innerType // rather ask for conversion? see actual pin creation for more comments
                             select pinName;

            // ignore changes to binsize for now

            return danger.Count() > 0 || typeDanger.Count() > 0;
        }
        public override void Evaluate(int SpreadMax)
        {
            // graceful fallback when being fed bad data
            if (FNew.IsAnyInvalid() || FTopic.IsAnyInvalid() || FSpreadCount.IsAnyInvalid())
            {
                FOutput.FlushNil();
                return;
            }

            if (!FNew.Any() && !ForceNewDefaults)
            {
                FOutput.FlushNil();
                return;
            }

            SpreadMax = FFormularSelection.SliceCount; // numbers of supported Formulars
            FOutput.SliceCount = SpreadMax;

            var counter = 0;
            for (int i = 0; i < SpreadMax; i++)
            {
                var formularName = FFormularSelection[i].Name;
                MessageFormular formular;
                try
                {
                    formular = RetrieveFormular(formularName);
                } catch (RegistryException)
                {
                    formular = null;
                }

                if (formular == null || formular.IsDynamic)
                    formular = new MessageFormular(formularName, ""); // empty fallback, in case not available or dynamic

                FOutput[i].SliceCount = 0;

                var count = FSpreadCount[i];
                for (int j = 0; j < count; j++)
                {
                    if (FNew[counter] || ForceNewDefaults)
                    {
                        Message message = new Message(formular);
                        message.Topic = FTopic[counter];
                        FOutput[i].Add(message);
                    }
                    counter++;
                }
            }
            FOutput.Flush();

            ForceNewDefaults = false;
        }
 /// <summary>
 /// Unregisters a specific Formular from a specific definer source
 /// </summary>
 /// <param name="definerId"></param>
 /// <returns>true, if undefine had an effect.</returns>
 public bool Undefine(string definerId, MessageFormular formular)
 {
     if (!Data.ContainsKey(definerId)) return false;
     return Data[definerId].Remove(formular);
 }
        private void OnConfig(IDiffSpread<string> spread)
        {
            if (!SkippedFirst)
            {
                // usually just the Default of the pin, any saved data will come next
                SkippedFirst = true;
                return;
                // default of the pin already mimmicks default Formular for this node
            }

            var formular = Formular;
            formular.Require(RequireEnum.None);

            if (FFormularSelection.IsAnyInvalid())
                formular.Name = MessageFormular.DYNAMIC;
            else formular.Name = FFormularSelection[0].Name;

            // overwrite fiels that occur in FConfig
            var config = new MessageFormular(MessageFormular.DYNAMIC, FConfig[0]);
            foreach (var field in config.FieldDescriptors)
            {
                formular[field.Name] = field;
            }

            Formular = formular;
        }
Example #27
0
 private void ReadLayoutPanel(object sender, MessageFormular formular)
 {
     Formular = formular;
 }
        public void Evaluate(int SpreadMax)
        {
            if (FConfiguration.IsAnyInvalid() || FName.IsAnyInvalid())
            {
                return;
            }

            ForceUpdate |= !FUpdate.IsAnyInvalid() && FUpdate[0];
            var change = ForceUpdate || FInherits.IsChanged || FName.IsChanged || FConfiguration.IsChanged;


            if (!ForceUpdate && !change)
            {
                if (_lastException != null)
                {
                    FError.FlushItem(_lastException.ToString());
                    throw _lastException;
                }
            }

            // untoggle exception.
            if (_lastException != null)
            {
                var tmp = _lastException;
                FError.FlushItem(_lastException.ToString());
                _lastException = null; // assume innocence
                throw tmp;
            }

            if (!change && !ForceUpdate)
            {
                return;
            }

            FOutput.SliceCount = SpreadMax = FName.SliceCount;

            var id  = this.PluginHost.GetNodePath(false);
            var reg = MessageFormularRegistry.Context;

            for (int i = 0; i < SpreadMax; i++)
            {
                if (string.IsNullOrWhiteSpace(FName[i]))
                {
                    _lastException = new ParseFormularException("A Formular cannot have an empty Name.");
                    return;
                }

                var config = string.Join(", ", FConfiguration[i]).Split(',');

                var fields = new List <FormularFieldDescriptor>();
                foreach (var def in config)
                {
                    FormularFieldDescriptor field;
                    try
                    {
                        field = new FormularFieldDescriptor(def.Trim(), true);
                    }
                    catch (ParseFormularException e)
                    {
                        _lastException = e;
                        return;
                    }

                    var match = (
                        from f in fields
                        where f.Name == field.Name
                        select f
                        ).FirstOrDefault();

                    if (match != null)
                    {
                        _lastException = new DuplicateFieldException("Cannot add \"" + def + "\" in Formular for [" + FName[i] + "]. Field with the same name already defined.", match, field);
                        return;
                    }
                    else
                    {
                        fields.Add(field);
                    }
                }


                var formular = new MessageFormular(FName[i], fields);

                if (!FInherits.IsAnyInvalid())
                {
                    // flatten
                    var allFields = (
                        from form in FInherits
                        from field in form.FieldDescriptors
                        select field
                        ).Distinct();

                    foreach (var field in allFields)
                    {
                        if (!formular.CanAppend(field))
                        {
                            var duplicate = formular[field.Name];
                            _lastException = new DuplicateFieldException("Cannot add new Field \"" + field.ToString() + "\" to Formular [" + formular.Name + "]. Field is already defined as \"" + duplicate.ToString() + "\".", field, duplicate);
                            return;
                        }
                        else
                        {
                            try
                            {
                                formular.Append(field, true);
                            }
                            catch (DuplicateFieldException e)
                            {
                                _lastException = e;
                                return;
                            }
                        }
                    }
                }

                // only register, when update has been hit!
                if (ForceUpdate)
                {
                    try
                    {
                        var defined = reg.Define(id, formular); // will raise Change events to inform all formularable nodes
                        if (defined)
                        {
                            FOutput[i] = formular;
                        }
                    }
                    catch (RegistryException e)
                    {
                        _lastException = e;
                        return;
                    }
                }
        /// <summary>Tries to define a Formular. Each named Formular can only be defined by one sender entity</summary>
        /// <param name="definerId">A unique string that helps to keep track, who registered a given Formular.</param>
        /// <param name="formular">A MessageFormular to be registered.</param>
        /// <param name="supressEvent">A bool indicating if the registry should skip informing interested parties about this change.</param>
        /// <exception cref="ArgumentNullException">Thrown when the Formular is null.</exception>
        /// <exception cref="RegistryException">This exception is thrown if a syntax error prevents the config to be parsed.</exception>
        /// <returns>success</returns>
        /// <remarks>Setting the supressEvent parameter to true will prevent this method to inform any TypeChanged subscribers.</remarks>
        public bool Define(string definerId, MessageFormular formular, bool supressEvent = false)
        {
            if (formular == null) throw new ArgumentNullException("Formular cannot be null");
            if (formular.IsDynamic) return false;

            if (!Data.ContainsKey(definerId)) Data[definerId] = new List<MessageFormular>();

            var conflict = (
                            from nodeId in Data.Keys
                            where definerId != nodeId
                            from form in Data[nodeId]
                            where formular.Name == form.Name
                            select form.Name
                        ).FirstOrDefault();

            if (conflict != null)
            {
                throw new RegistryException("Cannot add the formular to the registry. Another formular with the name \""+ conflict +"\" already exists.");
            }

            var ownFormulars = Data[definerId];
            var oldForm = (
                            from form in ownFormulars
                            where form.Name == formular.Name
                            select form
                         ).FirstOrDefault();

            // no need to worry someone, if we conclude nothing's changed.
            // if (formular.Equals(oldForm)) return false;

            if (oldForm != null) ownFormulars.Remove(oldForm);
            ownFormulars.Add(formular);

            if (!supressEvent)
            {
                if (FormularChanged != null) FormularChanged(this, formular);
            }
            return true;
        }
        protected bool LayoutByFormular(MessageFormular formular, bool keepUnused)
        {
            this.SuspendLayout();

            var empty = Enumerable.Empty <FieldPanel>();
            var prev  = FieldPanels.ToList();

            var unused = (
                from panel in prev
                where panel.IsFaulty && panel.CanEdit
                select panel
                ).Concat(
                from panel in prev
                where !panel.IsFaulty && !panel.IsEmpty
                where !formular.FieldNames.Contains(panel.Descriptor.Name)
                select panel
                ).Distinct().ToList();

            var remove = (
                from panel in prev
                where !panel.IsFaulty
                where panel.IsEmpty || !formular.FieldNames.Contains(panel.Descriptor.Name)
                select panel
                ).Concat(keepUnused? empty : unused).Distinct().ToList();

            // keep all that will
            var remain = (
                from panel in prev
                where !panel.IsFaulty
                where !panel.IsEmpty
                where formular.FieldNames.Contains(panel.Descriptor.Name)
                select panel
                ).Concat(keepUnused? unused : empty).Distinct().ToList();

            var currentDesc = (
                from panel in prev
                where !panel.IsEmpty
                select panel.Descriptor.Name
                );

            var fresh = (
                from field in formular.FieldDescriptors
                where !currentDesc.Contains(field.Name)
                select field
                ).ToList();

            var maxCount = remove.Count();
            var counter  = maxCount;

            foreach (var descriptor in fresh)
            {
                // if lingering panels available, recycle it or else instanciate new one
                if (counter > 0)
                {
                    FieldPanel revive = remove[maxCount - counter];
                    revive.Descriptor = descriptor; // will modify the checkbox and description text

                    revive.Visible = true;
                    revive.Locked  = Locked;
                    counter--;
                }
                else
                {
                    AddNewFieldPanel(descriptor);
                }
            }

            // cleanup: just keep them lingering around, recycle when needed. should speed up gui
            while (counter > 0)
            {
                FieldPanel panel = remove[maxCount - counter];
                if (panel != null && !(panel.IsFaulty && keepUnused))
                {
                    panel.IsEmpty = true;                                                   // removes Checked as well
                }
                counter--;
            }

            // update remaining fields
            foreach (FieldPanel panel in remain)
            {
                if (!panel.IsFaulty) // don't touch faulty panels, user might want to fix them later.
                {
                    var desc = formular[panel.Descriptor.Name];
                    desc.IsRequired  = panel.Checked;
                    panel.Descriptor = desc; // overwrite to stay in sync with the node's central formular
                }
            }

            this.ResumeLayout();
            return(true);
        }
        protected bool LayoutByFormular(MessageFormular formular, bool keepUnused)
        {
            this.SuspendLayout();

            var empty = Enumerable.Empty<FieldPanel>();
            var prev =    FieldPanels.ToList();

            var unused = (
                                from panel in prev
                                where panel.IsFaulty && panel.CanEdit
                                select panel
                          ).Concat(
                                from panel in prev
                                where !panel.IsFaulty && !panel.IsEmpty
                                where !formular.FieldNames.Contains(panel.Descriptor.Name)
                                select panel
                          ).Distinct().ToList();

            var remove =  (
                                from panel in prev
                                where !panel.IsFaulty
                                where panel.IsEmpty || !formular.FieldNames.Contains(panel.Descriptor.Name)
                                select panel
                          ).Concat(keepUnused? empty : unused).Distinct().ToList();

            // keep all that will
            var remain = (
                                from panel in prev
                                where !panel.IsFaulty
                                where !panel.IsEmpty
                                where formular.FieldNames.Contains(panel.Descriptor.Name)
                                select panel
                          ).Concat(keepUnused? unused : empty).Distinct().ToList();

            var currentDesc = (
                                from panel in prev
                                where !panel.IsEmpty
                                select panel.Descriptor.Name
                          );

            var fresh =   (
                                from field in formular.FieldDescriptors
                                where !currentDesc.Contains(field.Name)
                                select field
                          ).ToList();

            var maxCount = remove.Count();
            var counter = maxCount;

            foreach (var descriptor in fresh)
            {
                // if lingering panels available, recycle it or else instanciate new one
                if (counter > 0)
                {
                    FieldPanel revive = remove[maxCount - counter];
                    revive.Descriptor = descriptor; // will modify the checkbox and description text

                    revive.Visible = true;
                    revive.Locked = Locked;
                    counter--;
                }
                else
                {
                    AddNewFieldPanel(descriptor);
                }
            }

            // cleanup: just keep them lingering around, recycle when needed. should speed up gui
            while (counter > 0)
            {
                FieldPanel panel = remove[maxCount - counter];
                if (panel != null && !(panel.IsFaulty && keepUnused)) panel.IsEmpty = true; // removes Checked as well
                counter--;
            }

            // update remaining fields
            foreach (FieldPanel panel in remain)
            {
                if (!panel.IsFaulty) // don't touch faulty panels, user might want to fix them later.
                {
                    var desc = formular[panel.Descriptor.Name];
                    desc.IsRequired = panel.Checked;
                    panel.Descriptor = desc; // overwrite to stay in sync with the node's central formular
                }
            }

            this.ResumeLayout();
            return true;
        }
        public void Evaluate(int SpreadMax)
        {
            if (FConfiguration.IsAnyInvalid() || FName.IsAnyInvalid()) return;

            ForceUpdate |= !FUpdate.IsAnyInvalid() && FUpdate[0];
            var change = ForceUpdate || FInherits.IsChanged || FName.IsChanged || FConfiguration.IsChanged;

            if (!ForceUpdate && !change)
            {
                if (_lastException != null)
                {
                    FError.FlushItem(_lastException.ToString());
                    throw _lastException;
                }
            }

            // untoggle exception.
            if (_lastException != null)
            {
                var tmp = _lastException;
                FError.FlushItem(_lastException.ToString());
                _lastException = null; // assume innocence
                throw tmp;
            }

            if (!change && !ForceUpdate) return;

            FOutput.SliceCount = SpreadMax = FName.SliceCount;

            var id = this.PluginHost.GetNodePath(false);
            var reg = MessageFormularRegistry.Context;

            for (int i = 0; i < SpreadMax; i++)
            {
                if (string.IsNullOrWhiteSpace(FName[i]))
                {
                    _lastException = new ParseFormularException("A Formular cannot have an empty Name.");
                    return;
                }

                var config = string.Join(", ", FConfiguration[i]).Split(',');

                var fields = new List<FormularFieldDescriptor>();
                foreach (var def in config)
                {
                    FormularFieldDescriptor field;
                    try
                    {
                        field = new FormularFieldDescriptor(def.Trim(), true);
                    }
                    catch (ParseFormularException e)
                    {
                        _lastException = e;
                        return;
                    }

                    var match = (
                                    from f in fields
                                    where f.Name == field.Name
                                    select f
                                ).FirstOrDefault();

                    if (match != null)
                    {
                        _lastException = new DuplicateFieldException("Cannot add \"" + def + "\" in Formular for [" + FName[i] + "]. Field with the same name already defined.", match, field);
                        return;
                    }
                    else fields.Add(field);
                }

                var formular = new MessageFormular(FName[i], fields);

                if (!FInherits.IsAnyInvalid())
                {
                    // flatten
                    var allFields = (
                                        from form in FInherits
                                        from field in form.FieldDescriptors
                                        select field
                                     ).Distinct();

                    foreach (var field in allFields)
                    {
                        if (!formular.CanAppend(field))
                        {
                            var duplicate = formular[field.Name];
                            _lastException = new DuplicateFieldException("Cannot add new Field \"" + field.ToString() + "\" to Formular [" + formular.Name + "]. Field is already defined as \"" + duplicate.ToString() + "\".", field, duplicate);
                            return;
                        } else
                        {
                            try
                            {
                                formular.Append(field, true);
                            }
                            catch (DuplicateFieldException e)
                            {
                                _lastException = e;
                                return;
                            }
                        }
                    }
                }

                // only register, when update has been hit!
                if (ForceUpdate)
                try
                {
                        var defined = reg.Define(id, formular); // will raise Change events to inform all formularable nodes
                        if (defined)
                            FOutput[i] = formular;
                }
                catch (RegistryException e)
                {
                    _lastException = e;
                    return;
                }
                catch (ArgumentNullException e)
                {
                    _lastException = e;
                    return;
                }
            }

            // only register, when update has been hit!
            if (ForceUpdate)
            {
                foreach (var form in reg.GetFormularsFrom(id).ToList())
                {
                    if (!FName.Contains(form.Name))
                        reg.Undefine(id, form);
                }
                FOutput.Flush();
                EnumManager.UpdateEnum(MessageFormularRegistry.RegistryName, reg.AllFormularNames.First(), reg.AllFormularNames.ToArray());
            }

            ForceUpdate = false;
        }
        /// <summary>
        /// This will be called when a Formular is changed in the registry, to make all affected nodes comply with potential re-configuration
        /// </summary>
        /// <param name="sender">Usually Context</param>
        /// <param name="e">Contains the new Formular</param>
        protected virtual void FormularRemotelyChanged(MessageFormularRegistry sender, MessageFormular formular)
        {
            if (FFormularSelection.IsAnyInvalid()) return;  // before and during first frame input pins might not be valid yet
            if (formular.IsDynamic) return;

            if (FFormularSelection[0] == formular.Name)
            {
                formular = formular.Clone() as MessageFormular; // keep a copy

                if (CustomizeFormular)
                    formular.Require(RequireEnum.NoneBut, Formular); // never automatically add anything. e.g never add pins without user consent
                else formular.Require(RequireEnum.All); // always add all.

                Formular = formular;
            }
        }