refactor(undo): switch oakundo to refcounted value handles, migrate consumers
- OakUndoCommand/OakUndoStack become neutral by-value handles
{ctx, addref, release, abi_version}; a handle is a shared_ptr
equivalent at the ABI level, internals untouched (box owns/observes
flag; containers adopt, boxes created by factories own)
- oaknode command factories and undoable variants return/write value
handles; timeline command classes hold value handles; task import
take_command returns a value handle
- tests updated everywhere; suites green: oakundo 22, oaktimeline 117,
oaktask 106, oaknode 96, oakrender 44, oakcodec 18, oakcommon 193,
oakaudio 36
This commit is contained in:
@@ -84,7 +84,7 @@ OakNodeNode *oaknode_folder_as_node(OakNodeFolder *folder);
|
||||
* @brief Create an undoable FolderAddChild command. Owned; free with
|
||||
* oakundo_command_free().
|
||||
*/
|
||||
OakUndoCommand *oaknode_command_create_folder_add_child(
|
||||
OakUndoCommand oaknode_command_create_folder_add_child(
|
||||
OakNodeFolder *folder, OakNodeNode *child);
|
||||
|
||||
/**
|
||||
|
||||
@@ -88,7 +88,7 @@ int oaknode_group_add_input_passthrough_undoable(OakNodeGroup *group,
|
||||
OakNodeNode *node,
|
||||
const char *input_id,
|
||||
int element,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Remove the passthrough for (`node`, `input_id`, `element`)
|
||||
@@ -137,7 +137,7 @@ int oaknode_group_set_output_passthrough(OakNodeGroup *group,
|
||||
* (olive::NodeGroupSetOutputPassthrough).
|
||||
*/
|
||||
int oaknode_group_set_output_passthrough_undoable(
|
||||
OakNodeGroup *group, OakNodeNode *node, OakUndoCommand **out_command);
|
||||
OakNodeGroup *group, OakNodeNode *node, OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Resolve an input through group passthroughs
|
||||
|
||||
@@ -109,7 +109,7 @@ int oaknode_keyframe_set_time(OakNodeKeyframe *keyframe, int64_t time_num,
|
||||
*/
|
||||
int oaknode_keyframe_set_time_undoable(OakNodeKeyframe *keyframe,
|
||||
int64_t time_num, int64_t time_den,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Read the keyframe's value mapped into `out`. Values without a
|
||||
@@ -132,7 +132,7 @@ int oaknode_keyframe_set_value(OakNodeKeyframe *keyframe,
|
||||
*/
|
||||
int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
|
||||
const oaknode_value *v,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Read a string value. Two-stage getter.
|
||||
@@ -154,7 +154,7 @@ int oaknode_keyframe_set_value_string(OakNodeKeyframe *keyframe,
|
||||
*/
|
||||
int oaknode_keyframe_set_value_string_undoable(OakNodeKeyframe *keyframe,
|
||||
const char *value,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief The keyframe's interpolation type (oaknode_keyframe_type).
|
||||
@@ -171,7 +171,7 @@ int oaknode_keyframe_set_type(OakNodeKeyframe *keyframe, int type);
|
||||
* @brief Create a set-type command (same semantics as the live variant).
|
||||
*/
|
||||
int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief A bezier control point (`handle` is an
|
||||
@@ -192,7 +192,7 @@ int oaknode_keyframe_set_bezier_control(OakNodeKeyframe *keyframe, int handle,
|
||||
*/
|
||||
int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe *keyframe,
|
||||
int handle, double x, double y,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief The keyframe's track index.
|
||||
|
||||
+13
-13
@@ -171,7 +171,7 @@ int oaknode_node_set_label(OakNodeNode *node, const char *label);
|
||||
* @return OAKNODE_OK or a negative OAKNODE_E_* error code.
|
||||
*/
|
||||
int oaknode_node_set_label_undoable(OakNodeNode *node, const char *label,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief The node's override color index (Node::get_override_color();
|
||||
@@ -196,7 +196,7 @@ int oaknode_node_set_override_color(OakNodeNode *node, int index);
|
||||
* @return OAKNODE_OK or a negative OAKNODE_E_* error code.
|
||||
*/
|
||||
int oaknode_node_set_override_color_undoable(OakNodeNode *node, int index,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief 1 if the node is enabled (the boolean "enabled_in" input's
|
||||
@@ -220,7 +220,7 @@ int oaknode_node_set_enabled(OakNodeNode *node, int enabled);
|
||||
* @return OAKNODE_OK or a negative OAKNODE_E_* error code.
|
||||
*/
|
||||
int oaknode_node_set_enabled_undoable(OakNodeNode *node, int enabled,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/* ---- Input introspection ------------------------------------------------ */
|
||||
|
||||
@@ -310,7 +310,7 @@ int oaknode_node_set_input(OakNodeNode *node, const char *input_id,
|
||||
*/
|
||||
int oaknode_node_set_input_undoable(OakNodeNode *node, const char *input_id,
|
||||
const oaknode_value *v,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Read a string-family input's standard value. Two-stage getter.
|
||||
@@ -331,7 +331,7 @@ int oaknode_node_set_input_string(OakNodeNode *node, const char *input_id,
|
||||
int oaknode_node_set_input_string_undoable(OakNodeNode *node,
|
||||
const char *input_id,
|
||||
const char *value,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/* ---- Graph editing -------------------------------------------------------- */
|
||||
|
||||
@@ -356,7 +356,7 @@ int oaknode_node_connect(OakNodeNode *output_node, OakNodeNode *input_node,
|
||||
int oaknode_node_connect_undoable(OakNodeNode *output_node,
|
||||
OakNodeNode *input_node,
|
||||
const char *input_id,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Remove the edge feeding `input_node`'s `input_id` directly
|
||||
@@ -371,7 +371,7 @@ int oaknode_node_disconnect(OakNodeNode *input_node, const char *input_id);
|
||||
*/
|
||||
int oaknode_node_disconnect_undoable(OakNodeNode *input_node,
|
||||
const char *input_id,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Number of outgoing edges (Node::output_connections()).
|
||||
@@ -422,7 +422,7 @@ int oaknode_node_unlink(OakNodeNode *a, OakNodeNode *b, int *out_unlinked);
|
||||
* `link` != 0 links, 0 unlinks).
|
||||
*/
|
||||
int oaknode_node_link_undoable(OakNodeNode *a, OakNodeNode *b, int link,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief 1 if the two nodes are linked (Node::are_linked()).
|
||||
@@ -477,7 +477,7 @@ int oaknode_node_set_context_position(OakNodeNode *node, OakNodeNode *context,
|
||||
int oaknode_node_set_context_position_undoable(OakNodeNode *node,
|
||||
OakNodeNode *context, double x,
|
||||
double y, int expanded,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Remove the node from `context` directly (live).
|
||||
@@ -504,7 +504,7 @@ OakNodeNode *oaknode_node_create_copy(const OakNodeNode *node);
|
||||
* until then. Returns NULL on failure.
|
||||
*/
|
||||
OakNodeNode *oaknode_node_copy_in_graph(OakNodeNode *node,
|
||||
OakUndoCommand **out_command);
|
||||
OakUndoCommand *out_command);
|
||||
|
||||
/**
|
||||
* @brief Get the project this node belongs to (borrowed). *out may be
|
||||
@@ -537,7 +537,7 @@ int oaknode_node_disconnect_element(OakNodeNode *input_node,
|
||||
* @brief Create a command that adds a node to a project's graph
|
||||
* (olive::NodeAddCommand). Owned; free with oakundo_command_free().
|
||||
*/
|
||||
OakUndoCommand *oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
OakUndoCommand oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
OakNodeNode *node);
|
||||
|
||||
/**
|
||||
@@ -545,7 +545,7 @@ OakUndoCommand *oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
* repositions its dependencies recursively
|
||||
* (olive::NodeSetPositionAndDependenciesRecursivelyCommand). Owned.
|
||||
*/
|
||||
OakUndoCommand *oaknode_command_create_set_position_recursive(
|
||||
OakUndoCommand oaknode_command_create_set_position_recursive(
|
||||
OakNodeNode *node, OakNodeNode *context, double x, double y);
|
||||
|
||||
/**
|
||||
@@ -607,7 +607,7 @@ int oaknode_node_find_input_footage(const OakNodeNode *node,
|
||||
* Owned command handle; free with oakundo_command_free(). Returns NULL
|
||||
* on failure.
|
||||
*/
|
||||
OakUndoCommand *oaknode_command_create_remove_node(OakNodeNode *node);
|
||||
OakUndoCommand oaknode_command_create_remove_node(OakNodeNode *node);
|
||||
|
||||
/**
|
||||
* @brief Destroy an OWNED node immediately (C++ delete). NULL is a no-op.
|
||||
|
||||
@@ -57,7 +57,7 @@ OakTaskTask *oaktask_create_project_import(OakNodeFolder *folder,
|
||||
int url_count);
|
||||
|
||||
/** @brief Take the import's undo command (ownership transfer). */
|
||||
OakUndoCommand *oaktask_import_take_command(OakTaskTask *t);
|
||||
OakUndoCommand oaktask_import_take_command(OakTaskTask *t);
|
||||
|
||||
int oaktask_import_footage_count(OakTaskTask *t);
|
||||
|
||||
|
||||
+11
-11
@@ -41,60 +41,60 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/** @brief olive::TimelineAddTrackCommand. */
|
||||
OakUndoCommand *oaktimeline_add_track_command(OakNodeTrackList *list);
|
||||
OakUndoCommand oaktimeline_add_track_command(OakNodeTrackList *list);
|
||||
|
||||
/** @brief olive::TimelineRemoveTrackCommand. */
|
||||
OakUndoCommand *oaktimeline_remove_track_command(OakNodeTrack *track);
|
||||
OakUndoCommand oaktimeline_remove_track_command(OakNodeTrack *track);
|
||||
|
||||
/** @brief olive::TrackPlaceBlockCommand. */
|
||||
OakUndoCommand *oaktimeline_place_block_command(OakNodeTrackList *list,
|
||||
OakUndoCommand oaktimeline_place_block_command(OakNodeTrackList *list,
|
||||
int track_index,
|
||||
OakNodeBlock *block,
|
||||
int64_t in_num,
|
||||
int64_t in_den);
|
||||
|
||||
/** @brief olive::TrackReplaceBlockWithGapCommand. */
|
||||
OakUndoCommand *oaktimeline_replace_block_with_gap_command(
|
||||
OakUndoCommand oaktimeline_replace_block_with_gap_command(
|
||||
OakNodeTrack *track, OakNodeBlock *block);
|
||||
|
||||
/**
|
||||
* @brief olive::BlockTrimCommand. `mode` is an OakTimelineMovementMode
|
||||
* value (k_trim_in / k_trim_out).
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_trim_command(OakNodeTrack *track,
|
||||
OakUndoCommand oaktimeline_trim_command(OakNodeTrack *track,
|
||||
OakNodeBlock *block,
|
||||
int64_t new_length_num,
|
||||
int64_t new_length_den, int mode);
|
||||
|
||||
/** @brief olive::BlockSplitCommand on a set of blocks at one point. */
|
||||
OakUndoCommand *oaktimeline_split_command(OakNodeBlock *const *blocks,
|
||||
OakUndoCommand oaktimeline_split_command(OakNodeBlock *const *blocks,
|
||||
int count, int64_t point_num,
|
||||
int64_t point_den);
|
||||
|
||||
/** @brief olive::BlockSplitPreservingLinksCommand. */
|
||||
OakUndoCommand *oaktimeline_split_preserving_links_command(
|
||||
OakUndoCommand oaktimeline_split_preserving_links_command(
|
||||
OakNodeBlock *const *blocks, int count, const int64_t *point_nums,
|
||||
const int64_t *point_dens, int time_count);
|
||||
|
||||
/** @brief olive::TimelineRippleDeleteGapsAtRegionsCommand. */
|
||||
OakUndoCommand *oaktimeline_ripple_delete_gaps_command(
|
||||
OakUndoCommand oaktimeline_ripple_delete_gaps_command(
|
||||
OakNodeSequence *sequence, const int64_t *in_nums,
|
||||
const int64_t *in_dens, const int64_t *out_nums,
|
||||
const int64_t *out_dens, OakNodeTrack *const *tracks, int range_count);
|
||||
|
||||
/** @brief olive::TrackSlideCommand. */
|
||||
OakUndoCommand *oaktimeline_slide_command(
|
||||
OakUndoCommand oaktimeline_slide_command(
|
||||
OakNodeTrack *track, OakNodeBlock *const *blocks, int block_count,
|
||||
OakNodeBlock *in_adjacent, OakNodeBlock *out_adjacent,
|
||||
int64_t movement_num, int64_t movement_den);
|
||||
|
||||
/** @brief olive::TrackRippleRemoveAreaCommand. */
|
||||
OakUndoCommand *oaktimeline_ripple_remove_area_command(
|
||||
OakUndoCommand oaktimeline_ripple_remove_area_command(
|
||||
OakNodeTrack *track, int64_t in_num, int64_t in_den, int64_t out_num,
|
||||
int64_t out_den);
|
||||
|
||||
/** @brief olive::TrackListInsertGaps. */
|
||||
OakUndoCommand *oaktimeline_insert_gaps_command(OakNodeTrackList *list,
|
||||
OakUndoCommand oaktimeline_insert_gaps_command(OakNodeTrackList *list,
|
||||
int64_t point_num,
|
||||
int64_t point_den,
|
||||
int64_t length_num,
|
||||
|
||||
@@ -65,7 +65,7 @@ int oaktimeline_marker_at(const OakTimelineMarkerList *list, int index,
|
||||
* Owned command; free with oakundo_command_free(). Redo it directly or
|
||||
* push it on an undo stack. Returns NULL on failure.
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_marker_add_command(
|
||||
OakUndoCommand oaktimeline_marker_add_command(
|
||||
OakTimelineMarkerList *list, int in_num, int in_den, int out_num,
|
||||
int out_den, const char *name, int color);
|
||||
|
||||
@@ -74,13 +74,13 @@ OakUndoCommand *oaktimeline_marker_add_command(
|
||||
* OAKTIMELINE_E_NOT_FOUND (as NULL result documented by error) is
|
||||
* reported by returning NULL.
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_marker_remove_at_command(
|
||||
OakUndoCommand oaktimeline_marker_remove_at_command(
|
||||
OakTimelineMarkerList *list, int index);
|
||||
|
||||
/**
|
||||
* @brief Create a command that sets a marker's time range.
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_marker_set_time_command(
|
||||
OakUndoCommand oaktimeline_marker_set_time_command(
|
||||
OakTimelineMarkerList *list, int index, int in_num, int in_den,
|
||||
int out_num, int out_den);
|
||||
|
||||
@@ -89,7 +89,7 @@ OakUndoCommand *oaktimeline_marker_set_time_command(
|
||||
* `name` may be NULL to leave the name unchanged (color still applies
|
||||
* when >= 0; both NULL-name and color < 0 is a no-op error).
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_marker_set_props_command(
|
||||
OakUndoCommand oaktimeline_marker_set_props_command(
|
||||
OakTimelineMarkerList *list, int index, int color, const char *name);
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,7 +60,7 @@ int oaktimeline_workarea_set_range(OakTimelineWorkArea *w, int in_num,
|
||||
* The old range must be supplied by the caller (facade knows what it
|
||||
* changed from). Owned; free with oakundo_command_free().
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_workarea_set_range_command(
|
||||
OakUndoCommand oaktimeline_workarea_set_range_command(
|
||||
OakTimelineWorkArea *w, int in_num, int in_den, int out_num,
|
||||
int out_den, int old_in_num, int old_in_den, int old_out_num,
|
||||
int old_out_den);
|
||||
@@ -68,7 +68,7 @@ OakUndoCommand *oaktimeline_workarea_set_range_command(
|
||||
/**
|
||||
* @brief Create a set-enabled command (olive::WorkareaSetEnabledCommand).
|
||||
*/
|
||||
OakUndoCommand *oaktimeline_workarea_set_enabled_command(
|
||||
OakUndoCommand oaktimeline_workarea_set_enabled_command(
|
||||
OakTimelineWorkArea *w, int enabled);
|
||||
|
||||
/**
|
||||
|
||||
+47
-35
@@ -21,31 +21,43 @@
|
||||
#ifndef OAK_EDITOR_UNDO_UNDOCOMMAND_H
|
||||
#define OAK_EDITOR_UNDO_UNDOCOMMAND_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "undo/error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OAKUNDO_ABI_VERSION 1
|
||||
|
||||
/**
|
||||
* @brief Opaque handle to an undo command (olive::UndoCommand).
|
||||
* @brief Reference-counted handle to an undo command
|
||||
* (olive::UndoCommand).
|
||||
*
|
||||
* Handles created by oakundo_command_init() /
|
||||
* oakundo_command_init_multi() own the underlying command and must be
|
||||
* released with oakundo_command_free() UNLESS they are pushed onto an
|
||||
* OakUndoStack, which takes ownership. Handles returned by
|
||||
* oakundo_command_multi_child() are borrowed wrappers: free the wrapper
|
||||
* with oakundo_command_free(), the underlying command stays owned by the
|
||||
* multi command.
|
||||
* The object never leaves the library that created it; every external
|
||||
* reference is one of these handles. Semantics are shared_ptr-like:
|
||||
* init/factory functions return a handle with count 1, addref(ctx)
|
||||
* takes another reference, release(ctx) drops one and the library
|
||||
* destroys the object when the count reaches zero.
|
||||
*
|
||||
* Pushing a command onto an OakUndoStack transfers one reference to the
|
||||
* stack (the stack releases it when the command is discarded); callers
|
||||
* may keep their own reference or release it right after the push.
|
||||
*/
|
||||
typedef struct OakUndoCommand OakUndoCommand;
|
||||
typedef struct OakUndoCommand {
|
||||
void *ctx; /**< Opaque pointer to the reference-counted object. */
|
||||
void (*addref)(void *ctx); /**< Atomically increments the count. */
|
||||
void (*release)(void *ctx); /**< Decrements the count, destroys at 0. */
|
||||
uint32_t abi_version; /**< OAKUNDO_ABI_VERSION. */
|
||||
} OakUndoCommand;
|
||||
|
||||
/**
|
||||
* @brief Callback table backing a caller-defined undo command.
|
||||
*
|
||||
* Any callback may be NULL; a NULL redo/undo makes that direction a
|
||||
* no-op. free_fn is invoked when the command is destroyed (whether pushed
|
||||
* onto a stack or freed directly) and releases userdata.
|
||||
* no-op. free_fn is invoked when the command is destroyed (whether held
|
||||
* by a stack or released directly) and releases userdata.
|
||||
*/
|
||||
typedef struct OakUndoCommandVtable {
|
||||
void (*redo)(void *userdata);
|
||||
@@ -58,30 +70,30 @@ typedef struct OakUndoCommandVtable {
|
||||
*
|
||||
* The command takes ownership of `userdata`; `vtable` is copied.
|
||||
*
|
||||
* @return Command handle, or NULL on invalid argument or allocation
|
||||
* failure.
|
||||
* @return Command handle with count 1; ctx is NULL on invalid argument
|
||||
* or allocation failure.
|
||||
*/
|
||||
OakUndoCommand *oakundo_command_init(const OakUndoCommandVtable *vtable,
|
||||
void *userdata);
|
||||
OakUndoCommand oakundo_command_init(const OakUndoCommandVtable *vtable,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Create an empty multi command (olive::MultiUndoCommand).
|
||||
*
|
||||
* @return Command handle, or NULL on allocation failure.
|
||||
* @return Command handle with count 1; ctx is NULL on allocation
|
||||
* failure.
|
||||
*/
|
||||
OakUndoCommand *oakundo_command_init_multi(void);
|
||||
OakUndoCommand oakundo_command_init_multi(void);
|
||||
|
||||
/**
|
||||
* @brief Add `child` to the multi command `multi`.
|
||||
*
|
||||
* On success the multi command takes ownership of the underlying child
|
||||
* command; the child handle wrapper is consumed and must not be used or
|
||||
* freed afterwards.
|
||||
* The multi command takes one reference to the child; the caller keeps
|
||||
* its own reference and may release it after the call.
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_command_multi_add_child(OakUndoCommand *multi,
|
||||
OakUndoCommand *child);
|
||||
int oakundo_command_multi_add_child(OakUndoCommand multi,
|
||||
OakUndoCommand child);
|
||||
|
||||
/**
|
||||
* @brief Query the number of children in a multi command.
|
||||
@@ -90,19 +102,20 @@ int oakundo_command_multi_add_child(OakUndoCommand *multi,
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_command_multi_child_count(OakUndoCommand *multi, int *out_count);
|
||||
int oakundo_command_multi_child_count(OakUndoCommand multi,
|
||||
int *out_count);
|
||||
|
||||
/**
|
||||
* @brief Borrow a handle to the child at `index` of a multi command.
|
||||
* @brief Reference to the child at `index` of a multi command.
|
||||
*
|
||||
* The returned handle is a wrapper owned by the caller (free with
|
||||
* oakundo_command_free()); the underlying command is owned by `multi`.
|
||||
* The returned handle carries its own reference; release it with
|
||||
* oakundo_command_free().
|
||||
*
|
||||
* @return OAKUNDO_OK, OAKUNDO_E_NOT_FOUND for an out-of-range index, or
|
||||
* another negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_command_multi_child(OakUndoCommand *multi, int index,
|
||||
OakUndoCommand **out_child);
|
||||
int oakundo_command_multi_child(OakUndoCommand multi, int index,
|
||||
OakUndoCommand *out_child);
|
||||
|
||||
/**
|
||||
* @brief Execute the command's redo without a stack
|
||||
@@ -110,7 +123,7 @@ int oakundo_command_multi_child(OakUndoCommand *multi, int index,
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_command_redo_now(OakUndoCommand *command);
|
||||
int oakundo_command_redo_now(OakUndoCommand command);
|
||||
|
||||
/**
|
||||
* @brief Execute the command's undo without a stack
|
||||
@@ -118,15 +131,14 @@ int oakundo_command_redo_now(OakUndoCommand *command);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_command_undo_now(OakUndoCommand *command);
|
||||
int oakundo_command_undo_now(OakUndoCommand command);
|
||||
|
||||
/**
|
||||
* @brief Destroy a command handle.
|
||||
* @brief Release one reference to a command handle.
|
||||
*
|
||||
* Owned handles destroy the underlying command; borrowed handles (from
|
||||
* oakundo_command_multi_child()) only destroy the wrapper. Commands
|
||||
* pushed onto an OakUndoStack are owned by the stack and must not be
|
||||
* freed by the caller. NULL is a no-op.
|
||||
* Convenience wrapper around handle.release(handle.ctx): destroys the
|
||||
* command when the count reaches zero. NULL handle or NULL ctx is a
|
||||
* no-op; clears `command->ctx` after releasing.
|
||||
*/
|
||||
void oakundo_command_free(OakUndoCommand *command);
|
||||
|
||||
|
||||
+35
-26
@@ -31,50 +31,59 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Opaque handle to an undo stack (olive::UndoStack).
|
||||
* @brief Reference-counted handle to an undo stack (olive::UndoStack).
|
||||
*
|
||||
* Same ownership/count semantics as OakUndoCommand (see
|
||||
* undo/undocommand.h).
|
||||
*/
|
||||
typedef struct OakUndoStack OakUndoStack;
|
||||
typedef struct OakUndoStack {
|
||||
void *ctx; /**< Opaque pointer to the reference-counted object. */
|
||||
void (*addref)(void *ctx); /**< Atomically increments the count. */
|
||||
void (*release)(void *ctx); /**< Decrements the count, destroys at 0. */
|
||||
uint32_t abi_version; /**< OAKUNDO_ABI_VERSION. */
|
||||
} OakUndoStack;
|
||||
|
||||
/**
|
||||
* @brief Create an undo stack.
|
||||
* @brief Create an undo stack (count 1).
|
||||
*
|
||||
* A fresh stack contains a single "New/Open Project" empty command,
|
||||
* matching olive::UndoStack::clear().
|
||||
*
|
||||
* @return Stack handle, or NULL on allocation failure.
|
||||
* @return Stack handle; ctx is NULL on allocation failure.
|
||||
*/
|
||||
OakUndoStack *oakundo_undostack_init(void);
|
||||
OakUndoStack oakundo_undostack_init(void);
|
||||
|
||||
/**
|
||||
* @brief Destroy an undo stack and all commands it owns.
|
||||
* @brief Release one reference to an undo stack.
|
||||
*
|
||||
* NULL is a no-op.
|
||||
* NULL handle or NULL ctx is a no-op; clears `stack->ctx` after
|
||||
* releasing.
|
||||
*/
|
||||
void oakundo_undostack_free(OakUndoStack *stack);
|
||||
|
||||
/**
|
||||
* @brief Push `command` onto the stack and execute its redo.
|
||||
*
|
||||
* On success the stack takes ownership of the underlying command; the
|
||||
* handle wrapper is consumed and must not be used or freed afterwards.
|
||||
* An empty multi command is deleted immediately (not pushed), matching
|
||||
* olive::UndoStack::push. `name` is the user-visible label (NULL behaves
|
||||
* like an empty label).
|
||||
* The stack takes one reference to the command; the caller keeps its
|
||||
* own reference and may release it after the call. An empty multi
|
||||
* command is deleted immediately (not pushed), matching
|
||||
* olive::UndoStack::push. `name` is the user-visible label (NULL
|
||||
* behaves like an empty label).
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_push(OakUndoStack *stack, OakUndoCommand *command,
|
||||
int oakundo_undostack_push(OakUndoStack stack, OakUndoCommand command,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* @brief Push a command that has already been executed (redo skipped).
|
||||
*
|
||||
* Ownership rules match oakundo_undostack_push().
|
||||
* Reference rules match oakundo_undostack_push().
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_push_pre_executed(OakUndoStack *stack,
|
||||
OakUndoCommand *command,
|
||||
int oakundo_undostack_push_pre_executed(OakUndoStack stack,
|
||||
OakUndoCommand command,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
@@ -82,14 +91,14 @@ int oakundo_undostack_push_pre_executed(OakUndoStack *stack,
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_undo(OakUndoStack *stack);
|
||||
int oakundo_undostack_undo(OakUndoStack stack);
|
||||
|
||||
/**
|
||||
* @brief Redo the most recently undone command, if any.
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_redo(OakUndoStack *stack);
|
||||
int oakundo_undostack_redo(OakUndoStack stack);
|
||||
|
||||
/**
|
||||
* @brief Undo/redo until the done-command count equals `index`
|
||||
@@ -97,7 +106,7 @@ int oakundo_undostack_redo(OakUndoStack *stack);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_jump(OakUndoStack *stack, int64_t index);
|
||||
int oakundo_undostack_jump(OakUndoStack stack, int64_t index);
|
||||
|
||||
/**
|
||||
* @brief Delete all commands and push the fresh "New/Open Project" empty
|
||||
@@ -105,7 +114,7 @@ int oakundo_undostack_jump(OakUndoStack *stack, int64_t index);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_clear(OakUndoStack *stack);
|
||||
int oakundo_undostack_clear(OakUndoStack stack);
|
||||
|
||||
/**
|
||||
* @brief Query whether undo (redo) is currently possible.
|
||||
@@ -114,8 +123,8 @@ int oakundo_undostack_clear(OakUndoStack *stack);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_can_undo(OakUndoStack *stack, int *out_value);
|
||||
int oakundo_undostack_can_redo(OakUndoStack *stack, int *out_value);
|
||||
int oakundo_undostack_can_undo(OakUndoStack stack, int *out_value);
|
||||
int oakundo_undostack_can_redo(OakUndoStack stack, int *out_value);
|
||||
|
||||
/**
|
||||
* @brief Total number of history rows (done + undone commands).
|
||||
@@ -124,7 +133,7 @@ int oakundo_undostack_can_redo(OakUndoStack *stack, int *out_value);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_count(OakUndoStack *stack, int64_t *out_count);
|
||||
int oakundo_undostack_count(OakUndoStack stack, int64_t *out_count);
|
||||
|
||||
/**
|
||||
* @brief Current position in the history: the number of done commands
|
||||
@@ -134,7 +143,7 @@ int oakundo_undostack_count(OakUndoStack *stack, int64_t *out_count);
|
||||
*
|
||||
* @return OAKUNDO_OK or a negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_index(OakUndoStack *stack, int64_t *out_index);
|
||||
int oakundo_undostack_index(OakUndoStack stack, int64_t *out_index);
|
||||
|
||||
/**
|
||||
* @brief Label of the history row at `row` (0-based, two-stage getter).
|
||||
@@ -143,7 +152,7 @@ int oakundo_undostack_index(OakUndoStack *stack, int64_t *out_index);
|
||||
* (non-negative), OAKUNDO_E_NOT_FOUND for an invalid row, or
|
||||
* another negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_command_text(OakUndoStack *stack, int64_t row,
|
||||
int oakundo_undostack_command_text(OakUndoStack stack, int64_t row,
|
||||
char *buf, int buf_size);
|
||||
|
||||
/**
|
||||
@@ -154,7 +163,7 @@ int oakundo_undostack_command_text(OakUndoStack *stack, int64_t row,
|
||||
* @return OAKUNDO_OK, OAKUNDO_E_NOT_FOUND for an invalid row, or another
|
||||
* negative OAKUNDO_E_* error code.
|
||||
*/
|
||||
int oakundo_undostack_command_is_done(OakUndoStack *stack, int64_t row,
|
||||
int oakundo_undostack_command_is_done(OakUndoStack stack, int64_t row,
|
||||
int *out_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -238,24 +238,20 @@ OakNodeNode *oaknode_folder_as_node(OakNodeFolder *folder)
|
||||
return reinterpret_cast<OakNodeNode *>(folder);
|
||||
}
|
||||
|
||||
OakUndoCommand *oaknode_command_create_folder_add_child(
|
||||
OakUndoCommand oaknode_command_create_folder_add_child(
|
||||
OakNodeFolder *folder, OakNodeNode *child)
|
||||
{
|
||||
if (!folder || !child) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle =
|
||||
new (std::nothrow) OakUndoCommand{ nullptr, true };
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
handle->command = new olive::FolderAddChild(
|
||||
reinterpret_cast<olive::Folder *>(folder),
|
||||
reinterpret_cast<olive::Node *>(child));
|
||||
return handle;
|
||||
return oakundo_capi::make_command_handle(
|
||||
new olive::FolderAddChild(
|
||||
reinterpret_cast<olive::Folder *>(folder),
|
||||
reinterpret_cast<olive::Node *>(child)),
|
||||
true);
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,18 +111,18 @@ int oaknode_group_add_input_passthrough_undoable(OakNodeGroup *group,
|
||||
OakNodeNode *node,
|
||||
const char *input_id,
|
||||
int element,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!group || !node || !input_id || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeGroupAddInputPassthrough(
|
||||
to_group(group),
|
||||
olive::NodeInput(to_node(node), input_id, element)));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -246,17 +246,17 @@ int oaknode_group_set_output_passthrough(OakNodeGroup *group,
|
||||
}
|
||||
|
||||
int oaknode_group_set_output_passthrough_undoable(
|
||||
OakNodeGroup *group, OakNodeNode *node, OakUndoCommand **out_command)
|
||||
OakNodeGroup *group, OakNodeNode *node, OakUndoCommand *out_command)
|
||||
{
|
||||
if (!group || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeGroupSetOutputPassthrough(to_group(group),
|
||||
to_node(node)));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
|
||||
+15
-15
@@ -213,19 +213,19 @@ int oaknode_keyframe_set_time(OakNodeKeyframe *keyframe, int64_t time_num,
|
||||
|
||||
int oaknode_keyframe_set_time_undoable(OakNodeKeyframe *keyframe,
|
||||
int64_t time_num, int64_t time_den,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!keyframe || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetKeyframeTimeCommand(
|
||||
to_key(keyframe),
|
||||
olive::core::Rational(static_cast<int>(time_num),
|
||||
static_cast<int>(time_den))));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -316,7 +316,7 @@ int oaknode_keyframe_set_value(OakNodeKeyframe *keyframe,
|
||||
|
||||
int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
|
||||
const oaknode_value *v,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!keyframe || !v || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -328,10 +328,10 @@ int oaknode_keyframe_set_value_undoable(OakNodeKeyframe *keyframe,
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetKeyframeValueCommand(to_key(keyframe),
|
||||
variant));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -373,17 +373,17 @@ int oaknode_keyframe_set_value_string(OakNodeKeyframe *keyframe,
|
||||
|
||||
int oaknode_keyframe_set_value_string_undoable(OakNodeKeyframe *keyframe,
|
||||
const char *value,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!keyframe || !value || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetKeyframeValueCommand(
|
||||
to_key(keyframe), olive::Variant(value)));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -426,7 +426,7 @@ int oaknode_keyframe_set_type(OakNodeKeyframe *keyframe, int type)
|
||||
}
|
||||
|
||||
int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!keyframe || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -438,9 +438,9 @@ int oaknode_keyframe_set_type_undoable(OakNodeKeyframe *keyframe, int type,
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new KeyframeSetTypeCommand(to_key(keyframe), keyframe_type));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -498,7 +498,7 @@ int oaknode_keyframe_set_bezier_control(OakNodeKeyframe *keyframe, int handle,
|
||||
|
||||
int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe *keyframe,
|
||||
int handle, double x, double y,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!keyframe || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -514,10 +514,10 @@ int oaknode_keyframe_set_bezier_control_undoable(OakNodeKeyframe *keyframe,
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle_ptr = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle_ptr = oaknode_c_api::wrap_command(
|
||||
new KeyframeSetBezierControlCommand(to_key(keyframe), bezier_handle,
|
||||
olive::PointF(x, y)));
|
||||
if (!handle_ptr) {
|
||||
if (!handle_ptr.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle_ptr;
|
||||
|
||||
+38
-38
@@ -167,16 +167,16 @@ int oaknode_node_set_label(OakNodeNode *node, const char *label)
|
||||
}
|
||||
|
||||
int oaknode_node_set_label_undoable(OakNodeNode *node, const char *label,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !label || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeRenameCommand(to_node(node), label));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -215,16 +215,16 @@ int oaknode_node_set_override_color(OakNodeNode *node, int index)
|
||||
}
|
||||
|
||||
int oaknode_node_set_override_color_undoable(OakNodeNode *node, int index,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeOverrideColorCommand(to_node(node), index));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -268,7 +268,7 @@ int oaknode_node_set_enabled(OakNodeNode *node, int enabled)
|
||||
}
|
||||
|
||||
int oaknode_node_set_enabled_undoable(OakNodeNode *node, int enabled,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -279,9 +279,9 @@ int oaknode_node_set_enabled_undoable(OakNodeNode *node, int enabled,
|
||||
olive::SplitValue split =
|
||||
olive::NodeValue::split_normal_value_into_track_values(
|
||||
olive::NodeValue::k_boolean, olive::Variant(enabled != 0));
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetSplitStandardValueCommand(ref, split));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -464,7 +464,7 @@ int oaknode_node_set_input(OakNodeNode *node, const char *input_id,
|
||||
|
||||
int oaknode_node_set_input_undoable(OakNodeNode *node, const char *input_id,
|
||||
const oaknode_value *v,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -485,9 +485,9 @@ int oaknode_node_set_input_undoable(OakNodeNode *node, const char *input_id,
|
||||
olive::SplitValue split =
|
||||
olive::NodeValue::split_normal_value_into_track_values(type, variant);
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetSplitStandardValueCommand(ref, split));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -545,7 +545,7 @@ int oaknode_node_set_input_string(OakNodeNode *node, const char *input_id,
|
||||
int oaknode_node_set_input_string_undoable(OakNodeNode *node,
|
||||
const char *input_id,
|
||||
const char *value,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !value || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -566,9 +566,9 @@ int oaknode_node_set_input_string_undoable(OakNodeNode *node,
|
||||
to_node(node)->get_input_data_type(input_id),
|
||||
olive::Variant(value));
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeParamSetSplitStandardValueCommand(ref, split));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -610,7 +610,7 @@ int oaknode_node_connect(OakNodeNode *output_node, OakNodeNode *input_node,
|
||||
int oaknode_node_connect_undoable(OakNodeNode *output_node,
|
||||
OakNodeNode *input_node,
|
||||
const char *input_id,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!output_node || !input_node || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -624,11 +624,11 @@ int oaknode_node_connect_undoable(OakNodeNode *output_node,
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeEdgeAddCommand(
|
||||
to_node(output_node),
|
||||
olive::NodeInput(to_node(input_node), input_id)));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -663,7 +663,7 @@ int oaknode_node_disconnect(OakNodeNode *input_node, const char *input_id)
|
||||
|
||||
int oaknode_node_disconnect_undoable(OakNodeNode *input_node,
|
||||
const char *input_id,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!input_node || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -678,10 +678,10 @@ int oaknode_node_disconnect_undoable(OakNodeNode *input_node,
|
||||
return OAKNODE_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeEdgeRemoveCommand(
|
||||
output, olive::NodeInput(to_node(input_node), input_id)));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -804,16 +804,16 @@ int oaknode_node_unlink(OakNodeNode *a, OakNodeNode *b, int *out_unlinked)
|
||||
}
|
||||
|
||||
int oaknode_node_link_undoable(OakNodeNode *a, OakNodeNode *b, int link,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!a || !b || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeLinkCommand(to_node(a), to_node(b), link != 0));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -964,7 +964,7 @@ int oaknode_node_set_context_position(OakNodeNode *node, OakNodeNode *context,
|
||||
int oaknode_node_set_context_position_undoable(OakNodeNode *node,
|
||||
OakNodeNode *context, double x,
|
||||
double y, int expanded,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !context || !out_command) {
|
||||
return OAKNODE_E_INVALID;
|
||||
@@ -977,10 +977,10 @@ int oaknode_node_set_context_position_undoable(OakNodeNode *node,
|
||||
// position map lives on the positioned node keyed by the context,
|
||||
// so the command's (node, context) arguments are swapped relative
|
||||
// to this function's signature.
|
||||
OakUndoCommand *handle = oaknode_c_api::wrap_command(
|
||||
OakUndoCommand handle = oaknode_c_api::wrap_command(
|
||||
new olive::NodeSetPositionCommand(to_node(context), to_node(node),
|
||||
position));
|
||||
if (!handle) {
|
||||
if (!handle.ctx) {
|
||||
return OAKNODE_E_NOMEM;
|
||||
}
|
||||
*out_command = handle;
|
||||
@@ -1039,7 +1039,7 @@ void oaknode_node_free(OakNodeNode *node)
|
||||
}
|
||||
|
||||
OakNodeNode *oaknode_node_copy_in_graph(OakNodeNode *node,
|
||||
OakUndoCommand **out_command)
|
||||
OakUndoCommand *out_command)
|
||||
{
|
||||
if (!node || !out_command) {
|
||||
return NULL;
|
||||
@@ -1054,7 +1054,7 @@ OakNodeNode *oaknode_node_copy_in_graph(OakNodeNode *node,
|
||||
return NULL;
|
||||
}
|
||||
*out_command = oaknode_c_api::wrap_command(command);
|
||||
if (!*out_command) {
|
||||
if (!out_command->ctx) {
|
||||
delete command;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1065,10 +1065,10 @@ OakNodeNode *oaknode_node_copy_in_graph(OakNodeNode *node,
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaknode_command_create_remove_node(OakNodeNode *node)
|
||||
OakUndoCommand oaknode_command_create_remove_node(OakNodeNode *node)
|
||||
{
|
||||
if (!node) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1076,7 +1076,7 @@ OakUndoCommand *oaknode_command_create_remove_node(OakNodeNode *node)
|
||||
new olive::NodeRemoveWithExclusiveDependenciesAndDisconnect(
|
||||
to_node(node)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,11 +1171,11 @@ int oaknode_node_disconnect_element(OakNodeNode *input_node,
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
OakUndoCommand oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
OakNodeNode *node)
|
||||
{
|
||||
if (!graph || !node) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1183,15 +1183,15 @@ OakUndoCommand *oaknode_command_create_add_node(OakNodeProject *graph,
|
||||
new olive::NodeAddCommand(
|
||||
reinterpret_cast<olive::Project *>(graph), to_node(node)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaknode_command_create_set_position_recursive(
|
||||
OakUndoCommand oaknode_command_create_set_position_recursive(
|
||||
OakNodeNode *node, OakNodeNode *context, double x, double y)
|
||||
{
|
||||
if (!node || !context) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -1200,7 +1200,7 @@ OakUndoCommand *oaknode_command_create_set_position_recursive(
|
||||
to_node(node), to_node(context),
|
||||
olive::Node::Position(olive::PointF(x, y))));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -250,22 +250,15 @@ inline int value_from_variant(olive::NodeValue::Type type, const olive::Variant
|
||||
|
||||
/**
|
||||
* @brief Wrap a freshly created olive::UndoCommand in an owned
|
||||
* OakUndoCommand handle. Returns NULL on allocation failure.
|
||||
* OakUndoCommand handle (reference count 1). Returns an empty handle
|
||||
* (ctx == NULL) on allocation failure.
|
||||
*/
|
||||
inline OakUndoCommand *wrap_command(olive::UndoCommand *command)
|
||||
inline OakUndoCommand wrap_command(olive::UndoCommand *command)
|
||||
{
|
||||
if (!command) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand();
|
||||
if (!handle) {
|
||||
delete command;
|
||||
return NULL;
|
||||
}
|
||||
handle->command = command;
|
||||
handle->owned = true;
|
||||
return handle;
|
||||
return oakundo_capi::make_command_handle(command, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -136,11 +136,11 @@ TEST(NodeGroupTest, PassthroughAddUndoable)
|
||||
OakNodeGroup *group = make_group_with_inner(as_handle(&inner));
|
||||
ASSERT_NE(group, nullptr);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_group_add_input_passthrough_undoable(
|
||||
group, as_handle(&inner), "float_in", -1, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
|
||||
int count = 0;
|
||||
EXPECT_EQ(oaknode_group_passthrough_count(group, &count), OAKNODE_OK);
|
||||
@@ -154,7 +154,7 @@ TEST(NodeGroupTest, PassthroughAddUndoable)
|
||||
EXPECT_EQ(oaknode_group_passthrough_count(group, &count), OAKNODE_OK);
|
||||
EXPECT_EQ(count, 0);
|
||||
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
oaknode_group_free(group);
|
||||
}
|
||||
|
||||
@@ -174,18 +174,18 @@ TEST(NodeGroupTest, OutputPassthroughLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_group_get_output_passthrough(group, &out), OAKNODE_OK);
|
||||
EXPECT_EQ(out, inner_handle);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_group_set_output_passthrough_undoable(group, nullptr,
|
||||
&command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_group_get_output_passthrough(group, &out), OAKNODE_OK);
|
||||
EXPECT_EQ(out, nullptr);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_group_get_output_passthrough(group, &out), OAKNODE_OK);
|
||||
EXPECT_EQ(out, inner_handle);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_group_set_output_passthrough(nullptr, inner_handle),
|
||||
OAKNODE_E_INVALID);
|
||||
|
||||
@@ -124,10 +124,10 @@ TEST(NodeKeyframeTest, TimeLiveAndUndoable)
|
||||
EXPECT_EQ(num, 1);
|
||||
EXPECT_EQ(den, 2);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_keyframe_set_time_undoable(key, 5, 1, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oaknode_keyframe_get_time(key, &num, &den), OAKNODE_OK);
|
||||
EXPECT_EQ(num, 1); // not yet executed
|
||||
|
||||
@@ -138,7 +138,7 @@ TEST(NodeKeyframeTest, TimeLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_keyframe_get_time(key, &num, &den), OAKNODE_OK);
|
||||
EXPECT_EQ(num, 1);
|
||||
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
oaknode_keyframe_free(key);
|
||||
|
||||
EXPECT_EQ(oaknode_keyframe_set_time(nullptr, 0, 1), OAKNODE_E_INVALID);
|
||||
@@ -163,17 +163,17 @@ TEST(NodeKeyframeTest, ValueLiveAndUndoable)
|
||||
EXPECT_DOUBLE_EQ(out.f[0], 3.25);
|
||||
|
||||
in = make_float(7.0);
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_keyframe_set_value_undoable(key, &in, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_value(key, &out), OAKNODE_OK);
|
||||
EXPECT_DOUBLE_EQ(out.f[0], 7.0);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_value(key, &out), OAKNODE_OK);
|
||||
EXPECT_DOUBLE_EQ(out.f[0], 3.25);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
// STRING rejected by the POD setter.
|
||||
in.type = OAKNODE_VALUE_STRING;
|
||||
@@ -195,18 +195,18 @@ TEST(NodeKeyframeTest, StringValueLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_keyframe_get_value_string(key, buf, sizeof(buf)), 6);
|
||||
EXPECT_STREQ(buf, "hello");
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_keyframe_set_value_string_undoable(key, "world",
|
||||
&command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_value_string(key, buf, sizeof(buf)), 6);
|
||||
EXPECT_STREQ(buf, "world");
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_value_string(key, buf, sizeof(buf)), 6);
|
||||
EXPECT_STREQ(buf, "hello");
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_keyframe_set_value_string(key, nullptr),
|
||||
OAKNODE_E_INVALID);
|
||||
@@ -229,18 +229,18 @@ TEST(NodeKeyframeTest, TypeLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_keyframe_get_type(key, &type), OAKNODE_OK);
|
||||
EXPECT_EQ(type, OAKNODE_KEYFRAME_HOLD);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_keyframe_set_type_undoable(key, OAKNODE_KEYFRAME_BEZIER,
|
||||
&command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_type(key, &type), OAKNODE_OK);
|
||||
EXPECT_EQ(type, OAKNODE_KEYFRAME_BEZIER);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_type(key, &type), OAKNODE_OK);
|
||||
EXPECT_EQ(type, OAKNODE_KEYFRAME_HOLD);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_keyframe_set_type(key, 99), OAKNODE_E_INVALID);
|
||||
EXPECT_EQ(oaknode_keyframe_set_type(nullptr, OAKNODE_KEYFRAME_HOLD),
|
||||
@@ -266,11 +266,11 @@ TEST(NodeKeyframeTest, BezierControlLiveAndUndoable)
|
||||
EXPECT_DOUBLE_EQ(x, -1.0);
|
||||
EXPECT_DOUBLE_EQ(y, 0.5);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_keyframe_set_bezier_control_undoable(
|
||||
key, OAKNODE_KEYFRAME_OUT_HANDLE, 2.0, -0.5, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_keyframe_get_bezier_control(
|
||||
key, OAKNODE_KEYFRAME_OUT_HANDLE, &x, &y),
|
||||
@@ -283,7 +283,7 @@ TEST(NodeKeyframeTest, BezierControlLiveAndUndoable)
|
||||
OAKNODE_OK);
|
||||
EXPECT_DOUBLE_EQ(x, 0.0);
|
||||
EXPECT_DOUBLE_EQ(y, 0.0);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_keyframe_set_bezier_control(key, 99, 0.0, 0.0),
|
||||
OAKNODE_E_INVALID);
|
||||
|
||||
@@ -117,10 +117,10 @@ TEST(NodeMetadataTest, LabelUndoableSymmetry)
|
||||
|
||||
EXPECT_EQ(oaknode_node_set_label(handle, "before"), OAKNODE_OK);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_label_undoable(handle, "after", &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(get_string(oaknode_node_get_label, handle), "before");
|
||||
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
@@ -128,7 +128,7 @@ TEST(NodeMetadataTest, LabelUndoableSymmetry)
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(get_string(oaknode_node_get_label, handle), "before");
|
||||
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(NodeMetadataTest, OverrideColorLiveAndUndoable)
|
||||
@@ -144,17 +144,17 @@ TEST(NodeMetadataTest, OverrideColorLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_node_get_override_color(handle, &color), OAKNODE_OK);
|
||||
EXPECT_EQ(color, 3);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_override_color_undoable(handle, 7, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_get_override_color(handle, &color), OAKNODE_OK);
|
||||
EXPECT_EQ(color, 7);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_get_override_color(handle, &color), OAKNODE_OK);
|
||||
EXPECT_EQ(color, 3);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(NodeMetadataTest, EnabledLiveAndUndoable)
|
||||
@@ -170,17 +170,17 @@ TEST(NodeMetadataTest, EnabledLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_node_is_enabled(handle, &enabled), OAKNODE_OK);
|
||||
EXPECT_EQ(enabled, 0);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_enabled_undoable(handle, 1, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_is_enabled(handle, &enabled), OAKNODE_OK);
|
||||
EXPECT_EQ(enabled, 1);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_is_enabled(handle, &enabled), OAKNODE_OK);
|
||||
EXPECT_EQ(enabled, 0);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(NodeInputTest, EnumerateInputs)
|
||||
@@ -302,10 +302,10 @@ TEST(NodeInputTest, ValueUndoableSymmetry)
|
||||
OakNodeNode *handle = as_handle(&node);
|
||||
|
||||
oaknode_value in = make_float(9.0);
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_input_undoable(handle, "float_in", &in, &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
|
||||
oaknode_value out;
|
||||
EXPECT_EQ(oaknode_node_get_input(handle, "float_in", &out), OAKNODE_OK);
|
||||
@@ -317,7 +317,7 @@ TEST(NodeInputTest, ValueUndoableSymmetry)
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_get_input(handle, "float_in", &out), OAKNODE_OK);
|
||||
EXPECT_DOUBLE_EQ(out.f[0], 0.0);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(NodeInputTest, StringValueLiveAndUndoable)
|
||||
@@ -343,11 +343,11 @@ TEST(NodeInputTest, StringValueLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_node_set_input_string(handle, "unknown_in", "x"),
|
||||
OAKNODE_E_NOT_FOUND);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_input_string_undoable(handle, "text_in",
|
||||
"world", &command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_get_input_string(handle, "text_in", buf,
|
||||
sizeof(buf)),
|
||||
@@ -358,7 +358,7 @@ TEST(NodeInputTest, StringValueLiveAndUndoable)
|
||||
sizeof(buf)),
|
||||
6);
|
||||
EXPECT_STREQ(buf, "hello");
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(NodeGraphTest, ConnectDisconnectLive)
|
||||
@@ -424,10 +424,10 @@ TEST(NodeGraphTest, ConnectDisconnectUndoable)
|
||||
OakNodeNode *src = as_handle(&source);
|
||||
OakNodeNode *dst = as_handle(&dest);
|
||||
|
||||
OakUndoCommand *add = nullptr;
|
||||
OakUndoCommand add = {};
|
||||
EXPECT_EQ(oaknode_node_connect_undoable(src, dst, "float_in", &add),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(add, nullptr);
|
||||
ASSERT_NE(add.ctx, nullptr);
|
||||
|
||||
int connected = 0;
|
||||
EXPECT_EQ(oakundo_command_redo_now(add), OAKUNDO_OK);
|
||||
@@ -442,10 +442,10 @@ TEST(NodeGraphTest, ConnectDisconnectUndoable)
|
||||
// Redo again so the remove command has an edge to work on.
|
||||
EXPECT_EQ(oakundo_command_redo_now(add), OAKUNDO_OK);
|
||||
|
||||
OakUndoCommand *remove = nullptr;
|
||||
OakUndoCommand remove = {};
|
||||
EXPECT_EQ(oaknode_node_disconnect_undoable(dst, "float_in", &remove),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(remove, nullptr);
|
||||
ASSERT_NE(remove.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(remove), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_input_is_connected(dst, "float_in", &connected),
|
||||
OAKNODE_OK);
|
||||
@@ -458,8 +458,8 @@ TEST(NodeGraphTest, ConnectDisconnectUndoable)
|
||||
EXPECT_EQ(oaknode_node_disconnect_undoable(dst, "int_in", &remove),
|
||||
OAKNODE_E_NOT_FOUND);
|
||||
|
||||
oakundo_command_free(remove);
|
||||
oakundo_command_free(add);
|
||||
oakundo_command_free(&remove);
|
||||
oakundo_command_free(&add);
|
||||
}
|
||||
|
||||
TEST(NodeLinkTest, LinkUnlinkLiveAndUndoable)
|
||||
@@ -492,16 +492,16 @@ TEST(NodeLinkTest, LinkUnlinkLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_node_are_linked(a, b, &linked), OAKNODE_OK);
|
||||
EXPECT_EQ(linked, 0);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_link_undoable(a, b, 1, &command), OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_are_linked(a, b, &linked), OAKNODE_OK);
|
||||
EXPECT_EQ(linked, 1);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_are_linked(a, b, &linked), OAKNODE_OK);
|
||||
EXPECT_EQ(linked, 0);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_node_link(nullptr, b, &done), OAKNODE_E_INVALID);
|
||||
}
|
||||
@@ -534,11 +534,11 @@ TEST(NodeContextTest, PositionsLiveAndUndoable)
|
||||
EXPECT_EQ(entry, ctx);
|
||||
EXPECT_EQ(oaknode_node_context_node_at(n, 1, &entry), OAKNODE_E_NOT_FOUND);
|
||||
|
||||
OakUndoCommand *command = nullptr;
|
||||
OakUndoCommand command = {};
|
||||
EXPECT_EQ(oaknode_node_set_context_position_undoable(n, ctx, 1.0, 2.0, 0,
|
||||
&command),
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(command, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oaknode_node_get_context_position(n, ctx, &x, &y, &expanded),
|
||||
OAKNODE_OK);
|
||||
@@ -549,7 +549,7 @@ TEST(NodeContextTest, PositionsLiveAndUndoable)
|
||||
EXPECT_EQ(oaknode_node_get_context_position(n, ctx, &x, &y, &expanded),
|
||||
OAKNODE_OK);
|
||||
EXPECT_DOUBLE_EQ(x, 10.5);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
|
||||
EXPECT_EQ(oaknode_node_remove_from_context(n, ctx), OAKNODE_OK);
|
||||
EXPECT_EQ(oaknode_node_remove_from_context(n, ctx), OAKNODE_E_NOT_FOUND);
|
||||
|
||||
@@ -118,11 +118,11 @@ OakTaskTask *oaktask_create_project_import(OakNodeFolder *folder,
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktask_import_take_command(OakTaskTask *t)
|
||||
OakUndoCommand oaktask_import_take_command(OakTaskTask *t)
|
||||
{
|
||||
olive::ProjectImportTask *task = import_impl(t);
|
||||
if (!task) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
return task->take_command();
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ ProjectImportTask::ImageSequenceConfirmFn ProjectImportTask::confirm_callback_;
|
||||
ProjectImportTask::ProjectImportTask(
|
||||
OakNodeFolder *folder, OakNodeProject *project,
|
||||
const std::vector<std::string> &filenames)
|
||||
: command_(nullptr)
|
||||
: command_({})
|
||||
, folder_(folder)
|
||||
, project_(project)
|
||||
, filenames_(filenames)
|
||||
@@ -80,8 +80,8 @@ ProjectImportTask::ProjectImportTask(
|
||||
|
||||
ProjectImportTask::~ProjectImportTask()
|
||||
{
|
||||
if (command_) {
|
||||
oakundo_command_free(command_);
|
||||
if (command_.ctx) {
|
||||
oakundo_command_free(&command_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ const int &ProjectImportTask::get_file_count() const
|
||||
bool ProjectImportTask::run()
|
||||
{
|
||||
command_ = oakundo_command_init_multi();
|
||||
if (!command_) {
|
||||
if (!command_.ctx) {
|
||||
set_error("Failed to create import command");
|
||||
return false;
|
||||
}
|
||||
@@ -103,8 +103,8 @@ bool ProjectImportTask::run()
|
||||
import(folder_, filenames_, imported, command_);
|
||||
|
||||
if (is_cancelled()) {
|
||||
oakundo_command_free(command_);
|
||||
command_ = nullptr;
|
||||
oakundo_command_free(&command_);
|
||||
command_ = OakUndoCommand{};
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -112,7 +112,7 @@ bool ProjectImportTask::run()
|
||||
|
||||
void ProjectImportTask::import(OakNodeFolder *folder,
|
||||
const std::vector<std::string> &entries,
|
||||
int &counter, OakUndoCommand *parent_command)
|
||||
int &counter, OakUndoCommand parent_command)
|
||||
{
|
||||
std::vector<std::string> mutable_entries = entries;
|
||||
|
||||
@@ -336,11 +336,11 @@ void ProjectImportTask::validate_image_sequence(
|
||||
|
||||
void ProjectImportTask::add_item_to_folder(OakNodeFolder *folder,
|
||||
OakNodeNode *item,
|
||||
OakUndoCommand *command)
|
||||
OakUndoCommand command)
|
||||
{
|
||||
OakUndoCommand *child =
|
||||
OakUndoCommand child =
|
||||
oaknode_command_create_folder_add_child(folder, item);
|
||||
if (child) {
|
||||
if (child.ctx) {
|
||||
oakundo_command_multi_add_child(command, child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
|
||||
/** Take ownership of the import command. After this call the task no
|
||||
* longer owns (and will not free) the returned command. */
|
||||
OakUndoCommand *take_command()
|
||||
OakUndoCommand take_command()
|
||||
{
|
||||
OakUndoCommand *c = command_;
|
||||
command_ = nullptr;
|
||||
OakUndoCommand c = command_;
|
||||
command_ = OakUndoCommand{};
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -87,14 +87,14 @@ protected:
|
||||
private:
|
||||
void import(OakNodeFolder *folder,
|
||||
const std::vector<std::string> &entries, int &counter,
|
||||
OakUndoCommand *parent_command);
|
||||
OakUndoCommand parent_command);
|
||||
|
||||
void validate_image_sequence(OakNodeFootage *footage,
|
||||
std::vector<std::string> &info_list,
|
||||
size_t index);
|
||||
|
||||
void add_item_to_folder(OakNodeFolder *folder, OakNodeNode *item,
|
||||
OakUndoCommand *command);
|
||||
OakUndoCommand command);
|
||||
|
||||
static bool item_is_still_image_footage_only(OakNodeFootage *footage);
|
||||
|
||||
@@ -104,7 +104,7 @@ private:
|
||||
static int64_t get_image_sequence_limit(const std::string &start_fn,
|
||||
int64_t start, bool up);
|
||||
|
||||
OakUndoCommand *command_;
|
||||
OakUndoCommand command_;
|
||||
|
||||
OakNodeFolder *folder_;
|
||||
|
||||
|
||||
@@ -192,12 +192,12 @@ bool LoadOTIOTask::run()
|
||||
OakNodeNode *sequence_node = oaknode_sequence_as_node(sequence);
|
||||
|
||||
oaknode_project_add_node(project_, sequence_node);
|
||||
OakUndoCommand *add_seq = oaknode_command_create_folder_add_child(
|
||||
OakUndoCommand add_seq = oaknode_command_create_folder_add_child(
|
||||
oaknode_project_root(project_), sequence_node);
|
||||
if (add_seq) {
|
||||
if (add_seq.ctx) {
|
||||
oakundo_command_redo_now(add_seq);
|
||||
oakundo_command_free(add_seq);
|
||||
}
|
||||
oakundo_command_free(&add_seq);
|
||||
}
|
||||
|
||||
// Create a folder for this sequence's footage
|
||||
OakNodeFolder *sequence_footage =
|
||||
@@ -205,14 +205,14 @@ bool LoadOTIOTask::run()
|
||||
if (sequence_footage) {
|
||||
oaknode_node_set_label(oaknode_folder_as_node(sequence_footage),
|
||||
timeline->name().c_str());
|
||||
OakUndoCommand *add_folder =
|
||||
OakUndoCommand add_folder =
|
||||
oaknode_command_create_folder_add_child(
|
||||
oaknode_project_root(project_),
|
||||
oaknode_folder_as_node(sequence_footage));
|
||||
if (add_folder) {
|
||||
if (add_folder.ctx) {
|
||||
oakundo_command_redo_now(add_folder);
|
||||
oakundo_command_free(add_folder);
|
||||
}
|
||||
oakundo_command_free(&add_folder);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate through tracks
|
||||
@@ -238,12 +238,12 @@ bool LoadOTIOTask::run()
|
||||
OakNodeTrackList *track_list = nullptr;
|
||||
oaknode_sequence_get_track_list(sequence, track_type,
|
||||
&track_list);
|
||||
OakUndoCommand *add_track =
|
||||
OakUndoCommand add_track =
|
||||
oaktimeline_add_track_command(track_list);
|
||||
if (add_track) {
|
||||
if (add_track.ctx) {
|
||||
oakundo_command_redo_now(add_track);
|
||||
oakundo_command_free(add_track);
|
||||
}
|
||||
oakundo_command_free(&add_track);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
oaknode_tracklist_get_track_count(track_list, &count);
|
||||
@@ -403,15 +403,15 @@ bool LoadOTIOTask::run()
|
||||
label.c_str());
|
||||
|
||||
if (sequence_footage) {
|
||||
OakUndoCommand *add_footage =
|
||||
OakUndoCommand add_footage =
|
||||
oaknode_command_create_folder_add_child(
|
||||
sequence_footage,
|
||||
oaknode_footage_as_node(
|
||||
probed_item));
|
||||
if (add_footage) {
|
||||
if (add_footage.ctx) {
|
||||
oakundo_command_redo_now(add_footage);
|
||||
oakundo_command_free(add_footage);
|
||||
}
|
||||
oakundo_command_free(&add_footage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +164,9 @@ TEST_F(OakTaskFixture, ImportDemoFootage)
|
||||
OAKTASK_E_NOT_FOUND);
|
||||
|
||||
// The import command adds the footage to the folder; undo removes it
|
||||
OakUndoCommand *cmd = oaktask_import_take_command(t);
|
||||
ASSERT_NE(cmd, nullptr);
|
||||
EXPECT_EQ(oaktask_import_take_command(t), nullptr);
|
||||
OakUndoCommand cmd = oaktask_import_take_command(t);
|
||||
ASSERT_NE(cmd.ctx, nullptr);
|
||||
EXPECT_EQ(oaktask_import_take_command(t).ctx, nullptr);
|
||||
|
||||
EXPECT_EQ(oaknode_folder_child_count(folder), 0); // not yet redone
|
||||
|
||||
@@ -176,7 +176,7 @@ TEST_F(OakTaskFixture, ImportDemoFootage)
|
||||
oakundo_command_undo_now(cmd);
|
||||
EXPECT_EQ(oaknode_folder_child_count(folder), 0);
|
||||
|
||||
oakundo_command_free(cmd);
|
||||
oakundo_command_free(&cmd);
|
||||
oaktask_task_free(t);
|
||||
|
||||
EXPECT_EQ(oaktask_create_project_import(nullptr, project_, urls, 1),
|
||||
@@ -385,11 +385,11 @@ TEST(OakTaskOTIO, SaveLoadRoundTrip)
|
||||
|
||||
OakNodeFolder *root = oaknode_project_root(project);
|
||||
ASSERT_NE(root, nullptr);
|
||||
OakUndoCommand *add_seq = oaknode_command_create_folder_add_child(
|
||||
OakUndoCommand add_seq = oaknode_command_create_folder_add_child(
|
||||
root, oaknode_sequence_as_node(sequence));
|
||||
ASSERT_NE(add_seq, nullptr);
|
||||
ASSERT_NE(add_seq.ctx, nullptr);
|
||||
oakundo_command_redo_now(add_seq);
|
||||
oakundo_command_free(add_seq);
|
||||
oakundo_command_free(&add_seq);
|
||||
|
||||
std::string path =
|
||||
(std::filesystem::temp_directory_path() / "oaktask_otio_test.otio")
|
||||
|
||||
+36
-40
@@ -32,16 +32,12 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
OakUndoCommand *wrap_command(olive::UndoCommand *command)
|
||||
OakUndoCommand wrap_command(olive::UndoCommand *command)
|
||||
{
|
||||
if (!command) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand{command, true};
|
||||
if (!handle) {
|
||||
delete command;
|
||||
}
|
||||
return handle;
|
||||
return oakundo_capi::make_command_handle(command, true);
|
||||
}
|
||||
|
||||
olive::core::Rational rat(int64_t n, int64_t d)
|
||||
@@ -56,73 +52,73 @@ olive::Timeline::MovementMode to_mode(int mode)
|
||||
|
||||
} // namespace
|
||||
|
||||
OakUndoCommand *oaktimeline_add_track_command(OakNodeTrackList *list)
|
||||
OakUndoCommand oaktimeline_add_track_command(OakNodeTrackList *list)
|
||||
{
|
||||
if (!list) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(new olive::TimelineAddTrackCommand(list));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_remove_track_command(OakNodeTrack *track)
|
||||
OakUndoCommand oaktimeline_remove_track_command(OakNodeTrack *track)
|
||||
{
|
||||
if (!track) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(new olive::TimelineRemoveTrackCommand(track));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_place_block_command(OakNodeTrackList *list,
|
||||
OakUndoCommand oaktimeline_place_block_command(OakNodeTrackList *list,
|
||||
int track_index,
|
||||
OakNodeBlock *block,
|
||||
int64_t in_num,
|
||||
int64_t in_den)
|
||||
{
|
||||
if (!list || !block) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(new olive::TrackPlaceBlockCommand(
|
||||
list, track_index, block, rat(in_num, in_den)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_replace_block_with_gap_command(
|
||||
OakUndoCommand oaktimeline_replace_block_with_gap_command(
|
||||
OakNodeTrack *track, OakNodeBlock *block)
|
||||
{
|
||||
if (!track || !block) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(
|
||||
new olive::TrackReplaceBlockWithGapCommand(track, block));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_trim_command(OakNodeTrack *track,
|
||||
OakUndoCommand oaktimeline_trim_command(OakNodeTrack *track,
|
||||
OakNodeBlock *block,
|
||||
int64_t new_length_num,
|
||||
int64_t new_length_den, int mode)
|
||||
{
|
||||
if (!track || !block || (mode != OAKTIMELINE_MOVEMENT_TRIM_IN &&
|
||||
mode != OAKTIMELINE_MOVEMENT_TRIM_OUT)) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -131,16 +127,16 @@ OakUndoCommand *oaktimeline_trim_command(OakNodeTrack *track,
|
||||
rat(new_length_num, new_length_den),
|
||||
to_mode(mode)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_split_command(OakNodeBlock *const *blocks,
|
||||
OakUndoCommand oaktimeline_split_command(OakNodeBlock *const *blocks,
|
||||
int count, int64_t point_num,
|
||||
int64_t point_den)
|
||||
{
|
||||
if (!blocks || count <= 0) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -153,17 +149,17 @@ OakUndoCommand *oaktimeline_split_command(OakNodeBlock *const *blocks,
|
||||
}
|
||||
return wrap_command(multi);
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_split_preserving_links_command(
|
||||
OakUndoCommand oaktimeline_split_preserving_links_command(
|
||||
OakNodeBlock *const *blocks, int count, const int64_t *point_nums,
|
||||
const int64_t *point_dens, int time_count)
|
||||
{
|
||||
if (!blocks || count <= 0 || !point_nums || !point_dens ||
|
||||
time_count <= 0) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -176,18 +172,18 @@ OakUndoCommand *oaktimeline_split_preserving_links_command(
|
||||
return wrap_command(new olive::BlockSplitPreservingLinksCommand(
|
||||
block_vec, times));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_ripple_delete_gaps_command(
|
||||
OakUndoCommand oaktimeline_ripple_delete_gaps_command(
|
||||
OakNodeSequence *sequence, const int64_t *in_nums,
|
||||
const int64_t *in_dens, const int64_t *out_nums,
|
||||
const int64_t *out_dens, OakNodeTrack *const *tracks, int range_count)
|
||||
{
|
||||
if (!sequence || !in_nums || !in_dens || !out_nums || !out_dens ||
|
||||
!tracks || range_count <= 0) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -203,17 +199,17 @@ OakUndoCommand *oaktimeline_ripple_delete_gaps_command(
|
||||
new olive::TimelineRippleDeleteGapsAtRegionsCommand(sequence,
|
||||
regions));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_slide_command(
|
||||
OakUndoCommand oaktimeline_slide_command(
|
||||
OakNodeTrack *track, OakNodeBlock *const *blocks, int block_count,
|
||||
OakNodeBlock *in_adjacent, OakNodeBlock *out_adjacent,
|
||||
int64_t movement_num, int64_t movement_den)
|
||||
{
|
||||
if (!track || !blocks || block_count <= 0) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -222,16 +218,16 @@ OakUndoCommand *oaktimeline_slide_command(
|
||||
track, block_vec, in_adjacent, out_adjacent,
|
||||
rat(movement_num, movement_den)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_ripple_remove_area_command(
|
||||
OakUndoCommand oaktimeline_ripple_remove_area_command(
|
||||
OakNodeTrack *track, int64_t in_num, int64_t in_den, int64_t out_num,
|
||||
int64_t out_den)
|
||||
{
|
||||
if (!track) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -239,18 +235,18 @@ OakUndoCommand *oaktimeline_ripple_remove_area_command(
|
||||
track, olive::core::TimeRange(rat(in_num, in_den),
|
||||
rat(out_num, out_den))));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_insert_gaps_command(OakNodeTrackList *list,
|
||||
OakUndoCommand oaktimeline_insert_gaps_command(OakNodeTrackList *list,
|
||||
int64_t point_num,
|
||||
int64_t point_den,
|
||||
int64_t length_num,
|
||||
int64_t length_den)
|
||||
{
|
||||
if (!list) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -258,6 +254,6 @@ OakUndoCommand *oaktimeline_insert_gaps_command(OakNodeTrackList *list,
|
||||
new olive::TrackListInsertGaps(list, rat(point_num, point_den),
|
||||
rat(length_num, length_den)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,16 +43,12 @@ OakTimelineMarkerList *wrap(olive::TimelineMarkerList *l)
|
||||
return reinterpret_cast<OakTimelineMarkerList *>(l);
|
||||
}
|
||||
|
||||
OakUndoCommand *wrap_command(olive::UndoCommand *command)
|
||||
OakUndoCommand wrap_command(olive::UndoCommand *command)
|
||||
{
|
||||
if (!command) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand{command, true};
|
||||
if (!handle) {
|
||||
delete command;
|
||||
}
|
||||
return handle;
|
||||
return oakundo_capi::make_command_handle(command, true);
|
||||
}
|
||||
|
||||
olive::core::Rational rat(int n, int d)
|
||||
@@ -130,12 +126,12 @@ int oaktimeline_marker_at(const OakTimelineMarkerList *list, int index,
|
||||
return needed;
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_marker_add_command(
|
||||
OakUndoCommand oaktimeline_marker_add_command(
|
||||
OakTimelineMarkerList *list, int in_num, int in_den, int out_num,
|
||||
int out_den, const char *name, int color)
|
||||
{
|
||||
if (!list) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -145,32 +141,32 @@ OakUndoCommand *oaktimeline_marker_add_command(
|
||||
rat(int(out_num), int(out_den))),
|
||||
name ? name : "", color));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_marker_remove_at_command(
|
||||
OakUndoCommand oaktimeline_marker_remove_at_command(
|
||||
OakTimelineMarkerList *list, int index)
|
||||
{
|
||||
olive::TimelineMarker *m = marker_at(list, index);
|
||||
if (!m) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(new olive::MarkerRemoveCommand(m, impl(list)));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_marker_set_time_command(
|
||||
OakUndoCommand oaktimeline_marker_set_time_command(
|
||||
OakTimelineMarkerList *list, int index, int in_num, int in_den,
|
||||
int out_num, int out_den)
|
||||
{
|
||||
olive::TimelineMarker *m = marker_at(list, index);
|
||||
if (!m) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -178,16 +174,16 @@ OakUndoCommand *oaktimeline_marker_set_time_command(
|
||||
m, olive::core::TimeRange(rat(int(in_num), int(in_den)),
|
||||
rat(int(out_num), int(out_den)))));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_marker_set_props_command(
|
||||
OakUndoCommand oaktimeline_marker_set_props_command(
|
||||
OakTimelineMarkerList *list, int index, int color, const char *name)
|
||||
{
|
||||
olive::TimelineMarker *m = marker_at(list, index);
|
||||
if (!m || (color < 0 && !name)) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -202,7 +198,7 @@ OakUndoCommand *oaktimeline_marker_set_props_command(
|
||||
}
|
||||
return wrap_command(new olive::MarkerChangeNameCommand(m, name));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,16 +39,12 @@ const olive::TimelineWorkArea *impl(const OakTimelineWorkArea *h)
|
||||
return reinterpret_cast<const olive::TimelineWorkArea *>(h);
|
||||
}
|
||||
|
||||
OakUndoCommand *wrap_command(olive::UndoCommand *command)
|
||||
OakUndoCommand wrap_command(olive::UndoCommand *command)
|
||||
{
|
||||
if (!command) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand{command, true};
|
||||
if (!handle) {
|
||||
delete command;
|
||||
}
|
||||
return handle;
|
||||
return oakundo_capi::make_command_handle(command, true);
|
||||
}
|
||||
|
||||
olive::core::Rational rat(int64_t n, int64_t d)
|
||||
@@ -113,13 +109,13 @@ int oaktimeline_workarea_set_range(OakTimelineWorkArea *w, int in_num,
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_workarea_set_range_command(
|
||||
OakUndoCommand oaktimeline_workarea_set_range_command(
|
||||
OakTimelineWorkArea *w, int in_num, int in_den, int out_num,
|
||||
int out_den, int old_in_num, int old_in_den, int old_out_num,
|
||||
int old_out_den)
|
||||
{
|
||||
if (!w) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -129,22 +125,22 @@ OakUndoCommand *oaktimeline_workarea_set_range_command(
|
||||
return wrap_command(
|
||||
new olive::WorkareaSetRangeCommand(impl(w), range, old_range));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oaktimeline_workarea_set_enabled_command(
|
||||
OakUndoCommand oaktimeline_workarea_set_enabled_command(
|
||||
OakTimelineWorkArea *w, int enabled)
|
||||
{
|
||||
if (!w) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
return wrap_command(
|
||||
new olive::WorkareaSetEnabledCommand(impl(w), enabled != 0));
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,29 +40,29 @@ inline bool node_can_be_removed(OakNodeBlock *b)
|
||||
return node_can_be_removed(oaknode_block_as_node(b));
|
||||
}
|
||||
|
||||
inline OakUndoCommand *create_remove_command(OakNodeNode *n)
|
||||
inline OakUndoCommand create_remove_command(OakNodeNode *n)
|
||||
{
|
||||
return oaknode_command_create_remove_node(n);
|
||||
}
|
||||
|
||||
inline OakUndoCommand *create_remove_command(OakNodeBlock *b)
|
||||
inline OakUndoCommand create_remove_command(OakNodeBlock *b)
|
||||
{
|
||||
return oaknode_command_create_remove_node(oaknode_block_as_node(b));
|
||||
}
|
||||
|
||||
inline OakUndoCommand *create_and_run_remove_command(OakNodeNode *n)
|
||||
inline OakUndoCommand create_and_run_remove_command(OakNodeNode *n)
|
||||
{
|
||||
OakUndoCommand *command = create_remove_command(n);
|
||||
OakUndoCommand command = create_remove_command(n);
|
||||
oakundo_command_redo_now(command);
|
||||
return command;
|
||||
}
|
||||
|
||||
inline OakUndoCommand *create_and_run_remove_command(OakNodeBlock *b)
|
||||
inline OakUndoCommand create_and_run_remove_command(OakNodeBlock *b)
|
||||
{
|
||||
return create_and_run_remove_command(oaknode_block_as_node(b));
|
||||
}
|
||||
|
||||
inline void free_remove_command(OakUndoCommand *command)
|
||||
inline void free_command_handle(OakUndoCommand *command)
|
||||
{
|
||||
oakundo_command_free(command);
|
||||
}
|
||||
@@ -73,35 +73,40 @@ inline void free_remove_command(OakUndoCommand *command)
|
||||
*/
|
||||
class CHandleCommandWrapper : public UndoCommand {
|
||||
public:
|
||||
CHandleCommandWrapper(OakUndoCommand *command)
|
||||
CHandleCommandWrapper(OakUndoCommand command)
|
||||
: command_(command)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CHandleCommandWrapper() override
|
||||
{
|
||||
if (command_) {
|
||||
oakundo_command_free(command_);
|
||||
if (command_.ctx) {
|
||||
oakundo_command_free(&command_);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_valid() const
|
||||
{
|
||||
return command_.ctx != nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void redo() override
|
||||
{
|
||||
if (command_) {
|
||||
if (command_.ctx) {
|
||||
oakundo_command_redo_now(command_);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void undo() override
|
||||
{
|
||||
if (command_) {
|
||||
if (command_.ctx) {
|
||||
oakundo_command_undo_now(command_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
OakUndoCommand *command_;
|
||||
OakUndoCommand command_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ const char *k_merge_blend_input = "blend_in";
|
||||
const char *k_math_param_a_input = "param_a_in";
|
||||
const char *k_math_param_b_input = "param_b_in";
|
||||
|
||||
void add_multi_child(OakUndoCommand *multi, OakUndoCommand *child)
|
||||
void add_multi_child(OakUndoCommand multi, OakUndoCommand child)
|
||||
{
|
||||
if (multi && child) {
|
||||
if (multi.ctx && child.ctx) {
|
||||
oakundo_command_multi_add_child(multi, child);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ TimelineAddTrackCommand::TimelineAddTrackCommand(
|
||||
: timeline_(timeline)
|
||||
, track_(nullptr)
|
||||
, merge_(nullptr)
|
||||
, position_command_(nullptr)
|
||||
, position_command_({})
|
||||
, automerge_tracks_(automerge_tracks)
|
||||
, track_orphaned_(false)
|
||||
, merge_orphaned_(false)
|
||||
@@ -164,8 +164,8 @@ TimelineAddTrackCommand::TimelineAddTrackCommand(
|
||||
|
||||
TimelineAddTrackCommand::~TimelineAddTrackCommand()
|
||||
{
|
||||
if (position_command_) {
|
||||
oakundo_command_free(position_command_);
|
||||
if (position_command_.ctx) {
|
||||
oakundo_command_free(&position_command_);
|
||||
}
|
||||
if (track_orphaned_ && track_) {
|
||||
oaknode_track_free(track_);
|
||||
@@ -221,7 +221,7 @@ void TimelineAddTrackCommand::redo()
|
||||
position_factor = -position_factor;
|
||||
}
|
||||
bool create_pos_command =
|
||||
(!position_command_ && (type == OAKNODE_TRACK_TYPE_VIDEO ||
|
||||
(!position_command_.ctx && (type == OAKNODE_TRACK_TYPE_VIDEO ||
|
||||
type == OAKNODE_TRACK_TYPE_AUDIO));
|
||||
if (create_pos_command) {
|
||||
position_command_ = oakundo_command_init_multi();
|
||||
@@ -250,19 +250,19 @@ void TimelineAddTrackCommand::redo()
|
||||
}
|
||||
oaknode_node_connect(track_node, merge_, blend_input_.c_str());
|
||||
|
||||
if (create_pos_command && position_command_) {
|
||||
if (create_pos_command && position_command_.ctx) {
|
||||
double sx = 0, sy = 0;
|
||||
oaknode_node_get_context_position(sequence_node, sequence_node,
|
||||
&sx, &sy, NULL);
|
||||
|
||||
OakUndoCommand *child = nullptr;
|
||||
OakUndoCommand child = {};
|
||||
if (oaknode_node_set_context_position_undoable(
|
||||
track_node, sequence_node, sx - 1,
|
||||
sy - position_factor, 0,
|
||||
&child) == OAKNODE_OK) {
|
||||
add_multi_child(position_command_, child);
|
||||
}
|
||||
child = nullptr;
|
||||
child = OakUndoCommand{};
|
||||
if (oaknode_node_set_context_position_undoable(
|
||||
merge_, sequence_node, sx, sy, 0, &child) == OAKNODE_OK) {
|
||||
add_multi_child(position_command_, child);
|
||||
@@ -285,14 +285,14 @@ void TimelineAddTrackCommand::redo()
|
||||
oaknode_node_connect(track_node, sequence_node,
|
||||
direct_input_.c_str());
|
||||
|
||||
if (create_pos_command && position_command_) {
|
||||
if (create_pos_command && position_command_.ctx) {
|
||||
// Just position directly next to the context node
|
||||
double sx = 0, sy = 0;
|
||||
oaknode_node_get_context_position(sequence_node,
|
||||
sequence_node, &sx, &sy,
|
||||
NULL);
|
||||
|
||||
OakUndoCommand *child = nullptr;
|
||||
OakUndoCommand child = {};
|
||||
if (oaknode_node_set_context_position_undoable(
|
||||
track_node, sequence_node, sx - 1,
|
||||
sy + position_factor, 0,
|
||||
@@ -304,14 +304,14 @@ void TimelineAddTrackCommand::redo()
|
||||
}
|
||||
|
||||
// Run position command if we created one
|
||||
if (position_command_) {
|
||||
if (position_command_.ctx) {
|
||||
oakundo_command_redo_now(position_command_);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineAddTrackCommand::undo()
|
||||
{
|
||||
if (position_command_) {
|
||||
if (position_command_.ctx) {
|
||||
oakundo_command_undo_now(position_command_);
|
||||
}
|
||||
|
||||
@@ -371,8 +371,8 @@ void TimelineAddTrackCommand::undo()
|
||||
//
|
||||
TransitionRemoveCommand::~TransitionRemoveCommand()
|
||||
{
|
||||
if (remove_command_) {
|
||||
free_remove_command(remove_command_);
|
||||
if (remove_command_.ctx) {
|
||||
free_command_handle(&remove_command_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ void TransitionRemoveCommand::redo()
|
||||
oaknode_track_ripple_remove_block(track_, block_);
|
||||
|
||||
if (remove_from_graph_) {
|
||||
if (!remove_command_) {
|
||||
if (!remove_command_.ctx) {
|
||||
remove_command_ = create_remove_command(block_);
|
||||
}
|
||||
|
||||
@@ -789,8 +789,8 @@ void TrackReplaceBlockWithGapCommand::create_remove_transition_command_if_necess
|
||||
//
|
||||
TimelineRemoveTrackCommand::~TimelineRemoveTrackCommand()
|
||||
{
|
||||
if (remove_command_) {
|
||||
free_remove_command(remove_command_);
|
||||
if (remove_command_.ctx) {
|
||||
free_command_handle(&remove_command_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,7 +996,7 @@ void TimelineAddDefaultTransitionCommand::add_transition(
|
||||
new TrackInsertBlockAfterCommand(t, transition, insert_after));
|
||||
|
||||
// Connect
|
||||
OakUndoCommand *edge_command = nullptr;
|
||||
OakUndoCommand edge_command = {};
|
||||
switch (mode) {
|
||||
case k_in:
|
||||
if (oaknode_node_connect_undoable(
|
||||
@@ -1015,7 +1015,7 @@ void TimelineAddDefaultTransitionCommand::add_transition(
|
||||
}
|
||||
/* fall through */
|
||||
case k_out:
|
||||
edge_command = nullptr;
|
||||
edge_command = OakUndoCommand{};
|
||||
if (oaknode_node_connect_undoable(
|
||||
oaknode_block_as_node(c), p,
|
||||
OAKNODE_TRANSITION_OUT_BLOCK_INPUT,
|
||||
|
||||
@@ -135,7 +135,7 @@ private:
|
||||
|
||||
std::string direct_input_;
|
||||
|
||||
OakUndoCommand *position_command_;
|
||||
OakUndoCommand position_command_;
|
||||
|
||||
bool automerge_tracks_;
|
||||
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
: track_(track)
|
||||
, list_(nullptr)
|
||||
, index_(0)
|
||||
, remove_command_(nullptr)
|
||||
, remove_command_({})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ private:
|
||||
|
||||
int index_;
|
||||
|
||||
OakUndoCommand *remove_command_;
|
||||
OakUndoCommand remove_command_;
|
||||
};
|
||||
|
||||
class TransitionRemoveCommand : public UndoCommand {
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
, out_block_(nullptr)
|
||||
, in_block_(nullptr)
|
||||
, remove_from_graph_(remove_from_graph)
|
||||
, remove_command_(nullptr)
|
||||
, remove_command_({})
|
||||
{
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ private:
|
||||
OakNodeBlock *in_block_;
|
||||
|
||||
bool remove_from_graph_;
|
||||
OakUndoCommand *remove_command_;
|
||||
OakUndoCommand remove_command_;
|
||||
};
|
||||
|
||||
class TrackReplaceBlockWithGapCommand : public UndoCommand {
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace olive
|
||||
//
|
||||
BlockTrimCommand::~BlockTrimCommand()
|
||||
{
|
||||
if (deleted_adjacent_command_) {
|
||||
free_remove_command(deleted_adjacent_command_);
|
||||
if (deleted_adjacent_command_.ctx) {
|
||||
free_command_handle(&deleted_adjacent_command_);
|
||||
}
|
||||
if (adjacent_orphaned_ && adjacent_) {
|
||||
oaknode_block_free(adjacent_);
|
||||
@@ -68,7 +68,7 @@ void BlockTrimCommand::redo()
|
||||
|
||||
// It no longer inputs/outputs anything, remove it
|
||||
if (remove_block_from_graph_ && node_can_be_removed(adjacent_)) {
|
||||
if (!deleted_adjacent_command_) {
|
||||
if (!deleted_adjacent_command_.ctx) {
|
||||
deleted_adjacent_command_ =
|
||||
create_and_run_remove_command(adjacent_);
|
||||
} else {
|
||||
@@ -102,7 +102,7 @@ void BlockTrimCommand::undo()
|
||||
adjacent_orphaned_ = true;
|
||||
} else {
|
||||
if (we_removed_adjacent_) {
|
||||
if (deleted_adjacent_command_) {
|
||||
if (deleted_adjacent_command_.ctx) {
|
||||
// We deleted adjacent, restore it now
|
||||
oakundo_command_undo_now(deleted_adjacent_command_);
|
||||
}
|
||||
@@ -188,11 +188,11 @@ void BlockTrimCommand::prepare()
|
||||
//
|
||||
TrackSlideCommand::~TrackSlideCommand()
|
||||
{
|
||||
if (in_adjacent_remove_command_) {
|
||||
free_remove_command(in_adjacent_remove_command_);
|
||||
if (in_adjacent_remove_command_.ctx) {
|
||||
free_command_handle(&in_adjacent_remove_command_);
|
||||
}
|
||||
if (out_adjacent_remove_command_) {
|
||||
free_remove_command(out_adjacent_remove_command_);
|
||||
if (out_adjacent_remove_command_.ctx) {
|
||||
free_command_handle(&out_adjacent_remove_command_);
|
||||
}
|
||||
if (in_adjacent_orphaned_ && in_adjacent_) {
|
||||
oaknode_block_free(in_adjacent_);
|
||||
@@ -216,7 +216,7 @@ void TrackSlideCommand::redo()
|
||||
oaknode_track_ripple_remove_block(track_, in_adjacent_);
|
||||
|
||||
if (node_can_be_removed(in_adjacent_)) {
|
||||
if (!in_adjacent_remove_command_) {
|
||||
if (!in_adjacent_remove_command_.ctx) {
|
||||
in_adjacent_remove_command_ =
|
||||
create_remove_command(in_adjacent_);
|
||||
}
|
||||
@@ -244,7 +244,7 @@ void TrackSlideCommand::redo()
|
||||
oaknode_track_ripple_remove_block(track_, out_adjacent_);
|
||||
|
||||
if (node_can_be_removed(out_adjacent_)) {
|
||||
if (!out_adjacent_remove_command_) {
|
||||
if (!out_adjacent_remove_command_.ctx) {
|
||||
out_adjacent_remove_command_ =
|
||||
create_remove_command(out_adjacent_);
|
||||
}
|
||||
@@ -270,7 +270,7 @@ void TrackSlideCommand::undo()
|
||||
block_remove_from_graph(in_adjacent_, track_);
|
||||
in_adjacent_orphaned_ = true;
|
||||
} else if (we_removed_in_adjacent_) {
|
||||
if (in_adjacent_remove_command_) {
|
||||
if (in_adjacent_remove_command_.ctx) {
|
||||
// We removed this, so we can restore it now
|
||||
oakundo_command_undo_now(in_adjacent_remove_command_);
|
||||
}
|
||||
@@ -290,7 +290,7 @@ void TrackSlideCommand::undo()
|
||||
block_remove_from_graph(out_adjacent_, track_);
|
||||
out_adjacent_orphaned_ = true;
|
||||
} else if (we_removed_out_adjacent_) {
|
||||
if (out_adjacent_remove_command_) {
|
||||
if (out_adjacent_remove_command_.ctx) {
|
||||
oakundo_command_undo_now(out_adjacent_remove_command_);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
, block_(block)
|
||||
, new_length_(new_length)
|
||||
, mode_(mode)
|
||||
, deleted_adjacent_command_(nullptr)
|
||||
, deleted_adjacent_command_({})
|
||||
, trim_is_a_roll_edit_(false)
|
||||
, remove_block_from_graph_(true)
|
||||
, doing_nothing_(false)
|
||||
@@ -109,7 +109,7 @@ private:
|
||||
bool needs_adjacent_;
|
||||
bool we_created_adjacent_;
|
||||
bool we_removed_adjacent_;
|
||||
OakUndoCommand *deleted_adjacent_command_;
|
||||
OakUndoCommand deleted_adjacent_command_;
|
||||
|
||||
bool trim_is_a_roll_edit_;
|
||||
bool remove_block_from_graph_;
|
||||
@@ -130,12 +130,12 @@ public:
|
||||
, we_created_in_adjacent_(false)
|
||||
, we_removed_in_adjacent_(false)
|
||||
, in_adjacent_(in_adjacent)
|
||||
, in_adjacent_remove_command_(nullptr)
|
||||
, in_adjacent_remove_command_({})
|
||||
, in_adjacent_orphaned_(false)
|
||||
, we_created_out_adjacent_(false)
|
||||
, we_removed_out_adjacent_(false)
|
||||
, out_adjacent_(out_adjacent)
|
||||
, out_adjacent_remove_command_(nullptr)
|
||||
, out_adjacent_remove_command_({})
|
||||
, out_adjacent_orphaned_(false)
|
||||
{
|
||||
}
|
||||
@@ -157,12 +157,12 @@ private:
|
||||
bool we_created_in_adjacent_;
|
||||
bool we_removed_in_adjacent_;
|
||||
OakNodeBlock *in_adjacent_;
|
||||
OakUndoCommand *in_adjacent_remove_command_;
|
||||
OakUndoCommand in_adjacent_remove_command_;
|
||||
bool in_adjacent_orphaned_;
|
||||
bool we_created_out_adjacent_;
|
||||
bool we_removed_out_adjacent_;
|
||||
OakNodeBlock *out_adjacent_;
|
||||
OakUndoCommand *out_adjacent_remove_command_;
|
||||
OakUndoCommand out_adjacent_remove_command_;
|
||||
bool out_adjacent_orphaned_;
|
||||
};
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ TrackRippleRemoveAreaCommand::TrackRippleRemoveAreaCommand(
|
||||
TrackRippleRemoveAreaCommand::~TrackRippleRemoveAreaCommand()
|
||||
{
|
||||
delete splice_split_command_;
|
||||
for (OakUndoCommand *c : remove_block_commands_) {
|
||||
free_remove_command(c);
|
||||
for (OakUndoCommand &c : remove_block_commands_) {
|
||||
free_command_handle(&c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ void TrackRippleRemoveAreaCommand::redo()
|
||||
}
|
||||
}
|
||||
|
||||
for (OakUndoCommand *c : remove_block_commands_) {
|
||||
for (OakUndoCommand &c : remove_block_commands_) {
|
||||
oakundo_command_redo_now(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
bool allow_splitting_gaps_;
|
||||
|
||||
BlockSplitCommand *splice_split_command_;
|
||||
std::vector<OakUndoCommand *> remove_block_commands_;
|
||||
std::vector<OakUndoCommand > remove_block_commands_;
|
||||
};
|
||||
|
||||
class TrackListRippleRemoveAreaCommand : public UndoCommand {
|
||||
|
||||
@@ -83,8 +83,8 @@ private:
|
||||
//
|
||||
BlockSplitCommand::~BlockSplitCommand()
|
||||
{
|
||||
if (reconnect_tree_command_) {
|
||||
oakundo_command_free(reconnect_tree_command_);
|
||||
if (reconnect_tree_command_.ctx) {
|
||||
oakundo_command_free(&reconnect_tree_command_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ void BlockSplitCommand::redo()
|
||||
|
||||
assert(point_ > block_in && point_ < block_out);
|
||||
|
||||
if (reconnect_tree_command_) {
|
||||
if (reconnect_tree_command_.ctx) {
|
||||
oakundo_command_redo_now(reconnect_tree_command_);
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ void BlockSplitCommand::undo()
|
||||
oaknode_track_ripple_remove_block(track, new_block_);
|
||||
|
||||
// If we ran a reconnect command, disconnect now
|
||||
if (reconnect_tree_command_) {
|
||||
if (reconnect_tree_command_.ctx) {
|
||||
oakundo_command_undo_now(reconnect_tree_command_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
: block_(block)
|
||||
, new_block_(nullptr)
|
||||
, point_(point)
|
||||
, reconnect_tree_command_(nullptr)
|
||||
, reconnect_tree_command_({})
|
||||
, moved_transition_(nullptr)
|
||||
{
|
||||
}
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
Rational old_length_;
|
||||
Rational point_;
|
||||
|
||||
OakUndoCommand *reconnect_tree_command_;
|
||||
OakUndoCommand reconnect_tree_command_;
|
||||
|
||||
OakNodeBlock *moved_transition_;
|
||||
std::string moved_transition_input_;
|
||||
|
||||
@@ -80,11 +80,11 @@ TEST_F(TimelineSequenceFixture, MarkerAddCountAtRemove)
|
||||
EXPECT_EQ(oaktimeline_marker_count(list, nullptr),
|
||||
OAKTIMELINE_E_INVALID);
|
||||
|
||||
OakUndoCommand *cmd =
|
||||
OakUndoCommand cmd =
|
||||
oaktimeline_marker_add_command(list, 1, 2, 3, 4, "mark", 5);
|
||||
ASSERT_NE(cmd, nullptr);
|
||||
ASSERT_NE(cmd.ctx, nullptr);
|
||||
oakundo_command_redo_now(cmd);
|
||||
oakundo_command_free(cmd);
|
||||
oakundo_command_free(&cmd);
|
||||
|
||||
EXPECT_EQ(oaktimeline_marker_count(list, &count), OAKTIMELINE_OK);
|
||||
ASSERT_EQ(count, 1);
|
||||
@@ -108,15 +108,15 @@ TEST_F(TimelineSequenceFixture, MarkerAddCountAtRemove)
|
||||
&out_d, &color, name, sizeof(name)),
|
||||
OAKTIMELINE_E_INVALID);
|
||||
|
||||
OakUndoCommand *rm = oaktimeline_marker_remove_at_command(list, 0);
|
||||
ASSERT_NE(rm, nullptr);
|
||||
OakUndoCommand rm = oaktimeline_marker_remove_at_command(list, 0);
|
||||
ASSERT_NE(rm.ctx, nullptr);
|
||||
oakundo_command_redo_now(rm);
|
||||
oakundo_command_free(rm);
|
||||
oakundo_command_free(&rm);
|
||||
|
||||
EXPECT_EQ(oaktimeline_marker_count(list, &count), OAKTIMELINE_OK);
|
||||
EXPECT_EQ(count, 0);
|
||||
|
||||
EXPECT_EQ(oaktimeline_marker_remove_at_command(list, 4), nullptr);
|
||||
EXPECT_EQ(oaktimeline_marker_remove_at_command(list, 4).ctx, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TimelineSequenceFixture, MarkerSetTimeAndPropsUndo)
|
||||
@@ -124,15 +124,15 @@ TEST_F(TimelineSequenceFixture, MarkerSetTimeAndPropsUndo)
|
||||
OakTimelineMarkerList *list = oaktimeline_marker_list_of(node_);
|
||||
ASSERT_NE(list, nullptr);
|
||||
|
||||
OakUndoCommand *add =
|
||||
OakUndoCommand add =
|
||||
oaktimeline_marker_add_command(list, 0, 1, 1, 1, "a", 1);
|
||||
ASSERT_NE(add, nullptr);
|
||||
ASSERT_NE(add.ctx, nullptr);
|
||||
oakundo_command_redo_now(add);
|
||||
oakundo_command_free(add);
|
||||
oakundo_command_free(&add);
|
||||
|
||||
OakUndoCommand *set_time =
|
||||
OakUndoCommand set_time =
|
||||
oaktimeline_marker_set_time_command(list, 0, 10, 1, 20, 1);
|
||||
ASSERT_NE(set_time, nullptr);
|
||||
ASSERT_NE(set_time.ctx, nullptr);
|
||||
oakundo_command_redo_now(set_time);
|
||||
|
||||
int in_n = 0;
|
||||
@@ -146,13 +146,13 @@ TEST_F(TimelineSequenceFixture, MarkerSetTimeAndPropsUndo)
|
||||
NULL, NULL, 0),
|
||||
0);
|
||||
EXPECT_EQ(in_n, 0);
|
||||
oakundo_command_free(set_time);
|
||||
oakundo_command_free(&set_time);
|
||||
|
||||
OakUndoCommand *props =
|
||||
OakUndoCommand props =
|
||||
oaktimeline_marker_set_props_command(list, 0, 7, "renamed");
|
||||
ASSERT_NE(props, nullptr);
|
||||
ASSERT_NE(props.ctx, nullptr);
|
||||
oakundo_command_redo_now(props);
|
||||
oakundo_command_free(props);
|
||||
oakundo_command_free(&props);
|
||||
|
||||
int color = 0;
|
||||
char name[32];
|
||||
@@ -162,9 +162,11 @@ TEST_F(TimelineSequenceFixture, MarkerSetTimeAndPropsUndo)
|
||||
EXPECT_EQ(color, 7);
|
||||
EXPECT_STREQ(name, "renamed");
|
||||
|
||||
EXPECT_EQ(oaktimeline_marker_set_props_command(list, 0, -1, NULL),
|
||||
EXPECT_EQ(oaktimeline_marker_set_props_command(list, 0, -1, NULL)
|
||||
.ctx,
|
||||
nullptr);
|
||||
EXPECT_EQ(oaktimeline_marker_set_time_command(list, 9, 0, 1, 1, 1),
|
||||
EXPECT_EQ(oaktimeline_marker_set_time_command(list, 9, 0, 1, 1, 1)
|
||||
.ctx,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -173,11 +175,11 @@ TEST_F(TimelineSequenceFixture, MarkerListXmlRoundTrip)
|
||||
OakTimelineMarkerList *list = oaktimeline_marker_list_of(node_);
|
||||
ASSERT_NE(list, nullptr);
|
||||
|
||||
OakUndoCommand *add =
|
||||
OakUndoCommand add =
|
||||
oaktimeline_marker_add_command(list, 1, 3, 2, 3, "xml", 4);
|
||||
ASSERT_NE(add, nullptr);
|
||||
ASSERT_NE(add.ctx, nullptr);
|
||||
oakundo_command_redo_now(add);
|
||||
oakundo_command_free(add);
|
||||
oakundo_command_free(&add);
|
||||
|
||||
OakXmlWriter writer = oakcommon_xml_writer_init();
|
||||
ASSERT_NE(writer.ctx, nullptr);
|
||||
@@ -265,9 +267,9 @@ TEST_F(TimelineSequenceFixture, WorkareaUndoCommands)
|
||||
OakTimelineWorkArea *w = oaktimeline_workarea_of(node_);
|
||||
ASSERT_NE(w, nullptr);
|
||||
|
||||
OakUndoCommand *range_cmd = oaktimeline_workarea_set_range_command(
|
||||
OakUndoCommand range_cmd = oaktimeline_workarea_set_range_command(
|
||||
w, 1, 2, 1, 1, 0, 1, 1, 1);
|
||||
ASSERT_NE(range_cmd, nullptr);
|
||||
ASSERT_NE(range_cmd.ctx, nullptr);
|
||||
oakundo_command_redo_now(range_cmd);
|
||||
|
||||
int in_n = 0, out_n = 0;
|
||||
@@ -280,11 +282,11 @@ TEST_F(TimelineSequenceFixture, WorkareaUndoCommands)
|
||||
EXPECT_EQ(oaktimeline_workarea_get(w, &in_n, NULL, &out_n, NULL, NULL),
|
||||
OAKTIMELINE_OK);
|
||||
EXPECT_EQ(in_n, 0);
|
||||
oakundo_command_free(range_cmd);
|
||||
oakundo_command_free(&range_cmd);
|
||||
|
||||
OakUndoCommand *enable_cmd =
|
||||
OakUndoCommand enable_cmd =
|
||||
oaktimeline_workarea_set_enabled_command(w, 1);
|
||||
ASSERT_NE(enable_cmd, nullptr);
|
||||
ASSERT_NE(enable_cmd.ctx, nullptr);
|
||||
oakundo_command_redo_now(enable_cmd);
|
||||
|
||||
int enabled = 0;
|
||||
@@ -298,12 +300,13 @@ TEST_F(TimelineSequenceFixture, WorkareaUndoCommands)
|
||||
&enabled),
|
||||
OAKTIMELINE_OK);
|
||||
EXPECT_EQ(enabled, 0);
|
||||
oakundo_command_free(enable_cmd);
|
||||
oakundo_command_free(&enable_cmd);
|
||||
|
||||
EXPECT_EQ(oaktimeline_workarea_set_range_command(nullptr, 0, 1, 1, 1,
|
||||
0, 1, 1, 1),
|
||||
0, 1, 1, 1)
|
||||
.ctx,
|
||||
nullptr);
|
||||
EXPECT_EQ(oaktimeline_workarea_set_enabled_command(nullptr, 1),
|
||||
EXPECT_EQ(oaktimeline_workarea_set_enabled_command(nullptr, 1).ctx,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -381,8 +384,8 @@ TEST_F(TimelineSequenceFixture, AddAndRemoveTrackCommands)
|
||||
EXPECT_EQ(oaknode_tracklist_get_track_count(list, &count), OAKNODE_OK);
|
||||
const int before = count;
|
||||
|
||||
OakUndoCommand *add = oaktimeline_add_track_command(list);
|
||||
ASSERT_NE(add, nullptr);
|
||||
OakUndoCommand add = oaktimeline_add_track_command(list);
|
||||
ASSERT_NE(add.ctx, nullptr);
|
||||
oakundo_command_redo_now(add);
|
||||
|
||||
EXPECT_EQ(oaknode_tracklist_get_track_count(list, &count), OAKNODE_OK);
|
||||
@@ -393,8 +396,8 @@ TEST_F(TimelineSequenceFixture, AddAndRemoveTrackCommands)
|
||||
OAKNODE_OK);
|
||||
ASSERT_NE(track, nullptr);
|
||||
|
||||
OakUndoCommand *rm = oaktimeline_remove_track_command(track);
|
||||
ASSERT_NE(rm, nullptr);
|
||||
OakUndoCommand rm = oaktimeline_remove_track_command(track);
|
||||
ASSERT_NE(rm.ctx, nullptr);
|
||||
oakundo_command_redo_now(rm);
|
||||
|
||||
EXPECT_EQ(oaknode_tracklist_get_track_count(list, &count), OAKNODE_OK);
|
||||
@@ -408,11 +411,11 @@ TEST_F(TimelineSequenceFixture, AddAndRemoveTrackCommands)
|
||||
EXPECT_EQ(oaknode_tracklist_get_track_count(list, &count), OAKNODE_OK);
|
||||
EXPECT_EQ(count, before);
|
||||
|
||||
oakundo_command_free(add);
|
||||
oakundo_command_free(rm);
|
||||
oakundo_command_free(&add);
|
||||
oakundo_command_free(&rm);
|
||||
|
||||
EXPECT_EQ(oaktimeline_add_track_command(nullptr), nullptr);
|
||||
EXPECT_EQ(oaktimeline_remove_track_command(nullptr), nullptr);
|
||||
EXPECT_EQ(oaktimeline_add_track_command(nullptr).ctx, nullptr);
|
||||
EXPECT_EQ(oaktimeline_remove_track_command(nullptr).ctx, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
@@ -437,9 +440,9 @@ TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
oaknode_block_as_node(clip)),
|
||||
OAKNODE_OK);
|
||||
|
||||
OakUndoCommand *place =
|
||||
OakUndoCommand place =
|
||||
oaktimeline_place_block_command(list, 0, clip, 0, 1);
|
||||
ASSERT_NE(place, nullptr);
|
||||
ASSERT_NE(place.ctx, nullptr);
|
||||
oakundo_command_redo_now(place);
|
||||
|
||||
int block_count = 0;
|
||||
@@ -448,9 +451,9 @@ TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
ASSERT_EQ(block_count, 1);
|
||||
|
||||
// Trim out to length 4
|
||||
OakUndoCommand *trim = oaktimeline_trim_command(
|
||||
OakUndoCommand trim = oaktimeline_trim_command(
|
||||
track, clip, 4, 1, OAKTIMELINE_MOVEMENT_TRIM_OUT);
|
||||
ASSERT_NE(trim, nullptr);
|
||||
ASSERT_NE(trim.ctx, nullptr);
|
||||
oakundo_command_redo_now(trim);
|
||||
|
||||
int n = 0, d = 0;
|
||||
@@ -460,13 +463,13 @@ TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
oakundo_command_undo_now(trim);
|
||||
EXPECT_EQ(oaknode_block_get_length(clip, &n, &d), OAKNODE_OK);
|
||||
EXPECT_EQ(n, 10);
|
||||
oakundo_command_free(trim);
|
||||
oakundo_command_free(&trim);
|
||||
|
||||
// Split at 5: two blocks of 5
|
||||
OakNodeBlock *blocks[] = { clip };
|
||||
OakUndoCommand *split =
|
||||
OakUndoCommand split =
|
||||
oaktimeline_split_command(blocks, 1, 5, 1);
|
||||
ASSERT_NE(split, nullptr);
|
||||
ASSERT_NE(split.ctx, nullptr);
|
||||
oakundo_command_redo_now(split);
|
||||
|
||||
EXPECT_EQ(oaknode_track_get_block_count(track, &block_count),
|
||||
@@ -477,12 +480,12 @@ TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
EXPECT_EQ(oaknode_track_get_block_count(track, &block_count),
|
||||
OAKNODE_OK);
|
||||
ASSERT_EQ(block_count, 1);
|
||||
oakundo_command_free(split);
|
||||
oakundo_command_free(&split);
|
||||
|
||||
// Ripple remove [3..5] then undo
|
||||
OakUndoCommand *remove_area =
|
||||
OakUndoCommand remove_area =
|
||||
oaktimeline_ripple_remove_area_command(track, 3, 1, 5, 1);
|
||||
ASSERT_NE(remove_area, nullptr);
|
||||
ASSERT_NE(remove_area.ctx, nullptr);
|
||||
oakundo_command_redo_now(remove_area);
|
||||
|
||||
// Removing [3..5] from [0..10] splices it into [0..3] + [5..10]
|
||||
@@ -501,19 +504,21 @@ TEST_F(TimelineSequenceFixture, PlaceTrimSplitRemoveAreaCommands)
|
||||
oakundo_command_undo_now(remove_area);
|
||||
EXPECT_EQ(oaknode_block_get_length(clip, &n, &d), OAKNODE_OK);
|
||||
EXPECT_EQ(n, 10);
|
||||
oakundo_command_free(remove_area);
|
||||
oakundo_command_free(&remove_area);
|
||||
|
||||
oakundo_command_undo_now(place);
|
||||
EXPECT_EQ(oaknode_track_get_block_count(track, &block_count),
|
||||
OAKNODE_OK);
|
||||
EXPECT_EQ(block_count, 0);
|
||||
oakundo_command_free(place);
|
||||
oakundo_command_free(&place);
|
||||
|
||||
EXPECT_EQ(oaktimeline_place_block_command(nullptr, 0, clip, 0, 1),
|
||||
EXPECT_EQ(oaktimeline_place_block_command(nullptr, 0, clip, 0, 1)
|
||||
.ctx,
|
||||
nullptr);
|
||||
EXPECT_EQ(oaktimeline_trim_command(track, clip, 1, 1, 99), nullptr);
|
||||
EXPECT_EQ(oaktimeline_split_command(blocks, 0, 1, 1), nullptr);
|
||||
EXPECT_EQ(oaktimeline_ripple_remove_area_command(nullptr, 0, 1, 1, 1),
|
||||
EXPECT_EQ(oaktimeline_trim_command(track, clip, 1, 1, 99).ctx, nullptr);
|
||||
EXPECT_EQ(oaktimeline_split_command(blocks, 0, 1, 1).ctx, nullptr);
|
||||
EXPECT_EQ(oaktimeline_ripple_remove_area_command(nullptr, 0, 1, 1, 1)
|
||||
.ctx,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
@@ -550,9 +555,9 @@ TEST_F(TimelineSequenceFixture, ReplaceWithGapCommand)
|
||||
OAKNODE_OK);
|
||||
EXPECT_EQ(oaknode_track_append_block(track, clip2), OAKNODE_OK);
|
||||
|
||||
OakUndoCommand *replace =
|
||||
OakUndoCommand replace =
|
||||
oaktimeline_replace_block_with_gap_command(track, clip);
|
||||
ASSERT_NE(replace, nullptr);
|
||||
ASSERT_NE(replace.ctx, nullptr);
|
||||
oakundo_command_redo_now(replace);
|
||||
|
||||
int block_count = 0;
|
||||
@@ -569,9 +574,10 @@ TEST_F(TimelineSequenceFixture, ReplaceWithGapCommand)
|
||||
oakundo_command_undo_now(replace);
|
||||
EXPECT_EQ(oaknode_track_get_block_at(track, 0, &first), OAKNODE_OK);
|
||||
EXPECT_EQ(first, clip);
|
||||
oakundo_command_free(replace);
|
||||
oakundo_command_free(&replace);
|
||||
|
||||
EXPECT_EQ(oaktimeline_replace_block_with_gap_command(nullptr, clip),
|
||||
EXPECT_EQ(oaktimeline_replace_block_with_gap_command(nullptr, clip)
|
||||
.ctx,
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(oaknode_track_ripple_remove_block(track, clip), OAKNODE_OK);
|
||||
@@ -582,18 +588,20 @@ TEST_F(TimelineSequenceFixture, SlideAndInsertGapsAndRippleDeleteGapsFactories)
|
||||
{
|
||||
OakNodeBlock *clip = oaknode_block_clip_create();
|
||||
EXPECT_EQ(oaktimeline_slide_command(nullptr, &clip, 1, nullptr,
|
||||
nullptr, 1, 1),
|
||||
nullptr, 1, 1)
|
||||
.ctx,
|
||||
nullptr);
|
||||
|
||||
OakNodeTrackList *list = nullptr;
|
||||
ASSERT_EQ(oaknode_sequence_get_track_list(
|
||||
sequence_, OAKNODE_TRACK_TYPE_VIDEO, &list),
|
||||
OAKNODE_OK);
|
||||
EXPECT_EQ(oaktimeline_insert_gaps_command(nullptr, 0, 1, 1, 1),
|
||||
EXPECT_EQ(oaktimeline_insert_gaps_command(nullptr, 0, 1, 1, 1).ctx,
|
||||
nullptr);
|
||||
|
||||
EXPECT_EQ(oaktimeline_ripple_delete_gaps_command(
|
||||
sequence_, nullptr, nullptr, nullptr, nullptr, nullptr, 0),
|
||||
sequence_, nullptr, nullptr, nullptr, nullptr, nullptr, 0)
|
||||
.ctx,
|
||||
nullptr);
|
||||
|
||||
oaknode_block_free(clip);
|
||||
|
||||
@@ -21,21 +21,100 @@
|
||||
#ifndef OAK_UNDO_COMMANDHANDLE_H
|
||||
#define OAK_UNDO_COMMANDHANDLE_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
#include "../src/undocommand.h"
|
||||
|
||||
/**
|
||||
* @brief Internal layout of the OakUndoCommand handle, shared between the
|
||||
* c_api translation units.
|
||||
* @brief Internal control block behind OakUndoCommand, shared between
|
||||
* the c_api translation units.
|
||||
*
|
||||
* `owned` is true for handles created by oakundo_command_init() /
|
||||
* oakundo_command_init_multi() and false for borrowed wrappers handed out
|
||||
* by oakundo_command_multi_child().
|
||||
* `owns` is true for commands created through init factories (the box
|
||||
* deletes the command when the count reaches zero) and false for
|
||||
* references into library-owned structures (multi children, stack
|
||||
* entries): releasing those only destroys the box.
|
||||
*/
|
||||
struct OakUndoCommand {
|
||||
struct OakUndoCommandBox {
|
||||
olive::UndoCommand *command;
|
||||
bool owned;
|
||||
bool owns;
|
||||
std::atomic<uint32_t> refs;
|
||||
|
||||
OakUndoCommandBox(olive::UndoCommand *c, bool o)
|
||||
: command(c)
|
||||
, owns(o)
|
||||
, refs(1)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
namespace oakundo_capi
|
||||
{
|
||||
|
||||
inline OakUndoCommand make_command_handle(olive::UndoCommand *command,
|
||||
bool owns);
|
||||
|
||||
inline void command_addref(void *ctx)
|
||||
{
|
||||
if (ctx) {
|
||||
static_cast<OakUndoCommandBox *>(ctx)->refs.fetch_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
inline void command_release(void *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
OakUndoCommandBox *box = static_cast<OakUndoCommandBox *>(ctx);
|
||||
if (box->refs.fetch_sub(1) == 1) {
|
||||
if (box->owns) {
|
||||
delete box->command;
|
||||
}
|
||||
delete box;
|
||||
}
|
||||
}
|
||||
|
||||
inline OakUndoCommand make_command_handle(olive::UndoCommand *command,
|
||||
bool owns)
|
||||
{
|
||||
OakUndoCommand handle = {};
|
||||
if (!command) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
OakUndoCommandBox *box = new (std::nothrow) OakUndoCommandBox(command,
|
||||
owns);
|
||||
if (!box) {
|
||||
if (owns) {
|
||||
delete command;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
handle.ctx = box;
|
||||
handle.addref = command_addref;
|
||||
handle.release = command_release;
|
||||
handle.abi_version = OAKUNDO_ABI_VERSION;
|
||||
return handle;
|
||||
}
|
||||
|
||||
inline olive::UndoCommand *to_command(OakUndoCommand h)
|
||||
{
|
||||
if (!h.ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<OakUndoCommandBox *>(h.ctx)->command;
|
||||
}
|
||||
|
||||
inline void mark_container_owned(OakUndoCommand h)
|
||||
{
|
||||
if (h.ctx) {
|
||||
static_cast<OakUndoCommandBox *>(h.ctx)->owns = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace oakundo_capi
|
||||
|
||||
#endif // OAK_UNDO_COMMANDHANDLE_H
|
||||
|
||||
@@ -20,10 +20,17 @@
|
||||
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <new>
|
||||
|
||||
#include "../src/undocommand.h"
|
||||
|
||||
#include "commandhandle.h"
|
||||
|
||||
using oakundo_capi::make_command_handle;
|
||||
using oakundo_capi::mark_container_owned;
|
||||
using oakundo_capi::to_command;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -33,7 +40,8 @@ namespace
|
||||
class CallbackUndoCommand : public olive::UndoCommand {
|
||||
public:
|
||||
CallbackUndoCommand(const OakUndoCommandVtable &vtable, void *userdata)
|
||||
: vtable_(vtable), userdata_(userdata)
|
||||
: vtable_(vtable)
|
||||
, userdata_(userdata)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -64,75 +72,66 @@ private:
|
||||
void *userdata_;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
OakUndoCommand *oakundo_command_init(const OakUndoCommandVtable *vtable,
|
||||
void *userdata)
|
||||
OakUndoCommand oakundo_command_init(const OakUndoCommandVtable *vtable,
|
||||
void *userdata)
|
||||
{
|
||||
if (!vtable) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
|
||||
try {
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand();
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
handle->command = new CallbackUndoCommand(*vtable, userdata);
|
||||
handle->owned = true;
|
||||
return handle;
|
||||
return make_command_handle(new CallbackUndoCommand(*vtable, userdata), true);
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
OakUndoCommand *oakundo_command_init_multi(void)
|
||||
OakUndoCommand oakundo_command_init_multi(void)
|
||||
{
|
||||
try {
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand();
|
||||
if (!handle) {
|
||||
return NULL;
|
||||
}
|
||||
handle->command = new olive::MultiUndoCommand();
|
||||
handle->owned = true;
|
||||
return handle;
|
||||
return make_command_handle(new olive::MultiUndoCommand(), true);
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
return OakUndoCommand{};
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_multi_add_child(OakUndoCommand *multi,
|
||||
OakUndoCommand *child)
|
||||
int oakundo_command_multi_add_child(OakUndoCommand multi,
|
||||
OakUndoCommand child)
|
||||
{
|
||||
if (!multi || !multi->command || !child || !child->command) {
|
||||
olive::UndoCommand *parent = to_command(multi);
|
||||
olive::UndoCommand *child_cmd = to_command(child);
|
||||
if (!parent || !child_cmd) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
olive::MultiUndoCommand *mcu =
|
||||
dynamic_cast<olive::MultiUndoCommand *>(multi->command);
|
||||
dynamic_cast<olive::MultiUndoCommand *>(parent);
|
||||
if (!mcu) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
mcu->add_child(child->command);
|
||||
// Ownership of the underlying command moved to the multi command;
|
||||
// consume the wrapper.
|
||||
delete child;
|
||||
mcu->add_child(child_cmd);
|
||||
// The multi command now owns the C++ object; the caller's box
|
||||
// becomes a non-owning reference (its release no longer deletes).
|
||||
mark_container_owned(child);
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_multi_child_count(OakUndoCommand *multi, int *out_count)
|
||||
int oakundo_command_multi_child_count(OakUndoCommand multi, int *out_count)
|
||||
{
|
||||
if (!multi || !multi->command || !out_count) {
|
||||
olive::UndoCommand *parent = to_command(multi);
|
||||
if (!parent || !out_count) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
olive::MultiUndoCommand *mcu =
|
||||
dynamic_cast<olive::MultiUndoCommand *>(multi->command);
|
||||
dynamic_cast<olive::MultiUndoCommand *>(parent);
|
||||
if (!mcu) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
@@ -145,15 +144,16 @@ int oakundo_command_multi_child_count(OakUndoCommand *multi, int *out_count)
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_multi_child(OakUndoCommand *multi, int index,
|
||||
OakUndoCommand **out_child)
|
||||
int oakundo_command_multi_child(OakUndoCommand multi, int index,
|
||||
OakUndoCommand *out_child)
|
||||
{
|
||||
if (!multi || !multi->command || !out_child) {
|
||||
olive::UndoCommand *parent = to_command(multi);
|
||||
if (!parent || !out_child) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
olive::MultiUndoCommand *mcu =
|
||||
dynamic_cast<olive::MultiUndoCommand *>(multi->command);
|
||||
dynamic_cast<olive::MultiUndoCommand *>(parent);
|
||||
if (!mcu) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
@@ -163,41 +163,38 @@ int oakundo_command_multi_child(OakUndoCommand *multi, int index,
|
||||
return OAKUNDO_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
OakUndoCommand *handle = new (std::nothrow) OakUndoCommand();
|
||||
if (!handle) {
|
||||
return OAKUNDO_E_NOMEM;
|
||||
}
|
||||
handle->command = mcu->child(index);
|
||||
handle->owned = false;
|
||||
*out_child = handle;
|
||||
// Non-owning reference; the child stays owned by the multi command
|
||||
*out_child = make_command_handle(mcu->child(index), false);
|
||||
return out_child->ctx ? OAKUNDO_OK : OAKUNDO_E_NOMEM;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_redo_now(OakUndoCommand command)
|
||||
{
|
||||
olive::UndoCommand *c = to_command(command);
|
||||
if (!c) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
c->redo_now();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_redo_now(OakUndoCommand *command)
|
||||
int oakundo_command_undo_now(OakUndoCommand command)
|
||||
{
|
||||
if (!command || !command->command) {
|
||||
olive::UndoCommand *c = to_command(command);
|
||||
if (!c) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
command->command->redo_now();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_command_undo_now(OakUndoCommand *command)
|
||||
{
|
||||
if (!command || !command->command) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
command->command->undo_now();
|
||||
c->undo_now();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
@@ -206,12 +203,10 @@ int oakundo_command_undo_now(OakUndoCommand *command)
|
||||
|
||||
void oakundo_command_free(OakUndoCommand *command)
|
||||
{
|
||||
if (!command) {
|
||||
if (!command || !command->ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (command->owned) {
|
||||
delete command->command;
|
||||
}
|
||||
delete command;
|
||||
command->release(command->ctx);
|
||||
command->ctx = NULL;
|
||||
}
|
||||
|
||||
+118
-52
@@ -20,192 +20,257 @@
|
||||
|
||||
#include "undo/undostack.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
|
||||
#include "../src/undostack.h"
|
||||
|
||||
#include "commandhandle.h"
|
||||
|
||||
struct OakUndoStack {
|
||||
using oakundo_capi::mark_container_owned;
|
||||
using oakundo_capi::to_command;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct StackBox {
|
||||
olive::UndoStack impl;
|
||||
std::atomic<uint32_t> refs;
|
||||
|
||||
StackBox()
|
||||
: refs(1)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
OakUndoStack *oakundo_undostack_init(void)
|
||||
void stack_addref(void *ctx)
|
||||
{
|
||||
try {
|
||||
return new (std::nothrow) OakUndoStack();
|
||||
} catch (...) {
|
||||
return NULL;
|
||||
if (ctx) {
|
||||
static_cast<StackBox *>(ctx)->refs.fetch_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
void stack_release(void *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
StackBox *box = static_cast<StackBox *>(ctx);
|
||||
if (box->refs.fetch_sub(1) == 1) {
|
||||
delete box;
|
||||
}
|
||||
}
|
||||
|
||||
olive::UndoStack *to_stack(OakUndoStack h)
|
||||
{
|
||||
if (!h.ctx) {
|
||||
return nullptr;
|
||||
}
|
||||
return &static_cast<StackBox *>(h.ctx)->impl;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OakUndoStack oakundo_undostack_init(void)
|
||||
{
|
||||
OakUndoStack handle = {};
|
||||
|
||||
StackBox *box = new (std::nothrow) StackBox();
|
||||
if (!box) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
handle.ctx = box;
|
||||
handle.addref = stack_addref;
|
||||
handle.release = stack_release;
|
||||
handle.abi_version = OAKUNDO_ABI_VERSION;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void oakundo_undostack_free(OakUndoStack *stack)
|
||||
{
|
||||
delete stack;
|
||||
if (!stack || !stack->ctx) {
|
||||
return;
|
||||
}
|
||||
|
||||
stack->release(stack->ctx);
|
||||
stack->ctx = NULL;
|
||||
}
|
||||
|
||||
int oakundo_undostack_push(OakUndoStack *stack, OakUndoCommand *command,
|
||||
int oakundo_undostack_push(OakUndoStack stack, OakUndoCommand command,
|
||||
const char *name)
|
||||
{
|
||||
if (!stack || !command || !command->command) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
olive::UndoCommand *cmd = to_command(command);
|
||||
if (!s || !cmd) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
olive::UndoCommand *impl = command->command;
|
||||
stack->impl.push(impl, name ? name : "");
|
||||
// Ownership of the underlying command moved to the stack (or was
|
||||
// deleted as an empty multi command); consume the wrapper.
|
||||
delete command;
|
||||
s->push(cmd, name ? name : "");
|
||||
// The stack now owns the C++ object (or deleted it as an empty
|
||||
// multi command); the caller's box becomes a non-owning reference.
|
||||
mark_container_owned(command);
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_push_pre_executed(OakUndoStack *stack,
|
||||
OakUndoCommand *command,
|
||||
int oakundo_undostack_push_pre_executed(OakUndoStack stack,
|
||||
OakUndoCommand command,
|
||||
const char *name)
|
||||
{
|
||||
if (!stack || !command || !command->command) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
olive::UndoCommand *cmd = to_command(command);
|
||||
if (!s || !cmd) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
olive::UndoCommand *impl = command->command;
|
||||
stack->impl.push_pre_executed(impl, name ? name : "");
|
||||
delete command;
|
||||
s->push_pre_executed(cmd, name ? name : "");
|
||||
mark_container_owned(command);
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_undo(OakUndoStack *stack)
|
||||
int oakundo_undostack_undo(OakUndoStack stack)
|
||||
{
|
||||
if (!stack) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
stack->impl.undo();
|
||||
s->undo();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_redo(OakUndoStack *stack)
|
||||
int oakundo_undostack_redo(OakUndoStack stack)
|
||||
{
|
||||
if (!stack) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
stack->impl.redo();
|
||||
s->redo();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_jump(OakUndoStack *stack, int64_t index)
|
||||
int oakundo_undostack_jump(OakUndoStack stack, int64_t index)
|
||||
{
|
||||
if (!stack) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
stack->impl.jump(index < 0 ? 0 : static_cast<size_t>(index));
|
||||
s->jump(index < 0 ? 0 : static_cast<size_t>(index));
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_clear(OakUndoStack *stack)
|
||||
int oakundo_undostack_clear(OakUndoStack stack)
|
||||
{
|
||||
if (!stack) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
stack->impl.clear();
|
||||
s->clear();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_can_undo(OakUndoStack *stack, int *out_value)
|
||||
int oakundo_undostack_can_undo(OakUndoStack stack, int *out_value)
|
||||
{
|
||||
if (!stack || !out_value) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s || !out_value) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
*out_value = stack->impl.can_undo() ? 1 : 0;
|
||||
*out_value = s->can_undo() ? 1 : 0;
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_can_redo(OakUndoStack *stack, int *out_value)
|
||||
int oakundo_undostack_can_redo(OakUndoStack stack, int *out_value)
|
||||
{
|
||||
if (!stack || !out_value) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s || !out_value) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
*out_value = stack->impl.can_redo() ? 1 : 0;
|
||||
*out_value = s->can_redo() ? 1 : 0;
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_count(OakUndoStack *stack, int64_t *out_count)
|
||||
int oakundo_undostack_count(OakUndoStack stack, int64_t *out_count)
|
||||
{
|
||||
if (!stack || !out_count) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s || !out_count) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
*out_count = stack->impl.command_count();
|
||||
*out_count = s->command_count();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_index(OakUndoStack *stack, int64_t *out_index)
|
||||
int oakundo_undostack_index(OakUndoStack stack, int64_t *out_index)
|
||||
{
|
||||
if (!stack || !out_index) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s || !out_index) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
*out_index = stack->impl.done_count();
|
||||
*out_index = s->done_count();
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_command_text(OakUndoStack *stack, int64_t row,
|
||||
int oakundo_undostack_command_text(OakUndoStack stack, int64_t row,
|
||||
char *buf, int buf_size)
|
||||
{
|
||||
if (!stack) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
if (row < 0 || row >= stack->impl.command_count()) {
|
||||
if (row < 0 || row >= s->command_count()) {
|
||||
return OAKUNDO_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
std::string name = stack->impl.command_name(int(row));
|
||||
std::string name = s->command_name(int(row));
|
||||
|
||||
int required = static_cast<int>(name.size()) + 1;
|
||||
if (buf && buf_size > 0) {
|
||||
@@ -222,19 +287,20 @@ int oakundo_undostack_command_text(OakUndoStack *stack, int64_t row,
|
||||
}
|
||||
}
|
||||
|
||||
int oakundo_undostack_command_is_done(OakUndoStack *stack, int64_t row,
|
||||
int oakundo_undostack_command_is_done(OakUndoStack stack, int64_t row,
|
||||
int *out_value)
|
||||
{
|
||||
if (!stack || !out_value) {
|
||||
olive::UndoStack *s = to_stack(stack);
|
||||
if (!s || !out_value) {
|
||||
return OAKUNDO_E_INVALID;
|
||||
}
|
||||
|
||||
try {
|
||||
if (row < 0 || row >= stack->impl.command_count()) {
|
||||
if (row < 0 || row >= s->command_count()) {
|
||||
return OAKUNDO_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
*out_value = stack->impl.command_is_done(int(row)) ? 1 : 0;
|
||||
*out_value = s->command_is_done(int(row)) ? 1 : 0;
|
||||
return OAKUNDO_OK;
|
||||
} catch (...) {
|
||||
return OAKUNDO_E_FAILED;
|
||||
|
||||
@@ -46,11 +46,11 @@ OakUndoCommandVtable make_vtable()
|
||||
return vtable;
|
||||
}
|
||||
|
||||
OakUndoCommand *make_command(CommandLog &log)
|
||||
OakUndoCommand make_command(CommandLog &log)
|
||||
{
|
||||
OakUndoCommandVtable vtable = make_vtable();
|
||||
OakUndoCommand *command = oakundo_command_init(&vtable, &log);
|
||||
EXPECT_NE(command, nullptr);
|
||||
OakUndoCommand command = oakundo_command_init(&vtable, &log);
|
||||
EXPECT_NE(command.ctx, nullptr);
|
||||
return command;
|
||||
}
|
||||
|
||||
@@ -59,25 +59,25 @@ OakUndoCommand *make_command(CommandLog &log)
|
||||
TEST(OakUndoCommand, InitFree)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoCommand *command = make_command(log);
|
||||
oakundo_command_free(command);
|
||||
OakUndoCommand command = make_command(log);
|
||||
oakundo_command_free(&command);
|
||||
EXPECT_EQ(log.free_count, 1);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, InitNullVtableFails)
|
||||
{
|
||||
EXPECT_EQ(oakundo_command_init(nullptr, nullptr), nullptr);
|
||||
EXPECT_EQ(oakundo_command_init(nullptr, nullptr).ctx, nullptr);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, FreeNullIsNoOp)
|
||||
{
|
||||
oakundo_command_free(nullptr);
|
||||
{ OakUndoCommand h = {}; oakundo_command_free(&h); }
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, RedoUndoNowRoundtrip)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoCommand *command = make_command(log);
|
||||
OakUndoCommand command = make_command(log);
|
||||
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(log.redo_count, 1);
|
||||
@@ -91,13 +91,15 @@ TEST(OakUndoCommand, RedoUndoNowRoundtrip)
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(log.undo_count, 1);
|
||||
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, RedoNowNullHandleFails)
|
||||
{
|
||||
EXPECT_EQ(oakundo_command_redo_now(nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_undo_now(nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_redo_now(OakUndoCommand{}),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_undo_now(OakUndoCommand{}),
|
||||
OAKUNDO_E_INVALID);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, NullCallbacksAreNoOp)
|
||||
@@ -107,19 +109,19 @@ TEST(OakUndoCommand, NullCallbacksAreNoOp)
|
||||
vtable.undo = nullptr;
|
||||
vtable.free_fn = nullptr;
|
||||
|
||||
OakUndoCommand *command = oakundo_command_init(&vtable, nullptr);
|
||||
ASSERT_NE(command, nullptr);
|
||||
OakUndoCommand command = oakundo_command_init(&vtable, nullptr);
|
||||
ASSERT_NE(command.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(command), OAKUNDO_OK);
|
||||
EXPECT_EQ(oakundo_command_undo_now(command), OAKUNDO_OK);
|
||||
oakundo_command_free(command);
|
||||
oakundo_command_free(&command);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, MultiAddChildAndCount)
|
||||
{
|
||||
CommandLog log_a;
|
||||
CommandLog log_b;
|
||||
OakUndoCommand *multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi, nullptr);
|
||||
OakUndoCommand multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi.ctx, nullptr);
|
||||
|
||||
int count = -1;
|
||||
EXPECT_EQ(oakundo_command_multi_child_count(multi, &count), OAKUNDO_OK);
|
||||
@@ -142,7 +144,7 @@ TEST(OakUndoCommand, MultiAddChildAndCount)
|
||||
EXPECT_EQ(log_b.undo_count, 1);
|
||||
|
||||
// Freeing the multi frees the children it owns.
|
||||
oakundo_command_free(multi);
|
||||
oakundo_command_free(&multi);
|
||||
EXPECT_EQ(log_a.free_count, 1);
|
||||
EXPECT_EQ(log_b.free_count, 1);
|
||||
}
|
||||
@@ -150,43 +152,43 @@ TEST(OakUndoCommand, MultiAddChildAndCount)
|
||||
TEST(OakUndoCommand, MultiChildBorrowedHandle)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoCommand *multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi, nullptr);
|
||||
OakUndoCommand multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi.ctx, nullptr);
|
||||
ASSERT_EQ(oakundo_command_multi_add_child(multi, make_command(log)),
|
||||
OAKUNDO_OK);
|
||||
|
||||
OakUndoCommand *child = nullptr;
|
||||
OakUndoCommand child = {};
|
||||
EXPECT_EQ(oakundo_command_multi_child(multi, 0, &child), OAKUNDO_OK);
|
||||
ASSERT_NE(child, nullptr);
|
||||
ASSERT_NE(child.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_command_redo_now(child), OAKUNDO_OK);
|
||||
EXPECT_EQ(log.redo_count, 1);
|
||||
|
||||
// Freeing the borrowed wrapper must not free the underlying command.
|
||||
oakundo_command_free(child);
|
||||
oakundo_command_free(&child);
|
||||
EXPECT_EQ(log.free_count, 0);
|
||||
|
||||
oakundo_command_free(multi);
|
||||
oakundo_command_free(&multi);
|
||||
EXPECT_EQ(log.free_count, 1);
|
||||
}
|
||||
|
||||
TEST(OakUndoCommand, MultiErrorPaths)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoCommand *multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi, nullptr);
|
||||
OakUndoCommand *plain = make_command(log);
|
||||
OakUndoCommand multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi.ctx, nullptr);
|
||||
OakUndoCommand plain = make_command(log);
|
||||
|
||||
int count = 0;
|
||||
OakUndoCommand *child = nullptr;
|
||||
OakUndoCommand child = {};
|
||||
|
||||
EXPECT_EQ(oakundo_command_multi_add_child(nullptr, plain),
|
||||
EXPECT_EQ(oakundo_command_multi_add_child(OakUndoCommand{}, plain),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_multi_add_child(multi, nullptr),
|
||||
EXPECT_EQ(oakundo_command_multi_add_child(multi, OakUndoCommand{}),
|
||||
OAKUNDO_E_INVALID);
|
||||
// plain is not a multi command
|
||||
EXPECT_EQ(oakundo_command_multi_add_child(plain, make_command(log)),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_multi_child_count(nullptr, &count),
|
||||
EXPECT_EQ(oakundo_command_multi_child_count(OakUndoCommand{}, &count),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_command_multi_child_count(multi, nullptr),
|
||||
OAKUNDO_E_INVALID);
|
||||
@@ -197,6 +199,6 @@ TEST(OakUndoCommand, MultiErrorPaths)
|
||||
EXPECT_EQ(oakundo_command_multi_child(multi, -1, &child),
|
||||
OAKUNDO_E_NOT_FOUND);
|
||||
|
||||
oakundo_command_free(multi);
|
||||
oakundo_command_free(plain);
|
||||
oakundo_command_free(&multi);
|
||||
oakundo_command_free(&plain);
|
||||
}
|
||||
|
||||
@@ -53,36 +53,36 @@ OakUndoCommandVtable make_vtable()
|
||||
return vtable;
|
||||
}
|
||||
|
||||
OakUndoCommand *make_command(CommandLog &log)
|
||||
OakUndoCommand make_command(CommandLog &log)
|
||||
{
|
||||
OakUndoCommandVtable vtable = make_vtable();
|
||||
OakUndoCommand *command = oakundo_command_init(&vtable, &log);
|
||||
EXPECT_NE(command, nullptr);
|
||||
OakUndoCommand command = oakundo_command_init(&vtable, &log);
|
||||
EXPECT_NE(command.ctx, nullptr);
|
||||
return command;
|
||||
}
|
||||
|
||||
int64_t stack_index(OakUndoStack *stack)
|
||||
int64_t stack_index(OakUndoStack stack)
|
||||
{
|
||||
int64_t index = -1;
|
||||
EXPECT_EQ(oakundo_undostack_index(stack, &index), OAKUNDO_OK);
|
||||
return index;
|
||||
}
|
||||
|
||||
int64_t stack_count(OakUndoStack *stack)
|
||||
int64_t stack_count(OakUndoStack stack)
|
||||
{
|
||||
int64_t count = -1;
|
||||
EXPECT_EQ(oakundo_undostack_count(stack, &count), OAKUNDO_OK);
|
||||
return count;
|
||||
}
|
||||
|
||||
int stack_can_undo(OakUndoStack *stack)
|
||||
int stack_can_undo(OakUndoStack stack)
|
||||
{
|
||||
int value = -1;
|
||||
EXPECT_EQ(oakundo_undostack_can_undo(stack, &value), OAKUNDO_OK);
|
||||
return value;
|
||||
}
|
||||
|
||||
int stack_can_redo(OakUndoStack *stack)
|
||||
int stack_can_redo(OakUndoStack stack)
|
||||
{
|
||||
int value = -1;
|
||||
EXPECT_EQ(oakundo_undostack_can_redo(stack, &value), OAKUNDO_OK);
|
||||
@@ -93,8 +93,8 @@ int stack_can_redo(OakUndoStack *stack)
|
||||
|
||||
TEST(OakUndoStack, InitFree)
|
||||
{
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
// A fresh stack holds the "New/Open Project" empty command.
|
||||
EXPECT_EQ(stack_count(stack), 1);
|
||||
@@ -102,12 +102,12 @@ TEST(OakUndoStack, InitFree)
|
||||
EXPECT_EQ(stack_can_undo(stack), 0);
|
||||
EXPECT_EQ(stack_can_redo(stack), 0);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, FreeNullIsNoOp)
|
||||
{
|
||||
oakundo_undostack_free(nullptr);
|
||||
{ OakUndoStack h = {}; oakundo_undostack_free(&h); }
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, NullHandleFails)
|
||||
@@ -117,39 +117,39 @@ TEST(OakUndoStack, NullHandleFails)
|
||||
int value = 0;
|
||||
char buf[8];
|
||||
|
||||
EXPECT_EQ(oakundo_undostack_push(nullptr, make_command(log), "x"),
|
||||
EXPECT_EQ(oakundo_undostack_push(OakUndoStack{}, make_command(log), "x"),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_push_pre_executed(nullptr, make_command(log),
|
||||
EXPECT_EQ(oakundo_undostack_push_pre_executed(OakUndoStack{}, make_command(log),
|
||||
"x"),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_undo(nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_redo(nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_jump(nullptr, 0), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_clear(nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_can_undo(nullptr, &value), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_can_redo(nullptr, &value), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_count(nullptr, &value64), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_index(nullptr, &value64), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_command_text(nullptr, 0, buf, sizeof(buf)),
|
||||
EXPECT_EQ(oakundo_undostack_undo(OakUndoStack{}), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_redo(OakUndoStack{}), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_jump(OakUndoStack{}, 0), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_clear(OakUndoStack{}), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_can_undo(OakUndoStack{}, &value), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_can_redo(OakUndoStack{}, &value), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_count(OakUndoStack{}, &value64), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_index(OakUndoStack{}, &value64), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_command_text(OakUndoStack{}, 0, buf, sizeof(buf)),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_command_is_done(nullptr, 0, &value),
|
||||
EXPECT_EQ(oakundo_undostack_command_is_done(OakUndoStack{}, 0, &value),
|
||||
OAKUNDO_E_INVALID);
|
||||
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
EXPECT_EQ(oakundo_undostack_push(stack, nullptr, "x"), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_push_pre_executed(stack, nullptr, "x"),
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
EXPECT_EQ(oakundo_undostack_push(stack, OakUndoCommand{}, "x"), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_push_pre_executed(stack, OakUndoCommand{}, "x"),
|
||||
OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_can_undo(stack, nullptr), OAKUNDO_E_INVALID);
|
||||
EXPECT_EQ(oakundo_undostack_count(stack, nullptr), OAKUNDO_E_INVALID);
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, PushUndoRedoRoundtrip)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, make_command(log), "edit"),
|
||||
OAKUNDO_OK);
|
||||
@@ -171,7 +171,7 @@ TEST(OakUndoStack, PushUndoRedoRoundtrip)
|
||||
EXPECT_EQ(stack_can_undo(stack), 1);
|
||||
EXPECT_EQ(stack_can_redo(stack), 0);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
EXPECT_EQ(log.free_count, 1);
|
||||
}
|
||||
|
||||
@@ -179,8 +179,8 @@ TEST(OakUndoStack, PushClearsRedoable)
|
||||
{
|
||||
CommandLog log_a;
|
||||
CommandLog log_b;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, make_command(log_a), "a"),
|
||||
OAKUNDO_OK);
|
||||
@@ -194,14 +194,14 @@ TEST(OakUndoStack, PushClearsRedoable)
|
||||
EXPECT_EQ(stack_can_redo(stack), 0);
|
||||
EXPECT_EQ(stack_count(stack), 2);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, PushPreExecutedSkipsRedo)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push_pre_executed(stack, make_command(log),
|
||||
"done elsewhere"),
|
||||
@@ -215,33 +215,33 @@ TEST(OakUndoStack, PushPreExecutedSkipsRedo)
|
||||
ASSERT_EQ(oakundo_undostack_redo(stack), OAKUNDO_OK);
|
||||
EXPECT_EQ(log.redo_count, 1);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, EmptyMultiIsDiscarded)
|
||||
{
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
OakUndoCommand *multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi, nullptr);
|
||||
OakUndoCommand multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi.ctx, nullptr);
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, multi, "empty"), OAKUNDO_OK);
|
||||
EXPECT_EQ(stack_count(stack), 1);
|
||||
|
||||
multi = oakundo_command_init_multi();
|
||||
ASSERT_NE(multi, nullptr);
|
||||
ASSERT_NE(multi.ctx, nullptr);
|
||||
ASSERT_EQ(oakundo_undostack_push_pre_executed(stack, multi, "empty"),
|
||||
OAKUNDO_OK);
|
||||
EXPECT_EQ(stack_count(stack), 1);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, Jump)
|
||||
{
|
||||
CommandLog logs[3];
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
char name[8];
|
||||
@@ -271,14 +271,14 @@ TEST(OakUndoStack, Jump)
|
||||
ASSERT_EQ(oakundo_undostack_jump(stack, -5), OAKUNDO_OK);
|
||||
EXPECT_EQ(stack_index(stack), 1);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, Clear)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, make_command(log), "edit"),
|
||||
OAKUNDO_OK);
|
||||
@@ -294,14 +294,14 @@ TEST(OakUndoStack, Clear)
|
||||
int(strlen("New/Open Project")) + 1);
|
||||
EXPECT_STREQ(buf, "New/Open Project");
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, CommandTextTwoStage)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, make_command(log), "hello"),
|
||||
OAKUNDO_OK);
|
||||
@@ -333,14 +333,14 @@ TEST(OakUndoStack, CommandTextTwoStage)
|
||||
OAKUNDO_OK);
|
||||
EXPECT_EQ(oakundo_undostack_command_text(stack, 2, nullptr, 0), 1);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, CommandIsDone)
|
||||
{
|
||||
CommandLog log;
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
ASSERT_EQ(oakundo_undostack_push(stack, make_command(log), "edit"),
|
||||
OAKUNDO_OK);
|
||||
@@ -359,13 +359,13 @@ TEST(OakUndoStack, CommandIsDone)
|
||||
EXPECT_EQ(oakundo_undostack_command_is_done(stack, 0, nullptr),
|
||||
OAKUNDO_E_INVALID);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
TEST(OakUndoStack, MaxUndoCommands)
|
||||
{
|
||||
OakUndoStack *stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack, nullptr);
|
||||
OakUndoStack stack = oakundo_undostack_init();
|
||||
ASSERT_NE(stack.ctx, nullptr);
|
||||
|
||||
// The fresh stack holds 1 empty command; push well past the 200 cap.
|
||||
std::vector<std::unique_ptr<CommandLog>> logs;
|
||||
@@ -397,7 +397,7 @@ TEST(OakUndoStack, MaxUndoCommands)
|
||||
EXPECT_EQ(stack_can_undo(stack), 0);
|
||||
EXPECT_EQ(stack_count(stack), 200);
|
||||
|
||||
oakundo_undostack_free(stack);
|
||||
oakundo_undostack_free(&stack);
|
||||
}
|
||||
|
||||
namespace
|
||||
|
||||
Reference in New Issue
Block a user