Ability to stack multiple Windows on the screen at the same time using Glide (similar to StackPanel for non Glide Library)

Hi Everyone,

I want to do the following using the Glide library:


Title Window (480 x 30)

Body Window (480 x 112)

Status Window (480 x 30)

I’ve seen a few examples using StackPanel, but this doesn’t seem compatible with Glide, and I am too heavily invested in Glide Windows to rework at this point.

Is there a way to do the above using Glide libraries?

all I have discovered so far is…a ‘Window’ is not a viable argument to StackPanel.Children.add(Window)

Any guidance appreciated

Would a canvas work for you?

Hi Mike,

I’ve just been trying to use multiple canvas’s and not getting far…

I want to have;

  • A generic Title Look and feel,
  • Body changes as per …
  • A generic footer for time, status ino etc

I have’t seen and examples of canvas’s used in this way (to better understand the purpose of the canvas)

Every example of canvas I have seen uses canvas as fullscreen dimensions.

Are there any examples? (I exhausted stackPanel, examples - but found they could not be used), any guidance appreciated. Unfortunately, the GHIGraphicDemo doesn’t use Glide.

Hi again Mike,
If your meaning is to have one canvas…

I’d want my base class to contain header, and footer info, and only the child would contain the body… Would this work?

I’d need to regularly update the labels for time etc - which shouldn’t be a problem.

Off to bed shortly, now quite late.

I just though it would be cleaner to do something simlar to StackPanel (if possible)

I have a similar question:

Since the constructor to the Window class does not have X and Y coordinates, only Width and Height, I assume the intention is to have every window cover the full display, and to swap them in and out as needed?

It would be nice to allow a window to be smaller than the display size, and to be positioned anywhere on the screen.

I checked the canvas documentation and realized that it could not be used as I thought.

Looks like Glide does not support multiple visible windows at the same time. I hink this would add a lot of complexity to the touch hit analyis routines.

WPF is slow for a reason. :slight_smile:

You simply need to create your own UI components that extend DisplayObjectContainer.


using System;
using Microsoft.SPOT;

using GHIElectronics.NETMF.Glide;
using GHIElectronics.NETMF.Glide.Display;

namespace StackingExample
{
    public class Titlebar : DisplayObjectContainer
    {
        public Titlebar(string name, int width, int height)
        {
            Name = name;
            Width = width;
            Height = height;
        }

        public override void Render()
        {
            // Draw a background first.
            Parent.Graphics.DrawRectangle(Rect, Colors.Blue, Alpha);

            // Then render the children.
            base.Render();
        }
    }
}

You can then add a TextBlock to it.

            // Title bar
            titlebar = new Titlebar("titlebar", Glide.LCD.Width, 30);

            // Add a TextBlock to display the title.
            TextBlock textBlock = new TextBlock("textBlock", 255, 0, 0, Glide.LCD.Width, 30);
            textBlock.Text = "I'm the title bar.";
            textBlock.FontColor = Colors.White;
            textBlock.TextAlign = HorizontalAlignment.Center;
            textBlock.TextVerticalAlign = VerticalAlignment.Middle;
            titlebar.AddChild(textBlock);

Hi Josh
Many thanks for your help

I’m pretty new to embedded graphics, and more at home in automation etc

I’m trying to work out the next step beyond the titlebar object

Can I now use stackpanel? As it would appear the titlebar object stil has no x, y to be added as a child of Window.addchild()

I think this would be a great eg for download to get everyone kick started
Regards Ian

To answer my previous unknowns…

Here’s a working solution with titlebar, body and statusbar

with runtime updates inside title and status


//-------------------------------------------------------------------------
//Courtesy of Earthed Solutions Pty Ltd (AUSTRALIA)
//www.earthed.net.au
//Custom Embedded and Windows Solutions since 1991
//-------------------------------------------------------------------------

using System;
using System.Threading;
using System.Collections;

using Microsoft.SPOT;
using GHIElectronics.NETMF.Glide;
using GHIElectronics.NETMF.Glide.Display;
using GHIElectronics.NETMF.Glide.UI;

namespace FEZ_Cobra_Console_Application_Eg1
{


    public class Titlebar : DisplayObjectContainer
    {

        public Titlebar(string name, int width, int height)
        {
            Init(name, width, height);
        }

