using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Drawing; using System.Windows.Forms; using System.ComponentModel; using System.Drawing.Drawing2D; using TradeIdeas.TIProData; using TradeIdeas.MiscSupport; namespace TradeIdeas.TIProGUI { class TickerSymbol : System.Windows.Forms.UserControl { private double _scrollSpeed = .025d; // private int _oldWidth = -1; private double _oldRight; private List _newSymbols = new List(); private List _oldSymbols = new List(); private DateTime _then; private CompareCount _compareCount = null; //private PointF _start; //private PointF _end; private float[] _dist = { 0.0f, 0.18f, 1.0f }; private ColorBlend _myBlendGreen = new ColorBlend(); private ColorBlend _myBlendRed = new ColorBlend(); private const int SYMBOL_GAP = 1; //this is a gap that functions as a divider between symbols on the ticker... private const int HEIGHT_OFFSET = 0; private List pointMap; //store info pertaining to each symbol that comes on the ticker. private Timer timer = new Timer(); /*Required:*/ private System.ComponentModel.Container _components = null; // new variable for symbol linking channel - RVH20210927 private string _linkChannel = SymbolLinkChannels.DefaultLinkChannel; public TickerSymbol() { InitializeComponent(); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.DoubleBuffer, true); this.SetStyle(ControlStyles.ResizeRedraw, true); this.SetStyle(ControlStyles.Selectable, true); this.SetStyle(ControlStyles.UserPaint, true); this.BackColor = Color.Black; pointMap = new List(); _oldRight = this.ClientRectangle.Width; this.Paint += new PaintEventHandler(TickerSymbol_Paint); //Set up Gradients.. //_start = new PointF(0, 0); //_end = new PointF(0, Height - HEIGHT_OFFSET); Color[] colorsGreen = { Color.FromArgb(0, 139, 0), Color.Green, Color.FromArgb(0, 27, 0) }; Color[] colorsRed = { Color.FromArgb(139, 0, 0), Color.Red, Color.FromArgb(27, 0, 0) }; _myBlendGreen.Colors = colorsGreen; _myBlendGreen.Positions = _dist; _myBlendRed.Colors = colorsRed; _myBlendRed.Positions = _dist; timer.Interval = 500; timer.Enabled = true; timer.Tick += new System.EventHandler(timer_Tick); this.MouseEnter += new EventHandler(TickerSymbol_MouseEnter); this.MouseLeave +=new EventHandler(TickerSymbol_MouseLeave); this.MouseClick += new MouseEventHandler(TickerSymbol_MouseSingleClick); this.MouseDoubleClick +=new MouseEventHandler(TickerSymbol_MouseDoubleClick); } public CompareCount CompareCountOwner { get {return _compareCount;} set { _compareCount = value;} } private void TickerSymbol_MouseEnter(object sender, EventArgs e) { timer.Stop(); } private void TickerSymbol_MouseLeave(object sender, EventArgs e) { timer.Start(); } private void TickerSymbol_MouseSingleClick(object sender, MouseEventArgs e) { if (GuiEnvironment.IntegrationSupportSingleClick) { Point p = e.Location; foreach (CustomTextRectangle r in pointMap) { if (r.contains(p)) { RowData rowData = r.getSymbolInfo().getRowData(); SendToExternalLinking(rowData); break; } } timer.Start(); } } private void RecordExternalLinkUseCase(RowData rowData) { GuiEnvironment.RecordExternalLinkingUseCase(rowData, "Ticker"); } private void SendToExternalLinking(RowData rowData) { RecordExternalLinkUseCase(rowData); string symbol = rowData.GetSymbol(); string exchange = rowData.GetExchange(); GuiEnvironment.sendSymbolToExternalConnector(symbol, exchange, "", null, rowData, linkChannel: _linkChannel, dockWindowID: GuiEnvironment.GetDockWindowID(this.ParentForm)); } private void TickerSymbol_MouseDoubleClick(object sender, MouseEventArgs e) { if (GuiEnvironment.IntegrationSupportSingleClick == false) { Point p = e.Location; foreach (CustomTextRectangle r in pointMap) { if (r.contains(p)) { RowData rowData = r.getSymbolInfo().getRowData(); SendToExternalLinking(rowData); break; } } timer.Start(); } } protected override void Dispose(bool disposing) { if (disposing) { if (_components != null) { _components.Dispose(); } } base.Dispose(disposing); } //For Designer support... private void InitializeComponent() { // // TickerSymbol // this.Name = "TickerSymbol"; this.Size = new System.Drawing.Size(264, 32); this.Paint += new PaintEventHandler(TickerSymbol_Paint); } public void addSymbol(String config, RowData rowData, Color color) { if (rowData.GetSymbol() != "") { _newSymbols.Add(new SymbolInfo(config,rowData,color)); } } public void startScrolling() { _then = DateTime.Now; timer.Start(); } public void reset() { timer.Stop(); _oldSymbols.Clear(); _newSymbols.Clear(); _oldRight = this.ClientRectangle.Width; timer.Start(); } private void TickerSymbol_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.InterpolationMode = InterpolationMode.HighQualityBicubic; paintTicker(g); } private void paintTicker(Graphics g) { pointMap.Clear(); SolidBrush brushBlack = new SolidBrush(Color.Black); g.FillRectangle(brushBlack, 0, HEIGHT_OFFSET, Width, Height); brushBlack.Dispose(); double currentRight = Math.Max(_oldRight, Width); //if we are already too far behind, ignore the new symbols if (_oldRight > Width + 2000) { _newSymbols.Clear(); } while (_newSymbols.Count() > 0) { SymbolInfo current = new SymbolInfo(_newSymbols[0].getConfig(), _newSymbols[0].getRowData(), _newSymbols[0].getColor()); _newSymbols.RemoveAt(0); SizeF size = g.MeasureString(current.getSymbol(), Font); int w = (int)size.Width; currentRight += w; _oldSymbols.Insert(0, current); } _oldRight = currentRight; List toRemove = new List(); foreach (SymbolInfo current in _oldSymbols) { if (currentRight < 0) { toRemove.Add(current); } else { SizeF size = g.MeasureString(current.getSymbol(), Font); int symbolWidth = (int)size.Width; CustomTextRectangle r = new CustomTextRectangle((int)currentRight - symbolWidth, HEIGHT_OFFSET, symbolWidth - SYMBOL_GAP, Height, current); LinearGradientBrush gradBrsh = new LinearGradientBrush(r.getRectangle(), Color.Transparent, Color.Transparent, LinearGradientMode.Vertical); if (currentRight >= 0) { if (current.getColor() == Color.Red) { gradBrsh.InterpolationColors = _myBlendRed; } else { gradBrsh.InterpolationColors = _myBlendGreen; } pointMap.Add(r); g.FillRectangle(gradBrsh, r.getRectangle()); gradBrsh.Dispose(); //Draw the symbol string SolidBrush brshBlack = new SolidBrush(Color.Black); SolidBrush brshWhite = new SolidBrush(Color.White); g.DrawString(current.getSymbol(), Font, brshBlack, (int)currentRight - symbolWidth - 1, 4); g.DrawString(current.getSymbol(), Font, brshWhite, (int)currentRight - symbolWidth - 2, 3); // Dispose brushes brshBlack.Dispose(); brshWhite.Dispose(); } currentRight -= symbolWidth; } if (_oldRight > Width) { DateTime now = DateTime.Now; if (now >= _then) { TimeSpan diff = now.Subtract(_then); long timeDiff = (long) diff.TotalMilliseconds; updateScrollSpeed(_oldRight - Width, timeDiff); _oldRight = Math.Max(Width, _oldRight - _scrollSpeed * (timeDiff)); } _then = now; } _then = DateTime.Now; } } private void updateScrollSpeed(double pixelsBehind, long timeDiff) { if (pixelsBehind >= 1000d) { _scrollSpeed += 0.006d * (timeDiff / 120d); _scrollSpeed = Math.Min(_scrollSpeed, 0.12d); } else if (pixelsBehind >= 300d) { _scrollSpeed += 0.003d * (timeDiff / 120d); _scrollSpeed = Math.Min(_scrollSpeed, 0.09d); } else if (pixelsBehind < 50) { _scrollSpeed -= 0.006d * (timeDiff / 120d); _scrollSpeed = Math.Max(_scrollSpeed, 0.018d); } else { if (_scrollSpeed > 0.75d) { _scrollSpeed -= 0.003d * (timeDiff / 120d); _scrollSpeed = Math.Max(_scrollSpeed, 0.075d); } else { _scrollSpeed += 0.003d * (timeDiff / 120d); _scrollSpeed = Math.Min(_scrollSpeed, 0.075d); } } } private void timer_Tick(object sender, EventArgs e) { this.Refresh(); } /// /// Set the symbol link channel /// /// The link channel public void SetLinkChannel(string linkChannel) { _linkChannel = linkChannel; } /// /// Get the symbol link channel /// public string GetLinkChannel() { return _linkChannel; } } public class SymbolInfo { private String _symbol; private Color _color; private String _exchange; private String _config; private RowData _rowData; public SymbolInfo(String config, RowData rowData, Color col) { _rowData = rowData; _symbol = " " + _rowData.GetSymbol() + " "; _exchange = _rowData.GetExchange(); _color = col; _config = config; } public Color getColor() { return _color; } public String getSymbol() { return _symbol; } public String getExchange() { return _exchange; } public String getConfig() { return _config; } public RowData getRowData() { return _rowData; } } public class CustomTextRectangle { private double _x; private double _y; private double _width; private double _height; public SymbolInfo _symbolInfo; public Rectangle _bounds; CustomTextRectangle(){} public CustomTextRectangle(double x,double y,double width,double height, SymbolInfo symbolInfo) { _x = x; _y = y; _width = width; _height = height; _symbolInfo = symbolInfo; _bounds = new Rectangle((int)x,(int)y,(int)width,(int)height); } public Rectangle getRectangle() { return _bounds; } public void setSymbolInfo(SymbolInfo symbol) { _symbolInfo = symbol; } public SymbolInfo getSymbolInfo() { return _symbolInfo; } public double getX() { return _x; } public double getY() { return _y; } public double getWidth() { return _width; } public double getHeight() { return _height; } public bool contains(Point p) { return _bounds.Contains(p); } } }