Skip to content

ui_edit_doc ui_edit_view

Leo Kuznetsov edited this page Jun 30, 2024 · 1 revision

Understanding ui_edit_doc and ui_edit_view in Text Editing Applications

Overview

Text editing applications require efficient handling of document content and user interaction. Two critical components in this domain are ui_edit_doc and ui_edit_view. These structures and their associated interfaces provide the foundation for document manipulation and user interaction within a text editor. Let's delve into the theory of their operations and examine a sample implementation.

ui_edit_doc - Document Management

The ui_edit_doc structure represents the document's content and its history of changes. It includes:

  • Insert/Delete Transactions: It ensures that all changes (insertions or deletions) are completed fully or not at all, maintaining document integrity.
  • Undo/Redo Semantics:
    • All or Nothing: Changes can be reverted or reapplied entirely, ensuring consistent document states.
    • Automation with replace_text(): This function provides an option to handle transactions on a different basis, which is useful for automated tasks or scripts that may require customized undo/redo functionality.

The ui_edit_str structure maintains UTF-8 strings with several optimizations:

  • Heap or Non-Heap Storage: Strings can either be in heap memory or remain outside, depending on the use case:

    • Outside Heap: Efficient for short ASCII strings, common in programming languages, allowing quick indexing and minimal memory usage.
    • Inside Heap: Necessary for mutable or long strings, facilitating efficient modifications.
  • UTF-8 Benefits: By using UTF-8, the structure avoids the complexities associated with UTF-16, such as surrogate pairs, and provides a straightforward indexing mechanism for ASCII content.

  • Text Storage: Managed in paragraphs using the ui_edit_text_t structure, which stores an array of ui_edit_str_t structures for each paragraph.

  • Undo/Redo Mechanism: Implemented through linked lists of ui_edit_to_do_t structures, representing actions that can be undone or redone.

  • Listeners: A linked list of ui_edit_listener_t structures for notifications on text changes. The ui_edit_listener_t structures enable a flexible notification system:

    • Linked List of Listeners: Each listener can be notified before and after text changes, allowing multiple components to react independently.
    • Multiple Views: This setup supports multiple views of the same document, such as:
    • Vertical/Horizontal Split: Modern editors often have split views for different perspectives on the same document. Each view can update independently while reflecting changes in real-time.
    • Collaborative Editing: Multiple users or interfaces can interact with the document simultaneously, with updates broadcast to all listeners.

Key Functions

  1. Initialization:

    bool init(ui_edit_doc_t* d, const uint8_t* utf8_or_null, int32_t bytes, bool heap);

    Initializes the document. The utf8_or_null pointer provides initial content, which can be stored on the heap based on the heap flag.

  2. Text Replacement:

    bool replace_text(ui_edit_doc_t* d, const ui_edit_range_t* r, const ui_edit_text_t* t, ui_edit_to_do_t* undo_or_null);

    Replaces text in the specified range. If undo_or_null is provided, the operation is stored for potential undo.

  3. Undo/Redo Operations:

    bool undo(ui_edit_doc_t* d);
    bool redo(ui_edit_doc_t* d);

    Manage the undo and redo stacks, allowing users to revert or reapply changes.

  4. Notification Subscriptions:

    bool subscribe(ui_edit_doc_t* d, ui_edit_notify_t* notify);
    void unsubscribe(ui_edit_doc_t* d, ui_edit_notify_t* notify);

    Allows other components to receive notifications before and after text changes, enabling responsive UI updates.

ui_edit_view - User Interaction

ui_edit_view handles the rendering and interaction aspects of the text editor. It maintains the visual state and manages user input, such as keyboard and mouse actions.

Structure Components

  • Document Reference: Points to the associated ui_edit_doc_t for text content.
  • Caret and Selection: Managed with ui_edit_range_t for selection and ui_point_t for caret position.
  • Scrolling and Layout: ui_edit_pr_t structures for tracking the view's scrolling state and visible runs.
  • User Settings: Flags like ro (read-only) and sle (single-line edit) to customize behavior.

Key Functions

  1. Initialization:

    void init(ui_edit_t* e, ui_edit_doc_t* d);

    Links the editor view to the document, preparing it for user interactions.

  2. Text Manipulation:

    void paste(ui_edit_t* e, const char* text, int32_t bytes);
    void erase(ui_edit_t* e);

    Handles pasting new text and erasing selected content.

  3. Navigation:

    void key_up(ui_edit_t* e);
    void key_down(ui_edit_t* e);
    void key_left(ui_edit_t* e);
    void key_right(ui_edit_t* e);

    Responds to user input for moving the caret through the text.

  4. Clipboard Operations:

    void copy_to_clipboard(ui_edit_t* e);
    void cut_to_clipboard(ui_edit_t* e);
    void paste_from_clipboard(ui_edit_t* e);

    Facilitates clipboard interactions for text copy, cut, and paste.

Sample Code Breakdown

Let's examine a sample implementation that utilizes ui_edit_doc and ui_edit_view to create a basic text editor:

static void edit_document_view_sample(ui_view_t* parent) {
    static void* text;
    static int64_t bytes;

    if (text == null) {
        if (ut_args.c > 1) {
            if (ut_files.exists(ut_args.v[1])) {
                errno_t r = ut_mem.map_ro(ut_args.v[1], &text, &bytes);
                if (r != 0) {
                    traceln("ut_mem.map_ro(%s) failed %s", ut_args.v[1], ut_str.error(r));
                }
            } else {
                traceln("file \"%s\" does not exist", ut_args.v[1]);
            }
        }
    }

    static ui_view_t list = ui_view(list);
    static ui_edit_t edit = {0};
    static ui_edit_doc_t doc = {0};

    if (doc.text.np == 0) {
        swear(ui_edit_doc.init(&doc, text, (int32_t)bytes, false));
        ui_edit.init(&edit, &doc);
    }

    ui_view.add(&test,
        ui_view.add(&list,
            &edit.view,
        null),
    null);

    list.max_w      = ui.infinity;
    list.max_h      = ui.infinity;
    edit.view.debug = true;
    edit.view.fm    = &ui_app.fm.H1;
    edit.view.max_w = ui.infinity;
    edit.view.max_h = ui.infinity;
    ui_app.focus = &edit.view;
}

Detailed Explanation

  1. File Mapping:

    • The function checks if an external file is provided as an argument and maps its content into memory. This allows the text editor to load and display the file's content.
  2. Static Initialization:

    • ui_view_t list: Acts as a container for the editor, setting up the view hierarchy.
    • ui_edit_t edit: Represents the text editor, initialized with default values.
    • ui_edit_doc_t doc: The document instance, also initialized with default values.
  3. Document Initialization:

    • If the document is not initialized (i.e., no paragraphs), it calls ui_edit_doc.init to set up the document structure, followed by ui_edit.init to link the editor view.
  4. UI Setup:

    • Adds the editor view (edit.view) to the parent view (list), configuring the maximum width and height to support large text content.
  5. Focus and Debugging:

    • Sets focus on the editor view and enables debugging for development purposes, assisting in identifying layout and interaction issues.

Conclusion

The ui_edit_doc and ui_edit_view structures provide a comprehensive framework for managing document content and user interactions in a text editor. The separation of document management from user interface handling promotes modularity and ease of maintenance. By leveraging these components, developers can build sophisticated text editing applications with robust undo/redo capabilities and intuitive user interactions.

This example demonstrates the foundational setup, but real-world applications can extend these components to incorporate additional features such as syntax highlighting, search functionalities, and more complex user interfaces.

Clone this wiki locally