public final class ActionBindingMessages {

  /* Interpreter errors */
  public static final String SCILAB_SAMECOMMAND = Messages.gettext("Same command executed again");
  public static final String SCILAB_UNABLE =
      Messages.gettext("Unable to communicate with the interpreter");

  /** This class is a static singleton, thus it must not be instantiated */
  private ActionBindingMessages() {}
}
  private boolean canWriteFile(String name) {
    if (new File(name).exists()) {
      Component c = DrawerVisitor.getVisitor(figureUID).getComponent();
      Window parentWindow = (Window) SwingUtilities.getAncestorOfClass(Window.class, c);
      int actionDialog =
          JOptionPane.showConfirmDialog(
              parentWindow,
              Messages.gettext("Replace existing file?"),
              Messages.gettext("File already exists"),
              JOptionPane.YES_NO_OPTION);
      if (actionDialog != JOptionPane.YES_OPTION) {
        return false;
      }
    }

    return true;
  }
 /** Change Global property forceGLCanvas if no GLJPanel is available, GLCanvas is forced */
 public static boolean switchToGLCanvas(boolean onOrOff) {
   Debug.DEBUG("SwingScilabCanvasImpl", "switchToGLCanvas " + onOrOff);
   if (!onOrOff && noGLJPanel) {
     InterpreterManagement.requestScilabExec(
         Messages.gettext(
             "disp(\"WARNING: Despite of our previous warning, you choose to use Scilab with advanced graphics capabilities. Type \"\"help usecanvas\"\" for more information.\")"));
   }
   enableGLCanvas = onOrOff;
   return enableGLCanvas;
 }
  /** Manage the export (bitmap/vectorial format) and export errors */
  public void exportManager() {
    // get the extension of the fileName chosen by the user (can be 'null')
    String userExtension = getExtension(this.exportName);

    if (userExtension == null) {
      // fileName without extension + "by extension (.*)" selected
      JOptionPane.showMessageDialog(
          this,
          Messages.gettext("Please specify a file format"),
          Messages.gettext("Error on export"),
          JOptionPane.ERROR_MESSAGE);
      return;
    } else if (userExtension.equals(bmp)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(gif)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(jpg[0]) || userExtension.equals(jpg[1])) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(png)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(ppm)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(emf)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(eps)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(pdf)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(svg)) {
      vectorialExport(userExtension);
    } else {
      // fileName with a wrong extension + "by extension (.*)" selected
      JOptionPane.showMessageDialog(
          this,
          String.format(
              Messages.gettext(
                  "Unrecognized extension '%s'.\n Please specify a valid file format."),
              userExtension),
          Messages.gettext("Error on export"),
          JOptionPane.ERROR_MESSAGE);
      return;
    }
  }
 /**
  * Execute the code in example
  *
  * @param pre the preformatted Element containing Scilab's code
  */
 public void execExample(Element pre) {
   String code = getCode(pre);
   try {
     ScilabConsole.getConsole()
         .getAsSimpleConsole()
         .sendCommandsToScilab(code, true /* display */, false /* store in history */);
   } catch (NoClassDefFoundError e) {
     ScilabModalDialog.show(
         (SimpleTab) SwingUtilities.getAncestorOfClass(SimpleTab.class, x),
         Messages.gettext("Feature not available in this mode..."));
   }
 }
  /**
   * Get the variable editor singleton with specified data.
   *
   * @param type the variable type
   * @param data : the data to fill the editor with
   * @param variableName : the scilab name of the variable being edited.
   * @return the Variable Editor
   */
  public static ScilabVariableEditor getVariableEditor(
      final String type, final Object[][] data, final String variableName) {
    if (instance == null) {
      try {
        SwingUtilities.invokeAndWait(
            new Runnable() {
              public void run() {
                instance = new ScilabVariableEditor(type, data, variableName);
                instance.setVisible(true);
              }
            });
      } catch (Exception e) {
        System.err.println(e);
      }
    } else {
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              SwingScilabWindow window =
                  (SwingScilabWindow)
                      SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, editorTab);
              window.setVisible(true);
              window.toFront();
              final JTable table = editorTab.getCurrentTable();
              int r = -1;
              int c = -1;

              if (table != null) {
                r = table.getSelectedRow();
                c = table.getSelectedColumn();
              }
              boolean b = map.containsKey(variableName);
              instance.updateData(variableName, type, data);
              if (b && r != -1 && c != -1) {
                table.setRowSelectionInterval(r, r);
                table.setColumnSelectionInterval(c, c);
              }
            }
          });
    }

    editorTab.setName(
        Messages.gettext("Variable Editor") + " - " + variableName + "  (" + type + ")");
    return instance;
  }
/**
 * Class to retrieve object from the xml configuration file
 *
 * @author Calixte DENIZET
 */
public class XConfiguration {

  // User configuration file
  private static final String USER_CONFIG_FILE =
      ScilabConstants.SCIHOME.toString() + "/XConfiguration.xml";
  private static final String SCI = System.getenv("SCI");
  private static final String SCILAB_CONFIG_FILE =
      SCI + "/modules/preferences/etc/XConfiguration.xml";

  private static final String ERROR_READ = Messages.gettext("Could not load file: ");
  private static final String ERROR_WRITE = Messages.gettext("Could not write the file: ");
  private static final String SEVERE_ERROR =
      Messages.gettext("A severe error occurred: cannot load the preferences file.");
  private static final String PARSING_ERROR =
      Messages.gettext(
          "An error occurred when loading the preferences file, try to reload the default one.");

  private static final XPathFactory xpathFactory = XPathFactory.newInstance();
  private static final Map<Class<?>, StringParser> conv = new HashMap<Class<?>, StringParser>();

  private static final EventListenerList listenerList = new EventListenerList();
  private static final Set<String> modifiedPaths = new HashSet<String>();

  private static Document doc;
  private static boolean hasBeenRead;

  static {
    addXConfigurationListener(ScilabGeneralPrefs.getInstance());

    try {
      Class histoprefs =
          ClassLoader.getSystemClassLoader()
              .loadClass("org.scilab.modules.history_manager.HistoryPrefs");
      Method getinstance = histoprefs.getDeclaredMethod("getInstance");
      addXConfigurationListener((XConfigurationListener) getinstance.invoke(null));
    } catch (ClassNotFoundException e) {
      // Nothing displayed (always occurs in MN mode)
    } catch (Exception e) {
      System.err.println(e);
    }
  }

