*---------------------------------------------------------------------*
*                Z _ B J H _ C O N T R O L _ T R E E                  *
*                                                                     *
*               Autor:  Bernd Haase (bjh@bmksound.de)                 *
*---------------------------------------------------------------------*
* Programm bereitet eine einfach Baumstruktur (Tree-Control) aus Be-  *
* stellungen auf und zeigt diesen Baum im linken Teil des Bildschir-  *
* mes. Einige Funktionen im Bereich Knoten und Knotentechnik sind     *
* implementiert, ansonsten macht dieses Programm nichts. Der rechte   *
* Bildschirm bleibt leer.                                             *
*---------------------------------------------------------------------*
* Definition des Dynpros 9000. Das Dynpro kann ganz normal mit allen  *
* Schmakazien ausgestattet sein, wie Table Control und Tab Strips. Nur*
* beim Splitting wird links ein Teil für die Knoten eingehangen, somit*
* verschiebt sich das eigentlich Dynpro nach rechts                   *
* GUI-Status 9000: grün=BACK, rot=ENDE, Fernglas=FIND, FINW           *
*---------------------------------------------------------------------*
* 851 Suchtext wurde im Baum nicht gefunden                           *
* 852 Keine weiteren Ergebnisse zum Suchtext                          *
*---------------------------------------------------------------------*
* (DM) Tree-Control mit Suchfunktion                                  *
*---------------------------------------------------------------------*
* 07.03.2008 BHaa: Programm abgespeckt aus Original z_bjh_oo_tree     *
*---------------------------------------------------------------------*

SAP Programm Tree Control, einen Baum mit Knotenstruktur, Explorer

REPORT z_bjh_control_tree.

INCLUDE <icon>.

TABLES:
 eket,   "Lieferplaneinteilungen
 ekko,   "Einkaufsbelegkopf
 ekpo,   "Einkaufsbelegposition
 lfa1.   "Lieferantenstamm (allgemeiner Teil)

TYPES:
 tv_text1(1) TYPE c.

TYPES:
* Typendeklarationen zum Knotenaufbau und Knotenlöschen
* Die Deklaration der Variable ist ausnahmsweise in englisch, somit ist
* internationales Kopieren einfacher
 tv_node(8)   TYPE n,          "Identifier über alle Knoten
 ts_node      TYPE treemsnodt,
 tt_nodes     TYPE STANDARD TABLE OF ts_node,
 ts_node_del  TYPE tm_nodekey,
 tt_nodes_del TYPE STANDARD TABLE OF ts_node_del.

CONSTANTS:
* Dynpro, welches die Daten erhalten soll. Beschreibung siehe oben
 gc_container_dynpro TYPE d020s-dnum VALUE '9000',

* Identifier und dazugehöriges Bildchen im Baum
 gc_e_eint TYPE tv_text1 VALUE 'E',
 gc_i_eint LIKE icons-text VALUE icon_date,
 gc_e_kopf TYPE tv_text1 VALUE 'K',
 gc_i_kopf LIKE icons-text VALUE icon_header,              "Ebene 2
 gc_e_lief TYPE tv_text1 VALUE 'L',
 gc_i_lief LIKE icons-text VALUE icon_supplier,            "1.Knoten
 gc_e_pos  TYPE tv_text1 VALUE 'P',
 gc_i_pos  LIKE icons-text VALUE icon_rating_neutral,

* Testbild, welches wechselt, bei Doppelklick auf Knoten
 gc_i_testbild LIKE icons-text VALUE icon_okay.

DATA:
* der erklärende Text zu jedem Knoten
 gv_text TYPE text80,

* Struktur des Lieferantenstammes, wird teils für den Text benötigt
 gs_lfa1 LIKE lfa1.

****************
* Bestellungen *
****************
DATA:
* Kopfdaten
 BEGIN OF gs_ekko,
   ebeln LIKE ekko-ebeln,
 END OF gs_ekko,
 gt_ekko LIKE TABLE OF gs_ekko,

