Click here to Skip to main content
15,881,812 members
Articles / Desktop Programming / X11

Programming Xlib with Mono Develop - Part 2: Athena widgets (proof of concept)

Rate me:
Please Sign up or sign in to vote.
4.89/5 (4 votes)
14 Sep 2013CPOL12 min read 30.5K   231   5  
How to call native Xt API from Mono Develop C# ending up in a very little Athena widget application.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

using X11;

namespace Xt
{
	
	/// <summary> Prototype the SetStatusLabel event. </summary>
	/// <param name="label"> The label to set to the status bar. <see cref="System.String"/> </param>
	public delegate void SetStatusLabelDelegate (string label);

	/// <summary> Base class for application shells. </summary>
	public class XtApplicationShell : XtWmShell
	{

        // ###############################################################################
        // ### C O N S T A N T S
        // ###############################################################################

        #region Constants

        /// <summary> The class name constant. </summary>
        public new const string		CLASS_NAME = "XtApplicationShell";
		
        #endregion

		// ###############################################################################
        // ### A T T R I B U T E S
        // ###############################################################################

		#region Static attributes
		
		/// <summary> The only application shell instance. </summary>
		private static XtApplicationShell _instance = null;
		
        #endregion

		#region Attributes
		
		/// <summary> The application's context. </summary>
		protected IntPtr			_appContext			= IntPtr.Zero;
		
		/// <summary> The shell widgets resource name. </summary>
		private string				_shellResourceName	= "ApplicationShell";
		
		/// <summary> The list of associated shells, that interact with the window manager. </summary>
		protected List<XtWmShell>	_associatedShells	= new List<XtWmShell> ();
		
		/// <summary> Path to the application icon. </summary>
		public string				IconPath			= "attention.bmp";

        #endregion

		// ###############################################################################
        // ### E V E N T S
        // ###############################################################################

		#region Events
		
		/// <summary> Register the SetStatusLabel event handler. </summary>
		public event SetStatusLabelDelegate SetStatusLabel;
		
        #endregion
		
        // ###############################################################################
        // ### C O N S T R U C T I O N   A N D   I N I T I A L I Z A T I O N
        // ###############################################################################

        #region Construction
		
		/// <summary> Default constructor. </summary>
		[ObsoleteAttribute("Use parametrized constructor instead!")]
		private XtApplicationShell ()
		{	;	}
		
		/// <summary> Initializing constructor. </summary>
		/// <param name="shellResourceName"> The ressource name of the underlaying shell. <see cref="System.String"/> </param>
		/// <param name="fallbackResources"> The fallback ressources to apply. <see cref="Xt.XtFallbackRessources"/> </param>
		public XtApplicationShell (string shellResourceName, Xt.XtFallbackRessources fallbackResources)
		{
			if (_instance != null)
			{
				Console.WriteLine (CLASS_NAME + "::ctr () ERROR: Already an instance created.");
			}

			_shellResourceName = shellResourceName;

			TInt argc = 0;
			_shell	= Xtlib.XtAppInitialize (ref _appContext, _shellResourceName, IntPtr.Zero, 0, ref argc,
			                                IntPtr.Zero, fallbackResources.Marshal (), IntPtr.Zero, 0);

			_instance = this;
		}
		
		#endregion
		
        // ###############################################################################
        // ### D E S T R U C T I O N
        // ###############################################################################

        #region Destruction
		
		/// <summary> IDisposable implementation. </summary>
		public override void Dispose ()
		{
			Console.WriteLine (CLASS_NAME + "::Dispose ()");
			
			this.DisposeByParent ();
		}

		/// <summary> Dispose by parent. </summary>
		public override void DisposeByParent ()
		{	
			UnregisterConfigureNotifyAction ();
			UnregisterDeleteWindowAction ();

			base.DisposeByParent ();
		}
		
        #endregion
		
        // ###############################################################################
        // ### P R O P E R T I E S
        // ###############################################################################
		
		#region Static properties
		
		/// <summary> Get the only application shell instance. </summary>
		public static XtApplicationShell Instance
		{	get	{ return _instance;	}	}
		
        #endregion
		
		#region Properties

		/// <summary> Get the shell's resource name. </summary>
		public string SHELL_RESOURCE_NAME
		{	get	{	return _shellResourceName;	}	}

		/// <summary> Get the application content. </summary>
		public IntPtr AppContext
		{	get	{	return _appContext;	}	}		
		
		/// <summary> Get the list of associated shells, that interact with the window manager. </summary>
		public List<XtWmShell> AssociatedShells
		{	get	{	return _associatedShells;	}	}
		
        #endregion
		
        // ###############################################################################
        // ### M E T H O D S
        // ###############################################################################

		#region Methods
		
