root/chrome/browser/ui/views/location_bar/location_bar_layout.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. computed_width
  2. item_edit_padding_
  3. AddDecoration
  4. AddDecoration
  5. LayoutPass1
  6. LayoutPass2
  7. LayoutPass3

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/location_bar/location_bar_layout.h"

#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "ui/gfx/rect.h"
#include "ui/views/view.h"


// Description of a decoration to be added inside the location bar, either to
// the left or to the right.
struct LocationBarDecoration {
  LocationBarDecoration(int y,
                        int height,
                        bool auto_collapse,
                        double max_fraction,
                        int edge_item_padding,
                        int item_padding,
                        int builtin_padding,
                        views::View* view);

  // The y position of the view inside its parent.
  int y;

  // The height of the view.
  int height;

  // True means that, if there is not enough available space in the location
  // bar, the view will reduce its width either to its minimal width or to zero
  // (making it invisible), whichever fits. If true, |max_fraction| must be 0.
  bool auto_collapse;

  // Used for resizeable decorations, indicates the maximum fraction of the
  // location bar that can be taken by this decoration, 0 for non-resizable
  // decorations. If non-zero, |auto_collapse| must be false.
  double max_fraction;

  // Padding to use if the decoration is the first element next to the edge.
  int edge_item_padding;

  // Padding to use if the decoration follows another decoration.
  int item_padding;

  // Padding built into the decoration and that should be removed, on
  // both sides, during layout.
  int builtin_padding;

  views::View* view;

  // The width computed by the layout process.
  double computed_width;
};

LocationBarDecoration::LocationBarDecoration(int y,
                                             int height,
                                             bool auto_collapse,
                                             double max_fraction,
                                             int edge_item_padding,
                                             int item_padding,
                                             int builtin_padding,
                                             views::View* view)
    : y(y),
      height(height),
      auto_collapse(auto_collapse),
      max_fraction(max_fraction),
      edge_item_padding(edge_item_padding),
      item_padding(item_padding),
      builtin_padding(builtin_padding),
      view(view),
      computed_width(0) {
  DCHECK((max_fraction == 0.0) || (!auto_collapse && (max_fraction > 0.0)));
}


// LocationBarLayout ---------------------------------------------------------

LocationBarLayout::LocationBarLayout(Position position, int item_edit_padding)
    : position_(position),
      item_edit_padding_(item_edit_padding) {
}


LocationBarLayout::~LocationBarLayout() {
}

void LocationBarLayout::AddDecoration(int y,
                                      int height,
                                      bool auto_collapse,
                                      double max_fraction,
                                      int edge_item_padding,
                                      int item_padding,
                                      int builtin_padding,
                                      views::View* view) {
  decorations_.push_back(new LocationBarDecoration(
      y, height, auto_collapse, max_fraction, edge_item_padding, item_padding,
      builtin_padding, view));
}

void LocationBarLayout::AddDecoration(int y,
                                      int height,
                                      int builtin_padding,
                                      views::View* view) {
  decorations_.push_back(new LocationBarDecoration(
      y, height, false, 0, LocationBarView::GetItemPadding(),
      LocationBarView::GetItemPadding(), builtin_padding, view));
}

void LocationBarLayout::LayoutPass1(int* entry_width) {
  bool first_item = true;
  for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
       ++i) {
    // Autocollapsing decorations are ignored in this pass.
    if (!(*i)->auto_collapse) {
      *entry_width -= -2 * (*i)->builtin_padding +
          (first_item ? (*i)->edge_item_padding : (*i)->item_padding);
    }
    first_item = false;
    // Resizing decorations are ignored in this pass.
    if (!(*i)->auto_collapse && ((*i)->max_fraction == 0.0)) {
      (*i)->computed_width = (*i)->view->GetPreferredSize().width();
      *entry_width -= (*i)->computed_width;
    }
  }
  *entry_width -= item_edit_padding_;
}

void LocationBarLayout::LayoutPass2(int *entry_width) {
  for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
       ++i) {
    if ((*i)->max_fraction > 0.0) {
      int max_width = static_cast<int>(*entry_width * (*i)->max_fraction);
      (*i)->computed_width =
          std::min((*i)->view->GetPreferredSize().width(),
                   std::max((*i)->view->GetMinimumSize().width(), max_width));
      *entry_width -= (*i)->computed_width;
    }
  }
}

void LocationBarLayout::LayoutPass3(gfx::Rect* bounds, int* available_width) {
  bool first_visible = true;
  for (Decorations::iterator i(decorations_.begin()); i != decorations_.end();
       ++i) {
    // Collapse decorations if needed.
    if ((*i)->auto_collapse) {
      int padding = -2 * (*i)->builtin_padding +
          (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
      // Try preferred size, if it fails try minimum size, if it fails collapse.
      (*i)->computed_width = (*i)->view->GetPreferredSize().width();
      if ((*i)->computed_width + padding > *available_width)
        (*i)->computed_width = (*i)->view->GetMinimumSize().width();
      if ((*i)->computed_width + padding > *available_width) {
        (*i)->computed_width = 0;
        (*i)->view->SetVisible(false);
      } else {
        (*i)->view->SetVisible(true);
        (*available_width) -= (*i)->computed_width + padding;
      }
    } else {
      (*i)->view->SetVisible(true);
    }

    // Layout visible decorations.
    if (!(*i)->view->visible())
      continue;
    int padding = -(*i)->builtin_padding +
        (first_visible ? (*i)->edge_item_padding : (*i)->item_padding);
    first_visible = false;
    int x = (position_ == LEFT_EDGE) ? (bounds->x() + padding) :
        (bounds->right() - padding - (*i)->computed_width);
    (*i)->view->SetBounds(x, (*i)->y, (*i)->computed_width, (*i)->height);
    bounds->set_width(bounds->width() - padding - (*i)->computed_width +
        (*i)->builtin_padding);
    if (position_ == LEFT_EDGE) {
      bounds->set_x(
          bounds->x() + padding + (*i)->computed_width - (*i)->builtin_padding);
    }
  }
  bounds->set_width(bounds->width() - item_edit_padding_);
  if (position_ == LEFT_EDGE)
    bounds->set_x(bounds->x() + item_edit_padding_);
}

/* [<][>][^][v][top][bottom][index][help] */