* Positionen
 BEGIN OF gs_ekpo,
   ebeln LIKE ekpo-ebeln,
   ebelp LIKE ekpo-ebelp,
   matnr LIKE ekpo-matnr,
 END OF gs_ekpo,
 gt_ekpo LIKE TABLE OF gs_ekpo,

* Einteilungen
 BEGIN OF gs_eket,
   ebeln LIKE eket-ebeln,
   ebelp LIKE eket-ebelp,
   etenr LIKE eket-etenr,
   eindt LIKE eket-eindt,
 END OF gs_eket,
 gt_eket LIKE TABLE OF gs_eket.

**********
* Knoten *
**********
* somit ist gleich Zugriff auf die Klassen, ohne Sie erst definieren zu
* müssen
CLASS md_node       DEFINITION DEFERRED.
CLASS md_ereignisse DEFINITION DEFERRED.

DATA:
* fortlaufender Zähler für alle Knoten
 gi_node       TYPE tv_node,
* welchen Knoten hat der Lieferant
 gi_node_lf    TYPE tv_node,
* welche Knoten-Id hat der letzte Bestellbelegkopf
 gi_node_ekko  TYPE tv_node,
* und welchen Knoten die letzte Bestellposition
 gi_node_ekpo  TYPE tv_node,
* Knoten ohne Bedeutung, wichtig für die Unterprogrammaufrufe
 gi_node_dummy TYPE tv_node,

* Knotentabellen
 gs_node       TYPE ts_node,
 gt_nodes      TYPE tt_nodes,
* Knotentabelle, wenn ein ganzer Block Knoten gelöscht werden soll
 gt_nodes_del  TYPE tt_nodes_del,
* Knotentabelle für den Abtausch von Characteristicas
 gs_node_upd   TYPE treemsuno,
 gt_nodes_upd  TYPE treemsunot,
* Zusatzdaten zum Knoten werden hierüber verwaltet
 go_node       TYPE REF TO md_node,
* Ereignisse, allgemein, beinhalten neben Knoten auch andere Controls,
* sofern welche aktiv sind
 go_ereignisse TYPE REF TO md_ereignisse,

* suchen und finden in den Knoten
 gi_search_result TYPE i,
* Knoten des Suchergebnisses, besonders hervorheben
 gv_search_node   TYPE ts_node_del.

DATA:
* Referenzierung für die Bildschirmverarbeitung der Knoten
 go_screen_tree   TYPE REF TO cl_gui_docking_container,
 go_tree          TYPE REF TO cl_simple_tree_model.

DATA:
* Beispiel beim Drücken vom F4
 gx_knoten_offen TYPE xfeld.

FIELD-SYMBOLS:
 <fs_node> TYPE ts_node.

**********
* Dynpro *
**********
DATA:
 gv_okcode LIKE sy-ucomm.

*---------------------------------------------------------------------*
*                         CLASS  DEFINITION                           *
*                                                                     *
*                           M D _ N O D E                             *
*---------------------------------------------------------------------*
CLASS md_node DEFINITION.

 PUBLIC SECTION.

   DATA:
     mv_ebeln LIKE ekpo-ebeln,
     mv_ebelp LIKE ekpo-ebelp,
     mv_etenr LIKE eket-etenr,
     mv_matnr LIKE ekpo-ebelp.

   METHODS:
     constructor.

ENDCLASS.                    "md_node DEFINITION

*---------------------------------------------------------------------*
*                         CLASS  DEFINITION                           *
*                                                                     *
*                     M D _ E R E I G N I S S E                       *
*---------------------------------------------------------------------*
CLASS md_ereignisse DEFINITION.

 PUBLIC SECTION.

   METHODS:
* Ereignisse im Bildschirmbereich der Baumstruktur Doppelklick
* Doppelklick auf einen Knoten in der Baumstruktur
       knoten_doppelklick
           FOR EVENT node_double_click OF cl_simple_tree_model
           IMPORTING
                node_key,

* einen Knoten in der Baumstruktur markiert (durch Einfachklick). Im
* folgenden stehen einige Funktionstasten zur Auswahl
       knoten_klick
           FOR EVENT node_keypress     OF cl_simple_tree_model
           IMPORTING
                node_key
                key.

