using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Net; using System.Windows.Forms; using System.Xml; using TradeIdeas.ServerConnection; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI { public partial class CustomChannelList : Form { public class UserChannelData { // Note all string properties are initialized to null. public string id; public string channelName; public string cloudLink; public string imageResourceName; //This is empty when we are using an image saved by the user to the server. // This is the only single image that will be stored on the server for the particular cloudlink in question // The user may replace this image with another if editing for that particular cloudlink. All edit results are shown dynamically // instead of storing an "active" image and "inactive" image for each cloudlink. This image is "bare"- it's produced from the // image immediately produced when the user crops the image he's uploaded. It's not adorned with any borders or writing.. that stuff // is done elsewhere during editing... public Image baseImage; // This is null when we are using resource images. } List _userDat = new List(); IConnectionMaster _connectionMaster = GuiEnvironment.FindConnectionMaster(""); private const int MAX_CHANNELS = 5; public CustomChannelList() { InitializeComponent(); CustomChannelEditor.InitOratorStdFont(); //Load local copy of user channels _userDat.Clear(); foreach (UserChannelData item in GuiEnvironment.UserChannelList) { _userDat.Add(item); } LoadChannelThumbnailImages(); populateListView(); } private void LoadChannelThumbnailImages() { channelThumbnail.Images.Clear(); foreach (UserChannelData channel in _userDat) { if (channel.baseImage != null) { Image img = CustomChannelEditor.CreateDynamicInactiveChannel(channel.baseImage, channel.channelName); if (img != null) channelThumbnail.Images.Add(channel.id, img); } if (channel.imageResourceName != null && !channel.imageResourceName.Equals("")) { Image img = CustomChannelEditor.CreateDynamicInactiveResourceImageChannel(channel.imageResourceName, channel.channelName); if (img != null) channelThumbnail.Images.Add(channel.id, img); } } } private void populateListView() { listView1.Items.Clear(); for (int i = 0; i < _userDat.Count; i++) { ListViewItem guiItem = new ListViewItem(); guiItem.Text = _userDat[i].channelName; guiItem.SubItems.Add(_userDat[i].cloudLink); guiItem.SubItems.Add(_userDat[i].id); guiItem.ImageIndex = channelThumbnail.Images.IndexOfKey(_userDat[i].id); if (guiItem.ImageIndex != -1) listView1.Items.Add(guiItem); } getNumberOfChannels(); } private void btnDelete_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count == 0) return; ListViewItem item = listView1.SelectedItems[0]; //currently doing only single select String id = item.SubItems[2].Text; //the unique id if (item != null) { listView1.Items.Remove(item); btnDelete.Enabled = false; foreach (UserChannelData d in _userDat) { if (d.id == id) { _userDat.Remove(d); //remove the requisite image from the image list: channelThumbnail.Images.RemoveByKey(d.id); break; } } } populateListView(); getNumberOfChannels(); } private void listView1_SelectedIndexChanged(object sender, EventArgs e) { btnDelete.Enabled = (listView1.SelectedItems.Count > 0); btnEdit.Enabled = (listView1.SelectedItems.Count > 0); } private void btnAdd_Click(object sender, EventArgs e) { // Only open editor if we do not exceed max custom channels. if (_userDat.Count >= MAX_CHANNELS) { MessageBox.Show("You are limited to " + MAX_CHANNELS + " custom channels. Please delete or edit one of your current custom channels.", "Max Number of Custom Channels Reached"); return; } CustomChannelEditor editor = new TIProGUI.CustomChannelEditor(); editor.ShowDialog(); if (editor.DialogResult == DialogResult.OK) { UserChannelData retVal = new UserChannelData(); retVal.id = Guid.NewGuid().ToString(); retVal.channelName = editor.CurrentChannelName; retVal.cloudLink = editor.CloudCodeURL; retVal.imageResourceName = editor.ImageResourceName; Image newThumbnailImage = editor.CurrentChannelImage; if (null != editor.CurrenBaseImage) retVal.baseImage = editor.CurrenBaseImage; if (null != newThumbnailImage) { channelThumbnail.Images.Add(retVal.id, newThumbnailImage);//gets displayed in the list box _userDat.Add(retVal); populateListView(); } } } private void getNumberOfChannels() { if (listView1.Items.Count < MAX_CHANNELS) btnAdd.Enabled = true; else btnAdd.Enabled = false; } public static Image getImage(string url) { //Snippet from "Cambo Tutorial" https://www.youtube.com/watch?v=aaYJX7ORfn8 try { WebClient w = new WebClient(); byte[] imageByte = w.DownloadData(url); MemoryStream stream = new MemoryStream(imageByte); Image im = Image.FromStream(stream); var result = new Bitmap(im); return result; } catch { return null; } } private void btnUp_Click(object sender, EventArgs e) { processUpMotion(); _userDat = updateListOrder(_userDat); } private void btnDown_Click(object sender, EventArgs e) { processDownMotion(); _userDat = updateListOrder(_userDat); } private void processDownMotion() { if (listView1.SelectedItems.Count == 1 && listView1.SelectedIndices[0] != -1 && listView1.SelectedIndices[0] < listView1.Items.Count) { ListViewItem item, belowItem; int itemIndex, belowItemIndex; itemIndex = listView1.SelectedIndices[0]; belowItemIndex = listView1.SelectedIndices[0] + 1; if (belowItemIndex >= listView1.Items.Count) { return; } item = (ListViewItem)listView1.Items[itemIndex]; belowItem = (ListViewItem)listView1.Items[belowItemIndex]; listView1.Items.RemoveAt(itemIndex); listView1.Items.Insert(belowItemIndex, item); } } private void processUpMotion() { if (listView1.SelectedItems.Count == 1 && listView1.SelectedIndices[0] != -1 && listView1.SelectedIndices[0] != 0) { ListViewItem item, aboveItem; int itemIndex, aboveItemIndex; itemIndex = listView1.SelectedIndices[0]; aboveItemIndex = listView1.SelectedIndices[0] - 1; item = (ListViewItem)listView1.Items[itemIndex]; aboveItem = (ListViewItem)listView1.Items[aboveItemIndex]; listView1.Items.RemoveAt(aboveItemIndex); listView1.Items.Insert(itemIndex, aboveItem); } } private List updateListOrder(List data) { List retVal = new List(); //populate lists with now reordered stuff from the ListView. foreach (ListViewItem item in listView1.Items) { String id = item.SubItems[2].Text; //the unique id UserChannelData usrChan = getUserChannelStruct(id, data); retVal.Add(usrChan); } return retVal; } private UserChannelData getUserChannelStruct(string id, List data) { UserChannelData retVal = new UserChannelData(); foreach (UserChannelData d in data) { if (d.id.Equals(id)) { retVal = d; break; } } return retVal; } private void btnEdit_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count == 1) { int itemIndex = listView1.SelectedIndices[0]; ListViewItem item = (ListViewItem)listView1.Items[itemIndex]; String id = item.SubItems[2].Text; //the unique id associated with the selected custom channel. //Fetch the UserChannelDat object that contains the data of the selected channel. UserChannelData selectedChannelData = getUserChannelStruct(id, _userDat); CustomChannelEditor editor = new TIProGUI.CustomChannelEditor(selectedChannelData); editor.ShowDialog(); if (editor.DialogResult == DialogResult.OK) { //update the _userDat list as well as the image list. selectedChannelData = editor.getDataEditObject(); Image newThumbnailImage = editor.CurrentChannelImage; List temp = new List(); ImageList tempImage = new ImageList(); tempImage.ColorDepth = ColorDepth.Depth32Bit; tempImage.ImageSize = new Size(75, 43); tempImage.TransparentColor = Color.Transparent; for (int i = 0; i < _userDat.Count; i++) { if (_userDat[i].id == selectedChannelData.id) { temp.Add(selectedChannelData); tempImage.Images.Add(selectedChannelData.id, newThumbnailImage); } else { temp.Add(_userDat[i]); if (_userDat[i].baseImage != null) { Image thumbnailImage = CustomChannelEditor.CreateDynamicInactiveChannel((_userDat[i]).baseImage, (_userDat[i]).channelName); tempImage.Images.Add((_userDat[i]).id, thumbnailImage); } else { Image thumbnailImage = CustomChannelEditor.CreateDynamicInactiveResourceImageChannel(_userDat[i].imageResourceName, _userDat[i].channelName); tempImage.Images.Add((_userDat[i]).id, thumbnailImage); } } } _userDat = temp; channelThumbnail.Images.Clear(); //In order for the images to appear correctly as thumbnails in the listview (correct channel name) // I had to explicitly loop thru the tempImages list and add each item to the channelThumbNail image list. The thumbnails //would not show at all if I used the line "channelThumbnail = tempImage;" instead.. for (int i = 0; i < tempImage.Images.Count; i++) { channelThumbnail.Images.Add((_userDat[i]).id, tempImage.Images[i]); } populateListView(); btnEdit.Enabled = false; } } } private void btnApply_Click(object sender, EventArgs e) { GuiEnvironment.SetUserChannelList(_userDat); ChannelBarForm.UpdateUserChannelBar(); SaveUserChannelsToServer(); Close(); } private void btnCancel_Click(object sender, EventArgs e) { Close(); } private void SaveUserChannelsToServer() { // We need to create the contents of 6 files. // The first file, custom_channels.xml, will contain the xml data. // The remaining 5 files are image files: channel_image_0.png, channel_image_1.png, // channel_image_2.png, channel_image_3.png, and channel_image_4.png. // Delete image files from server before updating user channel list. DeleteAllUserImageFiles(); XmlDocument doc = new XmlDocument(); doc.LoadXml(""); XmlNode node = doc.Node(0); int imageNumber = 0; foreach (UserChannelData item in GuiEnvironment.UserChannelList) { XmlNode userChannelContainer = node.NewNode("USER_CHANNEL"); userChannelContainer.SetProperty("CHANNEL_NAME", item.channelName); userChannelContainer.SetProperty("IMAGE_RESOURCE_NAME", item.imageResourceName); userChannelContainer.SetProperty("CLOUD_LINK", item.cloudLink); string imageFileName = "channel_image_" + imageNumber + ".png"; // Save or delete image file ModifyImageFile(item.baseImage, imageFileName); imageNumber++; } // Save first xml file var message = TalkWithServer.CreateMessage( "command", "user_file_save", "body", doc.OuterXml, // body="" is a delete command other wise it is the contents of the file "name", "custom_channels.xml"); _connectionMaster.SendManager.SendMessage(message, null); } private void DeleteAllUserImageFiles() { DeleteUserImageFile("channel_image_0.png"); DeleteUserImageFile("channel_image_1.png"); DeleteUserImageFile("channel_image_2.png"); DeleteUserImageFile("channel_image_3.png"); DeleteUserImageFile("channel_image_4.png"); } private void DeleteUserImageFile(string imageFileName) { // body = "" will delete the file var message = TalkWithServer.CreateMessage("command", "user_file_save", "body", "", "name", imageFileName); _connectionMaster.SendManager.SendMessage(message, null); } private void ModifyImageFile(Image image, string imageFileName) { byte[] bytes = null; if (null != image) { // Save the file, current file on server will be replaced. bytes = GuiEnvironment.CopyImageToByteArray(image); var message = TalkWithServer.CreateMessage( "command", "user_file_save", "body", bytes, // body="" is a delete command other wise it is the contents of the file "name", imageFileName); _connectionMaster.SendManager.SendMessage(message, null); } else { // Delete the file DeleteUserImageFile(imageFileName); } } } }