TouchUI - ScrollList (part 10)

by Chris 11. December 2009 10:00

One of the controls that inherit from the ScrollControl (described in the previous part of this series) is the ScrollList control. As the name implies, this is a list that implement modern features like soft (kinetics) scrolling, and the design and functionality was inspired by the table view control on iPhone.

The control holds a generic list of scroll list items (suitably name ScrollListItem), and during the paining of the control, it instructs all the list items to paint themselves. It also takes care of the painting of the background of each item, to enable every other line to have a different background color, and also to highlight the selected item. The painting is efficient in the way that only the items that are (at least partly) visible is painted, and the code looks like this:

public override void Paint(Graphics g)
{
    DoAutomaticMotion();

   
int firstListItem = Math.Max(-(ScrollTop / ListItemHeight), 0);
   
int lastListItem = Math.Min(firstListItem +
        (Rectangle.Height / ListItemHeight) + 2, ListItems.Count);
   
for(int i = firstListItem; i < lastListItem; i++)
    {
       
if(i == SelectedLine)
        {
            ListItems[i].Selected =
true;
            g.FillRectangle(HighBrush,
new Rectangle(0,
                Rectangle.Top + ListItemHeight * i + ScrollTop,
                Rectangle.Width, ListItemHeight));
        }
       
else
        {
            ListItems[i].Selected =
false;
           
if(i % 2 == 1)
                g.FillRectangle(GrayBrush,
new Rectangle(0,
                    Rectangle.Top + ListItemHeight * i + ScrollTop,
                    Rectangle.Width, ListItemHeight));
        }

        ListItems[i].Rectangle =
new Rectangle(0,
            Rectangle.Top + ListItemHeight * i + ScrollTop,
            Rectangle.Width, ListItemHeight);
        ListItems[i].Paint(g);
    }
}

The control also takes care of translating a generic selection in the base class ScrollControl into an selection of an item in the list. The owner of this control, normally a dialog, is notified of each selection through an event (Selected). This is handled for both the finger (mouse) and if a hardware (physical) key on the phone is pressed. This hardware key support means that the control is also functional on a non-touch device.

The implementation of each list item is done by inheriting from ScrollListItem and mainly implement the Paint method. See the sample code for more details.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | User Interface | Windows Mobile

TouchUI - ScrollControls (part 9)

by Chris 4. December 2009 13:26

Now we have come to the heart of this series, as this is where the most important part of the TouchUI framework is implemented. It's the base control class for the controls that allow scrolling, and the implementation was derived in some parts from the excellent SmoothListBox by Fredrik Bornander.

As you will see when you look at the implementation, there are a lot of settings that you can use to modify the exact behavior, and here are some examples:

  • snapBackFactor: how fast should the control snap back when passed the top and bottom borders
  • dragDistanceFactor: factor to increase the actual speed of dragging
  • maxVelocity: maximum scrolling velocity
  • deaccelerationFactor: how fast should the scrolling decelerate when we let go
  • borderDeaccelerationFactor: same as before, but on the top and bottom borders

The action starts when the finger (mouse) is pushed down...

public override void MouseDown(Point p)
{
    mouseDownPoint = p;
    previousPoint = mouseDownPoint;
}

...and position is simply saved. This becomes useful as the finger is dragged...

public override void MouseMove(Point p)
{
    int delta = p.Y - previousPoint.Y;
    draggedDistance = delta;
    scroll(delta);
    previousPoint = p;
}

...the distance dragged is recorded for each movement, and also the control is scrolled accordingly:

private void scroll(int offset)
{
    ScrollTop += offset;
}

When the finger is finally released...

public override void MouseUp(Point p)
{
    velocity = Math.Min(Math.Max(dragDistanceFactor * draggedDistance,
        -maxVelocity), maxVelocity);
    draggedDistance = 0;
    DoAutomaticMotion();
}

...the speed is recorded and the main scrolling logic is called...

