본문 바로가기
ALV · 화면 · 리포트

[SAP ABAP] TEXTEDIT + SIMPLE TREE 드래그앤드롭 구현 — CL_DRAGDROP flavor 메커니즘 (on_drag·on_drop)

by Song.sh 2026. 5. 29.

SAP GUI 화면에서 트리(Tree) 의 항목을 마우스로 끌어다 텍스트 편집기(TextEdit) 에 떨어뜨리면 그 내용이 입력되는 드래그앤드롭(Drag & Drop) UI 를 만들 수 있습니다. 왼쪽 트리에서 항목을 선택해 오른쪽 편집기로 끌어다 놓는, 직관적인 양식 작성 화면이 대표적인 예입니다.

 

이 기능의 핵심은 CL_DRAGDROP 라는 "동작(behavior) 정의 객체" 입니다. "이 컨트롤은 드래그 출발지인가 / 드롭 목적지인가", "복사인가 이동인가", "어떤 종류(flavor) 의 데이터인가" 를 미리 정의해두고, 트리 노드와 편집기에 각각 연결합니다. 그리고 실제 드래그·드롭 순간에 발생하는 이벤트를 핸들러로 받아 데이터를 주고받습니다.

 

이 글에서는 컨테이너 계층(Easy Splitter 좌우 분할) → CL_DRAGDROP behavior 정의 → 트리/편집기 연결 → 이벤트 핸들러 → flavor 메커니즘까지 정리합니다. 데이터는 모두 가상 예시값입니다.

핵심 — 컨테이너 계층과 drag&drop 4요소

화면 구조는 Easy Splitter 로 좌(트리) / 우(편집기) 를 나눕니다.

Screen 100
  └ Custom Control 'CONTAINER'
      └ g_container (cl_gui_custom_container)
          └ g_splitter (cl_gui_easy_splitter_container · 수직 분할)
              ├ top_left_container     ← g_tree     (cl_gui_simple_tree)
              └ bottom_right_container ← g_textedit (cl_gui_textedit)

drag&drop 을 구성하는 4가지 요소는 다음과 같습니다.

요소 클래스/개념 역할
Behavior cl_dragdrop 드래그/드롭 동작 규칙 정의 (출발지·목적지·효과)
Flavor cndd_flavor 데이터 종류 구분 (Head/Body/Letter 등)
Data Object 로컬 클래스 (예: lcl_dragdrop_dataobject) 실제로 옮길 데이터를 담는 그릇
Event Handler on_drag·on_drop 드래그·드롭 순간의 동작 처리

핵심 흐름: 트리 노드를 끌면 on_drag 이벤트에서 데이터 객체를 실어 보내고, 편집기에 놓으면 on_drop 이벤트에서 그 데이터를 꺼내 편집기에 삽입합니다.


1단계 — 컨테이너 + TREE + TEXTEDIT 생성

Easy Splitter 로 화면을 좌우로 나누고, 왼쪽엔 트리, 오른쪽엔 편집기를 붙입니다.

FORM create_container.

  g_container = NEW #( container_name = 'CONTAINER' ).

  g_splitter = NEW #(
    parent      = g_container
    orientation = 1 ).                  " 수직 분할(좌/우)

  g_splitter->set_sash_position( sash_position = 30 ).   " 왼쪽 30%

* 오른쪽 — 텍스트 편집기
  g_textedit = NEW #(
    parent                     = g_splitter->bottom_right_container
    wordwrap_mode              = cl_gui_textedit=>wordwrap_at_windowborder
    wordwrap_to_linebreak_mode = cl_gui_textedit=>false ).

* 왼쪽 — 심플 트리
  g_tree = NEW #(
    parent              = g_splitter->top_left_container
    node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single ).

ENDFORM.

wordwrap_at_windowborder 는 창 너비에서 자동 줄바꿈, node_sel_mode_single 은 트리 단일 선택 모드.


2단계 — CL_DRAGDROP behavior 정의

