1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use super::*;

use animation::*;
use animation::editor::*;
use animation::inmemory::pending_log::*;

use rusqlite::*;
use std::time::Duration;

impl SqliteAnimation {
    ///
    /// If there has been an error, retrieves what it is and clears the condition
    /// 
    pub fn retrieve_and_clear_error(&self) -> Option<Error> {
        self.db.retrieve_and_clear_error()
    }

    ///
    /// Panics if this animation has reached an error condition
    ///
    pub fn panic_on_error(&self) {
        self.retrieve_and_clear_error().map(|erm| panic!("{:?}", erm));
    }

    ///
    /// Convenience method that performs some edits on this animation
    /// 
    pub fn perform_edits(&self, edits: Vec<AnimationEdit>) {
        let mut editor = self.edit();
        editor.set_pending(&edits);
        editor.commit_pending();
    }

    ///
    /// Commits a set of edits to this animation
    /// 
    fn commit_edits<I: IntoIterator<Item=AnimationEdit>>(&self, edits: I) {
        // Assign element IDs
        let mut assigned_edits  = vec![];

        for edit in edits {
            assigned_edits.push(edit.assign_element_id(|| self.db.assign_element_id()));
        }

        // The animation editor performs the edits (via the MutableAnimation implementation)
        let editor = AnimationEditor::new();

        // Send the edits to the edit log
        self.db.insert_edits(assigned_edits.iter().cloned());

        // Perform the edits
        let mut mutable = self.db.edit();
        editor.perform(&mut *mutable, assigned_edits);
    }
}

impl Animation for SqliteAnimation {
    #[inline]
    fn size(&self) -> (f64, f64) {
        self.db.size()
    }

    #[inline]
    fn get_layer_ids(&self) -> Vec<u64> {
        self.db.get_layer_ids()
    }

    fn duration(&self) -> Duration {
        self.db.duration()
    }

    fn frame_length(&self) -> Duration {
        self.db.frame_length()
    }

    fn get_layer_with_id<'a>(&'a self, layer_id: u64) -> Option<Reader<'a, Layer>> {
        // Try to retrieve the layer from the editor
        let layer = self.db.get_layer_with_id(layer_id);

        // Turn into a reader if it exists
        let layer = layer.map(|layer| {
            let boxed: Box<Layer> = Box::new(layer);
            boxed
        });

        layer.map(|layer| Reader::new(layer))
    }

    fn get_log<'a>(&'a self) -> Reader<'a, EditLog<AnimationEdit>> {
        self.db.get_log()
    }

    fn edit<'a>(&'a self) -> Editor<'a, PendingEditLog<AnimationEdit>> {
        // Create an edit log that will commit to this object's log
        let edit_log = InMemoryPendingLog::new(move |edits| self.commit_edits(edits));

        // Turn it into an editor
        let edit_log: Box<'a+PendingEditLog<AnimationEdit>> = Box::new(edit_log);
        Editor::new(edit_log)
    }

    fn edit_layer<'a>(&'a self, layer_id: u64) -> Editor<'a, PendingEditLog<LayerEdit>> {
        // Create an edit log that will commit to this object's log
        let edit_log = InMemoryPendingLog::new(move |edits| {
            let edits = edits.into_iter()
                .map(|edit| AnimationEdit::Layer(layer_id, edit));

            self.commit_edits(edits)
        });

        // Turn it into an editor
        let edit_log: Box<'a+PendingEditLog<LayerEdit>> = Box::new(edit_log);
        Editor::new(edit_log)
    }
}