При разработке приложений для SAP R3  пришлось столкнуться с таким фактом, что абсолютное большинство программистов на языке ABAP пишут в процедурном стиле и ООП используют только для привязки событий ALV компонентов, каждый раз заново изобретая велосипед, из-за чего подход к построению интерфейсов в разных транзакциях зависит целиком от вменяемости конкретного разработчика и для доработки программы в каждом конкретном случае приходится тратить много времени и сил просто для разбора исходных текстов. С целью унификации подхода к разработке интерфейса после прочтения книги Igor Barbaric "Design Patterns in Object-Oriented ABAP" была предпринята попытка создание ООП-каркаса для построения GUI на языке ABAP. Каркас включает в себя классы-обвязки для работы с Enjoy-controls: ALV-Grid, ALV-Tree и т.д.
Соглашения для написания классов
- методы, которые не могут быть абстрактными начинаются с do_XXX, и если возможна реализация в потомке, то в предке создается заглушка
 - методы, котрые могут быть абстрактными и перекрытыми в потомках начинаются с get_XXX и set_XXX
 
Соглашения для использования логики экранов
- Все объекты экранов помещаются в стек и управляются с помощью единичного объекта lcl_gui_application
 - Для обработки используются модули:
 - status_window (PBO)
 - user_command_window (PAI)
 - user_command_exit (USER-EXIT)
 
TYPE-POOLS: slis.
*----------------------------------------------------------------------*
*       INTERFACE lif_gui_screen
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_gui_screen.
  " Вызвать экран
  METHODS: call_screen.
ENDINTERFACE.                    "lif_gui_screen
*----------------------------------------------------------------------*
*       INTERFACE lif_gui_dialog
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_gui_dialog.
  " Показать диалог
  METHODS: call_dialog IMPORTING i_action TYPE i OPTIONAL
                                      i_x TYPE i OPTIONAL
                                      i_y TYPE i OPTIONAL
                                      i_m TYPE i OPTIONAL
                                      i_n TYPE i OPTIONAL.
ENDINTERFACE.                    "lif_gui_dialog
*----------------------------------------------------------------------*
*       INTERFACE lif_gui_view_screen
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_gui_view_screen.
  " Сохранить изменения в записи
  METHODS: save_record.
  " Перейти на следующую запись
  METHODS: next_record.
  " Перейти на предидущую запись
  METHODS: prev_record.
ENDINTERFACE.                    "lif_gui_view_screen
*----------------------------------------------------------------------*
*       INTERFACE lif_gui_view_dialog
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_gui_view_dialog.
  " Получить данные
  METHODS: read_record CHANGING i_record TYPE REF TO data.
  " Установить данные
  METHODS: init_record IMPORTING i_record TYPE REF TO data.
  " Получить режим
  METHODS: read_action RETURNING value(r_result) TYPE i.
  " Установить режим
  METHODS: init_action IMPORTING value(i_action) TYPE i.
ENDINTERFACE.                    "lif_gui_view_dialog
*----------------------------------------------------------------------*
*       INTERFACE lif_gui_process_screen
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_gui_progress_indicator.
  METHODS:
    progress_indicator
      IMPORTING
        i_perc TYPE i
        i_text TYPE syucomm.
ENDINTERFACE.                    "lif_gui_process_screen
CLASS lcl_gui_window DEFINITION DEFERRED.
*----------------------------------------------------------------------*
*       CLASS lcl_gui_utils  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_utils DEFINITION
  ABSTRACT.
  PUBLIC SECTION.
    CLASS-METHODS:
      " Создание списка полей для ALV-Grid
      build_dd_fieldcatalog
        IMPORTING
          value(i_program_name) TYPE  sy-repid OPTIONAL
          value(i_internal_tabname) TYPE slis_tabname OPTIONAL
          value(i_structure_name) TYPE dd02l-tabname OPTIONAL
          value(i_client_never_display) TYPE  slis_char_1 DEFAULT 'X'
          value(i_inclname) TYPE  trdir-name OPTIONAL
          value(i_bypassing_buffer) TYPE  char01 OPTIONAL
          value(i_buffer_active) TYPE  char01 OPTIONAL
        EXPORTING
          et_fldcat_lvc TYPE  lvc_t_fcat
        CHANGING
          itab TYPE STANDARD TABLE
        EXCEPTIONS
            inconsistent_interface
            program_error
            no_fields
            it_data_missing,
      " Очистка объекта
      free_and_initial
        CHANGING
          ch_window TYPE REF TO lcl_gui_window.
ENDCLASS.                    "lcl_gui_utils  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_application  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_application DEFINITION
  ABSTRACT.
  PUBLIC SECTION.
    METHODS:
      " Конструктор
      constructor,
      " Стартовый метод для транзакций
      start ABSTRACT.
    " PBO
    CLASS-METHODS: pbo IMPORTING i_ucomm TYPE syucomm.
    " PAI
    CLASS-METHODS: pai IMPORTING i_ucomm TYPE syucomm.
    " User-exit
    CLASS-METHODS: user_exit IMPORTING i_ucomm TYPE syucomm.
    " Зарегистрировать окно
    CLASS-METHODS: register IMPORTING i_window TYPE REF TO lcl_gui_window.
    " Вернуться
    CLASS-METHODS: back.
    " Выход
    CLASS-METHODS: exit.
  PROTECTED SECTION.
    " Очистить стек
    CLASS-METHODS: clear.
    " Добавить экран в стек
    CLASS-METHODS: push IMPORTING i_window TYPE REF TO lcl_gui_window.
    " Получить экран из стека
    CLASS-METHODS: pick RETURNING value(r_result) TYPE REF TO lcl_gui_window
                        EXCEPTIONS ex_empty no_result.
    " Извлечь экран из стека
    CLASS-METHODS: pop RETURNING value(r_result) TYPE REF TO lcl_gui_window
                       EXCEPTIONS ex_empty no_result.
    " Экемпляр
    CLASS-DATA: o_this TYPE REF TO lcl_gui_application.
  PRIVATE SECTION.
    " Окна
    CLASS-DATA: o_stack TYPE osreftab.
    " Номер экрана выбора
    CLASS-DATA: m_dynnr TYPE sydynnr VALUE IS INITIAL.
ENDCLASS.                    "lcl_gui_application  DEFINITIO
*----------------------------------------------------------------------*
*  DATA ok_code TYPE syucomm
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
DATA ok_code TYPE syucomm.
*----------------------------------------------------------------------*
*  MODULE status_window OUTPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE status_window OUTPUT.
  ok_code = sy-ucomm.
  CALL METHOD lcl_gui_application=>pbo( ok_code ).
ENDMODULE.                    "status_window OUTPUT
*----------------------------------------------------------------------*
*  MODULE user_command_window INPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE user_command_window INPUT.
  ok_code = sy-ucomm.
  CALL METHOD lcl_gui_application=>pai( ok_code ).
ENDMODULE.                    "user_command_window INPUT
*----------------------------------------------------------------------*
*  MODULE user_command_exit INPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE user_command_exit INPUT.
  ok_code = sy-ucomm.
  CALL METHOD lcl_gui_application=>user_exit( ok_code ).
ENDMODULE.                    "user_command_exit INPUT
*----------------------------------------------------------------------*
*       CLASS lcl_gui_window  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_window DEFINITION
  ABSTRACT.
  PUBLIC SECTION.
    CONSTANTS: c_cancel TYPE i VALUE 0,
               c_browse TYPE i VALUE 1,
               c_create TYPE i VALUE 2,
               c_update TYPE i VALUE 3,
               c_delete TYPE i VALUE 4.
    " Получить экземпляр
    CLASS-METHODS: get_window IMPORTING value(i_class) TYPE string
                                        value(i_dynnr) TYPE sydynnr
                              RETURNING value(r_result) TYPE REF TO lcl_gui_window.
    METHODS: constructor IMPORTING i_dynnr TYPE sydynnr.
    METHODS: free.
    " Логика PBO
    METHODS: do_pbo IMPORTING i_ucomm TYPE syucomm.
    " Логика PBI
    METHODS: do_pai IMPORTING i_ucomm TYPE syucomm.
    " Логика PBI
    METHODS: do_exit CHANGING ch_ucomm TYPE syucomm.
    " Получить номер экрана
    METHODS: get_dynnr RETURNING value(r_result) TYPE sydynnr.
  PRIVATE SECTION.
    " Номер экрана
    DATA: m_dynnr TYPE sydynnr.
ENDCLASS.                    "lcl_gui_window  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_screen  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_screen DEFINITION
  ABSTRACT
  INHERITING FROM lcl_gui_window.
  PUBLIC SECTION.
    INTERFACES: lif_gui_screen.
    " Вызов экрана
    ALIASES: call_screen FOR lif_gui_screen~call_screen.
    " Получить экземпляр
    CLASS-METHODS: get_screen IMPORTING value(i_class) TYPE string
                                        value(i_dynnr) TYPE sydynnr
                              RETURNING value(r_result) TYPE REF TO lif_gui_screen.
    " Free
    METHODS: free REDEFINITION.
    " Логика PBO
    METHODS: do_pbo REDEFINITION.
    " Логика PBI
    METHODS: do_pai REDEFINITION.
  PROTECTED SECTION.
    " Вызвать экран
    METHODS: do_call_screen FINAL.
    " Инициализиировать экран
    METHODS: do_init_screen.
ENDCLASS.                    "lcl_gui_screen  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_dialog  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_dialog DEFINITION
  INHERITING FROM lcl_gui_window.
  PUBLIC SECTION.
    INTERFACES: lif_gui_dialog.
    CONSTANTS:
      c_applyfunc   TYPE syucomm VALUE 'APPLY',
      c_cancelfunc  TYPE syucomm VALUE 'CANCEL'.
    " Вызов
    ALIASES:
      call_dialog FOR lif_gui_dialog~call_dialog.
    " Получить экземпляр
    CLASS-METHODS: get_dialog IMPORTING value(i_class) TYPE string
                                        value(i_dynnr) TYPE sydynnr
                                              i_screen TYPE REF TO lcl_gui_screen
                                                   i_x TYPE i OPTIONAL
                                                   i_y TYPE i OPTIONAL
                                                   i_m TYPE i OPTIONAL
                                                   i_n TYPE i OPTIONAL
                              RETURNING value(r_result) TYPE REF TO lif_gui_dialog.
    METHODS: constructor IMPORTING i_dynnr  TYPE sydynnr
                                   i_screen TYPE REF TO lcl_gui_screen
                                                   OPTIONAL
                                        i_x TYPE i OPTIONAL
                                        i_y TYPE i OPTIONAL
                                        i_m TYPE i OPTIONAL
                                        i_n TYPE i OPTIONAL.
    " Логика PBO
    METHODS: do_pbo REDEFINITION.
    " Логика PBI
    METHODS: do_pai REDEFINITION.
    " Вызывающий экран
    METHODS: set_screen IMPORTING i_screen TYPE REF TO lcl_gui_screen.
    " Вызывающий экран
    METHODS: get_screen RETURNING value(r_result) TYPE REF TO lcl_gui_screen.
    " Местоположение
    METHODS: set_bounds IMPORTING i_x TYPE i
                                  i_y TYPE i
                                  i_m TYPE i OPTIONAL
                                  i_n TYPE i OPTIONAL.
    " Местоположение
    METHODS: get_bounds EXPORTING e_x TYPE i
                                  e_y TYPE i
                                  e_m TYPE i
                                  e_n TYPE i.
  PROTECTED SECTION.
    " Показать диалог
    METHODS:
      do_call_dialog FINAL
        IMPORTING
          i_action TYPE i OPTIONAL
               i_x TYPE i OPTIONAL
               i_y TYPE i OPTIONAL
               i_m TYPE i OPTIONAL
               i_n TYPE i OPTIONAL.
    " Получить режим
    METHODS: do_read_action RETURNING value(r_result) TYPE i.
    " Установить режим
    METHODS: do_init_action IMPORTING value(i_action) TYPE i.
    " Принять
    METHODS: do_apply_record.
    " Отмена
    METHODS: do_cancel_record.
    " Вызывающий экран
    DATA: m_screen TYPE REF TO lcl_gui_screen.
    " Режим действий
    DATA: m_action TYPE i.
    " Параметры
    DATA: m_x TYPE i,
          m_y TYPE i,
          m_m TYPE i,
          m_n TYPE i.
ENDCLASS.                    "lcl_gui_dialog  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_subscreen  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_subscreen DEFINITION
  ABSTRACT
  INHERITING FROM lcl_gui_window.
  PUBLIC SECTION.
    CLASS-METHODS:
      " PBO
      pbo
        IMPORTING
          i_ucomm TYPE syucomm,
      " PAI
      pai
        IMPORTING
          i_ucomm TYPE syucomm.
    METHODS:
      constructor
        IMPORTING
          i_dynnr TYPE sydynnr
          i_owner TYPE REF TO lcl_gui_window,
      " Логика PBO
      do_pbo REDEFINITION,
      " Логика PBI
      do_pai REDEFINITION.
  PROTECTED SECTION.
    METHODS:
      " Инициализация
      do_init_subscreen.
    CLASS-DATA:
      o_this TYPE REF TO lcl_gui_subscreen.
  PRIVATE SECTION.
    DATA:
       " Владелец
       m_owner TYPE REF TO lcl_gui_window.
ENDCLASS.                    "lcl_gui_subscreen  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_screen  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_screen DEFINITION
  ABSTRACT
  INHERITING FROM lcl_gui_screen.
  PUBLIC SECTION.
    INTERFACES: lif_gui_view_screen.
    " Сохранить изменения в записи
    ALIASES: save_record FOR lif_gui_view_screen~save_record.
    " Перейти на следующую запись
    ALIASES: next_record FOR lif_gui_view_screen~next_record.
    " Перейти на предидущую запись
    ALIASES: prev_record FOR lif_gui_view_screen~prev_record.
    " Логика PBO
    METHODS: do_pbo REDEFINITION.
    " Логика PBI
    METHODS: do_pai REDEFINITION.
  PROTECTED SECTION.
    " Инициировать диалог
    METHODS: do_active_dialog.
    " Просмотреть запись
    METHODS: do_browse_dialog.
    " Диалог для добавления
    METHODS: do_create_dialog.
    " Диалог для обновления
    METHODS: do_update_dialog.
    " Диалог для удаления
    METHODS: do_delete_dialog.
    " Сохранить активную запись
    METHODS: do_save_record.
    " Перейти на запись вверх
    METHODS: do_next_record RETURNING value(r_result) TYPE REF TO data.
    " Перейти на запись вниз
    METHODS: do_prev_record RETURNING value(r_result) TYPE REF TO data.
    " Получить активную запись
    METHODS: do_read_record RETURNING value(r_result) TYPE REF TO data.
    " Сохранить активную запись
    METHODS: do_init_record IMPORTING value(i_action) TYPE i
                                      value(i_record) TYPE REF TO data.
    " Проверить запись
    METHODS: do_check_record IMPORTING value(i_action) TYPE i
                                       value(i_record) TYPE REF TO data
                             RETURNING value(r_result) TYPE i.
    " Проверить роль
    METHODS: do_check_role IMPORTING value(i_action) TYPE i
                           RETURNING value(r_result) TYPE char1.
    " Создать запись
    METHODS: do_create_record IMPORTING value(i_record) TYPE REF TO data
                              EXCEPTIONS no_result.
    " Редактировать активную запись
    METHODS: do_update_record IMPORTING value(i_record) TYPE REF TO data
                              EXCEPTIONS no_result.
    " Удалить запись
    METHODS: do_delete_record IMPORTING value(i_record) TYPE REF TO data
                              EXCEPTIONS no_result.
    " CRUD - выбрать запись по ID
    METHODS: do_select_by_id IMPORTING i_record TYPE REF TO data
                             EXCEPTIONS no_result.
    " CRUD - создать запись по ID
    METHODS: do_create_by_id IMPORTING i_record TYPE REF TO data
                             EXCEPTIONS no_result.
    " CRUD - изменить запись по ID
    METHODS: do_update_by_id IMPORTING i_record TYPE REF TO data
                             EXCEPTIONS no_result.
    " CRUD - удалить запись по ID
    METHODS: do_delete_by_id IMPORTING i_record TYPE REF TO data
                             EXCEPTIONS no_result.
    " Получить имя структуры данных
    METHODS: get_structure_name ABSTRACT
                                RETURNING value(r_result) TYPE string.
    " Получить типизированную строку данных
    METHODS: get_structure_data ABSTRACT
                                RETURNING value(r_result) TYPE REF TO data.
    " Dialog
    DATA: m_dialog TYPE REF TO lif_gui_view_dialog.
ENDCLASS.                    "lcl_gui_view_screen  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_dialog  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_dialog DEFINITION
  ABSTRACT
  INHERITING FROM lcl_gui_dialog.
  PUBLIC SECTION.
    INTERFACES: lif_gui_view_dialog.
    " Получить данные
    ALIASES: read_record FOR lif_gui_view_dialog~read_record.
    " Установить данные
    ALIASES: init_record FOR lif_gui_view_dialog~init_record.
    " Получить режим
    ALIASES: read_action FOR lif_gui_view_dialog~read_action.
    " Установить режим
    ALIASES: init_action FOR lif_gui_view_dialog~init_action.
    " Логика PBO
    METHODS: do_pbo REDEFINITION.
    " Логика PBI
    METHODS: do_pai REDEFINITION.
  PROTECTED SECTION.
    " Принять
    METHODS: do_apply_record REDEFINITION.
    " Получить данные
    METHODS: do_read_record CHANGING i_record TYPE REF TO data.
    " Установить данные
    METHODS: do_init_record IMPORTING i_record TYPE REF TO data.
    " Сохранить текущую
    METHODS: do_save_record.
    " Перейти на запись вверх
    METHODS: do_next_record.
    " Перейти на запись вниз
    METHODS: do_prev_record.
ENDCLASS.                    "lcl_gui_view_dialog  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_subscreen  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_subscreen DEFINITION
  INHERITING FROM lcl_gui_subscreen
  ABSTRACT.
  PUBLIC SECTION.
    METHODS:
      " Проверить
      validate ABSTRACT
        EXCEPTIONS no_valid,
      " Получить данные
      get_data ABSTRACT
        CHANGING
          i_data TYPE REF TO data,
      " Установить данные
      set_data ABSTRACT
        IMPORTING
          i_data TYPE REF TO data,
      " Получить режим
      get_mode
        RETURNING value(result) TYPE i,
      " Установить режим
      set_mode
        IMPORTING value(i_mode) TYPE i.
  PRIVATE SECTION.
    DATA:
      " Режим
      m_mode TYPE i VALUE c_browse.
ENDCLASS.                    "lcl_gui_view_subscreen  DEFINITIO
*----------------------------------------------------------------------*
*       CLASS lcl_gui_grid_screen  DEFINITIO
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_grid_screen DEFINITION
  ABSTRACT
  INHERITING FROM lcl_gui_view_screen.
  PUBLIC SECTION.
    METHODS: free REDEFINITION.
  PROTECTED SECTION.
    " Инициализиировать экран
    METHODS: do_init_screen REDEFINITION.
    " Перейти на запись вверх
    METHODS: do_next_record REDEFINITION.
    " Перейти на запись вниз
    METHODS: do_prev_record REDEFINITION.
    " Получить активную запись
    METHODS: do_read_record REDEFINITION.
    " Сохранить активную запись
    METHODS: do_init_record REDEFINITION.
    " Вариант для ALVGRID
    METHODS: do_init_variant.
    " Layout ALVGRID
    METHODS: do_init_layout.
    " Поля ALVGRID
    METHODS: do_init_fields.
    " Специальные поля
    METHODS: do_init_groups.
    " Сортировка
    METHODS: do_init_sorted.
    " Получить данные
    METHODS: do_init_outtab.
    " Получить заголовок для ALVGrid
    METHODS: get_alvgrid_title ABSTRACT
                       RETURNING value(r_result) TYPE string.
    " Получить имя ALV контейнера
    METHODS: get_container_name ABSTRACT
                       RETURNING value(r_result) TYPE string.
    " Навигация
    METHODS: get_selected_rows EXCEPTIONS no_rows.
    METHODS: set_selected_rows EXCEPTIONS no_rows.
    " Установить обработчики для грида
    METHODS: set_alvgrid_handlers.
    " Устновить событие редактирования
    METHODS: set_alvgrid_edit_event.
    " Изменение выделеных строк
    METHODS: set_index_before_create.
    METHODS: set_index_after_delete.
    " Handle events for ALVGrid
    METHODS: do_handle_toolbar
               FOR EVENT toolbar OF cl_gui_alv_grid
               IMPORTING e_object       " type ref to cl_alv_event_toolbar_set
                         e_interactive. " type char01
    METHODS: do_handle_user_command
               FOR EVENT user_command OF cl_gui_alv_grid
               IMPORTING e_ucomm. " type sy-ucomm
    METHODS: do_hotspot_click_command
               FOR EVENT hotspot_click OF cl_gui_alv_grid
               IMPORTING e_row_id     " type  lvc_s_row
                         e_column_id  " type  lvc_s_col
                         es_row_no.   " type  lvc_s_roid
    METHODS: do_double_click_command
               FOR EVENT double_click OF cl_gui_alv_grid
               IMPORTING e_row      " type lvc_s_row optional
                         e_column   " type lvc_s_col optional
                         es_row_no. " type lvc_s_roid optional
    " ALV objects
    DATA: m_grid TYPE REF TO cl_gui_alv_grid,
          m_container TYPE REF TO cl_gui_custom_container.
    " ALV properties
    DATA: m_variant   TYPE disvariant,
          m_layout    TYPE lvc_s_layo,
          m_save      TYPE c VALUE space,
          m_fieldcat  TYPE lvc_t_fcat,
          m_sortcat   TYPE lvc_t_sort,
          m_groupcat  TYPE lvc_t_sgrp.
    " ALV navigation
    DATA: m_index_rows TYPE lvc_t_row,
          m_select_row TYPE lvc_s_row.
    " ALV data
    DATA: m_outtab TYPE REF TO data.
ENDCLASS.                    "lcl_gui_grid_screen  DEFINITIO
*&---------------------------------------------------------------------*
*&  Include           ZCA_GUI_SCREENS
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Разработчик : Андрей Володин
*& Постановщик :
*& Дата начала разработки : 15.12.2008
*& Описание разработки :
*& Запрос ITSM :
*&---------------------------------------------------------------------*
*& Лог изменений
*& Дата      Разработчик   Описание
*&
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&  Include           ZCA_GUI_SCREENS
*&---------------------------------------------------------------------*
CLASS lcl_gui_utils IMPLEMENTATION.
  METHOD build_dd_fieldcatalog.
*     IMPORTING
*          value(i_program_name) TYPE  sy-repid OPTIONAL
*          value(i_internal_tabname) TYPE slis_tabname OPTIONAL
*          value(i_structure_name) TYPE dd02l-tabname OPTIONAL
*          value(i_client_never_display) TYPE  slis_char_1 DEFAULT 'X'
*          value(i_inclname) TYPE  trdir-name OPTIONAL
*          value(i_bypassing_buffer) TYPE  char01 OPTIONAL
*          value(i_buffer_active) TYPE  char01 OPTIONAL
*        EXPORTING
*          et_fldcat_lvc TYPE  lvc_t_fcat
*        CHANGING
*          itab TYPE STANDARD TABLE
*        EXCEPTIONS
*            inconsistent_interface
*            program_error
*            no_fields
*            it_data_missing
    DATA: lt_fldcat_slis TYPE slis_t_fieldcat_alv.
    CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
      EXPORTING
        i_program_name         = i_program_name
        i_internal_tabname     = i_internal_tabname
        i_structure_name       = i_structure_name
        i_client_never_display = i_client_never_display
        i_inclname             = i_inclname
        i_bypassing_buffer     = i_bypassing_buffer
        i_buffer_active        = i_buffer_active
      CHANGING
        ct_fieldcat            = lt_fldcat_slis
      EXCEPTIONS
        inconsistent_interface = 1
        program_error          = 2
        OTHERS                 = 3.
    IF sy-subrc EQ 1.
      RAISE inconsistent_interface.
    ELSEIF sy-subrc EQ 2.
      RAISE program_error .
    ENDIF.
    IF lt_fldcat_slis[] IS INITIAL.
      RAISE no_fields.
    ENDIF.
    CALL FUNCTION 'LVC_TRANSFER_FROM_SLIS'
      EXPORTING
        it_fieldcat_alv = lt_fldcat_slis[]
      IMPORTING
        et_fieldcat_lvc = et_fldcat_lvc[]
      TABLES
        it_data         = itab[]
      EXCEPTIONS
        it_data_missing = 1
        OTHERS          = 2.
    IF sy-subrc EQ 1.
      RAISE it_data_missing.
    ENDIF.
    IF et_fldcat_lvc[] IS INITIAL.
      RAISE no_fields.
    ENDIF.
  ENDMETHOD.                    "build_dd_fieldcatalog
  METHOD free_and_initial.
    " CHANGING
    "  ch_window  TYPE REF TO lcl_gui_window.
    CHECK ch_window IS NOT INITIAL.
    CALL METHOD ch_window->free( ).
    FREE ch_window.
  ENDMETHOD.                    "free_and_initial
ENDCLASS.                    "lcl_gui_utils IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_application IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_application IMPLEMENTATION.
  METHOD constructor.
    IF o_this IS NOT INITIAL.
      FREE o_this.
    ENDIF.
    o_this = me.
  ENDMETHOD.                    "constructor
  METHOD pbo.
    " importing i_ucomm type syucomm
    DATA l_window TYPE REF TO lcl_gui_window.
    " Последнее значение
    CALL METHOD lcl_gui_application=>pick
      RECEIVING
        r_result  = l_window
      EXCEPTIONS
        ex_empty  = 1
        no_result = 2
        OTHERS    = 3.
    IF sy-subrc EQ 0.
      CALL METHOD l_window->do_pbo
        EXPORTING
          i_ucomm = i_ucomm.
    ENDIF.
  ENDMETHOD.                    "pbo
  METHOD pai.
    " importing i_ucomm type syucomm
    DATA l_window TYPE REF TO lcl_gui_window.
    " Последнее значение
    CALL METHOD lcl_gui_application=>pick
      RECEIVING
        r_result  = l_window
      EXCEPTIONS
        ex_empty  = 1
        no_result = 2
        OTHERS    = 3.
    IF sy-subrc EQ 0.
      CALL METHOD l_window->do_pai
        EXPORTING
          i_ucomm = i_ucomm.
    ENDIF.
  ENDMETHOD.                    "pai
  METHOD user_exit.
    " importing i_ucomm type syucomm
    DATA:
      l_ucomm TYPE syucomm,
      l_window TYPE REF TO lcl_gui_window.
    l_ucomm = i_ucomm.
    " Последнее значение
    CALL METHOD lcl_gui_application=>pick
      RECEIVING
        r_result  = l_window
      EXCEPTIONS
        ex_empty  = 1
        no_result = 2
        OTHERS    = 3.
    IF sy-subrc EQ 0.
      IF l_ucomm EQ 'BACK' OR l_ucomm EQ 'CANCEL'.
        CALL METHOD l_window->do_exit
          CHANGING
            ch_ucomm = l_ucomm.
      ENDIF.
    ENDIF.
    CASE l_ucomm.
      WHEN 'BACK'.
        CALL METHOD lcl_gui_application=>back( ).
      WHEN 'CANCEL'.
        CALL METHOD lcl_gui_application=>exit( ).
    ENDCASE.
  ENDMETHOD.                    "user_exit
  METHOD register.
    " importing i_window type ref to lcl_gui_window
    CALL METHOD lcl_gui_application=>push
      EXPORTING
        i_window = i_window.
  ENDMETHOD.                    "register
  METHOD clear.
    DATA: l_object TYPE REF TO object,
          l_window TYPE REF TO lcl_gui_window.
    LOOP AT o_stack INTO l_object.
      l_window ?= l_object.
      CHECK l_window IS NOT INITIAL.
      CALL METHOD l_window->free.
      FREE l_window.
    ENDLOOP.
    REFRESH o_stack.
  ENDMETHOD.                    "clear
  METHOD push.
    " importing i_window type ref to lcl_gui_window
    " Если стек пуст
    IF LINES( o_stack ) EQ 0.
      APPEND i_window TO o_stack.
      RETURN.
    ENDIF.
    " Если элемент уже в стеке
    DATA: l_tabix  TYPE sytabix,
          l_exists TYPE char1 VALUE IS INITIAL,
          l_object TYPE REF TO object,
          l_window TYPE REF TO lcl_gui_window.
    LOOP AT o_stack INTO l_object.
      l_tabix = sy-tabix.
      l_window ?= l_object.
      CHECK l_window IS NOT INITIAL.
      IF l_window->get_dynnr( ) EQ
         i_window->get_dynnr( ).
        IF l_tabix NE LINES( o_stack ).
          DELETE o_stack INDEX l_tabix.
          APPEND i_window TO o_stack.
          RETURN.
        ENDIF.
      ENDIF.
    ENDLOOP.
    " В любом случае
    APPEND i_window TO o_stack.
  ENDMETHOD.                    "push
  METHOD pick.
    " returning value(r_result) type ref to lcl_gui_window
    " exceptions ex_empty no_result
    DATA: l_tabix TYPE sytabix.
    l_tabix = LINES( o_stack ).
    " Если стек пуст
    IF l_tabix EQ 0.
      RAISE ex_empty.
    ENDIF.
    " Последнее значение
    DATA: l_object TYPE REF TO object.
    READ TABLE o_stack INDEX l_tabix INTO l_object.
    IF sy-subrc NE 0.
      RAISE no_result.
    ENDIF.
    r_result ?= l_object.
    IF r_result IS INITIAL.
      RAISE no_result.
    ENDIF.
  ENDMETHOD.                    "pick
  METHOD pop.
    " returning value(r_result) type ref to lcl_gui_window
    " exceptions ex_empty no_result
    DATA: l_tabix TYPE sytabix.
    l_tabix = LINES( o_stack ).
    " Если стек пуст
    IF l_tabix EQ 0.
      RAISE ex_empty.
    ENDIF.
    " Последнее значение
    CALL METHOD lcl_gui_application=>pick
      RECEIVING
        r_result  = r_result
      EXCEPTIONS
        ex_empty  = 1
        no_result = 2
        OTHERS    = 3.
    CASE sy-subrc.
      WHEN 0.
        DELETE o_stack INDEX l_tabix.
      WHEN 1.
        RAISE ex_empty.
      WHEN 2.
        RAISE no_result.
    ENDCASE.
  ENDMETHOD.                    "pop
  METHOD back.
    DATA l_window TYPE REF TO lcl_gui_window.
    CALL METHOD lcl_gui_application=>pop
      RECEIVING
        r_result  = l_window
      EXCEPTIONS
        ex_empty  = 1
        no_result = 2
        OTHERS    = 3.
    IF sy-subrc EQ 0.
      CALL METHOD l_window->free( ).
    ENDIF.
    LEAVE TO SCREEN 0.
  ENDMETHOD.                    "back
  METHOD exit.
    " Очистить стек окон
    CALL METHOD lcl_gui_application=>clear.
    " Выход
    LEAVE PROGRAM.
  ENDMETHOD.                    "exit
ENDCLASS.                    "lcl_gui_application IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_window IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_window IMPLEMENTATION.
  METHOD get_window.
    " importing value(i_class) type string
    "           value(i_dynnr) type sydynnr
    " returning value(r_result) type ref to lcl_gui_window
    DATA:
      l_this TYPE REF TO lcl_gui_window.
    TRY.
        CREATE OBJECT l_this
          TYPE
            (i_class)
          EXPORTING
            i_dynnr   = i_dynnr.
        IF l_this IS NOT INITIAL.
          r_result = l_this.
        ELSE.
          FREE l_this.
        ENDIF.
      CATCH cx_sy_create_object_error.
        MESSAGE 'Create object error'
          TYPE 'S' DISPLAY LIKE 'E'.
    ENDTRY.
  ENDMETHOD.                    "get_window
  METHOD constructor.
    " importing i_dynnr type sydynnr
    m_dynnr = i_dynnr.
  ENDMETHOD.                    "constructor
  METHOD free.
  ENDMETHOD.                    "free
  METHOD do_pbo.
    " importing i_ucomm type syucomm
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
  ENDMETHOD.                    "do_pai
  METHOD do_exit.
    " importing i_ucomm type syucomm
  ENDMETHOD.                    "do_exit
  METHOD get_dynnr.
    " returning value(r_result) type sydynnr
    r_result = m_dynnr.
  ENDMETHOD.                    "get_dynnr
ENDCLASS.                    "lcl_gui_window IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_screen IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_screen IMPLEMENTATION.
  METHOD get_screen.
    " importing value(i_class) type string
    "           value(i_dynnr) type sydynnr
    " returning value(r_result) type ref to lif_gui_screen
    DATA: l_window TYPE REF TO lcl_gui_window,
          l_screen TYPE REF TO lcl_gui_screen.
    TRY .
        CALL METHOD lcl_gui_window=>get_window
          EXPORTING
            i_class  = i_class
            i_dynnr  = i_dynnr
          RECEIVING
            r_result = l_window.
        IF l_window IS NOT INITIAL.
          l_screen ?= l_window.
        ENDIF.
        IF l_screen IS NOT INITIAL.
          r_result = l_screen.
        ENDIF.
      CATCH cx_root.
        FREE l_screen.
    ENDTRY.
  ENDMETHOD.                    "get_screen
  METHOD free.
  ENDMETHOD.                    "free
  METHOD do_pbo.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pbo
      EXPORTING
        i_ucomm = i_ucomm.
    " Инициализировать экран
    CALL METHOD me->do_init_screen.
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pai
      EXPORTING
        i_ucomm = i_ucomm.
  ENDMETHOD.                    "do_pai
  METHOD do_call_screen.
    DATA l_dynnr TYPE sydynnr.
    " Номер экрана
    CALL METHOD me->get_dynnr
      RECEIVING
        r_result = l_dynnr.
    " Зарегистрировать
    CALL METHOD lcl_gui_application=>register
      EXPORTING
        i_window = me.
    " Вызов экрана
    CALL SCREEN l_dynnr.
  ENDMETHOD.                    "do_call_screen
  METHOD do_init_screen.
  ENDMETHOD.                    "do_init_screen
  METHOD lif_gui_screen~call_screen.
    " Отобразить экран
    CALL METHOD me->do_call_screen.
  ENDMETHOD.                    "lif_gui_screen~call_screen
ENDCLASS.                    "lcl_gui_screen IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_dialog IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_dialog IMPLEMENTATION.
  METHOD get_dialog.
    " importing value(i_class) type string
    "           value(i_dynnr) type sydynnr
    "                 i_screen type ref to lcl_gui_screen
    "                      i_x type i optional
    "                      i_y type i optional
    "                      i_m type i optional
    "                      i_n type i optional
    " returning value(r_result) type ref to lif_gui_dialog.
    DATA: l_window TYPE REF TO lcl_gui_window,
          l_dialog TYPE REF TO lcl_gui_dialog.
    TRY .
        CALL METHOD lcl_gui_window=>get_window
          EXPORTING
            i_class  = i_class
            i_dynnr  = i_dynnr
          RECEIVING
            r_result = l_window.
        IF l_window IS NOT INITIAL.
          l_dialog ?= l_window.
        ENDIF.
        IF l_dialog IS NOT INITIAL.
          CALL METHOD l_dialog->set_screen
            EXPORTING
              i_screen = i_screen.
          CALL METHOD l_dialog->set_bounds
            EXPORTING
              i_x = i_x
              i_y = i_y
              i_m = i_m
              i_n = i_n.
          r_result = l_dialog.
        ENDIF.
      CATCH cx_root.
        FREE l_dialog.
    ENDTRY.
  ENDMETHOD.                    "get_dialog
  METHOD constructor.
    " importing i_dynnr  type sydynnr
    "           i_screen type ref to lcl_gui_screen
    "                           optional
    "                i_x type i optional
    "                i_y type i optional
    "                i_m type i optional
    "                i_n type i optional
    " Базовый метод
    CALL METHOD super->constructor
      EXPORTING
        i_dynnr = i_dynnr.
    " Вызвавший экран
    me->m_screen = i_screen.
    " Координаты
    me->m_x = i_x.
    me->m_y = i_y.
    me->m_m = i_m.
    me->m_n = i_n.
  ENDMETHOD.                    "constructor
  METHOD do_pbo.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pbo
      EXPORTING
        i_ucomm = i_ucomm.
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pai
      EXPORTING
        i_ucomm = i_ucomm.
    CASE i_ucomm.
      WHEN c_applyfunc.
        CALL METHOD me->do_apply_record( ).
      WHEN c_cancelfunc.
        CALL METHOD me->do_cancel_record( ).
    ENDCASE.
  ENDMETHOD.                    "do_pai
  METHOD set_screen.
    " importing i_screen type ref to lcl_gui_screen
    IF i_screen IS NOT INITIAL.
      m_screen = i_screen.
    ENDIF.
  ENDMETHOD.                    "set_screen
  METHOD get_screen.
    " returning value(r_result) type ref to lcl_gui_screen
    r_result = m_screen.
  ENDMETHOD.                    "get_screen
  METHOD set_bounds.
    " importing i_x type i
    "           i_y type i
    "           i_m type i optional
    "           i_n type i optional
    IF i_x IS NOT INITIAL. m_x = i_x. ENDIF.
    IF i_y IS NOT INITIAL. m_y = i_y. ENDIF.
    IF i_m IS NOT INITIAL. m_m = i_m. ENDIF.
    IF i_n IS NOT INITIAL. m_n = i_n. ENDIF.
  ENDMETHOD.                    "set_bounds
  METHOD get_bounds.
    " exporting e_x type i
    "           e_y type i
    "           e_m type i
    "           e_n type i
    e_x = m_x.
    e_y = m_y.
    e_m = m_m.
    e_n = m_n.
  ENDMETHOD.                    "get_bounds
  METHOD do_call_dialog.
    " IMPORTING i_action TYPE i OPTIONAL
    "                i_x TYPE i OPTIONAL
    "                i_y TYPE i OPTIONAL
    "                i_m TYPE i OPTIONAL
    "                i_n TYPE i OPTIONAL
    DATA l_action TYPE i.
    IF i_action IS INITIAL.
      l_action = c_browse.
    ELSE.
      l_action = i_action.
    ENDIF.
    CALL METHOD me->do_init_action( l_action ).
    IF i_x IS NOT INITIAL. m_x = i_x. ENDIF.
    IF i_y IS NOT INITIAL. m_y = i_y. ENDIF.
    IF i_m IS NOT INITIAL. m_m = i_m. ENDIF.
    IF i_n IS NOT INITIAL. m_n = i_n. ENDIF.
    DATA l_dynnr TYPE sydynnr.
    " Номер экрана
    CALL METHOD me->get_dynnr
      RECEIVING
        r_result = l_dynnr.
    " Зарегистрировать
    CALL METHOD lcl_gui_application=>register
      EXPORTING
        i_window = me.
    IF m_m IS INITIAL OR m_n IS INITIAL.
      CALL SCREEN l_dynnr STARTING AT m_x m_y.
    ELSE.
      CALL SCREEN l_dynnr STARTING AT m_x m_y
                            ENDING AT m_m m_n.
    ENDIF.
  ENDMETHOD.                    "do_call_dialog
  METHOD do_read_action.
    " RETURNING value(r_result) TYPE i
    r_result = m_action.
  ENDMETHOD.                    "do_read_action
  METHOD do_init_action.
    " IMPORTING value(i_action) TYPE i
    m_action = i_action.
  ENDMETHOD.                    "do_init_action
  METHOD do_apply_record.
    CALL METHOD lcl_gui_application=>back( ).
  ENDMETHOD.                    "do_apply_record
  METHOD do_cancel_record.
    CALL METHOD lcl_gui_application=>back( ).
  ENDMETHOD.                    "do_cancel_record
  METHOD lif_gui_dialog~call_dialog.
    " IMPORTING i_action TYPE i OPTIONAL
    "                i_x TYPE i OPTIONAL
    "                i_y TYPE i OPTIONAL
    "                i_m TYPE i OPTIONAL
    "                i_n TYPE i OPTIONAL
    CALL METHOD me->do_call_dialog
      EXPORTING
        i_action = i_action
        i_x      = i_x
        i_y      = i_y
        i_m      = i_m
        i_n      = i_n.
  ENDMETHOD.                    "lif_gui_dialog~call_dialog
ENDCLASS.                    "lcl_gui_dialog IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_subscreen IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_subscreen IMPLEMENTATION.
  METHOD pbo.
    " IMPORTING i_ucomm TYPE syucomm
    IF o_this IS NOT INITIAL.
      CALL METHOD o_this->do_pbo( i_ucomm ).
    ENDIF.
  ENDMETHOD.                    "pbo
  METHOD pai.
    " IMPORTING i_ucomm TYPE syucomm
    IF o_this IS NOT INITIAL.
      CALL METHOD o_this->do_pai( i_ucomm ).
    ENDIF.
  ENDMETHOD.                    "pai
  METHOD constructor.
    " IMPORTING i_dynnr TYPE sydynnr
    "           i_owner TYPE REF TO lcl_gui_window
    CALL METHOD super->constructor
      EXPORTING
        i_dynnr = i_dynnr.
    " Одиночка
    o_this = me.
    " Владелец
    m_owner = i_owner.
  ENDMETHOD.                    "constructor
  METHOD do_pbo.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pbo( i_ucomm ).
    " Инициализация
    CALL METHOD me->do_init_subscreen.
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pai( i_ucomm ).
  ENDMETHOD.                    "do_pai
  METHOD do_init_subscreen.
  ENDMETHOD.                    "do_init_subscreen
