Glide -- Graphical Library for NETMF

Hi Peterd,
I suppose no. Before 0.2.1 release I had to delete and add again the FileGrid component because I couldn’t remove rows properly every time I needed to refresh the grid (it is because every time there might be completely different content). Older rows were still remaining. Now with using Clear and Adding items again I have only new content in DataGrid. But maybe I’m missing something. Gotta know how to interpret the description of Clear().

Let’s wait for Josh’s opinion.

Edit:
Mike,
It looks like SlideWindow uses it’s own indexing that is implemented in a not intuitive way, but according to the description of method parameters it looks like something has to be swapped inside ;). I was using this shortly just to know how does it work, now I’m not using this but I think that it would be better for SlideWindow just to have one input parameter - the window to slide over the current main window.

Regards,
Tomasz

@ Tomasz3
Label and TextBlock are essentially the same. Except Label can also toggle CheckBox or Radio buttons. I will combine Label’s functionality into TextBlock in the next release.
I don’t believe .NET Micro Framework supports UTF-8.
I will look into sorting and the image stretching.


@ peterd
DataGrid.Clear - Clears everything except the columns (this includes rows, selected index, scroll, etc).


@ Tomasz3
A data grid refresh would be updating row(s) or cell(s) as the data changes.


@ Mike
I understand the confusion, this will be addressed. It the upcoming release it will be

SlideWindow(fromWindow, toWindow, direction).

I have 9 windows in GUI I’m working on. Some of them are full of content, Images, buttons etc., so It takes a long time to initialize every window. For now it is about 14,2s. I think I will improve this later, but for now I wanted to try if initializing windows in separate threads will do the work.
In my own InitializeGUI() method I make threads with such pattern:

var splashInitThread = new Thread(() => SplashWindow.Initialize(Resources.GetString(Resources.StringResources.Splash)));
splashInitThread.Start();

But… I got a null reference exception at one of the last windows, it cannot get a child by name. When I decide to continue the execution of my program, it finishes, but with something like several windows flushed simultaneously (this happens also when I initialize those ‘exceptional’ windows without threading, thread-initialized windows have somehow combined graphics).
I doubt that it is some problem with Glide, but if you know how may I solve this - if it is possible in general and if it makes sense - please write.

Also, does it make sense to put in a thread some operations on a window when setting another window to Glide.MainWindow (these operations are not to be seen)? Or operations on MainWindow? I’m thinking about improving the time of swapping between windows or refreshing the window.

Regards,
Tomasz

Hi Josh,

Some requests:

Adjustable size and color of radiobuttons
Adjustable color of buttons.
Is it possible to make older versions of Glide software and library doc available?

Regards

Peter

i was looking at this example to calibrate the touch screen on my Cobra.
[url]http://www.ghielectronics.com/downloads/Glide/Library/html/90770305-3144-ec5b-d0f4-4593bcd76b52.htm[/url]

i did everything (or so i think) that it said but it is complaining about this line saying
// Load the window
window = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Window));

Error 1 The name ‘Resources’ does not exist in the current context

Also, i did change this:

To This

As i read in another section that you are supposed to change it from x.x.x to the version number you are using. This particular example did not say to do this.

Jdal,

Now I’ve tried to use the same example to calibrate the touch screen.
I run new Cobra Console Application, copied everything, added new text file to the resources, and also adjusted the namespace - I had to change “Test” to “FEZ_Cobra_Console_Application3” because before this it told me “Cannot access internal class ‘Resources’ here”. After this change it works fine. Maybe that is the problem?

Regards,
Tomasz

Josh,

After displaying the keyboard and pressing “done” the keyboard disappears but some “leftovers” might be seen in the background - like it is still there with alpha > 0.
With BackColor set to black it isn’t visible but when I had #625649 it was.

Also, issue with DisabledFontColor. I set it in the xml file, i.eg. for a button DisabledFontColor=“ffffff” or “FF0000”.
But it doesn’t differ from other buttons. While in debug mode I see that this field for both of colors (well, for all of the buttons) is set to 8421504. But changing it in the program like

var btn = (Button)window.GetChildByName(buttonName);
btn.DisabledFontColor = Color.White;

works.

Regards,
Tomasz

Confused with Label text… ???

I have a number of screens with labels on them, and update the contents regularly (e.g. clock display).
However, the updated data just seems to overwrite the old text, like it is layering on top, and eventually
it just looks like a black mess.

