При разработке приложений для 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 и др.
Комментарии
Отправить комментарий