## Processing Design Spec > by Processing team * This is an object based design i.e. whatever a client draws from mousedown to mouseUp event will be considered as one object. * Only after a client completely draws an object i.e. do a mouseup, it will be passed to server and then be visible to other clients. * All the clients as well as server will maintain all the objects made by all the clients locally. * At the time of connection establishment, the clock of a user is synchronised with that of the server. Timestamp is provided to each object while creating it on client side itself. * Server maintains information about all clients using the board. Whenever it receives an object for broadcast, it performs necessary operation for its local data and then send this object to all other clients through network. #### Initial Setup: A client logins and ask to create a new board or an already existing board on server * Each client will maintain two stacks which will initially be empty. * Stack1 - for storing the objects on which this client has performed the operation, for undo operation. * Stack2 - for storing the objects on which this client has recently undone some operation. * Each client will maintain a map of pixel to max-priority queue of objectId based on timestamp i.e. each node of priority queue will contain objectId and timestamp. * Each client and the server will maintain a map of objectId to object, this map will contain all the objects from all the clients. * When a client ask for a new board or an already existing one from server, server sends the map from objectId to object and the map from pixel to priority queue. * Processing module on the client side uses map of pixel to priority queue to sent the UI the vector of changed intensity and pixels for display. ### Feature Handling #### 1. Draw using brush / draw shape * Client#1 draws something using brush or draw any shape. * On mouseup, UI will pass all the pixels and intensity value to us and we will create corresponding object. This object will contain objectId, userId, timestamp, operation (to be done on this object, here it is create), pixels that belong to this object and intensity. * Add this object to the stack going to be used for undo on client side. * We will also add this object to both the maps. * We will pass this object to the server. * Server will also add this object to both the maps. * Then send this object to all other clients. * Processing module on other clients side will receive this object and add this object in their maps. Then pass the changes to UI. Hence whatever the client#1 had drawn will now be visible to all the other clients. #### 2. Erase * Using an eraser is equivalent to creating a new white object. The new white object will have a flag called "erase" indicating that this is an erase object. * An erase object cannot be selected from UI (If the object at the top of a pixel position is an erase object, selection will not work from UI). #### 3. Select and Delete * UI will pass us the coordinate, where user has clicked after choosing the "select" feature. * At any pixel position, only the topmost i.e. the most recently draw object can be selected. On client side, we will check if there is any object at that pixel position using the map, if so then for representing the selected object we can send the object pixel to the UI. Now there are two possible cases - * Case 1: If the selected object was created by the same user. * Delete the object from map of objectId to object on client side. * Push this object with operation "delete" on the undo stack. * Also delete it from the map of pixel to priority queue of objectId and timestamp. * The map of pixel to priority queue of objectId and timestamp will be used to know which object was present at a particular position, in case if the selected object was at the top of the priority queue, then the object present below it should now be visible. We will find the changes using map and pass it to UI. * In parallel the information of deleting this object is sent to server. * Server will delete this object from its local maps and it will also notify other clients to delete this object from their local machine. * Processing module on the other clients side will also find the changes and pass changes to UI. * Case 2: If the selected object was created by some other user (client#2) * client#1 deletes the object from map of objectId to object. * Also deletes it from the map of pixel to priority queue of objectId and timestamp. * As the object is now selected by client#1 the object will now belong to client#1. Hence we will change the userId of selected object from client#2 userId to client#1 userId. * Push this object with operation "delete" on the undo stack. * In parallel the information of deleting this object is send to the server. * Server will delete this object from its local maps and it will also notify other clients to delete this object from their local machine. * Processing module on the other clients side first checks if the object belongs to that client, in case it does then remove all instances of the deleted objects from both the stack. Also delete object from both the maps and pass changes to UI. * The above steps to handle the two possible cases will apply for select and rotate and select and colour change as well because after a different user modifies (rotates, deletes, changes colour) of a particular object, the object belongs to the new user. Hence, undo and redo operations from previous user should not work. #### 4. Select and Rotate (for now rotate will only be in multiple of 90 degree) * First, client has to select the object for which it wants to rotate, UI will provide the position of mouse click and angle of rotation, and we will check if there is any object at that position. * For representation of 'selection' operation we can send the object pixels to UI. * If there is any object, we will calculate the difference in maximum and minimum coordinates along both the axes (x and y), calculate the centre of rotation and create a suitable rotation matrix. * We apply rotation operation on each of the pixel of object, using the rotation matrix and receive a new set of pixel positions. * We will perform the above delete feature for the previous object and create another object with the new set of pixel positions. This object will lie in the same layer (level) as it was before (we will give it the same objectId and timestamp as the previous object). * Use the above steps in "select and delete" to handle the user stacks and userId of the object. The operation stored in the user stack is "rotate". * Also, parallely send the updated object to the central server. * The central server than updates its maps and sends this info to all other clients in the same way as previous feature. #### 5. Color change * First, client has to select the object whose color it wants to change, UI will provide the position of mouse click and new color, and we will check if there is any object at that position. * For representation of 'selection' operation we can send the object pixels to UI. * We will perform the above delete feature for the previous object and create another object with the same set of positions but new intensity. This object will lie in the same layer (level) as it was before (we will give it the same objectId and timestamp as the previous object). * Use the above steps in "select and delete" to handle the user stacks and userId of the object. The operation stored in the user stack is "colorChange". * Also, parallely send the updated object to the central server. * Server will update the colour of that object in the maps and pass this object to all other clients. * All other clients will also update the color of that object, find the changed pixels and pass it to UI. #### 6. Undo-Redo * Each object contains the operation which was done on it (ex in case of draw operation is create) * There can be four possible operations that can be on the board - Create an object, Delete an object, Change colour of an object, Rotate an object. * Each client will have two stacks in their local machine. Size of stacks will be fixed. Hence Undo-redo will be available for fixed number of steps. * As each object contains operation performed on it, when any user clicks on undo button the top most object will be taken out from the undo stack and the operation performed on it will be reversed and transfered to the server. * If the operation is "create", then delete function will be called on that object and that object will be passed to the redo stack with operation as "create". * If the operation is "delete", then create function will called on that object and that object will be passed to the redo stack with operation as "delete". * If the operation is "colorChange", then colour change function will be called on that object with the previous colour as new color and current colour as the previous colour and this object will be passed to the redo stack with operation as "colorChange". * If the operation is "rotate", then rotate function will be called again with the angle 360-"rotatedAngle" on that object and the object will be passed in the redo stack with operation as "rotate". * Similarly, if the redo button is clicked by any user, the top-most operation will be performed and we will pop the top object from the redo stack and will pass it to the undo stack. <!-- [Point to remember while implementing: point by rakesh] --> #### 7. Interface with Network * Serialisation and deserialisation * Java objects can be directly serialised and deserialised. * To make a Java object serializable we can implement the java.io.Serializable interface. * The ObjectOutputStream class contains writeObject() method for serializing an Object. * The ObjectInputStream class contains readObject() method for deserializing an object. * We will have a header to indicate that the object belongs to processing module. Same will be done by the content module. So that whenever data is received through the network we can check which module it belongs to. ``` s = { header : "processingObject", data : "serialized data" } ``` #### 8. Persistence * Create a class for Persistence only on the server. An object of this class will contain the entire board state (two maps and all objects). * The above object can be serialized and the obtained byte stream can be stored/retrieved from the disk. * After retrieval, it can be deserialized to obtain the entire board state.