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

Source Code of com.google.speedtracer.client.visualizations.view.EventWaterfallRow$UiEventTitleCell

/*
* 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.coreext.client.JSOArray;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.graphics.client.Color;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.topspin.ui.client.Container;
import com.google.gwt.topspin.ui.client.DefaultContainerImpl;
import com.google.speedtracer.client.model.AggregateTimeVisitor;
import com.google.speedtracer.client.model.HintRecord;
import com.google.speedtracer.client.model.LogMessageVisitor;
import com.google.speedtracer.client.model.UiEvent;
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.visualizations.model.SluggishnessModel;
import com.google.speedtracer.client.visualizations.model.SluggishnessVisualization;
import com.google.speedtracer.client.visualizations.view.FilteringScrollTable.Cell;
import com.google.speedtracer.client.visualizations.view.FilteringScrollTable.TableRow;

/**
* A row in the table that contains a waterfall bar and summary data about a
* UiEvent.
*
* TODO (jaimeyap): Re-examine the class hierarchy with FilteringScrollTable and
* its associated Row classes to see if there is a simplifying refactor.
*/
public class EventWaterfallRow extends TableRow {
  /**
   * Styles.
   */
  public interface Css extends CssResource {
    double calloutPadding();

    String colorBox();

    String durationCallout();

    String eventBar();

    String iconContainer();

    String logMessageAnnotation();
  }

  /**
   * Externalized Resources.
   */
  public interface Resources extends HintletIndicator.Resources,
      EventTraceBreakdown.Resources, EventWaterfallRowDetails.Resources {
    @Source("resources/EventWaterfallRow.css")
    Css eventWaterfallRowCss();
  }

  /**
   * Cell that contains the pillbox graph for the UiEvent. It is essentially the
   * waterfall component for the row.
   *
   * Normal Cells have only String contents. This cell needs to be able to
   * lazily grab an Element to display.
   */
  public class UiEventPillboxCell extends Cell {
    private DivElement durationCallout;

    public UiEventPillboxCell() {
      eventWaterfall.super("", -1);
    }

    @Override
    protected Element createElement() {
      Element elem = super.createElement();
      elem.appendChild(eventBreakdown.getRenderedCanvasElement());
      sizeEventBar(elem);
      return elem;
    }

    private void sizeEventBar(Element elem) {
      SluggishnessVisualization visualization = eventWaterfall.getVisualization();
      int cellWidth = visualization.getTimeline().getCurrentGraphWidth();
      SluggishnessModel model = visualization.getModel();
      double totalDuration = model.getCurrentRight() - model.getCurrentLeft();

      assert totalDuration > 0 : "Attempted to render row with 0 duration window";

      double duration = getEvent().getDuration();
      double domainToPixels = (cellWidth / totalDuration);

      double barPixelWidth = Math.max(duration * domainToPixels, 1);
      double barOffset = (getEvent().getTime() - model.getCurrentLeft())
          * domainToPixels;

      EventWaterfallRow.Css css = resources.eventWaterfallRowCss();
      final Element graphElem = eventBreakdown.getRenderedCanvasElement();
      final Style graphStyle = graphElem.getStyle();
      graphElem.setClassName(css.eventBar());
      graphStyle.setWidth(barPixelWidth, Unit.PX);
      graphStyle.setLeft(barOffset, Unit.PX);

      if (durationCallout == null) {
        durationCallout = elem.getOwnerDocument().createDivElement();
        durationCallout.setClassName(css.durationCallout());
        durationCallout.setInnerText(TimeStampFormatter.format(duration));
        elem.appendChild(durationCallout);
      }

      double calloutOffset = barOffset + barPixelWidth + css.calloutPadding();
      // TODO (jaimeyap): Position callout to the left of the bar if it hangs
      // off the right. Only issue is that nothing is attached to the DOM yet so
      // measuring the offsetWidth of the callout is not currently possible.
      durationCallout.getStyle().setLeft(calloutOffset, Unit.PX);
    }
  }

  /**
   * Cell that displays the name of the UiEvent and an icon if a hintlet is
   * present for this event.
   *
   * The appearance of the hintlet is changes depending on the most severe
   * hintlet record present.
   *
   */
  public class UiEventTitleCell extends Cell {
    private HintletIndicator hintIcon;
    private Container iconContainer;

