diff --git a/services/static-webserver/client/source/class/osparc/editor/AnnotationEditor.js b/services/static-webserver/client/source/class/osparc/editor/AnnotationEditor.js index ec0f956c590..f62e7b8ef1e 100644 --- a/services/static-webserver/client/source/class/osparc/editor/AnnotationEditor.js +++ b/services/static-webserver/client/source/class/osparc/editor/AnnotationEditor.js @@ -21,20 +21,22 @@ qx.Class.define("osparc.editor.AnnotationEditor", { construct: function(annotation) { this.base(arguments); - const layout = new qx.ui.layout.Grid(5, 5); - layout.setColumnAlign(0, "right", "middle"); - layout.setColumnAlign(1, "left", "middle"); - this._setLayout(layout); + this._setLayout(new qx.ui.layout.VBox(10)); - this.set({ - padding: 10 - }); + this.__form = new qx.ui.form.Form(); + this.getChildControl("form-renderer"); if (annotation) { this.setAnnotation(annotation); } }, + events: { + "addAnnotation": "qx.event.type.Event", + "cancel": "qx.event.type.Event", + "deleteAnnotation": "qx.event.type.Event", + }, + properties: { annotation: { check: "osparc.workbench.Annotation", @@ -52,113 +54,155 @@ qx.Class.define("osparc.editor.AnnotationEditor", { }, members: { - __addColor: function() { - this._add(new qx.ui.basic.Label(this.tr("Color")), { - row: 0, - column: 0 - }); - const colorPicker = new osparc.form.ColorPicker(); - this._add(colorPicker, { - row: 0, - column: 1 - }); - return colorPicker; + __form: null, + + getForm: function() { + return this.__form; }, - __applyAnnotation: function(annotation) { - this._removeAll(); + _createChildControlImpl: function(id) { + let control; + switch (id) { + case "form-renderer": + control = new qx.ui.form.renderer.Single(this.__form); + this._add(control); + break; + case "text-field": + control = new qx.ui.form.TextField(); + this.__form.add(control, "Text", null, "text"); + break; + case "text-area": + control = new qx.ui.form.TextArea().set({ + autoSize: true, + minHeight: 70, + maxHeight: 140 + }); + this.__form.add(control, "Note", null, "note"); + break; + case "color-picker": + control = new osparc.form.ColorPicker(); + this.__form.add(control, "Color", null, "color"); + break; + case "font-size": + control = new qx.ui.form.Spinner(); + this.__form.add(control, "Size", null, "size"); + break; + case "buttons-layout": + control = new qx.ui.container.Composite(new qx.ui.layout.HBox(10).set({ + alignX: "right" + })); + this._add(control); + break; + case "cancel-btn": { + const buttons = this.getChildControl("buttons-layout"); + control = new qx.ui.form.Button(this.tr("Cancel")).set({ + appearance: "form-button-text" + }); + control.addListener("execute", () => this.fireEvent("cancel"), this); + buttons.add(control); + break; + } + case "add-btn": { + const buttons = this.getChildControl("buttons-layout"); + control = new qx.ui.form.Button(this.tr("Add")).set({ + appearance: "form-button" + }); + control.addListener("execute", () => this.fireEvent("addAnnotation"), this); + buttons.add(control); + break; + } + case "delete-btn": { + const buttons = this.getChildControl("buttons-layout"); + control = new qx.ui.form.Button(this.tr("Delete")).set({ + appearance: "danger-button" + }); + control.addListener("execute", () => this.fireEvent("deleteAnnotation"), this); + buttons.add(control); + break; + } + } + return control || this.base(arguments, id); + }, + __applyAnnotation: function(annotation) { if (annotation === null) { return; } - let row = 0; - if (["text", "rect"].includes(annotation.getType())) { - const colorPicker = this.__addColor(); - annotation.bind("color", colorPicker, "color"); - colorPicker.bind("color", annotation, "color"); - row++; - } - const attrs = annotation.getAttributes(); if (annotation.getType() === "text") { - this._add(new qx.ui.basic.Label(this.tr("Text")), { - row, - column: 0 + const textField = this.getChildControl("text-field").set({ + value: attrs.text }); - const textField = new qx.ui.form.TextField(attrs.text); textField.addListener("changeValue", e => annotation.setText(e.getData())); - this._add(textField, { - row, - column: 1 - }); - row++; } else if (annotation.getType() === "note") { - this._add(new qx.ui.basic.Label(this.tr("Note")), { - row, - column: 0 - }); - const textArea = new qx.ui.form.TextArea(attrs.text).set({ - autoSize: true, - minHeight: 70, - maxHeight: 140 + const textArea = this.getChildControl("text-area").set({ + value: attrs.text }); textArea.addListener("changeValue", e => annotation.setText(e.getData())); - this._add(textArea, { - row, - column: 1 - }); - row++; + } + + if (["text", "rect"].includes(annotation.getType())) { + const colorPicker = this.getChildControl("color-picker"); + annotation.bind("color", colorPicker, "value"); + colorPicker.bind("value", annotation, "color"); } if (annotation.getType() === "text") { - this._add(new qx.ui.basic.Label(this.tr("Size")), { - row, - column: 0 - }); - const fontSizeField = new qx.ui.form.Spinner(attrs.fontSize); + const fontSizeField = this.getChildControl("font-size").set({ + value: attrs.fontSize + }) fontSizeField.addListener("changeValue", e => annotation.setFontSize(e.getData())); - this._add(fontSizeField, { - row, - column: 1 - }); - row++; } - - this.__makeItModal(); }, __applyMarker: function(marker) { - this._removeAll(); - if (marker === null) { return; } - const colorPicker = this.__addColor(); + const colorPicker = this.getChildControl("color-picker"); marker.bind("color", colorPicker, "color"); colorPicker.bind("color", marker, "color"); + }, + + addDeleteButton: function() { + this.getChildControl("delete-btn"); + }, - this.__makeItModal(); + addAddButtons: function() { + this.getChildControl("cancel-btn"); + this.getChildControl("add-btn"); + + // Listen to "Enter" key + this.addListener("keypress", keyEvent => { + if (keyEvent.getKeyIdentifier() === "Enter") { + this.fireEvent("addAnnotation"); + } + }, this); }, - __makeItModal: function() { + makeItModal: function() { + this.set({ + padding: 10 + }); + this.show(); - const showHint = () => this.show(); - const hideHint = () => this.exclude(); + const showEditor = () => this.show(); + const hideEditor = () => this.exclude(); const tapListener = event => { if (osparc.utils.Utils.isMouseOnElement(this, event)) { return; } - hideHint(); + hideEditor(); this.set({ annotation: null, marker: null }); document.removeEventListener("mousedown", tapListener); }; - showHint(); + showEditor(); document.addEventListener("mousedown", tapListener); } } diff --git a/services/static-webserver/client/source/class/osparc/form/ColorPicker.js b/services/static-webserver/client/source/class/osparc/form/ColorPicker.js index 7c1498f189f..f8a9ab9ec64 100644 --- a/services/static-webserver/client/source/class/osparc/form/ColorPicker.js +++ b/services/static-webserver/client/source/class/osparc/form/ColorPicker.js @@ -8,55 +8,74 @@ qx.Class.define("osparc.form.ColorPicker", { extend: qx.ui.core.Widget, + include : [ + qx.ui.form.MForm + ], + implement : [ + qx.ui.form.IStringForm, + qx.ui.form.IForm + ], construct: function() { this.base(arguments); - this._setLayout(new qx.ui.layout.HBox()); + const layout = new qx.ui.layout.HBox(); + this._setLayout(layout); - this._add(this.getChildControl("random-button")); - this._add(this.getChildControl("selector-button")); - this._add(this.getChildControl("color-input")); + this.getChildControl("random-button"); + this.getChildControl("selector-button"); + this.getChildControl("color-input"); }, properties: { - color: { + value: { check: "Color", - event: "changeColor", + event: "changeValue", init: "#303030" } }, + // eslint-disable-next-line qx-rules/no-refs-in-members members: { + _forwardStates: { + focused : true, + invalid : true + }, + _createChildControlImpl: function(id) { let control; switch (id) { case "random-button": control = new qx.ui.form.Button(null, "@FontAwesome5Solid/sync-alt/12"); - control.addListener("execute", () => this.setColor(osparc.utils.Utils.getRandomColor()), this); - this.bind("color", control, "backgroundColor"); - this.bind("color", control, "textColor", { + control.addListener("execute", () => this.setValue(osparc.utils.Utils.getRandomColor()), this); + this.bind("value", control, "backgroundColor"); + this.bind("value", control, "textColor", { converter: value => qx.theme.manager.Color.getInstance().resolve(osparc.utils.Utils.getContrastedTextColor(value)) }); + this._add(control); break; case "selector-button": control = new qx.ui.form.Button(null, "@FontAwesome5Solid/eye-dropper/12"); control.addListener("execute", () => this.__openColorSelector(), this); - this.bind("color", control, "backgroundColor"); - this.bind("color", control, "textColor", { + this.bind("value", control, "backgroundColor"); + this.bind("value", control, "textColor", { converter: value => qx.theme.manager.Color.getInstance().resolve(osparc.utils.Utils.getContrastedTextColor(value)) }); + this._add(control); break; case "color-input": control = new qx.ui.form.TextField().set({ - width: 60, + width: 80, required: true }); - this.bind("color", control, "value"); + this._add(control, { + flex: 1 + }); + this.bind("value", control, "value"); control.addListener("changeValue", e => { const newColor = e.getData(); if (osparc.utils.Validators.hexColor(newColor, control)) { - this.setColor(newColor); + this.setValue(newColor); } }); break; @@ -66,12 +85,30 @@ qx.Class.define("osparc.form.ColorPicker", { __openColorSelector: function() { const colorSelector = new qx.ui.control.ColorSelector(); - const rgb = qx.util.ColorUtil.hexStringToRgb(this.getColor()); + const rgb = qx.util.ColorUtil.hexStringToRgb(this.getValue()); colorSelector.setRed(rgb[0]); colorSelector.setGreen(rgb[1]); colorSelector.setBlue(rgb[2]); osparc.ui.window.Window.popUpInWindow(colorSelector, this.tr("Pick a color"), 590, 380); - colorSelector.addListener("changeValue", e => this.setColor(e.getData())); - } + colorSelector.addListener("changeValue", e => this.setValue(e.getData())); + }, + + // overridden + resetValue: function() { + this.getChildControl("color-input").resetValue(); + }, + + // overridden + focus: function() { + this.base(arguments); + this.getChildControl("color-input").getFocusElement().focus(); + }, + + // overridden + tabFocus: function() { + const field = this.getChildControl("color-input"); + field.getFocusElement().focus(); + field.selectAllText(); + }, } }); diff --git a/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js b/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js index 0c4594d3376..4ebd0569c0c 100644 --- a/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js +++ b/services/static-webserver/client/source/class/osparc/info/ServiceUtils.js @@ -86,12 +86,13 @@ qx.Class.define("osparc.info.ServiceUtils", { * @param serviceData {Object} Serialized Service Object */ createContact: function(serviceData) { - const owner = new qx.ui.basic.Label(); - owner.set({ - value: osparc.utils.Utils.getNameFromEmail(serviceData["contact"]), - toolTipText: serviceData["contact"] + const contact = new qx.ui.basic.Label(); + contact.set({ + value: osparc.store.Support.mailToText(serviceData["contact"], (serviceData["name"] + ":" + serviceData["version"])), + selectable: true, + rich: true }); - return owner; + return contact; }, /** diff --git a/services/static-webserver/client/source/class/osparc/store/Support.js b/services/static-webserver/client/source/class/osparc/store/Support.js index 508ad582644..e79de4d1a27 100644 --- a/services/static-webserver/client/source/class/osparc/store/Support.js +++ b/services/static-webserver/client/source/class/osparc/store/Support.js @@ -137,7 +137,7 @@ qx.Class.define("osparc.store.Support", { mailToText: function(email, subject) { const color = qx.theme.manager.Color.getInstance().resolve("text"); - const textLink = `