using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; using System.Xml; using TradeIdeas.MiscSupport; using TradeIdeas.TIProData; using TradeIdeas.TIProData.Configuration; using TradeIdeas.TIProData.Interfaces; using TradeIdeas.TIProGUI.CBT; using TradeIdeas.XML; namespace TradeIdeas.TIProGUI { public partial class ConfigWindow : Form { private ConfigurationWindowManager _configurationWindowManager; private ConfigurationType _configurationType; /// /// This holds the strategy is it is being built. This can be copied at the end to /// give the final result. /// private PrepairedStrategy _strategy; private AlertStrategy _multiStrategyChanges = new AlertStrategy(); public Dictionary StrategyChanges { get { Dictionary changes = new Dictionary(); foreach (MultiStrategy.DataWatcher strategy in _loadedMultiStrategies.Keys) { string originalConfig = strategy.Config; AlertStrategy alertStrategy = _loadedMultiStrategies[strategy]; foreach (var pair in _multiStrategyChanges.MinFilters) { Filter filter = pair.Key; string value = pair.Value; alertStrategy.MinFilters[filter] = value; } foreach (var pair in _multiStrategyChanges.MaxFilters) { Filter filter = pair.Key; string value = pair.Value; alertStrategy.MaxFilters[filter] = value; } foreach (Exchange exchange in _multiExchangesToAdd) { if (!alertStrategy.Exchanges.Contains(exchange)) alertStrategy.Exchanges.Add(exchange); } foreach (Exchange exchange in _multiExchangesToRemove) { if (alertStrategy.Exchanges.Contains(exchange)) alertStrategy.Exchanges.Remove(exchange); } if (chkSymbolListMultiChangeWarning.Checked == false) { AlertStrategy alertStrategyInitial = _loadedMultiStrategiesInitialSymbolList[strategy]; alertStrategy.SingleSymbol = alertStrategyInitial.SingleSymbol; alertStrategy.SymbolListDisposition = alertStrategyInitial.SymbolListDisposition; alertStrategy.SymbolLists = alertStrategyInitial.SymbolLists; } else if (_multiEditSymbolListChanges) { alertStrategy.SingleSymbol = _strategy.SingleSymbol; alertStrategy.SymbolListDisposition = _strategy.SymbolListDisposition; //The stuff in the below commented lines are taken care of in the checkbox click handler //of the symbol list. //alertStrategy.SymbolLists = _strategy.SymbolLists; //alertStrategy.SymbolLists.Clear(); //AlertStrategy alertStrategyInitial = _loadedMultiStrategiesInitialSymbolList[strategy]; } if (!changes.ContainsKey(originalConfig)) changes.Add(originalConfig, alertStrategy.MakeConfigString()); } return changes; } } /// /// Invariant: _alertStrategy == _strategy as AlertStrategy. /// This variable only exists to cache that cast, so we don't have to do it over and over. /// Always used SetStrategy() to set this variable and preserve the invariant. /// private AlertStrategy _alertStrategy; /// /// Invariant: _topListStrategy == _strategy as TopListStrategy. /// This variable only exists to cache that cast, so we don't have to do it over and over. /// Always used SetStrategy() to set this variable and preserve the invariant. /// private TopListStrategy _topListStrategy; public AlertStrategy AlertStrategy { get { return _alertStrategy; } } public TopListStrategy TopListStrategy { get { return _topListStrategy; } } public PrepairedStrategy Strategy { get { return _strategy; } } private Dictionary _loadedMultiStrategies = new Dictionary(); /* This dictionary is also used with the Config All functionality of the MultiStrategyWindow and addresses a bug with the * symbollists. Changes can be made inadvertenetly when OK button is pressed. This dictionary holds the initial symbollist * settings when the config window is initially brought up. If user decides not to have changes made to all strategies, then * upon pressing "OK", any symbol list changes made during that editing session will be "rolled back" to the initial values * in this "_loadedMultiStrategiesInitialSymbolList " dictionary. */ private Dictionary _loadedMultiStrategiesInitialSymbolList = new Dictionary(); /*This dictionary, "_symbolListMultiSelectStatus" is used for initially populating the symbollist checkboxes in the ConfigureAll version of this window*/ private Dictionary _symbolListMultiSelectStatus = new Dictionary(); private List _multiStrategies = new List(); public List MultiStrategies { get { return _multiStrategies; } set { List tempStrategyList = value; _multiStrategies.Clear(); if (null != value) { foreach (MultiStrategy.DataWatcher strategy in tempStrategyList) { if (null != strategy && null != strategy.Config) _multiStrategies.Add(strategy); } } _loadedMultiStrategies.Clear(); if (null != value) LoadMultiStrategies(); } } private readonly string MULTIPLE_VALUES = "XXXXX"; private bool _multiEditSymbolListChanges = false; //For dealing with alert-filter icon display... private ImageCacheManager _imageCacheManager; private IConnectionMaster _connectionMaster; //for dealing with the Single Stock Window.. private int _displayBeginPopulate = 0; private int _columnCount = 1; /// /// This is the image list for the strategy icons. /// public ImageList StrategyImageList { get { return strategyImageList; } } //Icon attribute for list box display. We don't have borders //around icons in the list box(as opposed to the panel). Hence //we won't use GuiEnvironment.ICON_WIDTH private const int ICON_WIDTH = 40; //For creating new symbol lists private SymbolListsCacheManager _symbolListsCacheManager; /*Dictionary for mapping a node name to its assignmed integral image index. We will need this when using the orange arrow to select strategies. Must be mutually exclusive*/ private Dictionary _dict = new Dictionary(); //for populating combo box in SymbolList tab private List _symbolListCombo = new List(); /*We wish to show the user's current settings(if any) in the strategies panel upon startup of the config window.*/ private TreeNode _settingsNode; // This is the symbol list tree view private SymbolListTreeView _tvSymbolList = new SymbolListTreeView(); private SymbolListChooserPanel _panelCommonSymbolLists = new SymbolListChooserPanel(); private HashSet _commonSymbolLists = new HashSet(); private ToolStripDropDown _symbolListTreeViewPopup; private int _nodeNameTally = 0; private string _nodeName; /*Two Lists for keeping track of the images being displayed in stratgies box. Some objects are filters, which have the same internal ID be they minimum or maximum- So they must some how be differentiated. When using a Dictionary, sometimes one can encounter a case where both FilterIcons must show(min and max), but would result in a duplicate-key exception being thrown, An example would be in in the "Approaching Daily Highs" description in the Strategies Tab. So the object list will store each object(filter or alert) and the imageType List will store its corresponding "type". That is, I used '0' = alert, '1' = maxFilter,'2' = minFilter*/ private List _images = new List(); private List _imageType = new List(); //This linked list is to keep track of recent changes(alerts and/or filters) that //will ultimately be displayed as icons in the WindowName panel within the //"Recent Changes" area... private LinkedList _recentChanges = new LinkedList(); //Below dictionary used within the flip method.... private Dictionary _alertsFilterInQuestion = new Dictionary(); //Container for visible alerts and filters--SIMPLIFIED CONFIG WINDOW private static List _visibleAlertsAndFilters = new List(); /*Due to performance issues, the alert and filter tabs cannot be populated within the OnLoaded method because the program will "hang" for quite a while. Not only do we wish to have the icons corresponding to the current setting to display * within the Strategy tab when the GUI first appears, we also wish to have the corresponing checks(Alerts tab) and other filter data(Filters tab) as well. As a workaround, the two booleans below ensure that those data will be visible when the alerts or filters tab\\ are clicked and no other strategy has been loaded...*/ private bool _currentSettingAlertFlag = true; private bool _currentSettingFilterFlag = true; private AlertStrategy _currentAlert; private TopListStrategy _currentTopList; //for furnishing data on tool-tips private StrategyNode _selected; //for the categories in the search tab struct Category { public string rawString; public string userViewString; }; private List _categoryList = new List(); //for language translations private List _phrases; private List _commonPhrases; private List _phrasesMultiStrat; //for the config window and viewing alerts/filters in alerts,wsf,column,sort tab. private List _begAlerts; private List _begFilters; private List _singleStockFilters; //for management of filters within CurrentColumns Panel. Namely when // one wishes to use the column-chooser('Up' or 'Down' buttons) private List _upDownFilterPlaceHolder = new List(); //boolean for loading the topList(filter Tab) for very first time.... private bool _firstLoadTopList = true; //Bools for initializing the filter, alert, column and sort panels,and search private bool _needToInitializeFilterPanel = false; private bool _needToInitializeAlertPanel = false; private bool _needToInitializeSearchBox = false; private bool _needToInitializeSortPanel = true; private bool _needToInitializeColumnsList = true; private bool _configuringFromOutside = false; private bool _serverSortFromOutside = false; private string _outsideICode; //when accessing this window from another window private double? _setFromOutsideMaxFilter = null; private double? _setFromOutsideMinFilter = null; //very first time user clicks on WindowsSpecificFilter tab or Alerts tab //This is used to determine when the OK button is enabled when config window private bool _firstFilterView = true; private bool _firstAlertsView = true; private bool _firstSearchView = true; private bool _firstSortView = true; //For managing the HideUnused function in Alert Tab and filter Tab private static List _alertTempList = new List(); private static List _filterTempList = new List(); //The list below will be populated with all alert objects,filter objects //in the OnLoaded so that this doesn't have to occur every time // the user hits "Show All" within alert and Filter tabs. private List _allAlertList = new List(); private List _allFilterList = new List(); //These lists are to contain unique items to just alert or toplist //This keeps track on *what's displayed on the screen.* private static List _uniqueToAlerts = new List(); private static List _uniqueToTopList = new List(); private static List _tempFilter_AlertConfig = new List(); private static List _tempFilter_TopListConfig = new List(); //Start location of Config window when first brought up... //private static int _configLocation_X = 50; //private static int _configLocation_Y = 50; //Start size of Config window when *first* brought up (default size) private static int _configWindowHeight = -1; private static int _configWindowWidth = -1; //Make sure SimpleColumns is populated only ONCE!!!///// private static bool _firstInstance = true; // Save current language private string _currentLanguage; //use this to determine whether to populate the right-hand side //of the Strategies panel with alerts/filters. If the last node added // does not equal "Current Settings" (as with the multistrategy window) //then the right-hand side should be devoid of alerts and filters. TreeNodeCollection _into; //Fonts... private const float DEFAULT_FONT_SIZE = 10.0F; private FontManager _fontManager; //Context Menu for ListBox (search menu) private ContextMenuStrip _listBoxSearchContext = new ContextMenuStrip(); /*The below is to keep tabs of what's selected in the search tab, which is a ListBox. Unlike a panel which contains images in picture boxes that can easily be customized with a context menu, it is a little bit more messy with a list box, as one cannot pass the name of a filter (or alert). The ListBox owns the *single* context menu, whereas in the windows specific filters *panel*, each filter/alert is hooked up with it's own context menu. So within a ListBox, we use the right-mouse-click handler to associate the selected item(Alert/Filter) based on the mouse location. Once we have the selected item, then we can extract the internal code for the particular item and store it in the below "_selectedContexSearchItem"*/ private string _selectedContextSearchItem; //for the user tracking private ISendManager _sendManager; private string _windowPrefix = ""; private bool _columnChooserMode = false; private bool _fromScratch = false; /// /// Hide the columns panel. Also disable various buttons and menu items that /// reference the columns panel. This was previously called _usingOddsMaker. /// This option is, in fact, currently used for the OddsMaker exit condition /// and the Compare Count window. It could be used in other places, too. /// private bool _dontShowColumns = false; //For removing Heartbeat alert private bool _removeHeartBeatAlert = false; //This List keeps track of item(s) selected through the "Find" button //which will be bolded. private List _itemSelectionsForBolding = new List(); // Remember old font so we can update window size private static Font _oldFont; // this is a dictionary that is used to // A) hold the translations for the symbol list dispositions // B) allows the SelectedValue of the combobox to be cast to a SymbolListDisposition enum private Dictionary _symbolListDispositions = new Dictionary(); // Boolean used to control selecting tabs; if the strategies have not completed loading, then ignore new tab selection private bool _loadingComplete = false; private readonly Dictionary _tabPageTrackingCodes = new Dictionary(); private readonly IList _extraColumns; private string _AIConfig = ""; //for "configuring" columns (viewing actually) of AIStrategy/StrategyTrade windows private List _allCustomColumns = new List(); private BindingSource _allCustomColumnsBindingSource = new BindingSource(); private List _visibleCustomColumns = new List(); private BindingSource _visibleCustomColumnsBindingSource = new BindingSource(); // Are we configuring a window, or just a single strategy within a window. // The only affects the wording, not the functionality. private readonly bool _notAWindow; //the below is for the "Single Stock Window" if this bool is true, then we must adjust this config window accordingly (e.g. remove requisite tabs) private bool _isSingleStock; //the below boolean in oddsmaker.. This is tailored when one is using the "column in results" option, and we're using an abbreviateed version of config window. private bool _usingOddsMaker; //define delegate called ConfigEventHandler (a signature) public delegate void ConfigEventHandler(object Object, ConfigArgs args); // Define an Event based on the above Delegate(since we want to hook the event handler up in MainForm, where the userConfigSetting object is accessable, we will keep this //handler as static since we're subscibing to it before a config window object is instantiated. public static event ConfigEventHandler OnAdvancedConfigWinChanged; // Only need one of these to support all tooltips private ToolTip toolTip = new ToolTip(); // Define brush used in DrawItem private static Brush myBrush = Brushes.Black; // NEW SYMBOL LOOKUP SymbolLookupB _symbolLookup = new SymbolLookupB(); private List _listBoxes = new List(); public ConfigWindow(ConfigurationType configurationType, IConnectionMaster connectionMaster, string config, bool columnChooserMode = false, bool fromScratch = false, bool dontShowColumns = false, IList extraColumns = null, string useCaseName = null, bool notAWindow = false, List multiStrategies = null, bool isSingleStock = false, bool usingOddsMaker = false, double? setMinFilter = null, double? setMaxFilter = null, List allCustomColumns = null, List allVisibleCustomColumns = null, int columnCount = 1) { this.StartPosition = FormStartPosition.CenterParent; InitializeComponent(); MinimizeBox = false; StartPosition = FormStartPosition.CenterParent; if (null == connectionMaster) return; if (null != GuiEnvironment.BeforeConfiguringCode) GuiEnvironment.BeforeConfiguringCode(); ConfigDemoUserControl.Init(connectionMaster.SendManager); _fromScratch = fromScratch; _columnChooserMode = columnChooserMode; _sendManager = connectionMaster.SendManager; _configurationType = configurationType; _imageCacheManager = connectionMaster.ImageCacheManager; _connectionMaster = connectionMaster; _dontShowColumns = dontShowColumns; _extraColumns = extraColumns; _notAWindow = notAWindow; _isSingleStock = isSingleStock; _usingOddsMaker = usingOddsMaker; _setFromOutsideMinFilter = setMinFilter; _setFromOutsideMaxFilter = setMaxFilter; MultiStrategies = multiStrategies; _columnCount = columnCount; //For loading stuff with all windows //Sometimes the wait can be several seconds, so //we need to activate the wait panel pnlWait.Visible = false; _symbolListsCacheManager = GuiEnvironment.GetSymbolListsCacheManager(connectionMaster); _symbolListsCacheManager.SymbolListsReadyUpdate -= _symbolListsCacheManager_ReadyUpdate; _symbolListsCacheManager.SymbolListsReadyUpdate += _symbolListsCacheManager_ReadyUpdate; // Manually call the delegate once to initialize the Create List button _symbolListsCacheManager_ReadyUpdate(_symbolListsCacheManager); _phrases = GuiEnvironment.XmlConfig.Node("CONFIG_WINDOW").Node("PHRASES"); _commonPhrases = GuiEnvironment.XmlConfig.Node("COMMON_PHRASES"); _phrasesMultiStrat = GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("PHRASES"); _begAlerts = GuiEnvironment.XmlConfig.Node("CONFIG_WINDOW").Node("BEGINNER_ALERTS"); _begFilters = GuiEnvironment.XmlConfig.Node("CONFIG_WINDOW").Node("BEGINNER_FILTERS"); _singleStockFilters = GuiEnvironment.XmlConfig.Node("CONFIG_WINDOW").Node("SINGLE_STOCK_FILTERS"); _currentLanguage = GuiEnvironment.CultureManager.Current.TwoLetterISOLanguageName; _panelCommonSymbolLists.setConFigurationType(configurationType); if (dontShowColumns) tabStrategies.TabPages.Remove(tabColumns); switch (configurationType) { case ConfigurationType.Alerts: btnSortBy.Visible = false; Text = _phrases.Node("ALERT_CONFIG_WINDOW").PropertyForCulture("TEXT", "***"); // tabStrategies.TabPages.Remove(tabColumns); useCaseName = useCaseName ?? "Alert"; tabStrategies.TabPages.Remove(tabSort); tabStrategies.TabPages.Remove(tabColumnOrder); SetStrategy(new AlertStrategy()); SetInitialConfig(config); break; case ConfigurationType.TopList: if (!_isSingleStock) { useCaseName = useCaseName ?? "TopList"; btnSortBy.Visible = true; Text = _phrases.Node("TOP_LIST_CONFIG_WINDOW").PropertyForCulture("TEXT", "***"); tabStrategies.TabPages.Remove(tabAlerts); tabStrategies.TabPages.Remove(tabColumnOrder); //Set _currentSettingAlertFlag to false so that Top List filter window initializes correctly. //Fixes Window Specific Filters tab data not updating when a user selects Start from Scratch //and hits Load. _currentSettingAlertFlag = false; SetStrategy(new TopListStrategy()); SetInitialConfig(config); } else //making the Single Stock Window { useCaseName = useCaseName ?? "SingleStock"; btnSortBy.Enabled = false; btnFind.Enabled = false; Text = _phrases.Node("SINGLE_STOCK_CONFIG_WINDOW").PropertyForCulture("TEXT", "***"); tabStrategies.TabPages.Remove(tabAlerts); tabStrategies.TabPages.Remove(tabStrategy); tabStrategies.TabPages.Remove(tabExchange); tabStrategies.TabPages.Remove(tabWindowName); tabStrategies.TabPages.Remove(tabSort); tabStrategies.TabPages.Remove(tabSymbolList); tabStrategies.TabPages.Remove(tabWindowsSpecificFilters); AddListBoxes(); SetStrategy(new TopListStrategy()); SetInitialConfig(config); } break; case ConfigurationType.MultiStrategy: { tabStrategies.TabPages.Remove(tabColumnOrder); } break; case ConfigurationType.CustomColumns: { _allCustomColumns = allCustomColumns; _visibleCustomColumns = allVisibleCustomColumns; lstAllColumns.DisplayMember = "WireName"; _allCustomColumnsBindingSource.DataSource = _allCustomColumns; _visibleCustomColumnsBindingSource.DataSource = _visibleCustomColumns; lstAllColumns.DataSource = _allCustomColumnsBindingSource; lstCurrentColumns.DisplayMember = "Description"; lstCurrentColumns.DataSource = _visibleCustomColumnsBindingSource; tabStrategies.TabPages.Remove(tabSort); tabStrategies.TabPages.Remove(tabColumnOrder); tabStrategies.TabPages.Remove(tabAlerts); tabStrategies.TabPages.Remove(tabStrategy); tabStrategies.TabPages.Remove(tabExchange); tabStrategies.TabPages.Remove(tabWindowName); tabStrategies.TabPages.Remove(tabSearch); tabStrategies.TabPages.Remove(tabSymbolList); tabStrategies.TabPages.Remove(tabWindowsSpecificFilters); _AIConfig = config; } break; } _windowPrefix = "ConfigWindow." + useCaseName; bool loggedIn = (connectionMaster.LoginManager.AccountStatus == AccountStatus.Good); bool isDemo = connectionMaster.LoginManager.IsDemo; if (!loggedIn) tabStrategies.TabPages.Remove(tabSymbolList); //For dealing with alert-filter icon display... if (!IsHandleCreated) { CreateHandle(); } _imageCacheManager.CachedImageAvailable -= new CachedImageAvailable(_imageCacheManager_CachedImageAvailable); _imageCacheManager.CachedImageAvailable += new CachedImageAvailable(_imageCacheManager_CachedImageAvailable); // this.pnlSort.MouseHover += new EventHandler(pnlSort_MouseHover); _fontManager = new FontManager(this, DEFAULT_FONT_SIZE); _fontManager.selectTheFont(); // Tree views are not coveredd by the fontmanager. strategyTreeView.Font = Font; _tvSymbolList.Font = Font; btnFind.Font = btnHelp.Font; if (_oldFont == null) _oldFont = Font; // The right number of pixels seems to depend on the computer. So I try to estimate a good // size based on the current font and icon width Width = (int)Math.Round(CreateGraphics().MeasureString("Distance from Inside Market Dollars/Share x Shares/Day", Font).Width * 2.1) + 50 + (int)GuiEnvironment.ICON_WIDTH * 3; Icon = GuiEnvironment.Icon; if ((_configWindowHeight == -1 && _configWindowWidth == -1) || (!_oldFont.Equals(Font))) { _configWindowWidth = Width; _configWindowHeight = Height; _oldFont = Font; //Save font of currently resized window } PopulateStrings(); if (_columnChooserMode) { tabStrategies.TabPages.Remove(tabAlerts); tabStrategies.TabPages.Remove(tabWindowsSpecificFilters); tabStrategies.TabPages.Remove(tabExchange); tabStrategies.TabPages.Remove(tabSymbolList); tabStrategies.TabPages.Remove(tabWindowName); tabStrategies.TabPages.Remove(tabStrategy); tabStrategies.SelectedTab = tabColumns; btnFlip.Enabled = false; } else if (_configurationType == ConfigurationType.MultiStrategy) { tabStrategies.TabPages.Remove(tabAlerts); tabStrategies.TabPages.Remove(tabWindowName); tabStrategies.TabPages.Remove(tabStrategy); tabStrategies.TabPages.Remove(tabColumns); tabStrategies.TabPages.Remove(tabSort); tabStrategies.TabPages.Remove(tabWindowName); tabStrategies.SelectedTab = tabWindowsSpecificFilters; btnShowColumn.Visible = false; btnFlip.Enabled = false; } else if (_configurationType == ConfigurationType.CustomColumns) { btnFlip.Visible = false; btnColumnsHideUnused.Visible = false; btnAddDefaultColumn.Visible = false; btnColumnSeek.Visible = false; btnColumnShowAll.Visible = false; } //set check-box for using advanced window chkUseAdvancedConfig.Checked = !GuiEnvironment.SmallConfigWindow; /*After the font has been adjusted with _fontManager.selectTheFont(), we now adjust the combo box within the SymbolList tab. The longest item will be what the length of the combo box will be set to (plus a little extra). The longest item will depend upon the language chosen...*/ _symbolListCombo.Add(TextRenderer.MeasureText(_phrases.Node("RADIO_ALL").PropertyForCulture("TEXT", "***"), Font).Width); _symbolListCombo.Add(TextRenderer.MeasureText(_phrases.Node("RADIO_ONLY").PropertyForCulture("TEXT", "***"), Font).Width); _symbolListCombo.Add(TextRenderer.MeasureText(_phrases.Node("RADIO_EXCLUDE").PropertyForCulture("TEXT", "***"), Font).Width); _symbolListCombo.Add(TextRenderer.MeasureText(_phrases.Node("RADIO_EXCLUDE").PropertyForCulture("TEXT", "***"), Font).Width); cboSelectionCombo.Width = _symbolListCombo.Max() + (cboSelectionCombo.Width / 10); // create the event handler for the symbol list treeview _tvSymbolList.SymbolListChosen -= new SymbolListChosen(_tvSymbolList_SymbolListChosen); _tvSymbolList.SymbolListChosen += new SymbolListChosen(_tvSymbolList_SymbolListChosen); int distanceFromTabBottom = tabSymbolList.Bottom - btnCreateNewList.Top + 25; Size panelSize = new Size(buttonAddListToCommon.Right - cboSelectionCombo.Left, tabSymbolList.Height - distanceFromTabBottom); //Size panelSize = new Size(buttonAddListToCommon.Left - 20 - cboSelectionCombo.Left, tabSymbolList.Bottom - 10 - cboSelectionCombo.Bottom - 15); _panelCommonSymbolLists.Size = panelSize; _panelCommonSymbolLists.Location = new Point(cboSelectionCombo.Left, cboSelectionCombo.Bottom + 5); _panelCommonSymbolLists.SymbolListEnableChanged += new SymbolListEnableChangedDelegate(_panelCommonSymbolLists_SymbolListEnableChanged); _panelCommonSymbolLists.SymbolListRemoved += new SymbolListRemovedDelegate(_panelCommonSymbolLists_SymbolListRemoved); tabSymbolList.Controls.Add(_panelCommonSymbolLists); if (fromScratch) btnOK.Enabled = true; btnShowColumn.Text = _phrases.Node("SHOW_COLUMN").PropertyForCulture("TEXT", "***"); // At one time we were showing this if we were in the OddsMaker columns window. //btnShowColumn.Text = _phrases.Node("ADD_COLUMN").PropertyForCulture("TEXT", "***"); setAITheme(); // Store these in a dictionary now, because it's easier than having a big if/elseif/elseif statement later. _tabPageTrackingCodes[tabStrategy] = _windowPrefix + ".StrategiesTab"; _tabPageTrackingCodes[tabSearch] = _windowPrefix + ".SearchTab"; _tabPageTrackingCodes[tabAlerts] = _windowPrefix + ".SelectAlertsTab"; _tabPageTrackingCodes[tabWindowsSpecificFilters] = _windowPrefix + ".WSFTab"; _tabPageTrackingCodes[tabExchange] = _windowPrefix + ".ExchangesTab"; _tabPageTrackingCodes[tabSymbolList] = _windowPrefix + ".SymbolListTab"; _tabPageTrackingCodes[tabColumns] = _windowPrefix + ".ColumnsTab"; _tabPageTrackingCodes[tabSort] = _windowPrefix + ".SortTab"; _tabPageTrackingCodes[tabWindowName] = _windowPrefix + ".WindowNameTab"; // NEW SYMBOL LOOKUP //if (GuiEnvironment.DevelopmentMode) //{ string apiURL = GuiEnvironment.AppConfig.Node("SYMBOL_LOOKUP").Property("API_URL", ""); int symbolLimit = GuiEnvironment.AppConfig.Node("SYMBOL_LOOKUP").Property("SYMBOL_LIMIT", -1); int keystrokePause = GuiEnvironment.AppConfig.Node("SYMBOL_LOOKUP").Property("KEYSTROKE_PAUSE", -1); txtSingleSymbol.Enabled = false; txtSingleSymbol.Visible = false; _symbolLookup = new SymbolLookupTextBox() { ApiUrl = apiURL, SymbolLimit = symbolLimit, KeyStrokePause = keystrokePause, }; _symbolLookup.TextBoxFont = Font; _symbolLookup.Visible = false; this.tabSymbolList.Controls.Add(_symbolLookup); _symbolLookup.Size = new Size(tabSymbolList.Width - (cboSelectionCombo.Left * 2), 23); _symbolLookup.Location = new Point(cboSelectionCombo.Left, cboSelectionCombo.Bottom + 7); _symbolLookup.AutoSetHeight(); _symbolLookup.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; _symbolLookup.symbolSelected += SymbolUpdated; _symbolLookup.symbolTextValidated += SymbolValidated; //} } private void ClearListBoxes() { foreach (var item in _listBoxes) { item.Items.Clear(); } } private void AddListBoxes() { this.listBoxPanel1.SuspendLayout(); for (int i = 0; i < _columnCount; i++) { ListBox listBox = new ListBox() { Size = new System.Drawing.Size(250, listBoxPanel1.Height - 20), Location = new Point(i * 250 + 5*i,0), BackColor = SystemColors.Control, DrawMode = DrawMode.OwnerDrawVariable, FormattingEnabled = true, ItemHeight = 16, Name = "lst-"+i, Tag = i, }; listBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.DrawItem); listBox.MeasureItem += new System.Windows.Forms.MeasureItemEventHandler(this.MeasureItem); listBox.SelectedIndexChanged += new System.EventHandler(this.lst_SelectedIndexChanged); this.listBoxPanel1.Controls.Add(listBox); _listBoxes.Add(listBox); } this.listBoxPanel1.ResumeLayout(); } private void setAITheme() { if (_configurationType == ConfigurationType.CustomColumns) { this.BackColor = Color.FromArgb(1, 53, 79); tabColumns.BackColor = Color.FromArgb(1, 53, 79); tabColumns.Margin = Padding.Empty; lblSelectedColumns.ForeColor = Color.White; lstAllColumns.BackColor = Color.Black; lstCurrentColumns.BackColor = Color.Black; Text = "AI Column Config"; } } public void showWaitPanel() { pnlWait.BringToFront(); pnlWait.Visible = true; } public void hideWaitPanel() { pnlWait.Visible = false; } void _panelCommonSymbolLists_SymbolListRemoved(SymbolList symbolList) { if (GuiEnvironment.CommonSymbolListCodes.Contains(symbolList.InternalCode)) GuiEnvironment.CommonSymbolListCodes.Remove(symbolList.InternalCode); _tvSymbolList.UnhighlightNode(symbolList); PrepairedStrategy strategy = _alertStrategy as PrepairedStrategy; if (null == strategy) strategy = _topListStrategy as PrepairedStrategy; if (null == strategy) strategy = _strategy as PrepairedStrategy; if (strategy.SymbolLists.Contains(symbolList)) _panelCommonSymbolLists_SymbolListEnableChanged(symbolList, false); _multiEditSymbolListChanges = true; } /// /// This gets called when the user enables or disables a symbol list. /// /// The symbol list itself /// True if enabled, false if disabled void _panelCommonSymbolLists_SymbolListEnableChanged(SymbolList symbolList, bool listEnabled) { btnOK.Enabled = true; PrepairedStrategy strategy = _alertStrategy as PrepairedStrategy; if (null == strategy) strategy = _topListStrategy as PrepairedStrategy; if (null == strategy && null != _strategy) strategy = _strategy; _multiEditSymbolListChanges = true; Debug.Assert(null != strategy); SymbolListDisposition _selectedListDisposition = (SymbolListDisposition)cboSelectionCombo.SelectedValue; if (listEnabled && !strategy.SymbolLists.Contains(symbolList)) { strategy.SymbolLists.Add(symbolList); } else if (!listEnabled && strategy.SymbolLists.Contains(symbolList)) { strategy.SymbolLists.Remove(symbolList); } if (_configurationType == ConfigurationType.MultiStrategy) { //The code above relates to the configwindow generated from a single strategy. //When the multiconfig version of this ConfigWindow is used, this //is the if-block that you need. Unlike the "normal version" of ConfigWindow,When you check/uncheck a symbolist, that //symbolist will be checked/uncheck in all strategies. The "square" box is produced only by the app itself. The user // cannot produce a "square" in the checkbox (i.e. user can't produce indeterminite state) if (_symbolListMultiSelectStatus.ContainsKey(symbolList)) { if (listEnabled) { _symbolListMultiSelectStatus[symbolList] = MultiSelectStatus.All; foreach (KeyValuePair kvp in _loadedMultiStrategies) { if (!(kvp.Value).SymbolLists.Contains(symbolList)) { (kvp.Value).SymbolLists.Add(symbolList); } } } else { _symbolListMultiSelectStatus[symbolList] = MultiSelectStatus.None; foreach (KeyValuePair kvp in _loadedMultiStrategies) { if ((kvp.Value).SymbolLists.Contains(symbolList)) { (kvp.Value).SymbolLists.Remove(symbolList); } } } } } if (listEnabled && _selectedListDisposition == SymbolListDisposition.All) { strategy.SymbolListDisposition = SymbolListDisposition.OnlyThese; cboSelectionCombo.SelectedValue = SymbolListDisposition.OnlyThese; } if (listEnabled) _tvSymbolList.HighlightAndSelectNode(symbolList); else _tvSymbolList.HighlightNode(symbolList); } private void LoadCommonSymbolLists() { _commonSymbolLists.Clear(); foreach (string symbolListInternalCode in GuiEnvironment.CommonSymbolListCodes) { SymbolList symbolList = _configurationWindowManager.FindSymbolList(symbolListInternalCode); _commonSymbolLists.Add(symbolList); } } private void populateSearchListBoxContextMenu() { _listBoxSearchContext.Items.Add(_phrases.Node("HELP").PropertyForCulture("TEXT", "***"), null, new EventHandler(searchPopup)); //item [0] _listBoxSearchContext.Items.Add(_phrases.Node("ADD").PropertyForCulture("TEXT", "***"), null, new EventHandler(searchPopup)); //item [1] if (_isSingleStock) { _listBoxSearchContext.Items[1].Enabled = false; } if (_columnChooserMode) // Only showing columns, not filters. _listBoxSearchContext.Items[_listBoxSearchContext.Items.Count - 1].Enabled = false; _listBoxSearchContext.Items.Add(_phrases.Node("SHOW_AS_COLUMN").PropertyForCulture("TEXT", "***"), null, new EventHandler(searchPopup)); //item [2] if (_dontShowColumns) { // Disable the "Show Column" item. _listBoxSearchContext.Items[_listBoxSearchContext.Items.Count - 1].Enabled = false; } _listBoxSearchContext.Items.Add(_phrases.Node("SORT_BY").PropertyForCulture("TEXT", "***"), null, new EventHandler(searchPopup)); //item [2] if (_isSingleStock) { _listBoxSearchContext.Items[_listBoxSearchContext.Items.Count - 1].Enabled = false; } _listBoxSearchContext.Items.Add(_phrases.Node("SHOW_ME").PropertyForCulture("TEXT", "***"), null, new EventHandler(searchPopup)); //item [3] _listBoxSearchContext.Items[_listBoxSearchContext.Items.Count - 1].Image = cbtImageList.Images[0]; } private ContextMenuStrip createIconPopup(string iconID, string wSF, string filterInternalCode) { //Context menu popup for icons in Strategy tab and WindowName tab ContextMenuStrip iconPopup = new ContextMenuStrip(); //Here, we'll set up the popup(contextmenu) for icons within the strategy tab and //Window Name tab. iconPopup.Items.Add(_phrases.Node("HELP").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); //item [0] if (iconID == "Alert") { iconPopup.Items.Add(_phrases.Node("MODIFY_ALERT").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); //item [1] } else { iconPopup.Items.Add(_phrases.Node("MODIFY_FILTER").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); //item [1] } if (iconID == "Filter") { iconPopup.Items.Add(_phrases.Node("SHOW_AS_COLUMN").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); //item [2] if (_dontShowColumns) { // Disable the "Show Column" item. iconPopup.Items[iconPopup.Items.Count - 1].Enabled = false; } iconPopup.Items.Add(_phrases.Node("SHOW_ME").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); iconPopup.Items[iconPopup.Items.Count - 1].Image = cbtImageList.Images[0]; if (filterInternalCode != "") //check to see if we make the "Show Me" visible or not-this depends on whether there's material present... { if (ConfigDemoUserControl.Available(filterInternalCode)) { iconPopup.Items[iconPopup.Items.Count - 1].Visible = true; } else { iconPopup.Items[iconPopup.Items.Count - 1].Visible = false; } } } if (_configurationType == ConfigurationType.TopList) { if (!_isSingleStock) { iconPopup.Items.Add(_phrases.Node("SORT_BY").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); //item [3] } } if (wSF == "WSF") { iconPopup.Items[1].Visible = false; } return iconPopup; } private void PopulateStrings() { // Note: I see no need to implement ICultureChanged in this window. It is a modal dialog box // which is never reused. Calling this method in the constructor should be sufficient. //Tab Names... tabStrategy.Text = _phrases.Node("STRATEGIES").PropertyForCulture("TEXT", "***"); tabAlerts.Text = _phrases.Node("SELECT_ALERTS").PropertyForCulture("TEXT", "***"); tabWindowsSpecificFilters.Text = _phrases.Node("WINDOW_SPECIFIC_FILTERS").PropertyForCulture("TEXT", "***"); tabExchange.Text = _phrases.Node("EXCHANGES").PropertyForCulture("TEXT", "***"); tabSymbolList.Text = _phrases.Node("SYMBOL_LISTS").PropertyForCulture("TEXT", "***"); tabColumns.Text = _phrases.Node("COLUMNS").PropertyForCulture("TEXT", "***"); tabSort.Text = _phrases.Node("SORT").PropertyForCulture("TEXT", "***"); tabWindowName.Text = _phrases.Node("WINDOW_NAME").PropertyForCulture("TEXT", "***"); // Now called "summary". //Labels within each tab.... lblSearchCategory.Text = _phrases.Node("CATEGORY").PropertyForCulture("TEXT", "***"); lblSearchTabTerms.Text = _phrases.Node("SEARCH_TERMS").PropertyForCulture("TEXT", "***"); lblMin.Text = _phrases.Node("MINIMUM").PropertyForCulture("TEXT", "***"); lblMax.Text = _phrases.Node("MAXIMUM").PropertyForCulture("TEXT", "***"); lblSelectedColumns.Text = _phrases.Node("SELECTED_COLUMNS").PropertyForCulture("TEXT", "***"); lblSummary.Text = _phrases.Node("CURRENT_STRATEGY_DESC").PropertyForCulture("TEXT", "***"); // Reset the font size of the wait text lblWait.Font = new Font("Arial", 24); lblWait.Text = _phrases.Node("WAIT_LABEL").PropertyForCulture("TEXT", "***"); //lblAllColumns.Text = _phrases.Node("ALL_COLUMNS").PropertyForCulture("TEXT", "***"); groupRadio.Text = _phrases.Node("SORT_BY").PropertyForCulture("TEXT", "***"); rdoBiggest.Text = _phrases.Node("BIGGEST_ON_TOP").PropertyForCulture("TEXT", "***"); rdoSmallest.Text = _phrases.Node("SMALLEST_ON_TOP").PropertyForCulture("TEXT", "***"); lblChanges.Text = _phrases.Node("CHANGED_ITEMS").PropertyForCulture("TEXT", "***"); if (_notAWindow) // Something like "Strategy Name:" lblWindowName.Text = _phrases.Node("WINDOW_NAME_LABEL_STRATEGY").PropertyForCulture("TEXT", "***"); else // Something like "Window Name:" lblWindowName.Text = _phrases.Node("WINDOW_NAME_LABEL").PropertyForCulture("TEXT", "***"); //load the combo box in SymbolList tab _symbolListDispositions.Add(SymbolListDisposition.All, _phrases.Node("RADIO_ALL").PropertyForCulture("TEXT", "***")); _symbolListDispositions.Add(SymbolListDisposition.OnlyThese, _phrases.Node("RADIO_ONLY").PropertyForCulture("TEXT", "***")); _symbolListDispositions.Add(SymbolListDisposition.ExcludeThese, _phrases.Node("RADIO_EXCLUDE").PropertyForCulture("TEXT", "***")); _symbolListDispositions.Add(SymbolListDisposition.SingleSymbol, _phrases.Node("RADIO_SINGLE_SYMBOL").PropertyForCulture("TEXT", "***")); cboSelectionCombo.DataSource = new BindingSource(_symbolListDispositions, null); cboSelectionCombo.DisplayMember = "Value"; cboSelectionCombo.ValueMember = "Key"; //cboSelectionCombo.SelectedIndex = 0; //cboSelectionCombo.SelectedValue = SymbolListDisposition.All; //buttons btnFlip.Text = _phrases.Node("FLIP").PropertyForCulture("TEXT", "***"); btnLoadSet.Text = _phrases.Node("LOAD_SETTINGS").PropertyForCulture("TEXT", "***"); btnOK.Text = _commonPhrases.Node("OK").PropertyForCulture("TEXT", "***"); btnCancel.Text = _commonPhrases.Node("CANCEL").PropertyForCulture("TEXT", "***"); btnHelp.Text = _phrases.Node("HELP").PropertyForCulture("TEXT", "***"); btnFind.Text = _phrases.Node("ADD").PropertyForCulture("TEXT", "***"); btnShowColumn.Text = _phrases.Node("SHOW_COLUMN").PropertyForCulture("TEXT", "***"); btnSortBy.Text = _phrases.Node("SORT_BY").PropertyForCulture("TEXT", "***"); btnHideUnused.Text = _phrases.Node("HIDE_UNUSED").PropertyForCulture("TEXT", "***"); btnShowAll.Text = _phrases.Node("SHOW_ALL").PropertyForCulture("TEXT", "***"); btnFilterHideUnused.Text = _phrases.Node("HIDE_UNUSED").PropertyForCulture("TEXT", "***"); btnColumnsHideUnused.Text = _phrases.Node("HIDE_UNUSED").PropertyForCulture("TEXT", "***"); btnColumnShowAll.Text = _phrases.Node("SHOW_ALL").PropertyForCulture("TEXT", "***"); btnFilterShowAll.Text = btnShowAll.Text = _phrases.Node("SHOW_ALL").PropertyForCulture("TEXT", "***"); btnSearchClearAll.Text = _phrases.Node("CLEAR_ALL").PropertyForCulture("TEXT", "***"); btnSortHideUnused.Text = _phrases.Node("HIDE_UNUSED").PropertyForCulture("TEXT", "***"); btnSortShowAll.Text = _phrases.Node("SHOW_ALL").PropertyForCulture("TEXT", "***"); btnAddDefaultAlert.Text = btnAddDefaultFilter.Text = btnAddDefaultColumn.Text = btnAddDefaultSort.Text = _phrases.Node("ADD_DEFAULTS").PropertyForCulture("TEXT", "***"); btnSeek.Text = btnFilterSeek.Text = btnColumnSeek.Text = btnSortSeek.Text = _phrases.Node("MORE").PropertyForCulture("TEXT", "***"); //using advanced window check box chkUseAdvancedConfig.Text = _phrases.Node("SMALL_CONFIG").PropertyForCulture("TEXT", "***"); //Tool Tips toolTip1.SetToolTip(this.showMeButton, _phrases.Node("SHOW_ME").PropertyForCulture("TEXT", "***")); toolTip1.SetToolTip(btnAdd, _phrases.Node("ADD").PropertyForCulture("TEXT", "***")); toolTip1.SetToolTip(btnRemove, _phrases.Node("REMOVE").PropertyForCulture("TEXT", "***")); toolTip1.SetToolTip(btnUp, _phrases.Node("MOVE_UP").PropertyForCulture("TEXT", "***")); toolTip1.SetToolTip(btnDown, _phrases.Node("MOVE_DOWN").PropertyForCulture("TEXT", "***")); //localization for button that is borrowed from the SymbolListForm btnCreateNewList.Text = GuiEnvironment.XmlConfig.Node("SYMBOL_LIST").Node("PHRASES").Node("CREATE_NEW_LIST").PropertyForCulture("TEXT", "***"); GuiEnvironment.HideCheckBox(chkUseAdvancedConfig); } // This is strictly for performance. It's possible that we will get a lot of // repeated callbacks from _imageCacheManager_CachedImageAvailable. There is // no need to answer all of them. If one is pending -- if the other thread // told us to do an update but we haven't done it yet -- and additional // notifications come, we only have to do the update once. private volatile bool _imageUpdatePending = false; // This seems to help a lot when we are first displaying the config window. // I wonder if we will have similar problems once other parts of the program // start sending other pictures, like the charts. We might still be wasting // a lot of time in this callback. private delegate void DoUpdate(); void _imageCacheManager_CachedImageAvailable() { if (InvokeRequired) { if (!_imageUpdatePending) { _imageUpdatePending = true; BeginInvoke((MethodInvoker)_imageCacheManager_CachedImageAvailable); } } else { if (IsDisposed) { return; } _imageUpdatePending = false; ReDisplayImages(); ReDisplayAlerts(); ReDisplayFilters(); ReDisplayRecentChanges(); } } private void SetStrategy(PrepairedStrategy strategy) { _strategy = strategy; _alertStrategy = strategy as AlertStrategy; _topListStrategy = strategy as TopListStrategy; } private void SetMultiStrategyColumns() { //The following code replaces the default Columns in this strategy //for Columns currently used in the MultiStrategy window if (_alertStrategy.Columns.Count > 0) { List newColumns = new List(); string originalConfigString = _alertStrategy.OriginalConfigString; string[] colParts = originalConfigString.Split(new string[] { "&show" }, StringSplitOptions.RemoveEmptyEntries); //Copy columns currently in the config string and in Columns to the newColumns foreach (IDisplayColumn column in _alertStrategy.Columns) { for (int i = 0; i < colParts.Length; i++) { //Skip first string found since this contains no column data if (i == 0) continue; //Construct internal code from config string string internalCode = colParts[i].Substring(colParts[i].LastIndexOf('=') + 1); if (internalCode == column.InternalCode) { newColumns.Add(column); break; } } } //Add special column StrategyName // add parameter for form type - RVH20210602 //ColumnInfo strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME")); ColumnInfo strategyNameColumnInfo = new ColumnInfo(GuiEnvironment.XmlConfig.Node("MULTI_STRATEGY_WINDOW").Node("COLUMNS").Node("STRATEGY_NAME"), "MULTI_STRATEGY_WINDOW"); DisplayOnlyField displayOnlyField = new DisplayOnlyField("StrategyName", strategyNameColumnInfo.Description); if (originalConfigString.Contains("StrategyName") && newColumns.Count > 0 && newColumns[newColumns.Count - 1].Description != displayOnlyField.Description) { newColumns.Add(displayOnlyField as IDisplayColumn); } //Note that the following Columns are always present in the _alertStrategy.Columns: Symbol, Time, Type, and Description. //The config string passed via the Columns menu of the Multi-Strategy window may have these columns missing. //So we clear _alertStrategy.Columns and then add the columns that are included in the config string. if (newColumns.Count >= 0) { _alertStrategy.Columns.Clear(); _alertStrategy.Columns = newColumns; } } } private bool SkipStrategies() { // Ideally we'd check if the strategy tab was hidden. But the constructor would // have to be reorganized to make sure tabs were hidden before sending the config // request. return _columnChooserMode; } private void SetInitialConfig(string config) { if (_configurationWindowManager != null) { _configurationWindowManager.Abandon(); } _configurationWindowManager = new ConfigurationWindowManager(); _configurationWindowManager.LoadFromServer(_connectionMaster, _configurationType, OnLoaded, config, skipStrategies: SkipStrategies()); } private void OnLoaded(ConfigurationWindowManager configurationWindowManager) { /*This method "initializes" the config window when it is first pulled up...*/ if (InvokeRequired) { BeginInvoke((MethodInvoker)delegate { OnLoaded(configurationWindowManager); }); } else { // We could get here for a couple of reasons. 1) A normal call to create the // dialog box and we are in the correct thread. 2) The dialog box was closed // and disposed before we got this call. In case #2 we are probably not in the // GUI thread. But the image cache manager is thread safe. #2 probably means // that someone called PreloadImages(), and we wanted to load the images and // do nothing more. LoadImageCache(); // This is also thread safe. We call this because it's effecient; we already // have the data. The main program could call // ConfigDemo.HistogramInit(null, connectionMaster) directly, but that would // cause a second request for the same data. Also, the main program is already // calling PreloadImages() so why make the main program know about this call, // too. So the code is simpler, too. ConfigDemoHistogram.HistogramInit(configurationWindowManager, null); if (IsDisposed) return; if (configurationWindowManager != _configurationWindowManager) return; PopulateCategories(); if (_configuringFromOutside && (_setFromOutsideMinFilter.HasValue || _setFromOutsideMaxFilter.HasValue)) { if (null != configurationWindowManager.CurrentSettings) { Filter configFromOutsideFilter = configurationWindowManager.FindFilter(_outsideInternalCode); if (null != configFromOutsideFilter) { if (!configurationWindowManager.CurrentSettings.MaxFilters.ContainsKey(configFromOutsideFilter)) configurationWindowManager.CurrentSettings.MaxFilters.Add(configFromOutsideFilter, ""); if (!configurationWindowManager.CurrentSettings.MinFilters.ContainsKey(configFromOutsideFilter)) configurationWindowManager.CurrentSettings.MinFilters.Add(configFromOutsideFilter, ""); } } } //////////////////////////// if (tabStrategies.SelectedTab == tabWindowsSpecificFilters) searchFilters(); else _needToInitializeFilterPanel = true; if (tabStrategies.SelectedTab == tabColumns) loadAllColumnsList(); else _needToInitializeColumnsList = true; if (tabStrategies.SelectedTab == tabAlerts) searchAlerts(); else _needToInitializeAlertPanel = true; //////Simplified Config Window Code if (tabStrategies.SelectedTab == tabSearch) useTheSearchTab(); else _needToInitializeSearchBox = true; ////////////////////////////// /*NOTE: Putting methods such as drawSelectAlertsTab() and drawFilters() within this OnLoaded Method causes the GUI to hang for quite a while-which is why (in the case of the _alertStrategy) I had executed those two methods as events when one clicks on the Alerts tab or Windows Specific tab...the populating seems to go faster...*/ AddStrategyNodes(); //here we adjust the item height so that some of the //entries within the tree will not "run together" upon a font change strategyTreeView.ItemHeight = Font.Height + 3; if (_configurationWindowManager.CurrentSettings == null) { if (_configurationType == ConfigurationType.Alerts) SetStrategy(new AlertStrategy()); else SetStrategy(new TopListStrategy()); } else { if (_configurationType == ConfigurationType.Alerts) { SetStrategy(new AlertStrategy(_configurationWindowManager.CurrentSettings)); // This is the best place to set the multi-strategy columns if (_columnChooserMode && !_dontShowColumns && !_usingOddsMaker) { SetMultiStrategyColumns(); } } else SetStrategy(new TopListStrategy(_configurationWindowManager.CurrentSettings)); } //Must move here so that the proper exchange boxes can be checked... loadTheExchanges(); loadTheSymbolLists(); if (_configurationType == ConfigurationType.TopList) { if (null == _configurationWindowManager.CurrentSettings) txtWindowName.Text = ""; else txtWindowName.Text = _configurationWindowManager.CurrentSettings.WindowName; } showCurrentSettingsOnStartup(); if (_configuringFromOutside && (_setFromOutsideMinFilter.HasValue || _setFromOutsideMaxFilter.HasValue)) { if (null != _configureFromOutsideMaxTextBox) MarkFilterChanged(_configureFromOutsideMaxTextBox, _outsideInternalCode); if (null != _configureFromOutsideMinTextBox) MarkFilterChanged(_configureFromOutsideMinTextBox, _outsideInternalCode); } if (_into[_into.Count - 1].Text != "Current Settings") { //creating a "blank" strategy object... /*This if-block makes sure that when a new MultiStrategy window is first configured, that there won't be any spurious icons of alerts/filters and text in the right-hand side of the strategies tab.*/ _connectionMaster.StreamingAlertsManager.GetAlerts("&WN=Blank+Strategy"); iconFlowLayoutPanel.Controls.Clear(); txtWindowName.Text = ""; } //set the keystroke delays for the search boxes within // the Search tab // 100 ms was too fast! It would update several times during normal typing. txtSearchTerms.Delay = 250; if (!_fromScratch && !(_configuringFromOutside && (_setFromOutsideMaxFilter.HasValue || _setFromOutsideMinFilter.HasValue))) btnOK.Enabled = false; if (_serverSortFromOutside) { /*Strangely enough, this was the crucial point to activate the OK button when doing the serversort from another window (e.g. the Server Sort on ColumnFilter context menu item*/ btnOK.Enabled = true; } if (_configuringFromOutside) { /*Really weird, but when carfully stepping through code when invoking the config window from outside source (e.g. a TopList window), in order to get the selected filter to scroll to its appropriate position, the below line had to be placed in *this* method*/ recolorLabels(filtersPanel); //we need to strip away the "WSF_" and "Max" or "Min" (7 char total) to get the //actual internal code of the item in question for "bolding" purposes string highlightCode = _outsideICode.Remove(0, 7); highLightLabels(filtersPanel, highlightCode); scrollToItem(_outsideICode, filtersPanel); } } if (_columnChooserMode == true) { /*This was found to be the optimal point in the code to place this if-block. For a strange reason, when the modified verson of the config window is prepared (only the "columns" tab.,the current columns already present do not populate the current-columns panel. If one were to,say, enter something in the search text, or even change the index of the combo-box, the current selected filters will finally appear. But of course we don't want the user to have to do that. We want to see all the pertinent info from the moment the window is brought into view. This if-block takes care of that.*/ loadAllColumnsList(); } } private void PopulateCategories() { //create the list of Category structs from all of the alert and filter categories foreach (string s in _configurationWindowManager.Categories) { Category category; category.rawString = s; category.userViewString = GetPleasingCategoryString(s); _categoryList.Add(category); } //bool tester = _columnChooserMode; /////Code for simpler config window. Combo and text box in Search Tab///////// cboSearchCategory.Items.Clear(); if (_configurationType == ConfigurationType.Alerts) { if (_columnChooserMode == false) { cboSearchCategory.Items.Clear(); cboSearchCategory.Items.Add(_phrases.Node("ALL_ALERTS_AND_FILTERS").PropertyForCulture("TEXT", "***")); foreach (Category c in _categoryList) { cboSearchCategory.Items.Add(c.userViewString); } } else { cboSearchCategory.Items.Clear(); cboSearchCategory.Items.Add(_phrases.Node("ALL_FILTERS").PropertyForCulture("TEXT", "***")); foreach (string s in _configurationWindowManager.CategoriesFilters) { cboSearchCategory.Items.Add(GetPleasingCategoryString(s)); } } } else //topList { cboSearchCategory.Items.Add(_phrases.Node("ALL_FILTERS").PropertyForCulture("TEXT", "***")); foreach (string s in _configurationWindowManager.CategoriesFilters) { cboSearchCategory.Items.Add(GetPleasingCategoryString(s)); } } cboSearchCategory.SelectedIndex = 0; ///////////////////////////// populateSearchListBoxContextMenu(); lstSearchResults.ContextMenuStrip = _listBoxSearchContext; } private void AddStrategyNodes() { strategyTreeView.Nodes.Clear(); lblStrategyDescriptionLabel.Text = ""; StrategyNode top = _configurationWindowManager.StrategyTree; if (top == null) { return; } if (top.IsFolder()) { foreach (StrategyNode node in top.Children) { AddStrategyNodes(node, strategyTreeView.Nodes); } } else { // We should never get here. The way our library parses the message from the // server, there has to be a folder on top. //AddStrategyNodes(top, null); Debug.Assert(false); } } private void AddStrategyNodes(StrategyNode top, TreeNodeCollection into) { TreeNode newNode = new TreeNode(top.Name); switch (top.Icon) { case "+": newNode.ImageIndex = 4; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); break; case "-": newNode.ImageIndex = 5; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); break; case "*": newNode.ImageIndex = 2; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); break; case "folder": newNode.ImageIndex = 3; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); break; case ":)": //current settings if (_configurationType == ConfigurationType.TopList) // not configured on the server yet, but we're ready newNode.ImageIndex = 7; else newNode.ImageIndex = 6; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); _settingsNode = newNode; break; default: newNode.ImageIndex = 0; newNode.SelectedImageIndex = newNode.ImageIndex; newNode.Name = _nodeNameTally.ToString(); _dict.Add(newNode.Name, newNode.ImageIndex); break; } newNode.Tag = top; into.Add(newNode); _into = into; _nodeNameTally++; if (top.IsFolder()) { foreach (StrategyNode node in top.Children) { AddStrategyNodes(node, newNode.Nodes); } } } private void ShowFilterDetails(PrepairedStrategy strategy) { ConfigDemoInWords.DescribeInWords(_configurationWindowManager, strategy, testDescribeFiltersRichTextBox); } private void strategyTreeView_AfterSelect(object sender, TreeViewEventArgs e) { /* In VisualStudio go to the event properties for the Treeview and select this method for "After Select"*/ _selected = strategyTreeView.SelectedNode.Tag as StrategyNode; if (_selected != null && !_selected.IsFolder()) { ShowFilterDetails(_selected.PrepairedStrategy); // Just for the sake of debugging. Need to decide the best place to display this. if (strategyTreeView.SelectedNode.ImageIndex == 1) { btnLoadSet.Enabled = false; } else { btnLoadSet.Enabled = true; } _images.Clear(); _imageType.Clear(); iconFlowLayoutPanel.SuspendLayout(); RemoveControls(iconFlowLayoutPanel, typeof(PictureBox)); iconFlowLayoutPanel.ResumeLayout(); int? ageInSeconds = _selected.PrepairedStrategy.Age; if (null != ageInSeconds) lblStrategyDescriptionLabel.Text = _phrases.Node("YOU_LAST_STARTED_THIS_WINDOW").PropertyForCulture("TEXT") + ReadableElapsedTime((int)ageInSeconds) + "."; else if (_selected.Description == "These were your settings before you requested the configuration window.") lblStrategyDescriptionLabel.Text = _phrases.Node("THESE_WERE_YOUR_SETTINGS").PropertyForCulture("TEXT", "***"); else lblStrategyDescriptionLabel.Text = _selected.Description; iconFlowLayoutPanel.SetFlowBreak(lblStrategyDescriptionLabel, true); if (null != _selected.AlertStrategy) { foreach (Alert _alert in _selected.AlertStrategy.Alerts) { _images.Add(_alert); _imageType.Add(0); } } foreach (var pair in _selected.PrepairedStrategy.MaxFilters) { _images.Add(pair.Key); _imageType.Add(1); } foreach (var pair in _selected.PrepairedStrategy.MinFilters) { _images.Add(pair.Key); _imageType.Add(2); } showImage(_images, _imageType); } } private void showCurrentSettingsOnStartup() { _loadingComplete = false; if (_configurationType == ConfigurationType.Alerts) { if (_settingsNode != null) { _settingsNode.ImageIndex = 1; btnLoadSet.Enabled = false; StrategyNode mySetting = _settingsNode.Tag as StrategyNode; txtWindowName.Text = mySetting.PrepairedStrategy.WindowName; _images.Clear(); _imageType.Clear(); lblStrategyDescriptionLabel.Text = _phrases.Node("THESE_WERE_YOUR_SETTINGS").PropertyForCulture("TEXT", "***"); iconFlowLayoutPanel.SetFlowBreak(lblStrategyDescriptionLabel, true); foreach (Alert alert in mySetting.AlertStrategy.Alerts) { _images.Add(alert); _imageType.Add(0); loadAlertAndFilterList((object)alert); } foreach (var pair in mySetting.AlertStrategy.MaxFilters) { _images.Add(pair.Key); _imageType.Add(1); loadAlertAndFilterList((object)pair.Key); } foreach (var pair in mySetting.AlertStrategy.MinFilters) { _images.Add(pair.Key); _imageType.Add(2); loadAlertAndFilterList((object)pair.Key); } foreach (IDisplayColumn dc in _strategy.Columns) { loadAlertAndFilterList((object)dc); } _selected = mySetting; _currentAlert = mySetting.AlertStrategy; showImage(_images, _imageType); searchAlerts(); //populate alert tab with selected strategy icons searchFilters(); //populate filter tab with selected strategy icons } } else if (_configurationType == ConfigurationType.TopList) //topList { if (_settingsNode != null) { _settingsNode.ImageIndex = 1; btnLoadSet.Enabled = false; StrategyNode mySetting = _settingsNode.Tag as StrategyNode; _currentTopList = mySetting.TopListStrategy; txtWindowName.Text = _currentTopList.WindowName; //lblStrategyDescriptionLabel.Text = mySetting.Description.ToString(); lblStrategyDescriptionLabel.Text = _phrases.Node("THESE_WERE_YOUR_SETTINGS").PropertyForCulture("TEXT", "***"); _images.Clear(); _imageType.Clear(); iconFlowLayoutPanel.SetFlowBreak(lblStrategyDescriptionLabel, true); foreach (var pair in _currentTopList.MaxFilters) { _images.Add(pair.Key); _imageType.Add(1); loadAlertAndFilterList((object)pair.Key); } foreach (var pair in _currentTopList.MinFilters) { _images.Add(pair.Key); _imageType.Add(2); loadAlertAndFilterList((object)pair.Key); } foreach (IDisplayColumn c in _currentTopList.Columns) { //TODO is this filter only or also displayfield? if (c is Filter) { loadAlertAndFilterList((object)c); } } _selected = mySetting; showImage(_images, _imageType); setAlertAndFilterBoxes(_currentTopList); _recentChanges.Clear(); searchFilters(); lstSortSetUp(); } } else if (_configurationType == ConfigurationType.MultiStrategy) { _multiCombinedMaxFilters = GetCombinedFilters(true); _multiCombinedMinFilters = GetCombinedFilters(false); foreach (var pair in _multiCombinedMaxFilters) { _images.Add(pair.Key); _imageType.Add(1); loadAlertAndFilterList((object)pair.Key); } foreach (var pair in _multiCombinedMinFilters) { _images.Add(pair.Key); _imageType.Add(2); loadAlertAndFilterList((object)pair.Key); } showImage(_images, _imageType); setAlertAndFilterBoxes(null); _recentChanges.Clear(); searchFilters(); } _loadingComplete = true; hideWaitPanel(); } private Dictionary _multiCombinedMaxFilters = new Dictionary(); private Dictionary _multiCombinedMinFilters = new Dictionary(); private Dictionary _multiFilterTooltipText = new Dictionary(); private Dictionary GetCombinedFilters(bool useMaxFilters) { Dictionary filters = new Dictionary(); try { foreach (Filter filter in _configurationWindowManager.FiltersInOrder) { bool filterInUse = false; bool strategySeenWithoutFilter = false; string filterValue = ""; string toolTipText = ""; foreach (MultiStrategy.DataWatcher strategy in _multiStrategies) { if (_loadedMultiStrategies.ContainsKey(strategy)) { PrepairedStrategy alertStrategy = _loadedMultiStrategies[strategy]; string value = ""; if (useMaxFilters && alertStrategy.MaxFilters.ContainsKey(filter)) value = alertStrategy.MaxFilters[filter]; else if (!useMaxFilters && alertStrategy.MinFilters.ContainsKey(filter)) value = alertStrategy.MinFilters[filter]; if (value == "") toolTipText += "N/A " + strategy.Name + "\n"; else toolTipText += value + " " + strategy.Name + "\n"; if (filterInUse || (strategySeenWithoutFilter && value != "")) { filterInUse = true; if (filterValue != value) filterValue = MULTIPLE_VALUES; // XXXXX means filter is in use by at least two strategies and the filter values are not the same } else if (value != "") { filterInUse = true; filterValue = value; strategySeenWithoutFilter = true; } else strategySeenWithoutFilter = true; } } if (filterInUse) { string minmaxFilterName = filter.MaxCode; if (!useMaxFilters) minmaxFilterName = filter.MinCode; _multiFilterTooltipText.Add(minmaxFilterName, toolTipText); filters.Add(filter, filterValue); } } } catch (Exception e) { string debugView = e.ToString(); } return filters; } public List GetVisibleCustomColumns() { return _visibleCustomColumns; } private void btnOK_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.OK", _sendManager); if (_configurationType == ConfigurationType.CustomColumns) { DialogResult = System.Windows.Forms.DialogResult.OK; } else if (_columnChooserMode) { _symbolListsCacheManager.SymbolListsReadyUpdate -= _symbolListsCacheManager_ReadyUpdate; _imageCacheManager.CachedImageAvailable -= _imageCacheManager_CachedImageAvailable; DialogResult = System.Windows.Forms.DialogResult.OK; } else if (tabStrategies.SelectedTab != tabStrategy && tabStrategies.SelectedTab != tabWindowName && !_isSingleStock && _configurationType != ConfigurationType.MultiStrategy) { tabStrategies.SelectedTab = tabWindowName; } else { if (cboSelectionCombo.Items.Count != 0) //If user is logged in as DEMO, this cboSelectionCombo has no items... { SymbolListDisposition selectedSymbolListDisposition = (SymbolListDisposition)cboSelectionCombo.SelectedValue; if (selectedSymbolListDisposition == SymbolListDisposition.SingleSymbol) { // NEW SYMBOL LOOKUP //if (GuiEnvironment.DevelopmentMode) //{ if (_symbolLookup.GetSymbol() != "") { _panelCommonSymbolLists.ClearSymbolLists(); _strategy.SingleSymbol = _symbolLookup.GetSymbol(); } //} //else //{ // if (txtSingleSymbol.Text != "") // { // _panelCommonSymbolLists.ClearSymbolLists(); // _strategy.SingleSymbol = txtSingleSymbol.Text; // } //} } else _strategy.SingleSymbol = ""; } // Process the heartbeat alert if (_configurationType == ConfigurationType.Alerts) { if (returnToConfigWindow()) { // Stay in config window and show the alerts tab tabStrategies.SelectedTab = tabAlerts; return; } } if (_isSingleStock) { _strategy = _topListStrategy; } _symbolListsCacheManager.SymbolListsReadyUpdate -= _symbolListsCacheManager_ReadyUpdate; _imageCacheManager.CachedImageAvailable -= _imageCacheManager_CachedImageAvailable; DialogResult = System.Windows.Forms.DialogResult.OK; if (null != GuiEnvironment.AfterConfiguringCode) GuiEnvironment.AfterConfiguringCode(_strategy); } } /// /// ReturnToConfigWindow presents a messagebox that allows the user to keep or change an /// empty alert strategy (or a strategy with only the heartbeat alert) or calls to removes the Heartbeat alert from the strategy. /// Case 1: /// If no alerts are selected in the strategy, a message box displays a warning. This results in a heartbeat strategy /// Case 2: /// If the heartbeat alert is the only selected alert in the strategy, a message box displays a warining. This results in a heartbeat strategy /// Case 3: /// The heartbeat alert will be removed if the user started with a heartbeat strategy and the user selected additional alerts. (_removeHeartBeatAlert == true) /// Case 4: /// The heartbeat alert will not be removed if the heartbeat checkbox state changed by the user. (_removeHeartBeatAlert == false) /// /// /// Boolean == true : return back to the Alert tab of the Config window. /// == false : close Config window. /// /// private bool returnToConfigWindow() { string testString = ""; if (_alertStrategy.Alerts.Count() == 0) { testString = _phrases.Node("NO_ALERTS").PropertyForCulture("TEXT", "***"); } if (testString != "") { DialogResult dialogResult = MessageBox.Show(testString, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (dialogResult == DialogResult.Yes) return true; } else if (_removeHeartBeatAlert) removeHeartBeatAlert(); return false; } /// /// Remove heartbeat alert from current strategy. /// private void removeHeartBeatAlert() { foreach (Alert a in _alertStrategy.Alerts) { if (a.InternalCode == "HB") { _alertStrategy.Alerts.Remove(a); SetStrategy(_alertStrategy); break; } } } private void btnFlip_Click(object sender, EventArgs e) { if (!_loadingComplete) return; GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Flip", _sendManager); tabStrategies.SelectedTab = tabWindowName; btnLoadSet.Enabled = true; string FlipPrefix = "Flipped: "; if (_configurationType == ConfigurationType.Alerts) { _alertsFilterInQuestion.Clear(); //First, find out which alerts/filters are within the specified // strategy before the flip...These(string codes) will be added to the //Dictionary called "alertFiltersInQuestion" beforeFlipAlertStrategy(_alertStrategy); //Do the flip here... SetStrategy(_configurationWindowManager.Flip(_alertStrategy)); /*Now make sure that any alerts/filters within the flipped _alertStrategy are *not* duplicated in the alertsFilterInQuestion Dictionary. If an alert/filter is a dupe, then that particular alert/filter must be removed from the Dictionary . This is because after flipping, you need to show the icons(alert or filter) that *changed* * ...*/ foreach (Alert a in _alertStrategy.Alerts) { if (isFlipDuplicate(a.InternalCode)) { _alertsFilterInQuestion.Remove(a.InternalCode); } else { _alertsFilterInQuestion.Add(a.InternalCode, "~"); } } foreach (var f in _alertStrategy.MinFilters) { if (isFlipDuplicate(f.Key.MinCode, f.Value)) { _alertsFilterInQuestion.Remove(f.Key.MinCode); } else { /*When the filter after the flip has a differnt value in its textbox than before the flip, it is not considered a duplicate, thus upon adding to the dictionary, we might run into a "duplicate key" exception.(being that the key contains the filter code) * ...so before adding, gotta make sure that any previous key with the same name is deleted...*/ if (isFlipDuplicate(f.Key.MinCode)) { _alertsFilterInQuestion.Remove(f.Key.MinCode); } _alertsFilterInQuestion.Add(f.Key.MinCode, f.Value); } } foreach (var f in _alertStrategy.MaxFilters) { if (isFlipDuplicate(f.Key.MaxCode, f.Value)) { _alertsFilterInQuestion.Remove(f.Key.MaxCode); } else { if (isFlipDuplicate(f.Key.MaxCode)) { _alertsFilterInQuestion.Remove(f.Key.MaxCode); } _alertsFilterInQuestion.Add(f.Key.MaxCode, f.Value); } } foreach (var s in _alertsFilterInQuestion) { populateRecentChangesFromFlip(s.Key); } if (txtWindowName.Text.Contains(FlipPrefix)) { txtWindowName.Text = txtWindowName.Text.Replace(FlipPrefix, ""); } else { txtWindowName.Text = txtWindowName.Text.Insert(0, FlipPrefix); } //The below linkedlist,tempHolder, is a temporary placeholder for "recentChanges" //data. It's necessary when the panels have to be reset to display the new //pattern of checkmarks and textbox data for the flipped strategy (during //the panel reset, the recentChanges LinkedList gets cleared). Futhermore, //the integrity of the flipped _alertStrategy must be maintained as well because // it too, gets affected by the resetPanel-Hence the creation of a temporary //placeholder,tempAlertStrategy, as well... LinkedList tempHolder = new LinkedList(_recentChanges); AlertStrategy tempAlertStrategy = new AlertStrategy(_alertStrategy); resetPanels(); //restore the original flipped _alertStrategy SetStrategy(tempAlertStrategy); setAlertAndFilterBoxes(_alertStrategy); //depending upon strategy, this method can //inadvertenly change recentChanges.. //restore recentChanges... _recentChanges = tempHolder; showRecentChanges(sender, e); } else if (_configurationType == ConfigurationType.TopList) //toplist { _alertsFilterInQuestion.Clear(); //First, find out which filters are within the specified // strategy before the flip...These(string codes) will be added to the //Dictionary called "alertFiltersInQuestion" beforeFlipTopListStrategy(_topListStrategy); //do the flip... SetStrategy(_configurationWindowManager.Flip(_topListStrategy)); foreach (var f in _topListStrategy.MinFilters) { if (isFlipDuplicate(f.Key.MinCode, f.Value)) { _alertsFilterInQuestion.Remove(f.Key.MinCode); } else { if (isFlipDuplicate(f.Key.MinCode)) { _alertsFilterInQuestion.Remove(f.Key.MinCode); } _alertsFilterInQuestion.Add(f.Key.MinCode, f.Value); } } foreach (var f in _topListStrategy.MaxFilters) { if (isFlipDuplicate(f.Key.MaxCode, f.Value)) { _alertsFilterInQuestion.Remove(f.Key.MaxCode); } else { if (isFlipDuplicate(f.Key.MaxCode)) { _alertsFilterInQuestion.Remove(f.Key.MaxCode); } _alertsFilterInQuestion.Add(f.Key.MaxCode, f.Value); } } foreach (var s in _alertsFilterInQuestion) { populateRecentChangesFromFlip(s.Key); } if (txtWindowName.Text.Contains(FlipPrefix)) { txtWindowName.Text = txtWindowName.Text.Replace(FlipPrefix, ""); } else { txtWindowName.Text = txtWindowName.Text.Insert(0, FlipPrefix); } /*Same stuff for the TopListStrategy as AlertStrategy*/ LinkedList tempHolder = new LinkedList(_recentChanges); TopListStrategy tempTopStrategy = new TopListStrategy(_topListStrategy); resetPanels(); //restore the original flipped _topListStrategy SetStrategy(tempTopStrategy); setAlertAndFilterBoxes(_topListStrategy); //restore recentChanges... _recentChanges = tempHolder; showRecentChanges(sender, e); } } private void beforeFlipAlertStrategy(AlertStrategy alertStrategy) { /*This method is associated with the "flip" button and determines the alerts and filters before the flip Ultimately, they will be displayed as icons on the "recent changes" area in the WindowName panel. This method tailored for the alertStrategy*/ foreach (Alert a in alertStrategy.Alerts) { _alertsFilterInQuestion.Add(a.InternalCode, "~"); } foreach (var pair in alertStrategy.MinFilters) { string val; if (pair.Value != null) { val = pair.Value; } else { val = "~"; //dummy symbol...used a simple filler for a value } _alertsFilterInQuestion.Add(pair.Key.MinCode, val); } foreach (var pair in alertStrategy.MaxFilters) { string val; if (pair.Value != null) { val = pair.Value; } else { val = "~"; } _alertsFilterInQuestion.Add(pair.Key.MaxCode, val); } } private void beforeFlipTopListStrategy(TopListStrategy topList) { /*This method is also associated with the "flip" button but is tailored towards the topListStrategy*/ foreach (var pair in topList.MinFilters) { string val; if (pair.Value != null) { val = pair.Value; } else { val = "~"; } _alertsFilterInQuestion.Add(pair.Key.MinCode, val); } foreach (var pair in topList.MaxFilters) { string val; if (pair.Value != null) { val = pair.Value; } else { val = "~"; } _alertsFilterInQuestion.Add(pair.Key.MaxCode, val); } } private void showImage(List objects, List types) { /*This method displays alert/filter icons in the Strategies Tab*/ string testString = null; iconFlowLayoutPanel.SuspendLayout(); for (int i = 0; i < objects.Count; i++) { Alert alertImage; Filter filterImage; string filterInternalCode = ""; PictureBox pictureBox = new PictureBox(); pictureBox.MouseClick += new MouseEventHandler(pictureBox_MouseClick); pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; if ((objects[i] as Filter) != null) //filters will have "Show Me", which will be a visible menu item only if there's material present { filterImage = (Filter)objects[i]; // Icons have transparent border around the picture. So the layout looks the same // regardless of whether an image is an alert or a filter. pictureBox.BorderStyle = BorderStyle.None; filterInternalCode = filterImage.InternalCode; if (_imageType[i] == 1) //Max filter.. { string toolText = "Max " + filterImage.Description; Dictionary maxFilters = null; if ((null != _multiCombinedMaxFilters) && (_configurationType == ConfigurationType.MultiStrategy)) maxFilters = _multiCombinedMaxFilters; else if (null != _selected && null != _selected.PrepairedStrategy && null != _selected.PrepairedStrategy.MaxFilters) maxFilters = _selected.PrepairedStrategy.MaxFilters; if (null != maxFilters) { foreach (var maxPair in maxFilters) { if (filterImage.MaxCode == maxPair.Key.MaxCode && maxPair.Value != null) { toolText = toolText + " = " + maxPair.Value + " (" + maxPair.Key.Units + ")"; } } } toolTip.SetToolTip(pictureBox, toolText); pictureBox.Name = "WSF_" + filterImage.MaxCode; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(filterImage.MaxCode); }; } else { //Retrieve the data associated with the icon displayed in the Strategies tab..and put //it in the tool-tip string toolText = "Min " + filterImage.Description; //can be internal code Dictionary minFilters = null; if ((null != _multiCombinedMinFilters) && (_configurationType == ConfigurationType.MultiStrategy)) minFilters = _multiCombinedMinFilters; else if (null != _selected && null != _selected.PrepairedStrategy && null != _selected.PrepairedStrategy.MinFilters) minFilters = _selected.PrepairedStrategy.MinFilters; if (null != minFilters) { foreach (var minPair in minFilters) { if (filterImage.MinCode == minPair.Key.MinCode && minPair.Value != null) { string textValue = minPair.Value; double value; if (ServerFormats.TryParse(minPair.Value, out value)) textValue = value.ToString(); toolText = toolText + " = " + textValue + " (" + minPair.Key.Units + ")"; } } } toolTip.SetToolTip(pictureBox, toolText); pictureBox.Name = "WSF_" + filterImage.MinCode; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(filterImage.MinCode); }; } testString = "Filter"; } else { alertImage = (Alert)objects[i]; pictureBox.BorderStyle = BorderStyle.Fixed3D; // Alerts should fit perfectly within the 3D border. //Set up toolTips.. string toolText = alertImage.Description; if (null != _selected && null != _selected.AlertStrategy && _selected.AlertStrategy.Alerts != null) { foreach (var alert in _selected.AlertStrategy.AlertQuality) { if (alertImage.InternalCode == alert.Key.InternalCode && alert.Value != null) { string textValue = alert.Value; double value; if (ServerFormats.TryParse(alert.Value, out value)) textValue = value.ToString(); toolText = toolText + "; Filter = " + textValue + " (" + alert.Key.FilterDescription + ")"; } } } toolTip.SetToolTip(pictureBox, toolText); pictureBox.Name = alertImage.InternalCode; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetAlert(alertImage.InternalCode); }; // Test: The following line did not change the performance at all. //pictureBox.Image = _imageCacheManager.GetAlert(alertImage.InternalCode); testString = "Alert"; } pictureBox.ContextMenuStrip = createIconPopup(testString, "", filterInternalCode); pictureBox.ContextMenuStrip.Name = pictureBox.Name; pictureBox.Margin = new Padding(1); iconFlowLayoutPanel.Controls.Add(pictureBox); } ReDisplayImages(); iconFlowLayoutPanel.ResumeLayout(); } private void iconFlowLayoutPanel_MouseClick(object sender, MouseEventArgs e) { } private string ReadableElapsedTime(int secondsAgo) { List _timePhrases = GuiEnvironment.XmlConfig.Node("ALERTS").Node("COMMON"); string description = ""; if (secondsAgo < 2) { description = _timePhrases.Node("WITHIN_THE_LAST_SECOND").PropertyForCulture("TEXT", "***"); } else if (secondsAgo < 100) { description = secondsAgo + " " + _timePhrases.Node("SECONDS").PropertyForCulture("TEXT", "***") + " " + _timePhrases.Node("AGO").PropertyForCulture("TEXT", "***"); } else { int minutes = (secondsAgo + 30) / 60; if (minutes < 100) { description = minutes + " " + _timePhrases.Node("MINUTES").PropertyForCulture("TEXT", "***") + " " + _timePhrases.Node("AGO").PropertyForCulture("TEXT", "***"); } else { int hours = (secondsAgo + 1800) / 3600; if (hours <= 36) { description = hours + " " + _timePhrases.Node("HOURS").PropertyForCulture("TEXT", "***") + " " + _timePhrases.Node("AGO").PropertyForCulture("TEXT", "***"); } else { int days = (secondsAgo + 43200) / 86400; description = days + " " + _timePhrases.Node("DAYS").PropertyForCulture("TEXT", "***") + " " + _timePhrases.Node("AGO").PropertyForCulture("TEXT", "***"); } } } return description; } private void ReDisplayImages() { foreach (Control control in iconFlowLayoutPanel.Controls) { DoUpdate doUpdate = control.Tag as DoUpdate; if (null != doUpdate) { doUpdate(); } } } private void ReDisplayAlerts() { foreach (Control control in alertPanel.Controls) { DoUpdate alertUpdate = control.Tag as DoUpdate; if (null != alertUpdate) { alertUpdate(); } } } private void ReDisplayFilters() { foreach (Control control in filtersPanel.Controls) { DoUpdate filterUpdate = control.Tag as DoUpdate; if (null != filterUpdate) { filterUpdate(); } } } private void ReDisplayRecentChanges() { foreach (Control control in pnlRecentChanges.Controls) { DoUpdate changes = control.Tag as DoUpdate; if (null != changes) { changes(); } } } private void ReDisplaySummary() { foreach (Control control in pnlSummary.Controls) { DoUpdate changes = control.Tag as DoUpdate; if (null != changes) { changes(); } } } private void pictureBox_MouseClick(object sender, MouseEventArgs e) { if (e.Button == System.Windows.Forms.MouseButtons.Left) { btnFind_Click(sender, e); } } private void strategyIcon_MouseDoubleClick(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".LoadSettings", _sendManager); LoadSelectedStrategy(); } private void LoadSelectedStrategy() { _loadingComplete = false; loadSettings(); if (_configurationType == ConfigurationType.Alerts) { //Reset HideUnsued buttons for Alert btnHideUnused.Enabled = btnFilterHideUnused.Enabled = btnColumnsHideUnused.Enabled = true; _alertStrategy.SingleSymbol = ""; foreach (Alert a in _alertStrategy.Alerts) { loadAlertAndFilterList((object)a); } foreach (var pair in _alertStrategy.MaxFilters) { loadAlertAndFilterList((object)pair.Key); } foreach (var pair in _alertStrategy.MinFilters) { loadAlertAndFilterList((object)pair.Key); } searchAlerts(); //populate Alert Tab searchFilters(); //Populate Window Specific Filter Tab loadAllColumnsList(); //Populate All Column Panel in Columns Tab } else //top List configuration { //Reset HideUnsued buttons for Top List btnFilterHideUnused.Enabled = btnColumnsHideUnused.Enabled = btnSortHideUnused.Enabled = true; foreach (var pair in _topListStrategy.MaxFilters) { loadAlertAndFilterList((object)pair.Key); } foreach (var pair in _topListStrategy.MinFilters) { loadAlertAndFilterList((object)pair.Key); } /* The below for-loop makes sure that columns(filters) not seen in the strategy tab for a specific strategy will get added to the _visibleAlertAndFilterList*/ foreach (IDisplayColumn col in _strategy.Columns) { //TODO: should display fields get added here as well? if (col is Filter) { loadAlertAndFilterList((object)col); } } _topListStrategy.SingleSymbol = ""; lstSortSetUp(); //Populate Sort Tab searchFilters(); //Populate Window Specific Filter Tab loadAllColumnsList(); //Populate All Column Panel in Columns Tab } btnLoadSet.Enabled = false; btnOK.Enabled = true; _firstFilterView = false; _firstAlertsView = false; _loadingComplete = true; } //Creates ability to scroll thru the alerts or filters using the mouse wheel private void MouseWheelEvent(object sender, MouseEventArgs e) { if (tabStrategies.SelectedTab == tabAlerts) { alertPanel.Select(); } else if (tabStrategies.SelectedTab == tabWindowsSpecificFilters) { filtersPanel.Select(); } else if (tabStrategies.SelectedTab == tabColumns) { // allColumnsPanel.Select(); } else if (tabStrategies.SelectedTab == tabSearch) { lstSearchResults.Select(); } } private void tabStrategies_MouseClick(object sender, EventArgs e) //MouseEventArgs { //When user enters the tab, he/she is able to scroll thru the alerts/filters. if (tabStrategies.SelectedTab == tabAlerts) { alertPanel.Focus(); } else if (tabStrategies.SelectedTab == tabWindowsSpecificFilters) { filtersPanel.Focus(); } else if (tabStrategies.SelectedTab == tabColumns) { //allColumnsPanel.Focus(); } else if (tabStrategies.SelectedTab == tabSort) { lstSort.Focus(); } else if (tabStrategies.SelectedTab == tabSearch) { lstSearchResults.Focus(); } } private void pnlSort_MouseHover(object sender, EventArgs e) { lstSort.Focus(); } private void ckAlert_MouseClick(object sender, MouseEventArgs e) { /*When a checkbox for the alerts is checked..the "recentChanges" list gets updated.*/ CheckBox alertCheckBox = (CheckBox)sender; Alert alert = _configurationWindowManager.FindAlert(alertCheckBox.Name); if (alert != null) { if (_firstAlertsView && _firstFilterView && !btnOK.Enabled && !_fromScratch) { btnOK.Enabled = false; } else { btnOK.Enabled = true; } if (alertCheckBox.Checked == true) { _alertStrategy.Alerts.Add(alert); if (!isDuplicatePresent(alertCheckBox.Name)) { _recentChanges.AddFirst(alertCheckBox.Name); } } else { _alertStrategy.Alerts.Remove(alert); if (!isDuplicatePresent(alertCheckBox.Name)) { _recentChanges.AddFirst(alertCheckBox.Name); } } //If we changed the state of the heartbeat alert then we want to keep it if (alert.InternalCode == "HB") _removeHeartBeatAlert = false; } } private void txtAlert_TextChanged(object sender, EventArgs e) { TextBox alertTextBox = (TextBox)sender; Alert alert = _configurationWindowManager.FindAlert(alertTextBox.Name); if (alert != null) { if (_firstAlertsView && _firstFilterView && !btnOK.Enabled && !_fromScratch) { btnOK.Enabled = false; } else { btnOK.Enabled = true; } //btnOK.Enabled = true; double quality; if (ServerFormats.TryParseWithAbbreviations(alertTextBox.Text, out quality)) { _alertStrategy.AlertQuality[alert] = ServerFormats.ToString(quality); } else { _alertStrategy.AlertQuality[alert] = alertTextBox.Text; } if (!isDuplicatePresent(alertTextBox.Name)) { _recentChanges.AddFirst(alertTextBox.Name); } } } private void txtMinMax_TextChanged(object sender, EventArgs e) { /*When a textbox for the filter is filled in..the "recentChanges" list gets updated.*/ TextBox filterTextBox = (TextBox)sender; string internalCode = filterTextBox.Name.Substring(3); MarkFilterChanged(filterTextBox, internalCode); } private void MarkFilterChanged(TextBox filterTextBox, string internalCode) { Filter filter = _configurationWindowManager.FindFilter(internalCode); if (filter != null) { if (filterTextBox.Name.Contains("Min")) { if (_firstFilterView && _firstAlertsView && !btnOK.Enabled && !_fromScratch) { btnOK.Enabled = false; } else { btnOK.Enabled = true; } double value; if (ServerFormats.TryParseWithAbbreviations(filterTextBox.Text, out value)) { if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) _multiStrategyChanges.MinFilters[filter] = ServerFormats.ToString(value); else _strategy.MinFilters[filter] = ServerFormats.ToString(value); } else { if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) _multiStrategyChanges.MinFilters[filter] = filterTextBox.Text; else _strategy.MinFilters[filter] = filterTextBox.Text; } if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) filterTextBox.BackColor = Color.LightYellow; if (!isDuplicatePresent(filterTextBox.Name)) _recentChanges.AddFirst(filterTextBox.Name); } else if (filterTextBox.Name.Contains("Max")) { if (_firstFilterView && _firstAlertsView && !btnOK.Enabled && !_fromScratch) btnOK.Enabled = false; else btnOK.Enabled = true; //keep double value; if (ServerFormats.TryParseWithAbbreviations(filterTextBox.Text, out value)) { if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) _multiStrategyChanges.MaxFilters[filter] = ServerFormats.ToString(value); else _strategy.MaxFilters[filter] = ServerFormats.ToString(value); } else { if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) _multiStrategyChanges.MaxFilters[filter] = filterTextBox.Text; else _strategy.MaxFilters[filter] = filterTextBox.Text; } if (_configurationType == ConfigurationType.MultiStrategy && !_firstFilterView) filterTextBox.BackColor = Color.LightYellow; if (!isDuplicatePresent(filterTextBox.Name)) _recentChanges.AddFirst(filterTextBox.Name); } } } private void resetPanels() { /*This method clears out controls from panels, such as for the alerts and filters..and recreates them if need be, also all check-boxes and text-boxes are reset to accept the new data when there's a change of strategy*/ if (_configurationType == ConfigurationType.Alerts) { foreach (Control control in alertPanel.Controls) { if (control as CheckBox != null) { CheckBox cK = (CheckBox)control; cK.Checked = false; } if (control as TextBox != null) { TextBox text = (TextBox)control; text.Text = ""; } } foreach (Control control in filtersPanel.Controls) { if (control as TextBox != null) { TextBox text = (TextBox)control; text.Text = ""; } } } else //toplist { foreach (Control control in filtersPanel.Controls) { if (control as TextBox != null) { TextBox text = (TextBox)control; text.Text = ""; } } } } private void btnLoadSet_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".LoadSettings", _sendManager); LoadSelectedStrategy(); } private void loadSettings() { /*This method is to set the orange arrow icon at appropriate node in the strategy panel when the "Load Settings" button is clicked(using "selected" as a TreeNode object*/ TreeNode selected = strategyTreeView.SelectedNode as TreeNode; _recentChanges.Clear(); _alertsFilterInQuestion.Clear(); if (selected != null) { btnLoadSet.Enabled = false; btnOK.Enabled = true; selected.SelectedImageIndex = 1; //orange arrow icon selected.ImageIndex = 1; //orange arrow icon _nodeName = selected.Name; TreeNodeCollection nodes = strategyTreeView.Nodes; loadSetRecursive(strategyTreeView.Nodes); StrategyNode selectedStrategy = strategyTreeView.SelectedNode.Tag as StrategyNode; //Reset the alert and filters panel to "clean slate" in preparation to fill in the //appropriate checkmarks and text-boxes arising from the data obtained from the //strategy that has been loaded: if (selectedStrategy != null && !selectedStrategy.IsFolder()) { pnlRecentChanges.Controls.Clear(); resetPanels(); _recentChanges.Clear(); if (_configurationType == ConfigurationType.Alerts) { SetStrategy(new AlertStrategy(selectedStrategy.PrepairedStrategy)); setAlertAndFilterBoxes(_alertStrategy); _recentChanges.Clear(); //must not see any icon in recentChanges panel txtWindowName.Text = selectedStrategy.PrepairedStrategy.WindowName; loadTheExchanges(); loadTheSymbolLists(); } else { SetStrategy(new TopListStrategy(selectedStrategy.PrepairedStrategy)); txtWindowName.Text = selectedStrategy.PrepairedStrategy.WindowName; loadTheExchanges(); loadTheSymbolLists(); } } } } private void loadSetRecursive(TreeNodeCollection nodes) { /*This method is affiliated with the orange arrow placement - and traverses the whole tree... makes sure that no other nodes other than the selected node have an orange arrow icon*/ foreach (TreeNode n in nodes) { if (n.Name != _nodeName) { foreach (var pair in _dict) { if (pair.Key == n.Name) { n.SelectedImageIndex = n.ImageIndex = pair.Value; } } } loadSetRecursive(n.Nodes); } } private TextBox _configureFromOutsideMinTextBox = null; private TextBox _configureFromOutsideMaxTextBox = null; private void setAlertAndFilterBoxes(Object strategyObject) { try { AlertStrategy alertStrategy; TopListStrategy topListStrategy; /*This method checks the appropriate boxes and fills in the appropriate values within the SelectAlertPanel and FiltersPanel For some reason, I had to keep the actual changing of the text within textboxes out of the foreach loop while it is iterating through Dictionary items...otherwise an "collection was modified" exception was thrown. No object was added or removed in those loops. Placing that same statement outside the realm of that particular iterating loop however, was OK...*/ if (strategyObject as AlertStrategy != null && _configurationType == ConfigurationType.Alerts) { alertStrategy = (AlertStrategy)strategyObject; foreach (Alert a in alertStrategy.Alerts) { foreach (Control control in alertPanel.Controls) { if (control as CheckBox != null) { CheckBox cK = (CheckBox)control; if (cK.Name == a.InternalCode) { cK.Checked = true; } } if (control as TextBox != null) { TextBox txt = (TextBox)control; bool flag = false; string textValue = null; if (txt.Name == a.InternalCode) { foreach (var pair in alertStrategy.AlertQuality) { if (pair.Key.InternalCode == txt.Name && pair.Value != "") { //txt.Text = pair.Value; This statement throws "collection was modified" exception !! //This is the reason for using the "flag" and "textValue" variables... flag = true; textValue = pair.Value; double value; if (ServerFormats.TryParse(pair.Value, out value)) textValue = value.ToString(); } } } if (flag == true) { txt.Text = textValue; } } } } foreach (Control control in filtersPanel.Controls) { if (control as TextBox != null) { TextBox filterTxt = (TextBox)control; bool maxFlag = false; bool minFlag = false; string textValue = null; foreach (var maxPair in alertStrategy.MaxFilters) { if (filterTxt.Name == maxPair.Key.MaxCode && maxPair.Value != null) { maxFlag = true; double value; if (ServerFormats.TryParse(maxPair.Value, out value)) { textValue = value.ToString(); } else { textValue = maxPair.Value; } } if (_configuringFromOutside && filterTxt.Name == maxPair.Key.MaxCode && maxPair.Key.InternalCode == _outsideInternalCode && _setFromOutsideMaxFilter.HasValue && filterTxt.BackColor != Color.LightYellow) { maxFlag = true; string previousTextValue = textValue; textValue = _setFromOutsideMaxFilter.Value.ToString(); filterTxt.BackColor = Color.LightYellow; if (previousTextValue == "") previousTextValue = "Blank"; toolTip.SetToolTip(filterTxt, "Previously: " + previousTextValue); _configureFromOutsideMaxTextBox = filterTxt; } } if (maxFlag == true) { filterTxt.Text = textValue; } foreach (var minPair in alertStrategy.MinFilters) { if (filterTxt.Name == minPair.Key.MinCode && minPair.Value != null) { minFlag = true; double value; if (ServerFormats.TryParse(minPair.Value, out value)) { textValue = value.ToString(); } else { textValue = minPair.Value; } } if (_configuringFromOutside && filterTxt.Name == minPair.Key.MinCode && minPair.Key.InternalCode == _outsideInternalCode && _setFromOutsideMinFilter.HasValue && filterTxt.BackColor != Color.LightYellow) { minFlag = true; string previousTextValue = textValue; textValue = _setFromOutsideMinFilter.Value.ToString(); filterTxt.BackColor = Color.LightYellow; if (previousTextValue == "") previousTextValue = "Blank"; toolTip.SetToolTip(filterTxt, "Previously: " + previousTextValue); _configureFromOutsideMinTextBox = filterTxt; } } if (minFlag == true) { filterTxt.Text = textValue; } } } } else if (strategyObject as TopListStrategy != null && _configurationType == ConfigurationType.TopList) //topListStrategy { topListStrategy = (TopListStrategy)strategyObject; foreach (Control control in filtersPanel.Controls) { if (control as TextBox != null) { TextBox filterTxt = (TextBox)control; bool maxFlag = false; bool minFlag = false; string textValue = null; foreach (var maxPair in topListStrategy.MaxFilters) { if (filterTxt.Name == maxPair.Key.MaxCode && maxPair.Value != null) { maxFlag = true; double value; if (ServerFormats.TryParse(maxPair.Value, out value)) { textValue = value.ToString(); } else { textValue = maxPair.Value; } } } if (maxFlag == true) { filterTxt.Text = textValue; } foreach (var minPair in topListStrategy.MinFilters) { if (filterTxt.Name == minPair.Key.MinCode && minPair.Value != null) { minFlag = true; double value; if (ServerFormats.TryParse(minPair.Value, out value)) { textValue = value.ToString(); } else { textValue = minPair.Value; } } } if (minFlag == true) { filterTxt.Text = textValue; } } } } else if (_configurationType == ConfigurationType.MultiStrategy) { hideWaitPanel(); foreach (Control control in filtersPanel.Controls) { TextBox filterTxt = control as TextBox; if (null != filterTxt) { bool maxFlag = false; bool minFlag = false; string textValue = null; foreach (var maxPair in _multiCombinedMaxFilters) { if (filterTxt.Name == maxPair.Key.MaxCode && maxPair.Value != null) { maxFlag = true; double value; if (ServerFormats.TryParse(maxPair.Value, out value)) { textValue = value.ToString(); } else { textValue = maxPair.Value; } } } if (maxFlag == true) { if (textValue == MULTIPLE_VALUES) { filterTxt.Text = ""; filterTxt.BackColor = Color.LightGray; } else { filterTxt.Text = textValue; } if (_configurationType == ConfigurationType.MultiStrategy && _multiFilterTooltipText.ContainsKey(filterTxt.Name)) { toolTip.SetToolTip(filterTxt, _multiFilterTooltipText[filterTxt.Name]); } } foreach (var minPair in _multiCombinedMinFilters) { if (filterTxt.Name == minPair.Key.MinCode && minPair.Value != null) { minFlag = true; double value; if (ServerFormats.TryParse(minPair.Value, out value)) { textValue = value.ToString(); } else { textValue = minPair.Value; } } } if (minFlag == true) { if (textValue == MULTIPLE_VALUES) { filterTxt.Text = ""; filterTxt.BackColor = Color.LightGray; } else { filterTxt.Text = textValue; } if (_configurationType == ConfigurationType.MultiStrategy && _multiFilterTooltipText.ContainsKey(filterTxt.Name)) { toolTip.SetToolTip(filterTxt, _multiFilterTooltipText[filterTxt.Name]); } } } } } } catch (Exception e) { string debugView = e.ToString(); } } public static string GetPleasingCategoryString(string rawString) { /* * This method will allow us to make the list of categories in * the search combo box look more pleasing to the eye..as seen in * the web version. */ string newString = ""; if (rawString == "") { return ""; } //First, strip away the right angled brackets... string firstPass = rawString.Remove((rawString.Length - 1), 1); //now, the left angled brackets string secondPass = firstPass.Substring(1); //Convert everything to lowercase..we'll work from there.. string strippedString = secondPass.ToLower(); //now split up string using space as delimiter...(categories with more than //one word are separated by a space. NOTE: The "space" coming off the server isn't //the "normal" space that we can use like ' '. In this case, the space is ASCII 160, so I had to //use the below parameter in the Split function which represents this type of space //in order for the string to split. string[] words = strippedString.Split('\u00A0'); int count = 0; foreach (string word in words) { if (word == "nbbo") { string w = word.ToUpper(); newString += w + " "; if (count == 0) { count++; continue; } } if (count == 0) //First word is always capitalized... { newString = Regex.Replace(words[count], "(?:^|\\s)\\w", new MatchEvaluator(delegate (Match m) { return m.Value.ToUpper(); })); //courtesy of http://royaltutorials.com/c-ucwords/ newString += " "; } else if (word == "of" || word == "and" || word == "vs" || word == "the" || word == "a" || word == "an" || word == "to" || word == "from" || word == "in") { newString += word + " "; } else { string element = Regex.Replace(words[count], "(?:^|\\s)\\w", new MatchEvaluator(delegate (Match m) { return m.Value.ToUpper(); })); newString += element + " "; } count++; } string retVal = newString.TrimEnd(); //get rid of trailing whitespace return retVal; } private string fetchRawCategoryString(string str) { string retVal = ""; //Here we loop thru the category list to find the matching "ugly string" foreach (Category cat in _categoryList) { if (cat.userViewString == str) { retVal = cat.rawString; } } return retVal; } //For simplified Config Window private void useTheSearchTab(object sender, EventArgs e) { useTheSearchTab(); } private void useTheSearchTab() { /*This method is to actually do searching...and is triggered as an event for both the combo-box and search text box(textchanged event)*/ HashSet objects; if (cboSearchCategory.SelectedIndex > 0) { string selected = cboSearchCategory.SelectedItem.ToString(); objects = _configurationWindowManager.Search(txtSearchTerms.Text, fetchRawCategoryString(selected)); resetButtonsOnSearchTab(); } else { objects = _configurationWindowManager.Search(txtSearchTerms.Text); resetButtonsOnSearchTab(); } lstSearchResults.Items.Clear(); foreach (object item in objects) { Alert alertImage; Filter filterImage; if (item as Alert != null) { if (!_columnChooserMode) { alertImage = (Alert)item; lstSearchResults.Items.Add(alertImage); } } else if (item as Filter != null) { filterImage = (Filter)item; // if (_isSingleStock && (filterImage.InternalCode == "TV" || filterImage.InternalCode == "RV" || filterImage.InternalCode == "Price" || filterImage.InternalCode == "FCP" || filterImage.InternalCode == "FCD")) // { //The above filters are those which are not configurable by the user and appear in the top section of //both tabs of the SingleStockWindow // continue; // } lstSearchResults.Items.Add(filterImage); } } } private void tabSearch_Enter(object sender, EventArgs e) { if (_needToInitializeSearchBox) { _needToInitializeSearchBox = false; useTheSearchTab(); if (_firstSearchView) { if (btnOK.Enabled) { btnOK.Enabled = true; } _firstSearchView = false; } else { btnOK.Enabled = true; } } } private void lstSearchResults_MouseUp(object sender, MouseEventArgs e) { /*We only wish to pull up a context menu when only *ONE* item is selected. if the Search panel has no selected items (highlighted), or more than one selected item, the context menu will not pop up.*/ if (e.Button == MouseButtons.Right) { if (lstSearchResults.SelectedIndices.Count == 1 && lstSearchResults.IndexFromPoint(e.Location) == lstSearchResults.SelectedIndex) //Only wish to show context with *single* selected item. { resetSearchContext(); object item = new object(); Filter f; Alert a; item = lstSearchResults.Items[lstSearchResults.SelectedIndex]; if (item as Filter != null) { f = (Filter)item; _selectedContextSearchItem = "WSF_" + f.MaxCode; } else //an alert was selected { a = (Alert)item; _selectedContextSearchItem = a.InternalCode; } if (_configurationType == ConfigurationType.Alerts) { //was a filter clicked? if so, we must disable "SortBy" if (item as Filter != null) { lstSearchResults.ContextMenuStrip.Items[3].Visible = false; /*we also must check to see if theres cbt material available for this filter-if not, we must not allow the "Show Me entry to show in the context menu*/ lstSearchResults.ContextMenuStrip.Items[lstSearchResults.ContextMenuStrip.Items.Count - 1].Visible = ConfigDemoUserControl.Available((lstSearchResults.SelectedItem as Filter).InternalCode); } else //an alert was selected instead,hide ShowColumn and SortBy { lstSearchResults.ContextMenuStrip.Items[2].Visible = false; lstSearchResults.ContextMenuStrip.Items[3].Visible = false; lstSearchResults.ContextMenuStrip.Items[4].Visible = false; } } _listBoxSearchContext.Show(); } else { _listBoxSearchContext.Hide(); } } } private void resetSearchContext() { //Here we make all the items in menu strip visible, //so we can hide items selectivley depending upon the item that //is clicked in the search panel(alert or filter) and the //mode that the user is currently in (Alert or TopList) foreach (ToolStripMenuItem t in lstSearchResults.ContextMenuStrip.Items) { t.Visible = true; } } private void DrawItem(Object sender, DrawItemEventArgs e) { ListBox lb = (ListBox)sender; Image alertImage = null; Image minFilterImage; Image maxFilterImage; string testString = _phrases.Node("STRING_LENGTH_SET").PropertyForCulture("TEXT", "***"); int checkTextSize = TextRenderer.MeasureText(testString, Font).Width; if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { if (_configurationType == ConfigurationType.CustomColumns) { Brush brush = new SolidBrush(Color.FromArgb(79, 79, 79)); e.Graphics.FillRectangle(brush, e.Bounds); } else { e.Graphics.FillRectangle(Brushes.LightSkyBlue, e.Bounds); } } else { if (_configurationType == ConfigurationType.CustomColumns) { e.Graphics.FillRectangle(Brushes.Black, e.Bounds); } else { // Otherwise, draw the rectangle filled in beige. e.Graphics.FillRectangle(SystemBrushes.Control, e.Bounds); } } //Do not draw condition if (e.Index < 0) return; if (lb.Items[e.Index] as String != null) { try { //Center the columnName string columnName = (String)lb.Items[e.Index]; var textSize = TextRenderer.MeasureText(columnName, Font); int textSpacer = (e.Bounds.Height - textSize.Height)/2; e.Graphics.DrawString(columnName, this.Font, Brushes.White, e.Bounds.X + 10, e.Bounds.Y + textSpacer); } catch { } } else if (_configurationType == ConfigurationType.CustomColumns && lb.Items[e.Index] as IDisplayColumn != null) { try { //Center the columnDescription IDisplayColumn column = (IDisplayColumn)lb.Items[e.Index]; var textSize = TextRenderer.MeasureText(column.Description, Font); int textSpacer = (e.Bounds.Height - textSize.Height)/2; e.Graphics.DrawString(column.Description, this.Font, Brushes.White, e.Bounds.X + 10, e.Bounds.Y + textSpacer); } catch { } } else if (lb.Items[e.Index] as Alert != null) { try { Alert alert = (Alert)lb.Items[e.Index]; alertImage = _imageCacheManager.GetAlert(alert.InternalCode); // alertImage = null; //testing if (alertImage != null) { //Calculate the image spacer var imageSpacer = (e.Bounds.Height - alertImage.Height)/2; e.Graphics.DrawImage(alertImage, e.Bounds.X + 3, e.Bounds.Y + imageSpacer); } // Check to see if we need to truncate the alert description. var textSize = TextRenderer.MeasureText(alert.Description.ToString(), Font); int textWidth = textSize.Width; var textSpacer = (e.Bounds.Height - textSize.Height)/2; if (textWidth > checkTextSize && !String.IsNullOrEmpty(alert.FilterDescription)) { e.Graphics.DrawString(TruncateStringWithEllipse(alert.Description.ToString(), testString.Length), this.Font, myBrush, e.Bounds.X + 3 + ICON_WIDTH + 5, e.Bounds.Y + textSpacer); } else { e.Graphics.DrawString(alert.Description.ToString(), this.Font, myBrush, e.Bounds.X + 3 + ICON_WIDTH + 5, e.Bounds.Y + textSpacer); } //Draw units..(if any) if (!String.IsNullOrEmpty(alert.FilterDescription)) { string units = ("(" + alert.FilterDescription.ToString() + ")"); e.Graphics.DrawString(units, this.Font, myBrush, e.Bounds.X + ICON_WIDTH + checkTextSize + 3, e.Bounds.Y + textSpacer); } } catch { } } else { try { IDisplayColumn column = (IDisplayColumn)lb.Items[e.Index]; if (column is Filter) { Filter filter = (Filter)column; minFilterImage = _imageCacheManager.GetFilter(filter.MinCode); maxFilterImage = _imageCacheManager.GetFilter(filter.MaxCode); // minFilter = null; for testing // maxFilter = null; for testing string units = ("(" + filter.Units.ToString() + ")"); int filterSpace = ICON_WIDTH + 2; string description = filter.Description.ToString(); string descString = description + " " + units; int spacer = 3; if (lb.Name == "lstSearchResults") { if (minFilterImage != null) { int imageSpacer = (e.Bounds.Height - minFilterImage.Height)/2; e.Graphics.DrawImage(minFilterImage, e.Bounds.X + spacer, e.Bounds.Y + imageSpacer); } if (maxFilterImage != null) { int imageSpacer = (e.Bounds.Height - maxFilterImage.Height)/2; e.Graphics.DrawImage(maxFilterImage, e.Bounds.X + spacer + filterSpace, e.Bounds.Y + imageSpacer); } // Check to see if we need to truncate the filter description. var textSize = TextRenderer.MeasureText(description, Font); int textWidth = textSize.Width; var textSpacer = (e.Bounds.Height - textSize.Height)/2; if (textWidth > checkTextSize) { e.Graphics.DrawString(TruncateStringWithEllipse(description, testString.Length), this.Font, myBrush, e.Bounds.X + 3 + filterSpace * 2, e.Bounds.Y + textSpacer); } else { e.Graphics.DrawString(description, this.Font, myBrush, e.Bounds.X + 3 + filterSpace * 2, e.Bounds.Y + textSpacer); } e.Graphics.DrawString(units, this.Font, myBrush, e.Bounds.X + ICON_WIDTH * 2 + checkTextSize, e.Bounds.Y + textSpacer); } else if (lb.Name == "lstAllColumns" || lb.Name == "lstCurrentColumns" || lb.Name.StartsWith("lst-") || lb.Name == "lstSort") { if (minFilterImage != null) { int imageSpacer = (e.Bounds.Height - minFilterImage.Height)/2; e.Graphics.DrawImage(minFilterImage, e.Bounds.X + 10, e.Bounds.Y + imageSpacer); } var textSize = TextRenderer.MeasureText(descString, Font); int textSpacer = (e.Bounds.Height - textSize.Height)/2; e.Graphics.DrawString(descString, this.Font, myBrush, e.Bounds.X + spacer + 10 + ICON_WIDTH, e.Bounds.Y + textSpacer); } } else if (column is DisplayOnlyField) { var textSize = TextRenderer.MeasureText(column.Description.ToString(), Font); int textSpacer = (e.Bounds.Height - textSize.Height)/2; e.Graphics.DrawString(column.Description.ToString(), this.Font, myBrush, e.Bounds.X + 10, e.Bounds.Y + textSpacer); } } catch { } } } /// /// Truncate description string based on length and by not breaking up a word. Truncated string will have an ellipse. /// This should only be called due to user defined filter description being too long or new filters/alert descriptions /// are longer than STRING_LENGTH_SET defined in Common.xml. /// Based on stackoverflow: https://stackoverflow.com/questions/6724840/how-can-i-truncate-my-strings-with-a-if-they-are-too-long /// /// /// /// Truncated string with ellipses. private string TruncateStringWithEllipse(string value, int length) { if (string.IsNullOrEmpty(value)) return string.Empty; var returnValue = value; if (value.Length > length) { var tmp = value.Substring(0, length); if (tmp.LastIndexOf(' ') > 0) returnValue = tmp.Substring(0, tmp.LastIndexOf(' ')) + " ..."; } return returnValue; } private void MeasureItem(Object sender, MeasureItemEventArgs e) { // Cast the sender object back to ListBox type. ListBox theListBox = (ListBox)sender; // Get the string contained in each item. var itemString = theListBox.Items[e.Index].ToString(); // Measure the string contained on the item var sizeF = e.Graphics.MeasureString(itemString, Font); var stringHeight = (int)Math.Ceiling(sizeF.Height); var iconHeight = GuiEnvironment.ICON_HEIGHT + 3; //Set the height to the string Height or a minimum of the Icon Height e.ItemHeight = Math.Max(stringHeight,iconHeight); } private void btnHelp_Click(object sender, EventArgs e) { string htmlString = "http://www.trade-ideas.com/ProductHelp.html#"; // Add a means to specify a custom product help page. if (!GuiEnvironment.AppConfig.Node("PRODUCT_HELP").Property("TEXT", "").Equals("")) htmlString = GuiEnvironment.AppConfig.Node("PRODUCT_HELP").Property("TEXT"); if (sender as ToolStripMenuItem != null) { ContextMenuStrip c = (ContextMenuStrip)((ToolStripMenuItem)sender).GetCurrentParent(); GuiEnvironment.RecordUseCase(_windowPrefix + ".RightClick.Help", _sendManager); if (c.Name == "") { if (!_selectedContextSearchItem.Contains("WSF_")) { htmlString += (_configurationWindowManager.FindAlert(_selectedContextSearchItem)).InternalCode; } else //have a filter { htmlString += _selectedContextSearchItem; } } else { if (!c.Name.Contains("WSF_")) { htmlString += (_configurationWindowManager.FindAlert(c.Name)).InternalCode; } else // have a filter { htmlString += c.Name; } } } else if (lstSearchResults.SelectedItem as Alert != null) { htmlString += ((Alert)lstSearchResults.SelectedItem).InternalCode; } else //using "Help" button { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Help", _sendManager); htmlString += "WSF_" + ((Filter)lstSearchResults.SelectedItem).MaxCode; } if (GuiEnvironment.ShowHelp)//Context Sensitive Help { System.Diagnostics.Process.Start(htmlString); } } private void lstSearchResults_SelectedIndexChanged(object sender, EventArgs e) { if (lstSearchResults.SelectedIndices.Count == 1) { btnHelp.Enabled = true; btnSortBy.Enabled = true; if (isFilterSelected()) { btnShowColumn.Enabled = !_dontShowColumns; showMeButton.Enabled = ConfigDemoUserControl.Available((lstSearchResults.SelectedItem as Filter).InternalCode); btnFind.Text = _phrases.Node("ADD_FILTER").PropertyForCulture("TEXT", "***"); } else { btnFind.Text = _phrases.Node("ADD_ALERT").PropertyForCulture("TEXT", "***"); btnShowColumn.Enabled = false; showMeButton.Enabled = false; } btnFind.Enabled = !_columnChooserMode; btnSearchClearAll.Enabled = true; } else if (lstSearchResults.SelectedIndices.Count == 0) { btnHelp.Enabled = false; btnSortBy.Enabled = false; btnShowColumn.Enabled = false; btnFind.Enabled = false; btnSearchClearAll.Enabled = false; showMeButton.Enabled = false; } else if (lstSearchResults.SelectedIndices.Count > 1) { /* The foreach below is used to determine the text * for the "Find" button. We'll start the Filtercounter * as zero. if the counter equals the number of selected items * then we'll use " Add Filters". If counter remains at zero. then * we'll use "Add Alerts". Otherwise, we just use "Add" (selected items * consist of both Alerts and Filters */ int filterCount = 0; foreach (object o in lstSearchResults.SelectedItems) { if (o as Filter != null) { filterCount++; } } if (filterCount == 0) { btnFind.Text = _phrases.Node("ADD_ALERTS").PropertyForCulture("TEXT", "***"); } else if (filterCount == lstSearchResults.SelectedItems.Count) { btnFind.Text = _phrases.Node("ADD_FILTERS").PropertyForCulture("TEXT", "***"); } else { btnFind.Text = _phrases.Node("ADD").PropertyForCulture("TEXT", "***"); } btnHelp.Enabled = false; btnSortBy.Enabled = false; if (isFilterSelected()) { btnShowColumn.Enabled = !_dontShowColumns; } else { btnShowColumn.Enabled = false; } btnFind.Enabled = !_columnChooserMode; btnSearchClearAll.Enabled = true; showMeButton.Enabled = false; } if (_isSingleStock) { btnSortBy.Enabled = false; btnFind.Enabled = false; } } private bool isFilterSelected() { foreach (object item in lstSearchResults.SelectedItems) { if (item as Filter != null) { return true; } } return false; } private void resetButtonsOnSearchTab() { //Sometimes, there's a null reference exception that occurs as follows: if someone //highlights an alert/filter the appropriate buttons are enabled. Then uses the catagory //box(or text box) and selects another category that displays a whole different //subset of the alerts/filters. The buttons are still enabled..and when the Help //button is clicked, the exception is thrown. So, anytime one uses the Category combo //or search terms checkbox, these buttons get reset. btnHelp.Enabled = false; btnSortBy.Enabled = false; btnShowColumn.Enabled = false; btnFind.Enabled = false; showMeButton.Enabled = false; } private void btnFind_Click(object sender, EventArgs e) //new { _itemSelectionsForBolding.Clear(); bool isRefreshNeeded = true; bool checkOkButton = btnOK.Enabled; object selectedObject = null; string test = ""; //Now load the List container with the chosen items from the Find operation if (sender as PictureBox != null || sender as MenuItem != null || sender as ToolStripMenuItem != null) //function being called from a clicked icon. { if (sender as PictureBox != null) { GuiEnvironment.RecordUseCase(_windowPrefix + ".IconClick.Find", _sendManager); PictureBox clicked = (PictureBox)sender; test = clicked.Name; } else if (sender as ToolStripMenuItem != null) { ContextMenuStrip c = (ContextMenuStrip)((ToolStripMenuItem)sender).GetCurrentParent(); if (c.Name == "") { GuiEnvironment.RecordUseCase(_windowPrefix + ".RightClick.Find", _sendManager); test = _selectedContextSearchItem; } else { test = c.Name; } } if (!test.Contains("WSF_")) { btnHideUnused.Enabled = true; Alert a = _configurationWindowManager.FindAlert(test); int check = loadAlertAndFilterList((object)a); if (check == 1) { isRefreshNeeded = false; } selectedObject = (object)a; _itemSelectionsForBolding.Add(selectedObject); } else //have a filter { btnFilterHideUnused.Enabled = true; Filter f = _configurationWindowManager.FindFilter(test.Substring(7)); int check = loadAlertAndFilterList((object)f); if (check == 1) { isRefreshNeeded = false; } selectedObject = (object)f; _itemSelectionsForBolding.Add(selectedObject); } } else //function being called from the "Find" button { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Find", _sendManager); int duplicates = 0; foreach (Object obj in lstSearchResults.SelectedItems) { if (obj as Filter != null) { btnColumnsHideUnused.Enabled = true; btnFilterHideUnused.Enabled = true; } else //have alert { btnHideUnused.Enabled = true; } _itemSelectionsForBolding.Add(obj); duplicates += loadAlertAndFilterList(obj); } if (lstSearchResults.Items.Count > 1) //multiple selection { selectedObject = lstSearchResults.SelectedItems[0]; } else //only single item selected { selectedObject = lstSearchResults.SelectedItem; } if (duplicates == lstSearchResults.SelectedItems.Count) { isRefreshNeeded = false; } } if (_configurationType == ConfigurationType.Alerts) { if (isRefreshNeeded) //This is when we're adding new items that aren't already on panel in question { searchAlerts(); //populate Alert panel with objects in the list } } if (!_columnChooserMode) { if (isRefreshNeeded) { searchFilters(); } } //populate filters tab with filters in the list loadAllColumnsList(); //populate the columns panel(right side) with filter in list if (_configurationType == ConfigurationType.TopList) { btnSortHideUnused.Enabled = true; lstSortSetUp(); //populate the sort panel if in top list } string iCode; //Next scroll to the appropriate tab(filter or alert) using the first element(element //zero) in the selected listbox items--this is for the case where there is //more than one item selected. Also, selected items(s) get bolded-multiple selected items //are only possible using the "Find" button. if (selectedObject as Alert != null) { Alert alert = (Alert)selectedObject; alertPanel.VerticalScroll.Value = 0; tabStrategies.SelectedTab = tabAlerts; iCode = alert.InternalCode; //performance-we don't want to be refreshing two panels and iterating //the controls of two panels if we've only selected one item... if (_itemSelectionsForBolding.Count == 1) { recolorLabels(alertPanel); highLightLabels(alertPanel, iCode); } else { /*The below bool needs to be set to false. This is so that the * case where the user chooses *both* alerts and filters, the selected filter * items will also be bolded when the user clicks on the filters tab. The * reverse holds true for the below "else if (selectedObject as Filter != null) block... * In that case it is the _needToInitializeAlertPanel bool...*/ _needToInitializeFilterPanel = false; highlightMultipleItems(); } scrollToItem(iCode, alertPanel); } else if (selectedObject as Filter != null) { if (!_columnChooserMode) { btnColumnsHideUnused.Enabled = true; Filter filter = (Filter)selectedObject; filtersPanel.VerticalScroll.Value = 0; tabStrategies.SelectedTab = tabWindowsSpecificFilters; //Since the max and min filter are on the same "line" within the // window specific filter panel, it doesn't matter wheter iCode is //set to .MaxCode or .MinCode. iCode = "WSF_" + filter.MaxCode; //performance-we don't want to be refreshing two panels and iterating //the controls of two panels if we've only selected one item... if (_itemSelectionsForBolding.Count == 1) { recolorLabels(filtersPanel); highLightLabels(filtersPanel, filter.InternalCode); } else { _needToInitializeAlertPanel = false; highlightMultipleItems(); } scrollToItem(iCode, filtersPanel); } else { tabStrategies.SelectedTab = tabColumns; } } if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private string _outsideInternalCode = ""; public void configFromOutside(string fCode, double? minFilter = null, double? maxFilter = null) { /* This method will allow the config window's "showDialog"" to display the form in the state as if one had used the "Find" button from the Config window itself. This method is called when configuring from an outside source (e.g. clicking on a filter heading on a toplist or alert form)*/ filtersPanel.VerticalScroll.Value = 0; _outsideICode = "WSF_" + "Max" + fCode; _outsideInternalCode = fCode; tabStrategies.SelectedTab = tabWindowsSpecificFilters; _configuringFromOutside = true; _setFromOutsideMinFilter = minFilter; _setFromOutsideMaxFilter = maxFilter; _firstFilterView = false; } public void serverSortFromOutside(string fCode) { _serverSortFromOutside = true; _outsideICode = fCode; tabStrategies.SelectedTab = tabSort; } private void scrollToItem(string identifier, Panel p) { foreach (Control c in p.Controls) { if (c.GetType().Name == "PictureBox") { PictureBox test = (PictureBox)c; if (test.Name == identifier) { if (Math.Abs(test.Location.Y) > p.VerticalScroll.Maximum) { //This is to prevent a "value greater than maximum" exception p.VerticalScroll.Value = p.VerticalScroll.Maximum; } else { p.VerticalScroll.Value = Math.Abs(test.Location.Y); } break; } } } p.PerformLayout(); } private void highLightLabels(Panel p, string internalCode) { foreach (Control c in p.Controls) { if (c as Label != null) { if (c.GetType().Name == "Label") { Label lbl = (Label)c; if (lbl.Name == internalCode) { lbl.BackColor = Color.LightSkyBlue; } } } if (c.GetType().Name == "CheckBox") { CheckBox chk = (CheckBox)c; if (chk.Name == internalCode) { chk.BackColor = Color.LightSkyBlue; } } } } private void recolorLabels(Panel panel) { /*This method resets background colors of labels to transparent..*/ if (panel.Controls.Count != 0) { foreach (Control c in panel.Controls) { if (c as Label != null) { Label label = (Label)c; if (c.Name != "separator") { label.BackColor = Color.Transparent; } } if (c as CheckBox != null) { CheckBox chk = (CheckBox)c; chk.BackColor = Color.Transparent; } } } } private void unboldItems(Panel p) //all labels must be unbolded before we bold the desired ones... { foreach (Control c in p.Controls) { if (c.GetType().Name == "Label") { Label test = (Label)c; test.Font = new Font(this.Font, FontStyle.Regular); } if (c.GetType().Name == "CheckBox") //items in the alert panel have checkboxes that include text { CheckBox test = (CheckBox)c; test.Font = new Font(this.Font, FontStyle.Regular); } } p.PerformLayout(); } private void highlightMultipleItems() { recolorLabels(filtersPanel); recolorLabels(alertPanel); foreach (object o in _itemSelectionsForBolding) { if (o as Filter != null) { highLightLabels(filtersPanel, ((Filter)o).InternalCode); } else if (o as Alert != null) { highLightLabels(alertPanel, ((Alert)o).InternalCode); } } } private int loadAlertAndFilterList(object obj) { /*We want to ultimately keep tabs of the number of duplicates as this will indicate to us whether or not to refresh the Alert and/or Window Specific Filter tabs. This is for performance.*/ int dupeCount = 0; if (!anyDuplicatesExist(obj, _visibleAlertsAndFilters)) { _visibleAlertsAndFilters.Add(obj); } else { dupeCount++; } return dupeCount; } private bool anyDuplicatesExist(object obj, List listOfObjects) { bool flag = false; /*This snippet insures that only ONE of each type of icon will popluate the visible alert-and-filter List collection*/ foreach (object s in listOfObjects) { if (s as Alert != null && obj as Alert != null) { Alert test = (Alert)s; if (test.InternalCode == ((Alert)obj).InternalCode) { flag = true; break; } } else if (s as Filter != null && obj as Filter != null) { Filter test = (Filter)s; if (test.InternalCode == ((Filter)obj).InternalCode) { flag = true; break; } } } return flag; } private void btnShowColumn_Click(object sender, EventArgs e) { List singleStockTemp = new List(); int duplicates = 0; //first, check whether "sender" is coming from an individual icon from strategy panel or windowName panel.. if (sender as ToolStripMenuItem != null) { Filter f; ContextMenuStrip c = (ContextMenuStrip)((ToolStripMenuItem)sender).GetCurrentParent(); if (c.Name == "") { f = _configurationWindowManager.FindFilter(_selectedContextSearchItem.Substring(7)); //Remove the WSF_ prefix } else { f = _configurationWindowManager.FindFilter(c.Name.Substring(7)); //Remove the WSF_ prefix } GuiEnvironment.RecordUseCase(_windowPrefix + ".RightClick.ShowAsColumn", _sendManager); duplicates = loadAlertAndFilterList((object)f); if (!isDuplicateForCurrentColumns(f)) { if (_configurationType == ConfigurationType.Alerts) { _strategy = _alertStrategy; //this will fix colum hide bug _alertStrategy.Columns.Add(f); // _strategy.Columns.Add(f); fillCurrentColumnsList(); btnOK.Enabled = true; } else //TopList { _strategy = _topListStrategy; _topListStrategy.Columns.Add(f); fillCurrentColumnsList(); btnOK.Enabled = true; } } } else //coming from the "ShowColumn" Button { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.ShowAsColumn", _sendManager); //First put the any selected filters in the visibleAlertsAndFilterList foreach (object item in lstSearchResults.SelectedItems) { if (item as Filter != null) { duplicates = loadAlertAndFilterList(item); if (!isDuplicateForCurrentColumns((Filter)item)) { if (_configurationType == ConfigurationType.Alerts) { _strategy = _alertStrategy; //this will fix colum hide bug _alertStrategy.Columns.Add((Filter)item); // _strategy.Columns.Add((Filter)item); fillCurrentColumnsList(); btnOK.Enabled = true; } else //TopList { _strategy = _topListStrategy; _topListStrategy.Columns.Add((Filter)item); fillCurrentColumnsList(); btnOK.Enabled = true; } } } } } if (_configurationType == ConfigurationType.TopList) { lstSortSetUp(); //populate the sort panel if in top list } loadAllColumnsList(); //refresh allcolumnPanel if (duplicates == 0) //(performance related) { searchFilters(); //refresh filter tab } tabStrategies.SelectedTab = tabColumns; //navigate to columns tab btnColumnsHideUnused.Enabled = true; } private void btnSearchClearAll_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.ClearAll", _sendManager); lstSearchResults.SelectedItems.Clear(); } private void btnSortBy_Click(object sender, EventArgs e) { Filter f; if (sender as ToolStripMenuItem != null) { GuiEnvironment.RecordUseCase(_windowPrefix + ".RightClick.SortBy", _sendManager); ContextMenuStrip c = (ContextMenuStrip)((ToolStripMenuItem)sender).GetCurrentParent(); if (c.Name == "") { f = (_configurationWindowManager.FindFilter(_selectedContextSearchItem.Substring(7))); } else { f = (_configurationWindowManager.FindFilter(c.Name.Substring(7))); } loadAlertAndFilterList((object)f); } else { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.SortBy", _sendManager); f = (Filter)lstSearchResults.SelectedItem; loadAlertAndFilterList(lstSearchResults.SelectedItem); } btnOK.Enabled = true; tabStrategies.SelectedTab = tabSort; //display the sort tab searchFilters(); //Referesh to show the new filter selected by "Sort By" button lstSortSetUp(); //Referesh to show the new filter selected by "Sort By" button sortByButtonSet(f); } private void btnHideUnused_Click(object sender, EventArgs e) { //Set button states btnAddDefaultAlert.Enabled = true; btnShowAll.Enabled = true; btnHideUnused.Enabled = false; GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.HideUnused", _sendManager); bool checkOkButton = btnOK.Enabled; //...erase unused from the alert panel. I presume that //these unused alerts will also be eliminated from the List //that keeps tabs of all visible alerts and filters. // In this method we first find all the alerts that are being used and // store them in a "temp" list. If an alert is either checked, or is //part of the current selected strategy, then it won't be removed _alertTempList.Clear(); foreach (Control c in alertPanel.Controls) { if (c as CheckBox != null) { Alert a = _configurationWindowManager.FindAlert(((CheckBox)c).Name); if (((CheckBox)c).Checked) { if (!anyDuplicatesExist(a, _alertTempList)) { _alertTempList.Add((object)a); } } } if (c as TextBox != null) { Alert a = _configurationWindowManager.FindAlert(((TextBox)c).Name); if (((TextBox)c).Text != "") { if (!anyDuplicatesExist(a, _alertTempList)) { _alertTempList.Add((object)a); } } } } //now we must update the visibleAlertsAndFilters List and retain the filters that //are already present. Since this button is for alert removal only. foreach (object obj in _visibleAlertsAndFilters) { if (obj as Filter != null) { _alertTempList.Add(obj); } } reloadAlertFilterList(_alertTempList); searchAlerts(); //repopulate alert panel, minus the unused alerts if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private List getMostCommonAlerts() { List returnedList = new List(); foreach (XmlNode alert in _begAlerts.Enum()) { string test = alert.Property("CODE"); returnedList.Add(_configurationWindowManager.FindAlert(test)); } return returnedList; } private List getMostCommonFilters() { List returnedList = new List(); if (_isSingleStock) { foreach (XmlNode filter in _singleStockFilters.Enum()) { string test = filter.Property("CODE"); returnedList.Add(_configurationWindowManager.FindFilter(test)); } } else { foreach (XmlNode filter in _begFilters.Enum()) { string test = filter.Property("CODE"); returnedList.Add(_configurationWindowManager.FindFilter(test)); } } return returnedList; } /// /// This returns a list of currently used alerts. /// private List getUsedAlerts() { List usedList = new List(); List alertTempList = new List(); foreach (Control c in alertPanel.Controls) { if (c as CheckBox != null) { Alert a = _configurationWindowManager.FindAlert(((CheckBox)c).Name); if (((CheckBox)c).Checked) { if (!anyDuplicatesExist(a, alertTempList)) { alertTempList.Add((object)a); usedList.Add(a); } } } if (c as TextBox != null) { Alert a = _configurationWindowManager.FindAlert(((TextBox)c).Name); if (((TextBox)c).Text != "") { if (!anyDuplicatesExist(a, alertTempList)) { alertTempList.Add((object)a); usedList.Add(a); } } } } alertTempList.Clear(); return usedList; } private void btnBegAlert_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".BeginnerAlert", _sendManager); btnShowBegIntAdvAlert_Click(sender, e); } //variant of "Show Most Common" "Beginner" "Intermediate" "Advanced" private void btnShowBegIntAdvAlert_Click(object sender, EventArgs e) { //Set button states btnHideUnused.Enabled = true; btnShowAll.Enabled = true; bool checkOkButton = btnOK.Enabled; List common = new List(); List used = getUsedAlerts(); List tempList = new List(); btnAddDefaultAlert.Enabled = false; common = getMostCommonAlerts(); //Remove all Alerts from _visibleAlertsAndFilters before adding the used and common alerts foreach (object obj in _visibleAlertsAndFilters) { if (obj as Filter != null) { tempList.Add(obj); } } _visibleAlertsAndFilters = tempList; //Add currently used alerts to _visibleAlertsAndFilters foreach (Alert a in used) { loadAlertAndFilterList((object)a); } //Add common alerts to _visibleAlertsAndFilters foreach (Alert a in common) { loadAlertAndFilterList((object)a); } searchAlerts(); Alert firstItem = common[0]; //Next line commented out since it would cause wrong positioning of displayed panel data //scrollToItem(firstItem.InternalCode, alertPanel); if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } /// /// This returns a list of currently used filters. /// private List getusedFilters() { List usedList = new List(); List filterTempList = new List(); foreach (Control c in filtersPanel.Controls) { if (c as TextBox != null) { Filter f = _configurationWindowManager.FindFilter((((TextBox)c).Name).Substring(3)); if (f == null) { continue; } if (((TextBox)c).Text != "" || isSelectedColumn(f) || isThisFilterBeingSorted(f)) //first check to see if textbox empty { //if textbox is not empty, or //is being used as a selected column, then leave it around... if (!anyDuplicatesExist(f, filterTempList)) { filterTempList.Add((object)f); usedList.Add(f); } } } } filterTempList.Clear(); return usedList; } private void btnBegFilter_Click(object sender, EventArgs e) { if (!_loadingComplete) return; GuiEnvironment.RecordUseCase(_windowPrefix + ".BeginnerFilter", _sendManager); btnFilterBegIntAdv_Click(sender, e); } private void btnBegColumn_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".BeginnerColumn", _sendManager); btnFilterBegIntAdv_Click(sender, e); } private void btnBegSort_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".BeginnerSort", _sendManager); btnFilterBegIntAdv_Click(sender, e); } private void btnFilterBegIntAdv_Click(object sender, EventArgs e) { //Set button states btnFilterHideUnused.Enabled = btnColumnsHideUnused.Enabled = btnSortHideUnused.Enabled = true; btnFilterShowAll.Enabled = btnColumnShowAll.Enabled = btnSortShowAll.Enabled = true; bool checkOkButton = btnOK.Enabled; List common = new List(); List used = getusedFilters(); List tempList = new List(); btnAddDefaultFilter.Enabled = btnAddDefaultColumn.Enabled = btnAddDefaultSort.Enabled = false; common = getMostCommonFilters(); //Remove all Filters from _visibleAlertsAndFilters before adding the used and common filters foreach (object obj in _visibleAlertsAndFilters) { if (obj as Alert != null) { tempList.Add(obj); } } _visibleAlertsAndFilters = tempList; //Add currently used filters to _visibleAlertsAndFilters foreach (Filter a in used) { loadAlertAndFilterList((object)a); } //Add common filters to _visibleAlertsAndFilters foreach (Filter a in common) { loadAlertAndFilterList((object)a); } searchFilters(); loadAllColumnsList(); if (_configurationType == ConfigurationType.TopList) { lstSortSetUp(); //populate the sort panel if in top list } if (((Button)sender).Name.Contains("Filter")) { //Next line commented out since it would cause wrong positioning of displayed panel data //scrollToItem(common[0].InternalCode, filtersPanel); } if (((Button)sender).Name.Contains("Column")) { lstAllColumns.SelectedItem = (object)common[0]; } if (((Button)sender).Name.Contains("Sort")) { lstSort.SelectedItem = (object)common[0]; } if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private bool isInUseForSomeStrategies(TextBox textBox) { return textBox.BackColor == Color.LightGray || textBox.BackColor == Color.LightYellow; } private void btnFilterHideUnused_Click(object sender, EventArgs e) { if (!_loadingComplete) return; //Set button states btnFilterHideUnused.Enabled = btnColumnsHideUnused.Enabled = btnSortHideUnused.Enabled = false; btnAddDefaultFilter.Enabled = true; btnAddDefaultColumn.Enabled = true; btnAddDefaultSort.Enabled = true; btnFilterShowAll.Enabled = btnColumnShowAll.Enabled = btnSortShowAll.Enabled = true; bool checkOkButton = btnOK.Enabled; _filterTempList.Clear(); foreach (Control c in filtersPanel.Controls) { TextBox textBox = c as TextBox; if (null != textBox) { Filter f = _configurationWindowManager.FindFilter(textBox.Name.Substring(3)); if (f == null) continue; if (textBox.Text != "" || isSelectedColumn(f) || isThisFilterBeingSorted(f) || isInUseForSomeStrategies(textBox)) //first check to see if textbox empty { //if textbox is not empty, or //is being used as a selected column, then leave it around... if (!anyDuplicatesExist(f, _filterTempList)) { _filterTempList.Add((object)f); } } } } //now we must update the visibleAlertsAndFilters List and retain the alerts(if any) already //present. foreach (object obj in _visibleAlertsAndFilters) { if (obj as Alert != null) { _filterTempList.Add(obj); } } reloadAlertFilterList(_filterTempList); searchFilters(); //repopulate filter panel, minus the unused alerts lstSortSetUp(); loadAllColumnsList(); if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private void btnColumnsHideUnused_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Columns.HideUnused", _sendManager); btnFilterHideUnused_Click(sender, e); } private void btnSortHideUnused_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Sort.HideUnused", _sendManager); btnFilterHideUnused_Click(sender, e); } private void btnShowAll_Click(object sender, EventArgs e) { //Set button states btnHideUnused.Enabled = true; btnAddDefaultAlert.Enabled = true; btnShowAll.Enabled = false; GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.ShowAll", _sendManager); bool checkOkButton = btnOK.Enabled; List temp = new List(); foreach (object o in _visibleAlertsAndFilters) { if (o as Filter != null) { temp.Add(o); } } _visibleAlertsAndFilters = loadTempList(temp, true); searchAlerts(); searchFilters(); loadAllColumnsList(); if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private void btnFilterShowAll_Click(object sender, EventArgs e) { if (!_loadingComplete) return; //Set button states btnFilterHideUnused.Enabled = btnColumnsHideUnused.Enabled = btnSortHideUnused.Enabled = true; btnAddDefaultFilter.Enabled = true; btnAddDefaultColumn.Enabled = true; btnAddDefaultSort.Enabled = true; btnFilterShowAll.Enabled = btnColumnShowAll.Enabled = btnSortShowAll.Enabled = false; bool checkOkButton = btnOK.Enabled; List temp = new List(); foreach (object o in _configurationWindowManager.DisplayOnlyFieldsInOrder) { temp.Add(o); } foreach (object o in _visibleAlertsAndFilters) { if (o as Alert != null) { temp.Add(o); } } _visibleAlertsAndFilters = loadTempList(temp, false); searchFilters(); if (_configurationType == ConfigurationType.Alerts) { searchAlerts(); } else //top list { lstSortSetUp(); } loadAllColumnsList(); if (checkOkButton == false && !_fromScratch) { btnOK.Enabled = false; } } private void btnColumnShowAll_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Columns.ShowAll", _sendManager); btnFilterShowAll_Click(sender, e); } private void btnSortShowAll_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.Sort.ShowAll", _sendManager); btnFilterShowAll_Click(sender, e); } private bool isSelectedColumn(IDisplayColumn c) { PrepairedStrategy pStrategy = new PrepairedStrategy(); if (_configurationType == ConfigurationType.Alerts) { pStrategy = _alertStrategy; } else //top list mode { pStrategy = _topListStrategy; } // If we're doing multistrategy edit, ignore columns if (_configurationType != ConfigurationType.MultiStrategy) { foreach (IDisplayColumn col in pStrategy.Columns) { if (col.InternalCode == c.InternalCode) { return true; } } } return false; } //TODO display only field as well? private bool isThisFilterBeingSorted(Filter f) { if (_configurationType == ConfigurationType.TopList) { return (f == _topListStrategy.SortBy); } return false; } //private bool isFilterInCurrentStrategy(Filter f) //{ // if (_configurationType == ConfigurationType.Alerts) // { // foreach (var filt in _alertStrategy.MaxFilters) // { // if (f.InternalCode == filt.Key.InternalCode) // { // return true; // } // } // foreach (var filt in _alertStrategy.MinFilters) // { // if (f.InternalCode == filt.Key.InternalCode) // { // return true; // } // } // } // else //in Top List mode... // { // foreach (var pair in _currentTopList.MaxFilters) // { // if (f.InternalCode == pair.Key.InternalCode) // { // return true; // } // } // foreach (var pair in _currentTopList.MinFilters) // { // if(f.InternalCode == pair.Key.InternalCode) // { // return true; // } // } // } // return false; //} //private bool isAlertInCurrentStrategy(Alert a) //{ // foreach (Alert alrt in _alertStrategy.Alerts) // { // if (alrt.InternalCode == a.InternalCode) // { // return true; // } // } // return false; //} private List loadTempList(List workingList, bool isShowAllAlert) // { List newList = new List(); if (isShowAllAlert) //add the alert to the workingList and return { foreach (object o in _allAlertList) { workingList.Add(o); } } else //add filters to the workingList and return { foreach (object o in _allFilterList) { workingList.Add(o); } } return newList = workingList; } private void reloadAlertFilterList(List myList) { //This method reloads the _visibleAlertAndFilters after a Hide Unused operation //You just can't set the _visibleAlertAndFilters = _tempList as weird things happen //You must copy each item from the _tempList to the _visibleAlertAndFilters... _visibleAlertsAndFilters.Clear(); foreach (object obj in myList) { loadAlertAndFilterList(obj); } } private void popup(object sender, EventArgs e) { ToolStripMenuItem chosen = (ToolStripMenuItem)sender; ContextMenuStrip context = (ContextMenuStrip)chosen.GetCurrentParent(); if (chosen == context.Items[0]) //help { btnHelp_Click(sender, e); } else if (chosen == context.Items[1]) //Find { btnFind_Click(sender, e); } else if (chosen == context.Items[2]) //Show Column { btnShowColumn_Click(sender, e); } else if (chosen == context.Items[3]) //showMe { showMeButton_Click(sender, e); } else if (chosen == context.Items[4]) //sortby { btnSortBy_Click(sender, e); } } private void searchPopup(object sender, EventArgs e) { ToolStripMenuItem chosen = (ToolStripMenuItem)sender; if (chosen == _listBoxSearchContext.Items[0]) //help { btnHelp_Click(sender, e); } else if (chosen == _listBoxSearchContext.Items[1]) //find { btnFind_Click(sender, e); } else if (chosen == _listBoxSearchContext.Items[2]) //showColumn { btnShowColumn_Click(sender, e); } else if (chosen == _listBoxSearchContext.Items[3]) //sort by { btnSortBy_Click(sender, e); } else if (chosen == _listBoxSearchContext.Items[4]) //showme { showMeButton_Click(sender, e); } } private void searchAlerts(object sender, EventArgs e) { searchAlerts(); } private void searchAlerts() { alertPanel.SuspendLayout(); ExtensionMethods.Clear(alertPanel.Controls, true); alertPanel.ResumeLayout(); int top = 10; alertPanel.SuspendLayout(); foreach (Object item in _visibleAlertsAndFilters) { if (item is Alert alertImage) { var labelHeight = TextRenderer.MeasureText(alertImage.Description.ToString(), Font).Height; var maxHeight = Math.Max(labelHeight, GuiEnvironment.ICON_HEIGHT); var centerImage = maxHeight == labelHeight; PictureBox pictureBox = new PictureBox(); pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.BorderStyle = BorderStyle.Fixed3D; pictureBox.Top = (int)(centerImage ? top + (maxHeight - pictureBox.Height) * 0.8 : top); pictureBox.Left = 10; pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; pictureBox.Name = alertImage.InternalCode; Alert saveAlert = alertImage; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetAlert(saveAlert.InternalCode); }; //Set up the context menu--we only want this menu to display "Help" ContextMenuStrip iconPopup = new ContextMenuStrip(); iconPopup.Name = saveAlert.InternalCode; iconPopup.Items.Add(_phrases.Node("HELP").PropertyForCulture("TEXT", "***"), null, new EventHandler(popup)); pictureBox.ContextMenuStrip = iconPopup; CheckBox ckAlert = new CheckBox(); //we need to know the "length" of a fresh checkbox object, without //any text. Then, we can add that length to the length of the //longest text item to furnish the offset(total "width" of checkbox) to place the text box. int initialCheckLength = ckAlert.Width; ckAlert.MouseClick += new MouseEventHandler(ckAlert_MouseClick); ckAlert.Text = alertImage.Description.ToString(); ckAlert.Top = (int)(centerImage ? top : top + (maxHeight - labelHeight)*0.3); ckAlert.Left = GuiEnvironment.ICON_WIDTH + 15; ckAlert.AutoSize = true; ckAlert.FlatStyle = FlatStyle.Flat; ckAlert.Name = alertImage.InternalCode.ToString(); // Add controls in the desired tabbing order alertPanel.Controls.Add(pictureBox); alertPanel.Controls.Add(ckAlert); if (alertImage.FilterDescription != null) { //since we wish consistency, we'll make the offset equal to the //length of the checkbox plus the length of the below, which is the //longest string. Who knows, that might change any additional new alerts //have longer textual descriptons than the one below. string testString = _phrases.Node("STRING_LENGTH_SET").PropertyForCulture("TEXT", "***"); int checkTextSize = TextRenderer.MeasureText(testString, Font).Width; int textBoxWidth = TextRenderer.MeasureText("10000000000", Font).Width; ckAlert.Width = initialCheckLength + checkTextSize; TextBox txtAlert = new TextBox(); txtAlert.TextChanged += new EventHandler(txtAlert_TextChanged); txtAlert.Width = textBoxWidth; txtAlert.Left = ckAlert.Width + 3; txtAlert.BorderStyle = BorderStyle.Fixed3D; txtAlert.Top = pictureBox.Top; txtAlert.Name = alertImage.InternalCode.ToString(); txtAlert.Font = new Font(Font.FontFamily, Font.Size - Font.Size * 0.30f, Font.Style); alertPanel.Controls.Add(txtAlert); /*Add the description label for the text box...*/ Label lblAlert = new Label(); lblAlert.Name = alertImage.InternalCode.ToString(); lblAlert.Left = txtAlert.Right + 3; lblAlert.AutoSize = true; lblAlert.Text = alertImage.FilterDescription.ToString(); lblAlert.Top = centerImage? (int)(ckAlert.Top + ckAlert.Height * 0.20): ckAlert.Top; alertPanel.Controls.Add(lblAlert); } top += maxHeight; } } ReDisplayAlerts(); alertPanel.ResumeLayout(); LinkedList tempRecentHolder = new LinkedList(_recentChanges); if (_currentSettingAlertFlag && _currentSettingFilterFlag) { setAlertAndFilterBoxes(_currentAlert); _recentChanges.Clear(); //must not see any icon in recentChanges panel _currentSettingAlertFlag = false; } else { AlertStrategy tempAlertStrategy = new AlertStrategy(_alertStrategy); setAlertAndFilterBoxes(_alertStrategy); SetStrategy(tempAlertStrategy); _recentChanges = tempRecentHolder; } } private void tabAlerts_Enter(object sender, EventArgs e) { if (_needToInitializeAlertPanel) { //TODO need code here to check whether the pael in the Alert //Window is empty...If so, it will need to be populated. _needToInitializeAlertPanel = false; searchAlerts(); if (_firstAlertsView) { if (btnOK.Enabled) { btnOK.Enabled = true; } _firstAlertsView = false; } else { btnOK.Enabled = true; } } } private void searchFilters(object sender, EventArgs e) { searchFilters(); } private void searchFilters() { try { //set up parameters to aid with font changes int minLabelWidth = TextRenderer.MeasureText("Position in Bollinger Bands(60 Minute)", Font).Width; int textBoxWidth = TextRenderer.MeasureText("10000000000", Font).Width; Label dummy = new Label(); int defaultLabelLength = dummy.Width; filtersPanel.SuspendLayout(); ExtensionMethods.Clear(filtersPanel.Controls, true); filtersPanel.ResumeLayout(); int top = 10; filtersPanel.SuspendLayout(); foreach (Object item in _visibleAlertsAndFilters) { Button showMe = new Button(); string filterInternalID = ""; string testString = "Filter"; if (item is Filter filter) { if (!isFilterValid(item)) { continue; } filterInternalID = filter.InternalCode; PictureBox pictureBoxMin = new PictureBox(); PictureBox pictureBoxMax = new PictureBox(); pictureBoxMin.Visible = pictureBoxMax.Visible = true; pictureBoxMin.Height = pictureBoxMax.Height = GuiEnvironment.ICON_HEIGHT; pictureBoxMin.Width = pictureBoxMax.Width = GuiEnvironment.ICON_WIDTH; pictureBoxMin.SizeMode = pictureBoxMax.SizeMode = PictureBoxSizeMode.CenterImage; pictureBoxMin.BorderStyle = pictureBoxMax.BorderStyle = BorderStyle.None; pictureBoxMin.Top = pictureBoxMax.Top = top; //distinctions in max and min filters... pictureBoxMin.Name = "WSF_" + filter.MinCode; pictureBoxMax.Name = "WSF_" + filter.MaxCode; //set up the context menus.. pictureBoxMin.ContextMenuStrip = createIconPopup(testString, "WSF", filterInternalID); pictureBoxMax.ContextMenuStrip = createIconPopup(testString, "WSF", filterInternalID); pictureBoxMin.ContextMenuStrip.Name = pictureBoxMin.Name; pictureBoxMax.ContextMenuStrip.Name = pictureBoxMax.Name; Filter saveFilter = filter; pictureBoxMin.Tag = (DoUpdate)delegate { pictureBoxMin.Image = _imageCacheManager.GetFilter(saveFilter.MinCode); }; pictureBoxMax.Tag = (DoUpdate)delegate { pictureBoxMax.Image = _imageCacheManager.GetFilter(saveFilter.MaxCode); }; //Configure the text boxes for the min and max icons... TextBox txtMin = new TextBox(); txtMin.TextChanged += new EventHandler(txtMinMax_TextChanged); txtMin.Width = textBoxWidth; txtMin.BorderStyle = BorderStyle.Fixed3D; txtMin.Name = saveFilter.MinCode; TextBox txtMax = new TextBox(); txtMax.TextChanged += new EventHandler(txtMinMax_TextChanged); txtMax.Width = textBoxWidth; txtMax.BorderStyle = BorderStyle.Fixed3D; txtMax.Name = saveFilter.MaxCode; txtMin.Font = txtMax.Font = new Font(Font.FontFamily, Font.Size - Font.Size * 0.20f, Font.Style); //Now set up the "show me" buttons... showMe.Click += new EventHandler(b_Click); showMe.Image = cbtImageList.Images[0]; showMe.Width = GuiEnvironment.ICON_WIDTH; showMe.Height = GuiEnvironment.ICON_HEIGHT; showMe.Visible = false; if (ConfigDemoUserControl.Available(filter.InternalCode)) { showMe.Tag = filter; showMe.Visible = true; } //set up tool Tip for these buttons.. toolTip.SetToolTip(showMe, _phrases.Node("SHOW_ME").PropertyForCulture("TEXT", "***")); //Add the description label to the text box Label lblFilterMin = new Label(); lblFilterMin.TextAlign = ContentAlignment.TopRight; lblFilterMin.Height = Font.Height + 2; //view y's and g's on large font lblFilterMin.UseMnemonic = false; lblFilterMin.Text = saveFilter.Description.ToString(); lblFilterMin.Name = filter.InternalCode; Label lblFilterMax = new Label(); lblFilterMax.AutoSize = true; lblFilterMax.Text = saveFilter.Units.ToString(); lblFilterMax.Name = filter.InternalCode; //set distances between items lblFilterMin.Left = -4 * (int)Font.Size; lblFilterMin.Width = minLabelWidth + defaultLabelLength; pictureBoxMin.Left = lblFilterMin.Right + 3; txtMin.Left = pictureBoxMin.Right + 3; showMe.Left = txtMin.Right + 3; pictureBoxMax.Left = showMe.Right + 3; txtMax.Left = pictureBoxMax.Right + 3; lblFilterMax.Left = txtMax.Right + 3; lblMin.Left = txtMin.Left; lblMax.Left = txtMax.Left; var labelHeight = TextRenderer.MeasureText(saveFilter.Description, Font).Height+3; var maxHeight = Math.Max(labelHeight, GuiEnvironment.ICON_HEIGHT); var centerImage = maxHeight == labelHeight; lblFilterMin.Top = lblFilterMax.Top = centerImage ? top : top + (maxHeight - labelHeight)/2; txtMax.Top = txtMin.Top = centerImage ? pictureBoxMin.Top : lblFilterMin.Top; showMe.Top = pictureBoxMax.Top = pictureBoxMin.Top = centerImage ? top + (maxHeight - pictureBoxMin.Height)/2 : top; //add to panel in the correct tabbing order... filtersPanel.Controls.Add(pictureBoxMin); filtersPanel.Controls.Add(pictureBoxMax); filtersPanel.Controls.Add(txtMin); filtersPanel.Controls.Add(showMe); filtersPanel.Controls.Add(txtMax); filtersPanel.Controls.Add(lblFilterMin); filtersPanel.Controls.Add(lblFilterMax); top += maxHeight; } } ReDisplayFilters(); filtersPanel.ResumeLayout(); /*Noticed a very nasty bug whereby the WindowName tab can display filter icons(those that had actual values in them) when they're not supposed to be..this can happen when first loading the strategy's setting, then flipping, followed by clicking the WindowFilterTab and finally the WindowName tab Within the WindowName tab an unwanted filter(s) can be seen..namely a filter that has a value in its textbox whichalready hasn't been displayed. This bug was noticed upon changing indices of the drop-down menu bar with the filters... Thus, recentChanges and _alertStrategy must be preserved when the appropriate values are "filled in" the Filters tab as a result of a flip...The recentChanges as well as the strategy must not get corrupted during operations such as changing indices on drop-down menus...*/ LinkedList tempRecentHolder = new LinkedList(_recentChanges); if (_currentSettingFilterFlag && _currentSettingAlertFlag) { if (_configurationType == ConfigurationType.Alerts) { setAlertAndFilterBoxes(_currentAlert); } else if (_configurationType == ConfigurationType.TopList) //topList { setAlertAndFilterBoxes(_currentTopList); } else { setAlertAndFilterBoxes(null); } _recentChanges.Clear(); //must not see any icon in recentChanges panel _currentSettingFilterFlag = false; } else { if (_configurationType == ConfigurationType.Alerts) { AlertStrategy tempAlertStrategy = new AlertStrategy(_alertStrategy); setAlertAndFilterBoxes(_alertStrategy); SetStrategy(tempAlertStrategy); } else if (_configurationType == ConfigurationType.TopList) //toplist { if (_topListStrategy != null) { TopListStrategy tempTopStrategy = new TopListStrategy(_topListStrategy); setAlertAndFilterBoxes(_topListStrategy); SetStrategy(tempTopStrategy); } } else { setAlertAndFilterBoxes(null); } _recentChanges = tempRecentHolder; } } catch (Exception e) { string debugView = e.ToString(); } } private void b_Click(object sender, EventArgs e) { GuiEnvironment.RecordUseCase(_windowPrefix + ".Button.WSF.ShowMe", _sendManager); Button test = sender as Button; Filter filter = (Filter)test.Tag; LaunchConfigDemo(filter); } private void LaunchConfigDemo(Filter filter) { if (null == filter) // This shouldn't happen. The button should be disabled. return; Initializer args; args.Filter = filter; args.ConnectionMaster = _connectionMaster; args.ConfigurationWindowManager = _configurationWindowManager; args.CurrentStrategy = _strategy; args.WindowPrefix = _windowPrefix; using (ConfigDemo dialog = new ConfigDemo(args)) { dialog.MinText = getFilterInfoFromConfig(filter.InternalCode, true); dialog.MaxText = getFilterInfoFromConfig(filter.InternalCode, false); dialog.ShowDialog(); if (dialog.DialogResult == System.Windows.Forms.DialogResult.OK) { putFilterInfoToConfig(filter.InternalCode, dialog.MinText, dialog.MaxText); } } } private void tabWindowsSpecificFilters_Enter(object sender, EventArgs e) { if (_needToInitializeFilterPanel) { bool checkOkButton = btnOK.Enabled; _needToInitializeFilterPanel = false; searchFilters(); if (_firstFilterView) { if (checkOkButton) { btnOK.Enabled = true; } else { btnOK.Enabled = false; } _firstFilterView = false; } else { btnOK.Enabled = true; } } } private void showRecentChanges(object sender, EventArgs e) { /*This method displays icons(if any) in the Recent Changes area within the WindowName tab*/ if (_recentChanges.Count == 0) { pnlRecentChanges.Visible = false; lblChanges.Hide(); } else { ExtensionMethods.Clear(pnlRecentChanges.Controls, true); pnlRecentChanges.Visible = true; lblChanges.Visible = true; } pnlRecentChanges.SuspendLayout(); string testString = null; foreach (var item in _recentChanges) { string codeID; PictureBox pictureBox = new PictureBox(); pictureBox.MouseClick += new MouseEventHandler(pictureBox_MouseClick); pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; if (item.Contains("Max") || item.Contains("Min")) { string filterInternalID = ""; testString = "Filter"; pictureBox.BorderStyle = BorderStyle.None; if (item.Contains("Max")) { Filter f = _configurationWindowManager.FindFilter(item.Substring(3)); filterInternalID = f.InternalCode; toolTip.SetToolTip(pictureBox, "Max " + f.Description); pictureBox.Name = "WSF_" + item; pictureBox.ContextMenuStrip = createIconPopup(testString, "", filterInternalID); pictureBox.ContextMenuStrip.Name = pictureBox.Name; codeID = item; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(codeID); }; } else { Filter f = _configurationWindowManager.FindFilter(item.Substring(3)); filterInternalID = f.InternalCode; toolTip.SetToolTip(pictureBox, "Min " + f.Description); pictureBox.Name = "WSF_" + item; pictureBox.ContextMenuStrip = createIconPopup(testString, "", filterInternalID); pictureBox.ContextMenuStrip.Name = pictureBox.Name; codeID = item; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(codeID); }; } } else { testString = "Alert"; Alert a = _configurationWindowManager.FindAlert(item); toolTip.SetToolTip(pictureBox, a.Description); pictureBox.BorderStyle = BorderStyle.Fixed3D; pictureBox.Name = item; pictureBox.ContextMenuStrip = createIconPopup(testString, "", ""); pictureBox.ContextMenuStrip.Name = pictureBox.Name; codeID = item; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetAlert(codeID); }; } pictureBox.Margin = new Padding(1); pnlRecentChanges.Controls.Add(pictureBox); } ReDisplayRecentChanges(); pnlRecentChanges.ResumeLayout(); //SUMMARY PANEL STRATEGY UPDATE CODING BELOW" pnlSummary.SuspendLayout(); ExtensionMethods.Clear(pnlSummary.Controls, true); pnlSummary.ResumeLayout(); int top = 5; int leftPadding = 10; pnlSummary.SuspendLayout(); if (_configurationType == ConfigurationType.Alerts && _alertStrategy.Alerts.Any()) { //make the Alert Header Label: Label alertHeader = new Label(); alertHeader.Text = "Alerts:"; alertHeader.Name = "Header"; alertHeader.Top = top; alertHeader.Left = leftPadding; alertHeader.Font = new Font(this.Font, FontStyle.Bold); alertHeader.Height = TextRenderer.MeasureText(alertHeader.Text, Font).Height; pnlSummary.Controls.Add(alertHeader); top += alertHeader.Height; foreach (Alert alert in _alertStrategy.Alerts) { string description = alert.Description.ToString(); var labelHeight = TextRenderer.MeasureText(description, Font).Height; var maxHeight = Math.Max(GuiEnvironment.ICON_HEIGHT, labelHeight); var centerImage = maxHeight == labelHeight; testString = "Alert"; PictureBox pictureBox = new PictureBox(); pictureBox.MouseClick += new MouseEventHandler(pictureBox_MouseClick); pictureBox.BorderStyle = BorderStyle.Fixed3D; pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.Top = centerImage ? top + (maxHeight - pictureBox.Height)/2 : top; pictureBox.Left = leftPadding; toolTip.SetToolTip(pictureBox, alert.Description); pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; pictureBox.Name = alert.InternalCode; pictureBox.ContextMenuStrip = createIconPopup(testString, "", ""); pictureBox.ContextMenuStrip.Name = pictureBox.Name; Alert saveAlert = alert; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetAlert(saveAlert.InternalCode); }; pnlSummary.Controls.Add(pictureBox); //make the labels Label lblAlert = new Label(); lblAlert.Name = alert.InternalCode.ToString(); lblAlert.Left = pictureBox.Right + 6; lblAlert.AutoSize = true; lblAlert.Text = description; lblAlert.Top = centerImage ? top: top + (maxHeight - labelHeight)/2; pnlSummary.Controls.Add(lblAlert); top += maxHeight; } } //filters...(loading up Config.Demo's "summaryDictionary"...) Dictionary> summaryDictionary = ConfigDemoInWords.DescribeInWords(_configurationWindowManager, _strategy, null); if (_configurationType == ConfigurationType.Alerts) { top += 10; } else { top = 7; } //make the Filter Header Label: if (summaryDictionary.Any()) { Label filterHeader = new Label(); filterHeader.Text = "Filters:"; filterHeader.Name = "Header"; filterHeader.Top = top; filterHeader.Left = leftPadding; filterHeader.Font = new Font(this.Font, FontStyle.Bold); filterHeader.Height = TextRenderer.MeasureText(filterHeader.Text, filterHeader.Font).Height; pnlSummary.Controls.Add(filterHeader); top += filterHeader.Height; foreach (KeyValuePair> kvp in summaryDictionary) { var text = returnComments(kvp.Value); var labelHeight = TextRenderer.MeasureText(text, Font).Height; var maxHeight = Math.Max(GuiEnvironment.ICON_HEIGHT, labelHeight); var centerImage = maxHeight == labelHeight; testString = "Filter"; PictureBox pictureBox = new PictureBox(); pictureBox.MouseClick += new MouseEventHandler(pictureBox_MouseClick); pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.Top = centerImage? top + (maxHeight - pictureBox.Height)/2 : top; pictureBox.Left = leftPadding; pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; /*"_Min" used since we're displaying the teal filters in the panel...really shouldn't matter in this case*/ pictureBox.Name = "WSF_Min" + (kvp.Key).InternalCode; Filter saveFilter = kvp.Key; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(saveFilter.MinCode); }; toolTip.SetToolTip(pictureBox, saveFilter.Description); pictureBox.ContextMenuStrip = createIconPopup(testString, "", (kvp.Key).InternalCode); pictureBox.ContextMenuStrip.Name = pictureBox.Name; if (returnComments(kvp.Value).Contains("All stocks")) { /*We only want stuff showing in the summary panel that have actual data in the text box corresponding to the filter*/ continue; } pnlSummary.Controls.Add(pictureBox); //make the labels Label lblFilter = new Label(); lblFilter.Name = kvp.Key.InternalCode.ToString(); lblFilter.Left = pictureBox.Right + 6; lblFilter.AutoSize = true; lblFilter.AutoEllipsis = true; lblFilter.Text = text; lblFilter.Top = centerImage? top : top + (maxHeight - labelHeight)/2; pnlSummary.Controls.Add(lblFilter); top += maxHeight; } } // Display TopList sort by (server sort) information if (_configurationType == ConfigurationType.TopList) { // Add Sort filter _topListStrategy.SortBy Filter sortFilter = null; /*This method retrieves the SortBy data when user instantiates a TopListConfig Window*/ foreach (Filter f in _configurationWindowManager.FiltersInOrder) { if (_serverSortFromOutside) { if (f.InternalCode == _outsideICode) { sortFilter = f; break; } } else if (f == _topListStrategy.SortBy) { sortFilter = f; break; } } String sortDirection = ""; if (_topListStrategy.BiggestOnTop == true) { sortDirection = "Biggest on Top"; } else { sortDirection = "Smallest on Top"; } if (sortFilter != null) { //make the Sort By Header Label: Label sortHeader = new Label(); sortHeader.Text = "Sort By:"; sortHeader.Name = "Header"; sortHeader.Top = top; sortHeader.Left = leftPadding; sortHeader.Font = new Font(this.Font, FontStyle.Bold); sortHeader.Size = TextRenderer.MeasureText(sortHeader.Text, sortHeader.Font); pnlSummary.Controls.Add(sortHeader); top += sortHeader.Height; var text = sortFilter.Description + " with " + sortDirection; var labelHeight = TextRenderer.MeasureText(text, Font).Height; var maxHeight = Math.Max(GuiEnvironment.ICON_HEIGHT, labelHeight); var centerImage = maxHeight == labelHeight; testString = "Filter"; PictureBox pictureBox = new PictureBox(); pictureBox.MouseClick += new MouseEventHandler(pictureBox_MouseClick); pictureBox.Visible = true; pictureBox.Height = GuiEnvironment.ICON_HEIGHT; pictureBox.Width = GuiEnvironment.ICON_WIDTH; pictureBox.Top = centerImage ? top + (maxHeight - pictureBox.Height)/2 : top; pictureBox.Left = leftPadding; pictureBox.SizeMode = PictureBoxSizeMode.CenterImage; /*"_Min" used since we're displaying the teal filters in the panel...really shouldn't matter in this case*/ pictureBox.Name = "WSF_Min" + sortFilter.InternalCode; pictureBox.Tag = (DoUpdate)delegate { pictureBox.Image = _imageCacheManager.GetFilter(sortFilter.MinCode); }; toolTip.SetToolTip(pictureBox, sortFilter.Description); pictureBox.ContextMenuStrip = createIconPopup(testString, "", sortFilter.InternalCode); pictureBox.ContextMenuStrip.Name = pictureBox.Name; //make the labels Label lblFilter = new Label(); lblFilter.Name = sortFilter.InternalCode.ToString(); lblFilter.Left = pictureBox.Right + 6; lblFilter.AutoSize = true; lblFilter.Text = text; lblFilter.Top = centerImage ? top : top + (maxHeight - labelHeight)/2; pnlSummary.Controls.Add(pictureBox); pnlSummary.Controls.Add(lblFilter); } } ReDisplaySummary(); pnlSummary.ResumeLayout(); } private string returnComments(List item) { string final = ""; if (item.Count == 1) { item[0] = item[0].Replace("The", "Stocks where the"); return final = item[0]; } else //multiple sentences in string..It is noted that each sentence begins with "The" { for (int i = 0; i < item.Count; i++) { if (i == 0) { item[i] = item[i].Replace("The", "Stocks where the"); } else { item[i] = item[i].Replace("The", "Also where the"); } final += item[i] + " "; } } return final; } private void tabWindowName_Layout(object sender, LayoutEventArgs e) { /*Utilitze the space more efficiently -let the summary panel use up the space that the "recent changes" panel would have occupied were it visible. When the "recent changes" panel does become visible however, the summary panel will decrease in size.*/ if (!pnlRecentChanges.Visible) { pnlSummary.Height = pnlRecentChanges.Bottom - pnlSummary.Top; } else { pnlSummary.Height = lblChanges.Top - pnlSummary.Top; pnlRecentChanges.Top = lblChanges.Bottom + 3; } wordWrap(); } private void tabWindowName_Resize(object sender, EventArgs e) { wordWrap(); } private void wordWrap() { if (pnlSummary.Controls.Count <= 0) return; var controls = pnlSummary.Controls; const string header = "Header"; var top = 5; if (_configurationType == ConfigurationType.Alerts && _alertStrategy.Alerts.Any()) { var headerLabel = controls.OfType