Advertisement
thebys

DSDCG mainform 05012013

Jan 4th, 2013
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using DSDCG.Models;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Data;
  10. using System.Windows.Documents;
  11. using System.Windows.Input;
  12. using System.Windows.Media;
  13. using System.Windows.Media.Imaging;
  14. using System.Windows.Navigation;
  15. using System.Windows.Shapes;
  16. using System.IO;
  17. using System.Reflection;
  18. using System.Threading;
  19. using DSDCG.Workers;
  20.  
  21.  
  22. namespace DSDCG
  23. {
  24.     /// <summary>
  25.     /// Interaction logic for MainWindow.xaml
  26.     /// </summary>
  27.     public partial class MainWindow : Window
  28.     {
  29.         public MediaItem _activeItem;
  30.         public Container _activeContainer;
  31.         public Container Storyboard;
  32.         //něco nám užírá CIDy, asi při manipulaci s kontejnerama se někde něco pořád tvoří... tick, vyřešeno
  33.         //něco způsobuje, že se neukládá / nepřenáší / nenačítá čas...
  34.         public int currentCID = 1; //storyboard má 1, další kontejnery maj 2 a furt nahoru...
  35.         public int currentMID = 1; //není žádný rootitem takže první přidělujeme jedničku...
  36.         public MainWindow()
  37.         {
  38.             InitializeComponent();
  39.             Storyboard = new Container(currentCID, "Storyboard", new TimeSpan(0, 0, 0));
  40.             currentCID++;
  41.             _activeContainer = new Container(currentCID, "Kontejner 1", new TimeSpan(0, 0, 30));
  42.             currentCID++;
  43.             LoadActiveContainer(_activeContainer);
  44.             this.Storygrid.Children.Add(DrawSomething(Storyboard)); //vykreslíme /root kontejner
  45.         }
  46.  
  47.         #region obsluha formu
  48.         private void Button_Click_1(object sender, RoutedEventArgs e) //opensinglefiledialog
  49.         {
  50.             Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
  51.             dlg.Filter = "soubory obrázků |*.jpg;*.jpeg;*.png;*.bmp;*.gif|soubory videa |*.avi;*.mp4;*.mkv;*.wmv"; // Filter files by extension
  52.             Nullable<bool> result = dlg.ShowDialog();
  53.  
  54.             // Process open file dialog box results
  55.             if (result == true)
  56.             {
  57.                 // Open document
  58.                 MediaItemType newitemtype = MediaItemType.text;
  59.                 FileInfo fi = new FileInfo(dlg.FileName);
  60.                 if (fi.Extension == ".jpg" || fi.Extension == ".jpeg" || fi.Extension == ".png" || fi.Extension == ".bmp" || fi.Extension == ".gif")
  61.                 {
  62.                     newitemtype = MediaItemType.image;
  63.                 }
  64.                 else if (fi.Extension == ".avi" || fi.Extension == ".mp4" || fi.Extension == ".mkv" || fi.Extension == ".wmv")
  65.                 {
  66.                     newitemtype = MediaItemType.video;
  67.                 }
  68.                 _activeItem = new MediaItem(currentMID, dlg.SafeFileName, System.IO.Path.GetDirectoryName(dlg.FileName), newitemtype, string.Empty, string.Empty, new TimeSpan(0, 0, 10));
  69.                 currentMID++;
  70.                 LoadActiveItem(_activeItem);
  71.             }
  72.         }
  73.         private void SaveStoryboardButton_Click(object sender, RoutedEventArgs e)//savefiledialog - pouze ukládá storyboard.xml nekonsoliduje...
  74.         {
  75.             Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  76.             dlg.Filter = "Nekonsolidovaný storyboard |*.sb"; // Filter files by extension
  77.             Nullable<bool> result = dlg.ShowDialog();
  78.             if (result == true)
  79.             {
  80.                 //budeme muset konsolidovat zdroje... řešit složky...
  81.                 //a všechno to správně seserializovat a uložit a zabalit a udělat reverzní operace...
  82.                 Serializer serializer1 = new Serializer();
  83.                 //ask about saving changes maybe?
  84.                 serializer1.SerializeStoryboard(Storyboard, dlg.FileName, false, dlg.SafeFileName);
  85.             }
  86.  
  87.         }
  88.         private void LoadStoryboardButton_Click(object sender, RoutedEventArgs e)//openfiledialog - načítá pouze nekonsolidované kampaně
  89.         {
  90.             Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
  91.             dlg.Filter = "Nekonsolidovaný storyboard |*.sb"; // Filter files by extension
  92.             Nullable<bool> result = dlg.ShowDialog();
  93.             if (result == true)
  94.             {
  95.                 Serializer serializer1 = new Serializer();
  96.                 //ask about saving changes maybe?
  97.                 Storyboard = serializer1.DeserializeStoryboard(dlg.FileName);
  98.                 //a překreslíme:
  99.                 redraw();
  100.             }
  101.         }
  102.         private void ExportButton_Click_1(object sender, RoutedEventArgs e)//konsoliduje soubory a tím finalizuje storyboard k přehrávání.
  103.         {
  104.             string boardroot;
  105.             Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  106.             dlg.Filter = "Konsolidovaný storyboard |*.ksb"; // Filter files by extension
  107.             Nullable<bool> result = dlg.ShowDialog();
  108.             if (result == true)
  109.             {
  110.                 boardroot = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(dlg.FileName));
  111.                 //budeme muset konsolidovat zdroje... řešit složky...
  112.                 //a všechno to správně seserializovat a uložit a zabalit a udělat reverzní operace...
  113.                 Konsolidator konsolidator1 = new Konsolidator();
  114.                 Serializer serializer1 = new Serializer();
  115.                 //ask about saving changes maybe?
  116.                 konsolidator1.ConsolidateStoryboard(Storyboard, boardroot);
  117.                 serializer1.SerializeStoryboard(Storyboard, boardroot, true, dlg.SafeFileName);
  118.             }
  119.         }
  120.         private void saveitembutton_Click(object sender, RoutedEventArgs e)
  121.         {
  122.             SaveActiveItem();
  123.             redraw();
  124.         } //uloží změny z formu do activeitemu
  125.         private void discarditemchangesbutton_Click(object sender, RoutedEventArgs e)
  126.         {
  127.             LoadActiveItem(_activeItem);
  128.         } //odmaže změny - vrátí co je v _activeitemu
  129.         private void discardcontainerchanges_Click(object sender, RoutedEventArgs e)
  130.         {
  131.             LoadActiveContainer(_activeContainer);
  132.         } //odmaže změny - vrátí co je v activecontaineru
  133.         private void DeleteActiveItemButton_Click(object sender, RoutedEventArgs e)//smaže aktivní item
  134.         {
  135.             DeleteItem(_activeItem);
  136.             redraw();
  137.         }
  138.         private void savecontainer_Click(object sender, RoutedEventArgs e)//uloží změny z formuláře do aktivního kontejneru
  139.         {
  140.             SaveActiveContainer();
  141.             redraw();
  142.         }
  143.         private void addtocontainer_Click(object sender, RoutedEventArgs e)
  144.         {
  145.             //changedvalues keep/discard dialog here...
  146.             _activeContainer.mediaItems.Add(new MediaItem(_activeItem.MID, _activeItem.name, _activeItem.path, _activeItem.type.Value, _activeItem.title, _activeItem.text, _activeItem.duration));
  147.             //a překreslíme:
  148.             redraw();
  149.         } //přidá do aktivního kontejneru aktivní media item...
  150.         private void CreateInActiveButton_Click(object sender, RoutedEventArgs e)
  151.         {
  152.             Container newcont = new Container();
  153.             newcont.name = this.containername.Text;
  154.             newcont.cid = currentCID;
  155.             currentCID++;
  156.             newcont.behaviour = (Behaviour)this.containerbehaviour.SelectedItem;
  157.             try
  158.             {
  159.                 newcont.duration = TimeSpan.Parse(this.containerduration.Text);
  160.                 _activeContainer.containers.Add(newcont);
  161.  
  162.             }
  163.             catch
  164.             {
  165.                 MessageBox.Show("Čas se nepodařilo rozparsovat, uveďte jej prosím ve správném formátu");
  166.                 LoadActiveContainer(newcont);
  167.  
  168.             }
  169.             finally { redraw(); }
  170.  
  171.         } //vytvoří z dat ve formu kontejner do aktivního kontejneru
  172.         private void DeleteActiveContainer_Click(object sender, RoutedEventArgs e)
  173.         {
  174.             DeleteContainer(_activeContainer.cid);
  175.             redraw();
  176.         } //odmaže aktivní kontejner a všechny subkontejnery
  177.  
  178.         private void redrawButton_Click(object sender, RoutedEventArgs e)
  179.         {
  180.             redraw();
  181.         } //znovuvykreslovací tlačítko boardu.
  182.         void itembtn_Click(object sender, RoutedEventArgs e)
  183.         {
  184.             ItemButton clickeditem = sender as ItemButton;
  185.             _activeItem = clickeditem.RelatedMediaItem;
  186.             LoadActiveItem(_activeItem);
  187.         } //co se stane když někdo klikne na mediaitembutton
  188.         void congrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  189.         {
  190.             e.Handled = true;
  191.             BoardGrid contgrid = new BoardGrid();
  192.             contgrid = sender as BoardGrid;
  193.             contgrid.RelatedContainer.contbrush = contgrid.Background;
  194.             _activeContainer = contgrid.RelatedContainer;
  195.             LoadActiveContainer(contgrid.RelatedContainer);
  196.         } //selektor kontejnerů na kliknutí...
  197.  
  198.         private void exit_Click(object sender, RoutedEventArgs e)
  199.         {
  200.             Application.Current.Shutdown();
  201.         } //exitovací tlačítko :)
  202.         #endregion
  203.  
  204.         #region methods
  205.         public void redraw() //znovuvykreslovací metoda storyboardu...
  206.         {
  207.             Storygrid.Children.Clear();
  208.             this.Storygrid.Children.Add(DrawSomething(Storyboard));
  209.         }
  210.         private void LoadActiveItem(MediaItem ItemToBeLoaded) //načte _activeitem do formu...
  211.         {
  212.             this.filename.Text = ItemToBeLoaded.name;
  213.             this.filepath.Text = ItemToBeLoaded.path;
  214.             this.filepath.ToolTip = ItemToBeLoaded.path;
  215.             this.filetype.SelectedItem = ItemToBeLoaded.type;
  216.             try
  217.             {
  218.                 this.title.Text = _activeItem.title;
  219.             }
  220.             catch (Exception)
  221.             {
  222.                 this.title.Text = string.Empty;
  223.             }
  224.             try
  225.             {
  226.                 this.text.Text = _activeItem.text;
  227.             }
  228.             catch (Exception)
  229.             {
  230.                 this.text.Text = string.Empty;
  231.             }
  232.             try
  233.             {
  234.                 this.duration.Text = _activeItem.duration.ToString();
  235.             }
  236.             catch (Exception)
  237.             {
  238.                 this.duration.Text = new TimeSpan(0, 13, 37).ToString();
  239.             }
  240.         }
  241.         private void SaveActiveItem() //savne data z formu do _activeitem
  242.         {
  243.             _activeItem.name = this.filename.Text;
  244.             _activeItem.path = this.filepath.Text;
  245.             _activeItem.type = (MediaItemType)this.filetype.SelectedItem;
  246.             _activeItem.title = this.title.Text;
  247.             _activeItem.text = this.text.Text;
  248.             try
  249.             {
  250.                 _activeItem.duration = TimeSpan.Parse(this.duration.Text);
  251.             }
  252.             catch
  253.             {
  254.                 MessageBox.Show("Čas se nepodařilo rozparsovat, uveďte jej prosím ve správném formátu");
  255.                 LoadActiveItem(_activeItem);
  256.             }
  257.         }
  258.         private void LoadActiveContainer(Container ContainerToBeLoaded) //načte _activecontainer do formu
  259.         {
  260.             this.containername.Text = ContainerToBeLoaded.name;
  261.             this.ActiveContainerNameLabel.Content = ContainerToBeLoaded.name;
  262.             try
  263.             {
  264.                 this.containerbehaviour.SelectedItem = ContainerToBeLoaded.behaviour;
  265.             }
  266.             catch
  267.             {
  268.             }
  269.             if (ContainerToBeLoaded.contbrush != null)
  270.             {
  271.                 ActiveContainerBorder.BorderBrush = ContainerToBeLoaded.contbrush;
  272.             }
  273.             else
  274.             {
  275.                 ActiveContainerBorder.BorderBrush = Brushes.Transparent;
  276.             }
  277.             if (_activeContainer.duration != null)
  278.             {
  279.                 this.containerduration.Text = _activeContainer.duration.ToString();
  280.             }
  281.             if (_activeContainer.duration == null)
  282.             {
  283.                 this.containerduration.Text = new TimeSpan(0, 0, 20).ToString();
  284.             }
  285.         }
  286.         private void SaveActiveContainer() //načte data z formu do _activecontainer
  287.         {
  288.             _activeContainer.name = this.containername.Text;
  289.             _activeContainer.behaviour = (Behaviour)this.containerbehaviour.SelectedItem;
  290.             try
  291.             {
  292.                 _activeContainer.duration = TimeSpan.Parse(this.containerduration.Text);
  293.             }
  294.             catch
  295.             {
  296.                 MessageBox.Show("Čas se nepodařilo rozparsovat, uveďte jej prosím ve správném formátu");
  297.                 LoadActiveContainer(_activeContainer);
  298.             }
  299.         }
  300.         private void UpdateContainer(int cid, Container newcont) //první část rekurzivního procházení kontejnerů...
  301.         {
  302.             if (cid == 1)
  303.             {
  304.                 Storyboard = newcont;
  305.             }
  306.             else
  307.             {
  308.                 Container ContainerToUpdate = new Container();
  309.                 ContainerToUpdate = searchContainerByID(cid, Storyboard, false);
  310.                 if (ContainerToUpdate != null || ContainerToUpdate.cid != 0)
  311.                 {
  312.                     ContainerToUpdate = newcont;
  313.                 }
  314.             }
  315.  
  316.  
  317.         }
  318.         private Container searchContainerByID(int cid, Container startcont, bool returnParent) //rekurzivní procházecí funkce kontejnerů, používám ji abych mohl editovat storyboard
  319.         {
  320.             //Storyboard.containers.Find(delegate(Container c) { return c.cid == cid; }); alternativní vyhledávací metoda
  321.             if (!returnParent)
  322.             {
  323.                 if (startcont.cid == cid)
  324.                 {
  325.                     return startcont;
  326.                 }
  327.                 else
  328.                 {
  329.                     foreach (Container cont in startcont.containers)
  330.                     {
  331.                         return (searchContainerByID(cid, cont, returnParent));
  332.                     }
  333.                     return null;
  334.                 }
  335.             }
  336.             else
  337.             {
  338.                 foreach (Container cont in startcont.containers)
  339.                 {
  340.  
  341.                     if (cont.cid == cid)
  342.                     {
  343.                         return startcont;
  344.                     }
  345.                     else
  346.                     {
  347.                         return (searchContainerByID(cid, cont, true));
  348.                     }
  349.                 }
  350.                 return null;
  351.             }
  352.  
  353.  
  354.         }
  355.         private Container searchContainerByMID(int MID, Container startcont) //najde kontejner obsahující MID
  356.         {
  357.             if (startcont.mediaItems.Find(delegate(MediaItem item)
  358.             {
  359.                 return item.MID == MID;
  360.             }) != null)
  361.             {
  362.                 return startcont;
  363.             }
  364.             else
  365.             {
  366.                 foreach (Container cont in startcont.containers)
  367.                 {
  368.                     return searchContainerByMID(MID, cont);
  369.                 }
  370.             }
  371.             return null;
  372.         }
  373.         public TextBlock GenerateGridTextBlock(string text, int fontsize, Thickness paddingThickness, int row, int col)
  374.         {
  375.             TextBlock newblock = new TextBlock();
  376.             newblock.Text = text;
  377.             newblock.FontSize = fontsize;
  378.             newblock.Padding = paddingThickness;
  379.             Grid.SetRow(newblock, row);
  380.             Grid.SetColumn(newblock, col);
  381.             return newblock;
  382.         } //šikovná věcička, ušetřila mi spoustu řádků textblocků
  383.         private Brush PickRandomBrush()
  384.         {
  385.             Brush[] AcceptableColors = new Brush[4] { Brushes.Wheat, Brushes.LimeGreen, Brushes.LightGray, Brushes.Ivory };
  386.             Brush result = Brushes.Transparent;
  387.             Thread.Sleep(3);
  388.             Random rnd = new Random();
  389.             int random = rnd.Next(AcceptableColors.Length);
  390.             result = AcceptableColors[random];
  391.             return result;
  392.         }//funkce nějakýho toníka ze stackoverflow, mrknout na credits "pickbrush()"
  393.         public Border DrawSomething(Container CTD)
  394.         {
  395.             //CTD.cid = currentCID;
  396.             //currentCID++;
  397.  
  398.             Border br1 = new Border();
  399.             br1.BorderBrush = Brushes.Black;
  400.             br1.BorderThickness = new Thickness(1);
  401.             br1.Padding = new Thickness(1);
  402.  
  403.             Border br2 = new Border();
  404.             br2.BorderBrush = PickRandomBrush();
  405.             br2.BorderThickness = new Thickness(1);
  406.             br2.Padding = new Thickness(1);
  407.  
  408.             BoardGrid congrid = new BoardGrid();
  409.             congrid.RelatedContainer = CTD;
  410.             congrid.Background = PickRandomBrush();
  411.             congrid.HorizontalAlignment = HorizontalAlignment.Left;
  412.             congrid.VerticalAlignment = VerticalAlignment.Center;
  413.             congrid.HorizontalAlignment = HorizontalAlignment.Right;
  414.             congrid.ShowGridLines = false;
  415.             congrid.MouseLeftButtonDown += congrid_MouseLeftButtonDown;
  416.  
  417.             ColumnDefinition gridCol1 = new ColumnDefinition();
  418.             gridCol1.Width = new GridLength();
  419.             ColumnDefinition gridCol2 = new ColumnDefinition();
  420.             gridCol2.Width = new GridLength();
  421.             RowDefinition gridRow1 = new RowDefinition();
  422.             gridRow1.Height = new GridLength();
  423.             RowDefinition gridRow2 = new RowDefinition();
  424.             gridRow2.Height = new GridLength();
  425.             RowDefinition gridRow3 = new RowDefinition();
  426.             gridRow3.Height = new GridLength();
  427.  
  428.             RowDefinition gridRow4 = new RowDefinition();
  429.             gridRow4.Height = new GridLength();
  430.  
  431.             for (int z = 0; z < CTD.containers.Count; z++)
  432.             {
  433.                 RowDefinition rowDef1 = new RowDefinition();
  434.                 rowDef1.Height = new GridLength();
  435.                 congrid.RowDefinitions.Add(rowDef1);
  436.             }
  437.  
  438.  
  439.             StackPanel mediastackpanel = new StackPanel();
  440.             mediastackpanel.Orientation = Orientation.Horizontal;
  441.             Grid.SetRow(mediastackpanel, 3);
  442.             Grid.SetColumn(mediastackpanel, 1);
  443.             foreach (MediaItem item in CTD.mediaItems)
  444.             {
  445.                 ItemButton itembtn = new ItemButton();
  446.                 itembtn.RelatedMediaItem = item;
  447.                 itembtn.Content = item.name;
  448.                 itembtn.ToolTip = "Cesta: " + item.path + "\nTyp: " + item.type.ToString() + "\nTrvání: " + item.duration.ToString();
  449.                 itembtn.Click += itembtn_Click;
  450.                 mediastackpanel.Children.Add(itembtn);
  451.             }
  452.  
  453.  
  454.             int i = 0;
  455.             foreach (Container container in CTD.containers)
  456.             {
  457.                 Border brx = DrawSomething(container);
  458.                 int col = Convert.ToInt32(i % 2);
  459.                 Grid.SetColumn(brx, col);
  460.                 int row = Convert.ToInt32(4 + (Math.Truncate((double)i / 2)));
  461.                 Grid.SetRow(brx, row);
  462.                 congrid.Children.Add(brx);
  463.                 i++;
  464.             }
  465.  
  466.  
  467.             congrid.Children.Add(GenerateGridTextBlock("Jméno kontejneru", 14, new Thickness(2), 0, 0));
  468.             congrid.Children.Add(GenerateGridTextBlock("Chování kontejneru", 14, new Thickness(2), 1, 0));
  469.             congrid.Children.Add(GenerateGridTextBlock("Trvání kontejneru", 14, new Thickness(2), 2, 0));
  470.             congrid.Children.Add(GenerateGridTextBlock("Mediální položky", 14, new Thickness(2), 3, 0));
  471.             congrid.Children.Add(GenerateGridTextBlock(CTD.name, 14, new Thickness(2), 0, 1));
  472.             string behaviour = string.Empty;
  473.             try
  474.             {
  475.                 behaviour = CTD.behaviour.ToString();
  476.             }
  477.             catch (Exception)
  478.             {
  479.                 behaviour = Behaviour.sequence.ToString();
  480.             }
  481.             finally
  482.             {
  483.                 congrid.Children.Add(GenerateGridTextBlock(behaviour, 14, new Thickness(2), 1, 1));
  484.             }
  485.             congrid.Children.Add(GenerateGridTextBlock(CTD.duration.ToString(), 14, new Thickness(2), 2, 1));
  486.             congrid.Children.Add(mediastackpanel);
  487.             congrid.ColumnDefinitions.Add(gridCol1);
  488.             congrid.ColumnDefinitions.Add(gridCol2);
  489.             congrid.RowDefinitions.Add(gridRow1);
  490.             congrid.RowDefinitions.Add(gridRow2);
  491.             congrid.RowDefinitions.Add(gridRow3);
  492.             congrid.RowDefinitions.Add(gridRow4);
  493.             br1.Child = congrid;
  494.             br2.Child = br1;
  495.             br2.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
  496.             br2.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
  497.  
  498.             return br2;
  499.         } //vykreslovací srdce všeho... rekurzivně vykresluje kontejnery od storyboardu dolu...
  500.         private void DeleteItem(MediaItem ItemToDelete) //smaže item s daným MID
  501.         {
  502.             try
  503.             {
  504.                 Container Parentcont = searchContainerByMID(ItemToDelete.MID, Storyboard);
  505.                 try
  506.                 {
  507.                     Parentcont.mediaItems.Remove(ItemToDelete);
  508.                     Storygrid.Children.Clear();
  509.                     //(re)draw storyboard
  510.                     this.Storygrid.Children.Add(DrawSomething(Storyboard));
  511.                 }
  512.                 catch (NullReferenceException)
  513.                 {
  514.                     MessageBox.Show("Položku se nepodařilo smazat, možná už je smazaná...");
  515.                 }
  516.             }
  517.             catch (NullReferenceException)
  518.             {
  519.  
  520.             }
  521.  
  522.  
  523.  
  524.         }
  525.         private void DeleteContainer(int cid)//odmaže kontejner s daným CID
  526.         {
  527.             if (cid != 1)
  528.             {
  529.                 Container contToDelete = searchContainerByID(cid, Storyboard, false);
  530.                 Container parentcont = searchContainerByID(cid, Storyboard, true);
  531.                 try
  532.                 {
  533.                     parentcont.containers.Remove(contToDelete);
  534.                     Storygrid.Children.Clear();
  535.                     //(re)draw storyboard
  536.                     this.Storygrid.Children.Add(DrawSomething(Storyboard));
  537.                 }
  538.                 catch (NullReferenceException)
  539.                 {
  540.                     MessageBox.Show("kontejner ke samazání se nepodařilo nalézt...");
  541.                 }
  542.             }
  543.             else
  544.             {
  545.                 MessageBox.Show("Storyboard nelze smazat, vytvořte si nový projekt");
  546.             }
  547.         }
  548.         #endregion
  549.     }
  550. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement