I am trying to implement a status indicator that includes some text and a green/red/yellow circle. I want this panel to be included in several forms, and that when the text/color is updated, the changes are reflected on every children.
I have a base class:
public class StatusIndicatorBase : Panel
{
public Brush indicatorColor;
public SolidBrush redBrush = new SolidBrush(Color.Red);
public SolidBrush greenBrush = new SolidBrush(Color.Green);
public SolidBrush yellowBrush = new SolidBrush(Color.Yellow);
public Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent };
public int indicatorBorderSize = 1;
public int indicatorSize = 20;
public int marginSize = 8;
public enum status { red, green, yellow };
public void SetText(string message, status currentStatus)
{
int oldWidth = TextRenderer.MeasureText(indicatorText.Text, indicatorText.Font).Width;
indicatorText.Text = message;
int newWidth = TextRenderer.MeasureText(indicatorText.Text, indicatorText.Font).Width;
indicatorText.Width = newWidth;
indicatorText.Top = (indicatorText.Height - this.Height);
this.Width = indicatorText.Width + indicatorSize;
this.Location = new Point(this.Location.X + (oldWidth - newWidth), this.Location.Y);
SetColor(currentStatus);
this.Refresh();
}
public string GetText()
{
return indicatorText.Text;
}
public void SetColor(status currentStatus)
{
switch (currentStatus)
{
case status.green:
indicatorColor = greenBrush;
break;
case status.red:
indicatorColor = redBrush;
break;
case status.yellow:
indicatorColor = yellowBrush;
break;
}
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen pen = new Pen(Color.Black, indicatorBorderSize);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int size = indicatorSize - indicatorBorderSize * 4;
g.DrawEllipse(pen, this.Width - indicatorSize, 0, size, size);
g.FillEllipse(indicatorColor, this.Width - indicatorSize, 0, size, size);
g.Dispose();
this.BringToFront();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
}
}
And the children class that inheritate from it:
public class StatusIndicator : StatusIndicatorBase
{
public StatusIndicator(int clientWidth, int clientHeight)
{
this.Height = indicatorSize;
this.RightToLeft = RightToLeft.Yes;
this.Location = new Point(clientWidth - indicatorSize - marginSize, clientHeight - this.Height - marginSize);
this.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
SetText("", status.green);
this.Controls.Add(indicatorText);
}
}
Then I create a few status indicator objects in different forms:
statusIndicator = new StatusIndicator(this.ClientRectangle.Width, this.ClientRectangle.Height);
this.Controls.Add(statusIndicator);
However, when I do:
statusIndicator.SetText("All goooood", StatusIndicator.status.green);
only that statusIndicator will get updated.
I know that I am doing something wrong, probably the whole approach is wrong, but I cannot figure out what.
I managed to solve this without inheritance, like @canton7 commented.
public class StatusIndicatorBase
{
public static SolidBrush redBrush = new SolidBrush(Color.Red);
public static SolidBrush greenBrush = new SolidBrush(Color.Green);
public static SolidBrush yellowBrush = new SolidBrush(Color.Yellow);
public static SolidBrush indicatorColor = greenBrush;
public static Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent, Text = "" };
public static int indicatorBorderSize = 1;
public static int indicatorSize = 20;
public static int marginSize = 8;
public int oldTextWidth;
public int newTextWidth;
public enum status { red, green, yellow };
public static void SetText(string message, status currentStatus)
{
SetColor(currentStatus);
indicatorText.Text = message;
}
public static string GetText()
{
return indicatorText.Text;
}
private static void SetColor(status currentStatus)
{
switch (currentStatus)
{
case status.green:
indicatorColor = greenBrush;
break;
case status.red:
indicatorColor = redBrush;
break;
case status.yellow:
indicatorColor = yellowBrush;
break;
}
}
Then created a class that inheritates from Panel and use an event for TextChanged to fire when the StatusIndicatorBase text changes. This way I can have several panels with the indicator "light" and text and update the text on all of them by just changing the text on StatusIndicatorBase.
public class StatusIndicator : Panel
{
private Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent, Text = ""};
private SolidBrush indicatorColor = StatusIndicatorBase.indicatorColor;
public StatusIndicator(int clientWidth, int clientHeight)
{
this.Height = StatusIndicatorBase.indicatorSize;
this.RightToLeft = RightToLeft.Yes;
this.Location = new Point(clientWidth - StatusIndicatorBase.indicatorSize - StatusIndicatorBase.marginSize, clientHeight - this.Height - StatusIndicatorBase.marginSize);
this.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
this.Controls.Add(this.indicatorText);
UpdateIndicator();
StatusIndicatorBase.indicatorText.TextChanged += IndicatorText_TextChanged;
}
private void IndicatorText_TextChanged(object sender, EventArgs e)
{
UpdateIndicator();
}
public void UpdateIndicator()
{
int oldWidth = TextRenderer.MeasureText(this.indicatorText.Text, this.indicatorText.Font).Width;
this.indicatorText.Text = StatusIndicatorBase.indicatorText.Text;
int newWidth = TextRenderer.MeasureText(this.indicatorText.Text, this.indicatorText.Font).Width;
this.indicatorText.Width = newWidth;
this.indicatorText.Top = (indicatorText.Height - this.Height);
this.Width = this.indicatorText.Width + StatusIndicatorBase.indicatorSize;
this.Location = new Point (this.Location.X + (oldWidth - newWidth), this.Location.Y);
this.indicatorColor = StatusIndicatorBase.indicatorColor;
this.Refresh();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen pen = new Pen(Color.Black, StatusIndicatorBase.indicatorBorderSize);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int size = StatusIndicatorBase.indicatorSize - StatusIndicatorBase.indicatorBorderSize * 4;
g.DrawEllipse(pen, this.Width - StatusIndicatorBase.indicatorSize, 0, size, size);
g.FillEllipse(this.indicatorColor, this.Width - StatusIndicatorBase.indicatorSize, 0, size, size);
g.Dispose();
this.BringToFront();
}
}