using System; using System.Globalization; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Net; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Xml; using TradeIdeas.XML; using System.Windows.Forms; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Configuration; using TradeIdeas.ServerConnection; using System.Drawing.Drawing2D; using TradeIdeas.MiscSupport; using System.Collections.Specialized; using System.Web; using System.IO; using TradeIdeas.TIProData.Interfaces; // TODO When the user changes symbols, immediately clear everything. // Currently we don't clear the old data until we get new data. // When things are going well, that is sufficient. // When the server is slow, the network is broken, etc, this causes a problem. namespace TradeIdeas.TIProGUI { public partial class SingleStockWindow : Form, ISaveLayout, ISnapToGrid, IDemoMode, ICultureListener, IChildable, IAcceptSymbolLinking, ISupportLimitedMode, ICanConfigure, IContextMenuStrip, TopListRequest.Listener, IFont { private enum Painting { Cylinder, Cone }; private string _config; private IConnectionMaster _connectionMaster; private LayoutManager _layoutManager = LayoutManager.Instance(); private TopListRequest.Token _topList; List _phrases; List _scottTradeSettings; private List _rightSide = new List(); private List _leftSide = new List(); private Color DESCRIPTION_FOREGROUND = Color.FromArgb(104, 104, 104); private static Image _cone = Properties.Resources.RBlueCone; private const float ROW_HEIGHT = 25F; private float _rowHeight = ROW_HEIGHT; private const int CYLINDER_WIDTH = 45; private const int CYLINDER_HEIGHT = 20; private int _cylinderWidth = CYLINDER_WIDTH; private int _cylinderHeight = CYLINDER_HEIGHT; private const int ICON_WIDTH = 40; private const int ICON_HEIGHT = 24; private int _contractedWindow; private int _contractedWindowDefault = 311; private const int THRESHOLD = 52; private int _threshold = THRESHOLD; private const int LABEL_WIDTH = 250; private int _labelWidth = LABEL_WIDTH; private const string FORM_TYPE = "SINGLE_STOCK_WINDOW"; private const string _defaultFileName = "DEFAULT_SINGLE_STOCK.WTI"; private string _fileNameSaved; private string _shortWindowName; private ToolTip _resultToolTip = new ToolTip(); //"one tool tip can provide tips for thousands of controls" http://stackoverflow.com/questions/7238525/how-can-i-change-the-text-of-an-existing-tooltip-control-in-a-picturebox-in-my private bool _inIconMode = false; private bool _needToRedrawFields = false; // I.e. we just reconfigured. private bool _settingNewSymbol = true; private bool _headerLabelsVisible = true; private volatile bool _imageUpdatePending = false; private volatile bool _profileUpdatePending = false; private delegate void DoUpdate(); private ConfigurationWindowManager _configurationWindowManager = new ConfigurationWindowManager(); private ImageCacheManager _imageCacheManager; private CompanyProfileManager _companyProfileManager; ISendManager _sendManager; GeneralInfo _generalInfo; private int _sideRightLeft = 0; private int _displayBeginPopulate = 0; private bool _validDataReceived = true; private string _currentSymbol = ""; private bool _outsideMarketHours; private string _currentWindowName = ""; private string _timeString = ""; private Boolean _inBlankMode = true; //special mode for freshly instantiated Single Stock Windows under ScottTrade. private Boolean _savedWindow = false; //used in conjunction with _inBlankMode static XmlNode _defaultSingleStockSettings = null; private Boolean _initCboSymbol = true; private Boolean _initCboSymbolProfile = true; // new variable to set that dock panel is being used - RVH20210329 private bool _dockPanelMode = true; /*It appeared as though the very first row would wrap-which meant that upon resizing the window to a narrower width caused not only the text to wrap, but the cylinder to become extremely tall and grotesque-as it would equal the new row height. None of the other rows exhibited this behavior. Attempts to change the the row to absolute height in the visual studio designer did not help. So, to rememdy the wrapping issue, a new row was added in the designer and set to autosize. this row served as the dummy, while data(components) would then be added to the next row afterwards. Thus resizing the form gave no wrapping effects to the data, as none of them are in the "dummy" row.*/ public static readonly WindowIconCache WindowIconCache = new WindowIconCache("SINGLE_SYMBOL_WINDOW"); /// /// /// /// /// /// /// /// The initial value for the stock symbol to look up. /// If you leave this as null we try to guess based on the config string. /// /// /// Should the Outside Market Hours flag be set or cleared? /// If you leave this as null we try to guess based on the config string. /// public SingleStockWindow(IConnectionMaster connectionMaster, string config, Boolean newWindow, string initialSymbol = null, bool? initialOmh = null) { if ((null == initialSymbol) || (null == initialOmh)) { // I really, really hate doing this type of parsing on the client side. // When the newest client saves the window we explicitly store SYMBOL and OMH in the XML. // We only have to do this parsing if the layout was saved by an older client. // The older client would send config to the server to get it parsed. That made the // code slower and more complicated. NameValueCollection parsed = HttpUtility.ParseQueryString(config); if (null == initialSymbol) initialSymbol = parsed.Get("SingleSymbol"); if (null == initialSymbol) { string symbolListSpec = parsed.Get("SL"); if ((null != symbolListSpec) && ("" != symbolListSpec) && ('x' == symbolListSpec[0])) initialSymbol = symbolListSpec.Substring(1); } if (null == initialOmh) initialOmh = parsed.Get("omh") == "1"; } _outsideMarketHours = (bool)initialOmh; _currentSymbol = initialSymbol ?? ""; _limitedMode = GuiEnvironment.LimitedMode; _connectionMaster = connectionMaster; _config = config; _sendManager = _connectionMaster.SendManager; _generalInfo = GuiEnvironment.GetGeneralInfo(_sendManager); InitializeComponent(); selectTheFont(); SetConfiguration(_config); cboSymbol.Text = _currentSymbol; // Insert new symbol entries at the top of the list. if (!cboSymbol.Items.Contains(_currentSymbol)) cboSymbol.Items.Insert(0, _currentSymbol); cboSymbolProfile.Text = _currentSymbol; if (!cboSymbolProfile.Items.Contains(_currentSymbol)) cboSymbolProfile.Items.Insert(0, _currentSymbol); outsideMarketHoursToolStripMenuItem.Checked = _outsideMarketHours; saveToCloudToolStripMenuItem.Image = SaveToCloud.WindowIconCache.MenuImage; _phrases = GuiEnvironment.XmlConfig.Node("SINGLE_SYMBOL_WINDOW").Node("PHRASES"); _scottTradeSettings = GuiEnvironment.XmlConfig.Node("SINGLE_SYMBOL_WINDOW").Node("SETTINGS"); _inBlankMode = _scottTradeSettings.Node("BLANK_MODE").Property("VALUE", true); populateStrings(); WindowIconCache.SetIcon(this); _companyProfileManager = connectionMaster.CompanyProfileManager; _imageCacheManager = connectionMaster.ImageCacheManager; _imageCacheManager.CachedImageAvailable += new CachedImageAvailable(_imageCacheManager_CachedImageAvailable); _companyProfileManager.ProfileReceived += new CompanyProfileReceived(_companyProfileManager_ProfileReceived); Disposed += OnDisposed; if (newWindow) { this.StartPosition = FormStartPosition.CenterParent; //for "brand new window". So we won't have new ones stacked on top of each other at 0,0 } else { this.StartPosition = FormStartPosition.Manual; //Added to correct location issue when snap to window is disabled. } if (newWindow && _scottTradeSettings.Node("BLANK_MODE").Property("VALUE", true)) { //When we're in ScottTrade Elite, the only time that "new window" is true, is when // we're using the "Send Symbol To Single Stock Window" in a context menu (alert, toplistst, multistrat) _inBlankMode = false; } SetSnapToGrid(GuiEnvironment.SnapToGrid); UpdateSymbolLinkingCheckboxStatus(); tabProfile.ContextMenuStrip = contextMenuStrip1; AddExtraMenuItems(GuiEnvironment.GetExtraMenuItems().Where(x => x.TIFormType == TIFormType.All || x.TIFormType == TIFormType.SingleStock).ToList(), contextMenuStrip1.Items); } static public void OpenNewSingleStockWindow(string initialSymbol, Form parentForm) { List _phs; _phs = GuiEnvironment.XmlConfig.Node("SINGLE_SYMBOL_WINDOW").Node("PHRASES"); string singleStockFileName = "DEFAULT_SINGLE_STOCK.WTI"; LayoutManager layoutManager = LayoutManager.Instance(); string programDirFileName = layoutManager.Directory + "\\" + singleStockFileName; string readOnlyDir = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); string sharedDirFileName = readOnlyDir + "\\" + GuiEnvironment.AppNameInternal + "\\" + singleStockFileName; string singleStockConfig = _phs.Node("NEW_SINGLE_STOCK_WINDOW_DEFAULT").Property("TEXT"); XmlNode singleStockDefinition = null; if (System.IO.File.Exists(programDirFileName)) //check if it's there in user's home dir singleStockDefinition = layoutManager.GetXmlFromFile(programDirFileName); else if (System.IO.File.Exists(sharedDirFileName)) //check for default in shared folder... singleStockDefinition = layoutManager.GetXmlFromFile(sharedDirFileName); SingleStockWindow singleStockWindow; if (null != singleStockDefinition) { SingleStockWindow.SetDefaultSingleStockSettings(singleStockDefinition); singleStockConfig = singleStockDefinition.Node("WINDOW").Property("CONFIG", ""); if (initialSymbol == null) { initialSymbol = singleStockDefinition.Node("WINDOW").Property("SYMBOL", null); } singleStockWindow = new SingleStockWindow(GuiEnvironment.FindConnectionMaster(""), singleStockConfig, true, initialSymbol); singleStockWindow.Restore(_defaultSingleStockSettings, false, false); } else { singleStockWindow = new SingleStockWindow(GuiEnvironment.FindConnectionMaster(""), singleStockConfig, true, initialSymbol); if (initialSymbol != null) { singleStockWindow.setNewSymbol(initialSymbol); } else { singleStockWindow.setNewSymbol("SPY"); } singleStockWindow.Show(); } GuiEnvironment.SetWindowOpeningPosition(singleStockWindow, parentForm); } static public void SetDefaultSingleStockSettings(XmlNode description) { _defaultSingleStockSettings = XmlHelper.Node(description, "WINDOW"); } 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.ClickedCode(menuItem, this); } public void updateWindow() { populateStrings(); } private void populateStrings() { configureToolStripMenuItem.Text = _phrases.Node("CONFIGURE").PropertyForCulture("TEXT", "***"); duplicateToolStripMenuItem.Text = _phrases.Node("DUPLICATE").PropertyForCulture("TEXT", "***"); smallBordersToolStripMenuItem.Text = _phrases.Node("SMALL_BORDERS").PropertyForCulture("TEXT", "***"); smallBordersToolStripMenuItem.Text = _phrases.Node("SAVE_TO_CLOUD").PropertyForCulture("TEXT", "***"); saveAsDefaultToolStripMenuItem.Text = _phrases.Node("SAVE_AS_DEFAULT").PropertyForCulture("TEXT", "***"); saveAsToolStripMenuItem.Text = _phrases.Node("SAVE_AS").PropertyForCulture("TEXT", "***"); outsideMarketHoursToolStripMenuItem.Text = _phrases.Node("OUTSIDE_HOURS").PropertyForCulture("TEXT", "***"); doSymbolLinkingToolStripMenuItem.Text = _phrases.Node("SYMBOL_LINKING").PropertyForCulture("TEXT", "***"); string windowTitle = _currentWindowName; if (_connectionMaster.LoginManager.IsDemo) { windowTitle += GuiEnvironment.XmlConfig.Node("COMMON_PHRASES").Node("DEMO_DISCLAIMER").PropertyForCulture("TEXT", "***"); saveToCloudToolStripMenuItem.Enabled = false; Text = windowTitle; } else { if (_inBlankMode) { Text = "Single Stock Window"; } else { Text = _currentWindowName; } saveToCloudToolStripMenuItem.Enabled = true; } //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", "***"); } } public void CultureChanged() { populateStrings(); } private void OnDisposed(Object sender, EventArgs e) { _imageCacheManager.CachedImageAvailable -= _imageCacheManager_CachedImageAvailable; _companyProfileManager.ProfileReceived -= _companyProfileManager_ProfileReceived; } void _imageCacheManager_CachedImageAvailable() { if (InvokeRequired) { if (!_imageUpdatePending) { _imageUpdatePending = true; BeginInvoke((MethodInvoker)_imageCacheManager_CachedImageAvailable); } } else { if (IsDisposed) { return; } _imageUpdatePending = false; } } void _companyProfileManager_ProfileReceived(CompanyProfileInfo profile) { if (InvokeRequired) { if (!_profileUpdatePending) { _profileUpdatePending = true; BeginInvoke((MethodInvoker)delegate { _companyProfileManager_ProfileReceived(profile); }); } } else { if (IsDisposed) { return; } _profileUpdatePending = false; if (null != profile.Symbol) //noted that on rare case a null exception pops up. add this line to check for null strategy { if (_currentSymbol.ToUpper().ToString() == profile.Symbol.ToUpper().ToString()) //validate symbol we get with the one which we had sent { if (profile.Summary != "") { if (_settingNewSymbol) { _settingNewSymbol = false; lblSummaryTitle.Visible = true; txtSummary.Text = profile.Summary; pnlLowerSection.Top = txtSummary.Top + txtSummary.Height + 5; } } else { lblSummaryTitle.Visible = false; txtSummary.Text = ""; pnlLowerSection.Top = lblSummaryTitle.Top; } } } } } private void populateDetailPanel(TopListInfo metaData, RowData rowData) { System.Diagnostics.Debug.Assert(null != metaData); System.Diagnostics.Debug.Assert(null != rowData); _sideRightLeft = _displayBeginPopulate; _rightSide.Clear(); _leftSide.Clear(); foreach (ColumnInfo c in metaData.Columns) { if (_sideRightLeft == 0) { _leftSide.Add(c); } if (_sideRightLeft == 1) { _rightSide.Add(c); } if (_sideRightLeft == 0) _sideRightLeft = 1; else if (_sideRightLeft == 1) _sideRightLeft = 0; } processUserNonchangeables(rowData); if (_needToRedrawFields || pnlDetail.Controls.Count == 0) { _resultToolTip.RemoveAll(); foreach (Control c in pnlDetail.Controls) { if (c as CustomPanel != null) { c.Paint -= new PaintEventHandler(pnlResult_Paint); } } pnlDetail.Controls.Clear(); //clears all controls in tablelayoutpanel pnlDetail.RowStyles.Clear(); pnlDetail.RowCount = 0; //clears all rows in the tablelayoutpanel of the details tab. populateDetailTab(rowData); _needToRedrawFields = false; } else { updateTopListData(rowData); } if (_headerLabelsVisible == false) { changeHeaderLabelVisiblity(false); } } private static readonly string[] EXTRA_FIELDS = new string[] { "D_Name", "D_SubSector", "D_SubIndustry", "D_Exch", "D_Sector", "D_Industry", "D_IndGrp", "Price", "FCP", "FCD", "RV", "TV" }; public void SetConfiguration(string config) { _needToRedrawFields = true; _config = config; if (null != _topList) { _topList.Cancel(); _topList = null; } if (_inBlankMode) { cboSymbol.Text = ""; cboSymbolProfile.Text = ""; } else { cboSymbol.Text = _currentSymbol; cboSymbolProfile.Text = _currentSymbol; } if ((null != config) && ("" != config) && (null != _currentSymbol) && ("" != _currentSymbol)) { // If config is missing, we're probably trying to shut this down. If symbol is // missing, but you try send the request anyway, you might get strange results. TopListRequest request = new TopListRequest(); foreach (string internalCode in EXTRA_FIELDS) request.AddExtraColumn(internalCode); request.Collaborate = config; request.OutsideMarketHours = _outsideMarketHours; request.SaveToMru = false; // Use the value set in the collaborate string. I have verified that the server // gets that info and is using it right. Not only do we see the data for this // symbol, but we are in the "fast" queue on the server. Single symbol top list // requests are handled differently for performance reasons. //request.SingleSymbol request.SkipMetaData = false; request.SortFormula = "1"; // Always display the data even if one field is null. request.Streaming = true; // Always display the data even if one field is null, we didn't list the exchanges right, etc. request.WhereFormula = "1"; request.SingleSymbol = _currentSymbol; _topList = request.Send(_connectionMaster.SendManager, this); } } void TopListRequest.Listener.OnDisconnect(TopListRequest.Token token) { this.BeginInvokeIfRequired((MethodInvoker)delegate { if (_topList == token) // Unexpected disconnect. We still want to listen. _topList = _topList.GetRequest().Send(_connectionMaster.SendManager, this); }); } void TopListRequest.Listener.OnMetaData(TopListRequest.Token token) { // Ignore this event. Look for the meta data when we receive the row data. } void TopListRequest.Listener.OnRowData(List rows, DateTime? start, DateTime? end, TopListRequest.Token token) { this.BeginInvokeIfRequired((MethodInvoker)delegate { if (_topList == token) OnRowData(rows, start, end); }); } /// /// Call this in the GUI thread when _topList is pointing to the right request. /// /// From the server. /// From the server. /// From the server. private void OnRowData(List rows, DateTime? start, DateTime? end) { //we'll "display" one row. This row has all of the pertinent data that will be displayed //in the Single Stock Detail tab. TopListInfo metaData = _topList.GetMetaData(); if ((rows.Count == 1) && (null != metaData)) { _topList.GetRequest().LastUpdate = DateTime.Now; _validDataReceived = true; cboSymbol.BackColor = Color.White; cboSymbolProfile.BackColor = Color.White; changeAllLabelVisibility(true); changeHeaderLabelVisiblity(true); RowData data = rows[0]; getTimeString(start, end); populateDetailPanel(_topList.GetMetaData(), data); } else //if someone enters an invalid stock symbol, the rowcount will be zero (no data) { // If the row count is more than 1 it's probably a programmer error. I changed // the code so we'd get here in that case. It's not worth it's own error message // because I don't expect it to happen. The important thing is that if we do get // more rows that expected, we don't just randomly pick the a row and display it. _validDataReceived = false; cboSymbol.BackColor = Color.FromArgb(249, 167, 175); cboSymbolProfile.BackColor = Color.FromArgb(249, 167, 175); _resultToolTip.RemoveAll(); foreach (Control c in pnlDetail.Controls) { if (c as CustomPanel != null) { c.Paint -= new PaintEventHandler(pnlResult_Paint); } } clearPanelsAndLabels(); lblSummaryTitle.Visible = false; changeAllLabelVisibility(false); changeHeaderLabelVisiblity(false); Text = "No data available"; } } private void getTimeString(DateTime? start = null, DateTime? end = null) { StringBuilder result = new StringBuilder(); if ((null != start) || (null != end)) { //We want to grab just the end value. If it's null, we'll take the start value if (null != end) { result.Append(((DateTime)end).ToString(GuiEnvironment.AlertTimeShortFormat)); } else if (null != start) { result.Append(((DateTime)start).ToString(GuiEnvironment.AlertTimeShortFormat)); } DateTime date = end.HasValue ? end.Value : start.Value; if (date < ServerFormats.Today) { try { string dateFormat = GuiEnvironment.XmlConfig.Node("DATE_FORMAT").PropertyForCulture("TEXT", null); if (null != dateFormat) { if (null != end) { lblDateDetail.Text = end.Value.ToString(dateFormat); lblDateProfile.Text = end.Value.ToString(dateFormat); } else if (null != start) { lblDateDetail.Text = start.Value.ToString(dateFormat); lblDateProfile.Text = start.Value.ToString(dateFormat); } } else { lblDateDetail.Text = ""; lblDateProfile.Text = ""; } } catch { // Presumaly a bad value in the file could lead us here. By default print nothing. } } else { lblDateDetail.Text = ""; lblDateProfile.Text = ""; } } _timeString = result.ToString(); } private void clearLabelData() //set to "" when one enters invalid string { lblPriceDetail.Text = lblPriceProfile.Text = lblCompanyNameProfile.Text = lblCompanyNameDetail.Text = ""; lblChangeDollarDetail.Text = lblChangeDollarProfile.Text = lblChangePercentDetail.Text = lblChangePercentProfile.Text = ""; lblRelVolDetail.Text = lblRelVolProfile.Text = lblVolumeDetail.Text = lblVolumeProfile.Text = ""; lblExchange.Text = lblSIndustry.Text = lblSSector.Text = lblIndustry.Text = lblSector.Text = lblIndustryGroup.Text = ""; txtSummary.Text = ""; } private void changeAllLabelVisibility(bool change) { label1.Visible = label2.Visible = label4.Visible = label5.Visible = change; label3.Visible = label7.Visible = label8.Visible = label9.Visible = label10.Visible = label11.Visible = label12.Visible = change; lblPriceDetail.Visible = lblPriceProfile.Visible = lblCompanyNameProfile.Visible = lblCompanyNameDetail.Visible = change; lblChangeDollarDetail.Visible = lblChangeDollarProfile.Visible = lblChangePercentDetail.Visible = lblChangePercentProfile.Visible = change; lblRelVolDetail.Visible = lblRelVolProfile.Visible = lblVolumeDetail.Visible = lblVolumeProfile.Visible = change; lblExchange.Visible = lblSIndustry.Visible = lblSSector.Visible = lblSector.Visible = lblIndustry.Visible = lblIndustryGroup.Visible = change; lblDateDetail.Visible = lblDateProfile.Visible = lblTimeDetail.Visible = lblTimeProfile.Visible = change; } private void processUserNonchangeables(RowData rowData) //Refers to items in that are non configurable from config window (e.g. stuff in the tab's "top section" like change, volume, relative volume...) { if (!_inBlankMode) { if (rowData.GetAsString("c_D_SubIndustry", "") == "") { _currentWindowName = rowData.GetCompanyName(); } else { _currentWindowName = rowData.GetCompanyName() + " - " + rowData.GetAsString("c_D_SubIndustry", ""); } _companyProfileManager.RequestNow(_currentSymbol); lblCompanyNameDetail.Text = lblCompanyNameProfile.Text = rowData.GetCompanyName(); _shortWindowName = rowData.GetCompanyName(); this.Text = _currentWindowName; lblVolumeDetail.Text = lblVolumeProfile.Text = (getDoubleString(rowData, "c_TV", 0) == "***") ? "" : getDoubleString(rowData, "c_TV", 0); lblRelVolDetail.Text = lblRelVolProfile.Text = (getDoubleString(rowData, "c_RV", 2) == "***") ? "" : getDoubleString(rowData, "c_RV", 2); lblPriceDetail.Text = lblPriceProfile.Text = (getDoubleString(rowData, "c_Price", 2) == "***") ? "" : getDoubleString(rowData, "c_Price", 2); lblExchange.Text = _generalInfo.GetExchangeName(rowData.GetExchange()); lblSSector.Text = rowData.GetAsString("c_D_SubSector", ""); lblSIndustry.Text = rowData.GetAsString("c_D_SubIndustry", ""); lblSector.Text = rowData.GetAsString("c_D_Sector", ""); lblIndustryGroup.Text = rowData.GetAsString("c_D_IndGrp", ""); lblIndustry.Text = rowData.GetAsString("c_D_Industry", ""); lblTimeProfile.Text = _timeString; lblTimeDetail.Text = _timeString; //For "top part" of tabs (e.g. price,relative volume, etc) decimal changeDollar = 0; double changePercent = 0; if (rowData.Data.ContainsKey("c_FCP") && rowData.Data.ContainsKey("c_FCD") && ServerFormats.TryParse(rowData.GetAsString("c_FCP"), out changePercent) && Decimal.TryParse(rowData.GetAsString("c_FCD"), NumberStyles.Any | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out changeDollar)) { Color textColor; string textPrefix = ""; if (changeDollar > 0) { textPrefix = "+ "; textColor = Color.Green; } else if (changeDollar < 0) { textColor = Color.Red; } else { textColor = Color.Black; } lblChangeDollarDetail.Text = lblChangeDollarProfile.Text = textPrefix + Math.Round(changeDollar, 2).ToString(); lblChangePercentDetail.ForeColor = lblChangePercentProfile.ForeColor = lblChangeDollarDetail.ForeColor = lblChangeDollarProfile.ForeColor = textColor; lblChangePercentDetail.Text = lblChangePercentProfile.Text = "(" + Math.Round(changePercent, 2).ToString() + "%)"; lblChangePercentDetail.Left = lblChangeDollarDetail.Right + 1; lblChangePercentProfile.Left = lblChangeDollarProfile.Right + 1; } } else { lblSummaryTitle.Visible = true; lblCompanyNameDetail.Text = lblCompanyNameProfile.Text = ""; lblVolumeDetail.Text = lblVolumeProfile.Text = ""; lblRelVolDetail.Text = lblRelVolProfile.Text = ""; lblPriceDetail.Text = lblPriceProfile.Text = ""; lblExchange.Text = ""; lblSSector.Text = ""; lblSIndustry.Text = ""; lblSector.Text = ""; lblIndustryGroup.Text = ""; lblIndustry.Text = ""; lblTimeProfile.Text = ""; lblTimeDetail.Text = ""; txtSummary.Text = ""; lblChangeDollarDetail.Text = lblChangeDollarProfile.Text = ""; lblChangePercentDetail.Text = lblChangePercentProfile.Text = ""; _shortWindowName = ""; } populateStrings(); } /// /// Convert "Price" into "c_Price". /// /// /// A key suitable for looking up a field in a RowData object. private string WireName(string internalCode) { return CommonAlertFields.GetFilterWireName(internalCode); } /// /// /// /// /// A key suitable for looking up a field in a RowData object. private string WireName(ColumnInfo column) { return WireName(column.InternalCode); } private string processUserChangeables(RowData rowData, ColumnInfo c) { string finalString = ""; int value; if (c.Format == "" || c.Format == null) //string { finalString = rowData.GetAsString(WireName(c), "***"); } if (c.Format == "p") { if (c.Units == "%") { finalString = getDoubleString(rowData, WireName(c), 2) + "%"; } else { finalString = "$" + getDoubleString(rowData, WireName(c), 2); } } if (ServerFormats.TryParse(c.Format, out value)) { if (c.Units == "$") { finalString = "$" + getDoubleString(rowData, WireName(c), value); } else if (c.Units == "%") { finalString = getDoubleString(rowData, WireName(c), value) + "%"; } else { finalString = getDoubleString(rowData, WireName(c), value); } } if (finalString.Contains("***")) { return ""; } return finalString; } private void populateDetailTab(RowData rowData) { // TODO - Review for cross-thread exceptions. Happens when adding controls to pnlDetails // when opening a new window while in debug mode with breakpoints. System.Diagnostics.Debug.Assert(!InvokeRequired); //First, determine how many rows that are needed... //since rows were populated in "zig-zag" fashion (left-right-left..etc)-any uneven list counts //will always differ by one. int numberOfRows = 0; if (_leftSide.Count == 0 && _rightSide.Count == 0) { return; } if (_leftSide.Count == _rightSide.Count) { numberOfRows = _leftSide.Count; } else { numberOfRows = Math.Max(_leftSide.Count, _rightSide.Count); } pnlDetail.AutoScroll = false; for (int i = 0; i < numberOfRows; i++) { pnlDetail.RowStyles.Add(new RowStyle(SizeType.Absolute, _rowHeight)); pnlDetail.RowCount++; //this adds the new row to the tablelayoutpanel if (i < _leftSide.Count) { if (_leftSide[i].Graphics == "%R" && !_inBlankMode) { makeGraphics(_leftSide[i], rowData, 2, Painting.Cylinder); } else if (_leftSide[i].Graphics == "RBCone" && !_inBlankMode) { makeGraphics(_leftSide[i], rowData, 2, Painting.Cone); } else { Label label_val = new Label(); label_val.Tag = _leftSide[i]; if (!_inBlankMode) { label_val.Text = processUserChangeables(rowData, _leftSide[i]); } _resultToolTip.SetToolTip(label_val, label_val.Text + checkUnits(_leftSide[i].Units)); pnlDetail.Controls.Add(label_val, 2, pnlDetail.RowCount - 1); label_val.Margin = new Padding(4, 4, 0, 4); label_val.Dock = DockStyle.Right; //"right justifies" item in cell label_val.AutoSize = true; } Label label_desc = new Label(); label_desc.Tag = _leftSide[i].InternalCode; label_desc.Name = _leftSide[i].Description; label_desc.ForeColor = DESCRIPTION_FOREGROUND; label_desc.Text = _leftSide[i].Description + ":"; label_desc.Margin = new Padding(0, 4, 4, 4); label_desc.Width = _labelWidth; if (_inIconMode) { PictureBox pBox = prepareIconForDisplay(_leftSide[i].InternalCode, _leftSide[i].Description); pnlDetail.Controls.Add(pBox, 1, pnlDetail.RowCount - 1); reDisplayIcons(); } else { pnlDetail.Controls.Add(label_desc, 1, pnlDetail.RowCount - 1); } } if (i < _rightSide.Count) { if (_rightSide[i].Graphics == "%R" && !_inBlankMode) { makeGraphics(_rightSide[i], rowData, 5, Painting.Cylinder); } else if (_rightSide[i].Graphics == "RBCone" && !_inBlankMode) { makeGraphics(_rightSide[i], rowData, 5, Painting.Cone); } else { Label label_val = new Label(); label_val.Tag = _rightSide[i]; if (!_inBlankMode) { label_val.Text = processUserChangeables(rowData, _rightSide[i]); } _resultToolTip.SetToolTip(label_val, label_val.Text + checkUnits(_rightSide[i].Units)); pnlDetail.Controls.Add(label_val, 5, pnlDetail.RowCount - 1); label_val.Margin = new Padding(4, 4, 0, 4); label_val.Dock = DockStyle.Right; //"right justifies" item in cell label_val.AutoSize = true; } //Description labels..same for both right and left sides... Label label_desc = new Label(); label_desc.Tag = _rightSide[i].InternalCode; label_desc.Name = _rightSide[i].Description; label_desc.ForeColor = DESCRIPTION_FOREGROUND; label_desc.Text = _rightSide[i].Description + ":"; label_desc.Margin = new Padding(0, 4, 4, 4); label_desc.Width = _labelWidth; if (_inIconMode) { PictureBox pBox = prepareIconForDisplay(_rightSide[i].InternalCode, _rightSide[i].Description); pnlDetail.Controls.Add(pBox, 4, pnlDetail.RowCount - 1); reDisplayIcons(); } else { pnlDetail.Controls.Add(label_desc, 4, pnlDetail.RowCount - 1); } } } pnlDetail.AutoScroll = false; //false then true somehow tricks the panel not to show the vertical scrollbar when it's not necessary upon startup.(invalidate/refresh didn't work); pnlDetail.AutoScroll = true; } private string checkUnits(string units) { if (units == "%" || units == "$") { return ""; } return " " + units; } private void makeGraphics(ColumnInfo inf, RowData rowData, int columnNumber, Painting p) { if (rowData.Data.ContainsKey(WireName(inf))) { double result; if (ServerFormats.TryParse(rowData.GetAsString(WireName(inf)), out result)) { ExTag exTag = new ExTag(); CustomPanel pnlResult = new CustomPanel(); pnlResult.Width = _cylinderWidth; pnlResult.Height = _cylinderHeight; pnlResult.Name = ServerFormats.ToString(result); exTag.Add("COLUMN_INFO", inf); exTag.Add("PICTURE", p); pnlResult.Tag = exTag; pnlResult.Paint += new PaintEventHandler(pnlResult_Paint); pnlDetail.Controls.Add(pnlResult, columnNumber, pnlDetail.RowCount - 1); pnlResult.Anchor = AnchorStyles.Right | AnchorStyles.Top; _resultToolTip.SetToolTip(pnlResult, ServerFormats.ToString(result)); } } } private void updateTopListData(RowData rowData) { foreach (Control control in pnlDetail.Controls) { Label label = control as Label; if (label != null) { ColumnInfo inf = label.Tag as ColumnInfo; if (inf != null) { TableLayoutPanelCellPosition pos = pnlDetail.GetCellPosition(label); if (pos.Column != 1 && pos.Column != 4) { inf = (ColumnInfo)label.Tag; if (!_inBlankMode) { label.Text = processUserChangeables(rowData, inf); } _resultToolTip.SetToolTip(label, label.Text + checkUnits(inf.Units)); } } } CustomPanel panel = control as CustomPanel; if (panel != null) { ExTag exTag = (ExTag)panel.Tag; Painting picture = (Painting)exTag.Get("PICTURE"); ColumnInfo inf = exTag.Get("COLUMN_INFO") as ColumnInfo; if (inf != null) { if (rowData.Data.ContainsKey(WireName(inf))) { double result = 0; if (ServerFormats.TryParse(rowData.GetAsString(WireName(inf)), out result)) { panel.Name = ServerFormats.ToString(result); if (!_inBlankMode) { Graphics g = panel.CreateGraphics(); if (picture == Painting.Cylinder) { paintCylinder(panel, g); } else { paintCone(panel, g); } } } _resultToolTip.SetToolTip(panel, ServerFormats.ToString(result)); } } } } } private string getDoubleString(RowData rowData, string internalCode, int placesPastDecimal) // many of the "doubles" are either one ore two places past decimal point. { string retVal = "***"; string formatSpec = "N0" + placesPastDecimal.ToString(); if (rowData.Data.ContainsKey(internalCode)) { double result; if (ServerFormats.TryParse(rowData.GetAsString(internalCode), out result)) { if (internalCode == "c_TV") //Volume is shown in panel header, we don't want smart numbering for this one. { retVal = result.ToString(formatSpec); } else { if (checkMBT(result) == "") { retVal = result.ToString(formatSpec); } else { retVal = checkMBT(result); } } } } return retVal; } private string checkMBT(double value) //check if number is billion,trillions-abbreviate if conditions met { string retVal = ""; double result; if (value >= 1000000 && value < 1000000000) { result = value / 1.0e+6; retVal = result.ToString("N02") + "M"; } if (value >= 1000000000 && value < 1000000000000) { result = value / 1.0e+9; retVal = result.ToString("N02") + "B"; } else if (value >= 1000000000000) { result = value / 1.0e+12; retVal = result.ToString("N02") + "T"; } return retVal; } private void pnlResult_Paint(object sender, PaintEventArgs e) { CustomPanel p = (CustomPanel)sender; Graphics graphics = e.Graphics; ExTag result = (ExTag)p.Tag; Painting picture = (Painting)(result.Get("PICTURE")); if (picture == Painting.Cylinder) { paintCylinder(p, graphics); } else { paintCone(p, graphics); } } private void paintCylinder(CustomPanel p, Graphics graphics) { double cellAsDouble; ServerFormats.TryParse(p.Name, out cellAsDouble); Rectangle destination = p.ClientRectangle; int midPointCellBounds = (int)(destination.Width / 2.0) + destination.X; Brush whiteBrush = new SolidBrush(Color.White); graphics.FillRectangle(whiteBrush, destination); whiteBrush.Dispose(); Rectangle r = destination; if (cellAsDouble < 0) { Brush redBrush = new SolidBrush(Color.Red); graphics.FillRectangle(redBrush, destination); redBrush.Dispose(); } else if (cellAsDouble > 100) { Brush greenBrush = new SolidBrush(Color.LimeGreen); graphics.FillRectangle(greenBrush, destination); greenBrush.Dispose(); } else if (cellAsDouble < 50) { Brush redBrush = new SolidBrush(Color.FromArgb(DataCell.getAlpha(cellAsDouble), Color.Red)); r.Width = (int)(r.Width * cellAsDouble / 100.0); Rectangle rFill = destination; rFill.Width = (int)(destination.Width / 2.0) - r.Width; rFill.Location = new Point(midPointCellBounds - rFill.Width, destination.Y); graphics.FillRectangle(redBrush, rFill); redBrush.Dispose(); } else if (cellAsDouble == 50) { Brush wht = new SolidBrush(Color.White); graphics.FillRectangle(wht, destination); wht.Dispose(); } else if (cellAsDouble > 50) { Brush grn = new SolidBrush(Color.FromArgb(DataCell.getAlpha(cellAsDouble), Color.LimeGreen)); r.Width = (int)(r.Width * cellAsDouble / 100.0); r.Width = r.Width - (int)(destination.Width / 2.0); r.Location = new Point(midPointCellBounds, destination.Y); graphics.FillRectangle(grn, r); grn.Dispose(); } DataCell.MakeCylinder(graphics, destination); } private void paintCone(CustomPanel p, Graphics graphics) { double result; ServerFormats.TryParse(p.Name, out result); string formattedString = result.ToString("#,#0.0"); Rectangle destination = p.ClientRectangle; p.BackColor = Color.FromArgb(0, 0, 9); int coneWidth = (int)(destination.Width * (result / 100)); DataCell.DrawTheCones(result, destination, coneWidth, formattedString, graphics); } private void btnSearchProfit_Click(object sender, EventArgs e) { _inBlankMode = false; clearPanelsAndLabels(); setNewSymbol(cboSymbolProfile.Text); SendToExternalLinking(); } private void btnSearchDetail_Click(object sender, EventArgs e) { _inBlankMode = false; clearPanelsAndLabels(); setNewSymbol(cboSymbol.Text); SendToExternalLinking(); } public void setNewSymbol(string newSymbol) { _settingNewSymbol = true; _currentSymbol = newSymbol.Trim().ToUpper(); if (_scottTradeSettings.Node("BLANK_MODE").Property("VALUE", true) && _currentSymbol == "") { _inBlankMode = true; } SetConfiguration(_config); cboSymbol.SelectAll(); cboSymbolProfile.SelectAll(); // Insert new symbol entries at the top of the list. if (!cboSymbol.Items.Contains(_currentSymbol)) cboSymbol.Items.Insert(0, _currentSymbol); if (!cboSymbolProfile.Items.Contains(_currentSymbol)) cboSymbolProfile.Items.Insert(0, _currentSymbol); } private void clearPanelsAndLabels() { pnlDetail.Controls.Clear(); pnlDetail.RowStyles.Clear(); pnlDetail.RowCount = 0; clearLabelData(); } private void SendToExternalLinking() { // Link only if enabled if (SymbolLinkingEnabled && (null != _currentSymbol) && ("" != _currentSymbol)) { RecordExternalLinkUseCase(_currentSymbol); SymbolDetailsCacheManager.Info info = _connectionMaster.SymbolDetailsCacheManager.Request(_currentSymbol); string exchange = (null == info) ? "" : info.Exchange; GuiEnvironment.sendSymbolToExternalConnector(_currentSymbol, exchange, "", this); } } private void RecordExternalLinkUseCase(string symbol) { GuiEnvironment.RecordExternalLinkingUseCase(symbol, "SS", _connectionMaster.SendManager); } //http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcellpaintingeventargs.cellbounds(v=vs.110).aspx private void pnlDetail_CellPaint(object sender, TableLayoutCellPaintEventArgs e) { if (e.Column == 1 || e.Column == 2 || e.Column == 4 || e.Column == 5) { e.Graphics.DrawLine(new Pen(Color.FromArgb(224, 224, 224)), e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1); } } private void tabSheet_SelectedIndexChanged(object sender, EventArgs e) { if (_inIconMode && tabSheet.SelectedTab == tabStock) { reDisplayIcons(); } else if (tabSheet.SelectedTab == tabProfile && _currentSymbol != "") { setNewSymbol(_currentSymbol); } } private void panel1_SizeChanged(object sender, EventArgs e) { if (panel1.Width <= _contractedWindow) { _headerLabelsVisible = false; changeHeaderLabelVisiblity(false); } else { _headerLabelsVisible = true; if (_validDataReceived) { changeHeaderLabelVisiblity(true); } else { changeHeaderLabelVisiblity(false); } } } private void pnlDetail_SizeChanged(object sender, EventArgs e) { //Since the two columns that are set to Percent (filter description) are both 50/50 in relation // to size of whole panel, they're sizing the same, so it doesn't matter which column we use as // a test. int width = pnlDetail.GetColumnWidths()[1]; //This method *isn't* exposed by intellisense!! if (pnlDetail.Width <= _contractedWindow) { _headerLabelsVisible = false; showIcons(); } else //if (pnlDetail.Width > contractedWindow) { _headerLabelsVisible = true; if (_validDataReceived) { changeHeaderLabelVisiblity(true); } else { changeHeaderLabelVisiblity(false); } showNormal(); } } private void showIcons() { _inIconMode = true; changeHeaderLabelVisiblity(false); pnlDetail.ColumnStyles[6].SizeType = SizeType.Percent; //At least One column must be kept as percent else the horizontal scroll bar will appear. pnlDetail.ColumnStyles[1].SizeType = SizeType.Absolute; pnlDetail.ColumnStyles[4].SizeType = SizeType.Absolute; pnlDetail.ColumnStyles[1].Width = _threshold; pnlDetail.ColumnStyles[4].Width = _threshold; swapLabelForIcon(); pnlDetail.AutoScroll = false; pnlDetail.AutoScroll = true; pnlDetail.VerticalScroll.Enabled = true; reDisplayIcons(); } private void showNormal() { _inIconMode = false; pnlDetail.ColumnStyles[6].SizeType = SizeType.Absolute; pnlDetail.ColumnStyles[1].SizeType = pnlDetail.ColumnStyles[4].SizeType = SizeType.Percent; _imageCacheManager = _connectionMaster.ImageCacheManager; swapIconForLabel(); pnlDetail.AutoScroll = false; pnlDetail.AutoScroll = true; pnlDetail.VerticalScroll.Enabled = true; } private void swapLabelForIcon() { foreach (Control control in pnlDetail.Controls) { Label label = control as Label; if (label != null) { string inf = label.Tag as string; if (inf != null) { TableLayoutPanelCellPosition pos = pnlDetail.GetCellPosition(label); int column = pos.Column; int row = pos.Row; if (column == 1 || column == 4) { PictureBox pBox = prepareIconForDisplay(inf, label.Name); pnlDetail.Controls.Remove(pnlDetail.GetControlFromPosition(column, row)); pnlDetail.Controls.Add(pBox, column, row); pBox.Margin = new Padding(0, 0, 0, 0); reDisplayIcons(); } } } } } private PictureBox prepareIconForDisplay(string internalCode, string description) { ExTag exTag = new ExTag(); PictureBox pBox = new PictureBox(); exTag.Add("DoUpdate", (DoUpdate)delegate { pBox.Image = _imageCacheManager.GetFilter("Min" + internalCode); }); exTag.Add("InternalCode", internalCode); exTag.Add("Description", description); pBox.Height = ICON_HEIGHT; pBox.Width = ICON_WIDTH; pBox.SizeMode = PictureBoxSizeMode.CenterImage; pBox.BorderStyle = BorderStyle.None; pBox.Name = internalCode; _resultToolTip.SetToolTip(pBox, description); pBox.Tag = exTag; return pBox; } private void swapIconForLabel() { foreach (Control control in pnlDetail.Controls) { PictureBox picBox = control as PictureBox; if (picBox != null) { ExTag result = (ExTag)picBox.Tag; TableLayoutPanelCellPosition pos = pnlDetail.GetCellPosition(picBox); int column = pos.Column; int row = pos.Row; if (column == 1 || column == 4) { Label label = new Label(); label.Width = _labelWidth; label.ForeColor = Color.Gray; label.Text = result.Get("Description").ToString() + ":"; label.Tag = result.Get("InternalCode").ToString(); label.Name = result.Get("Description").ToString(); pnlDetail.Controls.Remove(pnlDetail.GetControlFromPosition(column, row)); pnlDetail.Controls.Add(label, column, row); label.Margin = new Padding(0, 4, 4, 4); } } } } private void reDisplayIcons() { foreach (Control control in pnlDetail.Controls) { ExTag result = control.Tag as ExTag; if (result != null) { if (result.KeyExists("DoUpdate")) { DoUpdate filterUpdate = (DoUpdate)result.Get("DoUpdate"); if (null != filterUpdate) { filterUpdate(); } } } } } private void SingleStockWindow_Activated(object sender, EventArgs e) //for symbol linking-prevent appending of new symbol to old text in textbox. { if (tabSheet.SelectedTab == tabStock) { cboSymbol.Focus(); cboSymbol.SelectionStart = 0; cboSymbol.SelectionLength = cboSymbol.Text.Length; } else { cboSymbolProfile.Focus(); cboSymbolProfile.SelectionStart = 0; cboSymbolProfile.SelectionLength = cboSymbol.Text.Length; } } private void configureToolStripMenuItem_Click(object sender, EventArgs e) { DoConfiguration(); } private void DoConfiguration() { ConfigWindowWrapper configWindowWrapper = ConfigWindowWrapper.DefaultFactory(ConfigurationType.TopList, _connectionMaster); configWindowWrapper.InitialConfig = _config; configWindowWrapper.AllowOkayImmediately = true; configWindowWrapper.IsSingleStock = true; if (_leftSide.Count == _rightSide.Count) { if (_sideRightLeft == 1) { _sideRightLeft = 0; } } configWindowWrapper.SingleStockWindowValue = _displayBeginPopulate; configWindowWrapper.ShowIt(); if (!configWindowWrapper.Canceled) { _sideRightLeft = configWindowWrapper.SingleStockWindowValue; _displayBeginPopulate = configWindowWrapper.SingleStockWindowValue; TopListStrategy strategy = (TopListStrategy)configWindowWrapper.Strategy; // Make sure we store _currentSymbol and _outsideMarketHours back into the collaborate // string. The new client ignores those. We will also store them directly into the // XML file. The new client reads these directly from the XML file. But the older // client will ignore the symbol that we store directly into the XML file. It will only // look at the symbol that we store here. There are similar issues with the // OutsideMarketHours flag. In that case the older client actually looks at both // places and if they don't match things might not work well. // // If you only have the new client, you don't have to worry about any of this. The // next three lines are useless but they don't hurt anything. // // If you have a new client but you want to be compatible with old and new clients, // the following three lines will help. (E.g. if Brad is making a new cloud layout // to share with a lof of people, this applies to him.) If you want to make a layout // that everyone can use, start by setting the symbol and OMH the way you want them. // Then start the config window. Then hit OK (not Cancel) in the config window. Then // save your layout. strategy.SingleSymbol = _currentSymbol; strategy.SymbolListDisposition = SymbolListDisposition.SingleSymbol; strategy.OutsideMarketHours = _outsideMarketHours; SetConfiguration(strategy.MakeConfigString()); } } /// /// Implements the IChildable interface. This allows apps like Scottrade Elite to still use the LayoutManager /// without it automatically opening up windows. /// private bool _isChild = false; public bool IsChild { get { return _isChild; } set { _isChild = value; } } public TIFormType TIFormType { get { return TIProGUI.TIFormType.SingleStock; } } public Rectangle? ActualSize { get; set; } /// /// 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() { // not implemented yet return ""; } WindowIconCache ISaveLayout.WindowIconCache { get { return WindowIconCache; } } private void saveToCloudStripMenuItem_Click(object sender, EventArgs e) { SaveToCloud.DoIt(_sendManager, this); } private void smallBordersStripMenuItem_Click(object sender, EventArgs e) { setBorders(); } private void outsideMarketHoursToolStripMenuItem_Click(object sender, EventArgs e) { setMarketHours(); } private void duplicateToolStripMenuItem_Click(object sender, EventArgs e) { LayoutManager.Instance().Duplicate(this); } 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); } if (null != _config) { description.SetProperty("CONFIG", _config); } description.SetProperty("SYMBOL", _currentSymbol); description.SetProperty("SMALL_BORDERS", smallBordersToolStripMenuItem.Checked.ToString()); description.SetProperty("OUTSIDE_MARKET_HOURS", _outsideMarketHours); description.SetProperty("CONTRACTED_WINDOW", _contractedWindow); description.SetProperty("SIDE_RIGHT_LEFT", _sideRightLeft); description.SetProperty("DISPLAY_BEGIN_POPULATE", _displayBeginPopulate); description.SetProperty("SYMBOL_LINKING_ENABLED", SymbolLinkingEnabled); description.SetProperty("SAVED_WINDOW", true); description.SetProperty("PINNED", _pinned); description.SetProperty("IN_BLANK_MODE", _inBlankMode); if (tabSheet.SelectedTab == tabProfile) description.SetProperty("ACTIVE_TAB", "PROFILE"); else description.SetProperty("ACTIVE_TAB", "DETAIL"); } 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 { // Read these three values first. You can fill in other values, like small borders, after // the constructor has finished. But we want enough information to send a good request to // the server in the constructor. string config = description.Property("CONFIG", GuiEnvironment.XmlConfig.Node("SINGLE_SYMBOL_WINDOW").Node("NEW_SINGLE_STOCK_WINDOW_DEFAULT").Property("TEXT")); string symbol = description.Property("SYMBOL", null); bool? outsideMarketHours = description.PropertyBool("OUTSIDE_MARKET_HOURS"); SingleStockWindow singleStockWindow = new SingleStockWindow(connectionMaster, config, false, symbol, outsideMarketHours); // change parameters to accommodate dock panel changes - RVH20210402 //singleStockWindow.Restore(description, ignorePosition, cascadePosition); singleStockWindow.Restore(description, ignorePosition, cascadePosition, dockPanelMode, mainDockPanelName, mainDockPanelTitle, dockPanelID); singleStockWindow.RestoredLayout = description; } }); } 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 = "") { // 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; smallBordersToolStripMenuItem.Checked = description.Property("SMALL_BORDERS", false); // only call this if not in dock panel mode - RVH20210329 if (!_dockPanelMode) setBorders(); // User maybe loading a contracted window saved under a different fonmt size // so we need to set _contractedWindow correctly int contractedWindow = description.Property("CONTRACTED_WINDOW", _contractedWindowDefault); if (contractedWindow > _contractedWindow) _contractedWindow = contractedWindow; _sideRightLeft = description.Property("SIDE_RIGHT_LEFT", 0); _displayBeginPopulate = description.Property("DISPLAY_BEGIN_POPULATE", 0); SymbolLinkingEnabled = description.Property("SYMBOL_LINKING_ENABLED", false); _pinned = description.Property("PINNED", false); pinnedToolStripMenuItem.Checked = _pinned; _savedWindow = description.Property("SAVED_WINDOW", false); if (_savedWindow) { _inBlankMode = description.Property("IN_BLANK_MODE", false); } if (pnlDetail.Width <= _contractedWindow) { showIcons(); } else { showNormal(); } string activeTab = description.Property("ACTIVE_TAB", "DETAIL"); if (activeTab == "PROFILE") tabSheet.SelectTab(tabProfile); } private void saveAsDefaultToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("SingleStockWindow.RightClick.SaveAsDefault", _sendManager); string programDirFileName = _layoutManager.Directory + "\\" + _defaultFileName; _layoutManager.SaveOne(this, programDirFileName); } private void changeHeaderLabelVisiblity(bool change) { lblCompanyNameDetail.Visible = change; lblCompanyNameProfile.Visible = change; label1.Visible = change; label2.Visible = change; lblVolumeDetail.Visible = change; lblVolumeProfile.Visible = change; lblRelVolDetail.Visible = change; lblRelVolProfile.Visible = change; label4.Visible = change; label5.Visible = change; } private void setBorders() { if (smallBordersToolStripMenuItem.Checked) { FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; } else { FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; } } private void setMarketHours() { _outsideMarketHours = outsideMarketHoursToolStripMenuItem.Checked; SetConfiguration(_config); } public void SetSnapToGrid(bool enabled) { formSnapper1.Enabled = enabled; if (GuiEnvironment.RunningWin10 && enabled) { formSnapper1.Win10HeightAdjustment = GuiEnvironment.HEIGHT_INCREASE; formSnapper1.Win10WidthAdjustment = GuiEnvironment.WIDTH_INCREASE; } } void IDemoMode.OnDemoModeChanged() { updateWindow(); } private void SingleStockWindow_FormClosed(object sender, FormClosedEventArgs e) { SetConfiguration(null); if (_configurationWindowManager != null) { _configurationWindowManager.Abandon(); _configurationWindowManager = null; // helped with memory leaks } } private bool _symbolLinkingEnabled = true; public bool SymbolLinkingEnabled { get { return _symbolLinkingEnabled; } set { _symbolLinkingEnabled = value; UpdateSymbolLinkingCheckboxStatus(); } } private void doSymbolLinkingToolStripMenuItem_Click(object sender, EventArgs e) { SymbolLinkingEnabled = !SymbolLinkingEnabled; UpdateSymbolLinkingCheckboxStatus(); } private void UpdateSymbolLinkingCheckboxStatus() { doSymbolLinkingToolStripMenuItem.Checked = SymbolLinkingEnabled; } public void ChangeSymbol(string symbol, RowData rowData, string sourceWindow) { if (SymbolLinkingEnabled) { _inBlankMode = false; clearPanelsAndLabels(); setNewSymbol(symbol); } } private string _linkChannel = ""; public string LinkChannel { get { return _linkChannel; } set { _linkChannel = value; } } public string CurrentSymbol() { return _currentSymbol; } public bool LinkEnabled { get { return SymbolLinkingEnabled; } set { SymbolLinkingEnabled = value; } } private bool _limitedMode = false; public bool LimitedMode { get { return _limitedMode; } set { _limitedMode = value; } } private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) { if (null != GuiEnvironment.RobotStrategyMenuCode) GuiEnvironment.RobotStrategyMenuCode(contextMenuStrip1, _currentSymbol, "SS", null); GuiEnvironment.HideMenuItems(contextMenuStrip1.Items); GuiEnvironment.EnforceLimitedMode(contextMenuStrip1); } public void ShowConfiguration() { DoConfiguration(); } public ContextMenuStrip MyContextMenuStrip { get { return contextMenuStrip1; } } public List GetStrategyConfigs() { List toReturn = new List(); return toReturn; } private void pinnedToolStripMenuItem_Click(object sender, EventArgs e) { _pinned = pinnedToolStripMenuItem.Checked; } public void selectTheFont() { Font = GuiEnvironment.FontSettings; contextMenuStrip1.Font = Font; cboSymbolProfile.Font = Font; cboSymbol.Font = Font; pnlDetail.Font = Font; // Labels lblDateDetail.Font = Font; lblDateProfile.Font = Font; lblTimeDetail.Font = Font; lblTimeProfile.Font = Font; lblPriceDetail.Font = Font; lblPriceProfile.Font = Font; lblCompanyNameProfile.Font = Font; lblCompanyNameDetail.Font = Font; lblChangeDollarDetail.Font = Font; lblChangeDollarProfile.Font = Font; lblChangePercentDetail.Font = Font; lblChangePercentProfile.Font = Font; lblRelVolDetail.Font = Font; lblRelVolProfile.Font = Font; lblVolumeDetail.Font = Font; lblVolumeProfile.Font = Font; lblExchange.Font = Font; lblSIndustry.Font = Font; lblSSector.Font = Font; lblIndustry.Font = Font; lblSector.Font = Font; lblIndustryGroup.Font = Font; txtSummary.Font = Font; label1.Font = Font; label2.Font = Font; label4.Font = Font; label5.Font = Font; label7.Font = Font; label8.Font = Font; label9.Font = Font; label10.Font = Font; label11.Font = Font; label12.Font = Font; // Scale preferred sizes Size textSize = TextRenderer.MeasureText("8", this.Font); _rowHeight = 2 * textSize.Height; _cylinderWidth = (int)(3.5 * textSize.Width); _cylinderHeight = (int)(1.6 * textSize.Height); _threshold = 4 * textSize.Width; _labelWidth = 19 * textSize.Width; _contractedWindowDefault = 24 * textSize.Width; // Sometimes one of these columns are negative in particular pnlDetail.GetColumnWidths()[6] _contractedWindow = 2 * (_threshold + pnlDetail.GetColumnWidths()[0] + pnlDetail.GetColumnWidths()[3]); if (0 < pnlDetail.GetColumnWidths()[2]) _contractedWindow += pnlDetail.GetColumnWidths()[2]; if (0 < pnlDetail.GetColumnWidths()[5]) _contractedWindow += pnlDetail.GetColumnWidths()[5]; if (0 < pnlDetail.GetColumnWidths()[6]) _contractedWindow += pnlDetail.GetColumnWidths()[6]; } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase("SingleStockWindow.RightClick.SaveAs", _sendManager); LayoutManager layoutManager = LayoutManager.Instance(); 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) { fileName = _phrases.Node("FILE_PREFIX").PropertyForCulture("TEXT", "***") + _shortWindowName; } else { fileName = _fileNameSaved; } dialog.FileName = FileNameMethod.QuoteFileName(fileName); if (dialog.ShowDialog() == DialogResult.OK) { layoutManager.SaveOne(this, dialog.FileName); _fileNameSaved = Path.GetFileName(dialog.FileName); } dialog.Dispose(); } private bool _pausedSurfing = false; private void contextMenuStrip1_Opened(object sender, EventArgs e) { // temporarily pause surfing if the context menu is opened Surfer.SurfManager surfManager = Surfer.SurfManager.Instance(); if (null != surfManager) { if (surfManager.IsRunning) { _pausedSurfing = true; surfManager.Stop(); } } } private void contextMenuStrip1_Closed(object sender, ToolStripDropDownClosedEventArgs e) { if (_pausedSurfing) { Surfer.SurfManager surfManager = Surfer.SurfManager.Instance(); if (null != surfManager) { _pausedSurfing = false; surfManager.Start(false); } } } private void cboSymbol_TextChanged(object sender, EventArgs e) { if (_initCboSymbol)//When this window is being freshly instantiated, this event handler does fire... { _initCboSymbol = false; return; } string text = cboSymbol.Text.ToUpper(); cboSymbol.Text = text; cboSymbol.SelectionStart = cboSymbol.Text.Length; cboSymbol.BackColor = Color.White; if (_scottTradeSettings.Node("BLANK_MODE").Property("VALUE", true) && text == "") { _inBlankMode = true; } else { _inBlankMode = false; } } private void cboSymbol_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { clearPanelsAndLabels(); setNewSymbol(cboSymbol.Text); SendToExternalLinking(); e.Handled = true; e.SuppressKeyPress = true; } } private void cboSymbol_Click(object sender, EventArgs e) { cboSymbol.SelectAll(); } private void cboSymbolProfile_TextChanged(object sender, EventArgs e) { if (_initCboSymbolProfile) //When this window is being freshly instantiated, this event handler does fire... { _initCboSymbolProfile = false; return; } string text = cboSymbolProfile.Text.ToUpper(); cboSymbolProfile.Text = text; cboSymbolProfile.SelectionStart = cboSymbolProfile.Text.Length; cboSymbolProfile.BackColor = Color.White; if (_scottTradeSettings.Node("BLANK_MODE").Property("VALUE", true) && text == "") { _inBlankMode = true; } else { _inBlankMode = false; } } private void cboSymbolProfile_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { clearPanelsAndLabels(); setNewSymbol(cboSymbolProfile.Text); SendToExternalLinking(); e.Handled = true; e.SuppressKeyPress = true; } } private void cboSymbolProfile_Click(object sender, EventArgs e) { cboSymbolProfile.SelectAll(); } private void SingleStockWindow_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 class ExTag //courtesy of: http://www.codeproject.com/Tips/376545/How-to-apply-many-Tags-for-a-Control-using-Csharp { private Dictionary TagDictionary { get; set; } public ExTag() { this.TagDictionary = new Dictionary(); } public void Add(string key, object value) { this.TagDictionary.Add(key, value); } public bool KeyExists(string key) { return TagDictionary.ContainsKey(key); } public object Get(string key) { return this.TagDictionary[key]; } } public interface IAcceptSymbolLinking { void ChangeSymbol(string symbol, RowData rowData, string sourceWindow); string CurrentSymbol(); string LinkChannel { get; set; } bool LinkEnabled { get; set; } } public interface ISymbolLinkingChannel { void SetLinkChannel(string linkChannel); string GetLinkChannel(); } }