		/// <summary> Alloc a color from the default colormap of the display's default screen. </summary>
		/// <param name="colorname"> The color to alloc. <see cref="System.String"/> </param>
		/// <returns> The color pixel on success, or the white pixel otherwise. <see cref="TPixel"/> </returns>
		public TPixel AllocColorFromDefaultColormap (string colorname)
		{
			IntPtr display = Xtlib.XtDisplay (_shell);
			if (display == IntPtr.Zero)
				return (TPixel)1;
			
			TInt   scrnID  = X11lib.XDefaultScreen (display);
			
			X11lib.XColor tmp = new X11lib.XColor ();
			X11lib.XParseColor (display, X11lib.XDefaultColormap (display, scrnID), X11Utils.StringToSByteArray(colorname), ref tmp);
			X11lib.XAllocColor (display, X11lib.XDefaultColormap (display, scrnID), ref tmp);
			return tmp.pixel;
		}
		
		/// <summary> Process the SetStatusLabel event handler. </summary>
		/// <param name="label"> The label to set to the status bar. <see cref="System.String"/> </param>
		public void OnSetStatusLabel (string label)
		{
			SetStatusLabelDelegate setStatusLabel = SetStatusLabel;
			if (setStatusLabel != null)
				setStatusLabel (label);
		}
		
		/// <summary> Run the shell. </summary>
		public void Run ()
		{
			if (_appContext == IntPtr.Zero)
			{
				Console.WriteLine (CLASS_NAME + "::Run () ERROR: Application context pointer is zero.");
			    return;
			}
			if (_shell == IntPtr.Zero)
			{
				Console.WriteLine (CLASS_NAME + "::Run () ERROR: Application shell pointer is zero.");
			    return;
			}

			try
			{
				// Register a  "configure notify action" to application context, translate the "configure notify action", add/overwrite
				// the shell widget's translation table and set windows manager protocol hook for the shell widget.
				// This must be can *** BEFORE *** XtRealizeWidget ().
				RegisterConfigureNotifyAction (_appContext, this.ConfigureNotifyAction);
				
				Xtlib.XtRealizeWidget (_shell);
				
				SetShellIcon (IconPath);
				
				// Register a "delete window action" to application context, translate the "delete window action", add/overwrite
				// the shell widget's translation table and set windows manager protocol hook for the shell widget.
				// This must be done *** AFTER *** XtRealizeWidget ().
				RegisterDeleteWindowAction (_appContext, this.DeleteWindowAction);

				Xtlib.XtAppMainLoop (_appContext);
			}
			catch (Exception e)
			{
				Console.WriteLine (e.Message);
				Console.WriteLine (e.StackTrace);
			}
		}
		
		/// <summary> The prototype of shell specific close. </summary>
		/// <remarks> Application shels may implement the application exit, all other shells may implement popdown. </remarks>
		public override void Close ()
		{
			Console.WriteLine (CLASS_NAME + "::Close ()");
			
			XtGrabExclusiveMessageBox dlg = new XtGrabExclusiveMessageBox (this, "Do you really want to\nquit the application?", "Quit request", XtDialog.DialogIcon.Question);
			dlg.Name = "QueryForApplicationClose";
			dlg.DialogEnd += HandleDlgDialogEnd_QueryForApplicationClose;
			dlg.Run (_appContext);
		}
		
		#endregion

		#region .NET message handler

		/// <summary> Implement the HandleDialogEnd event handler. </summary>
		/// <param name="label"> The label to set to the status bar. <see cref="System.String"/> </param>
		void HandleDlgDialogEnd_QueryForApplicationClose (XtDialog source)
		{
			if (source.Result == XtDialog.DialogResult.Ok)
			{
				Xtlib.exit(0);
			}
		}

		#endregion
		
		#region Actions
		
		/// <summary> Define the "delete window action", invoked by the windows manager on window's decoration close [X] button. </summary>
		/// <param name="widget"> The widget, that is source of the event. Typically the the shell's toplevel widget. <see cref="System.IntPtr"/> </param>
		/// <param name="xevent"> The event, that is invoked. <see cref="XEvent"/> </param>
		/// <param name="parameters"> Additional parameters (as String[]). Not used for WM_DELETE_WINDOW. <see cref="System.IntPtr"/> </param>
		/// <param name="num_params"> The number of additional parameters. 0 for WM_DELETE_WINDOW. <see cref="XCardinal"/> </param>
		/// <remarks> The prototype must match the XtActionProc delegate. </remarks>
		public void DeleteWindowAction (IntPtr widget, ref XEvent xevent, IntPtr parameters, ref XCardinal num_params)
		{
			Console.WriteLine (CLASS_NAME + "::DeleteWindowAction()");
			this.Close ();
		}
		
		#endregion

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Celonis SA
Germany Germany
I am currently the CEO of Symbioworld GmbH and as such responsible for personnel management, information security, data protection and certifications. Furthermore, as a senior programmer, I am responsible for the automatic layout engine, the simulation (Activity Based Costing), the automatic creation of Word/RTF reports and the data transformation in complex migration projects.

The main focus of my work as a programmer is the development of Microsoft Azure Services using C# and Visual Studio.

Privately, I am interested in C++ and Linux in addition to C#. I like the approach of open source software and like to support OSS with own contributions.

Comments and Discussions