Index: console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Droppable.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Droppable.java (revision ) +++ console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Droppable.java (revision ) @@ -0,0 +1,122 @@ +package org.hippoecm.frontend.plugins.console.editor; + +import org.apache.wicket.Component; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.markup.head.IHeaderResponse; +import org.apache.wicket.markup.head.OnLoadHeaderItem; +import org.apache.wicket.request.IRequestParameters; +import org.apache.wicket.request.resource.JavaScriptResourceReference; +import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.util.string.StringValue; +import org.apache.wicket.util.visit.IVisit; +import org.apache.wicket.util.visit.IVisitor; +import org.hippoecm.frontend.plugins.yui.AbstractYuiAjaxBehavior; +import org.hippoecm.frontend.plugins.yui.header.IYuiContext; + +public abstract class Droppable extends AbstractYuiAjaxBehavior { + + + private final static ResourceReference DRAGDROP_JS = new JavaScriptResourceReference(Droppable.class, "dragdrop.js"); + + public Droppable() { + super(null); + } + + @Override + public void addHeaderContribution(IYuiContext context) { + context.addModule("dragdrop"); + context.addModule("utilities"); + context.addJavascriptReference(DRAGDROP_JS); + } + + @Override + protected void onRenderHead(final IHeaderResponse response) { + super.onRenderHead(response); + + // build a comma separated list of draggable components + final String groupId = getComponent().getMarkupId(); + final StringBuilder builder = new StringBuilder(); + getComponent().getPage().visitChildren(new DraggableVisitor() { + @Override + void visit(Draggable draggable) { + if (builder.length() > 0) { + builder.append(','); + } + builder.append('\''); + builder.append(draggable.getComponent().getMarkupId()); + builder.append('\''); + } + }); + + // initialize client-side drag&drop app + response.render(OnLoadHeaderItem.forScript("Wicket.yui.DragDropContainerApp.init(null, null," + + " {groupId:'" + groupId + "',items:[" + builder + "], callbackUrl:'" + getCallbackUrl() + "'});")); + + } + + protected boolean accept(Draggable draggable) { + return true; + } + + @Override + protected void respond(final AjaxRequestTarget target) { + // A drag & drop action was performed by the user. Find out which component was dropped on which component. + final IRequestParameters requestParameters = getComponent().getRequest().getRequestParameters(); + final StringValue sourceIdValue = requestParameters.getParameterValue("srcId"); + final StringValue destinationValueId = requestParameters.getParameterValue("destId"); + + if (!sourceIdValue.isEmpty() && !destinationValueId.isEmpty()) { + final String sourceId = sourceIdValue.toString(); + final String destinationId = destinationValueId.toString(); + final int index = requestParameters.getParameterValue("index").toInt(0); + getComponent().getPage().visitChildren(new DraggableVisitor() { + + private Component sourceComponent; + private Component destinationComponent; + boolean done = false; + + @Override + void visit(Draggable draggable) { + if (draggable.getComponent().getMarkupId().equals(destinationId)) { + destinationComponent = draggable.getComponent(); + } else if (draggable.getComponent().getMarkupId().equals(sourceId)) { + sourceComponent = draggable.getComponent(); + } + if (!done && sourceComponent != null && destinationComponent != null) { + onDrop(target, sourceComponent, destinationComponent, index); + done = true; + } + } + }); + } + } + + /** + * Called when a drag & drop action is performed by the user. Depending on the drag movement, sourceComponent is + * inserted either before or after targetComponent. The index parameter is used to determine this. + * + * @param target Wicket AjaxRequestTarget + * @param sourceComponent The component that was dragged & dropped + * @param targetComponent The component on which the sourceComponent was dropped + * @param index the index at which to insert the component + */ + public abstract void onDrop(AjaxRequestTarget target, Component sourceComponent, Component targetComponent, + int index); + + private abstract class DraggableVisitor implements IVisitor { + @Override + public void component(final Component component, final IVisit visit) { + for (Behavior behavior : component.getBehaviors()) { + if (behavior instanceof Draggable) { + final Draggable draggable = (Draggable) behavior; + if (accept(draggable)) { + visit(draggable); + } + } + } + } + + abstract void visit(Draggable draggable); + } +} Index: console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Draggable.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Draggable.java (revision ) +++ console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/Draggable.java (revision ) @@ -0,0 +1,28 @@ +package org.hippoecm.frontend.plugins.console.editor; + +import org.apache.wicket.Component; +import org.apache.wicket.behavior.Behavior; + +public class Draggable extends Behavior { + private static final long serialVersionUID = 1L; + Component component; + + public Draggable() { + + } + + @Override + public void bind(final Component component) { + this.component = component; + component.setOutputMarkupId(true); + } + + @Override + public boolean getStatelessHint(Component component) { + return false; + } + + public Component getComponent() { + return component; + } +} Index: console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/dragdrop.js IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/dragdrop.js (revision ) +++ console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/dragdrop.js (revision ) @@ -0,0 +1,136 @@ +/* + * Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +(function() { + if (window.Wicket === undefined) { + window.Wicket = {}; + } + if (window.Wicket.yui === undefined) { + window.Wicket.yui = {}; + } + + var Dom = window.YAHOO.util.Dom, Util = window.YAHOO.util + , log = function(str) { + window.YAHOO.log(str, 'info', 'dragdrop'); + window.console.log(str); + }; + + window.Wicket.yui.DragDropContainerApp = { + groupId : null, + target: null, + items: [], + + init: function(type, obj, args) { + log('init DragDropContainer[' + args.groupId + ']'); + + var group = args.groupId || null, + items = args.items || [], + url = args.callbackUrl, + i; + + if (this.groupId !== group) { //disable check for now + this.groupId = group; + this.target = new window.YAHOO.util.DDTarget(group, null, {useShim: true}); + window.YAHOO.hippo.HippoAjax.registerDestroyFunction(Dom.get(group), this.reset, this); + } + + for (i = 0; i < items.length; i++) { + this.items[i] = new window.Wicket.yui.DragDropContainer(items[i], group, {useShim: true}, url); + } + }, + + reset: function() { + var i; + log('Reset DragDropContainer[' + this.groupId + ']'); + if (this.target !== null) { + this.target.unreg(); + } + this.target = null; + this.groupId = null; + for (i = 0; i < this.items.length; i++) { + this.items[i].unreg(); + } + this.items = []; + } + }; + + window.Wicket.yui.DragDropContainer = function(id, sGroup, config, callbackUrl) { + window.Wicket.yui.DragDropContainer.superclass.constructor.call(this, id, sGroup, config); + + this.callbackUrl = callbackUrl + '&did=' + id; + this.goingUp = false; + this.lastY = 0; + + // By default, anchor links are not allowed to initiate a drag. + this.removeInvalidHandleType('a'); + Dom.setStyle(this.getDragEl(), "opacity", 0.67); // The proxy is slightly transparent + }; + + window.YAHOO.extend(window.Wicket.yui.DragDropContainer, window.YAHOO.util.DDProxy, window.YAHOO.util.DD, { + + container: null, + + init: function() { + this.initConstraints(); + }, + + initConstraints: function() { + //Get the top, right, bottom and left positions + var region = Dom.getRegion(this.cont); + //Get the element we are working on + var el = this.getEl(); + //Get the xy position of it + var xy = Dom.getXY(el); + //Get the width and height + var width = parseInt(Dom.getStyle(el, 'width'), 10); + var height = parseInt(Dom.getStyle(el, 'height'), 10); + //Set left to x minus left + var left = xy[0] - region.left; + //Set right to right minus x minus width + var right = region.right - xy[0] - width; + //Set top to y minus top + var top = xy[1] - region.top; + //Set bottom to bottom minus y minus height + var bottom = region.bottom - xy[1] - height; + //Set the constraints based on the above calculations + this.setXConstraint(left, right); + this.setYConstraint(top, bottom); + }, + startDrag: function(x, y) { + }, + + endDrag: function(e) { + }, + + onDragDrop: function(e, id) { + }, + + onDrag: function(e) { + }, + + onDragOver: function(e, id) { + }, + + isValidDragDrop: function(srcEl, destEl) { + // ignore fields being dragged over themselves + if (Dom.isAncestor(srcEl, destEl)) { + return false; + } + + return true; + } + }); + +}()); Index: console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/PropertyValueEditor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/PropertyValueEditor.java (revision 44764) +++ console/frontend/src/main/java/org/hippoecm/frontend/plugins/console/editor/PropertyValueEditor.java (revision ) @@ -62,6 +62,18 @@ protected void populateItem(Item item) { EditorPlugin plugin = findParent(EditorPlugin.class); IPluginContext context = plugin.getPluginContext(); + item.setOutputMarkupId(true); + + item.add(new Draggable()); + item.add(new Droppable() { + private static final long serialVersionUID = 1L; + + @Override + public void onDrop(AjaxRequestTarget target, Component sourceComponent, Component targetComponent, int index) { + this.onDrop(target, sourceComponent, targetComponent, index); + } + }); + List factoryList = context.getServices(ValueEditorFactory.SERVICE_ID, ValueEditorFactory.class); try { final JcrPropertyValueModel valueModel = (JcrPropertyValueModel) item.getModel(); @@ -155,4 +167,8 @@ } } + protected void onDrop(final AjaxRequestTarget target, final Component sourceComponent, final Component targetComponent, final int index) { + //TODO Handle on drop + log.debug("On drop event"); + } }