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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
#![deny(missing_docs)] //! Editor interface. use std::any::Any; use std::sync::Arc; /// A generic interface for editors, implemented on controllers. /// /// Provides all information necessary to execute actions, /// select objects, navigate and update. /// This makes it possible to write reusable generic actions. /// /// History is handled externally, using `Box<Any>` for changes. /// The editor should not store any history internally, /// unless it is garbage collected from within the `Any` data sent outside. /// /// All changes must be reversible from the information that is sent outside. /// You can use `Arc` to check for uniqueness for resources with a handle. /// If the internal `Arc` is unique, it means the information can safely be /// removed. This must happen internally. /// /// A history buffer must keep handles alive since they can not be recreated. /// If this is a problem, then the editor must map to a recreatable resource. /// /// The controller should keep same selection state across multiple views. /// /// References should not be handled internally. /// This is done through algorithms using the reference information. /// For example, before deleting an object, checks that all affected /// references are cascading, such there are no loose references after deletion. /// Cascading references deletes the objects that the reference points from. /// /// Methods that returns `Result` can trigger a rollback in actions. /// This is to prevent logical errors from affecting data. /// Concurrent actions are not permitted at the same time. /// /// View information must be stored internally in the editor. /// If the editor state depends on the view state, then it should not be /// updated before `refresh_views` is called. pub trait Editor { /// Gets the current cursor position in 2D. fn cursor_2d(&self) -> Option<[f64; 2]>; /// Gets the current cursor position in 3D world coordinates. fn cursor_3d(&self) -> Option<[f64; 3]>; /// Try to hit objects at 2D position. fn hit_2d(&self, pos: [f64; 2]) -> Vec<(Type, Object)>; /// Try to hit objects at 3D position. fn hit_3d(&self, pos: [f64; 3]) -> Vec<(Type, Object)>; /// Select a single object. fn select(&mut self, ty: Type, obj: Object) -> Result<(), ()>; /// Select multiple objects. /// Adds to the current selection. fn select_multiple(&mut self, ty: Type, objs: &[Object]) -> Result<(), ()>; /// Deselect multiple objects. /// Removes from the current selection. fn deselect_multiple(&mut self, ty: Type, objs: &[Object]) -> Result<(), ()>; /// Deselect everything of a type. fn select_none(&mut self, ty: Type) -> Result<(), ()>; /// Inserts a new object. fn insert(&mut self, ty: Type, args: &Any) -> Result<Object, ()>; /// Returns an object which references must be updated when /// using swap-remove by replacing object with last one in same table. fn delete(&mut self, ty: Type, obj: Object) -> Result<Option<Object>, ()>; /// Updates an object with new values. fn update(&mut self, ty: Type, obj: Object, args: &Any) -> Result<(), ()>; /// Replaces an object with another. /// Keeps references pointing to the old object, but deletes /// references pointing from the old object. fn replace(&mut self, ty: Type, from: Object, to: Object) -> Result<Option<Object>, ()>; /// Get the field of an object. fn get<'a>(&'a self, ty: Type, obj: Object) -> Result<&'a Any, ()>; /// Get references pointing to an object. fn references_to(&self, ty: Type, obj: Object) -> Vec<Reference>; /// Get references pointing from an object to other objects. fn references_from(&self, ty: Type, obj: Object) -> Vec<Reference>; /// Get the visible objects of a type. fn visible(&self, ty: Type) -> Vec<Object>; /// Gets the selected object of a type. /// If the editor supports multiple selection, /// the selected object is usually the last in the selected list. fn selected(&self, ty: Type) -> Option<Object>; /// Gets the multiple selected objects of a type. /// The order of the selected objects matter. fn multiple_selected(&self, ty: Type) -> Vec<Object>; /// Get all objects of a type. fn all(&self, ty: Type) -> Vec<Object>; /// Navigate to an object such that it becomes visible. fn navigate_to(&mut self, ty: Type, obj: Object) -> Result<(), ()>; /// Gets the types in the editor. fn types(&self) -> Vec<Type>; /// Get the fields of an object. /// This requires an object because it can be dynamically typed. /// Fields of statically types are known at compile time. fn fields_of(&self, ty: Type, obj: Object) -> Vec<Field>; /// Updates a field. This is used by property widgets. fn update_field(&mut self, ty: Type, obj: Object, field: Field, val: &Any) -> Result<(), ()>; /// Refreshes the views. /// This is called at the end of each action to update cached data. fn refresh_views(&mut self); } /// The type of an object. /// This does not have be unique for Rust types. /// Dynamically typed objects should use same id. #[derive(Clone, Copy, Debug)] pub struct Type(pub &'static str); /// The object id. #[derive(Clone, Copy, Debug)] pub struct Object(pub usize); /// Stores information about a reference. pub struct Reference { /// The type of the from object. pub from_ty: Type, /// The id of the from object. pub from_obj: Object, /// The type of the to object. pub to_type: Type, /// The id of the to object. pub to_obj: Object, /// Whether to delete objects using this reference. /// When `false`, deletion will be cancelled with an error. pub cascade: bool, } /// Field information. pub struct Field { /// The name of field. pub name: Arc<String>, /// The type of the field. pub ty: Type, /// The index within array, 0 for normal fields. pub index: usize, /// 0 for a normal named field, length for array. pub array: usize, } /// A helper function for `Editor::delete` implementation. pub fn delete<T>(items: &mut Vec<T>, obj: Object) -> Result<Option<Object>, ()> { if items.len() == 0 { return Err(()); } let upd_obj = if obj.0 == items.len() - 1 { // The deleted object was last, no update needed. None } else { // Update references to the last object, // which now takes the place of the deleted object. Some(Object(items.len() - 1)) }; items.swap_remove(obj.0); Ok(upd_obj) } /// A helper function for `Editor::update` implementation. pub fn update<T: Any + Clone>(items: &mut Vec<T>, obj: Object, args: &Any) -> Result<(), ()> { match args.downcast_ref::<T>() { None => { return Err(()); } Some(val) => { items[obj.0] = val.clone(); Ok(()) } } } /// A helper function for `Editor::all` implementation. pub fn all<T>(items: &Vec<T>) -> Vec<Object> { (0..items.len()).map(|i| Object(i)).collect() } /// A helper function for `Editor::get` implementation. pub fn get<T: Any>(items: &Vec<T>, obj: Object) -> Result<&Any, ()> { Ok(try!(items.get(obj.0).ok_or(()))) }