Farewell, HD7

Al final ocurrió lo que tenía que ocurrir. Hoy, al HD7 le ha dado por apagarse de repente. Al iniciarlo, se ha quedado en la pantalla de inicio permanentemente. Sin botones de volumen (dejaron de funcionar hace unos días) no puedo resetearlo a fábrica ni cambiar el SO. Si cambio la tarjeta de memoria, muestra un error diciendo que, porfa, ponga una nueva y resetee el teléfono a fábrica.

La única opción que me quedaba era abrir el teléfono y tratar de arreglar los botones de volumen y, en última instancia, intentar activarlos manualmente tocando algunas conexiones. Pero no ha habido suerte. Eso sí, he hecho fotos que igual a alguno interesan, están en Flickr.

Ahora el tema de “qué móvil me cojo” es más urgente. Y cada vez lo veo más claro. El iPhone no me acaba de convencer del todo, la interfaz me parece un poco aburrida. Android está bien, pero echando un vistazo de nuevo al Market me he acordado de que la mitad de las aplicaciones son considerablemente feas. Además, no he encontrado ninguna aplicación de música que se sincronice con una aplicación de escritorio y que tenga listas de reproducción inteligentes y valoración de pistas. Así que Android probablemente queda también descartado.

Y la alternativa es un Lumia 800, que no está nada mal de precio, tiene un diseño espectacular y Windows Phone es un sistema que me está gustando de verdad. La cantidad de aplicaciones no me preocupa demasiado, es algo que está cambiando (véase un ejemplo). La verdad, nunca pensé que podría gustarme tanto un sistema de Microsoft… Pero tiene toda la pinta de que al final voy a repetir Windows Phone.

¿Y qué teléfono me cojo?

El HD7 está agonizando ya. No me quejo: lo raro es que haya sobrevivido tanto después del golpe que se pegó el pobre. La cosa fue que yo bajaba corriendo las escaleras a ver si pillaba el cercanías. Corriendo con la funda del móvil (y el móvil dentro) en la mano. La física hizo de las suyas y el móvil salió volando hacia delante a una velocidad muy, muy considerable. Voló en línea recta unos 10 metros, más o menos, hasta que se estampó contra la reja de una máquina de bebidas.

Yo pensaba que el móvil ya estaba para la basura, pero lo mejor de todo es que cuando lo cogí sólo tenía un bollo en la carcasa y el panel LCD dañado, así que la pantalla se veía como está en la imagen. Creedme, con el golpe que se llevó es poco.

Continue reading

ExtendedListBox: custom WP7 Listbox control which detects end of scroll, allows infinite scrolling

The solution was posted months ago in Silverlight – Windows Phone Team’s blog. The only thing I made is making an extended ListBox control with an event which allows easy management of end-of-scroll states.

Advantages against the traditional ListBox control? ExtendedListBox will fire an event when the user has scrolled to the end or beginning of the list. With this event you can manage to do an infinite-scrolling control (more or less).

The class is this:

