Server/MarqueeLabel.cs
changeset 18 7acec5059fa6
parent 17 19c1aaf900dc
child 30 c375286d1a1c
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Server/MarqueeLabel.cs	Tue Aug 12 20:55:50 2014 +0200
     1.3 @@ -0,0 +1,293 @@
     1.4 +using System;
     1.5 +using System.Collections.Generic;
     1.6 +using System.ComponentModel;
     1.7 +using System.Diagnostics;
     1.8 +using System.Linq;
     1.9 +using System.Text;
    1.10 +using System.Threading.Tasks;
    1.11 +//using System.Timers;
    1.12 +using System.Windows.Forms;
    1.13 +using System.Drawing;
    1.14 +
    1.15 +namespace SharpDisplayManager
    1.16 +{
    1.17 +    [System.ComponentModel.DesignerCategory("Code")]
    1.18 +    public class MarqueeLabel : Label
    1.19 +    {
    1.20 +        private bool iOwnTimer;
    1.21 +        private StringFormat iStringFormat;
    1.22 +        private SolidBrush iBrush;
    1.23 +        private SizeF iTextSize;
    1.24 +        private SizeF iSeparatorSize;
    1.25 +
    1.26 +        [Category("Appearance")]
    1.27 +        [Description("Separator in our scrolling loop.")]
    1.28 +        [DefaultValue(" | ")]
    1.29 +        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    1.30 +        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    1.31 +        public string Separator { get; set; }
    1.32 +
    1.33 +        [Category("Behavior")]
    1.34 +        [Description("How fast is our text scrolling, in pixels per second.")]
    1.35 +        [DefaultValue(32)]
    1.36 +        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    1.37 +        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    1.38 +        public int PixelsPerSecond { get; set; }
    1.39 +
    1.40 +        [Category("Behavior")]
    1.41 +        [Description("Use an internal or an external timer.")]
    1.42 +        [DefaultValue(true)]
    1.43 +        [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    1.44 +        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    1.45 +        public bool OwnTimer
    1.46 +        {
    1.47 +            get
    1.48 +            {
    1.49 +                return iOwnTimer;
    1.50 +            }
    1.51 +            set
    1.52 +            {
    1.53 +                iOwnTimer = value;
    1.54 +
    1.55 +                if (iOwnTimer)
    1.56 +                {
    1.57 +                    Timer = new Timer();
    1.58 +                    Timer.Interval = 10;
    1.59 +                    Timer.Tick += new EventHandler(Timer_Tick);
    1.60 +                    Timer.Start();
    1.61 +                }
    1.62 +                else
    1.63 +                {
    1.64 +                    if (Timer != null)
    1.65 +                        Timer.Dispose();
    1.66 +                    Timer = null;
    1.67 +                }
    1.68 +
    1.69 +            }
    1.70 +        }
    1.71 +
    1.72 +        private int CurrentPosition { get; set; }
    1.73 +        private Timer Timer { get; set; }
    1.74 +        private DateTime LastTickTime { get; set; }
    1.75 +        private double PixelsLeft { get; set; }
    1.76 +        //DateTime a = new DateTime(2010, 05, 12, 13, 15, 00);
    1.77 +        //DateTime b = new DateTime(2010, 05, 12, 13, 45, 00);
    1.78 +        //Console.WriteLine(b.Subtract(a).TotalMinutes);
    1.79 +
    1.80 +        public MarqueeLabel()
    1.81 +        {
    1.82 +            UseCompatibleTextRendering = true;
    1.83 +            //PixelsPerSecond = 32;
    1.84 +            LastTickTime = DateTime.Now;
    1.85 +            PixelsLeft = 0;
    1.86 +            iBrush = new SolidBrush(ForeColor);
    1.87 +        }
    1.88 +
    1.89 +        public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime)
    1.90 +        {
    1.91 +            if (!NeedToScroll())
    1.92 +            {
    1.93 +                CurrentPosition = 0;
    1.94 +                return;
    1.95 +            }
    1.96 +
    1.97 +            while (CurrentPosition > (iTextSize.Width + iSeparatorSize.Width))
    1.98 +            {
    1.99 +                CurrentPosition -= ((int)(iTextSize.Width + iSeparatorSize.Width));
   1.100 +            }
   1.101 +
   1.102 +            PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond;
   1.103 +
   1.104 +            //Keep track of our pixels left over
   1.105 +            //PixelsLeft = offset - Math.Truncate(offset);
   1.106 +            double offset = Math.Truncate(PixelsLeft);
   1.107 +            PixelsLeft -= offset;
   1.108 +
   1.109 +            CurrentPosition += Convert.ToInt32(offset);
   1.110 +
   1.111 +            /*
   1.112 +            if (offset > 1.0)
   1.113 +            {
   1.114 +                BackColor = Color.Red;
   1.115 +            }
   1.116 +            else if (offset==1.0)
   1.117 +            {
   1.118 +                if (BackColor != Color.White)
   1.119 +                {
   1.120 +                    BackColor = Color.White;
   1.121 +                }
   1.122 +
   1.123 +            }
   1.124 +            else
   1.125 +            {
   1.126 +                //Too slow
   1.127 +                //BackColor = Color.Green;
   1.128 +            }*/
   1.129 +
   1.130 +            //Only redraw if something has changed
   1.131 +            if (offset != 0)
   1.132 +            {
   1.133 +                Invalidate();
   1.134 +            }
   1.135 +        }
   1.136 +
   1.137 +        void Timer_Tick(object sender, EventArgs e)
   1.138 +        {
   1.139 +            DateTime NewTickTime = DateTime.Now;
   1.140 +            //
   1.141 +            UpdateAnimation(LastTickTime, NewTickTime);
   1.142 +            //
   1.143 +            LastTickTime = NewTickTime;
   1.144 +        }
   1.145 +
   1.146 +        private StringFormat GetStringFormatFromContentAllignment(ContentAlignment ca)
   1.147 +        {
   1.148 +            StringFormat format = new StringFormat();
   1.149 +            format = StringFormat.GenericTypographic;
   1.150 +            switch (ca)
   1.151 +            {
   1.152 +                case ContentAlignment.TopCenter:
   1.153 +                    format.Alignment = StringAlignment.Near;
   1.154 +                    format.LineAlignment = StringAlignment.Center;
   1.155 +                    break;
   1.156 +                case ContentAlignment.TopLeft:
   1.157 +                    format.Alignment = StringAlignment.Near;
   1.158 +                    format.LineAlignment = StringAlignment.Near;
   1.159 +                    break;
   1.160 +                case ContentAlignment.TopRight:
   1.161 +                    format.Alignment = StringAlignment.Near;
   1.162 +                    format.LineAlignment = StringAlignment.Far;
   1.163 +                    break;
   1.164 +                case ContentAlignment.MiddleCenter:
   1.165 +                    format.Alignment = StringAlignment.Center;
   1.166 +                    format.LineAlignment = StringAlignment.Center;
   1.167 +                    break;
   1.168 +                case ContentAlignment.MiddleLeft:
   1.169 +                    format.Alignment = StringAlignment.Center;
   1.170 +                    format.LineAlignment = StringAlignment.Near;
   1.171 +                    break;
   1.172 +                case ContentAlignment.MiddleRight:
   1.173 +                    format.Alignment = StringAlignment.Center;
   1.174 +                    format.LineAlignment = StringAlignment.Far;
   1.175 +                    break;
   1.176 +                case ContentAlignment.BottomCenter:
   1.177 +                    format.Alignment = StringAlignment.Far;
   1.178 +                    format.LineAlignment = StringAlignment.Center;
   1.179 +                    break;
   1.180 +                case ContentAlignment.BottomLeft:
   1.181 +                    format.Alignment = StringAlignment.Far;
   1.182 +                    format.LineAlignment = StringAlignment.Near;
   1.183 +                    break;
   1.184 +                case ContentAlignment.BottomRight:
   1.185 +                    format.Alignment = StringAlignment.Far;
   1.186 +                    format.LineAlignment = StringAlignment.Far;
   1.187 +                    break;
   1.188 +            }
   1.189 +
   1.190 +            format.FormatFlags |= StringFormatFlags.NoWrap;
   1.191 +            format.FormatFlags |= StringFormatFlags.NoClip;
   1.192 +            format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
   1.193 +            format.Trimming = StringTrimming.None;
   1.194 +
   1.195 +            return format;
   1.196 +        }
   1.197 +
   1.198 +        protected override void OnForeColorChanged(EventArgs e)
   1.199 +        {
   1.200 +            //Color has changed recreate our brush
   1.201 +            iBrush = new SolidBrush(ForeColor);
   1.202 +
   1.203 +            base.OnForeColorChanged(e);
   1.204 +        }
   1.205 +
   1.206 +
   1.207 +        private void HandleTextSizeChange()
   1.208 +        {
   1.209 +            //For all string measurements and drawing issues refer to the following article:
   1.210 +            // http://stackoverflow.com/questions/1203087/why-is-graphics-measurestring-returning-a-higher-than-expected-number
   1.211 +            //Update text size according to text and font
   1.212 +            Graphics g = this.CreateGraphics();
   1.213 +            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   1.214 +            iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
   1.215 +            iTextSize = g.MeasureString(Text, Font, Int32.MaxValue, iStringFormat);
   1.216 +            iSeparatorSize = g.MeasureString(Separator, Font, Int32.MaxValue, iStringFormat);
   1.217 +
   1.218 +            if (NeedToScroll())
   1.219 +            {
   1.220 +                //Always align left when scrolling
   1.221 +                iStringFormat.Alignment = StringAlignment.Near;
   1.222 +            }
   1.223 +        }
   1.224 +
   1.225 +        protected override void OnTextChanged(EventArgs e)
   1.226 +        {
   1.227 +            HandleTextSizeChange();
   1.228 +
   1.229 +            base.OnTextChanged(e);
   1.230 +        }
   1.231 +
   1.232 +        protected override void OnFontChanged(EventArgs e)
   1.233 +        {
   1.234 +            HandleTextSizeChange();
   1.235 +
   1.236 +            base.OnFontChanged(e);
   1.237 +        }
   1.238 +
   1.239 +        protected override void OnTextAlignChanged(EventArgs e)
   1.240 +        {
   1.241 +            iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
   1.242 +
   1.243 +            base.OnTextAlignChanged(e);
   1.244 +
   1.245 +        }
   1.246 +
   1.247 +        protected override void OnPaint(PaintEventArgs e)
   1.248 +        {
   1.249 +            //Disable anti-aliasing
   1.250 +            e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   1.251 +            if (NeedToScroll())
   1.252 +            {
   1.253 +                //Draw the first one
   1.254 +                e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
   1.255 +                e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   1.256 +                //Draw separator
   1.257 +                e.Graphics.TranslateTransform(iTextSize.Width, 0);
   1.258 +                e.Graphics.DrawString(Separator, Font, iBrush, ClientRectangle, iStringFormat);
   1.259 +                //Draw the last one
   1.260 +                e.Graphics.TranslateTransform(iSeparatorSize.Width, 0);
   1.261 +                e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   1.262 +            }
   1.263 +            else
   1.264 +            {
   1.265 +                e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   1.266 +            }
   1.267 +
   1.268 +
   1.269 +
   1.270 +            //DrawText is not working without anti-aliasing. See: stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality
   1.271 +            //TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, BackColor, iTextFormatFlags);
   1.272 +
   1.273 +            //base.OnPaint(e);
   1.274 +        }
   1.275 +
   1.276 +        public bool NeedToScroll()
   1.277 +        {
   1.278 +            //if (Width < e.Graphics.MeasureString(Text, Font).Width)
   1.279 +            if (Width < iTextSize.Width)
   1.280 +            {
   1.281 +                return true;
   1.282 +            }
   1.283 +            return false;
   1.284 +        }
   1.285 +
   1.286 +        protected override void Dispose(bool disposing)
   1.287 +        {
   1.288 +            if (disposing)
   1.289 +            {
   1.290 +                if (Timer != null)
   1.291 +                    Timer.Dispose();
   1.292 +            }
   1.293 +            Timer = null;
   1.294 +        }
   1.295 +    }
   1.296 +}