/*
* Copyright 2010 kk-electronic a/s.
*
* This file is part of KKPortal.
*
* KKPortal is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KKPortal 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KKPortal. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kk_electronic.kkportal.core.ui;
import java.util.HashSet;
import java.util.List;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.layout.client.Layout;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.LayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.kk_electronic.kkportal.core.dnd.DND;
import com.kk_electronic.kkportal.core.dnd.DragSource;
import com.kk_electronic.kkportal.core.dnd.DND.DropSink;
public class GroupDisplay<T extends IsWidget & KnownHeight & DragSource> implements DropSink<T>,IsWidget {
LayoutPanel canvas = new LayoutPanel();
private final DND<T> dnd;
private double margin = 1;
private Unit marginunit = Unit.EM;
public static interface Handler<T>{
public void onElementDrop(double x, int y, T element);
}
private Handler<T> handler;
public void setHandler(Handler<T> handler) {
this.handler = handler;
}
@Inject
public GroupDisplay(DND<T> dnd) {
this.dnd = dnd;
dnd.registerDropSink(this);
}
private native Layout iHateJavaProtection(LayoutPanel layoutPanel) /*-{
return layoutPanel.@com.google.gwt.user.client.ui.LayoutPanel::layout;
}-*/;
HashSet<Widget> displayed = new HashSet<Widget>();
public void setWidgets(List<List<T>> widgets){
if(canvas.isAttached() == false){
return;
}
if(widgets == null){
canvas.clear();
displayed.clear();
return;
}
HashSet<Widget> needRemoval = new HashSet<Widget>(displayed);
Layout l = iHateJavaProtection(canvas);
double x = margin * l.getUnitSize(marginunit, false)/l.getUnitSize(Unit.PCT, false);
double y = margin * l.getUnitSize(marginunit, true);
double left = x;
for(List<T> column:widgets){
double top = y;
//TODO: Support weighted column sizes
double width = (100.0-x) / widgets.size()-x;
for(final T face:column){
final Widget widget = face.asWidget();
int height = face.getDesiredHeight();
if(!displayed.contains(widget)){
canvas.add(widget);
canvas.getWidgetContainerElement(widget).getStyle().clearOverflow();
displayed.add(widget);
face.getDragHandle().addMouseDownHandler(new MouseDownHandler() {
@Override
public void onMouseDown(MouseDownEvent event) {
dnd.startDrag(event, face);
}
});
}
canvas.setWidgetLeftWidth(widget, left, Unit.PCT, width, Unit.PCT);
canvas.setWidgetTopHeight(widget, top, Unit.PX, height, Unit.PX);
top += height+y;
needRemoval.remove(face);
}
left += width + x;
}
for(Widget toRemove : needRemoval){
canvas.remove(toRemove);
displayed.remove(toRemove);
//TODO:remove handler
}
canvas.animate(150);
}
@Override
public boolean Drop(MouseUpEvent event, final T element) {
Widget widget = element.asWidget();
int height = widget.getOffsetHeight();
event.setRelativeElement(canvas.getElement());
final int x = event.getX();
final int y = event.getY();
/*
* Note must be 100.0 and not 100 since the later would result in
* integer division which most likely would be 0
*/
double width = (100.0 * widget.getOffsetWidth()) / canvas.getOffsetWidth();
final int top = widget.getAbsoluteTop() - canvas.getAbsoluteTop();
final double left = (100.0 * (widget.getAbsoluteLeft() - canvas.getAbsoluteLeft()))
/ canvas.getOffsetWidth();
final double xpct = 100.0 * x / canvas.getOffsetWidth();
canvas.add(widget);
canvas.getWidgetContainerElement(widget).getStyle().clearOverflow();
canvas.setWidgetTopHeight(widget, top, Unit.PX, height, Unit.PX);
canvas.setWidgetLeftWidth(widget, left, Unit.PCT, width, Unit.PCT);
if (handler != null) {
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
handler.onElementDrop(xpct, y, element);
}
});
return true;
}
return false;
}
@Override
public Widget asWidget() {
return canvas;
}
public boolean checkForResizes() {
if (canvas.getWidgetCount() == 0)
return false;
//ArrayList<Pair<Integer, Integer>> worklist = new ArrayList<Pair<Integer,Integer>>();
boolean newSizes = false;
for (int i = 0, l = canvas.getWidgetCount(); i < l; i++) {
Widget widget = canvas.getWidget(i);
int desiredHeight = 0;
if (widget instanceof KnownHeight) {
KnownHeight heightWidget = (KnownHeight) widget;
desiredHeight = heightWidget.getDesiredHeight();
if (desiredHeight != heightWidget.getLastHeight()) {
//worklist.add(new Pair(heightWidget.getId(), desiredHeight));
heightWidget.saveHeight(desiredHeight);
newSizes = true;
}
}
}
return newSizes;
}
}