summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-02 18:28:52 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-02 18:28:52 +0000
commitdaac7521c5e097c788aed05258228ce7d81c8bb4 (patch)
treeacc814b017eb9ec0ddb9fbfd4cebbeb96aba1cf6
parent4da9faca3b8cb8687017ca4acc9c1164964062ad (diff)
downloadchromium_src-daac7521c5e097c788aed05258228ce7d81c8bb4.zip
chromium_src-daac7521c5e097c788aed05258228ce7d81c8bb4.tar.gz
chromium_src-daac7521c5e097c788aed05258228ce7d81c8bb4.tar.bz2
Add extra views to the new net internals page. This adds tabs along the top for proxy, dns, sockets, requests, and http cache subsections. The actual subviews are placeholders.
BUG=37421 Review URL: http://codereview.chromium.org/1593009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@43502 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/resources/net_internals/detailsview.js139
-rw-r--r--chrome/browser/resources/net_internals/index.html41
-rw-r--r--chrome/browser/resources/net_internals/layoutmanager.js151
-rw-r--r--chrome/browser/resources/net_internals/main.css55
-rw-r--r--chrome/browser/resources/net_internals/main.js57
-rw-r--r--chrome/browser/resources/net_internals/requestsview.js58
-rw-r--r--chrome/browser/resources/net_internals/resizableverticalsplitview.js125
-rw-r--r--chrome/browser/resources/net_internals/tabswitcherview.js141
-rw-r--r--chrome/browser/resources/net_internals/topmidbottomview.js59
-rw-r--r--chrome/browser/resources/net_internals/util.js18
-rw-r--r--chrome/browser/resources/net_internals/view.js130
-rwxr-xr-xchrome/chrome_browser.gypi5
12 files changed, 737 insertions, 242 deletions
diff --git a/chrome/browser/resources/net_internals/detailsview.js b/chrome/browser/resources/net_internals/detailsview.js
index 271c19f..847d94b 100644
--- a/chrome/browser/resources/net_internals/detailsview.js
+++ b/chrome/browser/resources/net_internals/detailsview.js
@@ -9,85 +9,118 @@
*
* @constructor
*/
-function DetailsView(logTabHandleId,
- timelineTabHandleId,
- detailsTabContentId) {
- // The DOM nodes that which contain the tab title.
- this.tabHandles_ = {};
+function DetailsView(tabHandlesContainerId,
+ logTabId,
+ timelineTabId,
+ logBoxId,
+ timelineBoxId) {
+ TabSwitcherView.call(this, new DivView(tabHandlesContainerId));
- this.tabHandles_['timeline'] = document.getElementById(timelineTabHandleId);
- this.tabHandles_['log'] = document.getElementById(logTabHandleId);
+ this.logView_ = new DetailsLogView(logBoxId);
+ this.timelineView_ = new DetailsTimelineView(timelineBoxId);
- // The DOM node that contains the currently active tab sheet.
- this.contentArea_ = document.getElementById(detailsTabContentId);
-
- // Attach listeners to the "tab handles" so when you click them, it switches
- // active view.
-
- var self = this;
-
- this.tabHandles_['timeline'].onclick = function() {
- self.switchToView_('timeline');
- };
-
- this.tabHandles_['log'].onclick = function() {
- self.switchToView_('log');
- };
-
- this.currentData_ = [];
+ this.addTab(logTabId, this.logView_);
+ this.addTab(timelineTabId, this.timelineView_);
// Default to the log view.
- this.switchToView_('log');
+ this.switchToTab(logTabId);
};
+inherits(DetailsView, TabSwitcherView);
+
// The delay between updates to repaint.
DetailsView.REPAINT_TIMEOUT_MS = 50;
/**
- * Switches to the tab with name |viewName|. (Either 'log' or 'timeline'.
+ * Updates the data this view is using.
*/
-DetailsView.prototype.switchToView_ = function(viewName) {
- if (this.currentView_) {
- // Remove the selected styling on currently selected tab.
- changeClassName(this.tabHandles_[this.currentView_], 'selected', false);
- }
+DetailsView.prototype.setData = function(currentData) {
+ // Make a copy of the array (in case the caller mutates it), and sort it
+ // by the source ID.
+ var sortedCurrentData = DetailsView.createSortedCopy_(currentData);
- this.currentView_ = viewName;
- changeClassName(this.tabHandles_[this.currentView_], 'selected', true);
- this.repaint_();
+ for (var i = 0; i < this.tabs_.length; ++i)
+ this.tabs_[i].contentView.setData(sortedCurrentData);
};
+DetailsView.createSortedCopy_ = function(origArray) {
+ var sortedArray = origArray.slice(0);
+ sortedArray.sort(function(a, b) {
+ return a.getSourceId() - b.getSourceId();
+ });
+ return sortedArray;
+};
+
+//-----------------------------------------------------------------------------
+
/**
- * Updates the data this view is using.
+ * Base class for the Log view and Timeline view.
+ *
+ * @constructor
*/
-DetailsView.prototype.setData = function(currentData) {
- // Make a copy of the array (in case the caller mutates it), and sort it
- // by the source ID.
- this.currentData_ = DetailsView.createSortedCopy_(currentData);
+function DetailsSubView(boxId) {
+ DivView.call(this, boxId);
+ this.sourceEntries_ = [];
+}
+
+inherits(DetailsSubView, DivView);
- // Invalidate the view.
- if (!this.outstandingRepaint_) {
+DetailsSubView.prototype.setData = function(sourceEntries) {
+ this.sourceEntries_ = sourceEntries;
+
+ // Repaint the view.
+ if (this.isVisible() && !this.outstandingRepaint_) {
this.outstandingRepaint_ = true;
- window.setTimeout(this.repaint_.bind(this),
+ window.setTimeout(this.repaint.bind(this),
DetailsView.REPAINT_TIMEOUT_MS);
}
};
-DetailsView.prototype.repaint_ = function() {
+DetailsSubView.prototype.repaint = function() {
this.outstandingRepaint_ = false;
- this.contentArea_.innerHTML = '';
+ this.getNode().innerHTML = '';
+};
- if (this.currentView_ == 'log') {
- PaintLogView(this.currentData_, this.contentArea_);
+DetailsSubView.prototype.show = function(isVisible) {
+ DetailsSubView.superClass_.show.call(this, isVisible);
+ if (isVisible) {
+ this.repaint();
} else {
- PaintTimelineView(this.currentData_, this.contentArea_);
+ this.getNode().innerHTML = '';
}
};
-DetailsView.createSortedCopy_ = function(origArray) {
- var sortedArray = origArray.slice(0);
- sortedArray.sort(function(a, b) {
- return a.getSourceId() - b.getSourceId();
- });
- return sortedArray;
+//-----------------------------------------------------------------------------
+
+
+/**
+ * Subview that is displayed in the log tab.
+ * @constructor
+ */
+function DetailsLogView(boxId) {
+ DetailsSubView.call(this, boxId);
+}
+
+inherits(DetailsLogView, DetailsSubView);
+
+DetailsLogView.prototype.repaint = function() {
+ DetailsLogView.superClass_.repaint.call(this);
+ PaintLogView(this.sourceEntries_, this.getNode());
+};
+
+//-----------------------------------------------------------------------------
+
+/**
+ * Subview that is displayed in the timeline tab.
+ * @constructor
+ */
+function DetailsTimelineView(boxId) {
+ DetailsSubView.call(this, boxId);
+}
+
+inherits(DetailsTimelineView, DetailsSubView);
+
+DetailsTimelineView.prototype.repaint = function() {
+ DetailsTimelineView.superClass_.repaint.call(this);
+ PaintTimelineView(this.sourceEntries_, this.getNode());
};
diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html
index fab3304..fb7ff9a 100644
--- a/chrome/browser/resources/net_internals/index.html
+++ b/chrome/browser/resources/net_internals/index.html
@@ -6,20 +6,42 @@ found in the LICENSE file.
-->
<head>
<link tyle="text/css" rel="stylesheet" href="main.css" />
- <script src="main.js"></script>
<script src="util.js"></script>
+ <script src="view.js"></script>
+ <script src="tabswitcherview.js"></script>
+ <script src="main.js"></script>
<script src="requestsview.js"></script>
<script src="detailsview.js"></script>
<script src="sourceentry.js"></script>
- <script src="layoutmanager.js"></script>
+ <script src="resizableverticalsplitview.js"></script>
+ <script src="topmidbottomview.js"></script>
<script src="timelineviewpainter.js"></script>
<script src="logviewpainter.js"></script>
<script src="loggrouper.js"></script>
</head>
<body onload="onLoaded()">
+ <!-- Tab switcher for main categories. -->
+ <div id=categoryTabHandles>
+ <ul>
+ <li><a href="#" id=proxyTab>Proxy</a></li>
+ <li><a href="#" id=requestsTab>Requests</a></li>
+ <li><a href="#" id=dnsTab>DNS</a></li>
+ <li><a href="#" id=socketsTab>Sockets</a></li>
+ <li><a href="#" id=httpCacheTab>HTTP Cache</a></li>
+ </ul>
+ <div style="clear: both;"></div>
+ </div>
+ <!-- Sections TODO -->
+ <div id=proxyTabContent>TODO: display proxy information (PAC error log, initialization log, current settings.)</div>
+ <div id=dnsTabContent>TODO: display dns information (outstanding jobs, host cache).</div>
+ <div id=socketsTabContent>TODO: display socket information (outstanding connect jobs)</div>
+ <div id=httpCacheTabContent>TODO: display http cache information (disk cache navigator)</div>
+
+ <!-- ================= Requests view =================== -->
+
<!-- Filter Box: This the top bar which contains the search box. -->
<div id=filterBox>
- <table width=100% height=100%>
+ <table width=100%>
<tr>
<td width=1%>Filter:</td>
<td width=98%><input type="search" incremental id=filterInput /></td>
@@ -29,13 +51,13 @@ found in the LICENSE file.
</div>
<!-- Requests Box: This the panel on the left which lists the requests -->
<div id=requestsBox>
- <table id=requestsListTable cellspacing=0 cellpadding=0>
+ <table id=requestsListTable cellspacing=0 cellpadding=0 width=100%>
<thead>
<tr>
<td><input type=checkbox id=selectAll /></td>
<td>ID</td>
<td>Source</td>
- <td>URL</td>
+ <td width=99%>URL</td>
</tr>
</thead>
<!-- Requests table body: This is where request rows go into -->
@@ -50,16 +72,17 @@ found in the LICENSE file.
<!-- Splitter Box: This is a handle to resize the vertical divider -->
<div id=splitterBox></div>
<!-- Details box: This is the panel on the right which shows information -->
- <div id=detailsBox>
+ <div id=detailsTabHandles>
<table class=tabSwitcher cellspacing=0>
<tr>
- <th id=detailsLogTabHandle>Log</th>
+ <th id=detailsLogTab>Log</th>
<td class=tabSwitcherSpacer>&nbsp;</td>
- <th id=detailsTimelineTabHandle>Timeline</th>
+ <th id=detailsTimelineTab>Timeline</th>
</tr>
</table>
<div class=tabSwitcherLine></div>
- <div id=detailsTabArea></div>
</div>
+ <div id=detailsLogBox></div>
+ <div id=detailsTimelineBox></div>
</body>
</html>
diff --git a/chrome/browser/resources/net_internals/layoutmanager.js b/chrome/browser/resources/net_internals/layoutmanager.js
deleted file mode 100644
index 0491a63..0000000
--- a/chrome/browser/resources/net_internals/layoutmanager.js
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2010 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.
-
-/**
- * The class LayoutManager implements a vertically split layout that takes up
- * the whole window, and provides a draggable bar to resize the left and right
- * panes. Its elements are layed out as follows:
- *
- *
- * <<-- sizer -->>
- *
- * +----------------------++----------------+
- * | topbar || |
- * +----------------------+| |
- * | || |
- * | || |
- * | || |
- * | || |
- * | middlebox || rightbox |
- * | || |
- * | || |
- * | || |
- * | || |
- * | || |
- * +----------------------++ |
- * | bottombar || |
- * +----------------------++----------------+
- *
- * The "topbar" and "bottombar" have a fixed height which is determined
- * by their initial content height. The rest of the boxes fill to occupy the
- * remaining space.
- *
- * The consumer provides DIVs for each of these regions, and the LayoutManager
- * positions them correctly in the window.
- *
- * @constructor
- */
-function LayoutManager(topbarId,
- middleboxId,
- bottombarId,
- sizerId,
- rightboxId) {
- // Lookup the elements.
- this.topbar_ = document.getElementById(topbarId);
- this.middlebox_ = document.getElementById(middleboxId);
- this.bottombar_ = document.getElementById(bottombarId);
- this.sizer_ = document.getElementById(sizerId);
- this.rightbox_ = document.getElementById(rightboxId);
-
- // Make all the elements absolutely positioned.
- this.topbar_.style.position = "absolute";
- this.middlebox_.style.position = "absolute";
- this.bottombar_.style.position = "absolute";
- this.sizer_.style.position = "absolute";
- this.rightbox_.style.position = "absolute";
-
- // Set the initial split position at 50%.
- setNodeWidth(this.rightbox_, window.innerWidth / 2);
-
- // Setup the "sizer" so it can be dragged left/right to reposition the
- // vertical split.
- this.sizer_.addEventListener("mousedown", this.onDragSizerStart_.bind(this),
- true);
-
- // Recalculate the layout whenever the window size changes.
- window.addEventListener("resize", this.recalculateLayout_.bind(this), true);
-
- // Do the initial layout .
- this.recalculateLayout_();
-}
-
-// Minimum width to size panels to, in pixels.
-LayoutManager.MIN_PANEL_WIDTH = 50;
-
-/**
- * Repositions all of the elements to fit the window.
- */
-LayoutManager.prototype.recalculateLayout_ = function() {
- // Calculate the horizontal split points.
- var totalWidth = window.innerWidth;
- var rightboxWidth = this.rightbox_.offsetWidth;
- var sizerWidth = this.sizer_.offsetWidth;
- var leftPaneWidth = totalWidth - (rightboxWidth + sizerWidth);
-
- // Don't let the left pane get too small.
- if (leftPaneWidth < LayoutManager.MIN_PANEL_WIDTH) {
- leftPaneWidth = LayoutManager.MIN_PANEL_WIDTH;
- rightboxWidth = totalWidth - (sizerWidth + leftPaneWidth);
- }
-
- // Calculate the vertical split points.
- var totalHeight = window.innerHeight;
- var topbarHeight = this.topbar_.offsetHeight;
- var bottombarHeight = this.bottombar_.offsetHeight;
- var middleboxHeight = totalHeight - (topbarHeight + bottombarHeight);
-
- // Position the boxes using calculated split points.
- setNodePosition(this.topbar_, 0, 0,
- leftPaneWidth, topbarHeight);
- setNodePosition(this.middlebox_, 0, topbarHeight,
- leftPaneWidth,
- middleboxHeight);
- setNodePosition(this.bottombar_, 0, (topbarHeight + middleboxHeight),
- leftPaneWidth, bottombarHeight);
-
- setNodePosition(this.sizer_, leftPaneWidth, 0,
- sizerWidth, totalHeight);
- setNodePosition(this.rightbox_, leftPaneWidth + sizerWidth, 0,
- rightboxWidth, totalHeight);
-};
-
-/**
- * Called once we have clicked into the sizer. Starts capturing the mouse
- * position to implement dragging.
- */
-LayoutManager.prototype.onDragSizerStart_ = function(event) {
- this.sizerMouseMoveListener_ = this.onDragSizer.bind(this);
- this.sizerMouseUpListener_ = this.onDragSizerEnd.bind(this);
-
- window.addEventListener("mousemove", this.sizerMouseMoveListener_, true);
- window.addEventListener("mouseup", this.sizerMouseUpListener_, true);
-
- event.preventDefault();
-};
-
-/**
- * Called when the mouse has moved after dragging started.
- */
-LayoutManager.prototype.onDragSizer = function(event) {
- var newWidth = window.innerWidth - event.pageX;
-
- // Avoid shrinking the right box too much.
- newWidth = Math.max(newWidth, LayoutManager.MIN_PANEL_WIDTH);
-
- setNodeWidth(this.rightbox_, newWidth);
- this.recalculateLayout_();
-};
-
-/**
- * Called once the mouse has been released, and the dragging is over.
- */
-LayoutManager.prototype.onDragSizerEnd = function(event) {
- window.removeEventListener("mousemove", this.sizerMouseMoveListener_, true);
- window.removeEventListener("mouseup", this.sizerMouseUpListener_, true);
-
- this.sizerMouseMoveListener_ = null;
- this.sizerMouseUpListener_ = null;
-
- event.preventDefault();
-};
diff --git a/chrome/browser/resources/net_internals/main.css b/chrome/browser/resources/net_internals/main.css
index e6d6437..cc87520 100644
--- a/chrome/browser/resources/net_internals/main.css
+++ b/chrome/browser/resources/net_internals/main.css
@@ -6,6 +6,7 @@ found in the LICENSE file.
* {
-webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
}
body {
font-family: sans-serif;
@@ -116,8 +117,8 @@ body {
height: 10px;
}
-#detailsTabArea {
- margin-top: 10px;
+#detailsTabHandles {
+ border: 1px solid white;
}
.logSourceEntry {
@@ -132,3 +133,53 @@ body {
.logSourceEntry * td {
font-size: 10px;
}
+
+#categoryTabHandles ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+#categoryTabHandles {
+ border-bottom: 1px solid #555;
+ background: #aaa;
+}
+
+#categoryTabHandles li {
+ float: left;
+ margin-left: 5px;
+}
+
+#categoryTabHandles a {
+ text-decoration: none;
+ text-align: center;
+ display: block;
+ width: 9em;
+ padding: 5px;
+ background: #ccc;
+}
+
+#categoryTabHandles a:hover {
+ background: #eee;
+}
+
+#categoryTabHandles a:visited,
+#categoryTabHandles a {
+ color: blue;
+}
+
+#categoryTabHandles .selected {
+ background: white;
+}
+
+#categoryTabHandles a.selected {
+ position:relative;
+ top: 1px;
+ font-weight: bold;
+ color: black;
+}
+
+#detailsLogBox,
+#detailsTimelineBox {
+ overflow: auto;
+}
diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js
index b23d71f..7b9d3c9 100644
--- a/chrome/browser/resources/net_internals/main.js
+++ b/chrome/browser/resources/net_internals/main.js
@@ -14,26 +14,47 @@ var LogSourceType = null;
* Main entry point. called once the page has loaded.
*/
function onLoaded() {
- // Layout the various DIVs in a vertically split fashion.
- new LayoutManager("filterBox",
- "requestsBox",
- "actionBox",
- "splitterBox",
- "detailsBox");
-
- // Create the view which displays information on the current selection.
- var detailsView = new DetailsView("detailsLogTabHandle",
- "detailsTimelineTabHandle",
- "detailsTabArea");
-
// Create the view which displays requests lists, and lets you select, filter
// and delete them.
- new RequestsView('requestsListTableBody',
- 'filterInput',
- 'filterCount',
- 'deleteSelected',
- 'selectAll',
- detailsView);
+ var requestsView = new RequestsView('requestsListTableBody',
+ 'filterInput',
+ 'filterCount',
+ 'deleteSelected',
+ 'selectAll',
+
+ // IDs for the details view.
+ "detailsTabHandles",
+ "detailsLogTab",
+ "detailsTimelineTab",
+ "detailsLogBox",
+ "detailsTimelineBox",
+
+ // IDs for the layout boxes.
+ "filterBox",
+ "requestsBox",
+ "actionBox",
+ "splitterBox");
+
+ // Create a view which lets you tab between the different sub-views.
+ var categoryTabSwitcher =
+ new TabSwitcherView(new DivView('categoryTabHandles'));
+
+ // Populate the main tabs.
+ categoryTabSwitcher.addTab('requestsTab', requestsView);
+ categoryTabSwitcher.addTab('proxyTab', new DivView('proxyTabContent'));
+ categoryTabSwitcher.addTab('dnsTab', new DivView('dnsTabContent'));
+ categoryTabSwitcher.addTab('socketsTab', new DivView('socketsTabContent'));
+ categoryTabSwitcher.addTab('httpCacheTab',
+ new DivView('httpCacheTabContent'));
+
+ // Select the requests tab as the default.
+ categoryTabSwitcher.switchToTab('requestsTab');
+
+ // Make this category tab widget the primary view, that fills the whole page.
+ var windowView = new WindowView(categoryTabSwitcher);
+
+ // Trigger initial layout.
+ windowView.resetGeometry();
// Tell the browser that we are ready to start receiving log events.
notifyApplicationReady();
diff --git a/chrome/browser/resources/net_internals/requestsview.js b/chrome/browser/resources/net_internals/requestsview.js
index 40707a4..16b39b9 100644
--- a/chrome/browser/resources/net_internals/requestsview.js
+++ b/chrome/browser/resources/net_internals/requestsview.js
@@ -3,25 +3,55 @@
// found in the LICENSE file.
/**
- * RequestsView is the class which glues together the different components to
- * form the primary UI:
+ * RequestsView displays a filtered list of all the requests, and a details
+ * pane for the selected requests.
*
- * - The search filter
- * - The requests table
- * - The details panel
- * - The action bar
+ * +----------------------++----------------+
+ * | filter box || |
+ * +----------------------+| |
+ * | || |
+ * | || |
+ * | || |
+ * | || |
+ * | requests list || details |
+ * | || view |
+ * | || |
+ * | || |
+ * | || |
+ * | || |
+ * +----------------------++ |
+ * | action bar || |
+ * +----------------------++----------------+
*
* @constructor
*/
function RequestsView(tableBodyId, filterInputId, filterCountId,
- deleteSelectedId, selectAllId, detailsView) {
+ deleteSelectedId, selectAllId,
+ tabHandlesContainerId, logTabId, timelineTabId,
+ detailsLogBoxId, detailsTimelineBoxId,
+ topbarId, middleboxId, bottombarId, sizerId) {
+ View.call(this);
+
+ // Initialize the sub-views.
+ var leftPane = new TopMidBottomView(new DivView(topbarId),
+ new DivView(middleboxId),
+ new DivView(bottombarId));
+
+ this.detailsView_ = new DetailsView(tabHandlesContainerId,
+ logTabId,
+ timelineTabId,
+ detailsLogBoxId,
+ detailsTimelineBoxId);
+
+ this.splitterView_ = new ResizableVerticalSplitView(
+ leftPane, this.detailsView_, new DivView(sizerId));
+
this.sourceIdToEntryMap_ = {};
this.currentSelectedSources_ = [];
LogDataProvider.addObserver(this);
this.tableBody_ = document.getElementById(tableBodyId);
- this.detailsView_ = detailsView;
this.filterInput_ = document.getElementById(filterInputId);
this.filterCount_ = document.getElementById(filterCountId);
@@ -43,9 +73,21 @@ function RequestsView(tableBodyId, filterInputId, filterCountId,
this.invalidateDetailsView_();
}
+inherits(RequestsView, View);
+
// How soon after updating the filter list the counter should be updated.
RequestsView.REPAINT_FILTER_COUNTER_TIMEOUT_MS = 0;
+RequestsView.prototype.setGeometry = function(left, top, width, height) {
+ RequestsView.superClass_.setGeometry.call(this, left, top, width, height);
+ this.splitterView_.setGeometry(left, top, width, height);
+};
+
+RequestsView.prototype.show = function(isVisible) {
+ RequestsView.superClass_.show.call(this, isVisible);
+ this.splitterView_.show(isVisible);
+};
+
RequestsView.prototype.onFilterTextChanged_ = function() {
this.setFilter_(this.filterInput_.value);
};
diff --git a/chrome/browser/resources/net_internals/resizableverticalsplitview.js b/chrome/browser/resources/net_internals/resizableverticalsplitview.js
new file mode 100644
index 0000000..78b62a0
--- /dev/null
+++ b/chrome/browser/resources/net_internals/resizableverticalsplitview.js
@@ -0,0 +1,125 @@
+// Copyright (c) 2010 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.
+
+/**
+ * This view implements a vertically split display with a draggable divider.
+ *
+ * <<-- sizer -->>
+ *
+ * +----------------------++----------------+
+ * | || |
+ * | || |
+ * | || |
+ * | || |
+ * | leftView || rightView |
+ * | || |
+ * | || |
+ * | || |
+ * | || |
+ * | || |
+ * +----------------------++----------------+
+ *
+ * @param {!View} leftView The widget to position on the left.
+ * @param {!View} rightView The widget to position on the right.
+ * @param {!DivView} sizerView The widget that will serve as draggable divider.
+ * @constructor
+ */
+function ResizableVerticalSplitView(leftView, rightView, sizerView) {
+ View.call(this);
+
+ this.leftView_ = leftView;
+ this.rightView_ = rightView;
+ this.sizerView_ = sizerView;
+
+ // Setup the "sizer" so it can be dragged left/right to reposition the
+ // vertical split.
+ sizerView.getNode().addEventListener(
+ "mousedown", this.onDragSizerStart_.bind(this), true);
+}
+
+inherits(ResizableVerticalSplitView, View);
+
+// Minimum width to size panels to, in pixels.
+ResizableVerticalSplitView.MIN_PANEL_WIDTH = 50;
+
+/**
+ * Repositions all of the elements to fit the window.
+ */
+ResizableVerticalSplitView.prototype.setGeometry = function(
+ left, top, width, height) {
+ ResizableVerticalSplitView.superClass_.setGeometry.call(
+ this, left, top, width, height);
+
+ // If this is the first setGeometry(), initialize the split point at 50%.
+ if (!this.rightSplit_)
+ this.rightSplit_ = parseInt((width / 2).toFixed(0));
+
+ // Calculate the horizontal split points.
+ var rightboxWidth = this.rightSplit_;
+ var sizerWidth = this.sizerView_.getWidth();
+ var leftboxWidth = width - (rightboxWidth + sizerWidth);
+
+ // Don't let the left pane get too small.
+ if (leftboxWidth < ResizableVerticalSplitView.MIN_PANEL_WIDTH) {
+ leftboxWidth = ResizableVerticalSplitView.MIN_PANEL_WIDTH;
+ rightboxWidth = width - (sizerWidth + leftboxWidth);
+ }
+
+ // Position the boxes using calculated split points.
+ this.leftView_.setGeometry(left, top, leftboxWidth, height);
+ this.sizerView_.setGeometry(this.leftView_.getRight(), top,
+ sizerWidth, height);
+ this.rightView_.setGeometry(this.sizerView_.getRight(), top,
+ rightboxWidth, height);
+};
+
+ResizableVerticalSplitView.prototype.show = function(isVisible) {
+ ResizableVerticalSplitView.superClass_.show.call(this, isVisible);
+ this.leftView_.show(isVisible);
+ this.sizerView_.show(isVisible);
+ this.rightView_.show(isVisible);
+};
+
+/**
+ * Called once we have clicked into the sizer. Starts capturing the mouse
+ * position to implement dragging.
+ */
+ResizableVerticalSplitView.prototype.onDragSizerStart_ = function(event) {
+ this.sizerMouseMoveListener_ = this.onDragSizer.bind(this);
+ this.sizerMouseUpListener_ = this.onDragSizerEnd.bind(this);
+
+ window.addEventListener("mousemove", this.sizerMouseMoveListener_, true);
+ window.addEventListener("mouseup", this.sizerMouseUpListener_, true);
+
+ event.preventDefault();
+};
+
+/**
+ * Called when the mouse has moved after dragging started.
+ */
+ResizableVerticalSplitView.prototype.onDragSizer = function(event) {
+ // Convert from page coordinates, to view coordinates.
+ this.rightSplit_ = this.getWidth() - (event.pageX - this.getLeft());
+
+ // Avoid shrinking the right box too much.
+ this.rightSplit_ = Math.max(
+ this.rightSplit_, ResizableVerticalSplitView.MIN_PANEL_WIDTH);
+
+ // Force a layout with the new |rightSplit_|.
+ this.setGeometry(
+ this.getLeft(), this.getTop(), this.getWidth(), this.getHeight());
+};
+
+/**
+ * Called once the mouse has been released, and the dragging is over.
+ */
+ResizableVerticalSplitView.prototype.onDragSizerEnd = function(event) {
+ window.removeEventListener("mousemove", this.sizerMouseMoveListener_, true);
+ window.removeEventListener("mouseup", this.sizerMouseUpListener_, true);
+
+ this.sizerMouseMoveListener_ = null;
+ this.sizerMouseUpListener_ = null;
+
+ event.preventDefault();
+};
diff --git a/chrome/browser/resources/net_internals/tabswitcherview.js b/chrome/browser/resources/net_internals/tabswitcherview.js
new file mode 100644
index 0000000..b712edc
--- /dev/null
+++ b/chrome/browser/resources/net_internals/tabswitcherview.js
@@ -0,0 +1,141 @@
+// Copyright (c) 2010 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.
+
+/**
+ * TabSwitcher is an implementation of View that handles tab switching.
+ *
+ * +-----------------------------------+
+ * | Tab1 / Tab2 / Tab3 / .. | <- tab handle view
+ * +-----------------------------------+
+ * | |
+ * | |
+ * | |
+ * | stacked tab content areas |
+ * | (only 1 is visible at a time) |
+ * | |
+ * | |
+ * | |
+ * +-----------------------------------+
+ *
+ * @parameter {!View} tabHandleView the view that contains the tab handles.
+ *
+ * @constructor
+ */
+function TabSwitcherView(tabHandleView) {
+ View.call(this);
+ this.tabHandleView_ = tabHandleView;
+ this.tabs_ = [];
+}
+
+inherits(TabSwitcherView, View);
+
+TabSwitcherView.prototype.setGeometry = function(left, top, width, height) {
+ TabSwitcherView.superClass_.setGeometry.call(this, left, top, width, height);
+
+ this.tabHandleView_.setGeometry(
+ left, top, width, this.tabHandleView_.getHeight());
+
+ var contentTop = this.tabHandleView_.getBottom();
+ var contentHeight = height - this.tabHandleView_.getHeight();
+
+ // Position each of the tabs content areas.
+ for (var i = 0; i < this.tabs_.length; ++i) {
+ var tab = this.tabs_[i];
+ tab.contentView.setGeometry(left, contentTop, width, contentHeight);
+ }
+};
+
+TabSwitcherView.prototype.show = function(isVisible) {
+ TabSwitcherView.superClass_.show.call(this, isVisible);
+
+ this.tabHandleView_.show(isVisible);
+
+ var activeTab = this.findActiveTab();
+ if (activeTab)
+ activeTab.contentView.show(isVisible);
+};
+
+/**
+ * Adds a new tab (initially hidden).
+ *
+ * @param {String} id The ID for DOM node that will be made clickable to select
+ * this tab. This is also the ID we use to identify the
+ * "tab".
+ * @param {!View} view The tab's actual contents.
+ */
+TabSwitcherView.prototype.addTab = function(id, contentView) {
+ var tab = new TabEntry(id, contentView);
+ this.tabs_.push(tab);
+
+ // Attach a click handler, used to switch to the tab.
+ var self = this;
+ tab.getTabHandleNode().onclick = function() {
+ self.switchToTab(id);
+ };
+
+ // Start tabs off as hidden.
+ tab.contentView.show(false);
+};
+
+/**
+ * Returns the currently selected tab, or null if there is none.
+ * @returns {!TabEntry}
+ */
+TabSwitcherView.prototype.findActiveTab = function() {
+ for (var i = 0; i < this.tabs_.length; ++i) {
+ var tab = this.tabs_[i];
+ if (tab.active)
+ return tab;
+ }
+ return null;
+};
+
+/**
+ * Returns the tab with ID |id|.
+ * @returns {!TabEntry}
+ */
+TabSwitcherView.prototype.findTabById = function(id) {
+ for (var i = 0; i < this.tabs_.length; ++i) {
+ var tab = this.tabs_[i];
+ if (tab.id == id)
+ return tab;
+ }
+ return null;
+};
+
+/**
+ * Focuses on tab with ID |id|.
+ */
+TabSwitcherView.prototype.switchToTab = function(id) {
+ var oldTab = this.findActiveTab();
+ if (oldTab)
+ oldTab.setSelected(false);
+
+ var newTab = this.findTabById(id);
+ newTab.setSelected(true);
+};
+
+//-----------------------------------------------------------------------------
+
+/**
+ * @constructor
+ */
+function TabEntry(id, contentView) {
+ this.id = id;
+ this.contentView = contentView;
+}
+
+TabEntry.prototype.setSelected = function(isSelected) {
+ this.active = isSelected;
+ changeClassName(this.getTabHandleNode(), 'selected', isSelected);
+ this.contentView.show(isSelected);
+};
+
+/**
+ * Returns the DOM node that is used to select the tab.
+ */
+TabEntry.prototype.getTabHandleNode = function() {
+ return document.getElementById(this.id);
+};
+
diff --git a/chrome/browser/resources/net_internals/topmidbottomview.js b/chrome/browser/resources/net_internals/topmidbottomview.js
new file mode 100644
index 0000000..2b045c7
--- /dev/null
+++ b/chrome/browser/resources/net_internals/topmidbottomview.js
@@ -0,0 +1,59 @@
+// Copyright (c) 2010 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.
+
+/**
+ * This view stacks three boxes -- one at the top, one at the bottom, and
+ * one that fills the remaining space between those two.
+ *
+ * +----------------------+
+ * | topbar |
+ * +----------------------+
+ * | |
+ * | |
+ * | |
+ * | |
+ * | middlebox |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +----------------------+
+ * | bottombar |
+ * +----------------------+
+ *
+ * @constructor
+ */
+function TopMidBottomView(topView, midView, bottomView) {
+ View.call(this);
+
+ this.topView_ = topView;
+ this.midView_ = midView;
+ this.bottomView_ = bottomView;
+}
+
+inherits(TopMidBottomView, View);
+
+TopMidBottomView.prototype.setGeometry = function(left, top, width, height) {
+ TopMidBottomView.superClass_.setGeometry.call(this, left, top, width, height);
+
+ // Calculate the vertical split points.
+ var topbarHeight = this.topView_.getHeight();
+ var bottombarHeight = this.bottomView_.getHeight();
+ var middleboxHeight = height - (topbarHeight + bottombarHeight);
+
+ // Position the boxes using calculated split points.
+ this.topView_.setGeometry(left, top, width, topbarHeight);
+ this.midView_.setGeometry(left, this.topView_.getBottom(),
+ width, middleboxHeight);
+ this.bottomView_.setGeometry(left, this.midView_.getBottom(),
+ width, bottombarHeight);
+};
+
+TopMidBottomView.prototype.show = function(isVisible) {
+ TopMidBottomView.superClass_.show.call(this, isVisible);
+ this.topView_.show(isVisible);
+ this.midView_.show(isVisible);
+ this.bottomView_.show(isVisible);
+};
diff --git a/chrome/browser/resources/net_internals/util.js b/chrome/browser/resources/net_internals/util.js
index 780a030..27b5cc5 100644
--- a/chrome/browser/resources/net_internals/util.js
+++ b/chrome/browser/resources/net_internals/util.js
@@ -15,6 +15,17 @@ Function.prototype.bind = function(thisObj) {
};
/**
+ * Inherit the prototype methods from one constructor into another.
+ */
+function inherits(childCtor, parentCtor) {
+ function tempCtor() {};
+ tempCtor.prototype = parentCtor.prototype;
+ childCtor.superClass_ = parentCtor.prototype;
+ childCtor.prototype = new tempCtor();
+ childCtor.prototype.constructor = childCtor;
+};
+
+/**
* Sets the width (in pixels) on a DOM node.
*/
function setNodeWidth(node, widthPx) {
@@ -39,6 +50,13 @@ function setNodePosition(node, leftPx, topPx, widthPx, heightPx) {
}
/**
+ * Sets the visibility for a DOM node.
+ */
+function setNodeDisplay(node, isVisible) {
+ node.style.display = isVisible ? '' : 'none';
+}
+
+/**
* Adds a node to |parentNode|, of type |tagName|.
*/
function addNode(parentNode, tagName) {
diff --git a/chrome/browser/resources/net_internals/view.js b/chrome/browser/resources/net_internals/view.js
new file mode 100644
index 0000000..1338d4f
--- /dev/null
+++ b/chrome/browser/resources/net_internals/view.js
@@ -0,0 +1,130 @@
+// Copyright (c) 2010 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.
+
+/**
+ * Base class to represent a "view". A view is an absolutely positioned box on
+ * the page.
+ *
+ * @constructor
+ */
+function View() {
+ this.isVisible_ = true;
+}
+
+/**
+ * Called to reposition the view on the page. Measurements are in pixels.
+ */
+View.prototype.setGeometry = function(left, top, width, height) {
+ this.left_ = left;
+ this.top_ = top;
+ this.width_ = width;
+ this.height_ = height;
+};
+
+/**
+ * Called to show/hide the view.
+ */
+View.prototype.show = function(isVisible) {
+ this.isVisible_ = isVisible;
+};
+
+View.prototype.isVisible = function() {
+ return this.isVisible_;
+};
+
+View.prototype.getLeft = function() {
+ return this.left_;
+};
+
+View.prototype.getTop = function() {
+ return this.top_;
+};
+
+View.prototype.getWidth = function() {
+ return this.width_;
+};
+
+View.prototype.getHeight = function() {
+ return this.height_;
+};
+
+View.prototype.getRight = function() {
+ return this.getLeft() + this.getWidth();
+};
+
+View.prototype.getBottom = function() {
+ return this.getTop() + this.getHeight();
+};
+
+
+//-----------------------------------------------------------------------------
+
+/**
+ * DivView is an implementation of View that wraps a DIV.
+ *
+ * @constructor
+ */
+function DivView(divId) {
+ View.call(this);
+
+ this.node_ = document.getElementById(divId);
+
+ // Initialize the default values to those of the DIV.
+ this.width_ = this.node_.offsetWidth;
+ this.height_ = this.node_.offsetHeight;
+ this.isVisible_ = this.node_.style.display != 'none';
+}
+
+inherits(DivView, View);
+
+DivView.prototype.setGeometry = function(left, top, width, height) {
+ DivView.superClass_.setGeometry.call(this, left, top, width, height);
+
+ this.node_.style.position = "absolute";
+ setNodePosition(this.node_, left, top, width, height);
+};
+
+DivView.prototype.show = function(isVisible) {
+ DivView.superClass_.show.call(this, isVisible);
+ setNodeDisplay(this.node_, isVisible);
+};
+
+/**
+ * Returns the wrapped DIV
+ */
+DivView.prototype.getNode = function() {
+ return this.node_;
+};
+
+//-----------------------------------------------------------------------------
+
+/**
+ * Implementation of View that sizes its child to fit the entire window.
+ *
+ * @param {!View} childView
+ *
+ * @constructor
+ */
+function WindowView(childView) {
+ View.call(this);
+ this.childView_ = childView;
+ window.addEventListener("resize", this.resetGeometry.bind(this), true);
+}
+
+inherits(WindowView, View);
+
+WindowView.prototype.setGeometry = function(left, top, width, height) {
+ WindowView.superClass_.setGeometry.call(this, left, top, width, height);
+ this.childView_.setGeometry(left, top, width, height);
+};
+
+WindowView.prototype.show = function() {
+ WindowView.superClass_.show.call(this, isVisible);
+ this.childView_.show(isVisible);
+};
+
+WindowView.prototype.resetGeometry = function() {
+ this.setGeometry(0, 0, window.innerWidth, window.innerHeight);
+};
+
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 0a48364..961419e 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -3174,15 +3174,18 @@
'files': [
'browser/resources/net_internals/detailsview.js',
'browser/resources/net_internals/index.html',
- 'browser/resources/net_internals/layoutmanager.js',
'browser/resources/net_internals/loggrouper.js',
'browser/resources/net_internals/logviewpainter.js',
'browser/resources/net_internals/main.css',
'browser/resources/net_internals/main.js',
'browser/resources/net_internals/requestsview.js',
+ 'browser/resources/net_internals/resizableverticalsplitview.js',
'browser/resources/net_internals/sourceentry.js',
+ 'browser/resources/net_internals/tabswitcherview.js',
'browser/resources/net_internals/timelineviewpainter.js',
+ 'browser/resources/net_internals/topmidbottomview.js',
'browser/resources/net_internals/util.js',
+ 'browser/resources/net_internals/view.js',
]
},
]