public virtual void DoAutomaticMotion()
{
    velocity *= deaccelerationFactor;
   
if(ScrollTop > 0 || ScrollTop + ScrollHeight < Rectangle.Height)
        velocity *= borderDeaccelerationFactor;
   
float deltaDistance = elapsedTime * velocity;
   
if(Math.Abs(deltaDistance) >= 1.0f)
        scroll((
int)deltaDistance);
   
else
    {
       
if(ScrollTop != 0)
        {
           
if(ScrollTop > 0)
                scroll(-
Math.Max(1, (int)(snapBackFactor * (float)(ScrollTop))));
           
else
            {
               
if(ScrollHeight > Rectangle.Height)
                {
                   
int bottomPosition = ScrollTop + ScrollHeight + Rectangle.Top;
                   
if(bottomPosition < Rectangle.Height)
                        scroll(
Math.Max(1, (int)(snapBackFactor *
                            (float)(Rectangle.Height - bottomPosition))));
                }
               
else
                    scroll(Math.Max(1, -((int)(snapBackFactor *
                        (float)ScrollTop))));
            }
        }
    }
}

...and it handles the automatic motion of the control when the finger is released. It also takes care of the handling of the borders, and the automatic negative scroll that occurs then the borders are passed.

Another important thing that happens in the MouseUp method is...

PointSelected = (Math.Abs(p.Y - mouseDownPoint.Y) < 5);
if(Math.Abs(mouseDownPoint.X - p.X) > 50)
    HorizontalGesture = mouseDownPoint.X - p.X;
else
    HorizontalGesture = 0;

...that indicate if something was selected in the control (difference between pressed and released vertical position is less that five pixels), and whether sweep gesture was made (difference between pressed and released horizontal position greater than fifty pixels).

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | User Interface | Windows Mobile

TouchUI - Controls (part 8)

by Chris 28. November 2009 14:02

As I showed in a previous part of this series, I don't use any controls for the simpler dialog painting (i.e. for heading, line, etc). For more advanced painting and logic, the notion of controls is welcome, and is obviously a part of the TouchUI framework.

I started off in the traditional way, building WinForm controls, but soon realized that I really don't like all the overhead that comes with that. Also, I wanted the central control that is not natural when each control receive their own (mouse) events. So I ended up creating something new from scratch, and the root TouchUI control ended up being defined like this:

public class Control
{
   
public Rectangle Rectangle { get; set; }
   
public int ScreenFactor { get; set; }
   
public Color BackColor { get; set; }

    public virtual void Paint(Graphics g) { }
   
public virtual void MouseDown(Point p) { }
   
public virtual void MouseMove(Point p) { }
   
public virtual void MouseUp(Point p) { }
   
public virtual void Resize(Rectangle r) { }
   
public virtual void KeyDown(KeyEventArgs e) { }
   
public virtual void KeyUp(KeyEventArgs e) { }
}

Note that a rectangle is used for placement, and the important screen factor to handle painting on high-res devices. Also note how each event is actually a plain method reversing the "event bubbling" to push the "events" down the control hierarchy.

The pain is that each level explicitly need to forward the calls, but the gain is that none of the controls need to be aware of any events happening in the system. The end result is a few more calls and a minimum of overhead.

Currently rated 4.3 by 3 people

  • Currently 4.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - Active UI (part 7)

by Chris 21. November 2009 14:01

When creating a highly active user interface, there is a main difference with a traditional WinForms app, and it is the frequency that the screen is updates. In a WinForms app, only the parts of the screen that has changed is updated, and that logic creates a lot of overhead. Also, with that model it's harder to do things like soft scrolling and animations.

No, I needed something different, and I started to think about games. I guess my recent implementation of the Animeter utility also made me think along those lines. In games you typical find an active user interface as things mostly change all the time, and the screen is updated at a certain frame rate (number of times per second). As you may know, the standard screen refresh rate in an ordinary movie is around 24 frames per second, but for animated moves a more common frequency is about half of that. For most cases in a mobile app, that is sufficient to allow for things to come alive.