ENDCLASS.                    "md_ereignisse DEFINITION

*---------------------------------------------------------------------*
*                       CLASS  IMPLEMENTATION                         *
*                                                                     *
*                           M D _ N O D E                             *
*---------------------------------------------------------------------*
CLASS md_node IMPLEMENTATION.

 METHOD constructor.

   MOVE gs_ekko-ebeln TO mv_ebeln.
   MOVE gs_ekpo-ebelp TO mv_ebelp.
   MOVE gs_eket-etenr TO mv_etenr.
   MOVE gs_ekpo-matnr TO mv_matnr.

 ENDMETHOD.                    "constructor

ENDCLASS.                    "md_node IMPLEMENTATION

*---------------------------------------------------------------------*
*                       CLASS  IMPLEMENTATION                         *
*                                                                     *
*                     M D _ E R E I G N I S S E                       *
*---------------------------------------------------------------------*
CLASS md_ereignisse IMPLEMENTATION.

*---------------------------------------------------------------------*
*                       CLASS  IMPLEMENTATION                         *
*                                                                     *
*                     M D _ E R E I G N I S S E                       *
*                                                                     *
*                K N O T E N  _ D O P P E L K L I C K                 *
*---------------------------------------------------------------------*
* Doppelklick auf einem Knoten. Dieser Knoten ändert dann alternierend*
* das angezeigte Bildchen                                             *
*---------------------------------------------------------------------*
 METHOD knoten_doppelklick.

* welcher Knoten wurde angeklickt, dessen Daten laden
   READ TABLE gt_nodes ASSIGNING <fs_node>
   WITH KEY node_key = node_key.

   CHECK sy-subrc = 0.

   CLEAR:   gt_nodes_upd, gs_node_upd.
   REFRESH: gt_nodes_upd.

* Struktur des Änderungsknotens befüllen. Die Basis bleibt jedoch die
* Knotentabelle, diese wird natürlich mit angepaßt
   MOVE-CORRESPONDING <fs_node> TO gs_node_upd.

* nur neues Bild setzen / umstellen
   IF <fs_node>-n_image = gc_i_testbild.
     PERFORM knoten_bild USING    <fs_node>-no_branch
                         CHANGING gs_node_upd-n_image.
     MOVE gs_node_upd-n_image TO: gs_node_upd-exp_image,
                            <fs_node>-n_image, <fs_node>-exp_image.
   ELSE.
     MOVE gc_i_testbild TO: gs_node_upd-n_image, gs_node_upd-exp_image,
                            <fs_node>-n_image,   <fs_node>-exp_image.
   ENDIF.

* ähnlich wie bei Bapis die Felder kennzeichnen, die in den Attributen
* geändert werden sollen
   MOVE 'X' TO: gs_node_upd-u_n_image, gs_node_upd-u_exp_imag.

   APPEND gs_node_upd TO gt_nodes_upd.

* alle Knoten (hier nur einer !) am Bildschirm ändern und anzeigen
   CALL METHOD go_tree->update_nodes
     EXPORTING
       node_table          = gt_nodes_upd
     EXCEPTIONS
       error_in_node_table = 1.

 ENDMETHOD.                    "knoten_doppelklick

*---------------------------------------------------------------------*
*                       CLASS  IMPLEMENTATION                         *
*                                                                     *
*                     M D _ E R E I G N I S S E                       *
*                                                                     *
*                      K N O T E N _ K L I C K                        *
*---------------------------------------------------------------------*
* Auf einen Knoten wurde geklickt. Gemäß boolscher Algebra XOR  *
* ausführen, einen geschlossenen Knoten öffnen und alle direkt ihm    *
* geordneten Wurzelknoten anzeigen. Einen offener Knoten wird ge-     *
* schlossen und alle ihm zugeordneten Knoten verschwinden am Schirm.  *
*---------------------------------------------------------------------*
 METHOD knoten_klick.

   CASE key.
     WHEN go_tree->key_f4.
* nur F4 ist aktiv geschaltet worden
       IF gx_knoten_offen EQ space.
* aktuellen Knoten aufmachen. Dabei aber nur die untergliederten
* direkten Wurzelknoten anzeigen
         gx_knoten_offen = 'X'.
         CALL METHOD go_tree->expand_root_nodes
           EXPORTING
             expand_subtree      = 'X'
             level_count         = 99
           EXCEPTIONS
             illegal_level_count = 1
             OTHERS              = 2.
         IF sy-subrc <> 0.
*     MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
         ENDIF.
       ELSE.
* Knoten wird geschlossen, mit ihme werden auch alle untergliederten
* nicht mehr in diesem Moment sichtbar sein.
         CALL METHOD go_tree->collapse_all_nodes.

         gx_knoten_offen = space.
       ENDIF.
   ENDCASE.

 ENDMETHOD.                    "knoten_klick

ENDCLASS.                    "md_ereignisse IMPLEMENTATION

*---------------------------------------------------------------------*
*                                                                     *
*                 A u s w a h l b i l d s c h i r m                   *
*                                                                     *
*---------------------------------------------------------------------*
* Auswahl welche Bestellungen zu welchem Lieferant
SELECTION-SCREEN BEGIN OF BLOCK a1 WITH FRAME TITLE text-901.
PARAMETERS:
 pm_lifnr LIKE ekko-lifnr.
SELECT-OPTIONS:
 so_ebeln FOR ekko-ebeln.
SELECTION-SCREEN END OF BLOCK a1.

INITIALIZATION.
 PERFORM dynpro_baum_aufbau.

 PERFORM dynpro_control_ereignisse.

***********************************************************************
*                                                                     *
*                     P R O G R A M M S T A R T                       *
*                                                                     *
***********************************************************************
AT SELECTION-SCREEN.

* Lieferant muß bekannt sein, ansonsten Fehler und Abbruch
 SELECT SINGLE * FROM lfa1 INTO gs_lfa1
 WHERE lifnr = pm_lifnr.
 IF sy-subrc <> 0.
   MESSAGE e000(mm).
 ENDIF.

* die Basis besorgen. Daten beschaffen, die es in die Baumstruktur zu
* transferieren gilt
 PERFORM hole_belege.

* Daten stehen bereit, nun die Knoten für den Baum selbst aufbauen
 PERFORM knoten_tabelle.

* alle aufbereiteten Knoten in den Baum hängen
 CALL METHOD go_tree->add_nodes
   EXPORTING
     node_table          = gt_nodes
   EXCEPTIONS
     error_in_node_table = 1
     OTHERS              = 2.

* Sprung ins Dynpro und somit zur Anzeige
 LEAVE TO SCREEN '9000'.

END-OF-SELECTION.
 EXIT.

*---------------------------------------------------------------------*
*                        H O L E _ B E L E G E                        *
*---------------------------------------------------------------------*
* Spieldaten, die die Basis für das programm bilden, einlesen in den  *
* dafür vorgesehenen Tabellen                                         *
*---------------------------------------------------------------------*
FORM hole_belege.

* lese alle Bestellungen innerhalb der Auswahl
 SELECT * FROM ekko
 INTO CORRESPONDING FIELDS OF TABLE gt_ekko
 WHERE lifnr =  pm_lifnr
 AND   ebeln IN so_ebeln.

 CHECK NOT gt_ekko[] IS INITIAL.

* lese alle Positionen zu allen gefundenen Bestellungen
 SELECT * FROM ekpo
 INTO  CORRESPONDING FIELDS OF TABLE gt_ekpo
 FOR   ALL ENTRIES IN gt_ekko
 WHERE ebeln = gt_ekko-ebeln.

* und auch alle Einteilungen
 SELECT * FROM eket
 INTO  CORRESPONDING FIELDS OF TABLE gt_eket
 FOR   ALL ENTRIES IN gt_ekko
 WHERE ebeln = gt_ekko-ebeln.

* sortieren, etwas für's Auge
 SORT gt_ekko BY ebeln.

 SORT gt_ekpo BY ebeln ebelp.

 SORT gt_eket BY ebeln ebelp etenr.

ENDFORM.                    "hole_belege

*---------------------------------------------------------------------*
*                    K N O T E N _ T A B E L L E                      *
*---------------------------------------------------------------------*
* Alle Daten stehen bereitet, nun diese Daten umsetzen in eine Knoten-*
* tabelle und die Verkettung und Verpointerung zwischen den Ebenen so *
* gestalten, daß Kopf, Position und Einteilung je unterschiedliche    *
* Ebenen bilden, diese aber in der Struktur richtig zu dazugehörigen  *
* Kopfdaten sind                                                      *
*---------------------------------------------------------------------*
FORM knoten_tabelle.

 CLEAR:   gt_nodes, gi_node.
 REFRESH: gt_nodes.

* Ursprungsknoten, bildet der Lieferant
 CONCATENATE pm_lifnr
             gs_lfa1-name1
             gs_lfa1-ort01
             INTO gv_text SEPARATED BY ' '.

 PERFORM knoten_neu
         USING    0
                  gc_e_lief
                  gv_text
         CHANGING gi_node_lf.

* alle Bestellungen
 LOOP AT gt_ekko INTO gs_ekko.
   CLEAR: gs_ekpo, gs_eket.

   MOVE gs_ekko-ebeln TO gv_text.

   PERFORM knoten_neu
           USING    gi_node_lf
                    gc_e_kopf
                    gv_text
           CHANGING gi_node_ekko.

   CLEAR: gi_node_ekpo.

* alle Positionen der aktuellen Bestellung. Diese Art und Weise wie
* hier programmiert ist nicht zwingend so umzusetzen, es könnten auch
* erst alle Besttköpfe aufgebaut werden und dann alle Positionen.
* Jedoch ist dann die Knotenidentifikation der Kopfdaten abzuspeichern
* und auch erneut nachzulesen, was hier entfallen kann. Die Variable
* der Identifikation ist nur von temporärem Interesse
   LOOP AT gt_ekpo INTO gs_ekpo
   WHERE ebeln = gs_ekko-ebeln.
     CLEAR: gs_eket.

     CONCATENATE gs_ekko-ebeln
                 gs_ekpo-ebelp
                 gs_ekpo-matnr
                 INTO gv_text SEPARATED BY ' '.

     PERFORM knoten_neu
             USING    gi_node_ekko
                      gc_e_pos
                      gv_text
             CHANGING gi_node_ekpo.

* alle Einteilungen zur Position
     LOOP AT gt_eket INTO gs_eket
     WHERE ebeln = gs_ekpo-ebeln
     AND   ebelp = gs_ekpo-ebelp.
       CLEAR: gi_node_dummy.

       WRITE gs_eket-eindt TO gv_text.

       PERFORM knoten_neu
               USING    gi_node_ekpo
                        gc_e_eint
                        gv_text
               CHANGING gi_node_dummy.
     ENDLOOP.

     IF gi_node_dummy > 0.
* es gab eine Einteilung zur Position, somit kann der Knoten der
* Position als aufklappbar markiert werden
       READ TABLE gt_nodes ASSIGNING <fs_node>
       WITH KEY node_key = gi_node_ekpo.
       IF sy-subrc = 0.
         MOVE 'X' TO <fs_node>-expander.
       ENDIF.
     ENDIF.

   ENDLOOP.

   IF gi_node_ekpo > 0.
* Bestellung hat mindestens eine Position, Knoten aufklappbar setzen
     READ TABLE gt_nodes ASSIGNING <fs_node>
     WITH KEY node_key = gi_node_ekko.
     IF sy-subrc = 0.
       MOVE 'X' TO <fs_node>-expander.
     ENDIF.
   ENDIF.
 ENDLOOP.

ENDFORM.                    "knoten_tabelle

