Package com.google.speedtracer.client.visualizations.view

Source Code of com.google.speedtracer.client.visualizations.view.NetworkPillBox$Resources

/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.speedtracer.client.visualizations.view;

import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.SpanElement;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.events.client.EventListenerRemover;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.topspin.ui.client.ClickEvent;
import com.google.gwt.topspin.ui.client.ClickListener;
import com.google.gwt.topspin.ui.client.DefaultContainerImpl;
import com.google.gwt.topspin.ui.client.Div;
import com.google.gwt.topspin.ui.client.MouseOutEvent;
import com.google.gwt.topspin.ui.client.MouseOutListener;
import com.google.gwt.topspin.ui.client.MouseOverEvent;
import com.google.gwt.topspin.ui.client.MouseOverListener;
import com.google.gwt.topspin.ui.client.Window;
import com.google.speedtracer.client.ServerEventController;
import com.google.speedtracer.client.model.NetworkResource;
import com.google.speedtracer.client.timeline.Constants;
import com.google.speedtracer.client.util.TimeStampFormatter;
import com.google.speedtracer.client.util.dom.DocumentExt;
import com.google.speedtracer.client.util.dom.EventListenerOwner;
import com.google.speedtracer.client.util.dom.LazilyCreateableElement;
import com.google.speedtracer.client.util.dom.OwnsEventListeners;

/**
* The portion of a ResourceRow corresponding to the pillbox aligned on the
* TimeLine.
*/
public class NetworkPillBox extends Div implements OwnsEventListeners {
  /**
   * CSS.
   */
  public interface Css extends CssResource {

    String calloutLeft();

    int calloutOffset();

    String calloutRight();

    int pillBoxHeight();

    String pillBoxLeft();

    String pillBoxLeftFail();

    String pillBoxLeftRedirect();

    String pillBoxRight();

    String pillBoxRightFail();

    String pillBoxRightRedirect();

    String pillBoxTimeLine();

    String pillBoxWrapper();

    String selected();

    String timeOverlay();

    int timeOverlayPadding();
  }

  /**
   * Externalized interface.
   */
  public interface Resources extends RequestDetails.Resources,
      HintletRecordsTree.Resources {
    @Source("resources/graphLabelCalloutLeft.png")
    ImageResource leftCallout();

    @Source("resources/NetworkPillBox.css")
    NetworkPillBox.Css networkPillBoxCss();

    @Source("resources/graphLabelCalloutRight.png")
    ImageResource rightCallout();
  }

  /**
   * The left time overlay.
   */
  private class LeftOverlay extends TimeOverlay {
    protected LeftOverlay(Element parent) {
      super(parent);
    }

    public void moveAbove() {
      int leftShift = Constants.GRAPH_PIXEL_OFFSET
          - getParentElem().getAbsoluteLeft();
      getIconElem().getStyle().setProperty("display", "none");
      getElement().getStyle().setPropertyPx("top",
          -resources.networkPillBoxCss().timeOverlayPadding());
      getElement().getStyle().setPropertyPx("marginLeft", leftShift);
    }

    @Override
    public void moveOut() {
      getIconElem().getStyle().setProperty("display", "");
      int leftShift = (overHang - getWidth())
          + resources.networkPillBoxCss().calloutOffset();
      getElement().getStyle().setPropertyPx("marginLeft", leftShift);
    }

    @Override
    protected Element createElement() {
      Element elem = super.createElement();
      Element iconElem = getIconElem();
      iconElem.setClassName(resources.networkPillBoxCss().calloutLeft());
      elem.appendChild(getIconElem());

      return elem;
    }
  }

  /**
   * The right time overlay.
   */
  private class RightOverlay extends TimeOverlay {
    protected RightOverlay(Element parent) {
      super(parent);
    }

    @Override
    public void moveOut() {
      getIconElem().getStyle().setProperty("display", "");
      int leftShift = getParentWidth()
          - (overHang + resources.networkPillBoxCss().calloutOffset());
      getElement().getStyle().setPropertyPx("marginLeft", leftShift);
    }

    @Override
    protected Element createElement() {
      Element elem = super.createElement();
      Element iconElem = getIconElem();
      iconElem.setClassName(resources.networkPillBoxCss().calloutRight());
      elem.appendChild(getIconElem());
      elem.insertBefore(getIconElem(), elem.getFirstChild());

      return elem;
    }
  }

  /**
   * The time overlay that gets shown for one of the sides of the pillbox when
   * hovering over it.
   */
  private abstract class TimeOverlay extends LazilyCreateableElement {
    protected static final int overHang = 4;

    private SpanElement iconElem;

    private final Element parent;

    private Element timeTextElem;

    protected TimeOverlay(Element parent) {
      super(listenerOwner, resources.networkPillBoxCss().timeOverlay());
      this.parent = parent;
    }