public class ExtendedListBox : ListBox
    {
        // Compression states: Thanks to http://blogs.msdn.com/b/slmperf/archive/2011/06/30/windows-phone-mango-change-listbox-how-to-detect-compression-end-of-scroll-states.aspx
 
        protected bool _isBouncy = false;
        private bool alreadyHookedScrollEvents = false;
 
        public ExtendedListBox()
        {
            this.Loaded += new RoutedEventHandler(ListBox_Loaded);
        }
 
        private void ListBox_Loaded(object sender, RoutedEventArgs e)
        {
            ScrollBar sb = null;
            ScrollViewer sv = null;
            if (alreadyHookedScrollEvents)
                return;
 
            alreadyHookedScrollEvents = true;
            this.AddHandler(ExtendedListBox.ManipulationCompletedEvent, (EventHandler<manipulationcompletedeventargs>)LB_ManipulationCompleted, true);
            sb = (ScrollBar)FindElementRecursive(this, typeof(ScrollBar));
            sv = (ScrollViewer)FindElementRecursive(this, typeof(ScrollViewer));
 
            if (sv != null)
            {
                // Visual States are always on the first child of the control template 
                FrameworkElement element = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
                if (element != null)
                {
                    VisualStateGroup vgroup = FindVisualState(element, "VerticalCompression");
                    VisualStateGroup hgroup = FindVisualState(element, "HorizontalCompression"); 
                    if (vgroup != null)
                        vgroup.CurrentStateChanging += new EventHandler<visualstatechangedeventargs>(vgroup_CurrentStateChanging);
                    if (hgroup != null)
                        hgroup.CurrentStateChanging += new EventHandler</visualstatechangedeventargs><visualstatechangedeventargs>(hgroup_CurrentStateChanging);
                }
            }
 
        }
 
        public delegate void OnCompression(object sender, CompressionEventArgs e);
        public event OnCompression Compression;
 
        private void hgroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e)
        {
            if (e.NewState.Name == "CompressionLeft")
            {
                _isBouncy = true;
                if (Compression != null)
                    Compression(this, new CompressionEventArgs(CompressionType.Left));
            }
 
            if (e.NewState.Name == "CompressionRight")
            {
                _isBouncy = true;
                if (Compression != null)
                    Compression(this, new CompressionEventArgs(CompressionType.Right));
            }
            if (e.NewState.Name == "NoHorizontalCompression")
            {
                _isBouncy = false;
            }
        }
 
        private void vgroup_CurrentStateChanging(object sender, VisualStateChangedEventArgs e)
        {
            if (e.NewState.Name == "CompressionTop")
            {
                _isBouncy = true;
                if (Compression != null)
                    Compression(this, new CompressionEventArgs(CompressionType.Top));
            }
            if (e.NewState.Name == "CompressionBottom")
            {
                _isBouncy = true;
                if(Compression!=null)
                    Compression(this, new CompressionEventArgs(CompressionType.Bottom));
            }
            if (e.NewState.Name == "NoVerticalCompression")
                _isBouncy = false;
        }
 
        private void LB_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
        {
            if (_isBouncy)
                _isBouncy = false;
        }
 
        private UIElement FindElementRecursive(FrameworkElement parent, Type targetType)
        {
            int childCount = VisualTreeHelper.GetChildrenCount(parent);
            UIElement returnElement = null;
            if (childCount > 0)
            {
                for (int i = 0; i < childCount; i++)
                {
                    Object element = VisualTreeHelper.GetChild(parent, i);
                    if (element.GetType() == targetType)
                    {
                        return element as UIElement;
                    }
                    else
                    {
                        returnElement = FindElementRecursive(VisualTreeHelper.GetChild(parent, i) as FrameworkElement, targetType);
                    }
                }
            }
            return returnElement;
        }
 
        private VisualStateGroup FindVisualState(FrameworkElement element, string name)
        {
            if (element == null)
                return null;
 
            IList groups = VisualStateManager.GetVisualStateGroups(element);
            foreach (VisualStateGroup group in groups)
                if (group.Name == name)
                    return group;
 
            return null;
        }
    }
 
    public class CompressionEventArgs : EventArgs
    {
        public CompressionType Type { get; protected set; }
 
        public CompressionEventArgs(CompressionType type)
        {
            Type = type;
        }
    }
 
    public enum CompressionType { Top, Bottom, Left, Right };

It fires the event Compression whenever a scroll has ended. CompressionEventArgs contains the info on the side the scroll has ended. But this is not sufficient to make things work. You have to add this code to your App.xaml:

<style TargetType="ScrollViewer">
            <setter Property="VerticalScrollBarVisibility" Value="Auto"/>
            <setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
            <setter Property="Background" Value="Transparent"/>
            <setter Property="Padding" Value="0"/>
            <setter Property="BorderThickness" Value="0"/>
            <setter Property="BorderBrush" Value="Transparent"/>
            <setter Property="Template">
                </setter><setter .Value>
                    <controltemplate TargetType="ScrollViewer">
                        <border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
                            <visualstatemanager .VisualStateGroups>
                                <visualstategroup x:Name="ScrollStates">
                                    </visualstategroup><visualstategroup .Transitions>
                                        <visualtransition GeneratedDuration="00:00:00.5"/>
                                    </visualstategroup>
                                    <visualstate x:Name="Scrolling">
                                        <storyboard>
                                            <doubleanimation Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                                            <doubleanimation Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
                                        </storyboard>
                                    </visualstate>
                                    <visualstate x:Name="NotScrolling"/>
 
                                <visualstategroup x:Name="VerticalCompression">
                                    <visualstate x:Name="NoVerticalCompression"/>
                                    <visualstate x:Name="CompressionTop"/>
                                    <visualstate x:Name="CompressionBottom"/>
                                </visualstategroup>
                                <visualstategroup x:Name="HorizontalCompression">
                                    <visualstate x:Name="NoHorizontalCompression"/>
                                    <visualstate x:Name="CompressionLeft"/>
                                    <visualstate x:Name="CompressionRight"/>
                                </visualstategroup>
                            </visualstatemanager>
                            <grid Margin="{TemplateBinding Padding}">
                                <scrollcontentpresenter x:Name="ScrollContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
                                <scrollbar x:Name="VerticalScrollBar" IsHitTestVisible="False" Height="Auto" Width="5" HorizontalAlignment="Right" VerticalAlignment="Stretch" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" />
                                <scrollbar x:Name="HorizontalScrollBar" IsHitTestVisible="False" Width="Auto" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{TemplateBinding HorizontalOffset}" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" />
                            </grid>
                        </border>
                    </controltemplate>
                </setter>
 
        </style>

Just with this, you can start working with the ExtendedListBox. And I suppose you could also extend in the same way similar controls, just reusing the code.

All of the code is completely free to use, and the credits go to Silverlight – WP blog, they developed the main part of this trick. I only put it together.

2011, adiós

31 de diciembre de 2011. Toca resumen de uno de los años más increíbles de mi vida. La verdad es que no sé por dónde empezar.

He acabado (por fin) el Bachillerato LOE e Internacional. Y con nota, encima. Ha sido una de las experiencias más enriquecedoras que uno puede tener. Gente muy interesante, con puntos de vista distintos a los que estaba acostumbrado. También una visión distinta de la enseñanza y de que hay más formas de aprender. Además, durante los dos años de BI cambié mi decisión de carrera. En un principio iba a hacer Química. Pero si se juntan una profesora de Matemáticas muy buena y un temario de Química no muy atractivo…

Al final, siguiendo con mi habitual sadomasoquismo y ganas de hacer dos cosas a la vez, me metí a un doble grado: Ingeniería Informática y Matemáticas en la Universidad Autónoma de Madrid. No me arrepiento: estoy aprendiendo mucho, es entretenido y el ambiente de la UAM (tanto compañeros, profesores e instalaciones) es genial.

Por otra parte, este año he seguido en Genbeta (y ya van dos). Y, sin saber muy bien cómo, he acabado viajando dos veces a Estados Unidos en poco más de un mes. Primero, desde Evernote invitaron a varios blogs europeos a la Evernote Trunk Conference. Uno de ellos era Genbeta, y a mí me tocó la suerte de ir. Pero lo mejor vino después: imaginaos mi sorpresa cuando, estando en medio de una presentación, me llega un correo de Antonio Ortiz: si estoy disponible para ir en Septiembre a EEUU de nuevo, a la BUILD Windows donde MS presentaría Windows 8. Poco tardé en responder. Al final, entre los dos viajes he conocido a bastante gente interesante, y he aprendido muchísimo (y también he descubierto que me defiendo mejor en inglés hablado de lo que esperaba).

