Glide -- Graphical Library for NETMF

Hi!

I am trying to create a program which has a functionality to acces the USB mass storage and explore it. Currently I am able to see the folders and files (with only one desired extension) from the root directory. One of the possible actions is ‘delete file’.

I have a problem to figure out several issues with data grid.

  1. I would like to make column name position fixed - is there a way to do this?
  2. When I leave a window containing DataGrid object it would be nice to reset the effect of scrolling (to see the data grid again from the first row) - how to?
  3. Is there any way to clear the DataGrid? I tried for example while loop containing trycatch with RemoveRowAt(0) but it became endless loop.

If someone knows how to solve these issues, please write.

Regards,
Tomasz

edit:

  • ad 1.edit: well now I see that it won’t do the work, because I can’t disable it’s interactivity to ‘overload’ scrolling with buttons - cells must remain tappable
  • ad 2.: somehow done, i’m just counting each time the number of added rows (in my method RefreshGrid()) and after returning to another window i use ScrollUp(fileCount, 0);
  • ad 3.: before invoking RefreshGrid() I’am using ClearGrid() which looks like that:
var fileGrid = (DataGrid)LoadMenuWindow._thisWindow.GetChildByName("FileGrid");
var i = 0;
while (true)
{
  fileGrid.RemoveRowAt(i);
  i++;
  if (i > LoadMenuWindow.fileCount)
    break;
}

But something goes wrong - I see that few are still in the grid. I’ll still be thinking how to solve this.

edit2:

  • ad 3.: Somehow done, I’m using RemoveChild and AddChild (+everything else like AddColumn, Font, TapCellEvent) to Window every time when refreshing the DataGrid.
    If someone knows how to solve problem #1 or knows better solution to #2 or #3, please write ;).

Greetings,
Tomasz

@ Josh
Ah, ok, it only worked if the CornerRadius is set to 0.

cu
Andreas

Another point is the view stack of the shown elements. it is possible to change this ?
When i mix xml elements with canvas drawn elements, the canvas drawn elements always stay on top.
i would like to choose the point of insert a new element afterwards.

cu
Andreas

@ Tomasz3
Your issues will be resolved in the next release with revamped DataGrid component. The following additional methods will be available:

// Methods

public void ScrollTo(int index)
public void Clear() // this will properly clear the datagrid and reset everything

// Properties

public bool TappableCells
public bool ShowHeaders
public bool SortableHeaders
public bool ShowScrollbar
public int ScrollbarWidth

@ af6767
New methods will address the depth issue.

public void AddChildAt(int index, DisplayObject child)
public void RemoveChildAt(int index, DisplayObject child)

@ Josh
Whoa, nice, thanks for response, this will be a cure :slight_smile:

Now I got another two things, I don’t know if it’ll be necessary for everyone, just take a look…

  1. I decided to make a DataGrid which has all rows with white background, with white grid color and with red selected row color - my intention is to make more typical USB mass storage explorer using DataGrid. But there is still something that I have also had with default DataGrid color settings. When selecting a row by tapping, it’s border color changes. But when I select another row, a white border that is visible remains at older selected row. I could also see this when I made all rows background white (row background white seems to be slightly darker than grid white???) - I suppose that somehow grid isn’t rendered from the beginning…?
  2. Also when I have a DataGrid with fixed height - i.e. 160px, and there is amount of rows (including header) that isn’t enough to fill the DataGrid in height, this nice black scrollbar is 160px, while i.e. rows are only 140px and the rest 20px is the window background. I solved this by writing method FillToEight() which just adds several rows with " " needed to satisfy DataGrid’s height :).

When I’ll be done with my GUI I’ll show you :).

Regards,
Tomasz

Hi,

Another case: you solved my problem with image as a background in v. 0.2.0 (before either the buttons were inaccessible or transparent, depends on order of defining image and buttons in xml), so I decided to use this. But then there is a small problem, I mean single pixels or group of three pixels at each corner of image/button rect. When a button/image gets disabled or enabled, they appear and remain until I exit and enter again.
I’m assuming that I’m doing enable/disable button/image properly:

public void EnableButton(string buttonName, Window window)
{
    var btn = (Button)window.GetChildByName(buttonName);
    btn.Enabled = true;
    window.FillRect(btn.Rect);
    btn.Invalidate();
}