드래그앤드롭의 규칙을 CL_DRAGDROP 객체에 등록합니다. add 메소드로 "어떤 flavor 를, 드래그 출발지로 쓸지(dragsrc), 드롭 목적지로 쓸지(droptarget), 효과는 복사/이동 중 무엇인지(effect)" 를 정의합니다.

DATA l_effect TYPE i.

* 편집기 — 드롭 목적지 (Head/Body 받음, 복사+이동 모두 허용)
g_behaviour_textedit = NEW #( ).
l_effect = cl_dragdrop=>copy + cl_dragdrop=>move.   " 1 + 2

g_behaviour_textedit->add(
  EXPORTING
    flavor     = g_dragdrop_flavor_head    " 'Head'
    dragsrc    = ' '                       " 출발지 아님
    droptarget = 'X'                       " 목적지 O
    effect     = l_effect ).

* 트리 Head 노드 — 드래그 출발지 (복사+이동)
g_behaviour_tree_head = NEW #( ).
g_behaviour_tree_head->add(
  EXPORTING
    flavor     = g_dragdrop_flavor_head
    dragsrc    = 'X'                       " 출발지 O
    droptarget = ' '                       " 목적지 아님
    effect     = cl_dragdrop=>copy + cl_dragdrop=>move ).

CL_DRAGDROP 의 효과(effect) 상수는 다음과 같습니다.

상수 의미
cl_dragdrop=>none 0 효과 없음
cl_dragdrop=>copy 1 복사 (원본 유지)
cl_dragdrop=>move 2 이동 (원본 삭제)
copy + move 3 복사·이동 둘 다 허용 (Ctrl 키로 전환)

값을 합산(copy + move = 3) 하면 두 효과를 모두 허용한다는 뜻입니다.


3단계 — behavior 를 컨트롤/노드에 연결

정의한 behavior 를 편집기와 트리 노드에 할당합니다. 편집기는 set_dragdrop 으로, 트리 노드는 get_handle 로 얻은 핸들을 노드의 dragdropid 에 넣습니다.

* 편집기에 behavior 연결
g_textedit->set_dragdrop( dragdrop = g_behaviour_textedit ).

* 트리 노드용 behavior 핸들 획득
DATA l_handle_tree_head TYPE i.
g_behaviour_tree_head->get_handle( IMPORTING handle = l_handle_tree_head ).

* 노드 정의 시 dragdropid 에 핸들 할당
DATA l_node LIKE mtreesnode.
l_node-node_key   = '1RChild1'.
l_node-relatkey   = '1Root'.
l_node-relatship  = cl_gui_simple_tree=>relat_last_child.
l_node-text       = 'Mr. Hong'.
l_node-dragdropid = l_handle_tree_head.   " ★ 이 노드의 드래그 동작 = head behavior
APPEND l_node TO g_node_table.

* 트리에 노드 일괄 추가
g_tree->add_nodes(
  EXPORTING
    table_structure_name = 'MTREESNODE'
    node_table           = g_node_table
  EXCEPTIONS
    failed              = 1
    error_in_node_table = 2
    OTHERS              = 5 ).

각 노드의 dragdropid 에 어떤 behavior 핸들을 넣느냐에 따라, 그 노드가 어떤 flavor 로 드래그되는지가 결정됩니다.


4단계 — 이벤트 핸들러 등록

드래그·드롭 순간의 동작을 처리할 핸들러를 SET HANDLER 로 연결합니다.

g_event_receiver = NEW #( ).

SET HANDLER g_event_receiver->handle_tree_drag          FOR g_tree.      " 트리 드래그 시작
SET HANDLER g_event_receiver->handle_tree_drop_complete FOR g_tree.      " 드롭 완료(move 처리)
SET HANDLER g_event_receiver->select_textedit_flavor    FOR g_textedit.  " 드롭 위치별 flavor 결정
SET HANDLER g_event_receiver->handle_textedit_drop      FOR g_textedit.  " 편집기에 데이터 삽입

g_textedit->register_event_dblclick( ).
SET HANDLER g_event_receiver->handle_textedit_doubleclick FOR g_textedit.

각 이벤트의 역할은 다음과 같습니다.

이벤트 발생 컨트롤 처리 내용
on_drag 트리 끌린 노드의 데이터 객체를 drag_drop_object->object 에 실음
on_get_flavor 편집기 드롭 위치(줄 번호) 에 따라 받을 flavor 결정
on_drop 편집기 데이터 객체를 꺼내 set_selected_text_as_r3table 로 삽입
on_drop_complete 트리 효과가 move 면 원본 노드 삭제

flavor 메커니즘 — 같은 드래그, 다른 처리

flavor 는 "같은 드래그 동작이라도 데이터 종류에 따라 다르게 처리" 하기 위한 꼬리표입니다. 예를 들어 편집기 첫 줄(제목 영역) 에는 Head flavor 만 받고, 본문 영역에는 Body flavor 를 받도록 구분할 수 있습니다.

* 드롭 위치(줄 번호) 에 따라 받을 flavor 를 결정
METHOD select_textedit_flavor.
  IF line = 1.                                    " 첫 줄이면
    SEARCH flavors FOR g_dragdrop_flavor_head.    " Head 가능한지 확인
    IF sy-subrc EQ 0.
      dragdrop_object->set_flavor( newflavor = g_dragdrop_flavor_head ).
    ELSE.
      dragdrop_object->abort( ).                  " 안 되면 드롭 취소
    ENDIF.
  ENDIF.
ENDMETHOD.

* 실제 드롭 시 flavor 에 따라 다른 데이터 삽입
METHOD handle_textedit_drop.
  DATA l_dataobj TYPE REF TO lcl_dragdrop_dataobject.

  CATCH SYSTEM-EXCEPTIONS move_cast_error = 1.
    l_dataobj ?= dragdrop_object->object.         " 데이터 객체 꺼내기
  ENDCATCH.
  IF sy-subrc EQ 1.
    dragdrop_object->abort( ).
    EXIT.
  ENDIF.

  CASE dragdrop_object->flavor.
    WHEN g_dragdrop_flavor_head.                  " Head → 제목 데이터 삽입
      sender->set_selected_text_as_r3table( table = l_dataobj->head ).
    WHEN g_dragdrop_flavor_body.                  " Body → 본문 데이터 삽입
      sender->set_selected_text_as_r3table( table = l_dataobj->body ).
  ENDCASE.
ENDMETHOD.

같은 데이터 객체라도 어떤 flavor 로 드롭됐는지에 따라 head 를 넣을지 body 를 넣을지 분기합니다.


자주 빠뜨리는 함정

get_handle 호출 시점

get_handle 은 behavior 를 프런트엔드로 전송하도록 표시하는 역할도 합니다. 노드의 dragdropid 에 넣기 전에 반드시 핸들을 먼저 얻어야 합니다.

move_cast_error 미처리

on_drop 에서 dragdrop_object->object 를 데이터 객체로 다운캐스팅(?=) 할 때, 예상과 다른 객체가 오면 캐스팅 에러가 납니다. 반드시 CATCH SYSTEM-EXCEPTIONS move_cast_error 로 감싸고, 실패 시 abort( ) 해야 합니다.

dragsrc / droptarget 방향 혼동

드래그 출발지는 dragsrc = 'X', 드롭 목적지는 droptarget = 'X'. 트리는 출발지, 편집기는 목적지로 방향을 맞춰야 합니다. 둘 다 잘못 주면 드래그가 시작되지 않거나 드롭이 안 됩니다.

move 효과인데 원본 삭제 누락

효과를 move 로 허용했다면 on_drop_complete 에서 원본 트리 노드를 delete_node 로 지워야 "이동" 이 완성됩니다. 안 지우면 복사처럼 보입니다.

컨테이너 생성 가드

PBO 의 IF g_container IS INITIAL 가드 없이 매번 생성하면 컨트롤·이벤트가 중복 등록되어 동작이 꼬입니다.


전체 코드 — 복사용 통합본

아래는 INCLUDE 로 나뉜 원본을 단일 프로그램으로 합친 통합본입니다. SE38 에 붙이고 SE51 에서 Screen 100 에 Custom Control 'CONTAINER' 를 그린 뒤, Flow Logic 에 status_0100 · container (PBO) · user_command_0100 (PAI) 를 연결하면 됩니다. 데이터 텍스트는 모두 가상 예시값.

*&---------------------------------------------------------------------*
*& Report ZRXX_TEXT_TREE_DND (예시)
*&---------------------------------------------------------------------*
*& TEXTEDIT + SIMPLE TREE 드래그앤드롭
*&---------------------------------------------------------------------*
REPORT zrxx_text_tree_dnd.

* ── 전역 선언 ───────────────────────────────────────────────
CLASS lcl_event_receiver       DEFINITION DEFERRED.
CLASS lcl_dragdrop_dataobject  DEFINITION DEFERRED.

CONSTANTS g_line_length TYPE i VALUE 50.

DATA: g_container TYPE REF TO cl_gui_custom_container,
      g_splitter  TYPE REF TO cl_gui_easy_splitter_container,
      g_tree      TYPE REF TO cl_gui_simple_tree,
      g_textedit  TYPE REF TO cl_gui_textedit.

DATA: g_behaviour_tree_head   TYPE REF TO cl_dragdrop,
      g_behaviour_tree_body   TYPE REF TO cl_dragdrop,
      g_behaviour_tree_letter TYPE REF TO cl_dragdrop,
      g_behaviour_textedit    TYPE REF TO cl_dragdrop.

DATA: g_event_receiver TYPE REF TO lcl_event_receiver,
      g_datapool       TYPE TABLE OF REF TO lcl_dragdrop_dataobject.

TYPES: g_textline_type(g_line_length) TYPE c,
       g_texttable_type TYPE TABLE OF g_textline_type.

DATA: g_ok_code    TYPE sy-ucomm,
      g_node_table TYPE TABLE OF mtreesnode.

CONSTANTS: g_dragdrop_flavor_head   TYPE cndd_flavor VALUE 'Head',
           g_dragdrop_flavor_body   TYPE cndd_flavor VALUE 'Body',
           g_dragdrop_flavor_letter TYPE cndd_flavor VALUE 'Letter'.

* ── 데이터 객체 클래스 ──────────────────────────────────────
CLASS lcl_dragdrop_dataobject DEFINITION.
  PUBLIC SECTION.
    DATA: text TYPE g_texttable_type,
          head TYPE g_texttable_type,
          body TYPE g_texttable_type.
ENDCLASS.
CLASS lcl_dragdrop_dataobject IMPLEMENTATION.
ENDCLASS.

* ── 이벤트 핸들러 클래스 ────────────────────────────────────
CLASS lcl_event_receiver DEFINITION.
  PUBLIC SECTION.
    METHODS handle_textedit_drop FOR EVENT on_drop OF cl_gui_textedit
      IMPORTING index line pos dragdrop_object sender.
    METHODS select_textedit_flavor FOR EVENT on_get_flavor OF cl_gui_textedit
      IMPORTING index line pos flavors dragdrop_object.
    METHODS handle_tree_drag FOR EVENT on_drag OF cl_gui_simple_tree
      IMPORTING node_key drag_drop_object.
    METHODS handle_tree_drop_complete FOR EVENT on_drop_complete OF cl_gui_simple_tree
      IMPORTING node_key drag_drop_object sender.
    METHODS handle_textedit_doubleclick FOR EVENT dblclick OF cl_gui_textedit
      IMPORTING sender.
ENDCLASS.

