Monday, 4 January 2016

Writing an office addin for your website

Once a month I attend the Newcastle Coders Group, where they have presentations on coding and other topics. Last month there was a presentation by Andrew Coates from Microsoft on writing your own plugins for Office.

This seemed quite easy so I wrote my own plugin for the website physiotherapy exercises in a day or so.

You can use any server technology you like to provide the content, it does not need to be ASP NET.
You can write plugins for excel, mail, powerpoint etc. This one is for word.

You can create an office plugin using Visual Studio 2015 community edition, more details can be found here.

A tutorial for developing your adding can be found here.

Microsoft provide their own (html based) UI Toolkit, called fabric for developing office apps. It can be found here.

You can get a free developer account with a one year subscription to office 365 and then submit your app on the seller dashboard.

It took a few tries for me to get the app approved, it can take up to 5 days each time you submit. Some tips I learnt from my mistakes :
  • Make sure your application version is exactly the same, including all the decimals (for example 1.0.0.0).
  • Don't include any taskbar in your screenshots, it will result in your screenshots getting rejected
  • Read the guidelines carefully
So why don't you try making one for your own website?

Saturday, 2 January 2016

My First Plugin - Adding android wear features to your Nativescript app - part 2

Back in November I blogged about making my app usable on an android wear watch. At the time this was a prototype.

I have now got it working nicely with communication features from the phone to the watch, so you can select exercises on your phone and then push the selection to the watch.

All you need to do is have the application currently running and open on your phone and watch and make your selection.

To do this, I had to write some android code using Android Studio and the wearable component of google play services.

Messaging between the phone and the watch is covered in the google development documentation here. These examples are both also very useful.

Selecting Exercises on the Phone

Choosing to push selection to Watch

Previewing on Phone
Using a bit of trial and error and the blog post here as well documentation on building plugins I managed to get it working.

One class is used to send and receive messages for google play services and start the listener for messages on the watch.

 package org.nativescript.androidwear.messaging;

import android.content.Context;
import android.widget.Toast;
import android.os.Looper;

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class SendReceiveMessage extends WearableListenerService {

    private static final long CONNECTION_TIME_OUT_MS = 100;
    private static SendReceiveMessageListener onMessageReceivedCallback = null;
    private static GoogleApiClient client;
    private static SendReceiveMessage listener;
    private static boolean notifyToast = false;

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        receive(this, messageEvent.getPath(), new String(messageEvent.getData()));
    }

    public static void registerListener(SendReceiveMessageListener listener)
    {
        onMessageReceivedCallback = listener;
    }

    /**
     * Receive message, displaying as a toast if no action set, otherwise running the action
     */

    public static void receive(Context context, String messagePath, String  messageReceived) {
        if (onMessageReceivedCallback == null) {
            if (notifyToast) {
                Toast.makeText(context, messagePath + " received no callback", Toast.LENGTH_LONG).show();
            }
        }
        else
        {
            if (notifyToast) {
                Toast.makeText(context, messagePath + " received with callback", Toast.LENGTH_LONG).show();
            }
            onMessageReceivedCallback.receive(messagePath,messageReceived);
        }
    }

    /**
     * Start listening for messages
     */

    public static void startListener(Context context, boolean notify)
    {
        // Get Client

        client =  new GoogleApiClient.Builder(context)
                .addApi(Wearable.API)
                .build();

        listener = new SendReceiveMessage();
        Wearable.MessageApi.addListener(client,listener);
        notifyToast = notify;
        if (notify) {
            Toast.makeText(context, "Listener started!!", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Stop listening for messages
     */

    public static void stopListener(Context context, boolean notify)
    {
        Wearable.MessageApi.removeListener(client,listener);
        if (notify) {
            Toast.makeText(context, "Listener stopped!!", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Sends a message to the connected mobile device, telling it to show a Toast.
     */
    public static void send(final Context context, final String messagePath, final String messageToSend, final boolean notify) {

        // Get Client

        final GoogleApiClient client =  new GoogleApiClient.Builder(context)
                .addApi(Wearable.API)
                .build();

        new Thread(new Runnable() {
            @Override
            public void run() {

                // Get First Node

                client.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
                NodeApi.GetConnectedNodesResult result =
                        Wearable.NodeApi.getConnectedNodes(client).await();
                List<Node> nodes = result.getNodes();
                if (nodes.size() > 0) {
                    final String nodeId = nodes.get(0).getId();

                    // Send Message

                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            client.blockingConnect(CONNECTION_TIME_OUT_MS, TimeUnit.MILLISECONDS);
                            Wearable.MessageApi.sendMessage(client, nodeId, messagePath, messageToSend.getBytes()).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
                                @Override
                                public void onResult(MessageApi.SendMessageResult sendMessageResult) {
                                    if (!sendMessageResult.getStatus().isSuccess()) {
                                        Looper.prepare();
                                        Toast.makeText(context, "Message not sent - failure", Toast.LENGTH_LONG).show();
                                        Looper.loop();
                                    }
                                }
                            });
                            client.disconnect();

                            if (notify) {
                                Looper.prepare();
                                Toast.makeText(context, "Message sent", Toast.LENGTH_LONG).show();
                                Looper.loop();
                            }
                        }
                    }).start();
                }
                else
                {
                    if (notify) {
                        Looper.prepare();
                        Toast.makeText(context, "Message not sent - no nodes", Toast.LENGTH_LONG).show();
                        Looper.loop();
                    }
                }
                client.disconnect();

            }
        }).start();
    }
}
   

The second file is an interface, used as a bridging mechanism between the android code and nativescript.
package org.nativescript.androidwear.messaging;

/**
 * Created by Peter on 1/01/2016.
 */
public interface SendReceiveMessageListener {
    void receive(final String messagePath, final String messageReceived);
}
The build.gradle file is set up to build a library file.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "21.1.2"

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 22
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.google.android.gms:play-services-wearable:8.4.0'
}

Once built you can use the library aar file in plugin.

nativescript-wear-messaging
--platforms
----android
------libs
--------wearmessaging.aar
-------AndroidManifest.xml
-------include.gradle
--index.js
-- package.json

The typescript version of the index.js file is
var app = require('application');
var context = app.android.context;

// If notify is turned on, it will display debug toast messages for testing

var notify = false;

// Call this first in the page you want to use the messaging in

export function startListener() {
    try {
        org.nativescript.androidwear.messaging.SendReceiveMessage.startListener(context, notify);
    }
    catch (ex) {
        alert(ex.message);
    }
}

// Call this when the page is closed

export function stopListener() {
    try {
        org.nativescript.androidwear.messaging.SendReceiveMessage.stopListener(context, notify);
    }
    catch (ex) {
        alert(ex.message);
    }
}

// Pass in a callback in the page you want to listen for messages, you can JSON.parse to convert strings back into objects

export function receive(receiveCallback: (messagePath: string, messageReceived: string) => void) {
    try {
        var sendReceiveMessageListener = new org.nativescript.androidwear.messaging.SendReceiveMessageListener({ receive: receiveCallback });
        org.nativescript.androidwear.messaging.SendReceiveMessage.registerListener(sendReceiveMessageListener);
    }
    catch (ex) {
        alert(ex.message);
    }
}

// Call this from your phone app, the message path is the keyname of the message, you can use JSON.stringify to convert objects to be sent

export function send(messagePath: string, messageToSend: string) {
    try {
        org.nativescript.androidwear.messaging.SendReceiveMessage.send(context, messagePath, messageToSend, notify);
    }
    catch (ex) {
        alert(ex.message);
    }
}
The manifest file needs to contain a reference to the custom WearListenerService. This will then be copied into the overall AndroidManifest file.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
    android:versionName="1.0" >
 <application>
  <service
            android:name="org.nativescript.androidwear.messaging.SendReceiveMessage" >
            <intent-filter>
                <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
            </intent-filter>
        </service>
 </application>
</manifest>
The include gradle needs to include detail on the dependencies
//default elements
android { 
    productFlavors {
        "nativescript-wear-messaging" {
            dimension "nativescript-wear-messaging"
        }
    }
}

//optional elements
dependencies {
compile 'com.android.support:appcompat-v7:23.1.1'
    compile "com.google.android.gms:play-services-wearable:8.4.0"
}
The plugin needs to be installed on the mobile phone and watch versions of the code. Messages can be sent to/from each device. A snippet of the code for the model can be seen below.
         // Called on page load

    public startListenerReload() {
        try {

            // Start listening for messages
           
            wearMessaging.startListener();
            
            // When message is received process then

            wearMessaging.receive(

                (messagePath: string, messageReceived: string) => {
                    try {

                        // Check message is the one we are interested in, store it in application settings
                        // Convert to JSON object and display on screen

                        if (messagePath == this.messagingPath) {
                            appSettings.setString("exercises", messageReceived);
                            var exercises = <IExercises>JSON.parse(messageReceived);
                            this.loadData(exercises);
                        }
                    }
                    catch (ex) {
                        alert(ex.message);
                    }
                }
            );
            
            // load previously loaded messages

            var messageReceived = appSettings.getString("exercises", "");
            if (messageReceived != "") {
                var exercises = <IExercises>JSON.parse(messageReceived);
                this.loadData(exercises);
            }
        }
        catch (ex) {
            alert(ex.message);
        }
    }

    // Send message to other device

    public sendMessages(exercises: IExercises) {
        wearMessaging.send(this.messagingPath, JSON.stringify(exercises));
    }

Sunday, 27 December 2015

Another look at the Telerik RadListView For NativeScript

Telerik put out release 2 of their Telerik UI at the end of October and I blogged about it here.

There was a number of issues with it, that preventing me from using it to the full potential and I am happy to be able to say, these have almost all been fixed in release 3.

Important fixes in release 3.
  1. Any elements you have bound in the itemtemplate now reflect changes from your model.
  2. The ListViewLayout can now be changed programatically and the changes are reflected by the UI.
  3. The ItemTap event used to be triggered twice when you tapped on an item, this has been resolved, so it can now be used as expected.
  4. Scrolling too fast would result in errors
New Functionality in release 3
  1. A new API for managing selection
  2. Ability to block UI updates while you do changes to the source collection which results in better performance.
Making a Grid that resizes on screen rotation and different device sizes

The ListViewGridLayout option allows you to set the number of items displayed as columns or rows (depending on the scroll direction). At this stage, it hasn't been designed for fixed width columns with a varying number of columns, but you can do this programatically by determining the screen dimensions using the platform module and listening for changes using the application module (fix 2 above).

// Monitor for orientation changes

   application.on("orientationChanged", (args: application.OrientationChangedEventData) => {
            this.resetRadListView();
        });

......

 public resetRadListView() {
        var displayMode = applicationSettingsHelper.getDisplayMode();

        // Grid View Mode

        if (displayMode == 0) {

            // Determine number of images that can be displayed

            var deviceWidth = platform.screen.mainScreen.widthPixels / platform.screen.mainScreen.scale;
            var spanCount = Math.round(deviceWidth / 82);
            var gridLayout = new radListView.ListViewGridLayout();
            gridLayout.spanCount = spanCount;
            gridLayout.scrollDirection = "Vertical";
            this.galleryRadListView.listViewLayout = gridLayout;
            this.galleryRadListView.backgroundColor = new color.Color("Black");

        // List View Mode

        } else {
            var linearLayout = new radListView.ListViewLinearLayout();
            linearLayout.scrollDirection = "Vertical";
            this.galleryRadListView.listViewLayout = linearLayout;
            this.galleryRadListView.backgroundColor = new color.Color("White");
        }
        this.galleryRadListView.items = this.observableExerciseRecordsVisible;
        this.galleryRadListView.refresh();
    }

