Logged in as 38.107.191.95 : Discusión para esta IP Registrarse/Entrar
Views:
Herramientas:

Monodevelop AddIns

De Mono Hispano

Autores:
Jose Ramon Palanco jose.palanco@hazent.com correo


Contents

Introducción

MonoDevelop (y SharpDevelop) se han escrito pensados para ser extendidos fácilemnete. Esto se puede hacer simplemente con dos cosas. Un assembly (.dll) que contenga el código del add-in y un fichero XML (.addin) que mapee el código de nuestro add-in en MonoDevelop.

Terminología

  • add-in: Lo que mucha gente entiende por plugin.
  • pad: Contenedor de partes de programa como el navegador de solución o la salida de compilación
  • vista: Area principal como el SourceEditor -editor- .
  • binding: Compilación, ejecución y gestión de proyecto para un lenguaje de programación.
  • servicio: Parte encargada de ofrecer una actividad, como MessageService, encargado de mostrar mensajes al usuario.

Add-in assembly

Mediante el código de este assembly podemos añadir funcionalidades a MonoDevelop como puedan ser: nuevos menus, pads, vistas, servicios. commandos, ... Es recomendable descargarse el códio fuente de MonoDevelop (de la versión con la que estemos trabajando) y mirar src/AddIns/ para ver como se implementa cada cosa. En la mayoría de los casos bastará con heredar de una clase abstracta o implementar una interfaz.

Ejemplo de un servicio:

 using System;
 using MonoDevelop.Core.Services;
 
 namespace MonoDevelop.Services;
 {
     public class ExampleService : AbstractService
     {
         // Incluir funcionalidad aquí
     }
 }

Aquí teneis una lista de la que normalmente querréis heredar:

  • ./src/Main/Base/Gui/Dialogs/AbstractOptionPanel.cs
  • ./src/Main/Base/Gui/Dialogs/Wizard/AbstractWizardPanel.cs
  • ./src/Main/Base/Gui/Pads/ClassScout/BrowserNode/AbstractClassScoutNode.cs
  • ./src/Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/AbstractBrowserNode.cs
  • ./src/Main/Base/Gui/AbstractBaseViewContent.cs
  • ./src/Main/Base/Gui/AbstractPadContent.cs
  • ./src/Main/Base/Gui/AbstractViewContent.cs
  • ./src/Main/Base/Gui/AbstractSecondaryViewContent.cs

El fichero .addin.xml

Debemos de crear un fichero .addin.xml que mapee nuestro código en las partes de MonoDevelop donde queremos incrustarlo. Ahí debemos especificar servicios a cargar, donde colocar nuestra entrada del menu de usuario, etc...

Debido a que MonoDevelop está desarrollado por un subconjunto de add-ins (es un diseño impresionantemente modular), no tenemos límite para hacer lo que queramos desde un add-in. Disponemos de directivas condicionales y otras construcciones avanzadas. En el siguiente ejemplo MonoDevelopNunit.addin.xml, veremos como se especifica el nombre del assembly a cargar, el servicio a lanzar dentro del nodo /Workspace/Services, dos vistas y algún menú. Es importante darse cuenta de que el atributo de la clase se usa para especificar el tipo a instanciar para esa parte del add-in.

 <AddIn name        = "MonoDevelop Nunit"
        author      = "John Luke"
        copyright   = "GPL"
        url         = "http://monodevelop.com"
        description = "NUnit testing tool"
        version     = "0.2">
 
     <Runtime>
         <Import assembly="MonoDevelop.Nunit.dll" />
     </Runtime>
 
     <Extension path="/Workspace/Services">
         <Class id    = "NunitService"
                class = "MonoDevelop.Services.NunitService" />
     </Extension>
 
     <Extension path="/SharpDevelop/Workbench/Views">
         <Class id    = "NunitTestTree"
                class = "MonoDevelop.Nunit.Gui.TestTree" />
         <Class id    = "NunitResultTree"
                class = "MonoDevelop.Nunit.Gui.ResultTree" />
     </Extension>
 
     <Extension path="/SharpDevelop/Workbench/MainMenu/Tools">
         <MenuItem id           = "NunitMenu"
                   _label       = "NUnit"
                   insertafter  = "ExternalTools"
                   insertbefore = "Options">
             <MenuItem id       = "LoadTestAssembly"
                       _label   = "Load Assembly"
                       shortcut = ""
                       class    = "MonoDevelop.Commands.NunitLoadAssembly" />
 
             <MenuItem id       = "NunitRunTests"
                       _label   = "Run Tests"
                       shortcut = ""
                       class    = "MonoDevelop.Commands.NunitRunTests" />
         </MenuItem>
     </Extension>
 
 </AddIn>
 

Add-in tree

Los AddIns se cargan y fusionan en un AddInTree, de tal manera que MonoDevelop conoce todos los elementos y donde cargarlos. Mira build/AddIns/SharpDevelopCore.addin.xml para ver varios lugares donde colgar tu add-in.

Formato del Add-in XML

Existe un fichero AddIn.xsd que especifica el formato XML requerido/óptimo. Quizá a alguien le interese data/resources/AddIn.xsd

Compilación e instalación

AddIns Existentes

  • SourceEditor
  • CSharpBinding
  • JavaBinding
  • NemerleBinding
  • DebuggerAddin
  • Monodoc
  • StartPage (no se ha portado entero, en MD 0.8 debería estar)
  • NUnit (incompleto)

ideas:

  • Corrector ortográfico
  • Ruby(.NET)Binding
  • (Iron)PythonBinding
  • Regex builder and checker
  • Nant, Xdevelop, integration
  • Stetic and GladeCodeGenerator integration (like VisualStudio... just design the GUI and click)
  • AspNetEditor and XSP integration
  • Beagle backend for search code like koders.com
  • koders.com integration
  • MonoUML integration
  • Database designer integration (maybe into monouml?)
  • GForge integration
  • Cecil integration for debugging thru assemblies out of our project
  • Compilación continua y subrayado de errores con listado de soluciones aplicacles con click
  • Asistente de tabulado e indentación dependiendo del tipo de lenguaje
  • XAML integration
  • reorganize usings (reorganize imports in eclipse)
  • GccCILBackendBinding
  • refactorización
  • buscar instanciación de una clase a partir del texto seleccionado

Advertencias

A pesar de que MonoDevelop usa el mismo formato que SharpDevelop, los add-ins que hagan uso de interfaz gráfica no funcionarán debido a que las librerías usadas por estos proyectos son muy diferentes. Incluso muchas veces tendremos problemas con gtk# debido a que las librerías de monodevelop se hayan compilado contra una versión distinta a la que estemos compilando nosotros.

El tipo de error es dificil de localizar, pero sabiendo esto podremos percatartnos cuando obtengamos un error similar a:

... type must be 'Gtk.Widget' to match overridden member ...

Y nos cercioremos de que estamos colocando los parámetros del tipo correcto.

Internacionalización

MonoDevelop usa gettext en vez de usar recursos para realizar la tradución a otras lenguas. Esto es una ventaja debido a que gran parte de la comunidad de desarrolladores de este entorno conoce gettext.

Con gettext, en vez de usar cadenas directamente en nuestro código, hacemos algo similar a esto:

GettextCatalog.GetString ("cadena que veran los usuarios")
String.Format (GettextCatalog.GetString ("cadena que veran los usuarios {0}"), variable)

Luego debemos de añadir esas cadenas a MonoDevelop/po/FICHEROS_POT.in

Código

Hola Mundo

Crearemos un fichero holamundo.addin.xml

<AddIn name	 = "Hola Mundo"
       author	 = "Jose Ramon Palanco"
       copyright = "MIT X11"
       url       = "http://www.monohispano.org"
       description = ""
       version   = "0.01">

	<Runtime>
		<Import assembly="holamundo.dll"/>
	</Runtime>
	
	<Extension path = "/SharpDevelop/Commands">
		<Command id = "MonoDevelop.HolaMundo.Commands.Command1"
			_label = "_Hola Mundo"
			defaultHandler = "MonoDevelop.HolaMundo.Test"
			description = "Hola Mundo" />
	</Extension>


	<Extension path="/SharpDevelop/Workbench/MainMenu/Help">
	<CommandItem  id = "MonoDevelop.HolaMundo.Commands.Command1" insertafter="Separator2" insertbefore="Web" 
		/>
	</Extension>

</AddIn>

En la etiqueta <Runtime> estamos importando holamundo.dll. En el path "/SharpDevelop/Workbench/MainMenu/Help" insertamos una entrada en el menú con identificador HolaMundo después de Web y antes del segundo separador con la etiqueta "Hola Mundo" que llama al comando HolaMundoCommand.

Ahora tenemos que hacer ese comando. Para ellos nos ponemos a escribir holamundo.cs.

using System;
using MonoDevelop.Core.AddIns.Codons;
using MonoDevelop.Commands;

namespace MonoDevelop.HolaMundo
{
	public enum Commands
	{
		Command1
	}

	public class Test : CommandHandler
	{
		protected override void Run()
		{
			Console.WriteLine("Hola Mundo");
		}
	}
}


Aquí estamos heredando de AbstractMenuCommand (Core/src/MonoDevelop.Core/AddIns/Codons/AbstractCommand.cs). Vamos a ojearlo, ya que es muy pequeño:

using System;
using System.Collections;
using System.CodeDom.Compiler;

using MonoDevelop.Core.AddIns;
using MonoDevelop.Core.AddIns.Codons;
using MonoDevelop.Core.Properties;

