private void beginDrag(Event evt) { String docId = initDragParams_.getDocId(); int dragTabWidth = initDragWidth_; // set drag element state dragTabsHost_ = getTabBarElement(); dragScrollHost_ = dragTabsHost_.getParentElement(); outOfBounds_ = 0; candidatePos_ = null; startPos_ = null; // attempt to determine which tab the cursor is over Point hostPos = DomUtils.getRelativePosition(Document.get().getBody(), dragTabsHost_); int dragX = evt.getClientX() - hostPos.getX(); for (int i = 0; i < dragTabsHost_.getChildCount(); i++) { Node node = dragTabsHost_.getChild(i); if (node.getNodeType() == Node.ELEMENT_NODE) { int left = DomUtils.leftRelativeTo(dragTabsHost_, Element.as(node)) - dragScrollHost_.getScrollLeft(); int right = left + Element.as(node).getOffsetWidth(); if (left <= dragX && dragX <= right) { candidatePos_ = i; break; } } } // let the rest of the IDE know we're dragging (this will enable us to // disable drag targets that might otherwise be happy to accept the // data) curState_ = STATE_DRAGGING; events_.fireEvent( new DocTabDragStateChangedEvent(DocTabDragStateChangedEvent.STATE_DRAGGING)); // the relative position of the last node determines how far we // can drag dragMax_ = DomUtils.leftRelativeTo(dragTabsHost_, getLastChildElement(dragTabsHost_)) + getLastChildElement(dragTabsHost_).getClientWidth(); lastCursorX_ = evt.getClientX(); // account for cursor starting out of bounds (e.g. dragging into // empty space on the right of the panel) if (lastCursorX_ > dragMax_ + (initDragParams_.getCursorOffset())) outOfBounds_ = (lastCursorX_ - dragMax_) - initDragParams_.getCursorOffset(); // attempt to ascertain whether the element being dragged is one of // our own documents for (DocTab tab : docTabs_) { if (tab.getDocId() == docId) { dragElement_ = tab.getElement().getParentElement().getParentElement(); break; } } // if we couldn't find the horizontal drag position in any tab, append // to the end if (candidatePos_ == null) { candidatePos_ = dragTabsHost_.getChildCount(); } destPos_ = candidatePos_; // if we're dragging one of our own documents, figure out its physical // position if (dragElement_ != null) { for (int i = 0; i < dragTabsHost_.getChildCount(); i++) { if (dragTabsHost_.getChild(i) == dragElement_) { startPos_ = i; break; } } } // compute the start location for the drag if (candidatePos_ >= dragTabsHost_.getChildCount()) { Element lastTab = getLastChildElement(dragTabsHost_); lastElementX_ = DomUtils.leftRelativeTo(dragTabsHost_, lastTab) + lastTab.getOffsetWidth(); } else { lastElementX_ = DomUtils.leftRelativeTo( dragTabsHost_, Element.as(dragTabsHost_.getChild(candidatePos_))); } // if we're dragging one of our own tabs, snap it out of the // tabset if (dragElement_ != null) { dragElement_.getStyle().setPosition(Position.ABSOLUTE); dragElement_.getStyle().setLeft(lastElementX_, Unit.PX); dragElement_.getStyle().setZIndex(100); Scheduler.get() .scheduleDeferred( new ScheduledCommand() { @Override public void execute() { dragElement_.getStyle().setDisplay(Display.NONE); } }); } // create the placeholder that shows where this tab will go when the // mouse is released dragPlaceholder_ = Document.get().createDivElement(); dragPlaceholder_.getStyle().setWidth(dragTabWidth - 4, Unit.PX); dragPlaceholder_.getStyle().setHeight(dragTabsHost_.getClientHeight() - 3, Unit.PX); dragPlaceholder_.getStyle().setDisplay(Display.INLINE_BLOCK); dragPlaceholder_.getStyle().setPosition(Position.RELATIVE); dragPlaceholder_.getStyle().setFloat(Float.LEFT); dragPlaceholder_.getStyle().setBorderStyle(BorderStyle.DOTTED); dragPlaceholder_.getStyle().setBorderColor("#A1A2A3"); dragPlaceholder_.getStyle().setBorderWidth(1, Unit.PX); dragPlaceholder_.getStyle().setMarginLeft(1, Unit.PX); dragPlaceholder_.getStyle().setMarginRight(1, Unit.PX); dragPlaceholder_.getStyle().setProperty("borderTopLeftRadius", "4px"); dragPlaceholder_.getStyle().setProperty("borderTopRightRadius", "4px"); dragPlaceholder_.getStyle().setProperty("borderBottom", "0px"); if (candidatePos_ < dragTabsHost_.getChildCount()) { dragTabsHost_.insertBefore(dragPlaceholder_, dragTabsHost_.getChild(candidatePos_)); } else { dragTabsHost_.appendChild(dragPlaceholder_); } }
public void ensureSelectedTabIsVisible(boolean animate) { if (currentAnimation_ != null) { currentAnimation_.cancel(); currentAnimation_ = null; } Element selectedTab = (Element) DomUtils.findNode( getElement(), true, false, new NodePredicate() { public boolean test(Node n) { if (n.getNodeType() != Node.ELEMENT_NODE) return false; return ((Element) n).getClassName().contains("gwt-TabLayoutPanelTab-selected"); } }); if (selectedTab == null) { return; } selectedTab = selectedTab.getFirstChildElement().getFirstChildElement(); Element tabBar = getTabBarElement(); if (!isVisible() || !isAttached() || tabBar.getOffsetWidth() == 0) return; // not yet loaded final Element tabBarParent = tabBar.getParentElement(); final int start = tabBarParent.getScrollLeft(); int end = DomUtils.ensureVisibleHoriz( tabBarParent, selectedTab, padding_, padding_ + rightMargin_, true); // When tabs are closed, the overall width shrinks, and this can lead // to cases where there's too much empty space on the screen Node lastTab = getLastChildElement(tabBar); if (lastTab == null || lastTab.getNodeType() != Node.ELEMENT_NODE) return; int edge = DomUtils.getRelativePosition(tabBarParent, Element.as(lastTab)).x + Element.as(lastTab).getOffsetWidth(); end = Math.min(end, Math.max(0, edge - (tabBarParent.getOffsetWidth() - rightMargin_))); if (edge <= tabBarParent.getOffsetWidth() - rightMargin_) end = 0; if (start != end) { if (!animate) { tabBarParent.setScrollLeft(end); } else { final int finalEnd = end; currentAnimation_ = new Animation() { @Override protected void onUpdate(double progress) { double delta = (finalEnd - start) * progress; tabBarParent.setScrollLeft((int) (start + delta)); } @Override protected void onComplete() { if (this == currentAnimation_) { tabBarParent.setScrollLeft(finalEnd); currentAnimation_ = null; } } }; currentAnimation_.run(Math.max(200, Math.min(1500, Math.abs(end - start) * 2))); } } }