        public Titlebar(string name, int width, int height, int iX, int iY)
        {
            X = iX;
            Y = iY;
            Init(name, width, height);
        }

        public void Init(string name, int width, int height)
        {
            Name = name;
            Width = width;
            Height = height;
            Compose();
        }

        public override void Render()
        {
            // Draw a background first.
            Parent.Graphics.DrawRectangle(Rect, Colors.Blue, Alpha);

            // Then render the children.
            base.Render();
        }

        public void Compose()
        {
            // Add a TextBlock to display the title.
            TextBlock textBlock = new TextBlock(Name + "_textBlock", 255, 0, 0, Width, Height);
            textBlock.Text = "I'm the title bar.";
            textBlock.FontColor = Colors.White;
            textBlock.TextAlign = HorizontalAlignment.Center;
            textBlock.TextVerticalAlign = VerticalAlignment.Middle;

            //===================
            // Glue glide objects 
            //===================
            this.AddChild(textBlock);
        }

        public void SetTitle(string sText)
        {
            string sChild = Name + "_textBlock";

            DisplayObject Obj = this.GetChildByName(sChild);
            if (Obj != null)
            {
                TextBlock t = (TextBlock)Obj;
                t.Text = sText;

                //force redraw of changes
                this.Invalidate();
            }
        }

    }

    public class Statusbar : DisplayObjectContainer
    {
        private string msUser;
        
        public Statusbar(string name, int width, int height)
        {
            Init(name, width, height);
        }

        public Statusbar(string name, int width, int height, int iX, int iY)
        {
            X = iX;
            Y = iY;
            Init(name, width, height);
        }

        public void Init(string name, int width, int height)
        {
            Name = name;
            Width = width;
            Height = height;
            msUser = "";
            Compose();
        }

        public void SetUser(string sUser)
        {
            msUser = sUser;
        }

        public string GetUser()
        {
            string sRet = "User: ";
            if (msUser.Equals(""))
            {
                sRet = sRet + "---";
            }
            else
            {
                sRet = sRet + msUser;
            }
            return sRet;
        }


        public string GetTime()
        {
            string sRet = "";
            DateTime t = DateTime.Now;
            sRet = t.ToString("H:mm:ss");
            return sRet;
        }

        public void Compose()
        {
            // Add a TextBlock to display user & Time.
            TextBlock statusBlock = new TextBlock(Name + "_statusBlock", 255, 0, 0, Width, Height);
            statusBlock.Text = GetUser() + "    " + GetTime();
            statusBlock.FontColor = Colors.White;
            statusBlock.TextAlign = HorizontalAlignment.Right;
            statusBlock.TextVerticalAlign = VerticalAlignment.Middle;

            //===================
            // Glue glide objects 
            //===================
            this.AddChild(statusBlock);

        }

        public override void Render()
        {
            // Draw a background first.
            Parent.Graphics.DrawRectangle(Rect, Colors.Blue, Alpha);

            // Then render the children.
            base.Render();
        }

        public void SetStatus()
        {
            string sChild = Name + "_statusBlock";

            DisplayObject Obj = this.GetChildByName(sChild);
            if (Obj != null)
            {
                TextBlock t = (TextBlock)Obj;
                t.Text = GetUser() + "    " + GetTime();

                //force redraw of changes
                this.Invalidate();
            }
        }
    }


    public class Body : DisplayObjectContainer
    {
        public Body(string name, int width, int height)
        {
            Init(name, width, height);
        }

        public Body(string name, int width, int height, int iX, int iY)
        {
            X = iX;
            Y = iY;
            Init(name, width, height);
        }
        
        public void Init(string name, int width, int height)
        {
            Name = name;
            Width = width;
            Height = height;
        }

        public override void Render()
        {
            // Draw a background first.
            Parent.Graphics.DrawRectangle(Rect, Colors.White, Alpha);

            // Then render the children.
            base.Render();
        }
    }


    public class Program
    {
        // This will hold the windows.
        static Window[] windows = new Window[3];
        static Titlebar mTitlebar;
        static Statusbar mStatusbar;
        static Body mBody;

        // Indicates the current window index.
        static int index = 0;


