📜 ⬆️ ⬇️

Abstract UI. New C # framework called XWT

If you look at existing modern frameworks for implementing user interfaces (WPF, GTK, Qt, wxWidgets, and even trendy web solutions), then it is easy to see that they resemble each other like twins. Any framework contains buttons, fields, checkboxes, switches, characterized by identical logic from the user's point of view. The differences are only in the low-level implementation.

When somewhere in the programming world appears something too similar, then it tends to wrap in a layer of abstraction. And then I accidentally stumbled upon a similar solution created by the guys from Xamarin. Those who sell the C # framework for iOS and Android . This solution was called Xwt - apparently, it stands for Xamarin Window Toolkit.


')
Abstract




The idea is simple. Controls along with the basic properties are wrapped in an interface that is implemented by means of existing frameworks. In this case, the implementations are located in separate assemblies and on each platform it is enough to place any one assembly.

First, about the interface: since the Xwt task was to port MonoDevelop from Gtk to Cocoa, the Xwt interface is extremely close to the Gtk # interface. Controls are placed in automatically scaled line, column, and tabular layouts in accordance with the fill and expand rules inherited from GTK. Also, the TreeView / TreeStore device was preserved from Gtk, although it was a little closer to the .NET standards.

The current version of Xwt has implementations for WPF, Gtk and Cocoa. At the same time, no one forbids using Gtk on Windows or Mac OS X.

You can pick up the framework in the source from here . The interface is separately assembled in Xwt.dll, and the assembly in Xwt.Gtk.dll, Xwt.Mac.dll, Xwt.WPF.dll. At the same time, implementation options and links to them are rigidly spelled out in the head file, so you can add your own implementations only by forking the entire project.

Let's try to make a small application on Xwt:
class Program { [STAThread] static void Main(string[] args) { Xwt.Application.Initialize(Xwt.ToolkitType.Wpf); Xwt.Window MainWindow = new Xwt.Window() { Title = "Xwt Test" }; MainWindow.CloseRequested += (o, e) => { Xwt.Application.Exit(); }; Xwt.Menu MainMenu = new Xwt.Menu(); Xwt.RichTextView TextView = new Xwt.RichTextView(); Xwt.MenuItem FileOpenMenuItem = new Xwt.MenuItem(""); Xwt.Menu FileMenu = new Xwt.Menu(); FileOpenMenuItem.Clicked += (o,e) => { Xwt.OpenFileDialog Dialog = new Xwt.OpenFileDialog(" "); if (Dialog.Run(MainWindow)) { TextView.LoadFile(Dialog.FileName, Xwt.Formats.TextFormat.Markdown); } }; Xwt.MenuItem FileMenuItem = new Xwt.MenuItem("") { SubMenu = FileMenu }; FileMenu.Items.Add(FileOpenMenuItem); MainMenu.Items.Add(FileMenuItem); MainWindow.MainMenu = MainMenu; MainWindow.Content = TextView; MainWindow.Show(); Xwt.Application.Run(); } } 


Please note that the corresponding interfaces are made not only for controls, but also for standard dialog boxes. As a bonus, Markdown's parser is built into the RichTextView control :)

Here is what we will see when running this application:


Replace one line with Xwt.Application.Initialize(Xwt.ToolkitType.Gtk); and we get another result.


More abstraction


The authors went even further and included an abstract drawing interface, close in its external interface to Gdk. Within this interface, there is, for example, Xwt.Drawing.Color , which is different from both System.Drawing.Color and Gdk.Color .

Here is a simple code that draws a circle. It runs successfully on all platforms.
 class DrawCircle : Xwt.Canvas { protected override void OnDraw(Xwt.Drawing.Context ctx, Xwt.Rectangle dirtyRect) { ctx.SetColor(Xwt.Drawing.Colors.Black); ctx.SetLineWidth(1); ctx.Arc(50, 50, 30, 0, 350); ctx.Stroke(); } } class Program { [STAThread] static void Main(string[] args) { Xwt.Application.Initialize(Xwt.ToolkitType.Wpf); Xwt.Window MainWindow = new Xwt.Window() { Title = "Xwt Test" }; MainWindow.CloseRequested += (o, e) => { Xwt.Application.Exit(); }; DrawCircle Canvas = new DrawCircle(); MainWindow.Content = Canvas; MainWindow.Show(); Xwt.Application.Run(); } } 


On the one hand, a cross-platform drawing interface is certainly a necessary thing. On the other hand, the existing code cannot be transferred, neither if it is written for System.Drawing, nor for Cairo.

Big claims


In addition to the abstract drawing engine, the authors of the framework threatened to create an abstraction for animations. At the current stage, it presents something similar to earlier versions of $ .animate (): a simple wrapper over a timer. It was hard for me to imagine animated Gtk #, so I just tried to make a simple shake, as in the fancy login windows.

  class Program { [STAThread] static void Main(string[] args) { Xwt.Application.Initialize(Xwt.ToolkitType.Gtk); Xwt.Window W = new Xwt.Window() { }; Xwt.Button B = new Xwt.Button("Animate"); W.Content = B; W.Show(); B.Clicked += (o, e) => { #region  // -    ,      WX = WX    - ,    .    .    ,  . double CurX = WX, CurY = WY; WX = CurX; WY = CurY; double DiffX = WX - CurX, DiffY = WY - CurY; WX = CurX - DiffX; WY = CurY - DiffY; #endregion W.Animate("", (X) => { W.Location = new Point((CurX - DiffX) + 8 * Math.Sin(20 * X), (CurY - DiffY)); }, length: 750, repeat: () => false); }; Xwt.Application.Run(); } } 


The above example successfully worked with ToolkitType.Gtk and ToolkitType.Wpf.

Instead of conclusion


Now this is a very raw, open-source project, distributed under the MIT license, it has no documentation at all, none at all. However, the whole IDE (MonoDevelop 4) is written on it. Within the framework of the project, there is still no graphic designer, and it is not yet clear which way the developers will go with the declarative language - Glade fork or XAML adaptation. Already, the framework can be used for academic projects in conjunction with Mono, and with the advent of at least the simplest declarative language, it will also be convenient. Funny, in my opinion, it would be to implement a jQuery backend with the deployment of a local web server: this would allow running such academic solutions without any UI platform at all, for example, on a virtual machine in the cloud. At the same time, the principle for the wimps “write once, run everywhere” would remain. And it would be possible to launch MonoDevelop itself directly in the cloud :) There is a small chance that Xamarin, in the process of friendship with Microsoft, will eventually introduce Xwt as the main Microsoft solution for cross-platform UI, and then this raw free project will be everywhere.

Some experts believe that trying to interface existing UI toolkits on different platforms is a task by definition not having an adequate solution, because different platforms have different user experience. Xwt, however, is quite workable. Its disadvantage is that it covers a rigid set of controls and behaviors, and thus requires the implementation of all these interfaces from the backend. It would be much better if each control was a semblance of a contract; the application would indicate a set of such contracts and would be executed only on those frameworks where these contracts are available.

And I would also like to ask mac owners to try to test the framework's work in various modes.

Source: https://habr.com/ru/post/201460/


All Articles