Creating a graphic library from scratch - page 9

 
Aliaksandr Hryshyn:

More:

Right-click on the window areas with the right mouse button, a menu appears. Shift the mouse and click with the left mouse button. This causes the window to move.

It is possible. For your information, I'm developing and testing myself, so I simply don't know about some bugs until I accidentally encounter them in the process. I'm doing everything by myself...

 

Here's my example, in the attached file, there are three windows overlapping each other.

Creating one window with subwindows is like this, just using the engine without additional code. Except for handling the event of clicking on the top buttons.

cStrategy_viewer::cStrategy_viewer()
  {
   int width_type=126;
   int height_type=30;
   int width_object=170;
   int height_object=22;

   my_handler.md=GetPointer(this);
   int obj_types_count=(ER_NODE_TYPE_COUNT-1);
//Основное окно
   _main_window=new cV_object_rectangle();
   _main_window.Set_property_info(vop_position_x,10);
   _main_window.Set_property_info(vop_position_y,50);
   _main_window.Set_property_info(vop_size_x,width_type*obj_types_count);
   _main_window.Set_property_info(vop_size_y,700);
   _main_window.Set_property_info(vop_is_zorder_top_on_click,true);
   _main_window.Create(cV_object_base::global_parent_object);
//Заголовок
   cV_object_rectangle *caption=new cV_object_rectangle();
   caption.Set_property_info(vop_position_x,-1);
   caption.Set_property_info(vop_position_y,-1);
   caption.Set_property_info(vop_size_x,_main_window.Get_property(vop_size_x).data_long);
   caption.Set_property_info(vop_size_y,20);
   caption.Create(_main_window);
//Текст заголовка.Будет отображаться полное имя файла стратегии
   _caption_text=new cV_object_label();
   _caption_text.Set_property_info(vop_position_x,-1);
   _caption_text.Set_property_info(vop_position_y,-1);
   _caption_text.Set_property_info(vop_size_x,caption.Get_property(vop_size_x).data_long);
   _caption_text.Set_property_info(vop_text,"Стратегия ....");
   _caption_text.Set_property_info(vop_text_anchor,TA_CENTER);
   _caption_text.Set_property_info(vop_font_size,20);
   _caption_text.Set_property_info(vop_is_movable,true);
   _caption_text.Set_property_info(vop_moving_parent_index,2);
   _caption_text.Set_property_info(vop_is_position_fixing_parent_x,true);
   _caption_text.Set_property_info(vop_is_position_fixing_parent_y,true);
   _caption_text.Set_property_info(vop_position_fixing_parent_index_x,2);
   _caption_text.Set_property_info(vop_position_fixing_parent_index_y,2);
   _caption_text.Create(caption);
//Контейнер для типов объектов
   _object_types=new cV_object_base();
   _object_types.Set_property_info(vop_position_x,0);
   _object_types.Set_property_info(vop_position_y,20);
   _object_types.Set_property_info(vop_size_x,obj_types_count*width_type);
   _object_types.Set_property_info(vop_size_y,height_type);
   _object_types.Create(_main_window);
//Типы объектов
   cV_object_rectangle *obje_type;
   cV_object_label *obje_type_text;
   for(int i1=0; i1<obj_types_count; i1++)
     {
      obje_type=new cV_object_rectangle();
      obje_type.Set_property_info(vop_position_x,i1*width_type);
      obje_type.Set_property_info(vop_position_y,0);
      obje_type.Set_property_info(vop_size_x,width_type);
      obje_type.Set_property_info(vop_size_y,height_type);
      obje_type.Set_property_info(vop_border_line_width,3);
      obje_type.Set_property_info(vop_color_borders_mouse_moving,clrLightBlue);
      obje_type.Set_property_info(vop_color_borders_selected,clrYellow);
      obje_type.Set_property_info(vop_is_change_color_borders_on_mouse_move,true);
      obje_type.Set_property_info(vop_is_change_color_borders_on_select,true);
      obje_type.Set_property_info(vop_is_selected,false);
      obje_type.Set_property_info(vop_is_my_event_MOUSE_DOWN_UP_CLICK_LEFT,true);
      color clr=0;
      switch(eNode_type(i1+1))
        {
         case nt_function:
           {
            clr=clrDimGray;
            break;
           }
         case nt_indicator_data:
           {
            clr=clrNavy;
            break;
           }
         case nt_indicator:
           {
            clr=clrMaroon;
            break;
           }
         case nt_if:
           {
            clr=clrBlack;
            break;
           }
         case nt_const:
           {
            clr=clrGreen;
            break;
           }
         case nt_buffer:
           {
            clr=clrBlue;
            break;
           }
         case nt_node_top:
           {
            clr=clrIndigo;
            break;
           }
        }
      obje_type.Set_property_info(vop_color_borders,clr);
      obje_type.Set_property_info(vop_color_back,clr);
      obje_type.Create(_object_types);
      obje_type.Add_event_handler(GetPointer(my_handler));
      obje_type_text=new cV_object_label();
      obje_type_text.Set_property_info(vop_text,StringSubstr(EnumToString(eNode_type(i1+1)),3));
      obje_type_text.Set_property_info(vop_color_back,clrWhite);
      obje_type_text.Set_property_info(vop_size_x,width_type-1);
      obje_type_text.Set_property_info(vop_position_x,-3);
      obje_type_text.Set_property_info(vop_position_y,5-3);
      obje_type_text.Set_property_info(vop_text_anchor,TA_CENTER);
      obje_type_text.Set_property_info(vop_font_size,18);
      obje_type_text.Create(obje_type);
     }
   _object_types.Get_child(0).Set_property(vop_is_selected,true);
//Окно отображения объектов
   cV_object_rectangle *objects_viever=new cV_object_rectangle();
   objects_viever.Set_property_info(vop_position_x,0);
   objects_viever.Set_property_info(vop_position_y,height_type+_object_types.Get_property(vop_position_y).data_long);
   objects_viever.Set_property_info(vop_size_x,width_object);
   objects_viever.Set_property_info(vop_size_y,30*height_object);
   objects_viever.Create(_main_window);
//Контейнер объектов
   int functions_count=cRules::Get_object_count(nt_function);
   _objects=new cV_object_base();
   _objects.Set_property_info(vop_position_x,0);
   _objects.Set_property_info(vop_position_y,0);
   _objects.Set_property_info(vop_size_x,width_object);
   _objects.Set_property_info(vop_size_y,functions_count*height_object);
   _objects.Set_property_info(vop_color_back,clrOlive);
//_objects.Set_property_info(vop_is_position_fixing_parent_x,true);
//_objects.Set_property_info(vop_is_position_fixing_parent_y,true);
   _objects.Create(objects_viever);
//Объекты
   for(int i1=0; i1<functions_count; i1++)
     {
      cV_object_label *object=new cV_object_label();
      object.Set_property_info(vop_size_x,width_object-2);
      object.Set_property_info(vop_position_x,1);
      object.Set_property_info(vop_position_y,i1*height_object);
      object.Set_property_info(vop_color_back,clrWhite);
      object.Set_property_info(vop_text,cRules::Get_object_name(nt_function,i1));
      object.Set_property_info(vop_text_anchor,TA_LEFT);
      object.Set_property_info(vop_font_size,height_object-2);
      object.Create(_objects);
     }
  }

Handling the event of clicking on the top buttons:

void cStrategy_viewer::cMy_handler::On_event(sEvent &event)
  {
   cV_object_base *obj=GetPointer(event.object);
   switch(event.id)
     {
      case CHARTEVENT_CLICK_:
        {
         if(obj.Get_parent()==GetPointer(md._object_types))
           {
            obj.Set_property(vop_is_selected,true);
           }
         break;
        }
     }
  }

There are several buttons and only one parent window

Files:
 
Реter Konow:

There was such a bug. Fixed it. The event itself is fixed fine, but bugs occur with various changes that cannot be avoided in code development.

Yes, it's complicated.

A picture from the demo:


 
It's just that in a business like this, the first thing you have to do is work out the events and window controls, and the rest is easier, although there's a lot more work to be done elsewhere.
 
Anyone interested in making a visual element library from scratch :) ?
 
Aliaksandr Hryshyn:
It's just that in this case, first of all, we have to elaborate the events and window controls, the rest is easier, but there is much more work to do.

The groundwork is already in place.

1: windows should have close and collapse buttons (at least).

2: windows should redraw on top of each other when clicked.

3: The windows should move with the mouse.

4: windows should be "detected" (brought into focus) on the chart when the cursor moves ( pointed event).

5. All elements of the windows must be on a common "map" of the window and be detected when the mouse is hovered (event pointed).

 

The simplest elements:

1. A static, dimensionally unchanging and indelible Window.

2. Button.

3. Checkbox.

4. Radio button.

5. Tab.

6. Line, frame, divider, rectangle.


Elements of medium complexity:

1. Sliders.

2. Progress bars.

3. Input fields.

4. Scrolling fields.

5. Simple list items.


High-complexity items.

1. A drop-down list (a very complex element).

2. A dynamic (stretchable) window. Super-complex.


There are about 50 types of controls. Each should have a common and unique set of properties supported by the corresponding engine functionality. Properties at least 100, otherwise the work of the elements will be severely limited.

Simple shapes and lines don't need many properties, but the more complex the element, the more there are.
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
Документация по MQL5: Константы, перечисления и структуры / Константы объектов / Свойства объектов
  • www.mql5.com
Все объекты, используемые в техническом анализе, имеют привязку на графиках по координатам цены и времени – трендовая линия, каналы, инструменты Фибоначчи и т.д.  Но есть ряд вспомогательных объектов, предназначенных для улучшения интерфейса, которые имеют привязку к видимой всегда части графика (основное окно графика или подокна индикаторов...
 

Shit! I forgot about the tables! It's a jungle out there... ))))

And a tree-like list, and all sorts of collapsers of all sorts...

 
Each interactive control has a parameter controlled by it with its own set of properties. For example, a button has a bool-type parameter (1 or 0), an input field has a string-type parameter, a slider has a range-type parameter... An input field with buttons has a parameter with properties current_value, last_value, min, max, step, value_type and others. Each property is supported by the functionality.

Each interactive element should (ideally) have 8 different states that change at different events.

For example: neutral, neutral_pointed, activated_neutral, activated_pointed, neutral_highlighted, activated_highlighted, neutral_locked, activated_locked.

Each state is designed with its own set of element property values and comes into effect at its own events, which are fixed by special functionality.
 
Реter Konow:

Shit! I forgot about the tables! It's a jungle out there... ))))

And a tree-like list, and all sorts of collapsers...

In my case, the "jungle" is no more complicated than average: a display window (the visible area of the table), a full-size window in which all cells must fit, it will slide inside the main window, windows for rows and cells in them, plus scrolling (a slider bounded by a bar). The constraints on relative positioning are determined by the properties. Only for the slider it is necessary to intercept object movement events and already correct the position ofthe "full size window". This is all done by virtual windows, we need to bolt visual part to it, without visual part there will be windows for lines and full size window. And for an editable cell, make an input field (this is a custom one), all the other stuff will be handled by the engine - it will get right events for each cell (mouse events, redrawing, moving)..... These are the possibilities, but there are also a couple of ideas to increase performance in case there are too many windows (large lists, tables, several thousand windows).

Reason: