2 * Copyright (C) 2011 Lukáš Karas <lukas.karas@centrum.cz>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 import QtQuick 1.1 // version 1.1 include PinchArea
23 import MyTools 1.0 // for WheelArea
31 signal sendWbMessage(string sessionId, string xmlContent);
32 signal messageSent(string content);
34 property int canvasWidth : 640;
35 property int canvasHeight: 480;
36 //property string uid : "demo@makneto.org"
39 console.log("II [BoardWidget.qml]: "+msg);
42 console.log("EE [BoardWidget.qml]: "+msg);
45 console.log("WW [BoardWidget.qml]: "+msg);
48 //signal foregroundColorChanged(variant color)
49 signal whiteboardMessageReceived(string data, string contact)
50 property bool whiteboardInitialiyed: false
51 property variant queue: undefined
52 property int animationLength : 200;
54 function onWhiteboardMessageReceived(data, contact){
55 if (whiteboardInitialiyed){
56 whiteboardMessageReceived.disconnect(onWhiteboardMessageReceived);
60 if (queue===undefined)
64 obj.contact = contact;
70 //log("whiteboard is not initialized... "+JSON.stringify(queue.length));
81 source: "img/fullscreen.png"
84 AnchorChanges { target: board; anchors.top: board.parent.top; anchors.left: board.parent.left; }
91 source: "img/minimize.png"
94 AnchorChanges { target: board; anchors.right: board.parent.right; anchors.bottom: board.parent.bottom}
102 duration: animationLength
107 id: onHeightAnimation
108 duration: animationLength
111 Behavior on opacity {
112 NumberAnimation{duration: animationLength}
115 transitions: Transition {
116 // smoothly reanchor myRect and move into new position
117 AnchorAnimation { duration: animationLength }
120 Component.onCompleted: {
121 whiteboardMessageReceived.connect(onWhiteboardMessageReceived);
122 //toolbar.foregroundColorChanged.connect(board.foregroundColorChanged);
128 anchors{top:parent.top; right: toolbar.left; left: parent.left; bottom: parent.bottom}
130 property int previousWidth : canvasWidth+30
131 property int previousHeith : canvasHeight+30
136 PinchArea -> resizeAfterPinch -> onSnapshotTaken -> SVG resizing -> canvasResized
138 For faster and smooth zooming, we use PinchArea with combination WebView scale property.
139 After touch gesture release, we call resizeAfterPinch(). This take snaphost (graber component)
140 of current WebView content (scaled) and overlap WebView.
141 When snapshot is taken and shown (onSnapshotTaken), we invoke SVG scaling inside WebView.
142 This operation is long (up to seconds) and not smooth. After SVG resizing is caled canvasResized()
143 method. We currently change WebView size, return scale to 1 and remove old screenshot...
147 width: canvasWidth * 3
148 height: canvasHeight * 3
151 settings.pluginsEnabled: false
153 property bool whiteboardInitialized : false;
154 property real previousX: 0
155 property real previousY: 0
159 javaScriptWindowObjects: [QtObject {
160 WebView.windowObjectName: "connector"
161 function getUID(){ return board.parent.sessionId; }
163 wbView.whiteboardInitialized = true;
164 log("html part of whiteboard is initialized! lets make big stufs...");
165 // html part is loaded, init MaknetoWhiteboard...
166 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.init('+board.canvasWidth+', '+board.canvasHeight+')' );
168 //var zoom = Math.min( wbView.width / (wbView.contentsSize.width *0.3), wbView.height / (wbView.contentsSize.height *0.3) );
169 //wbView.evaluateJavaScript ( '$("#workArea").scrollLeft(640)');
170 //wbView.calculateZoom();
171 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.setZoom('+ wbView.width / (canvasWidth*3) +')' );
173 whiteboardMessageReceived.connect(onWhiteboardMessageReceived);
174 toolbar.foregroundColorChanged.connect(onForegroundColorChanged);
175 messageSent.connect(onMessageSent);
176 whiteboardInitialiyed = true;
177 while (queue !== undefined && queue.length !== 0){
179 var obj = tmp.shift(); // take first element (from array begin)
181 //log("queue message: "+obj.data);
182 onWhiteboardMessageReceived(obj.data, obj.contact);
185 function onForegroundColorChanged(c){
186 //log("onForegroundColorChanged "+c);
187 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.setForegroundColor("'+c+'")' );
189 function onWhiteboardMessageReceived(data, contact){
190 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.processXmlCommand('+JSON.stringify(data)+')' );
191 //log("on whiteboard msg received from "+contact+" "+JSON.stringify(data));
193 function onMessageSent(content){
194 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.messageSent('+JSON.stringify(content)+')' );
196 function sendMessage(xmlMessage){
198 sendWbMessage(board.parent.sessionId, xmlMessage);
201 function enableRendering(b){
202 wbView.renderingEnabled = b;
204 function canvasResized(){
205 var originalWidth = wbView.width;
206 var originalHeight = wbView.height;
207 wbView.width = wbView.width * wbView.scale;
208 wbView.height= wbView.height* wbView.scale;
210 // move to new center
211 wbView.x = wbView.x + (originalWidth - wbView.width)*.5;
212 wbView.y = wbView.y + (originalHeight - wbView.height)*.5;
213 wbView.previousX = wbView.x;
214 wbView.previousY = wbView.y;
216 log("resizeAfterPinch "+wbView.scale+" "+Math.floor(originalWidth)+"x"+Math.floor(originalHeight)+
217 " => "+Math.floor(wbView.width)+"x"+Math.floor(wbView.height)+" ..."+Math.floor(wbView.x) +""+Math.floor(wbView.y)+"");
219 pinchy.pinch.minimumX = Math.max( (wbView.width / (-2/3)) , -(wbView.width - wrapper.width));
220 pinchy.pinch.minimumY = Math.max( (wbView.height / (-2/3)) , -(wbView.height - wrapper.height));
221 pinchy.pinch.maximumX = 0;
222 pinchy.pinch.maximumY = 0;
224 var minWscale = wrapper.width / wbView.width;
225 var minHscale = wrapper.height / wbView.height;
226 pinchy.pinch.minimumScale = Math.max(minHscale, minWscale);
227 var maxWscale = (wrapper.width*15) / wbView.width;
228 var maxHscale = (wrapper.height*15) / wbView.height;
229 pinchy.pinch.maximumScale = Math.min(maxHscale, maxWscale);
231 graber.state = "hide";
232 //graberTimer.start();
236 WebView.windowObjectName: "console"
237 function log(msg) { console.log("II [Whiteboard]: " + msg); }
238 function debug(msg) { console.log("DD [Whiteboard]: " + msg); }
239 function warn(msg) { console.log("WW [Whiteboard]: " + msg); }
240 function error(msg) { console.log("EE [Whiteboard]: " + msg); }
244 function resizeAfterPinch(){
246 // TODO: SHOW waiting cursor while resizing SVG image
247 graber.takeSnapshot();
248 graber.state = "visible";
251 onContentsSizeChanged: {
255 Component.onCompleted: {
256 wbView.previousX = wbView.x +15
257 wbView.previousY = wbView.y +15
260 //html: "<html><head><script>console.log(\"This is in WebKit!\"); window.connector.qmlCall();</script></head><body><h1>Qt WebKit!</h1></body></html>"
261 url:"qrc:/whiteboard/main.html"
274 PropertyChanges { target: graber; opacity: 0 }
278 PropertyChanges { target: graber; opacity: 1 }
283 from: "hide"; to: "visible"
284 NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad; duration: 0 }
287 from: "visible"; to: "hide"
288 NumberAnimation { properties: "opacity"; easing.type: Easing.InOutQuad; duration: 100 }
292 log("snapshot taken");
293 wbView.evaluateJavaScript ( 'MaknetoWhiteboard.instance.setZoom('+ wbView.width * wbView.scale / (canvasWidth*3) +')' );
298 //Rectangle { id: rect; color: "transparent"; border.color: "yellow"; x: 150; y: 150; height: 250; width: 250 }
301 * I don't know better solution detect when resize animations stops...
304 id: animationNotifier
305 interval: 300; running: false; repeat: false
307 wrapper.onDimensionChanged(false);
311 // while animation we using QML scale for webView
312 function onDimensionChanged(fast){
313 if (wrapper.width < 10 || wrapper.height < 10)
317 var minWscale = wrapper.width / wbView.width;
318 var minHscale = wrapper.height / wbView.height;
319 pinchy.pinch.minimumScale = Math.max(minHscale, minWscale);
321 var wSc = wrapper.width / previousWidth;
322 var hSc = wrapper.height / previousHeith;
323 wbView.scale = Math.max(pinchy.pinch.minimumScale, Math.min(wSc, hSc)); // FIXME: it is good?
324 wbView.x = wbView.previousX + (wrapper.width - previousWidth) / 2
325 wbView.y = wbView.previousY + (wrapper.height - previousHeith) / 2
328 log("fast scale to "+wbView.scale+"");
329 log(" "+Math.floor( wbView.previousX)+" + ("+Math.floor(wrapper.width)+" - "+Math.floor(previousWidth)+") / 2) = "+Math.floor( wbView.x)+"");
330 log(" "+Math.floor( wbView.previousY)+" + ("+Math.floor(wrapper.height)+" - "+Math.floor(previousHeith)+") / 2) = "+Math.floor( wbView.y)+"");
333 animationNotifier.stop();
334 animationNotifier.start();
336 wbView.resizeAfterPinch();
337 previousWidth = wrapper.width;
338 previousHeith = wrapper.height
343 onDimensionChanged(true);
346 onDimensionChanged(true);
354 pinch.dragAxis: Pinch.XandYAxis
355 pinch.minimumScale: 1
356 pinch.maximumScale: 1
357 pinch.minimumX: -canvasWidth*2
359 pinch.minimumY: -canvasHeight*2
361 //pinch.minimumRotation: -150
362 //pinch.maximumRotation: 150
365 log("onPinchStarted");
367 wbView.evaluateJavaScript("MaknetoWhiteboard.instance.whiteboard.mouseUp2()");
372 wbView.resizeAfterPinch();
377 * delayed mouse down event is workaround for late detected gestures.
383 interval: 200; running: false; repeat: false
385 log("delayed mouseDown");
386 wbView.evaluateJavaScript("MaknetoWhiteboard.instance.whiteboard.mouseDown2("+(mouseX-wbView.x)+", "+(mouseY-wbView.y)+",0)");
392 acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
396 property int startWbX;
397 property int startWbY;
398 property variant pressed;
401 //log("mouseArea: onPressed");
402 //mouse.accepted = false;
407 pressed = mouse.button;
409 if (mouse.button == Qt.LeftButton){
411 pressDelay.mouseX = mouse.x;
412 pressDelay.mouseY = mouse.y;
414 //wbView.evaluateJavaScript("MaknetoWhiteboard.instance.whiteboard.mouseDown2("+(mouseX-wbView.x)+", "+(mouseY-wbView.y)+",0)");
420 //log("mouseArea: onDoubleClicked");
423 //log("mouseArea: onPositionChanged");
426 //log("mouseArea: onPressAndHold");
429 //log("mouseArea: onReleased");
431 wbView.evaluateJavaScript("MaknetoWhiteboard.instance.whiteboard.mouseUp2()");
433 onMousePositionChanged: {
435 //log("mouseArea: onMousePositionChanged");
436 if (pressed == Qt.LeftButton){
438 wbView.evaluateJavaScript("MaknetoWhiteboard.instance.whiteboard.mouseMove2("+(mouse.x-wbView.x)+", "+(mouse.y-wbView.y)+")");
442 if (pressed == Qt.RightButton || pressed == Qt.MiddleButton){
445 wbView.x = (mouse.x - startX) + startWbX;
446 wbView.y = (mouse.y - startY) + startWbY;
447 if (wbView.x < pinchy.pinch.minimumX)
448 wbView.x = pinchy.pinch.minimumX;
449 if (wbView.y < pinchy.pinch.minimumY)
450 wbView.y = pinchy.pinch.minimumY;
451 if (wbView.x > pinchy.pinch.maximumX)
452 wbView.x = pinchy.pinch.maximumX;
453 if (wbView.y > pinchy.pinch.maximumY)
454 wbView.y = pinchy.pinch.maximumY;
455 //log(" ... move "+wbView.x+" "+pinchy.pinch.minimumX);
460 // we use wheel for zooming on desktop...
464 //console.log("Vertical Wheel: " + delta)
465 var scaleRange = pinchy.pinch.maximumScale - pinchy.pinch.minimumScale;
467 wbView.scale += scaleRange * (delta / 5000);
468 if (wbView.scale > pinchy.pinch.maximumScale)
469 wbView.scale = pinchy.pinch.maximumScale;
470 if (wbView.scale < pinchy.pinch.minimumScale)
471 wbView.scale = pinchy.pinch.minimumScale;
472 // FIXME: adjust position when we zoom out
474 animationNotifier.stop();
475 animationNotifier.start();
478 //console.log("Horizontal Wheel: " + delta)
485 anchors{bottom: parent.bottom; right: parent.right; top: parent.top}
486 BorderImage { source: "img/lineedit.sci"; anchors.fill: parent }
491 wbView.renderingEnabled = false;
492 wbView.renderingEnabled = true;
495 wbView.renderingEnabled = false;
496 wbView.renderingEnabled = true;