--- title: Developing UI order: 91 --- ## TL;DR - To create a new page in abapGit you subclass `ZCL_ABAPGIT_GUI_PAGE` and redefine `RENDER_CONTENT` method - Use `ZCL_ABAPGIT_HTML` to collect HTML content - Use `ZCL_ABAPGIT_HTML=>ICON` to render icons - Use `ZCL_ABAPGIT_HTML=>A` to render anchors, don't render them manually `...` - Please, please, care about usability, content readability and style in general :pray: ;) - Check `ZCL_ABAPGIT_GUI_CHUNK_LIB` for some existing html chunks like `render_error` ## GUI components abapGit UI is based on HTML and `CL_GUI_HTML_VIEWER`. Main parts are: - ZCL_ABAPGIT_GUI - the class which initializes `CL_GUI_HTML_VIEWER` and manages page stack - ZCL_ABAPGIT_GUI_ASSET_MANAGER - manages static assets like images, css, js code and fonts - ZCL_ABAPGIT_HTML - helper for HTML accumulation and rendering - ZCL_ABAPGIT_GUI_ROUTER - abapGit specific global event handling, main to route between the pages or run globally defined actions like repo installation - ZCL_ABAPGIT_GUI_PAGE - base class for pages. It renders typical html headers and abapGit related java scripts. So in most cases you probably just want to subclass it and render just the content ## Rendering content An example of `RENDER_CONTENT` (or any other helper method with HTML output) ```abap METHOD render_content. CREATE OBJECT ro_html. ro_html->add( '
' ). ro_html->add( '

My content

' ). ro_html->add_icon( 'star/error' ). ro_html->add_a( iv_txt = 'click me' iv_act = 'some_event_handled_in_abap' ). ro_html->add( render_some_complex_stuff( ) ). ro_html->add( '
' ). ENDMETHOD. ``` ### Html helper `ro_html` which is the instance of `ZCL_ABAPGIT_HTML` is helper tool for html rendering. It accumulates html content and then can output it with `render` method. It has a couple of important methods: - **ADD** - adds a chunk to accumulated HTML. You can pass a string or another `ZCL_ABAPGIT_HTML` instance. In the example above `render_some_stuff` may either return a string or have the same pattern as `render_content` (retuning `ZCL_ABAPGIT_HTML` instance) - **ADD_ICON and ICON** - renders an icon. abapGit uses web-fonts to render icons (see [adding icons](./development/adding-icons.html)). The method accepts the icon name and a css-class name which represents a color separated by '/'. E.g. in the example above it will render 'star' icon and assign 'error' css class to it which has red color in abapGit styes. The method has it's static brother `ZCL_ABAPGIT_HTML=>ICON` which is more convenient in some cases and just returns a rendered html string. - **ADD_A and A** - renders a link (anchor) (`A` - static method). It is strongly suggested that you use this method instead of rendering `` tags directly. Params: - `IV_TXT` - text to be rendered inside anchor - `IV_TYP` - type of action done on click. 3 options: - `zif_abapgit_html=>c_action_type-url`- direct link to an url, - `...-sapevent` (the default) - pass an event to sap handler, - `...-onclick` - call a JS function, - `...-dummy` - just render an anchor but no action - `IV_ACT` - depending on the type should be either URL or sapevent name or JS function to call - `IV_OPT` - `zif_abapgit_html=>c_html_opt-strong` or `...-cancel` or `...-crossout` - some semantic predefined styles to add to the link - `IV_CLASS` - additional css class, if needed - `IV_STYLE` - additional direct styles to use (generally discouraged, please use css classes instead) - `IV_ID` - id of the anchor (may be needed for JS code) ## Renderables Sub-classing `ZCL_ABAPGIT_GUI_PAGE` is not the only way to render the content. You may want to separate some visual component which is not a page e.g. `ZCL_ABAPGIT_GUI_VIEW_REPO` is a class like that. In essence you have to implement `ZIF_ABAPGIT_GUI_RENDERABLE` and it's method - `render`. Then you can reuse it or even pass directly to GUI class as a page to render. ## Router and event handlers To process sapevents in abap the component (page) must implement `ZIF_ABAPGIT_GUI_EVENT_HANDLER=>on_event`. It has the same importing params as `sapevent` handler of `cl_gui_html_viewer`, please refer SAP official documentation for param meaning and detail. For the exporting params see below. Events can be processed on 2 levels - in page **or** in the router. If an event occures, the GUI checks if the current page implements `ZIF_ABAPGIT_GUI_EVENT_HANDLER` and if so calls it. If the event was not handled by the page (see below how this is indicated) the event is passed to the router. Router (`ZCL_ABAPGIT_GUI_ROUTER`) is the class which handle global abapGit commands like opening specific pages and actions like repo installation/deletion. In order to indicate the result of event handling an `on_event` implementation must return `ev_state` (element of `zcl_abapgit_gui=>c_event_state`) and, optionally, `ei_page`: - `not_handled` (same as `initial`) - event was not handled, process by next handler (e.g. the router) - `re_render` - just re-render the current page (probably internal state of the page object was changed so the visualization should too) - `new_page` - render `ei_page` - `go_back` - render previous page in the call stack (e.g. user pressed F3) - `no_more_act` - action was handled, no further processing required, and in particular **no re-rendering** - `new_page_w_bookmark` - `ei_page` and put a bookmark - allows to use `go_back_to_bookmark` action that will skip all the page stack till the first bookmark - `new_page_replacing` - `ei_page` and replace the current page in stack (so that F3 returns to the parent of the current page) - `go_back_to_bookmark` - go back and skip all the page stack till the first bookmark (works with `new_page_w_bookmark`) ## Asset manager `ZCL_ABAPGIT_GUI_ASSET_MANAGER` class is responsible for managing static assets. Very briefly: relevant assets must be registered in the asset manager instance during GUI initiation so that they can be used in the browser UI. The registration happens in `ZCL_ABAPGIT_UI_FACTORY=>INIT_ASSET_MANAGER`. Here is an abstract from the method for example: ```abap DEFINE _inline. APPEND &1 TO lt_inline. " <<< THIS IS USED TO INCLUDE ASSET IN-CODE WITH ABAPMERGE END-OF-DEFINITION. DATA lt_inline TYPE string_table. CLEAR lt_inline. " @@abapmerge include zabapgit_css_common.w3mi.data.css > _inline '$$'. ro_asset_man->register_asset( iv_url = 'css/common.css' " <<< PATH TO THE ASSET FROM HTML, WHICH IS ALSO IT'S UNIQUE NAME iv_type = 'text/css' " <<< CONTENT TYPE OF THE ASSET iv_mime_name = 'ZABAPGIT_CSS_COMMON' " <<< MIME OBJECT NAME iv_inline = concat_lines_of( table = lt_inline sep = cl_abap_char_utilities=>newline ) ). CLEAR lt_inline. " @@abapmerge include-base64 zabapgit_icon_font.w3mi.data.woff > _inline '$$'. " <<< THE FILE BINARY !!! ro_asset_man->register_asset( iv_url = 'font/ag-icons.woff' iv_type = 'font/woff' iv_mime_name = 'ZABAPGIT_ICON_FONT' iv_base64 = concat_lines_of( table = lt_inline ) ). " see https://github.com/larshp/abapGit/issues/201 for source SVG ro_asset_man->register_asset( iv_url = 'img/logo' iv_type = 'image/png' iv_base64 = 'iVBORw0KGgoAAAANSUhENCSVQICAgIfAhkiAAA...'. ``` There are several ways to store content of a static asset in abapGit. 1. Pass the asset inline. e.g. the logo at the end is a PNG image. It is encoded as BASE64 and passed as `iv_base64` param 2. Inline can be also a text then should be passed with `iv_inline` 3. Read from a MIME object - if inline is not passed, the assets falls back to the MIME The tricky thing is that abapGit can be either installed as a development version, deploying all the MIME objects in particular **or** as a single file. This single file must contain all the assets (images, css, js and fonts) **in-code**. This is enabled by **abapmerge** tool. Consider the `css/common.css` registration above. - First, `lt_inline` is cleared. And in the development version of abapGit it is then just passed to `register_asset` being initial. The asset manager is thus falls back to `ZABAPGIT_CSS_COMMON` MIME object (which is conveniently deployed in case of dev version). - in case of one-file abapGit version there is no MIME object. However, `@@abapmerge include` statement is processed by abapmerge and the file `zabapgit_css_common.w3mi.data.css` is included to the code line by line in form of `_inline '$$'`, where `$$` is the text file line. Thus, at the moment of `register_asset` the content of `lt_inline` is **not** initial and takes the priority over the missing MIME. Note: for the binary files, like fonts, use `@@abapmerge include-base64` pragma.