Making it easier to program in EiffelVision

34 views
Skip to first unread message

Thomas Beale

unread,
Aug 14, 2012, 8:37:07 AM8/14/12
to eiff...@googlegroups.com
we have built a (rough) layer on top of EV to make it much easier to program visual applications.

This makes it possible to write code like the following:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    make (a_code_select_action_agent: like code_select_action_agent; a_path_select_action_agent: detachable like path_select_action_agent)
        do
            create gui_controls.make (0)

            code_select_action_agent := a_code_select_action_agent
            path_select_action_agent := a_path_select_action_agent

            -- create widgets
            create ev_root_container
            ev_root_container.set_data (Current)

            -- ============ DEFINITION HBOX, with GRID & control panel =============
            create ev_definition_hbox
            ev_definition_hbox.set_padding (Default_padding_width)
            ev_definition_hbox.set_border_width (Default_border_width)
            ev_root_container.extend (ev_definition_hbox)

            -- EV_GRID
            create gui_definition_grid.make (True, False, True, True)
            gui_definition_grid.set_tree_expand_collapse_icons (get_icon_pixmap ("tool/tree_expand"), get_icon_pixmap ("tool/tree_collapse"))
            ev_definition_hbox.extend (gui_definition_grid.ev_grid)

            -- ========== view controls control panel ===========
            create gui_definition_control_panel.make
            ev_definition_hbox.extend (gui_definition_control_panel.ev_root_container)
            ev_definition_hbox.disable_item_expand (gui_definition_control_panel.ev_root_container)

            -- tree collapse/expand control
            create gui_definition_treeview_control.make (create {EVX_TREE_CONTROL_GRID}.make (gui_definition_grid),
                agent (a_row: EV_GRID_ROW): BOOLEAN do Result := not attached {BMM_MODEL_ELEMENT} a_row.data end)
            gui_definition_control_panel.add_frame (gui_definition_treeview_control.ev_root_container, False)

            -- ========= view detail level options  =========

            -- 'Detail level' frame
            create view_detail_frame_ctl.make (get_text ("view_detail_controls_text"), 85, 100, False)
            gui_definition_control_panel.add_frame_control (view_detail_frame_ctl, False)

            -- view detail radio buttons
            create view_detail_radio_ctl.make (get_text ("domain_detail_button_text"), get_text ("technical_detail_button_text"),
                get_text ("domain_detail_button_tooltip"), get_text ("technical_detail_button_tooltip"),
                agent :BOOLEAN do Result := not show_technical_view end,
                agent update_show_technical_view, 0, 0)
            view_detail_frame_ctl.extend (view_detail_radio_ctl.ev_root_container, False)
            gui_controls.extend (view_detail_radio_ctl)

            -- include codes checkbox
            create add_codes_checkbox_ctl.make_active (get_text ("domain_view_add_codes_text"), Void,
                agent :BOOLEAN do Result := show_codes end, agent update_show_codes)
            view_detail_frame_ctl.extend (add_codes_checkbox_ctl.ev_data_control, False)
            gui_controls.extend (add_codes_checkbox_ctl)


            -- ========= RM view options =========

            -- 'RM visibility' frame
            create rm_property_visibility_frame_ctl.make (get_text ("rm_visibility_controls_text"), 85, 0, False)
            gui_definition_control_panel.add_frame_control (rm_property_visibility_frame_ctl, False)

            -- add RM data properties check button
            create rm_attrs_visible_checkbox_ctl.make_active (get_text ("show_rm_properties_button_text"),
                get_text ("show_rm_properties_tooltip"),
                agent :BOOLEAN do Result := show_rm_data_properties end, agent update_show_rm_data_properties)
            gui_controls.extend (rm_attrs_visible_checkbox_ctl)
            rm_property_visibility_frame_ctl.extend (rm_attrs_visible_checkbox_ctl.ev_data_control, False)

            -- add RM runtime properties option check button
            create rm_runtime_attrs_visible_checkbox_ctl.make_active (get_text ("show_rm_runtime_properties_button_text"),
                get_text ("show_rm_runtime_properties_tooltip"),
                agent :BOOLEAN do Result := show_rm_runtime_properties end, agent update_show_rm_runtime_properties)
            gui_controls.extend (rm_runtime_attrs_visible_checkbox_ctl)
            rm_property_visibility_frame_ctl.extend (rm_runtime_attrs_visible_checkbox_ctl.ev_data_control, False)

            -- add RM infrastructure properties option check button
            create rm_if_attrs_visible_checkbox_ctl.make_active (get_text ("show_rm_if_properties_button_text"),
                get_text ("show_rm_if_properties_tooltip"),
                agent :BOOLEAN do Result := show_rm_infrastructure_properties end, agent update_show_rm_infrastructure_properties)
            gui_controls.extend (rm_if_attrs_visible_checkbox_ctl)
            rm_property_visibility_frame_ctl.extend (rm_if_attrs_visible_checkbox_ctl.ev_data_control, False)

            -- 'RM rendering' frame
            create rm_rendering_frame_ctl.make (get_text ("rm_rendering_controls_text"), 85, 0, False)
            gui_definition_control_panel.add_frame_control (rm_rendering_frame_ctl, False)

            -- use RM inheritance rendering check button
            create view_rm_display_inheritance_checkbox_ctl.make_active (get_text ("show_rm_inh_button_text"),
                get_text ("show_rm_inh_button_tooltip"),
                agent :BOOLEAN do Result := show_rm_inheritance end, agent update_show_rm_inheritance)
            gui_controls.extend (view_rm_display_inheritance_checkbox_ctl)
            rm_rendering_frame_ctl.extend (view_rm_display_inheritance_checkbox_ctl.ev_data_control, False)

            -- ============ RULES HBOX, with GRID & control panel =============
            create ev_rules_hbox
            ev_rules_hbox.set_padding (Default_padding_width)
            ev_rules_hbox.set_border_width (Default_border_width)
            ev_root_container.extend (ev_rules_hbox)

            -- EV_GRID
            create gui_rules_grid.make (True, False, True, False)
            gui_rules_grid.set_tree_expand_collapse_icons (get_icon_pixmap ("tool/tree_expand"), get_icon_pixmap ("tool/tree_collapse"))
            ev_rules_hbox.extend (gui_rules_grid.ev_grid)

            -- ========== view controls control panel ===========
            create gui_rules_control_panel.make
            ev_rules_hbox.extend (gui_rules_control_panel.ev_root_container)
            ev_rules_hbox.disable_item_expand (gui_rules_control_panel.ev_root_container)

            -- tree collapse/expand control
            create gui_rules_treeview_control.make (create {EVX_TREE_CONTROL_GRID}.make (gui_rules_grid),
                agent (a_row: EV_GRID_ROW): BOOLEAN do Result := not attached {BMM_MODEL_ELEMENT} a_row.data end)
            gui_rules_control_panel.add_frame (gui_rules_treeview_control.ev_root_container, False)


            -- ==================== setup ============================
            -- initial state
            if not show_technical_view then
                rm_attrs_visible_checkbox_ctl.disable_editable
            end
        end

~~~~~~~~~~~~~~~~~~~

this is about one quarter of the code needed using raw EV calls (for obvious reasons). The library is in an alpha state, and very rough - I have not even separated it into a demonstration application.

What I wonder is: is there any interest to do this, or are there already other efforts to do such things? From my point of view EV2 has massive functionality and great design, but low usability - so we need a layer (multiple layers probably) on top to make it easy to write visual logic. This includes update / display logic for data input, undo/redo chain and so on.

Is there any interest in us making this work more accessible and public? I don't want to waste time on that if noone is interested.

Alternatively, are there other such efforts hiding somewhere?


- thomas
evx.png

Peter Gummer

unread,
Aug 14, 2012, 8:57:20 AM8/14/12
to eiff...@googlegroups.com
Thomas Beale wrote:

> we have built a (rough) layer on top of EV to make it much easier to program visual applications.


What I'm really interested in is a decent replacement for EiffelBuild. Having to hand-code this stuff because EiffelBuild only allows you to design whole windows, rather than individual components, is ridiculous. It's more than 15 years now since Delphi allowed you to design components visually and then assemble them visually and reusably onto windows. Visual Studio has been able to do it too for at least ten years (in my experience; maybe it was doing it long before that).

Hand-coding GUI components is always orders of magnitude slower than a decent visual designer, no matter how well designed the libraries are or how proficient you've become at hand-coding it. With a good visual designer, the feedback is instantaneous: you see immediately that things are not how you want them to look, rather than having to go through a code-compile-run cycle.

Would you write a long document that contains complicated formatting and diagrams, by hand-coding it in a mark-up language? Sure you could do it, but it would be much quicker to use a proper word processing application. It's the same with GUI designers: they are just a far more efficient. EiffelVision deserves better than EiffelBuild.

Peter

Thomas Beale

unread,
Aug 14, 2012, 9:22:45 AM8/14/12
to eiff...@googlegroups.com
I agree, but I think it isn't so simple. For example, the call below does the following:
  • create a new EV_MULTIPLE_COLUMN_LIST (via EVX_TEXT_LIST_CONTROL)
  • with a label (first arg)
  • connect it to a ARRAYED_LIST [STRING] data source for display - source_archetype.description.other_contributors (2nd arg)
  • connect the visual control via add-new and remove-existing agents to the back-end object (modify is done by direct knowledge of ARRAYED_LIST [STRING] semantics) (args 3&4)
  • connect an undo/redo chain that is used for a dozen or so components on the same form (arg 5)
  • set some height and width values (args 6&7)
  • indicate whether to make the control + label horizonally or vertically arranged (arg 8)
            -- contributors - list
            create auth_contrib_list_ctl.make_editable (get_text ("auth_contrib_label_text"),
                agent :DYNAMIC_LIST [STRING] do if attached source_archetype.description.other_contributors then Result := source_archetype.description.other_contributors end end,
                agent (a_str: STRING; i: INTEGER) do source_archetype.description.add_other_contributor (a_str, i) end,
                agent (a_str: STRING) do source_archetype.description.remove_other_contributor (a_str) end,
                authoring_tab_undo_redo_chain,
                30, min_entry_control_width, False)

            auth_contrib_list_ctl: EVX_TEXT_LIST_CONTROL

Visual appearance is as follows:



The thing that took some work was all the agent connecting logic. I wonder how that could be done in a visual designer?

Also, we need more higher-level controls. As peter already knows, the following 'control' consists of 2 high-level things I standardised.


  1. the 'control panel', which is the whole panel that can be attached within a EV_XX_BOX with another thing that it controls (EV_GRID etc). The control panel has an inbuilt hide/show widget (the ">>" button).
  2. Within that is a standard 'Tree zoom' control with four buttons for driving a EV_TREE or EV_GRID in tree mode. Attached to this visual control is a class that knows how to make a EV_GRID or TREE collapse and expand in smart (and dumb) ways. Achieving that required a whole bunch of additions to EV_GRID itself.
I think a new EiffelBuld tool would first have to subscribe to an underlying toolkit, with concepts like the above - obviously engineered better, but essentially assuming that controls have data sources, modifier routines, undo/redo etc that have to be created and connected. Also including high-level smart controls, maybe we can think of them as 'business' or 'scientific' app controls.

So maybe a proper version of this lib is the kind of thing that a new generation EiffelBuild needs to be based on?

- thomas

Peter Gummer

unread,
Aug 14, 2012, 9:44:08 AM8/14/12
to eiff...@googlegroups.com
Thomas Beale wrote:

> The thing that took some work was all the agent connecting logic. I wonder how that could be done in a visual designer?


EiffelBuild, Delphi, Visual Studio ... they all allow you to hook up agents (or, as Delphi and .NET prefer to call them, "events") to visual widgets.

You still have to write the code inside the agent yourself, of course.

But I wouldn't even care too much about agents. I'm just saying that I think it's really dumb that we have to write code in order to do visual layout. I'm perfectly happy to hook my agents up manually in code, if I have to ... I just don't want to have to go through a code-compile-run cycle in order to see whether it looks good, because it takes a minute or so to do that each time, whereas doing it visually is instantaneous.


> I think a new EiffelBuld tool would first have to subscribe to an underlying toolkit, with concepts like the above - obviously engineered better, but essentially assuming that controls have data sources, modifier routines, undo/redo etc that have to be created and connected. Also including high-level smart controls, maybe we can think of them as 'business' or 'scientific' app controls.
>
> So maybe a proper version of this lib is the kind of thing that a new generation EiffelBuild needs to be based on?


Maybe. I'm not a fan of doing data-binding via GUI designers. I learned a long time ago that although it tends make easy tasks marginally easier, it makes slightly more difficult tasks almost impossible. In the long run (in my experience) the pain outweighs the gain.

I just want to do visual stuff visually. EiffelBuild really does do 90% of what I want.

I'm happy to write code for non-visual stuff (data-binding, agents, etc.), because code is good at that.

Peter
Reply all
Reply to author
Forward
0 new messages