jeudi 23 février 2012

MEF - Managed Extensibility Framework

Mais qu'est ce que c'est que cet MEF? Voilà à peu de chose prêt ce que je me suis demandé lorsque l'on m'en a parlé. Oui mais comment ça marche? Est la seconde question qui m'a tenu pendant des heures.

En fait, MEF est une chose très simple mais possédant peut de documentation claire, chose que je vais tenter de faire de façon à éviter à d'autres que moi de perdre un temps précieux à trouver de l'aide sur la toile.

Le but de MEF est d'importer des plugins de façon simple, qu'il se trouve dans le même projet ou sous forme d'un fichier ".dll" et c'est là que ça devient intéressant. Car la particularité de MEF comparé à une autre méthode est le fait que lors d'un appel d'un plugin, si il est là il sera traité, si ils sont plusieurs, ils le seront tous et si malheureusement la recherche ne donne rien cela ne déclanche aucunes erreurs c'est plutôt "Je vais charger des plugins. Oh mais je trouve rien là où ils devraient être. Bon ben tampis, je continue ma route". Son comportement est similaire à un bus qui se stop à un arrêt et qu'il y ai des passagers ou non, ça ne change rien pour lui.
Dans le cas présent, on va chercher des ".dll" dans un dossier "plugins" et y récupérer des donneés.
Dans votre projet et dans vos plugins, il faut rajouter la référence de Visual Studio 2010 "System.ComponentModel.Composition" car, bien que basé sur de l'opensource, le framework est désormais inclus dans le framework .Net.

Le code de notre dll est le suivant:
Plugin10.cs
using System.ComponentModel.Composition;
using GPIInterface;

namespace Plugin10
{
    [Export(typeof(IGrany))]
    public class Plugin10 : IGrany
    {
        public string PluginTitle(){
            return "Plugin numéro 10";
        }
        public string PluginDescription(){
            return "Ceci est le premier plugin";
        }
        public string PluginImageName(){
            return "10.jpg";
        }
        public string PluginName(){
            return "Plugin10";
        }
    }
}

Comment on peut le voir, le plugin implémente une interface qui défini simplement les méthodes qui doivent se trouver dans tous les plugins. Mais cela ne change rien à notre projet.
La partie la plus vitale est la ligne "[Export(typeof(IGrany))]" où l'on explique ce que l'on exporte et quelle interface est utilisée.
Le fichier qui importe devra posséder la ligne :
[ImportMany(AllowRecomposition = true)]
        public List<IGrany> Applications { get; set; }

Ensuite dans le même fichier, se trouve une méthode qui possède le code suivant:

MainWindow.cs
AggregateCatalog catalog = new AggregateCatalog(new DirectoryCatalog("Plugins"),
                new AssemblyCatalog(Assembly.GetExecutingAssembly()));
CompositionContainer container = new CompositionContainer(catalog);
container.ComposeParts(this);
           
foreach (var apps in Applications)
{
   ArrayList plugin = new ArrayList();
   plugin.Insert(0, apps.PluginDescription());
   plugin.Insert(1, apps.PluginImageName());
   plugin.Insert(2, apps.PluginName());
   plugin.Insert(3, apps.PluginTitle());
   _dataPlugins.Add(plugin);
}

Les trois premières lignes sont indispensables pour aller chercher les plugins dans le dossier et le reste permet d'en extraire les données de façon indépendante à leur nombre.

On peut dés lors ajouter des dll en quantité dans le dossier et ils seront tous gérés sans modifications du code principale.

Pour une bonne explication sur les bases de MEF, je vous recommande la vidéo suivante: http://channel9.msdn.com/Events/TechDays/TechDays-2011-Belgium/TD029
Enjoy!

FluidKit - ElementFlow

Après avoir vu les transistions, arrêtons nous un instant sur une seconde capacité du FluidKit, l'ElementFlow. Cet élément permet de faire défiler des images de façon fluide et stylée sans avoir besoin de se plonger dans un code sans fin du Xaml.
Tout comme pour l'article précédent, il est indispensable d'ajouter la dll du kit avant tout opération.
Je ne vais pas détailler toutes les options de configuration disponible, mais me contenter de vous offrir une interface contenant l'éssentiel de ce que l'on peut attendre face à une libraire d'images, c'est à dire une interface de visualisation et un "slider".

