Tipos MIME en IIS Express / WebMatrix

Si habéis probado WebMatrix sabréis que es una herramienta muy útil y práctica cuando todo funciona bien. Hace poco quise hacer una prueba con una fuente WOFF y no había manera de hacerla funcionar, aunque por mucho que mirara el código no encontraba qué estaba haciendo mal…

<style type="text/css">
    @font-face
    {
        font-family: SegoeCustom;
        src:  url('fonts/segoe.woff') format('woff');
        font-weight: normal;
        font-style: normal;        
    }
    p {
        font-family:SegoeCustom, sans-serif;
        font-size:100px;
        }
</style>

Lo que pasaba es que estaba haciendo la prueba en WebMatrix y los tipos MIME admitidos son sólo los más comunes, aquí vemos el resultado en la lista de requests:

Podemos intentar modificar los tipos MIME con el IIS Manager, pero en IIS 8 no he conseguido encontrarlos, los habrán cambiado de sitio otra vez :) . Menos mal que tenemos una manera mucho más sencilla de controlar los tipos MIME a nivel de aplicación web, desde el archivo web.config de la siguiente manera:

<?xml version="1.0"?>
<configuration>
  <system.webServer>
      <staticContent>
        <mimeMap fileExtension=".woff" mimeType="font/x-woff" />
      </staticContent>
  </system.webServer>
</configuration>

IIS Express nos permite añadir los tipos directamente en el web.config, lo que nos será muy útil en WebMatrix y también en VS2010 cuando estemos usando IIS Express.

Podéis encontrar más detalles en el blog de msdn.

Categorías:Trucos Etiquetas: ,

XAML Flyout y otras funcionalidades de UI en aplicaciones Metro

Si ya habéis empezado a desarrollar aplicaciones Metro y las estáis haciendo en XAML os habréis dado cuenta que todavía faltan algunos controles que habréis visto en algunas aplicaciones y demos, pues en la plataforma JavaScript ya los tenemos.
Mientras esperamos los controles oficiales, algunos desarrolladores han tenido la gentileza de compartir con los demás sus propios controles, aquí tenéis dos que he utilizado.

  • Tim Heuer nos proporciona la librería Callisto que nos permitirá añadir algunas funcionalidades que nos faltan en el framework de XAML que viene para las aplicaciones Metro de Windows 8, como por ejemplo los elementos FlyOut: https://github.com/timheuer/callisto
  • Como en esa librería tampoco está todo, en Codeplex también tenemos el WinRT XAML Toolkit que contiene algunos elementos útiles como diálogos personalizables o un visor de estilos: http://winrtxamltoolkit.codeplex.com/

Espero que os sean tan útiles como a mí :)

Categorías:Trucos Etiquetas: ,

Eventos táctiles en aplicaciones Metro HTML5

Touch the Sun - IMG_9463_72dpi Los eventos táctiles en Windows 8 son muy fáciles de manejar y desde HTML5 tenemos un modo muy directo de hacerlo a través de tres eventos que nos permitirán manejar ratón, lápiz y dispositivo táctil a la vez y de una manera muy sencilla.

Estos son: MSPointerDown, MSPointerUp y MSPointerMove que podremos aplicar a cualquier elemento visual.

Para ver cómo funciona vamos a hacer una aplicación de dibujo muy básica con un canvas sobre el que podremos pintar con los dedos, con un dispositivo tipo lápiz o con el ratón. Colocamos un elemento canvas en el default.html de una aplicación Metro:

<canvas id="demoCanvas"></canvas>

Una vez tengamos el canvas, tendremos que utilizar esos eventos. En el onactivated de nuestra página (en default.js) vamos a añadir código a los eventos que he comentado antes:

var demoCanvas;
var ctx;

app.onactivated = function (eventObject) {
    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
        if (eventObject.detail.previousExecutionState !==
            Windows.ApplicationModel.Activation.ApplicationExecutionState.terminated) {
            // TODO: This application has been newly launched. Initialize
            // your application here.
        } else {
            // TODO: This application has been reactivated from suspension.
            // Restore application state here.
        }
        WinJS.UI.processAll();

        demoCanvas = document.querySelector("#demoCanvas");
        //ponemos el canvas a fullscreen
        demoCanvas.width = document.body.clientWidth;
        demoCanvas.height = document.body.clientHeight;

        //obtenemos el context para pintar
        ctx = demoCanvas.getContext("2d");

        //usamos los tres eventos para activar el pincel y pintar
        demoCanvas.addEventListener("MSPointerDown", startDrawing);
        demoCanvas.addEventListener("MSPointerUp", stopDrawing);
        demoCanvas.addEventListener("MSPointerMove", draw);
    }
};

Una vez tenemos los eventos, vamos a escribir esos tres métodos para pintar en el canvas. Las funciones recibirán un parámetro con la información del evento.
En la función startDrawing vamos a recuperar qué tipo de puntero estamos utilizando (ratón, lápiz o táctil) para cambiar el grosor del trazo:

var doDraw = false;
var pointerDeviceType;

function startDrawing(e) {
    doDraw = true;
    var pointer = Windows.UI.Input.PointerPoint.getCurrentPoint(e.pointerId)
    pointerDeviceType= pointer.pointerDevice.pointerDeviceType;
    draw(e);
}

En el evento stopDrawing simplemente deshabilitamos el trazo, para evitar que vaya pintando cuando movemos el ratón:

function stopDrawing(e) {
    doDraw = false;
}

Y en el método draw pintaremos con trazos diferentes según el dispositivo y colores diferentes según el identificador del puntero, para poder identificar múltiples inputs simultáneos:

function draw(e) {
    if (doDraw) {
        //cambiamos entre tres colores según el id del puntero
        var id = e.pointerId % 3;
        var rgb = [0, 0, 0];
        rgb[id] = 255;

        //cambiamos el grosor según el puntero (ratón=fino, lápiz=mediano, táctil=grueso)
        var width = 10;
        switch (pointerDeviceType) {
            case Windows.Devices.Input.PointerDeviceType.mouse:
                width = 10;
            case Windows.Devices.Input.PointerDeviceType.pen:
                width = 20;
                break;
            case Windows.Devices.Input.PointerDeviceType.touch:
                width = 40;
        }

        //pintamos un círculo en el contexto 2d en la posición del movimiento
        ctx.beginPath();
        ctx.arc(e.clientX, e.clientY, width, 0, 2 * Math.PI, false);
        ctx.fillStyle = "rgb(" + rgb.join(",") + ")";
        ctx.fill();
    }
}

Aquí podemos ver el resultado en el simulador de Windows 8:

Puedes descargar el código de ejemplo en Codeplex.

Categorías:Tutoriales Etiquetas: ,

Problemas con el appcert.exe en Windows 8

abril 24, 2012 Deja un comentario

Aviso: en esta entrada explico cómo borrar mediante comandos de PowerShell las aplicaciones Metro que tengáis instaladas. Usar sólo en caso de extrema necesidad.

Cuando estamos desarrollando aplicaciones Metro nos va a pasar alguna vez que el despliegue se quede a medias o que ni siquiera esté el despliegue hecho pero la aplicación figure como registrada. Normalmente eso no nos supondrá ningún problema, pues muchas veces esas aplicaciones ni siquiera aparecerán en la pantalla de inicio.
El problema vendrá más adelante, cuando queramos utilizar el kit de certificación de la tienda (Wack: appcertui.exe/appcert.exe) para probar que nuestra aplicación funciona correctamente antes de enviarla a validar, para así ahorrarnos unos cuantos días de espera.
Cuando Wack nos dice que no ha podido probar nuestra aplicación porque no estaba instalada en realidad no es culpa de nuestro despliegue, sino de alguna aplicación que se quedó en algún estado indeterminado de la materia dentro del registro de aplicaciones Metro.

¿Y por qué ocurre esto?

Si listamos las aplicaciones que tenemos instaladas con el comando de PowerShell Get-AppxPackage, obtendremos un listado en el que aparecerán aplicaciones como esta:

Name            : 7b10c66c-6210-460f-a1e0-7cf7545030d6
Publisher       : CN=xxxxx
Architecture    : Neutral
ResourceId      :
Version         : 1.0.0.0
PackageFullName : 7b10c66c-6210-460f-a1e0-7cf7545030d6_1.0.0.0_neutral...
InstallLocation : C:\Users\xxxxx\AppData\Local\Temporary Projects\Application1\bin\Debug\AppX
IsFramework     : False

Si os fijáis bien en la InstallLocation, en mi caso es una carpeta temporal que seguramente se acabará borrando en algún momento, en otros casos (según cómo esté configurado el visual studio) no se borrará, pero puede que la borremos nosotros porque movamos el proyecto, o era simplemente un proyecto de prueba. Así que en algún momento obtendremos esto:

Name            : 7b10c66c-6210-460f-a1e0-7cf7545030d6
Publisher       : CN=xxxxx
Architecture    : Neutral
ResourceId      :
Version         : 1.0.0.0
PackageFullName : 7b10c66c-6210-460f-a1e0-7cf7545030d6_1.0.0.0_neutral...
InstallLocation :
IsFramework     : False

Y debido a un bug del Wack, éste no encontrará ninguna aplicación que esté después de una app sin InstallLocation. Gracias a powershell podemos listar todas las apps que se hayan quedado en ese estado:

Get-AppxPackage | Where-Object {$_.InstallLocation -eq $null }

¿Cómo solucionarlo?

Modificando un poco el script podemos borrar todas esas aplicaciones zombi de un golpe:

Get-AppxPackage | Where-Object {$_.InstallLocation -eq $null } | Foreach {Remove-AppxPackage $_.PackageFullName}

¿Qué hago si todavía falla?

Puede que en algunos casos ni así consigamos que nos funcione el Wack, por culpa de alguna otra app instalada, como es muy probable que sea por una de las que hemos compilado nosotros, lo que podemos hacer es borrar todas las apps que tengamos dentro de la carpeta de usuarios:

Get-AppxPackage | Where-Object {$_.InstallLocation -like $home } | Foreach {Remove-AppxPackage $_.PackageFullName}

Mucho cuidado con este comando, borrará todas las aplicaciones que estén instaladas desde la carpeta C:\Users\[nombre de usuario]

Categorías:Trucos Etiquetas:

Cuenta Atrás en Windows 8

marzo 28, 2012 3 comentarios

Descarga el código del ejemplo en codeplex.

El pasado día 22 de Marzo se realizó en el ParcBit, organizado por el grupo de usuarios Netsaimada, un gran evento sobre ALM donde participaban Luis Fraile y Rodrigo Corral. Aproveché el evento, ya que me dejaron “colarme”, para explicar el desarrollo de aplicaciones Metro en Windows 8.
En los eventos suele ocurrir que el ponente tiene más cosas que contar que tiempo en una sesión. Para evitar que las sesiones se vayan comiendo el tiempo de las siguientes, suele haber alguien de la organización que avisa al ponente cuando está agotando el tiempo.
Si esa persona soy yo es un desastre, porque se me olvida mirar el reloj, pierdo el papel con el horario de las sesiones y otras cosas por el estilo. Así que Darío me propuso hacer un cronómetro para una tableta Acer Iconia que traía con Windows 8 y pensé que no me costaría mucho desarrollar una aplicación sencilla con una cuenta atrás y un botón de iniciar y parar.




Es una aplicación hecha en pocos minutos y sin muchas pretensiones, pero nos servirá para demostrar unas cuantas características interesantes del Windows 8.

¿Qué características vamos a usar?

Para desarrollar una aplicación así tenemos que tener en cuenta unas cuantas cosas:

  • Las aplicaciones metro sólo se están ejecutando mientras están en primer plano
  • Cuando una aplicación metro pasa a segundo plano puede ocurrir que se cierre completamente
  • Las aplicaciones metro no pueden instalar nada en el sistema, todo lo que utilice la aplicación debe desplegarse con la misma. Si queremos usar una fuente de letras personalizada la debemos distribuir con la aplicación
  • Para mejorar la usabilidad de nuestra aplicación, esta debe adaptarse a los diferentes tamaños de pantalla. Añadiendo una vista acoplada podremos conseguir que nuestra aplicación sea utilizada durante más tiempo

El desarrollo

Como es una aplicación muy sencilla y queremos comprobar cómo de fácil es crear una aplicación en HTML5/Javascript, vamos a crear una aplicación con la plantilla más sencilla, la Blank Application:



Una vez creado el proyecto, vamos a programar todo en los ficheros default.html, default.js y default.css. Lo primero vamos a crear el contenedor para los dígitos, el cuadro para introducir el tiempo y los botones de start y stop dentro del body:

<body>
    <div id="timer">
        <p class="timer-time" id="time">00:00:00</p>
        <div class="timer-config" style="height: 228px;">
            <label for="length">Minutes:</label>
            <input type="number" id="length" min="1" value="60" />
            <button>Start</button>
            <button>Stop</button>
        </div>
    </div>
</body>

Y ahora podemos programar nuestro reloj, primero nos creamos una clase que nos permita inicializar un timer a una hora en concreto y saber cuánto tiempo ha pasado desde entonces. Como no tengo demasiada experiencia con JavaScript, he buscado un poco por allí y por allá y con algunos retazos de lo que me he encontrado me he creado mi propio objeto:

var downTimer = {
    time: 0,
    length: 0,
    now: function () { return (new Date()).getTime(); },
    start: function (length) { this.time = this.now(); this.length = length*1000; },
    since: function () { return this.now() - this.time; },
    last: function () {
        var l = this.length - this.since();
        if (l < 0) return this.msToTime(0);
        else
            return this.msToTime(l);
    },
    stop: function () { this.time = this.length = 0; },
    msToTime: function (s) {
            var ms = s % 1000;
            s = (s - ms) / 1000;
            var secs = s % 60;
            s = (s - secs) / 60;
            var mins = s % 60;
            var hrs = (s - mins) / 60;
            return (hrs<10?'0':'')+ hrs + ':' + (mins<10?'0':'') + mins + ':' + (secs<10?'0':'') + secs;
        }
}

Como en Javascript no tenemos clases, pero es un lenguaje dinámico, podemos crear objetos complejos sin complicarnos demasiado. En el caso anterior es un objeto singleton donde declaramos directamente las variables y funciones que vamos a utilizar. Las importantes en este objeto son las funciones start, stop y last que son las que harán todo el trabajo.

Ahora, dentro del evento app.onactivated, llamaremos a un timeout de javascript para que ejecute de manera cíclica un método de refresco para nuestro contador, cada 33 milisegundos para simular un ciclo de 30 frames por segundo, aunque con 12 o incluso 3 frames nos bastaría:

//execute at 30fps (enough)
setInterval(refresh, 33);

Definiremos la función refresh para que refresque el elemento time con el contenido de nuestra clase downtimer:
function refresh() {
    var element = document.getElementById("time");
    element.textContent = downTimer.last();
}

Para que nuestra cuenta atrás funcione sólo nos falta que los botones de start y stop tengan funcionalidad. Para hacerlo más elegante definiremos dos métodos en un espacio de nombres y así los podremos llamar bien desde la página:
WinJS.Namespace.define("defaultPage",{
    startClick: function () {
        var length = document.getElementById("length").value;
        downTimer.start(length * 60);
    },
    stopClick: function () {
        downTimer.stop();
    }
});

Una vez tenemos las funciones dentro de un espacio de nombres modificamos los botones en el default.html para que al pulsarlos se llame a las funciones que hemos definido:

<button onclick="defaultPage.startClick()">Start</button>
<button onclick="defaultPage.stopClick()">Stop</button>

Probamos la aplicación así y ya tenemos una cuenta atrás funcionado:



Aunque la pantalla nos queda algo vacía, vamos a darle un poco de estilo.

Cambiar el UI con CSS

Hasta ahora nos hemos preocupado sólo por la funcionalidad, vamos a cambiar el aspecto con unos pocos trucos de css.
Vamos primero a por el contador, me gustaría más una fuente estilo reloj digital, pero no podemos asegurarnos que el Windows 8 donde se instale la aplicación vaya a tenerla instalada, así que tendremos que encontrar una fuente que podamos distribuir con nuestra aplicación. Como estamos haciendo una aplicación HTML, lo más fácil es encontrar alguna fuente gratuita, convertirla en formato woff y distribuirla con la aplicación. Para ello añadimos la fuente a una carpeta del proyecto:

Y una vez allí, la configuramos en el default.css:

@font-face {
    font-family: 'dsdigital';
    src: url('/fonts/dsdigital.woff') format('woff');
    font-weight: normal;
    font-style: normal;
}

#timer .timer-time {
        font-family: 'dsdigital';
        font-size: 190px;        
        text-align: center;
    }

Ahora ya empieza a parecer algo más serio:



Sólo nos queda darle algo más de estilo al cuadro de texto y a los botones para que sean más adecuados para utilizar de forma táctil. Un poco más de CSS, utilizar el id de los elementos dentro del CSS no es muy adecuado, pero para hacer una demo rápida nos valdrá:

#timer .timer-config {
    position: relative;
    width: 580px;
    margin-left: auto;
    margin-right: auto;
    display: block;        
}
#timer label {
            font-size: 1.45em;
}
#timer input {
    border: #000 1px;
    height: 2em;
    font-size: 2.45em;
    text-align: right;
}
#timer button {
        width: 2em;
        background: #000;
        color: #eee8d2;
        border: #fff 1px;
        height: 2em;
            font-size: 2.45em;
            font-weight: 300;
    }

 #timer button:active {
            background: #00f;
        }

Otra cosa que me gustaría es que los botones tengan un glyph en lugar de un texto, para que se entienda en cualquier idioma. Una primera idea sería poner una imagen, pero para no tener problemas con el escalado podemos usar algunos caracteres Unicode como el Black Rectangle (25A0) y el Black Right-Pointing Pointer (25B6):
<button onclick="defaultPage.startClick()">▶</button>
<button onclick="defaultPage.stopClick()">■</button>

Y así ya tendremos la aplicación básica.

Vista Acoplada

Una de las características de las aplicaciones Metro en Windows 8 es que son a pantalla completa, pero en los dispositivos que tengan la resolución suficiente el usuario puede tener una vista acoplada a un lado de la aplicación. Esto nos ayudará a que los usuarios utilicen nuestra aplicación durante más tiempo.
En nuestro caso, crear la vista acoplada no necesitará de código javascript, nos bastará con adaptar la hoja de estilos para la que la vista quede más compacta. En la misma hoja de estilos de la página tenemos unas reglas para las diferentes vistas, editamos la vista snapped así:

@media screen and (-ms-view-state: snapped) {
    body {
        font-size: 10px;
    }
    #timer .timer-time {
        font-size: 50px;
    }
    #timer .timer-config {
        height: 230px;
        width: 315px;
        margin: 5px;
        padding: 5px;
        text-align: center;
    }
}

Y ya tenemos una vista ajustada a la ventana acoplada:


Itinerancia de datos

Ahora que nuestra aplicación ya tiene el contador, funciona y se ve bonita, le podemos añadir muy fácilmente una pequeña funcionalidad que nos vendrá bien cuando paremos nuestra aplicación o utilicemos la aplicación en varios dispositivos. Podemos guardar la información importante de nuestro temporizador en la configuración de itinerancia, que se copiará automáticamente entre los diferentes dispositivos que tengamos con Windows 8 y utilicemos con la misma cuenta LiveID.

var appdata = Windows.Storage.ApplicationData;