So on my Galaxy Note 4, it displays 4 images across in portrait mode and 8 images across in landscape mode, as can be seen below.

PORTRAIT

LANDSCAPE

Making the RadListView perform different actions on Press and LongPress

There is a ItemTap event which you can you use to do the first action. I have used this to indicate selection of records in the model. This displays a green tick in the image (fix 1/3 above).
export function itemTap(args: radListView.ListViewEventData) {
    model.galleryViewModel.itemToggle(args.itemIndex);
}
SELECTED

There is no LongPress event available, but you can do this by using the new built in selection functionality with selectionBehavior set to LongPress. This displays a popup window with the exercise detail. After selection, you need to programatically deselect it again.
export function itemSelected(args: radListView.ListViewEventData) {
    model.galleryViewModel.itemDisplay(args.itemIndex);
    listView.deselectItemAt(args.itemIndex);
}
POPUP

Different Views

Adding to our settings section the ability to choose three different RadListView layouts.
  1. Images Grid (as above)
  2. Rows with image and title
  3. Rows with image and full text
This way the user can decide to select exercises in the way they are most comfortable.

Known Issues

If you use the ScrollToIndex option in GridView layout, it sometimes does not repaint the UI correctly. I have raised a ticket for this and hopefully it will be fixed in the final version coming out in March.

Monday, 23 November 2015

Using Font Awesome to build your own user controls in NativeScript

This tweet detailed how you can use FontAwesome in your Nativescript app.

All you need to do if copy the font into the app/fonts folder.

I thought I would use this to make some simple controls to demonstate what is possible.



Here is some example code for an image button, checkbox, radiobox, rating and tick button.

The checkbox, radiobox and rating can all bind to values and change when you tap them.

As outlined in the documentation, you need to make a reference to the custom control at the top of the page.

<Page xmlns="http://www.nativescript.org/tns.xsd" xmlns:fa="helpers/faHelper" backgroundColor="gray">
  <StackLayout style="margin:10">
    <Label text="Font Awesome Demo" fontSize="30" color="white"/>
    <fa:CheckImage style="background-image:'~/res/drawingshigh/ex0001.jpg'"/>
    <fa:Label icon="fa_android" fontSize="25" label=" Android Demo"/>
    <fa:Label icon="fa_apple" fontSize="25" label=" Apple Demo"/>
    <GridLayout columns="*,*" rows="auto,auto,auto">
      <fa:CheckBox label=" Check On" fontSize="25" checkBoxSize="50" checked="true" row="0" col="0" />
      <fa:CheckBox label=" Check Off" fontSize="25" checkBoxSize="50" checked="false" row="0" col="1" />
      <fa:Radio label=" Radio On" fontSize="25" radioSize="50" checked="true" row="1" col="0"/>
      <fa:Radio label=" Radio Off" fontSize="25" radioSize="50" checked="false" row="1" col="1"/>
      <fa:Button label="Buy Coffee" icon="fa_coffee" fontSize="25" color="White" backgroundColor="black" style="margin:10" row="2" col="0" />
      <fa:Button label="Buy Gift" icon="fa_gift" fontSize="25" iconRight="true" color="White" backgroundColor="black" iconColor="green" style="margin:10" row="2" col="1" />
    </GridLayout>
    <fa:Rating value="3" maxValue="5" label=" Rating" labelSize="25" ratingSize="40"/>
  </StackLayout>
</Page>
Typescript code behind it is as below. Note there is a converter to allow you to use the standard FontAwesome icon names.

Note that there is a small bug with the way this works for spans. This is being worked on by Telerik.

Hopefully this may be useful to you and give you ideas what you can build yourself.
import label = require("ui/label");
import gestures = require("ui/gestures");
import dependencyObservable = require("ui/core/dependency-observable");
import proxy = require("ui/core/proxy");
import span = require("text/span");
import formattedString = require("text/formatted-string");
import button = require("ui/button");
import observableArray = require("data/observable-array");
import color = require("color");
import enums = require("ui/enums");
import stackLayout = require("ui/layouts/stack-layout");

function onCheckedCheckBoxPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var checkBox = <CheckBox>data.object;
    checkBox.setFields();
}

function onLabelCheckBoxPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var checkBox = <CheckBox>data.object;
    checkBox.setFields();
}

function onCheckBoxSizeCheckBoxPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var checkBox = <CheckBox>data.object;
    checkBox.setFields();
}

export class CheckBox extends label.Label {

    public static labelProperty = new dependencyObservable.Property(
        "label",
        "CheckBox",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelCheckBoxPropertyChanged
        )
    );

    public static checkBoxSizeProperty = new dependencyObservable.Property(
        "checkBoxSize",
        "CheckBox",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onCheckBoxSizeCheckBoxPropertyChanged
        )
    );

    public static checkedProperty = new dependencyObservable.Property(
        "checked",
        "CheckBox",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onCheckedCheckBoxPropertyChanged
        )
    );

    constructor() {
        super();
        this.textWrap = true;
        this.style.fontFamily = "FontAwesome";
        this.observe(gestures.GestureTypes.tap, (args: gestures.GestureEventData) => {
            this.checked = !this.checked;
        });
    }

    public set checkBoxSize(value: number) {
        this._setValue(CheckBox.checkBoxSizeProperty, value);
    }

    public get checkBoxSize() {
        return this._getValue(CheckBox.checkBoxSizeProperty);
    }

    public set label(value: string) {
        this._setValue(CheckBox.labelProperty, value);
    }

    public get label() {
        return this._getValue(CheckBox.labelProperty);
    }

    public set checked(value: boolean) {
        this._setValue(CheckBox.checkedProperty, value);
    }

    public get checked() {
        return this._getValue(CheckBox.checkedProperty);
    }

    public setFields() {
        var textAdd = new formattedString.FormattedString();

        this.formattedText.spans = new observableArray.ObservableArray<span.Span>();
        var spanAdd = new span.Span();
        spanAdd.text = convertKeyHex(this.checked ? key.fa_square_o : key.fa_check_square_o);
        spanAdd.fontSize = this.checkBoxSize;
        textAdd.spans.push(spanAdd);

        spanAdd = new span.Span();
        spanAdd.text = this.label;
        spanAdd.fontSize = this.fontSize;
        textAdd.spans.push(spanAdd);

        this.formattedText = textAdd;
    }
}

function onCheckedRadioPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var radio = <Radio>data.object;
    radio.setFields();
}

function onLabelRadioPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var radio = <Radio>data.object;
    radio.setFields();
}

function onRadioSizeRadioPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var checkBox = <CheckBox>data.object;
    checkBox.setFields();
}

export class Radio extends label.Label {

    public static radioSizeProperty = new dependencyObservable.Property(
        "radioSize",
        "Radio",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onRadioSizeRadioPropertyChanged
        )
    );

    public static labelProperty = new dependencyObservable.Property(
        "label",
        "Radio",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelRadioPropertyChanged
        )
    );

    public static checkedProperty = new dependencyObservable.Property(
        "checked",
        "Radio",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onCheckedRadioPropertyChanged
        )
    );

    constructor() {
        super();
        this.textWrap = true;
        this.style.fontFamily = "FontAwesome";
        this.observe(gestures.GestureTypes.tap, (args: gestures.GestureEventData) => {
            if (this.checked) {
                return;
            }
            this.checked = !this.checked;
        });
    }

    public set radioSize(value: number) {
        this._setValue(Radio.radioSizeProperty, value);
    }

    public get radioSize() {
        return this._getValue(Radio.radioSizeProperty);
    }

    public set label(value: string) {
        this._setValue(Radio.labelProperty, value);
    }

    public get label() {
        return this._getValue(Radio.labelProperty);
    }

    public set checked(value: boolean) {
        this._setValue(Radio.checkedProperty, value);
    }

    public get checked() {
        return this._getValue(Radio.checkedProperty);
    }

    public setFields() {
        var textAdd = new formattedString.FormattedString();

        this.formattedText.spans = new observableArray.ObservableArray<span.Span>();
        var spanAdd = new span.Span();
        spanAdd.text = convertKeyHex(this.checked ? key.fa_circle_o : key.fa_check_circle_o);
        spanAdd.fontSize = this.radioSize;
        textAdd.spans.push(spanAdd);

        spanAdd = new span.Span();
        spanAdd.text = this.label;
        spanAdd.fontSize = this.fontSize;
        textAdd.spans.push(spanAdd);

        this.formattedText = textAdd;
    }
}


function onMaxValueRatingPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var rating = <Rating>data.object;
    rating.setFields();
}

function onValueRatingPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var rating = <Rating>data.object;
    rating.setFields();
}

function onLabelRatingPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var rating = <Rating>data.object;
    rating.setFields();
}

function onLabelSizeRatingPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var rating = <Rating>data.object;
    rating.setFields();
}

function onRatingSizeRatingPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var rating = <Rating>data.object;
    rating.setFields();
}


export class Rating extends stackLayout.StackLayout {

    public static labelProperty = new dependencyObservable.Property(
        "label",
        "Rating",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelRatingPropertyChanged
        )
    );

    public static valueProperty = new dependencyObservable.Property(
        "value",
        "Rating",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onValueRatingPropertyChanged
        )
    );

    public static labelSizeProperty = new dependencyObservable.Property(
        "labelSize",
        "Rating",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelSizeRatingPropertyChanged
        )
    );

    public static ratingSizeProperty = new dependencyObservable.Property(
        "ratingSize",
        "Rating",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onRatingSizeRatingPropertyChanged
        )
    );

    public static maxValueProperty = new dependencyObservable.Property(
        "maxValue",
        "Rating",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onMaxValueRatingPropertyChanged
        )
    );

    constructor() {
        super();
        this.MaxValue = 5;
        this.Value = 3;
        this.RatingSize = 40;
        this.LabelSize = 25;
        this.orientation = enums.Orientation.horizontal;
    }

    public set Value(value: number) {
        this._setValue(Rating.valueProperty, value);
    }

    public get Value() {
        return this._getValue(Rating.valueProperty);
    }

    public set LabelSize(value: number) {
        this._setValue(Rating.labelSizeProperty, value);
    }

    public get LabelSize() {
        return this._getValue(Rating.labelSizeProperty);
    }

    public set RatingSize(value: number) {
        this._setValue(Rating.ratingSizeProperty, value);
    }

    public get RatingSize() {
        return this._getValue(Rating.ratingSizeProperty);
    }

    public set MaxValue(value: number) {
        this._setValue(Rating.maxValueProperty, value);
    }

    public get MaxValue() {
        return this._getValue(Rating.maxValueProperty);
    }

    public set label(value: string) {
        this._setValue(Rating.labelProperty, value);
    }

    public get label() {
        return this._getValue(Rating.labelProperty);
    }

    public setFields() {
        this.removeChildren()
        for (var i = 0, imax = this.MaxValue; i < imax; i++) {
            var labelAdd = new label.Label();
            labelAdd.style.fontFamily = "FontAwesome";
            labelAdd.text = convertKeyHex(i < this.Value ? key.fa_star : key.fa_star_o);
            labelAdd.fontSize = this.RatingSize;
            labelAdd.bindingContext = i+1;
            labelAdd.observe(gestures.GestureTypes.tap, (args: gestures.GestureEventData) => {
                this.Value = args.view.bindingContext;
            });
            this.addChild(labelAdd);
        }
        var labelAdd = new label.Label();
        labelAdd.fontSize = this.LabelSize;
        labelAdd.text = this.label;
        labelAdd.observe(gestures.GestureTypes.tap, (args: gestures.GestureEventData) => {
            this.Value = 0;
        });
        this.addChild(labelAdd);
    }
}

function onCheckedCheckImagePropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var radio = <CheckImage>data.object;
    radio.setFields();
}

export class CheckImage extends label.Label {

    public static checkedProperty = new dependencyObservable.Property(
        "checked",
        "CheckImage",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onCheckedCheckImagePropertyChanged
        )
    );

    constructor() {
        super();
        this.textWrap = true;
        this.style.fontFamily = "FontAwesome";
        this.style.backgroundImage = "~/res/drawingshigh/ex0001.jpg";
        this.style.backgroundRepeat = enums.BackgroundRepeat.noRepeat;
        this.style.backgroundSize ="100% 100%";
        this.textAlignment = enums.TextAlignment.center;
        this.horizontalAlignment = enums.HorizontalAlignment.center;
        this.verticalAlignment = enums.VerticalAlignment.center;
        this.style.fontSize = 150;
        this.style.width = 164;
        this.style.height = 200;
        this.style.padding = "1";
        this.style.margin = "1";
        this.style.color = new color.Color("Green");

        this.observe(gestures.GestureTypes.tap, (args: gestures.GestureEventData) => {
            this.checked = !this.checked;
        });
    }

    public set checked(value: boolean) {
        this._setValue(CheckImage.checkedProperty, value);
    }

    public get checked() {
        return this._getValue(CheckImage.checkedProperty);
    }

    public setFields() {
        this.text = this.checked ? convertKeyHex(key.fa_check) : "";
    }
}

function onLabelButtonPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Button>data.object;
    button.setFields();
}

function onIconButtonPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Button>data.object;
    button.setFields();
}

function onIconRightButtonPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Button>data.object;
    button.setFields();
}

function onIconColorButtonPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Button>data.object;
    button.setFields();
}

export class Button extends button.Button {

    public static labelProperty = new dependencyObservable.Property(
        "label",
        "Button",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelButtonPropertyChanged
        )
    );

    public static iconProperty = new dependencyObservable.Property(
        "icon",
        "Button",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconButtonPropertyChanged
        )
    );

    public static iconRightProperty = new dependencyObservable.Property(
        "iconRight",
        "Button",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconRightButtonPropertyChanged
        )
    );

    public static iconColorProperty = new dependencyObservable.Property(
        "iconColor",
        "Button",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconColorButtonPropertyChanged
        )
    );

    public set icon(value: key) {
        this._setValue(Button.iconProperty, value);
    }

    public get icon() {
        return this._getValue(Button.iconProperty);
    }

    public set iconRight(value: boolean) {
        this._setValue(Button.iconRightProperty, value);
    }

    public get iconRight() {
        return this._getValue(Button.iconRightProperty);
    }

    public set iconColor(value: string) {
        this._setValue(Button.iconColorProperty,value);
    }

    public get iconColor() {
        return this._getValue(Button.iconColorProperty);
    }

    public set label(value: string) {
        this._setValue(Button.labelProperty, value);
    }

    public get label() {
        return this._getValue(Button.labelProperty);
    }

    constructor() {
        super();
        this.style.fontFamily = "FontAwesome";
        this.iconColor = "Red";
    }

    public setFields() {
        var spanAdd1 = new span.Span();
        spanAdd1.text = convertKeyHex(this.icon);
        spanAdd1.foregroundColor = new color.Color(this.iconColor);

        var spanAdd2 = new span.Span();
        spanAdd2.text = this.label;

        var textAdd = new formattedString.FormattedString();

        if (this.iconRight) {
            spanAdd2.text = spanAdd2.text + " ";
            textAdd.spans.push(spanAdd2);
            textAdd.spans.push(spanAdd1);
        } else {
            spanAdd2.text = " "+spanAdd2.text;
            textAdd.spans.push(spanAdd1);
            textAdd.spans.push(spanAdd2);
        }

        this.formattedText = textAdd;
    }
}

function onLabelLabelPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Label>data.object;
    button.setFields();
}

function onIconLabelPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Label>data.object;
    button.setFields();
}

function onIconRightLabelPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Label>data.object;
    button.setFields();
}

function onIconColorLabelPropertyChanged(data: dependencyObservable.PropertyChangeData) {
    var button = <Label>data.object;
    button.setFields();
}

export class Label extends label.Label {

    public static labelProperty = new dependencyObservable.Property(
        "label",
        "Label",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onLabelLabelPropertyChanged
        )
    );

    public static iconProperty = new dependencyObservable.Property(
        "icon",
        "Label",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconLabelPropertyChanged
        )
    );

    public static iconRightProperty = new dependencyObservable.Property(
        "iconRight",
        "Label",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconRightLabelPropertyChanged
        )
    );

    public static iconColorProperty = new dependencyObservable.Property(
        "iconColor",
        "Label",
        new proxy.PropertyMetadata(
            undefined,
            dependencyObservable.PropertyMetadataSettings.None,
            onIconColorLabelPropertyChanged
        )
    );

    public set icon(value: key) {
        this._setValue(Label.iconProperty, value);
    }

    public get icon() {
        return this._getValue(Label.iconProperty);
    }

    public set iconRight(value: boolean) {
        this._setValue(Label.iconRightProperty, value);
    }

    public get iconRight() {
        return this._getValue(Label.iconRightProperty);
    }

    public set iconColor(value: color.Color) {
        this._setValue(Label.iconColorProperty, value);
    }

    public get iconColor() {
        return this._getValue(Label.iconColorProperty);
    }

    public set label(value: string) {
        this._setValue(Label.labelProperty, value);
    }

    public get label() {
        return this._getValue(Label.labelProperty);
    }

    constructor() {
        super();
        this.iconColor = new color.Color("White");
        this.textWrap = true;
        this.style.fontFamily = "FontAwesome";
    }

    public setFields() {
        var spanAdd1 = new span.Span();
        spanAdd1.text = convertKeyHex(this.icon);
        spanAdd1.foregroundColor = this.iconColor;
        spanAdd1.fontSize = 50;

        var spanAdd2 = new span.Span();
        spanAdd2.text = this.label;

        var textAdd = new formattedString.FormattedString();

        if (this.iconRight) {
            textAdd.spans.push(spanAdd2);
            textAdd.spans.push(spanAdd1);
        } else {
            textAdd.spans.push(spanAdd1);
            textAdd.spans.push(spanAdd2);
        }

        this.formattedText = textAdd;
    }
}


export function convertKeyHex(value: key | string) {
    var valueOut = convertKey(value);
    return String.fromCharCode(parseInt(valueOut, 16));
}

