Anda di halaman 1dari 17

Horst Keller and Gisbert Loff

ABAP Objects in Action -


Screen Programming with the Control Framework

In the preceding two issues of the SAP Technical Journal we presented ABAP Objects in a more theoretical
way. After a general introduction to ABAP Objects in Number 3 we discussed the concepts of inheritance,
interfaces and polymorphism in depth in Number 4.

Now you might say: 'That's nice but what can I do with ABAP Objects and does it touch my daily ABAP live at
all?' The answer is definitely 'Yes!' and in this article, we will give you one of several explanations why: We will
show you how to program screens that include controls with ABAP Objects by presenting a demonstration
program with a single screen user interface as shown in Figure 1.

Figure 1 User interface of the demonstration program.

The screen is split in three parts. The upper left part shows a picture of an airplane. This picture has no
function but is purely for decoration purposes. Of course you might change that after reading the article! The
lower left part contains a tree-like structure, where the user can select carriers or flight connections from
SAP's flight model which you know from demonstrations or training. The large area on the right side can
alternatively show the Web site of the selected carrier or detail lists for flight connections. Figure 1 shows the
situation after selecting node 'UA'.

1
In R/3 Release 4.6 or higher you will find a lot of screens that are designed with the control technology, as for
example the object browser of the ABAP Development Workbench. The usage of control technology on
screens is an important part of the Enjoy SAP initiative to enhance the usability of the system for the end
users.

In the following we will give you a short introduction to the Controls Technology and take you then on a
detailed walk through the demonstration program, where you will learn how to use ABAP Objects to design
such enjoyable screens.

Control Technology Overview


The R/3 System communicates with the user via screens on the frontend. In classical ABAP programming,
screens may contain input/output fields, checkboxes, radio buttons, and push buttons to interact with the user.
All user actions that raise the runtime event PAI (Process After Input) and the respective processing on the
application server are connected to a function code that is transported to the application server.

Controls. Controls are independent software components that from Release 4.5 on are shipped with the SAP
GUI. You can place controls on screens instead or besides the classical components. In the moment, SAP
supports ActiveX controls for MS Windows platforms and JavaBeans for the SAP GUI in the Java
environment. Controls have the advantage, that they provide a lot of functionality and can keep a lot of data at
the presentation server without putting weight on the application server, as for example during scrolling and
editing of texts. This means on the other hand, that a frequent data exchange between frontend and
application backend may increase the network load. Therefore, controls are appropriate, when most of the
work can be done at the frontend and exchange with the backend does not occur too often.

Control Frame Work. In order to facilitate programming with controls, from R/3 Release 4.6 on the SAP Basis
system provides the so called Control Framework (CFW). The CFW encapsulates all available controls in
global classes of ABAP Objects. In order to work with controls on your screens, you simply have to create
objects of that global classes, call their methods and react on their events. Since the CFW classes are part of
an inheritance tree, you will find standardized interfaces for most of the common functionality provided by the
controls.

The CFW distinguishes between application controls and container controls. The application controls are the
components you want to use on the screen. Container controls provide a software layer that standardizes all
layout related issues and the implementation of application controls. All application controls must be linked to
a container control while the container control is linked to an area of the screen (see Figure 2).

2
Screen
Docking Container

Custom Control
Custom Container
Application Control
Splitter Container
Application Control

Docking Container
Application Control

Figure 2 Container controls and application controls on screens.

Container Controls. Container controls provide areas on the screen, which can be used for application
controls. Important container controls are encapsulated in the following classes:

• CL_GUI_CUSTOM_CONTAINER: When you create an object of that class, you must link it to a so called
Custom Control on a screen via the IMPORTING parameter CONTAINER_NAME of its constructor. A
Custom Control is simply an area of a screen that you create and name with the Screen Painter. You can
create several Custom Controls within the area of one screen and you can use Custom Controls together
with classical screen elements . Any application control that you link to a custom container will appear
within its screen area.
• CL_GUI_DOCKING_CONTAINER: When you create an object of that class, you must link it to one of the
four edges of a screen. By doing so, you create a new area docked to a screen without using the screen
painter. Any application control that you link to a docking container will appear within that screen area.
• CL_GUI_SPLITTER_CONTAINER: When you create an object of that class, you must link it to an already
existing container control. By doing so, you split the area of the existing control either vertically or
horizontally into two new areas. You can then link application controls to the new areas. You can also nest
splitter controls to create more areas.