public void DisableButton(string buttonName, Window window)
{
    var btn = (Button)window.GetChildByName(buttonName);
    btn.Enabled = false;
    window.FillRect(btn.Rect);
    btn.Invalidate();
}

Regards,
Tomasz

@ Tomasz3
Your issues with the selection color should be resolved next release. Currently the scrollbar is full height when rows don’t exceed the data grid’s height. In the new release the scrollbar’s scrubber will only appear when the list is scrollable (item list exceeds the height).

Now on to the Enable and Disable button methods. The reason this doesn’t work is because FillRect fills the background color behind the buttons. Since your buttons are over an image you see that button corners are now a color and not transparent. What you need is a way to fill a rectangle (the same size as the button) of the image behind it. Unfortunately this doesn’t exist currently, but has already been addressed in the next release.

In the next release you can set a window’s background image directly:

window.BackImage = Resources.GetBitmap(Resources.BitmapResources.background);

This way when you call FillRect it actually uses the image rather than the window’s background color.

A temporary solution would be to do this:

static void EnableButton(string buttonName, Window window)
{
    Button btn = (Button)window.GetChildByName(buttonName);
    btn.Enabled = true;
            
    //window.FillRect(btn.Rect);
    Image image = (Image)window.GetChildByName("image");
    window.Graphics.DrawImage(btn.X, btn.Y, image.Bitmap, btn.X, btn.Y, btn.Width, btn.Height);

    btn.Invalidate();
}

static void DisableButton(string buttonName, Window window)
{
    Button btn = (Button)window.GetChildByName(buttonName);
    btn.Enabled = false;

    //window.FillRect(btn.Rect);
    Image image = (Image)window.GetChildByName("image");
    window.Graphics.DrawImage(btn.X, btn.Y, image.Bitmap, btn.X, btn.Y, btn.Width, btn.Height);

    btn.Invalidate();
}

Make sure to change “image” to what your image component is called.

The manual scrolling on the datagrid works well. However, when scrolling the datagrid using the ScrollDown method, and you get to the end it repeats the last row several times. If there was a way for me to tell when the last row was visible, then I could prevent the ScrollDown method from being called.

The DataGrid was rebuilt for the upcoming V 0.2.1 release. I think anyone who uses it will be pleased. The next release will be this week. This will solve your issues mcox.

Thanks Josh

Glide track bar control that can be added as shown in the figure do?

Yes a slider control will be included in the next release.

YAY! Glide V 0.2.1 released!

http://www.ghielectronics.com/glide/

Hi Josh,

I’ve tried the new Glide version (0.2.1) and have some questions/remarks:

  1. We have made our own touch screen driver. It looks as if the slider doesn’t react on ‘our’ move events. I’m sure they are being generated.
  2. The setrowdata function of the datagrid control doesn’t seem to work anymore.
  3. Could you add an imagebutton (a button with a bitmap) to Gllide ?
  4. We’re using a 7" display so drawing a new window takes a while. A textblock is used to present the date and time. Updating is done in a thread. It happens now and then that the date and time update takes place before the new windows is ready. Is it possible to add an event to Glide that indicates that a window drawing is finished?

Regards,

Peter

  1. Are you feeding events in like this? http://www.ghielectronics.com/glide/example/5/
    Is it limited to just the Slider or do other components not work with your implementation too?
  2. The data is changed it just may not be shown on screen correctly. Even invalidate doesn’t show the change, but if you sort a column the change will appear. This has been fixed for next release.
  3. A Bitmap property will be exposed on the button component. For the time being you could use an image component.
  4. In the next release a RenderedEvent will occur.

Hi,

I’m thinking about Label and TextBlock components…
Label contains just two methods and one property more than TextBlock. But maybe is there any difference in way of rendering these two?
I mean I’m using TextBlock as a labels (i.e. my DataGrid header) but maybe Label has “less weight” for such purposes? Or maybe Label is intended to be used in connection with CheckBox and RadioButton?

Regards,
Tomasz

P.S. Now DataGrid is way better, grats :). But I am still torturing it :D. I would like to know if sorting data will ignore letters case? Like it is in MS Excel/OO.org Calc or Windows file explorer.
P.P.S. I made buttons for some “fast scrolling” in my own Canvas-made component, and I wanted for it to have some proper text. I found in UTF-8 character table a double angle quotation mark: »
I found that it should be written as ». I do so in xml resource, but then I got just a rectangle instead of this character. So for now I have to use >>.
Is this an issue with Glide or with .NET MF?
P.P.P.S. I am using Image.Stretch but it stretches a bitmap in both dimension as long, as it reaches the width of Image component, but it doesn’t stretch it more in y dimension. I think that sometimes this type of stretching might be useful.