export enum key {
    fa_500px,
    fa_adjust,
    fa_adn,
    fa_align_center,
    fa_align_justify,
    fa_align_left,
    fa_align_right,
    fa_amazon,
    fa_ambulance,
    fa_anchor,
    fa_android,
    fa_angellist,
    fa_angle_double_down,
    fa_angle_double_left,
    fa_angle_double_right,
    fa_angle_double_up,
    fa_angle_down,
    fa_angle_left,
    fa_angle_right,
    fa_angle_up,
    fa_apple,
    fa_archive,
    fa_area_chart,
    fa_arrow_circle_down,
    fa_arrow_circle_left,
    fa_arrow_circle_o_down,
    fa_arrow_circle_o_left,
    fa_arrow_circle_o_right,
    fa_arrow_circle_o_up,
    fa_arrow_circle_right,
    fa_arrow_circle_up,
    fa_arrow_down,
    fa_arrow_left,
    fa_arrow_right,
    fa_arrow_up,
    fa_arrows,
    fa_arrows_alt,
    fa_arrows_h,
    fa_arrows_v,
    fa_asterisk,
    fa_at,
    fa_automobile,
    fa_backward,
    fa_balance_scale,
    fa_ban,
    fa_bank,
    fa_bar_chart,
    fa_bar_chart_o,
    fa_barcode,
    fa_bars,
    fa_battery_0,
    fa_battery_1,
    fa_battery_2,
    fa_battery_3,
    fa_battery_4,
    fa_battery_empty,
    fa_battery_full,
    fa_battery_half,
    fa_battery_quarter,
    fa_battery_three_quarters,
    fa_bed,
    fa_beer,
    fa_behance,
    fa_behance_square,
    fa_bell,
    fa_bell_o,
    fa_bell_slash,
    fa_bell_slash_o,
    fa_bicycle,
    fa_binoculars,
    fa_birthday_cake,
    fa_bitbucket,
    fa_bitbucket_square,
    fa_bitcoin,
    fa_black_tie,
    fa_bold,
    fa_bolt,
    fa_bomb,
    fa_book,
    fa_bookmark,
    fa_bookmark_o,
    fa_briefcase,
    fa_btc,
    fa_bug,
    fa_building,
    fa_building_o,
    fa_bullhorn,
    fa_bullseye,
    fa_bus,
    fa_buysellads,
    fa_cab,
    fa_calculator,
    fa_calendar,
    fa_calendar_check_o,
    fa_calendar_minus_o,
    fa_calendar_o,
    fa_calendar_plus_o,
    fa_calendar_times_o,
    fa_camera,
    fa_camera_retro,
    fa_car,
    fa_caret_down,
    fa_caret_left,
    fa_caret_right,
    fa_caret_square_o_down,
    fa_caret_square_o_left,
    fa_caret_square_o_right,
    fa_caret_square_o_up,
    fa_caret_up,
    fa_cart_arrow_down,
    fa_cart_plus,
    fa_cc,
    fa_cc_amex,
    fa_cc_diners_club,
    fa_cc_discover,
    fa_cc_jcb,
    fa_cc_mastercard,
    fa_cc_paypal,
    fa_cc_stripe,
    fa_cc_visa,
    fa_certificate,
    fa_chain,
    fa_chain_broken,
    fa_check,
    fa_check_circle,
    fa_check_circle_o,
    fa_check_square,
    fa_check_square_o,
    fa_chevron_circle_down,
    fa_chevron_circle_left,
    fa_chevron_circle_right,
    fa_chevron_circle_up,
    fa_chevron_down,
    fa_chevron_left,
    fa_chevron_right,
    fa_chevron_up,
    fa_child,
    fa_chrome,
    fa_circle,
    fa_circle_o,
    fa_circle_o_notch,
    fa_circle_thin,
    fa_clipboard,
    fa_clock_o,
    fa_clone,
    fa_close,
    fa_cloud,
    fa_cloud_download,
    fa_cloud_upload,
    fa_cny,
    fa_code,
    fa_code_fork,
    fa_codepen,
    fa_coffee,
    fa_cog,
    fa_cogs,
    fa_columns,
    fa_comment,
    fa_comment_o,
    fa_commenting,
    fa_commenting_o,
    fa_comments,
    fa_comments_o,
    fa_compass,
    fa_compress,
    fa_connectdevelop,
    fa_contao,
    fa_copy,
    fa_copyright,
    fa_creative_commons,
    fa_credit_card,
    fa_crop,
    fa_crosshairs,
    fa_css3,
    fa_cube,
    fa_cubes,
    fa_cut,
    fa_cutlery,
    fa_dashboard,
    fa_dashcube,
    fa_database,
    fa_dedent,
    fa_delicious,
    fa_desktop,
    fa_deviantart,
    fa_diamond,
    fa_digg,
    fa_dollar,
    fa_dot_circle_o,
    fa_download,
    fa_dribbble,
    fa_dropbox,
    fa_drupal,
    fa_edit,
    fa_eject,
    fa_ellipsis_h,
    fa_ellipsis_v,
    fa_empire,
    fa_envelope,
    fa_envelope_o,
    fa_envelope_square,
    fa_eraser,
    fa_eur,
    fa_euro,
    fa_exchange,
    fa_exclamation,
    fa_exclamation_circle,
    fa_exclamation_triangle,
    fa_expand,
    fa_expeditedssl,
    fa_external_link,
    fa_external_link_square,
    fa_eye,
    fa_eye_slash,
    fa_eyedropper,
    fa_facebook,
    fa_facebook_f,
    fa_facebook_official,
    fa_facebook_square,
    fa_fast_backward,
    fa_fast_forward,
    fa_fax,
    fa_feed,
    fa_female,
    fa_fighter_jet,
    fa_file,
    fa_file_archive_o,
    fa_file_audio_o,
    fa_file_code_o,
    fa_file_excel_o,
    fa_file_image_o,
    fa_file_movie_o,
    fa_file_o,
    fa_file_pdf_o,
    fa_file_photo_o,
    fa_file_picture_o,
    fa_file_powerpoint_o,
    fa_file_sound_o,
    fa_file_text,
    fa_file_text_o,
    fa_file_video_o,
    fa_file_word_o,
    fa_file_zip_o,
    fa_files_o,
    fa_film,
    fa_filter,
    fa_fire,
    fa_fire_extinguisher,
    fa_firefox,
    fa_flag,
    fa_flag_checkered,
    fa_flag_o,
    fa_flash,
    fa_flask,
    fa_flickr,
    fa_floppy_o,
    fa_folder,
    fa_folder_o,
    fa_folder_open,
    fa_folder_open_o,
    fa_font,
    fa_fonticons,
    fa_forumbee,
    fa_forward,
    fa_foursquare,
    fa_frown_o,
    fa_futbol_o,
    fa_gamepad,
    fa_gavel,
    fa_gbp,
    fa_ge,
    fa_gear,
    fa_gears,
    fa_genderless,
    fa_get_pocket,
    fa_gg,
    fa_gg_circle,
    fa_gift,
    fa_git,
    fa_git_square,
    fa_github,
    fa_github_alt,
    fa_github_square,
    fa_gittip,
    fa_glass,
    fa_globe,
    fa_google,
    fa_google_plus,
    fa_google_plus_square,
    fa_google_wallet,
    fa_graduation_cap,
    fa_gratipay,
    fa_group,
    fa_h_square,
    fa_hacker_news,
    fa_hand_grab_o,
    fa_hand_lizard_o,
    fa_hand_o_down,
    fa_hand_o_left,
    fa_hand_o_right,
    fa_hand_o_up,
    fa_hand_paper_o,
    fa_hand_peace_o,
    fa_hand_pointer_o,
    fa_hand_rock_o,
    fa_hand_scissors_o,
    fa_hand_spock_o,
    fa_hand_stop_o,
    fa_hdd_o,
    fa_header,
    fa_headphones,
    fa_heart,
    fa_heart_o,
    fa_heartbeat,
    fa_history,
    fa_home,
    fa_hospital_o,
    fa_hotel,
    fa_hourglass,
    fa_hourglass_1,
    fa_hourglass_2,
    fa_hourglass_3,
    fa_hourglass_end,
    fa_hourglass_half,
    fa_hourglass_o,
    fa_hourglass_start,
    fa_houzz,
    fa_html5,
    fa_i_cursor,
    fa_ils,
    fa_image,
    fa_inbox,
    fa_indent,
    fa_industry,
    fa_info,
    fa_info_circle,
    fa_inr,
    fa_instagram,
    fa_institution,
    fa_internet_explorer,
    fa_intersex,
    fa_ioxhost,
    fa_italic,
    fa_joomla,
    fa_jpy,
    fa_jsfiddle,
    fa_key,
    fa_keyboard_o,
    fa_krw,
    fa_language,
    fa_laptop,
    fa_lastfm,
    fa_lastfm_square,
    fa_leaf,
    fa_leanpub,
    fa_legal,
    fa_lemon_o,
    fa_level_down,
    fa_level_up,
    fa_life_bouy,
    fa_life_buoy,
    fa_life_ring,
    fa_life_saver,
    fa_lightbulb_o,
    fa_line_chart,
    fa_link,
    fa_linkedin,
    fa_linkedin_square,
    fa_linux,
    fa_list,
    fa_list_alt,
    fa_list_ol,
    fa_list_ul,
    fa_location_arrow,
    fa_lock,
    fa_long_arrow_down,
    fa_long_arrow_left,
    fa_long_arrow_right,
    fa_long_arrow_up,
    fa_magic,
    fa_magnet,
    fa_mail_forward,
    fa_mail_reply,
    fa_mail_reply_all,
    fa_male,
    fa_map,
    fa_map_marker,
    fa_map_o,
    fa_map_pin,
    fa_map_signs,
    fa_mars,
    fa_mars_double,
    fa_mars_stroke,
    fa_mars_stroke_h,
    fa_mars_stroke_v,
    fa_maxcdn,
    fa_meanpath,
    fa_medium,
    fa_medkit,
    fa_meh_o,
    fa_mercury,
    fa_microphone,
    fa_microphone_slash,
    fa_minus,
    fa_minus_circle,
    fa_minus_square,
    fa_minus_square_o,
    fa_mobile,
    fa_mobile_phone,
    fa_money,
    fa_moon_o,
    fa_mortar_board,
    fa_motorcycle,
    fa_mouse_pointer,
    fa_music,
    fa_navicon,
    fa_neuter,
    fa_newspaper_o,
    fa_object_group,
    fa_object_ungroup,
    fa_odnoklassniki,
    fa_odnoklassniki_square,
    fa_opencart,
    fa_openid,
    fa_opera,
    fa_optin_monster,
    fa_outdent,
    fa_pagelines,
    fa_paint_brush,
    fa_paper_plane,
    fa_paper_plane_o,
    fa_paperclip,
    fa_paragraph,
    fa_paste,
    fa_pause,
    fa_paw,
    fa_paypal,
    fa_pencil,
    fa_pencil_square,
    fa_pencil_square_o,
    fa_phone,
    fa_phone_square,
    fa_photo,
    fa_picture_o,
    fa_pie_chart,
    fa_pied_piper,
    fa_pied_piper_alt,
    fa_pinterest,
    fa_pinterest_p,
    fa_pinterest_square,
    fa_plane,
    fa_play,
    fa_play_circle,
    fa_play_circle_o,
    fa_plug,
    fa_plus,
    fa_plus_circle,
    fa_plus_square,
    fa_plus_square_o,
    fa_power_off,
    fa_print,
    fa_puzzle_piece,
    fa_qq,
    fa_qrcode,
    fa_question,
    fa_question_circle,
    fa_quote_left,
    fa_quote_right,
    fa_ra,
    fa_random,
    fa_rebel,
    fa_recycle,
    fa_reddit,
    fa_reddit_square,
    fa_refresh,
    fa_registered,
    fa_remove,
    fa_renren,
    fa_reorder,
    fa_repeat,
    fa_reply,
    fa_reply_all,
    fa_retweet,
    fa_rmb,
    fa_road,
    fa_rocket,
    fa_rotate_left,
    fa_rotate_right,
    fa_rouble,
    fa_rss,
    fa_rss_square,
    fa_rub,
    fa_ruble,
    fa_rupee,
    fa_safari,
    fa_save,
    fa_scissors,
    fa_search,
    fa_search_minus,
    fa_search_plus,
    fa_sellsy,
    fa_send,
    fa_send_o,
    fa_server,
    fa_share,
    fa_share_alt,
    fa_share_alt_square,
    fa_share_square,
    fa_share_square_o,
    fa_shekel,
    fa_sheqel,
    fa_shield,
    fa_ship,
    fa_shirtsinbulk,
    fa_shopping_cart,
    fa_sign_in,
    fa_sign_out,
    fa_signal,
    fa_simplybuilt,
    fa_sitemap,
    fa_skyatlas,
    fa_skype,
    fa_slack,
    fa_sliders,
    fa_slideshare,
    fa_smile_o,
    fa_soccer_ball_o,
    fa_sort,
    fa_sort_alpha_asc,
    fa_sort_alpha_desc,
    fa_sort_amount_asc,
    fa_sort_amount_desc,
    fa_sort_asc,
    fa_sort_desc,
    fa_sort_down,
    fa_sort_numeric_asc,
    fa_sort_numeric_desc,
    fa_sort_up,
    fa_soundcloud,
    fa_space_shuttle,
    fa_spinner,
    fa_spoon,
    fa_spotify,
    fa_square,
    fa_square_o,
    fa_stack_exchange,
    fa_stack_overflow,
    fa_star,
    fa_star_half,
    fa_star_half_empty,
    fa_star_half_full,
    fa_star_half_o,
    fa_star_o,
    fa_steam,
    fa_steam_square,
    fa_step_backward,
    fa_step_forward,
    fa_stethoscope,
    fa_sticky_note,
    fa_sticky_note_o,
    fa_stop,
    fa_street_view,
    fa_strikethrough,
    fa_stumbleupon,
    fa_stumbleupon_circle,
    fa_subscript,
    fa_subway,
    fa_suitcase,
    fa_sun_o,
    fa_superscript,
    fa_support,
    fa_table,
    fa_tablet,
    fa_tachometer,
    fa_tag,
    fa_tags,
    fa_tasks,
    fa_taxi,
    fa_television,
    fa_tencent_weibo,
    fa_terminal,
    fa_text_height,
    fa_text_width,
    fa_th,
    fa_th_large,
    fa_th_list,
    fa_thumb_tack,
    fa_thumbs_down,
    fa_thumbs_o_down,
    fa_thumbs_o_up,
    fa_thumbs_up,
    fa_ticket,
    fa_times,
    fa_times_circle,
    fa_times_circle_o,
    fa_tint,
    fa_toggle_down,
    fa_toggle_left,
    fa_toggle_off,
    fa_toggle_on,
    fa_toggle_right,
    fa_toggle_up,
    fa_trademark,
    fa_train,
    fa_transgender,
    fa_transgender_alt,
    fa_trash,
    fa_trash_o,
    fa_tree,
    fa_trello,
    fa_tripadvisor,
    fa_trophy,
    fa_truck,
    fa_try,
    fa_tty,
    fa_tumblr,
    fa_tumblr_square,
    fa_turkish_lira,
    fa_tv,
    fa_twitch,
    fa_twitter,
    fa_twitter_square,
    fa_umbrella,
    fa_underline,
    fa_undo,
    fa_university,
    fa_unlink,
    fa_unlock,
    fa_unlock_alt,
    fa_unsorted,
    fa_upload,
    fa_usd,
    fa_user,
    fa_user_md,
    fa_user_plus,
    fa_user_secret,
    fa_user_times,
    fa_users,
    fa_venus,
    fa_venus_double,
    fa_venus_mars,
    fa_viacoin,
    fa_video_camera,
    fa_vimeo,
    fa_vimeo_square,
    fa_vine,
    fa_vk,
    fa_volume_down,
    fa_volume_off,
    fa_volume_up,
    fa_warning,
    fa_wechat,
    fa_weibo,
    fa_weixin,
    fa_whatsapp,
    fa_wheelchair,
    fa_wifi,
    fa_wikipedia_w,
    fa_windows,
    fa_won,
    fa_wordpress,
    fa_wrench,
    fa_xing,
    fa_xing_square,
    fa_y_combinator,
    fa_y_combinator_square,
    fa_yahoo,
    fa_yc,
    fa_yc_square,
    fa_yelp,
    fa_yen,
    fa_youtube,
    fa_youtube_play,
    fa_youtube_square,
};

