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