diff --git a/package-lock.json b/package-lock.json index b844ac5..4860fec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,9 @@ "@testing-library/user-event": "^13.5.0", "antd": "^5.20.0", "autoprefixer": "^10.4.20", + "dom-to-image-more": "^3.4.5", "fabric": "^6.1.0", + "file-saver": "^2.0.5", "postcss-cli": "^11.0.0", "re-resizable": "^6.9.17", "react": "^18.3.1", @@ -7670,6 +7672,11 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-to-image-more": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-3.4.5.tgz", + "integrity": "sha512-xLkG5idpEPgfuf5bZ82kbNnXq4U4PAB4wd7Zun7cEHrYvjolMtTQdIlheQURS8jLy07TGZeWqoTqGW6onZr0Tw==" + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -9275,6 +9282,11 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", diff --git a/package.json b/package.json index c9bce63..a0677e3 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "@testing-library/user-event": "^13.5.0", "antd": "^5.20.0", "autoprefixer": "^10.4.20", + "dom-to-image-more": "^3.4.5", "fabric": "^6.1.0", + "file-saver": "^2.0.5", "postcss-cli": "^11.0.0", "re-resizable": "^6.9.17", "react": "^18.3.1", diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 261db6f..e20c21c 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -2,9 +2,12 @@ import React from "react" // import { DndContext } from '@dnd-kit/core' -import { DeleteOutlined, EditOutlined, ReloadOutlined } from "@ant-design/icons" +import { DeleteOutlined, EditOutlined, FileImageOutlined, ReloadOutlined } from "@ant-design/icons" import { Button, Tooltip, Dropdown } from "antd" +import domtoimage from "dom-to-image-more" +import { saveAs } from 'file-saver' + // import Droppable from "../components/utils/droppableDnd" import Widget from "./widgets/base" import Cursor from "./constants/cursor" @@ -291,6 +294,24 @@ class Canvas extends React.Component { label: (
this.deleteSelectedWidgets([selectedWidget])}> Delete
), icons: , danger: true + }, + { + type: 'divider', + }, + { + key: "snap", + label: (
{ + domtoimage.toPng(selectedWidget.getElement(), { + width: selectedWidget.getElement().offsetWidth * 2, // Multiply element's width by 2 + height: selectedWidget.getElement().offsetHeight * 2 // Multiply element's height by 2 + }).then((dataUrl) => { + saveAs(dataUrl, 'widget.png') + }).catch((error) => { + console.error('Error capturing widget as PNg:', error) + }) + }}> + Save as Image
), + icons: , } ] }) diff --git a/src/frameworks/tkinter/assets/widgets/Toplevel.png b/src/frameworks/tkinter/assets/widgets/Toplevel.png new file mode 100644 index 0000000..86bbdbb Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/Toplevel.png differ diff --git a/src/frameworks/tkinter/assets/widgets/button.png b/src/frameworks/tkinter/assets/widgets/button.png index 2d45182..ad0d3a7 100644 Binary files a/src/frameworks/tkinter/assets/widgets/button.png and b/src/frameworks/tkinter/assets/widgets/button.png differ diff --git a/src/frameworks/tkinter/assets/widgets/check.png b/src/frameworks/tkinter/assets/widgets/check.png new file mode 100644 index 0000000..85f1d61 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/check.png differ diff --git a/src/frameworks/tkinter/assets/widgets/dropdown.png b/src/frameworks/tkinter/assets/widgets/dropdown.png new file mode 100644 index 0000000..16f27ec Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/dropdown.png differ diff --git a/src/frameworks/tkinter/assets/widgets/frame.png b/src/frameworks/tkinter/assets/widgets/frame.png new file mode 100644 index 0000000..6c78833 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/frame.png differ diff --git a/src/frameworks/tkinter/assets/widgets/frame2.png b/src/frameworks/tkinter/assets/widgets/frame2.png new file mode 100644 index 0000000..91433d4 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/frame2.png differ diff --git a/src/frameworks/tkinter/assets/widgets/input.png b/src/frameworks/tkinter/assets/widgets/input.png new file mode 100644 index 0000000..0cb4dbf Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/input.png differ diff --git a/src/frameworks/tkinter/assets/widgets/label.png b/src/frameworks/tkinter/assets/widgets/label.png new file mode 100644 index 0000000..6dbfacf Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/label.png differ diff --git a/src/frameworks/tkinter/assets/widgets/mainwindow.jpg b/src/frameworks/tkinter/assets/widgets/mainwindow.jpg new file mode 100644 index 0000000..72a62a0 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/mainwindow.jpg differ diff --git a/src/frameworks/tkinter/assets/widgets/mainwindow.png b/src/frameworks/tkinter/assets/widgets/mainwindow.png new file mode 100644 index 0000000..45270a0 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/mainwindow.png differ diff --git a/src/frameworks/tkinter/assets/widgets/radio.png b/src/frameworks/tkinter/assets/widgets/radio.png new file mode 100644 index 0000000..3b1b794 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/radio.png differ diff --git a/src/frameworks/tkinter/assets/widgets/slider.png b/src/frameworks/tkinter/assets/widgets/slider.png new file mode 100644 index 0000000..9916b8e Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/slider.png differ diff --git a/src/frameworks/tkinter/assets/widgets/textarea.png b/src/frameworks/tkinter/assets/widgets/textarea.png new file mode 100644 index 0000000..8b79b65 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/textarea.png differ diff --git a/src/frameworks/tkinter/assets/widgets/widget.png b/src/frameworks/tkinter/assets/widgets/widget.png new file mode 100644 index 0000000..2d45182 Binary files /dev/null and b/src/frameworks/tkinter/assets/widgets/widget.png differ diff --git a/src/frameworks/tkinter/sidebarWidgets.js b/src/frameworks/tkinter/sidebarWidgets.js index ad21802..d66c326 100644 --- a/src/frameworks/tkinter/sidebarWidgets.js +++ b/src/frameworks/tkinter/sidebarWidgets.js @@ -1,7 +1,5 @@ -import Widget from "../../canvas/widgets/base" -import ButtonWidget from "./assets/widgets/button.png" import { CheckBox, RadioButton } from "./widgets/ checkButton" import Button from "./widgets/button" import Frame from "./widgets/frame" @@ -12,71 +10,83 @@ import OptionMenu from "./widgets/optionMenu" import Slider from "./widgets/slider" import TopLevel from "./widgets/toplevel" +import MainWindowImage from "./assets/widgets/mainwindow.png" +import TopLevelImage from "./assets/widgets/Toplevel.png" +import FrameImage from "./assets/widgets/frame2.png" +import LabelImage from "./assets/widgets/label.png" +import ButtonImage from "./assets/widgets/button.png" +import InputImage from "./assets/widgets/input.png" +import TextAreaImage from "./assets/widgets/textarea.png" +import SliderImage from "./assets/widgets/slider.png" +import DropDownImage from "./assets/widgets/dropdown.png" +import CheckButtonImage from "./assets/widgets/check.png" +import RadioButtonImage from "./assets/widgets/radio.png" + const TkinterSidebar = [ { name: "Main window", - img: ButtonWidget, + img: MainWindowImage, link: "https://github.com", widgetClass: MainWindow }, { name: "Top Level", - img: ButtonWidget, + img: TopLevelImage, link: "https://github.com", widgetClass: TopLevel }, { name: "Frame", - img: ButtonWidget, + img: FrameImage, link: "https://github.com", widgetClass: Frame }, { name: "Label", - img: ButtonWidget, + img: LabelImage, link: "https://github.com", widgetClass: Label }, { name: "Button", - img: ButtonWidget, + img: ButtonImage, link: "https://github.com", widgetClass: Button }, { name: "Entry", - img: ButtonWidget, + img: InputImage, link: "https://github.com", widgetClass: Input }, { name: "Text", - img: ButtonWidget, + img: TextAreaImage, link: "https://github.com", widgetClass: Text }, { name: "CheckBox", - img: ButtonWidget, + img: CheckButtonImage, link: "https://github.com", widgetClass: CheckBox }, { name: "Radio button", - img: ButtonWidget, + img: RadioButtonImage, link: "https://github.com", widgetClass: RadioButton }, { name: "Scale", - img: ButtonWidget, + img: SliderImage, link: "https://github.com", widgetClass: Slider }, { name: "Option Menu", - img: ButtonWidget, + img: DropDownImage, link: "https://github.com", widgetClass: OptionMenu }, diff --git a/src/frameworks/tkinter/widgets/spinBox.js b/src/frameworks/tkinter/widgets/spinBox.js new file mode 100644 index 0000000..8d6ef43 --- /dev/null +++ b/src/frameworks/tkinter/widgets/spinBox.js @@ -0,0 +1,81 @@ +import Widget from "../../../canvas/widgets/base" +import Tools from "../../../canvas/constants/tools" +import { removeKeyFromObject } from "../../../utils/common" + + +class SpinBox extends Widget{ + + static widgetType = "spin_box" + constructor(props) { + super(props) + + this.droppableTags = null // disables drops + + const newAttrs = removeKeyFromObject("layout", this.state.attrs) + + this.state = { + ...this.state, + size: { width: 120, height: 40 }, + attrs: { + ...newAttrs, + styling: { + ...newAttrs.styling, + foregroundColor: { + label: "Foreground Color", + tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string + value: "#000", + onChange: (value) => { + this.setWidgetStyling("color", value) + this.setAttrValue("styling.foregroundColor", value) + } + } + }, + placeHolder: { + label: "PlaceHolder", + tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string + toolProps: {placeholder: "text", maxLength: 100}, + value: "placeholder text", + onChange: (value) => this.setAttrValue("placeHolder", value) + } + + } + } + } + + componentDidMount(){ + super.componentDidMount() + this.setAttrValue("styling.backgroundColor", "#fff") + this.setWidgetName("Entry") + } + + getToolbarAttrs(){ + + const toolBarAttrs = super.getToolbarAttrs() + + return ({ + id: this.__id, + widgetName: toolBarAttrs.widgetName, + placeHolder: this.state.attrs.placeHolder, + size: toolBarAttrs.size, + + ...this.state.attrs, + + }) + } + + renderContent(){ + return ( +
+
+
+ {this.getAttrValue("placeHolder")} +
+
+
+ ) + } + +} + + +export default SpinBox \ No newline at end of file