package com.project.website.canvas.client.shared.widgets;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.TouchStartEvent;
import com.google.gwt.event.dom.client.TouchStartHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.project.shared.client.handlers.RegistrationsManager;
import com.project.shared.client.utils.ElementUtils;
import com.project.shared.client.utils.EventUtils;
import com.project.shared.client.utils.SchedulerUtils;
import com.project.shared.client.utils.WindowUtils;
import com.project.shared.data.Point2D;
import com.project.shared.data.Rectangle;
import com.project.website.canvas.client.resources.CanvasResources;
public class FloatingToolbar extends FlowPanel
{
private static final int TOOLBAR_MARGIN = 10;
private final RegistrationsManager registrationsManager = new RegistrationsManager();
protected Widget _editedWidget = null;
private final ScheduledCommand updatePositionCommand = new ScheduledCommand() {
@Override public void execute() {
actualUpdatePosition();
}
};
public FloatingToolbar()
{
this.addStyleName(CanvasResources.INSTANCE.main().floatingToolbar());
}
public void setEditedWidget(Widget widget)
{
if (this._editedWidget == widget)
{
return;
}
this._editedWidget = widget;
this.setVisible(null != this._editedWidget);
this.registrationsManager.clear();
if (null == this._editedWidget)
{
return;
}
this.setRegistrations();
this.updatePosition();
}
private void setRegistrations()
{
final FloatingToolbar that = this;
this.registrationsManager.add(this._editedWidget.addDomHandler(new MouseDownHandler() {
@Override public void onMouseDown(MouseDownEvent event) {
that.updatePosition();
}}, MouseDownEvent.getType()));
this.registrationsManager.add(this._editedWidget.addDomHandler(new TouchStartHandler() {
@Override public void onTouchStart(TouchStartEvent event) {
that.updatePosition();
}}, TouchStartEvent.getType()));
// this.registrationsManager.add(this._editedWidget.addDomHandler(new MouseUpHandler() {
// @Override public void onMouseUp(MouseUpEvent event) {
// that.updatePosition();
// }}, MouseUpEvent.getType()));
// this.registrationsManager.add(this._editedWidget.addDomHandler(new KeyDownHandler() {
// @Override public void onKeyDown(KeyDownEvent event) {
// that.updatePosition();
// }}, KeyDownEvent.getType()));
this.registrationsManager.add(this._editedWidget.addDomHandler(new FocusHandler() {
@Override public void onFocus(FocusEvent event) {
that.updatePosition();
}}, FocusEvent.getType()));
this.registrationsManager.add(Window.addResizeHandler(new ResizeHandler() {
@Override public void onResize(ResizeEvent event) {
that.updatePosition();
}
}));
this.registrationsManager.add(Event.addNativePreviewHandler(new NativePreviewHandler() {
@Override
public void onPreviewNativeEvent(NativePreviewEvent event)
{
if (EventUtils.nativePreviewEventTypeEquals(event, KeyDownEvent.getType())) {
// Update the position after the element has handled the event.
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override public void execute() {
that.updatePosition();
}
});
}
}
}));
}
public void updatePosition()
{
SchedulerUtils.OneTimeScheduler.get().scheduleDeferredOnce(updatePositionCommand);
}
public void actualUpdatePosition()
{
if (null == this._editedWidget) {
return;
}
Element element = this._editedWidget.getElement();
Rectangle elementRect = ElementUtils.getElementAbsoluteRectangle(element);
Point2D minCorner = elementRect.getCenter();
Point2D maxCorner = elementRect.getCenter();
Point2D[] corners = elementRect.getCorners().asArray();
for (int i = 0 ; i < corners.length; i++)
{
minCorner = Point2D.min(minCorner, corners[i]);
maxCorner = Point2D.max(maxCorner, corners[i]);
}
Point2D mySize = ElementUtils.getElementOffsetSize(this.getElement());
Point2D windowSize = WindowUtils.getClientSize();
Point2D maxToolbarPosInWindow = windowSize.minus(mySize).minus(new Point2D(TOOLBAR_MARGIN, TOOLBAR_MARGIN));
Point2D targetPos = minCorner.minus(new Point2D(0, mySize.getY() + TOOLBAR_MARGIN));
Point2D fixedTargetPos = targetPos.limitTo(Point2D.zero, maxToolbarPosInWindow);
if (targetPos.getY() < 0)
{
// The toolbar will be inside the element, move it to below it instead of trying to fit it above.
fixedTargetPos = new Point2D(fixedTargetPos.getX(), maxCorner.getY() + TOOLBAR_MARGIN)
.limitTo(Point2D.zero, maxToolbarPosInWindow);
}
ElementUtils.setElementCSSPosition(this.getElement(), fixedTargetPos);
}
}