Discussion of article "Graphical Interfaces I: Preparation of the Library Structure (Chapter 1)" - page 3

 
AlexBar3073:

...But from the OOP point of view, the proposed method has the best chance of practical implementation. :)

Easier said than done.

AlexBar3073:

...

Let's consider, for example, the function of moving a form on the graph.

In the function we need to enumerate all created objects of the form. Why? Because all the created elements are placed in the container (array) of the form itself. Why do you need to enumerate all the created elements in the function? Why can't you just loop around the container and change the coordinates of all the elements?

...

Pay attention to the type(CChartObject) of the array(m_objects), which stores pointers of all graphical objects of this or that element(CElement). You can try to use dynamic type conversion in this case, but then the code will become even more complicated and voracious in terms of resource consumption, because you will have to make additional checks for the pointer type.

As for Delete() and similar methods, you can loop through them (I just haven't got to it yet), since all objects have CChartObject type.

I cautiously assume that everything will become much easier after the transition to the second stage of library development, when all elements will be drawn. That is, there will be one element - one object(bmp).

 
Anatoli Kazharski:

additional checks on pointer type.

And how to make a check on the pointer type in MQL?

According to my data, the language does not have any means for this. I would like to check if an object is an instance of a particular class or if it is a descendant of a class in the hierarchy.

For example, I am implementing an MVC pattern and for certain models with editable properties (having a common ancestor) I subscribe one view-object. In order to display the property table of this object. After changes to the model, the listener (view) is redrawn and the model object is passed.

Here we have to cast the model to one of the model hierarchy types (which can return properties). But it is impossible to check that an object of the right type has arrived.

Theoretically, a third-party programmer creating an application for an interface can make a mistake and sign this view to another model (from another hierarchy, which does not have an ancestor with editable properties). This cannot be handled in runtime and the application will crash.

Anatoli Kazharski:

I cautiously assume that everything will become much easier after the transition to the second stage of library development, when all elements will be drawn. That is, there will be one element - one object(bmp).

I just went this way a couple of years ago. First I made a DOM model for the interface, drawing primitives, aggregation of views, passing events (popup, stop). Everything was drawn on MQL graph objects and in principle worked. But when the number of objects exceeded 200, it started to slow down due to the overhead of redrawing each object. That's why everything was abandoned for another year until Canvas appeared. Then everything was quickly transferred to it by replacing the basic draw methods of view and update logic without changing anything else. And now even several thousand views on the screen do not lead to delayed drawing, because everything is drawn and compared very quickly in memory, and the output is only a picture, i.e. only 1 element from the objects on the chart.

However, for the last year, for lack of free time, the development of the UI library has practically stopped.


 

In order not to be unsubstantiated, I will give an example of an interface built on the basis of UI on a single Canvas element

 
Igor Volodin:

In order not to be unsubstantiated I will give an example of an interface built on the basis of UI on one element Canvas

+ likes )
 
Igor Volodin:

How can I check for the pointer type in MQL?

According to my data, the language does not have any means for this. I would like to check if an object is an instance of a particular class or if it is a descendant of a class in the hierarchy.

For example, I am implementing an MVC pattern and for certain models with editable properties (having a common ancestor) I subscribe one view-object. In order to display the property table of this object. After changes to the model, the listener (view) is redrawn and the model object is passed.

Here we have to cast the model to one of the model hierarchy types (which can return properties). But it is impossible to check that an object of the right type has arrived.

Theoretically, a third-party programmer creating an application for an interface can make a mistake and sign this view to another model (from another hierarchy, which does not have an ancestor with editable properties). This cannot be handled in runtime and the application will crash.

...

Maybe via dynamic_cast? When I started developing the library, dynamic_cast was not available yet.

Something like this (example from here) :

class CFoo { };
class CBar { };
//+------------------------------------------------------------------+
//| Script programme start function|
//+------------------------------------------------------------------+
void OnStart()
  {
   void *vptr[2];
   vptr[0]=new CFoo();
   vptr[1]=new CBar();
//---
   for(int i=0;i<ArraySize(vptr);i++)
     {
      if(dynamic_cast<CFoo *>(vptr[i])!=NULL)
         Print("CFoo * object at index ",i);
      if(dynamic_cast<CBar *>(vptr[i])!=NULL)
         Print("CBar * object at index ",i);
     }
   CFoo *fptr=vptr[1];  // pointer conversion error, vptr[1] is not a CFoo object
  }
//+------------------------------------------------------------------+

//---

Igor Volodin:

I followed this way a couple of years ago. First I made a DOM model for the interface, drawing primitives, aggregation of views, passing events (popup, stop). Everything was drawn on MQL graph objects and in principle worked. But when the number of objects exceeded 200, it started to slow down due to the overhead of redrawing each object. That's why everything was abandoned for another year until Canvas appeared. Then everything was quickly transferred to it by replacing the basic draw methods of view and update logic without changing anything else. And now even several thousand views on the screen do not lead to delayed drawing, because everything is drawn and compared very quickly in memory, and the output is only a picture, i.e. only 1 element from the objects on the chart.

It is true that for the last year, for lack of free time, the development of the UI library has practically stopped.

This is very interesting. Have you implemented your own input fields too ?

 
Igor Volodin:

In order not to be unsubstantiated, I will give an example of an interface built on the basis of UI on one Bitmap element

Looks cool. Thanks for the example. )

There was a topic where your recommendations would be very useful: Making a crowdsource project on Canvas

 
Anatoli Kazharski:

Maybe via dynamic_cast? When I started developing the library dynamic_cast was not yet available.

CFoo *foo = dynamic_cast<CFoo *>(&bar); // no critical execution error will occur


Oh, I didn't see that. Oh, thank you. It turns out they added it in August. If it returns NULL and no critical error occurs, it's already very good. We can work )

Anatoli Kazharski:

Have you implemented your own input fields too?

With input fields it is done like this:

at the event focus on the object of the editable field, a graphical object of the editable field of the required configuration with the current value is inserted into the UI, with which you can work, using also the input buffer (there is no way without it in the interface),

at blur event the value of the field is saved (and the system graph object - Edit is deleted). And the value is displayed on the bmp with text.

 

Igor Volodin:

...

With input fields it is done in the following way:

at the focus event on the object of the editable field, a graphical object of the editable field of the required configuration with the current value is inserted into the UI, with which you can work using, among other things, the input buffer (there is no way to work without it in the interface),

at blur event the value of the field is saved (and the system graph object - Edit is deleted). And the value is displayed on the bmp as text.

Aha, got it. Thanks for the clarification.

I think that this is the best option, but I want to try to realise everything in such a way that everything is drawn on one object. It would allow to get full independence and experience when it doesn't matter in what environment you create a GUI. Let's say there is only a canvas and nothing else. )

 
Anatoli Kazharski:

Looks cool. Thanks for the example. )

There was a topic here where your recommendations would come in handy: Doing a crowdsourced Canvas project

Thanks. Looking at your amount of work on the interface, a big kudos to you. I wouldn't have been able to do that. Firstly publicity, secondly consistency.

Crowdsourced? Risky. Of course, if you have a stable income and free time, it is possible to work for the benefit of society. But MQL society will use it for commercial products, not free ones. And the GPL licence alone will not prohibit it.

In short, I don't see any profit for me.

 
Anatoli Kazharski:

But eventually I would like to try to realise everything in such a way that everything is drawn on one object. It would allow to get full independence and experience when it doesn't matter in what environment you create a graphic interface. Let's say there is only a canvas and nothing else. )

Ask Renate for functions to work with the system buffer and you can draw everything.