In TouchUI, that frequency is handled by a timer set to fire at every 80 milliseconds creating a frame rate of 12.5:

timer = new Timer();
timer.Interval = 80;

timer.Tick += new EventHandler(timer_Tick);
timer.Enabled =
true;

Each time that happens, the screen is redrawn by triggering a simple form refresh:

private void timer_Tick(object sender, EventArgs e)
{
   
this.Refresh();
}

That, in turn, will trigger the OnPaint method to be called, that is responsible for all the painting (as you saw in the previous part of this series).

While this allows for a very responsive and flexible user interface, you need to realize that it really puts the processor to work. Therefore, you probably want to turn all these updates off as soon as the user switch to another app or when the device is put in sleep mode. It can be done by catching the form's activate and deactivate events, like this:

private void MainForm_Activated(object sender, EventArgs e)
{
    timer.Enabled = true;
}

private void MainForm_Deactivate(object sender, EventArgs e)
{
   
timer.Enabled = false;
}

With all this in place, we have a great foundation for creating a highly active user experience with soft scrollling and animations.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - Painting (part 6)

by Chris 14. November 2009 14:00

As most things happening in a TouchUI app, the action begins in the main form (MainForm), and that is also true for the painting of all the graphics. To take full control over how the graphics is drawn in an app, the form's OnPaint method should be overridden, like this:

protected override void OnPaint(PaintEventArgs e)
{
   
base.OnPaint(e);

    dialogStack.Last().Paint(Common.Instance.PaintGraphics);
   
Rectangle r = Common.Instance.ClientRectangle;
    e.Graphics.DrawImage(Common.Instance.PaintBitmap, r, r, GraphicsUnit.Pixel);
}

The Common.Instance is a singleton used to store global things in the app, and is hold the current screen dimensions (ClientRectangle). It also holds an instance of the GDI Graphics class (PaintGraphics) pointing to a bitmap (PaintBitmap) that is used to draw to the screen (via e.Graphics). The bitmap is used as a buffer instead of doing the different GDI painting operations directly to the screen, and that is a good practice (called "double buffering") that will help you avoid things like screen flickering. Another important measure to avoid flickering is to override the OnBackGround like this:

 

protected override void OnPaintBackground(PaintEventArgs e) { }

Note that I don't call the form's (base class) implementation (base.OnPaintBackground).

So, we have a way of making the currently active dialog responsible for the painting of the screen, and this is an example of the Paint method of the main dialog:

public override void Paint(Graphics g)
{
    g.Clear(BackColor);

    g.DrawString(this.Text, NormalFont, HighBrush, 8, 5);
    g.DrawLine(Normal
Pen, 0, 23, Rectangle.Width, 23);
}

This code takes care of painting (clearing) the background, the heading text, and the horizontal line below the heading. The result looks something like this:

image

As we will see in some of the upcoming parts of this series, the dialog continues to pass the responsibility of painting to each of its controls, that does their work in much the same way.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - One Form, Many Dialogs (part 5)

by Chris 7. November 2009 13:59

One of the hardest parts of writing apps for CF is the handling of the different forms, and also the navigation between the forms. The handling involves loading the forms (that takes time), showing the forms (and hiding the other forms to prevent strange behavior when switching between apps), and the memory management of forms (especially if they contain many controls, they use a lot of memory). After years with different form handling solutions (stacks with preloaded forms, etc), I finally decided to leave all those troubles behind by only having one form in my apps.