ENDCLASS.                    "lcl_gui_subscreen IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_screen IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_screen IMPLEMENTATION.
  METHOD lif_gui_view_screen~save_record.
    CALL METHOD me->do_save_record.
  ENDMETHOD.                    "lif_gui_screen~save_record
  METHOD lif_gui_view_screen~next_record.
    CALL METHOD me->do_next_record.
  ENDMETHOD.                    "lif_gui_screen~next_record
  METHOD lif_gui_view_screen~prev_record.
    CALL METHOD me->do_prev_record.
  ENDMETHOD.                    "lif_gui_screen~prev_record
  METHOD do_pbo.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pbo
      EXPORTING
        i_ucomm = i_ucomm.
    "set pf-status ''.
    "set titlebar ''.
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
    CASE i_ucomm.
      WHEN 'BROWSE'.
        CALL METHOD me->do_browse_dialog.
      WHEN 'CREATE'.
        CALL METHOD me->do_create_dialog.
      WHEN 'UPDATE'.
        CALL METHOD me->do_update_dialog.
      WHEN 'DELETE'.
        CALL METHOD me->do_delete_dialog.
    ENDCASE.
    CALL METHOD super->do_pai
      EXPORTING
        i_ucomm = i_ucomm.
  ENDMETHOD.                    "do_pai
  METHOD do_active_dialog.
    IF m_dialog IS NOT INITIAL.
      FREE m_dialog.
    ENDIF.
  ENDMETHOD.                    "do_active_dialog
  METHOD do_browse_dialog.
    DATA l_record TYPE REF TO data.
    CALL METHOD me->do_read_record
      RECEIVING
        r_result = l_record.
    CHECK l_record IS NOT INITIAL.
    CALL METHOD me->do_active_dialog.
    CHECK m_dialog IS NOT INITIAL.
    CALL METHOD m_dialog->init_record
      EXPORTING
        i_record = l_record.
    DATA l_dialog TYPE REF TO lcl_gui_dialog.
    l_dialog ?= m_dialog.
    CHECK l_dialog IS NOT INITIAL.
    CALL METHOD l_dialog->call_dialog
      EXPORTING
        i_action = me->c_browse.
  ENDMETHOD.                    "do_browse_dialog
  METHOD do_create_dialog.
    DATA l_access TYPE char1.
    CALL METHOD me->do_check_role
      EXPORTING
        i_action = me->c_create
      RECEIVING
        r_result = l_access.
    CHECK l_access IS NOT INITIAL.
    DATA l_record TYPE REF TO data.
    CALL METHOD me->get_structure_data
      RECEIVING
        r_result = l_record.
    CHECK l_record IS NOT INITIAL.
    CALL METHOD me->do_active_dialog.
    CHECK m_dialog IS NOT INITIAL.
    CALL METHOD m_dialog->init_record
      EXPORTING
        i_record = l_record.
    DATA l_dialog TYPE REF TO lcl_gui_dialog.
    l_dialog ?= m_dialog.
    CHECK l_dialog IS NOT INITIAL.
    CALL METHOD l_dialog->call_dialog
      EXPORTING
        i_action = me->c_create.
  ENDMETHOD.                    "do_create_dialog
  METHOD do_update_dialog.
    DATA l_access TYPE char1.
    CALL METHOD me->do_check_role
      EXPORTING
        i_action = me->c_update
      RECEIVING
        r_result = l_access.
    CHECK l_access IS NOT INITIAL.
    DATA l_record TYPE REF TO data.
    CALL METHOD me->do_read_record
      RECEIVING
        r_result = l_record.
    CHECK l_record IS NOT INITIAL.
    CALL METHOD me->do_active_dialog.
    CHECK m_dialog IS NOT INITIAL.
    CALL METHOD m_dialog->init_record
      EXPORTING
        i_record = l_record.
    DATA l_dialog TYPE REF TO lcl_gui_dialog.
    l_dialog ?= m_dialog.
    CHECK l_dialog IS NOT INITIAL.
    CALL METHOD l_dialog->call_dialog
      EXPORTING
        i_action = me->c_update.
  ENDMETHOD.                    "do_update_dialog
  METHOD do_delete_dialog.
    DATA l_access TYPE char1.
    CALL METHOD me->do_check_role
      EXPORTING
        i_action = me->c_delete
      RECEIVING
        r_result = l_access.
    CHECK l_access IS NOT INITIAL.
    DATA l_record TYPE REF TO data.
    CALL METHOD me->do_read_record
      RECEIVING
        r_result = l_record.
    CHECK l_record IS NOT INITIAL.
    DATA l_result TYPE char1 VALUE IS INITIAL.
    CALL FUNCTION 'POPUP_TO_CONFIRM'
      EXPORTING
        text_question  = 'Удалить запись?'
      IMPORTING
        answer         = l_result
      EXCEPTIONS
        text_not_found = 1
        OTHERS         = 2.
    CHECK l_result EQ '1'.
    CALL METHOD me->do_delete_record
      EXPORTING
        i_record  = l_record
      EXCEPTIONS
        no_result = 1
        OTHERS    = 2.
  ENDMETHOD.                    "do_delete_dialog
  METHOD do_create_record.
    " importing value(i_record) type ref to data
    " exceptions no_result
    CHECK i_record IS NOT INITIAL.
    TRY .
        CALL METHOD me->do_create_by_id
          EXPORTING
            i_record  = i_record
          EXCEPTIONS
            no_result = 1
            OTHERS    = 2.
        IF sy-subrc EQ 0.
          CALL METHOD me->do_init_record
            EXPORTING
              i_action = c_create
              i_record = i_record.
        ELSE.
          RAISE no_result.
        ENDIF.
      CATCH cx_root.
        RAISE no_result.
    ENDTRY.
  ENDMETHOD.                    "do_create_record
  METHOD do_update_record.
    " importing value(i_record) type ref to data
    " exceptions no_result
    CHECK i_record IS NOT INITIAL.
    TRY .
        CALL METHOD me->do_update_by_id
          EXPORTING
            i_record  = i_record
          EXCEPTIONS
            no_result = 1
            OTHERS    = 2.
        IF sy-subrc EQ 0.
          CALL METHOD me->do_init_record
            EXPORTING
              i_action = c_update
              i_record = i_record.
        ELSE.
          RAISE no_result.
        ENDIF.
      CATCH cx_root.
        RAISE no_result.
    ENDTRY.
  ENDMETHOD.                    "do_edit_record
  METHOD do_delete_record.
    " importing value(i_record) type ref to data
    " exceptions no_result
    CHECK i_record IS NOT INITIAL.
    TRY.
        CALL METHOD me->do_delete_by_id
          EXPORTING
            i_record  = i_record
          EXCEPTIONS
            no_result = 1
            OTHERS    = 2.
        IF sy-subrc EQ 0.
          CALL METHOD me->do_init_record
            EXPORTING
              i_action = c_delete
              i_record = i_record.
        ELSE.
          RAISE no_result.
        ENDIF.
      CATCH cx_root.
        RAISE no_result.
    ENDTRY.
  ENDMETHOD.                    "do_delete_record
  METHOD do_save_record.
    DATA: l_action TYPE i,
          l_record TYPE REF TO data.
    CALL METHOD me->get_structure_data
      RECEIVING
        r_result = l_record.
    CHECK l_record IS NOT INITIAL.
    CALL METHOD m_dialog->read_record
      CHANGING
        i_record = l_record.
    CALL METHOD m_dialog->read_action
      RECEIVING
        r_result = l_action.
    IF l_action EQ me->c_create.
      " Проверка
      CALL METHOD me->do_check_record
        EXPORTING
          i_action = l_action
          i_record = l_record
        RECEIVING
          r_result = l_action.
    ENDIF.
    CASE l_action.
      WHEN me->c_create.
        CALL METHOD me->do_create_record
          EXPORTING
            i_record  = l_record
          EXCEPTIONS
            no_result = 1
            OTHERS    = 2.
      WHEN me->c_update.
        CALL METHOD me->do_update_record
          EXPORTING
            i_record  = l_record
          EXCEPTIONS
            no_result = 1
            OTHERS    = 2.
      WHEN OTHERS.
    ENDCASE.
    IF sy-subrc EQ 0 AND ( l_action EQ c_create OR l_action EQ c_update ).
      MESSAGE 'Данные успешно сохранены' TYPE 'S'.
    ELSE.
      MESSAGE 'Произошла ошибка при сохранении данных'
        TYPE 'S' DISPLAY LIKE 'E'.
    ENDIF.
    FREE l_record.
  ENDMETHOD.                    "do_save_record
  METHOD do_next_record.
    " returning value(r_result) type ref to data
  ENDMETHOD.                    "do_next_record
  METHOD do_prev_record.
    " returning value(r_result) type ref to data
  ENDMETHOD.                    "do_prev_record
  METHOD do_read_record.
    " returning value(r_result) type ref to data
  ENDMETHOD.                    "do_read_record
  METHOD do_init_record.
    " importing value(i_action) type i
    " value(i_record) type ref to data
  ENDMETHOD.                    "do_init_record
  METHOD do_check_record.
    " importing value(i_action) type i
    "           value(i_record) type ref to data
    " returning value(r_result) type i
  ENDMETHOD.                    "do_check_record
  METHOD do_check_role.
    " importing value(i_action) type i
    " returning value(r_result) type char1
  ENDMETHOD.                    "do_check_role
  METHOD do_select_by_id.
    " importing i_record type ref to data
    " exceptions no_result
  ENDMETHOD.                    "do_select_by_id
  METHOD do_create_by_id.
    " importing i_record type ref to data
    " exceptions no_result
  ENDMETHOD.                    "do_create_by_id
  METHOD do_update_by_id.
    " importing i_record type ref to data
    " exceptions no_result
  ENDMETHOD.                    "do_update_by_id
  METHOD do_delete_by_id.
    " importing i_record type ref to data
    " exceptions no_result
  ENDMETHOD.                    "do_delete_by_id
