import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.storage.client.Storage;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
// drag this far before actually moving window
protected static final int MOVE_TRESHOLD = 5;
- // window minimum sizes
+ // window minimum height, minimum width comes from tab+controls
protected static final int MIN_HEIGHT = 40;
- protected static final int HANDLE_SIZE = 5;
+
+ // size of area to grab for resize; bottom corners size in CSS
+ protected static final int HANDLE_SIZE = 7;
// identifiers for localStorage
private static final String STORAGE_PREFIX = "v-debug-";
// sections
protected ArrayList<Section> sections = new ArrayList<Section>();
- // handles resizing (mouse)
- protected ResizeHandler resizeHandler = new ResizeHandler();
- protected HandlerRegistration resizeReg = null;
- protected HandlerRegistration resizeReg2 = null;
-
- // handles window movement (mouse)
- protected MoveHandler moveHandler = new MoveHandler();
- protected HandlerRegistration moveReg = null;
+ // handles resize/move
+ protected HandlerRegistration mouseDownHandler = null;
+ protected HandlerRegistration mouseMoveHandler = null;
// TODO this class should really be a singleton.
static VDebugWindow instance;
head.add(sectionHead);
window.add(content);
+ addHandles();
+
head.setStylePrimaryName(STYLENAME_HEAD);
tabs.setStylePrimaryName(STYLENAME_TABS);
controls.setStylePrimaryName(STYLENAME_CONTROLS);
Style s = content.getElement().getStyle();
s.setOverflow(Overflow.AUTO);
- // window can be moved by dragging header
- moveReg = head.addDomHandler(moveHandler, MouseDownEvent.getType());
- // resize from all sides and corners
- resizeReg = content.addDomHandler(resizeHandler,
+ // move/resize
+ final MouseHandler mouseHandler = new MouseHandler();
+ mouseDownHandler = this.addDomHandler(mouseHandler,
MouseDownEvent.getType());
- // changes mouse pointer when hovering sides / corners
- resizeReg2 = content.addDomHandler(resizeHandler,
+ mouseMoveHandler = this.addDomHandler(mouseHandler,
MouseMoveEvent.getType());
+
+ }
+
+ /**
+ * Adds dummy handle elements to the bottom corners that might have
+ * scrollbars that interfere with resizing on some platforms.
+ *
+ * @since 7.1
+ */
+ private void addHandles() {
+ Element el = DOM.createDiv();
+ el.setClassName(VDebugWindow.STYLENAME + "-handle "
+ + VDebugWindow.STYLENAME + "-handle-sw");
+ content.getElement().appendChild(el);
+
+ el = DOM.createDiv();
+ el.setClassName(VDebugWindow.STYLENAME + "-handle "
+ + VDebugWindow.STYLENAME + "-handle-se");
+ content.getElement().appendChild(el);
}
/**
*/
public void close() {
// TODO disable even more
- if (resizeReg != null) {
- resizeReg.removeHandler();
- resizeReg2.removeHandler();
- moveReg.removeHandler();
+ if (mouseDownHandler != null) {
+ mouseDownHandler.removeHandler();
+ mouseMoveHandler.removeHandler();
+ mouseDownHandler = null;
+ mouseMoveHandler = null;
}
Highlight.hideAll();
hide();
content.setHeight(fullH + "px");
}
+ applyBounds(x, y);
+ }
+
+ private void applyBounds() {
+ int x = getPopupLeft();
+ int y = getPopupTop();
+ applyBounds(x, y);
+ }
+
+ private void applyBounds(int x, int y) {
// bounds check
if (x < 0) {
x = 0;
}
setPopupPosition(x, y);
+
}
/**
*/
static String getTimingTooltip(int sinceStart, int sinceReset) {
String title = formatDuration(sinceStart) + " since start";
- title += ", " + formatDuration(sinceReset) + " since timer reset";
- title += " @ "
+ title += ", " + formatDuration(sinceReset) + " since timer reset";
+ title += " @ "
+ DateTimeFormat.getFormat("HH:mm:ss.SSS").format(new Date());
return title;
}
}
/**
- * Handler for moving window.
+ * Handler for resizing and moving window, also updates cursor on mousemove.
*
* @since 7.1
* @author Vaadin Ltd
*/
- protected class MoveHandler implements MouseDownHandler,
+ protected class MouseHandler implements MouseMoveHandler, MouseDownHandler,
NativePreviewHandler {
- HandlerRegistration handler;
+ boolean resizeLeft;
+ boolean resizeRight;
+ boolean resizeUp;
+ boolean resizeDown;
+ boolean move;
+ boolean sizing;
+
+ // dragging stopped, remove handler on next event
+ boolean stop;
+
+ HandlerRegistration dragHandler;
+
int startX;
int startY;
+ int startW;
+ int startH;
int startTop;
int startLeft;
- // moving stopped, remove handler on next event
- boolean stop;
+ @Override
+ public void onMouseMove(MouseMoveEvent event) {
+ if (null == dragHandler) {
+ updateResizeFlags(event);
+ updateCursor();
+ }
+ }
+
+ @Override
+ public void onMouseDown(MouseDownEvent event) {
+ if (event.getNativeButton() != NativeEvent.BUTTON_LEFT
+ || dragHandler != null) {
+ return;
+ }
+ updateResizeFlags(event);
+ if (sizing || move) {
+ // some os/browsers don't pass events trough scrollbars; hide
+ // while dragging (esp. important for resize from right/bottom)
+ content.getElement().getStyle().setOverflow(Overflow.HIDDEN);
+
+ startX = event.getClientX();
+ startY = event.getClientY();
+
+ startW = content.getOffsetWidth();
+ startH = content.getOffsetHeight();
+
+ startTop = getPopupTop();
+ startLeft = getPopupLeft();
+
+ dragHandler = Event.addNativePreviewHandler(this);
+
+ event.preventDefault();
+
+ stop = false;
+ }
+
+ }
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (event.getTypeInt() == Event.ONMOUSEMOVE && !stop
&& hasMoved(event.getNativeEvent())) {
+
int dx = event.getNativeEvent().getClientX() - startX;
int dy = event.getNativeEvent().getClientY() - startY;
- setPopupPosition(startLeft + dx, startTop + dy);
+ if (sizing) {
+ int minWidth = tabs.getOffsetWidth()
+ + controls.getOffsetWidth();
+
+ if (resizeLeft) {
+ int w = startW - dx;
+ if (w < minWidth) {
+ w = minWidth;
+ dx = startW - minWidth;
+ }
+ content.setWidth(w + "px");
+ setPopupPosition(startLeft + dx, getPopupTop());
+
+ } else if (resizeRight) {
+ int w = startW + dx;
+ if (w < minWidth) {
+ w = minWidth;
+ }
+ content.setWidth(w + "px");
+ }
+ if (resizeUp) {
+ int h = startH - dy;
+ if (h < MIN_HEIGHT) {
+ h = MIN_HEIGHT;
+ dy = startH - MIN_HEIGHT;
+ }
+ content.setHeight(h + "px");
+ setPopupPosition(getPopupLeft(), startTop + dy);
+
+ } else if (resizeDown) {
+ int h = startH + dy;
+ if (h < MIN_HEIGHT) {
+ h = MIN_HEIGHT;
+ }
+ content.setHeight(h + "px");
+
+ }
+
+ } else if (move) {
+ setPopupPosition(startLeft + dx, startTop + dy);
+ }
event.cancel();
} else if (event.getTypeInt() == Event.ONMOUSEUP) {
} else if (stop) {
stop = false;
- handler.removeHandler();
- handler = null;
+ dragHandler.removeHandler();
+ dragHandler = null;
+ sizing = false;
+ move = false;
+
+ // restore scrollbars
+ content.getElement().getStyle().setOverflow(Overflow.AUTO);
+
+ updateCursor();
+ applyBounds();
readPositionAndSize();
writeStoredState();
+
+ event.cancel();
}
+
}
private boolean hasMoved(NativeEvent event) {
|| Math.abs(startY - event.getClientY()) > MOVE_TRESHOLD;
}
- @Override
- public void onMouseDown(MouseDownEvent event) {
- if (handler == null) {
- handler = Event.addNativePreviewHandler(MoveHandler.this);
- }
- startX = event.getClientX();
- startY = event.getClientY();
- startLeft = getPopupLeft();
- startTop = getPopupTop();
- stop = false;
- event.preventDefault();
- }
-
- }
-
- /**
- * Handler for resizing window.
- *
- * @since 7.1
- * @author Vaadin Ltd
- */
- protected class ResizeHandler implements MouseDownHandler,
- MouseMoveHandler, NativePreviewHandler {
-
- boolean resizeLeft;
- boolean resizeRight;
- boolean resizeUp;
- boolean resizeDown;
-
- boolean sizing;
-
- HandlerRegistration dragHandler;
-
- int startX;
- int startY;
- int startW;
- int startH;
- int startTop;
- int startLeft;
-
- @Override
- public void onMouseDown(MouseDownEvent event) {
- sizing = updateResizeFlags(event);
-
- if (sizing) {
- startX = event.getClientX();
- startY = event.getClientY();
-
- startW = content.getOffsetWidth();
- startH = content.getOffsetHeight();
-
- startTop = getPopupTop();
- startLeft = getPopupLeft();
-
- dragHandler = Event.addNativePreviewHandler(this);
-
- event.preventDefault();
- }
-
- }
-
- @Override
- public void onMouseMove(MouseMoveEvent event) {
- updateResizeFlags(event);
- updateCursor();
- }
-
private void updateCursor() {
- Element c = content.getElement();
+ Element c = getElement();
if (resizeLeft) {
if (resizeUp) {
c.getStyle().setCursor(Cursor.NW_RESIZE);
c.getStyle().setCursor(Cursor.N_RESIZE);
} else if (resizeDown) {
c.getStyle().setCursor(Cursor.S_RESIZE);
+ } else if (move) {
+ c.getStyle().setCursor(Cursor.MOVE);
} else {
c.getStyle().setCursor(Cursor.AUTO);
}
}
- private boolean updateResizeFlags(MouseEvent event) {
+ protected void updateResizeFlags(MouseEvent event) {
+ if (event.isShiftKeyDown()) {
+ // resize from lower right
+ resizeUp = false;
+ resizeLeft = false;
+ resizeRight = true;
+ resizeDown = true;
+ move = false;
+ sizing = true;
+ return;
+
+ } else if (event.isAltKeyDown()) {
+ // move it
+ move = true;
+ resizeUp = false;
+ resizeLeft = false;
+ resizeRight = false;
+ resizeDown = false;
+ sizing = false;
+ return;
+ }
+
Element c = getElement();
int w = c.getOffsetWidth();
- int h = c.getOffsetHeight() - head.getOffsetHeight();
+ int h = c.getOffsetHeight();
int x = event.getRelativeX(c);
- int y = event.getRelativeY(c) - head.getOffsetHeight();
-
- resizeLeft = x < HANDLE_SIZE;
- resizeRight = x > (w - HANDLE_SIZE);
- resizeUp = y < HANDLE_SIZE;
- resizeDown = y > (h - HANDLE_SIZE);
-
- return resizeLeft || resizeRight || resizeUp || resizeDown;
-
- }
+ int y = event.getRelativeY(c);
- @Override
- public void onPreviewNativeEvent(NativePreviewEvent event) {
- if (event.getTypeInt() == Event.ONMOUSEMOVE) {
-
- int dx = event.getNativeEvent().getClientX() - startX;
- int dy = event.getNativeEvent().getClientY() - startY;
+ resizeLeft = x < HANDLE_SIZE && y > tabs.getOffsetHeight();
+ resizeRight = (x > (w - HANDLE_SIZE) && y > tabs.getOffsetHeight())
+ || (x > (w - 2 * HANDLE_SIZE) && y > (h - 2 * HANDLE_SIZE));
+ resizeUp = y > tabs.getOffsetHeight()
+ && y < tabs.getOffsetHeight() + HANDLE_SIZE;
+ resizeDown = y > (h - HANDLE_SIZE)
+ || (x > (w - 2 * HANDLE_SIZE) && y > (h - 2 * HANDLE_SIZE));
- int minw = tabs.getOffsetWidth() + controls.getOffsetWidth();
- if (resizeLeft) {
- int w = startW - dx;
- if (w >= minw) {
- content.setWidth(w + "px");
- setPopupPosition(startLeft + dx, getPopupTop());
- }
- } else if (resizeRight) {
- int w = startW + dx;
- if (w >= minw) {
- content.setWidth(w + "px");
- }
- }
- if (resizeUp) {
- int h = startH - dy;
- if (h >= MIN_HEIGHT) {
- content.setHeight(h + "px");
- setPopupPosition(getPopupLeft(), startTop + dy);
- }
- } else if (resizeDown) {
- int h = startH + dy;
- if (h >= MIN_HEIGHT) {
- content.setHeight(h + "px");
- }
- }
+ move = !resizeDown && !resizeLeft && !resizeRight && !resizeUp
+ && y < head.getOffsetHeight();
- } else if (event.getTypeInt() == Event.ONMOUSEUP) {
- dragHandler.removeHandler();
- dragHandler = null;
- content.getElement().getStyle().setCursor(Cursor.AUTO);
- sizing = false;
- readPositionAndSize();
- writeStoredState();
- }
+ sizing = resizeLeft || resizeRight || resizeUp || resizeDown;
- event.cancel();
}
}