Code

Adding JessyInk 1.5.1 extension set by Hannes Hochreiner
[inkscape.git] / share / extensions / jessyInk_core_mouseHandler_zoomControl.js
1 // Copyright 2008, 2009 Hannes Hochreiner
2 // This program is free software: you can redistribute it and/or modify
3 // it under the terms of the GNU General Public License as published by
4 // the Free Software Foundation, either version 3 of the License, or
5 // (at your option) any later version.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11 //
12 // You should have received a copy of the GNU General Public License
13 // along with this program.  If not, see http://www.gnu.org/licenses/.
15 // Add event listener for initialisation.
16 document.addEventListener("DOMContentLoaded",  jessyInk_core_mouseHandler_zoomControl_init, false);
18 /** Initialisation function.
19  *  
20  *  This function looks for the objects of the appropriate sub-type and hands them to another function that will add the required methods.
21  */
22 function jessyInk_core_mouseHandler_zoomControl_init()
23 {
24         var elems = document.getElementsByTagNameNS("https://launchpad.net/jessyink", "mousehandler");
26         for (var counter = 0; counter < elems.length; counter++)
27         {
28                 if (elems[counter].getAttributeNS("https://launchpad.net/jessyink", "subtype") == "jessyInk_core_mouseHandler_zoomControl")
29                         jessyInk_core_mouseHandler_zoomControl(elems[counter]);
30         }
31 }
33 /** Function to initialise an object.
34  *
35  *  @param obj Object to be initialised.
36  */
37 function jessyInk_core_mouseHandler_zoomControl(obj)
38 {
39         // Last dragging position.
40         obj.dragging_last;
41         // Flag to indicate whether dragging is active currently.
42         obj.dragging_active = false;
43         // Flag to indicate whether dragging is working currently.
44         obj.dragging_working = false;
45         // Flag to indicate whether the user clicked.
46         obj.click = false;
48         /** Function supplying a custom mouse handler.
49          *
50          *  @returns A dictionary containing the new mouse handler functions.
51          */
52         obj.getMouseHandler = function ()
53         {
54                 var handlerDictio = new Object();
56                 handlerDictio[SLIDE_MODE] = new Object();
57                 handlerDictio[SLIDE_MODE][MOUSE_DOWN] = obj.mousedown;
58                 handlerDictio[SLIDE_MODE][MOUSE_MOVE] = obj.mousemove;
59                 handlerDictio[SLIDE_MODE][MOUSE_UP] = obj.mouseup;
60                 handlerDictio[SLIDE_MODE][MOUSE_WHEEL] = obj.mousewheel;
62                 return handlerDictio;
63         }
65         /** Event handler for mouse clicks.
66          *
67          *  @param e Event object.
68          */
69         obj.mouseclick = function (e)
70         {
71                 var elem = obj.getAdHocViewBbox(slides[activeSlide]["viewGroup"], obj.getCoords(e));
73                 processingEffect = true;
75                 effectArray = new Array();
77                 effectArray[0] = new Object();
78                 effectArray[0]["effect"] = "view";
79                 effectArray[0]["dir"] = 1;
80                 effectArray[0]["element"] = slides[activeSlide]["viewGroup"];
81                 effectArray[0]["options"] = new Object();
82                 effectArray[0]["options"]["length"] = 200;
84                 if (elem == null)
85                         effectArray[0]["options"]["matrixNew"] = (new matrixSVG()).fromSVGElements(1, 0, 0, 1, 0, 0);
86                 else
87                         effectArray[0]["options"]["matrixNew"] = obj.pointMatrixToTransformation(obj.rectToMatrix(elem)).mult((new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.getScreenCTM()).inv().mult((new matrixSVG()).fromSVGMatrix(elem.parentNode.getScreenCTM())).inv());
89                 transCounter = 0;
90                 startTime = (new Date()).getTime();
91                 lastFrameTime = null;
92                 effect(1);
93         }
95         /** Function to search for the element the user clicked on.
96          *
97          *      This function searches for the element with the highest z-order, which encloses the point the user clicked on
98          *      and which view box fits entierly into the currently visible part of the slide.
99          *
100          *  @param elem Element to start the search from.
101          *  @param pnt Point where the user clicked.
102          *  @returns The element the user clicked on or null, if no element could be found.
103          */
104         obj.getAdHocViewBbox = function (elem, pnt)
105         {
106                 var children = elem.childNodes;
107                 
108                 for (var counter = 0; counter < children.length; counter++)
109                 {
110                         if (children[counter].getBBox)
111                         {
112                                 var childPointList = obj.projectRect(children[counter].getBBox(), children[counter].getScreenCTM());
114                                 var viewBbox = document.documentElement.createSVGRect();
116                                 viewBbox.x = 0.0;
117                                 viewBbox.y = 0.0;
118                                 viewBbox.width = WIDTH;
119                                 viewBbox.height = HEIGHT;
121                                 var screenPointList = obj.projectRect(viewBbox, slides[activeSlide]["element"].getScreenCTM());
123                                 if (obj.pointsWithinRect([pnt], childPointList) && obj.pointsWithinRect(childPointList, screenPointList))
124                                         return children[counter];
126                                 child = obj.getAdHocViewBbox(children[counter], pnt);
128                                 if (child != null)
129                                         return child;
130                         }
131                 }
133                 return null;
134         }
136         /** Function to project a rectangle using the projection matrix supplied.
137          *
138          *  @param rect The rectangle to project.
139          *  @param projectionMatrix The projection matrix.
140          *  @returns A list of the four corners of the projected rectangle starting from the upper left corner and going counter-clockwise.
141          */
142         obj.projectRect = function (rect, projectionMatrix)
143         {
144                 var pntUL = document.documentElement.createSVGPoint();
145                 pntUL.x = rect.x;
146                 pntUL.y = rect.y;
147                 pntUL = pntUL.matrixTransform(projectionMatrix);
149                 var pntLL = document.documentElement.createSVGPoint();
150                 pntLL.x = rect.x;
151                 pntLL.y = rect.y + rect.height;
152                 pntLL = pntLL.matrixTransform(projectionMatrix);
154                 var pntUR = document.documentElement.createSVGPoint();
155                 pntUR.x = rect.x + rect.width;
156                 pntUR.y = rect.y;
157                 pntUR = pntUR.matrixTransform(projectionMatrix);
159                 var pntLR = document.documentElement.createSVGPoint();
160                 pntLR.x = rect.x + rect.width;
161                 pntLR.y = rect.y + rect.height;
162                 pntLR = pntLR.matrixTransform(projectionMatrix);
164                 return [pntUL, pntLL, pntUR, pntLR];
165         }
167         /** Function to determine whether all the points supplied in a list are within a rectangle.
168          *
169          *  @param pnts List of points to check.
170          *  @param pointList List of points representing the four corners of the rectangle.
171          *  @return True, if all points are within the rectangle; false, otherwise.
172          */
173         obj.pointsWithinRect = function (pnts, pointList)
174         {
175                 var pntUL = pointList[0];
176                 var pntLL = pointList[1];
177                 var pntUR = pointList[2];
179                 var matrixOrig = (new matrixSVG()).fromElements(pntUL.x, pntLL.x, pntUR.x, pntUL.y, pntLL.y, pntUR.y, 1, 1, 1);
180                 var matrixProj = (new matrixSVG()).fromElements(0, 0, 1, 0, 1, 0, 1, 1, 1);
182                 var matrixProjection = matrixProj.mult(matrixOrig.inv());
184                 for (var blockCounter = 0; blockCounter < Math.ceil(pnts.length / 3.0); blockCounter++)
185                 {
186                         var subPnts = new Array();
188                         for (var pntCounter = 0; pntCounter < 3.0; pntCounter++)
189                         {
190                                 if (blockCounter * 3.0 + pntCounter < pnts.length)
191                                         subPnts[pntCounter] = pnts[blockCounter * 3.0 + pntCounter];
192                                 else
193                                 {
194                                         var tmpPnt = document.documentElement.createSVGPoint();
195                                         
196                                         tmpPnt.x = 0.0;
197                                         tmpPnt.y = 0.0;
199                                         subPnts[pntCounter] = tmpPnt;
200                                 }
201                         }
203                         var matrixPnt = (new matrixSVG).fromElements(subPnts[0].x, subPnts[1].x, subPnts[2].x, subPnts[0].y, subPnts[1].y, subPnts[2].y, 1, 1, 1);
204                         var matrixTrans = matrixProjection.mult(matrixPnt);
206                         for (var pntCounter = 0; pntCounter < 3.0; pntCounter++)
207                         {
208                                 if (blockCounter * 3.0 + pntCounter < pnts.length)
209                                 {
210                                         if ((pntCounter == 0) && !((matrixTrans.e11 > 0.01) && (matrixTrans.e11 < 0.99) && (matrixTrans.e21 > 0.01) && (matrixTrans.e21 < 0.99)))
211                                                 return false;
212                                         else if ((pntCounter == 1) && !((matrixTrans.e12 > 0.01) && (matrixTrans.e12 < 0.99) && (matrixTrans.e22 > 0.01) && (matrixTrans.e22 < 0.99)))
213                                                 return false;
214                                         else if ((pntCounter == 2) && !((matrixTrans.e13 > 0.01) && (matrixTrans.e13 < 0.99) && (matrixTrans.e23 > 0.01) && (matrixTrans.e23 < 0.99)))
215                                                 return false;
216                                 }
217                         }
218                 }
220                 return true;
221         }
223         /** Event handler for mouse movements.
224          *
225          *  @param e Event object.
226          */
227         obj.mousemove = function (e)
228         {
229                 obj.click = false;
231                 if (!obj.dragging_active || obj.dragging_working)
232                         return false;
234                 obj.dragging_working = true;
236                 var p = obj.getCoords(e);
238                 if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1)
239                 {
240                         var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1);
241                 }
242                 else
243                 {
244                         var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix);
245                 }
247                 matrix.e13 += p.x - obj.dragging_last.x;
248                 matrix.e23 += p.y - obj.dragging_last.y;
250                 slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute());
252                 obj.dragging_last = p;
253                 obj.dragging_working = false;
255                 return false;
256         }
258         /** Event handler for mouse down.
259          *
260          *  @param e Event object.
261          */
262         obj.mousedown = function (e)
263         {
264                 if (obj.dragging_active)
265                         return false;
267                 var value = 0;
269                 if (e.button)
270                         value = e.button;
271                 else if (e.which)
272                         value = e.which;
274                 if (value == 1)
275                 {
276                         obj.dragging_last = obj.getCoords(e);
277                         obj.dragging_active = true;
278                         obj.click = true;
279                 }
281                 return false;
282         }
284         /** Event handler for mouse up.
285          *
286          *  @param e Event object.
287          */
288         obj.mouseup = function (e)
289         {
290                 obj.dragging_active = false;
292                 if (obj.click)
293                         return obj.mouseclick(e);
294                 else
295                         return false;
296         }
298         /** Function to get the coordinates of a point corrected for the offset of the viewport.
299          *
300          *  @param e Point.
301          *  @returns Coordinates of the point corrected for the offset of the viewport.
302          */
303         obj.getCoords = function (e)
304         {
305                 var svgPoint = document.documentElement.createSVGPoint();
306                 svgPoint.x = e.clientX + window.pageXOffset;
307                 svgPoint.y = e.clientY + window.pageYOffset;
309                 // The following is needed for Google Chrome, but causes problems
310                 // with Firefox, as viewport is not implemented in Firefox 3.5.
311                 try
312                 {
313                         svgPoint.x += document.rootElement.viewport.x;
314                         svgPoint.y += document.rootElement.viewport.y;
315                 }
316                 catch (ex)
317                 {
318                 }
320                 return svgPoint;
321         }
323         /** Event handler for scrolling.
324          *
325          *  @param e Event object.
326          */
327         obj.mousewheel = function(e)
328         {
329                 var p = obj.projectCoords(obj.getCoords(e));
331                 if (slides[activeSlide].viewGroup.transform.baseVal.numberOfItems < 1)
332                 {
333                         var matrix = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1);
334                 }
335                 else
336                 {
337                         var matrix = (new matrixSVG()).fromSVGMatrix(slides[activeSlide].viewGroup.transform.baseVal.consolidate().matrix);
338                 }
340                 if (e.wheelDelta)
341                 { // IE Opera
342                         delta = e.wheelDelta/120;
343                 }
344                 else if (e.detail)
345                 { // MOZ
346                         delta = -e.detail/3;
347                 }
349                 var widthOld = p.x * matrix.e11 + p.y * matrix.e12;
350                 var heightOld = p.x * matrix.e21 + p.y * matrix.e22;
352                 matrix.e11 *= (1.0 - delta / 20.0);
353                 matrix.e12 *= (1.0 - delta / 20.0);
354                 matrix.e21 *= (1.0 - delta / 20.0);
355                 matrix.e22 *= (1.0 - delta / 20.0);
357                 var widthNew = p.x * matrix.e11 + p.y * matrix.e12;
358                 var heightNew = p.x * matrix.e21 + p.y * matrix.e22;
360                 matrix.e13 += (widthOld - widthNew);
361                 matrix.e23 += (heightOld - heightNew);
363                 slides[activeSlide]["viewGroup"].setAttribute("transform", matrix.toAttribute());
365                 return false;
366         }
368         /** Function to project a point to screen coordinates.
369          *
370          *      @param Point.
371          *      @returns The point projected to screen coordinates.
372          */
373         obj.projectCoords = function(pnt)
374         {
375                 var matrix = slides[activeSlide]["element"].getScreenCTM();
377                 if (slides[activeSlide]["viewGroup"])
378                         matrix = slides[activeSlide]["viewGroup"].getScreenCTM();
380                 pnt = pnt.matrixTransform(matrix.inverse());
381                 return pnt;
382         }
384         /** Function to convert a rectangle into a point matrix.
385          *
386          *      The function figures out a rectangle that encloses the rectangle given and has the same width/height ratio as the viewport of the presentation.
387          *
388          *  @param rect Rectangle.
389          *  @return The upper left, upper right and lower right corner of the rectangle in a point matrix.
390          */
391         obj.rectToMatrix = function(rect)
392         {
393                 rectWidth = rect.getBBox().width;
394                 rectHeight = rect.getBBox().height;
395                 rectX = rect.getBBox().x;
396                 rectY = rect.getBBox().y;
397                 rectXcorr = 0;
398                 rectYcorr = 0;
400                 scaleX = WIDTH / rectWidth;
401                 scaleY = HEIGHT / rectHeight;
403                 if (scaleX > scaleY)
404                 {
405                         scaleX = scaleY;
406                         rectXcorr -= (WIDTH / scaleX - rectWidth) / 2;
407                         rectWidth = WIDTH / scaleX;
408                 }       
409                 else
410                 {
411                         scaleY = scaleX;
412                         rectYcorr -= (HEIGHT / scaleY - rectHeight) / 2;
413                         rectHeight = HEIGHT / scaleY;
414                 }
416                 if (rect.transform.baseVal.numberOfItems < 1)
417                 {
418                         mRectTrans = (new matrixSVG()).fromElements(1, 0, 0, 0, 1, 0, 0, 0, 1);
419                 }
420                 else
421                 {
422                         mRectTrans = (new matrixSVG()).fromSVGMatrix(rect.transform.baseVal.consolidate().matrix);
423                 }
425                 newBasePoints = (new matrixSVG()).fromElements(rectX, rectX, rectX, rectY, rectY, rectY, 1, 1, 1);
426                 newVectors = (new matrixSVG()).fromElements(rectXcorr, rectXcorr + rectWidth, rectXcorr + rectWidth, rectYcorr, rectYcorr, rectYcorr + rectHeight, 0, 0, 0);
428                 return mRectTrans.mult(newBasePoints.add(newVectors));
429         }
431         /** Function to return a transformation matrix from a point matrix.
432          *
433          *      @param mPoints The point matrix.
434          *      @returns The transformation matrix.
435          */
436         obj.pointMatrixToTransformation = function(mPoints)
437         {
438                 mPointsOld = (new matrixSVG()).fromElements(0, WIDTH, WIDTH, 0, 0, HEIGHT, 1, 1, 1);
440                 return mPointsOld.mult(mPoints.inv());
441         }