Here is a sample of the code:

            Label dtl = (Label)topWindow.GetChildByName("dtl");
 
            while (true)
            {
                dtl.Text = "";
                dtl.Invalidate();
                dtl.Text = DateTime.Now.ToString("ddd d MMM HH:mm yyyy");
                dtl.Invalidate();
                Thread.Sleep(60000);
            }
 

any ideas, is there a way to blank out a label before re-writing the contents?

Ross

Ross,

Try this:

Label dtl = (Label)topWindow.GetChildByName("dtl");
 
            while (true)
            {
                ThisWindow.FillRect(text.Rect); //it will cover previously printed label text
                //dtl.Text = "";
                //dtl.Invalidate();
                dtl.Text = DateTime.Now.ToString("ddd d MMM HH:mm yyyy");
                dtl.Invalidate();
                Thread.Sleep(60000);
            }

Regards,
Tomasz

That fixed it, many thanks!!! :smiley:

Image retention seems to be an issue within NETMF. The hack to solve this is to set the area to black then draw over it. I did this on the Window class, I believe this will help with the keyboard retention issue.

Josh,

How about this issue with no change of disabled font color? Or am I doing something wrong?

Next case - I’m trying to create my own popping up numerical keyboard. At the moment I have something like this (pre-pre-alpha ;)):
Window.txt resource:

<Glide Version="0.2.1">
  <Window Name="window" Width="320" Height="240" BackColor="000000">
    <TextBox Name="Box" X="58" Y="32" Width="84" Height="32" Alpha="255" Text="base octave" TextAlign="Center" Font="2" FontColor="000000"/>
    <TextBox Name="Box2" X="58" Y="80" Width="84" Height="32" Alpha="255" Text="bpm" TextAlign="Center" Font="2" FontColor="000000"/>
  </Window>
</Glide>

Program.cs:

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

namespace FEZ_Cobra_Console_Application4
{
    public static class Program
    {
        private static Window _window;
        private static TextBox _recentlyEdited;
        private static int _boxValue;

        public static void Main()
        {
            _window = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Window));

            GlideTouch.Initialize();

            InitWin();

            Glide.MainWindow = _window;

            Thread.Sleep(-1);
        }

        static void InitWin()
        {
            var box = (TextBox)_window.GetChildByName("Box");
            box.ValueChangedEvent += BoxValueChangedEvent;
            box.TapEvent += BoxTapEvent;

            var box2 = (TextBox)_window.GetChildByName("Box2");
            box2.ValueChangedEvent += BoxValueChangedEvent;
            box2.TapEvent += Box2TapEvent;

            var kb = new NumericalKeyboard(_window);
            kb.MaxDigits = 3;
            kb.MaxValue = 998;
            kb.ZeroAccepted = false;
            _window.AddChildAt(2, kb);
        }

        static void BoxTapEvent(object sender)
        {
            _recentlyEdited = (TextBox)sender;
            var kb = (NumericalKeyboard)_window.GetChildByName("NumericalKeyboard");
            kb.DisabledButtons = new[] { "0", "9", "BKSP", "CLR" };
            kb.OneDigit = true;
            kb.Open(sender);
        }

        private static void Box2TapEvent(object sender)
        {
            _recentlyEdited = (TextBox)sender;
            var kb = (NumericalKeyboard)_window.GetChildByName("NumericalKeyboard");
            kb.DisabledButtons = null;
            kb.OneDigit = false;
            kb.Open(sender);
        }

        static void BoxValueChangedEvent(object sender)
        {
            _boxValue = int.Parse(_recentlyEdited.Text);
            Debug.Print(_boxValue.ToString());
        }
    }
}

And NumericalKeyboard.cs:

using System;
using System.Collections;
using GHIElectronics.NETMF.Glide;
using GHIElectronics.NETMF.Glide.Display;
using GHIElectronics.NETMF.Glide.Geom;
using GHIElectronics.NETMF.Glide.UI;

namespace FEZ_Cobra_Console_Application4
{
    sealed class NumericalKeyboard : DisplayObjectContainer
    {
        private int _tempValue;
        private bool _firstChange;
        public bool OneDigit;
        public bool ZeroAccepted;
        public int DefaultValue;
        public int MaxDigits;
        public int MaxValue;
        public string[] DisabledButtons = new string[10];
        private TextBox _relatedObject;