        public static void Calibrate()
        {
            //Essential to make touch match graphics
            Glide.FitToScreen = true;

            //Activate touch, to ensure touch points matches graphics objects
            //essential after upgrade Fez Cobra from 4.1.3 to 4.1.6 and screen defaulted back to 320x240
            GlideTouch.Initialize();
            const int CAL_POINTS = 5;
            short[] sx = new short[CAL_POINTS] { 240, 48, 48, 432, 432 };
            short[] sy = new short[CAL_POINTS] { 136, 26, 246, 246, 26 };
            short[] cx = new short[CAL_POINTS] { 478, 189, 169, 781, 790 };
            short[] cy = new short[CAL_POINTS] { 481, 238, 741, 767, 231 };
            Microsoft.SPOT.Touch.Touch.ActiveTouchPanel.SetCalibration(CAL_POINTS, sx, sy, cx, cy);
        }


        public static void Main()
        {
            int Title_H = 30;
            int Status_H = 30;
            int Body_H = Glide.LCD.Height - Title_H - Status_H;

            //---------------------------------------------------------------------------
            // Setup LCD and TouchScreen
            //---------------------------------------------------------------------------
            Calibrate();

            //---------------------------------------------------------------------------
            // Title bar
            //---------------------------------------------------------------------------
            mTitlebar = new Titlebar("titlebar", Glide.LCD.Width, Title_H, 0, 0);

            //---------------------------------------------------------------------------
            // Status bar
            //---------------------------------------------------------------------------
            mStatusbar = new Statusbar("statusbar", Glide.LCD.Width, Status_H, 0, 0 + Title_H + Body_H);

            //---------------------------------------------------------------------------
            // Body Content (varies every time)
            //---------------------------------------------------------------------------
            mBody = new Body("body", Glide.LCD.Width, Glide.LCD.Height - mTitlebar.Height - mStatusbar.Height, 0,0 + Title_H);

            // Add a TextBlock to body (button etc) 
            TextBlock bodyBlock = new TextBlock("bodyBlock", 255, 0, 0, Glide.LCD.Width, 60);
            bodyBlock.Text = "Earthed Solutions Pty Ltd";
            bodyBlock.FontColor = Colors.DarkGray;
            bodyBlock.TextAlign = HorizontalAlignment.Center;
            bodyBlock.TextVerticalAlign = VerticalAlignment.Middle;


            // Add a TextBlock to body (button etc) 
            int iBtn_H = 50;
            int iBtn_W = 150;
            Button bodyButton = new Button("bodyButton", 255, ((Glide.LCD.Width -iBtn_W)/ 2) , ((Glide.LCD.Height -iBtn_H)/ 2) , iBtn_W, iBtn_H);
            bodyButton.Text = "OK";
            
            //===================
            // Glue glide objects 
            //===================
            mBody.AddChild(bodyBlock);
            mBody.AddChild(bodyButton);

            //---------------------------------------------------------------------------
            // Create window
            //---------------------------------------------------------------------------
            Window W = new Window("Window", Glide.LCD.Width, Glide.LCD.Height);
            W.BackColor = Colors.White;

            //---------------------------------------------------------------------------
            // Glue Together
            //---------------------------------------------------------------------------
            W.AddChild(mTitlebar);       //Top
            W.AddChild(mBody);           //Middle
            W.AddChild(mStatusbar);      //Bottom

            // Assigning a window to MainWindow flushes it to the screen.
            Glide.MainWindow = W;

            int i = 0;
            bool bUser = false;

            while (true)
            {

                //-------------------------------------------------------------------
                //Update Time and user info on Screen
                //-------------------------------------------------------------------
                mStatusbar.SetStatus();

                Thread.Sleep(10);
                i++;


                //-------------------------------------------------------------------
                //Arbitrary Update of Title
                //-------------------------------------------------------------------
                mTitlebar.SetTitle("www.earthed.net.au" + "  [" + i.ToString() + "]");  

                if (i > 50)
                {
                    i = 0;
                    
                    bUser = !bUser;

                    if (bUser)
                    {
                        mStatusbar.SetUser("Earthed.Ian");
                    }
                    else
                    {
                        mStatusbar.SetUser("GHI.Josh");
                    }
                }
            }
        }
    }
}

If anyone has any enhancements on this please feel free to mention on this thread

Youtube Video of the above code attached:

How do you delete a comment? Seems they can only be MODIFIED?