/**
   * Animate opening a tab in the foreground.
   *
   * @param id The id of the new tab to animate.
   * @param sourceId The id of the tab that spawned this new tab.
   * @param newIsIncognito true if the new tab is an incognito tab.
   * @param originX The X coordinate of the last touch down event that spawned this tab.
   * @param originY The Y coordinate of the last touch down event that spawned this tab.
   */
  private void tabCreatedInForeground(
      int id, int sourceId, boolean newIsIncognito, float originX, float originY) {
    LayoutTab newLayoutTab = createLayoutTab(id, newIsIncognito, NO_CLOSE_BUTTON, NO_TITLE);
    if (mLayoutTabs == null || mLayoutTabs.length == 0) {
      mLayoutTabs = new LayoutTab[] {newLayoutTab};
    } else {
      mLayoutTabs = new LayoutTab[] {mLayoutTabs[0], newLayoutTab};
    }
    updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id, sourceId)));

    newLayoutTab.setBorderAlpha(0.0f);
    newLayoutTab.setStaticToViewBlend(1.f);

    forceAnimationToFinish();

    Interpolator interpolator = BakedBezierInterpolator.TRANSFORM_CURVE;
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.SCALE,
        0.f,
        1.f,
        FOREGROUND_ANIMATION_DURATION,
        0,
        false,
        interpolator);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.ALPHA,
        0.f,
        1.f,
        FOREGROUND_ANIMATION_DURATION,
        0,
        false,
        interpolator);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.X,
        originX,
        0.f,
        FOREGROUND_ANIMATION_DURATION,
        0,
        false,
        interpolator);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.Y,
        originY,
        0.f,
        FOREGROUND_ANIMATION_DURATION,
        0,
        false,
        interpolator);

    mTabModelSelector.selectModel(newIsIncognito);
    startHiding(id, false);
  }
  @Override
  protected void updateLayout(long time, long dt) {
    super.updateLayout(time, dt);
    if (mBaseTab == null) return;

    mBaseTab.setY(mSearchPanel.getBasePageY());
    mBaseTab.setBrightness(mSearchPanel.getBasePageBrightness());

    boolean needUpdate = mBaseTab.updateSnap(dt);
    if (needUpdate) requestUpdate();
  }
  private void ensureSourceTabCreated(int sourceTabId) {
    if (mLayoutTabs != null && mLayoutTabs.length == 1 && mLayoutTabs[0].getId() == sourceTabId) {
      return;
    }
    // Just draw the source tab on the screen.
    TabModel sourceModel = mTabModelSelector.getModelForTabId(sourceTabId);
    if (sourceModel == null) return;
    LayoutTab sourceLayoutTab =
        createLayoutTab(sourceTabId, sourceModel.isIncognito(), NO_CLOSE_BUTTON, NO_TITLE);
    sourceLayoutTab.setBorderAlpha(0.0f);

    mLayoutTabs = new LayoutTab[] {sourceLayoutTab};
    updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(sourceTabId)));
  }
 @Override
 protected void hideContextualSearch(boolean immediately) {
   if (isActive() && mBaseTab != null) {
     startHiding(mBaseTab.getId(), false);
     if (immediately) doneHiding();
   }
 }
  /**
   * Creates the Base Page's LayoutTab to be presented in the screen.
   *
   * @param layoutTab The {@link Layout} instance.
   */
  private void createBaseLayoutTab(LayoutTab layoutTab) {
    if (mTabModelSelector == null) return;

    int baseTabId = mTabModelSelector.getCurrentTabId();
    if (baseTabId == Tab.INVALID_TAB_ID) return;

    mBaseTab =
        createLayoutTab(
            baseTabId, mTabModelSelector.isIncognitoSelected(), NO_CLOSE_BUTTON, NO_TITLE);

    assert mBaseTab != null;
    mBaseTab.setScale(1.f);
    mBaseTab.setBorderScale(1.f);
    mBaseTab.setBorderAlpha(0.f);

    mLayoutTabs = new LayoutTab[] {mBaseTab};
  }
  @Override
  protected void updateSceneLayer(
      Rect viewport,
      Rect contentViewport,
      LayerTitleCache layerTitleCache,
      TabContentManager tabContentManager,
      ResourceManager resourceManager,
      ChromeFullscreenManager fullscreenManager) {
    super.updateSceneLayer(
        viewport,
        contentViewport,
        layerTitleCache,
        tabContentManager,
        resourceManager,
        fullscreenManager);
    assert mSceneLayer != null;

    final LayoutTab[] tabs = getLayoutTabsToRender();
    if (tabs == null || tabs.length != 1 || tabs[0].getId() == Tab.INVALID_TAB_ID) {
      return;
    }
    LayoutTab layoutTab = tabs[0];
    final float dpToPx = getContext().getResources().getDisplayMetrics().density;

    mReaderModeSceneLayer.update(mReaderModePanel, resourceManager);

    mSceneLayer.update(
        dpToPx, contentViewport, layerTitleCache, tabContentManager, fullscreenManager, layoutTab);

    // TODO(pedrosimonetti): Coordinate w/ dtrainor@ to improve integration with TreeProvider.
    SceneLayer overlayLayer = null;
    if (mSearchPanel.isShowing()) {
      overlayLayer = super.getSceneLayer();
    } else if (mReaderModePanel != null && mReaderModePanel.isShowing()) {
      overlayLayer = mReaderModeSceneLayer;
    }
    mSceneLayer.setContentSceneLayer(overlayLayer);

    // TODO(dtrainor): Find the best way to properly track this metric for cold starts.
    // We should probably erase the thumbnail when we select a tab that we need to restore.
    if (tabContentManager != null && tabContentManager.hasFullCachedThumbnail(layoutTab.getId())) {
      TabModelBase.logPerceivedTabSwitchLatencyMetric();
    }
  }
 @Override
 public boolean handlesTabCreating() {
   // Prevents the new Tab animation from happening when promoting to a new Tab.
   startHiding(mBaseTab.getId(), false);
   doneHiding();
   // Updates TopControls' State so the Toolbar becomes visible.
   // TODO(pedrosimonetti): The transition when promoting to a new tab is only smooth
   // if the SearchContentView's vertical scroll position is zero. Otherwise the
   // ContentView will appear to jump in the screen. Coordinate with @dtrainor to solve
   // this problem.
   mSearchPanel.getManagementDelegate().updateTopControlsState(TopControlsState.BOTH, false);
   return true;
 }
  /** Animate the closing of a tab */
  @Override
  public void onTabClosed(long time, int id, int nextId, boolean incognito) {
    super.onTabClosed(time, id, nextId, incognito);

    if (mClosedTab != null) {
      TabModel nextModel = mTabModelSelector.getModelForTabId(nextId);
      if (nextModel != null) {
        LayoutTab nextLayoutTab =
            createLayoutTab(nextId, nextModel.isIncognito(), NO_CLOSE_BUTTON, NO_TITLE);
        nextLayoutTab.setDrawDecoration(false);

        mLayoutTabs = new LayoutTab[] {nextLayoutTab, mClosedTab};
        updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(nextId, mClosedTab.getId())));
      } else {
        mLayoutTabs = new LayoutTab[] {mClosedTab};
      }

      forceAnimationToFinish();
      mAnimatedTab = mClosedTab;
      addToAnimation(
          this,
          Property.DISCARD_AMOUNT,
          0,
          getDiscardRange(),
          TAB_CLOSED_ANIMATION_DURATION,
          0,
          false,
          BakedBezierInterpolator.FADE_OUT_CURVE);

      mClosedTab = null;
      if (nextModel != null) {
        mTabModelSelector.selectModel(nextModel.isIncognito());
      }
    }
    startHiding(nextId, false);
  }
  /**
   * Updates the position, scale, rotation and alpha values of mAnimatedTab.
   *
   * @param discard The value that specify how far along are we in the discard animation. 0 is
   *     filling the screen. Valid values are [-range .. range] where range is computed by {@link
   *     SimpleAnimationLayout#getDiscardRange()}.
   */
  private void setDiscardAmount(float discard) {
    if (mAnimatedTab != null) {
      final float range = getDiscardRange();
      final float scale = Stack.computeDiscardScale(discard, range, true);

      final float deltaX = mAnimatedTab.getOriginalContentWidth();
      final float deltaY = mAnimatedTab.getOriginalContentHeight() / 2.f;
      mAnimatedTab.setX(deltaX * (1.f - scale));
      mAnimatedTab.setY(deltaY * (1.f - scale));
      mAnimatedTab.setScale(scale);
      mAnimatedTab.setBorderScale(scale);
      mAnimatedTab.setAlpha(Stack.computeDiscardAlpha(discard, range));
    }
  }
  /** Set up for the tab closing animation */
  @Override
  public void onTabClosing(long time, int id) {
    reset();

    // Make sure any currently running animations can't influence tab if we are reusing it.
    forceAnimationToFinish();

    // Create the {@link LayoutTab} for the tab before it is destroyed.
    TabModel model = mTabModelSelector.getModelForTabId(id);
    if (model != null) {
      mClosedTab = createLayoutTab(id, model.isIncognito(), NO_CLOSE_BUTTON, NO_TITLE);
      mClosedTab.setBorderAlpha(0.0f);
      mLayoutTabs = new LayoutTab[] {mClosedTab};
      updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id)));
    } else {
      mLayoutTabs = null;
      mClosedTab = null;
    }
    // Only close the id at the end when we are done querying the model.
    super.onTabClosing(time, id);
  }
  /**
   * Animate opening a tab in the background.
   *
   * @param id The id of the new tab to animate.
   * @param sourceId The id of the tab that spawned this new tab.
   * @param newIsIncognito true if the new tab is an incognito tab.
   * @param originX The X screen coordinate in dp of the last touch down event that spawned this
   *     tab.
   * @param originY The Y screen coordinate in dp of the last touch down event that spawned this
   *     tab.
   */
  private void tabCreatedInBackground(
      int id, int sourceId, boolean newIsIncognito, float originX, float originY) {
    LayoutTab newLayoutTab = createLayoutTab(id, newIsIncognito, NO_CLOSE_BUTTON, NEED_TITLE);
    // mLayoutTabs should already have the source tab from tabCreating().
    assert mLayoutTabs.length == 1;
    LayoutTab sourceLayoutTab = mLayoutTabs[0];
    mLayoutTabs = new LayoutTab[] {sourceLayoutTab, newLayoutTab};
    updateCacheVisibleIds(new LinkedList<Integer>(Arrays.asList(id, sourceId)));

    forceAnimationToFinish();

    newLayoutTab.setBorderAlpha(0.0f);
    final float scale = StackAnimation.SCALE_AMOUNT;
    final float margin = Math.min(getWidth(), getHeight()) * (1.0f - scale) / 2.0f;

    // Step 1: zoom out the source tab and bring in the new tab
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.SCALE,
        1.0f,
        scale,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.X,
        0.0f,
        margin,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.Y,
        0.0f,
        margin,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.BORDER_SCALE,
        1.0f / scale,
        1.0f,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.BORDER_ALPHA,
        0.0f,
        1.0f,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.TRANSFORM_CURVE);

    float pauseX = margin;
    float pauseY = margin;
    if (getOrientation() == Orientation.PORTRAIT) {
      pauseY = BACKGROUND_COVER_PCTG * getHeight();
    } else {
      pauseX = BACKGROUND_COVER_PCTG * getWidth();
    }

    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.ALPHA,
        0.0f,
        1.0f,
        BACKGROUND_STEP1_DURATION / 2,
        0,
        false,
        BakedBezierInterpolator.FADE_IN_CURVE);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.SCALE,
        0.f,
        scale,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.FADE_IN_CURVE);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.X,
        originX,
        pauseX,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.FADE_IN_CURVE);
    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.Y,
        originY,
        pauseY,
        BACKGROUND_STEP1_DURATION,
        0,
        false,
        BakedBezierInterpolator.FADE_IN_CURVE);

    // step 2: pause and admire the nice tabs

    // step 3: zoom in the source tab and slide down the new tab
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.SCALE,
        scale,
        1.0f,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.X,
        margin,
        0.0f,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.Y,
        margin,
        0.0f,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.BORDER_SCALE,
        1.0f,
        1.0f / scale,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.TRANSFORM_CURVE);
    addToAnimation(
        sourceLayoutTab,
        LayoutTab.Property.BORDER_ALPHA,
        1.0f,
        0.0f,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.TRANSFORM_CURVE);

    addToAnimation(
        newLayoutTab,
        LayoutTab.Property.ALPHA,
        1.f,
        0.f,
        BACKGROUND_STEP3_DURATION,
        BACKGROUND_STEP3_START,
        true,
        BakedBezierInterpolator.FADE_OUT_CURVE);
    if (getOrientation() == Orientation.PORTRAIT) {
      addToAnimation(
          newLayoutTab,
          LayoutTab.Property.Y,
          pauseY,
          getHeight(),
          BACKGROUND_STEP3_DURATION,
          BACKGROUND_STEP3_START,
          true,
          BakedBezierInterpolator.FADE_OUT_CURVE);
    } else {
      addToAnimation(
          newLayoutTab,
          LayoutTab.Property.X,
          pauseX,
          getWidth(),
          BACKGROUND_STEP3_DURATION,
          BACKGROUND_STEP3_START,
          true,
          BakedBezierInterpolator.FADE_OUT_CURVE);
    }

    mTabModelSelector.selectModel(newIsIncognito);
    startHiding(sourceId, false);
  }