  /**
   * Get the document in SCIHOME corresponding to the configuration file.
   *
   * @return the configuration document.
   */
  public static Document getXConfigurationDocument() {
    if (doc == null) {
      boolean error = false;
      File xml = new File(USER_CONFIG_FILE);
      if (!xml.exists()) {
        ScilabXMLUtilities.writeDocument(createDocument(), USER_CONFIG_FILE);
      }

      DocumentBuilder docBuilder = null;

      try {
        DocumentBuilderFactory factory = ScilabDocumentBuilderFactory.newInstance();
        docBuilder = factory.newDocumentBuilder();
        doc = docBuilder.parse(xml);
        float version = getDocumentVersion(doc);
        float defaultVersion = getDocumentVersion(getDefaultDocument());
        if (defaultVersion != version) {
          xml.delete();
          doc = null;
          return getXConfigurationDocument();
        } else {
          return doc;
        }
      } catch (ParserConfigurationException pce) {
        error = true;
      } catch (SAXException se) {
        error = true;
      } catch (IOException ioe) {
        error = true;
      }

      if (error) {
        if (hasBeenRead) {
          System.err.println(SEVERE_ERROR);
          doc = null;
          xml.delete();
          return docBuilder.newDocument();
        }

        hasBeenRead = true;
        doc = null;
        xml.delete();
        System.err.println(PARSING_ERROR);
        return getXConfigurationDocument();
      }

      return docBuilder.newDocument();
    }

    return doc;
  }

  /** Save the modifications */
  public static void writeDocument(String filename, Node written) {
    Transformer transformer = null;
    try {
      transformer = ScilabTransformerFactory.newInstance().newTransformer();
    } catch (TransformerConfigurationException e1) {
      System.err.println(ERROR_WRITE + filename);
      return;
    } catch (TransformerFactoryConfigurationError e1) {
      System.err.println(ERROR_WRITE + filename);
      return;
    }
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");

    StreamResult result = new StreamResult(new File(filename));
    DOMSource source = new DOMSource(written);
    try {
      transformer.transform(source, result);
    } catch (TransformerException e) {
      System.err.println(ERROR_WRITE + filename);
      return;
    }

    // Invalidate the current document
    if (filename.equals(USER_CONFIG_FILE)) {
      doc = null;
    }
  }

  /** Save the modifications */
  public static String dumpNode(Node written) {
    Transformer transformer = null;
    try {
      transformer = ScilabTransformerFactory.newInstance().newTransformer();
    } catch (TransformerConfigurationException e1) {
      System.err.println("Cannot dump xml");
      return "";
    } catch (TransformerFactoryConfigurationError e1) {
      System.err.println("Cannot dump xml");
      return "";
    }
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");

    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    StreamResult result = new StreamResult(new BufferedOutputStream(stream));
    DOMSource source = new DOMSource(written);
    String str = "";
    try {
      transformer.transform(source, result);
      str = stream.toString();
    } catch (TransformerException e) {
      System.err.println("Cannot dump xml");
      return str;
    } finally {
      try {
        stream.close();
      } catch (Exception e) {
      }
    }

    return str;
  }

  /**
   * Get the document version
   *
   * @param doc the document
   * @return the version
   */
  private static float getDocumentVersion(Document doc) {
    if (doc != null) {
      Element root = doc.getDocumentElement();
      String version = root.getAttribute("version");

      try {
        return Float.parseFloat(version);
      } catch (NumberFormatException e) {
      }
    }

    return 0.0f;
  }

  /**
   * Get the default document
   *
   * @return the document
   */
  private static Document getDefaultDocument() {
    DocumentBuilder docBuilder;
    DocumentBuilderFactory factory;
    Document mainDoc = null;

    try {
      factory = ScilabDocumentBuilderFactory.newInstance();
      docBuilder = factory.newDocumentBuilder();
      mainDoc = docBuilder.parse(SCILAB_CONFIG_FILE);
    } catch (ParserConfigurationException pce) {
      System.err.println("Cannot create a XML DocumentBuilder:\n" + pce);
      return null;
    } catch (SAXException se) {
      System.err.println("Weird... Cannot parse basic file:\n" + se);
      return null;
    } catch (IOException ioe) {
      System.err.println("Weird... Cannot parse basic file:\n" + ioe);
      return null;
    }

    return mainDoc;
  }

  /**
   * Create a document in using the XConfiguration-*.xml found in SCI/modules/MODULE_NAME/etc/
   *
   * @return the built document
   */
  public static Document createDocument() {
    DocumentBuilder docBuilder;
    DocumentBuilderFactory factory;
    Document mainDoc = getDefaultDocument();
    if (mainDoc == null) {
      return null;
    }

    Element root = mainDoc.getDocumentElement();

    factory = ScilabDocumentBuilderFactory.newInstance();

    try {
      docBuilder = factory.newDocumentBuilder();
    } catch (ParserConfigurationException pce) {
      System.err.println("Cannot create a XML DocumentBuilder:\n" + pce);
      return null;
    }

    List<File> etcs = getEtcDir();
    for (File etc : etcs) {
      File[] xmls =
          etc.listFiles(
              new FilenameFilter() {
                public boolean accept(File dir, String name) {
                  return name.endsWith(".xml") && name.startsWith("XConfiguration-");
                }
              });
      for (File xml : xmls) {
        try {
          Document doc = docBuilder.parse(xml);
          if (xml.getName().equals("XConfiguration-general.xml")) {
            try {
              XPath xp = xpathFactory.newXPath();
              NodeList nodes =
                  (NodeList)
                      xp.compile(
                              "//shortcuts/body/actions/action-folder/action[contains(@key, 'OSSCKEY')]")
                          .evaluate(doc, XPathConstants.NODESET);
              for (int i = 0; i < nodes.getLength(); i++) {
                Element e = (Element) nodes.item(i);
                e.setAttribute(
                    "key",
                    e.getAttribute("key").replace("OSSCKEY", ScilabKeyStroke.getOSMetaKey()));
              }
            } catch (XPathExpressionException e) {
              System.err.println(e);
            }
          }
          Node node = mainDoc.importNode(doc.getDocumentElement(), true);
          NodeList list = root.getElementsByTagName(node.getNodeName());
          if (list.getLength() != 0) {
            root.replaceChild(node, list.item(0));
          }
        } catch (SAXException se) {
          System.err.println(ERROR_READ + xml.getName());
        } catch (IOException ioe) {
          System.err.println(ERROR_READ + xml.getName());
        }
      }
    }

    return mainDoc;
  }

  /**
   * Get a the list of the etc dirs in modules dirs
   *
   * @return the lit of etc dirs
   */
  public static List<File> getEtcDir() {
    List<File> list = new ArrayList<File>();
    File modulesDir = new File(SCI + "/modules/");
    File[] modules =
        modulesDir.listFiles(
            new FileFilter() {
              public boolean accept(File f) {
                return f.isDirectory();
              }
            });

    for (File module : modules) {
      File etc = new File(module, "/etc/");
      if (etc.exists() && etc.isDirectory()) {
        list.add(etc);
      }
    }

    return list;
  }

