/*
Copyright (C) Arnaud Houdelette 2012-2014
Copyright (C) Emmanuel Langlois 2012-2014
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using System;
using System.Collections.Generic;
using System.Xml;
using System.Collections.ObjectModel;
namespace DMX2
{
public class SequenceurMaitre
{
public class Ligne {
public Ligne(){}
string nom;
TimeSpan duree = TimeSpan.Zero;
Dictionary data = new Dictionary();
public string Nom {
get {
return nom;
}
set {
nom = value;
}
}
public TimeSpan Duree {
get {
return duree;
}
set {
duree = value;
}
}
public string this [Sequenceur index] {
get {
string value;
if(!data.TryGetValue(index, out value)) return string.Empty;
return value;
}
set {
if(value.Length==0) {
if(data.ContainsKey(index))
data.Remove(index);
}
else
data[index] = value;
}
}
public void Save (XmlElement parent)
{
XmlElement el = parent.OwnerDocument.CreateElement ("Ligne");
parent.AppendChild (el);
el.SetAttribute ("nom", nom);
el.SetAttribute ("duree", duree.ToString ());
XmlElement xmlSeq;
foreach (var val in data) {
el.AppendChild(xmlSeq=parent.OwnerDocument.CreateElement ("data"));
xmlSeq.SetAttribute("seq",val.Key.ID.ToString());
xmlSeq.SetAttribute("val",val.Value);
}
}
public static Ligne Load (Conduite c, XmlElement el)
{
Ligne l = new Ligne();
l.nom = el.GetAttribute ("nom");
l.duree = TimeSpan.Parse(el.GetAttribute("duree"));
foreach (var xv in el.GetElementsByTagName("data")) {
XmlElement xmlSeq = xv as XmlElement;
Sequenceur seq = c.GetSeqByID(int.Parse(xmlSeq.GetAttribute("seq")));
l[seq]= xmlSeq.GetAttribute ("val");
}
return l;
}
}
List lignes = new List();
Ligne enCours = null;
TimeSpan timeStamp = TimeSpan.Zero;
actionEventTarget goNextEventTarget=null;
actionEventTarget goBackEventTarget=null;
bool change = false;
public TimeSpan TimeStamp {
get {
return timeStamp;
}
}
public int IndexLigneEnCours
{
get {
if (enCours == null) return -1;
return lignes.IndexOf(enCours);
}
}
Ligne aSuivre = null;
public int IndexLigneaSuivre
{
get {
if (aSuivre == null)
return -1;
return lignes.IndexOf (aSuivre);
}
set {
aSuivre = lignes[value];
}
}
public void EffetSuivant ()
{
lock (this) {
Conduite.Courante.CircuitTelecomande.Clear();
if(lignes.Count==0) return;
if (aSuivre == null) {
if (IndexLigneEnCours + 1 < lignes.Count)
enCours = lignes [IndexLigneEnCours + 1];
else
enCours = lignes [0];
} else {
enCours = aSuivre;
}
aSuivre = null;
timeStamp = TimeSpan.Zero;
change = true;
LanceSequenceurs();
}
}
public void EffetPrecedent ()
{
lock (this) {
if(lignes.Count==0) return;
if (IndexLigneEnCours > 0)
enCours = lignes [IndexLigneEnCours - 1];
else
enCours = lignes [0];
aSuivre = null;
timeStamp = TimeSpan.Zero;
change = true;
LanceSequenceurs();
}
}
void LanceSequenceurs ()
{
foreach (Sequenceur s in Conduite.Courante.Sequenceurs) {
if(enCours[s].Length > 0)
s.Command(enCours[s]);
}
}
public string[] GetCommands(Sequenceur s)
{
string[] res = new string[lignes.Count];
for (int i = 0; i < lignes.Count; i++) {
res[i] = lignes[i][s];
}
return res;
}
public void SetCommands (Sequenceur s, string[] commands)
{
lock (this) {
for (int i = 0; i < Math.Max(lignes.Count,commands.Length); i++) {
lignes [i] [s] = commands [i];
}
change= true;
}
}
public ReadOnlyCollection Lignes {
get {
return lignes.AsReadOnly();
}
}
public SequenceurMaitre ()
{
//lignes.Add(new Ligne());
goNextEventTarget = new actionEventTarget(
delegate(EventData data){
if(data.value==255) EffetSuivant();
return true;
});
goBackEventTarget = new actionEventTarget(
delegate(EventData data){
if(data.value==255) EffetPrecedent();
return true;
});
}
public int AjoutLigne (int pos)
{
lock (this) {
lignes.Insert (pos, new Ligne ());
return pos;
}
}
public void RetireLigne (int pos)
{
lock (this) {
if(pos<0 || pos >= lignes.Count) return;
if(lignes[pos]== enCours)
{
enCours=null;
if(pos+1 < lignes.Count)
aSuivre = lignes[pos+1];
}
if(lignes[pos] == aSuivre)
aSuivre=null;
lignes.RemoveAt(pos);
}
}
public void Tick (TimeSpan deltaT)
{
timeStamp += deltaT;
if(enCours != null)
if (enCours.Duree != TimeSpan.Zero && enCours.Duree <= timeStamp ) {
EffetSuivant();
}
}
public bool EffetChange ()
{
if (change) {
change = false;
return true;
}
return false;
}
public void BindEffetSuivant (string eventId)
{
if (eventId.Length == 0) {
Conduite.Courante.EventManager.Unbind (goNextEventTarget);
return;
}
Conduite.Courante.EventManager.Bind(eventId,goNextEventTarget);
}
public void BindEffetPrecedent (string eventId)
{
if (eventId.Length == 0) {
Conduite.Courante.EventManager.Unbind (goBackEventTarget);
return;
}
Conduite.Courante.EventManager.Bind(eventId,goBackEventTarget);
}
public void Save (XmlElement parent)
{
XmlElement el = parent.OwnerDocument.CreateElement("SequenceurMaitre");
parent.AppendChild(el);
foreach(Ligne l in lignes)
l.Save(el);
XmlElement xmlEl = parent.OwnerDocument.CreateElement ("EffetSuivant");
if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl);
xmlEl = parent.OwnerDocument.CreateElement ("EffetPrecedent");
if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl);
}
public static SequenceurMaitre Load (Conduite c, XmlElement el)
{
SequenceurMaitre seq = new SequenceurMaitre ();
foreach (var xl in el.GetElementsByTagName("Ligne")) {
seq.lignes.Add(Ligne.Load(c,xl as XmlElement));
}
XmlElement xmlE;
if ((xmlE = el["EffetSuivant"])!= null)
foreach(string id in EventManager.LoadBindings(xmlE))
seq.BindEffetSuivant(id);
if ((xmlE = el["EffetPrecedent"])!= null)
foreach(string id in EventManager.LoadBindings(xmlE))
seq.BindEffetPrecedent(id);
return seq;
}
}
}