1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * TabSwitcher is an implementation of View that handles tab switching.
7 *
8 *  +-----------------------------------+
9 *  | Tab1 / Tab2 / Tab3 / ..           |  <- tab handle view
10 *  +-----------------------------------+
11 *  |                                   |
12 *  |                                   |
13 *  |                                   |
14 *  |   stacked tab content areas       |
15 *  |   (only 1 is visible at a time)   |
16 *  |                                   |
17 *  |                                   |
18 *  |                                   |
19 *  +-----------------------------------+
20 *
21 * @parameter {!View} tabHandleView the view that contains the tab handles.
22 *
23 * @constructor
24 */
25function TabSwitcherView(tabHandleDivId) {
26  document.getElementById(tabHandleDivId).classList.add('tab-switcher-view');
27  var tabHandleView = new DivView(tabHandleDivId);
28
29  View.call(this);
30  this.tabHandleView_ = tabHandleView;
31  this.tabs_ = [];
32}
33
34inherits(TabSwitcherView, View);
35
36TabSwitcherView.prototype.setGeometry = function(left, top, width, height) {
37  TabSwitcherView.superClass_.setGeometry.call(this, left, top, width, height);
38
39  this.tabHandleView_.setGeometry(
40      left, top, width, this.tabHandleView_.getHeight());
41
42  var contentTop = this.tabHandleView_.getBottom();
43  var contentHeight = height - this.tabHandleView_.getHeight();
44
45  // Position each of the tabs content areas.
46  for (var i = 0; i < this.tabs_.length; ++i) {
47    var tab = this.tabs_[i];
48    tab.contentView.setGeometry(left, contentTop, width, contentHeight);
49  }
50};
51
52TabSwitcherView.prototype.show = function(isVisible) {
53  TabSwitcherView.superClass_.show.call(this, isVisible);
54
55  this.tabHandleView_.show(isVisible);
56
57  var activeTab = this.findActiveTab();
58  if (activeTab)
59    activeTab.contentView.show(isVisible);
60};
61
62/**
63 * Adds a new tab (initially hidden).
64 *
65 * @param {String} id The ID for DOM node that will be made clickable to select
66 *                    this tab. This is also the ID we use to identify the
67 *                    "tab".
68 * @param {!View} view The tab's actual contents.
69 */
70TabSwitcherView.prototype.addTab = function(id, contentView, switchOnClick) {
71  var tab = new TabEntry(id, contentView);
72  this.tabs_.push(tab);
73
74  if (switchOnClick) {
75    // Attach a click handler, used to switch to the tab.
76    var self = this;
77    tab.getTabHandleNode().onclick = function() {
78      self.switchToTab(id, null);
79    };
80  }
81
82  // Start tabs off as hidden.
83  tab.contentView.show(false);
84};
85
86/**
87 * Returns the currently selected tab, or null if there is none.
88 * @returns {!TabEntry}
89 */
90TabSwitcherView.prototype.findActiveTab = function() {
91  for (var i = 0; i < this.tabs_.length; ++i) {
92    var tab = this.tabs_[i];
93    if (tab.active)
94      return tab;
95  }
96  return null;
97};
98
99/**
100 * Returns the tab with ID |id|.
101 * @returns {!TabEntry}
102 */
103TabSwitcherView.prototype.findTabById = function(id) {
104  for (var i = 0; i < this.tabs_.length; ++i) {
105    var tab = this.tabs_[i];
106    if (tab.id == id)
107      return tab;
108  }
109  return null;
110};
111
112/**
113 * Focuses on tab with ID |id|.  |params| is a dictionary that will be
114 * passed to the tab's setParameters function, if it's non-null.
115 */
116TabSwitcherView.prototype.switchToTab = function(id, params) {
117  var oldTab = this.findActiveTab();
118  if (oldTab)
119    oldTab.setSelected(false);
120
121  var newTab = this.findTabById(id);
122  newTab.setSelected(true);
123  if (params)
124    newTab.contentView.setParameters(params);
125
126  // Update data needed by newly active tab, as it may be
127  // significantly out of date.
128  if (typeof g_browser != 'undefined' && g_browser.checkForUpdatedInfo)
129    g_browser.checkForUpdatedInfo();
130};
131
132TabSwitcherView.prototype.getAllTabIds = function() {
133  var ids = [];
134  for (var i = 0; i < this.tabs_.length; ++i)
135    ids.push(this.tabs_[i].id);
136  return ids;
137};
138
139// Shows/hides the DOM node that is used to select the tab.  Will not change
140// the active tab.
141TabSwitcherView.prototype.showTabHandleNode = function(id, isVisible) {
142  var tab = this.findTabById(id);
143  setNodeDisplay(tab.getTabHandleNode(), isVisible);
144};
145
146//-----------------------------------------------------------------------------
147
148/**
149 * @constructor
150 */
151function TabEntry(id, contentView) {
152  this.id = id;
153  this.contentView = contentView;
154}
155
156TabEntry.prototype.setSelected = function(isSelected) {
157  this.active = isSelected;
158  changeClassName(this.getTabHandleNode(), 'selected', isSelected);
159  this.contentView.show(isSelected);
160};
161
162/**
163 * Returns the DOM node that is used to select the tab.
164 */
165TabEntry.prototype.getTabHandleNode = function() {
166  return document.getElementById(this.id);
167};
168
169