using System; using Gtk; using System.Collections.Generic; using System.Diagnostics; using System.IO; namespace DMX2 { public partial class MainWindow: Gtk.Window { static MainWindow win; static object circuitKey = new object(); ListStore lsMatrice = null; FileInfo conduiteFile=null; public static MainWindow Win { get { return win; } } public MainWindow (): base (Gtk.WindowType.Toplevel) { win=this; Build (); MajWidgets(); ContextMenuHelper ctxHelper = new ContextMenuHelper(); ctxHelper.ContextMenu += EventPopup; ctxHelper.AttachToWidget(btnGo); ctxHelper.AttachToWidget(btnGoBack); ctxHelper.AttachToWidget(masterScale); } void EventPopup (object sender, ContextMenuEventArgs e) { Menu m = Conduite.Courante.EventManager.GetMenu(e.Widget.Name, delegate(object o,string eventId){ switch(o as string){ case "btnGo": Conduite.Courante.SequenceurMaitre.BindEffetSuivant(eventId); break; case "btnGoBack": Conduite.Courante.SequenceurMaitre.BindEffetPrecedent(eventId); break; case "masterScale": Conduite.Courante.BindMaster(eventId); break; } } ); m.ShowAll(); m.Popup(); } #region Sequenceur Maitre protected void ConstruitMatrice () { this.MatriceUI.EnableGridLines = TreeViewGridLines.Both; var idCol = new Gtk.TreeViewColumn (); var idCell = new Gtk.CellRendererText (); idCol.Title = "Num"; idCol.PackStart (idCell, true); idCol.SetCellDataFunc (idCell, new Gtk.TreeCellDataFunc (RenderMatriceNum)); this.MatriceUI.AppendColumn (idCol); var nomCol = new Gtk.TreeViewColumn (); var nomCell = new Gtk.CellRendererText (); nomCol.Title = "Nom"; nomCol.PackStart (nomCell, true); nomCol.SetCellDataFunc (nomCell, new Gtk.TreeCellDataFunc (RenderMatriceNom)); nomCell.Editable = true; nomCell.Edited += OnNomCellEdited; this.MatriceUI.AppendColumn (nomCol); var dureeCol = new Gtk.TreeViewColumn (); var dureeCell = new Gtk.CellRendererText (); dureeCol.Title = "Durée"; dureeCol.PackStart (dureeCell, true); dureeCol.SetCellDataFunc (dureeCell, new Gtk.TreeCellDataFunc (RenderMatriceDuree)); dureeCell.Editable = true; dureeCell.Edited += OnDureeCellEdited; this.MatriceUI.AppendColumn (dureeCol); lsMatrice = new Gtk.ListStore(typeof (SequenceurMaitre.Ligne)); this.MatriceUI.Model = lsMatrice; FillMatrice(); } void DetruitMatrice () { this.MatriceUI.Model = null; if (lsMatrice != null) lsMatrice.Dispose(); foreach (var col in MatriceUI.Columns) MatriceUI.RemoveColumn (col); } static object seqkey = new object(); void ConstruitMatriceSeqColumns () { foreach(var c in MatriceUI.Columns) if(c.CellRenderers[0].Data.ContainsKey(seqkey)) MatriceUI.RemoveColumn(c); Gtk.TreeViewColumn seqCol; Gtk.CellRendererText seqCell; foreach (Sequenceur seq in Conduite.Courante.Sequenceurs) { seqCol = new TreeViewColumn(); seqCell = new CellRendererText(); seqCol.Title = seq.Name; seqCol.PackStart(seqCell, true); seqCol.SetCellDataFunc ( seqCell, new Gtk.TreeCellDataFunc(RenderMatriceSeqVal)); seqCell.Editable = true; seqCell.Edited += OnSeqValCellEdited; seqCell.Data[seqkey] = seq; this.MatriceUI.AppendColumn(seqCol); } } void RenderMatriceNum (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) { if (Conduite.Courante==null) return; string num=string.Empty; SequenceurMaitre.Ligne l = tree_model.GetValue (iter, 0) as SequenceurMaitre.Ligne; if( Conduite.Courante.SequenceurMaitre.IndexLigneEnCours == Conduite.Courante.SequenceurMaitre.Lignes.IndexOf(l) ) num+= "->"; if( Conduite.Courante.SequenceurMaitre.IndexLigneaSuivre == Conduite.Courante.SequenceurMaitre.Lignes.IndexOf(l) ) num+= "* "; (cell as Gtk.CellRendererText).Text = num + (Conduite.Courante.SequenceurMaitre.Lignes.IndexOf(l)+1).ToString(); } void RenderMatriceNom (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) { if (Conduite.Courante==null) return; SequenceurMaitre.Ligne l = tree_model.GetValue (iter, 0) as SequenceurMaitre.Ligne; (cell as Gtk.CellRendererText).Text = l.Nom; } void RenderMatriceDuree (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) { if (Conduite.Courante==null) return; SequenceurMaitre.Ligne l = tree_model.GetValue (iter, 0) as SequenceurMaitre.Ligne; if (l.Duree== TimeSpan.Zero) (cell as Gtk.CellRendererText).Text = string.Empty; else (cell as Gtk.CellRendererText).Text = (l.Duree.TotalMilliseconds /100).ToString(); } void RenderMatriceSeqVal (TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) { if (Conduite.Courante==null) return; SequenceurMaitre.Ligne l = tree_model.GetValue (iter, 0) as SequenceurMaitre.Ligne; Sequenceur seq = cell.Data[seqkey] as Sequenceur; (cell as Gtk.CellRendererText).Text = l[seq]; } void FillMatrice () { lsMatrice.Clear (); foreach (SequenceurMaitre.Ligne l in Conduite.Courante.SequenceurMaitre.Lignes) { lsMatrice.AppendValues(l); } } void OnNomCellEdited (object o, EditedArgs args) { Gtk.TreeIter iter; lsMatrice.GetIter (out iter, new Gtk.TreePath (args.Path)); SequenceurMaitre.Ligne l = lsMatrice.GetValue(iter,0) as SequenceurMaitre.Ligne; l.Nom = args.NewText; } void OnDureeCellEdited (object o, EditedArgs args) { Gtk.TreeIter iter; lsMatrice.GetIter (out iter, new Gtk.TreePath (args.Path)); SequenceurMaitre.Ligne l = lsMatrice.GetValue (iter, 0) as SequenceurMaitre.Ligne; if (args.NewText.Length == 0) l.Duree = TimeSpan.Zero; else { int val; if(int.TryParse(args.NewText, out val)) l.Duree = TimeSpan.FromMilliseconds(val *100); } } void OnSeqValCellEdited (object o, EditedArgs args) { Gtk.CellRendererText cell = o as CellRendererText; Sequenceur seq = cell.Data[seqkey] as Sequenceur; Gtk.TreeIter iter; lsMatrice.GetIter (out iter, new Gtk.TreePath (args.Path)); SequenceurMaitre.Ligne l = lsMatrice.GetValue(iter,0) as SequenceurMaitre.Ligne; l[seq] = args.NewText; } int IndexEffetSelectionne() { var sel = MatriceUI.Selection.GetSelectedRows(); if(sel.Length ==0) return -1; return MatriceUI.Selection.GetSelectedRows()[0].Indices[0]; } void SelectionneEffet (int index) { if(index <0 ) return; MatriceUI.SetCursor( new TreePath( new int[1] {index }) ,null,false); } protected void OnBtnAjoutLigneClicked (object sender, EventArgs e) { int pos=IndexEffetSelectionne() + 1; Conduite.Courante.SequenceurMaitre.AjoutLigne(pos); FillMatrice(); MatriceUI.SetCursor( new TreePath( new int[1] {pos }) , MatriceUI.Columns[1] ,true); } protected void OnBtnRetireLigneClicked (object sender, EventArgs e) { if(IndexEffetSelectionne()==-1) return; Conduite.Courante.SequenceurMaitre.RetireLigne(IndexEffetSelectionne()); FillMatrice(); } protected void OnBtnGoBackClicked (object sender, EventArgs e) { Conduite.Courante.SequenceurMaitre.EffetPrecedent(); //FillMatrice(); } protected void OnBtnGoClicked (object sender, EventArgs e) { Conduite.Courante.SequenceurMaitre.EffetSuivant(); //FillMatrice(); } protected void OnMatriceUICursorChanged (object sender, EventArgs e) { if (Conduite.Courante==null) return; TreeViewColumn col; TreePath path; MatriceUI.GetCursor (out path, out col); if (MatriceUI.Columns [0] == col) { Conduite.Courante.SequenceurMaitre.IndexLigneaSuivre = IndexEffetSelectionne(); } } #endregion #region Application protected void OnDeleteEvent (object sender, DeleteEventArgs a) { Application.Quit (); a.RetVal = true; } protected void OnQuitActionActivated (object sender, EventArgs e) { Application.Quit (); } #endregion #region Gestion de la Conduite protected void OnNewActionActivated (object sender, EventArgs e) { var dlg = new Dialog ("Nom ?", this, DialogFlags.Modal); var entry = new Entry ("Conduite sans Nom"); dlg.AddButton (Stock.Ok, ResponseType.Ok).GrabDefault(); dlg.AddButton (Stock.Cancel, ResponseType.Cancel); dlg.VBox.Add (new Label("Nom de la nouvelle Conduite :")); dlg.VBox.Add (entry); dlg.VBox.ShowAll (); entry.ActivatesDefault=true; if ((ResponseType)dlg.Run () == ResponseType.Ok) { Conduite.Courante = new Conduite (); Conduite.Courante.Name = entry.Text; } MajWidgets(); dlg.Destroy(); } protected void OnCloseActionActivated (object sender, EventArgs e) { Conduite.Courante.Dispose(); Conduite.Courante= null; MajWidgets(); } protected void OnSaveActionActivated (object sender, EventArgs e) { if(conduiteFile==null) SaveFileAs(); else SaveFile(); } protected void OnSaveAsActionActivated (object sender, EventArgs e) { SaveFileAs(); } void SaveFileAs () { FileChooserDialog fcd = new FileChooserDialog ("Sauver sous ...", this, FileChooserAction.Save, "Annuler", ResponseType.Cancel, "Enregistrer", ResponseType.Accept); fcd.Filter = new FileFilter (); fcd.Filter.AddPattern ("*.dmx2"); bool ok = false; while (!ok) { if ((ResponseType)fcd.Run () == ResponseType.Cancel) { fcd.Destroy (); return; } string file = fcd.Filename; if (!file.EndsWith (".dmx2")) file += ".dmx2"; conduiteFile = new FileInfo(file); if(conduiteFile.Exists) { MessageDialog msg = new MessageDialog(fcd,DialogFlags.Modal, MessageType.Warning, ButtonsType.YesNo, "Le fichier existe déja. \nVoulez vous écraser le fichier existant ?"); if ((ResponseType)msg.Run () == ResponseType.Yes)ok=true; msg.Destroy(); } else ok=true; } fcd.Destroy(); SaveFile(); } void SaveFile () { if (conduiteFile == null) return; using (FileStream stream = conduiteFile.Open(FileMode.Create,FileAccess.Write)) { System.Xml.XmlDocument doc = Conduite.Courante.Save (); doc.Save (stream); stream.Close (); } } protected void OnOpenActionActivated (object sender, EventArgs e) { FileChooserDialog fcd = new FileChooserDialog ("Sauver sous ...", this, FileChooserAction.Open, "Annuler", ResponseType.Cancel, "Ouvrir", ResponseType.Accept); fcd.Filter = new FileFilter (); fcd.Filter.AddPattern ("*.dmx2"); if ((ResponseType)fcd.Run () == ResponseType.Cancel) { fcd.Destroy (); return; } FileInfo openFile = new FileInfo (fcd.Filename); fcd.Destroy (); if (!openFile.Exists) return; System.Xml.XmlDocument doc; try { using(FileStream stream = openFile.OpenRead()) { doc = new System.Xml.XmlDocument(); doc.Load(stream); stream.Close(); } Conduite cond = Conduite.Load(doc); if (cond==null) { // TODO Message erreur au chargement return; } Conduite.Courante = cond; conduiteFile = openFile; } catch (IOException) { } foreach (Sequenceur s in Conduite.Courante.Sequenceurs) AddSeqUI (s); MajWidgets(); NextUpdateFull(); } #endregion #region Gestion des Circuits protected void OnCircuitsActionActivated (object sender, EventArgs e) { GestionCircuits gc= new GestionCircuits(this); gc.Run(); gc.Destroy(); NextUpdateFull(); } #endregion #region Gestion des Sequenceurs // bonton ajout de sequenceur linéraire protected void OnSeqLinActionActivated (object sender, EventArgs e) { Sequenceur s = new SequenceurLineaire(); Conduite.Courante.AjoutSequenceur(s); AddSeqUI(s); NextUpdateFull(); } void AddSeqUI (Sequenceur s) { onglets.AppendPage(s.GetUI(),new Gtk.Label(s.Name)); onglets.ShowAll(); } protected void OnShowAllActionActivated (object sender, EventArgs e) { foreach (var notebookchild in onglets.Children) notebookchild.Destroy(); foreach (Sequenceur s in Conduite.Courante.Sequenceurs) AddSeqUI(s); } protected void OnSeqMacroActionActivated (object sender, EventArgs e) { Sequenceur s = new SequenceurMacro(); Conduite.Courante.AjoutSequenceur(s); AddSeqUI(s); NextUpdateFull(); } #endregion #region Gestion de l'affichage bool updScheduled=false; bool fullUpdateFlag=false; public void NextUpdateFull () { fullUpdateFlag=true; } public void ScheduleUpdate () { if (updScheduled) { //Console.WriteLine("{0} Skip !",DateTime.Now); return; } updScheduled=true; Gtk.Application.Invoke(new EventHandler(Update)); } void Update (object sender, EventArgs e) { lblInfo.Text = Info.GetInfo(); if(Conduite.Courante==null)return; foreach (var notebookchild in onglets.Children) { SequenceurUI sequi = notebookchild as SequenceurUI; if(sequi != null) sequi.Update(fullUpdateFlag); } MajCircuits(fullUpdateFlag); timeLabel.LabelProp = string.Format (@"{0:0\.0}", Conduite.Courante.SequenceurMaitre.TimeStamp.TotalMilliseconds / 100); if(fullUpdateFlag) ConstruitMatriceSeqColumns(); if( Conduite.Courante.SequenceurMaitre.EffetChange() )MatriceUI.QueueDraw(); fullUpdateFlag=false; masterScale.Value = Conduite.Courante.Master; updScheduled=false; } protected void MajWidgets () { if (Conduite.Courante != null) { //Activation / Désactivation des boutons en fonction de l'état de la counduite courante btnAjoutLigne.Sensitive = btnRetireLigne.Sensitive = btnGo.Sensitive = btnGoBack.Sensitive = showAllAction.Sensitive = universAction.Sensitive = masterScale.Sensitive = seqLinAction.Sensitive = seqMacroAction.Sensitive = circAction.Sensitive = saveAction.Sensitive = btnPause.Sensitive = btnBlackOut.Sensitive = saveAsAction.Sensitive = closeAction.Sensitive = true; openAction.Sensitive = newAction.Sensitive = false; this.Title = "DMX 2.0 - " + Conduite.Courante.Name; ConstruitMatrice(); } else { btnAjoutLigne.Sensitive = btnRetireLigne.Sensitive = btnGo.Sensitive = btnGoBack.Sensitive = showAllAction.Sensitive = universAction.Sensitive = masterScale.Sensitive = seqLinAction.Sensitive = seqMacroAction.Sensitive = circAction.Sensitive = saveAction.Sensitive = btnPause.Sensitive = btnBlackOut.Sensitive = saveAsAction.Sensitive = closeAction.Sensitive = false; openAction.Sensitive = newAction.Sensitive = true; this.Title = "DMX 2.0"; DetruitMatrice(); foreach (var widget in vboxCircuits.Children) vboxCircuits.Remove (widget); foreach (var notebookvbox in onglets.Children) notebookvbox.Destroy(); } } protected void MajCircuits (bool full) { // Ajoute une ProgressBar par circuit, met a jour le texte si necessaire ProgressBar pb;int i = 0; if (full) { foreach (var widget in vboxCircuits.Children) vboxCircuits.Remove (widget); foreach (var circuit in Conduite.Courante.Circuits) { vboxCircuits.PackStart (pb=new ProgressBar (),false,false,0); pb.Text = (++i).ToString() + " - " + circuit.Name; pb.HeightRequest = 12; pb.Data[circuitKey] = circuit; pb.Name ="pb"; } vboxCircuits.ShowAll (); } foreach (var widget in vboxCircuits.Children) { pb = (ProgressBar)widget; pb.Fraction = (double) (pb.Data[circuitKey] as Circuit).ValeurCourante / 255; } } #endregion protected void OnMasterScaleValueChanged (object sender, EventArgs e) { if(!updScheduled) Conduite.Courante.Master = (int)(masterScale.Value); ChangeCouleurInfo(); } bool isfullscreen=false; protected void OnFullscreenAction1Activated (object sender, EventArgs e) { if (!isfullscreen) { Fullscreen (); isfullscreen = true; } else { Unfullscreen(); isfullscreen = false; } } #region Boite dialogue Univers EditionUnivers uDlg = null; protected void OnUniversActionActivated (object sender, EventArgs e) { if (uDlg != null) { uDlg.Show(); return; } uDlg = new EditionUnivers(this); uDlg.ShowAll(); uDlg.Destroyed += udlgDestroyed; } void udlgDestroyed (object sender, EventArgs e) { uDlg=null; } #endregion protected void OnConnectActionActivated (object sender, EventArgs e) { Conduite.Courante.Drivers.Add( new DriverBoitierV1()); } protected void OnBtnPauseToggled (object sender, EventArgs e) { Conduite.Courante.Pause = btnPause.Active; ChangeCouleurInfo(); } protected void OnBtnBlackOutToggled (object sender, EventArgs e) { Conduite.Courante.BlackOut = btnBlackOut.Active; ChangeCouleurInfo(); } void ChangeCouleurInfo () { if (Conduite.Courante.BlackOut) { evInfo.ModifyBg (Gtk.StateType.Normal,new Gdk.Color (255, 100, 100)); return; } if (Conduite.Courante.Pause) { evInfo.ModifyBg (Gtk.StateType.Normal,new Gdk.Color (255, 255, 100)); return; } if (Conduite.Courante.Master != 100) { evInfo.ModifyBg (Gtk.StateType.Normal,new Gdk.Color (205, 205, 255)); return; } evInfo.ModifyBg (Gtk.StateType.Normal, this.Style.Background(StateType.Normal) ); } protected void OnSelectColorActionActivated (object sender, EventArgs e) { if(System.IO.File.Exists("style.gtkrc")) Gtk.Rc.Parse("style.gtkrc"); else using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("style.gtkrc")) using (System.IO.TextReader reader = new System.IO.StreamReader(stream)) Gtk.Rc.ParseString (reader.ReadToEnd()); this.ResetRcStyles(); } } }