Need some advice

I am trying to build an annuciator panel containing 110 indicators. Each indicator will contain some text, which will not change. It will be surrounded by a single pixel border. The background of the indicator will be one of three colors, which will indicate status. Tapping on a indicator will cause an infomation box to open.

So far, I am using a TextBox for each indicator. Using a canvas, I am able to draw a border around each TextBox.

The point at which I am stuck is drawing the background color for each indicator.

The Canvas class has a DrawRectange method which appeared to have the ability to draw the border and color the background. But, I believe that the Canvas is rendered after the control and would oblivate the text. Further, the indicator color can change often. There is not a method to remove drawing actions from the Canvas or even clear it. So the Canvas method does appear to be the way to go.

My next thought was keep the border in the Canvas, but create a class which inherits from TextBox, and override the Render method. I could then do the indicator color before calling base.Render(). I would use a FillRect to create the indicator color.

In looking at the FillRect methods, the documentation says the passed rectangle would be filled with the background image, or a color. But, there is no method which takes a color.

I could create a bitmap which is screen size, set it to be the background image for the window and then do the fill into the bitmap and use Window.FillRect to get the color into place.

Before I spend more time trying different ways of implementing what I want, I thought I would solicit advice. I get the feeling I might be missing an easy solution.

Thanks,
Mike

**** Got a chance to try using a background image for the window for coloring the indicator background and it appears to work. I still have to check it when switching between windows, but I think it will continue to work.

*** Still interested in other ways of doing it.

I think I would probably just draw a bunch of filled rectangles and overlay text. It’s simple enough to map out the touch regions and redraw as necessary. I did something similar a few years back (minus the text). It was on a Tahoe-II, but I can’t imagine it’s any harder on a FEZ.

Try not to laugh…

Ian:

I could do the GUI by directly manipulating a bitmap and flushing it to the LCD, but that would be easy way.

I decided to use Glide so I could become familiar with it. I am also interested to see how Glide operates with over 100 objects.

Ahhh… You didn’t mention Glide. I thought you were trying to pull a tack with a crowbar :wink:

Things are drawn in the order you add them; from first to last.

canvas.Clear(); // exists

I agree that there does need to be a way to update previous requests.

FillRect uses the background image (if set) or the background color. I’ll fix the documentation to make it clear.

Here’s an idea:

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation.Media;
using GHIElectronics.NETMF.Glide;
using GHIElectronics.NETMF.Glide.Display;
using GHIElectronics.NETMF.Glide.UI;

namespace Test
{
    public class Program
    {
        static Window window;
        static Canvas canvas;
        static Color[] colors = new Color[24];
        static TextBlock[] textBlock = new TextBlock[24];

        public static void Main()
        {
            window = new Window("window", 320, 240);
            window.BackColor = Colors.White;

            // Add canvas first
            canvas = new Canvas();
            window.AddChild(canvas);

            int x = 0;
            int y = 0;
            for (int i = 0; i < textBlock.Length; i++)
            {
                textBlock[i] = new TextBlock("textBlock" + i, 255, x, y + (i * 20), 160, 20);
                textBlock[i].Text = "Text " + i;
                textBlock[i].Font = FontManager.GetFont(FontManager.FontType.droid_reg12);
                textBlock[i].FontColor = Colors.White;
                textBlock[i].TextAlign = HorizontalAlignment.Center;
                textBlock[i].TextVerticalAlign = VerticalAlignment.Middle;
                textBlock[i].TapEvent += new OnTap(textBlock_TapEvent);
                window.AddChild(textBlock[i]);

                colors[i] = Colors.Green;
                canvas.DrawRectangle(0, 0, textBlock[i].X, textBlock[i].Y, textBlock[i].Width, textBlock[i].Height, 0, 0, colors[i], 0, 0, 0, 0, 0, 255);

                if (i == 11)
                {
                    x = 160;
                    y -= 240;
                }
            }

            GlideTouch.Initialize();
            Glide.MainWindow = window;

            Thread.Sleep(Timeout.Infinite);
        }

        static void textBlock_TapEvent(object sender)
        {
            TextBlock tb = (TextBlock)sender;

            canvas.Clear();

            for (int i = 0; i < textBlock.Length; i++)
            {
                if (tb == textBlock[i])
                    colors[i] = Colors.Red;
                
                canvas.DrawRectangle(0, 0, textBlock[i].X, textBlock[i].Y, textBlock[i].Width, textBlock[i].Height, 0, 0, colors[i], 0, 0, 0, 0, 0, 255);
            }

            window.Invalidate();
        }
    }
}

Thanks for the reply Josh.

I don’t know how I missed the Canvas.Clear method. :o

The code you provided would work nicely for a single window application. But, if there are multiple windows, there might be a problem. I don’t know if you keep a separate BitMap for all the windows, or there is a single BitMap which re-rendered when a window is brought to focus.

If it is the later, then only the last border will be drawn since the original original borders, which were drawn from the Canvas, has been lost when the first tap was detected.

In addition, you are invalidating the window which result in all the DisplayObjects being redrawn. With 100+ objects this might make for a sluggish refresh.

I think I am going to go with the use of a BitMap image for the window background, and paint the background color and border on the BitMap before rendering a TextBox. I will develop a bordered TextBox with background color. By overriding the Render method of the TextBox, I will not have to worry about refresh on window changes or any other external refresh stimuli such as a MessageBox. Also, when the background color is changed, only the changed TextBox needs to be repainted.

I think performance paranoia is good?

Performance paranoia is good.

Each window has its own bitmap so you don’t lose your current “state” when switching between windows.

My example is a way you could do it (currently) – not the fastest. Drawing a 110 objects at once with borders will be slow. Rather than have each object draw its own border you could use a canvas to draw the lines that separate them if they are side-by-side in a grid format (saves time).

A BackColor property will be added to TextBlock which makes sense. This will help you. Canvas will also receive a way to clear prior requests.

window = new Window("window", 320, 1100);

It’s not mentioned anywhere but if you set the height greater than the actual lcd size the window becomes scrollable! Using my example I drew 110 objects on screen with EMX and scrolling/updating was reactive (using the new BackColor property coming soon).

The addition of a Background color to a TextBlock leads to some interesting questions, I am looking forward to see how you handle use of the TextBlock background color versus using the parent window’s color.

It’s handled with the addition of a ShowBackColor property. This turns it on and off.

Been a busy weekend, but I have got the basic display done. Still have to implement the logic to update the display.

The application is going to display the status of 110 servers.

The window uses 110 enhanced TextBlock objects.

Come on GHI, hurry up and make a larger screen option :slight_smile:

Monitoring 110 servers with a uC? Now that’s quite a first spider project! What does all this server hardware do, if you don’t mind me asking?

Building a testbed to emulate a new high speed call setup protocol. Emulating a 100 node worldwide network plus supporting management points.

Google CORONET and DARPA

Is it possible for you to create 110 separate windows (one per button) ,to speed up refresh?

[quote]Is it possible for you to create 110 separate windows (one per button) ,to speed up refresh?
[/quote]

The main window consists of 110 TextBlocks.

It takes about 7-8 seconds to initialize the window, which is acceptable performance.