    public UiEventTitleCell() {
      eventWaterfall.super("", Constants.GRAPH_PIXEL_OFFSET);
      runVisitors();
    }

    public void refresh() {
      if (!isCreated()) {
        return;
      }
      updateIndicator();
    }

    @Override
    protected Element createElement() {
      EventWaterfallRow.Css css = resources.eventWaterfallRowCss();
      // Create the element that backs this Cell.
      Element elem = super.createElement();
      elem.getStyle().setProperty("borderRight", "1px solid #999");
      // Create the Event's color box and the title.
      addTitle(elem);
      // Create a container for the hint and log message icons.
      Element iconElem = elem.getOwnerDocument().createDivElement();
      iconElem.setClassName(css.iconContainer());
      elem.appendChild(iconElem);
      iconContainer = new DefaultContainerImpl(iconElem);
      // Add a hintlet indicator icon if there are hints.
      maybeAddHintIndicator(iconContainer);
      // If there is a log message in this event, show the info bubble.
      maybeAddLogIcon(iconElem);
      return elem;
    }

    private void addTitle(Element elem) {
      String title = UiEvent.typeToDetailedTypeString(event);
      Color color = EventRecordColors.getColorForType(event.getType());
      DivElement colorBox = elem.getOwnerDocument().createDivElement();
      colorBox.setClassName(resources.eventWaterfallRowCss().colorBox());
      colorBox.getStyle().setBackgroundColor(color.toString());
      elem.appendChild(colorBox);
      elem.appendChild(elem.getOwnerDocument().createTextNode(title));
    }

    private void annotateWithLogIcon(Element elem) {
      DivElement infoBubble = DocumentExt.get().createDivWithClassName(
          resources.eventWaterfallRowCss().logMessageAnnotation());
      elem.appendChild(infoBubble);
    }

    private void maybeAddHintIndicator(Container parentContainer) {
      JSOArray<HintRecord> hintletRecords = event.getHintRecords();
      if (hintletRecords != null) {
        hintIcon = new HintletIndicator(parentContainer, hintletRecords,
            resources);
      }
    }

    private void maybeAddLogIcon(Element iconElem) {
      if (event.hasUserLogs()) {
        // Annotate the parent row
        annotateWithLogIcon(iconElem);
      }
    }

    private void runVisitors() {
      AggregateTimeVisitor.apply(event);
      LogMessageVisitor.apply(event);
    }

    private void updateIndicator() {
      if (hintIcon == null) {
        maybeAddHintIndicator(iconContainer);
      } else {
        hintIcon.update(event.getHintRecords());
      }
    }
  }

  private final UiEvent event;

  private final EventTraceBreakdown eventBreakdown;

  private final EventWaterfall eventWaterfall;

  private final UiEventPillboxCell pillBoxCell;

  private final EventWaterfallRow.Resources resources;

  private final UiEventTitleCell titleCell;

  public EventWaterfallRow(EventWaterfall eventWaterfall, UiEvent event,
      EventWaterfallRow.Resources resources) {
    // We subclass a non-static inner class. So it needs an enclosing instance.
    eventWaterfall.super(event.getDuration());
    this.resources = resources;
    this.eventWaterfall = eventWaterfall;
    this.event = event;
    eventBreakdown = new EventTraceBreakdown(event,
        eventWaterfall.getPresenter(), resources);

    // Create cells.
    titleCell = new UiEventTitleCell();
    pillBoxCell = new UiEventPillboxCell();
    addCell(this.titleCell);
    addCell(this.pillBoxCell);
  }

  /**
   * Creates and sets the {@link EventWaterfallRowDetails} as this Row instances
   * RowDetails panel.
   */
  public void createDetails() {
    setDetails(new EventWaterfallRowDetails(eventWaterfall, this, resources));
  }

  public UiEvent getEvent() {
    return this.event;
  }

  public EventTraceBreakdown getEventBreakdown() {
    return eventBreakdown;
  }

  public UiEventTitleCell getTitleCell() {
    return titleCell;
  }

  @Override
  public void onResize() {
    pillBoxCell.sizeEventBar(pillBoxCell.getElement());
  }
}
TOP

Related Classes of com.google.speedtracer.client.visualizations.view.EventWaterfallRow$UiEventTitleCell

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.