    public boolean fitsInParent() {
      return (getWidth() <= getParentWidth());
    }

    public SpanElement getIconElem() {
      ensureIconElem();
      return iconElem;
    }

    public Element getParentElem() {
      return parent;
    }

    public int getParentWidth() {
      return parent.getOffsetWidth();
    }

    public int getWidth() {
      return getElement().getOffsetWidth();
    }

    public void moveIn() {
      int myWidth = getWidth();
      int leftShift = (getParentWidth() - myWidth) / 2;
      getIconElem().getStyle().setProperty("display", "none");
      getElement().getStyle().setPropertyPx("marginLeft", leftShift);
    }

    public abstract void moveOut();

    @Override
    protected Element createElement() {
      Element elem = DocumentExt.get().createDivWithClassName(getClassName());
      parent.appendChild(elem);
      return elem;
    }

    protected void ensureIconElem() {
      if (iconElem == null) {
        iconElem = DocumentExt.get().createSpanElement();
      }
    }

    protected void setTime(double time) {
      ensureTimeTextElem();
      timeTextElem.setInnerText(TimeStampFormatter.formatMilliseconds(time));
    }

    private void ensureTimeTextElem() {
      if (timeTextElem == null) {
        timeTextElem = getElement().getOwnerDocument().createElement("b");
        getElement().appendChild(timeTextElem);
      }
    }
  }

  /**
   * Manages the left and right time overlays.
   */
  private class TimeOverlayController {
    private final LeftOverlay leftOverlay;

    private final RightOverlay rightOverlay;

    public TimeOverlayController(Element leftPb, Element rightPb,
        NetworkResource networkResource) {
      leftOverlay = new LeftOverlay(leftPb);
      rightOverlay = new RightOverlay(rightPb);
    }

    public void hide() {
      leftOverlay.getElement().getStyle().setProperty("opacity", "0");
      rightOverlay.getElement().getStyle().setProperty("opacity", "0");
    }

    public void show() {
      double[] resourceTimes = capResourceTimes(networkResource);
      double leftTime = resourceTimes[MIDDLE] - resourceTimes[START];
      double rightTime = resourceTimes[END] - resourceTimes[MIDDLE];
      leftOverlay.setTime(leftTime);
      rightOverlay.setTime(rightTime);

      if (!leftOverlay.fitsInParent()) {
        leftOverlay.moveOut();
      } else {
        leftOverlay.moveIn();
      }

      if (!rightOverlay.fitsInParent()) {
        rightOverlay.moveOut();
      } else {
        rightOverlay.moveIn();
      }

      // Now figure out if our left overlay even fits on the screen. For now we
      // let the right overlay hang off since you most likely will have room to
      // zoom out. And it still wouldnt solve the "appearance of scrollbars"
      // issue.
      if (hangsOffLeftSide(leftOverlay)) {
        leftOverlay.moveAbove();
      }

      leftOverlay.getElement().getStyle().setProperty("opacity", "1");
      rightOverlay.getElement().getStyle().setProperty("opacity", "1");
    }

    private boolean hangsOffLeftSide(TimeOverlay overlay) {
      return (overlay.getElement().getAbsoluteLeft() < Constants.GRAPH_PIXEL_OFFSET);
    }
  }

  private static final int END = 2;

  private static final int MIDDLE = 1;

  private static final int START = 0;

  private RequestDetails details;

  private final double domainLeft;

  private final double domainRight;

  private final EventListenerOwner listenerOwner = new EventListenerOwner();

  private final NetworkResource networkResource;

  private int lastPanelWidth = 0;

  private final Element parentRowElement;

  private Element pbLeft;

  private Element pbRight;

  private final DivElement pillBoxContainer;

  private final NetworkPillBox.Resources resources;

  private final ServerEventController serverEventController;

  public NetworkPillBox(Element parentRowElement,
      NetworkResource networkResource, double windowDomainLeft,
      double windowDomainRight, Resources resources,
      ServerEventController serverEventController) {
    super(new DefaultContainerImpl(parentRowElement));
    this.parentRowElement = parentRowElement;
    this.networkResource = networkResource;
    this.resources = resources;
    this.domainLeft = windowDomainLeft;
    this.domainRight = windowDomainRight;
    this.serverEventController = serverEventController;

    Element elem = getElement();
    elem.setClassName(resources.networkPillBoxCss().pillBoxTimeLine());
    elem.getStyle().setMarginLeft(Constants.GRAPH_PIXEL_OFFSET, Unit.PX);

    NetworkPillBox.Css css = resources.networkPillBoxCss();
    this.pillBoxContainer = elem.getOwnerDocument().createDivElement();
    this.pillBoxContainer.setClassName(css.pillBoxWrapper());
    elem.appendChild(this.pillBoxContainer);

    createPillBox(css);
  }