Application Controls. After creating objects of container controls, you can create objects of application
controls. You must link each application control to an object of a container control by simply passing the
respective reference to the parameter PARENT of the application control's constructor. Important application
controls and the respective public classes are:

• CL_GUI_ALV_GRID: This control allows you to display interactive lists. ALV stands for ABAP List Viewer
and is going to replace the classical list processing.
• CL_GUI_HTML_VIEWER: This controls allows you to display HTML documents. For example, the new
help viewer of the ABAP keyword documentation uses an HTML control.
• CL_GUI_PICTURE: This control allows you to display arbitrary pictures on a R/3 screen. For example, the
SAP Easy Access uses a picture control as background.
• CL_GUI_SIMPLE_TREE: This control allows you to display and work with a treelike structure. Besides
the simple tree there are also other kinds of trees available. For example, the Object Navigator of the
ABAP Workbench uses a Tree Control.
• CL_GUI_TEXTEDIT: This control implements a fully fledged editor for viewing and maintaining texts. For

3
example, the ABAP Editor uses a Textedit control.

Note that the global classes follow a naming convention: The prefix CL denotes a global class and the prefix
GUI shows that the classes are part of the CFW and inherit from the same superclasses.

Control Methods. You use the methods defined in the control's classes to work with the controls displayed on
the screen. In general, you work with the methods of the application controls, for example to fill text from an
internal table into the text editor of the Textedit control. But sometimes you will call also methods of the CFW.
In order to minimize the network load between backend and frontend, method calls are buffered in a so called
Automation Queue before being sent to the frontend at defined synchronization points, as for example at the
end of PBO processing. You can always force a synchronization point in your program by calling the static
method CL_GUI_CFW=>FLUSH.

Control Events. User actions on controls can trigger events. The events of controls are not the classical
screen events, which trigger the PAI processing at the application server and send a function code, but they
are declared as ABAP Objects events in their global wrapper classes. For performance reasons, an user
action on controls is not automatically passed back to the application server. If you want an event to be
passed back to the application server, you must register it in your program using the special method
SET_REGISTERED_EVENTS that is available in all application controls. You can specify two kinds of event
handling:

• System Events (Default): The event is passed to the application server, but does not trigger the PAI
event (see Figure 3). In order to react on the event, you must register an event handler method in your
ABAP program with the SET HANDLER statement. Then this method is executed on the application
server. The advantage of using this technique is that the event handler method is executed automatically
and there are no conflicts with the classical automatic input checks associated with the screen. The
disadvantage is that the contents of the classical screen fields that might exist besides controls are not
automatically transported to the program. If you work with classical screen fields and you really need to
transport their contents during control event handling, you can call the static method
CL_GUI_CFW=>SET_NEW_OK_CODE to set a function code and trigger the PAI event including a field
transport. After PAI has been processed, the PBO event of the next screen is triggered (see Figure 3).

Control
System Event
Screen

Event
EventHandler
Handler PAI
PAIModule
Module PBO
PBOModule
Module
Method
Method

SET_NEW_OK_CODE
SET_NEW_OK_CODE

ABAP Program

Figure 3 Handling of system events.

4
• Application Events: The event is passed to the application server, and triggers the PAI (see Figure 4). If
you want to handle the event, you must include a method call for CL_GUI_CFW=>DISPATCH in an
appropriate PAI dialog module. The DISPATCH method calls all event handler methods that are defined
and registered with the SET HANDLER statement for that event. After the event handler has been
processed, control returns to the PAI module and PAI processing continues. The advantage is that you
can specify yourself the point at which the event is handled, and the contents of the screen fields are
transported to the application server beforehand. The disadvantage is that this kind of event handling can
lead to conflicts with the automatic input checks on the screen, causing events to be lost.

5
Application Event
Control

Screen

Event
EventHandler
Handler
PAI Method PBO
PBOModule
PAI Module
Module Method Module
DISPATCH
DISPATCH

ABAP Program

Figure 4 Handling of application events.

The two kinds of event handling and the possibility to choose between them reflects the fact that controls are
displayed on classical ABAP screens and that there might be classical screen elements besides controls. The
two kinds of event registration and the above mentioned methods of the CFW enable you to steer the
sequence of data transports between frontend and backend. If you do not use any classical screen
components at all, you can simply work with system events.

Introduction to the Demonstration Program


Our demonstration program is written as simple as possible. Its purpose is to demonstrate the concepts of
programming with GUI controls. Therefore, we omitted any lines of superfluous code and we didn't exploit all
possibilities that are provided by the used controls. After reading the article, you can go on and modify the
demonstration program to learn more. You find the code for the example in
DEMO_ABAP_OBJECTS_SPLIT_SCREEN in R/3 Release 4.6C or higher.

Program structure. Figure 5 shows the processing blocks of the demonstration program.

6
Class
ClassSCREEN_INIT
SCREEN_INIT Class
ClassSCREEN_HANDLER
SCREEN_HANDLER Classical
Classical Processing
ProcessingBlocks
Blocks

Methods
Methods Methods Event
EventBlocks
Blocks
Methods

CONSTRUCTOR
CONSTRUCTOR CONSTRUCTOR LOAD-OF-PROGRAM
LOAD-OF-PROGRAM
CONSTRUCTOR

INIT_SCREEN HANDLE_NODE_
HANDLE_NODE_
INIT_SCREEN DOUBLE_CLICK
DOUBLE_CLICK Dialog
DialogModules
Modules

FILL_TREE
FILL_TREE FILL_HTML MODULE
MODULE......PBO
PBO
FILL_HTML

FILL_PICTURE
FILL_PICTURE FILL_LIST
FILL_LIST MODULE
MODULE......PAI
PAI

DEMO_ABAP_OBJECTS_SPLIT_SCREEN
Figure 5 Structure of the demonstration program.

The program contains two local classes, SCREEN_INIT and SCREEN_HANDLER, which are used to create
and fill the controls and to react on the user's input. Since controls are displayed on classical ABAP screens,
we need a small classical framework to call a carrier screen for our controls. We use the event block LOAD-
OF-PROGRAM and two dialog modules for that purpose.

Listing 1 shows the respective coding structure of the program.

PROGRAM demo_abap_objects_split_screen.

* Classes *****************************************************

CLASS screen_init DEFINITION CREATE PRIVATE.


...
ENDCLASS.

CLASS screen_handler DEFINITION.


...
ENDCLASS.

CLASS screen_init IMPLEMENTATION.


...
ENDCLASS.

CLASS screen_handler IMPLEMENTATION.


...
ENDCLASS.

* Classical processing blocks **********************************

LOAD-OF-PROGRAM.
...

MODULE status_0100 OUTPUT.


...
ENDMODULE.

MODULE cancel INPUT.


...

7
ENDMODULE.

Listing 1 Layout of the demonstration program.

We have chosen the program type 1 (executable) for our demonstration program. Note that we could have
taken also one of the other program types that support screens, namely a module pool or a function pool.
Choosing an executable just simplifies the program execution, because you can start it directly from the ABAP
Editor.

The program does not contain any global data declarations and it does not make use of the classical reporting
events as for example START_OF_SELECTION. It is simply a container for our two local classes and the
three processing blocks of the classical screen framework.

The program at runtime. Figure 6 shows which objects the program uses during screen display and the
references between these objects.

Screen with Controls

CFW

CL_GUI_SPLITTER_CONTAINER ABAP Program

SCREEN_HANDLER

CL_GUI_SIMPLE_TREE

CL_GUI_SPLITTER_CONTAINER CL_GUI_HTML_VIEWER

CL_GUI_PICTURE CL_GUI_ALV_GRID

Figure 6 Runtime objects of the demonstration program.

During screen display, there is no instance of the local class SCREEN_INIT, because there is no global
reference variable in the program which can point to such an instance. An object of SCREEN_INIT will be
created temporarily during each PBO processing of the screen, where it is used as a factory to create the
control objects from the global classes CL_GUI_SPLITTER_CONTAINER, CL_GUI_PICTURE, and

8
CL_GUI_SIMPLE_TREE. After each PBO processing, the object of SCREEN_INIT will be deleted by the
garbage collector. The objects of the global classes are kept alive by pointers from the CFW, because they
are bound to screen areas. An instance of SCREEN_HANDLER is registered as an event handler for events
of object CL_GUI_SIMPLE_TREE. This instance itself holds references to objects of the global classes
CL_GUI_HTML_VIEWER and CL_GUI_ALV_GRID.

The instances of the global classes are linked to controls on the screen via the CFW layer. The two objects of
CL_GUI_SPLITTER_CONTAINER split the screen in three areas. The objects of the application controls are
linked to these areas. The objects of CL_GUI_HTML_VIEWER and CL_GUI_ALV_GRID are both linked to the
same area.

Demonstration Program in Detail


The following sections explain the definitions and the processing blocks of the demonstration program in
detail.

Cassical screen frame work. Listing 2 shows the complete coding of the three classical processing blocks.

LOAD-OF-PROGRAM.
CALL SCREEN 100.

MODULE status_0100 OUTPUT.


SET PF-STATUS 'SCREEN_100'.
SET TITLEBAR 'TIT_100'.
CALL METHOD screen_init=>init_screen.
ENDMODULE.

MODULE cancel INPUT.


LEAVE PROGRAM.
ENDMODULE.

Listing 2 Classical processing blocks of the demonstration program.

The ABAP runtime environment raises the event LOAD_OF_PROGRAM in the moment when the program is
started. The respective processing block does nothing but calling Screen 100. Screen 100 is created with the
Screen Painter. In its screen flow logic, the two dialog modules STATUS_0100 and CANCEL are called, the
latter with the addition AT EXIT-COMMAND. We did not use the Graphical Screen Painter for our example,
because we have no classical elements on our screen.

The PBO module sets an GUI status. Within that status the three function codes BACK, EXIT and CANCEL
are activated with function type E (Exit Command) in the symbol bar. Therefore, the PAI module is called only
when the user wants to leave the program. The most important action during PBO is calling the static method
INIT_SCREEN of class SCREEN_HANDLER. All actual screen handling is encapsulated in the two local
classes.

Local class definitions. Listing 3 shows the declaration parts of the two local classes of the program.

CLASS screen_init DEFINITION CREATE PRIVATE.


PUBLIC SECTION.
CLASS-METHODS init_screen.
METHODS constructor.
PRIVATE SECTION.
DATA: splitter_h TYPE REF TO cl_gui_splitter_container,
splitter_v TYPE REF TO cl_gui_splitter_container,
picture TYPE REF TO cl_gui_picture,
tree TYPE REF TO cl_gui_simple_tree.
METHODS: fill_tree,
fill_picture.
ENDCLASS.

CLASS screen_handler DEFINITION.


PUBLIC SECTION.
METHODS: constructor IMPORTING container

9
TYPE REF TO cl_gui_container,
handle_node_double_click
FOR EVENT node_double_click
OF cl_gui_simple_tree
IMPORTING node_key.
PRIVATE SECTION.
DATA: html_viewer TYPE REF TO cl_gui_html_viewer,
list_viewer TYPE REF TO cl_gui_alv_grid.
METHODS: fill_html IMPORTING carrid TYPE spfli-carrid,
fill_list IMPORTING carrid TYPE spfli-carrid
connid TYPE spfli-connid.
ENDCLASS.

Listing 3 Declaration parts of the two local classes.

Each of the declaration parts contains two visibility sections. Only those class components that must be used
from the outside client are declared in the public sections. All other components are encapsulated in the
private sections. All attributes are reference variables which refer to global classes of the CFW. Each class
has an instance constructor and private methods, that are used to fill the controls with data. Furthermore,
class SCREEN_INIT has a public static method INIT_SCREEN that can be called without creating an object of
that class and class SCREEN_HANDLER has an event handler method HANDLE_NODE_DOUBLE_CLICK
that can handle events of the global class CL_GUI_SIMPLE_TREE. Note the addition CREATE PRIVATE in
the definition of SCREEN_INIT. Objects of that class can be created only within the class itself.

Static method INIT_SCREEN. Listing 4 shows the static method INIT_SCREEN of class SCREEN_INIT.

METHOD init_screen.
DATA screen TYPE REF TO screen_init.
CREATE OBJECT screen.
ENDMETHOD.

Listing 4 The static method INIT_SCREEN of class SCREEN_INIT.

The single purpose of method INIT_SCREEN is to create a temporary object of class SCREEN_INIT. This is
done by using a local reference variable SCREEN. During the CREATE OBJECT statement, the instance
constructor of SCREEN_INIT is executed. Note that after leaving method INIT_SCREEN, the reference
variable SCREEN is deleted. The object is not referenced any more and will be deleted by the next turn of the
garbage collector.

Instance constructor of SCREEN_INIT. Listing 5 shows the instance constructor of class SCREEN_INIT.

METHOD constructor.
DATA: events TYPE cntl_simple_events,
event LIKE LINE OF events,
event_handler TYPE REF TO screen_handler,
container_left TYPE REF TO cl_gui_container,
container_right TYPE REF TO cl_gui_container,
container_top TYPE REF TO cl_gui_container,
container_bottom TYPE REF TO cl_gui_container.

CREATE OBJECT splitter_h


EXPORTING
parent = cl_gui_container=>screen0
rows = 1
columns = 2.

CALL METHOD splitter_h->set_border


EXPORTING border = cl_gui_cfw=>false.

CALL METHOD splitter_h->set_column_mode


EXPORTING mode = splitter_h->mode_absolute.

CALL METHOD splitter_h->set_column_width


EXPORTING id = 1

10
width = 110.

container_left = splitter_h->get_container( row = 1 column = 1 ).


container_right = splitter_h->get_container( row = 1 column = 2 ).

CREATE OBJECT splitter_v


EXPORTING
parent = container_left
rows = 2
columns = 1.

CALL METHOD splitter_v->set_border


EXPORTING border = cl_gui_cfw=>false.

CALL METHOD splitter_v->set_row_mode


EXPORTING mode = splitter_v->mode_absolute.

CALL METHOD splitter_v->set_row_height


EXPORTING id = 1
height = 160.

container_top = splitter_v->get_container( row = 1 column = 1 ).


container_bottom = splitter_v->get_container( row = 2 column = 1 ).

CREATE OBJECT picture


EXPORTING parent = container_top.

CREATE OBJECT tree


EXPORTING parent = container_bottom
node_selection_mode =
cl_gui_simple_tree=>node_sel_mode_single.

CREATE OBJECT event_handler


EXPORTING container = container_right.

event-eventid = cl_gui_simple_tree=>eventid_node_double_click.
event-appl_event = ' '.
APPEND event TO events.
CALL METHOD tree->set_registered_events
EXPORTING events = events.
SET HANDLER event_handler->handle_node_double_click FOR tree.

CALL METHOD: me->fill_picture,


me->fill_tree.
ENDMETHOD.

Listing 5 The instance constructor of class SCREEN_INIT.

The instance constructor is used to create all the container controls on Screen 100 and two of the application
controls. Furthermore it creates an event handler for one of the application controls. Most of the data objects
that are needed for that purpose are declared locally within the constructor. The reference variables of type
CL_GUI_CONTAINER can contain references that point to any container control at the screen.

First, the constructor creates an object of the global class CL_GUI_SPLITTER_CONTAINER using the
reference variable SPLITTER_H. In the CREATE statement, actual parameters are passed to the
IMPORTING-parameters of the global class' constructor. By passing the static attribute SCREEN0 of class
CL_GUI_CFW to the parameter PARENT, we use the entire area of Screen 100 as a Custom Control
implicitly. This is why we didn't use the graphical screen painter for Screen 100. But you could also go and
create a Custom Control on Screen 100 and pass its name instead of SCREEN0. Then, only this area will be
used for displaying the controls.

By filling the remaining IMPORTING-parameters with appropriate values, we split Screen 100 into two
columns. For each column, a new container control is created. References to each new container are stored
in a system table of the CFW. This table is not explicitly visible to the programmer. Nevertheless, it points to
container control objects of the program that are currently linked to a screen and prevents them from being
deleted by the garbage collector, even if it is not referenced in the program itself (see Figure 6). If you want to
remove a control object from the program, you must use its method FREE before initializing all respective

11
reference variables. After setting some attributes of the columns, we read the references to our containers
from the CFW into the local reference variables CONTAINER_LEFT and CONTAINER_RIGHT by functional
calls of method GET_CONTAINER.

After that, we follow the same procedure to split the left column into two rows. Here, we pass the reference in
CONTAINER_LEFT to the constructor of CL_GUI_SPLITTER_CONTAINER and get references of the two
new container objects into the local reference variables CONTAINER_TOP and CONTAINER_BOTTOM. Now
we have already created all container controls that we need and can go on to create our application controls.

With the instance constructor of class SCREEN_INIT, we create the two application controls for the containers
in the left column. As application controls, we create an object of CL_GUI_PICTURE and an object of
CL_GUI_SIMPLE_TREE. We link the objects to container controls by passing the references in
CONTAINER_TOP and CONTAINER_BOTTOM to their constructor's IMPORTING parameter PARENT.

Since we want our program to react on user actions in the Tree Control, we must provide and register an
event handler. To do so, we create an object of our local class SCREEN_HANDLER. The constructor of this
class demands an IMPORTING-parameter of type CL_GUI_CONTAINER and we pass the reference to the
right column's container control. As explained above, we must use the special method
SET_REGISTERED_EVENTS besides the simple SET HANDLER statement in order to register our object of
class SCREEN_HANDLER as an event handler for the Tree Control. The parameters are passed via an
internal table of type CNTL_SIMPLE_EVENTS, which is defined in the ABAP Dictionary. By moving a blank
character (initial value) and not an 'X' to the component APPL_EVENT, we define that the event is handled as
a system event (default) and not as an application event.

Finally, the constructor calls the methods FILL_PICTURE and FILL_TREE to initialize the contents of our
application controls on the screen.

Method FILL_PICTURE. Listing 6 shows the instance method FILL_PICTURE of class SCREEN_INIT.

METHOD fill_picture.
TYPES pict_line(256) TYPE c.
DATA pict_tab TYPE TABLE OF pict_line.
DATA url(255) TYPE c.

IMPORT pict_tab = pict_tab FROM DATABASE abtree(pi) ID 'FLIGHTS'.

CALL FUNCTION 'DP_CREATE_URL'


EXPORTING
type = 'IMAGE'
subtype = 'GIF'
TABLES
data = pict_tab
CHANGING
url = url.

CALL METHOD picture->load_picture_from_url EXPORTING url = url.


CALL METHOD picture->set_display_mode
EXPORTING display_mode = picture->display_mode_fit_center.
ENDMETHOD.

Listing 6 The instance method FILL_PICTURE of class SCREEN_INIT.

The method FILL_PICTURE imports a picture in GIF format from an INDX-type database table ABTREE into a
local internal table PICT_TAB. The function module DP_CREATE_URL creates an URL for that internal table
and passes it to the local variable URL. By passing that URL to method LOAD_PICTURE_FROM_URL of our
picture control object, we send the picture to the control at the screen. The method SET_DISPLAY_MODE
allows us to set the attributes of the picture on the screen.

Instead of working with an internal table, you can also use a local picture file on your presentation server and
pass its name directly to the parameter URL of method LOAD_PICTURE_FROM_URL. Our program has the
advantage of working for all users. The question remains, how one can save pictures in an INDX-type
database table. Listing 7 shows a little helper routine which fulfills that purpose.

12
REPORT picture_save.

PARAMETERS file TYPE rlgrap-filename DEFAULT 'C:\TEMP\.GIF'.


PARAMETERS id(20) TYPE c.

DATA pict_line(256) TYPE c.


DATA pict_tab LIKE TABLE OF pict_line.

CALL FUNCTION 'WS_UPLOAD'


EXPORTING
filename = file
filetype = 'BIN'
TABLES
data_tab = pict_tab.

EXPORT pict_tab = pict_tab TO DATABASE abtree(pi) ID id.

Listing 7 Helper routine to save pictures in a database table.

Provide your favorite picture in a folder as for example C:\TEMP\ of your presentation server and simply run
this little program. The program loads the picture in binary format into an internal table and exports it to an
INDX-type database table (We strongly recommend to create your own INDX-type table instead of using
ABTREE or INDX itself!)

Method FILL_TREE. Listing 8 shows the instance method FILL_TREE of class SCREEN_INIT.

METHOD fill_tree.
DATA: node_table TYPE TABLE OF abdemonode,
node TYPE abdemonode,
spfli_wa TYPE spfli,
spfli_tab TYPE SORTED TABLE OF spfli
WITH UNIQUE KEY carrid connid.

SELECT carrid connid


FROM spfli
INTO CORRESPONDING FIELDS OF TABLE spfli_tab.

node-hidden = ' '.


node-disabled = ' '.
node-isfolder = 'X'.
node-expander = ' '.

LOOP AT spfli_tab INTO spfli_wa.


AT NEW carrid.
node-node_key = spfli_wa-carrid.
CLEAR node-relatkey.
CLEAR node-relatship.
node-text = spfli_wa-carrid.
node-n_image = ' '.
node-exp_image = ' '.
APPEND node TO node_table.
ENDAT.
AT NEW connid.
CONCATENATE spfli_wa-carrid spfli_wa-connid INTO node-node_key.
node-relatkey = spfli_wa-carrid.
node-relatship = cl_gui_simple_tree=>relat_last_child.
node-text = spfli_wa-connid.
node-n_image = '@AV@'.
node-exp_image = '@AV@'.
ENDAT.
APPEND node TO node_table.
ENDLOOP.

CALL METHOD tree->add_nodes


EXPORTING table_structure_name = 'ABDEMONODE'
node_table = node_table.
ENDMETHOD.

13
Listing 8 The instance method FILL_TREE of class SCREEN_INIT.

To create a treelike structure within the Tree Control you must call method ADD_NODES and pass an internal
table of special structure and contents to that method. In our case, the line type of the internal table
NODE_TABLE is ABDEMONODE defined in the ABAP Dictionary. You must create such types by copying the
global template structure MTREESNODE.

The internal table contains one line for each node of the tree. Each node must have a unique key NODE_KEY.
The columns RELATKEY and RELATSHIP describe the relations between the nodes. Besides, you can add
description texts, change the standard icons, and so on.

In our example, we create a node table from the contents of database table SPFLI. SPFLI is the well known
table of flight connections from SAP's training and demonstration flight model. We select all data from SPFLI
into the sorted internal table SPFLI_TAB and process this table in a loop. There, we fill the internal table
NODE_TABLE with lines that represent a tree structure of two hierarchy levels. The attributes of the nodes are
set by assigning flags to some columns of NODE_TABLE. Note that we replace the standard folder icon with
an airplane icon for the subnodes by assigning the internal code '@AV@' to the image columns. You find the
internal codes of all SAP icons by executing the report SHOWICON.

Instance constructor of SCREEN_HANDLER. Listing 9 shows the instance constructor of class


SCREEN_HANDLER.

METHOD constructor.
CREATE OBJECT: html_viewer EXPORTING parent = container,
list_viewer EXPORTING i_parent = container.
ENDMETHOD.

Listing 9 The instance constructor of class SCREEN_HANDLER.

The instance constructor of class SCREEN_INIT creates an object of class SCREEN_HANDLER. Therefore,
the execution of the instance constructor of class SCREEN_HANDLER is embedded in the execution of the
instance constructor of class SCREEN_INIT. It creates two application control objects which are both linked to
the right column of our vertical splitter control. Remember, that the instance constructor of class
SCREEN_INIT passes the reference to the right column's container control to the constructor's parameter
CONTAINER in the CREATE OBJECT statement. The application controls can display either HTML pages or
lists but they are not filled during the constructor's execution yet. Filling these controls depends on the user's
action in the Tree Control.

Method HANDLE_NODE_DOUBLE_CLICK. Listing 10 shows the instance method


HANDLE_NODE_DOUBLE_CLICK of class SCREEN_HANDLER.

METHOD handle_node_double_click.
DATA: carrid TYPE spfli-carrid,
connid TYPE spfli-connid.

carrid = node_key(2).
connid = node_key+2(4).

IF connid IS INITIAL.
CALL METHOD: fill_html EXPORTING carrid = carrid,
html_viewer->set_visible EXPORTING visible = 'X',
list_viewer->set_visible EXPORTING visible = ' '.
ELSE.
CALL METHOD: fill_list EXPORTING carrid = carrid
connid = connid,
list_viewer->set_visible EXPORTING visible = 'X',
html_viewer->set_visible EXPORTING visible = ' '.
ENDIF.

CALL METHOD cl_gui_cfw=>flush.


ENDMETHOD.

14
Listing 10 The instance method HANDLE_NODE_DOUBLE_CLICK of class SCREEN_HANDLER.

This method is declared and registered as an event handler for the event NODE_DOUBLE_CLICK of our Tree
Control object. Therefore, each mouse double-click on a node of the tree triggers that method. The method
imports the event's EXPORTING parameter NODE_KEY which contains the key of the selected node.
Depending on the key's contents, the event handler either calls method FILL_HTML or FILL_LIST.
Furthermore, it sets the visibility of the two application controls referenced by HTML_VIEWER and
LIST_VIEWER. Remember that both controls are linked to the same container at the screen. The event
handler steers their alternative display in that container.

As stated above, method calls to the frontend are buffered in an automation queue. There is no automatic
synchronization point after handling a system event on the backend. Therefore, we must force the system to
process the preceding method calls by calling the static method CL_GUI_CFW=>FLUSH. Note that we do not
have any regular PAI processing in our program except when the user leaves the screen. The communication
between frontend and backend is handled by the CFW. The frontend to backend communication is triggered
by events and the backend to frontend communication is triggered by flushes.

Method FILL_HTML. Listing 12 shows the instance method FILL_HTML of class SCREEN_HANDLER.

METHOD fill_html.
DATA url TYPE scarr-url.

SELECT SINGLE url


FROM scarr
INTO url
WHERE carrid = carrid.

CALL METHOD html_viewer->show_url EXPORTING url = url.


ENDMETHOD.

Listing 12 The instance method FILL_HTML of class SCREEN_HANDLER.

This method reads the value of column URL from the database table SCARR according to the node the user
has selected by double-click. From release 4.6C on, the new column URL of the carrier database table
SCARR contains the addresses of the carrier's Web sites. If you don't find that data in your system or the
addresses have changed in the meantime, you might provide your own data and change the program
accordingly.

The selected URL is simply passed to the method SHOW_URL of our HTML control which displays it in its
area on the screen.

Method FILL_LIST. Listing 13 shows the instance method FILL_LIST of class SCREEN_HANDLER.

METHOD fill_list.
DATA: flight_tab TYPE TABLE OF demofli,
BEGIN OF flight_title,
carrname TYPE scarr-carrname,
cityfrom TYPE spfli-cityfrom,
cityto TYPE spfli-cityto,
END OF flight_title,
list_layout TYPE lvc_s_layo.

SELECT SINGLE c~carrname p~cityfrom p~cityto


INTO CORRESPONDING FIELDS OF flight_title
FROM ( scarr AS c
INNER JOIN spfli AS p ON c~carrid = p~carrid )
WHERE p~carrid = carrid AND
p~connid = connid.

SELECT fldate seatsmax seatsocc


INTO CORRESPONDING FIELDS OF TABLE flight_tab
FROM sflight
WHERE carrid = carrid AND connid = connid

15
ORDER BY fldate.

CONCATENATE flight_title-carrname
connid
flight_title-cityfrom
flight_title-cityto
INTO list_layout-grid_title SEPARATED BY space.

list_layout-smalltitle = 'X'.
list_layout-cwidth_opt = 'X'.
list_layout-no_toolbar = 'X'.

CALL METHOD list_viewer->set_table_for_first_display


EXPORTING i_structure_name = 'DEMOFLI'
is_layout = list_layout
CHANGING it_outtab = flight_tab.
ENDMETHOD.

Listing 13 The instance method FILL_LIST of class SCREEN_HANDLER.

This method gives you an impression of how to work with the new ABAP List Viewer that is going to replace
the classical ABAP list processing. As with the Tree Control, you have to prepare data in an internal table and
pass this table to a method of the List Viewer object. In our case we read detail information from database
table SFLIGHT into an internal table FLIGHT_TAB when the user has double-clicked a flight connection in the
tree.

Besides the actual data, we prepare and pass additional information as the list's title and some of its attributes
to the method. Figure 7 shows the screen after selecting a flight connection in the tree.

Figure 7 List display with an ALV control.

Conclusions

16
In this article we showed you the principal concepts of programming screens with the Control Framework
using a detailed demonstration program. The principal procedure can be condensed into the following steps:

1. Create container control objects and link them to areas at the screen.
2. Create application control objects and link them to the container controls.
3. Provide data for the controls in data objects, which for the most cases are internal tables of special global
types.
4. Send the data to the controls by calling control methods.
5. React on user actions on the controls by defining and registering event handler methods.

We did not explain the single control classes, its methods and events in detail, but we emphasized the ABAP
Objects programmer's point of view, who uses global classes of the CFW and defines his own local classes to
handle the control objects on the screen. In order to learn more about the controls of the control framework
you can refer to the documentation of the control classes or to their definition in the class builder of the ABAP
Workbench.

With that information you can then continue and explore the CFW on your own. As a next step you might react
on mouse clicks on the picture and branch for example to a list of airplanes (taken from database table
SAPLANE). Then you can introduce context menus for the nodes of the tree, which present the user selected
functions after clicking the right mouse button. And last but not least there is much to discover about the ALV,
which provides you a complete environment for interactive reporting

Horst Keller is senior technical writer in the SAP ABAP & GUI Group. He documents the ABAP language with
an emphasis on ABAP Objects. He also develops and teaches classes on ABAP programming. You can reach
him at horst.keller@sap.com.

Gisbert Loff is product manager in the SAP ABAP & GUI Group, where he handles all GUI related issues. He
has given various lecture presentations and workshops at technical education conferences and SAPPHIREs
You can reach him at gisbert.loff@sap.com.

17

Anda mungkin juga menyukai