        //todo: if there is one digit left to get to maxdigits look at maxvalue - if some buttons will make the number reach this value, disable them
        //todo: or some other possibility to check/inform the user whether the value is valid at specific point or not
        //my _toggledButtons from NIW will have to be managed from the outside

        //todo: comma/dot for double values and minus for sub-zero values

        private readonly ArrayList _buttons = new ArrayList
                                    {
                                        new Button("1", 255, 87, 58, 48, 32),
                                        new Button("2", 255, 136, 58, 48, 32),
                                        new Button("3", 255, 185, 58, 48, 32),
                                        new Button("4", 255, 87, 91, 48, 32),
                                        new Button("5", 255, 136, 91, 48, 32),
                                        new Button("6", 255, 185, 91, 48, 32),
                                        new Button("7", 255, 87, 124, 48, 32),
                                        new Button("8", 255, 136, 124, 48, 32),
                                        new Button("9", 255, 185, 124, 48, 32),
                                        new Button("0", 255, 136, 157, 48, 32),
                                        new Button("CLR", 255, 87, 157, 48, 32), //clear
                                        new Button("BKSP", 255, 185, 157, 48, 32), //bksp
                                        new Button("Ok", 255, 101, 193, 48, 32), //ok
                                        new Button("Cancel", 255, 174, 193, 48, 32), //cancel
                                    };

        private readonly TextBox _valueDisplay = new TextBox("ValueDisplay", 255, 120, 22, 80, 32);

        private readonly Canvas _drawer = new Canvas { X = 0, Y = 0, Width = 320, Height = 240, Name = "Drawer" };

        public NumericalKeyboard(DisplayObjectContainer window)
        {
            Name = "NumericalKeyboard";
            Parent = window;
            Visible = false;

            X = 0;
            Y = 0;
            Width = 320;
            Height = 240;

            DefaultValue = 0;
            ZeroAccepted = false;

            Rect = new Rectangle(0, 0, 320, 240); //is this needed?

            CombineDrawer();
            CombineDisplay();
            CombineButtons();
        }

        private void CombineDrawer()
        {
            _drawer.Parent = this;
            AddChild(_drawer);

            //_drawer.DrawRectangle(Colors.DarkGray, 0, 0, 0, 320, 240, 0, 0, Colors.DarkGray, 0, 0, Colors.DarkGray, 320, 240, 160); //I wanted to make everything on the parent window looking darker or disabled-like
            _drawer.DrawRectangle(Colors.White, 1, 76, 16, 168, 214, 0, 0, Colors.LightGray, 76, 16, Colors.Black, 84, 64, 255); //things on the window below rectangle are interactive if there is nothing more above - maybe I have to use an image instead
            //the outline must be different than White because after hiding the keyboard the outline is still there - Window BackColor is #ffffff; something with netmf
            //if the gradient is spread over whole Rectangle there might be seen some thick "lines" - like there are too few steps for usage like filling the whole big component background
        }

        private void CombineDisplay()
        {
            _valueDisplay.Parent = this;
            AddChild(_valueDisplay);

            _valueDisplay.TextAlign = 32;
            _valueDisplay.Font = FontManager.GetFont(FontManager.FontType.droid_reg10);
        }

        private void CombineButtons()
        {
            for (int i = 0; i < _buttons.Count; i++)
            {
                var foo = ((Button)_buttons[i]);
                
                AddChild(foo);
                foo.Parent = this;

                foo.Text = foo.Name;
                foo.Font = FontManager.GetFont(FontManager.FontType.droid_reg10);
                foo.TapEvent += NumKbTapEvent;
            }
        }

        private void NumKbTapEvent(object sender)
        {
            sender.GetType();
            var tappedBtn = ((Button)sender).Name;

            try
            {
                var tappedNum = int.Parse(tappedBtn);

                if (OneDigit)
                    _tempValue = tappedNum;
                else
                {
                    if (!_firstChange)
                    {
                        if (_tempValue.ToString().Length == MaxDigits)
                            return;
                        if (_tempValue*10+tappedNum >= MaxValue)
                            return;

                        _tempValue = _tempValue*10+tappedNum;
                    }
                    else
                    {
                        _tempValue = tappedNum;

                        _firstChange = false;
                    }
                }

                Update();
            }
            catch (Exception) //clr/bksp/ok/cancel tapped
            {
                var tappedFn = tappedBtn;

                switch (tappedFn)
                {
                    case "CLR":
                    {
                        _tempValue = 0;

                        Update();
                        break;
                    }
                    case "BKSP":
                    {
                        if (_tempValue.ToString().Length == 0)
                            return;

                        _tempValue = _tempValue / 10;

                        Update();
                        break;
                    }
                    case "Ok":
                    {
                        _relatedObject.Text = _tempValue.ToString();
                        Hide();
                        break;
                    }
                    case "Cancel":
                    {
                        Hide();
                        break;
                    }
                }
            }
        }