export function convertKey(valueText: string | key): string {

    var value: key;
    if (typeof valueText == "string") {
        value = key[valueText];
    } else {
        value = <key>valueText;
    }

    switch (value) {
        case key.fa_500px:
            return 'f26e';
        case key.fa_adjust:
            return 'f042';
        case key.fa_adn:
            return 'f170';
        case key.fa_align_center:
            return 'f037';
        case key.fa_align_justify:
            return 'f039';
        case key.fa_align_left:
            return 'f036';
        case key.fa_align_right:
            return 'f038';
        case key.fa_amazon:
            return 'f270';
        case key.fa_ambulance:
            return 'f0f9';
        case key.fa_anchor:
            return 'f13d';
        case key.fa_android:
            return 'f17b';
        case key.fa_angellist:
            return 'f209';
        case key.fa_angle_double_down:
            return 'f103';
        case key.fa_angle_double_left:
            return 'f100';
        case key.fa_angle_double_right:
            return 'f101';
        case key.fa_angle_double_up:
            return 'f102';
        case key.fa_angle_down:
            return 'f107';
        case key.fa_angle_left:
            return 'f104';
        case key.fa_angle_right:
            return 'f105';
        case key.fa_angle_up:
            return 'f106';
        case key.fa_apple:
            return 'f179';
        case key.fa_archive:
            return 'f187';
        case key.fa_area_chart:
            return 'f1fe';
        case key.fa_arrow_circle_down:
            return 'f0ab';
        case key.fa_arrow_circle_left:
            return 'f0a8';
        case key.fa_arrow_circle_o_down:
            return 'f01a';
        case key.fa_arrow_circle_o_left:
            return 'f190';
        case key.fa_arrow_circle_o_right:
            return 'f18e';
        case key.fa_arrow_circle_o_up:
            return 'f01b';
        case key.fa_arrow_circle_right:
            return 'f0a9';
        case key.fa_arrow_circle_up:
            return 'f0aa';
        case key.fa_arrow_down:
            return 'f063';
        case key.fa_arrow_left:
            return 'f060';
        case key.fa_arrow_right:
            return 'f061';
        case key.fa_arrow_up:
            return 'f062';
        case key.fa_arrows:
            return 'f047';
        case key.fa_arrows_alt:
            return 'f0b2';
        case key.fa_arrows_h:
            return 'f07e';
        case key.fa_arrows_v:
            return 'f07d';
        case key.fa_asterisk:
            return 'f069';
        case key.fa_at:
            return 'f1fa';
        case key.fa_automobile:
            return 'f1b9';
        case key.fa_backward:
            return 'f04a';
        case key.fa_balance_scale:
            return 'f24e';
        case key.fa_ban:
            return 'f05e';
        case key.fa_bank:
            return 'f19c';
        case key.fa_bar_chart:
            return 'f080';
        case key.fa_bar_chart_o:
            return 'f080';
        case key.fa_barcode:
            return 'f02a';
        case key.fa_bars:
            return 'f0c9';
        case key.fa_battery_0:
            return 'f244';
        case key.fa_battery_1:
            return 'f243';
        case key.fa_battery_2:
            return 'f242';
        case key.fa_battery_3:
            return 'f241';
        case key.fa_battery_4:
            return 'f240';
        case key.fa_battery_empty:
            return 'f244';
        case key.fa_battery_full:
            return 'f240';
        case key.fa_battery_half:
            return 'f242';
        case key.fa_battery_quarter:
            return 'f243';
        case key.fa_battery_three_quarters:
            return 'f241';
        case key.fa_bed:
            return 'f236';
        case key.fa_beer:
            return 'f0fc';
        case key.fa_behance:
            return 'f1b4';
        case key.fa_behance_square:
            return 'f1b5';
        case key.fa_bell:
            return 'f0f3';
        case key.fa_bell_o:
            return 'f0a2';
        case key.fa_bell_slash:
            return 'f1f6';
        case key.fa_bell_slash_o:
            return 'f1f7';
        case key.fa_bicycle:
            return 'f206';
        case key.fa_binoculars:
            return 'f1e5';
        case key.fa_birthday_cake:
            return 'f1fd';
        case key.fa_bitbucket:
            return 'f171';
        case key.fa_bitbucket_square:
            return 'f172';
        case key.fa_bitcoin:
            return 'f15a';
        case key.fa_black_tie:
            return 'f27e';
        case key.fa_bold:
            return 'f032';
        case key.fa_bolt:
            return 'f0e7';
        case key.fa_bomb:
            return 'f1e2';
        case key.fa_book:
            return 'f02d';
        case key.fa_bookmark:
            return 'f02e';
        case key.fa_bookmark_o:
            return 'f097';
        case key.fa_briefcase:
            return 'f0b1';
        case key.fa_btc:
            return 'f15a';
        case key.fa_bug:
            return 'f188';
        case key.fa_building:
            return 'f1ad';
        case key.fa_building_o:
            return 'f0f7';
        case key.fa_bullhorn:
            return 'f0a1';
        case key.fa_bullseye:
            return 'f140';
        case key.fa_bus:
            return 'f207';
        case key.fa_buysellads:
            return 'f20d';
        case key.fa_cab:
            return 'f1ba';
        case key.fa_calculator:
            return 'f1ec';
        case key.fa_calendar:
            return 'f073';
        case key.fa_calendar_check_o:
            return 'f274';
        case key.fa_calendar_minus_o:
            return 'f272';
        case key.fa_calendar_o:
            return 'f133';
        case key.fa_calendar_plus_o:
            return 'f271';
        case key.fa_calendar_times_o:
            return 'f273';
        case key.fa_camera:
            return 'f030';
        case key.fa_camera_retro:
            return 'f083';
        case key.fa_car:
            return 'f1b9';
        case key.fa_caret_down:
            return 'f0d7';
        case key.fa_caret_left:
            return 'f0d9';
        case key.fa_caret_right:
            return 'f0da';
        case key.fa_caret_square_o_down:
            return 'f150';
        case key.fa_caret_square_o_left:
            return 'f191';
        case key.fa_caret_square_o_right:
            return 'f152';
        case key.fa_caret_square_o_up:
            return 'f151';
        case key.fa_caret_up:
            return 'f0d8';
        case key.fa_cart_arrow_down:
            return 'f218';
        case key.fa_cart_plus:
            return 'f217';
        case key.fa_cc:
            return 'f20a';
        case key.fa_cc_amex:
            return 'f1f3';
        case key.fa_cc_diners_club:
            return 'f24c';
        case key.fa_cc_discover:
            return 'f1f2';
        case key.fa_cc_jcb:
            return 'f24b';
        case key.fa_cc_mastercard:
            return 'f1f1';
        case key.fa_cc_paypal:
            return 'f1f4';
        case key.fa_cc_stripe:
            return 'f1f5';
        case key.fa_cc_visa:
            return 'f1f0';
        case key.fa_certificate:
            return 'f0a3';
        case key.fa_chain:
            return 'f0c1';
        case key.fa_chain_broken:
            return 'f127';
        case key.fa_check:
            return 'f00c';
        case key.fa_check_circle:
            return 'f058';
        case key.fa_check_circle_o:
            return 'f05d';
        case key.fa_check_square:
            return 'f14a';
        case key.fa_check_square_o:
            return 'f046';
        case key.fa_chevron_circle_down:
            return 'f13a';
        case key.fa_chevron_circle_left:
            return 'f137';
        case key.fa_chevron_circle_right:
            return 'f138';
        case key.fa_chevron_circle_up:
            return 'f139';
        case key.fa_chevron_down:
            return 'f078';
        case key.fa_chevron_left:
            return 'f053';
        case key.fa_chevron_right:
            return 'f054';
        case key.fa_chevron_up:
            return 'f077';
        case key.fa_child:
            return 'f1ae';
        case key.fa_chrome:
            return 'f268';
        case key.fa_circle:
            return 'f111';
        case key.fa_circle_o:
            return 'f10c';
        case key.fa_circle_o_notch:
            return 'f1ce';
        case key.fa_circle_thin:
            return 'f1db';
        case key.fa_clipboard:
            return 'f0ea';
        case key.fa_clock_o:
            return 'f017';
        case key.fa_clone:
            return 'f24d';
        case key.fa_close:
            return 'f00d';
        case key.fa_cloud:
            return 'f0c2';
        case key.fa_cloud_download:
            return 'f0ed';
        case key.fa_cloud_upload:
            return 'f0ee';
        case key.fa_cny:
            return 'f157';
        case key.fa_code:
            return 'f121';
        case key.fa_code_fork:
            return 'f126';
        case key.fa_codepen:
            return 'f1cb';
        case key.fa_coffee:
            return 'f0f4';
        case key.fa_cog:
            return 'f013';
        case key.fa_cogs:
            return 'f085';
        case key.fa_columns:
            return 'f0db';
        case key.fa_comment:
            return 'f075';
        case key.fa_comment_o:
            return 'f0e5';
        case key.fa_commenting:
            return 'f27a';
        case key.fa_commenting_o:
            return 'f27b';
        case key.fa_comments:
            return 'f086';
        case key.fa_comments_o:
            return 'f0e6';
        case key.fa_compass:
            return 'f14e';
        case key.fa_compress:
            return 'f066';
        case key.fa_connectdevelop:
            return 'f20e';
        case key.fa_contao:
            return 'f26d';
        case key.fa_copy:
            return 'f0c5';
        case key.fa_copyright:
            return 'f1f9';
        case key.fa_creative_commons:
            return 'f25e';
        case key.fa_credit_card:
            return 'f09d';
        case key.fa_crop:
            return 'f125';
        case key.fa_crosshairs:
            return 'f05b';
        case key.fa_css3:
            return 'f13c';
        case key.fa_cube:
            return 'f1b2';
        case key.fa_cubes:
            return 'f1b3';
        case key.fa_cut:
            return 'f0c4';
        case key.fa_cutlery:
            return 'f0f5';
        case key.fa_dashboard:
            return 'f0e4';
        case key.fa_dashcube:
            return 'f210';
        case key.fa_database:
            return 'f1c0';
        case key.fa_dedent:
            return 'f03b';
        case key.fa_delicious:
            return 'f1a5';
        case key.fa_desktop:
            return 'f108';
        case key.fa_deviantart:
            return 'f1bd';
        case key.fa_diamond:
            return 'f219';
        case key.fa_digg:
            return 'f1a6';
        case key.fa_dollar:
            return 'f155';
        case key.fa_dot_circle_o:
            return 'f192';
        case key.fa_download:
            return 'f019';
        case key.fa_dribbble:
            return 'f17d';
        case key.fa_dropbox:
            return 'f16b';
        case key.fa_drupal:
            return 'f1a9';
        case key.fa_edit:
            return 'f044';
        case key.fa_eject:
            return 'f052';
        case key.fa_ellipsis_h:
            return 'f141';
        case key.fa_ellipsis_v:
            return 'f142';
        case key.fa_empire:
            return 'f1d1';
        case key.fa_envelope:
            return 'f0e0';
        case key.fa_envelope_o:
            return 'f003';
        case key.fa_envelope_square:
            return 'f199';
        case key.fa_eraser:
            return 'f12d';
        case key.fa_eur:
            return 'f153';
        case key.fa_euro:
            return 'f153';
        case key.fa_exchange:
            return 'f0ec';
        case key.fa_exclamation:
            return 'f12a';
        case key.fa_exclamation_circle:
            return 'f06a';
        case key.fa_exclamation_triangle:
            return 'f071';
        case key.fa_expand:
            return 'f065';
        case key.fa_expeditedssl:
            return 'f23e';
        case key.fa_external_link:
            return 'f08e';
        case key.fa_external_link_square:
            return 'f14c';
        case key.fa_eye:
            return 'f06e';
        case key.fa_eye_slash:
            return 'f070';
        case key.fa_eyedropper:
            return 'f1fb';
        case key.fa_facebook:
            return 'f09a';
        case key.fa_facebook_f:
            return 'f09a';
        case key.fa_facebook_official:
            return 'f230';
        case key.fa_facebook_square:
            return 'f082';
        case key.fa_fast_backward:
            return 'f049';
        case key.fa_fast_forward:
            return 'f050';
        case key.fa_fax:
            return 'f1ac';
        case key.fa_feed:
            return 'f09e';
        case key.fa_female:
            return 'f182';
        case key.fa_fighter_jet:
            return 'f0fb';
        case key.fa_file:
            return 'f15b';
        case key.fa_file_archive_o:
            return 'f1c6';
        case key.fa_file_audio_o:
            return 'f1c7';
        case key.fa_file_code_o:
            return 'f1c9';
        case key.fa_file_excel_o:
            return 'f1c3';
        case key.fa_file_image_o:
            return 'f1c5';
        case key.fa_file_movie_o:
            return 'f1c8';
        case key.fa_file_o:
            return 'f016';
        case key.fa_file_pdf_o:
            return 'f1c1';
        case key.fa_file_photo_o:
            return 'f1c5';
        case key.fa_file_picture_o:
            return 'f1c5';
        case key.fa_file_powerpoint_o:
            return 'f1c4';
        case key.fa_file_sound_o:
            return 'f1c7';
        case key.fa_file_text:
            return 'f15c';
        case key.fa_file_text_o:
            return 'f0f6';
        case key.fa_file_video_o:
            return 'f1c8';
        case key.fa_file_word_o:
            return 'f1c2';
        case key.fa_file_zip_o:
            return 'f1c6';
        case key.fa_files_o:
            return 'f0c5';
        case key.fa_film:
            return 'f008';
        case key.fa_filter:
            return 'f0b0';
        case key.fa_fire:
            return 'f06d';
        case key.fa_fire_extinguisher:
            return 'f134';
        case key.fa_firefox:
            return 'f269';
        case key.fa_flag:
            return 'f024';
        case key.fa_flag_checkered:
            return 'f11e';
        case key.fa_flag_o:
            return 'f11d';
        case key.fa_flash:
            return 'f0e7';
        case key.fa_flask:
            return 'f0c3';
        case key.fa_flickr:
            return 'f16e';
        case key.fa_floppy_o:
            return 'f0c7';
        case key.fa_folder:
            return 'f07b';
        case key.fa_folder_o:
            return 'f114';
        case key.fa_folder_open:
            return 'f07c';
        case key.fa_folder_open_o:
            return 'f115';
        case key.fa_font:
            return 'f031';
        case key.fa_fonticons:
            return 'f280';
        case key.fa_forumbee:
            return 'f211';
        case key.fa_forward:
            return 'f04e';
        case key.fa_foursquare:
            return 'f180';
        case key.fa_frown_o:
            return 'f119';
        case key.fa_futbol_o:
            return 'f1e3';
        case key.fa_gamepad:
            return 'f11b';
        case key.fa_gavel:
            return 'f0e3';
        case key.fa_gbp:
            return 'f154';
        case key.fa_ge:
            return 'f1d1';
        case key.fa_gear:
            return 'f013';
        case key.fa_gears:
            return 'f085';
        case key.fa_genderless:
            return 'f22d';
        case key.fa_get_pocket:
            return 'f265';
        case key.fa_gg:
            return 'f260';
        case key.fa_gg_circle:
            return 'f261';
        case key.fa_gift:
            return 'f06b';
        case key.fa_git:
            return 'f1d3';
        case key.fa_git_square:
            return 'f1d2';
        case key.fa_github:
            return 'f09b';
        case key.fa_github_alt:
            return 'f113';
        case key.fa_github_square:
            return 'f092';
        case key.fa_gittip:
            return 'f184';
        case key.fa_glass:
            return 'f000';
        case key.fa_globe:
            return 'f0ac';
        case key.fa_google:
            return 'f1a0';
        case key.fa_google_plus:
            return 'f0d5';
        case key.fa_google_plus_square:
            return 'f0d4';
        case key.fa_google_wallet:
            return 'f1ee';
        case key.fa_graduation_cap:
            return 'f19d';
        case key.fa_gratipay:
            return 'f184';
        case key.fa_group:
            return 'f0c0';
        case key.fa_h_square:
            return 'f0fd';
        case key.fa_hacker_news:
            return 'f1d4';
        case key.fa_hand_grab_o:
            return 'f255';
        case key.fa_hand_lizard_o:
            return 'f258';
        case key.fa_hand_o_down:
            return 'f0a7';
        case key.fa_hand_o_left:
            return 'f0a5';
        case key.fa_hand_o_right:
            return 'f0a4';
        case key.fa_hand_o_up:
            return 'f0a6';
        case key.fa_hand_paper_o:
            return 'f256';
        case key.fa_hand_peace_o:
            return 'f25b';
        case key.fa_hand_pointer_o:
            return 'f25a';
        case key.fa_hand_rock_o:
            return 'f255';
        case key.fa_hand_scissors_o:
            return 'f257';
        case key.fa_hand_spock_o:
            return 'f259';
        case key.fa_hand_stop_o:
            return 'f256';
        case key.fa_hdd_o:
            return 'f0a0';
        case key.fa_header:
            return 'f1dc';
        case key.fa_headphones:
            return 'f025';
        case key.fa_heart:
            return 'f004';
        case key.fa_heart_o:
            return 'f08a';
        case key.fa_heartbeat:
            return 'f21e';
        case key.fa_history:
            return 'f1da';
        case key.fa_home:
            return 'f015';
        case key.fa_hospital_o:
            return 'f0f8';
        case key.fa_hotel:
            return 'f236';
        case key.fa_hourglass:
            return 'f254';
        case key.fa_hourglass_1:
            return 'f251';
        case key.fa_hourglass_2:
            return 'f252';
        case key.fa_hourglass_3:
            return 'f253';
        case key.fa_hourglass_end:
            return 'f253';
        case key.fa_hourglass_half:
            return 'f252';
        case key.fa_hourglass_o:
            return 'f250';
        case key.fa_hourglass_start:
            return 'f251';
        case key.fa_houzz:
            return 'f27c';
        case key.fa_html5:
            return 'f13b';
        case key.fa_i_cursor:
            return 'f246';
        case key.fa_ils:
            return 'f20b';
        case key.fa_image:
            return 'f03e';
        case key.fa_inbox:
            return 'f01c';
        case key.fa_indent:
            return 'f03c';
        case key.fa_industry:
            return 'f275';
        case key.fa_info:
            return 'f129';
        case key.fa_info_circle:
            return 'f05a';
        case key.fa_inr:
            return 'f156';
        case key.fa_instagram:
            return 'f16d';
        case key.fa_institution:
            return 'f19c';
        case key.fa_internet_explorer:
            return 'f26b';
        case key.fa_intersex:
            return 'f224';
        case key.fa_ioxhost:
            return 'f208';
        case key.fa_italic:
            return 'f033';
        case key.fa_joomla:
            return 'f1aa';
        case key.fa_jpy:
            return 'f157';
        case key.fa_jsfiddle:
            return 'f1cc';
        case key.fa_key:
            return 'f084';
        case key.fa_keyboard_o:
            return 'f11c';
        case key.fa_krw:
            return 'f159';
        case key.fa_language:
            return 'f1ab';
        case key.fa_laptop:
            return 'f109';
        case key.fa_lastfm:
            return 'f202';
        case key.fa_lastfm_square:
            return 'f203';
        case key.fa_leaf:
            return 'f06c';
        case key.fa_leanpub:
            return 'f212';
        case key.fa_legal:
            return 'f0e3';
        case key.fa_lemon_o:
            return 'f094';
        case key.fa_level_down:
            return 'f149';
        case key.fa_level_up:
            return 'f148';
        case key.fa_life_bouy:
            return 'f1cd';
        case key.fa_life_buoy:
            return 'f1cd';
        case key.fa_life_ring:
            return 'f1cd';
        case key.fa_life_saver:
            return 'f1cd';
        case key.fa_lightbulb_o:
            return 'f0eb';
        case key.fa_line_chart:
            return 'f201';
        case key.fa_link:
            return 'f0c1';
        case key.fa_linkedin:
            return 'f0e1';
        case key.fa_linkedin_square:
            return 'f08c';
        case key.fa_linux:
            return 'f17c';
        case key.fa_list:
            return 'f03a';
        case key.fa_list_alt:
            return 'f022';
        case key.fa_list_ol:
            return 'f0cb';
        case key.fa_list_ul:
            return 'f0ca';
        case key.fa_location_arrow:
            return 'f124';
        case key.fa_lock:
            return 'f023';
        case key.fa_long_arrow_down:
            return 'f175';
        case key.fa_long_arrow_left:
            return 'f177';
        case key.fa_long_arrow_right:
            return 'f178';
        case key.fa_long_arrow_up:
            return 'f176';
        case key.fa_magic:
            return 'f0d0';
        case key.fa_magnet:
            return 'f076';
        case key.fa_mail_forward:
            return 'f064';
        case key.fa_mail_reply:
            return 'f112';
        case key.fa_mail_reply_all:
            return 'f122';
        case key.fa_male:
            return 'f183';
        case key.fa_map:
            return 'f279';
        case key.fa_map_marker:
            return 'f041';
        case key.fa_map_o:
            return 'f278';
        case key.fa_map_pin:
            return 'f276';
        case key.fa_map_signs:
            return 'f277';
        case key.fa_mars:
            return 'f222';
        case key.fa_mars_double:
            return 'f227';
        case key.fa_mars_stroke:
            return 'f229';
        case key.fa_mars_stroke_h:
            return 'f22b';
        case key.fa_mars_stroke_v:
            return 'f22a';
        case key.fa_maxcdn:
            return 'f136';
        case key.fa_meanpath:
            return 'f20c';
        case key.fa_medium:
            return 'f23a';
        case key.fa_medkit:
            return 'f0fa';
        case key.fa_meh_o:
            return 'f11a';
        case key.fa_mercury:
            return 'f223';
        case key.fa_microphone:
            return 'f130';
        case key.fa_microphone_slash:
            return 'f131';
        case key.fa_minus:
            return 'f068';
        case key.fa_minus_circle:
            return 'f056';
        case key.fa_minus_square:
            return 'f146';
        case key.fa_minus_square_o:
            return 'f147';
        case key.fa_mobile:
            return 'f10b';
        case key.fa_mobile_phone:
            return 'f10b';
        case key.fa_money:
            return 'f0d6';
        case key.fa_moon_o:
            return 'f186';
        case key.fa_mortar_board:
            return 'f19d';
        case key.fa_motorcycle:
            return 'f21c';
        case key.fa_mouse_pointer:
            return 'f245';
        case key.fa_music:
            return 'f001';
        case key.fa_navicon:
            return 'f0c9';
        case key.fa_neuter:
            return 'f22c';
        case key.fa_newspaper_o:
            return 'f1ea';
        case key.fa_object_group:
            return 'f247';
        case key.fa_object_ungroup:
            return 'f248';
        case key.fa_odnoklassniki:
            return 'f263';
        case key.fa_odnoklassniki_square:
            return 'f264';
        case key.fa_opencart:
            return 'f23d';
        case key.fa_openid:
            return 'f19b';
        case key.fa_opera:
            return 'f26a';
        case key.fa_optin_monster:
            return 'f23c';
        case key.fa_outdent:
            return 'f03b';
        case key.fa_pagelines:
            return 'f18c';
        case key.fa_paint_brush:
            return 'f1fc';
        case key.fa_paper_plane:
            return 'f1d8';
        case key.fa_paper_plane_o:
            return 'f1d9';
        case key.fa_paperclip:
            return 'f0c6';
        case key.fa_paragraph:
            return 'f1dd';
        case key.fa_paste:
            return 'f0ea';
        case key.fa_pause:
            return 'f04c';
        case key.fa_paw:
            return 'f1b0';
        case key.fa_paypal:
            return 'f1ed';
        case key.fa_pencil:
            return 'f040';
        case key.fa_pencil_square:
            return 'f14b';
        case key.fa_pencil_square_o:
            return 'f044';
        case key.fa_phone:
            return 'f095';
        case key.fa_phone_square:
            return 'f098';
        case key.fa_photo:
            return 'f03e';
        case key.fa_picture_o:
            return 'f03e';
        case key.fa_pie_chart:
            return 'f200';
        case key.fa_pied_piper:
            return 'f1a7';
        case key.fa_pied_piper_alt:
            return 'f1a8';
        case key.fa_pinterest:
            return 'f0d2';
        case key.fa_pinterest_p:
            return 'f231';
        case key.fa_pinterest_square:
            return 'f0d3';
        case key.fa_plane:
            return 'f072';
        case key.fa_play:
            return 'f04b';
        case key.fa_play_circle:
            return 'f144';
        case key.fa_play_circle_o:
            return 'f01d';
        case key.fa_plug:
            return 'f1e6';
        case key.fa_plus:
            return 'f067';
        case key.fa_plus_circle:
            return 'f055';
        case key.fa_plus_square:
            return 'f0fe';
        case key.fa_plus_square_o:
            return 'f196';
        case key.fa_power_off:
            return 'f011';
        case key.fa_print:
            return 'f02f';
        case key.fa_puzzle_piece:
            return 'f12e';
        case key.fa_qq:
            return 'f1d6';
        case key.fa_qrcode:
            return 'f029';
        case key.fa_question:
            return 'f128';
        case key.fa_question_circle:
            return 'f059';
        case key.fa_quote_left:
            return 'f10d';
        case key.fa_quote_right:
            return 'f10e';
        case key.fa_ra:
            return 'f1d0';
        case key.fa_random:
            return 'f074';
        case key.fa_rebel:
            return 'f1d0';
        case key.fa_recycle:
            return 'f1b8';
        case key.fa_reddit:
            return 'f1a1';
        case key.fa_reddit_square:
            return 'f1a2';
        case key.fa_refresh:
            return 'f021';
        case key.fa_registered:
            return 'f25d';
        case key.fa_remove:
            return 'f00d';
        case key.fa_renren:
            return 'f18b';
        case key.fa_reorder:
            return 'f0c9';
        case key.fa_repeat:
            return 'f01e';
        case key.fa_reply:
            return 'f112';
        case key.fa_reply_all:
            return 'f122';
        case key.fa_retweet:
            return 'f079';
        case key.fa_rmb:
            return 'f157';
        case key.fa_road:
            return 'f018';
        case key.fa_rocket:
            return 'f135';
        case key.fa_rotate_left:
            return 'f0e2';
        case key.fa_rotate_right:
            return 'f01e';
        case key.fa_rouble:
            return 'f158';
        case key.fa_rss:
            return 'f09e';
        case key.fa_rss_square:
            return 'f143';
        case key.fa_rub:
            return 'f158';
        case key.fa_ruble:
            return 'f158';
        case key.fa_rupee:
            return 'f156';
        case key.fa_safari:
            return 'f267';
        case key.fa_save:
            return 'f0c7';
        case key.fa_scissors:
            return 'f0c4';
        case key.fa_search:
            return 'f002';
        case key.fa_search_minus:
            return 'f010';
        case key.fa_search_plus:
            return 'f00e';
        case key.fa_sellsy:
            return 'f213';
        case key.fa_send:
            return 'f1d8';
        case key.fa_send_o:
            return 'f1d9';
        case key.fa_server:
            return 'f233';
        case key.fa_share:
            return 'f064';
        case key.fa_share_alt:
            return 'f1e0';
        case key.fa_share_alt_square:
            return 'f1e1';
        case key.fa_share_square:
            return 'f14d';
        case key.fa_share_square_o:
            return 'f045';
        case key.fa_shekel:
            return 'f20b';
        case key.fa_sheqel:
            return 'f20b';
        case key.fa_shield:
            return 'f132';
        case key.fa_ship:
            return 'f21a';
        case key.fa_shirtsinbulk:
            return 'f214';
        case key.fa_shopping_cart:
            return 'f07a';
        case key.fa_sign_in:
            return 'f090';
        case key.fa_sign_out:
            return 'f08b';
        case key.fa_signal:
            return 'f012';
        case key.fa_simplybuilt:
            return 'f215';
        case key.fa_sitemap:
            return 'f0e8';
        case key.fa_skyatlas:
            return 'f216';
        case key.fa_skype:
            return 'f17e';
        case key.fa_slack:
            return 'f198';
        case key.fa_sliders:
            return 'f1de';
        case key.fa_slideshare:
            return 'f1e7';
        case key.fa_smile_o:
            return 'f118';
        case key.fa_soccer_ball_o:
            return 'f1e3';
        case key.fa_sort:
            return 'f0dc';
        case key.fa_sort_alpha_asc:
            return 'f15d';
        case key.fa_sort_alpha_desc:
            return 'f15e';
        case key.fa_sort_amount_asc:
            return 'f160';
        case key.fa_sort_amount_desc:
            return 'f161';
        case key.fa_sort_asc:
            return 'f0de';
        case key.fa_sort_desc:
            return 'f0dd';
        case key.fa_sort_down:
            return 'f0dd';
        case key.fa_sort_numeric_asc:
            return 'f162';
        case key.fa_sort_numeric_desc:
            return 'f163';
        case key.fa_sort_up:
            return 'f0de';
        case key.fa_soundcloud:
            return 'f1be';
        case key.fa_space_shuttle:
            return 'f197';
        case key.fa_spinner:
            return 'f110';
        case key.fa_spoon:
            return 'f1b1';
        case key.fa_spotify:
            return 'f1bc';
        case key.fa_square:
            return 'f0c8';
        case key.fa_square_o:
            return 'f096';
        case key.fa_stack_exchange:
            return 'f18d';
        case key.fa_stack_overflow:
            return 'f16c';
        case key.fa_star:
            return 'f005';
        case key.fa_star_half:
            return 'f089';
        case key.fa_star_half_empty:
            return 'f123';
        case key.fa_star_half_full:
            return 'f123';
        case key.fa_star_half_o:
            return 'f123';
        case key.fa_star_o:
            return 'f006';
        case key.fa_steam:
            return 'f1b6';
        case key.fa_steam_square:
            return 'f1b7';
        case key.fa_step_backward:
            return 'f048';
        case key.fa_step_forward:
            return 'f051';
        case key.fa_stethoscope:
            return 'f0f1';
        case key.fa_sticky_note:
            return 'f249';
        case key.fa_sticky_note_o:
            return 'f24a';
        case key.fa_stop:
            return 'f04d';
        case key.fa_street_view:
            return 'f21d';
        case key.fa_strikethrough:
            return 'f0cc';
        case key.fa_stumbleupon:
            return 'f1a4';
        case key.fa_stumbleupon_circle:
            return 'f1a3';
        case key.fa_subscript:
            return 'f12c';
        case key.fa_subway:
            return 'f239';
        case key.fa_suitcase:
            return 'f0f2';
        case key.fa_sun_o:
            return 'f185';
        case key.fa_superscript:
            return 'f12b';
        case key.fa_support:
            return 'f1cd';
        case key.fa_table:
            return 'f0ce';
        case key.fa_tablet:
            return 'f10a';
        case key.fa_tachometer:
            return 'f0e4';
        case key.fa_tag:
            return 'f02b';
        case key.fa_tags:
            return 'f02c';
        case key.fa_tasks:
            return 'f0ae';
        case key.fa_taxi:
            return 'f1ba';
        case key.fa_television:
            return 'f26c';
        case key.fa_tencent_weibo:
            return 'f1d5';
        case key.fa_terminal:
            return 'f120';
        case key.fa_text_height:
            return 'f034';
        case key.fa_text_width:
            return 'f035';
        case key.fa_th:
            return 'f00a';
        case key.fa_th_large:
            return 'f009';
        case key.fa_th_list:
            return 'f00b';
        case key.fa_thumb_tack:
            return 'f08d';
        case key.fa_thumbs_down:
            return 'f165';
        case key.fa_thumbs_o_down:
            return 'f088';
        case key.fa_thumbs_o_up:
            return 'f087';
        case key.fa_thumbs_up:
            return 'f164';
        case key.fa_ticket:
            return 'f145';
        case key.fa_times:
            return 'f00d';
        case key.fa_times_circle:
            return 'f057';
        case key.fa_times_circle_o:
            return 'f05c';
        case key.fa_tint:
            return 'f043';
        case key.fa_toggle_down:
            return 'f150';
        case key.fa_toggle_left:
            return 'f191';
        case key.fa_toggle_off:
            return 'f204';
        case key.fa_toggle_on:
            return 'f205';
        case key.fa_toggle_right:
            return 'f152';
        case key.fa_toggle_up:
            return 'f151';
        case key.fa_trademark:
            return 'f25c';
        case key.fa_train:
            return 'f238';
        case key.fa_transgender:
            return 'f224';
        case key.fa_transgender_alt:
            return 'f225';
        case key.fa_trash:
            return 'f1f8';
        case key.fa_trash_o:
            return 'f014';
        case key.fa_tree:
            return 'f1bb';
        case key.fa_trello:
            return 'f181';
        case key.fa_tripadvisor:
            return 'f262';
        case key.fa_trophy:
            return 'f091';
        case key.fa_truck:
            return 'f0d1';
        case key.fa_try:
            return 'f195';
        case key.fa_tty:
            return 'f1e4';
        case key.fa_tumblr:
            return 'f173';
        case key.fa_tumblr_square:
            return 'f174';
        case key.fa_turkish_lira:
            return 'f195';
        case key.fa_tv:
            return 'f26c';
        case key.fa_twitch:
            return 'f1e8';
        case key.fa_twitter:
            return 'f099';
        case key.fa_twitter_square:
            return 'f081';
        case key.fa_umbrella:
            return 'f0e9';
        case key.fa_underline:
            return 'f0cd';
        case key.fa_undo:
            return 'f0e2';
        case key.fa_university:
            return 'f19c';
        case key.fa_unlink:
            return 'f127';
        case key.fa_unlock:
            return 'f09c';
        case key.fa_unlock_alt:
            return 'f13e';
        case key.fa_unsorted:
            return 'f0dc';
        case key.fa_upload:
            return 'f093';
        case key.fa_usd:
            return 'f155';
        case key.fa_user:
            return 'f007';
        case key.fa_user_md:
            return 'f0f0';
        case key.fa_user_plus:
            return 'f234';
        case key.fa_user_secret:
            return 'f21b';
        case key.fa_user_times:
            return 'f235';
        case key.fa_users:
            return 'f0c0';
        case key.fa_venus:
            return 'f221';
        case key.fa_venus_double:
            return 'f226';
        case key.fa_venus_mars:
            return 'f228';
        case key.fa_viacoin:
            return 'f237';
        case key.fa_video_camera:
            return 'f03d';
        case key.fa_vimeo:
            return 'f27d';
        case key.fa_vimeo_square:
            return 'f194';
        case key.fa_vine:
            return 'f1ca';
        case key.fa_vk:
            return 'f189';
        case key.fa_volume_down:
            return 'f027';
        case key.fa_volume_off:
            return 'f026';
        case key.fa_volume_up:
            return 'f028';
        case key.fa_warning:
            return 'f071';
        case key.fa_wechat:
            return 'f1d7';
        case key.fa_weibo:
            return 'f18a';
        case key.fa_weixin:
            return 'f1d7';
        case key.fa_whatsapp:
            return 'f232';
        case key.fa_wheelchair:
            return 'f193';
        case key.fa_wifi:
            return 'f1eb';
        case key.fa_wikipedia_w:
            return 'f266';
        case key.fa_windows:
            return 'f17a';
        case key.fa_won:
            return 'f159';
        case key.fa_wordpress:
            return 'f19a';
        case key.fa_wrench:
            return 'f0ad';
        case key.fa_xing:
            return 'f168';
        case key.fa_xing_square:
            return 'f169';
        case key.fa_y_combinator:
            return 'f23b';
        case key.fa_y_combinator_square:
            return 'f1d4';
        case key.fa_yahoo:
            return 'f19e';
        case key.fa_yc:
            return 'f23b';
        case key.fa_yc_square:
            return 'f1d4';
        case key.fa_yelp:
            return 'f1e9';
        case key.fa_yen:
            return 'f157';
        case key.fa_youtube:
            return 'f167';
        case key.fa_youtube_play:
            return 'f16a';
        case key.fa_youtube_square:
            return 'f166';
    }

    return "?";
}

Friday, 13 November 2015

Adding Android Wear features to your NativeScript app

Did you know nativescript can run on Android Wear? Well it can. A while back telerik posted a blog post about it.

This was in May and focused on using Android XML files and is a bit out of date, so I will try and extend that using a more NativeScript approach.

I thought I might as well extend some of the features of the Physiotherapy Exercises app I was working on so it would work on watchs.

Here is some photos of it running on a huawei watch



The current idea is to let people with a watch view selected exercises on their watch. They can use the arrows to navigate back and forth.



They can scroll up and down to see the text.



Finally they can tap the exercise to toggle between text and image or just images.

Coding

To get started, you can just create a standard nativescript project.
tns create [foldername] --appid [packagename]
cd [folder]
tns platform add android
You need add features to the android manifest located in \platforms\android\src\main folder. Add the following next to the <uses-permission ...> statements
<uses-feature android:name="android.hardware.type.watch" />
This is an early prototype, I have not set it up to use observables, be written in typescript and read data from other sources yet.

This is just demo code.

The xml for the main page is.
<Page xmlns="http://www.nativescript.org/tns.xsd" loaded="onPageLoaded" backgroundColor="#9A99FF">
  <GridLayout columns="auto,*,auto" rows="auto,*">
    <Label id="counter" text="1 of 10" class="counter" row="0" col="1"/>
    <ScrollView visibility="visible" id="text" tap="onTap" row="1" col="1">
      <StackLayout>
        <Label id="title" text="Balancing a ball while lifting one leg up and down" class="title" textWrap="true" />
        <Image id="image2" src="~/res/drawingshigh/ex0872.jpg"/>
        <Label text="Client's aim" class="subtitle" textWrap="true" />
        <Label id="clientAim" text="To improve your ability to sit unsupported." class="text" textWrap="true"/>
        <Label text="Client's instructions" class="subtitle" textWrap="true" />
        <Label id="clientInstructions" text="Position yourself sitting on a large ball with your feet on the floor. Practice lifting one leg up and down." class="text" textWrap="true"/>
        <Label text="Progressions and variations" class="subtitle" textWrap="true" />
        <Label id="progression" text="Less advanced: 1. Provide hand support for balance. 2. Decrease the height that the leg is lifted. More advanced: 1. Increase the height that the leg is lifted. 2. Increase the movement of the raised leg (eg. add knee extension or hip abduction)." class="text" textWrap="true"/>
      </StackLayout>
    </ScrollView>
    <Image id="image" src="~/res/drawingshigh/ex0872.jpg" visibility="collapsed" tap="onTap" row="0" col="0" colSpan="3" rowSpan="2"/>
    <Label row="0" col="0" rowSpan="2" text="<" class="arrow" tap="onArrowLeft"/>
    <Label row="0" col="2" rowSpan="2" text=">" class="arrow" tap="onArrowRight"/>
  </GridLayout>
</Page>
The javascript code behind is.
var gestures = require("ui/gestures");
var enums = require("ui/enums");


var exercises = [
    {
        title: "Assisted ankle plantarflexor stretch",
        image: "ex0320",
        clientAim: "To induce transient increases in the extensibility of the muscles at the back of your ankle.",
        clientInstructions: "Position yourself lying down with a rolled towel underneath your knee. Instruct a carer/therapist to place their hand around your heel and push your ankle upwards with their forearm.",
        progression: "None"
    },
    {
        title: "Balancing on a ball while lifting one leg up and down",
        image: "ex0872",
        clientAim: "To improve your ability to sit unsupported.",
        clientInstructions: "Position yourself sitting on a large ball with your feet on the floor. Practice lifting one leg up and down.",
        progression: "Less advanced: 1. Provide hand support for balance. 2. Decrease the height that the leg is lifted. More advanced: 1. Increase the height that the leg is lifted. 2. Increase the movement of the raised leg (eg. add knee extension or hip abduction)."
    }
    ,
    {
        title: "Finger and thumb flexor strengthening using grip device",
        image: "ex0667",
        clientAim: "To strengthen the muscles that bend your fingers and thumb.",
        clientInstructions: "Position yourself sitting with a grip strengthening device in your hand. Practice squeezing the device to make a fist.",
        progression: "More advanced: 1. Progress using strength training principles."
    }
     ,
    {
        title: "Throwing and catching a large ball with two hands",
        image: "ex0834",
        clientAim: "To improve your ability to throw and catch using both hands.",
        clientInstructions: "Position yourself standing up. Practice throwing and catching a ball with both hands.",
        progression: "Less advanced: 1. Use a lightweight ball or balloon. 2. Position the patient closer. More advanced: 1. Use a heavier ball. 2. Use a smaller ball. 3. Change the speed and trajectory of throw (eg. throw to either side of the patient)."
    }
       ,
    {
        title: "Walking sideways along a line",
        image: "ex0509",
        clientAim: "To improve your ability to walk.",
        clientInstructions: "Position yourself standing with your toes touching a line across the floor. Practice walking sideways along the line. Ensure that both feet point forwards.",
        progression: "Less advanced: 1. Take smaller steps. More advanced: 1. Take larger steps"
    }

]