2011 ha sido uno de los años más interesantes para mí. Gente nueva, temas nuevos… y me encuentro en una situación que no habría sido capaz de imaginar dos años antes. Ójala el 2012 sea, como mínimo, igual que el 2011 para mí.

Atheism… yeah, makes sense

Just saw this on @Zaski1 twitter… Ignoring the second part, yes, atheism makes sense. Not perfect sense, but it’s not crazy. The point: it’s difficult to understand without scientific knowledge.

There’s an interesting theory about Big Bang, related with strings theory. But it’s pretty hard to understand and explain in less than 500 words. So, if you’re really interested in this theory I recommend you the book “The elegant universe”, from Brian Green. In short (and probably imprecise): at first, there was a 11 dimension brane, a dot. It was a singularity and unstable, so it expanded. Three of the dimensions expanded: our space. Another one, the time. The ones which didn’t expand remain as the microscopic structure of the universe, and they’re collapsed. I said this part was pretty difficult. But it makes pretty good sense, promise.

Next: the creation of the particles. This is easier: everything tends to the state of minimum energy. Quarks alone have more energy (each one) than together, so they make another particles, like protons, neutrons and electrons. Oh, and these particles have also more energy alone than together: here comes the atoms. And I suppose you can guess what happens here about molecules.

An interesting point here. The transitions between states are allowed or forbidden depending on the energy. An example: you have two molecules, A and B. But you discover that the molecule AB is more stable (has less energy) than A and B alone. Why they’re not joining? Didn’t I say that everything tends to the state of minimun energy?

Yes. But tends does not mean “always passes”. Some transitions require energy. In this example, maybe you have to heat A and B (give them energy) to break their structures and allow them to form the molecule AB. This leads us to the “stable states”. Mainly, this means that a stable structure does not have enough energy to go to another state of less energy. That’s because things are not destroying themselves everytime and the cause we (and the whole universe) have not become a single dot yet.

Ok, so we have arrived and somewhat explained all of the things before biology and cells and all of that. This should be easier… except I’m not a biology man so I think I’m not able to explain it in a simple and correct way. But, as always, Wikipedia does it job very well. The rest is simple: evolution, the most adapted survive, the ones not adapted die. This, together with random modifications in cell replication and billions of years of time to evolve leads us to the world we have right now.

And the final question: why is the world like it is? Well, no one knows, but the most acceptable answer I’ve heard is this: It is like it is, but it also could have been in another way; just like when you throw a dice. The point is that, if it would not have been like this we would not be alive. So we are mainly a product of casuality and probability (this may not sound acceptable to you, but when you understand and accept quantum physics it does not seem so strange).

PD: A good book about quantum physics: How to teach physics to your dog. Funny, interesting, easy and short.

Trustworthy sources FTW

http://www.ticbeat.com/socialmedia/tuenti-se-desmorona/

In this post, TICBeat says that Tuenti is going down. They back this affirmation with two ultra-mega-hyper trustworthy sources: Alexa and DoubleClick Ad Planner.


Alexa is in no way useful. One example: here you have the stats for all the Weblogs SL network. As you can see, Xataka doubles Genbeta both in unique visitors and pageviews. Now, let’s look at what Alexa is saying about these two sites.

LOL.

Also, DoubleClick Ad Planner. It serves estimate stats. They say it. They may probably get the data from the ads from Adwords displayed. When a site doesn’t rely completely on AdWords, the estimations can’t be very accurate.

They also show stats from Nielsen and comScore (which groups Tuenti with all other Telefónica sites). But I bet that these stats don’t count the mobile users. And they’re a lot of them, people who accesses Tuenti from their mobile applications.

I don’t say that the official numbers from Tuenti are right. But the unofficial numbers are neither right. A lot of people is saying that Tuenti is going down based on bad sources. If you have to say something, at least check if the data you use can be really trusted.