using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Web; using System.Windows.Forms; using System.Windows.Input; using System.Xml; using TradeIdeas.MiscSupport; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Configuration; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.TIProGUI.OddsMaker; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI { public struct StrategyStruct //for the *Window* don't repeat for feature-this goes down to the symbol level... { public string StrategyConfig; public string StrategySymbol; public StrategyStruct(string config, string symbol) { StrategyConfig = config; StrategySymbol = symbol; } } public delegate void MultiStrategySymbolClickHandler(string symbol, string exchange); public partial class MultiStrategy : Form, ISaveLayout, ICultureListener, IFont, IGrid, IRowSelect, IDemoMode, IChildable, IContextMenuStrip, ISnapToGrid, ISupportLimitedMode, ICanConfigure, IAccountStatusChanged, IClearData, IHaveGrids, ICanRefreshNow, ISymbolLinkingChannel, IHandlesStrategies { private IList Columns; //includes entry for "StrategyName" and will be passed to hide/view columns method... private List _totalColumns = new List(); private IActionsForOwner _actions; private ISymbolLinkingForOwner _symbolLinking; private ColumnListState _columnListState = new ColumnListState(); private BindingList _boundList = new BindingList(); private readonly IConnectionMaster _connectionMaster; private ISendManager _sendManager; private LayoutManager _layoutManager = LayoutManager.Instance(); private const string FORM_TYPE = "MULTI_STRATEGY_WINDOW"; private List _phrases; private const int MIN_COLUMN_WIDTH = 5; private const int DEFAULT_ROW_HEIGHT = 20; private const string VERBOSE_COLUMN_HEADER = "Description"; private string _fileNameSaved; private string _fileNameSavedContents; private const string _defaultFileName = "DEFAULT_MULTI.WTI"; // for tracking currently "selected" row for modifying the right-click menu appropriately private RowData _currentRowData; private RowData _mostRecentRowData; private int _mostRecentRowIndex; private makeSendToContextMenu _sendToContextMenu; private bool _symbolSpecificContextMenuOpen = false; private string _individualStrategyConfig = ""; //For dealing with the "Speed" option private List QueuedStreamingStrategies = new List(); private DateTime QueueFinishTime; private int QueuePeriod; private List _speedItems = new List(); //for history private HistoryTimeFrame _timeframe; private enum HistoryModeEnum { Live, HistoryLoading, HistoryDone }; private HistoryModeEnum _historyMode = HistoryModeEnum.Live; private int _selectedStrategies = 0; public int Finished = 0; private bool _historyErrorOnDemo = false; // for showing/hiding marketingPanel if history accessed in delayed data mode private bool _currentlyUsingHistory = false;//for windows showing history that stay open when user then changes to a delayed-data-mode // custom column colors private Dictionary _columnColors = new Dictionary(); /// /// Record all historical data twice. Once to be displayed quickly, and once to be /// displayed at after we get it all. The latter is stored here. /// private SortedDictionary _historySortedList = new SortedDictionary(); /// /// Multi-symbol Send To Symbol List support /// private List _selectedRowsList = new List(); private List> _historyTempList = new List>(); private bool _historyUpdatedRecently; private HistoryModeEnum HistoryMode { get { return _historyMode; } set { if (_historyMode != value) { _historyMode = value; RefreshWindowName(); } } } //for repeat/dont repeat coupled with actions private List _newlyProcessedList = new List(); //used for repeat mode private List _notInRepeatList = new List(); //for non repeat mode private List _newlyPrecessedListText = new List(); //list used for get text to speak for repeat mode private List _notInRepeatListText = new List(); //list used for get text to speak for non repeat mode //For use in the Don't Repeat For" functionality Dictionary _strategyDelayTable = new Dictionary(); private bool _inNoRepeatMode = false; //_previousNoRepeatModeSetting is for preserving state of repeat mode when user //comes off history mode... private bool _previousNoRepeatModeSetting = false; private int _repeatInterval = 5; private bool _textHeaders = false; // new variable to set that dock panel is being used - RVH20210329 private bool _dockPanelMode = true; // new variable for symbol linking channel - RVH20210928 private string _linkChannel = SymbolLinkChannels.DefaultLinkChannel; private List _dataGrids = new List(); private DataCell.SymbolPlusLayoutType _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off; private bool _restoringLayout = false; public bool TextHeaders { get { return _textHeaders; } set { _textHeaders = value; UpdateTextHeadersMenuItem(); } } public bool InNoRepeatMode { get { return _inNoRepeatMode; } set { _inNoRepeatMode = value; } } public ContextMenuStrip MyContextMenuStrip { get { return contextMenuStrip1; } } /// /// Exposes the data grids. /// public List DataGrids { get { return _dataGrids; } } //Use a modified configuration class to cut down the clutter of //this class... private MultiStrategyConfiguration _config; public MultiStrategyConfiguration MultiStrategyConfiguration { get { return _config; } set { _config = value; } } private bool _isChild = false; public bool IsChild { get { return _isChild; } set { _isChild = value; } } public Rectangle? ActualSize { get; set; } public TIFormType TIFormType { get { return TIProGUI.TIFormType.MultiStrategy; } } /// /// This gets called before any other code in the SaveLayout function. Currently this is aimed at the Scottrade addin but anything can set this code. /// public Action
PreSaveLayoutCode { get; set; } /// /// This gets called after SaveBase and it passes the XmlNode that the form is being saved to. This allows extensions to add properties to the layout. Access the layout XmlNode /// from a form using RestoredLayout. /// public Action SaveLayoutCode { get; set; } /// /// This is the xml that was used to restore this form. If this form wasn't layout-restored then this will be null. /// public XmlNode RestoredLayout { get; set; } /// /// Returns the current configuration string used for collaboration. /// /// public string GetConfigString() { return _config.GetCollaborationString(); } // For use in showing columns private static readonly string[] COLUMNS_NUMBERSSPLIT_ON = new string[] { "&show" }; // For simplicity we have only one list of strategies. That's inside of the list box in // the config window. If we had more than one list, we'd have to keep the two lists in // sync. private ColumnInfo _strategyNameColumnInfo; private string _requestedWindowName; /// /// This is what the user put into the select window name dialog box. /// This is displayed on the title bar, in combination with other things. /// This will be null to say that nothing has been selected. /// An invalid name, like "" or " " will be converted to null automatically by /// this property. (We were previously checking for "" in several places, /// everywhere this was used.) /// public string RequestedWindowName { get { return _requestedWindowName; } set { if ((value != null) && (value.Trim() == "")) value = null; if (value != _requestedWindowName) { _requestedWindowName = value; RefreshWindowName(); } } } /// /// This is similar to but this is never null. /// If the user doesn't specify something, we pick a reasonable default. /// public string BaseWindowName { get { string result = RequestedWindowName; if (null == result) result = _phrases.Node("TITLE").PropertyForCulture("TEXT", "***"); return result; } } private void RefreshWindowName() { string windowName = BaseWindowName; switch (HistoryMode) { case HistoryModeEnum.Live: if (_connectionMaster.LoginManager.IsDemo) windowName += GuiEnvironment.XmlConfig.Node("COMMON_PHRASES").Node("DEMO_DISCLAIMER").PropertyForCulture("TEXT", "***"); break; case HistoryModeEnum.HistoryLoading: windowName = _phrases.Node("HISTORY").PropertyForCulture("TEXT", "***") + ": " + windowName + " " + _phrases.Node("LOADING").PropertyForCulture("TEXT", "***"); break; case HistoryModeEnum.HistoryDone: windowName = _phrases.Node("HISTORY").PropertyForCulture("TEXT", "***") + ": " + windowName; break; } this.Text = windowName; } public void RedrawTable() { dataGridView1.Invalidate(); } public static readonly WindowIconCache WindowIconCache = new WindowIconCache("MULTI_STRATEGY"); public MultiStrategy(IConnectionMaster connectionMaster) { _limitedMode = GuiEnvironment.LimitedMode; _connectionMaster = connectionMaster; _sendManager = _connectionMaster.SendManager; _config = new MultiStrategyConfiguration(this, _connectionMaster); _actions = new Actions(this); _symbolLinking = new SymbolLinking(this); // add parameter for form type - RVH20210602 //_strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME")); _strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME"), FORM_TYPE); _phrases = GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("PHRASES"); InitializeComponent(); _dataGrids.Add(dataGridView1); // check to see if auto-size columns is set - RVH20210720 if (GuiEnvironment.autosizeColumns) dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; ExtensionMethods.DoubleBufferedDatagrid(dataGridView1, true); saveToCloudToolStripMenuItem.Image = SaveToCloud.WindowIconCache.MenuImage; lblMessage.Text = _phrases.Node("IN_DEMO").PropertyForCulture("TEXT", "***"); linkLabel.Text = "Click here to subscribe."; LinkLabel.Link link = new LinkLabel.Link(); link.LinkData = "https://www.trade-ideas.com/login/?newaccount=1"; linkLabel.Links.Add(link); lblGoBack.Text = _phrases.Node("GO_BACK").PropertyForCulture("TEXT", "***"); if (!IsHandleCreated) CreateHandle(); dataGridView1.DataError += new DataGridViewDataErrorEventHandler(dataGridView1_DataError); dataGridView1.DataSource = _boundList; dataGridView1.ColumnHeadersHeight = ImageCacheManager.ICON_HEIGHT; dataGridView1.ClearSelection(); WindowIconCache.SetIcon(this); CultureChanged(); _timeframe = new HistoryTimeFrame(_connectionMaster, null, this); graphicalIndicatorToolStripMenuItem.Click += Column.GraphicsMenuItemCallback; //Load the list of the ToolStripMenuItems for speed... _speedItems.Add(slowestToolStripMenuItem); _speedItems.Add(slowToolStripMenuItem); _speedItems.Add(normalToolStripMenuItem); _speedItems.Add(fastToolStripMenuItem); _speedItems.Add(fasterToolStripMenuItem); _speedItems.Add(fastestToolStripMenuItem); ((IDemoMode)this).OnDemoModeChanged(); _config.add(); hideWelcomeLabel(); setGridLines(); chooseRowSelect(); selectTheFont(); AddExtraMenuItems(GuiEnvironment.GetExtraMenuItems().Where(x => x.TIFormType == TIFormType.All || x.TIFormType == TIFormType.MultiStrategy).ToList(), contextMenuStrip1.Items); SetSnapToGrid(GuiEnvironment.SnapToGrid); } private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs anError) { // This method was implemented to ignore unhandled exceptions when the user was using the up and down keys // for external linking at the same time the grid row entered was in flux due to adding or removing // rowdata during normal view mode operations. anError.ThrowException = false; //System.Diagnostics.Debug.WriteLine("Multi-StrategyForm: DataGridView.DataError Event handled: " + anError.Exception); } private void AddExtraMenuItems(List menuItems, ToolStripItemCollection into) { foreach (TIToolStripMenuItem menuItem in menuItems) { AddExtraMenuItem(menuItem, into); } } private void AddExtraMenuItem(TIToolStripMenuItem menuItemTemplate, ToolStripItemCollection into) { TIToolStripMenuItem thisMenuItem = menuItemTemplate.Clone(); thisMenuItem.Click += new EventHandler(menuItem_Click); into.Add(thisMenuItem); if (menuItemTemplate.HasDropDownItems) AddExtraMenuItems(menuItemTemplate.DropDownItems.Cast().ToList(), thisMenuItem.DropDownItems); } void menuItem_Click(object sender, EventArgs e) { TIToolStripMenuItem menuItem = sender as TIToolStripMenuItem; if (null != menuItem) { menuItem.RowData = _mostRecentRowData; menuItem.ClickedCode(menuItem, this); } } private void ToggleSymbolSpecificMenuItems(bool symbolSpecific, string symbol = "") { foreach (TIToolStripMenuItem menuItem in contextMenuStrip1.Items.OfType().Where(x => x.IsSymbolSpecific)) { if (symbol != "") { menuItem.Symbol = symbol; menuItem.RowData = _currentRowData; } menuItem.Visible = symbolSpecific; } } public void selectTheFont() { Font = GuiEnvironment.FontSettings; contextMenuStrip1.Font = GuiEnvironment.FontSettings; DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout); RefreshColumns(); } public void setGridLines() { if (GuiEnvironment.ShowGridLines) { dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.Single; } else { dataGridView1.CellBorderStyle = DataGridViewCellBorderStyle.None; } } public void chooseRowSelect() { if (GuiEnvironment.HighlightGridRow) { dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; } else { dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect; } } void IDemoMode.OnDemoModeChanged() { saveToCloudToolStripMenuItem.Enabled = !_connectionMaster.LoginManager.IsDemo; RefreshWindowName(); } public void CultureChanged() { // Reset MS strategies to get server translated columns // TODO uncomment next line to retrieve column translations from the server. //onClearData(); // Apply local language change // add parameter for form type - RVH20210602 //_strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME")); _strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME"), FORM_TYPE); clearToolStripMenuItem.Text = _phrases.Node("CLEAR").PropertyForCulture("TEXT", "***"); columnsToolStripMenuItem.Text = _phrases.Node("COLUMNS").PropertyForCulture("TEXT", "***"); saveContentsToolStripMenuItem.Text = _phrases.Node("SAVE_CONTENTS").PropertyForCulture("TEXT", "***"); windowNameToolStripMenuItem.Text = _phrases.Node("WINDOW_NAME").PropertyForCulture("TEXT", "***"); saveDefaultToolStripMenuItem.Text = _phrases.Node("SAVE_AS_DEFAULT").PropertyForCulture("TEXT", "***"); actionsToollStripMenuItem.Text = _phrases.Node("ACTIONS").PropertyForCulture("TEXT", "***"); duplicateToolStripMenuItem.Text = _phrases.Node("DUPLICATE").PropertyForCulture("TEXT", "***"); saveAsToolStripMenuItem.Text = _phrases.Node("SAVE_AS").PropertyForCulture("TEXT", "***"); graphicalIndicatorToolStripMenuItem.Text = _phrases.Node("GRAPHICAL_INDICATOR").PropertyForCulture("TEXT", "***"); strategiesToolStripMenuItem.Text = _phrases.Node("STRATEGIES").PropertyForCulture("TEXT", "***"); deleteAllToolStripMenuItem.Text = _phrases.Node("DELETE_ALL").PropertyForCulture("TEXT", "***"); collaborateAllToolStripMenuItem.Text = _phrases.Node("COLLABORATE_ALL").PropertyForCulture("TEXT", "***"); historyToolStripMenuItem.Text = _phrases.Node("HISTORY").PropertyForCulture("TEXT", "***"); realTimeToolStripMenuItem.Text = _phrases.Node("REAL_TIME").PropertyForCulture("TEXT", "***"); timeFrameToolStripMenuItem.Text = _phrases.Node("TIME_FRAME").PropertyForCulture("TEXT", "***"); allToolStripMenuItem.Text = _phrases.Node("ALL").PropertyForCulture("TEXT", "***"); dontRepeatToolStripMenuItem.Text = _phrases.Node("NO_REPEAT").PropertyForCulture("TEXT", "***"); //speed settings speedToolstripMenuItem.Text = _phrases.Node("SPEED").PropertyForCulture("TEXT", "***"); slowestToolStripMenuItem.Text = _phrases.Node("SLOWEST").PropertyForCulture("TEXT", "***"); slowToolStripMenuItem.Text = _phrases.Node("SLOW").PropertyForCulture("TEXT", "***"); normalToolStripMenuItem.Text = _phrases.Node("NORMAL").PropertyForCulture("TEXT", "***"); fastToolStripMenuItem.Text = _phrases.Node("FAST").PropertyForCulture("TEXT", "***"); fasterToolStripMenuItem.Text = _phrases.Node("FASTER").PropertyForCulture("TEXT", "***"); fastestToolStripMenuItem.Text = _phrases.Node("FASTEST").PropertyForCulture("TEXT", "***"); //Allows us to hide item for ScottradeELITE if (_phrases.Node("SAVE_TO_CLOUD").PropertyForCulture("TEXT", "***") == "---") { saveToCloudToolStripMenuItem.Visible = false; } else { saveToCloudToolStripMenuItem.Text = _phrases.Node("SAVE_TO_CLOUD").PropertyForCulture("TEXT", "***"); } //Allows us to hide item for ScottradeELITE if (_phrases.Node("SMALL_BORDERS").PropertyForCulture("TEXT", "***") == "---") { smallBordersToolStripMenuItem.Visible = false; } else { smallBordersToolStripMenuItem.Text = _phrases.Node("SMALL_BORDERS").PropertyForCulture("TEXT", "***"); } getAlertHelpStripMenuItem.Visible = false; //doesn't appear to be used... lblWelcome.Text = _phrases.Node("NO_STRATEGIES").PropertyForCulture("TEXT", "***"); RefreshColumns(); dataGridView1.Invalidate(); RefreshWindowName(); } private Dictionary _originallyIcon = new Dictionary(); public void RefreshColumns() { if (null != Columns) { int strategiesColumnWidth = 0; IList columns = Columns; _columnListState.LoadFrom(dataGridView1); dataGridView1.RowTemplate.DefaultCellStyle.Padding = new Padding(0); // Increase row height for Symbol Plus layout. DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout); dataGridView1.EnableHeadersVisualStyles = false; dataGridView1.Columns.Clear(); //TODO: I would rather loop over all IDisplayColumns from the server instead of using "D_". See ConfigWindow for examples. //Default columns are added if no display type columns have been selected if (!_config.Columns.Contains("D_")) if (!_config.Columns.Contains("StrategyName")) AddDefaultColumns(); //Add StrategyName column if selected by user if (_config.Columns.Contains("StrategyName")) { dataGridView1.Columns.Add(DataCell.GetColumn(_strategyNameColumnInfo, _connectionMaster, this, new StrategyNameCell(), symbolPlusLayoutType: _symbolPlusLayout)); //Adjust the cell template for the strategy column so that each //cell that gets filled with textual data coming off the server will be text- //wrapped. dataGridView1.Columns[0].Name = "Strategies"; DataGridViewCell cell = this.dataGridView1.Columns[0].CellTemplate; cell.Style.WrapMode = DataGridViewTriState.True; } //because the IList is read-only, we need to add the strategy name //to a List instead...then pass this List to the hide/show column picker... foreach (ColumnInfo cI in Columns) { _totalColumns.Add(cI); } _totalColumns.Add(_strategyNameColumnInfo); foreach (ColumnInfo columnInfo in Columns) { columnInfo.UseEmptyColor = false; DataGridViewCell cellTemplate = null; // TODO there must be a better way than this. I don't want to copy this code // from the alert window. There should be a way to reuse it in place. if (columnInfo.Format == "alert quality" || columnInfo.InternalCode == "D_Quality") cellTemplate = new AlertQualityCell(columnInfo, _connectionMaster); else if (columnInfo.Format == "i" || columnInfo.InternalCode == "D_Type") cellTemplate = new AlertTypeCell(); else if (columnInfo.InternalCode == "D_Desc") { cellTemplate = new DescriptionCell(columnInfo, _connectionMaster, new DescriptionFormatter()); cellTemplate.Style.WrapMode = DataGridViewTriState.True; //make a larger default width of the strategy name column. strategiesColumnWidth = (int)(columnInfo.PreferredWidth * 0.75); } if (_textHeaders) { if (!_originallyIcon.ContainsKey(columnInfo)) _originallyIcon.Add(columnInfo, columnInfo.TextHeader); columnInfo.TextHeader = true; } else { if (_originallyIcon.ContainsKey(columnInfo)) columnInfo.TextHeader = _originallyIcon[columnInfo]; } DataGridViewColumn column = DataCell.GetColumn(columnInfo, _connectionMaster, this, cellTemplate, symbolPlusLayoutType: _symbolPlusLayout); if (_textHeaders) column.HeaderCell.Style.WrapMode = DataGridViewTriState.True; if (columnInfo.IsNumeric() || columnInfo.Format == "symbolplus") { column.HeaderCell.ContextMenuStrip = BuildColumnContextMenu(columnInfo); if (columnInfo.IsNumeric()) column.HeaderCell.ContextMenuStrip.Opening += ContextMenuStrip_Opening; } //Add user selected columns if (_config.Columns.Contains(columnInfo.InternalCode)) dataGridView1.Columns.Add(column); } // Check column count to avoid possible index was out of range exception if (dataGridView1.ColumnCount > 0) { dataGridView1.Columns[0].Width = strategiesColumnWidth; // add parameter for form type - RVH20210528 //_columnListState.SaveTo(dataGridView1); _columnListState.SaveTo(dataGridView1, FORM_TYPE); } var symbolplusColumn = dataGridView1.Columns.Cast().FirstOrDefault(gridColumn => gridColumn.ColumnInfo.Format == "symbolplus"); if (symbolplusColumn != null) { var adjustedColumn = DataCell.GetColumn(symbolplusColumn.ColumnInfo, _connectionMaster, this, symbolPlusLayoutType: _symbolPlusLayout); dataGridView1.Columns[symbolplusColumn.Index].MinimumWidth = adjustedColumn.MinimumWidth; if (!_restoringLayout) dataGridView1.Columns[symbolplusColumn.Index].Width = adjustedColumn.MinimumWidth; else { var width = _columnListState.GetColumnStateWidth(symbolplusColumn.ColumnInfo.InternalCode); if (width != -1) dataGridView1.Columns[symbolplusColumn.Index].Width = width; _restoringLayout = false; } } // clearing the rows breaks the styling, so we need to go back through each row and style it ApplyColumnColors(); StyleAllRows(); } } void ContextMenuStrip_Opening(object sender, CancelEventArgs e) { ContextMenuStrip menuStrip = sender as ContextMenuStrip; if (null != menuStrip) { menuStrip.Font = Font; GuiEnvironment.EnforceLimitedMode(menuStrip); } } private System.Windows.Forms.ContextMenuStrip BuildColumnContextMenu(ColumnInfo columnInfo) { System.Windows.Forms.ContextMenuStrip contextMenu = new System.Windows.Forms.ContextMenuStrip(); if (columnInfo.Format == "symbolplus") { // Add symbol plus layout options. ToolStripMenuItem symbolPlusMenuItem = new ToolStripMenuItem("Symbol Plus"); symbolPlusMenuItem.Font = GuiEnvironment.FontSettings; symbolPlusMenuItem.DropDownOpening += SymbolPlusMenuItem_DropDownOpening; symbolPlusMenuItem.Checked = _symbolPlusLayout != DataCell.SymbolPlusLayoutType.Off; symbolPlusMenuItem.Click += delegate { if (symbolPlusMenuItem.Checked) { var selectedOption = symbolPlusMenuItem.DropDownItems.Cast().ToList().FirstOrDefault(item => item.Checked); selectedOption?.PerformClick(); } else { var normalOption = symbolPlusMenuItem.DropDownItems.Cast().ToList().FirstOrDefault(item => item.Text == "Normal"); normalOption?.PerformClick(); } }; contextMenu.Items.Add(symbolPlusMenuItem); } else { TIContentMenuItem colorColumnMenuItem = new TIContentMenuItem(columnInfo.InternalCode, "Custom Colors for " + columnInfo.Description, columnInfo); colorColumnMenuItem.Click += colorColumnMenuItem_Click; colorColumnMenuItem.Image = TopListColorChooser.WindowIconCache.MenuImage; contextMenu.Items.Add(colorColumnMenuItem); } return contextMenu; } private void SymbolPlusMenuItem_DropDownOpening(object sender, EventArgs e) { ToolStripMenuItem toolStripMenuItem = sender as ToolStripMenuItem; if (toolStripMenuItem != null) { toolStripMenuItem.DropDownItems.Clear(); ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem("Normal"); toolStripMenuItem1.Click += delegate { if (!toolStripMenuItem1.Checked) { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Normal); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Normal; } else { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off; } RefreshColumns(); }; ToolStripMenuItem toolStripMenuItem2 = new ToolStripMenuItem("Logo Only"); toolStripMenuItem2.Click += delegate { if (!toolStripMenuItem2.Checked) { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.LogoOnly); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.LogoOnly; } else { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off; } RefreshColumns(); }; ToolStripMenuItem toolStripMenuItem3 = new ToolStripMenuItem("No Logo"); toolStripMenuItem3.Click += delegate { if (!toolStripMenuItem3.Checked) { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.NoLogo); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.NoLogo; } else { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off; } RefreshColumns(); }; ToolStripMenuItem toolStripMenuItem4 = new ToolStripMenuItem("Symbol/Logo"); toolStripMenuItem4.Click += delegate { if (!toolStripMenuItem4.Checked) { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.SymbolLogo); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.SymbolLogo; } else { DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off); _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off; } RefreshColumns(); }; if (_symbolPlusLayout == DataCell.SymbolPlusLayoutType.Normal) toolStripMenuItem1.Checked = true; else if (_symbolPlusLayout == DataCell.SymbolPlusLayoutType.LogoOnly) toolStripMenuItem2.Checked = true; else if (_symbolPlusLayout == DataCell.SymbolPlusLayoutType.NoLogo) toolStripMenuItem3.Checked = true; else if (_symbolPlusLayout == DataCell.SymbolPlusLayoutType.SymbolLogo) toolStripMenuItem4.Checked = true; toolStripMenuItem.DropDownItems.Add(toolStripMenuItem1); toolStripMenuItem.DropDownItems.Add(toolStripMenuItem2); toolStripMenuItem.DropDownItems.Add(toolStripMenuItem3); toolStripMenuItem.DropDownItems.Add(toolStripMenuItem4); } } void colorColumnMenuItem_Click(object sender, EventArgs e) { TIContentMenuItem colorColumnMenuItem = sender as TIContentMenuItem; if (null != colorColumnMenuItem) { ColumnInfo columnInfo = colorColumnMenuItem.ColumnInfo; GradientColorChooser colorChooser = new GradientColorChooser(); GradientInfo gradientInfo = new GradientInfo(); if (_columnColors.ContainsKey(columnInfo.InternalCode)) gradientInfo = _columnColors[columnInfo.InternalCode]; colorChooser.GradientInfo = gradientInfo; TopListColorChooser configureColorsForm = new TopListColorChooser(_connectionMaster); configureColorsForm.LimitToColumn(columnInfo); configureColorsForm.GradientColorChooser = colorChooser; configureColorsForm.ShowDialog(); if (configureColorsForm.DialogResult == System.Windows.Forms.DialogResult.OK) { if (_columnColors.ContainsKey(columnInfo.InternalCode)) _columnColors[columnInfo.InternalCode] = colorChooser.GradientInfo; else _columnColors.Add(columnInfo.InternalCode, colorChooser.GradientInfo); columnInfo.GradientInfo = colorChooser.GradientInfo; StyleAllRows(); } configureColorsForm.Dispose(); } } public void AddSpecialColumns() { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(""); XmlNode temp = xmlDoc.SelectSingleNode("temp"); XmlNode columnsState = temp.NewNode("COLUMNS"); _columnListState.SaveTo(columnsState); XmlNode state = columnsState.Node("STATE"); //Columns will include all displayed columns //Add Special and old show/hide columns to the Columns string based on column order and column state. //This will allow the old layout MultiStrategy windows to display correctly. string newColumns = _config.Columns; string[] numberOfColumns = _config.Columns.Split(COLUMNS_NUMBERSSPLIT_ON, StringSplitOptions.RemoveEmptyEntries); int noColmns = numberOfColumns.Length; foreach (string colItem in _columnListState._columnOrder) { //Start by considering adding columns found in the column order list but not in the columns config string. if (!_config.Columns.Contains(colItem)) { if (colItem == "Description" && _config.Columns.Contains(columnCode(colItem))) { // Unlike the other column codes, "Description is the only case where the whole word ("Description") // is not present in the column code. So we use this if-block to check this particular case. // Otherwise what can occur is that extra "D_Desc" can be appended to the Columns string. continue; } //Check the state of the column candidate if (state.InnerXml.Contains(colItem)) { foreach (XmlNode node in state) { if ((colItem == node.Property("CODE", "")) && (node.Property("VISIBLE", "0") == "1" ? true : false)) { newColumns += columnCode(colItem) + "&show" + noColmns.ToString() + "="; noColmns++; break; } } } } } //Add defalt columns initially if (_columnListState._columnOrder.Count == 0) { newColumns += "D_Symbol" + "&show" + noColmns.ToString() + "="; noColmns++; newColumns += "D_Time" + "&show" + noColmns.ToString() + "="; noColmns++; newColumns += "StrategyName" + "&show" + noColmns.ToString() + "="; noColmns++; } //Update Column string to include special columns _config.Columns = newColumns; } private void AddDefaultColumns() { //Add default columns Symbol, Time, and Strategy Name to the column config string string[] numberOfColumns = _config.Columns.Split(COLUMNS_NUMBERSSPLIT_ON, StringSplitOptions.RemoveEmptyEntries); int noColmns = numberOfColumns.Length; _config.Columns += "D_Symbol" + "&show" + noColmns.ToString() + "="; noColmns++; _config.Columns += "D_Time" + "&show" + noColmns.ToString() + "="; noColmns++; _config.Columns += "StrategyName" + "&show" + noColmns.ToString() + "="; } private string columnCode(string col) { //The column code data in the state node of _columnsState are not the same codes used in the Columns config string. //This routines returns the correct column code. These codes only covers those columns avaliable with //the old show/hide column logic. string code = col; if (col == "Type") code = "D_Type"; else if (code == "Time") code = "D_Time"; else if (code == "Symbol") code = "D_Symbol"; else if (code == "StrategyName") code = "StrategyName"; else if (code == "Description") code = "D_Desc"; else if (code == "Quality") code = "Quality"; return code; } private void InstallNewColumns(IList newColumns) { if (!ColumnInfo.Equal(newColumns, Columns)) { Columns = newColumns; RefreshColumns(); } } private void StyleAllRows() { dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; foreach (DataGridViewRow row in dataGridView1.Rows) { StyleRow(row); } /*The StyleAllRows method is called during the process of loading a file. in this scenario, this method is executed after the dataGridView1_ColumnWidthChanged event method. This if-block is necessary to maintain the same state of the window just before saving-that is if the description header is minimized and all rows are of single row-height, this state will be returned when the file is loaded.(the row-heights won't be tall)*/ if (!isVerboseColumnWidthMinimum() && _symbolPlusLayout == DataCell.SymbolPlusLayoutType.Off) { dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; } } private void StyleRow(DataGridViewRow row) { RowData data = (RowData)row.DataBoundItem; row.DefaultCellStyle = (data.GetAsObject(typeof(DataWatcher)) as DataWatcher).Style; //numerical values right-aligned here row.DefaultCellStyle.Alignment = DataGridViewContentAlignment.NotSet; } private void resizeColumns_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.ResizeColumns", _sendManager); dataGridView1.AutoResizeColumns(); } private void smallBordersToolStripMenuItem_Click(object sender, EventArgs e) { setBorders(); } private void setBorders() { if (smallBordersToolStripMenuItem.Checked) FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; else FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; } private void dontRepeatToolStripMenuItem_Click(object sender, EventArgs e) //This is the Window level { using (NoRepeat _noRepeat = new NoRepeat(_inNoRepeatMode, _repeatInterval, 1)) { if (_noRepeat.ShowDialog() == DialogResult.OK) { //When the WINDOW Don't Repeat For is changed, then each strategy's "Don't Repeat For" is *turned off* foreach (DataWatcher strat in _config.Strategies) { strat.InNoRepeatMode = false; strat.StrategyDelayTable.Clear(); strat.PreviousNoRepeatModeSetting = false; } if (_noRepeat.SymbolDelayOptionChecked) { dontRepeatToolStripMenuItem.Checked = true; _inNoRepeatMode = true; _previousNoRepeatModeSetting = true; _strategyDelayTable.Clear(); _repeatInterval = _noRepeat.TimeDelay; SetConfigStreaming(); } else { dontRepeatToolStripMenuItem.Checked = false; _previousNoRepeatModeSetting = false; _inNoRepeatMode = false; _strategyDelayTable.Clear(); SetConfigStreaming(); //if (CurrentlyUsingHistory) //{ // HistoryTimeFrame.ConfigHistory c = HistoryTimeFrame.HistorySetting; // SetConfigHistory(c.itemConfig, c.itemStart, c.itemEnd); //} } } } } private bool processNewlyArrivedData(RowData rowData) { /*This method processes the newly arrived data, and before it's added to the boundsList. This method is used while in the "Don't Repeat For mode". With Alert Window, each symbol that comes off is "fixed"-you can't change its name. However with Multistrategy, you can change the name of any strategy you wish. One can give two different strategies the same name-although they have different config strings. Hence the reason for getting the strategy's config string instead of the name of strategy */ //Now we're getting to the newly arrived data... string symbol = rowData.GetSymbol(); string stratConfig = (rowData.GetAsObject(typeof(DataWatcher)) as DataWatcher).Config; DateTime time = (DateTime)rowData.GetTime(); if (_inNoRepeatMode) //"Global" no repeat. We're looking at just the symbol being repeated.. irrespective of the strategy { if (!isSymbolPresent(symbol)) { _strategyDelayTable.Add(new StrategyStruct(stratConfig, symbol), time); } else //if the symbol is already in dictionary, we must compare timespans { if (_repeatInterval == 0) //user has selected "Don't Repeat" option... { return false; //continue } DateTime tableTime = fetchStoredDictionaryTime(symbol); TimeSpan ts = time.Subtract(tableTime); int elapsedTime = Math.Abs((int)ts.TotalMinutes); if (elapsedTime >= _repeatInterval) { //update the dictionary removeStrategyStruct(symbol); _strategyDelayTable.Add(new StrategyStruct(stratConfig, symbol), time); } else //strategy data doesn't meet timedelay requirement..don't add to boundlist or dictionary update { return false; //continue } } } else { //first,get datawatcher (we already have its config string from the rowData object). DataWatcher newlyArrivedDataWatcher = rowData.GetAsObject(typeof(DataWatcher)) as DataWatcher; if (newlyArrivedDataWatcher == null) { return false; } //does this datawatcher object(strategy) have its Don't Repeat For turned on..? if (newlyArrivedDataWatcher.InNoRepeatMode) { //Now, check to see if this individual datawatcher object has symbol in question if (!newlyArrivedDataWatcher.isSymbolPresent(symbol)) { newlyArrivedDataWatcher.StrategyDelayTable.Add(symbol, time); } else //if the strategy is already in dictionary, we must compare timespans { if (newlyArrivedDataWatcher.RepeatInterval == 0) //This strategy noRepeat feature is not on //user has selected "Don't Repeat" option... { return false; //continue } DateTime? ttime = newlyArrivedDataWatcher.fetchStoredDictionaryTime(symbol); DateTime tableTime = (DateTime)ttime; if (ttime == null) { return false; } TimeSpan ts = time.Subtract(tableTime); int elapsedTime = Math.Abs((int)ts.TotalMinutes); if (elapsedTime >= newlyArrivedDataWatcher.RepeatInterval) { //update the strategy's dictionary newlyArrivedDataWatcher.removeSymbol(symbol); newlyArrivedDataWatcher.StrategyDelayTable.Add(symbol, time); } else //strategy data doesn't meet timedelay requirement..don't add to boundlist or dictionary update { return false; //continue } } } } _newlyProcessedList.Add(symbol); _newlyPrecessedListText.Add(_actions.GetTextToSpeak(GetAlertTemplate(), GetSubstitutionRules(rowData))); return true; } private bool areStrategyAndSymbolPresent(string strategy, string symbol) { foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategyConfig == strategy && s.StrategySymbol == symbol) { return true; } } return false; } private bool isSymbolPresent(string symbol) { foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategySymbol == symbol) { return true; } } return false; } private void removeStrategyStruct(string strategy, string symbol) //removing a dictionary entry... { foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategyConfig == strategy && s.StrategySymbol == symbol) { _strategyDelayTable.Remove(s); break; } } } private void removeStrategyStruct(string symbol) //removing a dictionary entry... { foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategySymbol == symbol) { _strategyDelayTable.Remove(s); break; } } } private DateTime fetchStoredDictionaryTime(string strategy, string symbol) { DateTime dT = new DateTime(); foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategyConfig == strategy && s.StrategySymbol == symbol) { dT = _strategyDelayTable[s]; break; } } return dT; } private DateTime fetchStoredDictionaryTime(string symbol) { DateTime dT = new DateTime(); foreach (StrategyStruct s in _strategyDelayTable.Keys) { if (s.StrategySymbol == symbol) { dT = _strategyDelayTable[s]; break; } } return dT; } public bool FakeStreaming { get; private set; } public int StreamingStrategyIntervalMS { get { return streamingStrategyTimer.Interval; } set { streamingStrategyTimer.Interval = value; } } /// /// Returns the substitution rules for the speech alert template for this window type /// /// /// RowData object that contains the row information /// /// private Dictionary GetSubstitutionRules(RowData data) { var rules = new Dictionary(); var description = data.GetAsString("c_D_Desc"); var index = description.IndexOf("."); if (index > 0) description = description.Substring(0, index); rules.Add("DESCRIPTION", description); rules.Add("SYMBOL", data.GetSymbol()); rules.Add("PRICE", data.GetPrice().ToString()); rules.Add("WINDOW_NAME", this.BaseWindowName); DataWatcher rowDataWatcher = data.GetAsObject(typeof(DataWatcher)) as DataWatcher; rules.Add("STRATEGY_NAME", rowDataWatcher.Name); return rules; } /// /// Returns the template for speech alerts for this window /// /// private string GetAlertTemplate() { return !string.IsNullOrEmpty(GuiEnvironment.MultiStrategyWindowAlertTemplate) ? GuiEnvironment.MultiStrategyWindowAlertTemplate : GuiEnvironment.DefaultAlertTemplate; } private void NewStreamingStrategies(List data) { //The below is copied from Phil's code from the speed setting for //alerts. if (FakeStreaming) { QueuedStreamingStrategies.AddRange(data); if (QueuedStreamingStrategies.Count > 0) { int estimatedInputPeriod; if (data.Count < 35) { // It stinks that we have to estimate this on the client. But this rule // is not too far from accurate. And the server probably won't change // much in the future. If you get fewer than 35 alerts at once, the server // will send the next batch in about 1 second. estimatedInputPeriod = 1000; } else { // If we get 35 or more alerts, the server will slow us down and send the // next batch in about 2 seconds. estimatedInputPeriod = 2000; // This is incomplete. For one thing, if any window gets 35 or more // alerts, all windows slow down. We could do better, but I think this // is reasonable. PDS. } QueuePeriod = estimatedInputPeriod / QueuedStreamingStrategies.Count; QueueFinishTime = DateTime.Now.AddMilliseconds(estimatedInputPeriod - 100); } } else { if (QueuedStreamingStrategies.Count > 0) { StreamingAlertsData(QueuedStreamingStrategies); QueuedStreamingStrategies.Clear(); } StreamingAlertsData(data); } } private void streamingStrategiesTimer_Tick(object sender, EventArgs e) { //this code is copied directly from phil's within the Alert Window. //seems to work for the speed settings of the multistrategy if (QueuedStreamingStrategies.Count == 0) return; int idealQueueSize = (int)((QueueFinishTime - DateTime.Now).TotalMilliseconds / QueuePeriod); if (idealQueueSize < 0) idealQueueSize = 0; int toSend = QueuedStreamingStrategies.Count - idealQueueSize; if (toSend <= 0) return; List current = new List(toSend); for (int i = 0; i < toSend; i++) current.Add(QueuedStreamingStrategies[i]); QueuedStreamingStrategies.RemoveRange(0, toSend); StreamingAlertsData(current); } private void normalToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Normal", _sendManager); normal(); } public void normal() { FakeStreaming = false; mutualExcludeSpeed(normalToolStripMenuItem); } private void slowestToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Slowest", _sendManager); slowest(); } public void slowest() { FakeStreaming = true; StreamingStrategyIntervalMS = 7368; mutualExcludeSpeed(slowestToolStripMenuItem); } private void slowToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Slow", _sendManager); slow(); } public void slow() { FakeStreaming = true; StreamingStrategyIntervalMS = 2714; mutualExcludeSpeed(slowToolStripMenuItem); } private void fastToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Fast", _sendManager); fast(); } public void fast() { FakeStreaming = true; StreamingStrategyIntervalMS = 368; mutualExcludeSpeed(fastToolStripMenuItem); } private void fasterToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Faster", _sendManager); faster(); } public void faster() { FakeStreaming = true; StreamingStrategyIntervalMS = 136; mutualExcludeSpeed(fasterToolStripMenuItem); } private void fastestToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Speed.Fastest", _sendManager); fastest(); } public void fastest() { FakeStreaming = true; StreamingStrategyIntervalMS = 50; mutualExcludeSpeed(fastestToolStripMenuItem); } private void mutualExcludeSpeed(ToolStripMenuItem item) { //this method ensures mutually exclusive speed menu-items foreach (ToolStripMenuItem t in _speedItems) { if (t.Text == item.Text) { t.Checked = true; continue; } t.Checked = false; } } private readonly int MAX_ITEMS = GuiEnvironment.XmlConfig.Node("ALERT_WINDOW").Node("MAX_ALERTS_BEFORE_DELETE").Property("VALUE", 1000); void StreamingAlertsData(List data, bool ignoreActions = false) { _notInRepeatList.Clear(); _newlyProcessedList.Clear(); _notInRepeatListText.Clear(); _newlyPrecessedListText.Clear(); // Delete stuff if the list gets too long. bool removedItems = false; int firstRow = dataGridView1.FirstDisplayedScrollingRowIndex; int firstColumn = dataGridView1.FirstDisplayedScrollingColumnIndex; bool deletedFirstVisibleRow = false; //After deleting strategies, dataGridView1.Columns is null so we need to refresh columns to avoid exceptions during debugging //or avoid empty windows during runtime. if (dataGridView1.Columns.Count == 0) RefreshColumns(); foreach (RowData rowData in data) { DataWatcher rowDataWatcher = rowData.GetAsObject(typeof(DataWatcher)) as DataWatcher; if (_inNoRepeatMode == false && (rowDataWatcher.InNoRepeatMode == true && processNewlyArrivedData(rowData) == true)) { doSorting(rowData); } else if (_inNoRepeatMode == false && (rowDataWatcher.InNoRepeatMode == true && processNewlyArrivedData(rowData) == false)) { continue; } else if (_inNoRepeatMode == false || (_inNoRepeatMode == true && processNewlyArrivedData(rowData) == true)) { doSorting(rowData); } if (firstRow > 0) { firstRow++; // keeping track of where the original top row is now } if (!_inNoRepeatMode) { _notInRepeatList.Add(rowData.GetSymbol()); _notInRepeatListText.Add(_actions.GetTextToSpeak(GetAlertTemplate(), GetSubstitutionRules(rowData))); } } if (GlobalDataSettings.GetDataGridColumnSetting(FORM_TYPE, "D_Symbol").Format == "symbolplus") { // Symbol Plus format is specified. So reset the symbol plus column format. DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, _symbolPlusLayout); } // Ignore actions if (!ignoreActions) { if (_newlyProcessedList.Count > 0) { _actions.Perform(_newlyPrecessedListText); } if (_notInRepeatList.Count > 0) { _actions.Perform(_notInRepeatListText); } } //if (_inNoRepeatMode) //{ // if (_newlyProcessedList.Count > 0) // { // _actions.Perform(_newlyProcessedList); // } //} //else //normal(non repeat) mode //{ // if (_notInRepeatList.Count > 0) // { // _actions.Perform(_notInRepeatList); // } //} // //dataGridView1.SuspendLayout(); while (_boundList.Count > MAX_ITEMS) { removedItems = true; if (!deletedFirstVisibleRow && _boundList.Count - 1 == firstRow) { deletedFirstVisibleRow = true; } _boundList.RemoveAt(_boundList.Count - 1); } if (removedItems && deletedFirstVisibleRow && dataGridView1.DisplayRectangle.Width > 3) { //scroll to top //use firstColumn as index for Cells to avoid referencing a hidden column that causes the debugger to through an exception dataGridView1.FirstDisplayedCell = dataGridView1.Rows[0].Cells[firstColumn]; } else if ((firstRow >= 0) && (firstRow <= (dataGridView1.Rows.Count - 1))) { if (dataGridView1.Rows[firstRow].Cells.Count != 0 && dataGridView1.DisplayRectangle.Width > 3) { dataGridView1.FirstDisplayedCell = dataGridView1.Rows[firstRow].Cells[firstColumn]; } } } // This is needed to keep track of the last column index that was used in the most recent menustripneeded callback. // It's required because of Limited Mode which disables or enables all menu items based on the mode. That is performed // in the Opening event, but the Opening event doesn't have a column index. This is used there. private int _lastContextMenuNeededColumnIndex; private void dataGridView1_CellContextMenuStripNeeded(object sender, DataGridViewCellContextMenuStripNeededEventArgs e) { _lastContextMenuNeededColumnIndex = e.ColumnIndex; Column.UpdateGraphicsMenuItem(graphicalIndicatorToolStripMenuItem, dataGridView1, e.ColumnIndex); } public class DataWatcher : IHoldOddsMakerConfig { private MultiStrategy _owner; private List _phrases; private StreamingAlerts _streamingAlerts; private History _history; private History _initialHistory; private bool _inDemoMode; private bool _dontRepeatDisabled = false; //when in history, we'll disable the actual strategy "do not repeat" menu item. public AlertForm _alert; public OddsMakerConfiguration.OddsMakerConfigMemento _userOddsSettings = new OddsMakerConfiguration.OddsMakerConfigMemento(); public OddsMakerConfigWindow _odds; private BackgroundWorker backgroundWorker1 = new BackgroundWorker(); private bool _inNoRepeatMode = false; private int _repeatInterval = 5; //_previousNoRepeatModeSetting is for preserving state of repeat mode when user //comes off history mode... private bool _previousNoRepeatModeSetting = false; //For use in the Don't Repeat For" functionality //Each strategy can be customized with its own "don't repeat for" settings-hence its own dictionary // private Dictionary _strategyDelayTable = new Dictionary(); private Dictionary _strategyDelayTable = new Dictionary(); public DataWatcher(MultiStrategy owner) { _owner = owner; Style = _owner.dataGridView1.DefaultCellStyle.Clone(); Style.Font = null; _phrases = GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("PHRASES"); } // Null means don't know. Empty string means the server said empty string. // We do this to be consistent with the title bar in the alert window, although // I don't know if we're going to use this feature here. Note: If we send // a new strategy, we keep the old name until the server gives us a new // one. If the cut off the strategy, we keep the old name forever. It's // certainly possible for someone to cut off a strategy, but still display // data from that strategy. So the name should stay. //comment out for now... needed to change the setter to public //when I was duplicating the MultiStrategy Window // public string Name { get; private set; } public string Name { get; set; } // This will be used for all rows generated from this strategy. Each row // will point to this object, not a copy of the object. Presumably you can // make a lot of changes at once by modifying this object, and then invalidating // the table. public DataGridViewCellStyle Style { get; private set; } private List _additionalSymbolPlusColumns = new List(); private bool _addedSymbolPlusColumns = false; private string _addedConfigFields = ""; private string _config; public string Config { get { return _config; } set { // Note that we do NOT check if the config string is the same as it was before. // That would be tricky because of the way we modify the config string. _config = value; if ((value != "") && (null != value)) { ReplaceColumnData(); //_config += _owner._config.Columns; } _addedSymbolPlusColumns = false; StartData(); } } public bool PreviousNoRepeatModeSetting { get { return _previousNoRepeatModeSetting; } set { _previousNoRepeatModeSetting = value; } } public bool InNoRepeatMode { get { return _inNoRepeatMode; } set { _inNoRepeatMode = value; } } public int RepeatInterval { get { return _repeatInterval; } set { _repeatInterval = value; } } public bool NoRepeatMenuItemDisabled { get { return _dontRepeatDisabled; } set { _dontRepeatDisabled = value; } } public Dictionary StrategyDelayTable { get { return _strategyDelayTable; } set { _strategyDelayTable = value; } } public bool ConfigValid() { return (_config != "") && (null != _config); } public bool InDemoMode { get { return _inDemoMode; } set { _inDemoMode = value; } } private bool _disabled = false; public bool Disabled { get { return _disabled; } set { if (value != _disabled) { _disabled = value; StartData(); } } } //now that each strategy can be individually customized with respect to "don't repeat" //the below three methods that are seen in the main program (global "don't repeat") //are used here..with some modification public bool isSymbolPresent(string symbol) { if (_strategyDelayTable.ContainsKey(symbol)) { return true; } return false; } public void removeSymbol(String symbol)//removing a dictionary entry... { _strategyDelayTable.Remove(symbol); } public DateTime? fetchStoredDictionaryTime(string symbol) { DateTime? dT = null; if (_strategyDelayTable.ContainsKey(symbol)) { dT = _strategyDelayTable[symbol]; } return dT; } /// /// The current default columns settings replaces the strategy column settings /// This wil avoid saving multiple column information for strategies (especially disabled ones). /// private void ReplaceColumnData() { string configWithoutColumns = RemoveShowColumns(); _config = configWithoutColumns + _owner._config.Columns; } private string RemoveShowColumns() { string queryString = _config; queryString.Replace("https://www.trade-ideas.com/Config.php?", ""); System.Collections.Specialized.NameValueCollection uriParameters = HttpUtility.ParseQueryString(queryString); List toRemove = new List(); foreach (string parameterName in uriParameters.Keys) { if (parameterName.StartsWith("show") || parameterName == "col_ver") toRemove.Add(parameterName); } foreach (string parameterName in toRemove) { uriParameters.Remove(parameterName); } return uriParameters.ToString(); } public void SwitchToStreaming() { StopHistory(); StartData(); } private void StartData() { if (null != _initialHistory) { _initialHistory.Stop(); _initialHistory.HistoryData -= _initialHistory_HistoryData; _initialHistory = null; } if (null != _streamingAlerts) { _streamingAlerts.Stop(); _streamingAlerts.StreamingAlertsConfig -= _streamingAlerts_StreamingAlertsConfig; _streamingAlerts.StreamingAlertsData -= _streamingAlerts_StreamingAlertsData; _streamingAlerts = null; } if ((!_disabled) && ConfigValid()) { ReplaceColumnData(); //_config += _owner._config.Columns; // Update config to include new fields needed for the Symbol Plus column. _config = AddAdditionalFieldsToConfig(_config, _additionalSymbolPlusColumns); _setConfigInitialHistory(_config, null, null); _streamingAlerts = _owner._connectionMaster.StreamingAlertsManager.GetAlerts(_config); if (_streamingAlerts == null) return; _streamingAlerts.StreamingAlertsConfig += _streamingAlerts_StreamingAlertsConfig; _streamingAlerts.StreamingAlertsData += _streamingAlerts_StreamingAlertsData; _streamingAlerts.Start(); } if ((_disabled) && ConfigValid()) { // Capture any new changes to columns for disabled strategies ReplaceColumnData(); //_config += _owner._config.Columns; } } void _streamingAlerts_StreamingAlertsData(List data, StreamingAlerts source) { _owner.BeginInvokeIfRequired((MethodInvoker)delegate { if (source == _streamingAlerts) { foreach (RowData rowData in data) { // Store a pointer back to this object. // This is required to set the style and the strategy name. // Both can change for existing rows if this object changes. rowData.Data.Add(typeof(DataWatcher), this); } _owner.NewStreamingStrategies(data); } }); } void _streamingAlerts_StreamingAlertsConfig(StreamingAlerts source) { _owner.BeginInvokeIfRequired((MethodInvoker)delegate { if (_streamingAlerts == source && null != source) { _config = source.Config; // Check to see if symbol plus is enabled. Add compliment columns, if it hasn't been done yet. if (GlobalDataSettings.GetDataGridColumnSetting(FORM_TYPE, "D_Symbol").Format == "symbolplus" && !_addedSymbolPlusColumns) { CreateAdditionalSymbolPlusColumns(source); _addedSymbolPlusColumns = true; if (_additionalSymbolPlusColumns.Count > 0) { StartData(); return; } } Name = source.WindowName; _owner.InstallNewColumns(source.Columns); _owner.dataGridView1.Invalidate(); } }); } public void _setConfigInitialHistory(string Config, DateTime? StartTime, DateTime? EndTime) { // No initial History if user is in delayed data mode. TODO: How to ask for initial history in delayed data mode? if (_owner._connectionMaster.LoginManager.IsDemo) return; Debug.Assert(null != Config); HistoryRequest r; r.Config = Config; r.StartTime = StartTime; // When user enters null for EndTime set EndTime to find data up midnight today. if (null == EndTime) EndTime = ServerFormats.Now.Date; r.EndTime = EndTime; r.MaxCount = 1; // request one data point per strategy _initialHistory = _owner._connectionMaster.HistoryManager.GetHistory(r); if (_initialHistory == null) return; _initialHistory.HistoryData += new HistoryData(_initialHistory_HistoryData); _initialHistory.HistoryStatus += new HistoryStatus(_initialHistory_HistoryStatus); _initialHistory.Start(); } void _initialHistory_HistoryData(List data, History source) { _owner.BeginInvokeIfRequired((MethodInvoker)delegate { if (source == _initialHistory) { // Check if user is in delayed data mode. // Added logic here to avoid exception when we change to delayed data mode from a regular subscriber. if (_owner._connectionMaster.LoginManager.IsDemo && null != _initialHistory) { _initialHistory.Stop(); return; } // If there is no column data available and initial history data is available then // restart initial history request. // This fixes a bug where no initial history would be displayed when initial history // data was ready before column data was ready. if ((_owner.dataGridView1.FirstDisplayedScrollingColumnIndex == -1) && (data.Count() > 0)) { //System.Diagnostics.Debug.WriteLine("_initialHistory_HistoryData: no column data, restart initial history request."); // Stop and start initial history request if (null != _initialHistory) { _initialHistory.Stop(); _initialHistory.HistoryData -= _initialHistory_HistoryData; _initialHistory.HistoryStatus -= _initialHistory_HistoryStatus; _initialHistory = null; } _setConfigInitialHistory(_config, null, null); return; } //Can't add rows if no columns exist if (_owner.dataGridView1.Columns.Count > 0) { foreach (RowData rowData in data) { // Store a pointer back to this object. // This is required to set the style and the strategy name. // Both can change for existing rows if this object changes. rowData.Data.Add(typeof(DataWatcher), this); } // For initial history data ignore actions. _owner.StreamingAlertsData(data, true); } } }); } void _initialHistory_HistoryStatus(History sender) { _owner.BeginInvokeIfRequired((MethodInvoker)delegate { if (sender == _initialHistory && null != _initialHistory) { // Stop as soon as we get data if (_initialHistory.HistoryDisposition == HistoryDisposition.Done || _initialHistory.HistoryDisposition == HistoryDisposition.MoreAvailable) { _initialHistory.Stop(); }; }; }); } public void Stop() { Config = null; } public void StopHistory() { if (null != _history) { _history.Stop(); _history.HistoryData -= _history_HistoryData; _history.HistoryStatus -= _history_HistoryStatus; _history = null; } } public void stopStreaming() { if (null != _initialHistory) { _initialHistory.Stop(); _initialHistory.HistoryData -= _initialHistory_HistoryData; _initialHistory.HistoryStatus -= _initialHistory_HistoryStatus; _initialHistory = null; } if (null != _streamingAlerts) { _streamingAlerts.Stop(); _streamingAlerts.StreamingAlertsConfig -= _streamingAlerts_StreamingAlertsConfig; _streamingAlerts.StreamingAlertsData -= _streamingAlerts_StreamingAlertsData; _streamingAlerts = null; } } public void StartHistory(DateTime? StartTime, DateTime? EndTime, DataWatcher d, int divisor) { /*m to 100 gives much better performance (that is,the total number of strategies being 100 per window versus 1000.*/ double m = 1000.0 / (double)divisor; int max = (int)(Math.Truncate(m)); HistoryRequest r; r.Config = d.Config; r.StartTime = StartTime; r.EndTime = EndTime; r.MaxCount = max; // null is the quick way to request the default. //r.MaxCount = 10; // For testing! d.stopStreaming(); _history = _owner._connectionMaster.HistoryManager.GetHistory(r); _history.HistoryData += new HistoryData(_history_HistoryData); _history.HistoryStatus += new HistoryStatus(_history_HistoryStatus); _history.Start(); } void _history_HistoryStatus(History sender) { _owner.BeginInvokeIfRequired((MethodInvoker)delegate { HistoryStatusInGuiThread(sender); }); } void HistoryStatusInGuiThread(History sender) { if (sender == _history) { _owner.HistoryStatus(sender); } } void _history_HistoryData(List alerts, History sender) { if (InDemoMode) { return; } if (alerts.Count > 0) _owner.BeginInvokeIfRequired((MethodInvoker)delegate { HistoryDataInGuiThread(alerts, sender); }); } void HistoryDataInGuiThread(List alerts, History sender) { if (sender == _history) { _owner.HistoryData(alerts, this); } } public override string ToString() { if (!ConfigValid()) { // This is specifically aimed at the list box on the config window. return _phrases.Node("NEW_STRATEGY").PropertyForCulture("TEXT", "***"); } else if (null == Name) { // The server has not gotten back with us yet. return _phrases.Node("UNKNOWN_NAME").PropertyForCulture("TEXT", "***"); } else if (Name.Trim() == "") { // The user picked a name like "" or " ". return _phrases.Node("NO_NAME").PropertyForCulture("TEXT", "***"); } else return Name; } public void SetOddsMakerSettings(OddsMakerConfiguration.OddsMakerConfigMemento oddsMakerSettings) { _userOddsSettings = oddsMakerSettings; } /// /// Create a list of columns for those needed by the Symbol Plus column. /// /// private void CreateAdditionalSymbolPlusColumns(StreamingAlerts source) { _additionalSymbolPlusColumns.Clear(); // Check to see if Price is not already a field. If not, add it. if (source.Columns.FirstOrDefault(x => x.WireName == "c_Price") == null) { _additionalSymbolPlusColumns.Add(new ColumnInfo() { InternalCode = "Price" }); } // Check to see if Change From Close Percent is not already a field. If not, add it. if (source.Columns.FirstOrDefault(x => x.WireName == "c_FCP") == null) { _additionalSymbolPlusColumns.Add(new ColumnInfo() { InternalCode = "FCP" }); } // Check to see if Change From Close Dollars is not already a field. If not, add it. if (source.Columns.FirstOrDefault(x => x.WireName == "c_FCD") == null) { _additionalSymbolPlusColumns.Add(new ColumnInfo() { InternalCode = "FCD" }); } } /// /// Add additional fields to config string. /// /// /// /// private string AddAdditionalFieldsToConfig(string config, List additionalColumns) { string newConfig = config; if (additionalColumns.Count > 0) { // Find last show parameter count. int showParamCt = 0; int showPOS = config.LastIndexOf("&show"); if (showPOS >= 0) { int equalPOS = config.IndexOf('=', showPOS); if (equalPOS >= 0) { string showParamNum = config.Substring(showPOS + 5, equalPOS - (showPOS + 5)); if (!int.TryParse(showParamNum, out showParamCt)) showParamCt = 0; } } // Add new fields to config string. int newParamCt = showParamCt; _addedConfigFields = ""; foreach (ColumnInfo columnInfo in additionalColumns) { _addedConfigFields += $"&show{newParamCt}={columnInfo.InternalCode}"; newParamCt++; } // Update last column number. newConfig = newConfig.Replace($"&show{showParamCt}=", $"&show{newParamCt}="); // Insert new parameters into config string. newConfig = newConfig.Insert(showPOS, _addedConfigFields); } return newConfig; } } private void HistoryStatus(History history) { if (null != history.Columns) InstallNewColumns(history.Columns); if (history.HistoryDisposition == HistoryDisposition.Done || history.HistoryDisposition == HistoryDisposition.MoreAvailable) { Finished++; } if (Finished == _selectedStrategies) { _historyTempList.Clear(); try { _boundList.Clear(); BindingList b = new BindingList(); dataGridView1.SuspendLayout(); foreach (var value in _historySortedList.Values.Reverse()) b.Add(value); dataGridView1.DataSource = b; _boundList = b; dataGridView1.ResumeLayout(); } catch (Exception ex) { string test = ex.Message; //for testing } HistoryMode = HistoryModeEnum.HistoryDone; } } void HistoryData(List alerts, DataWatcher dataWatcher) { //Can't add rows if no columns exist if (dataGridView1.Columns.Count > 0) { foreach (RowData rowData in alerts) { //When logged in as DEMO "ID" key is not available skip row data if (!rowData.Data.ContainsKey("ID")) continue; var test = rowData.Data["ID"]; string numstring = test as string; long number = Convert.ToInt64(numstring); rowData.Data.Add(typeof(DataWatcher), dataWatcher); if (!_historySortedList.ContainsKey(number)) { _historySortedList.Add(number, rowData); } } if (_historyTempList.Count == 0) // First data in a while. Schedule a screen update soon. DisplayTempHistoryDataSoon(); else // Data is flowing in faster than we can display it. // Defer the next screen update so we can display more at once. _historyUpdatedRecently = true; _historyTempList.Add(alerts); } } /// /// History data can come in pretty quickly. /// When it arrives we store it in _historySortedList and _historyTempList. /// At various intervals we copy _historyTempList into the grid. That is done here. /// _historySortedList will be handled later. /// When we handle _historySortedList, _historyTempList will become obsolete. /// private void DisplayTempHistoryData() { if (_historyUpdatedRecently) { // History is still streaming in too quickly. Try again later. _historyUpdatedRecently = false; DisplayTempHistoryDataSoon(); } else { // When I comment out SuspendLayout and ResumeLayout, it doesn't make any difference. // Presumably this whole idea of trying to defer the updates, so we can do more // between each call to SuspendLayout and ResumeLayout doesn't do anything. dataGridView1.SuspendLayout(); foreach (List batch in _historyTempList) foreach (RowData rowData in batch) _boundList.Add(rowData); dataGridView1.ResumeLayout(); _historyTempList.Clear(); } } private void DisplayTempHistoryDataSoon() { BeginInvoke((MethodInvoker)DisplayTempHistoryData); } private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e) { for (int i = 0; i < e.RowCount; i++) { DataGridViewRow row = dataGridView1.Rows[e.RowIndex + i]; StyleRow(row); } } public void doSorting(RowData rowData) { int insertionIndex = SortIndex(rowData); if (insertionIndex >= _boundList.Count) { _boundList.Add(rowData); //Add to the end } else { _boundList.Insert(insertionIndex, rowData); } } private int SortIndex(RowData rowData) //Modified from that in AlertForm.cs. Here we're sorting by Time..descending { //Return the insertion index where the rowData belongs in _bindingList int insertionIndex = 0; List rows = _boundList.ToList(); long test = rowData.GetTimeT(); if (test == 0) // we have error... { //send the index of the end of the rows return rows.Count; } if (rows.Count > 0) { foreach (RowData row in rows) { long rowDataAsLong = rowData.GetTimeT(); if (rowDataAsLong == 0) //This happens when we get error { continue; } long rowAsLong = row.GetTimeT(); //specifically for descending if (rowDataAsLong <= rowAsLong) { insertionIndex = rows.IndexOf(row) + 1; } else { return insertionIndex; } } } //If we reach here then we need to add the data to the end of the list return insertionIndex; } private class StrategyNameCell : DataGridViewTextBoxCell, IProvidesAlignment { public DataGridViewContentAlignment Alignment() { return DataGridViewContentAlignment.MiddleLeft; } protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) { BindingList tableData = (BindingList)DataGridView.DataSource; if (rowIndex >= tableData.Count) /* I see this sometimes in SimpleTIPro, but I never saw it in the TIProDataTest * project. I did what I could to make them as similar as possible, but I * still all this difference. * * This seems to be a temporary condition. Sometimes the table asks for the * value of a row just an instant before we can find the row. */ return ""; return (tableData[rowIndex].GetAsObject(typeof(DataWatcher)) as DataWatcher).Name; } } public void SaveLayout(XmlNode parent) { if (null != PreSaveLayoutCode) PreSaveLayoutCode(this); XmlNode description = LayoutManager.SaveBase(parent, this, FORM_TYPE, ActualSize); if (null != SaveLayoutCode) SaveLayoutCode(this, description); XmlNode strategies = description.NewNode("STRATEGIES"); XmlNode repeat = description.NewNode("SYMBOL_REPEAT"); if (null != RequestedWindowName) description.SetProperty("WINDOW_NAME", RequestedWindowName); description.SetProperty("CONNECTION", GuiEnvironment.ConnectionName(_connectionMaster)); description.SetProperty("COLUMN_CONFIG", this._config.Columns); description.SetProperty("SMALL_BORDERS", smallBordersToolStripMenuItem.Checked.ToString()); description.SetProperty("TEXTHEADERS", _textHeaders); description.SetProperty("PINNED", _pinned); //Save speed settings... XmlNode speeds = description.NewNode("STREAMING"); speeds.SetProperty("SLOWEST", slowestToolStripMenuItem.Checked.ToString()); speeds.SetProperty("SLOWER", slowToolStripMenuItem.Checked.ToString()); speeds.SetProperty("NORMAL", normalToolStripMenuItem.Checked.ToString()); speeds.SetProperty("FAST", fastToolStripMenuItem.Checked.ToString()); speeds.SetProperty("FASTER", fasterToolStripMenuItem.Checked.ToString()); speeds.SetProperty("FASTEST", fastestToolStripMenuItem.Checked.ToString()); List strategyCollection = _config.Strategies; foreach (DataWatcher dW in strategyCollection) { XmlNode strategy = strategies.NewNode("STRATEGY"); if (dW.Name != null) strategy.SetProperty("NAME", dW.Name); strategy.SetProperty("CONFIG", dW.Config); strategy.SetProperty("FORECOLOR", dW.Style.ForeColor.ToArgb()); strategy.SetProperty("BACKCOLOR", dW.Style.BackColor.ToArgb()); strategy.SetProperty("DISABLED", dW.Disabled); strategy.SetProperty("IN_NO_REPEAT_MODE", dW.InNoRepeatMode); strategy.SetProperty("REPEAT_INTERVAL", dW.RepeatInterval); strategy.SetProperty("PREVIOUS_NO_REPEAT_MODE_SETTING", dW.PreviousNoRepeatModeSetting); //oddsmaker settings-each strategy has its oddsmaker config settings saved... dW._userOddsSettings.Save(strategy); } //save the Actions settings... _actions.Save(description); //save the SymbolLinking settings... _symbolLinking.Save(description); //save the "Don't Repeat For" settings repeat.SetProperty("TIME_INTERVAL", _repeatInterval.ToString()); repeat.SetProperty("IS_CHECKED", _inNoRepeatMode.ToString()); if (_config.Strategies.Count == 1) { //want to save the state where the user saves an MS window with just //one strategy (the default (New Strategy). RefreshColumns(); _columnListState.LoadFrom(dataGridView1); resetGrid(); } else { _columnListState.LoadFrom(dataGridView1); } _columnListState.SaveTo(description.NewNode("COLUMNS")); XmlNode columnColors = description.NewNode("COLUMN_COLORS"); foreach (string internalCode in _columnColors.Keys) { XmlNode columnColor = columnColors.NewNode("COLUMN_COLOR"); columnColor.SetProperty("COLUMN", internalCode); GradientInfo gradientInfo = _columnColors[internalCode]; gradientInfo.Save(columnColor); } // Save the symbol plus layout. description.SetProperty("SYMBOL_PLUS_LAYOUT", _symbolPlusLayout.ToString()); } private void ApplyColumnColors() { foreach (string internalCode in _columnColors.Keys) { ColumnInfo columnInfo = GetColumn(internalCode); if (null != columnInfo) columnInfo.GradientInfo = _columnColors[internalCode]; } StyleAllRows(); } private ColumnInfo GetColumn(string internalCode) { ColumnInfo columnInfo = null; if (null != Columns && Columns.Count > 0) { foreach (ColumnInfo column in Columns) { if (column.InternalCode == internalCode) columnInfo = column; } } return columnInfo; } static public void RegisterLayout() { // change parameters to accommodate dock panel changes - RVH20210402 //LayoutManager.Instance().AddRestoreRule(FORM_TYPE, (RestoreLayout)delegate(XmlNode description, bool ignorePosition, bool cascadePosition) LayoutManager.Instance().AddRestoreRule(FORM_TYPE, (RestoreLayout)delegate (XmlNode description, bool ignorePosition, bool cascadePosition, bool dockPanelMode, string mainDockPanelName, string mainDockPanelTitle, string dockPanelID) { IConnectionMaster connectionMaster = GuiEnvironment.FindConnectionMaster(description.Property("CONNECTION")); if (null == connectionMaster) { // We could report an error here, but it's simpler just to do nothing. Any error message we tried to // report would probably be confusing at best to the user. } else { MultiStrategy multiStrategy = new MultiStrategy(connectionMaster); // change parameters to accommodate dock panel changes - RVH20210402 //multiStrategy.Restore(description, ignorePosition, cascadePosition); multiStrategy.Restore(description, ignorePosition, cascadePosition, dockPanelMode, mainDockPanelName, mainDockPanelTitle, dockPanelID); multiStrategy.RestoredLayout = description; if (null != GuiEnvironment.MultiStrategyRestoredCode) GuiEnvironment.MultiStrategyRestoredCode(multiStrategy); } }); } private bool _pinned = false; public bool Pinned { get { return _pinned; } set { _pinned = value; } } // change parameters to accommodate dock panel changes - RVH20210402 //public void Restore(XmlNode description, bool ignorePosition, bool cascadePosition) public void Restore(XmlNode description, bool ignorePosition, bool cascadePosition, bool dockPanelMode = false, string mainDockPanelName = "", string mainDockPanelTitle = "", string dockPanelID = "") { _restoringLayout = true; // change parameters to accommodate dock panel changes - RVH20210402 // LayoutManager.RestoreBase(description, this, ignorePosition, cascadePosition); LayoutManager.RestoreBase(description, this, ignorePosition, cascadePosition, null, false, dockPanelMode, mainDockPanelName, mainDockPanelTitle, dockPanelID); _dockPanelMode = dockPanelMode; List _phrases = GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("PHRASES"); int strategyTally = 0; //restore the "small borders" functionality before restoring form position smallBordersToolStripMenuItem.Checked = description.Property("SMALL_BORDERS", false); // only call this if not in dock panel mode - RVH20210329 if (!_dockPanelMode) setBorders(); _pinned = description.Property("PINNED", false); pinnedToolStripMenuItem.Checked = _pinned; //restore the "Don't Repeat For" settings... XmlNode repeat = description.Node("SYMBOL_REPEAT"); try { _repeatInterval = repeat.Property("TIME_INTERVAL", _repeatInterval); if (repeat.Property("IS_CHECKED", false)) { _inNoRepeatMode = true; dontRepeatToolStripMenuItem.Checked = true; } else { _inNoRepeatMode = false; dontRepeatToolStripMenuItem.Checked = false; } } catch { _inNoRepeatMode = false; dontRepeatToolStripMenuItem.Checked = false; } RequestedWindowName = description.Property("WINDOW_NAME", null); _config.RemoveAllStrategies(); _config.Columns = description.Property("COLUMN_CONFIG"); XmlNode strategyCollection = description.Node("STRATEGIES"); foreach (XmlNode strategy in strategyCollection.Enum()) { DataWatcher dW = new DataWatcher(this); dW.Name = strategy.Property("NAME"); dW.Config = strategy.Property("CONFIG"); dW.Style.ForeColor = Color.FromArgb(strategy.Property("FORECOLOR", -16777216)); dW.Style.BackColor = Color.FromArgb(strategy.Property("BACKCOLOR", -1)); string test = strategy.Property("IN_NO_REPEAT_MODE").ToLower(); //an old layout might not have this property. We'll set the individual dont_repeat_for the same as the global if this string is empty. if (test == "") { dW.InNoRepeatMode = false; dW.RepeatInterval = _repeatInterval; dW.PreviousNoRepeatModeSetting = false; } else { dW.InNoRepeatMode = strategy.Property("IN_NO_REPEAT_MODE", false); dW.RepeatInterval = strategy.Property("REPEAT_INTERVAL", 5); dW.PreviousNoRepeatModeSetting = strategy.Property("PREVIOUS_NO_REPEAT_MODE_SETTING", false); } dW.Disabled = strategy.Property("DISABLED", false); dW._userOddsSettings.Load(strategy); //loading up oddsmaker settings dW.Disabled = strategy.Property("DISABLED", false); dW._userOddsSettings.Load(strategy); //loading up oddsmaker settings if (dW.ConfigValid()) { //we're only loading strategies with non-null config //strings. Those with null config strings are skipped. _config.Strategies.Add(dW); strategyTally++; } } // _config.add(); _config.addNewOdds(); strategyTally++; //case where user saves multi-strat window with only the new strategy //entry...and nothing else.. if (strategyTally == 1) { historyToolStripMenuItem.Tag = "false"; //use tag to disable/enable ("EnforceLimitedMode") } else { historyToolStripMenuItem.Tag = null; //use tag to disable/enable ("EnforceLimitedMode") } // restore the speed settings XmlNode speeds = description.Node("STREAMING"); if (speeds.Property("SLOWEST", false)) { slowest(); } else if (speeds.Property("SLOWER", false)) { slow(); } else if (speeds.Property("NORMAL", false)) { normal(); } else if (speeds.Property("FAST", false)) { fast(); } else if (speeds.Property("FASTER", false)) { faster(); } else if (speeds.Property("FASTEST", false)) { fastest(); } else //Should not get here but set speed to normal as default { normal(); } //Now get the Actions settings... _actions.Load(description); //Now restore State of actions menuitem check box actionsToollStripMenuItem.Checked = _actions.InUse(); //Now get the SymbolLinking settings.. _symbolLinking.Load(description); _columnListState.LoadFrom(description.Node("COLUMNS")); //Add special and old show/hide columns to the column config string, AddSpecialColumns(); TextHeaders = description.Property("TEXTHEADERS", false); _previousNoRepeatModeSetting = dontRepeatToolStripMenuItem.Checked; //initialization //restore custom column colors XmlNode columnColors = description.Node("COLUMN_COLORS"); if (null != columnColors) { foreach (XmlNode columnColor in columnColors.Enum()) { GradientInfo gradientInfo = new GradientInfo(columnColor); string internalCode = columnColor.Property("COLUMN", ""); if (_columnColors.ContainsKey(internalCode)) _columnColors[internalCode] = gradientInfo; else _columnColors.Add(internalCode, gradientInfo); } ApplyColumnColors(); } // Restore the symbol plus layout. Enum.TryParse(description.Property("SYMBOL_PLUS_LAYOUT", "Off"), out _symbolPlusLayout); } public void showWelcomeLabel() { this.lblWelcome.Visible = true; } public void hideWelcomeLabel() { this.lblWelcome.Visible = false; } private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex != -1)// ignore if the header is clicked { string config = (_mostRecentRowData.GetAsObject(typeof(DataWatcher)) as DataWatcher).Config; // there has been some rare crashes that we haven't been able to reproduce but the errors // lean towards trying to access an index that is out of bounds. if (_boundList.Count > e.RowIndex) { if (GuiEnvironment.IntegrationSupportSingleClick) SendToExternalLinking(_mostRecentRowData); } } } private void RecordExternalLinkUseCase(RowData rowData) { GuiEnvironment.RecordExternalLinkingUseCase(rowData, "MS", _sendManager); } public void SendToExternalLinking(RowData rowData, bool promptUserIfEmpty = false) { if (null == rowData) return; RecordExternalLinkUseCase(rowData); string symbol = rowData.GetSymbol(); string exchange = rowData.GetExchange(); string listName = _symbolLinking.SavedSymbolListName; // Use BeginInvoke to avoid "reentrant call to the SetCurrentCellAddress" // exception when a user uses both keyboard and mouse symbol linking // simultaneously with external linking alternate method disabled. // http://stackoverflow.com/questions/26522927/how-to-evade-reentrant-call-to-setcurrentcelladdresscore BeginInvoke(new MethodInvoker(() => { GuiEnvironment.sendSymbolToExternalConnector(symbol, exchange, listName, this, rowData, promptUserIfEmpty: promptUserIfEmpty, linkChannel: _linkChannel, dockWindowID: GuiEnvironment.GetDockWindowID(this)); })); } private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex != -1) // ignore if the header is clicked { // there has been some rare crashes that we haven't been able to reproduce but the errors // lean towards trying to access an index that is out of bounds. if (_boundList.Count > e.RowIndex) { string config = (_mostRecentRowData.GetAsObject(typeof(DataWatcher)) as DataWatcher).Config; if (GuiEnvironment.IntegrationSupportSingleClick == false) SendToExternalLinking(_mostRecentRowData); } } } private void clearToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Clear", _sendManager); // Also clear don't repeat list when clearing data _strategyDelayTable.Clear(); _boundList.Clear(); } private void columnsToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Columns", _sendManager); _config.setColumns(_columnListState); //Update columns RefreshColumns(); } private void saveContentsToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.SaveContents", _sendManager); GridContentSaver contentSaver = new GridContentSaver(); string fileNameSavedContents = ""; if (_fileNameSavedContents == null) { // Is this right? Should we add BaseWindowName? // This seems to be a bit wordy and redundant. // Maybe is should say "Unnamed" instead of "Multi Strategy" a second time. // FILE_PREFIX_CONTENTS already includes "Multi Strategy". // TODO fileNameSavedContents = _phrases.Node("FILE_PREFIX_CONTENTS").PropertyForCulture("TEXT", "***") + BaseWindowName; } else { fileNameSavedContents = _fileNameSavedContents; } _fileNameSavedContents = contentSaver.saveGridContents(dataGridView1, fileNameSavedContents); } private void windowNameToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.WindowName", _sendManager); using (MultiStrategyWindowName form = new MultiStrategyWindowName(RequestedWindowName)) { form.StartPosition = FormStartPosition.CenterParent; form.Text = _phrases.Node("WINDOW_NAME").PropertyForCulture("TEXT", "***"); form.ShowDialog(); if (form.DialogResult == System.Windows.Forms.DialogResult.OK) RequestedWindowName = form.NewName; form.Dispose(); } } private void duplicateToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Duplicate", _sendManager); LayoutManager.Instance().Duplicate(this); } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.SaveAs", _sendManager); SaveFileDialog dialog = new SaveFileDialog(); if (null != _layoutManager.Directory) dialog.InitialDirectory = _layoutManager.Directory; dialog.Filter = _phrases.Node("WINDOW_FILTER").PropertyForCulture("TEXT", "***"); dialog.DefaultExt = "WTI"; string fileName = ""; if (_fileNameSaved == null) { // See notes about BaseWindowName in saveContentsToolStripMenuItem_Click. TODO fileName = _phrases.Node("FILE_PREFIX").PropertyForCulture("TEXT", "***") + BaseWindowName; } else { fileName = _fileNameSaved; } dialog.FileName = FileNameMethod.QuoteFileName(fileName); //shows directories... if (dialog.ShowDialog() == DialogResult.OK) { _layoutManager.SaveOne(this, dialog.FileName); _fileNameSaved = Path.GetFileName(dialog.FileName); } dialog.Dispose(); } private void saveDefaultToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.SaveDefault", _sendManager); string programDirFileName = _layoutManager.Directory + "\\" + _defaultFileName; _layoutManager.SaveOne(this, programDirFileName); } private void deleteAllToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.DeleteAll", _sendManager); //Add messagebox to confirm deletion string question = _phrases.Node("DELETE_ALL_Q").PropertyForCulture("TEXT", "***"); string caption = _phrases.Node("DELETE_ALL_CAPTION").PropertyForCulture("TEXT", "***"); var result = MessageBox.Show(question, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { //When we've deleted all of our strategies, it is assumed that //one would wish to start the hide/show progress of special columns from scratch. Thus, //when all strategies have been deleted (we'll *always* have a (New Strategy) entry //by the way), It will be assumed when the lone (NewStrategy) entry is configured //it will have all of the special columns visible again. The same will hold true // in the case where user individually deletes strategies until one remains ("New //Strategy"). "New Strategy" cannot be deleted... _config.RemoveAllStrategies(); _boundList.Clear(); resetGrid(); _config.addNewOdds(); historyToolStripMenuItem.Tag = "false"; } } public void resetGrid() { //This method "zeroes out" the grid //by disconnecting the Datasource, //setting ColumnCount to zero followed by //reconnecting the DataSource. The effect is //that whenever the user deletes all of his strategies // from MS window ((New Strategy) will always remain) //this method will be called and the DataGrid view //will not be showing any specialColumn/Filter headers dataGridView1.DataSource = null; dataGridView1.ColumnCount = 0; dataGridView1.DataSource = _boundList; } private void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e) { int selectedRow = e.RowIndex; //if (selectedRow != -1) if (selectedRow != -1 && !_symbolSpecificContextMenuOpen) { try { _currentRowData = _boundList[selectedRow]; _mostRecentRowData = _currentRowData; _mostRecentRowIndex = selectedRow; } catch { } } } private void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e) { _currentRowData = null; } private void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e) { _symbolSpecificContextMenuOpen = false; } private void strategiesToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { //Because a there are a lot of dynamically created menu items, when the context menu closes //I noted an increase in USER objects and some increase in Memory(Private Working Set). These //Menu Items also have dynamic created event handlers so even when the strategiesToolStripMenuItem // is cleared of its members, there can still be objects which can't be disposed properly on their // own because those event handlers are still connected. These bits of resources can add up when one // is using a multistrat with many strategies and one is constantly opening up the context menu.So the while-loop below disposes(properly) //of these objects and recreates them from fresh every time the window. while (strategiesToolStripMenuItem.DropDownItems.Count > 0) { ToolStripMenuItem tItem = (ToolStripMenuItem)strategiesToolStripMenuItem.DropDown.Items[0]; while (tItem.DropDownItems.Count > 0) { tItem.DropDownItems[0].Dispose(); } strategiesToolStripMenuItem.DropDownItems[0].Dispose(); } //Here we are dynamically creating menu items, depending on how many //strategy objects are present in the List... List dataList = _config.Strategies; if (_config.Strategies.Count == 0) { strategiesToolStripMenuItem.DropDown.Items.Clear(); ToolStripMenuItem item = new ToolStripMenuItem(); item.Text = _phrases.Node("NONE").PropertyForCulture("TEXT", "***"); item.Enabled = false; strategiesToolStripMenuItem.DropDown.Items.Add(item); } else { strategiesToolStripMenuItem.DropDown.Items.Clear(); int count = 0; foreach (DataWatcher strategy in dataList) { ToolStripMenuItem item = new ToolStripMenuItem(); if (strategy.ConfigValid()) { item.CheckOnClick = true; item.Checked = !strategy.Disabled; item.CheckedChanged += new EventHandler(item_CheckedChanged); // If the user changed the window name of a disabled strategy we need to call getThatWindowName // to update the dropdown list if ((strategy.Name == null) || (strategy.Disabled)) { //the only difference between a live strategy //and and one that is turned off, is that the //one which is turned off has null for the Name. item.Text = getThatWindowName(strategy); } else { item.Text = strategy.ToString(); } } else { item.Text = strategy.ToString(); } item.Tag = count; //keeping track of index strategiesToolStripMenuItem.DropDown.Items.Add(item); count++; populateStrategyOperations(item, strategy); } } GuiEnvironment.HideMenuItems(strategiesToolStripMenuItem.DropDownItems); } private void SetConfigureAllStatus() { if (_config.Strategies.Count < 3) configureAllToolStripMenuItem.Tag = "false"; else configureAllToolStripMenuItem.Tag = null; } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { SetConfigureAllStatus(); _selectedRowsList = new List(); if (dataGridView1.SelectedCells.Count > 1) { IEnumerable selectedRows = dataGridView1.SelectedCells.Cast() .Select(cell => cell.OwningRow) .Distinct(); foreach (DataGridViewRow row in selectedRows.ToList()) { _selectedRowsList.Add(_boundList[row.Index]); } } if (null != _currentRowData) { _individualStrategyConfig = (_currentRowData.GetAsObject(typeof(DataWatcher)) as DataWatcher).Config; sendSymbolToToolStripMenuItem.Visible = true; ShowRowSpecificMenuItems(_currentRowData); } else { ToggleSymbolSpecificMenuItems(false); sendSymbolToToolStripMenuItem.Visible = false; } if (null != GuiEnvironment.RobotStrategyMenuCode) { string symbol = ""; if (null != _currentRowData && _selectedRowsList.Count < 2) symbol = _currentRowData.GetSymbol(); GuiEnvironment.RobotStrategyMenuCode(contextMenuStrip1, symbol, "MS", _currentRowData); } GuiEnvironment.HideMenuItems(contextMenuStrip1.Items); GuiEnvironment.EnforceLimitedMode(contextMenuStrip1); //The option is enabled or not depending on whether there are defined strategies missingSymbolCheckToolStripMenuItem.Enabled = MultiStrategyConfiguration != null && MultiStrategyConfiguration.Strategies != null && MultiStrategyConfiguration.Strategies.Count > 1; Column.UpdateGraphicsMenuItem(graphicalIndicatorToolStripMenuItem, dataGridView1, _lastContextMenuNeededColumnIndex); // add symbol linking channels here symbolLinkingToolStripMenuItem.DropDown.Items.Clear(); //Detect if the current window is in floating mode var floatingMode = string.IsNullOrEmpty(GuiEnvironment.GetDockWindowID(this)); foreach (KeyValuePair channel in SymbolLinkChannels.Channels) { if (channel.Key == SymbolLinkChannels.DockWindowChannel && floatingMode) continue; ToolStripMenuItem menuItem = new ToolStripMenuItem(channel.Key, null, delegate { SetLinkChannel(channel.Key); }); menuItem.BackColor = channel.Value; Color foreColor = GradientInfo.AltColor(channel.Value); menuItem.ForeColor = foreColor; menuItem.Checked = _linkChannel == channel.Key; symbolLinkingToolStripMenuItem.DropDown.Items.Add(menuItem); } } /// /// Set the symbol link channel from symbol linking /// /// The link channel void ISymbolLinkingChannel.SetLinkChannel(string linkChannel) { SetLinkChannel(linkChannel); } /// /// Set the symbol link channel /// /// The link channel private void SetLinkChannel(string linkChannel) { _linkChannel = linkChannel; // change window icon SymbolLinkingChannelsHelper.SetFormIcon(this, "M", linkChannel); } /// /// Get the symbol link channel /// /// string ISymbolLinkingChannel.GetLinkChannel() { return _linkChannel; } private void sendSymbolToToolStripMenuItem_MouseEnter(object sender, EventArgs e) { if (sendSymbolToToolStripMenuItem.DropDownItems.Count == 1) /*We have the "dummy" item there just to make it look like the "send to" item has children*/ { sendSymbolToToolStripMenuItem.DropDownItems.Clear(); _sendToContextMenu = new makeSendToContextMenu(this, this, sendSymbolToToolStripMenuItem, _mostRecentRowData, _sendManager, _individualStrategyConfig, _connectionMaster); if (_selectedRowsList.Count > 1) _sendToContextMenu.setRowDataList(_selectedRowsList); } else { if (_selectedRowsList.Count > 1) _sendToContextMenu.setRowDataList(_selectedRowsList); else { string exchange = _mostRecentRowData.GetExchange(); string symbol = _mostRecentRowData.GetSymbol(); _sendToContextMenu.setRowData(_mostRecentRowData, _individualStrategyConfig, symbol, exchange, _connectionMaster); } } } private void getAlertHelpStripMenuItem_Click(object sender, EventArgs e) { String internalCode = _mostRecentRowData.GetAlertType(); if (internalCode != "") { GuiEnvironment.gotoHelpForAlert(internalCode); } } private void ShowRowSpecificMenuItems(RowData alert) { try { if (_mostRecentRowIndex != -1 && _mostRecentRowIndex < dataGridView1.Rows.Count) { _symbolSpecificContextMenuOpen = true; foreach (DataGridViewRow selectedRow in dataGridView1.SelectedRows) selectedRow.Selected = false; dataGridView1.Rows[_mostRecentRowIndex].Selected = true; string sendToText = _phrases.Node("SEND_SYMBOL_TO").PropertyForCulture("TEXT", "***"); if (sendToText == "---") sendSymbolToToolStripMenuItem.Visible = false; else sendSymbolToToolStripMenuItem.Visible = true; string symbol = alert.GetSymbol(); if (_selectedRowsList.Count > 1) symbol = ""; sendToText = sendToText.Replace("{symbol}", symbol); sendSymbolToToolStripMenuItem.Text = sendToText; graphicalIndicatorToolStripMenuItem.Visible = true; ToggleSymbolSpecificMenuItems(true, symbol); } } catch { } } private string getThatWindowName(DataWatcher strategy) { string configString = strategy.Config; string[] firstPass = configString.Split(new string[] { "&WN=" }, StringSplitOptions.RemoveEmptyEntries); //we'll want segment [1] if (firstPass.Length == 1) { //This scenario happens when the user enters //nothing for the strategy name (e.g. "" or " "), thus no //window name identifier would appear in the //the config string if that strategy is turned off.. return _phrases.Node("NO_NAME").PropertyForCulture("TEXT", "***"); } string[] lastPass = firstPass[1].Split('&'); return HttpUtility.UrlDecode(lastPass[0]); } private void timeFrameToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.History.TimeFrame", _sendManager); _timeframe.ShowDialog(this); _currentlyUsingHistory = true; if (_connectionMaster.LoginManager.IsDemo && _timeframe.ClickOK == true) { _historyErrorOnDemo = true; allToolStripMenuItem.Checked = false; realTimeToolStripMenuItem.Checked = true; timeFrameToolStripMenuItem.Checked = false; onAccountStatusChanged(); return; } if (_timeframe.ClickOK) { timeFrameToolStripMenuItem.Checked = true; realTimeToolStripMenuItem.Checked = false; allToolStripMenuItem.Checked = false; } } private void realTimeToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.History.RealTime", _sendManager); if (!realTimeToolStripMenuItem.Checked) { realTimeToolStripMenuItem.Checked = true; timeFrameToolStripMenuItem.Checked = false; allToolStripMenuItem.Checked = false; _historyErrorOnDemo = false; _currentlyUsingHistory = false; clearToolStripMenuItem.Tag = null; //This tag ultimately sets this menu item to "true" for enabled (EnforceLimitedMode) columnsToolStripMenuItem.Tag = null; //This tag ultimately sets this menu item to "true" for enabled (EnforceLimitedMode) actionsToollStripMenuItem.Tag = null; _strategyDelayTable.Clear(); SetConfigStreaming(); _historyMode = HistoryModeEnum.Live; RefreshWindowName(); //Enable menu items that are disabled during history columnsToolStripMenuItem.Enabled = true; clearToolStripMenuItem.Enabled = true; if (dontRepeatToolStripMenuItem.Enabled == false) //always gets set to false when in history { dontRepeatToolStripMenuItem.Tag = null; //This tag ultimately sets this menu item to "true" for enabled (EnforceLimitedMode) _inNoRepeatMode = _previousNoRepeatModeSetting; dontRepeatToolStripMenuItem.Checked = _previousNoRepeatModeSetting; foreach (DataWatcher d in _config.Strategies) { d.InNoRepeatMode = d.PreviousNoRepeatModeSetting; d.NoRepeatMenuItemDisabled = false; } dontRepeatToolStripMenuItem.Enabled = true; } } //else //{ // _currentlyUsingHistory = true; // if (_connectionMaster.LoginManager.IsDemo) // { // _historyErrorOnDemo = true; // onAccountStatusChanged(); // return; // } // Finished = 0; // getNumberSelectedStrategies(); // SetConfigHistory(null, null); //} } public void onAccountStatusChanged() { if (_connectionMaster.LoginManager.AccountStatus != AccountStatus.Good) //user gets "kicked off" { //lblMessage.Text = "No Connection"; // linkLabel.Visible = true; return; } if ((_connectionMaster.LoginManager.IsDemo && _historyErrorOnDemo == true) || ((_connectionMaster.LoginManager.IsDemo && _currentlyUsingHistory == true))) { showMarketingPanel(); } else { hideMarketingPanel(); } } private void showMarketingPanel() { pnlMarketing.BringToFront(); pnlMarketing.Visible = true; linkLabel.Visible = true; } private void hideMarketingPanel() { pnlMarketing.Visible = false; pnlMarketing.SendToBack(); } private void lblGoBack_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { hideMarketingPanel(); realTimeToolStripMenuItem.Checked = true; realTimeToolStripMenuItem_Click(null, new EventArgs()); timeFrameToolStripMenuItem.Checked = false; allToolStripMenuItem.Checked = false; } private void linkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { Process.Start(e.Link.LinkData as string); } public void getNumberSelectedStrategies() { _selectedStrategies = 0; _historyTempList.Clear(); _historySortedList.Clear(); foreach (DataWatcher d in _config.Strategies) { if (d.Config != null && d.Disabled == false) { d.StopHistory(); _selectedStrategies++; } } } private int LiveStrategyCount() { int count = 0; foreach (DataWatcher dataWatcher in _config.Strategies) if (dataWatcher.ConfigValid() && !dataWatcher.Disabled) count++; return count; } public void SetConfigHistory(DateTime? StartTime, DateTime? EndTime) { // Clear any old results that were in progress. _historyTempList.Clear(); _inNoRepeatMode = false; columnsToolStripMenuItem.Enabled = false; dontRepeatToolStripMenuItem.Enabled = false; dontRepeatToolStripMenuItem.Checked = false; dataGridView1.DataSource = _boundList; realTimeToolStripMenuItem.Checked = false; clearToolStripMenuItem.Enabled = false; dontRepeatToolStripMenuItem.Tag = "false"; actionsToollStripMenuItem.Tag = "false"; clearToolStripMenuItem.Tag = "false"; columnsToolStripMenuItem.Tag = "false"; HistoryMode = HistoryModeEnum.HistoryLoading; //If we have "x" number of strategies (less the empty strategy), then //we'll divide 1000 by that number. The maximum number of strategies //displayed in a strategy window is 1000. int divisor = LiveStrategyCount(); //We don't want to count the empty "New Strategy" _boundList.Clear(); foreach (DataWatcher d in _config.Strategies) { if (d.ConfigValid() && d.Disabled == false) //We have a valid Strategy, (not an empty "New Strategy") { d.InDemoMode = _connectionMaster.LoginManager.IsDemo; d.NoRepeatMenuItemDisabled = true; d.StartHistory(StartTime, EndTime, d, divisor); } } } public void SetConfigStreaming() { dataGridView1.DataSource = _boundList; HistoryMode = HistoryModeEnum.Live; foreach (DataWatcher d in _config.Strategies) d.SwitchToStreaming(); // Stop all of the history besore clearing the list. // Otherwise you might get the last of the historical alerts added to the window. // History sometimes stores things at first, and doesn't copy them to the window until it's done. _boundList.Clear(); } private void populateStrategyOperations(ToolStripMenuItem strategyMenu, DataWatcher strategy) { /*To reduce the amount of code, I could have used the below one-liner: "(strategyLevel.Items[i] as ToolStripMenuItem).DropDownItems.Add(_phrases.Node("CONFIGURE").PropertyForCulture("TEXT", "***"), null, strategyConfig_Click);" However I wanted to manually keep tabs of the index of each item , as ultimately the index of strategy items in these collections correspond * to the index of the object within single strategy list ( MultiStrategyConfiguration) */ int index = (int)strategyMenu.Tag; ToolStripMenuItem configControl = new ToolStripMenuItem(); configControl.Click += new EventHandler(strategyConfig_Click); configControl.Text = _phrases.Node("CONFIGURE").PropertyForCulture("TEXT", "***"); configControl.Tag = index; //keeps track of index strategyMenu.DropDownItems.Add(configControl); ToolStripMenuItem collaborateControl = new ToolStripMenuItem(); collaborateControl.Click += new EventHandler(collaborate_Click); collaborateControl.Text = _phrases.Node("COLLABORATE").PropertyForCulture("TEXT", "***"); collaborateControl.Tag = index; //keeps track of index strategyMenu.DropDownItems.Add(collaborateControl); ToolStripMenuItem duplicateControl = new ToolStripMenuItem(); duplicateControl.Click += new EventHandler(duplicate_Click); duplicateControl.Text = _phrases.Node("DUPLICATE").PropertyForCulture("TEXT", "***"); duplicateControl.Tag = index; //keeps track of index duplicateControl.Enabled = strategy.ConfigValid(); strategyMenu.DropDownItems.Add(duplicateControl); ToolStripMenuItem dontRepeatControl = new ToolStripMenuItem(); dontRepeatControl.Click += new EventHandler(dontRepeat_Click); dontRepeatControl.Checked = strategy.InNoRepeatMode; strategy.PreviousNoRepeatModeSetting = strategy.InNoRepeatMode; dontRepeatControl.Text = _phrases.Node("NO_REPEAT").PropertyForCulture("TEXT", "***"); dontRepeatControl.Tag = index; //keeps track of index dontRepeatControl.Enabled = (strategy.ConfigValid() && !strategy.NoRepeatMenuItemDisabled) && (HistoryMode == HistoryModeEnum.Live); strategyMenu.DropDownItems.Add(dontRepeatControl); ToolStripMenuItem colorControl = new ToolStripMenuItem(); colorControl.Click += new EventHandler(strategyColors_Click); colorControl.Text = _phrases.Node("COLORS").PropertyForCulture("TEXT", "***"); colorControl.Tag = index; //keeps track of index colorControl.ForeColor = strategy.Style.ForeColor; colorControl.BackColor = strategy.Style.BackColor; strategyMenu.DropDownItems.Add(colorControl); ToolStripMenuItem deleteControl = new ToolStripMenuItem(); deleteControl.Click += new EventHandler(delete_Click); deleteControl.Text = _phrases.Node("DELETE").PropertyForCulture("TEXT", "***"); deleteControl.Tag = index; //keeps track of index deleteControl.Enabled = strategy.ConfigValid(); strategyMenu.DropDownItems.Add(deleteControl); //Add the horizontal separator... strategyMenu.DropDownItems.Add(new ToolStripSeparator()); //Add Run OddsMaker menu item ToolStripMenuItem oddsMakerControl = new ToolStripMenuItem(); oddsMakerControl.Click += new EventHandler(oddsMaker_Click); oddsMakerControl.Text = _phrases.Node("RUN_ODDSMAKER").PropertyForCulture("TEXT", "***"); oddsMakerControl.Tag = index; //keeps track of index oddsMakerControl.Enabled = strategy.ConfigValid(); strategyMenu.DropDownItems.Add(oddsMakerControl); //Add Open Alert window menu item ToolStripMenuItem openAlertControl = new ToolStripMenuItem(); openAlertControl.Click += new EventHandler(openAlert_Click); openAlertControl.Text = _phrases.Node("OPEN_ALERT").PropertyForCulture("TEXT", "***"); openAlertControl.Tag = index; //keeps track of index openAlertControl.Enabled = strategy.ConfigValid(); strategyMenu.DropDownItems.Add(openAlertControl); } void item_CheckedChanged(object sender, EventArgs e) { DataWatcher chosenStrategy = getSpecificStrategy(sender); bool enabled = (sender as ToolStripMenuItem).Checked; chosenStrategy.Disabled = !enabled; } private void strategyConfig_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Config", _sendManager); DataWatcher chosenStrategy = getSpecificStrategy(sender); ((ToolStripMenuItem)sender).Text = chosenStrategy.Name; // TODO This sure looks like it is unnecessary PDS. _config.configureStrategy(chosenStrategy); if (_config.Strategies.Count > 1) { historyToolStripMenuItem.Tag = null;//use tag to disable/enable ("EnforceLimitedMode") } } private void collaborate_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Collaborate", _sendManager); var strategy = getSpecificStrategy(sender); var symbolLists = GuiEnvironment.GetSymbolListsCacheManager(_connectionMaster)?.GetSymbolLists(); var showWarning = HandlesStrategyUtils.StrategyConfigContainsPrivateList(strategy.Config, symbolLists); _config.collaborate(strategy, showWarning); } private void collaborateAllToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.CollaborateAll", _sendManager); var showWarm = StrategyContainsPrivateList(); if (_config.collaborateAll(showWarm)) { onClearData(); } lblWelcome.Visible = false; } public void SetConfiguration(string config) { _config.SetConfiguration(config); _boundList.Clear(); } private void strategyColors_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Colors", _sendManager); _config.setStrategyColors(getSpecificStrategy(sender)); } private void actionsToollStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Actions", _sendManager); _actions.ShowDialog(); if (_actions.InUse()) { actionsToollStripMenuItem.Checked = true; } else { actionsToollStripMenuItem.Checked = false; } } private void duplicate_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Duplicate", _sendManager); DataWatcher d = getSpecificStrategy(sender); _config.copy(d); } private void delete_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Delete", _sendManager); DataWatcher d = getSpecificStrategy(sender); int index = (int)(((ToolStripMenuItem)sender).Tag); _config.delete(d, index); if (_config.isStrategyListEmpty()) { _boundList.Clear(); _config.add(); historyToolStripMenuItem.Tag = "false"; //use tag to disable/enable ("EnforceLimitedMode") } if (_config.Strategies.Count == 1) { historyToolStripMenuItem.Tag = "false"; //use tag to disable/enable ("EnforceLimitedMode") } } private void dontRepeat_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.DontRepeat", _sendManager); DataWatcher d = getSpecificStrategy(sender); //get the ToolstripItem from sender... so we know to mark/unmark it with checkmark ToolStripMenuItem menuItem = (ToolStripMenuItem)sender; using (NoRepeat noRepeat = new NoRepeat(d.InNoRepeatMode, d.RepeatInterval, 2)) { if (noRepeat.ShowDialog() == DialogResult.OK) { //When a strategy's Don't Repeat For is changed, then the WINDOW "Don't Repeat For" is *turned off* _inNoRepeatMode = false; //turn off WINDOW Don't Repeat... _previousNoRepeatModeSetting = false; dontRepeatToolStripMenuItem.Checked = false; if (noRepeat.SymbolDelayOptionChecked) { menuItem.Checked = true; d.InNoRepeatMode = true; d.RepeatInterval = noRepeat.TimeDelay; d.PreviousNoRepeatModeSetting = true; d.StrategyDelayTable.Clear(); d.SwitchToStreaming(); } else { menuItem.Checked = false; d.InNoRepeatMode = false; d.PreviousNoRepeatModeSetting = false; d.StrategyDelayTable.Clear(); d.SwitchToStreaming(); } } } } /// /// This click event brings up the open an alert window menu for the particular strategy selected. /// If the window exists it will bring it to the front else it will create a new alert window. /// Logic reused from OddsMaker Results window'sGoToAlertWindow button. /// /// /// private void openAlert_Click(object sender, EventArgs e) { DataWatcher chosenStrategy = getSpecificStrategy(sender); GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.OpenAlert", _sendManager); //Create list of alert windows matching the chosen strategy List alertForms = Application.OpenForms.OfType().Where(x => !x.IsDisposed && x.GetConfigString() == chosenStrategy.Config).ToList(); if (alertForms.Count > 0) { AlertForm alertForm = alertForms.First(); alertForm.SetOddsMakerSettings(chosenStrategy._userOddsSettings); alertForm.WindowState = FormWindowState.Normal; alertForm.BringToFront(); } else { chosenStrategy._alert = new AlertForm(_connectionMaster, chosenStrategy.Config); // Need to apply custom columns colrs to the new alert window. XmlDocument doc = new XmlDocument(); XmlNode docNode = doc.CreateElement("NEWDOC"); XmlNode columnColors = XmlHelper.NewNode(docNode, "COLUMN_COLORS"); foreach (string internalCode in _columnColors.Keys) { XmlNode columnColor = columnColors.NewNode("COLUMN_COLOR"); columnColor.SetProperty("COLUMN", internalCode); GradientInfo gradientInfo = _columnColors[internalCode]; gradientInfo.Save(columnColor); } chosenStrategy._alert.SetColumnColors(docNode); chosenStrategy._alert.SetOddsMakerSettings(chosenStrategy._userOddsSettings); GuiEnvironment.SetWindowOpeningPosition(chosenStrategy._alert, this); // Add docking context menu entries to Alert window. [PRO-56] ContextMenuStrip contextMenuStrip = LayoutManager.GetContextMenu(chosenStrategy._alert); if (contextMenuStrip != null) { contextMenuStrip.Opening += LayoutManager.Instance().contextMenuStrip_Opening; } chosenStrategy._alert.Show(); } } private void oddsMaker_Click(object sender, EventArgs e) { /*This method brings up the oddsmaker menu for the particular strategy selected. */ DataWatcher chosenStrategy = getSpecificStrategy(sender); GuiEnvironment.RecordUseCase("MultiStrat.RightClick.Strategies.Oddsmaker", _sendManager); chosenStrategy._alert = new AlertForm(_connectionMaster, chosenStrategy.Config); chosenStrategy._odds = new OddsMakerConfigWindow(chosenStrategy.Config, _connectionMaster, chosenStrategy.Name, chosenStrategy, chosenStrategy._userOddsSettings); if (GuiEnvironment.openRelativeToMainWindow) { Screen CurrentScreen = Screen.FromControl(this); Rectangle workingRectangle = CurrentScreen.WorkingArea; chosenStrategy._odds.Location = new Point(GuiEnvironment.currentMainWindowLeft + 50, GuiEnvironment.currentMainWindowTop + 50); if (!workingRectangle.Contains(chosenStrategy._odds.DesktopBounds)) chosenStrategy._odds.Location = new Point(CurrentScreen.Bounds.X + 50, CurrentScreen.Bounds.Y + 50); // set position relative to current monitor } chosenStrategy._odds.ShowDialog(); //The OddsMakerConfigWindow is now disposed upon closing... } private DataWatcher getSpecificStrategy(object s) { /*This little method will return the desired strategy from the strategy list, given the name..*/ ToolStripMenuItem test = (ToolStripMenuItem)s; int index = (int)test.Tag; return _config.Strategies[index]; } private void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e) { /*For some reason, minimizing the description column(not seen with the others) can cause the height of the rows to increase dramatically. When the column width is totally minimized,we wish the row heights to be of single row-height to save on window real-estate*/ // only do this when the grid is not in autosizecolumnsmode = fill - RVH20210929 if (dataGridView1.AutoSizeColumnsMode != DataGridViewAutoSizeColumnsMode.Fill) { string test = getSectColumn(e.Column); if (e.Column.Width <= MIN_COLUMN_WIDTH && (e.Column.HeaderText != "" || e.Column.Name == "Strategies")) { dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; foreach (DataGridViewRow row in dataGridView1.Rows) { row.Height = DEFAULT_ROW_HEIGHT; } } else if (e.Column.HeaderText != test) { if (isVerboseColumnWidthMinimum()) { dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; return; } } else { dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells; } } } private string getSectColumn(DataGridViewColumn c) { string flag = ""; String test = c.HeaderText; foreach (string col in TopListForm.sectorColumns) { if (test == col) { flag = col; break; } } return flag; } private bool isVerboseColumnWidthMinimum() { /*This little method retrieves the width status of the Description column...whatever position it may be in the grid*/ foreach (DataGridViewColumn column in dataGridView1.Columns) { if (column.HeaderText == VERBOSE_COLUMN_HEADER && column.Width <= MIN_COLUMN_WIDTH) { return true; } } return false; } WindowIconCache ISaveLayout.WindowIconCache { get { return WindowIconCache; } } private void saveToCloudToolStripMenuItem_Click(object sender, EventArgs e) { SaveToCloud.DoIt(_sendManager, this); } private void MultiStrategy_FormClosed(object sender, FormClosedEventArgs e) { graphicalIndicatorToolStripMenuItem.Click -= Column.GraphicsMenuItemCallback; foreach (DataWatcher d in _config.Strategies) { d.StopHistory(); d.stopStreaming(); } //We now remove the strateegies during this event (instead of the FormClosing event) //so that the layout file saved during an exception contains the multi-strategy config data. _config.RemoveAllStrategies(); dataGridView1.Columns.Clear(); _boundList.Clear(); contextMenuStrip1.Opening -= LayoutManager.Instance().contextMenuStrip_Opening; } private void configureAllToolStripMenuItem_Click(object sender, EventArgs e) { DoMultiConfig(); } private void DoMultiConfig() { MultiConfigStrategyChooser strategyChooserForm = new MultiConfigStrategyChooser(); strategyChooserForm.Strategies = MultiStrategyConfiguration.Strategies; strategyChooserForm.StartPosition = FormStartPosition.CenterParent; DialogResult strategyChooserFormResult = strategyChooserForm.ShowDialog(); if (strategyChooserFormResult == DialogResult.OK) { List strategies = strategyChooserForm.SelectedStrategies; bool isCurrentFactorySmallConfig = false; if (ConfigWindowWrapper.DefaultFactory == SmallConfigWindowWrapper.Factory) { isCurrentFactorySmallConfig = true; ConfigWindowWrapper.DefaultFactory = TraditionalConfigWindowWrapper.Factory; } ConfigWindowWrapper configWindowWrapper = ConfigWindowWrapper.DefaultFactory(TradeIdeas.TIProData.Configuration.ConfigurationType.MultiStrategy, _connectionMaster); configWindowWrapper.MultiStrategies = strategies; configWindowWrapper.HideColumns = true; configWindowWrapper.ShowIt(); if (!configWindowWrapper.Canceled) { Dictionary changes = configWindowWrapper.StrategyChanges; foreach (MultiStrategy.DataWatcher strategy in strategies) { if (null != strategy.Config) { string config = strategy.Config; if (changes.ContainsKey(config)) { // strategy.Stop(); // Setting strategy.Config automatically stops any old data. strategy.Config = changes[config]; // strategy.StartData(); Setting strategy.Config automatically calls StartData(). } } } } if (isCurrentFactorySmallConfig) { ConfigWindowWrapper.DefaultFactory = SmallConfigWindowWrapper.Factory; } } strategyChooserForm.Dispose(); } private void textHeadersToolStripMenuItem_Click(object sender, EventArgs e) { _textHeaders = !textHeadersToolStripMenuItem.Checked; RefreshColumns(); UpdateTextHeadersMenuItem(); } private void UpdateTextHeadersMenuItem() { textHeadersToolStripMenuItem.Checked = _textHeaders; } public void SetSnapToGrid(bool enabled) { formSnapper1.Enabled = enabled; if (GuiEnvironment.RunningWin10 && enabled) { formSnapper1.Win10HeightAdjustment = GuiEnvironment.HEIGHT_INCREASE; formSnapper1.Win10WidthAdjustment = GuiEnvironment.WIDTH_INCREASE; } } private void dataGridView1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) { string ListName = _symbolLinking.SavedSymbolListName; string symbol = ""; string exchange = ""; int currentRow = 0; if (dataGridView1.SelectedRows.Count == 1) { if (e.KeyCode == Keys.Enter) { DataGridViewRow r = dataGridView1.SelectedRows[0]; currentRow = r.Index; RowData test = _boundList[currentRow]; symbol = test.GetSymbol(); exchange = test.GetExchange(); dataGridView1.PerformLayout(); SendToExternalLinking(test); } else if (e.KeyCode == Keys.Space) { DataGridViewRow r = dataGridView1.SelectedRows[0]; int selectedRow = r.Index; currentRow = selectedRow + 1; if (currentRow <= _boundList.Count - 1) { SetCurrentCell(currentRow); dataGridView1.Rows[selectedRow].Selected = false; dataGridView1.Rows[currentRow].Selected = true; RowData test = _boundList[currentRow]; symbol = test.GetSymbol(); exchange = test.GetExchange(); if (!dataGridView1.Rows[currentRow].Displayed) { try { while (!dataGridView1.Rows[currentRow].Displayed) { int firstRow = dataGridView1.FirstDisplayedScrollingRowIndex; dataGridView1.FirstDisplayedScrollingRowIndex = firstRow + 2; } dataGridView1.PerformLayout(); } catch { } } else if (currentRow + 1 < _boundList.Count && !dataGridView1.Rows[currentRow + 1].Displayed) { try { int firstRow = dataGridView1.FirstDisplayedScrollingRowIndex; dataGridView1.FirstDisplayedScrollingRowIndex = firstRow + 1; dataGridView1.PerformLayout(); } catch { } } SendToExternalLinking(test); } } } else if (dataGridView1.SelectedCells.Count != 0 && !TopListForm.moreThanOneRowWithSelectedCells(dataGridView1)) //Options -turn off selected row. { if (e.KeyCode == Keys.Enter) { //find the row of the first selected cell (more that currentRow = dataGridView1.SelectedCells[0].RowIndex; RowData test = _boundList[currentRow]; symbol = test.GetSymbol(); exchange = test.GetExchange(); SendToExternalLinking(test); } else if (e.KeyCode == Keys.Space) { int selectedRow = dataGridView1.SelectedCells[0].RowIndex; int selectedColumn = dataGridView1.SelectedCells[0].ColumnIndex; currentRow = selectedRow + 1; if (currentRow <= _boundList.Count - 1) { dataGridView1.CurrentCell = this.dataGridView1[selectedColumn, currentRow]; RowData test = _boundList[currentRow]; symbol = test.GetSymbol(); exchange = test.GetExchange(); if (!dataGridView1.Rows[currentRow].Displayed) { try { while (!dataGridView1.Rows[currentRow].Displayed) { int firstRow = dataGridView1.FirstDisplayedScrollingRowIndex; dataGridView1.FirstDisplayedScrollingRowIndex = firstRow + 2; } dataGridView1.PerformLayout(); } catch { } } else if (currentRow + 1 < _boundList.Count && !dataGridView1.Rows[currentRow + 1].Displayed) { try { int firstRow = dataGridView1.FirstDisplayedScrollingRowIndex; dataGridView1.FirstDisplayedScrollingRowIndex = firstRow + 1; dataGridView1.PerformLayout(); } catch { } } SendToExternalLinking(test); } } } } /// /// Set focus by setting the CurrentCell. We need to make sure that the column used is visible /// else we get an exception "Current cell cannot be set to an invisble cell". /// /// private void SetCurrentCell(int currentRow) { /* * Setting the current cell actually sets the focus. Row (or cell) selection * is independent from focus-which does set the record pointer. * http://social.msdn.microsoft.com/Forums/windows/en-US/080e68a3-2bcd-4c1d-ae60-54b43b9c040e/datagridview-focusing-a-particular-row?forum=winformsdatacontrols */ int colIndex = 0; foreach (Column col in dataGridView1.Columns) { // CurrentCell must have a visble column. if (col.Visible) { dataGridView1.CurrentCell = this.dataGridView1[colIndex, currentRow]; // Set focus on a row with a visible column. return; } colIndex++; } } private bool _limitedMode = false; public bool LimitedMode { get { return _limitedMode; } set { _limitedMode = value; } } public void ShowConfiguration() { DoMultiConfig(); } public List GetStrategyConfigs() { List toReturn = new List(); foreach (MultiStrategy.DataWatcher strategy in MultiStrategyConfiguration.Strategies) { StrategyConfig strategyConfig; strategyConfig.Config = strategy.Config; strategyConfig.ConfigurationType = ConfigurationType.Alerts; toReturn.Add(strategyConfig); } return toReturn; } private void pinnedToolStripMenuItem_Click(object sender, EventArgs e) { _pinned = pinnedToolStripMenuItem.Checked; } private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e) { // Let's skip this logic if I am loading history so to avoid erasing the history data if (HistoryMode != HistoryModeEnum.HistoryLoading) { int rowIndex = e.RowIndex; if (rowIndex != -1 && rowIndex < _boundList.Count) { _mostRecentRowIndex = rowIndex; _mostRecentRowData = _boundList[rowIndex]; // Require datagrid focus so we can ignore up/down key pressed outside of our application if (GuiEnvironment.IntegrationSupportUpDownKeys && dataGridView1.Focused && (Keyboard.IsKeyDown(Key.Down) || Keyboard.IsKeyDown(Key.Up))) SendToExternalLinking(_mostRecentRowData); } } } public void onClearData() { // If we are in live mode then we only need to clear data. If we are in history we need to establish live mode. // TODO: Investigate when we are requesting history with many strategies history takes a long time (i.e. HistoryLoading). // If a user selects Clear All during History Loading it takes an additional call so that the live streaming can resume. bool historyLoading = false; if (realTimeToolStripMenuItem.Checked) { _strategyDelayTable.Clear(); SetConfigStreaming(); //In live mode } else { if (HistoryMode == HistoryModeEnum.HistoryLoading) historyLoading = true; realTimeToolStripMenuItem.PerformClick(); //In history mode; restart live // Clear up broken streaming if history was stopped when loading if (historyLoading) SetConfigStreaming(); } } private void allToolStripMenuItem_Click(object sender, EventArgs e) { if (!allToolStripMenuItem.Checked) { allToolStripMenuItem.Checked = true; realTimeToolStripMenuItem.Checked = false; timeFrameToolStripMenuItem.Checked = false; _currentlyUsingHistory = true; if (_connectionMaster.LoginManager.IsDemo) { _historyErrorOnDemo = true; allToolStripMenuItem.Checked = false; realTimeToolStripMenuItem.Checked = true; timeFrameToolStripMenuItem.Checked = false; onAccountStatusChanged(); return; } Finished = 0; getNumberSelectedStrategies(); SetConfigHistory(null, null); } } private void MultiStrategy_TextChanged(object sender, EventArgs e) { // change Text of parent form if running in dock panel mode - RVH20210329 if (_dockPanelMode) { Form parent = (Form)this.Parent; if (parent != null) parent.Text = this.Text; } } public void RefreshNow() { if (_connectionMaster.LoginManager.IsDemo) return; // We must restart configuration based on current History setting. if (realTimeToolStripMenuItem.Checked) SetConfigStreaming(); else if (allToolStripMenuItem.Checked) { Finished = 0; getNumberSelectedStrategies(); SetConfigHistory(null, null); } else if (timeFrameToolStripMenuItem.Checked) _timeframe.LoadSettings(); } public bool StrategyContainsPrivateList() { var personalListDetected = false; var index = 0; var symbolLists = GuiEnvironment.GetSymbolListsCacheManager(_connectionMaster)?.GetSymbolLists(); while (index < _config.Strategies.Count && !personalListDetected) { var strategy = _config.Strategies[index]; personalListDetected = HandlesStrategyUtils.StrategyConfigContainsPrivateList(strategy.Config, symbolLists); index++; } return personalListDetected; } private void missingSymbolCheckToolStripMenuItem_Click(object sender, EventArgs e) { MissingSymbolCheckFormChooser missingSymbolCheckFormChooser = new MissingSymbolCheckFormChooser(this); DialogResult result = missingSymbolCheckFormChooser.ShowDialog(); if (result == DialogResult.OK) { var strategiesConfig = missingSymbolCheckFormChooser.GetSelectedStrategies(); if (strategiesConfig.Count > 0) { new WhyNoMatch(this, strategiesConfig, missingSymbolCheckFormChooser.Symbol, missingSymbolCheckFormChooser.FilterToColumns, missingSymbolCheckFormChooser.StartTime, missingSymbolCheckFormChooser.EndTime); } } } } }