undo.go
1package ygo
2
3/*
4#include "libyrs.h"
5#include <stdlib.h>
6*/
7import "C"
8import (
9 "fmt"
10 "unsafe"
11)
12
13// UndoManagerOptions configures the undo manager.
14type UndoManagerOptions struct {
15 // CaptureTimeoutMillis defines the time window for batching changes.
16 // -1 means use default, 0 means capture every change separately.
17 CaptureTimeoutMillis int32
18}
19
20// UndoManager tracks changes and provides undo/redo functionality.
21type UndoManager struct {
22 ptr *C.YUndoManager
23}
24
25// NewUndoManager creates an undo manager.
26func NewUndoManager(opts *UndoManagerOptions) (*UndoManager, error) {
27 var cOpts *C.YUndoManagerOptions
28 if opts != nil {
29 cOpts = &C.YUndoManagerOptions{capture_timeout_millis: C.int32_t(opts.CaptureTimeoutMillis)}
30 }
31
32 ptr := C.yundo_manager(cOpts)
33 if ptr == nil {
34 return nil, fmt.Errorf("failed to create undo manager")
35 }
36
37 m := &UndoManager{ptr: ptr}
38 return m, nil
39}
40
41// Destroy releases the undo manager.
42func (m *UndoManager) Destroy() {
43 if m.ptr != nil {
44 C.yundo_manager_destroy(m.ptr)
45 m.ptr = nil
46 }
47}
48
49// AddScope adds a shared type in a document to be tracked.
50func (m *UndoManager) AddScope(doc *Doc, t interface{ Branch() unsafe.Pointer }) error {
51 if m.ptr == nil {
52 return fmt.Errorf("undo manager is nil")
53 }
54 if doc == nil || doc.ptr == nil {
55 return ErrNilDocument
56 }
57 if t == nil {
58 return fmt.Errorf("target is nil")
59 }
60 branch := t.Branch()
61 if branch == nil {
62 return ErrNilBranch
63 }
64 C.yundo_manager_add_scope(m.ptr, doc.ptr, (*C.Branch)(branch))
65 return nil
66}
67
68// AddOrigin includes an origin in undo tracking.
69func (m *UndoManager) AddOrigin(origin []byte) error {
70 if m.ptr == nil {
71 return fmt.Errorf("undo manager is nil")
72 }
73 if len(origin) == 0 {
74 return fmt.Errorf("origin is empty")
75 }
76 C.yundo_manager_add_origin(m.ptr, C.uint32_t(len(origin)),
77 (*C.char)(unsafe.Pointer(&origin[0])))
78 return nil
79}
80
81// RemoveOrigin excludes an origin from undo tracking.
82func (m *UndoManager) RemoveOrigin(origin []byte) error {
83 if m.ptr == nil {
84 return fmt.Errorf("undo manager is nil")
85 }
86 if len(origin) == 0 {
87 return fmt.Errorf("origin is empty")
88 }
89 C.yundo_manager_remove_origin(m.ptr, C.uint32_t(len(origin)),
90 (*C.char)(unsafe.Pointer(&origin[0])))
91 return nil
92}
93
94// Clear removes all undo/redo history.
95func (m *UndoManager) Clear() error {
96 if m.ptr != nil {
97 C.yundo_manager_clear(m.ptr)
98 }
99 return nil
100}
101
102// Stop creates a new undo stack item explicitly.
103func (m *UndoManager) Stop() error {
104 if m.ptr != nil {
105 C.yundo_manager_stop(m.ptr)
106 }
107 return nil
108}
109
110// Undo reverts the last change. Returns true if successful.
111func (m *UndoManager) Undo() (bool, error) {
112 if m.ptr == nil {
113 return false, fmt.Errorf("undo manager is nil")
114 }
115 return C.yundo_manager_undo(m.ptr) != 0, nil
116}
117
118// Redo reapplies a undone change. Returns true if successful.
119func (m *UndoManager) Redo() (bool, error) {
120 if m.ptr == nil {
121 return false, fmt.Errorf("undo manager is nil")
122 }
123 return C.yundo_manager_redo(m.ptr) != 0, nil
124}
125
126// UndoStackLen returns the number of undoable items.
127func (m *UndoManager) UndoStackLen() (uint32, error) {
128 if m.ptr == nil {
129 return 0, fmt.Errorf("undo manager is nil")
130 }
131 return uint32(C.yundo_manager_undo_stack_len(m.ptr)), nil
132}
133
134// RedoStackLen returns the number of redoable items.
135func (m *UndoManager) RedoStackLen() (uint32, error) {
136 if m.ptr == nil {
137 return 0, fmt.Errorf("undo manager is nil")
138 }
139 return uint32(C.yundo_manager_redo_stack_len(m.ptr)), nil
140}