ENDCLASS.                    "lcl_gui_view_screen IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_dialog IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_dialog IMPLEMENTATION.
  METHOD do_pbo.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pbo
      EXPORTING
        i_ucomm = i_ucomm.
  ENDMETHOD.                    "do_pbo
  METHOD do_pai.
    " importing i_ucomm type syucomm
    CALL METHOD super->do_pai
      EXPORTING
        i_ucomm = i_ucomm.
    CASE i_ucomm.
      WHEN 'NEXT'.
        CALL METHOD me->do_next_record.
      WHEN 'PREV'.
        CALL METHOD me->do_prev_record.
    ENDCASE.
  ENDMETHOD.                    "do_pai
  METHOD do_apply_record.
    CALL METHOD me->do_save_record( ).
  ENDMETHOD.                    "do_apply_record
  METHOD do_read_record.
    " changing i_record type ref to data
  ENDMETHOD.                    "do_read_record
  METHOD do_init_record.
    " importing i_record type ref to data
  ENDMETHOD.                    "do_init_record
  METHOD do_save_record.
    CASE m_action.
      WHEN c_create OR c_update.
        DATA l_screen TYPE REF TO lcl_gui_view_screen.
        l_screen ?= m_screen.
        IF l_screen IS NOT INITIAL.
          CALL METHOD l_screen->save_record.
        ENDIF.
      WHEN c_cancel OR c_browse OR c_delete.
        CALL METHOD lcl_gui_application=>back( ).
      WHEN OTHERS.
        MESSAGE 'Неизвестный режим' TYPE 'S'.
    ENDCASE.
  ENDMETHOD.                    "do_save_record
  METHOD do_next_record.
    IF m_screen IS NOT INITIAL.
      IF m_action EQ c_create.
        MESSAGE 'В этом режиме функция недоступна' TYPE 'S'.
      ELSE.
        DATA l_screen TYPE REF TO lcl_gui_view_screen.
        l_screen ?= m_screen.
        IF l_screen IS NOT INITIAL.
          CALL METHOD l_screen->next_record.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDMETHOD.                    "do_next_record
  METHOD do_prev_record.
    IF m_screen IS NOT INITIAL.
      IF m_action EQ c_create.
        MESSAGE 'В этом режиме функция недоступна' TYPE 'S'.
      ELSE.
        DATA l_screen TYPE REF TO lcl_gui_view_screen.
        l_screen ?= m_screen.
        IF l_screen IS NOT INITIAL.
          CALL METHOD l_screen->prev_record.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDMETHOD.                    "do_prev_record
  METHOD lif_gui_view_dialog~init_record.
    " importing i_record type ref to data
    CALL METHOD me->do_init_record
      EXPORTING
        i_record = i_record.
  ENDMETHOD.                    "lif_gui_dialog~init_record
  METHOD lif_gui_view_dialog~read_record.
    " changing i_record type ref to data
    CALL METHOD me->do_read_record
      CHANGING
        i_record = i_record.
  ENDMETHOD.                    "lif_gui_dialog~read_record
  METHOD lif_gui_view_dialog~read_action.
    " returning value(r_result) type i
    r_result = me->do_read_action( ).
  ENDMETHOD.                    "lif_gui_dialog~read_action
  METHOD lif_gui_view_dialog~init_action.
    "importing value(i_action) type i
    CALL METHOD me->do_init_action( i_action ).
  ENDMETHOD.                    "lif_gui_dialog~init_action
ENDCLASS.                    "lcl_gui_view_dialog IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_view_subscreen IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_view_subscreen IMPLEMENTATION.
  METHOD get_mode.
    " RETURNING value(result) TYPE i
    result = m_mode.
  ENDMETHOD.                    "get_mode
  METHOD set_mode.
    " IMPORTING value(i_mode) TYPE i
    m_mode = i_mode.
  ENDMETHOD.                    "set_mode
