Showing posts with label Code. Show all posts
Showing posts with label Code. Show all posts

GitHub Is Pretty Magical

Warning: Weak browsers (aka Internet Explorer) may not be able to render this blog entry in its glory. Use a real browser!

If you browse on over to the Code and Applications section of this site, you will notice that it takes a little time to load. That’s because that entire page is being dynamically generated by your browser via the GitHub (JSON) APIs. What you see on that page is a live, up to the minute, list of every public project in my GitHub repository.

And here’s the JavaScript code that does it:

But that’s not really the magical part. Here’s the code that inserted the code above into this page:

<pre class="githubfile" file="githubprojects.js" repository="GithubProjects" user="koush"></pre>

The first bit of JavaScript code you see above is a live view of the file that is checked into my GitHub repository… and your browser is using the GitHub API to view it, highlight it (using SyntaxHighlighter), and then render it to your screen. Kudos to Github for a fantastic API!

I wrote GithubProjects up today as an exercise in learning jquery, AJAX, and some other Web 2.0 acronyms. Of course, all of this code is available in my GithubProjects repository.

Converting Enumerations to User Readable Strings in .NET

Suppose you have the following scenario: You have a function that can return multiple return types codes via an enum value. For each of those enum values, you want to inform the user the result of the operation by some user friendly string.

A common implementation I see is some sort of switch statement that resolves enumerations to a string by way of a switch statement or hash table or something. And whenever that string is needed, call into said method.

And although this is viable, this creates a disconnect between the enum and it’s actual string literal definition. In addition, for each new enumeration value, that giant switch statement needs to be updated with a new string value. If there were only a clean way to map an enum to a string value automatically… and there is! With clever usage of attributes, reflection, and extension methods, one can do something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace EnumString
{
[AttributeUsage(AttributeTargets.Field)]
class EnumStringAttribute : Attribute
{
string myValue;
public EnumStringAttribute(string value)
{
myValue = value;
}

public override string ToString()
{
return myValue.ToString();
}
}

static class ExtensionMethods
{
public static string ToUserString(this Enum enumeration)
{
var type = enumeration.GetType();
var field = type.GetField(enumeration.ToString());
var enumString = (from attribute in field.GetCustomAttributes(true) where attribute is EnumStringAttribute select attribute).FirstOrDefault();
if (enumString != null)
return enumString.ToString();
return enumeration.ToString();
}
}

enum AuthenticationResult
{
[EnumString("This username is not registered.")]
NotRegistered,
[EnumString("Incorrect password.")]
BadPassword,
[EnumString("Logging in...")]
Success,
}

class Program
{
static void Main(string[] args)
{
Console.WriteLine(AuthenticationResult.BadPassword.ToUserString());
Console.WriteLine(AuthenticationResult.NotRegistered.ToUserString());
Console.WriteLine(AuthenticationResult.Success.ToUserString());
}
}
}

Delaring string values can simply be done inline, and the usage is simple as well! Just call the new extension method to get your user friendly string!

(Of course, for localization, you may want to map the enum to a string resource rather than a hard coded string value; but a similar approach can be used.)

Gitweb Support for SyntaxHighlighter

After getting Gitosis set up on my Hackintosh, I set up gitweb as well. But vanilla gitweb is really ugly; it’s almost as bad as sitting at a console typing the git commands manually. So I spent a good day or so trying to tweak gitweb to work with SyntaxHighlighter. For the longest time, SyntaxHighlighter simply would not work on any page at all. After prodding for a while, I finally figured out that it was due to gitweb.cgi returning the content-type as “application/xhtml+xml” instead of “text/html”.

Click here to see a sample gitweb repository with SyntaxHighlighter enabled. Navigate around the projects, and click any of the language specific blob links (.c, .cs, etc) to see the new highlighting.

// This is SyntaxHighlighter, and
// it now works in gitweb!
if (true)
{
Console.WriteLine("Hooray!");
}

Head over to my GitHub repository to get my git fork with the tweaked gitweb and instructions!

P.S. This was my first time hacking at Perl. I feel violated.

P.P.S. The Perl brush is intentionally disabled. It is a little buggy.

Duck-Typing (or Duct Taping) Dynamic Objects in C#

I've been delving into DLR and dynamic types as of late; in particular, how to enforce a static "contract" (an interface per se) on a dynamic type. During my perusal of blogs and articles, I came across an article by Tobi that delved into what I was trying to do, but not in a generic fashion. The interesting bit of it is that Tobi referenced another open source project called the Castle Project. This project, among other things, has some utility methods that allow developers to create class proxies and implement interfaces at runtime.The proxied objects could then have their method and property calls specially handled by an IInterceptor implementation. So, after reviewing of the code and a little bit of hacking, I came up with runtime duck typing solution:

Python Code:

import clr 

class Dragon:
def Quack(self):
print "ROAR!"

dragon = Dragon()

C# Code:

public interface Duck
{
void Quack();
}

public class Cow
{
public void Quack()
{
Console.WriteLine("Moo?");
}
}

class Program
{
static void Main(string[] args)
{
ScriptEngine pythonEngine = Python.CreateEngine();
ScriptRuntime runtime = pythonEngine.Runtime;
ScriptScope scope = runtime.ExecuteFile("hello.py");
IDynamicObject dynamicObject = (IDynamicObject)scope.GetVariable("dragon");

// I can't figure out how to do this without the runtime?
// Using GetMetaObject and building an expression tree?
Duck dragon = DuctTapeHelper.DuctTape<Duck>(dynamicObject, runtime);
Duck cow = DuctTapeHelper.DuctTape<Duck>(new Cow());

// Duck Type!
dragon.Quack();
cow.Quack();
}
}

Notice that neither "Cow" or "Dragon" implement the "Duck" interface, but at runtime, an interface proxy is generated to allow them to become Ducks!

Incidentally, another potential way to do this, without the dependency on the Castle Project utilities, is to use reflection to generate a IronRuby/IronPython script that implements an interface proxy.

Here's the full source code to my version of the DuctTape project. I am packaging the various projects from DLR and Castle into it as well. The code is nowhere near complete; it is just a functional prototype to make sure the concepts actually work! I feel that it could be done better through expression trees, but I couldn't figure out how to use an Expression tree to call into a dynamic method on IDynamicObject. Please let me know if you have more insight into this, as I am still a DLR noob.

 

Completely Unrelated:

Does anyone know of a good way to embed code into a blog? As you can see, my line breaks become all messed up with whatever tool I use (I use Live Writer with Paste from Visual Studio or Source Code Snippet).

Solved:

Blogger has some silly "Convert line breaks" option that is defaulted to Yes. As a result, it completely mangles all line breaks if you have a <pre> tag in your post body. Turn that off, and all is well.

JNI in Android (and a foreword of why JNI Sucks)

wall-smaller

Quick Preface: You do NOT need root to create and use a shared native library (.so) in Android from your Java application.

I had never tried Java Native Interface until today. And I must say, it completely sucks. Not only is the header generation/implementation nontrivial and tedious, JNI is inherently broken in that it is not architecture/platform nonspecific. So I proudly present to you my list of why JNI sucks.

  • You can't access arbitrary functions in arbitrary DLLs. JNI requires that you write a glue C/C++ layer to do whatever you want to do natively.
  • On Android, your glue layer must contain a JNI_OnLoad function that explicitly register every method that needs to be made available to the JVM. The JVM can't simply check the export tables and intelligently import it.
  • Since developers must write a glue layer, you must also compile and package that glue layer per platform you are targeting. This design is absurd because platforms can have different CPU architectures and different Operating Systems, and still support similar calls in the similar libraries. For example:
    • OpenGL ES (libGLES_CM). On Windows Mobile it is called libGLES_CM.dll. On Linux/Android it is called libGLES_CM.so. These libraries have the same "undecorated" library name, and also contain the same functions with the same signatures. Unfortunately due to how how terrible an implementation JNI is, the same Java application would not work on every platform.
    • Standard System Libraries on Linux or Windows (libc, libdl, libm, ole32, kernel32, etc) - Once again, need to compile libraries per architecture (ARM, x86, x64, MIPS, etc) to use the common/base functions that would be available on the platform (GetWindowEx, statfs, etc).
  • Write once, run anywhere. (Given that you are willing to do multiple cross compiles and embed multiple native binaries into a single package and unpack the appropriate one at runtime.)

For amusement's sake, let's look at what a C# PInvoke looks like versus JNI on Android. Suppose we want to clear the screen in OpenGL:

C#:

Just declare the method signature and the DLL. Simple! Call that like any other method in C#. (Note that the managed executable generated by this code works on both Android or Windows Mobile. Yes, I tested it.)

[DllImportAttribute("libGLES_CM")]
public static extern void glClearColor(float red, float green, float blue, float alpha);

JNI? Let's start out by declaring it.

public static native void glClearColor(float red, float green, float blue, float alpha);

Not done yet! Now the fun begins. Drop to a command prompt and go to the bin directory of your project: javah com.koushikdutta.JNITest.JNITestAcitivity. Now we have a generated header file, com_koushikdutta_jnitest_JNITestActivity.h, that looks like this:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_koushikdutta_jnitest_JNITestActivity */

#ifndef _Included_com_koushikdutta_jnitest_JNITestActivity
#define _Included_com_koushikdutta_jnitest_JNITestActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_koushikdutta_jnitest_JNITestActivity
 * Method:    glClearColor
 * Signature: (FFFF)V
 */
JNIEXPORT void JNICALL Java_com_koushikdutta_jnitest_JNITestActivity_glClearColor
  (JNIEnv *, jclass, jfloat, jfloat, jfloat, jfloat);

#ifdef __cplusplus
}
#endif
#endif

Ok, now let's implement the C code:

#include <GLES/gl.h>

