Dart Documentationdock_spawnDockLayoutEngine

DockLayoutEngine Class

Constructors

Code new DockLayoutEngine(DockManager dockManager) #

DockLayoutEngine(this.dockManager);

Methods

Code void dockDown(DockNode referenceNode, DockNode newNode) #

docks the newNode to the bottom of referenceNode

void dockDown(DockNode referenceNode, DockNode newNode) {
  _performDock(referenceNode, newNode, "vertical", false);
}

Code void dockFill(DockNode referenceNode, DockNode newNode) #

docks the newNode by creating a new tab inside referenceNode

void dockFill(DockNode referenceNode, DockNode newNode) {
  _performDock(referenceNode, newNode, "fill", false);
}

Code void dockLeft(DockNode referenceNode, DockNode newNode) #

docks the newNode to the left of referenceNode

void dockLeft(DockNode referenceNode, DockNode newNode) {
  _performDock(referenceNode, newNode, "horizontal", true);
}

Code void dockRight(DockNode referenceNode, DockNode newNode) #

docks the newNode to the right of referenceNode

void dockRight(DockNode referenceNode, DockNode newNode) {
  _performDock(referenceNode, newNode, "horizontal", false);
}

Code void dockUp(DockNode referenceNode, DockNode newNode) #

docks the newNode to the top of referenceNode

void dockUp(DockNode referenceNode, DockNode newNode) {
  _performDock(referenceNode, newNode, "vertical", true);
}

Code Rectangle getDockBounds(DockNode referenceNode, IDockContainer containerToDock, String direction, bool insertBeforeReference) #

Gets the bounds of the new node if it were to dock with the specified configuration The state is not modified in this function. It is used for showing a preview of where the panel would be docked when hovered over a dock wheel button

Rectangle getDockBounds(DockNode referenceNode, IDockContainer containerToDock, String direction, bool insertBeforeReference) {
  DockNode compositeNode; // The node that contains the splitter / fill node
  int childCount;
  int childPosition;
  if (direction == "fill") {
    // Since this is a fill operation, the highlight bounds is the same as the reference node
    // TODO: Create a tab handle highlight to show that it's going to be docked in a tab
    Element targetElement = referenceNode.container.containerElement;
    Rectangle bounds = new Rectangle();
    bounds.x = targetElement.$dom_offsetLeft;
    bounds.y = targetElement.$dom_offsetTop;
    bounds.width = targetElement.$dom_clientWidth;
    bounds.height= targetElement.$dom_clientHeight;
    return bounds;
  }
  
  if (referenceNode.parent != null && referenceNode.parent.container.containerType == "fill") {
    // Ignore the fill container's child and move one level up
    referenceNode = referenceNode.parent;
  }
  
  // Flag to indicate of the renference node was replaced with a new composite node with 2 children 
  bool hierarchyModified = false;
  if (referenceNode.parent != null && referenceNode.parent.container.containerType == direction) {
    // The parent already is of the desired composite type.  Will be inserted as sibling to the reference node
    compositeNode = referenceNode.parent;
    childCount = compositeNode.children.length;
    childPosition = compositeNode.children.indexOf(referenceNode) + (insertBeforeReference ? 0 : 1);
  } else {
    // The reference node will be replaced with a new composite node of the desired type with 2 children
    compositeNode = referenceNode;
    childCount = 1;   // The newly inserted composite node will contain the reference node
    childPosition = (insertBeforeReference ? 0 : 1);
    hierarchyModified = true;
  }
  
  int splitBarSize = 5;  // TODO: Get from DOM
  num targetPanelSize = 0;
  num targetPanelStart = 0;
  if (direction == "vertical" || direction == "horizontal") {
    // Existing size of the composite container (without the splitter bars).
    // This will also be the final size of the composite (splitter / fill) 
    // container after the new panel has been docked
    int compositeSize = _getVaringDimension(compositeNode.container, direction) - (childCount - 1) * splitBarSize;
    
    // size of the newly added panel
    int newPanelOriginalSize = _getVaringDimension(containerToDock, direction);  
    num scaleMultiplier = compositeSize / (compositeSize + newPanelOriginalSize);
    
    // Size of the panel after it has been docked and scaled
    targetPanelSize = newPanelOriginalSize * scaleMultiplier;
    if (hierarchyModified) {
      targetPanelStart = insertBeforeReference ? 0 : compositeSize * scaleMultiplier;
    }
    else {
      for (int i = 0; i < childPosition; i++) {
        targetPanelStart += _getVaringDimension(compositeNode.children[i].container, direction);
      }
      targetPanelStart *= scaleMultiplier;
    }
  }
  
  Rectangle bounds = new Rectangle();
  if (direction == "vertical") {
    bounds.x = compositeNode.container.containerElement.$dom_offsetLeft;
    bounds.y = compositeNode.container.containerElement.$dom_offsetTop + targetPanelStart;
    bounds.width = compositeNode.container.width; 
    bounds.height = targetPanelSize;
  } else if (direction == "horizontal") {
    bounds.x = compositeNode.container.containerElement.$dom_offsetLeft + targetPanelStart;
    bounds.y = compositeNode.container.containerElement.$dom_offsetTop;
    bounds.width = targetPanelSize; 
    bounds.height = compositeNode.container.height;
  }
  
  return bounds;
}

Code void undock(DockNode node) #

void undock(DockNode node) {
  DockNode parentNode = node.parent;
  if (parentNode == null) {
    throw new DockException("Cannot undock.  panel is not a leaf node");
  }
  
  // Get the position of the node relative to it's siblings
  int siblingIndex = parentNode.children.indexOf(node);
  
  // Detach the node from the dock manager's tree hierarchy
  node.detachFromParent();
  
  // Fix the node's parent hierarchy
  if (parentNode.children.length < parentNode.container.minimumAllowedChildNodes) {
    // If the child count falls below the minimum threshold, destroy the parent and merge 
    // the children with their grandparents
    DockNode grandParent = parentNode.parent;
    parentNode.children.forEach((otherChild) {
      if (grandParent != null) {
        // parent node is not a root node
        grandParent.addChildAfter(parentNode, otherChild);
        parentNode.detachFromParent();
        parentNode.container.destroy();
        grandParent.performLayout();
      }
      else {
        // Parent is a root node.  
        // Make the other child the root node
        parentNode.detachFromParent();
        parentNode.container.destroy();
        dockManager.setRootNode(otherChild);
      }
    });
  }
  else {
    // the node to be removed has 2 or more other siblings. So it is safe to continue 
    // using the parent composite container. 
    parentNode.performLayout();
    
    // Set the next sibling as the active child (e.g. for a Tab host, it would select it as the active tab)
    if (parentNode.children.length > 0) {
      DockNode nextActiveSibling = parentNode.children[Math.max(0, siblingIndex - 1)];
      parentNode.container.setActiveChild(nextActiveSibling.container);
    }
  }
  dockManager.invalidate();
}

Fields

Code DockManager dockManager #

DockManager dockManager;