  public static void addModifiedPath(String path) {
    if (path != null && !path.isEmpty()) {
      modifiedPaths.add(path);
    }
  }

  public static void invalidate() {
    modifiedPaths.clear();
    doc = null;
  }

  public static void addXConfigurationListener(XConfigurationListener listener) {
    listenerList.add(XConfigurationListener.class, listener);
  }

  public static void removeXConfigurationListener(XConfigurationListener listener) {
    listenerList.remove(XConfigurationListener.class, listener);
  }

  public static XConfigurationListener[] getXConfigurationListeners() {
    return listenerList.getListeners(XConfigurationListener.class);
  }

  public static void fireXConfigurationEvent() {
    if (!modifiedPaths.isEmpty()) {
      XConfigurationEvent event = null;
      Object[] listeners = listenerList.getListenerList();
      for (int i = listeners.length - 2; i >= 0; i -= 2) {
        if (listeners[i] == XConfigurationListener.class) {
          if (event == null) {
            event = new XConfigurationEvent(modifiedPaths);
          }
          ((XConfigurationListener) listeners[i + 1]).configurationChanged(event);
        }
      }

      modifiedPaths.clear();
    }
  }

  /**
   * Register a StringParser for a given Class
   *
   * @param type the class type
   * @param parser the StringParser
   */
  public static void registerStringParser(Class<?> type, StringParser parser) {
    conv.put(type, parser);
  }

  /**
   * Get a StringParser for a given Class
   *
   * @param type the class type
   * @return the corresponding parser
   */
  public static StringParser getStringParser(Class<?> type) {
    return conv.get(type);
  }

