using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using TradeIdeas.MiscSupport;
using TradeIdeas.ServerConnection;
using TradeIdeas.TIProData;
using TradeIdeas.TIProData.Configuration;
using TradeIdeas.TIProData.Interfaces;
using TradeIdeas.XML;
namespace TradeIdeas.TIProGUI.LimitAlerts
{
public partial class LimitAlertsGrid : UserControl
{
private readonly IConnectionMaster _connectionMaster;
///
/// Main binding list that is used by dataGridView1.
///
private BindingList _rowDatas = new BindingList();
///
/// All limit alerts whether they match the current filter setting or not.
///
private BindingListWithRemoving _limitAlerts = new BindingListWithRemoving();
///
/// All limit alerts that match the current filter setting.
///
private BindingList _filteredLimitAlerts = new BindingList();
///
/// Maps a limit alert to its rowdata object contained in _rowDatas. Many operations require finding the limit alert's rowdata object to refresh it
/// this dictionary makes finding it really fast.
///
private Dictionary _limitAlertToRowData = new Dictionary();
// add parameter for form type - RVH20210602
//List _columns = RowDataHelper.GetColumnInfoFromClass(typeof(LimitAlert));
List _columns = RowDataHelper.GetColumnInfoFromClass(typeof(LimitAlert), FORM_TYPE);
private Dictionary _dataGridViewColumns = new Dictionary();
private Dictionary _dataGridViewColumnsNames = new Dictionary();
private Dictionary _columnInfosMap = new Dictionary();
private System.Windows.Forms.Timer _refreshTimer = new System.Windows.Forms.Timer();
// new variable for symbol linking channel - RVH20210927
private string _linkChannel = SymbolLinkChannels.DefaultLinkChannel;
private DataCell.SymbolPlusLayoutType _symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off;
private bool _showSymbolPlus = false;
public DataCell.SymbolPlusLayoutType SymbolPlusLayout
{
get { return _symbolPlusLayout; }
set
{
_symbolPlusLayout = value;
updateSymbolPlusMenuItem();
uncheckCurrentSymbolPlusItem();
var correspondingOption = _toolStripMenuItemSymbolPlus.DropDownItems.Cast().FirstOrDefault(item => (DataCell.SymbolPlusLayoutType)item.Tag == _symbolPlusLayout);
if (correspondingOption != null)
correspondingOption.PerformClick();
}
}
public LimitAlertsGrid(IConnectionMaster connectionMaster)
{
_connectionMaster = connectionMaster;
InitializeComponent();
GuiEnvironment.QuoteFeedManager.QuoteFeedDataReceived += QuoteFeedManager_QuoteFeedDataReceived;
InstallColumns();
// check to see if auto-size columns is set - RVH20210720
if (GuiEnvironment.autosizeColumns)
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
ExtensionMethods.DoubleBufferedDatagrid(dataGridView1, true);
dataGridView1.DataSource = _rowDatas;
dataGridView1.CellDoubleClick += dataGridView1_CellDoubleClick;
dataGridView1.CellMouseEnter += dataGridView1_CellMouseEnter;
dataGridView1.CellMouseLeave += dataGridView1_CellMouseLeave;
dataGridView1.Click += dataGridView1_Click;
dataGridView1.CellMouseDown += dataGridView1_CellMouseDown;
BuildContextMenu();
updateSymbolPlusMenuItem();
chooseRowSelect();
_refreshTimer = new System.Windows.Forms.Timer();
_refreshTimer.Interval = 1000;
_refreshTimer.Tick += _refreshTimer_Tick;
_refreshTimer.Start();
}
void _refreshTimer_Tick(object sender, EventArgs e)
{
this.BeginInvokeIfRequired(delegate ()
{
RowDataHelper.DoSorting(dataGridView1, _rowDatas, _sortByColumn, _sortType);
});
}
public void SetSelectedRow()
{
this.InvokeIfRequired(delegate ()
{
if (dataGridView1.Rows.Count > 0 && dataGridView1.Columns.Count > 0)
{
dataGridView1.ClearSelection();
dataGridView1.Rows[0].Cells[0].Selected = true;
dataGridView1.FirstDisplayedScrollingRowIndex = 0;
}
});
}
///
/// Updates any gradients that should be updated on a periodic basis.
///
public void UpdateGradients()
{
UpdatePandLGradient("DollarsSinceTriggered");
List> cellsToRefresh = GetCellsToRefresh();
foreach (Tuple cell in cellsToRefresh.ToList())
{
dataGridView1.InvalidateCell(cell.Item1, cell.Item2);
}
}
private List> GetCellsToRefresh()
{
List> toReturn = new List>();
List updateColumns = GetUpdateColumns();
foreach (RowData rowData in _rowDatas.ToList())
{
int rowIndex = _rowDatas.IndexOf(rowData);
foreach (int columnIndex in updateColumns.ToList())
{
toReturn.Add(Tuple.Create(columnIndex, rowIndex));
}
}
return toReturn;
}
private List GetUpdateColumns()
{
List toReturn = new List();
foreach (ColumnInfo columnInfo in _columns.ToList())
{
if (columnInfo.RealTimeUpdates)
{
if (_columnInfosMap.ContainsKey(columnInfo))
{
DataGridViewColumn column = _columnInfosMap[columnInfo];
toReturn.Add(column.Index);
}
}
}
return toReturn;
}
private void UpdatePandLGradient(string columnCode)
{
ColumnInfo columnInfo = null;
foreach (Column column in dataGridView1.Columns.OfType().ToList())
{
if (null != column.ColumnInfo && column.ColumnInfo.WireName == columnCode)
{
columnInfo = column.ColumnInfo;
break;
}
}
if (null != columnInfo)
{
double averageProfit = 0;
List rowDatas = _rowDatas.ToList();
var positiveRows = rowDatas.Where(x => x.GetAsDouble(columnCode, 0.0) > 0);
if (positiveRows.Count() > 0)
averageProfit = positiveRows.Average(x => x.GetAsDouble(columnCode, 0.0));
double averageLoss = 0;
var negativeRows = rowDatas.Where(x => x.GetAsDouble(columnCode, 0.0) < 0);
if (negativeRows.Count() > 0)
averageLoss = Math.Abs(negativeRows.Average(x => x.GetAsDouble(columnCode, 0.0)));
double max = Math.Max(averageProfit, averageLoss);
if (max > 0)
{
columnInfo.GradientInfo = new GradientInfo();
columnInfo.GradientInfo.Add(max, Color.Green);
columnInfo.GradientInfo.Add(0, Color.Black);
columnInfo.GradientInfo.Add(-max, Color.Red);
}
}
}
void QuoteFeedManager_QuoteFeedDataReceived(string symbol, RowData data)
{
this.BeginInvokeIfRequired(delegate ()
{
RefreshData(symbol);
});
}
public void setContextMenuFont(Font font)
{
dataGridView1.ContextMenuStrip.Font = font;
}
public DataGridView getDataGridView()
{
return dataGridView1;
}
private const string FORM_TYPE = "LIMIT_ALERTS";
static private bool IsDuplicate(LimitAlert limitAlert)
{
if (GuiEnvironment.LimitAlerts.Count > 0)
{
if (GuiEnvironment.LimitAlerts.Count(x => x.Symbol == limitAlert.Symbol && x.Price == limitAlert.Price && x.IsLong == limitAlert.IsLong && x.LongAfter == limitAlert.LongAfter && x.AfterHours == limitAlert.AfterHours) > 0)
return true;
}
return false;
}
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 (!connectionMaster.LoginManager.IsDemo)
{
int restoredAlerts = 0;
int duplicateAlerts = 0;
int notLoadedAlerts = 0;
string notLoadedMessage = "";
string marketPremium = GuiEnvironment.MarketingLink;
foreach (XmlNode limitAlertNode in description.ChildNodes)
{
LimitAlert limitAlert = new LimitAlert();
limitAlert.Restore(limitAlertNode);
bool duplicate = IsDuplicate(limitAlert);
if (duplicate)
duplicateAlerts++;
else
{
if ((GuiEnvironment.LimitAlerts.Count + restoredAlerts) < GuiEnvironment.MaxLimitAlerts)
{
restoredAlerts++;
GuiEnvironment.LimitAlertsMessageManager.CreateNewLimitAlert(limitAlert);
}
else
notLoadedAlerts++;
}
}
if (notLoadedAlerts == 1)
notLoadedMessage = Environment.NewLine + "Skipped " + notLoadedAlerts + " alert due to exceeding the maximun number of price alerts of " + GuiEnvironment.MaxLimitAlerts + ".";
else if (notLoadedAlerts > 0)
notLoadedMessage = Environment.NewLine + "Skipped " + notLoadedAlerts + " alerts due to exceeding the maximun number of price alerts of " + GuiEnvironment.MaxLimitAlerts + ".";
if (GuiEnvironment.MaxLimitAlerts == GuiEnvironment.STDLIMTALERTS && notLoadedAlerts > 0)
{
UpgradeMessageBox.Show("Created " + restoredAlerts + " new alerts. Found " + duplicateAlerts + " duplicates." + notLoadedMessage, "Copied Price Alerts", "Acccept", "Cancel");
}
else
MessageBox.Show("Created " + restoredAlerts + " new alerts. Found " + duplicateAlerts + " duplicates." + notLoadedMessage, "Copied Price Alerts");
}
else
{
UpgradeMessageBox.Show(Environment.NewLine + Environment.NewLine + "You need a subscription to use Price Alerts. Click link to learn more.", "Need Subscription", "OK", "");
}
});
}
void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.RowIndex != -1)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// if multiple rows are already selected, then don't change the selection.
// if one or zero rows is selected, then change selected row to the one you right clicked on.
if (!MultipleRowsSelected())
{
dataGridView1.ClearSelection();
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected = true;
SetMenuItemStatus();
}
// See if this column is Symbol Plus.
_showSymbolPlus = false;
if (e.ColumnIndex >= 0)
{
Column column = dataGridView1.Columns[e.ColumnIndex] as Column;
if (column != null && column.ColumnInfo != null && column.ColumnInfo.Format == "symbolplus")
_showSymbolPlus = true;
}
}
}
}
///
/// This function returns selected rows whether SelectionMode is FullRowSelect or CellSelect.
/// It has been modified to improve performance.
///
/// List of selected rows if any.
private HashSet GetSelectedRows()
{
//DateTime start = DateTime.Now;
HashSet selectedRows = new HashSet();
// In the event the user selects all the rows we can improve the datagrid performance
// by not using the dataGridView1.SelectedCells collection.
// https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.areallcellsselected.aspx
if (dataGridView1.AreAllCellsSelected(true))
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
selectedRows.Add(row);
}
}
else
{
foreach (DataGridViewCell selectedCell in dataGridView1.SelectedCells)
{
DataGridViewRow row = selectedCell.OwningRow;
if (!selectedRows.Contains(row))
selectedRows.Add(row);
}
}
//DateTime finish = DateTime.Now;
//System.Diagnostics.Debug.WriteLine("GetSelectedRows() took " + (finish-start).TotalMilliseconds + "ms to find " + selectedRows.Count + " of " + dataGridView1.Rows.Count);
return selectedRows;
}
private bool MultipleRowsSelected()
{
int rowCount = GetSelectedRows().Count;
//System.Diagnostics.Debug.WriteLine("MultipleRowsSelected(), dataGridView1.SelectedCells.Count=" + dataGridView1.SelectedCells.Count + ", rowCount=" + rowCount);
return rowCount > 1;
}
private bool SingleRowSelected()
{
return GetSelectedRows().Count == 1;
}
void dataGridView1_Click(object sender, EventArgs e)
{
if (!_hoveringOnHeader && null == _currentLimitAlert)
dataGridView1.ClearSelection();
}
void dataGridView1_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
{
_hoveringOnHeader = false;
_currentLimitAlert = null;
}
private bool _hoveringOnHeader = false;
private LimitAlert _currentLimitAlert = null;
void dataGridView1_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
_hoveringOnHeader = e.RowIndex == -1;
if (e.RowIndex != -1)
{
try
{
RowData rowData = dataGridView1.Rows[e.RowIndex].DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.Data["object"] as LimitAlert;
if (null != limitAlert)
_currentLimitAlert = limitAlert;
}
}
catch (Exception exc)
{
string debugView = exc.ToString();
}
}
}
public void ClearAlerts()
{
this.InvokeIfRequired(delegate ()
{
_rowDatas.Clear();
_limitAlerts.Clear();
_limitAlertToRowData.Clear();
});
}
private ToolStripMenuItem _toolStripMenuItemDeleteAlerts = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemCreateAlert = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemEditAlert = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemSaveAlerts = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemActions = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemStockTwitsShare = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemPinned = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemDuplicate = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemSaveToCloud = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemSetAsDefault = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemColumns = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemShowFilter = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemShowChartIntraday = new ToolStripMenuItem();
private ToolStripMenuItem _toolStripMenuItemShowChartDaily = new ToolStripMenuItem();
// new menu item for symbol linking - RVH20210927
private ToolStripMenuItem _toolStripMenuItemSymbolLinking = new ToolStripMenuItem();
// New menu item for symbol plus setting.
private ToolStripMenuItem _toolStripMenuItemSymbolPlus = new ToolStripMenuItem();
private void updateSymbolPlusMenuItem()
{
if (dataGridView1.ContextMenuStrip != null)
{
_toolStripMenuItemSymbolPlus.Checked = _symbolPlusLayout != DataCell.SymbolPlusLayoutType.Off;
}
}
private void uncheckCurrentSymbolPlusItem()
{
var currentSelectedOption = _toolStripMenuItemSymbolPlus.DropDownItems.Cast().FirstOrDefault(item => item.Checked);
if (currentSelectedOption != null)
currentSelectedOption.Checked = false;
}
private void addSymbolPlusMenuOptions()
{
ToolStripMenuItem toolStripMenuItem1 = new ToolStripMenuItem("Normal");
toolStripMenuItem1.Tag = DataCell.SymbolPlusLayoutType.Normal;
toolStripMenuItem1.Click += delegate
{
if (!toolStripMenuItem1.Checked)
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Normal);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.Normal;
uncheckCurrentSymbolPlusItem();
toolStripMenuItem1.Checked = true;
}
else
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off;
uncheckCurrentSymbolPlusItem();
}
DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout);
UpdateSymbolPlus();
updateSymbolPlusMenuItem();
};
ToolStripMenuItem toolStripMenuItem2 = new ToolStripMenuItem("Logo Only");
toolStripMenuItem2.Tag = DataCell.SymbolPlusLayoutType.LogoOnly;
toolStripMenuItem2.Click += delegate
{
if (!toolStripMenuItem2.Checked)
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.LogoOnly);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.LogoOnly;
uncheckCurrentSymbolPlusItem();
toolStripMenuItem2.Checked = true;
}
else
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off;
uncheckCurrentSymbolPlusItem();
}
DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout);
UpdateSymbolPlus();
updateSymbolPlusMenuItem();
};
ToolStripMenuItem toolStripMenuItem3 = new ToolStripMenuItem("No Logo");
toolStripMenuItem3.Tag = DataCell.SymbolPlusLayoutType.NoLogo;
toolStripMenuItem3.Click += delegate
{
if (!toolStripMenuItem3.Checked)
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.NoLogo);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.NoLogo;
uncheckCurrentSymbolPlusItem();
toolStripMenuItem3.Checked = true;
}
else
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off;
uncheckCurrentSymbolPlusItem();
}
DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout);
UpdateSymbolPlus();
updateSymbolPlusMenuItem();
};
ToolStripMenuItem toolStripMenuItem4 = new ToolStripMenuItem("Symbol/Logo");
toolStripMenuItem4.Tag = DataCell.SymbolPlusLayoutType.SymbolLogo;
toolStripMenuItem4.Click += delegate
{
if (!toolStripMenuItem4.Checked)
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.SymbolLogo);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.SymbolLogo;
uncheckCurrentSymbolPlusItem();
toolStripMenuItem4.Checked = true;
}
else
{
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, DataCell.SymbolPlusLayoutType.Off);
_symbolPlusLayout = DataCell.SymbolPlusLayoutType.Off;
uncheckCurrentSymbolPlusItem();
}
DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout);
UpdateSymbolPlus();
updateSymbolPlusMenuItem();
};
_toolStripMenuItemSymbolPlus.DropDownItems.Add(toolStripMenuItem1);
_toolStripMenuItemSymbolPlus.DropDownItems.Add(toolStripMenuItem2);
_toolStripMenuItemSymbolPlus.DropDownItems.Add(toolStripMenuItem3);
_toolStripMenuItemSymbolPlus.DropDownItems.Add(toolStripMenuItem4);
}
private void BuildContextMenu()
{
dataGridView1.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
_toolStripMenuItemSymbolPlus.Text = "Symbol Plus";
addSymbolPlusMenuOptions();
_toolStripMenuItemSymbolPlus.Click += delegate
{
if (_toolStripMenuItemSymbolPlus.Checked)
{
var selectedOption = _toolStripMenuItemSymbolPlus.DropDownItems.Cast().ToList().FirstOrDefault(item => item.Checked);
if (selectedOption != null)
selectedOption.PerformClick();
}
else
{
var normalOption = _toolStripMenuItemSymbolPlus.DropDownItems.Cast().ToList().FirstOrDefault(item => item.Text == "Normal");
if (normalOption != null)
normalOption.PerformClick();
}
};
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemSymbolPlus);
_toolStripMenuItemCreateAlert.Text = "Create New Price Alert...";
_toolStripMenuItemCreateAlert.Click += _toolStripMenuItemCreateAlert_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemCreateAlert);
_toolStripMenuItemEditAlert.Text = "Edit Price Alert...";
_toolStripMenuItemEditAlert.Click += _toolStripMenuItemEditAlert_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemEditAlert);
_toolStripMenuItemDeleteAlerts.Text = "Delete Price Alert...";
_toolStripMenuItemDeleteAlerts.Click += _toolStripMenuItemDeleteAlerts_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemDeleteAlerts);
dataGridView1.ContextMenuStrip.Items.Add(new ToolStripSeparator());
_toolStripMenuItemSaveAlerts.Text = "Share Price Alert...";
_toolStripMenuItemSaveAlerts.Click += _toolStripMenuItemSaveAlerts_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemSaveAlerts);
_toolStripMenuItemStockTwitsShare.Text = "Post Price Alert to StockTwits...";
_toolStripMenuItemStockTwitsShare.Click += _toolStripMenuItemStockTwitsShare_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemStockTwitsShare);
dataGridView1.ContextMenuStrip.Items.Add(new ToolStripSeparator());
_toolStripMenuItemActions.Text = "Actions...";
_toolStripMenuItemActions.Click += _toolStripMenuItemActions_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemActions);
_toolStripMenuItemColumns.Text = "Columns...";
_toolStripMenuItemColumns.Click += _toolStripMenuItemColumns_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemColumns);
_toolStripMenuItemPinned.Text = "Pinned";
_toolStripMenuItemPinned.CheckOnClick = true;
_toolStripMenuItemPinned.Checked = _pinned;
_toolStripMenuItemPinned.Click += _toolStripMenuItemPinned_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemPinned);
_toolStripMenuItemShowFilter.Text = "Show Filter";
_toolStripMenuItemShowFilter.CheckOnClick = true;
_toolStripMenuItemShowFilter.Checked = _showFilter;
_toolStripMenuItemShowFilter.Click += _toolStripMenuItemShowFilter_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemShowFilter);
_toolStripMenuItemShowChartIntraday.Text = "Show Intraday P&&L";
_toolStripMenuItemShowChartIntraday.CheckOnClick = true;
_toolStripMenuItemShowChartIntraday.Checked = _showChartIntraday;
_toolStripMenuItemShowChartIntraday.Click += _toolStripMenuItemShowChartIntraday_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemShowChartIntraday);
_toolStripMenuItemShowChartDaily.Text = "Show Daily P&&L";
_toolStripMenuItemShowChartDaily.CheckOnClick = true;
_toolStripMenuItemShowChartDaily.Checked = _showChartDaily;
_toolStripMenuItemShowChartDaily.Click += _toolStripMenuItemShowChartDaily_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemShowChartDaily);
// new menu item for symbol linking - RVH20210927
_toolStripMenuItemSymbolLinking.Text = "Symbol Linking";
//_toolStripMenuItemSymbolLinking.DropDownOpening += _toolStripMenuItemSymbolLinking_DropDownOpening;
// update symbol linking channels when the context menu is opening
dataGridView1.ContextMenuStrip.Opening += _toolStripMenuItemSymbolLinking_DropDownOpening;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemSymbolLinking);
dataGridView1.ContextMenuStrip.Items.Add(new ToolStripSeparator());
_toolStripMenuItemDuplicate.Text = "Duplicate";
_toolStripMenuItemDuplicate.Click += _toolStripMenuItemDuplicate_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemDuplicate);
_toolStripMenuItemSaveToCloud.Text = "Save to Cloud...";
_toolStripMenuItemSaveToCloud.Click += _toolStripMenuItemSaveToCloud_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemSaveToCloud);
_toolStripMenuItemSetAsDefault.Text = "Save As Default";
_toolStripMenuItemSetAsDefault.CheckOnClick = true;
_toolStripMenuItemSetAsDefault.Click += _toolStripMenuItemSetAsDefault_Click;
dataGridView1.ContextMenuStrip.Items.Add(_toolStripMenuItemSetAsDefault);
dataGridView1.ContextMenuStrip.Opening += ContextMenuStrip_Opening;
SetMenuItemStatus();
}
private void _toolStripMenuItemSymbolLinking_DropDownOpening(object sender, EventArgs e)
{
_toolStripMenuItemSymbolLinking.DropDown.Items.Clear();
//Detect if the current window is in floating mode
var floatingMode = string.IsNullOrEmpty(GuiEnvironment.GetDockWindowID(this.ParentForm));
foreach (KeyValuePair channel in SymbolLinkChannels.Channels)
{
if (channel.Key == SymbolLinkChannels.DockWindowChannel && floatingMode) continue;
ToolStripMenuItem menuItem = new ToolStripMenuItem(channel.Key, null, delegate
{
SetLinkChannel(channel.Key);
//foreach (ToolStripMenuItem toolStripMenuItem in _toolStripMenuItemSymbolLinking.DropDownItems)
//{
// if (toolStripMenuItem.Text == _linkChannel)
// toolStripMenuItem.Checked = true;
// else
// toolStripMenuItem.Checked = false;
//}
});
menuItem.BackColor = channel.Value;
Color foreColor = GradientInfo.AltColor(channel.Value);
menuItem.ForeColor = foreColor;
menuItem.Checked = _linkChannel == channel.Key;
_toolStripMenuItemSymbolLinking.DropDown.Items.Add(menuItem);
}
}
public void UpdateSymbolPlus(bool restoringLayout = false, int symbolPlusWidth = -1)
{
var column = dataGridView1.Columns.Cast().FirstOrDefault(gridColumn => gridColumn.ColumnInfo.Format == "symbolplus");
if (column != null)
{
var adjustedColumn = DataCell.GetColumn(column.ColumnInfo, _connectionMaster, this, symbolPlusLayoutType: _symbolPlusLayout);
dataGridView1.Columns[column.Index].MinimumWidth = adjustedColumn.MinimumWidth;
if (!restoringLayout)
dataGridView1.Columns[column.Index].Width = adjustedColumn.MinimumWidth;
else
{
if (symbolPlusWidth > -1)
dataGridView1.Columns[column.Index].Width = symbolPlusWidth;
}
}
}
//private void _toolStripMenuItemSymbolLinking_DropDownOpening(object sender, EventArgs e)
//{
// _toolStripMenuItemSymbolLinking.DropDown.Items.Clear();
// foreach (KeyValuePair channel in SymbolLinkChannels.Channels)
// {
// ToolStripMenuItem menuItem = new ToolStripMenuItem(channel.Key, null, delegate
// {
// SetLinkChannel(channel.Key);
// });
// menuItem.BackColor = channel.Value;
// menuItem.Checked = _linkChannel == channel.Key;
// _toolStripMenuItemSymbolLinking.DropDown.Items.Add(menuItem);
// }
//}
void _toolStripMenuItemShowChartDaily_Click(object sender, EventArgs e)
{
LimitAlertsForm parent = GetParent();
if (null != parent)
{
parent.ShowHideDailyChart(_toolStripMenuItemShowChartDaily.Checked);
_showChartDaily = _toolStripMenuItemShowChartDaily.Checked;
}
}
void _toolStripMenuItemShowChartIntraday_Click(object sender, EventArgs e)
{
LimitAlertsForm parent = GetParent();
if (null != parent)
{
parent.ShowHideIntradayChart(_toolStripMenuItemShowChartIntraday.Checked);
_showChartIntraday = _toolStripMenuItemShowChartIntraday.Checked;
}
}
void _toolStripMenuItemSaveToCloud_Click(object sender, EventArgs e)
{
LimitAlertsForm parent = GetParent();
if (null != parent)
parent.SaveToCloud();
}
void _toolStripMenuItemDuplicate_Click(object sender, EventArgs e)
{
LimitAlertsForm parent = GetParent();
if (null != parent)
parent.Duplicate();
}
void _toolStripMenuItemShowFilter_Click(object sender, EventArgs e)
{
LimitAlertsForm parent = GetParent();
if (null != parent)
{
parent.ShowHideFilterPanel(_toolStripMenuItemShowFilter.Checked);
_showFilter = _toolStripMenuItemShowFilter.Checked;
}
}
void _toolStripMenuItemColumns_Click(object sender, EventArgs e)
{
ConfigWindowWrapper configWindowWrapper = new TraditionalConfigWindowWrapper(ConfigurationType.CustomColumns, _connectionMaster);
configWindowWrapper.VisibleCustomColumns = RowDataHelper.GetVisibleColumns(_dataGridViewColumns);
configWindowWrapper.AllCustomColumns = RowDataHelper.GetAllColumns(_dataGridViewColumns);
configWindowWrapper.ShowIt();
// TODO the following defaultColumns should be customized for limit alerts.
string[] defaultColumns = new string[] { "Entry Time", "L/S", "Symbol", "Entry Price", "Exit Price", "Profit", "Strategy" };
if (!configWindowWrapper.CanceledAIColumnConfig)
RowDataHelper.ApplyVisibleColumns(defaultColumns, _columns, configWindowWrapper.VisibleCustomColumns, _dataGridViewColumnsNames);
}
private const string _defaultFileName = "DEFAULT_LIMITALERTS.WTI";
void _toolStripMenuItemSetAsDefault_Click(object sender, EventArgs e)
{
string programDirFileName = LayoutManager.Instance().Directory + "\\" + _defaultFileName;
LimitAlertsForm parent = GetParent();
if (null != parent)
LayoutManager.Instance().SaveOne(parent, programDirFileName);
}
void _toolStripMenuItemPinned_Click(object sender, EventArgs e)
{
_pinned = _toolStripMenuItemPinned.Checked;
}
void _toolStripMenuItemStockTwitsShare_Click(object sender, EventArgs e)
{
if (dataGridView1.SelectedCells.Count == 1)
{
RowData rowData = dataGridView1.SelectedCells[0].OwningRow.DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
SendToStockTwits(limitAlert);
}
}
}
private string _lastTiniedCloudLink = "";
private string _lastCloudLink = "";
private LimitAlert _lastSendingLimitAlert = null;
private void SendToStockTwits(LimitAlert limitAlert)
{
_lastSendingLimitAlert = limitAlert;
List saveAlerts = new List();
saveAlerts.Add(limitAlert);
_lastCloudLink = SaveLimitAlerts(saveAlerts, false);
_lastTiniedCloudLink = "";
new Thread(GetTinyUrl).Start();
}
private void StartStockTwitsForm()
{
LimitAlert limitAlert = _lastSendingLimitAlert;
RowData rowData = new RowData();
rowData.Data.Add("SYMBOL", limitAlert.Symbol);
string limitAlertAsString = "alert when price" + (limitAlert.IsLong ? " rises to " : " falls to ") + "$" + limitAlert.Price.ToString("N2");
if (limitAlert.InvalidPrice.HasValue)
limitAlertAsString += " unless it reaches $" + limitAlert.InvalidPrice.Value.ToString("N2") + " first";
if (_lastTiniedCloudLink != "")
limitAlertAsString += " " + _lastTiniedCloudLink;
SendToForm sendToForm = new SendToForm(AlertForm.SocialNetwork.STWITS, rowData, "", "", limitAlertAsString);
sendToForm.Show();
LimitAlertsForm parentForm = GetParent();
if (null != parentForm)
{
GuiEnvironment.SetWindowOpeningPosition(sendToForm, parentForm);
}
}
private void GetTinyUrl()
{
_lastTiniedCloudLink = GuiEnvironment.makeTinyURL(_lastCloudLink);
if (_lastTiniedCloudLink != "")
this.BeginInvokeIfRequired(StartStockTwitsForm);
}
void ContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
SetMenuItemStatus();
// Show or hide the Symbol Plus menu item.
_toolStripMenuItemSymbolPlus.Visible = _showSymbolPlus;
if (null != GuiEnvironment.RobotStrategyMenuCode)
{
string symbol = "";
if (SingleRowSelected())
{
RowData rowData = dataGridView1.SelectedCells[0].OwningRow.DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
symbol = limitAlert.Symbol;
GuiEnvironment.RobotStrategyMenuCode(dataGridView1.ContextMenuStrip, symbol, "PRICE_ALERTS", rowData);
}
}
else
GuiEnvironment.RobotStrategyMenuCode(dataGridView1.ContextMenuStrip, "", "PRICE_ALERTS", null);
}
}
void _toolStripMenuItemActions_Click(object sender, EventArgs e)
{
LimitAlertsForm parentForm = GetParent();
if (null != parentForm && null != parentForm.Actions)
{
// Hide show alert checkbox in the actions form since this feature is handled in this class.
parentForm.Actions.HideShowAlert = true;
parentForm.Actions.ShowDialog();
_toolStripMenuItemActions.Checked = parentForm.Actions.InUse();
}
}
void _toolStripMenuItemEditAlert_Click(object sender, EventArgs e)
{
if (SingleRowSelected())
{
RowData rowData = dataGridView1.SelectedCells[0].OwningRow.DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
{
LimitAlertCreateForm editForm = new LimitAlertCreateForm(limitAlert.Symbol);
editForm.WindowName = "Edit Price Alert";
editForm.Price = limitAlert.Price;
editForm.Notes = limitAlert.Notes;
editForm.InvalidPrice = limitAlert.InvalidPrice;
editForm.Expires = limitAlert.Expires;
editForm.Creation = limitAlert.Created;
editForm.Updated = limitAlert.Updated;
editForm.IsLong = limitAlert.IsLong;
editForm.LongAfter = limitAlert.LongAfter;
editForm.AfterHours = limitAlert.AfterHours;
editForm.Id = limitAlert.Id;
DialogResult result = editForm.ShowDialog();
if (result == DialogResult.OK)
GuiEnvironment.LimitAlertsMessageManager.CreateNewLimitAlert(editForm.LimitAlert);
}
}
}
}
void _toolStripMenuItemSaveAlerts_Click(object sender, EventArgs e)
{
HashSet selectedRows = GetSelectedRows();
if (selectedRows.Count > 0)
{
List toSave = new List();
foreach (DataGridViewRow row in selectedRows.ToList())
{
RowData rowData = row.DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
toSave.Add(limitAlert);
}
}
SaveLimitAlerts(toSave);
selectedRows.Clear();
}
}
///
/// Saves limit alerts to the cloud and brings up cloud link to share.
///
/// List of LimitAlert objects to share.
private string SaveLimitAlerts(List limitAlerts, bool bringUpCollaborateWindow = true)
{
XmlDocument xmlDoc = new XmlDocument();
XmlNode layoutNode = xmlDoc.CreateElement("LAYOUT");
xmlDoc.AppendChild(layoutNode);
XmlNode topNode = layoutNode.NewNode("LIMIT_ALERTS");
topNode.SetProperty("FORM_TYPE", FORM_TYPE);
string description = "";
List allSymbols = limitAlerts.Select(x => x.Symbol).ToList();
int uniqueSymbols = allSymbols.Distinct().Count();
string shortDescription = "Price Alerts - " + limitAlerts.Count;
if (limitAlerts.Count == 1)
shortDescription += " alert at $" + limitAlerts[0].Price.ToString("N2");
else
shortDescription += " alerts";
shortDescription += " for ";
if (uniqueSymbols == 1)
shortDescription += allSymbols[0];
else
shortDescription += uniqueSymbols + " symbols";
foreach (LimitAlert limitAlert in limitAlerts)
{
XmlNode limitAlertNode = topNode.NewNode("LIMIT_ALERT");
description += limitAlert.Symbol + " at $" + limitAlert.Price + "\n";
limitAlert.Save(limitAlertNode);
}
string layout = xmlDoc.OuterXml;
if (System.Text.Encoding.UTF8.GetByteCount(layout) > 500000)
MessageBox.Show("Unable to save these price alerts to the cloud. It is too big.", "Save or Share to Cloud");
else
{
Dictionary messageToServer = TalkWithServer.CreateMessage(
"command", "save_to_cloud",
"layout", layout,
"icon", FORM_TYPE,
"window_count", 0,
"clear_previous_layout", "0",
"short_description", shortDescription,
"long_description", description);
using (SaveToCloudResponse responseCloud = new SaveToCloudResponse(messageToServer, _connectionMaster.SendManager))
{
responseCloud.StartPosition = FormStartPosition.CenterParent;
responseCloud.ShowDialog();
string code = responseCloud._code;
if (code != null && bringUpCollaborateWindow)
{
try
{
Clipboard.SetText(code);
}
catch
{ }
CollaborateForm form = new CollaborateForm();
form.ConfigString = code;
form.Text = "Share this Link";
form.SetCloudOptions();
form.ShowDialog();
form.Dispose();
}
else
return code;
}
}
return "";
}
void _toolStripMenuItemCreateAlert_Click(object sender, EventArgs e)
{
// If the user is at the max limit alert count then we will give them the option to delete the oldest
// price alert and then proceeed to create the new price alert.
if (GuiEnvironment.LimitAlerts.Count >= GuiEnvironment.MaxLimitAlerts)
{
GuiEnvironment.UpdateOldestLimitAlertForDeletion();
if (GuiEnvironment.MaxLimitAlerts == GuiEnvironment.STDLIMTALERTS)
{
DialogResult result1 = UpgradeMessageBox.Show("You have reached the maximum number of price alerts allowed of " + GuiEnvironment.MaxLimitAlerts + "." + Environment.NewLine + Environment.NewLine + "Click OK to delete the oldest Price Alert and continue to create the new price alert.", "Confirm Price Alert", "OK", "Cancel");
if (result1 == System.Windows.Forms.DialogResult.OK)
{
// Delete oldest
GuiEnvironment.LimitAlertsMessageManager.DeleteAlert(GuiEnvironment.oldestLimitAlertForDeletion.Id);
}
else
return;
}
else
{
DialogResult result1 = MessageBox.Show("You have reached the maximum number of price alerts allowed of " + GuiEnvironment.MaxLimitAlerts + "." + " Click OK to delete the oldest Price Alert and continue to create the new price alert.", "Confirm Price Alert", MessageBoxButtons.OKCancel);
if (result1 == System.Windows.Forms.DialogResult.OK)
{
// Delete oldest limit alert
GuiEnvironment.LimitAlertsMessageManager.DeleteAlert(GuiEnvironment.oldestLimitAlertForDeletion.Id);
}
else
return;
}
}
LimitAlertCreateForm limitAlertForm = new LimitAlertCreateForm("SPY");
limitAlertForm.Price = 200.00;
limitAlertForm.IsLong = true;
limitAlertForm.LongAfter = true;
limitAlertForm.AfterHours = GuiEnvironment.LimitAlertAfterHours;
DialogResult result = limitAlertForm.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
GuiEnvironment.LimitAlertAfterHours = limitAlertForm.AfterHours;
GuiEnvironment.LimitAlertsMessageManager.CreateNewLimitAlert(limitAlertForm.LimitAlert);
}
}
void _toolStripMenuItemDeleteAlerts_Click(object sender, EventArgs e)
{
HashSet selectedRows = GetSelectedRows();
if (selectedRows.Count > 0)
{
DialogResult result = MessageBox.Show("Delete " + selectedRows.Count + " selected price alerts?", "Confirm deletion", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
foreach (DataGridViewRow row in selectedRows.ToList())
{
RowData rowData = row.DataBoundItem as RowData;
if (null != rowData)
{
LimitAlert limitAlert = rowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
GuiEnvironment.LimitAlertsMessageManager.DeleteAlert(limitAlert.Id);
}
}
}
SetSelectedRow();
}
}
///
/// Most recently retrieved filter values for symbols.
///
private Dictionary> _currentValues = new Dictionary>();
private Dictionary GetValueStore(string symbol)
{
Dictionary toReturn = new Dictionary();
if (_currentValues.ContainsKey(symbol))
toReturn = _currentValues[symbol];
else
_currentValues.Add(symbol, toReturn);
return toReturn;
}
private void RefreshData(string symbol)
{
bool limitAlertUpdated = false;
foreach (LimitAlert limitAlert in _limitAlerts.ToList())
{
if (limitAlert.Symbol == symbol)
{
limitAlertUpdated = true;
RowData currentValues = GuiEnvironment.QuoteFeedManager.GetCurrentValues(symbol);
if (null != currentValues)
{
limitAlert.CompanyName = currentValues.GetCompanyName();
limitAlert.ChangeFromTheClose = currentValues.GetAsDouble("c_FCD", null);
limitAlert.ChangeFromTheClosePercent = currentValues.GetAsDouble("c_FCP", null);
limitAlert.RelativeVolume = currentValues.GetAsDouble("c_RV", null);
limitAlert.Volatility = currentValues.GetAsDouble("c_VWV", null);
limitAlert.TodayVolume = currentValues.GetAsInt("c_TV", null);
limitAlert.CurrentPrice = currentValues.GetPrice();
AddLimitAlert(limitAlert);
}
}
}
if (limitAlertUpdated)
UpdateColumnGradients();
}
private void UpdateColumnGradients()
{
this.InvokeIfRequired(delegate ()
{
UpdateColumnGradient("DistanceFromAlert");
UpdateColumnGradient("PercentFromAlert");
UpdateColumnGradient("VolatilityBarsFromAlert");
});
}
private void UpdateColumnGradient(string columnCode)
{
ColumnInfo columnInfo = null;
foreach (Column column in dataGridView1.Columns.OfType())
{
if (null != column.ColumnInfo && column.ColumnInfo.WireName == columnCode)
{
columnInfo = column.ColumnInfo;
break;
}
}
if (null != columnInfo)
{
double averageProfit = 0;
List rowDatas = _rowDatas.ToList();
var positiveRows = rowDatas.Where(x => x.GetAsDouble(columnCode, 0.0) > 0);
if (positiveRows.Count() > 0)
averageProfit = positiveRows.Average(x => x.GetAsDouble(columnCode, 0.0));
double averageLoss = 0;
var negativeRows = rowDatas.Where(x => x.GetAsDouble(columnCode, 0.0) < 0);
if (negativeRows.Count() > 0)
averageLoss = Math.Abs(negativeRows.Average(x => x.GetAsDouble(columnCode, 0.0)));
double max = Math.Max(averageProfit, averageLoss);
if (max > 0)
{
columnInfo.GradientInfo = new GradientInfo();
columnInfo.GradientInfo.Add(max, Color.Green);
columnInfo.GradientInfo.Add(0, Color.Black);
columnInfo.GradientInfo.Add(-max, Color.Red);
}
}
}
///
/// Validate that the price alert is valid for the current market hours and the alert configuration
///
///
///
private bool IsAlertValidAfterHours(LimitAlert limitAlert)
{
var now = ServerFormats.Now;
var marketOpenLocal = GuiEnvironment.GetMarketOpenLocalTime();
var marketCloseLocal = GuiEnvironment.GetMarketCloseLocalTime();
var isMarketOpen = now > marketOpenLocal && now < marketCloseLocal;
var result = isMarketOpen || (!isMarketOpen && limitAlert.AfterHours);
return result;
}
public void AddLimitAlert(LimitAlert limitAlert, bool bringToFront = false)
{
// Enable"real time" updates in limit alerts.
GuiEnvironment.QuoteFeedManager.AddQuoteFeed(limitAlert.Symbol);
try
{
// Make a copy of the _limitAlerts to avert "Collection was modified enumeration operation may not execute" exceptions.
// _limitAlerts is being modified
List limitAlertList = _limitAlerts.ToList();
bool matched = limitAlertList.Where(x => x.Id == limitAlert.Id).Count() > 0;
if (matched)
{
LimitAlert destination = limitAlertList.Where(x => x.Id == limitAlert.Id).First();
int index = _limitAlerts.IndexOf(destination);
CopyRealTimeData(destination, limitAlert);
_limitAlerts[index] = limitAlert;
if (_limitAlertToRowData.ContainsKey(limitAlert))
_limitAlertToRowData[limitAlert].Data = limitAlert.ToRowData().Data;
else
_limitAlertToRowData.Add(limitAlert, limitAlert.ToRowData());
}
else
{
if (_limitAlerts.Count <= GuiEnvironment.MaxLimitAlerts)
_limitAlerts.Add(limitAlert);
else
System.Diagnostics.Debug.WriteLine("Skipped adding a price alert due to max price alert reached.");
}
limitAlertList.Clear();
}
catch (Exception e)
{
string debugView = e.ToString();
}
bool valid = IsAlertValidAfterHours(limitAlert);
if (bringToFront && LimitAlertMatchesFilter(limitAlert) && valid)
{
try
{
Parent.BringToFront();
// Perfrom actions
LimitAlertsForm parentForm = GetParent();
if (null != parentForm)
{
List actionSymbolList = new List();
actionSymbolList.Add(parentForm.Actions.GetTextToSpeak(GetAlertTemplate(), GetSubstitutionRules(limitAlert)));
// Turn off ShowWindow in the action method since it is handled above.
// Also exception occurs in the actions method when ShowWindow is set to true.
parentForm.Actions.ShowWindow = false;
parentForm.Actions.Perform(actionSymbolList);
}
// Sort before highlighting limit alert
this.BeginInvokeIfRequired(delegate ()
{
try
{
RowDataHelper.DoSorting(dataGridView1, _rowDatas, _sortByColumn, _sortType);
RowDataHelper.FixCellHeaders(dataGridView1, _columns, _sortByColumn);
HighlightLimitAlert(limitAlert);
}
catch (Exception e)
{
string debugView = e.ToString();
}
});
}
catch (Exception exception)
{
string debugView = exception.ToString();
}
}
}
///
/// Returns the substitution rules for the speech alert template for this window type
///
///
/// RowData object that contains the row information
///
///
private Dictionary GetSubstitutionRules(LimitAlert alert)
{
var rules = new Dictionary();
rules.Add("SYMBOL", alert.Symbol);
var direction = alert.IsLong ? "below" : "above";
var description = $"Price {alert.Price:0.00} has been reach from {direction}";
rules.Add("DESCRIPTION", description);
var parentName = GetParent()?.Text;
if (parentName != null)
rules.Add("WINDOW_NAME", parentName);
rules.Add("PRICE", alert.Price.ToString());
//pending review to detrmine what field to use as DESCRIPTION
return rules;
}
///
/// Returns the speech alerts template for this window
///
///
private string GetAlertTemplate()
{
return !string.IsNullOrEmpty(GuiEnvironment.PriceAlertAlertTemplate) ? GuiEnvironment.PriceAlertAlertTemplate : GuiEnvironment.DefaultAlertTemplate;
}
private void HighlightLimitAlert(LimitAlert limitAlert)
{
if (_limitAlertToRowData.ContainsKey(limitAlert))
{
RowHighlighter rowHighlighter = new RowHighlighter(dataGridView1, _limitAlertToRowData[limitAlert], Color.Yellow, 20000, 1000);
rowHighlighter.Start();
}
}
/*
var matchingAlerts = _limitAlerts.Where(x => x.Id == limitAlert.Id);
if (matchingAlerts.Count() > 0)
{
LimitAlert existingLimitAlert = matchingAlerts.First();
int limitIndex = _limitAlerts.IndexOf(limitAlert);
if (limitIndex != -1)
_limitAlerts[limitIndex] = limitAlert;
if (_limitAlertToRowData.ContainsKey(existingLimitAlert))
{
RowData rowData = _limitAlertToRowData[existingLimitAlert];
CopyRealTimeData(existingLimitAlert, limitAlert);
this.InvokeIfRequired(delegate()
{
string previousStatus = rowData.GetAsString("Status", "");
rowData.Data = limitAlert.ToRowData().Data;
int index = _rowDatas.IndexOf(rowData);
if (index != -1)
{
if (LimitAlertMatchesFilter(limitAlert))
{
dataGridView1.InvalidateRow(index);
RowDataHelper.DoSorting(dataGridView1, _rowDatas, _sortByColumn, _sortType);
if (previousStatus != "TRIGGERED" && limitAlert.Status == "TRIGGERED")
{
RowHighlighter rowHighlighter = new RowHighlighter(dataGridView1, rowData, Color.Yellow, 20000, 250);
rowHighlighter.Start();
}
}
else
{
if (_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Remove(limitAlert);
_rowDatas.Remove(rowData);
}
}
else if (LimitAlertMatchesFilter(limitAlert))
{
if (!_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Add(limitAlert);
RowDataHelper.AddRowData(_rowDatas, rowData, _localSortEnabled, _sortByColumn, _sortType);
}
LimitAlertsForm parent = GetParent();
if (bringToFront && null != parent && !parent.Disposing && LimitAlertMatchesFilter(limitAlert))
parent.BringToFront();
});
}
}
else
{
_limitAlerts.Add(limitAlert);
RowData rowData = limitAlert.ToRowData();
if (!_limitAlertToRowData.ContainsKey(limitAlert))
_limitAlertToRowData.Add(limitAlert, rowData);
if (LimitAlertMatchesFilter(limitAlert))
{
this.InvokeIfRequired(delegate()
{
RowDataHelper.AddRowData(_rowDatas, rowData, _localSortEnabled, _sortByColumn, _sortType);
RefreshData(limitAlert.Symbol);
LimitAlertsForm parent = GetParent();
if (bringToFront && null != parent && !parent.Disposing)
parent.BringToFront();
});
}
else if (_rowDatas.Contains(rowData))
{
this.InvokeIfRequired(delegate()
{
_rowDatas.Remove(rowData);
});
if (_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Remove(limitAlert);
}
}
if (bringToFront && LimitAlertMatchesFilter(limitAlert))
{
List symbols = new List();
symbols.Add(limitAlert.Symbol);
LimitAlertsForm parentForm = GetParent();
if (null != parentForm)
parentForm.Actions.Perform(symbols);
}
}
*/
private void CopyRealTimeData(LimitAlert source, LimitAlert destination)
{
destination.RelativeVolume = source.RelativeVolume;
destination.CurrentPrice = source.CurrentPrice;
destination.CompanyName = source.CompanyName;
destination.ChangeFromTheClose = source.ChangeFromTheClose;
destination.ChangeFromTheClosePercent = source.ChangeFromTheClosePercent;
destination.Volatility = source.Volatility;
destination.TodayVolume = source.TodayVolume;
}
private void InstallColumns()
{
RowDataHelper.SetGridDefaults(dataGridView1);
dataGridView1.MultiSelect = true;
_columnInfosMap.Clear();
foreach (ColumnInfo columnInfo in _columns)
{
columnInfo.UseEmptyColor = false;
DataGridViewColumn column = DataCell.GetColumn(columnInfo, _connectionMaster, this, null, false, this.CreateGraphics(), Font);
RowDataHelper.SetHeaderCellDefaults(column.HeaderCell);
if (columnInfo.InternalCode == "Strategy") //"Strategy" is the internal code of the strategy Name column
{
column.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
}
else
{
column.DefaultCellStyle.WrapMode = DataGridViewTriState.False;
}
column.Visible = false;
_dataGridViewColumns.Add(columnInfo, column);
_dataGridViewColumnsNames.Add(columnInfo, column);
dataGridView1.Columns.Add(column);
_columnInfosMap.Add(columnInfo, column);
}
/* ColumnInfo currentPriceColumnInfo = new ColumnInfo();
currentPriceColumnInfo.Format = "2";
currentPriceColumnInfo.Description = "Current Price";
currentPriceColumnInfo.InternalCode = "CurrentPrice";
currentPriceColumnInfo.WireName = "CurrentPrice";
currentPriceColumnInfo.TextHeader = true;
currentPriceColumnInfo.SizeHint = "XXXXX.XX";
DataGridViewColumn currentPriceColumn = DataCell.GetColumn(currentPriceColumnInfo, _connectionMaster, this, null, false, this.CreateGraphics(), Font);
RowDataHelper.SetHeaderCellDefaults(currentPriceColumn.HeaderCell);
_dataGridViewColumns.Add(currentPriceColumnInfo, currentPriceColumn);
_dataGridViewColumnsNames.Add(currentPriceColumnInfo.Description, currentPriceColumn);
dataGridView1.Columns.Add(currentPriceColumn);
_columnInfosMap.Add(currentPriceColumnInfo, currentPriceColumn);
ColumnInfo companyNameColumnInfo = new ColumnInfo();
companyNameColumnInfo.Format = "";
companyNameColumnInfo.Description = "Company Name";
companyNameColumnInfo.InternalCode = "CompanyName";
companyNameColumnInfo.WireName = "CompanyName";
companyNameColumnInfo.TextHeader = true;
companyNameColumnInfo.SizeHint = "XXXXXXXXXXXXXXXXXXXX";
DataGridViewColumn companyNameColumn = DataCell.GetColumn(companyNameColumnInfo, _connectionMaster, this, null, false, this.CreateGraphics(), Font);
RowDataHelper.SetHeaderCellDefaults(companyNameColumn.HeaderCell);
_dataGridViewColumns.Add(companyNameColumnInfo, companyNameColumn);
_dataGridViewColumnsNames.Add(companyNameColumnInfo.Description, companyNameColumn);
dataGridView1.Columns.Add(companyNameColumn);
_columnInfosMap.Add(companyNameColumnInfo, companyNameColumn);
*/
}
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
SetMenuItemStatus();
}
private void SetMenuItemStatus()
{
this.BeginInvokeIfRequired(delegate ()
{
HashSet selectedRows = GetSelectedRows();
_toolStripMenuItemDeleteAlerts.Enabled = _toolStripMenuItemSaveAlerts.Enabled = _toolStripMenuItemStockTwitsShare.Enabled = selectedRows.Count > 0;
_toolStripMenuItemEditAlert.Enabled = selectedRows.Count == 1;
if (selectedRows.Count > 1)
{
_toolStripMenuItemDeleteAlerts.Text = "Delete " + selectedRows.Count + " Selected Price Alerts...";
_toolStripMenuItemSaveAlerts.Text = "Share " + selectedRows.Count + " Selected Price Alerts...";
_toolStripMenuItemStockTwitsShare.Enabled = false;
}
else if (selectedRows.Count == 1)
{
RowData selectedRowData = dataGridView1.SelectedCells[0].OwningRow.DataBoundItem as RowData;
if (null != selectedRowData)
{
LimitAlert limitAlert = selectedRowData.GetAsObject("object") as LimitAlert;
if (null != limitAlert)
{
_toolStripMenuItemDeleteAlerts.Text = "Delete Price Alert for " + limitAlert.Symbol + " at " + limitAlert.Price + "...";
_toolStripMenuItemSaveAlerts.Text = "Share Price Alert for " + limitAlert.Symbol + " at " + limitAlert.Price + "...";
}
}
}
else
{
_toolStripMenuItemDeleteAlerts.Text = "Delete Price Alerts...";
_toolStripMenuItemSaveAlerts.Text = "Share Price Alerts...";
}
LimitAlertsForm parentForm = GetParent();
if (null != parentForm)
{
_toolStripMenuItemActions.Enabled = true;
_toolStripMenuItemActions.Checked = parentForm.Actions.InUse();
_toolStripMenuItemShowChartDaily.Checked = ShowChartDaily;
_toolStripMenuItemShowChartIntraday.Checked = ShowChartIntraday;
}
else
_toolStripMenuItemActions.Enabled = _toolStripMenuItemActions.Checked = false;
});
}
private LimitAlertsForm GetParent()
{
LimitAlertsForm parentForm = null;
if (null != Parent && null != Parent.Parent && Parent.Parent as LimitAlertsForm != null)
parentForm = Parent.Parent as LimitAlertsForm;
return parentForm;
}
internal void RemoveLimitAlert(LimitAlert limitAlert)
{
GuiEnvironment.LogMessage("[RemoveLimitAlert] Removing alert: " + limitAlert.ToFriendlyString());
if (_limitAlerts.Contains(limitAlert))
_limitAlerts.Remove(limitAlert);
RemoveQuoteFeedIfNecessary(limitAlert.Symbol);
}
private void RemoveQuoteFeedIfNecessary(string symbol)
{
// TODO currently we use the QuoteFeedManager to get data. Currently QuoteFeedManager has
// no way to unsubscribe.
}
private void SendToExternalLinking(int index)
{
RowData rowData = _rowDatas[index];
if (null != rowData && rowData.Data.ContainsKey("object"))
{
LimitAlert limitAlert = rowData.Data["object"] as LimitAlert;
if (null != limitAlert)
{
string symbol = limitAlert.Symbol;
if (symbol != "")
{
RowData linkRowData = new RowData();
if (limitAlert.Triggered.HasValue)
linkRowData.Data.Add("TIME", ServerFormats.ToTimeT(limitAlert.Triggered.Value));
else
linkRowData.Data.Add("TIME", ServerFormats.ToTimeT(limitAlert.Created));
linkRowData.Data.Add("SYMBOL", symbol);
linkRowData.Data.Add("ENTRY_PRICE", limitAlert.Price);
if (limitAlert.InvalidPrice.HasValue)
linkRowData.Data.Add("STOP_PRICE", limitAlert.InvalidPrice);
if (symbol != "")
{
RecordExternalLinkUseCase(linkRowData);
// add symbol linking channel - RVH20210927
GuiEnvironment.sendSymbolToExternalConnector(symbol, "", "", null, linkRowData, linkChannel: _linkChannel, dockWindowID: GuiEnvironment.GetDockWindowID(this.ParentForm));
//GuiEnvironment.sendSymbolToExternalConnector(symbol, "", "", null, linkRowData);
}
}
}
}
}
///
/// Set the symbol link channel
///
/// The link channel
public void SetLinkChannel(string linkChannel)
{
_linkChannel = linkChannel;
foreach (ToolStripMenuItem toolStripMenuItem in _toolStripMenuItemSymbolLinking.DropDownItems)
{
if (toolStripMenuItem.Text == _linkChannel)
toolStripMenuItem.Checked = true;
else
toolStripMenuItem.Checked = false;
}
// change window icon
TableLayoutPanel tableLayoutPanel = this.Parent as TableLayoutPanel;
if (tableLayoutPanel != null)
{
LimitAlertsForm limitAlertsForm = tableLayoutPanel.Parent as LimitAlertsForm;
if (limitAlertsForm != null)
limitAlertsForm.SetLinkChannel(linkChannel);
}
}
///
/// Get the symbol link channel
///
///
public string GetLinkChannel()
{
return _linkChannel;
}
private void RecordExternalLinkUseCase(RowData rowData)
{
GuiEnvironment.RecordExternalLinkingUseCase(rowData, "LA", _connectionMaster.SendManager);
}
void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == -1)
{
Column column = (Column)dataGridView1.Columns[e.ColumnIndex];
if (null != column && null != column.ColumnInfo)
{
GuiEnvironment.RecordUseCase("LA.Grid.Sort." + column.ColumnInfo.InternalCode, _connectionMaster.SendManager);
// Set sortType to descending by default when we pick a new column to sort.
if ((_sortByColumn == null) || (_sortByColumn != column.ColumnInfo))
_localSortEnabled = false;
_sortByColumn = column.ColumnInfo;
//_importSortBy = _sortByColumn.InternalCode;
if (!_localSortEnabled)
_sortType = SortType.Descending;
else
{
if (_sortType == SortType.Ascending)
_sortType = SortType.Descending;
else
_sortType = SortType.Ascending;
}
_localSortEnabled = true;
RowDataHelper.DoSorting(dataGridView1, _rowDatas, _sortByColumn, _sortType);
RowDataHelper.FixCellHeaders(dataGridView1, _columns, _sortByColumn);
}
}
else if (!GuiEnvironment.IntegrationSupportSingleClick)
SendToExternalLinking(e.RowIndex);
}
private ColumnInfo _sortByColumn;
public ColumnInfo getSortByColumn()
{
return _sortByColumn;
}
private string _importSortBy;
public string ImportSortBy
{
get { return _importSortBy; }
set { _importSortBy = value; }
}
public ColumnInfo SortByColumn
{
get { return _sortByColumn; }
set { _sortByColumn = value; }
}
private bool _localSortEnabled = false;
public bool LocalSortEnabled
{
get { return _localSortEnabled; }
set { _localSortEnabled = value; }
}
private SortType _sortType = SortType.Descending;
public SortType LocalSortType
{
get { return _sortType; }
set { _sortType = value; }
}
public List getColumnInfoList()
{
return _columns;
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex != -1 && GuiEnvironment.IntegrationSupportSingleClick)
SendToExternalLinking(e.RowIndex);
}
private bool _pinned = false;
public bool Pinned
{
get { return _pinned; }
set
{
_pinned = value;
_toolStripMenuItemPinned.Checked = _pinned;
}
}
private List _selectedStatuses = new List();
public List SelectedStatuses
{
get { return _selectedStatuses; }
set { _selectedStatuses = value; }
}
///
/// After this is run the _filteredLimitAlerts list is populated with limit alerts that satisfy the current filter setting.
///
private void FilterLimitAlerts()
{
int added = 0;
foreach (LimitAlert limitAlert in _limitAlerts.ToList())
{
if (LimitAlertMatchesFilter(limitAlert))
{
int index = _filteredLimitAlerts.IndexOf(limitAlert);
if (index == -1)
{
added++;
_filteredLimitAlerts.Add(limitAlert);
}
else
_filteredLimitAlerts[index] = limitAlert;
}
}
int removed = 0;
foreach (LimitAlert limitAlert in _filteredLimitAlerts.ToList())
{
if (!LimitAlertMatchesFilter(limitAlert))
{
removed++;
_filteredLimitAlerts.Remove(limitAlert);
}
}
//GuiEnvironment.LogMessage("[FilterLimitAlerts] Total satisfying filter: " + _filteredLimitAlerts.Count + ", added=" + added + ", removed=" + removed);
}
///
/// Returns true if the passed limit alert satisfies the current filter setting.
///
/// Limit Alert to test filtering for.
///
public bool LimitAlertMatchesFilter(LimitAlert limitAlert)
{
if (null == limitAlert)
return false;
LimitAlertStatus status = LimitAlertStatus.WORKING;
bool foundStatus = false;
if (Enum.TryParse(limitAlert.Status, out status))
foundStatus = true;
bool statusFilterExcluded = foundStatus && _selectedStatuses.Count > 0 && (!_selectedStatuses.Contains(status));
return !statusFilterExcluded;
}
private bool _dataBindingInProgress = false;
public void DoDataBinding()
{
this.InvokeIfRequired(delegate ()
{
try
{
if (!_dataBindingInProgress)
{
_refreshTimer.Stop();
_dataBindingInProgress = true;
FilterLimitAlerts();
SuspendLayout();
_rowDatas.Clear();
_limitAlertToRowData.Clear();
_limitAlerts.ListChanged -= _limitAlerts_ListChanged;
_limitAlerts.BeforeRemove -= _limitAlerts_BeforeRemove;
foreach (LimitAlert limitAlert in _limitAlerts.ToList())
{
RowData rowData = limitAlert.ToRowData();
if (_filteredLimitAlerts.Contains(limitAlert))
_rowDatas.Add(rowData);
if (_limitAlertToRowData.ContainsKey(limitAlert))
_limitAlertToRowData[limitAlert] = rowData;
else
_limitAlertToRowData.Add(limitAlert, rowData);
}
RowDataHelper.DoSorting(dataGridView1, _rowDatas, _sortByColumn, _sortType);
dataGridView1.DataSource = _rowDatas;
_limitAlerts.ListChanged += _limitAlerts_ListChanged;
_limitAlerts.BeforeRemove += _limitAlerts_BeforeRemove;
dataGridView1.ClearSelection();
SetSelectedRow();
if (GlobalDataSettings.GetDataGridColumnSetting(FORM_TYPE, "Symbol").Format == "symbolplus")
{
// Symbol Plus format is specified. So set the symbol plus column format.
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, _symbolPlusLayout);
DataGridViewHelper.SetRowHeight(dataGridView1, _symbolPlusLayout);
}
ResumeLayout();
_dataBindingInProgress = false;
_refreshTimer.Start();
}
}
catch (Exception e)
{
string debugView = e.StackTrace;
_dataBindingInProgress = false;
if (_refreshTimer.Enabled == false)
_refreshTimer.Start();
}
});
}
void _limitAlerts_BeforeRemove(object sender, ListChangedEventArgs e)
{
try
{
LimitAlert limitAlert = _limitAlerts[e.NewIndex];
if (null != limitAlert)
{
GuiEnvironment.LogMessage("[LimitAlerts-BeforeRemove] removing " + limitAlert.ToFriendlyString());
if (_limitAlerts.Count > 0)
{
if (_limitAlertToRowData.ContainsKey(limitAlert))
{
RowData rowData = _limitAlertToRowData[limitAlert];
_limitAlertToRowData.Remove(limitAlert);
if (_rowDatas.Contains(rowData))
{
this.InvokeIfRequired(delegate ()
{
//Remove the link between the grid and the data before removing the row from the datasource
//to avoid the issue https://trade-ideas.atlassian.net/browse/PRO-554
//See https://stackoverflow.com/questions/1630200/net-datagridview-index-0-does-not-have-a-value for more details.
dataGridView1.DataSource = null;
_rowDatas.Remove(rowData);
dataGridView1.DataSource = _rowDatas;
});
}
}
}
if (_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Remove(limitAlert);
}
else
{
GuiEnvironment.LogMessage("[LimitAlerts-BeforeRemove] limit alert is null");
}
}
catch (Exception exc)
{
string debugView = exc.StackTrace;
}
}
void _limitAlerts_ListChanged(object sender, ListChangedEventArgs e)
{
try
{
if (e.ListChangedType == ListChangedType.ItemAdded && _limitAlerts.Count > 0)
{
LimitAlert limitAlert = _limitAlerts[e.NewIndex];
//GuiEnvironment.LogMessage("[LimitAlerts-ListChanged-ItemAdded] Adding " + limitAlert.ToFriendlyString());
if (LimitAlertMatchesFilter(limitAlert))
{
RowData rowData = limitAlert.ToRowData();
if (!_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Add(limitAlert);
if (_limitAlertToRowData.ContainsKey(limitAlert))
_limitAlertToRowData[limitAlert].Data = rowData.Data;
else
{
GuiEnvironment.LogMessage("[ListChanged] Adding limit alert for " + limitAlert.Symbol + ", id: " + limitAlert.Id);
_limitAlertToRowData.Add(limitAlert, rowData);
this.InvokeIfRequired(delegate ()
{
RowDataHelper.AddRowData(_rowDatas, rowData, _localSortEnabled, _sortByColumn, _sortType);
});
}
}
if (GlobalDataSettings.GetDataGridColumnSetting(FORM_TYPE, "Symbol").Format == "symbolplus")
{
// Symbol Plus format is specified. So reset the symbol plus column format.
DataGridViewHelper.SetSymbolPlusLayout(dataGridView1, _symbolPlusLayout);
}
}
else if (e.ListChangedType == ListChangedType.ItemChanged && _limitAlerts.Count > 0 && e.NewIndex < _limitAlerts.Count && e.NewIndex >= 0)
{
LimitAlert limitAlert = _limitAlerts[e.NewIndex];
//System.Diagnostics.Debug.WriteLine("[LimitAlerts-ListChanged-ItemChanged] Changing " + limitAlert.ToFriendlyString());
//SendMessage("LimitAlert item changed: " + limitAlert.Symbol + ", limitAlertrowdatas: " + _limitAlertToRowData.Keys.Count + ", containsthislimitAlert: " + _limitAlertToRowData.ContainsKey(limitAlert));
if (_limitAlertToRowData.ContainsKey(limitAlert))
{
RowData rowData = _limitAlertToRowData[limitAlert];
int index = _rowDatas.IndexOf(rowData);
if (index != -1 && dataGridView1.Rows.Count > index)
{
_rowDatas[index].Data = limitAlert.ToRowData().Data;
dataGridView1.InvalidateRow(index);
}
if (LimitAlertMatchesFilter(limitAlert))
{
if (!_filteredLimitAlerts.Contains(limitAlert))
{
_filteredLimitAlerts.Add(limitAlert);
this.InvokeIfRequired(delegate ()
{
GuiEnvironment.LogMessage("[ListChanged] ItemChanged " + rowData.ToString());
RowDataHelper.AddRowData(_rowDatas, rowData, _localSortEnabled, _sortByColumn, _sortType);
});
}
}
else
{
if (_rowDatas.Contains(rowData))
{
this.InvokeIfRequired(delegate ()
{
_rowDatas.Remove(rowData);
});
}
if (_filteredLimitAlerts.Contains(limitAlert))
_filteredLimitAlerts.Remove(limitAlert);
}
}
}
}
catch (Exception exc)
{
string debugView = exc.StackTrace;
}
}
private bool _showChartDaily = false;
public bool ShowChartDaily
{
get { return _showChartDaily; }
set
{
_showChartDaily = value;
_toolStripMenuItemShowChartDaily.Checked = _showChartDaily;
}
}
private bool _showChartIntraday = false;
public bool ShowChartIntraday
{
get { return _showChartIntraday; }
set
{
_showChartIntraday = value;
_toolStripMenuItemShowChartIntraday.Checked = _showChartIntraday;
}
}
private bool _showFilter = false;
public bool ShowFilter
{
get { return _showFilter; }
set
{
_showFilter = value;
_toolStripMenuItemShowFilter.Checked = _showFilter;
}
}
internal void chooseRowSelect()
{
if (GuiEnvironment.HighlightGridRow)
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
else
dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
}
///
/// Sums up the TotalSinceTriggered column from all filtered alerts
///
///
internal double GetTotalSinceTriggered()
{
FilterLimitAlerts();
double toReturn = 0;
foreach (LimitAlert limitAlert in _filteredLimitAlerts.ToList())
{
if (null != limitAlert)
{
if (limitAlert.DollarsSinceTriggered.HasValue)
toReturn += limitAlert.DollarsSinceTriggered.Value;
}
}
return toReturn;
}
public bool MergingAlerts = false;
///
/// MergeAlerts will merge existing price alerts in this window with the master list of price alerts in GuiEnvironment.LimitAlerts.
/// Normally this is done on a reconnection after a disconnect or when switching connections.
///
internal void MergeAlerts()
{
this.BeginInvokeIfRequired(delegate ()
{
try
{
MergingAlerts = true;
GuiEnvironment.LogMessage("[MergeAlerts] Merging alerts. _limitAlerts: " + _limitAlerts.Count + ", _filtered: " + _filteredLimitAlerts.Count + ", _rowDatas: " + _rowDatas.Count);
Dictionary existingAlertIds = new Dictionary();
foreach (LimitAlert limitAlert in GuiEnvironment.LimitAlerts.ToList())
{
AddLimitAlert(limitAlert, false);
existingAlertIds.Add(limitAlert.Id, limitAlert.Id);
}
foreach (LimitAlert limitAlert in _limitAlerts.ToList())
{
if (!existingAlertIds.ContainsKey(limitAlert.Id))
{
this.InvokeIfRequired(delegate ()
{
_limitAlerts.Remove(limitAlert);
});
}
}
Dictionary existingRowDataIds = new Dictionary();
foreach (RowData rowData in _rowDatas.ToList())
{
string id = rowData.GetAsString("Id", "");
bool containsIdAlready = existingRowDataIds.ContainsKey(id);
if (!existingAlertIds.ContainsKey(id) || containsIdAlready)
{
GuiEnvironment.LogMessage("[MergeAlerts] removing rowData since id: " + id + " not found in existing limit alerts");
this.InvokeIfRequired(delegate ()
{
_rowDatas.Remove(rowData);
});
}
else
existingRowDataIds.Add(id, id);
}
GuiEnvironment.LogMessage("[MergeAlerts] Merging alerts complete. _limitAlerts: " + _limitAlerts.Count + ", _filtered: " + _filteredLimitAlerts.Count + ", _rowDatas: " + _rowDatas.Count);
SetSelectedRow();
MergingAlerts = false;
}
catch (Exception e)
{
string debugView = e.StackTrace;
MergingAlerts = false;
}
});
}
}
}