diff --git a/octoprint_customControl/__init__.py b/octoprint_customControl/__init__.py index 31fe752..4a134fc 100644 --- a/octoprint_customControl/__init__.py +++ b/octoprint_customControl/__init__.py @@ -8,66 +8,70 @@ from octoprint.settings import settings import octoprint.plugin + class CustomControlPlugin(octoprint.plugin.SettingsPlugin, - octoprint.plugin.TemplatePlugin, - octoprint.plugin.AssetPlugin): + octoprint.plugin.TemplatePlugin, + octoprint.plugin.AssetPlugin): + def get_settings_defaults(self): + return dict( + controls=[] + ) - def get_settings_defaults(self): - return dict( - controls = [] - ) + def get_template_configs(self): + if "editorcollection" in self._plugin_manager.enabled_plugins: + return [ + dict(type="plugin_editorcollection_EditorCollection", template="customControl_hookedsettings.jinja2", + custom_bindings=True) + ] + else: + return [ + dict(type="settings", template="customControl_hookedsettings.jinja2", custom_bindings=True) + ] - def get_template_configs(self): - if "editorcollection" in self._plugin_manager.enabled_plugins: - return [ - dict(type="plugin_editorcollection_EditorCollection", template="customControl_hookedsettings.jinja2", custom_bindings=True) - ] - else: - return [ - dict(type="settings", template="customControl_hookedsettings.jinja2", custom_bindings=True) - ] + def on_settings_save(self, data): + s = settings() + s.set(["controls"], data["controls"]) - def on_settings_save(self, data): - s = settings() - s.set(["controls"], data["controls"]) + def get_assets(self): + return dict( + js=[ + "js/jquery.ui.sortable.js", + "js/customControl.js", + "js/customControlDialog.js", + ], + css=["css/customControls.css"], + less=["less/customControls.less"] + ) - def get_assets(self): - return dict( - js=[ - "js/customControl.js", - "js/customControlDialog.js", - ], - css=["css/customControls.css"], - less=["less/customControls.less"] - ) + def get_update_information(self): + return dict( + customcontrol=dict( + displayName="Custom Control Editor Plugin", + displayVersion=self._plugin_version, - def get_update_information(self): - return dict( - customcontrol=dict( - displayName="Custom Control Editor Plugin", - displayVersion=self._plugin_version, + # version check: github repository + type="github_release", + user="Salandora", + repo="octoprint-customControl", + current=self._plugin_version, - # version check: github repository - type="github_release", - user="Salanddora", - repo="octoprint-customControl", - current=self._plugin_version, + # update method: pip + pip="https://github.com/Salandora/octoprint-customControl/archive/{target_version}.zip" + ) + ) - # update method: pip - pip="https://github.com/Salandora/octoprint-customControl/archive/{target_version}.zip" - ) - ) __plugin_name__ = "Custom Control Editor" + + def __plugin_load__(): - global __plugin_implementation__ - __plugin_implementation__ = CustomControlPlugin() + global __plugin_implementation__ + __plugin_implementation__ = CustomControlPlugin() - global __plugin_hooks__ - __plugin_hooks__ = { - "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information - } - - global __plugin_license__ - __plugin_license__ = "AGPLv3" + global __plugin_hooks__ + __plugin_hooks__ = { + "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information + } + global __plugin_license__ + __plugin_license__ = "AGPLv3" diff --git a/octoprint_customControl/static/css/customControls.css b/octoprint_customControl/static/css/customControls.css index 2a5fbd1..a8c7f17 100644 --- a/octoprint_customControl/static/css/customControls.css +++ b/octoprint_customControl/static/css/customControls.css @@ -1 +1,54 @@ -#customControls .custom_section_horizontal .custom_control{display:inline-block}#customControls .custom_section_vertical .custom_control{display:block}#customControls .custom_section_vertical_section{min-width:15px;min-height:15px;border:1px dashed #000}#customControls .slider.slider-disabled .slider-track{cursor:default!important}#customControls input[disabled]{background:#fff!important;cursor:text!important}#customControls .custom_section h1{cursor:pointer;display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #E5E5E5;font-weight:400} \ No newline at end of file +#customControls .innerSortable { + width: 100%; + min-height: 50px; +} +#customControls .custom_section_horizontal > .custom_control { + display: inline-block; +} +#customControls .custom_section_vertical > .custom_control { + display: block; +} +#customControls .custom_section_vertical_section { + min-width: 15px; + min-height: 15px; + border: 1px dashed #000000; +} +#customControls .slider.slider-disabled .slider-track { + cursor: default !important; +} +#customControls input[disabled] { + background: #fff !important; + cursor: text !important; +} +#customControls .btn-group { + margin-bottom: 10px; +} +#customControls .btn-group.distance > .btn { + width: 43px; + padding: 3px 0; + height: 30px; +} +#customControls .slider-handle { + width: 14px; + height: 14px; + margin-left: -7px; + margin-top: -3px; +} +#customControls .custom_section h1 { + cursor: pointer; + display: block; + width: 100%; + padding: 0; + margin-bottom: 10px; + font-size: 21px; + line-height: 40px; + color: #333; + border: 0; + border-bottom: 1px solid #E5E5E5; + font-weight: normal; +} +#customControls .custom_control .slider { + margin-left: 10px; + margin-right: 10px; + margin-bottom: 2px; +} diff --git a/octoprint_customControl/static/js/customControl.js b/octoprint_customControl/static/js/customControl.js index 9d59489..37960a3 100644 --- a/octoprint_customControl/static/js/customControl.js +++ b/octoprint_customControl/static/js/customControl.js @@ -56,7 +56,75 @@ // TODO: Brainstorming about how to handle additionalControls... self.staticID = 0; - self.controls(self._processControls(undefined, self.controlsFromServer)) + self.controls(undefined); + self.controls(self._processControls(undefined, self.controlsFromServer)); + + $(".innerSortable").sortable({ + connectWith: ".innerSortable", + items: "> .sortable", + cancel: '', + sort: function (event, ui) { + var self = $(this), + width = ui.helper.outerWidth(), + top = ui.helper.position().top;//changed to ; + + self.children().each(function () { + if ($(this).hasClass('ui-sortable-helper') || $(this).hasClass('ui-sortable-placeholder')) { + return true; + } + // If overlap is more than half of the dragged item + var distance = Math.abs(ui.position.left - $(this).position().left), + before = ui.position.left > $(this).position().left; + + if ((width - distance) > (width / 2) && (distance < width) && $(this).position().top === top) { + if (before) { + $('.ui-sortable-placeholder', self).insertBefore($(this)); + } else { + $('.ui-sortable-placeholder', self).insertAfter($(this)); + } + return false; + } + }); + }, + update: function(event, ui) { + var target = ko.dataFor(this); + var item = ko.dataFor(ui.item[0]); + + if (target == undefined) { + return; + } else { + if (target == self) { + if (!item.hasOwnProperty("children")) { + return; + } + } + else if (!target.hasOwnProperty("children")) { + return; + } + } + + var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); + if (position >= 0) { + if (item.parent != undefined) { + item.parent.children.remove(item); + + if (target == self) + self.controlsFromServer.splice(position, 0, item); + else + target.children.splice(position, 0, item); + } else { + self.controlsFromServer = _.without(self.controlsFromServer, item); + if (target == self) + self.controlsFromServer.splice(position, 0, item); + else + target.children.splice(position, 0, item); + } + } + }, + stop: function(event, ui) { + self.rerenderControls(); + } + }).disableSelection(); }; self._processControls = function (parent, controls) { @@ -197,7 +265,7 @@ if (customControl.hasOwnProperty("offset") && customControl.offset() != "") { offset = "offset" + customControl.offset(); } - return span + " " + offset; + return "sortable " + span + " " + offset; }; self.searchElement = function (list, id) { diff --git a/octoprint_customControl/static/less/customControls.less b/octoprint_customControl/static/less/customControls.less index 8e255da..740176d 100644 --- a/octoprint_customControl/static/less/customControls.less +++ b/octoprint_customControl/static/less/customControls.less @@ -1,14 +1,20 @@ #customControls { - .custom_section_horizontal .custom_control { + .innerSortable { + width: 100%; + min-height: 50px; + } + + .custom_section_horizontal > .custom_control { display:inline-block; } - .custom_section_vertical .custom_control { + + .custom_section_vertical > .custom_control { display:block; } .custom_section_vertical_section { min-width:15px; min-height:15px; - + border:1px dashed #000000; } @@ -21,19 +27,43 @@ cursor: text !important; } - .custom_section { - h1 { + .btn-group { + margin-bottom: 10px; + } + + .btn-group.distance > .btn { + width: 43px; + padding: 3px 0; + height: 30px; + } + + .slider-handle { + width: 14px; + height: 14px; + margin-left: -7px; + margin-top: -3px; + } + + .custom_section { + h1 { cursor: pointer; display: block; width: 100%; padding: 0; - margin-bottom: 20px; + margin-bottom: 10px; font-size: 21px; line-height: 40px; color: #333; border: 0; border-bottom: 1px solid #E5E5E5; - font-weight: normal; - } + font-weight: normal; + } + } + .custom_control { + .slider { + margin-left: 10px; + margin-right: 10px; + margin-bottom: 2px; + } } } \ No newline at end of file diff --git a/octoprint_customControl/templates/customControl_hookedsettings.jinja2 b/octoprint_customControl/templates/customControl_hookedsettings.jinja2 index 404325b..16c9533 100644 --- a/octoprint_customControl/templates/customControl_hookedsettings.jinja2 +++ b/octoprint_customControl/templates/customControl_hookedsettings.jinja2 @@ -4,7 +4,7 @@ - +