示例#12
0
  /**
   * Pushes all relevant {@link LayoutTab}s from a {@link Layout} to the CC Layer tree. This will
   * let them be rendered on the screen. This should only be called when the Compositor has disabled
   * ScheduleComposite calls as this will change the tree and could subsequently cause unnecessary
   * follow up renders.
   *
   * @param context The {@link Context} to use to query device information.
   * @param layout The {@link Layout} to push to the screen.
   */
  public void pushLayers(
      Context context,
      Rect viewport,
      Rect contentViewport,
      Layout layout,
      LayerTitleCache layerTitleCache,
      TabContentManager tabContentManager,
      ResourceManager resourceManager) {
    if (mNativePtr == 0) return;

    Resources res = context.getResources();
    final float dpToPx = res.getDisplayMetrics().density;

    LayoutTab[] tabs = layout.getLayoutTabsToRender();
    int tabsCount = tabs != null ? tabs.length : 0;

    nativeBeginBuildingFrame(mNativePtr);
    for (int i = 0; i < tabsCount; i++) {
      LayoutTab t = tabs[i];
      assert t.isVisible() : "LayoutTab in that list should be visible";
      final float decoration = t.getDecorationAlpha();

      int borderResource =
          t.isIncognito()
              ? R.drawable.tabswitcher_border_frame_incognito
              : R.drawable.tabswitcher_border_frame;
      int closeBtnResource =
          t.isIncognito() ? R.drawable.btn_tab_close_white_normal : R.drawable.btn_tab_close_normal;
      int borderColorResource = t.isIncognito() ? R.color.tab_back_incognito : R.color.tab_back;
      // TODO(dtrainor, clholgat): remove "* dpToPx" once the native part fully supports dp.
      nativePutLayer(
          mNativePtr,
          t.getId(),
          R.id.control_container,
          closeBtnResource,
          R.drawable.tabswitcher_border_frame_shadow,
          R.drawable.tabswitcher_border_frame_decoration,
          R.drawable.logo_card_back,
          borderResource,
          t.canUseLiveTexture(),
          (t.getFallbackThumbnailId() == ChromeTab.NTP_TAB_ID),
          t.getBackgroundColor(),
          ApiCompatibilityUtils.getColor(res, R.color.tab_switcher_background),
          ApiCompatibilityUtils.getColor(res, borderColorResource),
          t.isIncognito(),
          layout.getOrientation() == Orientation.PORTRAIT,
          t.getRenderX() * dpToPx,
          t.getRenderY() * dpToPx,
          t.getScaledContentWidth() * dpToPx,
          t.getScaledContentHeight() * dpToPx,
          t.getOriginalContentWidth() * dpToPx,
          t.getOriginalContentHeight() * dpToPx,
          contentViewport.height(),
          viewport.left,
          viewport.top,
          viewport.width(),
          viewport.height(),
          t.getClippedX() * dpToPx,
          t.getClippedY() * dpToPx,
          Math.min(t.getClippedWidth(), t.getScaledContentWidth()) * dpToPx,
          Math.min(t.getClippedHeight(), t.getScaledContentHeight()) * dpToPx,
          t.getTiltXPivotOffset() * dpToPx,
          t.getTiltYPivotOffset() * dpToPx,
          t.getTiltX(),
          t.getTiltY(),
          t.getAlpha(),
          t.getBorderAlpha() * decoration,
          decoration,
          t.getShadowOpacity() * decoration,
          t.getBorderCloseButtonAlpha() * decoration,
          LayoutTab.CLOSE_BUTTON_WIDTH_DP * dpToPx,
          t.getStaticToViewBlend(),
          t.getBorderScale(),
          t.getSaturation(),
          t.getBrightness(),
          t.showToolbar(),
          t.anonymizeToolbar(),
          t.getTextBoxBackgroundColor(),
          t.getToolbarAlpha(),
          t.getToolbarYOffset() * dpToPx,
          t.getSideBorderScale(),
          true,
          t.insetBorderVertical(),
          layerTitleCache,
          tabContentManager,
          resourceManager);
    }
    nativeFinishBuildingFrame(mNativePtr);
  }
 @Override
 public float getTopControlsOffset(float currentOffsetDp) {
   return MathUtils.clamp(
       mBaseTab.getY(), -mSearchPanel.getToolbarHeight(), Math.min(currentOffsetDp, 0f));
 }