  public static void set(final Document doc, final String path, String value) {
    XPath xp = xpathFactory.newXPath();
    NodeList nodes;
    try {
      nodes = (NodeList) xp.compile(path).evaluate(doc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
      System.err.println(e);
      return;
    }

    for (int i = 0; i < nodes.getLength(); i++) {
      Node n = nodes.item(i);
      if (n != null && n.getNodeType() == Node.ATTRIBUTE_NODE) {
        n.setNodeValue(value);
      }
    }

    writeDocument(USER_CONFIG_FILE, doc);
  }

  /** Save the current file */
  public static void save() {
    if (doc != null) {
      writeDocument(USER_CONFIG_FILE, doc);
    }
  }

  /**
   * Get all the nodes with the given path. All the get nodes are serialized into an object (generic
   * paramater) which must have a constructor without argument and with methods named
   * set&lt;Attribute Name&gt; with one argument and no returned value. For example a node &lt;foo
   * aaa="1" bbb="true" ccc-ddd="#001122"/&gt; could be retrieved with something like
   * XConfiguration.get(MyObject.class, doc, "//path/to/node") where MyObject should be something
   * like <code>
   * public class MyObject {
   *
   *    public MyObject() {
   *       // ...
   *    }
   *
   *    public void setAaa(int a) {
   *       // ...
   *    }
   *
   *    public void setBbb(boolean b) {
   *       // ...
   *    }
   *
   *    public void setCccDdd(Color c) {
   *       // ...
   *    }
   * }
   * </code> If an attribute must not be retrieved, just remove the setter.
   *
   * <p>It is possible to use the annotation @XConfAttribute to make easier the retrievement. For
   * example <code>
   * @XConfAttribute
   * public class MyObject {
   *
   *    public MyObject() {
   *       // ...
   *    }
   *
   *    @XConfAttribute(attributes={"aaa", "bbb", "ccc-ddd"})
   *    // the contents of aaa will be converted into int and passed as first argument
   *    // the contents of bbb will be converted into boolean and passed as second argument
   *    // the contents of ccc-ddd will be converted into Color and passed as third argument
   *    public void set(int n, boolean b, Color c) {
   *       // ...
   *    }
   *  }
   * </code>
   *
   * @param type the Class type to retrieve
   * @param doc the document to explore
   * @param path the xpath query to retrieve the corresponding nodeset.
   * @return an array of instance of class type.
   */
  public static final <T> T[] get(final Class<T> type, final Document doc, final String path) {
    XPath xp = xpathFactory.newXPath();
    NodeList nodes;
    try {
      nodes = (NodeList) xp.compile(path).evaluate(doc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
      System.err.println(e);
      return (T[]) Array.newInstance(type, 0);
    }

    if (type.getAnnotation(XConfAttribute.class) != null) {
      T[] arr = get(type, nodes);
      if (arr != null) {
        return arr;
      }
    }

    Method[] meths = type.getDeclaredMethods();
    Map<String, Method> mapMethods = new HashMap<String, Method>();
    for (Method m : meths) {
      String name = m.getName();
      if (name.startsWith("set")
          && m.getParameterTypes().length == 1
          && m.getReturnType().equals(Void.TYPE)) {
        mapMethods.put(m.getName(), m);
        m.setAccessible(true);
      }
    }

    Map<String, String> names = new HashMap<String, String>();

    T[] values = (T[]) Array.newInstance(type, nodes.getLength());
    for (int i = 0; i < values.length; i++) {
      NamedNodeMap map = nodes.item(i).getAttributes();
      try {
        Constructor<T> constructor = type.getDeclaredConstructor(new Class[] {});
        constructor.setAccessible(true);
        values[i] = constructor.newInstance();
      } catch (InstantiationException e) {
        System.err.println(e);
        break;
      } catch (IllegalAccessException e) {
        System.err.println(e);
        break;
      } catch (NoSuchMethodException e) {
        System.err.println(e);
        break;
      } catch (InvocationTargetException e) {
        System.err.println(e.getTargetException());
      }

      for (int j = 0; j < map.getLength(); j++) {
        Node n = map.item(j);
        String name = n.getNodeName();
        String methName = names.get(name);
        if (methName == null) {
          StringBuilder buffer = new StringBuilder("set");
          String[] parts = name.split("-");
          for (String part : parts) {
            if (part != null && part.length() > 0) {
              buffer.append(part.substring(0, 1).toUpperCase());
              buffer.append(part.substring(1).toLowerCase());
            }
          }
          methName = buffer.toString();
          names.put(name, methName);
        }
        String value = n.getNodeValue();
        Method method = mapMethods.get(methName);
        if (method != null) {
          Class[] paramsClass = method.getParameterTypes();
          StringParser parser = conv.get(paramsClass[0]);
          if (parser != null) {
            Object[] params = new Object[] {parser.parse(value)};
            try {
              method.invoke(values[i], params);
            } catch (IllegalAccessException e) {
              System.err.println(e);
            } catch (IllegalArgumentException e) {
              System.err.println(e);
            } catch (InvocationTargetException e) {
              System.err.println(e.getTargetException());
            }
          }
        }
      }
    }

    return values;
  }

  /**
   * Get a Map with where the key is the converted value (according to keyType) of the attribute
   * named key and the value is given in the same way.
   *
   * @param doc the document to read
   * @param key the attribute name where its value will be converted and used as a key in the map
   * @param keyType the Class of the key
   * @param value the attribute name where its value will be converted and used as a value in the
   *     map
   * @param valueType the Class of the value
   * @return the corresponding map.
   */
  public static final <T, U> Map<T, U> get(
      final Document doc,
      final String key,
      final Class<T> keyType,
      final String value,
      final Class<U> valueType,
      final String path) {
    XPath xp = xpathFactory.newXPath();
    Map<T, U> map = new HashMap<T, U>();
    NodeList nodes;
    try {
      nodes = (NodeList) xp.compile(path).evaluate(doc, XPathConstants.NODESET);
    } catch (XPathExpressionException e) {
      System.err.println(e);
      return map;
    }

    int len = nodes.getLength();
    for (int i = 0; i < len; i++) {
      NamedNodeMap nmap = nodes.item(i).getAttributes();
      Node k = nmap.getNamedItem(key);
      Node v = nmap.getNamedItem(value);
      if (k == null || v == null) {
        return map;
      }

      String kk = k.getNodeValue();
      String vv = v.getNodeValue();

      StringParser convK = conv.get(keyType);
      StringParser convV = conv.get(valueType);
      if (convK == null || convV == null) {
        return map;
      }

      map.put((T) convK.parse(kk), (U) convV.parse(vv));
    }

    return map;
  }

  /**
   * Getter for annoted class (with @XConfAttribute)
   *
   * @param type the class type
   * @param nodes the nodes to read
   * @return an array of instances of type, if the class is annoted
   *     with @XConfAttribute(isStatic=true), the returned array is empty.
   */
  private static final <T> T[] get(final Class<T> type, NodeList nodes) {
    Method[] meths = type.getDeclaredMethods();
    List<String[]> attrs = new ArrayList<String[]>();
    List<Method> methods = new ArrayList<Method>();
    Map<String[], Method> mapMethods = new HashMap<String[], Method>();
    for (Method m : meths) {
      String name = m.getName();
      Annotation ann = m.getAnnotation(XConfAttribute.class);
      if (ann != null) {
        String[] attributes = ((XConfAttribute) ann).attributes();
        if (attributes.length == m.getParameterTypes().length) {
          m.setAccessible(true);
          attrs.add(attributes);
          methods.add(m);
        } else {
          return null;
        }
      }
    }

    Annotation ann = type.getAnnotation(XConfAttribute.class);
    boolean mustInstantiate = !((XConfAttribute) ann).isStatic();

    T[] values = null;
    int len = nodes.getLength();
    if (mustInstantiate) {
      values = (T[]) Array.newInstance(type, len);
    }

    for (int i = 0; i < len; i++) {
      NamedNodeMap map = nodes.item(i).getAttributes();
      String nodeName = nodes.item(i).getNodeName();

      if (mustInstantiate) {
        try {
          Constructor<T> constructor = type.getDeclaredConstructor(new Class[] {});
          constructor.setAccessible(true);
          values[i] = constructor.newInstance();
        } catch (InstantiationException e) {
          System.err.println(e);
          break;
        } catch (IllegalAccessException e) {
          System.err.println(e);
          break;
        } catch (NoSuchMethodException e) {
          System.err.println(e);
          break;
        } catch (InvocationTargetException e) {
          System.err.println(e.getTargetException());
        }
      }

      for (int j = 0; j < methods.size(); j++) {
        Method method = methods.get(j);
        ann = method.getAnnotation(XConfAttribute.class);
        String tag = ((XConfAttribute) ann).tag();
        if (tag.isEmpty() || tag.equals(nodeName)) {
          String[] attributes = attrs.get(j);
          Object[] params = new Object[attributes.length];
          Class[] paramsClass = method.getParameterTypes();
          for (int k = 0; k < attributes.length; k++) {
            String p = "";
            Node node = null;
            if (map != null) {
              node = map.getNamedItem(attributes[k]);
            }
            if (node != null) {
              p = node.getNodeValue();
            }

            StringParser parser = conv.get(paramsClass[k]);
            if (parser != null) {
              params[k] = parser.parse(p);
            }
          }

          try {
            if (mustInstantiate) {
              method.invoke(values[i], params);
            } else {
              method.invoke(null, params);
            }
          } catch (IllegalAccessException e) {
            System.err.println(e);
          } catch (IllegalArgumentException e) {
            System.err.println(e);
          } catch (InvocationTargetException e) {
            System.err.println(e.getTargetException());
          }
        }
      }
    }

    if (mustInstantiate) {
      return values;
    } else {
      return (T[]) Array.newInstance(type, 0);
    }
  }

  /** Interface to implement to parse an attribute String into a Java object */
  public static interface StringParser {

    /**
     * Parse a string
     *
     * @param str the string to parse
     * @return the corresponding Object
     */
    public Object parse(String str);
  }

  static {
    conv.put(
        int.class,
        new StringParser() {
          public Integer parse(String str) {
            try {
              return Integer.parseInt(str);
            } catch (NumberFormatException e) {
              try {
                return (int) Double.parseDouble(str);
              } catch (NumberFormatException ee) {
                return new Integer(0);
              }
            }
          }
        });
    conv.put(
        char.class,
        new StringParser() {
          public Object parse(String str) {
            if (str.length() > 0) {
              return str.charAt(0);
            } else {
              return new Character((char) 0);
            }
          }
        });
    conv.put(
        byte.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Byte.parseByte(str);
            } catch (NumberFormatException e) {
              try {
                return (byte) Double.parseDouble(str);
              } catch (NumberFormatException ee) {
                return new Byte((byte) 0);
              }
            }
          }
        });
    conv.put(
        short.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Short.parseShort(str);
            } catch (NumberFormatException e) {
              try {
                return (short) Double.parseDouble(str);
              } catch (NumberFormatException ee) {
                return new Short((short) 0);
              }
            }
          }
        });
    conv.put(
        double.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Double.parseDouble(str);
            } catch (NumberFormatException ee) {
              return new Double((double) 0);
            }
          }
        });
    conv.put(
        float.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Float.parseFloat(str);
            } catch (NumberFormatException ee) {
              return new Float((float) 0);
            }
          }
        });
    conv.put(
        boolean.class,
        new StringParser() {
          public Object parse(String str) {
            return Boolean.parseBoolean(str);
          }
        });
    conv.put(
        long.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Long.parseLong(str);
            } catch (NumberFormatException e) {
              try {
                return (long) Double.parseDouble(str);
              } catch (NumberFormatException ee) {
                return new Long((long) 0);
              }
            }
          }
        });
    conv.put(
        String.class,
        new StringParser() {
          public Object parse(String str) {
            return str;
          }
        });
    conv.put(
        Color.class,
        new StringParser() {
          public Object parse(String str) {
            try {
              return Color.decode(str);
            } catch (NumberFormatException e) {
              return Color.BLACK;
            }
          }
        });
    conv.put(
        KeyStroke.class,
        new StringParser() {
          public Object parse(String str) {
            String[] toks = str.split(" +");
            StringBuilder buffer = new StringBuilder();
            for (int i = 0; i < toks.length - 1; i++) {
              buffer.append(toks[i].toLowerCase());
              buffer.append(" ");
            }
            buffer.append(toks[toks.length - 1].toUpperCase());
            return KeyStroke.getKeyStroke(buffer.toString());
          }
        });
  }

  @Retention(RetentionPolicy.RUNTIME)
  public @interface XConfAttribute {

    /**
     * Map method arguments with attributes name For example, <code>
     * @XConfAttribute(tag="mytag", attributes={"a", "b"})
     * void foo(String one, int tow) { ... }
     * </code> The value of attribute "a" is converted into a String and passed as "one"
     * argument,...
     */
    public String[] attributes() default {""};

    public String tag() default "";

    /** Used to avoid object instanciation so the differents annotated methods must be static. */
    public boolean isStatic() default false;
  }
}
  static {
    long lastTime = Calendar.getInstance().getTimeInMillis();

    Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");
    String OS_NAME = System.getProperty("os.name");
    Debug.DEBUG("SwingScilabCanvasImpl", "os.name=" + OS_NAME);
    String OS_ARCH = System.getProperty("os.arch");
    Debug.DEBUG("SwingScilabCanvasImpl", "os.arch=" + OS_ARCH);
    Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");

    /*
     * Bug #7526: moved out of the try/catch block since it contains
     * no OpenGL calls.
     */
    if (OS_NAME.contains("Windows") && OS_ARCH.equals("amd64")) {
      // bug 3919 : JOGL x64 doesn't like x64 remote desktop on Windows
      // @TODO : bug report to JOGL
      String REMOTEDESKTOP = System.getenv("SCILAB_MSTS_SESSION");
      if (REMOTEDESKTOP != null) {
        if (REMOTEDESKTOP.equals("OK")) {
          noGLJPanel = true;
        }
      }

      if (noGLJPanel) {
        /** Inform the users */
        InterpreterManagement.requestScilabExec(
            String.format(
                "disp(\"%s\"), disp(\"%s\")",
                String.format(
                    Messages.gettext(
                        "WARNING: Due to your configuration limitations, Scilab switched in a mode where mixing uicontrols and graphics is not available. Type %s for more information."),
                    "\"\"help usecanvas\"\""),
                String.format(
                    Messages.gettext("In some cases, %s fixes the issue"),
                    "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")));
      }
    }

    /*
     * Bug #7526: this code block causes a crash on Windows and Intel Graphic HD cards
     * with graphics drivers older than 8.15.10.2279 and is therefore not executed if
     * Windows is the OS (the tests on driver and OpenGL versions are Linux-specific).
     * Consequently, updateMaxCanvasSize, which determines the canvas size, is not called
     * any more on Windows. However, it is still called when an actual graphics window is created
     * (by the renderer module's SciRenderer init method), which still allows getting the maximum
     * canvas dimensions, so this should not be an issue.
     */
    if (!OS_NAME.contains("Windows")) {

      try {
        GLCanvas tmpCanvas = new GLCanvas(new GLCapabilities(GLProfile.getDefault()));
        Frame tmpFrame = new Frame();
        tmpFrame.add(tmpCanvas);
        tmpFrame.setVisible(true);

        tmpCanvas.getContext().makeCurrent();
        GL gl = tmpCanvas.getGL();

        String GL_VENDOR = gl.glGetString(GL.GL_VENDOR);
        Debug.DEBUG("SwingScilabCanvasImpl", "GL_VENDOR=" + GL_VENDOR);
        String GL_RENDERER = gl.glGetString(GL.GL_RENDERER);
        Debug.DEBUG("SwingScilabCanvasImpl", "GL_RENDERER=" + GL_RENDERER);
        String GL_VERSION = gl.glGetString(GL.GL_VERSION);
        Debug.DEBUG("SwingScilabCanvasImpl", "GL_VERSION=" + GL_VERSION);
        // Debug.DEBUG("SwingScilabCanvasImpl", "GL_EXTENSIONS="+gl.glGetString(GL.GL_EXTENSIONS));
        Debug.DEBUG("SwingScilabCanvasImpl", "=======================================");
        // System.getProperties().list(System.err);

        // get maximum axes size
        // RenderingCapabilities.updateMaxCanvasSize(gl);

        tmpCanvas.getContext().release();
        tmpFrame.remove(tmpCanvas);
        tmpFrame.setVisible(false);
        tmpFrame.dispose();
        Debug.DEBUG(
            "SwingScilabCanvasImpl",
            "Testing time = " + (Calendar.getInstance().getTimeInMillis() - lastTime) + "ms");

        noGLJPanel = false;

        // By default disable GLJPanel on Linux
        if (OS_NAME.contains("Linux")) {
          noGLJPanel = true;
          // Linux && NVIDIA
          if (GL_VENDOR.contains("NVIDIA")) {
            noGLJPanel = false;
          }
          // Linux && ATI
          if (GL_VENDOR.contains("ATI")) {
            StringTokenizer stSpace = new StringTokenizer(GL_VERSION, " ");
            StringTokenizer stDot = new StringTokenizer(stSpace.nextToken(), ".");
            int majorVersion = Integer.parseInt(stDot.nextToken());
            int minorVersion = Integer.parseInt(stDot.nextToken());
            int releaseVersion = Integer.parseInt(stDot.nextToken());
            // Only OpenGL version newer than 2.1.7873 works
            // available through ATI 8.8 installer
            // and driver newer than 8.52.3
            Debug.DEBUG(
                "SwingScilabCanvasImpl",
                "majorVersion = "
                    + majorVersion
                    + " minorVersion = "
                    + minorVersion
                    + " releaseVersion = "
                    + releaseVersion);
            if (majorVersion > 2
                || majorVersion == 2 && minorVersion > 1
                || majorVersion == 2 && minorVersion == 1 && releaseVersion >= 7873) {
              noGLJPanel = false;
            }
          }
        }

        if (noGLJPanel) {
          /** Inform the users */
          InterpreterManagement.requestScilabExec(
              String.format(
                  "disp(\"%s\"), disp(\"%s\")",
                  String.format(
                      Messages.gettext(
                          "WARNING: Due to your configuration limitations, Scilab switched in a mode where mixing uicontrols and graphics is not available. Type %s for more information."),
                      "\"\"help usecanvas\"\""),
                  String.format(
                      Messages.gettext("In some cases, %s fixes the issue"),
                      "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")));
        }
      } catch (GLException e) {
        noGLJPanel = true;
        /** Inform the users */
        InterpreterManagement.requestScilabExec(
            String.format(
                "disp(\"%s\"), disp(\"%s\")",
                Messages.gettext(
                    "Due to your video card drivers limitations, that are not able to manage OpenGL, Scilab will not be able to draw any graphics. Please update your driver."),
                String.format(
                    Messages.gettext("In some cases, %s fixes the issue"),
                    "\"\"system_setproperty(''jogl.gljpanel.nohw'','''');\"\"")));
      } catch (HeadlessException e) {
        // do not print anything on a CLI only environment
        noGLJPanel = true;
      }
    }
  }
  /**
   * We customize the file chooser for the graphic export by adding format selection
   *
   * @param figureId exported figure number
   */
  public void exportCustomFileChooser(Integer figureUID) {
    Figure figure = (Figure) GraphicController.getController().getObjectFromId(figureUID);
    String defaultName = figure.getName();
    int figureId = figure.getId();
    if (defaultName != null && !defaultName.isEmpty()) {
      defaultName = defaultName.replaceFirst("%d", Integer.toString(figureId));
    } else {
      defaultName = Messages.gettext("Untitled-export");
    }

    ArrayList<FileMask> v = new ArrayList<FileMask>(NB_FILE_MASKS); /* The order does matter */
    v.add(new FileMask(png, pngDesc));
    v.add(new FileMask(jpg, jpgDesc));
    v.add(new FileMask(eps, epsDesc));
    v.add(new FileMask(ps, psDesc));
    v.add(new FileMask(pdf, pdfDesc));
    v.add(new FileMask(svg, svgDesc));
    v.add(new FileMask(emf, emfDesc));
    v.add(new FileMask(gif, gifDesc));
    v.add(new FileMask(bmp, bmpDesc));
    v.add(new FileMask(ppm, ppmDesc));
    v.add(new FileMask(allFiles, allFilesDesc)); // should always be at the last position

    super.setDialogTitle(Messages.gettext("Export"));
    super.setApproveButtonText(Messages.gettext("Export"));
    File exportFile = new File(defaultName);
    super.setSelectedFile(exportFile);
    super.setAcceptAllFileFilterUsed(false);

    this.figureUID = figureUID;

    for (int i = 0; i < v.size(); i++) {
      FileMask fm = v.get(i);
      if (i == v.size() - 1) {
        /* Last case ... all files, remove the extension */
        fm.clearExtensions();
      }
      super.addChoosableFileFilter(fm);
    }

    // Preview panel
    JPanel panelPreview = new JPanel();

    // Title for preview panel
    TitledBorder titlePreview;
    titlePreview =
        BorderFactory.createTitledBorder(Messages.gettext("Preview selected image file"));
    panelPreview.setBorder(titlePreview);

    // add preview image
    panelPreview.add(new ImagePreview(this));

    // Main panel contains extensionTable panel & preview panel
    JPanel accessoryPanel = new JPanel();

    // accessoryPanel.add(scrollPane);
    accessoryPanel.add(panelPreview);
    accessoryPanel.setVisible(true);
    super.setAccessory(accessoryPanel);

    Component c = DrawerVisitor.getVisitor(figureUID).getComponent();
    Window parentWindow = (Window) SwingUtilities.getAncestorOfClass(Window.class, c);

    int selection = super.showSaveDialog(parentWindow);
    if (selection == JFileChooser.APPROVE_OPTION && super.getSelectedFile() != null) {
      this.exportName = super.getSelectedFile().getAbsolutePath();

      /* Bug 3849 fix */
      ConfigManager.saveLastOpenedDirectory(new File(exportName).getParentFile().getPath());

      String extensionCombo = new String();
      try {
        // The try catch is necessary here when the user input the full
        // filename (foo.jpg) and press tab. It is going to update
        // the filter causing the following line to fail (cannot cast)
        // Therefor, we switch back to the allFiles (*) case.
        FileMask ft = (FileMask) super.getFileFilter();
        // get the extension from the Filter
        extensionCombo = ft.getExtensionFromFilter();
        if (extensionCombo == null) {
          extensionCombo = allFiles;
        }
      } catch (java.lang.ClassCastException e) {
        extensionCombo = allFiles;
      }

      if (extensionCombo.equals(allFiles)) {
        exportManager();
      } else if (extensionCombo.equals(emf)
          || extensionCombo.equals(eps)
          || extensionCombo.equals(ps)
          || extensionCombo.equals(pdf)
          || extensionCombo.equals(svg)) {
        vectorialExport(extensionCombo);
      } else {
        bitmapExport(extensionCombo);
      }
    } else {; // no file chosen
    }
  }
/**
 * This is the son of the usual Scilab file chooser, it have been customized for the graphic export
 *
 * @author Sylvestre Koumar
 */
@SuppressWarnings(value = {"serial"})
public class SwingScilabExportFileChooser extends SwingScilabFileChooser {

  private static final int NB_FILE_MASKS = 12;

  private final String bmpDesc = Messages.gettext("Windows BMP image");
  private final String gifDesc = Messages.gettext("GIF image");
  private final String jpgDesc = Messages.gettext("JPEG image");
  private final String pngDesc = Messages.gettext("PNG image");
  private final String ppmDesc = Messages.gettext("PPM image");
  private final String emfDesc = Messages.gettext("Enhanced Metafile image (EMF)");
  private final String epsDesc = Messages.gettext("Encapsulated PostScript image (EPS)");
  private final String psDesc = Messages.gettext("PostScript image (PS)");
  private final String pdfDesc = Messages.gettext("PDF image");
  private final String svgDesc = Messages.gettext("SVG image");
  private final String allFilesDesc = Messages.gettext("All files");

  private final String bmp = "bmp";
  private final String gif = "gif";
  private final String[] jpg = {"jpg", "jpeg"};
  private final String png = "png";
  private final String ppm = "ppm";
  private final String emf = "emf";
  private final String eps = "eps";
  private final String ps = "ps";
  private final String pdf = "pdf";
  private final String svg = "svg";
  private final String allFiles = "*";