Code Xaml
MainWindow.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:Controls="clr-namespace:FluidKit.Controls;assembly=FluidKit"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Samples="clr-namespace:Fluid_ElementFlow2" x:Class="Fluid_ElementFlow2.MainWindow"
        mc:Ignorable="d">
    <Window.Resources>
        <Samples:StringCollection x:Key="DataSource" />

        <DataTemplate x:Key="TestDataTemplate"
                      DataType="{x:Type sys:String}">
            <Border x:Name="ElementVisual"
                    Background="White"
                    Padding="5"
                    BorderThickness="5"
                    BorderBrush="LightGray"
                    Grid.Row="0">
                <Image Source="{Binding}"
                       Stretch="Fill" />
            </Border>
        </DataTemplate>

    </Window.Resources>
    <Grid Background="#FF1A1A1A" FocusManager.FocusedElement="{Binding ElementName=_elementFlow}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.5*" />
            <ColumnDefinition Width="0.5*" />
        </Grid.ColumnDefinitions>

        <StackPanel Orientation="Vertical"
                    Grid.Row="1"
                    Grid.Column="0"
                    Grid.ColumnSpan="2"
                    Margin="5">
            <Slider x:Name="_selectedIndexSlider"
                    Minimum="0"
                    Value="0"
                    ValueChanged="ChangeSelectedIndex" />
        </StackPanel>
        <Controls:ElementFlow x:Name="_elementFlow"
                              Grid.Row="0"
                              Grid.Column="0"
                              Grid.ColumnSpan="2"
                              ItemsSource="{DynamicResource DataSource}"
                              ItemTemplate="{DynamicResource TestDataTemplate}"
                              TiltAngle="45"
                              ItemGap="0.4"
                              FrontItemGap="1.0"
                              PopoutDistance="2.2"
                              ElementWidth="600"
                              ElementHeight="400"
                              Margin ="0,-120,0,0"
                              SelectedIndex="{Binding Value, ElementName=_selectedIndexSlider}">
            <Controls:ElementFlow.Layout>
                <Controls:CoverFlow />
            </Controls:ElementFlow.Layout>
            <Controls:ElementFlow.Background>
                <LinearGradientBrush EndPoint="0.5,1"
                                     StartPoint="0.5,0">
                    <GradientStop Color="#FF181818" />
                    <GradientStop Color="#FF7A7A7A"
                                  Offset="0.5" />
                    <GradientStop Color="#FF1A1A1A"
                                  Offset="1" />
                </LinearGradientBrush>
            </Controls:ElementFlow.Background>
            <Controls:ElementFlow.Camera>
                <PerspectiveCamera FieldOfView="50"
                                   Position="0,1,6"
                                   LookDirection="0,-1,-6" />
            </Controls:ElementFlow.Camera>
        </Controls:ElementFlow>

        <TextBlock x:Name="_elementTitle"
                           Foreground="White"
                           FontWeight="Bold"
                           VerticalAlignment="Top"
                           HorizontalAlignment="Center"
                           Margin="10,20,10,10"
                           Grid.Row="0"
                           Grid.Column="0"
                           Grid.ColumnSpan="2"
                           FontSize="30"
                           FontFamily="Arial"
                           Text=""/>
       
        <TextBlock x:Name="_osTitle"
                   Foreground="White"
                   FontWeight="Bold"
                   VerticalAlignment="Top"
                   HorizontalAlignment="Right"
                   Margin="10,10,10,10"
                   Grid.Row="0"
                   Grid.Column="1"
                   FontSize="30"
                   FontFamily="Times New Roman"
                   Text="Grany OS"/>
      </Grid>
</Window>




Code C#
MainWindow.cs

using System;
using System.IO;
using System.Windows;
using FluidKit.Controls;
using System.Collections.Generic;
using System.ComponentModel.Composition;

namespace Fluid_ElementFlow2
{
    public partial class MainWindow
    {
        private StringCollection _dataSource;

        [ImportMany(AllowRecomposition = true)]
        public List<IGrany> Applications { get; set; }
       
  public MainWindow()
  {
   InitializeComponent();
   Loaded += Window1Loaded;
  }

