diff --git a/src/activities/drawing/ColorDialogue.qml b/src/activities/drawing/ColorDialogue.qml index 743460f36..3baac9664 100644 --- a/src/activities/drawing/ColorDialogue.qml +++ b/src/activities/drawing/ColorDialogue.qml @@ -1,199 +1,199 @@ /* GCompris - ColorDialogue.qml * * Copyright (C) 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity import "qrc:/gcompris/src/core/core.js" as Core Rectangle { id: picker width: background.width * 0.20 height: background.height * 0.33 color: "transparent" property real hue property real saturation property real lightness property int barHeight: height property int barWidth: width * 0.25 property color currentColorCode: picker.currentColor() function currentColor() { return Qt.hsla(picker.hue, picker.saturation, picker.lightness, 1.0) } function updateColor(clr) { // QML does not expose any way of getting the components of a color // parsed by Qt, thus we have to to the parsing ourselves (this breaks // named colors) if (clr[0] == '"') { clr = clr.slice(1, 8); } if (clr[0] == '#') { clr = clr.slice(1); } var r = parseInt(clr.slice(0, 2), 16) / 255; var g = parseInt(clr.slice(2, 4), 16) / 255; var b = parseInt(clr.slice(4, 6), 16) / 255; // Formulae taken from ColorPicker.qml, Plasma Workspace, // Copyright 2013 Marco Martin var min = Math.min(r, Math.min(g, b)) var max = Math.max(r, Math.max(g, b)) var c = max - min var h if (c == 0) { h = 0 } else if (max == r) { h = ((g - b) / c) % 6 } else if (max == g) { h = ((b - r) / c) + 2 } else if (max == b) { h = ((r - g) / c) + 4 } picker.hue = (1/6) * h console.log(picker.hue) picker.saturation = (c / (1 - Math.abs(2 * ((max + min) / 2) - 1))) picker.lightness = (max + min)/2 sMarker.y = saturation * barHeight hsMarker.y = hue * barHeight lsMarker.y = (1 - lightness) * barHeight return true; } // Vertical bar that displays the hue of the color MouseArea { id: hueBar width: picker.barWidth height: picker.barHeight anchors.left: parent.left anchors.leftMargin: 10 onPositionChanged: { picker.hue = mouse.y / height hsMarker.y = mouse.y > hueBar.y+hueBar.height ? Math.min(hueBar.y + hueBar.height - 2 , mouse.y) : Math.max(hueBar.y, mouse.y) } // Display the colors Rectangle { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.0/6.0; color: Qt.hsla(0.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 1.0/6.0; color: Qt.hsla(1.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 2.0/6.0; color: Qt.hsla(2.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 3.0/6.0; color: Qt.hsla(3.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 4.0/6.0; color: Qt.hsla(4.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 5.0/6.0; color: Qt.hsla(5.0/6.0, 1, picker.lightness, 1) } GradientStop { position: 6.0/6.0; color: Qt.hsla(6.0/6.0, 1, picker.lightness, 1) } } } // Marker Rectangle { id: hsMarker width: picker.barWidth height: 10 radius: 2 y: hueBar.y + hueBar.height / 2 anchors.horizontalCenter: hueBar.horizontalCenter color: "transparent" border { color: "white" width: 2 } } } //Vertical bar that displays the saturation of the color MouseArea { id: saturationBar width: picker.barWidth height: picker.barHeight anchors.left: hueBar.right anchors.leftMargin: 10 onPositionChanged: { picker.saturation = mouse.y/height sMarker.y = mouse.y > saturationBar.y+saturationBar.height ? Math.min(saturationBar.y + saturationBar.height - 2 , mouse.y) : Math.max(saturationBar.y, mouse.y) } Rectangle { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.0; color: Qt.hsla(picker.hue, 0, picker.lightness, 0) } GradientStop { position: 1.0; color: Qt.hsla(picker.hue, 1, picker.lightness, 1) } } } Rectangle { id: sMarker width: picker.barWidth height: 10 radius: 2 y: saturationBar.height * (1 - picker.saturation) color: "transparent" border { color: "white" width: 2 } } } // Vertical bar that displays the lightness of the color MouseArea { id: lightnessBar width: picker.barWidth height: picker.barHeight anchors.left: saturationBar.right anchors.leftMargin: 7 onPositionChanged: { picker.lightness = 1 - mouse.y / height lsMarker.y = lightnessBar.height * (1 - picker.lightness) } Rectangle { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.0; color: Qt.hsla(picker.hue, picker.saturation, 1, 1) } GradientStop { position: 0.5; color: Qt.hsla(picker.hue, picker.saturation, 0.5, 1) } GradientStop { position: 1.0; color: Qt.hsla(picker.hue, picker.saturation, 0, 1) } } } Rectangle { id: lsMarker width: picker.barWidth height: 10 radius: 2 y: lightnessBar.height * (1 - picker.lightness) color: "transparent" border { color: "white" width: 2 } } } } diff --git a/src/activities/drawing/Drawing.qml b/src/activities/drawing/Drawing.qml index b411fd9ca..34d92bb1e 100644 --- a/src/activities/drawing/Drawing.qml +++ b/src/activities/drawing/Drawing.qml @@ -1,923 +1,923 @@ -/* GCompris - paint.qml +/* GCompris - Drawing.qml * * Copyright (C) 2016 Toncu Stefan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity import "qrc:/gcompris/src/core/core.js" as Core // TODO1: undo/redo // TODO: (optional): Shape creator: press on the canvas to draw lines; at the end, press on the starting point to create a shape ActivityBase { id: activity onStart: focus = true onStop: {} pageComponent: Rectangle { id: background anchors.fill: parent color: "#add8e6" signal start signal stop Component.onCompleted: { activity.start.connect(start) activity.stop.connect(stop) } property bool started: false // When the width/height is changed, paint the last image on the canvas onWidthChanged: { if (items.background.started) { items.widthHeightChanged = true Activity.initLevel() } } onHeightChanged: { if (items.background.started) { items.widthHeightChanged = true Activity.initLevel() } } File { id: file onError: console.error("File error: " + msg); } Timer { id: timer interval: 1 running: true repeat: true property int index: 0 onTriggered: { index ++ if (index >= 10) stop() } } function reloadSelectedPen() { timer.index = 0 timer.start() } SaveToFilePrompt { id: saveToFilePrompt z: -1 onYes: { Activity.saveToFile(true) if (main.x == 0) load.opacity = 0 activity.home() } onNo: { if (main.x == 0) load.opacity = 0 activity.home() } onCancel: { saveToFilePrompt.z = -1 saveToFilePrompt.opacity = 0 main.opacity = 1 } } SaveToFilePrompt { id: saveToFilePrompt2 z: -1 onYes: { cancel() Activity.saveToFile(true) Activity.initLevel() } onNo: { cancel() Activity.initLevel() } onCancel: { saveToFilePrompt2.z = -1 saveToFilePrompt2.opacity = 0 main.opacity = 1 } } // Add here the QML items you need to access in javascript QtObject { id: items property Item main: activity.main property alias background: background property alias bar: bar property alias bonus: bonus property alias canvas: canvas property alias timer: timer property alias area: area property alias inputText: inputTextFrame.inputText property alias inputTextFrame: inputTextFrame property alias parser: parser property alias gridView2: loadSavedPainting.gridView2 property alias file: file property alias load: load property alias mainRegion: main property alias shape: shape property int activeColorIndex: 1 property alias toolsMode: foldablePanels.toolsMode property alias saveToFilePrompt2: saveToFilePrompt2 property alias saveToFilePrompt: saveToFilePrompt property color paintColor: "#00ff00" property var urlImage property bool next: false property bool next2: false property bool loadSavedImage: false property bool initSave: false property bool nothingChanged: true property bool widthHeightChanged: false property bool mainAnimationOnX: true property bool undoRedo: false property int sizeS: 2 property int index: 0 property string toolSelected: "pencil" property string patternType: "dot" property string lastUrl property string lastToolSelected: "pencil" } JsonParser { id: parser onError: console.error("Paint: Error parsing JSON: " + msg); } onStart: { Activity.start(items) } onStop: { Activity.stop() } DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | reload } onHelpClicked: { displayDialog(dialogHelp) } onHomeClicked: { if (!items.nothingChanged) { saveToFilePrompt.text = qsTr("Do you want to save your painting?") main.opacity = 0.5 saveToFilePrompt.opacity = 1 saveToFilePrompt.z = 200 } else { if (main.x == 0) load.opacity = 0 activity.home() } } onReloadClicked: { if (!items.nothingChanged) { saveToFilePrompt2.text = qsTr("Do you want to save your painting before reseting the board?") main.opacity = 0.5 saveToFilePrompt2.opacity = 1 saveToFilePrompt2.z = 200 } else { Activity.initLevel() } } } Bonus { id: bonus Component.onCompleted: win.connect(Activity.nextLevel) } function hideExpandedTools () { // hide the inputTextFrame items.inputTextFrame.opacity = 0 items.inputTextFrame.z = -1 items.inputText.text = "" } Rectangle { id: main width: parent.width height: parent.height color: background.color Behavior on x { enabled: items.mainAnimationOnX NumberAnimation { target: main property: "x" duration: 800 easing.type: Easing.InOutQuad } } Behavior on y { NumberAnimation { target: main property: "y" duration: 800 easing.type: Easing.InOutQuad } } // Text input box. TextInputTool { id: inputTextFrame } //Rectangle { // id: canvasBackground // z: 1 // anchors.fill: parent // anchors.margins: 8 // color: "green" Canvas { id: canvas anchors.fill: parent property real lastX property real lastY // for brush property var lastPoint property var currentPoint property var ctx property string url: "" GCText { id: onBoardText text: "" color: items.paintColor // font.pointSize: (ApplicationSettings.baseFontSize + 32) * ApplicationInfo.fontRatio font.pointSize: items.sizeS * 10 z: -1 opacity: 0 } function clearCanvas() { // clear all drawings from the board var ctx = getContext('2d') ctx.beginPath() ctx.clearRect(0, 0, canvas.width, canvas.height); paintWhite() canvas.ctx.strokeStyle = "#ffffff" } function paintWhite() { canvas.ctx = getContext("2d") canvas.ctx.fillStyle = "#ffffff" canvas.ctx.beginPath() canvas.ctx.moveTo(0, 0) canvas.ctx.lineTo(background.width, 0) canvas.ctx.lineTo(background.width, background.height) canvas.ctx.lineTo(0, background.height) canvas.ctx.closePath() canvas.ctx.fill() } onImageLoaded: { // load images from files if (canvas.url != "") { canvas.clearCanvas() if (items.loadSavedImage) { canvas.ctx.drawImage(canvas.url, 0, 0, canvas.width, canvas.height) } else { canvas.ctx.drawImage(canvas.url, canvas.width / 2 - canvas.height / 2, 0, canvas.height, canvas.height) } // mark the loadSavedImage as finished items.loadSavedImage = false requestPaint() items.lastUrl = canvas.url unloadImage(canvas.url) items.mainAnimationOnX = true canvas.url = "" // undo and redo } else if (items.undoRedo) { ctx.drawImage(items.urlImage,0,0) requestPaint() items.lastUrl = canvas.url unloadImage(items.urlImage) items.undoRedo = false } } function resetShape () { area.currentShape.rotationn = 0 area.currentShape.x = 0 area.currentShape.y = 0 area.currentShape.width = 0 area.currentShape.height = 0 area.endX = 0 area.endY = 0 canvas.lastX = 0 canvas.lastY = 0 } function midPointBtw(p1, p2) { return { x: p1.x + (p2.x - p1.x) / 2, y: p1.y + (p2.y - p1.y) / 2 }; } function distanceBetween(point1, point2) { return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)); } function angleBetween(point1, point2) { return Math.atan2( point2.x - point1.x, point2.y - point1.y ); } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function removeShadow() { // remove the shadow effect canvas.ctx.shadowColor = 'rgba(0,0,0,0)' canvas.ctx.shadowBlur = 0 canvas.ctx.shadowOffsetX = 0 canvas.ctx.shadowOffsetY = 0 } onPaint: { canvas.ctx = getContext('2d') } MouseArea { id: area anchors.fill: parent hoverEnabled: false property var mappedMouse: mapToItem(parent, mouseX, mouseY) property var currentShape: items.toolSelected == "circle" ? circle : rectangle property var originalX property var originalY property real endX property real endY Timer { id: moveOnBoardText interval: 1 repeat: true running: false triggeredOnStart: { onBoardText.x = area.realMouseX onBoardText.y = area.realMouseY - onBoardText.height * 0.8 } } property real realMouseX: mouseX property real realMouseY: mouseY onPressed: { if (items.nothingChanged) items.nothingChanged = false background.hideExpandedTools() mappedMouse = mapToItem(parent, mouseX, mouseY) print("tools: ",items.toolSelected) if (items.toolSelected == "rectangle" || items.toolSelected == "circle" || items.toolSelected == "lineShift") { // set the origin coordinates for current shape currentShape.x = mapToItem(parent, mouseX, mouseY).x currentShape.y = mapToItem(parent, mouseX, mouseY).y originalX = currentShape.x originalY = currentShape.y // set the current color for the current shape currentShape.color = items.paintColor } else if (items.toolSelected == "line") { // set the origin coordinates for current shape currentShape.x = mapToItem(parent, mouseX, mouseY).x currentShape.y = mapToItem(parent, mouseX, mouseY).y originalX = currentShape.x originalY = currentShape.y currentShape.height = items.sizeS // set the current color for the current shape currentShape.color = items.paintColor } else if (items.toolSelected == "text") { canvas.lastX = mouseX canvas.lastY = mouseY } else if (items.toolSelected == "pattern") { canvas.ctx.strokeStyle = "#ffffff" // very important! canvas.lastX = mouseX canvas.lastY = mouseY Activity.points.push({x: mouseX, y: mouseY}) } else if (items.toolSelected == "spray") { canvas.lastX = mouseX canvas.lastY = mouseY } else if (items.toolSelected == "eraser") { canvas.lastX = mouseX canvas.lastY = mouseY canvas.ctx.strokeStyle = "#ffefff" } else if (items.toolSelected == "pencil") { canvas.lastX = mouseX canvas.lastY = mouseY } else if (items.toolSelected == "brush3") { canvas.lastX = mouseX canvas.lastY = mouseY canvas.lastPoint = { x: mouseX, y: mouseY } } else if (items.toolSelected == "brush4") { canvas.ctx.strokeStyle = "#ffefff" Activity.points.push({x: mouseX, y: mouseY}) } else if (items.toolSelected == "brush5") { Activity.connectedPoints.push({x: mouseX, y: mouseY}) } else if (items.toolSelected == "blur") { canvas.lastX = mouseX canvas.lastY = mouseY } else { canvas.lastX = mouseX canvas.lastY = mouseY print("ON Pressed - tool not known") } } onReleased: { // for line tool mappedMouse = mapToItem(parent, mouseX, mouseY) area.endX = mappedMouse.x area.endY = mappedMouse.y // Reset text elements: // hide the text onBoardText.opacity = 0 onBoardText.z = -1 // stop the text following the cursor if (moveOnBoardText.running) moveOnBoardText.stop() // disable hover area.hoverEnabled = false if (items.toolSelected == "line") { canvas.removeShadow() canvas.ctx.fillStyle = items.paintColor canvas.ctx.beginPath() var angleRad = (360 - area.currentShape.rotationn) * Math.PI / 180 var auxX = items.sizeS * Math.sin(angleRad) var auxY = items.sizeS * Math.cos(angleRad) canvas.ctx.moveTo(area.currentShape.x,area.currentShape.y) canvas.ctx.lineTo(area.endX,area.endY) canvas.ctx.lineTo(area.endX + auxX,area.endY + auxY) canvas.ctx.lineTo(area.currentShape.x + auxX,area.currentShape.y + auxY) canvas.ctx.closePath() canvas.ctx.fill() canvas.resetShape() canvas.requestPaint() } if (items.toolSelected == "circle") { canvas.removeShadow() canvas.ctx = canvas.getContext('2d') canvas.ctx.beginPath(); canvas.ctx.arc(area.currentShape.x + area.currentShape.width / 2, area.currentShape.y + area.currentShape.width / 2, area.currentShape.width / 2, 0, 2 * Math.PI, false); canvas.ctx.fillStyle = items.paintColor canvas.ctx.fill(); canvas.resetShape() canvas.requestPaint() } if (items.toolSelected == "rectangle" || items.toolSelected == "lineShift") { canvas.removeShadow() canvas.ctx.fillStyle = items.paintColor canvas.ctx.beginPath() canvas.ctx.moveTo(area.currentShape.x,area.currentShape.y) canvas.ctx.lineTo(area.currentShape.x + area.currentShape.width,area.currentShape.y) canvas.ctx.lineTo(area.currentShape.x + area.currentShape.width,area.currentShape.y + area.currentShape.height) canvas.ctx.lineTo(area.currentShape.x,area.currentShape.y + area.currentShape.height) canvas.ctx.closePath() canvas.ctx.fill() canvas.resetShape() canvas.requestPaint() } // Todo: Remove use of onBoardText and use items.sizeS for font size! if (items.toolSelected == "text" && onBoardText.text != "") { canvas.removeShadow() canvas.ctx.fillStyle = items.paintColor canvas.ctx.font = "15px" + ApplicationSettings.font console.log(ApplicationSettings.font) //canvas.ctx.font = items.sizeS * 10 + "pt sans-serif" canvas.ctx.strokeText(onBoardText.text,area.realMouseX,area.realMouseY) onBoardText.text = "" canvas.requestPaint() } // reset the "points" array if (items.toolSelected == "pattern" || items.toolSelected == "brush4") Activity.points = [] if (items.toolSelected == "brush5") Activity.connectedPoints = [] // push the state of the current board on UNDO stack items.urlImage = canvas.toDataURL() items.lastUrl = items.urlImage Activity.undo = Activity.undo.concat(items.urlImage) if (Activity.redo.length != 0) { print("resetting redo array!") Activity.redo = [] } if (items.toolSelected != "circle" && items.toolSelected != "rectangle" && items.toolSelected != "line" && items.toolSelected != "lineShift") items.next = true else items.next = false // print("undo: " + Activity.undo.length + " redo: " + Activity.redo.length) area.hoverEnabled = false } onPositionChanged: { canvas.ctx = canvas.getContext('2d') canvas.ctx.strokeStyle = items.toolSelected == "eraser" ? "#ffffff" : items.toolSelected == "pattern" ? canvas.ctx.createPattern(shape.toDataURL(), 'repeat') : items.toolSelected == "brush4" ? "black" : items.paintColor if (items.toolSelected == "pencil" || items.toolSelected == "eraser") { canvas.removeShadow() canvas.ctx = canvas.getContext('2d') canvas.ctx.lineWidth = items.toolSelected == "eraser" ? items.sizeS * 4 : items.sizeS canvas.ctx.lineCap = 'round' canvas.ctx.lineJoin = 'round' canvas.ctx.beginPath() canvas.ctx.moveTo(canvas.lastX, canvas.lastY) canvas.lastX = area.mouseX canvas.lastY = area.mouseY canvas.ctx.lineTo(canvas.lastX, canvas.lastY) canvas.ctx.stroke() canvas.requestPaint() } else if (items.toolSelected == "rectangle") { mappedMouse = mapToItem(parent, mouseX, mouseY) var width = mappedMouse.x - area.originalX var height = mappedMouse.y - area.originalY if (Math.abs(width) > Math.abs(height)) { if (width < 0) { currentShape.x = area.originalX + width currentShape.y = area.originalY } if (height < 0) currentShape.y = area.originalY + height currentShape.width = Math.abs(width) currentShape.height = Math.abs(height) } else { if (height < 0) { currentShape.x = area.originalX currentShape.y = area.originalY + height } if (width < 0) currentShape.x = area.originalX + width currentShape.height = Math.abs(height) currentShape.width = Math.abs(width) } } else if (items.toolSelected == "circle") { mappedMouse = mapToItem(parent, mouseX, mouseY) var width = mappedMouse.x - area.originalX var height = mappedMouse.y - area.originalY if (height < 0 && width < 0) { currentShape.x = area.originalX - currentShape.width currentShape.y = area.originalY - currentShape.height } else if (height < 0) { currentShape.x = area.originalX currentShape.y = area.originalY - currentShape.height } else if (width < 0) { currentShape.x = area.originalX - currentShape.width currentShape.y = area.originalY } else { currentShape.x = area.originalX currentShape.y = area.originalY } currentShape.height = currentShape.width = Math.max(Math.abs(width), Math.abs(height)) } else if (items.toolSelected == "line") { mappedMouse = mapToItem(parent, mouseX, mouseY) var width = mappedMouse.x - area.originalX var height = mappedMouse.y - area.originalY var distance = Math.sqrt( Math.pow(width,2) + Math.pow(height,2) ) var p1x = area.originalX var p1y = area.originalY var p2x = area.originalX + 200 var p2y = area.originalY var p3x = mappedMouse.x var p3y = mappedMouse.y var p12 = Math.sqrt(Math.pow((p1x - p2x),2) + Math.pow((p1y - p2y),2)) var p23 = Math.sqrt(Math.pow((p2x - p3x),2) + Math.pow((p2y - p3y),2)) var p31 = Math.sqrt(Math.pow((p3x - p1x),2) + Math.pow((p3y - p1y),2)) var angleRad = Math.acos((p12 * p12 + p31 * p31 - p23 * p23) / (2 * p12 * p31)) var angleDegrees if (height < 0) angleDegrees = angleRad * 180 / Math.PI else angleDegrees = 360 - angleRad * 180 / Math.PI currentShape.rotationn = 360 - angleDegrees currentShape.width = distance } else if (items.toolSelected == "lineShift") { mappedMouse = mapToItem(parent, mouseX, mouseY) var width = mappedMouse.x - area.originalX var height = mappedMouse.y - area.originalY if (Math.abs(width) > Math.abs(height)) { if (height < 0) currentShape.y = area.originalY if (width < 0) { currentShape.x = area.originalX + width currentShape.y = area.originalY } currentShape.width = Math.abs(width) currentShape.height = items.sizeS } else { if (width < 0) currentShape.x = area.originalX if (height < 0) { currentShape.x = area.originalX currentShape.y = area.originalY + height } currentShape.height = Math.abs(height) currentShape.width = items.sizeS } } else if (items.toolSelected == "pattern") { canvas.removeShadow() Activity.points.push({x: mouseX, y: mouseY}) canvas.ctx = canvas.getContext('2d') canvas.ctx.lineWidth = items.sizeS * 5 canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round' var p1 = Activity.points[0] var p2 = Activity.points[1] if (!p1 || !p2) return canvas.ctx.beginPath() canvas.ctx.moveTo(p1.x, p1.y) for (var i = 1, len = Activity.points.length; i < len; i++) { var midPoint = canvas.midPointBtw(p1, p2); canvas.ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y); p1 = Activity.points[i]; p2 = Activity.points[i+1]; } canvas.ctx.lineTo(p1.x, p1.y); canvas.ctx.stroke(); canvas.requestPaint() } else if (items.toolSelected == "spray") { canvas.removeShadow() canvas.lastX = mouseX canvas.lastY = mouseY canvas.ctx = canvas.getContext('2d') canvas.ctx.lineWidth = items.sizeS * 5 canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round' canvas.ctx.moveTo(canvas.lastX, canvas.lastY) canvas.ctx.fillStyle = items.paintColor for (var i = 50; i--; i >= 0) { var radius = items.sizeS * 5; var offsetX = canvas.getRandomInt(-radius, radius); var offsetY = canvas.getRandomInt(-radius, radius); canvas.ctx.fillRect(canvas.lastX + offsetX, canvas.lastY + offsetY, 1, 1); } canvas.requestPaint() } else if (items.toolSelected == "brush3") { canvas.removeShadow() canvas.lastX = mouseX canvas.lastY = mouseY canvas.ctx.lineWidth = items.sizeS * 1.2 canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round'; canvas.ctx.beginPath(); canvas.ctx.globalAlpha = 1; canvas.ctx.moveTo(canvas.lastPoint.x, canvas.lastPoint.y); canvas.ctx.lineTo(canvas.lastX, canvas.lastY); canvas.ctx.stroke(); canvas.ctx.moveTo(canvas.lastPoint.x - 3, canvas.lastPoint.y - 3); canvas.ctx.lineTo(canvas.lastX - 3, canvas.lastY - 3); canvas.ctx.stroke(); canvas.ctx.moveTo(canvas.lastPoint.x - 2, canvas.lastPoint.y - 2); canvas.ctx.lineTo(canvas.lastX - 2, canvas.lastY - 2); canvas.ctx.stroke(); canvas.ctx.moveTo(canvas.lastPoint.x + 2, canvas.lastPoint.y + 2); canvas.ctx.lineTo(canvas.lastX + 2, canvas.lastY + 2); canvas.ctx.stroke(); canvas.ctx.moveTo(canvas.lastPoint.x + 3, canvas.lastPoint.y + 3); canvas.ctx.lineTo(canvas.lastX + 3, canvas.lastY + 3); canvas.ctx.stroke(); canvas.lastPoint = { x: canvas.lastX, y: canvas.lastY }; canvas.requestPaint() } else if(items.toolSelected == "brush4") { canvas.removeShadow() Activity.points.push({x: mouseX, y: mouseY}) canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round' canvas.ctx.fillStyle = items.paintColor canvas.ctx.lineWidth = items.sizeS / 4 for (var i = 0; i < Activity.points.length; i++) { canvas.ctx.beginPath(); canvas.ctx.arc(Activity.points[i].x, Activity.points[i].y, 5 * items.sizeS, 0, Math.PI * 2, false); canvas.ctx.fill(); canvas.ctx.stroke(); } canvas.requestPaint() } else if(items.toolSelected == "brush5") { canvas.removeShadow() Activity.connectedPoints.push({x: mouseX, y: mouseY}) canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round'; canvas.ctx.lineWidth = 1 var p1 = Activity.connectedPoints[0] var p2 = Activity.connectedPoints[1] if (!p1 || !p2) return canvas.ctx.beginPath() canvas.ctx.moveTo(p1.x, p1.y) for (var i = 1, len = Activity.connectedPoints.length; i < len; i++) { var midPoint = canvas.midPointBtw(p1, p2) canvas.ctx.quadraticCurveTo(p1.x, p1.y, midPoint.x, midPoint.y) p1 = Activity.connectedPoints[i] p2 = Activity.connectedPoints[i+1] } canvas.ctx.lineTo(p1.x, p1.y) canvas.ctx.stroke() for (var i = 0; i < Activity.connectedPoints.length; i++) { var dx = Activity.connectedPoints[i].x - Activity.connectedPoints[Activity.connectedPoints.length-1].x; var dy = Activity.connectedPoints[i].y - Activity.connectedPoints[Activity.connectedPoints.length-1].y; var d = dx * dx + dy * dy; if (d < 1000) { canvas.ctx.beginPath(); canvas.ctx.strokeStyle = 'rgba(0,0,0,0.8)'; canvas.ctx.moveTo( Activity.connectedPoints[Activity.connectedPoints.length-1].x + (dx * 0.1), Activity.connectedPoints[Activity.connectedPoints.length-1].y + (dy * 0.1)); canvas.ctx.lineTo( Activity.connectedPoints[i].x - (dx * 0.1), Activity.connectedPoints[i].y - (dy * 0.1)); canvas.ctx.stroke(); } } canvas.requestPaint() } else if (items.toolSelected == "blur") { canvas.ctx = canvas.getContext('2d') canvas.ctx.lineJoin = canvas.ctx.lineCap = 'round'; canvas.ctx.shadowBlur = 10 canvas.ctx.shadowColor = items.paintColor canvas.ctx.lineWidth = items.sizeS canvas.ctx.strokeStyle = items.paintColor canvas.ctx.beginPath() canvas.ctx.moveTo(canvas.lastX, canvas.lastY) canvas.lastX = area.mouseX canvas.lastY = area.mouseY canvas.ctx.lineTo(canvas.lastX, canvas.lastY) canvas.ctx.stroke() canvas.requestPaint() } } onClicked: { if (items.toolSelected == "fill") { canvas.removeShadow() canvas.ctx.fillStyle = items.paintColor canvas.ctx.beginPath() canvas.ctx.moveTo(0, 0) canvas.ctx.lineTo(background.width, 0) canvas.ctx.lineTo(background.width, background.height) canvas.ctx.lineTo(0, background.height) canvas.ctx.closePath() canvas.ctx.fill() canvas.requestPaint() } } } Rectangle { id: rectangle color: items.paintColor enabled: items.toolSelected == "rectangle" || items.toolSelected == "line"|| items.toolSelected == "lineShift" opacity: items.toolSelected == "rectangle" || items.toolSelected == "line"|| items.toolSelected == "lineShift" ? 1 : 0 property real rotationn: 0 transform: Rotation { id: rotationRect origin.x: 0 origin.y: 0 angle: rectangle.rotationn } } Rectangle { id: circle radius: width / 2 color: items.paintColor enabled: items.toolSelected == "circle" opacity: items.toolSelected == "circle" ? 1 : 0 property real rotationn: 0 } } } LoadDrawings { id: load } LoadSavedDrawings { id: loadSavedPainting } Canvas { id: shape opacity: 0 } FoldablePanels { id: foldablePanels } ColorDialogue { anchors.centerIn: parent visible: false } } } diff --git a/src/activities/drawing/FoldablePanels.qml b/src/activities/drawing/FoldablePanels.qml index 0d871fa98..633dd242c 100644 --- a/src/activities/drawing/FoldablePanels.qml +++ b/src/activities/drawing/FoldablePanels.qml @@ -1,440 +1,440 @@ /* GCompris - FoldablePanels.qml * * Copyright (C) 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity import "qrc:/gcompris/src/core/core.js" as Core Item { id: root property int tabWidth: background.width * 0.15 property int tabHeight: background.height * 0.06 property alias colorModel: colorModel property string activePanel: "null" property alias toolsMode: toolsMode property color panelColor: "#1A1A1B" ListModel { id: menuModel ListElement { itemName: qsTr("Save") imgSource: "qrc:/gcompris/src/activities/drawing/resource/filesaveas.svg" } ListElement { itemName: qsTr("Load") imgSource: "qrc:/gcompris/src/activities/drawing/resource/fileopen.svg" } ListElement { itemName: qsTr("Undo") imgSource: "qrc:/gcompris/src/activities/drawing/resource/undo.svg" } ListElement { itemName: qsTr("Redo") imgSource: "qrc:/gcompris/src/activities/drawing/resource/redo.svg" } ListElement { itemName: qsTr("Erase all") imgSource: "qrc:/gcompris/src/activities/drawing/resource/empty.svg" } ListElement { itemName: qsTr("Background color") imgSource: "qrc:/gcompris/src/activities/drawing/resource/color_wheel.svg" } ListElement { itemName: qsTr("Export to PNG") imgSource: "qrc:/gcompris/src/activities/drawing/resource/empty.svg" } } ListModel { id: toolsModel ListElement { itemName: qsTr("Pencil") imgSource: "qrc:/gcompris/src/activities/drawing/resource/pen.svg" } ListElement { itemName: qsTr("Geometric") imgSource: "qrc:/gcompris/src/activities/drawing/resource/empty.svg" } ListElement { itemName: qsTr("Text") imgSource: "qrc:/gcompris/src/activities/drawing/resource/empty.svg" } ListElement { itemName: qsTr("Brush") imgSource: "qrc:/gcompris/src/activities/drawing/resource/brush_paint.png" } ListElement { itemName: qsTr("Eraser") imgSource: "qrc:/gcompris/src/activities/drawing/resource/erase.svg" } ListElement { itemName: qsTr("Bucket fill") imgSource: "qrc:/gcompris/src/activities/drawing/resource/fill.svg" } } ListModel { id: colorModel ListElement {colorCode: "#ff0000"} ListElement {colorCode: "#000000"} ListElement {colorCode: "#0000ff"} ListElement {colorCode: "#ffff00"} ListElement {colorCode: "#00ffff"} ListElement {colorCode: "#ff00ff"} ListElement {colorCode: "#800000"} ListElement {colorCode: "#000080"} ListElement {colorCode: "#ff4500"} ListElement {colorCode: "#A0A0A0"} ListElement {colorCode: "#d2691e"} ListElement {colorCode: "#8b008b"} } Rectangle { id: menuTitle width: root.tabWidth height: root.tabHeight radius: 10 color: panelColor border.color: "white" y: -7 MouseArea { anchors.fill: parent enabled: (menuPanel.y < -5 && activePanel != "menuPanel") || (menuPanel.y > -5 && activePanel === "menuPanel") onClicked: { animTarget = menuTitle colorGrid.visible = false menuGrid.visible = true root.activePanel = "menuPanel" if(menuPanel.panelUnFolded) { foldAnimation.start() } else { menuGrid.model = menuModel menuTitle.visible = true menuGrid.visible = true unfoldAnimation.start() } } } GCText { text: "Menu" fontSize: tinySize anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit color: "white" } } Rectangle { id: toolsTitle width: root.tabWidth height: root.tabHeight radius: 10 color: panelColor border.color: "white" x: width + 2 y: -7 MouseArea { anchors.fill: parent enabled: (menuPanel.y < -5 && activePanel != "toolsPanel") || (menuPanel.y > -5 && activePanel === "toolsPanel") onClicked: { animTarget = toolsTitle colorGrid.visible = false menuGrid.visible = true root.activePanel = "toolsPanel" if(menuPanel.panelUnFolded) { foldAnimation.start() } else { toolsTitle.visible = true menuGrid.model = toolsModel menuGrid.visible = true unfoldAnimation.start() } } } GCText { text: "Tools" fontSize: tinySize anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit color: "white" } } Rectangle { id: colorsTitle width: root.tabWidth height: root.tabHeight radius: 10 color: panelColor border.color: "white" x: background.width - 2 * width - 2 y: -7 z: menuPanel.z - 1 MouseArea { anchors.fill: parent enabled: (menuPanel.y < -5 && activePanel != "colorPanel") || (menuPanel.y > -5 && activePanel === "colorPanel") onClicked: { animTarget = colorsTitle menuGrid.visible = false colorGrid.visible = true root.activePanel = "colorPanel" if(menuPanel.panelUnFolded) { foldAnimation.start() //foldTitle.start() } else { colorsTitle.visible = true unfoldAnimation.start() //unfoldTitle.start() } } } GCText { text: "Color" fontSize: tinySize anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit color: "white" } } Rectangle { id: toolsOptionTitle width: root.tabWidth height: root.tabHeight radius: 10 color: panelColor border.color: "white" x: background.width - width y: -7 MouseArea { anchors.fill: parent enabled: (menuPanel.y < -5 && activePanel != "toolOptions") || (menuPanel.y > -5 && activePanel === "toolOptions") onClicked: { animTarget = toolsOptionTitle root.activePanel = "toolOptions" menuGrid.visible = false colorGrid.visible = false if(menuPanel.panelUnFolded) { foldAnimation.start() } else { toolsOptionTitle.visible = true unfoldAnimation.start() } } } GCText { text: "Tool Options" fontSize: tinySize anchors.fill: parent horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit color: "white" } } property var animTarget: menuTitle NumberAnimation { id: unfoldTitle target: animTarget property: "y" to: menuPanel.height - 7 duration: 200 easing.type: Easing.InOutQuad } NumberAnimation { id: foldTitle target: animTarget property: "y" to: -7 duration: 200 easing.type: Easing.InOutQuad onStopped: root.activePanel = "null" } Rectangle { id: menuPanel anchors.leftMargin: 5 width: background.width height: background.height / 2.4 color: panelColor y: -height border.color: "white" property bool panelUnFolded: y >= -5 NumberAnimation { id: foldAnimation target: menuPanel property: "y" to: - menuPanel.height duration: 200 easing.type: Easing.InOutQuad onStarted: foldTitle.start() } NumberAnimation { id: unfoldAnimation target: menuPanel property: "y" to: 0 duration: 200 easing.type: Easing.InOutQuad onStarted: unfoldTitle.start() } GridView { id: menuGrid width: parent.width * 0.75 height: parent.height * 0.80 anchors.centerIn: parent visible: root.activePanel == "menuPanel" || root.activePanel == "toolsPanel" anchors.topMargin: 30 cellWidth: width / 4 cellHeight: height / 2.2 model: menuModel delegate:Item { Image { id: img source: imgSource sourceSize.width: menuGrid.cellWidth * 0.60 sourceSize.height: menuGrid.cellHeight * 0.60 MouseArea { anchors.fill: parent hoverEnabled: true onEntered: parent.scale = 1.1 onExited: parent.scale = 1.0 onClicked: { console.log(itemName) Activity.selectTool(itemName) foldAnimation.start() } } } GCText { text: itemName anchors.horizontalCenter: img.horizontalCenter anchors.top: img.bottom fontSize: tinySize color: "white" } } } GridView { id: colorGrid width: parent.width * 0.75 height: parent.height * 0.80 anchors.left: selectedColor.right anchors.verticalCenter: menuPanel.verticalCenter anchors.leftMargin: 30 anchors.rightMargin: 10 anchors.topMargin: 10 cellWidth: width / 4.7 cellHeight: height / 3.6 model: colorModel visible: root.activePanel == "colorPanel" z: 1800 delegate: Rectangle { id: root1 radius: 8 width: colorGrid.cellWidth * 0.80 height: colorGrid.cellHeight * 0.90 color: modelData scale: items.activeColorIndex === index ? 1.2 : 1 border.width: 3 border.color: modelData MouseArea { anchors.fill: parent hoverEnabled: true onEntered: { if(items.activeColorIndex != index) { parent.border.color = "grey" root1.scale = 1.1 } } onExited: { if(items.activeColorIndex != index) { root1.scale = 1 parent.border.color = modelData } } // set this color as current paint color onClicked: { items.activeColorIndex = index items.paintColor = root1.color background.hideExpandedTools() items.paintColor = color background.reloadSelectedPen() colorPicker.updateColor((items.paintColor).toString()) foldAnimation.start() } } } } ColorDialogue { id: colorPicker anchors.left: menuPanel.left anchors.verticalCenter: menuPanel.verticalCenter visible: colorGrid.visible anchors.leftMargin: 20 } Rectangle { id: selectedColor width: menuPanel.width * 0.08 height: menuPanel.height * 0.30 visible: colorGrid.visible radius: 8 border.width: 3 z: colorGrid.z anchors.left: colorPicker.right anchors.leftMargin: 10 anchors.bottom: colorGrid.bottom anchors.bottomMargin: 30 color: colorPicker.currentColorCode MouseArea { anchors.fill: parent onClicked: { items.paintColor = selectedColor.color animTarget = colorsTitle foldAnimation.start() } } } Button { style: GCButtonStyle { theme: "light" } text: qsTr("Save") width: selectedColor.width anchors.left: selectedColor.left anchors.bottomMargin: 30 visible: colorGrid.visible anchors.bottom: selectedColor.top onClicked: { root.colorModel.remove(items.activeColorIndex) root.colorModel.insert(items.activeColorIndex, {colorCode: (colorPicker.currentColor()).toString()}) items.paintColor = (colorPicker.currentColor()).toString() } } ToolsMode { id: toolsMode visible: root.activePanel == "toolOptions" } } Rectangle { width: root.tabWidth height: 8 x: animTarget.x y: animTarget.y color: panelColor } } diff --git a/src/activities/drawing/LoadDrawings.qml b/src/activities/drawing/LoadDrawings.qml index e342907c4..0c356e55a 100644 --- a/src/activities/drawing/LoadDrawings.qml +++ b/src/activities/drawing/LoadDrawings.qml @@ -1,170 +1,170 @@ /* GCompris - LoadDrawings.qml * * Copyright (C) 2016 Toncu Stefan * 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity Rectangle { id: load color: background.color width: background.width height: background.height opacity: 0 z: 5 anchors { top: main.top right: main.left } GridView { id: gridView anchors.fill: parent cellWidth: (background.width - exitButton.width) / 2 * slider1.value; cellHeight: cellWidth model: Activity.loadImagesSource delegate: Item { width: gridView.cellWidth height: gridView.cellHeight property alias loadImage: loadImage Image { id: loadImage source: modelData anchors.centerIn: parent sourceSize.width: parent.width * 0.7 sourceSize.height: parent.height * 0.7 width: parent.width * 0.9 height: parent.height * 0.9 mirror: false MouseArea { anchors.fill: parent onClicked: { canvas.url = loadImage.source canvas.loadImage(loadImage.source) main.x = 0 } } } } } Behavior on x { NumberAnimation { target: load property: "x" duration: 800 easing.type: Easing.InOutQuad } } Behavior on y { NumberAnimation { target: load property: "y" duration: 800 easing.type: Easing.InOutQuad } } GCButtonCancel { id: exitButton onClose: { items.mainAnimationOnX = true main.x = 0 } } Image { id: switchToSavedPaintings source: "qrc:/gcompris/src/activities/drawing/drawing.svg" anchors.right: parent.right anchors.top: exitButton.bottom smooth: true sourceSize.width: 60 * ApplicationInfo.ratio anchors.margins: 10 MouseArea { anchors.fill: parent onClicked: { if (loadSavedPainting.opacity == 0) loadSavedPainting.opacity = 1 items.mainAnimationOnX = false // move down the loadPaintings screen main.y = main.height loadSavedPainting.anchors.left = load.left // change the images sources from "saved images" to "load images" items.loadSavedImage = true } } } Slider { id: slider1 minimumValue: 0.3 value: 0.65 height: parent.height * 0.5 width: 60 opacity: 1 enabled: true anchors.right: parent.right anchors.rightMargin: switchToSavedPaintings.width / 2 - 10 anchors.top: switchToSavedPaintings.bottom orientation: Qt.Vertical style: SliderStyle { handle: Rectangle { height: 80 width: height radius: width / 2 color: background.color } groove: Rectangle { implicitHeight: slider1.width implicitWidth: slider1.height radius: height / 2 border.color: "#6699ff" color: "#99bbff" Rectangle { height: parent.height width: styleData.handlePosition implicitHeight: 100 implicitWidth: 6 radius: height/2 color: "#4d88ff" } } } } } diff --git a/src/activities/drawing/LoadSavedDrawings.qml b/src/activities/drawing/LoadSavedDrawings.qml index 43a1a7466..7c6229dab 100644 --- a/src/activities/drawing/LoadSavedDrawings.qml +++ b/src/activities/drawing/LoadSavedDrawings.qml @@ -1,184 +1,184 @@ /* GCompris - LoadSavedDrawings.qml * * Copyright (C) 2016 Toncu Stefan * 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity import "qrc:/gcompris/src/core/core.js" as Core Rectangle { id: loadSavedPainting color: background.color width: background.width height: background.height opacity: 0 z: 100 property alias gridView2: gridView2 anchors { bottom: main.top left: load.left } GCText { anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: - rightFrame.width / 2 fontSize: largeSize text: qsTr("No paintings saved") opacity: gridView2.count == 0 } GridView { id: gridView2 anchors.fill: parent cellWidth: (main.width - sizeOfImages.width) * slider.value cellHeight: main.height * slider.value flow: GridView.FlowTopToBottom z: 1 delegate: Rectangle { width: gridView2.cellWidth height: gridView2.cellHeight color: "transparent" Image { id: loadImage2 source: modelData.url anchors.centerIn: parent sourceSize.width: parent.width sourceSize.height: parent.height width: parent.width * 0.9 height: parent.height * 0.9 MouseArea { anchors.fill: parent onClicked: { loadSavedPainting.anchors.left = main.left canvas.url = loadImage2.source canvas.loadImage(loadImage2.source) main.x = 0 main.y = 0 } } GCButtonCancel { anchors.right: undefined anchors.left: parent.left sourceSize.width: 40 * ApplicationInfo.ratio onClose: { Activity.dataset.splice(index, 1) gridView2.model = Activity.dataset Activity.saveToFile(false) } } } } } Behavior on x { NumberAnimation { target: loadSavedPainting; property: "x"; duration: 800; easing.type: Easing.InOutQuad } } Behavior on y { NumberAnimation { target: loadSavedPainting; property: "y"; duration: 800; easing.type: Easing.InOutQuad } } Rectangle { id: rightFrame width: sizeOfImages.width + sizeOfImages.anchors.margins * 2 color: background.color anchors { right: parent.right top: parent.top bottom: parent.bottom } z: 2 Image { id: sizeOfImages source: "qrc:/gcompris/src/activities/drawing/drawing.svg" anchors.right: parent.right anchors.top: parent.top smooth: true sourceSize.width: 60 * ApplicationInfo.ratio anchors.margins: 10 MouseArea { anchors.fill: parent onClicked: { items.mainAnimationOnX = true // move down the loadPaintings screen main.y = 0 // change the images sources from "saved images" to "load images" items.loadSavedImage = false } } } Slider { id: slider minimumValue: 0.3 value: 0.65 height: parent.height * 0.5 width: 60 opacity: 1 enabled: true anchors.right: parent.right anchors.rightMargin: sizeOfImages.width / 2 - 10 anchors.top: sizeOfImages.bottom orientation: Qt.Vertical style: SliderStyle { handle: Rectangle { height: 80 width: height radius: width / 2 color: background.color } groove: Rectangle { implicitHeight: slider.width implicitWidth: slider.height radius: height / 2 border.color: "#6699ff" color: "#99bbff" Rectangle { height: parent.height width: styleData.handlePosition implicitHeight: 100 implicitWidth: 6 radius: height/2 color: "#4d88ff" } } } } } } diff --git a/src/activities/drawing/SaveToFilePrompt.qml b/src/activities/drawing/SaveToFilePrompt.qml index 9bef32371..6858c6e93 100644 --- a/src/activities/drawing/SaveToFilePrompt.qml +++ b/src/activities/drawing/SaveToFilePrompt.qml @@ -1,174 +1,174 @@ /* GCompris - SaveToFilePrompt.qml * * Copyright (C) 2016 Toncu Stefan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 -import "paint.js" as Activity +import "drawing.js" as Activity import "../../core" Rectangle { id: saveToFilePrompt width: parent.width * 0.6 height: parent.height * 0.6 radius: height / 30 color: "#b3b3cc" opacity: 0 anchors.centerIn: parent property string text signal yes signal no signal cancel GCText { text: saveToFilePrompt.text width: parent.width wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter anchors { verticalCenter: parent.verticalCenter verticalCenterOffset: - (yes.anchors.bottomMargin + yes.height) / 2 horizontalCenter: parent.horizontalCenter } } Rectangle { id: yes color: "#ffe6cc" width: parent.width * 3 / 10 height: parent.height / 6 radius: height / 2 anchors { bottom: parent.bottom bottomMargin: parent.height / 10 horizontalCenter: parent.horizontalCenter horizontalCenterOffset: - (width + (parent.width / 2 - width * 1.5) / 2) } GCText { text: qsTr("Yes") anchors.centerIn: parent } MouseArea { id: mouseArea1 anchors.fill: parent hoverEnabled: true onClicked: { saveToFilePrompt.yes() } states: State { name: "scaled"; when: mouseArea1.containsMouse PropertyChanges { target: yes scale: 1.1 } } transitions: Transition { NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic } } } } Rectangle { id: no color: "#ff6666" width: parent.width * 3 / 10 height: parent.height / 6 radius: height / 2 anchors { bottom: parent.bottom bottomMargin: parent.height / 10 horizontalCenter: parent.horizontalCenter } GCText { text: qsTr("No") anchors.centerIn: parent } MouseArea { id: mouseArea2 anchors.fill: parent hoverEnabled: true onClicked: { saveToFilePrompt.no() } states: State { name: "scaled"; when: mouseArea2.containsMouse PropertyChanges { target: no scale: 1.1 } } transitions: Transition { NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic } } } } Rectangle { id: cancel color: "#ccff99" width: parent.width * 3 / 10 height: parent.height / 6 radius: height / 2 anchors { bottom: parent.bottom bottomMargin: parent.height / 10 horizontalCenter: parent.horizontalCenter horizontalCenterOffset: width + (parent.width / 2 - width * 1.5) / 2 } GCText { text: qsTr("Cancel") anchors.centerIn: parent } MouseArea { id: mouseArea3 anchors.fill: parent hoverEnabled: true onClicked: { saveToFilePrompt.cancel() } states: State { name: "scaled"; when: mouseArea3.containsMouse PropertyChanges { target: cancel scale: 1.1 } } transitions: Transition { NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic } } } } Keys.onPressed: { if (event.key == Qt.Key_Backspace) { print("pressed backspace") } } } diff --git a/src/activities/drawing/TextInputTool.qml b/src/activities/drawing/TextInputTool.qml index c90d5bec1..e8e665a54 100644 --- a/src/activities/drawing/TextInputTool.qml +++ b/src/activities/drawing/TextInputTool.qml @@ -1,81 +1,81 @@ /* GCompris - TextInput.qml * * Copyright (C) 2016 Toncu Stefan * 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity Rectangle { id: inputTextFrame color: background.color width: inputText.width + okButton.width + inputText.height + 10 height: inputText.height * 1.1 anchors.centerIn: parent radius: height / 2 z: 1000 opacity: 0 property alias inputText: inputText TextField { id: inputText anchors.left: parent.left anchors.leftMargin: height / 1.9 anchors.verticalCenter: parent.verticalCenter height: 50 width: 300 placeholderText: qsTr("Type here") font.pointSize: 32 } // ok button Image { id: okButton source:"qrc:/gcompris/src/core/resource/bar_ok.svg" sourceSize.height: inputText.height fillMode: Image.PreserveAspectFit anchors.left: inputText.right anchors.leftMargin: 10 anchors.verticalCenter: inputText.verticalCenter MouseArea { id: mouseArea anchors.fill: parent enabled: inputTextFrame.opacity == 1 ? true : false onClicked: { onBoardText.text = inputText.text // hide the inputTextFrame inputTextFrame.opacity = 0 inputTextFrame.z = -1 // show the text onBoardText.opacity = 1 onBoardText.z = 100 onBoardText.x = area.realMouseX onBoardText.y = area.realMouseY - onBoardText.height * 0.8 // start the movement moveOnBoardText.start() } } } } diff --git a/src/activities/drawing/ToolItem.qml b/src/activities/drawing/ToolItem.qml index dfe0c09ba..31ed8a479 100644 --- a/src/activities/drawing/ToolItem.qml +++ b/src/activities/drawing/ToolItem.qml @@ -1,54 +1,54 @@ /* GCompris - ToolItem.qml * * Copyright (C) 2016 Toncu Stefan * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 -import "paint.js" as Activity +import "drawing.js" as Activity Image { id: toolItem sourceSize.width: 70; sourceSize.height: 70 width: 70; height: 70 source: Activity.url + name + ".svg" opacity: items.toolSelected == name ? 1 : 0.4 property string name signal click MouseArea { anchors.fill: parent onClicked: { items.toolSelected = name items.lastToolSelected = name background.hideExpandedTools() showSelected.x = toolItem.x + row2.spacing showSelected.y = toolItem.y + row2.spacing * 0.5 // make the hover over the canvas false area.hoverEnabled = false // change the selectBrush tool timer.index = 0 timer.start() background.reloadSelectedPen() click() } } } diff --git a/src/activities/drawing/ToolsMode.qml b/src/activities/drawing/ToolsMode.qml index 28d0fc08b..7c7f3ae12 100644 --- a/src/activities/drawing/ToolsMode.qml +++ b/src/activities/drawing/ToolsMode.qml @@ -1,121 +1,121 @@ /* GCompris - ToolsMode.qml * * Copyright (C) 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import QtQuick.Controls 1.5 import GCompris 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity Item { id: toolsMode width: parent.width height: parent.height anchors.centerIn: parent property alias modesModel: modes.model property alias pencilModes: pencilModes property alias geometricModes: geometricModes ListModel { id: pencilModes ListElement { name: "pencil"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/pencil.png" } ListElement { name: "dot"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/pattern1.png" } ListElement { name: "pattern2"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/pattern3.png" } ListElement { name: "pattern3"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/pattern3.png" } ListElement { name: "spray"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/spray.png" } ListElement { name: "brush3"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/brush3.png" } ListElement { name: "brush4"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/brush4.png" } ListElement { name: "brush5"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/brush5.png" } ListElement { name: "blur"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/blur.png" } } ListModel { id: geometricModes ListElement { name: "rectangle"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/rectangle.png" } ListElement { name: "circle"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/circle.png" } ListElement { name: "lineShift"; imgSource: "qrc:/gcompris/src/activities/drawing/resource/line_straight.svg" } ListElement { name: "line" imgSource: "qrc:/gcompris/src/activities/drawing/resource/line_free.png" } } GridView { id: modes width: parent.width * 0.50 height: parent.height * 0.85 cellWidth: width / 4.2 cellHeight: height / 3.2 anchors.verticalCenter: parent.verticalCenter anchors.left: parent.left anchors.leftMargin: 40 model: pencilModes delegate: modesComponent } Component { id: modesComponent Rectangle { width: modes.cellWidth height: modes.cellHeight color: items.toolSelected == name ? "lightblue" : "transparent" radius: 10 Image { source: imgSource width: parent.width * 0.80 height: parent.height * 0.80 anchors.centerIn: parent fillMode: Image.PreserveAspectFit } MouseArea { anchors.fill: parent onClicked: { items.toolSelected = name items.lastToolSelected = name background.hideExpandedTools() console.log("Click on " + name) // make the hover over the canvas false area.hoverEnabled = false // change the selectBrush tool timer.index = 0 timer.start() background.reloadSelectedPen() Activity.selectMode(name) } } } } ToolsSize { anchors.left: modes.right anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 30 } } diff --git a/src/activities/drawing/ToolsSize.qml b/src/activities/drawing/ToolsSize.qml index f11182b0d..3160eca31 100644 --- a/src/activities/drawing/ToolsSize.qml +++ b/src/activities/drawing/ToolsSize.qml @@ -1,53 +1,53 @@ /* GCompris - ToolsSize.qml * * Copyright (C) 2018 Amit Sagtani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import QtQuick 2.6 import QtQuick.Controls 1.5 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.0 import GCompris 1.0 import "../../core" -import "paint.js" as Activity +import "drawing.js" as Activity Item { id: toolsSize width: background.width > background.height ? background.width * 0.30 : background.width * 0.30 height: background.height * 0.35 GCSlider { id: slider anchors.centerIn: parent //anchors.verticalCenterOffset: 30 value: items.sizeS minimumValue: 2 maximumValue: 24 onValueChanged: items.sizeS = value stepSize: 2 } Row { id: thicknessRow spacing: slider.width / 4.6 x: slider.x anchors.bottom: slider.top Thickness { lineSize: 0.13 } Thickness { lineSize: 0.66 } Thickness { lineSize: 1.00 } Thickness { lineSize: 1.60 } } } diff --git a/src/activities/drawing/drawing.js b/src/activities/drawing/drawing.js index f15855091..3ec16b054 100644 --- a/src/activities/drawing/drawing.js +++ b/src/activities/drawing/drawing.js @@ -1,429 +1,420 @@ /* GCompris - drawing.js * * Copyright (C) 2016 Toncu Stefan * * This program is free software you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program if not, see . */ .pragma library .import QtQuick 2.0 as Quick .import GCompris 1.0 as GCompris .import "qrc:/gcompris/src/core/core.js" as Core -var url = "qrc:/gcompris/src/activities/drawing/resource/" +var url = "qrc:/gcompris/src/activities/paint/resource/" var currentLevel = 0 var numberOfLevel = 4 var items var loadImagesSource = [ "qrc:/gcompris/src/activities/photo_hunter/resource/photo1.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo2.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo3.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo4.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo5.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo6.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo7.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo8.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo9.svg", "qrc:/gcompris/src/activities/photo_hunter/resource/photo10.svg" ] var undo = [] var redo = [] +var aux = ["1","2","3","4","5"] + var userFile = "file://" + GCompris.ApplicationInfo.getSharedWritablePath() + "/paint/" + "levels-user.json" var dataset = null var ctx var points = [] var connectedPoints = [] function start(items_) { items = items_ currentLevel = 0 items.toolSelected = "pencil" items.paintColor = "#000000" initLevel() } function stop() { } function initLevel() { dataset = null points = [] connectedPoints = [] undo = [] redo = [] ctx = items.canvas.getContext("2d") ctx.fillStyle = "#ffffff" ctx.beginPath() ctx.clearRect(0, 0, items.background.width, items.background.height) ctx.moveTo(0, 0) ctx.lineTo(items.background.width, 0) ctx.lineTo(items.background.width, items.background.height) ctx.lineTo(0, items.background.height) ctx.closePath() ctx.fill() items.canvas.requestPaint() items.next = false items.next2 = false undo = ["data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAA4sAAAOLCAYAAAD5ExZjAAAACXBIWXMAAA7EAAAOxAGVKw4bAAATLElEQVR4nO3XsQ0AIRDAsOf33/lokTIAFPYEabNmZj4AAAA4/LcDAAAAeI9ZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgNq0MCxI5gV9wAAAAAElFTkSuQmCC"] // if the width/height is changed, the drawing is reset and repainted the last image saved if (items.widthHeightChanged) { // load the image items.canvas.url = items.lastUrl items.canvas.loadImage(items.lastUrl) // reset the flag to false items.widthHeightChanged = false } //load saved paintings from file parseImageSaved() items.gridView2.model = dataset getPattern() items.background.started = true items.background.hideExpandedTools() } function getPattern() { var dotWidth = 20, dotDistance = 5 var patternCtx = items.shape.getContext("2d") patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) items.shape.width = items.shape.height = dotWidth + dotDistance patternCtx.fillStyle = items.paintColor patternCtx.beginPath() patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); patternCtx.closePath() patternCtx.fill() items.shape.requestPaint() } function getPattern2() { var lineSize = 10, lineWidth = 5 var patternCtx = items.shape.getContext("2d") patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) items.shape.width = items.shape.height = lineSize patternCtx.strokeStyle = items.paintColor patternCtx.lineWidth = lineWidth patternCtx.beginPath() patternCtx.moveTo(0, lineWidth) patternCtx.lineTo(lineSize, lineWidth) patternCtx.closePath() patternCtx.stroke() } function getPattern3() { var lineSize = 20, lineWidth = 10 var ctx = items.shape.getContext("2d") ctx.clearRect(0, 0, items.shape.width, items.shape.height) items.shape.width = lineWidth; items.shape.height = lineSize; ctx.fillStyle = items.paintColor ctx.fillRect(lineWidth / 2, 0, lineWidth, lineSize); } function getSprayPattern() { var patternCtx = items.shape.getContext("2d") patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) items.shape.width = items.shape.height = 3 patternCtx.fillStyle = items.paintColor patternCtx.fillRect(0, 0, 2, 2); } function getCirclePattern() { var dotWidth = 10, dotDistance = 2.5 var patternCtx = items.shape.getContext("2d") patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) items.shape.width = dotWidth * 0.6 + dotDistance * 2 items.shape.height = items.shape.width patternCtx.strokeStyle = items.paintColor patternCtx.lineWidth = 1 patternCtx.beginPath() patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); patternCtx.closePath() patternCtx.stroke() } // parse the content of the paintings saved by the user function parseImageSaved() { dataset = items.parser.parseFromUrl(userFile) if (dataset == null) { console.error("ERROR! dataset = []") dataset = [] return } } // if showMessage === true, then show the message Core.showMessageDialog(...), else don't show it function saveToFile(showMessage) { // verify if the path is good var path = userFile.substring(0, userFile.lastIndexOf("/")) if (!items.file.exists(path)) { if (!items.file.mkpath(path)) console.error("Could not create directory " + path) else console.debug("Created directory " + path) } // add current painting to the dataset if (showMessage) dataset = dataset.concat({"imageNumber": 1, "url": items.canvas.toDataURL()}) // save the dataset to json file if (!items.file.write(JSON.stringify(dataset), userFile)) { if (showMessage) Core.showMessageDialog(items.main, //~ singular Error saving %n level to your levels file (%1) //~ plural Error saving %n levels to your levels file (%1) qsTr("Error saving %n level(s) to your levels file (%1)", "", numberOfLevel) .arg(userFile), "", null, "", null, null) } else { if (showMessage) Core.showMessageDialog(items.main, //~ singular Saved %n level to your levels file (%1) //~ plural Saved %n levels to your levels file (%1) qsTr("Saved %n level(s) to your levels file (%1)", "", numberOfLevel) .arg(userFile), "", null, "", null, null) } items.initSave = false //reload the dataset: parseImageSaved() items.gridView2.model = dataset // reset nothingChanged items.nothingChanged = true } // Exports the current drawing in png format. function exportToPng() { var path = GCompris.ApplicationInfo.getSharedWritablePath() + "/drawing" if(!items.file.exists(path)) { - if(!items.file.mkpath(path)) { - Core.showMessageDialog(items.main, - qsTr("Error: could not create the directory %1").arg(path), - "", null, "", null, null) + if(!items.file.mkpath(path)) console.error("Could not create directory " + path) - return; - } else console.debug("Created directory " + path) } var i = 0; + console.log(items.file.exists(path + "/drawing" + i.toString() + ".png")) + console.log((path + "/drawing" + i + ".png")) while(items.file.exists(path + "/drawing" + i.toString() + ".png")) { i += 1 } items.canvas.grabToImage(function(result) { - if(result.saveToFile(path + "/drawing" + i.toString() + ".png")) { - console.log("File drawing" + i + ".png saved successfully.") - Core.showMessageDialog(items.main, - qsTr("Saved drawing to %1").arg(path + "/drawing" + i.toString() + ".png"), - "", null, "", null, null) - - } - else { - Core.showMessageDialog(items.main, - qsTr("Error in saving the drawing."), - "", null, "", null, null) - } + result.saveToFile(path + "/drawing" + i.toString() + ".png"); + console.log("File drawing" + i + ".png saved successfully.") + Core.showMessageDialog(items.main, + qsTr("Saved drawing" + i + ".png path: " + path), + "", null, "", null, null) }) } function nextLevel() { if(numberOfLevel <= ++currentLevel) { currentLevel = 0 } initLevel() } function previousLevel() { if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel() } function selectTool(toolName) { console.log("Clicked on " + toolName) if(toolName === "Eraser") { items.toolSelected = "eraser" items.background.hideExpandedTools() items.background.reloadSelectedPen() } else if(toolName === "Bucket fill") { items.toolSelected = "fill" items.background.hideExpandedTools() // make the hover over the canvas false items.area.hoverEnabled = false // change the selectBrush tool items.timer.index = 0 items.timer.start() items.background.reloadSelectedPen() } else if(toolName === "Text") { items.toolSelected = "text" items.background.hideExpandedTools() items.background.reloadSelectedPen() // enable the text to follow the cursor movement items.area.hoverEnabled = true // make visible the inputTextFrame items.inputTextFrame.opacity = 1 items.inputTextFrame.z = 1000 // restore input text to "" items.inputText.text = "" } else if(toolName === "Undo") { items.background.hideExpandedTools() if (undo.length > 0 && items.next || undo.length > 1 && items.next == false) { items.undoRedo = true if (items.next) { redo = redo.concat(undo.pop()) } items.next = false items.next2 = true // pop the last image saved from "undo" array items.urlImage = undo.pop() // load the image in the canvas items.canvas.loadImage(items.urlImage) // save the image into the "redo" array redo = redo.concat(items.urlImage) // print("undo: " + undo.length + " redo: " + redo.length + " undo Pressed") } } else if(toolName === "Redo") { items.background.hideExpandedTools() if (redo.length > 0) { items.undoRedo = true if (items.next2) { undo = undo.concat(redo.pop()) } items.next = true items.next2 = false items.urlImage = redo.pop() items.canvas.loadImage(items.urlImage) undo = undo.concat(items.urlImage) // print("undo: " + undo.length + " redo: " + redo.length + " redo Pressed") } } else if(toolName === "Load") { if (items.load.opacity == 0) items.load.opacity = 1 items.background.hideExpandedTools() // mark the pencil as the default tool items.toolSelected = "pencil" // move the main screen to right items.mainRegion.x = items.background.width } else if(toolName === "Save") { saveToFile(true) } else if(toolName === "More Colors") { items.colorPalette.visible = true } else if(toolName === "Modes") { items.toolsMode.visible = true } else if(toolName === "Size") { items.toolsSize.visible = true } else if(toolName === "Erase all") { if (!items.nothingChanged) { - items.saveToFilePrompt.buttonPressed = "reload" - items.saveToFilePrompt.text = qsTr("Do you want to save your painting before reseting the board?") - items.saveToFilePrompt.opacity = 1 - items.saveToFilePrompt.z = 200 + items.saveToFilePrompt2.text = qsTr("Do you want to save your painting before reseting the board?") + items.saveToFilePrompt2.opacity = 1 + items.saveToFilePrompt2.z = 200 } else { initLevel() } } else if(toolName === "Geometric") { items.toolSelected = "rectangle" items.lastToolSelected = "rectangle" items.background.hideExpandedTools() items.background.reloadSelectedPen() items.toolsMode.modesModel = items.toolsMode.geometricModes } - else if(toolName === "Brush") { + else if(toolName === "Pencil") { items.toolSelected = "pencil" items.lastToolSelected = "pencil" items.background.hideExpandedTools() items.background.reloadSelectedPen() items.toolsMode.modesModel = items.toolsMode.pencilModes } else if(toolName === "Export to PNG") { exportToPng() } } function selectMode(modeName) { if(modeName === "dot") { items.toolSelected = "pattern" items.patternType = "dot" items.lastToolSelected = "pattern" getPattern() items.background.reloadSelectedPen() } else if(modeName === "pattern2") { items.toolSelected = "pattern" items.patternType = "horizLine" items.lastToolSelected = "pattern" getPattern2() items.background.reloadSelectedPen() } else if(modeName === "pattern3") { items.toolSelected = "pattern" items.patternType = "vertLine" items.lastToolSelected = "pattern" getPattern3() items.background.reloadSelectedPen() } } diff --git a/src/activities/drawing/paint.js b/src/activities/drawing/paint.js deleted file mode 100644 index ae10cc95c..000000000 --- a/src/activities/drawing/paint.js +++ /dev/null @@ -1,420 +0,0 @@ -/* GCompris - paint.js - * - * Copyright (C) 2016 Toncu Stefan - * - * This program is free software you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program if not, see . - */ - -.pragma library -.import QtQuick 2.0 as Quick -.import GCompris 1.0 as GCompris -.import "qrc:/gcompris/src/core/core.js" as Core - -var url = "qrc:/gcompris/src/activities/paint/resource/" - -var currentLevel = 0 -var numberOfLevel = 4 -var items -var loadImagesSource = [ - "qrc:/gcompris/src/activities/photo_hunter/resource/photo1.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo2.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo3.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo4.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo5.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo6.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo7.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo8.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo9.svg", - "qrc:/gcompris/src/activities/photo_hunter/resource/photo10.svg" - ] - -var undo = [] -var redo = [] - -var aux = ["1","2","3","4","5"] - -var userFile = "file://" + GCompris.ApplicationInfo.getSharedWritablePath() - + "/paint/" + "levels-user.json" - -var dataset = null - -var ctx - -var points = [] -var connectedPoints = [] - -function start(items_) { - items = items_ - currentLevel = 0 - items.toolSelected = "pencil" - items.paintColor = "#000000" - initLevel() -} - -function stop() { -} - -function initLevel() { - dataset = null - points = [] - connectedPoints = [] - - undo = [] - redo = [] - - ctx = items.canvas.getContext("2d") - ctx.fillStyle = "#ffffff" - - ctx.beginPath() - ctx.clearRect(0, 0, items.background.width, items.background.height) - - ctx.moveTo(0, 0) - ctx.lineTo(items.background.width, 0) - ctx.lineTo(items.background.width, items.background.height) - ctx.lineTo(0, items.background.height) - ctx.closePath() - ctx.fill() - items.canvas.requestPaint() - - items.next = false - items.next2 = false - - undo = ["data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAA4sAAAOLCAYAAAD5ExZjAAAACXBIWXMAAA7EAAAOxAGVKw4bAAATLElEQVR4nO3XsQ0AIRDAsOf33/lokTIAFPYEabNmZj4AAAA4/LcDAAAAeI9ZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgzCIAAABhFgEAAAizCAAAQJhFAAAAwiwCAAAQZhEAAIAwiwAAAIRZBAAAIMwiAAAAYRYBAAAIswgAAECYRQAAAMIsAgAAEGYRAACAMIsAAACEWQQAACDMIgAAAGEWAQAACLMIAABAmEUAAADCLAIAABBmEQAAgDCLAAAAhFkEAAAgNq0MCxI5gV9wAAAAAElFTkSuQmCC"] - - // if the width/height is changed, the drawing is reset and repainted the last image saved - if (items.widthHeightChanged) { - // load the image - items.canvas.url = items.lastUrl - items.canvas.loadImage(items.lastUrl) - // reset the flag to false - items.widthHeightChanged = false - } - - //load saved paintings from file - parseImageSaved() - items.gridView2.model = dataset - - getPattern() - items.background.started = true - - items.background.hideExpandedTools() -} - -function getPattern() { - var dotWidth = 20, dotDistance = 5 - var patternCtx = items.shape.getContext("2d") - patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) - items.shape.width = items.shape.height = dotWidth + dotDistance - patternCtx.fillStyle = items.paintColor - patternCtx.beginPath() - patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); - patternCtx.closePath() - patternCtx.fill() - items.shape.requestPaint() -} - -function getPattern2() { - var lineSize = 10, lineWidth = 5 - var patternCtx = items.shape.getContext("2d") - patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) - items.shape.width = items.shape.height = lineSize - patternCtx.strokeStyle = items.paintColor - patternCtx.lineWidth = lineWidth - patternCtx.beginPath() - patternCtx.moveTo(0, lineWidth) - patternCtx.lineTo(lineSize, lineWidth) - patternCtx.closePath() - patternCtx.stroke() -} - -function getPattern3() { - var lineSize = 20, lineWidth = 10 - var ctx = items.shape.getContext("2d") - ctx.clearRect(0, 0, items.shape.width, items.shape.height) - items.shape.width = lineWidth; - items.shape.height = lineSize; - ctx.fillStyle = items.paintColor - ctx.fillRect(lineWidth / 2, 0, lineWidth, lineSize); -} - -function getSprayPattern() { - var patternCtx = items.shape.getContext("2d") - patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) - items.shape.width = items.shape.height = 3 - patternCtx.fillStyle = items.paintColor - patternCtx.fillRect(0, 0, 2, 2); -} - -function getCirclePattern() { - var dotWidth = 10, dotDistance = 2.5 - var patternCtx = items.shape.getContext("2d") - patternCtx.clearRect(0, 0, items.shape.width, items.shape.height) - items.shape.width = dotWidth * 0.6 + dotDistance * 2 - items.shape.height = items.shape.width - patternCtx.strokeStyle = items.paintColor - patternCtx.lineWidth = 1 - patternCtx.beginPath() - patternCtx.arc(dotWidth / 2, dotWidth / 2, dotWidth / 2, 0, Math.PI * 2, false); - patternCtx.closePath() - patternCtx.stroke() -} - -// parse the content of the paintings saved by the user -function parseImageSaved() { - dataset = items.parser.parseFromUrl(userFile) - if (dataset == null) { - console.error("ERROR! dataset = []") - dataset = [] - return - } -} - -// if showMessage === true, then show the message Core.showMessageDialog(...), else don't show it -function saveToFile(showMessage) { - // verify if the path is good - var path = userFile.substring(0, userFile.lastIndexOf("/")) - if (!items.file.exists(path)) { - if (!items.file.mkpath(path)) - console.error("Could not create directory " + path) - else - console.debug("Created directory " + path) - } - - // add current painting to the dataset - if (showMessage) - dataset = dataset.concat({"imageNumber": 1, "url": items.canvas.toDataURL()}) - - // save the dataset to json file - if (!items.file.write(JSON.stringify(dataset), userFile)) { - if (showMessage) - Core.showMessageDialog(items.main, - //~ singular Error saving %n level to your levels file (%1) - //~ plural Error saving %n levels to your levels file (%1) - qsTr("Error saving %n level(s) to your levels file (%1)", "", numberOfLevel) - .arg(userFile), - "", null, "", null, null) - } else { - if (showMessage) - Core.showMessageDialog(items.main, - //~ singular Saved %n level to your levels file (%1) - //~ plural Saved %n levels to your levels file (%1) - qsTr("Saved %n level(s) to your levels file (%1)", "", numberOfLevel) - .arg(userFile), - "", null, "", null, null) - } - items.initSave = false - - //reload the dataset: - parseImageSaved() - items.gridView2.model = dataset - - // reset nothingChanged - items.nothingChanged = true -} - -// Exports the current drawing in png format. -function exportToPng() { - var path = GCompris.ApplicationInfo.getSharedWritablePath() + "/drawing" - if(!items.file.exists(path)) { - if(!items.file.mkpath(path)) - console.error("Could not create directory " + path) - else - console.debug("Created directory " + path) - } - var i = 0; - console.log(items.file.exists(path + "/drawing" + i.toString() + ".png")) - console.log((path + "/drawing" + i + ".png")) - while(items.file.exists(path + "/drawing" + i.toString() + ".png")) { - i += 1 - } - items.canvas.grabToImage(function(result) { - result.saveToFile(path + "/drawing" + i.toString() + ".png"); - console.log("File drawing" + i + ".png saved successfully.") - Core.showMessageDialog(items.main, - qsTr("Saved drawing" + i + ".png path: " + path), - "", null, "", null, null) - }) - -} - -function nextLevel() { - if(numberOfLevel <= ++currentLevel) { - currentLevel = 0 - } - initLevel() -} - -function previousLevel() { - if(--currentLevel < 0) { - currentLevel = numberOfLevel - 1 - } - initLevel() -} - - -function selectTool(toolName) { - console.log("Clicked on " + toolName) - if(toolName === "Eraser") { - items.toolSelected = "eraser" - items.background.hideExpandedTools() - items.background.reloadSelectedPen() - } - else if(toolName === "Bucket fill") { - items.toolSelected = "fill" - items.background.hideExpandedTools() - - // make the hover over the canvas false - items.area.hoverEnabled = false - - // change the selectBrush tool - items.timer.index = 0 - items.timer.start() - - items.background.reloadSelectedPen() - } - else if(toolName === "Text") { - items.toolSelected = "text" - items.background.hideExpandedTools() - items.background.reloadSelectedPen() - - // enable the text to follow the cursor movement - items.area.hoverEnabled = true - - // make visible the inputTextFrame - items.inputTextFrame.opacity = 1 - items.inputTextFrame.z = 1000 - - // restore input text to "" - items.inputText.text = "" - } - else if(toolName === "Undo") { - items.background.hideExpandedTools() - if (undo.length > 0 && items.next || - undo.length > 1 && items.next == false) { - items.undoRedo = true - - if (items.next) { - redo = redo.concat(undo.pop()) - } - - items.next = false - items.next2 = true - - // pop the last image saved from "undo" array - items.urlImage = undo.pop() - - // load the image in the canvas - items.canvas.loadImage(items.urlImage) - - // save the image into the "redo" array - redo = redo.concat(items.urlImage) - - // print("undo: " + undo.length + " redo: " + redo.length + " undo Pressed") - } - } - else if(toolName === "Redo") { - items.background.hideExpandedTools() - if (redo.length > 0) { - items.undoRedo = true - - if (items.next2) { - undo = undo.concat(redo.pop()) - } - - items.next = true - items.next2 = false - - items.urlImage = redo.pop() - - items.canvas.loadImage(items.urlImage) - undo = undo.concat(items.urlImage) - - // print("undo: " + undo.length + " redo: " + redo.length + " redo Pressed") - } - } - else if(toolName === "Load") { - if (items.load.opacity == 0) - items.load.opacity = 1 - - items.background.hideExpandedTools() - - // mark the pencil as the default tool - items.toolSelected = "pencil" - - // move the main screen to right - items.mainRegion.x = items.background.width - } - else if(toolName === "Save") { - saveToFile(true) - } - else if(toolName === "More Colors") { - items.colorPalette.visible = true - } - else if(toolName === "Modes") { - items.toolsMode.visible = true - } - else if(toolName === "Size") { - items.toolsSize.visible = true - } - else if(toolName === "Erase all") { - if (!items.nothingChanged) { - items.saveToFilePrompt2.text = qsTr("Do you want to save your painting before reseting the board?") - items.saveToFilePrompt2.opacity = 1 - items.saveToFilePrompt2.z = 200 - } else { - initLevel() - } - } - else if(toolName === "Geometric") { - items.toolSelected = "rectangle" - items.lastToolSelected = "rectangle" - items.background.hideExpandedTools() - items.background.reloadSelectedPen() - items.toolsMode.modesModel = items.toolsMode.geometricModes - } - else if(toolName === "Pencil") { - items.toolSelected = "pencil" - items.lastToolSelected = "pencil" - items.background.hideExpandedTools() - items.background.reloadSelectedPen() - items.toolsMode.modesModel = items.toolsMode.pencilModes - } - else if(toolName === "Export to PNG") { - exportToPng() - } -} - -function selectMode(modeName) { - if(modeName === "dot") { - items.toolSelected = "pattern" - items.patternType = "dot" - items.lastToolSelected = "pattern" - getPattern() - items.background.reloadSelectedPen() - } - else if(modeName === "pattern2") { - items.toolSelected = "pattern" - items.patternType = "horizLine" - items.lastToolSelected = "pattern" - getPattern2() - items.background.reloadSelectedPen() - } - else if(modeName === "pattern3") { - items.toolSelected = "pattern" - items.patternType = "vertLine" - items.lastToolSelected = "pattern" - getPattern3() - items.background.reloadSelectedPen() - } -}