JNIEXPORT void JNICALL Java_com_koushikdutta_jnitest_JNITestActivity_glClearColor
  (JNIEnv * env, jclass clazz, jfloat r, jfloat g, jfloat b, jfloat a)
{
    glClearColor(r, g, b, a);
}

You probably thought you were done, didn't you? Sun thinks otherwise. You need to register the function in C code as well. Don't screw up when copy pasting the cryptic method signature strings!

static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */

    {"glClearColor", "(FFFF)V", (void*)Java_com_koushikdutta_jnitest_JNITestActivity_glClearColor},
};

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }

    jniRegisterNativeMethods(env, "com/koushikdutta/JNITest/JNITestActivity", sMethods, 1);
    return JNI_VERSION_1_4;
}

To be completely fair, jniRegisterNativeMethods is actually a convenience function that is found in libnativehelper.so on Android; I imported that library for the sake of... convenience. Its implementation is as follows (JNIHelp.c in the source):

int jniRegisterNativeMethods(JNIEnv* env, const char* className,
    const JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;

    LOGV("Registering %s natives\n", className);
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        LOGE("Native registration unable to find class '%s'\n", className);
        return -1;
    }
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
        LOGE("RegisterNatives failed for '%s'\n", className);
        return -1;
    }
    return 0;
}

You need to load the library in Java code in your class's static constructor.

System.load("/data/data/com.koushikdutta.JNITest/libjnitest.so");

On Android, you must use System.load and provide a full path instead of using System.loadLibrary. This is because loadLibrary only checks /system/lib; it does not search LD_LIBRARY_PATH or your current working directory. Unfortunately, applications can't write to the /system/lib directory (without root).

.NET's P/Invoke is so much easier/better that a third party company (God forbid Sun actually do something to better the Java language) implemented something quite similar for Java, named, *drumroll please*, J/Invoke. Too bad Android doesn't have that. That would be nice.

Also, on Android, you can't do a normal ARM/GCC cross compile to make shared libraries (I've discussed this in a previous blog post). The resultant .so files will not work with Android's linker due to different linker scripts. To create shared libraries for Android, I would highly recommend just creating a subproject in the Android Source code tree and building the tree. Alternatively you can use the handy script found on this page.

Also, remember that the shared library will need to be contained in your APK file and extracted to the file system so it can be accessed. For an example of how that can be done, check out the source code that does something very similar in the Android Mono port.

Incidentally, this learning experience came about as a result of figuring out how to run Mono side by side with Java/Dalvik in the same process.

Windows Mobile Unified Sensor API heads to CodePlex

codeplex_toplogo[36]

At the behest of the development community and colleagues, the Windows Moble Unified Sensor API is now hosted on CodePlex. I will continue blogging about the changes on my website of course, but all the releases and source code must now be retrieved from CodePlex! (CodePlex is pretty awesome by the way... it has support for multiple source control bindings, and the web client repository browser is fantastic. (I use CodePlex for Windows Mobile stuff, and Google Code for Android. It makes sense in my head. [0])

In the following weeks, I intend to do the following:

  • Reexamine the implementation (and possibly even the current interfaces) so it is easier for manufacturers to build devices that can leverage the dizzying array of sensor enabled software that already utilize the Sensor API.
  • Clean up the HTC implementation.
  • Add support for capacitive touch panel to the HTC implementation with the new reversed engineered headers provided by a reader of this blog.
  • Create a few tutorials.
  • Add a FAQ to the CodePlex wiki.

If anyone else is interested in contributing to the Sensor API project, please let me know!

 

[0] The decision on whether to put the Android Mono port on CodePlex or Google Code was a tough one. :)

WindowlessControls Tutorial - Part 3

Cross compiling Mono is making me quite the productive blogger! This tutorial will expand on the ImageButtons I used in the previous tutorial. The buttons we placed only had a single image: nothing happens when they are focused or clicked. However, the class does support animated buttons! Using the previous tutorial code as a base to set up our background, I will add the new animated buttons:

// focus state bitmap
PlatformBitmap focused = PlatformBitmap.FromResource("Btn1.png");
// normal unselected state bitmap
PlatformBitmap unfocused = PlatformBitmap.FromResource("Btn1_Disabled.png");
// clicked state bitmap
PlatformBitmap clicked = PlatformBitmap.FromResource("Btn1_Pushed.png");

// set up the image button by setting the properties manually
ImageButton button1 = new ImageButton(unfocused, Stretch.None);
button1.Control.FocusedBitmap = focused;
button1.Control.ClickedBitmap = clicked;
button1.BackColor = Color.Transparent;

// OR set the button up by setting everything in the constructor
ImageButton button2 = new ImageButton(unfocused, Stretch.None, focused, clicked);
button2.BackColor = Color.Transparent;

// add the buttons
wrap.Controls.Add(button1);
wrap.Controls.Add(button2);

All you need to do is specify the images for the various button states, and the button will handle the animations for you! Click here for the updated tutorial source code.

WindowlessControls Tutorial Part 2

It's late, and I'm waiting for Mono to finish cross compiling for Android (hopefully with better results), so I figured I'd write up the next part of the WindowlessControls Tutorial series.