ENDCLASS.                    "lcl_gui_view_subscreen IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_gui_grid_screen IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_gui_grid_screen IMPLEMENTATION.
  METHOD free.
    FREE: m_grid, m_container.
    CALL METHOD super->free.
    CALL METHOD cl_gui_cfw=>flush.
  ENDMETHOD.                    "free
  METHOD do_init_screen.
    IF m_grid IS INITIAL.
      " Create GUI objects
      DATA l_container_name TYPE c LENGTH 32.
      CALL METHOD me->get_container_name
        RECEIVING
          r_result = l_container_name.
      CONDENSE l_container_name NO-GAPS.
      CHECK l_container_name IS NOT INITIAL.
      " Create objects
      CREATE OBJECT m_container
        EXPORTING
          container_name = l_container_name.
      CREATE OBJECT m_grid
        EXPORTING
          i_parent = m_container.
      " Fill structure for IS_VARIANT
      CALL METHOD me->do_init_variant.
      " Fill structure for IS_LAYOUT
      CALL METHOD me->do_init_layout.
      " Build field catalog
      CALL METHOD me->do_init_fields.
      " Build special groups
      CALL METHOD me->do_init_groups.
      " Build sort catalog
      CALL METHOD me->do_init_sorted.
      " Load data
      CALL METHOD me->do_init_outtab.
      " Set handlers
      CALL METHOD me->set_alvgrid_handlers.
      " Set receiver for edit
      CALL METHOD me->set_alvgrid_edit_event.
    ELSE.
      CALL METHOD m_grid->refresh_table_display.
    ENDIF.
    CALL METHOD cl_gui_cfw=>flush.
  ENDMETHOD.                    "do_init_screen
  METHOD do_init_variant.
    m_variant-report = sy-repid.
  ENDMETHOD.                    "do_init_variant
  METHOD do_init_layout.
    m_layout-no_rowins  = 'X'.
    m_layout-edit       = space.
    m_layout-sel_mode   = 'B'.
    m_layout-zebra      = 'X'.
    m_layout-smalltitle = 'X'.
    m_layout-grid_title = me->get_alvgrid_title( ).
  ENDMETHOD.                    "do_init_layout
  METHOD do_init_fields.
    DATA: fieldcat_wa TYPE lvc_s_fcat,
          l_struct_name TYPE dd02l-tabname.
    CALL METHOD me->get_structure_name
      RECEIVING
        r_result = l_struct_name.
    CONDENSE l_struct_name NO-GAPS.
    CHECK l_struct_name IS NOT INITIAL.
    CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
      EXPORTING
        i_structure_name       = l_struct_name
      CHANGING
        ct_fieldcat            = m_fieldcat
      EXCEPTIONS
        inconsistent_interface = 1
        program_error          = 2
        OTHERS                 = 3.
  ENDMETHOD.                    "do_init_fields
  METHOD do_init_groups.
  ENDMETHOD.                    "do_init_groups
  METHOD do_init_sorted.
  ENDMETHOD.                    "do_init_sorted
  METHOD do_init_outtab.
    CHECK m_outtab IS NOT INITIAL.
    DATA l_struct_name TYPE dd02l-tabname.
    CALL METHOD me->get_structure_name
      RECEIVING
        r_result = l_struct_name.
    CONDENSE l_struct_name NO-GAPS.
    CHECK l_struct_name IS NOT INITIAL.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    CHECK <outtab> IS ASSIGNED.
    TRY.
        CALL METHOD m_grid->set_table_for_first_display
          EXPORTING
            i_structure_name              = l_struct_name
            is_variant                    = m_variant
            i_save                        = m_save
            is_layout                     = m_layout
            it_special_groups             = m_groupcat
          CHANGING
            it_outtab                     = <outtab>
            it_fieldcatalog               = m_fieldcat
            it_sort                       = m_sortcat
          EXCEPTIONS
            invalid_parameter_combination = 1
            program_error                 = 2
            too_many_lines                = 3
            OTHERS                        = 4.
        IF sy-subrc <> 0.
          MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                     WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        ENDIF.
        CALL METHOD m_grid->set_toolbar_interactive.
        CHECK LINES( <outtab> ) GT 0.
        m_select_row-index = 1.
        APPEND m_select_row TO m_index_rows.
        CALL METHOD me->set_selected_rows
          EXCEPTIONS
            no_rows = 1
            OTHERS  = 2.
      CATCH cx_root.
    ENDTRY.
  ENDMETHOD.                    "do_init_outtab
  METHOD do_next_record.
    " returning value(r_result) type ref to data
    CHECK m_outtab IS NOT INITIAL.
    CHECK m_dialog IS NOT INITIAL.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    CHECK LINES( <outtab> ) GT 0.
    FIELD-SYMBOLS <select> TYPE lvc_s_row.
    READ TABLE m_index_rows INDEX 1 ASSIGNING <select>.
    CHECK sy-subrc EQ 0.
    IF <select>-index IS INITIAL OR <select>-index EQ 1.
      <select>-index = LINES( <outtab> ).
    ELSE.
      SUBTRACT 1 FROM <select>-index.
    ENDIF.
    MODIFY m_index_rows INDEX 1 FROM <select>.
    CALL METHOD me->set_selected_rows
      EXCEPTIONS
        no_rows = 1
        OTHERS  = 2.
    CHECK sy-subrc EQ 0.
    DATA: l_record TYPE REF TO data.
    CALL METHOD me->do_read_record
      RECEIVING
        r_result = r_result.
    CALL METHOD m_dialog->init_record
      EXPORTING
        i_record = r_result.
  ENDMETHOD.                    "do_next_record
  METHOD do_prev_record.
    " returning value(r_result) type ref to data
    CHECK m_outtab IS NOT INITIAL.
    CHECK m_dialog IS NOT INITIAL.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    CHECK LINES( <outtab> ) GT 0.
    FIELD-SYMBOLS <select> TYPE lvc_s_row.
    READ TABLE m_index_rows INDEX 1 ASSIGNING <select>.
    CHECK sy-subrc EQ 0.
    IF <select>-index IS INITIAL.
      <select>-index = 1.
    ELSEIF <select>-index EQ LINES( <outtab> ).
      <select>-index = 1.
    ELSEIF <select>-index LT LINES( <outtab> ).
      ADD 1 TO <select>-index.
    ENDIF.
    MODIFY m_index_rows INDEX 1 FROM <select>.
    CALL METHOD me->set_selected_rows
      EXCEPTIONS
        no_rows = 1
        OTHERS  = 2.
    CHECK sy-subrc EQ 0.
    CALL METHOD me->do_read_record
      RECEIVING
        r_result = r_result.
    CALL METHOD m_dialog->init_record
      EXPORTING
        i_record = r_result.
  ENDMETHOD.                    "do_prev_record
  METHOD do_read_record.
    " returning value(r_result) type ref to data
    CALL METHOD me->get_selected_rows
      EXCEPTIONS
        no_rows = 1
        OTHERS  = 2.
    CHECK sy-subrc EQ 0.
    READ TABLE m_index_rows
      INDEX 1 INTO m_select_row.
    CHECK sy-subrc EQ 0.
    DATA lv_index TYPE i.
    lv_index = m_select_row-index.
    CHECK lv_index IS NOT INITIAL.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    READ TABLE <outtab> INDEX lv_index
      REFERENCE INTO r_result.
  ENDMETHOD.                    "do_init_record
  METHOD do_init_record.
    "importing value(i_action) type i
    "          value(i_record) type ref to data
    CHECK i_record IS NOT INITIAL.
    FIELD-SYMBOLS <record> TYPE data.
    ASSIGN i_record->* TO <record>.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    CASE i_action.
      WHEN me->c_create.
        CALL METHOD me->set_index_before_create.
        APPEND <record> TO <outtab>.
      WHEN me->c_update.
        REFRESH m_index_rows.
        APPEND m_select_row TO m_index_rows.
        MODIFY <outtab> INDEX m_select_row-index FROM <record>.
      WHEN me->c_delete.
        DELETE <outtab> INDEX m_select_row-index.
        CALL METHOD me->set_index_after_delete.
    ENDCASE.
    CALL METHOD m_grid->refresh_table_display.
    CALL METHOD me->set_selected_rows
      EXCEPTIONS
        no_rows = 1
        OTHERS  = 2.
  ENDMETHOD.                    "do_save_record
  METHOD get_selected_rows.
    " exceptions no_rows
    CALL METHOD m_grid->get_selected_rows
      IMPORTING
        et_index_rows = m_index_rows.
    IF LINES( m_index_rows ) GT 0.
      READ TABLE m_index_rows INDEX 1 INTO m_select_row.
      IF sy-subrc NE 0.
        RAISE no_rows.
      ENDIF.
    ELSE.
      RAISE no_rows.
    ENDIF.
  ENDMETHOD.                    "get_selected_rows
  METHOD set_selected_rows.
    " exceptions no_rows
    IF LINES( m_index_rows ) GT 0.
      CALL METHOD m_grid->set_selected_rows
        EXPORTING
          it_index_rows = m_index_rows.
    ELSE.
      RAISE no_rows.
    ENDIF.
  ENDMETHOD.                    "set_selected_rows
  METHOD set_alvgrid_handlers.
    SET HANDLER me->do_handle_toolbar
      FOR m_grid.
    SET HANDLER me->do_handle_user_command
      FOR m_grid.
    SET HANDLER me->do_double_click_command
      FOR m_grid.
    SET HANDLER me->do_hotspot_click_command
      FOR m_grid.
  ENDMETHOD.                    "set_alvgrid_handlers
  METHOD set_alvgrid_edit_event.
    IF m_layout-edit NE space.
      CALL METHOD m_grid->register_edit_event
        EXPORTING
          i_event_id = cl_gui_alv_grid=>mc_evt_modified.
    ENDIF.
  ENDMETHOD.                    "set_alvgrid_edit_event
  METHOD set_index_before_create.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    DATA l_index TYPE i.
    l_index = LINES( <outtab> ) + 1.
    REFRESH m_index_rows.
    m_select_row-index = l_index.
    APPEND m_select_row TO m_index_rows.
  ENDMETHOD.                    "set_index_before_create
  METHOD set_index_after_delete.
    FIELD-SYMBOLS <outtab> TYPE STANDARD TABLE.
    ASSIGN m_outtab->* TO <outtab>.
    DATA l_count TYPE i.
    l_count = LINES( <outtab> ).
    REFRESH m_index_rows.
    IF l_count EQ 0.
      CLEAR m_select_row-index.
    ELSEIF m_select_row-index GT l_count.
      m_select_row-index = l_count.
    ENDIF.
    CHECK m_select_row-index IS NOT INITIAL.
    APPEND m_select_row TO m_index_rows.
  ENDMETHOD.                    "set_index_after_delete
  METHOD do_handle_toolbar.
    " importing e_object type ref to cl_alv_event_toolbar_set
    "           e_interactive type char01
    " Constatnts for button type
    CONSTANTS: c_button_normal           TYPE i VALUE 0,
               c_menu_and_default_button TYPE i VALUE 1,
               c_menu                    TYPE i VALUE 2,
               c_separator               TYPE i VALUE 3,
               c_radio_button            TYPE i VALUE 4,
               c_checkbox                TYPE i VALUE 5,
               c_menu_entry              TYPE i VALUE 6.
*    data ls_toolbar type stb_button.
    " Append separator to normal toolbar
*    clear ls_toolbar.
*    move c_separator to ls_toolbar-butn_type.
*    append ls_toolbar to e_object->mt_toolbar.
    " Append XXX report-button to normal toolbar
*    clear ls_toolbar.
*    move: 'xxx' to ls_toolbar-function,
*          icon_pdf to ls_toolbar-icon,
*          'xxx' to ls_toolbar-quickinfo,
*          '' to ls_toolbar-text,
*          '' to ls_toolbar-disabled.
*    append ls_toolbar to e_object->mt_toolbar.
  ENDMETHOD.                    "do_handle_toolbar
  METHOD do_handle_user_command.
    " importing e_ucomm type sy-ucomm
*    if e_ucomm eq 'xxx'.
*
*    endif.
  ENDMETHOD.                    "do_handle_user_command
  METHOD do_double_click_command.
    " importing e_row     type lvc_s_row  optional
    "           e_column  type lvc_s_col  optional
    "           es_row_no type lvc_s_roid optional
  ENDMETHOD.                    "do_double_click_command
  METHOD do_hotspot_click_command.
    " importing e_row_id     type lvc_s_row   optional
    "           e_column_id  type lvc_s_col   optional
    "           es_row_no    type lvc_s_roid  optional
*    data: l_tabix type i,
*          l_field type string.
*
*    move: e_row_id-index        to l_tabix,
*          e_column_id-fieldname to l_field.
  ENDMETHOD.                    "do_hotspot_click_command
ENDCLASS.                    "lcl_gui_grid_screen IMPLEMENTATION
Дополнительно, в программе реализован паттерны Singleton (класс приложения), Decorator (для подэкранов), Adapter и др. 
Комментарии
Отправить комментарий