var exerciseIndex = 0;

function onArrowLeft(args) {
    if (exerciseIndex > 0) {
        exerciseIndex = exerciseIndex - 1;
        displayData();
    }
}
exports.onArrowLeft = onArrowLeft;

function onArrowRight(args) {
    if (exerciseIndex < exercises.length - 1) {
        exerciseIndex = exerciseIndex + 1;
        displayData();
    }
}
exports.onArrowRight = onArrowRight;

function onTap(args) {
    if (text.visibility == enums.Visibility.collapse) {
        text.visibility = enums.Visibility.visible;
        image.visibility = enums.Visibility.collapse;

    }
    else {
        image.visibility = enums.Visibility.visible;
        text.visibility = enums.Visibility.collapse;
    }
}
exports.onTap = onTap;

function displayData() {
    var exercise = exercises[exerciseIndex];
    title.text = exercise.title;
    clientAim.text = exercise.clientAim;
    clientInstructions.text = exercise.clientInstructions;
    progression.text = exercise.progression;
    counter.text = (exerciseIndex + 1) + " of " + exercises.length;
    image.src = "~/res/drawingshigh/" + exercise.image + ".jpg";
    image2.src = "~/res/drawingshigh/" + exercise.image + ".jpg";
}

var text;
var image;
var image2;
var title;
var clientAim;
var clientInstructions;
var progression;
var counter;

function onPageLoaded(args) {
    var page = args.object;
    title = page.getViewById("title");
    clientAim = page.getViewById("clientAim");
    clientInstructions = page.getViewById("clientInstructions");
    progression = page.getViewById("progression");
    counter = page.getViewById("counter");
    text = page.getViewById("text");
    image = page.getViewById("image");
    image2 = page.getViewById("image2");

    displayData();
}
exports.onPageLoaded = onPageLoaded;

Designing your App

Google have quite a bit of documentation on how to write your app.

Note that I do not think nativescript supports the Wearable UI library directly (in terms of typescript definitions, xml options), so I have just tried getting a layout that works using what is available with "vanilla" NativeScript.

The arrows fill up the left/right rounded section, the number of exercises fill up the top rounded section leaving the remainder for scrollable content.

I tried using gestures but it does not seem to work with the gestures already built into android wear.

Running your App on the Android Wear Emulator

You cannot run your app on your watch using the tns commands, you have to use adb.
adb -e install myapp.apk
After your install it, you have to uninstall it first before installing it again.
adb uninstall packagename
Where package name is the name of the package as defined in the android manifest.

You can also just run your app on your Android mobile phone using standard tns commands, but you have to remember that it isn't very representative in terms of screen real estate space.

Building your App in Release Mode

Deploying an app to your android wear watch is different to deploying to your phone as you cannot just connect it up via a micro-usb cable. You have to package your app inside your phone/handheld app and also it must be built in release mode.

The tns command to do this is:
tns run android --release --key-store-path [your path] --key-store-password [password] --key-store-alias-password [password] --key-store-alias [alias]
Packaging your App

This is taken directly from the google developer docs found here.

  1. Include all the permissions declared in the manifest file of the wearable app in the manifest file of the mobile app. For example, if you specify the VIBRATE permission for the wearable app, you must also add that permission to the mobile app.
  2. Ensure that both the wearable and mobile APKs have the same package name and version number.
  3. Copy the signed wearable app to your handheld project's res/raw directory. We'll refer to the APK as wearable_app.apk.
  4. Create a res/xml/wearable_app_desc.xml file that contains the version and path information of the wearable app. For example:
    <wearableApp package="wearable.app.package.name">
      <versionCode>1</versionCode>
      <versionName>1.0</versionName>
      <rawPathResId>wearable_app</rawPathResId> 
    </wearableApp>
    
    The package, versionCode, and versionName are the same values specified in the wearable app's AndroidManifest.xml file. The rawPathResId is the static variable name of the APK resource. For example, for wearable_app.apk, the static variable name is wearable_app.
  5. Add a meta-data tag to your handheld app's tag to reference the wearable_app_desc.xml file.
      <meta-data android:name="com.google.android.wearable.beta.app"
                     android:resource="@xml/wearable_app_desc"/>
    
  6. Build and sign the handheld app.
Once you deploy this to your phone, it will automatically be uploaded to your watch.

Demo on Appetize

Instructions
  1. Start android phone app first by clicking "Tap to Play"
  2. Start watch by clicking "Tap To Play"
  3. On watch, click mouse button
  4. Scroll through options until you see "Start" click that
  5. Scroll through options until you see "Physio" click that
  6. If it is not visible, give it a bit of time and repeat as it can take a few seconds to sync between phone and watch app


A larger version link is available here.