Skip to Content

Important note: The uploaded files seem to be lost after the SCN system upgrade. You can find all related codings and screenshots at the end of the blog entry.

Another framework?

I checked out some approaches like SAPmvc from Marcelo Araujo Ramos, but they did not fit in my programming style. That is, I do not want to have any relevant program logic outside OO classes and I’d like to reduce dynpro usage to a minimum. So I started to create this framework which is a productive one, that means, me and my colleagues are using it already for over a year. It has evolved during this period and now I think it’s time to share it.

The general approach

Before we get deeper into the coding, I’d like to drop some explanations about the general architecture that a program that uses the framework will contain.

What program type?

This is a question I have often reflected on. When I create an OO based dialogue application, what kind of program should I use? Since the program has to manage at least one dynpro, we could choose between three types of program for our application:

      • A module pool
      • A function group
      • A report

Subroutine pools can not carry dynpros so we cannot use them. What type to use?

The module pool ist declared obsolete by SAP, so I decided to not use this one.

The objective of a function group is to host function modules, which are very uncomfortable to use in the OO environment (no automatic type determination of parameters, obsolete table types in parameters.

A report can contain dynpros and can be used even without the report events. In case of the need to create a real report with a selection screen, it’s naturally the only alternative (the framework supports also report-type programs). So I decided to create all my programs using reports. Another advantage is that I can always place a call screen statement unter start-of-selection, so my dialogue application can run directly from the editor pressing F8.

It’s not obligatory to use a report, though. )f you feel more comfortable using one of the other possibilities, the framework works as well. Once the program is created, you should define a main controller (I call it always LCL_CON_MAIN) as a subclass of ZCL_MVCFW_CON_MAIN and a model (LCL_MODEL). In some cases, the model could be also a public class, if you plan to reuse its functionality. Furthermore you will need one class for each additional controller. Create one controller for each subdynpro you use as well as each CFW screen control.

The model

The model component is a freely composed class that will keep the application data and do manipulations on it. All database accesses are done within the model. The model itself never interacts with the user, but only signals to the controller if something is do display or input is to be taken. One single model is typically, but complex applications can also have more of them.

The view

The framework uses the following types of views

Main dynpro: the main dynpro of the program (and there will be only exactly one; i’ll get back to this later) is the main view component. All further visible elements depend on it.

Sub dynpro: As we will see later on, the main dynpro is not intended to carry any fields. There is only a subdynpro area on it that spans the whole space. I normally create the main screen with the maximum size (200 li x 255 col). Any screen element such as input fields or custom controls will be created on a sub dynpro. You can have more than one sub dynpro and switch between them.

Selection screen: In a report-type application, there will be a selection screen, which we regard as a view component, too. I will introduce a selection-screen framework component in the next part.

CFW control view: Apart from the classical dynpros, any control type of the control framework will play the role of a separate view component

The controller

There will be one controller class for each view. The main controller manages the main dynpro and can react to user interaction via the GUI status functions, though this could be coded also in the sub dynpro controller. It also keeps a list of all instantiated controllers and will take care of the right instantiation, when a new one is needed. We will have a look at this in detail later on. It also should keep the main logic for the program flow.The CFW view controllers are responsible for the data flow to the dedicated screen control. Therefore, they keep a reference to the model in order to be able to get the data to display from there.

Framework architecture

The framework consists of the following repo objects:

  1. The main controller class ZCL_MVCFW_CON_MAIN. A program will define its own main controller inheriting from this class – all classes in the framework are abstract and need final classes in the program that inherit from these.
  2. The abstract dynpro controller ZCL_MCFW_CON_DYNPRO. It has a subclass for a subdynpro:
    1. ZCL_MVCFW_CON_SUBDYN: manage a subdynpro (it can also manage a dynpro in a popup)
      In the next part, I will introduce another subclass for selection screens
  3. The abstract CFW controller ZCL_MCFW_CON_CFW. It can be used to manage any CFW screen control
    1. ZCL_MVCFW_CON_ALV: a subclass of the above for the most common control ALV that contains a lot of useful stuff to manage an ALV grid control  (CL_GUI_ALV_GRID)
  4. An exception class ZCX_MCVFW_ERROR, which is quite generic and serves to pass exception situations to the controller

The coding is included in the demo application.

Demo application

The report ZP_MVCFW_ALV_DEMO (complete listing in the sources) is a simple application with a simple dynpro and two ALV grids in it. You can upload the demo application from the attached file ZP_MVCFW_ALV_DEMO.TXT.

Main screen

The main screen (see sources) contains one single element: a subscreen area (called SUBSCREEN) that spans over the whole available space. You can upload the screen from file ZP_MVCFW_ALV_DEMO_SCREEN_0001.TXT.

The flow logic:

process before output.

module pbo_0001.

    call subscreen subscreen including sy-repid gv_subdyn.

*

process after input.

    module pai_0001 at exit-command.

    call subscreen subscreen.

    module pai_0001.

Sub screen

The sub screen is the “working” screen. Here we have the input/output fields that we need. For the framework, it is indispensable that all fields are DDIC dependent and belong to the same structure.

You can upload the sub screen after having created it from the corresponding field

The sub screen in the demo application contains one field:

Screen logic:

process before output.

module pbo_sub.

*

process after input.

module pai_sub.

GUI interface of the demo application

To get the demo running, you will have to create a GUI status named MAIN. See the pictures to find the codes you have to create.

  • Set the code for the exit button to EXIT
  • Set the code for the back button to BACK
  • set the code for the cancel button to CANCEL
  • add the code SHOW to the application toolbar with icon ICON_DISPLAY

Furthermore, you will need a GUI title called MAIN with text “Display flight data”

The error class

To create the error class, just create the class as exception class with T100 interface and switch to the public section code. Then paste the coding from the demo application.

Methods of the framework

ZCL_MVCFW_CON_MAIN

This class is used as super class for the main controller (LCL_CON_MAIN in demo). It provides the following methods

Constructor

The constructor takes the program name as parameter. It is used in the SET PF-STATUS and SET TITLEBAR commands to specify the program. In the local subclass, call the super constructor giving the program name.

GET_INSTANCE

Factory-method (static). It will instantiate the class on first call,in other cases it returns the already created instance (singleton pattern).

GET_CON_DYNPRO

This is to be called from the PBO of subscreens to get the controller. Just like GET_INSTANCE, it will create the controller on the first call, afterwards it returns the already created controller. The framework keeps an internal table with all created controllers in memory

CREATE_CON_DYNPRO

When GET_CON_DYNPRO is called the first time, this method is invoked. Any program using the framework must redefine it with coding for the creation. See demo program for an example

GET_CON

This is the sibling of GET_CON_DYNPRO for CFW controllers. The type of the needed controller class has to be passed as parameter (for example: get_con( ‘LCL_CON_ALV_SFLIGHT’) ). In the demo application, constants are being used for the controller class names.

CREATE_ONE_CONTROLLER

Similar to CREATE_CON_DYNPRO. Redefine it and code the “create object” statements dependent from the input parameter that contains the class name.

GET_SELECTIONS

Used for report-type programs. Will be described in part two.

KILL_CON

Kill a controller (and the associated container)

PAI_EXIT

Can be used in case of exit commandos from the main screen.

PBO_MAIN

Returns the actually displayed sub dynpro and sets the PF-STATUS and TITLEBAR. To be called from the PBO module of the main screen

REFRESH

Calls the REFRESH method of each present container. Useful to do a complete refresh of all CFW controls

SET_SUBDYNPRO

Sets the sub dynpro number, the PF-STATUS and the TITLEBAR that are to be used during PBO. This method should be called during the first PBO in order to have a defined sub dynpro for the screen 0001. Normally you would call it from the constructor method of the main controller. Call it again, when a different screen is to be displayed.

ZCL_MVCFW_CON_DYNPRO

Constructor

Pass the DDIC structure name that contains the fields on the screen and the main controller to the constructor (in the constructor of your local derivation of the class).

INIT_SCREEN

Useful to clear all input fields

PAI

Is to be called from the module PAI_SUB. You can pass the screen structure to it, so it will compare all screen fields to the fields in the memory of the class. For each difference, PAI_FIELD_CHANGE will be called.

PAI_EXIT

Intended for exit commands on pushbuttons on the sub screen. No field validation will take place.

PAI_BEFORE_FIELD_CHANGE

Is called by PAI. Can be redefined for specific actions to be taken before the user input is validated.

PAI_FIELD_CHANGE

Is called by PAI. Each value of the given screen structure (parameter c_data of PAI) is compared to the correspondent structure in the memory of the class. For each difference found, this method is invoked where you can code reactions on changed field values on the screen.

PAI_USER_COMMAND

Is called by PAI after the field validation giving the user command. It has to be redefined and should contain reactions to user actions. You are free to decide if you want to handle user commands in a PAI method of the main controller or in here.

SHOW_ERROR

Called by PAI and PAI_FIELD_CHANGE in case of occurrence of an exception. Can be redefined in order to react accordingly.

ZCL_MVCFW_CON_CFW

Constructor

The constructor takes the GUI container where the CFW control should be placed as parameter. Normally a container will be created in CREATE_ONE_CONTROLLER before creating the object.

CHECK_CHANGED_DATA

Many CFW controls have input capabilities (Text editors, ALV grids…). Redefine this method for the CFW control to get the input into the program. In ZCL_MVCFW_CON_ALV for instance, it is redefined containing a CHECK_CHANGED_DATA call to the ALV object.

FREE

Is used by KILL_CON of the main controller.

GET_CONTAINER

Getter for the container of the control.

HIDE

Sets the container to invisible (useful for docking containers)

REFRESH

Generic refresh method. Each concrete CFW control can implement its own version. See ALV control for an example.

UNHIDE

Reveals the container after a HIDE( ) call.

Conclusion

For the remaining classes, I kindly ask to look at the demo application. The ALV controller is very useful in my daily work and I’d like to enforce you to create further derivations of the CFW controller for other screen control types.

In the second part (MVC (model view controller) framework for ABAP part 2) I will introduce an approach for reports that are using the framework. Any comments and bug reports are appreciated.

Jörg Krause

class ZCL_MVCFW_CON_MAIN definition
  public
  abstract
  create public .

public section.

*"* public components of class ZCL_MVCFW_CON_MAIN
*"* do not include other source files here!!!
  methods CONSTRUCTOR
    importing
      value(IV_PROGRAM) type SYREPID .
  methods CONTROLLER_EXISTS
    importing
      !IV_TYPE type C
    returning
      value(RV_RES) type ABAP_BOOL .
  methods GET_CON
    importing
      !IV_TYPE type C
    returning
      value(RO_RES) type ref to ZCL_MVCFW_CON_CFW
    raising
      ZCX_MVCFW_ERROR .
  methods GET_SELECTIONS
    exporting
      !ES_DATA type ANY .
  methods KILL_CON
    importing
      !IV_TYPE type C .
  methods GET_CON_DYNPRO
    importing
      !IV_SCREEN type SYDYNNR optional
    returning
      value(RO_RES) type ref to ZCL_MVCFW_CON_DYNPRO .
  methods PAI_EXIT
    importing
      !IV_UCOMM type SYUCOMM .
  methods PBO_MAIN
    returning
      value(RV_RES) type SYDYNNR .
  methods REFRESH
    importing
      !IV_TYPE type C optional
      !IV_GROUP type CHAR4 optional
    raising
      CX_STATIC_CHECK .
  methods SET_SUBDYNPRO
    importing
      !IV_DYNNR type SYDYNNR optional
      !IV_GUI_STATUS type GUI_STATUS optional
      !IV_TITLEBAR type GUI_TITLE optional
    preferred parameter IV_DYNNR .
  class-methods GET_INSTANCE
    importing
      value(IV_TYPE) type CHAR32 optional
      !IV_PROGRAM type SYREPID optional
    returning
      value(RO_RES) type ref to ZCL_MVCFW_CON_MAIN .
  protected section.

    types:
*"* protected components of class ZCL_MVCFW_CON_MAIN
*"* do not include other source files here!!!
      begin of gty_s_controller,
        type  type char32,
        dynnr type sydynnr,
        group type char4,
        o_con type ref to object,
      end of gty_s_controller .
    types:
      gty_t_controllers type sorted table of gty_s_controller
          with unique key type dynnr .

    data mv_subscreen type sydynnr .
    data mv_gui_status type gui_status .
    data mv_titlebar_text type text132 .
    data mt_controllers type gty_t_controllers .
    data mv_titlebar type gui_title .
    data mv_program type syrepid .

    methods set_gui_interface
      importing
        !iv_gui_status type gui_status optional
        !iv_titlebar   type gui_title optional .
    methods create_con_dynpro
      importing
        !iv_screen    type sydynnr optional
      returning
        value(ro_res) type ref to zcl_mvcfw_con_dynpro .
    methods create_one_controller
      importing
        !iv_type      type c
      returning
        value(ro_res) type ref to zcl_mvcfw_con_cfw
      raising
        zcx_mvcfw_error .
private section.

*"* private components of class ZCL_MVCFW_CON_MAIN
*"* do not include other source files here!!!
  class-data SO_ME type ref to ZCL_MVCFW_CON_MAIN .

  methods PUT_DYNPRO_CONTROLLER
    importing
      !IO_IN type ref to OBJECT
      !IV_DYNNR type SYDYNNR optional .
  methods GET_CONTAINER_TYPE
    importing
      !IO_IN type ref to CL_GUI_CONTAINER
      !IV_TYPE type CHAR32
    returning
      value(RO_RES) type ref to CL_GUI_CONTAINER .
ENDCLASS.



CLASS ZCL_MVCFW_CON_MAIN IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_PROGRAM                     TYPE        SYREPID
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method constructor.
    mv_program = iv_program.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->CONTROLLER_EXISTS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        C
* | [<-()] RV_RES                         TYPE        ABAP_BOOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method controller_exists.

    read table mt_controllers
      with key type = iv_type
      transporting no fields.
    if sy-subrc <> 0.
      rv_res = abap_false.
    else.
      rv_res = abap_true.
    endif.

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_MAIN->CREATE_CON_DYNPRO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_SCREEN                      TYPE        SYDYNNR(optional)
* | [<-()] RO_RES                         TYPE REF TO ZCL_MVCFW_CON_DYNPRO
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method create_con_dynpro.
    message 'CREATE_CON_DYNPRO must be redefined' type 'A'.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_MAIN->CREATE_ONE_CONTROLLER
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        C
* | [<-()] RO_RES                         TYPE REF TO ZCL_MVCFW_CON_CFW
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method create_one_controller.

    " to be redefined
* the type must be inheriting from zcl_mvcfw_con_cfw
* create object ro_res type (iv_type)
*    exporting iv_title = iv_title
*    (pass other parameters)

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->GET_CON
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        C
* | [<-()] RO_RES                         TYPE REF TO ZCL_MVCFW_CON_CFW
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method get_con.

    data ls_controller type gty_s_controller.

    read table mt_controllers into ls_controller
      with key type = iv_type.
    if sy-subrc <> 0.
      ls_controller-o_con = create_one_controller( iv_type ).
      ls_controller-type = iv_type.
      insert ls_controller into table mt_controllers.
    endif.
    ro_res ?= ls_controller-o_con.

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_MVCFW_CON_MAIN->GET_CONTAINER_TYPE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_IN                          TYPE REF TO CL_GUI_CONTAINER
* | [--->] IV_TYPE                        TYPE        CHAR32
* | [<-()] RO_RES                         TYPE REF TO CL_GUI_CONTAINER
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method get_container_type.


    if cl_abap_typedescr=>describe_by_object_ref( io_in )->get_relative_name( ) <> iv_type.
      if io_in->parent is bound.
        ro_res = get_container_type( io_in = io_in->parent
                                     iv_type = iv_type ).
      endif.
    else.
      ro_res = io_in.
    endif.

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->GET_CON_DYNPRO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_SCREEN                      TYPE        SYDYNNR(optional)
* | [<-()] RO_RES                         TYPE REF TO ZCL_MVCFW_CON_DYNPRO
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method get_con_dynpro.
    field-symbols: <ls_controller>    type gty_s_controller.
    data: lv_screen                   type sydynnr.

    if iv_screen is supplied.
      lv_screen = iv_screen.
    else.
      lv_screen   = sy-dynnr.
    endif.

    " to be redefined
    " return the singleton object for the subdynpro controller according to
    " the actual subscreen number
    read table mt_controllers assigning <ls_controller>
      with key type = space dynnr = lv_screen.
    if sy-subrc = 0.
      ro_res ?= <ls_controller>-o_con.
    else.
      ro_res = create_con_dynpro( lv_screen ).
      put_dynpro_controller( io_in = ro_res iv_dynnr = lv_screen ).
    endif.

    " in the caller, if ro_res remains not bound, do the instantiation
    " case sy-dynnr.
    "   when '0101'.
    "     ro_res = lcl_con_subdyn_0101=>get_instance( ).
    "     super->put_dynpro_controller( ro_res )

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_MVCFW_CON_MAIN=>GET_INSTANCE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        CHAR32(optional)
* | [--->] IV_PROGRAM                     TYPE        SYREPID(optional)
* | [<-()] RO_RES                         TYPE REF TO ZCL_MVCFW_CON_MAIN
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method get_instance.
    data lv_type type string.

    if so_me is not bound.
      lv_type = '\PROGRAM='.
      if iv_program is not supplied.
        lv_type = lv_type && sy-cprog.
      else.
        lv_type = lv_type && iv_program.
      endif.
      lv_type = lv_type && | \\CLASS=|.
      if iv_type is not supplied.
        lv_type = lv_type && 'LCL_CON_MAIN'.
      else.
        lv_type = lv_type && iv_type.
      endif.
      create object so_me
        type (lv_type)
        exporting
          iv_program = sy-repid.
    endif.
    ro_res = so_me.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->GET_SELECTIONS
* +-------------------------------------------------------------------------------------------------+
* | [<---] ES_DATA                        TYPE        ANY
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method get_selections.
    " to be redefined
    " the only access to the global fields in the selection screen
*    ms_selscreen-s_carrid   = s_carrid[].
*    ms_selscreen-s_connid   = s_connid[].
*    ms_selscreen-s_fldate   = s_fldate[].
*    ms_selscreen-p_batch    = p_batch.
*    if es_data is supplied.
*      es_data = ms_selscreen.
*    endif.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->KILL_CON
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        C
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method kill_con.

    data ls_controller type gty_s_controller.
    data lo_con type ref to zcl_mvcfw_con_cfw.
    data lo_cont type ref to cl_gui_container.

    read table mt_controllers into ls_controller
      with key type = iv_type.
    if sy-subrc = 0.
      delete mt_controllers index sy-tabix.
      lo_con ?= ls_controller-o_con.
      lo_cont = lo_con->get_container( ).
      free lo_con.
      free lo_cont.
    endif.

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->PAI_EXIT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM                       TYPE        SYUCOMM
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method pai_exit.

    " should be redefined for further logic
    leave program.

  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->PBO_MAIN
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RV_RES                         TYPE        SYDYNNR
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method pbo_main.

    data:
      lt_exclude_ucomm              type ui_functions.



    rv_res = mv_subscreen.

    set pf-status mv_gui_status of program mv_program excluding lt_exclude_ucomm.
    set titlebar mv_titlebar of program mv_program with mv_titlebar_text.


  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_MVCFW_CON_MAIN->PUT_DYNPRO_CONTROLLER
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_IN                          TYPE REF TO OBJECT
* | [--->] IV_DYNNR                       TYPE        SYDYNNR(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method put_dynpro_controller.
    data: ls_con                      type gty_s_controller.

    if iv_dynnr is supplied.
      ls_con-dynnr = sy-dynnr.
    else.
      ls_con-dynnr = sy-dynnr.
    endif.
    ls_con-o_con = io_in.
    insert ls_con into table mt_controllers.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->REFRESH
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TYPE                        TYPE        C(optional)
* | [--->] IV_GROUP                       TYPE        CHAR4(optional)
* | [!CX!] CX_STATIC_CHECK
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method refresh.

    data: ls_con type gty_s_controller,
          lo_con type ref to zcl_mvcfw_con_cfw.

    loop at mt_controllers into ls_con.
      if iv_type is supplied.
        check ls_con-type = iv_type.
      endif.
      if iv_group is supplied.
        check ls_con-type = iv_type.
      endif.
      lo_con ?= ls_con-o_con.
      lo_con->refresh( ).
    endloop.


  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_MAIN->SET_GUI_INTERFACE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_GUI_STATUS                  TYPE        GUI_STATUS(optional)
* | [--->] IV_TITLEBAR                    TYPE        GUI_TITLE(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method set_gui_interface.

    if iv_gui_status is supplied.
      mv_gui_status = iv_gui_status.
    endif.
    if iv_titlebar is supplied.
      mv_titlebar = iv_titlebar.
    endif.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_MAIN->SET_SUBDYNPRO
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_DYNNR                       TYPE        SYDYNNR(optional)
* | [--->] IV_GUI_STATUS                  TYPE        GUI_STATUS(optional)
* | [--->] IV_TITLEBAR                    TYPE        GUI_TITLE(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method set_subdynpro.

    if iv_dynnr is supplied.
      mv_subscreen = iv_dynnr.
    endif.
    if iv_gui_status is supplied.
      set_gui_interface(
        iv_gui_status = iv_gui_status
        ).
    endif.
    if iv_titlebar is supplied.
      set_gui_interface(
        iv_titlebar = iv_titlebar ).
    endif.
  endmethod.
ENDCLASS.
class ZCL_MVCFW_CON_DYNPRO definition
  public
  abstract
  create public .

public section.

  methods INIT_SCREEN .
*"* public components of class ZCL_MVCFW_CON_DYNPRO
*"* do not include other source files here!!!
  methods CONSTRUCTOR
    importing
      !IV_STRUC_NAME type TABNAME optional
      !IO_CON_MAIN type ref to ZCL_mvcfw_CON_MAIN optional
    preferred parameter IV_STRUC_NAME .
  methods PAI
    importing
      !IV_UCOMM type SYUCOMM optional
    changing
      !C_DATA type ANY optional .
  methods PAI_EXIT
    importing
      !IV_UCOMM type SYUCOMM optional .
protected section.

  data MO_CON_MAIN type ref to ZCL_MVCFW_CON_MAIN .
*"* protected components of class ZCL_MVCFW_CON_DYNPRO
*"* do not include other source files here!!!
  data MR_SCREEN_DATA type ref to DATA .
  data MV_SCREEN_STRUC type TABNAME .
  data MT_FIELD_LIST type DDFIELDS .
  data MV_STOP_FIELD_PROCESSING type ABAP_BOOL .

  methods PAI_FIELD_CHANGE
    importing
      !IV_FIELDNAME type DFIES-FIELDNAME
      !IV_SOURCE type ANY
      !IV_DESTIN type ANY
      !I_DATA type ANY
    raising
      CX_STATIC_CHECK .
  methods PAI_BEFORE_FIELD_CHANGE
    importing
      !IV_UCOMM type SYUCOMM
    changing
      !C_DATA type ANY
    raising
      CX_STATIC_CHECK .
  methods PAI_USER_COMMAND
    importing
      !IV_UCOMM type SYUCOMM
    raising
      CX_STATIC_CHECK .
  methods SHOW_ERROR .
private section.

*"* private components of class ZCL_MVCFW_CON_DYNPRO
*"* do not include other source files here!!!
  methods PAI_FIELD_CHANGES
    importing
      !I_DATA type ANY
    raising
      CX_STATIC_CHECK .
ENDCLASS.



CLASS ZCL_MVCFW_CON_DYNPRO IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_DYNPRO->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_STRUC_NAME                  TYPE        TABNAME(optional)
* | [--->] IO_CON_MAIN                    TYPE REF TO ZCL_MVCFW_CON_MAIN(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.

  if iv_struc_name is not initial.
    mv_screen_struc = iv_struc_name.
    create data mr_screen_data type (mv_screen_struc).
*   get default field list
    CALL FUNCTION 'DDIF_NAMETAB_GET'
      EXPORTING
        tabname   = iv_struc_name
        all_types = abap_true
      TABLES
*       X031L_TAB =
        dfies_tab = mt_field_list
      EXCEPTIONS
        not_found = 1
        OTHERS    = 2.
  endif.

  mo_con_main = io_con_main.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_DYNPRO->INIT_SCREEN
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method INIT_SCREEN.
    if mr_screen_data is bound.
      assign mr_screen_data->* to field-symbol(<ls_screen>).
      clear <ls_screen>.
    endif.
  endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_DYNPRO->PAI
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM                       TYPE        SYUCOMM(optional)
* | [<-->] C_DATA                         TYPE        ANY(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI.


  try.

      if c_data is supplied.
        pai_before_field_change( exporting iv_ucomm = iv_ucomm
                                 changing c_data = c_data ).
        pai_field_changes( c_data ).
      endif.

      pai_user_command( iv_ucomm ).

    catch cx_static_check.
      show_error( ).
  endtry.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_DYNPRO->PAI_BEFORE_FIELD_CHANGE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM                       TYPE        SYUCOMM
* | [<-->] C_DATA                         TYPE        ANY
* | [!CX!] CX_STATIC_CHECK
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI_BEFORE_FIELD_CHANGE.

    " this has to be redefined.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_DYNPRO->PAI_EXIT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM                       TYPE        SYUCOMM(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI_EXIT.


  try.
      pai_user_command( iv_ucomm ).

    catch cx_static_check.
      show_error( ).
  endtry.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_DYNPRO->PAI_FIELD_CHANGE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_FIELDNAME                   TYPE        DFIES-FIELDNAME
* | [--->] IV_SOURCE                      TYPE        ANY
* | [--->] IV_DESTIN                      TYPE        ANY
* | [--->] I_DATA                         TYPE        ANY
* | [!CX!] CX_STATIC_CHECK
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI_FIELD_CHANGE.

    " this has to be redefined

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Private Method ZCL_MVCFW_CON_DYNPRO->PAI_FIELD_CHANGES
* +-------------------------------------------------------------------------------------------------+
* | [--->] I_DATA                         TYPE        ANY
* | [!CX!] CX_STATIC_CHECK
* +--------------------------------------------------------------------------------------</SIGNATURE>
method pai_field_changes.


  data ls_field type dfies.

  field-symbols <ls_screen> type any.
  field-symbols <lv_source> type any.
  field-symbols <lv_destin> type any.
  data ls_comp type x030l.

  check mr_screen_data is bound.

  assign mr_screen_data->* to <ls_screen>.
  mv_stop_field_processing = abap_false.
  " find changed fields
  loop at mt_field_list into ls_field.
    assign component ls_field-fieldname of structure i_data to <lv_source>.
    if sy-subrc <> 0.
      exit.
    endif.
    assign component ls_field-fieldname of structure <ls_screen> to <lv_destin>.
    if sy-subrc <> 0.
      exit.
    endif.
    if <lv_source> <> <lv_destin>.
      pai_field_change( iv_fieldname = ls_field-fieldname
                        iv_source = <lv_source>
                        iv_destin = <lv_destin>
                        i_data    = i_data ).
      <lv_destin> = <lv_source>.

    endif.
    if mv_stop_field_processing = abap_true.
      exit.
    endif.
  endloop.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_DYNPRO->PAI_USER_COMMAND
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM                       TYPE        SYUCOMM
* | [!CX!] CX_STATIC_CHECK
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI_USER_COMMAND.

    " this has to be redefined

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_DYNPRO->SHOW_ERROR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method SHOW_ERROR.

    " this has to be redefined

endmethod.
ENDCLASS.
class ZCL_MVCFW_CON_SUBDYN definition
  public
  inheriting from ZCL_MVCFW_CON_DYNPRO
  abstract
  create public .

public section.

  methods PBO
    exporting
      !E_DATA type ANY .
protected section.
*"* protected components of class ZCL_MVCFW_CON_SUBDYN
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_MVCFW_CON_SUBDYN
*"* do not include other source files here!!!
ENDCLASS.



CLASS ZCL_MVCFW_CON_SUBDYN IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_SUBDYN->PBO
* +-------------------------------------------------------------------------------------------------+
* | [<---] E_DATA                         TYPE        ANY
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PBO.



endmethod.
ENDCLASS.
class ZCL_MVCFW_CON_CFW definition
  public
  abstract
  create public .

public section.

  methods CONSTRUCTOR
    importing
      !IO_CONTAINER type ref to CL_GUI_CONTAINER optional .
  methods GET_CONTAINER
    returning
      value(RO_RES) type ref to CL_GUI_CONTAINER .
  methods REFRESH
    raising
      ZCX_MVCFW_ERROR .
  methods CHECK_CHANGED_DATA
    raising
      zcx_mvcfw_error .
  methods HIDE .
  methods UNHIDE .
  methods FREE .
protected section.

  data MR_STRUC type ref to DATA .
*"* protected components of class ZCL_MVCFW_CON_CFW
*"* do not include other source files here!!!
  data MO_CONTAINER type ref to CL_GUI_CONTAINER .
private section.
*"* private components of class ZCL_MVCFW_CON_CFW
*"* do not include other source files here!!!
ENDCLASS.



CLASS ZCL_MVCFW_CON_CFW IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->CHECK_CHANGED_DATA
* +-------------------------------------------------------------------------------------------------+
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CHECK_CHANGED_DATA.

    " must be redefined

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_CONTAINER                   TYPE REF TO CL_GUI_CONTAINER(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.
  mo_container = io_container.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->FREE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method FREE.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->GET_CONTAINER
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RO_RES                         TYPE REF TO CL_GUI_CONTAINER
* +--------------------------------------------------------------------------------------</SIGNATURE>
method GET_CONTAINER.

  ro_res = mo_container.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->HIDE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method HIDE.
  mo_container->set_visible( abap_false ).
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->REFRESH
* +-------------------------------------------------------------------------------------------------+
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
method REFRESH.

    " must be redefined

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_CFW->UNHIDE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method UNHIDE.
  mo_container->set_visible( abap_true ).
endmethod.
ENDCLASS.
class ZCL_MVCFW_CON_ALV definition
  public
  inheriting from ZCL_mvcfw_CON_CFW
  abstract
  create public .

public section.

*"* public components of class ZCL_MVCFW_CON_ALV
*"* do not include other source files here!!!
  methods CONSTRUCTOR
    importing
      !IO_CONTAINER type ref to CL_GUI_CONTAINER
      !IV_STRUCTURE_NAME type TABNAME optional
      !IS_STRUCTURE type ANY optional
    raising
      ZCX_mvcfw_ERROR .
  methods REFRESH_TABLE
    exporting
      !EV_FIRST_REFRESH type ABAP_BOOL .
  methods INIT_ALV
    raising
      ZCX_mvcfw_ERROR .
  methods GET_SELECTED_ROWS
    exporting
      !ET_TAB type STANDARD TABLE .
protected section.
*"* protected components of class ZCL_MVCFW_CON_ALV
*"* do not include other source files here!!!

  data MT_EXCPT_QINF type LVC_T_QINF .
  data MT_SORT type LVC_T_SORT .
  data MO_ALV type ref to CL_GUI_ALV_GRID .
  data MR_TABLE type ref to DATA .
  data MV_STRUCTURE type TABNAME .
  data MT_FCAT type LVC_T_FCAT .
  data MV_SAVE type CHAR1 .
  data MV_FIRST_REFRESH type ABAP_BOOL value ABAP_TRUE. "#EC NOTEXT .
  data MS_LAYOUT type LVC_S_LAYO .
  data MS_VARI type DISVARIANT .
  data MT_EXCLUDE type UI_FUNCTIONS .

  methods ON_DATA_CHANGED
    for event DATA_CHANGED of CL_GUI_ALV_GRID
    importing
      !ER_DATA_CHANGED
      !E_ONF4
      !E_ONF4_BEFORE
      !E_ONF4_AFTER
      !E_UCOMM .
  methods ON_DATA_CHANGED_LATE
    for event DATA_CHANGED_FINISHED of CL_GUI_ALV_GRID
    importing
      !E_MODIFIED
      !ET_GOOD_CELLS .
  methods PREPARE_EXCPT_QINF .
  methods PREPARE_SORT
    exporting
      !ET_TAB type LVC_T_SORT .
  methods ON_BUTTON_CLICK
    for event BUTTON_CLICK of CL_GUI_ALV_GRID
    importing
      !ES_COL_ID
      !ES_ROW_NO .
  methods ON_DOUBLE_CLICK
    for event DOUBLE_CLICK of CL_GUI_ALV_GRID
    importing
      !E_ROW
      !E_COLUMN
      !ES_ROW_NO .
  methods ON_HOTSPOT_CLICK
    for event HOTSPOT_CLICK of CL_GUI_ALV_GRID
    importing
      !E_ROW_ID
      !E_COLUMN_ID
      !ES_ROW_NO .
  methods ON_TOOLBAR
    for event TOOLBAR of CL_GUI_ALV_GRID
    importing
      !E_OBJECT
      !E_INTERACTIVE .
  methods ON_UCOMM
    for event USER_COMMAND of CL_GUI_ALV_GRID
    importing
      !E_UCOMM .
  methods SET_STRUCTURE .
  methods PREPARE_LAYOUT
    returning
      value(RS_RES) type LVC_S_LAYO .
  methods PREPARE_FIELDCAT
    exporting
      !ET_TAB type LVC_T_FCAT .
  methods PREPARE_VARIANT
    returning
      value(RS_RES) type DISVARIANT .
  methods PREPARE_EXCLUDE
    exporting
      !ET_TAB type UI_FUNCTIONS .
  methods SHOW_TABLE .
  methods PREPARE_PRINT
    returning
      value(RS_RES) type LVC_S_PRNT .
  methods ALV_INPUT_ERROR
    importing
      !IO_DATA_CHANGED type ref to CL_ALV_CHANGED_DATA_PROTOCOL
      !IS_MODCELL type LVC_S_MODI .
private section.
*"* private components of class ZCL_MVCFW_CON_ALV
*"* do not include other source files here!!!

  data MS_PRINT type LVC_S_PRNT .
ENDCLASS.



CLASS ZCL_MVCFW_CON_ALV IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ALV_INPUT_ERROR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_DATA_CHANGED                TYPE REF TO CL_ALV_CHANGED_DATA_PROTOCOL
* | [--->] IS_MODCELL                     TYPE        LVC_S_MODI
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ALV_INPUT_ERROR.
  call method io_data_changed->add_protocol_entry
    exporting
      i_msgid     = sy-msgid
      i_msgty     = sy-msgty
      i_msgno     = sy-msgno
      i_msgv1     = sy-msgv1
      i_msgv2     = sy-msgv2
      i_msgv3     = sy-msgv3
      i_msgv4     = sy-msgv4
      i_fieldname = is_modcell-fieldname
      i_row_id    = is_modcell-row_id.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_ALV->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_CONTAINER                   TYPE REF TO CL_GUI_CONTAINER
* | [--->] IV_STRUCTURE_NAME              TYPE        TABNAME(optional)
* | [--->] IS_STRUCTURE                   TYPE        ANY(optional)
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.
  super->constructor( io_container ).
  mv_structure = iv_structure_name.
  if is_structure is supplied.
    create data mr_struc like is_structure.
    clear mv_structure.
  endif.
  init_alv( ).
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_ALV->GET_SELECTED_ROWS
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_TAB                         TYPE        STANDARD TABLE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method GET_SELECTED_ROWS.

  data: lt_rows                     type lvc_t_row,
        ls_row                      type lvc_s_row.

  FIELD-SYMBOLS: <ls_line>          type any,
                 <lt_table>         type STANDARD TABLE.

  assign mr_table->* to <lt_table>.

  mo_alv->get_selected_rows(
    importing
      et_index_rows     = lt_rows    " Numeric IDs of Selected Rows
  ).

  loop at lt_rows into ls_row.
    read table <lt_table> ASSIGNING <ls_line> index ls_row-index.
    if sy-subrc = 0.
      append <ls_line> to et_tab.
    endif.
  endloop.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_ALV->INIT_ALV
* +-------------------------------------------------------------------------------------------------+
* | [!CX!] ZCX_MVCFW_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
method INIT_ALV.
  if mo_alv is not bound.
    create object mo_alv
      exporting
        i_parent = mo_container.    " Parent Container


    set handler on_toolbar for mo_alv.
    set handler on_ucomm for mo_alv.
    set handler on_double_click for mo_alv.
    set handler on_hotspot_click for mo_alv.
    set handler on_button_click for mo_alv.
    set handler on_data_changed for mo_alv.
    set handler on_data_changed_late for mo_alv.

    if mv_structure is not initial.
      create data mr_table type table of (mv_structure).
    elseif mr_struc is not initial.
      assign mr_struc->* to field-symbol(<ls_struc>).
      create data mr_table like table of <ls_struc>.
    else.
      message e000(0k) with 'cannot init ALV without given structure' into sy-msgli.
      raise exception type zcx_mvcfw_error
        exporting
          textid   = value scx_t100key( msgid = sy-msgid msgno = sy-msgno attr1 = 'MV_MESSAGE_V1' )
          mv_message_v1 = sy-msgv1
*          previous =
      .
    endif.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_BUTTON_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] ES_COL_ID                      LIKE
* | [--->] ES_ROW_NO                      LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_BUTTON_CLICK.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_DATA_CHANGED
* +-------------------------------------------------------------------------------------------------+
* | [--->] ER_DATA_CHANGED                LIKE
* | [--->] E_ONF4                         LIKE
* | [--->] E_ONF4_BEFORE                  LIKE
* | [--->] E_ONF4_AFTER                   LIKE
* | [--->] E_UCOMM                        LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_DATA_CHANGED.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_DATA_CHANGED_LATE
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_MODIFIED                     LIKE
* | [--->] ET_GOOD_CELLS                  LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_DATA_CHANGED_LATE.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_DOUBLE_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_ROW                          LIKE
* | [--->] E_COLUMN                       LIKE
* | [--->] ES_ROW_NO                      LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_DOUBLE_CLICK.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_HOTSPOT_CLICK
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_ROW_ID                       LIKE
* | [--->] E_COLUMN_ID                    LIKE
* | [--->] ES_ROW_NO                      LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_HOTSPOT_CLICK.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_TOOLBAR
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_OBJECT                       LIKE
* | [--->] E_INTERACTIVE                  LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_TOOLBAR.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->ON_UCOMM
* +-------------------------------------------------------------------------------------------------+
* | [--->] E_UCOMM                        LIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
method ON_UCOMM.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_EXCLUDE
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_TAB                         TYPE        UI_FUNCTIONS
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_EXCLUDE.
    " has to be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_EXCPT_QINF
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_EXCPT_QINF.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_FIELDCAT
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_TAB                         TYPE        LVC_T_FCAT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_FIELDCAT.

  if mv_structure is not initial.

    call function 'LVC_FIELDCATALOG_MERGE'
       exporting
         i_structure_name       = mv_structure    " Structure name (structure, table, view)
      changing
        ct_fieldcat            = mt_fcat    " Field Catalog with Field Descriptions
      .
  else.
    assign mr_struc->* to field-symbol(<ls_struc>).
    data(lo_strucd) = cast cl_abap_structdescr(
      CL_ABAP_TYPEDESCR=>describe_by_data( <ls_struc> ) ).

    loop at lo_strucd->components assigning field-symbol(<ls_comp>).
      assign component <ls_comp>-name of structure <ls_struc> to field-symbol(<lv_col>).
      data(lo_descr) = cast cl_abap_elemdescr(
                            cl_abap_typedescr=>describe_by_data( <lv_col> ) ).
      data(ls_dfies) = lo_descr->get_ddic_field( ).
      append initial line to et_tab assigning field-symbol(<ls_fcat>).
      <ls_fcat>-fieldname = <ls_comp>-name.
      <ls_fcat>-rollname = ls_dfies-rollname.
    endloop.
  endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_LAYOUT
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RS_RES                         TYPE        LVC_S_LAYO
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_LAYOUT.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_PRINT
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RS_RES                         TYPE        LVC_S_PRNT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_PRINT.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_SORT
* +-------------------------------------------------------------------------------------------------+
* | [<---] ET_TAB                         TYPE        LVC_T_SORT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_SORT.

  " must be redefined, if needed
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->PREPARE_VARIANT
* +-------------------------------------------------------------------------------------------------+
* | [<-()] RS_RES                         TYPE        DISVARIANT
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PREPARE_VARIANT.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_ALV->REFRESH_TABLE
* +-------------------------------------------------------------------------------------------------+
* | [<---] EV_FIRST_REFRESH               TYPE        ABAP_BOOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
method REFRESH_TABLE.
  data: ls_stbl                     type lvc_s_stbl.

  if mv_first_refresh = abap_true.
    show_table( ).
    mv_first_refresh = abap_false.
    ev_first_refresh = abap_true.
  else.
    ls_stbl-row = abap_true.
    ls_stbl-col = abap_true.
    mo_alv->refresh_table_display( is_stable = ls_stbl ).
    ev_first_refresh = abap_false.
  endif.

endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->SET_STRUCTURE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method SET_STRUCTURE.
  " must be redefined
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZCL_MVCFW_CON_ALV->SHOW_TABLE
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
method SHOW_TABLE.
  field-symbols <lt_table> type standard table.
  assign mr_table->* to <lt_table>.

  check mo_alv is bound.

  get_container( )->set_visible( abap_true ).
  ms_layout = prepare_layout( ).
  ms_vari = prepare_variant( ).
  prepare_fieldcat( importing et_tab = mt_fcat ).
  prepare_exclude( importing et_tab = mt_exclude ).
  prepare_sort( IMPORTING et_tab = mt_sort ).
  prepare_excpt_qinf( ).

  " maybe mv_save has been set before by a redefinition
  if mv_save = space.
    mv_save = 'A'.
  endif.

  mo_alv->set_table_for_first_display(
    exporting
*        i_buffer_active               =     " Pufferung aktiv
*         i_bypassing_buffer            = abap_true    " Puffer ausschalten
*        i_consistency_check           =     " Starte Konsistenzverprobung für Schnittstellefehlererkennung
*        i_structure_name              =     " Strukturname der internen Ausgabetabelle
      is_variant                    = ms_vari    " Anzeigevariante
      i_save                        = mv_save    " Anzeigevariante sichern
*        i_default                     = 'X'    " Defaultanzeigevariante
       is_layout                     = ms_layout    " Layout
       is_print                      = ms_print    " Drucksteuerung
*        it_special_groups             =     " Feldgruppen
       it_toolbar_excluding          = mt_exclude     " excludierte Toolbarstandardfunktionen
*        it_hyperlink                  =     " Hyperlinks
*        it_alv_graphics               =     " Tabelle von der Struktur DTC_S_TC
        it_except_qinfo               = mt_excpt_qinf    " Tabelle für die Exception Quickinfo
*        ir_salv_adapter               =     " Interface ALV Adapter
    changing
      it_outtab                     = <lt_table>   " Ausgabetabelle
      it_fieldcatalog               = mt_fcat    " Feldkatalog
      it_sort                       = mt_sort    " Sortierkriterien

*        it_filter                     =     " Filterkriterien
  ).
endmethod.
ENDCLASS.
class ZCX_MVCFW_ERROR definition
  public
  inheriting from CX_STATIC_CHECK
  create public .

public section.

  interfaces IF_T100_MESSAGE .

  data MV_MESSAGE_V1 type SYMSGV .
  data MV_MESSAGE_V2 type SYMSGV .
  data MV_MESSAGE_V3 type SYMSGV .
  data MV_MESSAGE_V4 type SYMSGV .

  methods CONSTRUCTOR
    importing
      !TEXTID like IF_T100_MESSAGE=>T100KEY optional
      !PREVIOUS like PREVIOUS optional
      !MV_MESSAGE_V1 type SYMSGV optional
      !MV_MESSAGE_V2 type SYMSGV optional
      !MV_MESSAGE_V3 type SYMSGV optional
      !MV_MESSAGE_V4 type SYMSGV optional .
*&---------------------------------------------------------------------*
*& Report  Zmvcfw_DEMO_CONTROL
*& Demo for the use of the MVC framework in Zmvcfw with two ALV controls
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*

report  zp_mvcfw_alv_demo.

*----------------------------------------------------------------------*
*       CLASS lcl_model DEFINITION
*----------------------------------------------------------------------*
* The model class can also be public
*----------------------------------------------------------------------*
class lcl_model definition.

  public section.
    methods:
      constructor,
      get_log
        returning value(ro_res) type ref to if_reca_message_list,
      set_carrid
        importing iv_in type scarr-carrid,
      get_scarr
        returning value(rs_res) type scarr,
      get_spfli
        returning value(rs_res) type spfli,
      get_spfli_tab
        exporting et_tab type standard table,
      get_sflight_tab
        exporting et_tab type standard table,
      read_scarr
        raising
          zcx_mvcfw_error,
      read_sflights
        importing
          is_line type spfli
        raising
          zcx_mvcfw_error.

  private section.
    data: ms_scarr   type scarr,
          ms_spfli   type spfli,
          mt_spfli   type standard table of spfli
                                         with default key,
          mt_sflight type standard table of sflight
                                         with default key,
          mo_log     type ref to if_reca_message_list.

endclass.                    "lcl_model DEFINITION
*----------------------------------------------------------------------*
*       CLASS lcl_con_main DEFINITION
*----------------------------------------------------------------------*
* The main controller handles the overall program flow
*----------------------------------------------------------------------*
class lcl_con_main definition inheriting from zcl_mvcfw_con_main.

  public section.
    methods:
      " used by PBO of the subdynpro to get the adequate controller
      " this is a singleton, but 'create private' is not possible
      " because of the inheritance mechanism
      " the constructor will be called by zcl_mvcfw_con_main=>get_instance
      " the correct program name is passed automatically
      constructor
        importing
          iv_program type syrepid,
      " called by dynpro 0001, also for exit commands!
      pai_main
        importing
          iv_ucomm type syucomm,
      " method to show table spfli using an alv controller in a docking
      " at the bottom
      show_schedules
        raising zcx_mvcfw_error,
      " show flights for a schedule in a docking at right
      show_sflights
        raising zcx_mvcfw_error.


  protected section.
    methods:
      create_con_dynpro redefinition,
      create_one_controller redefinition.
  private section.
    " constants all controller types
    constants: cv_spfli    type char32 value 'LCL_CON_ALV_SPFLI',
               cv_sflight  type char32 value 'LCL_CON_ALV_SFLIGHT',
               cv_dyn_main type char32 value 'LCL_CON_DYNPRO_0100'.

    " the model will be created in constructor
    data: mo_model                  type ref to lcl_model.

endclass.                    "lcl_con_main DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_con_dynpro_0100 DEFINITION
*----------------------------------------------------------------------*
* Sub-dynpro controller
*----------------------------------------------------------------------*
class lcl_con_dynpro_0100 definition inheriting from zcl_mvcfw_con_subdyn.

  public section.
    methods:
      " add parameer io_model in addition to the strucure name
      constructor
        importing iv_struc_name type c default 'SCARR'
                  io_model      type ref to lcl_model,
      " used for filling the dynpro fields from model data
      pbo redefinition.

  protected section.
    methods:
      " react to single field changes
      pai_field_change redefinition,
      " process the user command
      pai_user_command redefinition.

  private section.
    data: mo_model type ref to lcl_model,
          mo_main  type ref to lcl_con_main.

endclass.                    "lcl_con_dynpro_0100 DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_con_alv_spfli DEFINITION
*----------------------------------------------------------------------*
* Controller class for the ALV at bottom
*----------------------------------------------------------------------*
class lcl_con_alv_spfli definition inheriting from zcl_mvcfw_con_alv.

  public section.
    methods:
      " refresh gets the data from the model and refreshes the display
      refresh redefinition,
      constructor
        importing
                  io_container type ref to cl_gui_container
                  io_model     type ref to lcl_model
        raising   cx_static_check.

  protected section.
    methods:
      prepare_layout redefinition,
      on_double_click redefinition,
      on_toolbar redefinition,
      on_ucomm redefinition.


  private section.
    data: mo_model type ref to lcl_model,
          mo_main  type ref to lcl_con_main.

endclass.                    "lcl_con_alv_spfli DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_con_alv_sflight DEFINITION
*----------------------------------------------------------------------*
* Controller class for the ALV at right
*----------------------------------------------------------------------*
class lcl_con_alv_sflight definition inheriting from zcl_mvcfw_con_alv.

  public section.
    methods:
      refresh redefinition,
      constructor
        importing
                  io_container type ref to cl_gui_container
                  io_model     type ref to lcl_model
        raising   cx_static_check.

  protected section.
    methods:
      prepare_layout redefinition,
      on_double_click redefinition,
      on_toolbar redefinition,
      on_ucomm redefinition.


  private section.
    data: mo_model type ref to lcl_model,
          mo_main  type ref to lcl_con_main.

endclass.                    "lcl_con_alv_spfli DEFINITION

" use tables for all structures on dynpros
tables scarr.
" these variables are mandatory
data: gv_subdyn  type sydynnr,
      gv_okcode  type syucomm,
      go_main    type ref to lcl_con_main,
      go_dyn_sub type ref to zcl_mvcfw_con_subdyn.

start-of-selection.
  " This report can be run directly.
  " as an  alternative, create a dialogue transaction for the screen
  call screen 1.

*----------------------------------------------------------------------*
*       CLASS lcl_Model IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
class lcl_model implementation.

  method constructor.
    mo_log = cf_reca_message_list=>create( ).
  endmethod.                    "constructor

  method get_log.
    ro_res = mo_log.
  endmethod.                    "get_log

  method set_carrid.
    ms_scarr-carrid = iv_in.
  endmethod.                    "set_carrid

  method get_scarr.
    rs_res = ms_scarr.
  endmethod.                    "get_spfli

  method get_spfli.
    rs_res = ms_spfli.
  endmethod.                    "get_spfli

  method get_spfli_tab.
    et_tab = mt_spfli.
  endmethod.                    "get_spfli_tab

  method get_sflight_tab.
    et_tab = mt_sflight.
  endmethod.                    "get_sflight_tab

  method read_scarr.
    clear mt_spfli.
    select single * from scarr
      into ms_scarr
      where carrid = ms_scarr-carrid.
    if sy-subrc <> 0.
      message e000(0k) with 'no data found' into sy-msgli.
      RAISE EXCEPTION type zcx_mvcfw_error EXPORTING
        textid = value scx_t100key( msgid = sy-msgid msgno = sy-msgno attr1 = 'MV_MESSAGE_V1' )
        mv_message_v1 = sy-msgv1.
    endif.
    select * from spfli
      into table mt_spfli
      where carrid = ms_scarr-carrid.
  endmethod.                    "read_spfli

  method read_sflights.
    clear mt_sflight.
    select * from sflight
      into table mt_sflight
      where carrid = ms_scarr-carrid and
            connid = is_line-connid.
    ms_spfli = is_line.
  endmethod.                    "read_sflights
endclass.                    "lcl_Model IMPLEMENTATION
*----------------------------------------------------------------------*
*       CLASS lcl_con_main IMPLEMENTATION
*----------------------------------------------------------------------*
* Main controller
*----------------------------------------------------------------------*
class lcl_con_main implementation.

  method constructor.
    " 1. pass the actual program name to the super-constructor
    " 2. create the model
    " 3. set the initial subdynpro
    data: lv_repid                  type syrepid.

    lv_repid = sy-repid.
    super->constructor( lv_repid ).
    create object mo_model.
    set_subdynpro(
      exporting
         iv_dynnr      = '0100'    " IV_DYNNR
         iv_gui_status = 'MAIN'     " IV_GUI_STATUS
         iv_titlebar   = 'MAIN'
    ).

  endmethod.                    "constructor

  method pai_main.
    " process dynpro-independant functions
    case iv_ucomm.
      when 'EXIT' or 'BACK' or 'CANC'.
        leave program.
    endcase.
  endmethod.                    "pai_main

  method create_con_dynpro.
    " a new controller is needed
    case sy-dynnr.
      when '0100'.
        create object ro_res
          type lcl_con_dynpro_0100
          exporting
            io_model = mo_model.
    endcase.

  endmethod.                    "get_con_dynpro

  method create_one_controller.
    " this is called by GET_CON, if it is called for the first time for a type
    " in further calls, GET_CON returns the object created at the first call
    " to obtain this, ZCL_mvcfw_CON_MAIN has a table with all active controllers
    " here you decide, where a screen control is to be displayed.
    " 1. Determine which control is to be created (iv_type)
    " 2. Create the container for the control
    " 3. Create the control giving the container and the model
    data: lo_docking                type ref to cl_gui_docking_container.

    case iv_type.
      when cv_spfli.
        create object lo_docking
          exporting
            side      = cl_gui_docking_container=>dock_at_bottom   " Side to Which Control is Docked
            extension = 100.    " Control Extension
        create object ro_res
          type (iv_type)
          exporting
            io_container = lo_docking
            io_model     = mo_model.
      when cv_sflight.
        create object lo_docking
          exporting
            side      = cl_gui_docking_container=>dock_at_right   " Side to Which Control is Docked
            extension = 500.    " Control Extension
        create object ro_res
          type (iv_type)
          exporting
            io_container = lo_docking
            io_model     = mo_model.
    endcase.

  endmethod.                    "create_one_controller

  method show_schedules.
    " show the schedules. Calling GET_CON the first time will create the control
    get_con( cv_spfli  )->refresh( ).
    " maybe the container is not visible. This will set it visible
    get_con( cv_spfli  )->unhide( ).

  endmethod.                    "show_schedules

  method show_sflights.

    get_con( cv_sflight  )->refresh( ).
    get_con( cv_sflight  )->unhide( ).

  endmethod.                    "show_sflights

endclass.                    "lcl_con_main IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_con_dynpro_0100 IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
class lcl_con_dynpro_0100 implementation.

  method constructor.
    " 1. call the general constructor with the structure name
    " 2. set the model object
    super->constructor( iv_struc_name ).
    mo_model = io_model.
    mo_main ?= lcl_con_main=>get_instance( ).
  endmethod.                    "constructor

  method pai_field_change.
    " --> in: iv_fieldname
    " --> in: iv_source (generic)
    case iv_fieldname.
      when 'CARRID'.
        " pass the data to the model
        mo_model->set_carrid( iv_source ).
    endcase.

  endmethod.                    "pai_field_change

  method pbo.
    " get the dynpro fields from the model
    e_data = mo_model->get_scarr( ).

  endmethod.                    "pbo

  method pai_user_command.
    " process dynpro dependant functions
    try.
        case iv_ucomm.
          when 'SHOW'.
            mo_model->read_scarr( ).
            mo_main->show_schedules( ).
        endcase.
      catch zcx_mvcfw_error into data(lo_err).
        message lo_err type 'S' display like 'E'.
    endtry.

  endmethod.                    "pai_user_command
endclass.                    "lcl_con_dynpro_0100 IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_con_alv_spfli IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
class lcl_con_alv_spfli implementation.

  method constructor.
    " The constructor MUST always contain:
    " 1. call of super constructor
    " set model
    " set main controller
    super->constructor(
      io_container = io_container
      iv_structure_name = 'SPFLI' ).

    " it is recommended to keep the model and the main controller in variables
    mo_model = io_model.
    mo_main ?= lcl_con_main=>get_instance( ).

  endmethod.                    "constructor


  method prepare_layout.
    data: ls_scarr                  type scarr.

    ls_scarr = mo_model->get_scarr( ).
    " rs_res is of type lvc_s_layo. You can set all its values herer
    rs_res-cwidth_opt = abap_true.
    rs_res-grid_title = 'Schedules for' && | | && ls_scarr-carrid && | | &&
                        'Double click for details'.
  endmethod.                    "prepare_layout

  method on_double_click.
    " this is a standard double click call from cl_gui_alv_grid

    field-symbols: <lt_table>       type standard table.
    data ls_line type spfli.

    try.
        assign mr_table->* to <lt_table>.

        read table <lt_table> into ls_line index e_row-index.
        if sy-subrc = 0.
          mo_model->read_sflights( ls_line ).
          mo_main->show_sflights( ).
        endif.
      catch zcx_mvcfw_error into data(lo_err).
        message lo_err type 'S' display like 'E'.
    endtry.
  endmethod.                    "on_double_click

  method refresh.
    " redefined. Here tha table is filled with data from the model

    field-symbols: <lt_table>       type standard table.
    data: ls_layout                 type lvc_s_layo.

    assign mr_table->* to <lt_table>.

    mo_model->get_spfli_tab( importing et_tab = <lt_table> ).
    " refresh the grid title, therefore set new layout values
    ls_layout = prepare_layout( ).

    mo_alv->set_frontend_layout( ls_layout ).
    " note that the first call of this method will call "set_table_for_first_display"
    refresh_table( ).
  endmethod.                    "refresh

  method on_toolbar.
    " we provide a "close" button to be able to hide the container
    data: ls_toolbar  type stb_button.

    clear ls_toolbar.
    ls_toolbar-butn_type = '3'.
    append ls_toolbar to e_object->mt_toolbar.

    clear ls_toolbar.
    move 'CLOSE' to ls_toolbar-function.
    move 'Close displayr' to ls_toolbar-quickinfo.
    move icon_close to ls_toolbar-icon.
    move ' ' to ls_toolbar-disabled.
    append ls_toolbar to e_object->mt_toolbar.


  endmethod.                    "on_toolbar

  method on_ucomm.
    case e_ucomm.
      when 'CLOSE'.
        " hide the container
        hide( ).
    endcase.
  endmethod.                    "on_ucomm
endclass.                    "lcl_con_alv_spfli IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_con_alv_sflight IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
class lcl_con_alv_sflight implementation.

  method constructor.
    super->constructor(
      io_container = io_container
      iv_structure_name = 'SFLIGHT' ).

    mo_model = io_model.
    mo_main ?= lcl_con_main=>get_instance( ).
  endmethod.                    "constructor

  method prepare_layout.
    data: ls_spfli                  type spfli.

    ls_spfli = mo_model->get_spfli( ).
    " rs_res is of type lvc_s_layo. You can set all its values herer
    rs_res-cwidth_opt = abap_true.
    rs_res-grid_title = 'Flights for' && | | && ls_spfli-carrid && | | &&
                        ls_spfli-connid.
  endmethod.                    "prepare_layout

  method on_double_click.

  endmethod.                    "on_double_click

  method refresh.

    field-symbols: <lt_table>       type standard table.
    data: ls_layout                 type lvc_s_layo.

    assign mr_table->* to <lt_table>.

    mo_model->get_sflight_tab( importing et_tab = <lt_table> ).
    " refresh the grid title, therefore set new layout values
    ls_layout = prepare_layout( ).

    mo_alv->set_frontend_layout( ls_layout ).

    refresh_table( ).

  endmethod.                    "refresh

  method on_toolbar.
    data: ls_toolbar  type stb_button.

    clear ls_toolbar.
    ls_toolbar-butn_type = '3'.
    append ls_toolbar to e_object->mt_toolbar.

    clear ls_toolbar.
    move 'CLOSE' to ls_toolbar-function.
    move 'Close displayr' to ls_toolbar-quickinfo.
    move icon_close to ls_toolbar-icon.
    move ' ' to ls_toolbar-disabled.
    append ls_toolbar to e_object->mt_toolbar.


  endmethod.                    "on_toolbar

  method on_ucomm.
    case e_ucomm.
      when 'CLOSE'.
        hide( ).
    endcase.
  endmethod.                    "on_ucomm
endclass.                    "lcl_con_alv_sflight IMPLEMENTATION

*&---------------------------------------------------------------------*
*&      Module  PBO_0001  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module pbo_0001 output.

  " get the main controller and call the pbo method
  go_main ?= lcl_con_main=>get_instance( ).
  gv_subdyn = go_main->pbo_main( ).

endmodule.                 " PBO_0001  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  PBO_0100  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module pbo_sub output.

  " get the subscreen controller and call the pbo method
  go_dyn_sub ?= go_main->get_con_dynpro( ).
  go_dyn_sub->pbo( importing e_data = scarr ).

endmodule.                 " PBO_0100  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  PAI_0001  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module pai_0001 input.
  " go_main is set in the pbo module!
  go_main->pai_main( gv_okcode ).
  clear gv_okcode.

endmodule.                 " PAI_0001  INPUT
*&---------------------------------------------------------------------*
*&      Module  PAI_0100  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
module pai_sub input.
  " get the subdynpro controller and call the pai method
  go_dyn_sub ?= go_main->get_con_dynpro( ).
  go_dyn_sub->pai( exporting iv_ucomm = gv_okcode
                   changing c_data = scarr ).

endmodule.                 " PAI_0100  INPUT

File content to upload to dynpro 0001:

****************************************************************																																
*   THIS FILE IS GENERATED BY THE SCREEN PAINTER.              *																																
*   NEVER CHANGE IT MANUALLY, PLEASE !                         *																																
****************************************************************																																
%_DYNPRO																																
ZP_MVCFW_ALV_DEMO																																
0001																																
740																																
             40																																
%_HEADER																																
ZP_MVCFW_ALV_DEMO                       0001 0001     27120192 37  0  0 27120  0G E                              20160803180330																																
%_DESCRIPTION																																
Main screen with sub area																																
%_FIELDS																																
SUBSCREEN			120	00	00	00	30	00	  1	  2		  0	  0	  0		 27	B				  1	  1	101									
GV_OKCODE		CHAR	 20	80	10	00	00	00	255	  1	O	  0	  0	  0		  0					  0	  0								____________________	                                       00	
%_FLOWLOGIC																																
																																
process before output.																																
																																
  module pbo_0001.																																
																																
  call subscreen subscreen including sy-repid gv_subdyn.																																
																																
*																																
process after input.																																
  module pai_0001 at exit-command.																																
  call subscreen subscreen.																																
  module pai_0001.																																
%_PARAMS																																
																																

File content to upload in dynpro 0100:

****************************************************************																																
*   THIS FILE IS GENERATED BY THE SCREEN PAINTER.              *																																
*   NEVER CHANGE IT MANUALLY, PLEASE !                         *																																
****************************************************************																																
%_DYNPRO																																
ZP_MVCFW_ALV_DEMO																																
0100																																
740																																
             40																																
%_HEADER																																
ZP_MVCFW_ALV_DEMO                       0100I0100      1 21192 37  0  0 21 83  0G E                              20160803180339																																
%_DESCRIPTION																																
Dialog Programming: Introductary Example																																
%_FIELDS																																
SCARR-CARRID	2	CHAR	 16	30	00	04	30	00	  1	  2		  0	  0	  0		  0					  0	  0								Airline_________	                                                                                                                                                                                                                                                        X	
SCARR-CARRID	C	CHAR	  3	A0	00	80	00	08	  1	 20		  0	  0	  0		  0			CAR		  6	  0								___	X                                      00	
		CHAR	 20	80	10	00	00	00	255	  1	O	  0	  0	  0		  0					  0	  0								____________________		
%_FLOWLOGIC																																
PROCESS BEFORE OUTPUT.																																
  MODULE pbo_sub.																																
*																																
PROCESS AFTER INPUT.																																
  module pai_sub.																																
%_PARAMS																																
																																

Status MAIN:

Title MAIN:

To report this post you need to login first.

16 Comments

You must be Logged on to comment or reply to a post.

  1. Marius Rieg

    Really appreciating this sophisticated design framework. I wanted to give the demo a try, but I’m afraid I can’t find the source subpage you mentioned above anywhere in the SCN. Am I missing something really easy or is the code in the text files everything we need?

    (0) 
    1. Jörg Krause Post author

      I’m really sorry about the wrong info. This subpage thing was part of a prior version of the document. I now corrected the posting.

      To install the classes, just download the demo application. In there, you will find all classes coded local. All you have to do is to create the classes and paste the code in source code mode. See chapter “Demo application” for further details.

      (0) 
      1. Marius Rieg

        No worries, I just wanted to be sure I don’t miss something important here. I’m really excited to try your framework as I’m currently in search of a pratical solution to get some standardization in our application development.

        (0) 
  2. Raghu Govindarajan

    Thanks Jörg for this write up. I am just wondering, did you consider using an oo-transaction instead of a report as your starting point?

    I conceptually like the idea of using the new CL_OS_SYSTEM=>GET_TRANSACTION_MANAGER( ) to control COMMITs and ROLLBACKs. I just wonder how it will work in conjunction with calling classical SAP function modules and BAPIs for data posting.

    (0) 
    1. Jörg Krause Post author

      Hello Raghu,

      This is a question, I poned myself already before I decided to use a report for my applications. After trying out several approaches, using a report as container for my applications was the conclusion. But why?

      In my company, classical sapgui environment is still in heavy use. That’s why the framework is focussed on SAPGUI presentation techniques with dynpros.In a pure OO environment, no dynpro can be used, you always have to create function modules or something similar to host the dynpro screens. I tried for a while the approach of OO transactions with function modules for the dynpros but it turned out a bit messy with all those public classes and function groups you have to create for one application. To simplify this, I decided to do a complete OO oriented development and embed it into a classical report where I can add the dynpros needed. I like the fact, that everything about the application is in one main repository object.

      Of course, sometimes the model is something you want to reuse in other programs. In this case, the model can be transferred easily from the local class to a repository object.

      All the best

      Jörg

      (0) 
      1. Raghu Govindarajan

        Jörg Krause wrote:


        I like the fact, that everything about the application is in one main repository object.

        This is the main reason that drives me to stick with module pool / report type programs. In my little corner of the world (I do SAPConsole / ITSMobile work), I often have 2-4 developers in a single package working on multiple distinct but related objects at the same time.

        I take anything which drives common look and feel – error messages screens (I can’t use status bar messages) for example – and put those in function groups. And all the data access in their own repository classes because they are most often used more than once.

        I make the argument – a loosing one with purists – that the Dynpro is my View – the report / module pool is my Controller and the classes for data access my Model. I will definitely draw on your ZCL_MVCFW_CON_DYNPRO for ideas though.

        Thank you again for being so informative and thoughtful in your approach!

        Raghu

        (1) 
  3. Stefan Mindt

    Hello Jörg
    I also can not see any attachments of your sample coding.
    Can you please advice, how we can see them/get them?
    Thanks a lot.
    Stefan
     

    (0) 
  4. Jörg Krause Post author

    Indeed the file attachments got lost 🙁
    Since I did not find a possibility to upload attachments, I inserted all codings into code blocks.
     

    (0) 
  5. Jacques Nomssi

    Hello Jörg,

    I installed the code in a  NW ABAP 7.5 Dev Edition and generated diagrams using those tools. Note class IF_RECA_MESSAGE_LIST is not available there.

    Class diagram:

    Sequence diagram from a sample execution:

    Do you use a distinct pattern to process a selected subset of the list? I found the iterator to be useful, but I am curious about alternatives where the model data are still encapsulated.

    regards,

    JNN

    (0) 
  6. Cao hongliang

     Hello Jörg,

    It’s a great blog! But I have a problem when using your MVC framework in a dynpro which consists of a main screen 0001 and two sub areas on it—–head and item. How can I get two subscreen controllers in module pbo_0001?

    (0) 
    1. Jörg Krause Post author

      The main screen should always contain only one subscreen area. If you want to use two sub screens, place them on the level 1 sub screen, like this:

      +-----------------Screen 0001------+ 
      |+-----------------Screen 0100 ---+|
      ||+--screen 0101-++--screen 0102-+||
      ||| || |||
      ||| || |||
      ||| || |||
      ||+--------------++--------------+||
      |+--------------------------------+|
      +----------------------------------+

       

      In PBO of 0101 and 0102, you can then get the controller reference as usual.

       

       

       

      (0) 

Leave a Reply