  public void manageEventListener(EventListenerRemover remover) {
    listenerOwner.manageEventListener(remover);
  }

  public void onResize(int panelWidth) {
    sizePillBox(panelWidth);
  }

  public void refresh() {
    if (details != null) {
      details.refresh();
    }

    stylePillBox();
    sizePillBox();
  }

  public void removeAllEventListeners() {
    listenerOwner.removeAllEventListeners();
  }

  /**
   * NetworkResources may have NaN times for responses and ends. This method
   * simply returns reasonable a start, middle, and end. Resonable is defined as
   * "if it is NaN extend to the right edge of the screen".
   */
  private double[] capResourceTimes(NetworkResource networkResource) {
    double start = networkResource.getStartTime();
    double middle = networkResource.getResponseReceivedTime();
    double end = networkResource.getEndTime();

    double cappedMiddle = middle;
    double cappedEnd = end;

    // We cap the middle and end to be at the right side of the screen if they
    // are not yet set
    if (Double.isNaN(end)) {
      cappedEnd = domainRight;
    }

    if (Double.isNaN(middle)) {
      cappedMiddle = cappedEnd;
    }

    double[] rtn = new double[3];
    rtn[0] = start;
    rtn[1] = cappedMiddle;
    rtn[2] = cappedEnd;
    return rtn;
  }

  private void stylePillBox() {
    NetworkPillBox.Css css = resources.networkPillBoxCss();

    if (networkResource.didFail()) {
      pbLeft.setClassName(css.pillBoxLeftFail());
      pbRight.setClassName(css.pillBoxRightFail());
    } else if (networkResource.isRedirect()) {
      pbLeft.setClassName(css.pillBoxLeftRedirect());
      pbRight.setClassName(css.pillBoxRightRedirect());
    } else {
      pbLeft.setClassName(css.pillBoxLeft());
      pbRight.setClassName(css.pillBoxRight());
    }
  }

  private void createPillBox(NetworkPillBox.Css css) {
    pbLeft = DocumentExt.get().createDivElement();
    pbRight = DocumentExt.get().createDivElement();

    pillBoxContainer.appendChild(pbLeft);
    pillBoxContainer.appendChild(pbRight);

    // Create the RequestDetails for this resource. The DOM should be lazily
    // created.
    details = new RequestDetails(getElement(), networkResource, listenerOwner,
        resources, serverEventController);

    // Add the ClickListener to toggle the visibility
    manageEventListener(ClickEvent.addClickListener(parentRowElement,
        parentRowElement, new ClickListener() {
          public void onClick(ClickEvent event) {
            details.toggleVisibility();
          }
        }));

    // Setup the overlay hover
    final TimeOverlayController timeOverlayController = new TimeOverlayController(
        pbLeft, pbRight, networkResource);

    manageEventListener(MouseOverEvent.addMouseOverListener(pillBoxContainer,
        parentRowElement, new MouseOverListener() {
          public void onMouseOver(MouseOverEvent event) {
            timeOverlayController.show();
          }
        }));

    manageEventListener(MouseOutEvent.addMouseOutListener(pillBoxContainer,
        parentRowElement, new MouseOutListener() {
          public void onMouseOut(MouseOutEvent event) {
            timeOverlayController.hide();
          }
        }));

    lastPanelWidth = Window.getInnerWidth() - Constants.GRAPH_HEADER_WIDTH;
    refresh();
  }

  private void sizePillBox() {
    sizePillBox(lastPanelWidth);
  }

  private void sizePillBox(int panelWidth) {
    double domainWidth = domainRight - domainLeft;
    double domainToPixels = (double) panelWidth / domainWidth;

    double[] resourceTimes = capResourceTimes(networkResource);
    double start = resourceTimes[START];
    double middle = resourceTimes[MIDDLE];
    double end = resourceTimes[END];

    this.lastPanelWidth = panelWidth;

    int leftOffset = (int) ((start - domainLeft) * domainToPixels);
    pillBoxContainer.getStyle().setPropertyPx("left", leftOffset);

    double leftTime = middle - start;
    double rightTime = end - middle;
    int leftWidth = (int) (leftTime * domainToPixels);
    int rightWidth = (int) (rightTime * domainToPixels);
    leftWidth = Math.max(leftWidth, 2);
    rightWidth = Math.max(rightWidth, 2);

    pbLeft.getStyle().setPropertyPx("width", leftWidth);
    pbRight.getStyle().setPropertyPx("width", rightWidth);
    pbRight.getStyle().setPropertyPx("left", leftWidth);
    pillBoxContainer.getStyle().setPropertyPx("width", leftWidth + rightWidth);
  }
}
TOP

Related Classes of com.google.speedtracer.client.visualizations.view.NetworkPillBox$Resources

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.