using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using TradeIdeas.ServerConnection; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Interfaces; namespace TradeIdeas.TIProGUI { public partial class SaveToCloud : Form { public static readonly WindowIconCache WindowIconCache = new WindowIconCache("SAVE_TO_CLOUD"); private ListViewItem _specialLayoutItems; WatermarkTextBox shortDescriptionTextBox = new WatermarkTextBox(); WatermarkTextBox longDescriptionTextBox = new WatermarkTextBox(); // new variable to track when list view is being updated - RVH20210415 private bool _listUpdating = false; public bool ShowPrivateSymbolsListWarning = false; public SaveToCloud() { InitializeComponent(); WindowIconCache.SetIcon(this); //set the anchoring to the two watermark textboxes... shortDescriptionTextBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; longDescriptionTextBox.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top; //modify and add the WatermarkTextBox shortDescriptionTextBox.Top = 32; shortDescriptionTextBox.Left = 3; shortDescriptionTextBox.Size = new System.Drawing.Size(633, 20); shortDescriptionTextBox.WatermarkText = "Title"; splitContainer1.Panel2.Controls.Add(shortDescriptionTextBox); //modify and add the WatermarkTextBox longDescriptionTextBox.Multiline = true; longDescriptionTextBox.AcceptsReturn = true; longDescriptionTextBox.ScrollBars = ScrollBars.Vertical; longDescriptionTextBox.Top = 58; longDescriptionTextBox.Left = 3; longDescriptionTextBox.Size = new System.Drawing.Size(633, 77); longDescriptionTextBox.WatermarkText = "Description"; splitContainer1.Panel2.Controls.Add(longDescriptionTextBox); foreach (Form form in Application.OpenForms.Cast
().Where(x => !x.IsDisposed).ToList()) { ISaveLayout saveable = form as ISaveLayout; if (null != saveable && !(form.ParentForm is WindowDocumentDock)) { ListViewItem item = new ListViewItem(form.Text); item.SubItems.Add(form.Location.ToString()); item.SubItems.Add(form.Size.ToString()); item.ImageIndex = GetIconId(saveable.WindowIconCache); item.Tag = saveable; listView1.Items.Add(item); } else { // also display any dock panel windows in list - RVH20210414 if (form is MainDockForm) { ListViewItem item = new ListViewItem(form.Text); item.SubItems.Add(form.Location.ToString()); item.SubItems.Add(form.Size.ToString()); item.ImageIndex = GetIconId(((MainDockForm)form).WindowIconCache); item.Tag = form; listView1.Items.Add(item); // Add each child form. MainDockForm dockForm = form as MainDockForm; foreach (Form childForm in dockForm.ChildForms) { ISaveLayout saveableChild = childForm as ISaveLayout; if (null != saveableChild) { ListViewItem item2 = new ListViewItem(childForm.Text); item2.SubItems.Add(childForm.Location.ToString()); item2.SubItems.Add(childForm.Size.ToString()); item2.ImageIndex = GetIconId(saveableChild.WindowIconCache); item2.Tag = saveableChild; listView1.Items.Add(item2); } } } } } _specialLayoutItems = new ListViewItem("Special layout items", GetIconId(GuiEnvironment.DefaultIcon)); listView1.Items.Add(_specialLayoutItems); //Set default list view listView1.View = View.Details; detailsToolStripMenuItem.Checked = true; //TODO: Currently the fill screen is only for dev mode. Once it is ready this logic should be removed. if (GuiEnvironment.DevelopmentMode) fillScreenCheckBox.Visible = true; else fillScreenCheckBox.Visible = false; UpdateControls(); Font = GuiEnvironment.FontSettings; LoadFromCloud.AutoResizeColumns(listView1); } /// /// This is just like if the user checked an item. /// /// The item to find and then check. private void FindAndCheck(Form toCheck, bool blockSelectionEvent = false) { if (blockSelectionEvent) _listUpdating = true; foreach (ListViewItem item in listView1.Items) if (item.Tag == toCheck) { item.Checked = true; if (blockSelectionEvent) _listUpdating = false; return; } if (blockSelectionEvent) _listUpdating = false; // Else, report error? } /// /// Uncheck all forms in list and set the short description. /// /// private void UncheckAllAndSetDescription(string description) { foreach (ListViewItem item in listView1.Items) item.Checked = false; clearPreviousLayoutCheckBox.Checked = false; shortDescriptionTextBox.Text = description; longDescriptionTextBox.Text = ""; } private int GetIconId(WindowIconCache source) { Icon icon = source.Icon; try { // This is required to get a high quality version of the icon. If you // add the icon directly to the image list, the icon will be resized // automatically, but it won't look as good. // Need to convert icons to bitmaps before adding them to the image list. // Doing so will avoid a dark border around the image. using (Icon smallIcon = new Icon(icon, smallImageList.ImageSize)) { smallImageList.Images.Add(smallIcon.ToBitmap()); } using (Icon largeIcon = new Icon(icon, largeImageList.ImageSize)) { largeImageList.Images.Add(largeIcon.ToBitmap()); } } catch { // Is it possible that the image was added to one list but not the other? while (smallImageList.Images.Count > largeImageList.Images.Count) smallImageList.Images.RemoveAt(largeImageList.Images.Count); return -1; } return smallImageList.Images.Count - 1; } /// /// /// /// /// /// Set this parameter to true to create a cloud link without the interface. initiallyCheck must also have a value. /// By default nothing is checked when the form come up. /// But if you set this to something other than null, this item will be checked. /// It will look exactly like the user checked it. /// public static string DoIt(ISendManager sendManager, Form initiallyChecked = null, bool noInterface = false) { string returnCode = ""; using (SaveToCloud dialog = new SaveToCloud()) { if (noInterface && null != initiallyChecked) { dialog.UncheckAllAndSetDescription(initiallyChecked.Text); } if (null != initiallyChecked) { dialog.FindAndCheck(initiallyChecked, noInterface); } if (noInterface && null != initiallyChecked) { dialog.SaveNow(); } else { dialog.StartPosition = FormStartPosition.CenterParent; dialog.ShowDialog(); } if (null != dialog.MessageToServer) { using (SaveToCloudResponse responseCloud = new SaveToCloudResponse(dialog.MessageToServer, sendManager)) { responseCloud.StartPosition = FormStartPosition.CenterParent; responseCloud.ShowDialog(); string code = responseCloud._code; if (code != null) { try { Clipboard.SetText(code); returnCode = code; } catch { } if (dialog.showShareDialog && !noInterface) { CollaborateForm form = new CollaborateForm(); form.ConfigString = code; form.Text = "Share this Link"; form.SetCloudOptions(); form.ShowWarning = dialog.ShowPrivateSymbolsListWarning; form.ShowDialog(); form.Dispose(); } } } } } return returnCode; } private void listView1_ItemChecked(object sender, ItemCheckedEventArgs e) { // if list view is being updated, don't execute this method - RVH20210415 if (_listUpdating) return; if ((shortDescriptionTextBox.Text == "") && (e.Item.Checked)) shortDescriptionTextBox.Text = e.Item.Text; //Clear textbox text if nothing checked if ((listView1.CheckedItems.Count == 0) && (longDescriptionTextBox.IsTextBoxEmpty)) { shortDescriptionTextBox.Text = ""; longDescriptionTextBox.Text = ""; } UpdateControls(); ProcessDockPanelWindowsSelection(e.Item.Tag as Form); } /// /// When the user selects or deselects a MainDockForm, the children windows will also be selected or deselected. /// When a user select or deselects a child window then the MainDockForm and its children will be selected or deselected. /// /// private void ProcessDockPanelWindowsSelection(Form checkedForm) { if (checkedForm == null) return; _listUpdating = true; if (listView1.CheckedItems.Count > 0) { foreach (ListViewItem item in listView1.Items) { Form form = item.Tag as Form; // Find selected dock window and apply selection logic to its child windows. if (form is MainDockForm && form.Handle == checkedForm.Handle) { ProcessAllChildWindows(form, item.Checked); break; } // Find the selected child window and apply selection logic to sibling windows and parent dock window. if (form != null && form.Handle == checkedForm.Handle) { Form parentForm = form.ParentForm; if (parentForm != null && parentForm is WindowDocumentDock) { Form grandParentForm = parentForm.ParentForm; if (grandParentForm != null && grandParentForm is MainDockForm) { // select all child windows ProcessAllChildWindows(grandParentForm, item.Checked); ProcessParentWindow(grandParentForm, item.Checked); break; } } } } } _listUpdating = false; } /// /// Given a MainDockForm select/deselect its child windows in the ListView. /// /// Dock window form. /// Status for the Checked property of the child windows in the ListView private void ProcessAllChildWindows(Form form, bool selected) { // We must use a unique identifier to identify children of this form. var formHandle = form.Handle; // select all child windows in list foreach (ListViewItem childItem in listView1.Items) { Form childForm = childItem.Tag as Form; // make sure it isn't the main dock window if (childForm != null && childForm != form && !(childForm is MainDockForm)) { Form parentForm = childForm.ParentForm; if (parentForm != null && parentForm is WindowDocumentDock) { Form grandParentForm = parentForm.ParentForm; if (grandParentForm != null && grandParentForm is MainDockForm && grandParentForm.Handle == formHandle) { childItem.Checked = selected; } } } } } /// /// Find the selected MainDockForm in the ListView and updates its Checked property in the ListView. /// /// Dock window form. /// Status for the Checked property of the MainDockForm in the ListView. private void ProcessParentWindow(Form form, bool selected) { // set short layout name to title of the parent form - RVH20210608 shortDescriptionTextBox.Text = form.Text; // We must use an unique identifier the parent of this form. var formHandle = form.Handle; // find parent window and select it foreach (ListViewItem item in listView1.Items) { Form parentForm = item.Tag as Form; if (parentForm != null && parentForm is MainDockForm && parentForm.Handle == formHandle) { item.Checked = selected; break; } } } private void UpdateControls() { saveAndShareButton.Enabled = listView1.CheckedItems.Count > 0; saveButton.Enabled = listView1.CheckedItems.Count > 0; Screen screen = null; bool multipleScreensFound = false; foreach (ListViewItem item in listView1.CheckedItems) { Form form = item.Tag as Form; if (null != form) if (null == screen) // First screen we've found. screen = Screen.FromControl(form); else if (!screen.Equals(Screen.FromControl(form))) { multipleScreensFound = true; break; } } // This mode only makes sense if we are saving things that are all on // one screen. We allow the case of 0 sceens because (a) we assume the // user just hasn't started picking screens yet and for the most part // you should be able to fill out a dialog box in any order you want // and (b) the Save button will be disabled anyway, so we know someone // can't save a layout like this. fillScreenCheckBox.Enabled = !multipleScreensFound; } private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { if (e.IsSelected) // Do not allow any selection. That would be confusing. You can check things, so you don't // need to select things. listView1.SelectedItems.Clear(); } private void selectAllButton_Click(object sender, EventArgs e) { if (shortDescriptionTextBox.Text == "") // This isn't very exciting. The real goal was to copy the name of a single strategy // when the user checks a box. But if the user hits the select all button, then that // code will always copy the name of the first window. This seems more reasonable. shortDescriptionTextBox.Text = "Layout"; foreach (ListViewItem item in listView1.Items) item.Checked = true; clearPreviousLayoutCheckBox.Checked = true; } private void selectNoneButton_Click(object sender, EventArgs e) { foreach (ListViewItem item in listView1.Items) item.Checked = false; clearPreviousLayoutCheckBox.Checked = false; shortDescriptionTextBox.Text = ""; longDescriptionTextBox.Text = ""; } private void SaveNow() { HashSet windowTypes = new HashSet(); // modify list type to Form to include all forms - RVH20210414 //List windows = new List(); List windows = new List(); int windowCount = 0; foreach (ListViewItem item in listView1.CheckedItems) { ISaveLayout window = item.Tag as ISaveLayout; if (null != window) { windowCount++; windows.Add((Form)item.Tag); //window); - add to list as Form - RVH20210414 windowTypes.Add(window.WindowIconCache.WindowName); } else { // also add dock panel windows - RVH20210414 if (item.Tag is MainDockForm) { windowCount++; windows.Add((Form)item.Tag); //window); - add to list as Form - RVH20210414 windowTypes.Add(((Form)item.Tag).Name); } } IHandlesStrategies strategyWindow = item.Tag as IHandlesStrategies; //If there is already a strategy that contains a private list of symbols, it is not necessary to check again. if (!ShowPrivateSymbolsListWarning && strategyWindow != null) { ShowPrivateSymbolsListWarning = strategyWindow.StrategyContainsPrivateList(); } } string layout = LayoutManager.Instance().SaveSome(_specialLayoutItems.Checked, windows).OuterXml; string icon = ""; if (windowTypes.Count == 1) icon = windowTypes.First(); if (String.IsNullOrEmpty(layout)) MessageBox.Show("Unable to save this layout to the cloud. Layout is empty.", "Save or Share to Cloud"); else if (System.Text.Encoding.UTF8.GetByteCount(layout) > 500000) MessageBox.Show("Unable to save this layout to the cloud. It is too big.", "Save or Share to Cloud"); else // MessageToServer is an output read by DoIt() MessageToServer = TalkWithServer.CreateMessage( "command", "save_to_cloud", "layout", layout, "icon", icon, "window_count", windowCount, "clear_previous_layout", clearPreviousLayoutCheckBox.Checked, "fill_screen", (fillScreenCheckBox.Checked && fillScreenCheckBox.Enabled), "short_description", shortDescriptionTextBox.Text, "long_description", longDescriptionTextBox.Text); } /// /// This is null if the user cancels. It is a valid message to the server if the user hits okay. /// public Dictionary MessageToServer { get; private set; } /// /// Controls whether we go to the share dialog or not. /// public Boolean showShareDialog = true; private void saveButton_Click(object sender, EventArgs e) { showShareDialog = false; SaveNow(); } private void saveAndShareButton_Click(object sender, EventArgs e) { showShareDialog = true; SaveNow(); } private void largeIconToolStripMenuItem_Click(object sender, EventArgs e) { listView1.View = View.LargeIcon; largeIconToolStripMenuItem.Checked = true; detailsToolStripMenuItem.Checked = smallIconToolStripMenuItem.Checked = listToolStripMenuItem.Checked = false; } private void detailsToolStripMenuItem_Click(object sender, EventArgs e) { listView1.View = View.Details; detailsToolStripMenuItem.Checked = true; largeIconToolStripMenuItem.Checked = smallIconToolStripMenuItem.Checked = listToolStripMenuItem.Checked = false; } private void smallIconToolStripMenuItem_Click(object sender, EventArgs e) { listView1.View = View.SmallIcon; smallIconToolStripMenuItem.Checked = true; largeIconToolStripMenuItem.Checked = detailsToolStripMenuItem.Checked = listToolStripMenuItem.Checked = false; } private void listToolStripMenuItem_Click(object sender, EventArgs e) { listView1.View = View.List; listToolStripMenuItem.Checked = true; largeIconToolStripMenuItem.Checked = detailsToolStripMenuItem.Checked = smallIconToolStripMenuItem.Checked = false; } } // Why do we have WatermarkTextBox in SaveToCloud.cs and WaterMarkTextBox in WaterMarkCheckBox.cs? // Was this on purpose? /// /// inspired by this forum entry: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/10f75954-6d14-4926-a02d-98649653b9c8/ /// and http://stackoverflow.com/questions/8566764/textbox-in-c-sharp-windows-form /// Watermark TextBox in winform /// public class WatermarkTextBox : TextBox { private string watermarkText; private Color watermarkColor; private Color foreColor; private bool isTextBoxEmpty; public WatermarkTextBox() { this.WatermarkText = "Watermark Text..."; this.WatermarkColor = Color.FromKnownColor(KnownColor.Silver); this.Enter += onEnter; this.Leave += onLeave; this.AutoCompleteMode = AutoCompleteMode.Suggest; this.AutoCompleteSource = AutoCompleteSource.CustomSource; } [Browsable(true)] public bool IsTextBoxEmpty { get { return this.isTextBoxEmpty; } } [Browsable(true)] public new Color ForeColor { get { return this.foreColor; } set { if (value == this.foreColor) { return; } this.foreColor = value; if (!this.isTextBoxEmpty) { base.ForeColor = value; } } } [Browsable(true)] public Color WatermarkColor { get { return this.watermarkColor; } set { if (value == this.watermarkColor) { return; } this.watermarkColor = value; if (this.isTextBoxEmpty) { base.ForeColor = this.watermarkColor; } } } [Browsable(true)] public string WatermarkText { get { return this.watermarkText; } set { if (value == this.watermarkText) { return; } this.watermarkText = value; if ((base.Text.Length == 0) || (isTextBoxEmpty)) { this.isTextBoxEmpty = true; base.Text = this.watermarkText; base.ForeColor = this.watermarkColor; } this.Invalidate(); } } public override string Text { get { return this.isTextBoxEmpty ? string.Empty : base.Text; } set { if (string.IsNullOrEmpty(value)) { this.isTextBoxEmpty = true; base.ForeColor = this.watermarkColor; base.Text = this.watermarkText; } else { this.isTextBoxEmpty = false; base.ForeColor = this.foreColor; base.Text = value; } } } private void onEnter(object sender, EventArgs e) { if (this.isTextBoxEmpty) { this.isTextBoxEmpty = false; base.ForeColor = this.foreColor; base.Text = string.Empty; } } private void onLeave(object sender, EventArgs e) { if (string.IsNullOrEmpty(base.Text)) { this.isTextBoxEmpty = true; base.ForeColor = this.watermarkColor; base.Text = this.watermarkText; } else { this.isTextBoxEmpty = false; } } } }