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}