namespace MonoDevelop.Core.AddIns.Codons
{
        public abstract class AbstractCommand : ICommand
        {
                object owner = null;

                 public virtual object Owner {
                        get {
                                return owner;
                        }
                        set {
                                owner = value;
                        }
                }
                public abstract void Run();
        }
}

AbstractCommand implementa ICommand y nos obliga (abstract) a implementar un método void Run() que es lo que hace el propio comando. En nuestro caso solo hemos escrito un "Hola Mundo". También podemos ver que nos permite sobre-escribir el acceso a owner, que ya veremos más adelante lo que es.

Para compilar (en Debian y Ubuntu) simplemente debemos de ejecutar:

$ mcs -r:/usr/lib/monodevelop/bin/MonoDevelop.Base.dll -target:library holamundo.cs

Para probar nuestro AddIn debemos colorcar el .xml y la .dll en /var/lib/monodevelop/AddIns/. Para que quede más ordenado es recomendable crear un directorio, ya que MonoDevelop es capaz de mirar dentro y queda todo más ordenadito:

$ sudo mkdir /var/lib/monodevelop/AddIns/HolaMundo
$ sudo cp holamundo.dll holamundo.addin.xml /var/lib/monodevelop/AddIns/HolaMundo


Ahora podemos arrancar MonoDevelop y ejecutar nuestro nuevo menú. Veréis como en la consola aparece nuestro "Hola Mundo".



Buscador de koders.com

En desarrollo

Referencias

Mapa del código

Nombre Ubicación Descricción Dependencias
MonoDevelop.Core src/Libraries/MonoDevelop.Core/ Contains the bare necessities for the IDE ninguna
MonoDevelop.Base src/Main/Base/ Es la base del IDE
  • MonoDevelop.Core
  • Gtk#/GNOME
gdl-sharp gdldock/ Binding of the gdl dock C library
  • Gtk#
ICSharpCode.SharpAssembly src/Libraries/SharpAssembly/ Librería de lectura de Assemblies ninguna
ICSharpCode.SharpRefactory src/Libraries/SharpRefactory/ C# parser library ninguna
MonoDevelop.SourceEditor src/AddIns/DisplayBindings/SourceEditor/ Editor por defecto de MonoDevelop
  • Gtk#
  • gtksourceview-sharp
  • MonoDevelop.Core
  • MonoDevelop.Base
  • MonoDevelop.Gui.Widgets
  • MonoDevelop.Gui.Utils
MonoDevelop.Gui.Utils src/Libraries/MonoDevelop.Gui.Utils/ Funciones adicionales extra
  • Gtk#/GNOME
MonoDevelop.Gui.Widgets src/Libraries/MonoDevelop.Gui.Widgets/ Widgets específicos de gtk#
  • Gtk#/GNOME
  • MonoDevelop.Core
  • MonoDevelop.Gui.Utils
MonoDevelop.Debugger src/AddIns/DebuggerAddIn/ Librería de soporte de debugging
  • Gtk#
  • Mono.Debugger
  • MonoDevelop.Base
  • MonoDevelop.Core
MonoDevelop.StartPage src/AddIns/Misc/StartPage/ Página de inicio del IDE
  • gecko-sharp
  • Gtk#
  • MonoDevelop.Core
  • MonoDevelop.Base
CSharpBinding src/AddIns/BackendBindings/CSharpBinding/ Backend for C# langauge support
  • MonoDevelop.Core
  • MonoDevelop.Base
  • MonoDevelop.SourceEditor
  • ICSharpCode.SharpRefactory
  • MonoDevelop.Gui.Widgets
JavaBinding src/AddIns/BackendBindings/JavaBinding/ Backend de Java langauge
  • Runtime y compilador externos
StartUp src/Main/StartUp/ Parsea la línea de comandos e invoca al resto de componentes
  • MonoDevelop.Core
  • MonoDevelop.Base
  • MonoDevelop.SourceEditor
  • ICSharpCode.SharpRefactory
  • MonoDevelop.Gui.Widgets

Créditos, Licencia y Errata

Los registros de iconos aún no están funcionando, pero se pueden ver ejemplos de como registrarlos via addin.xml en svn:


En el segundo archivo podremos ver:

                       label = GettextCatalog.GetString ("Tables");
                       string iconName = "md-mono-query-tables";
                       icon = Context.GetIcon (iconName);

                       TablesNode node = (TablesNode) dataObject;
                       node.RefreshEvent += RefreshHandler;


"md-mono-query-tables" a los iconos definidos en MonoQuery.addin.xml. Los iconos se almacenan como recurso en la .dll del add-in

Enviad comentarios a Jose Ramon Palanco (mailto:jose.palanco@hazent.com)

Send comments to jluke (mailto:jluke@cfl.rr.com) or the MonoDevelop mailing list (mailto:monodevelop-list@lists.ximian.com)

Licensed under the MIT License