WinJS.Namespace.define("defaultPage",{
    startClick: function () {
        var length = document.getElementById("length").value;
        downTimer.start(length * 60);
        //store roaming
        appdata.current.roamingSettings.values["time"] = downTimer.time;
        appdata.current.roamingSettings.values["length"] = downTimer.length;
    },
    stopClick: function () {
        downTimer.stop();
        //clear roaming
        appdata.current.roamingSettings.values["time"] = null;
        appdata.current.roamingSettings.values["length"] = null;
    }
});

Ahora sólo nos queda leer el dato al arrancar la aplicación en el evento app.onactivated:
app.onactivated = function (eventObject) {
    if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
        var time = appdata.current.roamingSettings.values["time"];
        if (time) {
            downTimer.time = time;
            downTimer.length = appdata.current.roamingSettings.values["length"];
        }
...

Al activar la aplicación leemos la configuración, si existe, y así nuestro contador seguirá como si nada hubiera pasado.
Este ejemplo costó menos de media hora de desarrollo, me ha costado muchísimo más describirlo que hacerlo :)

¿Qué hemos visto?

  • Algunas características que nos proporciona Windows 8, como la vista acoplada y la configuración de itinerancia, para dar un punto de calidad a nuestra aplicación, de manera muy sencilla pues Windows 8 nos proporciona la mayor parte de la funcionalidad “out of the box”.
  • La creación de espacios de nombres (namespaces) nos ayuda a organizar el código de nuestra aplicación, y nos facilita la escritura de código gracias al intellisense.
  • La integración del código HTML5/JavaScript estándar con el código específico de la plataforma Windows 8
  • Cómo incorporar fuentes de letras con nuestra aplicación
  • Uso de caracteres especiales Unicode para tener glyphs escalables
  • La separación del diseño y la lógica del interfaz
  • Las media queries de css para adaptar la interfaz a los diferentes tamaños y orientaciones del dispositivo

Y todo esto sólo con un cronómetro, imaginad lo que podéis llegar a hacer con vuestras aplicaciones.

Descarga el código del ejemplo en codeplex.

Categorías:Eventos, Tutoriales Etiquetas: ,

Azure queues y el mensaje One of the request inputs is out of range

febrero 15, 2012 Deja un comentario

Las colas en Windows Azure son muy útiles para escalar tareas que se pueden dejar en segundo plano, habitualmente desde un rol Web enviamos trabajos a Worker Roles utilizando colas.

Queue

Durante el inicio de los roles se suele abrir la cola, se comprueba que exista y si no existe la creamos. Son unas pocas líneas:

var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
var queueStorage = storageAccount.CreateCloudQueueClient();
var queue = queueStorage.GetQueueReference(nombreDeCola);
queue.CreateIfNotExist();

No es un código demasiado complicado, pero hoy me he pasado un buen rato devanándome los sesos porque me daba un error 400 con el siguiente mensaje:

One of the request inputs is out of range

Sin más.

Tras trastear un poco y comparar con otras colas me he dado cuenta que el nombre de la cola contenía alguna letra mayúscula y eso rompe las reglas de nombres en colas (y también en blobs).

Se agradecería un mensaje de error más descriptivo :)

Categorías:Trucos Etiquetas:

El efecto Kinect en Imagine Cup

febrero 13, 2012 2 comentarios

Kinect desensamblado

Este año voy a seguir Imagine Cup con especial interés, pues acompaño como mentor a un equipo de estudiantes de Illes Balears. Han decidido participar en las categoría de Game Design: Phone, también participarán en algún reto y estoy seguro que harán un buen papel.

Uno de los retos que a mi más me gustan y a algún que otro compañero es el de Kinect Fun Labs. Para añadirle más emoción, los 100 primeros de la primera ronda recibirán un dispositivo Kinect For Windows!

Hay hasta el 6 de marzo para presentar ideas para la primera ronda y mañana día 14 de febrero habrá un Live Meeting donde podremos resolver nuestras dudas sobre el concurso.

¡Quién fuera estudiante! Nos vemos en Australia :)

Categorías:Eventos Etiquetas: , , ,
Seguir

Get every new post delivered to your Inbox.

Únete a otros 169 seguidores