The single form in my TouchUI apps is usually called MainForm and even if it's not a part of the framework, it's really the main controller for the user interface. That is where initialization takes place, and all the events are fired in that single form. Each event (or overridden method) then gets passed on to the currently active dialog. A dialog is a TouchUI class that represent a logical form in the app, and the MainForm host a stack of currently loaded dialogs to ease navigation back up the dialog hierarchy. This is the first code (in the form's Load event) that runs when the app starts:

dialogStack = new List<Dialog>();
MainDialog mainDialog = new MainDialog(...);
dialogStack.Add(mainDialog);

As the dialog stack is a simple List, most of the other code in the MainForm will access the currently shown dialog with:

dialogStack.Last()

 

Here are some examples:

private void MainForm_MouseUp(object sender, MouseEventArgs e)
{
    dialogStack.Last().MouseUp(
new Point(e.X, e.Y));
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
    dialogStack.Last().KeyDown(e);
}
if(dialogStack.Last() is MainDialog)
{
   
MainDialog mainDialog = (MainDialog)dialogStack.Last();
   
DetailDialog detailDialog = new DetailDialog(...);
    dialogStack.Add(detailDialog);
}

 

The last code snippet is from the logic that navigates from the main dialog to a new dialog, and as you can see it resembles the initial code above. Therefore, moving up the hierarchy means to simply remove the last dialog in the stack (list).

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - GDI (part 4)

by Chris 30. October 2009 13:57

The technology that makes the main requirement for the TouchUI framework (see part 3) come true is GDI, which also has a managed wrapper. The main player in that API is the Graphics class, and here are a couple of its methods:

  • Clear()
  • DrawEllipse()
  • DrawImage()
  • DrawLine()
  • DrawPolygon()
  • DrawRectangle()
  • DrawString()
  • FillEllipse()
  • FillPolygon()
  • FillRectangle()
  • MeasureString()

This is actually most of its methods, but still this is all we need to create any graphics that we want. Also, since it's not that extensive, it's not too difficult to learn GDI. Here's some code:

Graphics g;
...
Pen bluePen =
new Pen(Color.Blue, 3); // 3 pixels thick
g.DrawRectangle(bluePen, 0, 0, 50, 50); // x, y, width, height
Pen redPen = new Pen(Color.Red, 2);
g.DrawEllipse(redPen, 0, 50, 80, 60);

Let's not bother with how the graphics instance (g) is created, and assume it is, then the result would look something like this:

image

That's what I like with GDI: get whatever graphics you want with just a few lines of code! In the coming posts in this series I will not explain the details about the different GDI methods used, but there are many good resources to find on the Web if you want to learn more about GDI.

GDI is actually the way that the core operating system (Windows CE) is drawing things to the screen, and if you are interested in knowing more about how this technology performs on a device, you should check out the article Native vs. Managed Code: GDI Performance by Chris Tacke. As you will see, there are some performance gain to be made by calling the native APIs instead of using the managed wrappers. But since I had a goal of pure managed code for the TouchUI framework, I will stick with the managed wrappers in this series.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - Introduction (part 3)

by Chris 23. October 2009 13:55

Let me start by presenting some of the things that I wanted from a simple framework for building nice looking user interfaces on WinPhone:

  1. Be able to do whatever I want (i.e. no graphical restrictions)
  2. Run on all devices with WinMo5 or later (incl. WinPhone 6.5)
  3. Run on all touch and non-touch devices
  4. No dependency of third-party products (Resco, miraByte, etc) or even libraries (GapiDraw, etc)
  5. No multi-form problems (task switching, etc)
  6. Support for any resolutions (from 176 x 220 all the way to 480 x 800)
  7. Support for any orientation (portrait / landscape)
  8. Soft (kinetics) scrolling with a finger (multi-touch is simple not possible with the current hardware)
  9. List item selection (with highlight coloring according to current theme)
  10. Form switching animations (left / right)
  11. Ability to recognize simple gestures
  12. Pure managed code (based on CF 3.5)
  13. All of the above with with a single code and executable!
  14. Easy to understand and use (i.e. few lines of code)

For an experienced CF developer, this list seems like very high expectations, but I will talk about each of the items in the list and show how it can be implemented.

Just to give you an idea of where we are heading, there are some screenshots of the TouchUI sample application (both the sample application and the TouchUI framework can be downloaded from the CodePlex project named TouchUI):

image image image

 

 

The first is screenshot is from a traditional non-touch device (WinMo 5 Smartphone with a 176 x 220 screen), and the second and third are from a new high-res device (WinPhone 6.5 Professional with 480 x 800 screen). The beautiful strawberry graphics is from a photo by Tina Phillips / FreeDigitalPhotos.net.

However, the best features are not visible in screenshots, e.g. the nice soft (kinetics) scrolling, and form switching animations. To better understand the user experience, I recommend you to download the code and load it up on a physical device. I hope you will enjoy it!

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - Alternatives (part 2)

by Chris 16. October 2009 13:44

When I was involved in starting up a mobile cross-platform project a few months ago, one of the goals was to make the experience between the platform as similar as possible. Not surprisingly, the platform that set the standard was iPhone, and the other platforms had to do as best they could to measure up. My main responsibility was the WinPhone platform, and it didn't take much analyzing to realize that old friends like the ListView and the Grid were out of the question. So I went out to look for what others were doing.

image

I started by looking at Alex Yakhnin's UI Framework, and was (as usual) impressed with the things that Alex can do with the standard controls. Just take a look at the ListBox on the right.

It was when I started to play around with it, and added a few more items in the list, that I was instantly put off when the classical scrollbars appeared in the otherwise nice control.

Even if there are many things to pick from the framework, like how to draw alpha-blended bitmaps in various ways, I wanted something that was not built on the native controls.

So I moved on to the MobileForms Toolkit from Resco, and even if I like what they are doing with many very nice controls, I wanted to have full control of the layout which ultimately require that you have the source code.

The same goes for Touch Controls Suite from miraByte which has some nice controls for scrollable lists with navigation. They are still working on the designer support, but is a nice alternative if you want to get going fast.

The thing I found that came closest to what I was looking for was the Fluid Controls by Thomas Gerber. The sample application was successfully designed to look very similar to the iPhone. It had many of the nice features, like the scrolling lists, animations, etc, but still there was two things that I was missing. First, I wanted something that conformed more with the design guidelines of WinPhone, like the use of the soft buttons (menus), form headings, etc. Second, the implementation was quite extensive, and I was not interested in learning an extensive codebase in order to build a nice user interface.

In the next part of this series, I will show you how I start on what would eventually be the TouchUI.

Currently rated 5.0 by 3 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

TouchUI - Background (part 1)

by Chris 9. October 2009 13:21

I started programming for Windows Mobile (Phone) even long before it was called that, even before it was called Pocket PC, and that was back in 1998 (it was actually called Palm PC at the time). I was amazed at the fact that my programming skills from the Windows platform was brought to a device that I could carry in my pocket. It had the same user interface controls that I was used to, and life was amazing.

Now, more than 10 years later I'm less amazed by using almost exactly the same controls in my mobile applications. A lot has happened in this time, but unfortunately this has not been reflected in the set of control that I have to my disposal. I know that many of my friends and fellow mobile developers have tried various ways of tweaking the existing controls into doing things that they were not meant to do. Some built new controls from the ground up, only to find that this they still didn't get all the way to were they wanted.

In my view, one of the more important things that iPhone brought to the table was a new set of controls that were designed specifically for mobile use. They were designed to be both easily controlled with a finger (or even multiple fingers at the same time) and good looking. Taking it one step further, they even added some fun (kinetics soft scrolling, sliding animations when changing views, etc) to the experience which has been really well received by the users. Recently, like in the latest version of Windows Mobile, or rather Windows Phone, WinPhone 6.5, some of these things have been made available in parts of the operating system. However, not much has changed in the tools available to us, the third-party developers, and especially when it comes to the controls.

I hope that will change soon, and that we will see a completely new set of controls for WinPhone designed with modern mobile user expectations in mind. It's probably not enough with just some of the enlargements to make them more finger-friendly that we can see in WinPhone 6.5. No, it needs to be a new set of controls that are designed for fingers that has a nice look, and even a bit of fun.

While waiting for that, I have put together a very simple (according to the KISS principle) framework called TouchUI that include some of the ideas I've been missing in the controls for WinPhone. But before we look more closely at it, I will look at some of the alternatives in the next part of this series.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | Windows Mobile | User Interface

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen