How to structure modal operator correctly with macro like step by step execution? I struggle with understanding the modal operator concept. Below is a chain of commands I would like to step by step to execute, while during translate the following steps should wait till translate is done. So a modal operator structure is needed here.

        bpy.ops.object.select_all(action='DESELECT')       
        bpy.ops.object.empty_add()       
        bpy.ops.transform.translate('INVOKE_DEFAULT')
        bpy.ops.view3d.snap_cursor_to_selected()
        bpy.ops.object.delete()


This is the template I found and understand.
I select one object, execute the command which will then get the location and the modal takes over. But I failed to implement my commands into this structure. How can I make the modal aware of that I added the empty and jump into translate.

I understand the confirm and cancel being the states where I can execute the rest after transform or even undo the initial empty generation if need needed.

import bpy


class ModalOperator(bpy.types.Operator):
    bl_idname = "object.modal_operator"
    bl_label = "Simple Modal Operator"

    def __init__(self):
        print("Start")

    def __del__(self):
        print("End")

    def execute(self, context):
       # bpy.ops.object.empty_new()
        context.object.location.x = self.value / 1000.0
        return {'FINISHED'}

    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':  # Apply
            self.value = event.mouse_x
            self.execute(context)
        elif event.type == 'LEFTMOUSE':  # Confirm
            bpy.ops.view3d.snap_cursor_to_selected()
           x bpy.ops.object.delete()
            return {'FINISHED'}
        elif event.type in {'RIGHTMOUSE', 'ESC'}:  # Cancel
            bpy.ops.object.delete(use_global=False)
            return {'CANCELLED'}

        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        self.init_loc_x = context.object.location.x
        self.value = event.mouse_x
        self.execute(context)

        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


class ObjectData(bpy.types.Panel):
    bl_label = "Object + Mesh Data"
    bl_idname = "ObjectData"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Modeling Toolbox"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        self.layout.operator("object.modal_operator")




def register(): bpy.utils.register_module(__name__)
def unregister(): bpy.utils.unregister_module(__name__)


if __name__ == "__main__":
    register()
Your operator is not a modal operator and you are calling a modal operator inside it ,  SnapOriginObject will exit and leave transform.translate('INVOKE_DEFAULT') running behind ( it won't wait as you expect ) , you have to create a modal operator ( see the templates ) where you catch the mouse events ( movements, clicks, position ) to move the empty and delete it when you are done.