CLASS lcl_event_receiver IMPLEMENTATION.

  METHOD handle_textedit_drop.
    DATA l_dataobj TYPE REF TO lcl_dragdrop_dataobject.
    CATCH SYSTEM-EXCEPTIONS move_cast_error = 1.
      l_dataobj ?= dragdrop_object->object.
    ENDCATCH.
    IF sy-subrc EQ 1.
      dragdrop_object->abort( ).
      EXIT.
    ENDIF.

    CASE dragdrop_object->flavor.
      WHEN g_dragdrop_flavor_head.
        sender->set_selected_text_as_r3table(
          EXPORTING table = l_dataobj->head
          EXCEPTIONS error_dp = 1 error_dp_create = 2 ).
      WHEN g_dragdrop_flavor_body.
        sender->set_selected_text_as_r3table(
          EXPORTING table = l_dataobj->body
          EXCEPTIONS error_dp = 1 error_dp_create = 2 ).
    ENDCASE.
  ENDMETHOD.

  METHOD select_textedit_flavor.
    IF line = 1.
      SEARCH flavors FOR g_dragdrop_flavor_head.
      IF sy-subrc EQ 0.
        dragdrop_object->set_flavor( newflavor = g_dragdrop_flavor_head ).
      ELSE.
        dragdrop_object->abort( ).
      ENDIF.
    ENDIF.
  ENDMETHOD.

  METHOD handle_tree_drag.
    DATA: l_dataobj TYPE REF TO lcl_dragdrop_dataobject,
          l_index   TYPE c.
    CASE node_key.
      WHEN '1RChild1'. l_index = 1.
      WHEN '1RChild2'. l_index = 2.
      WHEN '2RChild1'. l_index = 1.
    ENDCASE.
    READ TABLE g_datapool INDEX l_index INTO l_dataobj.
    IF sy-subrc EQ 0.
      drag_drop_object->object = l_dataobj.
    ENDIF.
  ENDMETHOD.

  METHOD handle_tree_drop_complete.
    IF drag_drop_object->effect = cl_dragdrop=>move.
      sender->delete_node( node_key = node_key ).
      DELETE g_node_table WHERE node_key = node_key.
    ENDIF.
  ENDMETHOD.

  METHOD handle_textedit_doubleclick.
    sender->set_status_text( status_text = '텍스트를 더블클릭하셨습니다' ).
  ENDMETHOD.

ENDCLASS.

* ── 실행 ────────────────────────────────────────────────────
START-OF-SELECTION.
  CALL SCREEN 100.

* ── PBO ─────────────────────────────────────────────────────
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'S100'.
ENDMODULE.

MODULE container OUTPUT.
  IF g_container IS INITIAL.
    PERFORM create_container.
    PERFORM create_dragdrop.
    PERFORM assign_dragdrop.
    PERFORM event_dragdrop.
    PERFORM node_data.
  ENDIF.
ENDMODULE.

* ── PAI ─────────────────────────────────────────────────────
MODULE user_command_0100 INPUT.
  CASE g_ok_code.
    WHEN 'BACK'.
      LEAVE TO SCREEN 0.
  ENDCASE.
ENDMODULE.

* ── 1) 컨테이너 + Tree + TextEdit 생성 ──────────────────────
FORM create_container.
  g_container = NEW #( container_name = 'CONTAINER' ).
  g_splitter  = NEW #( parent = g_container orientation = 1 ).
  g_splitter->set_sash_position( sash_position = 30 ).

  g_textedit = NEW #(
    parent                     = g_splitter->bottom_right_container
    wordwrap_mode              = cl_gui_textedit=>wordwrap_at_windowborder
    wordwrap_to_linebreak_mode = cl_gui_textedit=>false ).

  g_tree = NEW #(
    parent              = g_splitter->top_left_container
    node_selection_mode = cl_gui_simple_tree=>node_sel_mode_single ).
ENDFORM.

* ── 2) drag&drop behavior 정의 ──────────────────────────────
FORM create_dragdrop.
  DATA l_effect TYPE i.

* 편집기 — 드롭 목적지 (Head/Body/Letter 받음)
  g_behaviour_textedit = NEW #( ).
  l_effect = cl_dragdrop=>copy + cl_dragdrop=>move.
  g_behaviour_textedit->add( EXPORTING flavor = g_dragdrop_flavor_head
                                       dragsrc = ' ' droptarget = 'X' effect = l_effect ).
  g_behaviour_textedit->add( EXPORTING flavor = g_dragdrop_flavor_body
                                       dragsrc = ' ' droptarget = 'X' effect = l_effect ).
  g_behaviour_textedit->add( EXPORTING flavor = g_dragdrop_flavor_letter
                                       dragsrc = ' ' droptarget = 'X' effect = l_effect ).

* 트리 Head — 드래그 출발지 (복사+이동)
  g_behaviour_tree_head = NEW #( ).
  l_effect = cl_dragdrop=>copy + cl_dragdrop=>move.
  g_behaviour_tree_head->add( EXPORTING flavor = g_dragdrop_flavor_head
                                        dragsrc = 'X' droptarget = ' ' effect = l_effect ).

* 트리 Body — 드래그 출발지 (복사만)
  g_behaviour_tree_body = NEW #( ).
  l_effect = cl_dragdrop=>copy.
  g_behaviour_tree_body->add( EXPORTING flavor = g_dragdrop_flavor_body
                                        dragsrc = 'X' droptarget = ' ' effect = l_effect ).

* 트리 Letter — 드래그 출발지 (Head/Body/Letter 모두)
  g_behaviour_tree_letter = NEW #( ).
  l_effect = cl_dragdrop=>copy.
  g_behaviour_tree_letter->add( EXPORTING flavor = g_dragdrop_flavor_letter
                                          dragsrc = 'X' droptarget = ' ' effect = l_effect ).
  g_behaviour_tree_letter->add( EXPORTING flavor = g_dragdrop_flavor_head
                                          dragsrc = 'X' droptarget = ' ' effect = l_effect ).
  g_behaviour_tree_letter->add( EXPORTING flavor = g_dragdrop_flavor_body
                                          dragsrc = 'X' droptarget = ' ' effect = l_effect ).
ENDFORM.

* ── 3) behavior 연결 + 노드 빌드 ────────────────────────────
FORM assign_dragdrop.
  g_textedit->set_dragdrop( dragdrop = g_behaviour_textedit ).
  PERFORM build_node_table.
ENDFORM.

FORM build_node_table.
  DATA: l_node               LIKE mtreesnode,
        l_handle_tree_head   TYPE i,
        l_handle_tree_body   TYPE i,
        l_handle_tree_letter TYPE i.

  g_behaviour_tree_head->get_handle(   IMPORTING handle = l_handle_tree_head ).
  g_behaviour_tree_body->get_handle(   IMPORTING handle = l_handle_tree_body ).
  g_behaviour_tree_letter->get_handle( IMPORTING handle = l_handle_tree_letter ).

  CLEAR l_node.
  l_node-node_key = '1Root'. l_node-isfolder = 'X'.
  l_node-text = 'Letter head (copy & move)'.
  APPEND l_node TO g_node_table.

  CLEAR l_node.
  l_node-node_key = '1RChild1'. l_node-relatkey = '1Root'.
  l_node-relatship = cl_gui_simple_tree=>relat_last_child.
  l_node-text = 'Mr. Hong'.
  l_node-dragdropid = l_handle_tree_head.
  APPEND l_node TO g_node_table.

  CLEAR l_node.
  l_node-node_key = '1RChild2'. l_node-relatkey = '1Root'.
  l_node-relatship = cl_gui_simple_tree=>relat_last_child.
  l_node-text = 'Mr. Kim'.
  l_node-dragdropid = l_handle_tree_head.
  APPEND l_node TO g_node_table.

  CLEAR l_node.
  l_node-node_key = '2Root'. l_node-isfolder = 'X'.
  l_node-text = 'Letter Bodies (copy only)'.
  APPEND l_node TO g_node_table.

  CLEAR l_node.
  l_node-node_key = '2RChild1'. l_node-relatkey = '2Root'.
  l_node-relatship = cl_gui_simple_tree=>relat_last_child.
  l_node-text = 'Sample Body Text'.
  l_node-dragdropid = l_handle_tree_body.
  APPEND l_node TO g_node_table.

  g_tree->add_nodes(
    EXPORTING
      table_structure_name = 'MTREESNODE'
      node_table           = g_node_table
    EXCEPTIONS
      failed = 1 error_in_node_table = 2 dp_error = 3
      table_structure_name_not_found = 4 OTHERS = 5 ).

  g_tree->expand_node( node_key = '1Root' ).
  g_tree->expand_node( node_key = '2Root' ).
ENDFORM.

* ── 4) 이벤트 핸들러 등록 ───────────────────────────────────
FORM event_dragdrop.
  g_event_receiver = NEW #( ).
  SET HANDLER g_event_receiver->handle_textedit_drop      FOR g_textedit.
  SET HANDLER g_event_receiver->select_textedit_flavor    FOR g_textedit.
  SET HANDLER g_event_receiver->handle_tree_drag          FOR g_tree.
  SET HANDLER g_event_receiver->handle_tree_drop_complete FOR g_tree.
  g_textedit->register_event_dblclick( ).
  SET HANDLER g_event_receiver->handle_textedit_doubleclick FOR g_textedit.
ENDFORM.

* ── 데이터 풀 채우기 (가상 예시값) ──────────────────────────
FORM node_data.
  DATA: l_first    TYPE REF TO lcl_dragdrop_dataobject,
        l_second   TYPE REF TO lcl_dragdrop_dataobject,
        l_textline TYPE g_textline_type.

  l_first  = NEW #( ).
  l_second = NEW #( ).

  l_textline = '홍길동'.
  APPEND l_textline TO l_first->head.
  l_textline = '입사를 진심으로 축하합니다.'.
  APPEND l_textline TO l_first->head.
  APPEND l_first TO g_datapool.

  l_textline = '자재 등급 판정'.
  APPEND l_textline TO l_second->head.
  l_textline = '해당 자재 TEST-MAT-001 는 등급 A1 입니다.'.
  APPEND l_textline TO l_second->head.
  APPEND l_second TO g_datapool.

  l_textline = 'Sample body line 1'.
  APPEND l_textline TO l_first->body.
  l_textline = 'Sample body line 2'.
  APPEND l_textline TO l_first->body.
  APPEND l_first TO g_datapool.
ENDFORM.


요약

단계 FORM 핵심 행동
1 create_container Easy Splitter 좌(Tree) / 우(TextEdit) 분할
2 create_dragdrop cl_dragdrop behavior 정의 (flavor·dragsrc·droptarget·effect)
3 assign_dragdrop + build_node_table set_dragdrop + 노드 dragdropid 에 핸들 할당
4 event_dragdrop SET HANDLER 로 on_drag·on_drop 등 연결
5 node_data 각 노드에 대응하는 데이터 객체 적재

TextEdit + Tree 드래그앤드롭의 본질은 "cl_dragdrop 으로 동작 규칙을 정의하고, flavor 로 데이터 종류를 구분하고, on_drag/on_drop 이벤트로 데이터를 실어 보내고 꺼내는 것". 출발지(트리) 와 목적지(편집기) 의 dragsrc/droptarget 방향만 정확히 맞추면, 같은 패턴으로 ALV ↔ Tree, Tree ↔ Tree 등 다양한 컨트롤 간 드래그앤드롭에 응용할 수 있습니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다.

CL_DRAGDROP 의 효과 상수(copy=1·move=2·none=0) 와 add/get_handle 시그니처, CL_GUI_TEXTEDIT·CL_GUI_SIMPLE_TREE 의 이벤트는 NetWeaver 표준 정의(ECC 6.0 / S/4HANA on-premise 기준) 입니다. 적용 환경 버전에 따라 일부 차이가 있을 수 있으니 실제 적용 시 SE24 의 클래스 정의를 확인하시기 바랍니다. 본문 데이터 텍스트는 모두 가상 예시값입니다.