📜 ⬆️ ⬇️

Introduction to XWT

Greetings to all readers of this resource! At the moment, a lot of solutions have been developed to ensure cross-platform Microsoft .NET / Mono GUI applications. In this article, I will introduce readers to one of them, the official project from the developers of Mono - XWT Widget Toolkit (Xwt). You can download it at the moment only in the form of source codes from the github.com/mono/xwt repository. Unfortunately, it was not possible to find literate and complete articles about this toolkit on the Internet, so I had to smell everything myself. Since This article is not advertising and not a review, I will not explain how XWT is better or worse than the same Eto Forms or System.Windows.Forms (the latter works quite well on Mono). This article will discuss the principle of XWT and the basics of working with it.


Attention! This toolkit is extremely raw, and contains a lot of bugs. Using it in your applications be prepared to detect non-working properties, non-invoking events, etc. unpleasant phenomena


Introduction


The XWT Widget Toolkit (the name seems to be deciphered, and not the Xamarin Widget Toolkit, as many people think) is arranged according to a scheme where there is an abstract loader named Xwt.dll that loads backends built using standard Xwt interfaces from the Xwt.Gtk.dll libraries , Xwt.Wpf.dll, Xwt.Mac.dll, etc. You can read more about the XWT device in the habr-topic of November 11, 2013 . In terms of the API structure, Xwt is very similar to GTK #, which is not surprising - Xwt was created for porting MonoDevelop to platforms other than Linux (first of all, MacOS X).
')

Initialization


Xwt can be initialized as a host (for ordinary applications), or as a guest, when Xwt widgets are embedded in the native application. Both methods are generally similar, so they will be considered simultaneously.
First, XWT itself and the backend are initialized:
Xwt.Application.Initialize(Xwt.ToolkitType.Wpf); // Xwt.Application.InitializeAsGuest(Xwt.ToolkitType.Wpf); 

Using the argument, you can load various backends. In order for the backend to load, you must put the Xwt. *. Dll file in the directory in your application (if you use the Cocoa backend, you also need to put the MonoMac.dll file). You can set as an argument and just a string with the .net signature of the dll backend, but it is not recommended to do so, because “DLL hell” can happen. The attentive reader will immediately notice that the backend is set manually. Although the XWt.Application.Initialize () call is present in the XWT API with no arguments, it does not work as expected. Therefore, you will have to fence bicycles with the definition of the OS and the choice of ToolkitType yourself. Keep in mind that MacOSX is simply not defined .

After initialization, create a window (Xwt.Window) and display it.
 //MainWindow -  Xwt.Window,     new MainWindow().Show(); 

So, we loaded XWT, brought out the window, it blinked, and the process ended. And all because they forgot to start the flow of UI events. This is done in one line:
 Xwt.Application.Run(); 

At this point, the Main () function code will hang, so everything else needs to be done in the UI thread, that is, in the form created above.

Forms, dialogs and widgets


The controls (user controls) in this toolkit are called widgets. Widgets are embedded in other widgets (the only way), and widgets in the windows. Windows are classes that inherit from Xwt.WindowFrame. True, as a rule, they still represent instances or are inherited from the classes Window or Dialog. Dialogues from forms are distinguished by the possibility of displaying them in a modal mode (the Run(WindowFrame parent) function Run(WindowFrame parent) ), and also by dividing the working area into a department for a nested widget (Content) and control buttons (Buttons). Forms have only a title, a department for an embedded widget (Content) and a menu bar (MainMenu). The latter is not in the dialogues.
Both forms and dialogues have a basic set of events and properties, in general, similar to other GUI toolkits, except perhaps a bit abbreviated. When abusing the developers of Xamarin LLC, do not forget that behind each item of the Xwt interfaces there is a long revision of four backends at once.

Widgets are classes that inherit from Xwt.Widget. There are widgets - containers and widgets - controls. By themselves, windows can contain so many one widget to overcome this limitation and container widgets have been created. Containers, as the name implies, may contain an unlimited number of other widgets (including container ones), and are themselves responsible for placing them on their own host (parent), for example, a window or another container. Simple widgets, I think, do not need a description, although the documentation for them is clearly weak. Be prepared for the fact that known properties and events may be called differently. For example, click the mouse, incl. double, raises the ButtonPressed event.

To consolidate, let's look at an example from the previous article:
 class Program { [STAThread] //    WPF static void Main(string[] args) { // XWT     Xwt.Application.Initialize(Xwt.ToolkitType.Wpf); Xwt.Window MainWindow = new Xwt.Window() { Title = "Xwt Test" }; MainWindow.CloseRequested += (o, e) => { Xwt.Application.Exit(); //  exe'    }; //    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(); } } 


Container widgets


This toolkit contains a lot of container widgets, brazenly spied on from GTK . For those who are unfamiliar with GTK #, I will give an overview of the data of container containers.

Canvas - canvas



The easiest of containers. Allows both to lay out widgets in random order on themselves (AddChild (Xwt.Widget w)), and supports no drawing (OnDraw (Xwt.Drawing.Context ctx, Xwt.Rectangle dirtyRect)). However, it is not recommended for “everyday” use, since Xwt's rendering tools are far from perfect, and the rigid positioning of elements can lead to a complete separation of the widgets when their internal contents (and, therefore, their sizes) change.

Boxes - bookshelf (rack)



Vbox

Hbox
HBox and VBox widgets are designed to accommodate widgets on a ruler, with automatic control of the size and position of other widgets. Adding widgets is done by calling the PackStart and PackEnd functions. By manipulating the arguments, you can set the mode for holding and stretching widgets. Arguments margin * are set in an incomprehensible value, with a standard display resolution of 96dpi equal to strictly 1px, but continuing to work adequately with elevated DPI (with scale).

Table - table



For those familiar with the classic construction of web-pages, this will probably be the most convenient container of the existing ones. Yes, this is the most ordinary table. Each cell can be set by widget. For large fixed-markup applications, this is probably the best container ever. However, it does not allow the marking of "rubber", i.e. when the widget is resized in the cell, the column / row sizes change automatically, but you cannot just drag and drag the border (for now?).

Paned - panels



To create interfaces from two panels with support for changing proportions between them, there are containers VPaned and HPaned. At the moment, in Xwt it is impossible to change the proportions programmatically, although there are even two non-working properties for this, although I did not understand how they differ - Position and PositionFraction.

Notebook tabs



"Notebook" is designed to create a tabbed interface, as in the antediluvian settings windows. Keep in mind that you need to specify containers as a filling for the tabs, for example, VBox, otherwise you can place only one widget.

Expander - collapsible panel



This widget is designed to display various background, additional information or application controls. As well as the Notebook, containers are treated conditionally, since supports only one widget as a filling.

Examples of the use of XWT widgets can be found in the examples and tests attached to the source code of the toolkit. More information is unlikely to be found, because This toolkit is documented badly, if not to say that it is not documented at all. There are still few known applications on XWT, which is not surprising, but a search on Github ( tyts ) and other public repositories gives a lot of interesting startups.

In the next article, I will try to talk about XWT “buns”, such as introducing into native .NET applications, the built-in Markdown parser, features for setting focus on home-made widgets, as well as drawing graphics in XWT, working with TreeView and ListView, XWT flow control and counter methods with this, as well as some significant deficiencies (small bugs, this is not the language to be called) of this tulkit. If you know other important details of XWT, please mention in the comments - there will be something to mention in article 2.

PS If you are unable to open the XWT sln file under Visual Studio 2010, install SP1 or VS 2012+.

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


All Articles