  private String exportName;
  private String extensionSelected;
  private Integer figureUID;

  /**
   * Default constructor
   *
   * @param figureId id of the exported figure
   */
  public SwingScilabExportFileChooser(Integer figureUID) {
    super();
    this.figureUID = figureUID;
    SwingScilabDockablePanel tab = (SwingScilabDockablePanel) SwingView.getFromId(figureUID);
    setParentFrame(tab.getParentWindow());
    exportCustomFileChooser(figureUID);
  }

  /**
   * We customize the file chooser for the graphic export by adding format selection
   *
   * @param figureId exported figure number
   */
  public void exportCustomFileChooser(Integer figureUID) {
    Figure figure = (Figure) GraphicController.getController().getObjectFromId(figureUID);
    String defaultName = figure.getName();
    int figureId = figure.getId();
    if (defaultName != null && !defaultName.isEmpty()) {
      defaultName = defaultName.replaceFirst("%d", Integer.toString(figureId));
    } else {
      defaultName = Messages.gettext("Untitled-export");
    }

    ArrayList<FileMask> v = new ArrayList<FileMask>(NB_FILE_MASKS); /* The order does matter */
    v.add(new FileMask(png, pngDesc));
    v.add(new FileMask(jpg, jpgDesc));
    v.add(new FileMask(eps, epsDesc));
    v.add(new FileMask(ps, psDesc));
    v.add(new FileMask(pdf, pdfDesc));
    v.add(new FileMask(svg, svgDesc));
    v.add(new FileMask(emf, emfDesc));
    v.add(new FileMask(gif, gifDesc));
    v.add(new FileMask(bmp, bmpDesc));
    v.add(new FileMask(ppm, ppmDesc));
    v.add(new FileMask(allFiles, allFilesDesc)); // should always be at the last position

    super.setDialogTitle(Messages.gettext("Export"));
    super.setApproveButtonText(Messages.gettext("Export"));
    File exportFile = new File(defaultName);
    super.setSelectedFile(exportFile);
    super.setAcceptAllFileFilterUsed(false);

    this.figureUID = figureUID;

    for (int i = 0; i < v.size(); i++) {
      FileMask fm = v.get(i);
      if (i == v.size() - 1) {
        /* Last case ... all files, remove the extension */
        fm.clearExtensions();
      }
      super.addChoosableFileFilter(fm);
    }

    // Preview panel
    JPanel panelPreview = new JPanel();

    // Title for preview panel
    TitledBorder titlePreview;
    titlePreview =
        BorderFactory.createTitledBorder(Messages.gettext("Preview selected image file"));
    panelPreview.setBorder(titlePreview);

    // add preview image
    panelPreview.add(new ImagePreview(this));

    // Main panel contains extensionTable panel & preview panel
    JPanel accessoryPanel = new JPanel();

    // accessoryPanel.add(scrollPane);
    accessoryPanel.add(panelPreview);
    accessoryPanel.setVisible(true);
    super.setAccessory(accessoryPanel);

    Component c = DrawerVisitor.getVisitor(figureUID).getComponent();
    Window parentWindow = (Window) SwingUtilities.getAncestorOfClass(Window.class, c);

    int selection = super.showSaveDialog(parentWindow);
    if (selection == JFileChooser.APPROVE_OPTION && super.getSelectedFile() != null) {
      this.exportName = super.getSelectedFile().getAbsolutePath();

      /* Bug 3849 fix */
      ConfigManager.saveLastOpenedDirectory(new File(exportName).getParentFile().getPath());

      String extensionCombo = new String();
      try {
        // The try catch is necessary here when the user input the full
        // filename (foo.jpg) and press tab. It is going to update
        // the filter causing the following line to fail (cannot cast)
        // Therefor, we switch back to the allFiles (*) case.
        FileMask ft = (FileMask) super.getFileFilter();
        // get the extension from the Filter
        extensionCombo = ft.getExtensionFromFilter();
        if (extensionCombo == null) {
          extensionCombo = allFiles;
        }
      } catch (java.lang.ClassCastException e) {
        extensionCombo = allFiles;
      }

      if (extensionCombo.equals(allFiles)) {
        exportManager();
      } else if (extensionCombo.equals(emf)
          || extensionCombo.equals(eps)
          || extensionCombo.equals(ps)
          || extensionCombo.equals(pdf)
          || extensionCombo.equals(svg)) {
        vectorialExport(extensionCombo);
      } else {
        bitmapExport(extensionCombo);
      }
    } else {; // no file chosen
    }
  }

