diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.classpath b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.classpath
new file mode 100644
index 0000000000000000000000000000000000000000..22f30643cba38503dfc820a64bc4225fd8c743ba
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.project b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.project
new file mode 100644
index 0000000000000000000000000000000000000000..f41fad3044b9aa7a646fb8a6b1196372ae8f27b1
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.pde.PluginNature</nature>
+	</natures>
+</projectDescription>
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.settings/org.eclipse.jdt.core.prefs b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000000000000000000000000000000000..3a21537071bf4118b9e1ee864cb4bc258aa48211
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/META-INF/MANIFEST.MF b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..4c65ec15371140205ab000435823c40cd8c22071
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: RiseClipse IEC61850 SCL Tools UI
+Bundle-Vendor: CentraleSupélec & EDF
+Bundle-SymbolicName: fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui
+Bundle-Version: 1.0.0.qualifier
+Export-Package: fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.application,
+ fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component
+Require-Bundle: fr.centralesupelec.edf.riseclipse.main,
+ fr.centralesupelec.edf.riseclipse.iec61850.scl.validator
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/build.properties b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..f4cfb4e880c051d1184ba3049b396241f6f2272b
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/build.properties
@@ -0,0 +1,19 @@
+#  Copyright (c) 2018 CentraleSup�lec & EDF.
+#  All rights reserved. This program and the accompanying materials
+#  are made available under the terms of the Eclipse Public License v1.0
+#  which accompanies this distribution, and is available at
+#  http://www.eclipse.org/legal/epl-v10.html
+# 
+#  This file is part of the RiseClipse tool
+#  
+#  Contributors:
+#      Computer Science Department, CentraleSup�lec
+#      EDF R&D
+#  Contacts:
+#      dominique.marcadet@centralesupelec.fr
+#      aurelie.dehouck-neveu@edf.fr
+#  Web site:
+#      http://wdi.supelec.fr/software/RiseClipse/
+source.. = src/
+bin.includes = META-INF/,\
+               .
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/pom.xml b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d237a67a7e54c8f28b98788a2158d2da74c13171
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0                       http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+ 
+  <groupId>fr.centralesupelec.edf.riseclipse</groupId>
+  <artifactId>fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>jar</packaging>
+
+  <parent>
+    <groupId>fr.centralesupelec.edf.riseclipse</groupId>
+    <artifactId>RiseClipseValidator_SCL2003</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+
+  <properties>
+    <toolName>RiseClipseSCLValidatorApplication</toolName>
+  </properties>
+
+  <build>
+    <sourceDirectory>src</sourceDirectory>
+    <plugins>
+      <!-- Create a jar file with dependencies included -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>3.0.0</version>
+        <configuration>
+          <!-- set the name of the resulting runnable jar -->
+          <finalName>${toolName}-${project.version}</finalName>
+          <appendAssemblyId>false</appendAssemblyId>
+        </configuration>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui.application.RiseClipseSCLValidatorApplication</mainClass>
+                </transformer>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  <resource>plugin.properties</resource>
+                </transformer>
+              </transformers>
+              <filters>
+                <filter>
+                  <artifact>*:*</artifact>
+                  <excludes>
+                    <exclude>META-INF/*.SF</exclude>
+                    <exclude>META-INF/*.DSA</exclude>
+                    <exclude>META-INF/*.RSA</exclude>
+                  </excludes>
+                </filter>
+              </filters>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  
+  <dependencies>
+    <dependency>
+      <groupId>fr.centralesupelec.edf.riseclipse</groupId>
+      <artifactId>fr.centralesupelec.edf.riseclipse.iec61850.scl.tools</artifactId>
+      <version>1.1.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/application/RiseClipseValidatorSCLApplication.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/application/RiseClipseValidatorSCLApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..b19b74f18162b6e6d8b7714a648a870572de1e37
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/application/RiseClipseValidatorSCLApplication.java
@@ -0,0 +1,93 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.application;
+
+import java.awt.EventQueue;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.swing.JFrame;
+import javax.swing.JTabbedPane;
+
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component.OCLFilePane;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component.SCLFilePane;
+
+import javax.swing.JScrollPane;
+import javax.swing.JPanel;
+
+public class RiseClipseValidatorSCLApplication {
+
+    private JFrame frame;
+    private OCLFilePane oclTree;
+
+    /**
+     * Launch the application.
+     */
+    public static void main( String[] args ) {
+        EventQueue.invokeLater( new Runnable() {
+            public void run() {
+                try {
+                    RiseClipseValidatorSCLApplication window = new RiseClipseValidatorSCLApplication();
+                    window.frame.setVisible( true );
+                }
+                catch( Exception e ) {
+                    e.printStackTrace();
+                }
+            }
+        } );
+    }
+
+    /**
+     * Create the application.
+     */
+    public RiseClipseValidatorSCLApplication() {
+        initialize();
+    }
+
+    /**
+     * Initialize the contents of the frame.
+     */
+    private void initialize() {
+        frame = new JFrame();
+        frame.setTitle( "RiseClipseValidatorSCLApplication" );
+        frame.setBounds( 100, 100, 800, 600 );
+        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
+
+        JTabbedPane tabbedPane = new JTabbedPane( JTabbedPane.TOP );
+        frame.getContentPane().add( tabbedPane );
+
+        JPanel sclPanel = new SCLFilePane( this );
+        tabbedPane.addTab( "SCL Files", null, sclPanel, null );
+
+        JScrollPane oclPane = new JScrollPane();
+        tabbedPane.addTab( "OCL Files", null, oclPane, null );
+
+        File fileRoot = new File( System.getProperty( "user.dir" ) + "/OCL" );
+        oclTree = new OCLFilePane( fileRoot );
+        oclPane.setViewportView( oclTree );
+
+    }
+
+    public ArrayList< File > getOclFiles() {
+        ArrayList< File > oclFiles = new ArrayList<>();
+        oclTree.getOclFiles( oclFiles );
+        return oclFiles;
+    }
+
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/OCLFilePane.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/OCLFilePane.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca0c74de21727ba6f376231a186a116e727f215f
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/OCLFilePane.java
@@ -0,0 +1,118 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.awt.Component;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.swing.JCheckBox;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreePath;
+
+@SuppressWarnings( "serial" )
+public class OCLFilePane extends JTree {
+
+    private DefaultMutableTreeNode root;
+
+    public OCLFilePane( File fileRoot ) {
+        root = new DefaultMutableTreeNode( new SclFileCheckBox( fileRoot ) );
+        setModel( new DefaultTreeModel( root ) );
+        setShowsRootHandles( true );
+
+        createChildren( fileRoot, root );
+
+        setCellRenderer( new SclFileCellRenderer() );
+
+        addMouseListener( new MouseAdapter() {
+            public void mousePressed( MouseEvent e ) {
+                int selRow = getRowForLocation( e.getX(), e.getY() );
+
+                if( selRow != -1 ) {
+                    TreePath selPath = getPathForLocation( e.getX(), e.getY() );
+                    DefaultMutableTreeNode node = (( DefaultMutableTreeNode ) selPath.getLastPathComponent() );
+                    SclFileCheckBox checkbox = ( SclFileCheckBox ) node.getUserObject();
+                    propagateInTree( node, ! checkbox.getCheckBox().isSelected() );
+                    repaint();
+                }
+            }
+            
+            private void propagateInTree( DefaultMutableTreeNode node, boolean selected ) {
+                SclFileCheckBox checkbox = ( SclFileCheckBox ) node.getUserObject();
+                checkbox.getCheckBox().setSelected( selected );
+                for( int i = 0; i < node.getChildCount(); ++i ) {
+                    propagateInTree( ( DefaultMutableTreeNode ) node.getChildAt( i ), selected );
+                }
+            }
+        } );
+
+    }
+
+    private void createChildren( File fileRoot, DefaultMutableTreeNode node ) {
+        File[] files = fileRoot.listFiles();
+        if( files == null ) return;
+
+        for( File file : files ) {
+            DefaultMutableTreeNode childNode = new DefaultMutableTreeNode( new SclFileCheckBox( file ) );
+            node.add( childNode );
+            if( file.isDirectory() ) {
+                createChildren( file, childNode );
+            }
+        }
+    }
+
+    protected class SclFileCellRenderer implements TreeCellRenderer {
+
+        @Override
+        public Component getTreeCellRendererComponent( JTree tree, Object value, boolean selected, boolean expanded,
+                boolean leaf, int row, boolean hasFocus ) {
+            DefaultMutableTreeNode node = ( DefaultMutableTreeNode ) value;
+            SclFileCheckBox file = ( SclFileCheckBox ) node.getUserObject();
+            JCheckBox checkbox = file.getCheckBox();
+            checkbox.setEnabled( isEnabled() );
+            checkbox.setFont( getFont() );
+            checkbox.setFocusPainted( false );
+            checkbox.setBorderPainted( true );
+            return checkbox;
+        }
+    }
+
+    public void getOclFiles( ArrayList< File > oclFiles ) {
+        getOclFiles( root, oclFiles );
+    }
+
+    private void getOclFiles( DefaultMutableTreeNode node, ArrayList< File > oclFiles ) {
+        SclFileCheckBox checkbox = ( SclFileCheckBox ) node.getUserObject();
+        if( checkbox.getFile().isFile() ) {
+            if( checkbox.getCheckBox().isSelected() ) {
+                oclFiles.add( checkbox.getFile() );
+            }
+        }
+        else {
+            for( int i = 0; i < node.getChildCount(); ++i ) {
+                getOclFiles( ( DefaultMutableTreeNode ) node.getChildAt( i ), oclFiles );
+            }
+        }
+    }
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultFrame.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultFrame.java
new file mode 100644
index 0000000000000000000000000000000000000000..e17f9200b686bbb3cb999162692c4432aeadc96a
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultFrame.java
@@ -0,0 +1,54 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import javax.swing.JFrame;
+import javax.swing.JTabbedPane;
+
+import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
+
+@SuppressWarnings( "serial" )
+public class ResultFrame extends JFrame {
+
+    private JTabbedPane tabbedPane;
+
+    public ResultFrame() {
+        setTitle( "RiseClipseValidatorSCL results" );
+        setBounds( 200, 200, 800, 600 );
+        
+        tabbedPane = new JTabbedPane( JTabbedPane.TOP );
+        getContentPane().add( tabbedPane );
+        
+        setVisible( true );
+    }
+    
+    public IRiseClipseConsole getMainConsole() {
+        ResultPane console = new ResultPane( null, false );
+        tabbedPane.addTab( "RiseClipseValidatorSCL", null, console, null );
+        return console;
+    }
+
+    public IRiseClipseConsole getConsoleFor( String filename ) {
+        ResultPane result = new ResultPane( filename, true );
+        String name = filename.substring( filename.lastIndexOf( '/' ) + 1 );
+        tabbedPane.addTab( name, null, result, null );
+        return result;
+    }
+    
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultPane.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultPane.java
new file mode 100644
index 0000000000000000000000000000000000000000..86eb6ef8d204bed85e4a89799d6f1452765b7217
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/ResultPane.java
@@ -0,0 +1,256 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.awt.BorderLayout;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
+import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
+
+@SuppressWarnings( "serial" )
+public class ResultPane extends JPanel implements IRiseClipseConsole, ActionListener {
+    
+    private final static String newline = "\n";
+    
+    private ArrayList< Integer > levels;
+    private ArrayList< String > messages;
+    private JCheckBox cbVerbose;
+    private JCheckBox cbInfo;
+    private JCheckBox cbWarning;
+    private JCheckBox cbError;
+    private JTextArea text;
+
+    private JButton btnOpenFile;
+
+    private JButton btnSaveResults;
+
+    private String filename;
+
+    public ResultPane( String filename, boolean withButtons ) {
+        this.filename = filename;
+        
+        levels = new ArrayList<>();
+        messages = new ArrayList<>();
+
+        setLayout( new BorderLayout( 0, 0 ));
+        
+        JPanel cbPanel = new JPanel();
+        add( cbPanel, BorderLayout.NORTH );
+
+        cbVerbose = new JCheckBox( "Verbose" );
+        cbVerbose.setSelected( false );
+        cbVerbose.addActionListener( this );
+        cbPanel.add( cbVerbose );
+
+        cbInfo = new JCheckBox( "Info" );
+        cbInfo.setSelected( true );
+        cbInfo.addActionListener( this );
+        cbPanel.add( cbInfo );
+
+        cbWarning = new JCheckBox( "Warning" );
+        cbWarning.setSelected( true );
+        cbWarning.addActionListener( this );
+        cbPanel.add( cbWarning );
+
+        cbError = new JCheckBox( "Error" );
+        cbError.setSelected( true );
+        cbError.addActionListener( this );
+        cbPanel.add( cbError );
+        
+        text = new JTextArea( 0, 0 );
+        text.setEditable( false );
+
+        JScrollPane scrollPane = new JScrollPane( text );
+        add( scrollPane, BorderLayout.CENTER );
+
+        JPanel btnPanel = new JPanel();
+        add( btnPanel, BorderLayout.SOUTH );
+
+        if( withButtons ) {
+            btnOpenFile = new JButton( "Open file" );
+            btnOpenFile.addActionListener( this );
+            btnPanel.add( btnOpenFile );
+    
+            btnSaveResults = new JButton( "Save results" );
+            btnSaveResults.addActionListener( this );
+            btnPanel.add( btnSaveResults );
+        }
+    }
+
+    @Override
+    public void paint( Graphics g ) {
+        text.setText( allMesages() );
+
+        super.paint( g );
+    }
+    
+    private String allMesages() {
+        StringBuffer buf = new StringBuffer();
+        
+        for( int i = 0; i < messages.size(); ++i ) {
+            boolean display = cbVerbose.isSelected();
+            String level = "VERBOSE";
+            switch( levels.get( i )) {
+            case IRiseClipseConsole.VERBOSE_LEVEL:
+                break;
+            case IRiseClipseConsole.INFO_LEVEL:
+                display = cbInfo.isSelected();
+                level = "INFO";
+                break;
+            case IRiseClipseConsole.WARNING_LEVEL:
+                display = cbWarning.isSelected();
+                level = "WARNING";
+                break;
+            case IRiseClipseConsole.ERROR_LEVEL:
+                display = cbError.isSelected();
+                level = "ERROR";
+                break;
+            }
+            if( display ) {
+                String m = messages.get( i );
+                if(( m.length() > 0 ) && ( m.charAt( 0 ) == '\t' )) {
+                    buf.append( level + ":" + m + newline );
+                }
+                else {
+                    buf.append( level + ":\t" + m + newline );
+                }
+            }
+        }
+
+        return buf.toString();
+    }
+
+    @Override
+    public int setLevel( int level ) {
+        // We keep all messages
+        return IRiseClipseConsole.VERBOSE_LEVEL;
+    }
+
+    @Override
+    public void verbose( Object o ) {
+        levels.add( IRiseClipseConsole.VERBOSE_LEVEL );
+        messages.add( o.toString() );
+    }
+
+    @Override
+    public void info( Object o ) {
+        levels.add( IRiseClipseConsole.INFO_LEVEL );
+        messages.add( o.toString() );
+    }
+
+    @Override
+    public void warning( Object o ) {
+        levels.add( IRiseClipseConsole.WARNING_LEVEL );
+        messages.add( o.toString() );
+    }
+
+    @Override
+    public void error( Object o ) {
+        levels.add( IRiseClipseConsole.ERROR_LEVEL );
+        messages.add( o.toString() );
+    }
+
+    @Override
+    public void fatal( Object o ) {
+        levels.add( IRiseClipseConsole.FATAL_LEVEL );
+        messages.add( o.toString() );
+    }
+
+    @Override
+    public void actionPerformed( ActionEvent e ) {
+        Object source = e.getSource();
+        
+        if(( source == cbVerbose ) || ( source == cbInfo ) || ( source == cbWarning ) || ( source == cbError )) {
+            // The state of the checkbox is directly tested, so just repaint
+            repaint();
+            return;
+        }
+        
+        if( source == btnOpenFile ) {
+            
+            JFrame frame = new JFrame( filename ); 
+            frame.setBounds( 300, 300, 900, 700 );
+            
+            JTextArea textArea = new JTextArea();
+            try {
+                BufferedReader br = new BufferedReader( new FileReader( filename ));
+                textArea.read( br, null );
+                br.close();
+            }
+            catch( IOException ex ) {
+                AbstractRiseClipseConsole.getConsole().error( ex.getMessage() );
+                return;
+            }
+            
+            JScrollPane scrollPane = new JScrollPane( textArea );
+            TextLineNumber tln = new TextLineNumber( textArea );
+            scrollPane.setRowHeaderView( tln );
+            frame.getContentPane().add( scrollPane );
+            
+            frame.setVisible( true );
+
+            return;
+        }
+        
+        if( source == btnSaveResults ) {
+            JFileChooser fileChooser = new JFileChooser();
+            if( fileChooser.showSaveDialog( this ) == JFileChooser.APPROVE_OPTION ) {
+                File file = fileChooser.getSelectedFile();
+                try {
+                    BufferedWriter writer = new BufferedWriter( new FileWriter( file ));
+                    writer.write( allMesages() );
+                    writer.close();
+                }
+                catch( IOException ex ) {
+                    AbstractRiseClipseConsole.getConsole().error( ex.getMessage() );
+                }
+            }
+            
+        }
+    }
+
+    @Override
+    public void displayIdenticalMessages() {
+        // Not taken into account for the moment
+    }
+
+    @Override
+    public void doNotDisplayIdenticalMessages() {
+        // Not taken into account for the moment
+    }
+
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SCLFilePane.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SCLFilePane.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c03ee3cb223648ab63b78766439cca4781c48a7
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SCLFilePane.java
@@ -0,0 +1,109 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.RiseClipseValidatorSCL;
+import fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.application.RiseClipseValidatorSCLApplication;
+import fr.centralesupelec.edf.riseclipse.util.AbstractRiseClipseConsole;
+import fr.centralesupelec.edf.riseclipse.util.IRiseClipseConsole;
+
+@SuppressWarnings( "serial" )
+public class SCLFilePane extends JPanel implements ActionListener {
+
+    private JButton btnAddSclFile;
+    private JButton btnValidate;
+    private SclFileList sclFilesList;
+    private RiseClipseValidatorSCLApplication application;
+
+    public SCLFilePane( RiseClipseValidatorSCLApplication application ) {
+        this.application = application;
+        
+        setLayout( new BorderLayout( 0, 0 ));
+
+        JPanel btnPanel = new JPanel();
+        add( btnPanel, BorderLayout.SOUTH );
+
+        btnAddSclFile = new JButton( "Add SCL file" );
+        btnAddSclFile.addActionListener( this );
+        btnPanel.add( btnAddSclFile );
+
+        btnValidate = new JButton( "Validate" );
+        btnValidate.addActionListener( this );
+        btnPanel.add( btnValidate );
+
+        JScrollPane sclFilesPane = new JScrollPane();
+        add( sclFilesPane, BorderLayout.CENTER );
+        
+        sclFilesList = new SclFileList();
+        sclFilesPane.setViewportView( sclFilesList );
+    }
+
+    @Override
+    public void actionPerformed( ActionEvent e ) {
+        Object source = e.getSource();
+
+        if( source == btnAddSclFile ) {
+            JFileChooser fileChooser = new JFileChooser();
+            if( fileChooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION ) {
+                sclFilesList.add( fileChooser.getSelectedFile() );
+            }
+            return;
+        }
+
+        if( source == btnValidate ) {
+            ArrayList< File > oclFiles = application.getOclFiles();
+            List< String > oclFileNames =
+                    oclFiles
+                    .stream()
+                    .map( f -> f.getAbsolutePath() )
+                    .collect( Collectors.toList() );
+            
+            ArrayList< String > sclFiles = sclFilesList.getSclFiles();
+
+            ResultFrame result = new ResultFrame();
+            
+            IRiseClipseConsole console = result.getMainConsole();
+            AbstractRiseClipseConsole.changeConsole( console );
+            RiseClipseValidatorSCL.displayLegal( );
+            RiseClipseValidatorSCL.prepare( oclFileNames, null, false );
+            result.repaint();
+            for( int i = 0; i < sclFiles.size(); ++i ) {
+                console = result.getConsoleFor( sclFiles.get( i ));
+                AbstractRiseClipseConsole.changeConsole( console );
+                RiseClipseValidatorSCL.run( true, sclFiles.get( i ));
+                result.repaint();
+            }
+
+            return;
+        }
+    }
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileCheckBox.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileCheckBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc3884dfd294824f81f29514f80ec9f6c6bedc58
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileCheckBox.java
@@ -0,0 +1,43 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.io.File;
+
+import javax.swing.JCheckBox;
+
+public class SclFileCheckBox {
+
+    private File file;
+    private JCheckBox checkBox;
+
+    public SclFileCheckBox( File file ) {
+        this.file = file;
+        this.checkBox = new JCheckBox( file.getName() );
+        this.checkBox.setSelected( true );
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public JCheckBox getCheckBox() {
+        return checkBox;
+    }
+}
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileList.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileList.java
new file mode 100644
index 0000000000000000000000000000000000000000..f19f41497d3fd4073cc4c149f4dafbd42a2552ee
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/SclFileList.java
@@ -0,0 +1,109 @@
+/**
+ *  Copyright (c) 2018 CentraleSupélec & EDF.
+ *  All rights reserved. This program and the accompanying materials
+ *  are made available under the terms of the Eclipse Public License v1.0
+ *  which accompanies this distribution, and is available at
+ *  http://www.eclipse.org/legal/epl-v10.html
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Contributors:
+ *      Computer Science Department, CentraleSupélec
+ *      EDF R&D
+ *  Contacts:
+ *      dominique.marcadet@centralesupelec.fr
+ *      aurelie.dehouck-neveu@edf.fr
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.awt.Component;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JCheckBox;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+import javax.swing.ListSelectionModel;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
+
+/*
+ * Adapted from http://www.devx.com/tips/Tip/5342
+ */
+@SuppressWarnings( "serial" )
+public class SclFileList extends JList< SclFileCheckBox > {
+    
+    protected static Border noFocusBorder = new EmptyBorder( 1, 1, 1, 1 );
+    
+    private DefaultListModel< SclFileCheckBox > model;
+
+    public SclFileList() {
+        model = new DefaultListModel< SclFileCheckBox >();
+        setModel( model );
+        
+        setCellRenderer( new SclFileCellRenderer() );
+
+        addMouseListener( new MouseAdapter() {
+            public void mousePressed( MouseEvent e ) {
+                int index = locationToIndex( e.getPoint() );
+
+                if( index != -1 ) {
+                    JCheckBox checkbox = getModel().getElementAt( index ).getCheckBox();
+                    checkbox.setSelected( !checkbox.isSelected() );
+                    repaint();
+                }
+            }
+        } );
+
+        setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
+    }
+
+    public void add( File file ) {
+        for( int i = 0; i < model.size(); ++i ) {
+            if( model.getElementAt( i ).getFile().getAbsolutePath().equals( file.getAbsolutePath() )) {
+                return;
+            }
+        }
+        
+        SclFileCheckBox check = new SclFileCheckBox( file );
+        model.addElement( check );
+    }
+
+    protected class SclFileCellRenderer implements ListCellRenderer< SclFileCheckBox > {
+
+        @Override
+        public Component getListCellRendererComponent( JList< ? extends SclFileCheckBox > list, SclFileCheckBox file, int index,
+                boolean isSelected, boolean cellHasFocus ) {
+            JCheckBox checkbox = file.getCheckBox();
+            checkbox.setBackground( isSelected ? getSelectionBackground() : getBackground() );
+            checkbox.setForeground( isSelected ? getSelectionForeground() : getForeground() );
+            checkbox.setEnabled( isEnabled() );
+            checkbox.setFont( getFont() );
+            checkbox.setFocusPainted( false );
+            checkbox.setBorderPainted( true );
+            checkbox.setBorder( isSelected ? UIManager.getBorder( "List.focusCellHighlightBorder" ) : noFocusBorder );
+            return checkbox;
+        }
+    }
+
+    public ArrayList< String > getSclFiles() {
+        ArrayList< String > sclFiles = new ArrayList< String >();
+        
+        for( int i = 0; i < model.size(); ++i ) {
+            if( model.getElementAt( i ).getCheckBox().isSelected() ) {
+                sclFiles.add( model.getElementAt( i ).getFile().getAbsolutePath() );
+            }
+        }
+        
+        return sclFiles;
+    }
+
+}
+
+
diff --git a/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/TextLineNumber.java b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/TextLineNumber.java
new file mode 100644
index 0000000000000000000000000000000000000000..54c75ff54951e5566082673fa5ec7ed6c8608765
--- /dev/null
+++ b/fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui/src/fr/centralesupelec/edf/riseclipse/iec61850/scl/validator/ui/component/TextLineNumber.java
@@ -0,0 +1,467 @@
+/*
+ * Code from: https://tips4java.wordpress.com/2009/05/23/text-component-line-number/
+ * Posted by Rob Camick on May 23, 2009
+ * 
+ * There is no explicit license, but the web site says:
+ *   We assume no responsibility for the code. You are free to use and/or modify and/or distribute any or
+ *   all code posted on the Java Tips Weblog without restriction. A credit in the code comments would be nice,
+ *   but not in any way mandatory.We assume no responsibility for the code. You are free to use and/or modify
+ *   and/or distribute any or all code posted on the Java Tips Weblog without restriction. A credit in the code
+ *   comments would be nice, but not in any way mandatory.
+ */
+
+/*
+ * 
+ *  This file is part of the RiseClipse tool
+ *  
+ *  Web site:
+ *      http://wdi.supelec.fr/software/RiseClipse/
+ */
+package fr.centralesupelec.edf.riseclipse.iec61850.scl.validator.ui.component;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.MatteBorder;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Element;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.Utilities;
+
+
+/**
+ *  This class will display line numbers for a related text component. The text
+ *  component must use the same line height for each line. TextLineNumber
+ *  supports wrapped lines and will highlight the line number of the current
+ *  line in the text component.
+ *
+ *  This class was designed to be used as a component added to the row header
+ *  of a JScrollPane.
+ */
+@SuppressWarnings( "serial" )
+public class TextLineNumber extends JPanel implements CaretListener, DocumentListener, PropertyChangeListener {
+    public final static float LEFT = 0.0f;
+    public final static float CENTER = 0.5f;
+    public final static float RIGHT = 1.0f;
+
+    private final static Border OUTER = new MatteBorder( 0, 0, 0, 2, Color.GRAY );
+
+    private final static int HEIGHT = Integer.MAX_VALUE - 1000000;
+
+    //  Text component this TextTextLineNumber component is in sync with
+
+    private JTextComponent component;
+
+    //  Properties that can be changed
+
+    private boolean updateFont;
+    private int borderGap;
+    private Color currentLineForeground;
+    private float digitAlignment;
+    private int minimumDisplayDigits;
+
+    //  Keep history information to reduce the number of times the component
+    //  needs to be repainted
+
+    private int lastDigits;
+    private int lastHeight;
+    private int lastLine;
+
+    private HashMap< String, FontMetrics > fonts;
+
+    /**
+     *  Create a line number component for a text component. This minimum
+     *  display width will be based on 3 digits.
+     *
+     *  @param component  the related text component
+     */
+    public TextLineNumber( JTextComponent component ) {
+        this( component, 3 );
+    }
+
+    /**
+     *  Create a line number component for a text component.
+     *
+     *  @param component  the related text component
+     *  @param minimumDisplayDigits  the number of digits used to calculate
+     *                               the minimum width of the component
+     */
+    public TextLineNumber( JTextComponent component, int minimumDisplayDigits ) {
+        this.component = component;
+
+        setFont( component.getFont() );
+
+        setBorderGap( 5 );
+        setCurrentLineForeground( Color.RED );
+        setDigitAlignment( RIGHT );
+        setMinimumDisplayDigits( minimumDisplayDigits );
+
+        component.getDocument().addDocumentListener( this );
+        component.addCaretListener( this );
+        component.addPropertyChangeListener( "font", this );
+    }
+
+    /**
+     *  Gets the update font property
+     *
+     *  @return the update font property
+     */
+    public boolean getUpdateFont() {
+        return updateFont;
+    }
+
+    /**
+     *  Set the update font property. Indicates whether this Font should be
+     *  updated automatically when the Font of the related text component
+     *  is changed.
+     *
+     *  @param updateFont  when true update the Font and repaint the line
+     *                     numbers, otherwise just repaint the line numbers.
+     */
+    public void setUpdateFont( boolean updateFont ) {
+        this.updateFont = updateFont;
+    }
+
+    /**
+     *  Gets the border gap
+     *
+     *  @return the border gap in pixels
+     */
+    public int getBorderGap() {
+        return borderGap;
+    }
+
+    /**
+     *  The border gap is used in calculating the left and right insets of the
+     *  border. Default value is 5.
+     *
+     *  @param borderGap  the gap in pixels
+     */
+    public void setBorderGap( int borderGap ) {
+        this.borderGap = borderGap;
+        Border inner = new EmptyBorder( 0, borderGap, 0, borderGap );
+        setBorder( new CompoundBorder( OUTER, inner ) );
+        lastDigits = 0;
+        setPreferredWidth();
+    }
+
+    /**
+     *  Gets the current line rendering Color
+     *
+     *  @return the Color used to render the current line number
+     */
+    public Color getCurrentLineForeground() {
+        return currentLineForeground == null ? getForeground() : currentLineForeground;
+    }
+
+    /**
+     *  The Color used to render the current line digits. Default is Coolor.RED.
+     *
+     *  @param currentLineForeground  the Color used to render the current line
+     */
+    public void setCurrentLineForeground( Color currentLineForeground ) {
+        this.currentLineForeground = currentLineForeground;
+    }
+
+    /**
+     *  Gets the digit alignment
+     *
+     *  @return the alignment of the painted digits
+     */
+    public float getDigitAlignment() {
+        return digitAlignment;
+    }
+
+    /**
+     *  Specify the horizontal alignment of the digits within the component.
+     *  Common values would be:
+     *  <ul>
+     *  <li>TextLineNumber.LEFT
+     *  <li>TextLineNumber.CENTER
+     *  <li>TextLineNumber.RIGHT (default)
+     *  </ul>
+     *  @param currentLineForeground  the Color used to render the current line
+     */
+    public void setDigitAlignment( float digitAlignment ) {
+        this.digitAlignment = digitAlignment > 1.0f ? 1.0f : digitAlignment < 0.0f ? -1.0f : digitAlignment;
+    }
+
+    /**
+     *  Gets the minimum display digits
+     *
+     *  @return the minimum display digits
+     */
+    public int getMinimumDisplayDigits() {
+        return minimumDisplayDigits;
+    }
+
+    /**
+     *  Specify the mimimum number of digits used to calculate the preferred
+     *  width of the component. Default is 3.
+     *
+     *  @param minimumDisplayDigits  the number digits used in the preferred
+     *                               width calculation
+     */
+    public void setMinimumDisplayDigits( int minimumDisplayDigits ) {
+        this.minimumDisplayDigits = minimumDisplayDigits;
+        setPreferredWidth();
+    }
+
+    /**
+     *  Calculate the width needed to display the maximum line number
+     */
+    private void setPreferredWidth() {
+        Element root = component.getDocument().getDefaultRootElement();
+        int lines = root.getElementCount();
+        int digits = Math.max( String.valueOf( lines ).length(), minimumDisplayDigits );
+
+        //  Update sizes when number of digits in the line number changes
+
+        if( lastDigits != digits ) {
+            lastDigits = digits;
+            FontMetrics fontMetrics = getFontMetrics( getFont() );
+            int width = fontMetrics.charWidth( '0' ) * digits;
+            Insets insets = getInsets();
+            int preferredWidth = insets.left + insets.right + width;
+
+            Dimension d = getPreferredSize();
+            d.setSize( preferredWidth, HEIGHT );
+            setPreferredSize( d );
+            setSize( d );
+        }
+    }
+
+    /**
+     *  Draw the line numbers
+     */
+    @Override
+    public void paintComponent( Graphics g ) {
+        super.paintComponent( g );
+
+        //  Determine the width of the space available to draw the line number
+
+        FontMetrics fontMetrics = component.getFontMetrics( component.getFont() );
+        Insets insets = getInsets();
+        int availableWidth = getSize().width - insets.left - insets.right;
+
+        //  Determine the rows to draw within the clipped bounds.
+
+        Rectangle clip = g.getClipBounds();
+        int rowStartOffset = component.viewToModel( new Point( 0, clip.y ) );
+        int endOffset = component.viewToModel( new Point( 0, clip.y + clip.height ) );
+
+        while( rowStartOffset <= endOffset ) {
+            try {
+                if( isCurrentLine( rowStartOffset ) )
+                    g.setColor( getCurrentLineForeground() );
+                else
+                    g.setColor( getForeground() );
+
+                //  Get the line number as a string and then determine the
+                //  "X" and "Y" offsets for drawing the string.
+
+                String lineNumber = getTextLineNumber( rowStartOffset );
+                int stringWidth = fontMetrics.stringWidth( lineNumber );
+                int x = getOffsetX( availableWidth, stringWidth ) + insets.left;
+                int y = getOffsetY( rowStartOffset, fontMetrics );
+                g.drawString( lineNumber, x, y );
+
+                //  Move to the next row
+
+                rowStartOffset = Utilities.getRowEnd( component, rowStartOffset ) + 1;
+            }
+            catch( Exception e ) {
+                break;
+            }
+        }
+    }
+
+    /*
+     *  We need to know if the caret is currently positioned on the line we
+     *  are about to paint so the line number can be highlighted.
+     */
+    private boolean isCurrentLine( int rowStartOffset ) {
+        int caretPosition = component.getCaretPosition();
+        Element root = component.getDocument().getDefaultRootElement();
+
+        if( root.getElementIndex( rowStartOffset ) == root.getElementIndex( caretPosition ) )
+            return true;
+        else
+            return false;
+    }
+
+    /*
+     *  Get the line number to be drawn. The empty string will be returned
+     *  when a line of text has wrapped.
+     */
+    protected String getTextLineNumber( int rowStartOffset ) {
+        Element root = component.getDocument().getDefaultRootElement();
+        int index = root.getElementIndex( rowStartOffset );
+        Element line = root.getElement( index );
+
+        if( line.getStartOffset() == rowStartOffset )
+            return String.valueOf( index + 1 );
+        else
+            return "";
+    }
+
+    /*
+     *  Determine the X offset to properly align the line number when drawn
+     */
+    private int getOffsetX( int availableWidth, int stringWidth ) {
+        return ( int ) ( ( availableWidth - stringWidth ) * digitAlignment );
+    }
+
+    /*
+     *  Determine the Y offset for the current row
+     */
+    private int getOffsetY( int rowStartOffset, FontMetrics fontMetrics ) throws BadLocationException {
+        //  Get the bounding rectangle of the row
+
+        Rectangle r = component.modelToView( rowStartOffset );
+        int lineHeight = fontMetrics.getHeight();
+        int y = r.y + r.height;
+        int descent = 0;
+
+        //  The text needs to be positioned above the bottom of the bounding
+        //  rectangle based on the descent of the font(s) contained on the row.
+
+        if( r.height == lineHeight ) // default font is being used
+        {
+            descent = fontMetrics.getDescent();
+        }
+        else // We need to check all the attributes for font changes
+        {
+            if( fonts == null ) fonts = new HashMap< String, FontMetrics >();
+
+            Element root = component.getDocument().getDefaultRootElement();
+            int index = root.getElementIndex( rowStartOffset );
+            Element line = root.getElement( index );
+
+            for( int i = 0; i < line.getElementCount(); i++ ) {
+                Element child = line.getElement( i );
+                AttributeSet as = child.getAttributes();
+                String fontFamily = ( String ) as.getAttribute( StyleConstants.FontFamily );
+                Integer fontSize = ( Integer ) as.getAttribute( StyleConstants.FontSize );
+                String key = fontFamily + fontSize;
+
+                FontMetrics fm = fonts.get( key );
+
+                if( fm == null ) {
+                    Font font = new Font( fontFamily, Font.PLAIN, fontSize );
+                    fm = component.getFontMetrics( font );
+                    fonts.put( key, fm );
+                }
+
+                descent = Math.max( descent, fm.getDescent() );
+            }
+        }
+
+        return y - descent;
+    }
+
+    //
+    //  Implement CaretListener interface
+    //
+    @Override
+    public void caretUpdate( CaretEvent e ) {
+        //  Get the line the caret is positioned on
+
+        int caretPosition = component.getCaretPosition();
+        Element root = component.getDocument().getDefaultRootElement();
+        int currentLine = root.getElementIndex( caretPosition );
+
+        //  Need to repaint so the correct line number can be highlighted
+
+        if( lastLine != currentLine ) {
+            repaint();
+            lastLine = currentLine;
+        }
+    }
+
+    //
+    //  Implement DocumentListener interface
+    //
+    @Override
+    public void changedUpdate( DocumentEvent e ) {
+        documentChanged();
+    }
+
+    @Override
+    public void insertUpdate( DocumentEvent e ) {
+        documentChanged();
+    }
+
+    @Override
+    public void removeUpdate( DocumentEvent e ) {
+        documentChanged();
+    }
+
+    /*
+     *  A document change may affect the number of displayed lines of text.
+     *  Therefore the lines numbers will also change.
+     */
+    private void documentChanged() {
+        //  View of the component has not been updated at the time
+        //  the DocumentEvent is fired
+
+        SwingUtilities.invokeLater( new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    int endPos = component.getDocument().getLength();
+                    Rectangle rect = component.modelToView( endPos );
+
+                    if( rect != null && rect.y != lastHeight ) {
+                        setPreferredWidth();
+                        repaint();
+                        lastHeight = rect.y;
+                    }
+                }
+                catch( BadLocationException ex ) {
+                    /* nothing to do */ }
+            }
+        } );
+    }
+
+    //
+    //  Implement PropertyChangeListener interface
+    //
+    @Override
+    public void propertyChange( PropertyChangeEvent evt ) {
+        if( evt.getNewValue() instanceof Font ) {
+            if( updateFont ) {
+                Font newFont = ( Font ) evt.getNewValue();
+                setFont( newFont );
+                lastDigits = 0;
+                setPreferredWidth();
+            }
+            else {
+                repaint();
+            }
+        }
+    }
+
+}
+
+
diff --git a/pom.xml b/pom.xml
index 1b9e8d3559b7737d8ba5b9daf72c13e0a630e687..4bf8e2d1f676bd4ec7f0ff15336f8eba77932bc2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -147,6 +147,7 @@
 
   <modules>
     <module>fr.centralesupelec.edf.riseclipse.iec61850.scl.tools</module>
+    <module>fr.centralesupelec.edf.riseclipse.iec61850.scl.tools.ui</module>
   </modules>
 
 </project>