Proxima Home
Gallery
Download
Documentation
Proxima Client
Proxima Server
Proxima Engine
Building an editor
User manual
Publications
Contribute
Bug reporting
Oblomov Systems
Center
Home
Courses
People
Projects
Page
Edit Page
Rename Page
Attach File
Printable
Wiki Source
More ...
Web
Recent Changes
Notify Service
News
Page Index
Search
More ...
Wiki
About TWiki
Text Formatting
Registration
Change Password
Reset Password
Users
Groups
Log In
or
Register
Proxima Client
Proxima
<!-- * Explain setviewedArea? --> The Proxima !JavaScript client (source: =[[https://subversion.cs.uu.nl/viewvc/staff.doaitse.proxima/proxima/trunk/scripts/Editor.xml?view=co][$proxima/scripts/Editor.xml]]=) keeps track of a HTML rendering tree that represents the rendering of the edited document. The script catches all edit events that occur in the browser (mouse and keyboard) and sends these as commands to the server. The incremental updates that are received from the server are applied to the HTML rendering tree. The function =sendCommand= sends a command to the server. The syntax of these commands consists of the showed elements of the =Command= datatype declared in =[[https://subversion.cs.uu.nl/viewvc/staff.doaitse.proxima/proxima/trunk/src/Proxima/GUIServer.hs?view=co][$proxima/src/Proxima/GUIServer.hs]]=: <verbatim> data Command = Metrics ((String,Int,Bool,Bool),(Int,Int,[Int])) | ContextMenuRequest ((Int,Int),(Int,Int)) | ContextMenuSelect Int | Key (Int,Modifiers) | Chr (Int,Modifiers) | Mouse MouseCommand (Int,Int, Modifiers) | EditStyle StyleEdit | Find String | SetViewedArea CommonTypes.Rectangle | Redraw | Rearrange | ClearMetrics deriving (Show, Read) data MouseCommand = MouseDown | MouseMove | MouseUp | MouseDragStart | MouseDrop deriving (Show, Read) type Modifiers = (Bool,Bool,Bool) </verbatim> Because edit events may occur in quick succession, the client maintains a queue for edit events (global variable =commandQueue=). When the client is waiting for a server response, any additional events are queued until the result has arrived, after which all queued commands are sent. Communication with the server is performed through an XMLHTTP object, and on a server response, function =state_Change= updates the status lights and processes the received updates by calling =updateTree= for each update. ---+++ Font Metrics For each font in the presentation, the server requires the character height, the baseline and a list of character widths. Unfortunately, !JavaScript does not support general font queries. To solve the problem, =initFont=creates an invisible DIV element with id =font= that contains all characters of the font. The height and widths can be measured from this =font= element. (Each character is replicated a 1000 times to increase accuracy.) In order to determine the baseline, a single letter is rendered next to an element with height 0. Because the element is aligned at the baseline of the letter, its relative position (which can be queried) is the value for the baseline. On a font query, the function =queryFont= applies the queried font and style to the =font= element and returns the collected metrics, which are sent to the server by function =updateTree= as a =Metrics= command. ---+++ Context menus Because there is no default support for context menus in !JavaScript, we use code from Dynamic Drive (www.dynamicdrive.com). On a right click mouse event, a =ContextMenuRequest= command with the mouse position and the coordinates of the top-left corner of the screen are sent to the server. The server responds with a list of items that are displayed as a context menu, and when an item is clicked, a =ContextMenuSelect= command is sent with the index of the clicked menu item. ---+++ Mouse handler The mouse handler (=mouseHandler=) sends events to the server based on user mouse events. In addition, it handles scrolling and drag and drop. Standard !JavaScript croll events cannot be used, because these are also generated when the rendering is scrolled programmatically. Using a global variable to signal this difference did not turn out reliable. Therefore, scroll events are generated explicitly, when the user drags inside a scroll bar. A downside of this method is that it doesn't support scroll wheels. The mouse handler implements a small finite state machine to handle drag and drop. Its states are: *0:* No button down <br/> *1:* Button down, but no drag yet <br/> *2:* Drag in progress <br/> *3:* Dragging on a non-dragsource, for example when the user extends the selection The state transitions are straightforward and can be seen in the code. Drag sessions are only started when the element under the cursor has class =Draggable=. In order to provide an image of the dragged node, a clone is stored in =draggedElementClone=. ---+++ Predictive Rendering Network latency may cause a delay between sending the edit event and receiving the update from the server. We tackle this problem by having the client show the predicted effect of an edit operation, until the actual update is obtained from the server. When a key is entered, = insertCharPredictively= inserts the corresponding character in the HTML rendering tree at the position of the cursor, and the cursor is moved to the right by the width of the character. Furthermore, all right sibling elements in the same row and in parent rows are moved to the right as well, until a parent column is encountered. Because edit operations are queued if the client is already waiting for a response, we need to keep track of two kinds of predictively inserted characters: characters corresponding to the already sent insert operations (=sentPredictiveInserts=), and characters corresponding to the currently queued insert operations (=currentPredictiveInserts=). On arrival of the server response, all predictive inserts are undone with =removeAllPredictiveInserts=, to make it possible to apply the received incremental update on the rendering. Subsequently, the queued inserts are sent to the server, and the corresponding predictive updates are performed on the rendering again (by =reApplySentPredictiveInserts=). Because a presentation in Proxima can be complex, it is not always possible to correctly predict the effect of an inserted character. Nevertheless, the algorithm works well for all editors in the quite diverse suite of sample editors, and it provides a massive increase in response time. An area of future research will be to enhance the predictive rendering model for handling cursor movement and navigation, and perhaps extend the presentation language to allow predictive rendering for specialized cases, such as highlighting drop targets during dragging. -- Main.MartijnSchrage - 25 Feb 2010