abapGit/src/ui/zcl_abapgit_gui_page.clas.abap
Alexander Tsybulsky c056076170
Gui refactoring 2 (#3338)
* hotkeys refactoring: draft logic

- new interfaces
- gui services binding
- move render to zcl_hotkeys
- move global hotkeys to hotkeys class
- remove unnecessary stuff from gui_page

* implement zif_abapgit_gui_hotkeys in rel.pages

* settings page draft

* remove zif_abapgit_gui_page_hotkey

* linter fixes

* finalize rendering logic

* finalize settings

* linter fix

* sorting tweak

* fix abapgit_full work

Co-authored-by: Christian Günter <christianguenter@googlemail.com>
Co-authored-by: Lars Hvam <larshp@hotmail.com>
Co-authored-by: Frederik Hudák <frederik.hudak@sap.com>
2020-05-08 10:26:54 +02:00

443 lines
13 KiB
ABAP

CLASS zcl_abapgit_gui_page DEFINITION PUBLIC ABSTRACT
INHERITING FROM zcl_abapgit_gui_component
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES:
zif_abapgit_gui_renderable,
zif_abapgit_gui_event_handler,
zif_abapgit_gui_error_handler.
METHODS:
constructor RAISING zcx_abapgit_exception.
PROTECTED SECTION.
TYPES: BEGIN OF ty_control,
redirect_url TYPE string,
page_title TYPE string,
page_menu TYPE REF TO zcl_abapgit_html_toolbar,
END OF ty_control.
TYPES: BEGIN OF ty_event,
method TYPE string,
name TYPE string,
END OF ty_event.
TYPES: tt_events TYPE STANDARD TABLE OF ty_event WITH DEFAULT KEY.
DATA: ms_control TYPE ty_control.
METHODS render_content ABSTRACT
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html
RAISING zcx_abapgit_exception.
METHODS get_events
RETURNING VALUE(rt_events) TYPE tt_events
RAISING zcx_abapgit_exception.
METHODS render_event_as_form
IMPORTING is_event TYPE ty_event
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html
RAISING zcx_abapgit_exception.
METHODS scripts
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html
RAISING zcx_abapgit_exception.
PRIVATE SECTION.
DATA: mo_settings TYPE REF TO zcl_abapgit_settings,
mx_error TYPE REF TO zcx_abapgit_exception,
mo_exception_viewer TYPE REF TO zcl_abapgit_exception_viewer.
METHODS html_head
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
METHODS title
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
METHODS footer
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
METHODS redirect
RETURNING VALUE(ro_html) TYPE REF TO zcl_abapgit_html.
METHODS link_hints
IMPORTING
io_html TYPE REF TO zcl_abapgit_html
RAISING
zcx_abapgit_exception.
METHODS insert_hotkeys_to_page
IMPORTING
io_html TYPE REF TO zcl_abapgit_html
RAISING
zcx_abapgit_exception.
METHODS render_hotkey_overview
RETURNING
VALUE(ro_html) TYPE REF TO zif_abapgit_html
RAISING
zcx_abapgit_exception.
METHODS call_browser
IMPORTING
iv_url TYPE csequence
RAISING
zcx_abapgit_exception.
METHODS render_error_message_box
RETURNING
VALUE(ro_html) TYPE REF TO zcl_abapgit_html
RAISING
zcx_abapgit_exception.
ENDCLASS.
CLASS ZCL_ABAPGIT_GUI_PAGE IMPLEMENTATION.
METHOD call_browser.
cl_gui_frontend_services=>execute(
EXPORTING
document = |{ iv_url }|
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10 ).
IF sy-subrc <> 0.
zcx_abapgit_exception=>raise_t100( ).
ENDIF.
ENDMETHOD.
METHOD constructor.
super->constructor( ).
mo_settings = zcl_abapgit_persist_settings=>get_instance( )->read( ).
ENDMETHOD.
METHOD footer.
CREATE OBJECT ro_html.
ro_html->add( '<div id="footer">' ). "#EC NOTEXT
ro_html->add( zcl_abapgit_html=>a( iv_txt = '<img src="img/logo" alt="logo">'
iv_id = 'abapGitLogo'
iv_act = zif_abapgit_definitions=>c_action-abapgit_home ) ).
ro_html->add( '<table class="w100"><tr>' ). "#EC NOTEXT
ro_html->add( '<td class="w40"></td>' ). "#EC NOTEXT
ro_html->add( |<td><span class="version">{ zif_abapgit_version=>gc_abap_version }</span></td>| ). "#EC NOTEXT
ro_html->add( '<td id="debug-output" class="w40"></td>' ). "#EC NOTEXT
ro_html->add( '</tr></table>' ). "#EC NOTEXT
ro_html->add( '</div>' ). "#EC NOTEXT
ENDMETHOD.
METHOD get_events.
" Return actions you need on your page.
ENDMETHOD.
METHOD html_head.
CREATE OBJECT ro_html.
ro_html->add( '<head>' ). "#EC NOTEXT
ro_html->add( '<meta http-equiv="content-type" content="text/html; charset=utf-8">' ). "#EC NOTEXT
ro_html->add( '<meta http-equiv="X-UA-Compatible" content="IE=11,10,9,8" />' ). "#EC NOTEXT
ro_html->add( '<title>abapGit</title>' ). "#EC NOTEXT
ro_html->add( '<link rel="stylesheet" type="text/css" href="css/common.css">' ).
ro_html->add( '<link rel="stylesheet" type="text/css" href="css/ag-icons.css">' ).
" Themes
ro_html->add( '<link rel="stylesheet" type="text/css" href="css/theme-default.css">' ). " Theme basis
CASE mo_settings->get_ui_theme( ).
WHEN zcl_abapgit_settings=>c_ui_theme-dark.
ro_html->add( '<link rel="stylesheet" type="text/css" href="css/theme-dark.css">' ).
WHEN zcl_abapgit_settings=>c_ui_theme-belize.
ro_html->add( '<link rel="stylesheet" type="text/css" href="css/theme-belize-blue.css">' ).
ENDCASE.
ro_html->add( '<script type="text/javascript" src="js/common.js"></script>' ). "#EC NOTEXT
CASE mo_settings->get_icon_scaling( ). " Enforce icon scaling
WHEN mo_settings->c_icon_scaling-large.
ro_html->add( '<style>.icon { font-size: 200% }</style>' ).
WHEN mo_settings->c_icon_scaling-small.
ro_html->add( '<style>.icon.large { font-size: inherit }</style>' ).
ENDCASE.
ro_html->add( '</head>' ). "#EC NOTEXT
ENDMETHOD.
METHOD insert_hotkeys_to_page.
DATA lv_json TYPE string.
DATA lt_hotkeys TYPE zif_abapgit_gui_hotkeys=>tty_hotkey_with_descr.
FIELD-SYMBOLS: <ls_hotkey> LIKE LINE OF lt_hotkeys.
lt_hotkeys = mi_gui_services->get_hotkeys_ctl( )->get_registered_hotkeys( ).
lv_json = `{`.
LOOP AT lt_hotkeys ASSIGNING <ls_hotkey>.
IF sy-tabix > 1.
lv_json = lv_json && |,|.
ENDIF.
lv_json = lv_json && | "{ <ls_hotkey>-hotkey }" : "{ <ls_hotkey>-action }" |.
ENDLOOP.
lv_json = lv_json && `}`.
io_html->add( |setKeyBindings({ lv_json });| ).
ENDMETHOD.
METHOD link_hints.
DATA: lv_link_hint_key TYPE char01.
lv_link_hint_key = mo_settings->get_link_hint_key( ).
IF mo_settings->get_link_hints_enabled( ) = abap_true AND lv_link_hint_key IS NOT INITIAL.
io_html->add( |activateLinkHints("{ lv_link_hint_key }");| ).
io_html->add( |setInitialFocusWithQuerySelector('a span', true);| ).
io_html->add( |enableArrowListNavigation();| ).
ENDIF.
ENDMETHOD.
METHOD redirect.
CREATE OBJECT ro_html.
ro_html->add( '<!DOCTYPE html>' ). "#EC NOTEXT
ro_html->add( '<html>' ). "#EC NOTEXT
ro_html->add( '<head>' ). "#EC NOTEXT
ro_html->add( |<meta http-equiv="refresh" content="0; url={ ms_control-redirect_url }">| ). "#EC NOTEXT
ro_html->add( '</head>' ). "#EC NOTEXT
ro_html->add( '</html>' ). "#EC NOTEXT
ENDMETHOD.
METHOD render_error_message_box.
" You should remember that the we have to instantiate ro_html even
" it's overwritten further down. Because ADD checks whether it's
" bound.
CREATE OBJECT ro_html.
" You should remember that we render the message panel only
" if we have an error.
IF mx_error IS NOT BOUND.
RETURN.
ENDIF.
ro_html = zcl_abapgit_gui_chunk_lib=>render_error_message_box( mx_error ).
" You should remember that the exception viewer dispatches the events of
" error message panel
CREATE OBJECT mo_exception_viewer
EXPORTING
ix_error = mx_error.
" You should remember that we render the message panel just once
" for each exception/error text.
CLEAR:
mx_error.
ENDMETHOD.
METHOD render_event_as_form.
CREATE OBJECT ro_html.
ro_html->add(
|<form id='form_{ is_event-name }' method={ is_event-method } action='sapevent:{ is_event-name }'></from>| ).
ENDMETHOD.
METHOD render_hotkey_overview.
DATA lo_hotkeys_component TYPE REF TO zif_abapgit_gui_renderable.
lo_hotkeys_component ?= mi_gui_services->get_hotkeys_ctl( ). " Mmmm ...
ro_html = lo_hotkeys_component->render( ).
ENDMETHOD.
METHOD scripts.
CREATE OBJECT ro_html.
link_hints( ro_html ).
insert_hotkeys_to_page( ro_html ).
ro_html->add( 'var gGoRepoPalette = new CommandPalette(enumerateTocAllRepos, {' ).
ro_html->add( ' toggleKey: "F2",' ).
ro_html->add( ' hotkeyDescription: "Go to repo ..."' ).
ro_html->add( '});' ).
ro_html->add( 'var gCommandPalette = new CommandPalette(enumerateToolbarActions, {' ).
ro_html->add( ' toggleKey: "F1",' ).
ro_html->add( ' hotkeyDescription: "Command ..."' ).
ro_html->add( '});' ).
ENDMETHOD.
METHOD title.
CREATE OBJECT ro_html.
ro_html->add( '<div id="header">' ). "#EC NOTEXT
ro_html->add( '<table class="w100"><tr>' ). "#EC NOTEXT
ro_html->add( |<td class="logo">{
zcl_abapgit_html=>a( iv_txt = '<img src="img/logo" alt="logo">'
iv_id = 'abapGitLogo'
iv_act = zif_abapgit_definitions=>c_action-abapgit_home )
}</td>| ). "#EC NOTEXT
ro_html->add( |<td><span class="page_title"> &#x25BA; { ms_control-page_title }</span></td>| ). "#EC NOTEXT
IF ms_control-page_menu IS BOUND.
ro_html->add( '<td class="right">' ). "#EC NOTEXT
ro_html->add( ms_control-page_menu->render( iv_right = abap_true ) ).
ro_html->add( '</td>' ). "#EC NOTEXT
ENDIF.
ro_html->add( '</tr></table>' ). "#EC NOTEXT
ro_html->add( '</div>' ). "#EC NOTEXT
ENDMETHOD.
METHOD zif_abapgit_gui_error_handler~handle_error.
mx_error = ix_error.
rv_handled = abap_true.
ENDMETHOD.
METHOD zif_abapgit_gui_event_handler~on_event.
CASE iv_action.
WHEN zif_abapgit_definitions=>c_action-url.
call_browser( iv_getdata ).
ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.
WHEN zif_abapgit_definitions=>c_action-goto_source.
IF mo_exception_viewer IS BOUND.
mo_exception_viewer->goto_source( ).
ENDIF.
ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.
WHEN zif_abapgit_definitions=>c_action-show_callstack.
IF mo_exception_viewer IS BOUND.
mo_exception_viewer->show_callstack( ).
ENDIF.
ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.
WHEN zif_abapgit_definitions=>c_action-goto_message.
IF mo_exception_viewer IS BOUND.
mo_exception_viewer->goto_message( ).
ENDIF.
ev_state = zcl_abapgit_gui=>c_event_state-no_more_act.
ENDCASE.
ENDMETHOD.
METHOD zif_abapgit_gui_renderable~render.
DATA: lo_script TYPE REF TO zcl_abapgit_html,
lt_events TYPE tt_events.
FIELD-SYMBOLS:
<ls_event> LIKE LINE OF lt_events.
mi_gui_services->register_event_handler( me ).
" Redirect
IF ms_control-redirect_url IS NOT INITIAL.
ri_html = redirect( ).
RETURN.
ENDIF.
" Real page
CREATE OBJECT ri_html TYPE zcl_abapgit_html.
ri_html->add( '<!DOCTYPE html>' ). "#EC NOTEXT
ri_html->add( '<html>' ). "#EC NOTEXT
ri_html->add( html_head( ) ).
ri_html->add( '<body>' ). "#EC NOTEXT
ri_html->add( title( ) ).
ri_html->add( render_content( ) ). " TODO -> render child
ri_html->add( render_hotkey_overview( ) ).
ri_html->add( render_error_message_box( ) ).
lt_events = me->get_events( ). " TODO refactor ???
LOOP AT lt_events ASSIGNING <ls_event>.
ri_html->add( render_event_as_form( <ls_event> ) ).
ENDLOOP.
ri_html->add( footer( ) ).
ri_html->add( '</body>' ). "#EC NOTEXT
lo_script = scripts( ). " TODO refactor
IF lo_script IS BOUND AND lo_script->is_empty( ) = abap_false.
ri_html->add( '<script type="text/javascript">' ).
ri_html->add( lo_script ).
ri_html->add( 'confirmInitialized();' ).
ri_html->add( '</script>' ).
ENDIF.
ri_html->add( '</html>' ). "#EC NOTEXT
ENDMETHOD.
ENDCLASS.