        private void Update()
        {
            _valueDisplay.Text = _tempValue.ToString();
            _valueDisplay.Invalidate();

            if (_tempValue != 0)
                ToggleOK(true);
            if (_tempValue == 0 && !ZeroAccepted)
                ToggleOK(false);
        }

        private void ToggleOK(bool enabled)
        {
            ((Button)_buttons[12]).Enabled = enabled;
            ((Window)Parent).FillRect(((Button)_buttons[12]).Rect);
            ((Button)_buttons[12]).Invalidate();
        }

        public void Open(object sender)
        {
            _relatedObject = (TextBox)sender;
            try
            {
                _tempValue = int.Parse(_relatedObject.Text);
            }
            catch(Exception)
            {
                _tempValue = DefaultValue; //for the first time 0 doesn't disable the Ok button and it might be treated as useful
            }                              //but this might be changed and if you want to have different default values for different textBoxes
                                           //you should create a NumericalKeyboard for each of them
            _firstChange = true;
            if (DisabledButtons != null)
                DisableButtons();

            _valueDisplay.Text = _tempValue.ToString();

            Show();
        }

        private void EnableButtons()
        {
            foreach (var button in _buttons)
                if (((Button)button).Enabled == false)
                    ((Button)button).Enabled = true;
        }

        private void DisableButtons()
        {
            foreach (var buttonName in DisabledButtons)
                foreach (var button in _buttons)
                    if (((Button)button).Name == buttonName)
                        ((Button)button).Enabled = false;
        }

        private void Show() //it should disable everything below but something like Parent.Interactive = false; doesn't work
        {
            Visible = true;
            Parent.Invalidate();
        }

        private void Hide()
        {
            Visible = false;
            Parent.Invalidate();
            EnableButtons();
        }
    }
}

Please take a look at it, how can this be made better and how to solve some of the issues mentioned within comments.

Also for such purpose maybe it would be nice to make a rectangle with cornerRadius > 0 but still with gradient - or maybe an image with transparent corners as a keyboard background is a better (with better performance) solution to this issue.

Regards,
Tomasz

Edit: after pressing the Clear and Backspace buttons the textBox is refreshing with noticeable delay. Well, I would be a good FEZ Turtle programmer x_x.
Edit2: No way, it’s because it is in debug mode and it takes time to print the exception info after parse fails! ^^’

Josh.

The DisplayObjectContainer property Item doesn’t seem to exist.

Peter

DisplayObjectContainer is a class.
http://www.ghielectronics.com/downloads/Glide/Library/html/675b11cd-908e-4e73-d6ba-091f0cbb1bc9.htm

What do you mean by property?

Will GLIDE get its own forum board like cobra domino and others ?
Seems like it would be nice.

Josh,

What I mean is: Accoording to the library doc the class DisplayObjectContainer should have a property Item. I would like to use that to disable all controls on a window:

for (int i=0; i>window.NumChildren; i++)
window.Item[i].Disabled = true;

But Item does not exists or renamed to ‘this’.

Peter

This is what you need:

for (int i=0; i>window.NumChildren; i++)
window[i].Disabled = true;

Great, I was also thinking about something like this but I thought that there might be some other way ::)… Good to know, thanks :).

Regards,
Tomasz

This seems like the official thread for Glide, so I thought I’d post here instead of creating a new one…

Is it possible to use Glide to emulate my own LCD screen/device? For example, I have a graphical lcd from an old Nokia phone, it uses the st756r controller… could I make a pixel accurate lcd emulator using Glide? I’d create API commands that would be similar to the SPI layer interface, but instead of needing the physical hardware, it would display on screen with 100% pixel and functional accuracy!

Something like this:

@ andre.m - why no emulator?