Josh,

The slider problem is ‘solved’: To speed up things in our touch screen driver an up event is raised in the next cycle after a raisedownevent. Apperently the slider can’t handle this although move events were raised as well. Maybe I have to make my own slider.

About the datagrid: After a Clear() I want to fill the grid again with different values. When I use the SetDataRow to fill the grid the result is an empty grid. Sort doesn’t change anything;
Do you expect a new version of Glide soon? In that case I wait without trying to find a workaround.

Peter

Peterd,

I don’t know if you want to get exactly the same functionality with DataGrid as I do, but I am also ‘refilling’ the one-column grid.

I do it so, that I have implemented a method RefreshGrid(), where I do:

var fileGrid = (DataGrid)ThisWindow.GetChildByName("FileGrid");
fileGrid.Clear();

And after that I add items by using the for loop with:

var gridItem = new DataGridItem(new[] { someVariable });
fileGrid.AddItem(gridItem);

And fileGrid.Invalidate() at the end of method. It works fine for me and I don’t need to use SetDataRow. But maybe you want to use it though, or if SetDataRow will be fixed it will be better to use than AddItem.

Regards,
Tomasz

P.S. In the future it would be nice to have Refresh method for DataGrid and DataGrid object property which would determine which object contains data connected with the grid.

Hi Tomasz,

Isn’t this way of refilling not leading to an out of memory error? I thought Clear () just empties the cells and doesn’t delete the rows.

Peter

Josh:

I have been “playing” with Glide and have found it to be great!

I am having a little trouble using the Tween class. The documentation is a bit thin, and while I have been able to get the functionality I was trying to achieve working, I don’t understand why.

I have developed a simple program which displays my confusion. The program has two windows; a main screen which transfers to the second window when it is tapped. The second window transfers back to the main window when a button is pressed.

I desire the transistion from the main window to second window to be done by the Tween class with a down direction. The transistion from the second window to the main window to be done by Tween with an up direction.

I expected that returning from the second window would have the first two parameters of the Tween call reversed and the direction changed. I found this only causes the second windows to slide to itself.

Following is the the program I used

<Glide Version="0.2.1">
  <Window Name="window1" Width="480" Height="272" BackColor="FFFFFF">
    <Label Name="instance460" X="147" Y="106" Width="150" Height="32" Alpha="255" Text="Window 1" TextAlign="Right" Font="4" FontColor="000000"/>
  </Window>
</Glide>
<Glide Version="0.2.1">
  <Window Name="window2" Width="480" Height="272" BackColor="FFFFFF">
    <Label Name="instance545" X="184" Y="121" Width="150" Height="32" Alpha="255" Text="Window2" TextAlign="Right" Font="4" FontColor="000000"/>
    <Button Name="backButton" X="206" Y="224" Width="80" Height="32" Alpha="255" Text="Back" Font="4" FontColor="000000" DisabledFontColor="808080"/>
  </Window>
</Glide>
using System;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;

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

namespace Problem1
{
    public class Program
    {
        private static Window mainWindow = null;
        private static Window optionWindow = null;

        public static void Main()
        {
            // activate touch
            GlideTouch.Initialize();

            Init();

            // display awindow
            Glide.MainWindow = mainWindow;

            Thread.Sleep(Timeout.Infinite);
        }
        private static void Init()
        {
            mainWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Window1));
            optionWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.Window2));

            // events
            // main window tap
            mainWindow.TapEvent += Window1Tap;
            ((GHIElectronics.NETMF.Glide.UI.Button)optionWindow.GetChildByName("backButton")).TapEvent += Window2BackButtonTap;
        }

        private static void Window1Tap(object sender)
        {
            Tween.SlideWindow(optionWindow, mainWindow, Direction.Down);
        }

        private static void Window2BackButtonTap(object sender)
        {
            // does not work with following line as expected
            Tween.SlideWindow(mainWindow, optionWindow, Direction.Up);
            // works with the following line
            //Tween.SlideWindow(mainWindow, optionWindow, Direction.Down);
            // works with the following line
            //Tween.SlideWindow(optionWindow, mainWindow, Direction.Up);
        }
    }
}

Please help me understand… Thanks