Recently, Chris Craft blogged about Alpha Blending in .NET Compact Framework. One of his suggestions was to use the Alpha Mobile Controls. After using and learning that API bit, you will quickly discover that in practice, it is not really usable. When I initially began investigation into Alpha Blending controls, I took the same approach as Alpha Mobile Controls. This design ended up hitting a dead end due to layout issues, and difficulty in actually reusing controls. It made me rethink how to implement a mobile UI framework. The requirements then ballooned and I ended up implementing WindowlessControls.

In In this article, I will demonstrate usage of the following:

  • How to use the WrapPanel, another common layout element. A WrapPanel aligns elements either side by side or top to bottom in a given direction. When it runs out of room in that direction, it will wrap to the next line. This works just like WPF's WrapPanel.
  • How to use the OverlayPanel. The OverlayPanel allows you to layer controls on top of each other.
  • The ImageButton class - A clickable button that displays an image. This image can have alpha.
  • How to enable transparencies in WindowlessControls.

Let's start with these three images:

Wallpaper users tip

The first image will become the background for our form. The next two images will be transparent buttons on that background (the black/gray area is actually transparent, the blog is munging it).

To do this, we will need to create an OverlayPanel. This OverlayPanel will contain two other controls: a background and a foreground. The background will be a WindowlessImage containing the leaf bitmap. The foreground will be a WrapPanel containing the two ImageButtons. Let's see what this looks like in code:

 

public AlphaDemo()
{
    InitializeComponent();

    // we need to layer two controls on top of another: a background, with another panel containing more controls
    StackPanel stack = myHost.Control;
    OverlayPanel overlay = new OverlayPanel();
    stack.Controls.Add(overlay);

    // set up the background bitmap and control
    PlatformBitmap backgroundBitmap = PlatformBitmap.FromResource("Wallpaper.jpg");
    WindowlessImage background = new WindowlessImage(backgroundBitmap);
    background.Stretch = Stretch.Uniform;
    overlay.Controls.Add(background);

    // set up the foreground
    StackPanel foreground = new StackPanel();
    overlay.Controls.Add(foreground);

    // load the transparent images
    PlatformBitmap users = PlatformBitmap.FromResource("users.png");
    PlatformBitmap tip = PlatformBitmap.FromResource("tip.png");

    // the two buttons will be placed in a WrapPanel
    // a wrap panel will horizontally or vertically lay out elements in a given direction until it runs out of room in that direction.
    // when it runs out of room, it will "wrap" to the next line.
    // since this wrap panel is contained in a vertical stack panel, it will lay out elements horizontally, and wrap vertically to the next line.
    WrapPanel wrap = new WrapPanel();
    foreground.Controls.Add(wrap);

    // set up the users button
    ImageButton userButton = new ImageButton(users, Stretch.None);
    // controls must be explicitly marked as being transparent. transparency is disabled by default on controls for performance reasons.
    userButton.BackColor = Color.Transparent;
    wrap.Controls.Add(userButton);
    userButton.WindowlessClick += (s, e) =>
    {
        MessageBox.Show("You just clicked users!");
    };

    // set up a tip button next to the users
    ImageButton tipButton = new ImageButton(tip, Stretch.None);
    tipButton.BackColor = Color.Transparent;
    wrap.Controls.Add(tipButton);
    tipButton.WindowlessClick += (s, e) =>
    {
        MessageBox.Show("You just clicked the tip!");
    };
}

And when you run this code, you see the following buttons which support transparencies. Notice that in the portrait, the second button can't fit on the first line, so it wraps to the next line. But if you rotate the orientation, it no longer needs to wrap, and comes back up to the first line. That's the WrapPanel in action!

image image

Cool huh!? As the code comment says, transparencies are disabled by default. This is because performing alpha computations is very expensive, and should only be used on an as needed basis. Click here for the updated tutorial.

Windowless Controls Tutorial Part 1 - Continued

In my previous post, a reader mentioned that he was curious what happens to this tutorial when it is run a device that has a different form factor, or the screen is rotated. Well, the WindowlessControl system resizes and remeasures all its components of course!

image

But there's a problem, the image is scrolled off the screen! Let's fix that with a little code. Let's enable AutoScroll on "myHost" and then place a another VerticalStackPanelHost inside it that will then contain all the controls seen in this form. The myHost control will allow the new VerticalStackPanelHost to size vertically to whatever length it pleases, and show scroll bars automatically, as necessary. So, the modified constructor looks like this:

public HelloWorld()
{
InitializeComponent();

// myHost is a Control that provides a transition from System.Windows.Forms to WindowlessControls.
// myHost.Control is the WindowlessControls.WindowlessControl that is "hosted" in the Windows.Windows.Forms.Control.
// put all the forms contents into a scrollHost, which will resize arbitrarily to fit its contents
VerticalStackPanelHost scrollHost = new VerticalStackPanelHost();
StackPanel stack = scrollHost.Control;
stack.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Stretch;
myHost.Control.Controls.Add(scrollHost);

// enable auto scrolling on myHost so if the contents (scrollHost) are too big, scroll bars appear
myHost.AutoScroll = true;






 



image



This form will now automatically set itself up properly and show scroll bars as necessary! Click here for the updated source code.

WindowlessControls Tutorial Part 1

I've mentioned in passing several times that I use a home brew UI framework to do all my Windows Mobile development. The UI framework implements many things that are missing from System.Windows.Forms:

  • Relative Layout of Screen Elements - Controls are positioned relative to each other and to the screen, not at absolute positions, which is the behavior of Windows Forms. The benefit of relative layout is that your form can fit any screen form factor.
  • Transparent Controls - There are ways to get transparencies into Windows Mobile, but none elegant.
  • Smart Key Navigation - Up, down, left, and right actually navigate you in that direction. Very handy for non-touch screens.
  • Data Driven Controls - Controls are driven by the data they represent. This allows for a clean MVC pattern which is not available with Windows Forms.
  • Simple Animation System - Creating and handling "focus" and "click" states for buttons is very simple.
  • Custom Controls - This framework can be used to create rich custom controls quite easily.
  • Hierarchical Events - All events bubble upwards in the control hierarchy and can be handled at any level. Similar to WPF.
  • XAML style layout - Create your user interface using XML.

This framework can and has been used to create aesthetically pleasing applications, such as Klaxon; something that is generally very difficult to do in Windows Mobile. However, for tutorial purposes, I'm going to start with a very simple "Hello World" style application. This tutorial will demonstrate the following (click here for the source code):

  • Add a WindowlessControl "Host" to your Windows Form application.
  • Add controls to the "Host" to be handled by the layout and rendering engine.
  • Manipulate the layout of these controls.
  • Handle click events at different points in the control hierarchy.
  • Draw some text and a simple image.

WindowlessControls is a complete layout and rendering system. You can drop a WindowlessControl "Host" onto a Windows Form, and then begin adding other WindowlessControls into it to take advantage of its features.

  1. Create a Windows Mobile Windows Forms application.
  2. Add a Reference to WindowlessControls.
  3. Compile.
  4. Drag a VerticalStackPanelHost (named myHost below) onto the Form. Dock the VerticalStackPanelHost so it fills the entire form. This will become your gateway into the land of WindowlessControls. A StackPanel is similar to the WPF StackPanel. It lays out all elements inside it in a linear fashion. A VerticalStackPanelHost would thus lay out all elements vertically.

image

Now you are ready to add controls. First, let's add a simple label that says "Hello World!". We'll add this code into the Form's constructor:

public HelloWorld()
{
    InitializeComponent();

    // myHost is a Control that provides a transition from System.Windows.Forms to WindowlessControls.
    // myHost.Control is the WindowlessControls.WindowlessControl that is "hosted" in the Windows.Windows.Forms.Control.
    StackPanel stack = myHost.Control;
    // make the stack panel to stretch to fit the width of the screen
    stack.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Stretch;

    // hello world!
    WindowlessLabel hello1 = new WindowlessLabel("Hello World!");
    stack.Controls.Add(hello1);

That was painless enough. This will produce the left aligned "Hello World!" seen here:

image

Now let's try adding some larger text that is centered horizontally and some text that is right aligned:

// center this label and use a different font
Font center = new Font(FontFamily.GenericSerif, 20, FontStyle.Regular);
WindowlessLabel hello2 = new WindowlessLabel("Centered!", center);
hello2.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Center;
stack.Controls.Add(hello2);

// right align this control
WindowlessLabel right = new WindowlessLabel("Right Aligned!");
right.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Right;
stack.Controls.Add(right);

image

Notice that there is no need to specify any positioning with the various screen elements. All their heights and widths are calculated by the layout system, and the labels are "stacked" on top of each other automatically. Another supported property of any WindowlessControl is a "Margin". This allows the developer to specify a small amount of padding between the Control and its content. For example, to draw some text with a 20 pixel margin all around it, set the Margin property:

// show that controls support margins
WindowlessLabel margin = new WindowlessLabel("Margin!");
margin.Margin = new Thickness(20, 20, 20, 20); // margins for the left, top, right, and bottom
stack.Controls.Add(margin);

image

As you can see, there is a visible 20 pixel margin along the top and left of the rendered text. Just like any other layout framework, WindowlessControls supports the concept of nested controls: you can place controls within other controls. An entire control group is then subject to the layout of its parent. For example, by creating a centered stack panel and adding two labels to it, all the children of the StackPanel end up being centered:

// nest controls within another control and center the parent
StackPanel child = new StackPanel();
child.Controls.Add(new WindowlessLabel("Nested"));
child.Controls.Add(new WindowlessLabel("Controls"));

image

Now, let's add a Hyperlink into that same StackPanel, and handle it's WindowlessClick event:

// create a clickable hyperlink
HyperlinkButton button = new HyperlinkButton("Click Me!");
child.Controls.Add(button);
button.WindowlessClick += (s, e) =>
    {
        MessageBox.Show("Hello!");
    };

 

image

As shown in the code, the click event is called WindowlessClick as opposed to Click. Click is the standard Windows Forms event, whereas WindowlessClick behaves differently. This is because all WindowlessControls bubble all Control events to every Host in its hierarchy. This means that the WindowlessClick event is also fired and available to be handled on "myHost", the top level control! Let's test this out:

// when the hyperlink is clicked, the event will bubble up to every host in the hierarchy
// watch for the event and handle it
myHost.WindowlessClick += (s, e) =>
    {
        if (s != myHost)
        {
            MessageBox.Show("A click event just bubbled up to me from " + s.GetType().ToString() + "!");
        }
    };
child.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Center;
stack.Controls.Add(child);

image

Finally, let's draw a centered image on the screen. Grab an image and add it to your project. Set its Build Action to "Embedded Resource" in the properties pane. Then add the following code:

// draw a centered image
PlatformBitmap bitmap = PlatformBitmap.FromResource("mybrainhurts.jpg");
WindowlessImage image = new WindowlessImage(bitmap);
image.HorizontalAlignment = WindowlessControls.HorizontalAlignment.Center;
stack.Controls.Add(image);

image

Done! Note that PlatformBitmap is different from System.Drawing.Bitmap. The problem with System.Drawing.Bitmap is that it does not support transparencies on Windows Mobile. However, the Imaging API available in Windows Mobile does support images with per pixel alpha. PlatformBitmap provides an abstraction layer around images: they either wrap standard Bitmap objects or they wrap an IBitmapImage from the Imaging API. The PlatformBitmap.Load function will handle that abstraction for you transparently, and choose the appropriate API based on the image type.

Anyhow, I understand this doesn't look that enticing yet, but worry not! Next article, I'll demonstrate the data driven controls and custom/composite controls. That's when things get interesting.

Click here to download the source code for this tutorial.

GL Maps goes Open Source

glmaps

GL Maps is a really interesting and fun project, but I haven't had any time to work on it as of late! But I figure that other developers may be interested in carrying the torch. I'll probably return to this project some day in the distant future...

Download GL Maps source code here.

Drawing Text Overlays using the Tiled Map Client

(and the internal workings of the Tile Rendering Engine)

TextMapDrawable

This morning, I got an email from one of the users of the Tiled Maps library. He pointed out that although it was easy to place Bitmap overlays at a position on the map, he couldn't figure out how to draw text at that position. His approach was to draw text on a Bitmap and then draw that Bitmap onto the map. The problem he was running into, however, was having a proper transparent background on that Bitmap (Windows Mobile does not support an alpha channel). Although it is possible to do a masked blit in Windows Mobile, this method of drawing text onto a map is not ideal.

If one examines the internals of the Tiled Map Client, you will find that overlays that appear on the map actually have a very flexible abstraction layer around them. The TiledMapSession itself has no internal knowledge of the overlay renderering implementation, in that it does not actually perform the drawing. It is only concerned about the Width and Height, so it can perform proper layout to let the rendering engine (IMapRenderer) to draw the content at the proper location. This is how the Tiled Map Client is flexible enough to perform both 2D and 3D rendering:

/// <summary>
/// IMapRenderer provides the methods necessary for a TiledMapSession
/// to draw tiles to compose the map, as well as the other content
/// that may appear on the map.
/// </summary>
public interface IMapRenderer
{
    /// <summary>
    /// Get a IMapDrawable from a stream that contains a bitmap.
    /// </summary>
    /// <param name="session">The map session requesting the bitmap</param>
    /// <param name="stream">The input stream</param>
    /// <returns>The resultant bitmap</returns>
    IMapDrawable GetBitmapFromStream(TiledMapSession session, Stream stream);

    /// <summary>
    /// Given a IMapDrawable, draw its contents.
    /// </summary>
    /// <param name="drawable">The IMapDrawable to be drawn.</param>
    /// <param name="destRect">The destination rectangle of the drawable.</param>
    /// <param name="sourceRect">The source rectangle of the drawable.</param>
    void Draw(IMapDrawable drawable, Rectangle destRect, Rectangle sourceRect);

    /// <summary>
    /// Draw a filled rectangle on the map.
    /// </summary>
    /// <param name="color">The fill color.</param>
    /// <param name="rect">The destination rectangle.</param>
    void FillRectangle(Color color, Rectangle rect);

    /// <summary>
    /// Draw a line strip on the map.
    /// </summary>
    /// <param name="lineWidth">The width of the line stripe.</param>
    /// <param name="color">The line strip color.</param>
    /// <param name="points">The points which compose the line strip.</param>
    void DrawLines(float lineWidth, Color color, Point[] points);
}

/// <summary>
/// IMapDrawable is the interface used by the Tiled Map Client to represent content
/// onto a IMapRenderer.
/// IMapDrawable is generally tied to an implementation of IMapRenderer, 
/// which is responsible for internally representing and rendering the drawable.
/// </summary>
public interface IMapDrawable : IDisposable
{
    /// <summary>
    /// The width of the drawable content.
    /// </summary>
    int Width
    {
        get;
    }

    /// <summary>
    /// The height of the drawable content.
    /// </summary>
    int Height
    {
        get;
    }
}

So, how do we go from drawing a bitmap to drawing text? The standard/normal implementation and usage of an IMapRenderer is the GraphicsRenderer. The GraphicsRenderer is what facilitates rendering of a TiledMapSession to a System.Drawing.Graphics instance. Let's take a look at it's implementation of Draw:

public void Draw(IMapDrawable drawable, Rectangle destRect, Rectangle sourceRect)
{
    IGraphicsDrawable graphicsDrawable = drawable as IGraphicsDrawable;
    graphicsDrawable.Draw(Graphics, destRect, sourceRect);
}

As you can see, it casts the IMapDrawable to an IGraphicsDrawable and calls its implementation of Draw, passing it the Graphics object:

/// <summary>
/// IGraphicsDrawable is a type of IMapDrawable that can draw to a
/// System.Drawing.Graphics instance.
/// </summary>
public interface IGraphicsDrawable : IMapDrawable
{
    void Draw(Graphics graphics, Rectangle destRect, Rectangle sourceRect);
}

There are two provided implementations of IGraphicsDrawable: WinCEImagingBitmap, which uses the Imaging API to draw bitmaps that contain alpha, and StandardBitmap, which draws a standard System.Drawing.Bitmap. So what we need, is a third implementation, which I called TextMapDrawable. TextMapDrawable will implement IGraphicsDrawable and use Graphics.DrawString to draw text onto the Graphics object.

Here's my implementation of TextMapDrawable:

public class TextMapDrawable : IGraphicsDrawable
{
    static Bitmap myMeasureBitmap = new Bitmap(1, 1, PixelFormat.Format16bppRgb565);
    static Graphics myMeasureGraphics = Graphics.FromImage(myMeasureBitmap);

    public float MaxWidth
    {
        get;
        set;
    }

    public float MaxHeight
    {
        get;
        set;
    }

    Brush myBrush;
    public Brush Brush
    {
        get
        {
            return myBrush;
        }
        set
        {
            myBrush = value;
        }
    }

    bool myDirty = true;
    string myText;
    public string Text
    {
        get
        {
            return myText;
        }
        set
        {
            myText = value;
            myDirty = true;
        }
    }

    Font myFont;
    public Font Font
    {
        get
        {
            return myFont;
        }
        set
        {
            myDirty = true;
            myFont = value;
        }
    }

    #region IGraphicsBitmap Members

    public void Draw(Graphics graphics, Rectangle destRect, Rectangle sourceRect)
    {
        // just ignore source rect, doesn't mean anything in this context.
        if (CalculateDimensions() && myBrush != null)
            graphics.DrawString(myText, myFont, myBrush, destRect.X, destRect.Y);
    }

    #endregion

    bool CalculateDimensions()
    {
        bool valid = !string.IsNullOrEmpty(myText) && myFont != null;

        if (myDirty)
        {
            myDirty = false;
            if (valid)
            {
                SizeF size = myMeasureGraphics.MeasureString(myText, myFont);
                myWidth = (int)Math.Ceiling(size.Width);
                myHeight = (int)Math.Ceiling(size.Height);
            }
            else
            {
                myWidth = 0;
                myHeight = 0;
            }
        }
        return valid;
    }

    #region IMapBitmap Members

    int myWidth;
    public int Width
    {
        get
        {
            CalculateDimensions();
            return myWidth;
        }
    }

    int myHeight;
    public int Height
    {
        get
        {
            CalculateDimensions();
            return myHeight;
        }
    }

    #endregion

    #region IDisposable Members

    public void Dispose()
    {
    }

    #endregion
}

As you can see, it took only 38 lines of code (according to Visual Studio's Code Metrics) to allow drawing of text to the map! I have also updated the Tiled Map Client source for those interested in these changes.

Fixing the "setuid su" security hole on Modified Android RC30

shell

If you have a rooted Android phone, you are probably using a variation of JesusFreke's RC30 image. With JF's image, there are two ways you can get root:

  • For remote root, you can adb shell into the phone
  • For local root, run the root setuid su from Terminal Emulator or pTerminal.

The problem with the latter version is that any application can run su and get full unfettered access to everything on the phone. This leaves the door open to malicious applications. However, the answer is not simply removing the su file, as then there is no way to perform superuser tasks from within legitimate applications.

To that end, I wrote the Superuser application that fixes the security hole, and also allows you or any application to get root when properly authorized. I've also written a Shell application to demonstrate how an application can request authorization.

How Superuser sets itself up:

  • The standard RC30 install will have a setuid /system/bin/su. (if you deleted disabled it, reenable it for setup)
  • Install the Superuser Java application to your phone and run it.
  • Superuser will create a copy of su named superuser.
  • Superuser will chown superuser to user "root" and group app_gid (where app_gid is the group id of the Superuser application as determined by Android)
  • The superuser binary will also be chmod 4750 superuser, so that the Superuser Java application, and only that application, can execute it as root.
  • Finally, Superuser will chmod 4700 su to close the security hole.

How other applications get root access with the user's permissions:

  • Any application can fire an intent to request access to the locked down /system/bin/su.
  • When that happens, Superuser will catch the intent and ask the user if it should grant that application root permissions.
  • If allowed, Superuser will chown 0:app_gid /system/bin/su (where app_gid is the gid of the requesting application).
  • That application can then use /system/bin/su as normal.

Notes:

  • /system/bin/su will get reset to chown 0:0 after 10 seconds, so the requesting application must start the instance of su up within that grace period. This is a bit of a kludge, but I'm a Linux newbie and don't know a better/cleaner way to do it.
  • Since this is an unmodified version of su, 3rd party applications don't have to worry about piping in passwords and such.
  • This is using the standard Linux level permissions and restrictions, as well as the Android framework permissions present at the Java level.

Full source code to Superuser and Shell are at the bottom of this post.

So, here's what it the user experience looks like when running Shell and requesting root access:

First, we start up shell and try to run su. Note that running su is not allowed (as the uid of the process did not change). Shell needs to request permission to access su first:

nosu

This menu button fires the intent to request permission to su:

surequest

Superuser receives the request and asks the user if they wish to grant Shell superuser permissions:


suconfirm

Once granted, the user can properly execute su (as indicated by the root id in the prompt):

suworking

 

Superuser and Shell APK install files (will be on the market too soon).

Superuser and Shell Source Code.

Unified Sensor API now supports the Omnia Light Sensor

Around a month ago I got a tip from an anonymous reader (I think it's a Samsung developer) on how to access the Samsung's light sensor. The tip seems to work correctly [0], so I added support for that sensor in the Sensor API.

I ended up having to refactor the API a little to support the Samsung light sensor transparently: the changes are similar to the ones I made a few months ago for transparently creating the proper IGSensor implementation on a given device.

So, the change log:

  • HTCLightSensor is now a private class.
  • SamsungLightSensor is a new private class.
  • Refactored HTCGSensor and SamsungGSensor to derive from GSensorBase which inherits from PollingSensor. This change was made to consolidate much of the sensor code.
  • Instead of creating an HTCLightSensor or SamsungLightSensor explicitly, developers should use the new LightSensorFactory.CreateLightSensor method to get the appropriate ILightSensor object for the phone the application is running on.

Here's the link for the updated API and code samples.

I'll be recompiling Klaxon shortly to accommodate the new changes.

[0] It looks like the way this is done is by reading the backlight intensity value, rather than actually reading the light sensor. The Omnia sets the backlight value based on that reading.

Tile Client Update: New Features and Fixes

As a result of my work on GL Maps, I made several fixes, feature enhancements, and extensions to the original Tile Client and the sample code. Pictures and captions for your viewing pleasure (download is at very bottom):

Composite

I updated the desktop sample to demonstrate how to use a MapOverlay to put pushpins on the map. It also demonstrates how to use CompositeMapSession to blend multiple sessions together. Such as:

  • Satellites + Roads
  • Streets + Traffic

Directions

The desktop sample has also been updated to show how to retrieve and use directions from either Google or Virtual Earth. 

TileRefresh

The samples also demonstrate how to provide a custom refresh bitmap for when the tile is being downloaded.

SmartTile SmartTile2

But, refresh bitmaps are tacky! So, the Tile client now uses parent and child tiles (tiles from other zoom levels) to render temporarily if the tile is missing! On the left you see can see the map using parent tiles to render while the tiles are being downloaded. On the right you see the map again, in full detail, when the tiles have completed downloading.

cftransparent

And a much requested feature: Tiles and overlays now support transparencies on Windows Mobile! Above you can see a MapOverlay that is using alpha blending.

 

Change Log:

  • Developers must now instantiate a GraphicsRenderer and use that to render the map, rather than passing a Graphics object directly. This change was made to allow abstraction of the rendering device to support the 3D rendering a la GL Maps.
  • Tiles are now cached to disk. They will be refreshed from server every 2 days.
  • Fixed Google Directions retrieval.
  • Implemented "smart" tile rendering. If a tile is being downloaded, the parent or child tiles are used to render its content.
  • Fixed bug where MapOverlays were not being affected by the Offset property.
  • Implemented transparencies on Windows Mobile. To retrieve and use a transparent bitmap, simply call GraphicsRenderer.LoadBitmap! See the Windows Mobile sample for more detail.
  • Windows Mobile now converts bitmaps to 16bpp automatically after retrieval. This is a huge performance improvement, because instead of doing the pixel format conversion per paint, it happens only once.
  • Updated both samples to demonstrate more features.
  • Added a TiledMapSession.ClearAgedTiles(N) method to clear the tile cache of tiles that haven't been used in N milliseconds. This is useful for Windows Mobile where memory is a constraint, but clearing all tiles is undesirable.

Full source to the Tile Client and sample applications.