*---------------------------------------------------------------------*
*                         K N O T E N _ N E U                         *
*---------------------------------------------------------------------*
* Einen neuen Knoten in die Baumstruktur einhängen. Es wird jedoch nur*
* die Knotentabelle befüllt und erweitert, das Anzeigen oder Verändern*
* des Baumes am Bildschirm geschieht hier nicht                       *
*---------------------------------------------------------------------*
* =>] jv_node: Beziehung herstellen. Diesen Knoten wo angehängen      *
* =>] jv_ebene: in welcher Ebene, welche Stufe Knoten angesiedeln     *
* =>] jv_text: erklärender Text zum Knoten                            *
* ]=> ev_node: Identifizierung des neuen Knotens                      *
*---------------------------------------------------------------------*
FORM knoten_neu
    USING    jv_node
             jv_ebene
             jv_text
    CHANGING ev_node.

 CLEAR gs_node.

* Beziehung herstellen
 MOVE jv_node TO  gs_node-relatkey.
* Identifizierung des neuen Knotens
 ADD  1       TO  gi_node.
 MOVE gi_node TO: gs_node-node_key, ev_node.
* Text zum Knoten
 MOVE jv_text TO gs_node-text.

* dieses Flag wird hier mißbraucht
 MOVE jv_ebene TO gs_node-no_branch.

 MOVE 'X'           TO  gs_node-isfolder.
* Hinweis: in diesem Programm wird der Expand für den vererbenden
* Knoten erst später gesetzt
* MOVE jx_expand     TO  gs_node-expander.

* Bildchen setzen. Das Bildchen eines geschlossenen Knotens entspricht
* dem eines geöffneten Knotens
 PERFORM knoten_bild USING jv_ebene CHANGING gs_node-n_image.
 MOVE gs_node-n_image TO gs_node-exp_image.

 IF jv_ebene = gc_e_lief.
* Ursprungsknoten
   MOVE cl_simple_tree_model=>relat_first_child TO gs_node-relatship.
   CLEAR gs_node-relatkey.
   MOVE 'X' TO gs_node-expander.
 ELSE.
   gs_node-relatship = cl_simple_tree_model=>relat_last_child.
 ENDIF.

* Spaßeshalber werden einige Daten mit in die Knotentabelle übernommen.
* Was passiert, dazu bitte die Methode anschauen
 CREATE OBJECT go_node.

 gs_node-userobject ?= go_node.

 APPEND gs_node TO gt_nodes.

* nicht benutzte Variablen innerhalb der Knoten
*HIDDEN
*DISABLED
*STYLE
*DRAGDROPID

ENDFORM.                    "knoten_neu

*&---------------------------------------------------------------------*
*&      Form  knoten_bild
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->JV_EBENE   text
*      -->EV_BILD    text
*----------------------------------------------------------------------*
FORM knoten_bild
    USING    jv_ebene
    CHANGING ev_bild.

 CASE jv_ebene.
   WHEN gc_e_lief.
     MOVE gc_i_lief TO ev_bild.
   WHEN gc_e_kopf.
     MOVE gc_i_kopf TO ev_bild.
   WHEN gc_e_pos.
     MOVE gc_i_pos  TO ev_bild.
   WHEN gc_e_eint.
     MOVE gc_i_eint TO ev_bild.
 ENDCASE.

ENDFORM.                    "knoten_bild

*---------------------------------------------------------------------*
*               K N O T E N _ A L L E _ L O E S C H E N               *
*---------------------------------------------------------------------*
* Alle Knoten aus dem Baum löschen. Dieses ist wichtig beim Ende oder *
* Neustart, denn auch wenn das System neu startet, ist der Baum und   *
* deren Knoten noch aktiv. Da die Identnummern wieder von vorne anfan-*
* gen zu zählen, gäbe es erstens doppelte Nummern, die jedoch ein-    *
* deutig sein müssen sowie der Baum des ersten Laufes und auch des    *
* jetzigen Laufes                                                     *
*---------------------------------------------------------------------*
FORM knoten_alle_loeschen.

 CALL METHOD go_tree->delete_all_nodes.

 EXIT.

* oder ... als Beispiel ... alle Knoten löschen mit Angabe des Knotens
* über eine Tabelle

 CLEAR:   gt_nodes_del.
 REFRESH: gt_nodes_del.

* alle Knoten durchlaufen
 LOOP AT gt_nodes INTO gs_node.
   FREE gs_node-userobject.

   APPEND gs_node-node_key TO gt_nodes_del.
 ENDLOOP.

 CHECK NOT gt_nodes_del[] IS INITIAL.

* alle Knoten löschen
 CALL METHOD go_tree->delete_nodes
   EXPORTING
     node_key_table          = gt_nodes_del
   EXCEPTIONS
     error_in_node_key_table = 1
     OTHERS                  = 2.
 IF sy-subrc <> 0.
*   MESSAGE a115.
 ENDIF.

ENDFORM.                    "knoten_alle_loeschen

*---------------------------------------------------------------------*
*                 D Y N P R O _ B A U M _ A U F B A U                 *
*---------------------------------------------------------------------*
* Das betroffene Dynpro nehmen und links ein wenig Platz für die      *
* Anzeige des Baumes bereitstellen.                                   *
*---------------------------------------------------------------------*
FORM dynpro_baum_aufbau.

 DATA:
   lv_repid LIKE sy-repid VALUE sy-repid.

* Tree-Control Baumstruktur im Container aktivieren
 CREATE OBJECT go_screen_tree
    EXPORTING
      repid     = lv_repid
      dynnr     = gc_container_dynpro
      side      = cl_gui_docking_container=>dock_at_left
      extension = 300
    EXCEPTIONS
      cntl_error                  = 1
      cntl_system_error           = 2
      create_error                = 3
      lifetime_error              = 4
      lifetime_dynpro_dynpro_link = 5
      OTHERS                      = 6.

* ein einfache Baummodell-Instanz generieren
 CREATE OBJECT go_tree
        EXPORTING
             node_selection_mode =
             cl_simple_tree_model=>node_sel_mode_single
        EXCEPTIONS
             illegal_node_selection_mode = 1.
 IF sy-subrc <> 0.
*    MESSAGE a110 WITH text-006.
 ELSE.
   CALL METHOD go_tree->create_tree_control
     EXPORTING
       parent                       = go_screen_tree
     EXCEPTIONS
       lifetime_error               = 1
       cntl_system_error            = 2
       create_error                 = 3
       failed                       = 4
       tree_control_already_created = 5.
   IF sy-subrc <> 0.
*      MESSAGE a110 WITH text-006.
   ENDIF.
 ENDIF.

ENDFORM.                    "dynpro_baum_aufbau

*---------------------------------------------------------------------*
*           D Y N P R O _ C O N T R O L _ E R E I G N I S S E         *
*---------------------------------------------------------------------*
* Ereignisse definieren, die die Controls hergeben und benötigt werden*
*---------------------------------------------------------------------*
FORM dynpro_control_ereignisse.

 DATA:
   ls_ereignis   TYPE cntl_simple_event,
   lt_ereignisse TYPE cntl_simple_events.

* Ereignisse definieren, welche zurück in das PAI springen
 CLEAR:   lt_ereignisse.
 REFRESH: lt_ereignisse.

* Knoten-Doppelclick (Tree-Control)
 ls_ereignis-eventid = cl_simple_tree_model=>eventid_node_double_click.
 ls_ereignis-appl_event = 'X'.
 APPEND ls_ereignis TO lt_ereignisse.

* Taste gedrückt (Tree-Control)
 ls_ereignis-eventid = cl_simple_tree_model=>eventid_node_keypress.
 ls_ereignis-appl_event = ' '.
 APPEND ls_ereignis TO lt_ereignisse.

* alle gesetzten Ereignisse aktivieren
 CALL METHOD go_tree->set_registered_events
   EXPORTING
     events                    = lt_ereignisse
   EXCEPTIONS
     illegal_event_combination = 1
     unknown_event             = 2.

 IF sy-subrc <> 0.
*    MESSAGE a111.
 ENDIF.

* welche Funktionstaste bei Knoten anklicken (node_keypress) sollen
* aktiv sein. Die Werte zu den gedrückten Tasten können beim Ereignis
* abgefragt werden
 CALL METHOD go_tree->add_key_stroke
   EXPORTING
     key         = go_tree->key_f4
   EXCEPTIONS
     illegal_key = 1
     OTHERS      = 2.
 IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
 ENDIF.

* Ereignisklasse scharf schalten
 CREATE OBJECT go_ereignisse.

* Ereignisse aktivieren, welche am Bildschirm im TREE (Baum) ausgeführt
* oder angestossen wird
 SET HANDLER go_ereignisse->knoten_doppelklick FOR go_tree. "
 SET HANDLER go_ereignisse->knoten_klick       FOR go_tree. "

ENDFORM.                    "dynpro_baum_aufbau

*&---------------------------------------------------------------------*
*&      Module  status_9000  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_9000 OUTPUT.

 CLEAR gv_okcode.

 SET PF-STATUS '9000'.
*  SET TITLEBAR 'xxx'.

ENDMODULE.                 " status_9000  OUTPUT

*&---------------------------------------------------------------------*
*&      Module  user_command_ext  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_ext INPUT.

 LEAVE PROGRAM.

ENDMODULE.                 " user_command_ext  INPUT

*----------------------------------------------------------------------*
*  MODULE user_command_9000 INPUT
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
MODULE user_command_9000 INPUT.

 CASE gv_okcode.
   WHEN 'BACK'.
* Zurück zum Auswahlbildschirm
     PERFORM knoten_alle_loeschen.
     CALL SCREEN '1000'.

   WHEN 'ENDE'.
     PERFORM knoten_alle_loeschen.

*     CALL METHOD go_tree->free.     "Methode unbekannt

     CALL METHOD go_screen_tree->free.

     FREE go_screen_tree.

     LEAVE PROGRAM.

**********
* suchen *
**********
* suchen und finden. Weitersuchen.
* go_tree->STYLE_INTENSIFIED Hintergrund bleibt, Zeile hellblau
* go_tree->STYLE_INACTIVE Hintergrund bleibt, Zeile hellgrau
* go_tree->STYLE_INTENSIFD_CRITICAL Hintergrund bleibt, Zeile rot
* go_tree->STYLE_EMPHASIZED_NEGATIVE Zeile bleibt, Hintergrund hellrot
* go_tree->STYLE_EMPHASIZED_POSITIVE Zeile bleibt, Hintergrund hellgrün
* go_tree->STYLE_EMPHASIZED Zeile bleibt, Hintergrund hellgelb
   WHEN 'FIND'
   OR   'FINW'.
     IF gv_okcode = 'FIND'
     OR gv_search_node IS INITIAL.
* suchen starten. Es erscheint ein kleines Fenster, in dem der Wert
* eingetippert werden kann, gegen dem im Baum gesucht werden soll
       CALL METHOD go_tree->find
         IMPORTING
           result_type     = gi_search_result
           result_node_key = gv_search_node.
     ELSE.
* weitersuchen
       CALL METHOD go_tree->find_next
         IMPORTING
           result_type     = gi_search_result
           result_node_key = gv_search_node.
     ENDIF.

     IF gi_search_result = 1.
* der Wert ist tatsächlich irgendwo im Baum, den gewünschten Knoten auf
* jeden Fall sichtbar machen
       CALL METHOD go_tree->ensure_visible
         EXPORTING
           node_key = gv_search_node.
       CALL METHOD go_tree->node_set_style
         EXPORTING
           node_key = gv_search_node
           style    = go_tree->style_emphasized_positive.
     ELSE.
* kein (weiteres) Ergebnis, kein Knoten gefunden
       IF gv_search_node IS INITIAL.
         MESSAGE i242(fr).
       ELSE.
         MESSAGE i000(mm) WITH text-852.
       ENDIF.
* zurücksetzen der Suchlogik. Ein Weitersuchen wäre ohne Vernunft, wenn
* es keinen Treffer gibt
       CLEAR: gi_search_result, gv_search_node.
     ENDIF.

 ENDCASE.

ENDMODULE.                    "user_command_9000 INPUT

***** Ende *****
* Copyright BJH Software, Datei überarbeitet am: 21.3.2008