Discussion of article "MQL as a Markup Tool for the Graphical Interface of MQL Programs. Part 2"

 

New article MQL as a Markup Tool for the Graphical Interface of MQL Programs. Part 2 has been published:

This paper continues checking the new conception to describe the window interface of MQL programs, using the structures of MQL. Automatically creating GUI based on the MQL markup provides additional functionality for caching and dynamically generating the elements and controlling the styles and new schemes for processing the events. Attached is an enhanced version of the standard library of controls.

We can delete any interface element available in cache, i.e., not only those added by the Inject button. In this manner, you can, for example, delete the entire left half or the right "radiobox." Most interesting thing will happen, if we try to delete the upper container with two buttons. This will result in that the Export button won't be bound to the dialog anymore and will stay in the chart.

Editable Form: Adding and Deleting Elements

Editable Form: Adding and Deleting Elements

This happens, since it is the only element that is intentionally described as an automatic, not dynamic variable (in the form class, there is an instance of CButton, m_button3).

When the standard library tries to delete interface elements, it delegates this to array class CArrayObj, which, in turn, checks the pointer type and only deletes objects with POINTER_DYNAMIC. Thus, it becomes clear that, to construct an adaptive interface where elements can replace each other or be deleted completely, it is desirable to use dynamic placement, and cache offers an ready solution for this.

Author: Stanislav Korotky

 
Прилагается усовершенствованная версия стандартной библиотеки элементов управления.

So all this will only work with an enhanced version of the standard library?

 
I won't criticise the article for a long time, because it is already clear that the author doesn't think about the reader. He is talking to himself and he will be understood by those who are perfectly familiar with the standard library - its classes, methods and variables. The author "gallops" through the codes he knows and modifies something....

Lack of presentation of the general principles of the library, language or editor levelling the value of the article. Everyone can "dig" in the "innards" with clever words, but to explain the technology in a clear language - no, because you really need to understand its essence. I'm afraid the author has fallen victim to the illusion that he will make a markup language from a library (which he has learnt) and then immediately make a studio. At the same time, he naively considers window rubberisation and adding an element to a form as proof.

Since I won't wait for concepts from the author, I'm not interested in watching this incomprehensible action. Too bad. It's a pity that the author will have a hard time realising his ambitions and proving the "ridiculousness" of his results.

Good luck!
 
Реter Konow:
I won't criticise the article for a long time, because it is already clear that the author doesn't think about the reader. He is talking to himself and will be understood by those who are perfectly familiar with the standard library - its classes, methods and variables. The author "gallops" through the codes he knows and modifies something....

Lack of presentation of the general principles of the library, language or editor levelling the value of the article. Everyone can "dig" in the "innards" with clever words, but to explain the technology in a clear language - no, because you really need to understand its essence. I'm afraid the author has fallen victim to the illusion that he will make a markup language from a library (which he has learnt) and then immediately make a studio. At the same time, he naively considers window rubberisation and adding an element to a form as a confirmation.

Since I won't wait for concepts from the author, I'm not interested in watching this incomprehensible action. Too bad. It's a pity that the author will have a hard time realising his ambitions and proving the "ridiculousness" of his results.

Good luck!

And he who knows this library perfectly will hardly need any additions.

 
Dmitry Fedoseev:

And someone who is perfectly familiar with this library is unlikely to need any additions.

If you read the conclusion of the article carefully, you can understand the (controversial) conclusions of the author:

//------------------------------------------------------------------------------------------------------------------------

1. the author claims to have checked "the feasibility of the concept of describing the layout of the graphical interface of MQL programmes in the MQL language itself" (c).

  • Due to the specifics of the material presentation, I cannot say anything for/against this conclusion. It is not obvious.

//------------------------------------------------------------------------------------------------------------------------

2. "The use of dynamic generation of elements with centralised storage in the cache allows to simplify the creation and management of the hierarchy of components. Most tasks related to interface design, such as uniform style changes, event handling, on-the-fly editing of the layout and saving it in a format suitable for later use, can be implemented on the basis of the cache." (c)

  • It is unclear on what theoretical basis this conclusion was reached, as there is no description of the technology and the reader can neither agree nor deny. The reader should be introduced to the technology and then, they will agree with the proof of realisability.

//------------------------------------------------------------------------------------------------------------------------

3. "If you put these features together, it turns out that just about everything is available for a simple visual form editor. It could support only the most important properties common to many "controls", but would still allow the formation of interface blanks."(c)

  • Again, - without a generalised description of technological nuances, the reader who does not know perfectly the system of producing visual editors from graph libraries, can neither agree nor argue with the author. It is not obvious.

//------------------------------------------------------------------------------------------------------------------------

4. "However, we see that even the initial phase of evaluating the new concept required a lot of effort. Implementing a full-fledged editor in practice is therefore quite a challenge. And that is another story." (c)

  • In my opinion - this is the MOST objective conclusion. That is - "implementing a full-fledged editor is another story". I would agree with this conclusion. You can't just "rush" to make it (I've been trying to do it myself for several years).

//------------------------------------------------------------------------------------------------------------------------

My conclusion: in the Conclusion of the article (namely in the last conclusion), the author is closest to reality. But, the article is intended for readers who should come to the same conclusions as the topic develops, and for this purpose, it is necessary to gradually reveal the technology. The main disadvantage of the two articles is that there is no disclosure of technology. Their content is a discussion of the implementation of the author's non-obvious solutions without any preface to them. I hope the author will take this into account.

Документация по MQL5: Основы языка / Функции / Функции обработки событий
Документация по MQL5: Основы языка / Функции / Функции обработки событий
  • www.mql5.com
В языке MQL5 предусмотрена обработка некоторых предопределенных событий. Функции для обработки этих событий должны быть определены в программе MQL5: имя функции, тип возвращаемого значения, состав параметров (если они есть) и их типы должны строго соответствовать описанию функции-обработчика события. Именно по типу возвращаемого значения и по...
 
Реter Konow:

If you read the conclusion of the article carefully, you can understand the author's (controversial) conclusions:

//------------------------------------------------------------------------------------------------------------------------

1. the author claims to have checked "the feasibility of the concept of describing the layout of the graphical interface of MQL programmes in the MQL language itself" (c).

  • Due to the specifics of the material presentation, I cannot say anything for/against this conclusion. It is not obvious.

//------------------------------------------------------------------------------------------------------------------------

2. "Using dynamic element generation with centralised storage in a cache makes it easier to create and manage a hierarchy of components. Most tasks related to interface design can be implemented on the basis of the cache, such as uniform style changes, event handling, editing the layout on the fly and saving it in a format suitable for later use." (c)

  • It is not known on what theoretical basis this conclusion was reached, as there is no description of the technology and the reader can neither agree nor deny. The reader should be introduced to the technology and then, he will agree with the proof of realisability.

//------------------------------------------------------------------------------------------------------------------------

3. "If you put these features together, it turns out that just about everything is available for a simple visual form editor. It could support only the most important properties common to many "controls", but still allow you to form interface blanks."(c)

  • Again, - without a generalised description of the technological nuances, the reader who is not fluent in the system of producing visual editors from graph libraries can neither agree nor argue with the author. It is not obvious.

//------------------------------------------------------------------------------------------------------------------------

4. "However, we see that even the initial phase of evaluating the new concept required a lot of effort. Implementing a full-fledged editor in practice is therefore quite a challenge. And that is another story." (c)

  • In my opinion - this is the MOST objective conclusion. That is, "implementing a full-fledged editor is another story". I would agree with this conclusion. You can't just "brazenly" make it (I tried to do it myself for several years).

//------------------------------------------------------------------------------------------------------------------------

My conclusion: in the Conclusion of the article (namely in the last conclusion), the author is closest to reality. But, the article is intended for readers who should come to the same conclusions as the topic develops, and for this purpose, it is necessary to gradually reveal the technology. The main disadvantage of the two articles is that there is no disclosure of technology. Their content is a discussion of the implementation of the author's non-obvious solutions without any preface to them. I hope the author will take this into account.

I will abstain, because it is prohibitive.

 

I made a thorough analysis of the article content and realised that there are "particles" of the technology I was looking for, but they are arbitrarily scattered throughout the material. That is, the author did not separate theory from implementation and mixed everything up, in the process separating it with abundant code examples. I decided to collect the basics of his concept in one place to get a complete idea of it.

Copies of the article fragments explaining the technology (the sequence is preserved, code samples are omitted):

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1. the general structure of the library of standard elements, taking into account adapted versions with support for "rubberstamping" and third-party containers, is given in the class diagram. (my addition: the diagram is given).

2. element generation and caching

So far, elements have been constructed as automatic instances within a window object. They are essentially "blanks" that are then initialised by methods like Create. The GUI element layout system can create these elements itself, rather than fetching them from a window. For this purpose, it is enough to have some kind of storage. Let's call it LayoutCache. Basically, it is an array of pointers of the base class (common for all elements), where they can be placed using the save method. The interface also implements (if possible at this abstract level) or declares (for later overriding) methods to search for elements by number, name, reference, or fact of "parent" relationship (feedback from nested elements to the container).

Let's add a cache as a static member to the LayoutBase class. Each window will have to create a cache instance for itself and set it as a working cache using setCache at the very beginning of a method like CreateLayout. Since MQL programmes are single-threaded, we have a guarantee that windows (if several are needed) will not be formed in parallel and compete for the cacher pointer. We will clear the pointer automatically in the LayoutBase destructor when the stack is over - this means that we have left the last outer container in the layout description and there is no need to save anything else. Zeroing the reference does not mean we are clearing the cache. It just ensures that the potential next layout will not mistakenly add "controllers" from another window. To fill the cache, let's add a new kind of init method to LayoutBase - this time without a pointer or reference to a "third-party" GUI element in the parameters. Due to the template we have the ability to write a new T and spawn objects during the layout process (by default, 1 object at a time, but optionally we can have several).

A concrete cache implementation is written for the standard library elements - StdLayoutCache (here given with abbreviations, the full code is in the appendix).

Note that the get method searches for a "control" either by sequence number (if the input parameter is positive) or by identifier (it is passed with a minus sign). Here by identifier we mean a unique number assigned by the library of standard components for event dispatching. In events it is passed in the lparam parameter.

3. styliser

Since the cache is an object that centrally processes elements, it is convenient to use it to perform many other tasks besides styling. In particular, the rules of a single style (colour, font, indentation) can be applied to elements in a unified way. It is enough to configure this style in one place, instead of writing the same properties for each "control" separately. In addition, the cache can take on the task of handling messages for cached elements. Potentially we can dynamically construct, cache and interactively interact with absolutely all elements. Then we don't need to declare any "explicit" elements in the window at all. A little later we will see how dynamically created elements compare favourably with automatic ones.

To support centralised styles, the StdLayoutCache class has a stall method: The apply method will be called for each "control" twice: at the initialisation stage (STYLE_PHASE_BEFORE_INIT) and at the registration stage in the container (STYLE_PHASE_AFTER_INIT). Thus, the LayoutBase::init methods add a call to the first phase: and the destructor adds similar strings, but with STYLE_PHASE_AFTER_INIT for the second phase.

Two phases are needed because styling purposes are different. Some elements sometimes need to have individual properties that have a higher priority than the general ones set in the styliser. In the initialisation phase, the "control" is still empty - without the settings made in the layout. At the registration stage, all properties are already set in it and you can additionally change the style based on them. The most obvious example is as follows. It is desirable to display all input fields with the "read-only" flag in grey. But the "read-only" property is assigned to the "control" during the layout process, after initialisation, so the first stage is not suitable and the second stage is required. On the other hand, usually not all input fields will have this flag, and in all other cases it is necessary to set the default colour before the layout language performs selective customisation.

Incidentally, a similar technology can be used for centralised localisation of the interface of MQL programs into different national languages.

4. event processing

The second function, which is logically assigned to the cache, is the processing of events. For them in the LayoutCache class, a stub method is added (C is a parameter of the class template): Again, it can be implemented in a derived class, but not necessarily. The event codes are defined by the specific library.

To make this method work, we need event capture macro definitions similar to those in the standard library and written in the map, for example, like this: The new macros will redirect events to the cache object.

5. Example 2. Dialogue with Controls

The demo project contains the CControlsDialog class with the basic types of Standard Library "controls". By analogy with the first example, let's remove all the methods for their creation and replace them with a single CreateLayout. By the way, there were 17 methods of these methods in the old project, and they were called from each other with the help of complex conditional operators. In the cache class, the onEvent event handler is declared, which we will connect via the event map. Here the handler reflects the message to the parent window, where it is displayed in the information field as in the previous versions of the example.

The styler class provides for setting the same fields for all elements, a non-standard font on all buttons, and displaying CEdit with the "read-only" attribute in grey (we have one, but if added, it will automatically fall under the general setting).

A reference to the cache is stored in the window, it is created and deleted in the constructor and destructor respectively, with the window reference passed as a parameter when created to provide feedback.


An algorithm for scaling nested elements to fit the size of the container has been added to the CBox class. It is executed in the AdjustFlexControls method and takes effect only if the special value WND_ALIGN_CONTENT is specified in the container alignment flags. It is not part of the standard ENUM_WND_ALIGN_FLAGS enumeration. The container analyses the "controls" to see which ones are fixed-sized and which ones are not. "Controls" with a fixed size are those for which no alignment to the sides of the container (in a particular dimension) is specified. For all such "controls", the container calculates the sum of their sizes, subtracts it from the total container size, and divides the remainder proportionally among all remaining "controls". For example, if there are two "controls" in the container, and neither of them has an anchor, they will share the entire container area in half.

This is a very convenient mode, but it should not be abused on a set of nested containers - because of the one-pass algorithm of size calculation, alignment of internal elements to the area of the container, which in turn is adjusted to the content generates uncertainty (for this reason, the layout classes have a special ON_LAYOUT_REFRESH event, which the window can send to itself in order to repeat the size calculation).

The ON_EVENT_LAYOUT_CTRL_DLG macro enables mouse click notifications for any buttons of the NotifiableButton class (in our case, there is only one). The ON_EVENT_LAYOUT_INDEX macro sends the same event to the button with the specified index in the cache. But this macro could not be written, because the last line of the ON_EVENT_LAYOUT_ARRAY macro will send a mouse click to any element in the cache if its lparam identifier matches.

In principle, you could move all the items to the cache and handle their events in a new way, but the old way works too and they can be combined.

Example 3. DynamicForm dynamic layouts

In this last example, we will look at a form where all elements will be dynamically created in the cache. This will give us a couple of important new features.

As in the previous example, the cache will support element styling. The only styling settings are the same prominent boxes, which will allow us to see containers nested within each other and select them as desired with the mouse.

Inside the CreateLayout method, the following simple interface structure is described. The main container occupies the entire client area of the window, as usual. At the top is a block with two buttons: Inject and Export. All the space below it is occupied by a container divided into left and right columns.

The container where new elements should be inserted is first searched for in the cache by the name "column1". This container comes as the first parameter when the injectionPanel object is created. The fact that the element to be passed is already in the cache is taken into account in a special way in the layout algorithm - it is not added to the cache again, but is placed in the container stack as usual. In this way it is possible to add elements to "old" containers.

Based on the user's choice, an object of the required type is created using the new operator in the getPtr auxiliary method. In order for the added "controls" to work properly, unique identifiers are randomly generated for them. The special AutoPtr class provides the pointer deletion when leaving the code block.