        /// <summary>
        /// Configuration of variables and environment
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
  private void Window1Loaded(object sender, RoutedEventArgs e)
  {
            _elementFlow.Layout = new CoverFlow();
            _dataSource = FindResource("DataSource") as StringCollection;
            AddCards(); // Loading of application's pictures
            _selectedIndexSlider.Maximum = _elementFlow.Items.Count - 1;
            _elementFlow.SelectedIndex = _elementFlow.Items.Count / 2;
  }

               
  /// <summary>
  /// Update informations during navigation between applications
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="args"></param>
        private void ChangeSelectedIndex(object sender, RoutedPropertyChangedEventArgs<double> args)
  {
            int index = (int)args.NewValue;
            string source = _dataSource[index];
            string[] titleWithExtension = source.Split(new Char[] { '\\' });
            string[] titleWithoutExtension = titleWithExtension[titleWithExtension.Length - 1].Split(new Char[] { '.' });
            _elementFlow.SelectedIndex = index;
            _elementTitle.Text = titleWithoutExtension[0];
  }
       
        /// <summary>
        /// Search all the plugins available
        /// </summary>
        private void AddCards()
        {
            string path = Directory.GetCurrentDirectory()+"\\Images";
            string[] fichiers = Directory.GetFiles(path);
            foreach (string fichier in fichiers)
            {
                _dataSource.Insert(_dataSource.Count, fichier);
            }
        }
    }
}



StringCollection.cs

using System.Collections.ObjectModel;
namespace GranyPluginsImplement
{
    public class StringCollection : ObservableCollection<string>
    {
        public StringCollection()
        {
        }
    }
}
 

Avec ces 3 fichiers, vous obtenez une interface simple et agréable que vous pourrez à votre guise personnaliser, le rendu étant le suivant:



Si vous sauhaitez d'avantages de possibilités de ElementFlow, je vous conseille de regarder l'exemple fourni avec le code source.

vendredi 17 février 2012

FluidKit - Transition

Bien que l'on soit un bon programmeur concevant de bons programmes, un point faible qui revient souvent est le design de l'application. Bien qu'une application puisse être performante, il est toujours préférable qu'elle soit également agréable à utiliser. Si comme moi, vous ne possédez pas la passion du graphisme et des jolies transitions entre les pages, il existe des librairies pouvant vous être très utiles.
L'une d'entre elles est FluidKit qui, en plus de ses capacités, est gratuit et ça c'est appréciable. Le projet est disponible en téléchargement sur le lien suivant: Une fois téléchargé, il vous suffit de le compiler de manière à créer un fichier DLL qu'il vous suffira d'ajouter à votre projet. Pour comprendre de quoi il est capable, son exécution vous permettra d'avoir un aperçu de ses capacités.
Des exemples accompagnent toutes ses fonctions mais leur compréhension n'est pas toujours aisées donc dans un premier temps, je donne un exemple d'utilisation de la propriété "Transition".

Code Xaml
<Window x:Class="GranyOS.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:FluidKit.Controls;assembly=FluidKit"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <controls:SlideTransition x:Key="SlideTransition"/>
        <controls:FlipTransition x:Key="FlipTransition"/>
        <controls:CubeTransition x:Key="CubeTransition"/>
    </Window.Resources>
    <Grid>
        <controls:TransitionPresenter Height="200" HorizontalAlignment="Left" Margin="170,60,0,0" Name="contentControl1" VerticalAlignment="Top" Width="300">
            <StackPanel Height="200" x:Name="stackPanel1" Width="300" Background="Chocolate"/>
            <StackPanel Height="200" x:Name="stackPanel2" Width="300" Background="DarkRed"/>
        </controls:TransitionPresenter>
        <Button Content="Cube Transition" Height="58" HorizontalAlignment="Left" Margin="24,51,0,0" Name="button1" VerticalAlignment="Top" Width="123" Click="button1_Click" />
        <Button Content="Flip Transition" Height="58" HorizontalAlignment="Left" Margin="24,127,0,0" Name="button2" VerticalAlignment="Top" Width="123" Click="button2_Click" />
        <Button Content="Slide Transition" Height="58" HorizontalAlignment="Left" Margin="24,202,0,0" Name="button3" VerticalAlignment="Top" Width="123" Click="button3_Click" />
    </Grid>
</Window>

Une fois dans votre code C#, clique-droit sur référence et prenez "ajouter une référence". Dans l'onglet "Parcourir" sélectionnez le fichier "fluidkit.dll" généré par vos soins comme expliqué plus haut.
De ce point là, une instance d'using permet d'ajouter la librairie à votre code et la possibilité d'implémenter la librairie "Controls.Transition".
Code C#
using FluidKit.Controls;

namespace GranyOS
{
    public partial class MainWindow : Window
    {
        private string _currentlyShowingImage = "stackPanel1";
        public MainWindow(){
            InitializeComponent();
        }

        private void button1_Click(object sender, RoutedEventArgs e){
            CubeTransition transition = Resources["CubeTransition"] as CubeTransition;
            if (_currentlyShowingImage == "stackPanel1"){
                transition.Rotation = Direction.LeftToRight;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel1", "stackPanel2");
                _currentlyShowingImage = "stackPanel";
            }
            else{
                transition.Rotation = Direction.RightToLeft;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel2", "stackPanel1");
                _currentlyShowingImage = "stackPanel1";
            }
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            FlipTransition transition = Resources["FlipTransition"] as FlipTransition;
            if (_currentlyShowingImage == "stackPanel1"){
                transition.Rotation = Direction.BottomToTop;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel1", "stackPanel2");
                _currentlyShowingImage = "stackPanel";
            }
            else{
                transition.Rotation = Direction.RightToLeft;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel2", "stackPanel1");
                _currentlyShowingImage = "stackPanel1";
            }
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            SlideTransition transition = Resources["SlideTransition"] as SlideTransition;
            if (_currentlyShowingImage == "stackPanel1"){
                transition.Direction = Direction.LeftToRight;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel1", "stackPanel2");
                _currentlyShowingImage = "stackPanel";
            }
            else{
                transition.Direction = Direction.LeftToRight;
                contentControl1.Transition = transition;
                contentControl1.ApplyTransition("stackPanel2", "stackPanel1");
                _currentlyShowingImage = "stackPanel1";
            }
        }
    }
}

jeudi 16 février 2012

Microsoft Kinect

Le Kinect est un composant utilisé par Microsoft avec leur console XboX360 et déporté par la suite sur les ordinateurs. La version initiale ne peut être connectée au pc que via un câble spécifique alors que la dernière mouture peut se connecter directement en USB et donc de s'affranchir de l'adaptateur.

Kinect Xbox360:

Microsoft Kinect:
La distinction peut se faire facilement grâce au nom affiché sur le matériel. Bien que semblable à la version Xbox, la version PC est légèrement différente dans ses performances. Elle est par exemple capable d'interpréter ce qu'elle voit depuis une distance plus proche.

Depuis le 1 février 2012, le SDK officiel est disponible en téléchargement dans se version finale 1.0 ici et les informations globales relatives au Windows Kinect sur le site Kinect for Windows.

Du fait de sa jeunesse, le SDK 1.0 ne dispose pas encore d'une documentation étoffée, néanmoins un bon moyen de commencer à l'utiliser est de suivre les vidéos disponibles ici et là .

mardi 7 février 2012

A l'inverse de la fin, le commencement est contrôlable

Bienvenue sur mon blog.
Ici seront publiés les secrets les plus enfouis du monde de l'IT, les conversations les plus importantes que se sont échangés les grands visionnaires de notre monde, les pensées les plus profondes des microprocesseurs ainsi que toutes les informations sur le mystère de l'existence d'un chiffre 2 dans le code binaire.
Néanmoins, ces sujets étant fort sensibles, je commencerais par simplement me présenter et advienne que pourra.

Je me nomme Arnaud Bessems, 24ans, bientôt diplômé "Ingénieur industriel en Informatique" et durant les 3 prochains mois, réaliserai un stage au sein du Microsoft Innovation Center de Mons.

De façon à ne pas transformer ce blog en une page facebook, je finirai cette introduction en mentionnant que je suis l'alpha, l'oméga et ce car actuellement mon âge est l'inverse de la grande réponse à la question de la vie, de l'univers et du reste.