package org.activityinfo.ui.client.component.formdesigner.drop;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* 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
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.VetoDragException;
import com.allen_sauer.gwt.dnd.client.drop.FlowPanelDropController;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import org.activityinfo.model.form.FormElement;
import org.activityinfo.model.form.FormField;
import org.activityinfo.model.form.FormSection;
import org.activityinfo.ui.client.component.form.field.FormFieldWidget;
import org.activityinfo.ui.client.component.formdesigner.FormDesigner;
import org.activityinfo.ui.client.component.formdesigner.container.FieldWidgetContainer;
import org.activityinfo.ui.client.component.formdesigner.container.SectionWidgetContainer;
import org.activityinfo.ui.client.component.formdesigner.container.WidgetContainer;
import org.activityinfo.ui.client.component.formdesigner.event.PanelUpdatedEvent;
import org.activityinfo.ui.client.component.formdesigner.palette.DnDLabel;
import org.activityinfo.ui.client.component.formdesigner.palette.FieldTemplate;
import org.activityinfo.ui.client.component.formdesigner.palette.SectionTemplate;
import org.activityinfo.ui.client.component.formdesigner.palette.Template;
import javax.annotation.Nullable;
import java.util.List;
/**
* @author yuriyz on 07/07/2014.
*/
public class DropPanelDropController extends FlowPanelDropController implements DropControllerExtended {
private final Positioner positioner = new Positioner();
private FormDesigner formDesigner;
private FlowPanel dropTarget;
public DropPanelDropController(FlowPanel dropTarget, FormDesigner formDesigner) {
super(dropTarget);
this.formDesigner = formDesigner;
this.dropTarget = dropTarget;
}
@Override
public void onPreviewDrop(DragContext context) throws VetoDragException {
super.onPreviewDrop(context); // important ! - calculates drop index
if (context.draggable instanceof DnDLabel) {
previewDropNewWidget(context);
} else {
drop(context.draggable, context);
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
formDesigner.updateFieldOrder();
removePositioner();
}
});
}
}
private void previewDropNewWidget(final DragContext context) throws VetoDragException {
final Template template = ((DnDLabel) context.draggable).getTemplate();
if (template instanceof FieldTemplate) {
final FormField formField = ((FieldTemplate)template).create();
formDesigner.getFormFieldWidgetFactory().createWidget(formDesigner.getFormClass(), formField, NullValueUpdater.INSTANCE).then(new Function<FormFieldWidget, Void>() {
@Nullable
@Override
public Void apply(@Nullable FormFieldWidget formFieldWidget) {
final FieldWidgetContainer fieldWidgetContainer = new FieldWidgetContainer(formDesigner, formFieldWidget, formField);
drop(fieldWidgetContainer, context, formField);
return null;
}
});
} else if (template instanceof SectionTemplate) {
final FormSection formSection = ((SectionTemplate)template).create();
SectionWidgetContainer widgetContainer = new SectionWidgetContainer(formDesigner, formSection);
drop(widgetContainer, context, formSection);
}
// forbid drop of source control widget
throw new VetoDragException();
}
private void drop(final Widget widget, DragContext context) {
// hack ! - replace original selected widget with our container, drop it and then restore selection
final List<Widget> originalSelectedWidgets = context.selectedWidgets;
context.selectedWidgets = Lists.newArrayList(widget);
DropPanelDropController.super.onDrop(context); // drop container
context.selectedWidgets = originalSelectedWidgets; // restore state;
formDesigner.getSavedGuard().setSaved(false);
}
private void drop(final WidgetContainer widgetContainer, DragContext context, final FormElement formElement) {
drop(widgetContainer.asWidget(), context);
formDesigner.getEventBus().fireEvent(new PanelUpdatedEvent(widgetContainer, PanelUpdatedEvent.EventType.ADDED));
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
@Override
public void execute() {
int widgetIndex = dropTarget.getWidgetIndex(widgetContainer.asWidget());
// update model
formDesigner.getFormClass().insertElement(widgetIndex, formElement);
formDesigner.getDragController().makeDraggable(widgetContainer.asWidget(), widgetContainer.getDragHandle());
removePositioner();
}
});
}
@Override
protected Widget newPositioner(DragContext context) {
return positioner.asWidget();
}
@Override
public void setPositionerToEnd() {
removePositioner();
dropTarget.insert(positioner, (dropTarget.getWidgetCount()));
}
private void removePositioner() {
int currentIndex = dropTarget.getWidgetIndex(positioner);
if (currentIndex != -1) {
dropTarget.remove(currentIndex);
}
}
}