If you add too many elements, they will go outside the container boundaries. This happens because the container classes we have do not yet know how to react correctly to overflow. In this case we could, for example, show a scroll bar and hide the elements that protrude beyond the boundaries.

But it doesn't matter. The point of this example is that we can generate dynamic content by customising the form and provide the necessary filling and size of containers.

In addition to adding elements, this dialogue box also knows how to delete them. Any element on the form can be selected with a mouse click. The class and name of the element are displayed in the log, and the element itself is highlighted with a red frame. If you click on an already selected element, the dialogue box will prompt you to confirm the deletion and will delete the element if you agree. All this is implemented in our cache class.

We can delete any UI element available in the cache, that is, not only those added by the Inject button. In this way we can, for example, delete the whole left half or the right "radio box". But the most interesting thing will happen if we try to delete the top container with two buttons. As a result, the Export button will lose its binding to the dialogue box and will remain on the chart.

This happens because it is the only element deliberately described as an automatic rather than dynamic variable (there is an instance of CButton m_button3 in the form class).

When the standard library tries to remove interface elements, it delegates this to the CArrayObj array class, and it in turn checks the pointer type and removes only objects with POINTER_DYNAMIC. Thus, it becomes obvious that to build an adaptive interface where elements can replace each other or be completely deleted, it is desirable to use dynamic placement, and cache offers a ready solution for this.

Finally, let's turn to the second button of the dialogue - Export. As you can guess by its name, it is intended for saving the current state of the dialogue as a text file in the considered MQL-layout syntax. Of course, the form allows you to customise its appearance only to a limited extent, for demonstration purposes, but the very possibility to unload the appearance into a ready-made MQL code, which can then be easily copied into a program and get the same interface, is potentially quite a valuable technology. Of course, only the interface is transferred, and the event handling code or general settings of the styliser must be plugged in independently.

The export is provided by the LayoutExporter class, we will not look at it in detail, the source codes are attached.



Документация по MQL5: Стандартная библиотека
Документация по MQL5: Стандартная библиотека
  • www.mql5.com
Стандартная библиотека MQL5 написана на языке MQL5 и предназначена для облегчения написания программ (индикаторов, скриптов, экспертов) конечным пользователям. Библиотека обеспечивает удобный доступ к большинству внутренних функций MQL5.
 
I tried to find a system, a concept, a technology in the above text - I did not find it. It is not even a "sketch" and more like a stream of consciousness. However, if you constantly switch to code examples, you will not notice it. And it's a pity.
 
Реter Konow:
I tried to find a system, a concept, a technology in the above text - I did not find it. It is not even a "sketch" and more like a stream of consciousness. However, if you constantly switch to code examples, you will not notice it. It's a pity.

Actually, everything is clear there for someone who knows OOP.

Those who don't know it are to blame.

 
Koldun Zloy:

It's actually pretty clear there for someone who knows OOP.

Those who don't know it are to blame.

I understand the desire to stand up for the author, but it should be done at the level of a professional, not a kindergarten.

We are talking about the structure of the presentation of the concept. In fact, there is no structure or concept in the text of the article. There are bits and pieces, chaotically scattered in different parts. However, those who have developed complex systems can understand it. For the rest of us it will do...

From the first article the goal was stated: to check the realisability of the CONCEPT of GUI layout by means of MQL, in the form of a language wrapper or vis.editor.

So, there is no CONCEPT, but instead spontaneous reasoning diluted with codes.

Example: the author first talks about the cache as a fundamental solution for generating/destroying controllers, and immediately moves on to the styliser, bypassing all other issues. Further, he puts changes to the standard event model after the topic of styles. What kind of weird priorities are these?
 

The point of this markup language is that it does not require a separate interpreter. It is built directly into the program code.

But without knowledge of OOP, you cannot see much in the articles.

And since you don't plan to study OOP, why are you here at all?