  private boolean canWriteFile(String name) {
    if (new File(name).exists()) {
      Component c = DrawerVisitor.getVisitor(figureUID).getComponent();
      Window parentWindow = (Window) SwingUtilities.getAncestorOfClass(Window.class, c);
      int actionDialog =
          JOptionPane.showConfirmDialog(
              parentWindow,
              Messages.gettext("Replace existing file?"),
              Messages.gettext("File already exists"),
              JOptionPane.YES_NO_OPTION);
      if (actionDialog != JOptionPane.YES_OPTION) {
        return false;
      }
    }

    return true;
  }

  /**
   * Return the file extension
   *
   * @param fileName Name of the file
   * @return the extension
   */
  public String getExtension(String fileName) {
    if (fileName != null) {
      int i = fileName.lastIndexOf('.');
      if (i > 0 && i < fileName.length() - 1) {
        return fileName.substring(i + 1).toLowerCase();
      }
    }
    return null;
  }

  /** Manage the export (bitmap/vectorial format) and export errors */
  public void exportManager() {
    // get the extension of the fileName chosen by the user (can be 'null')
    String userExtension = getExtension(this.exportName);

    if (userExtension == null) {
      // fileName without extension + "by extension (.*)" selected
      JOptionPane.showMessageDialog(
          this,
          Messages.gettext("Please specify a file format"),
          Messages.gettext("Error on export"),
          JOptionPane.ERROR_MESSAGE);
      return;
    } else if (userExtension.equals(bmp)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(gif)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(jpg[0]) || userExtension.equals(jpg[1])) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(png)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(ppm)) {
      bitmapExport(userExtension);
    } else if (userExtension.equals(emf)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(eps)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(pdf)) {
      vectorialExport(userExtension);
    } else if (userExtension.equals(svg)) {
      vectorialExport(userExtension);
    } else {
      // fileName with a wrong extension + "by extension (.*)" selected
      JOptionPane.showMessageDialog(
          this,
          String.format(
              Messages.gettext(
                  "Unrecognized extension '%s'.\n Please specify a valid file format."),
              userExtension),
          Messages.gettext("Error on export"),
          JOptionPane.ERROR_MESSAGE);
      return;
    }
  }

  /**
   * Export an bitmap file
   *
   * @param userExtension extension caught by the user
   */
  public void bitmapExport(String userExtension) {
    Cursor old = getCursor();
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

    ExportData exportData = new ExportData(figureUID, this.exportName, userExtension, null);

    String actualFilename = exportData.getExportName();
    if (this.getExtension(actualFilename) == null) {
      // Could not get the extension from the user input
      // take the one from the list
      actualFilename += "." + userExtension;
    }

    if (!canWriteFile(actualFilename)) {
      return;
    }

    FileExporter.fileExport(figureUID, actualFilename, exportData.getExportExtension(), -1, 0);

    setCursor(old);
  }

  /**
   * Export a vectorial file
   *
   * @param userExtension extension caught by the user
   */
  public void vectorialExport(String userExtension) {
    SwingScilabDockablePanel tab = (SwingScilabDockablePanel) SwingView.getFromId(figureUID);
    Component c = DrawerVisitor.getVisitor(figureUID).getComponent();
    ExportData exportData = new ExportData(figureUID, this.exportName, userExtension, null);

    String actualFilename = exportData.getExportName();
    if (this.getExtension(actualFilename) == null) {
      actualFilename += "." + userExtension;
    }

    if (!canWriteFile(actualFilename)) {
      return;
    }

    ExportOptionWindow exportOptionWindow = new ExportOptionWindow(exportData);
    exportOptionWindow.displayOptionWindow(tab);
    exportOptionWindow.landscapePortraitOption();
  }
}
  /**
   * Create the popup menu on the help
   *
   * @param c The graphic component
   */
  private void createPopupMenu(JComponent c) {
    final JPopupMenu popup = new JPopupMenu();

    JMenuItem menuItem;

    /* Execute into Scilab */
    ActionListener actionListenerExecuteIntoScilab =
        (ActionEvent actionEvent) -> {
          String selection = accessibleHtml.getSelectedText();
          if (selection == null) {
            ScilabHelpBrowser.getHelpBrowser()
                .getInfoBar()
                .setText(Messages.gettext("No text selected"));
          } else {
            ScilabConsole.getConsole()
                .getAsSimpleConsole()
                .sendCommandsToScilab(selection, true /* display */, true /* store in history */);
          }
        };
    menuItem = new JMenuItem(Messages.gettext("Execute into Scilab"));
    menuItem.addActionListener(actionListenerExecuteIntoScilab);
    if (!ScilabConsole.isExistingConsole()) {
      /* Only available in STD mode */
      menuItem.setEnabled(false);
    }
    popup.add(menuItem);

    /* Edit in the Scilab Text Editor */
    ActionListener actionListenerLoadIntoTextEditor =
        (ActionEvent actionEvent) -> {
          String selection = accessibleHtml.getSelectedText();
          if (selection == null) {
            ScilabHelpBrowser.getHelpBrowser()
                .getInfoBar()
                .setText(Messages.gettext("No text selected"));
          } else {
            edit(selection);
          }
        };

    menuItem = new JMenuItem(Messages.gettext("Edit in the Scilab Text Editor"));
    try {
      Class scinotesClass = Class.forName("org.scilab.modules.scinotes.SciNotes");
    } catch (ClassNotFoundException e) {
      /* SciNotes not available */
      menuItem.setEnabled(false);
    }
    menuItem.addActionListener(actionListenerLoadIntoTextEditor);
    popup.add(menuItem);
    popup.addSeparator();

    /* Back in the history*/
    ActionListener actionListenerBackHistory =
        (ActionEvent actionEvent) -> {
          DefaultHelpHistoryModel history = SwingScilabHelpBrowser.getHelpHistory();
          /* Not at the first position */
          if (history.getIndex() > 0) {
            SwingScilabHelpBrowser.getHelpHistory().goBack();
          }
        };

    menuItem = new JMenuItem(Messages.gettext("Back"));
    menuItem.addActionListener(actionListenerBackHistory);
    popup.add(menuItem);

    /* Forward in the history*/
    ActionListener actionListenerForwardHistory =
        (ActionEvent actionEvent) -> {
          DefaultHelpHistoryModel history = SwingScilabHelpBrowser.getHelpHistory();
          /* Not at the last position */
          if (history.getHistory().size() != (history.getIndex() + 1)) {
            SwingScilabHelpBrowser.getHelpHistory().goForward();
          }
        };

    menuItem = new JMenuItem(Messages.gettext("Forward"));
    menuItem.addActionListener(actionListenerForwardHistory);
    popup.add(menuItem);
    popup.addSeparator();

    /* Copy */
    menuItem = new JMenuItem(new DefaultEditorKit.CopyAction());
    menuItem.setText(Messages.gettext("Copy"));
    popup.add(menuItem);
    popup.addSeparator();

    /* Select all */
    ActionListener actionListenerSelectAll =
        (ActionEvent actionEvent) -> {
          accessibleHtml.selectAll();
        };
    menuItem = new JMenuItem(Messages.gettext("Select All"));
    menuItem.addActionListener(actionListenerSelectAll);
    popup.add(menuItem);

    /* Edit in the Scilab Text Editor */
    final JMenuItem helpMenuItem = new JMenuItem("Help on the selected text");

    ActionListener actionListenerHelpOnKeyword =
        (ActionEvent actionEvent) -> {
          String selection = accessibleHtml.getSelectedText();
          if (selection == null) {
            ScilabHelpBrowser.getHelpBrowser()
                .getInfoBar()
                .setText(Messages.gettext("No text selected"));
          } else {
            ScilabHelpBrowser.getHelpBrowser().searchKeywork(selection);
          }
        };
    PropertyChangeListener listenerTextItem =
        (PropertyChangeEvent arg0) -> {
          String keyword = accessibleHtml.getSelectedText();
          if (keyword == null) {
            helpMenuItem.setText(Messages.gettext("Help about a selected text"));
          } else {
            int nbOfDisplayedOnlyXChar = 10;
            if (keyword.length() > nbOfDisplayedOnlyXChar) {
              keyword = keyword.substring(0, nbOfDisplayedOnlyXChar) + "...";
            }
            helpMenuItem.setText(Messages.gettext("Help about '") + keyword + "'");
          }
        };
    helpMenuItem.addPropertyChangeListener(listenerTextItem);
    helpMenuItem.addActionListener(actionListenerHelpOnKeyword);
    popup.add(helpMenuItem);

    /* Creates the Popupmenu on the component */
    accessibleHtml.setComponentPopupMenu(popup);
  }