<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[215256] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/215256">215256</a></dd>
<dt>Author</dt> <dd>mattbaker@apple.com</dd>
<dt>Date</dt> <dd>2017-04-11 20:05:34 -0700 (Tue, 11 Apr 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: checkboxes in Settings screen use inappropriate layout
https://bugs.webkit.org/show_bug.cgi?id=166993
&lt;rdar://problem/30002272&gt;

Reviewed by Devin Rousso.

* Localizations/en.lproj/localizedStrings.js:
New checkbox setting strings.

* UserInterface/Main.html:
New settings view classes.

* UserInterface/Views/GeneralSettingsView.js: Added.
(WebInspector.GeneralSettingsView):
(WebInspector.GeneralSettingsView.prototype.initialLayout):
Move settings UI creation from SettingsTabContentView.

* UserInterface/Views/SettingEditor.js: Added.
Basic setting editor UI for the following input types: checkbox,
number, and select. In the future it may be useful to include
additional types, such as radio buttons.

(WebInspector.SettingEditor):
(WebInspector.SettingEditor.createForSetting):
(WebInspector.SettingEditor.prototype.get element):
(WebInspector.SettingEditor.prototype.get type):
(WebInspector.SettingEditor.prototype.get label):
(WebInspector.SettingEditor.prototype.get value):
(WebInspector.SettingEditor.prototype.set value):
(WebInspector.SettingEditor.prototype._createEditorElement):

* UserInterface/Views/SettingsGroup.js: Added.
A container holding editors for one or more WebInspector.Settings.
Every editor belongs to a group. SettingsView provides convenience
methods for adding settings and groups, so create instances directly
shouldn't normally be necessary.

(WebInspector.SettingsGroup):
(WebInspector.SettingsGroup.prototype.get element):
(WebInspector.SettingsGroup.prototype.addSetting):
(WebInspector.SettingsGroup.prototype.addCustomSetting):

* UserInterface/Views/SettingsTabContentView.css:
Refactored styles to more closely match Xcode settings UI.
Eliminated redundant use of &quot;setting&quot; from CSS class names.

(.content-view.settings):
(.content-view.settings .navigation-bar .item.radio.button.text-only):
(.content-view.settings .navigation-bar .item.radio.button.text-only.selected):
(.content-view.settings &gt; .settings-view &gt; .separator):
(.content-view.settings &gt; .settings-view &gt; .container):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .title):
(body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .title):
(body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .title):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
(body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
(body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor select):
(.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
(body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
(body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
(.content-view.settings &gt; .header): Deleted.
(.content-view.settings &gt; .separator): Deleted.
(.content-view.settings &gt; .setting-container): Deleted.
(.content-view.settings &gt; .setting-container.combined): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
(body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
(body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-value-controller): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-value-controller input): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
(body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
(body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-value-controller select): Deleted.
(.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.
(body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.
(body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.

* UserInterface/Views/SettingsTabContentView.js:
To better organize the growing number of settings, multiple settings views
are now supported, with a navigation bar for switching between them. For
now there is a single &quot;General&quot; setting view, and and the navigation bar
is hidden. Adding a second view will cause the bar to be shown.

(WebInspector.SettingsTabContentView):
(WebInspector.SettingsTabContentView.prototype.get type):
(WebInspector.SettingsTabContentView.prototype.get selectedSettingsView):
(WebInspector.SettingsTabContentView.prototype.set selectedSettingsView):
(WebInspector.SettingsTabContentView.prototype.addSettingsView):
(WebInspector.SettingsTabContentView.prototype._navigationItemSelected):
(WebInspector.SettingsTabContentView.prototype.layout): Deleted.
No longer needed.

* UserInterface/Views/SettingsView.js: Added.
Base class for displaying editing UI for a collection of related
WebInspector.Setting objects.

(WebInspector.SettingsView):
(WebInspector.SettingsView.prototype.get identifier):
(WebInspector.SettingsView.prototype.get displayName):
A string suitable for display in a NavigationBar showing a list of
SettingsViews (e.g. &quot;General&quot;, &quot;Text Editing&quot;, &quot;Fonts &amp; Colors&quot;, etc).

(WebInspector.SettingsView.prototype.addSetting):
Add UI for a setting, consisting of a title, an editor appropriate for
the setting's value type, and optional label and formatting options.
For example:

    addSetting(&quot;Setting 1:&quot;, new WebInspector.Setting(…, true), &quot;Item one&quot;)
    addSetting(&quot;Setting 2:&quot;, new WebInspector.Setting(…, 1), &quot;units&quot;)

will create a checkbox and number input field:

    Setting 1: [x] Item one
    Setting 2: [  1] units

(WebInspector.SettingsView.prototype.addCustomSetting):
Add UI for a specific editor type, with optional formatting options.
A setting can be updated in response to changes in the editor's value.

(WebInspector.SettingsView.prototype.addGroup):
Add a group, for listing multiple settings under one title. For example:

   group = addGroup(&quot;Title:&quot;)
   group.addSetting(new WebInspector.Setting(…, true), &quot;Item one&quot;)
   group.addSetting(new WebInspector.Setting(…, false), &quot;Item two&quot;)

will create two checkboxes under the same title:

   Title: [x] Item one
          [ ] Item two

(WebInspector.SettingsView.prototype.addSeparator):
Add vertical space between two settings or groups.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsGeneralSettingsViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/GeneralSettingsView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingEditorjs">trunk/Source/WebInspectorUI/UserInterface/Views/SettingEditor.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingsGroupjs">trunk/Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsSettingsViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/SettingsView.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (215255 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2017-04-11 23:24:26 UTC (rev 215255)
+++ trunk/Source/WebInspectorUI/ChangeLog        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -1,3 +1,142 @@
</span><ins>+2017-04-11  Matt Baker  &lt;mattbaker@apple.com&gt;
+
+        Web Inspector: checkboxes in Settings screen use inappropriate layout
+        https://bugs.webkit.org/show_bug.cgi?id=166993
+        &lt;rdar://problem/30002272&gt;
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New checkbox setting strings.
+
+        * UserInterface/Main.html:
+        New settings view classes.
+
+        * UserInterface/Views/GeneralSettingsView.js: Added.
+        (WebInspector.GeneralSettingsView):
+        (WebInspector.GeneralSettingsView.prototype.initialLayout):
+        Move settings UI creation from SettingsTabContentView.
+
+        * UserInterface/Views/SettingEditor.js: Added.
+        Basic setting editor UI for the following input types: checkbox,
+        number, and select. In the future it may be useful to include
+        additional types, such as radio buttons.
+
+        (WebInspector.SettingEditor):
+        (WebInspector.SettingEditor.createForSetting):
+        (WebInspector.SettingEditor.prototype.get element):
+        (WebInspector.SettingEditor.prototype.get type):
+        (WebInspector.SettingEditor.prototype.get label):
+        (WebInspector.SettingEditor.prototype.get value):
+        (WebInspector.SettingEditor.prototype.set value):
+        (WebInspector.SettingEditor.prototype._createEditorElement):
+
+        * UserInterface/Views/SettingsGroup.js: Added.
+        A container holding editors for one or more WebInspector.Settings.
+        Every editor belongs to a group. SettingsView provides convenience
+        methods for adding settings and groups, so create instances directly
+        shouldn't normally be necessary.
+
+        (WebInspector.SettingsGroup):
+        (WebInspector.SettingsGroup.prototype.get element):
+        (WebInspector.SettingsGroup.prototype.addSetting):
+        (WebInspector.SettingsGroup.prototype.addCustomSetting):
+
+        * UserInterface/Views/SettingsTabContentView.css:
+        Refactored styles to more closely match Xcode settings UI.
+        Eliminated redundant use of &quot;setting&quot; from CSS class names.
+
+        (.content-view.settings):
+        (.content-view.settings .navigation-bar .item.radio.button.text-only):
+        (.content-view.settings .navigation-bar .item.radio.button.text-only.selected):
+        (.content-view.settings &gt; .settings-view &gt; .separator):
+        (.content-view.settings &gt; .settings-view &gt; .container):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .title):
+        (body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .title):
+        (body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .title):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
+        (body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
+        (body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;]):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor select):
+        (.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
+        (body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
+        (body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;]):
+        (.content-view.settings &gt; .header): Deleted.
+        (.content-view.settings &gt; .separator): Deleted.
+        (.content-view.settings &gt; .setting-container): Deleted.
+        (.content-view.settings &gt; .setting-container.combined): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
+        (body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
+        (body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-name): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-value-controller): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-value-controller input): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
+        (body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
+        (body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;]): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-value-controller select): Deleted.
+        (.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.
+        (body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.
+        (body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;]): Deleted.
+
+        * UserInterface/Views/SettingsTabContentView.js:
+        To better organize the growing number of settings, multiple settings views
+        are now supported, with a navigation bar for switching between them. For
+        now there is a single &quot;General&quot; setting view, and and the navigation bar
+        is hidden. Adding a second view will cause the bar to be shown.
+
+        (WebInspector.SettingsTabContentView):
+        (WebInspector.SettingsTabContentView.prototype.get type):
+        (WebInspector.SettingsTabContentView.prototype.get selectedSettingsView):
+        (WebInspector.SettingsTabContentView.prototype.set selectedSettingsView):
+        (WebInspector.SettingsTabContentView.prototype.addSettingsView):
+        (WebInspector.SettingsTabContentView.prototype._navigationItemSelected):
+        (WebInspector.SettingsTabContentView.prototype.layout): Deleted.
+        No longer needed.
+
+        * UserInterface/Views/SettingsView.js: Added.
+        Base class for displaying editing UI for a collection of related
+        WebInspector.Setting objects.
+
+        (WebInspector.SettingsView):
+        (WebInspector.SettingsView.prototype.get identifier):
+        (WebInspector.SettingsView.prototype.get displayName):
+        A string suitable for display in a NavigationBar showing a list of
+        SettingsViews (e.g. &quot;General&quot;, &quot;Text Editing&quot;, &quot;Fonts &amp; Colors&quot;, etc).
+
+        (WebInspector.SettingsView.prototype.addSetting):
+        Add UI for a setting, consisting of a title, an editor appropriate for
+        the setting's value type, and optional label and formatting options.
+        For example:
+
+            addSetting(&quot;Setting 1:&quot;, new WebInspector.Setting(…, true), &quot;Item one&quot;)
+            addSetting(&quot;Setting 2:&quot;, new WebInspector.Setting(…, 1), &quot;units&quot;)
+
+        will create a checkbox and number input field:
+
+            Setting 1: [x] Item one
+            Setting 2: [  1] units
+
+        (WebInspector.SettingsView.prototype.addCustomSetting):
+        Add UI for a specific editor type, with optional formatting options.
+        A setting can be updated in response to changes in the editor's value.
+
+        (WebInspector.SettingsView.prototype.addGroup):
+        Add a group, for listing multiple settings under one title. For example:
+
+           group = addGroup(&quot;Title:&quot;)
+           group.addSetting(new WebInspector.Setting(…, true), &quot;Item one&quot;)
+           group.addSetting(new WebInspector.Setting(…, false), &quot;Item two&quot;)
+
+        will create two checkboxes under the same title:
+
+           Title: [x] Item one
+                  [ ] Item two
+
+        (WebInspector.SettingsView.prototype.addSeparator):
+        Add vertical space between two settings or groups.
+
</ins><span class="cx"> 2017-04-10  Nikita Vasilyev  &lt;nvasilyev@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: WebSockets: Don't clip data in the data grid
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (215255 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2017-04-11 23:24:26 UTC (rev 215255)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -408,6 +408,7 @@
</span><span class="cx"> localizedStrings[&quot;Function&quot;] = &quot;Function&quot;;
</span><span class="cx"> localizedStrings[&quot;Function Name Variable&quot;] = &quot;Function Name Variable&quot;;
</span><span class="cx"> localizedStrings[&quot;Garbage Collection&quot;] = &quot;Garbage Collection&quot;;
</span><ins>+localizedStrings[&quot;General&quot;] = &quot;General&quot;;
</ins><span class="cx"> localizedStrings[&quot;Getter&quot;] = &quot;Getter&quot;;
</span><span class="cx"> localizedStrings[&quot;Global Code&quot;] = &quot;Global Code&quot;;
</span><span class="cx"> localizedStrings[&quot;Global Lexical Environment&quot;] = &quot;Global Lexical Environment&quot;;
</span><span class="lines">@@ -461,7 +462,7 @@
</span><span class="cx"> localizedStrings[&quot;Inset&quot;] = &quot;Inset&quot;;
</span><span class="cx"> localizedStrings[&quot;Instances&quot;] = &quot;Instances&quot;;
</span><span class="cx"> localizedStrings[&quot;Invalid&quot;] = &quot;Invalid&quot;;
</span><del>-localizedStrings[&quot;Invalid Characters:&quot;] = &quot;Invalid Characters:&quot;;
</del><ins>+localizedStrings[&quot;Invalid characters&quot;] = &quot;Invalid characters&quot;;
</ins><span class="cx"> localizedStrings[&quot;Inverted&quot;] = &quot;Inverted&quot;;
</span><span class="cx"> localizedStrings[&quot;Invoke getter&quot;] = &quot;Invoke getter&quot;;
</span><span class="cx"> localizedStrings[&quot;Iterations&quot;] = &quot;Iterations&quot;;
</span><span class="lines">@@ -757,6 +758,7 @@
</span><span class="cx"> localizedStrings[&quot;Show the navigation sidebar (%s)&quot;] = &quot;Show the navigation sidebar (%s)&quot;;
</span><span class="cx"> localizedStrings[&quot;Show type information&quot;] = &quot;Show type information&quot;;
</span><span class="cx"> localizedStrings[&quot;Show warnings logged to the Console&quot;] = &quot;Show warnings logged to the Console&quot;;
</span><ins>+localizedStrings[&quot;Show:&quot;] = &quot;Show:&quot;;
</ins><span class="cx"> localizedStrings[&quot;Shrink&quot;] = &quot;Shrink&quot;;
</span><span class="cx"> localizedStrings[&quot;Size&quot;] = &quot;Size&quot;;
</span><span class="cx"> localizedStrings[&quot;Size of current object plus all objects it keeps alive&quot;] = &quot;Size of current object plus all objects it keeps alive&quot;;
</span><span class="lines">@@ -888,7 +890,6 @@
</span><span class="cx"> localizedStrings[&quot;Vertical&quot;] = &quot;Vertical&quot;;
</span><span class="cx"> localizedStrings[&quot;View variable value&quot;] = &quot;View variable value&quot;;
</span><span class="cx"> localizedStrings[&quot;Visibility&quot;] = &quot;Visibility&quot;;
</span><del>-localizedStrings[&quot;Visible&quot;] = &quot;Visible&quot;;
</del><span class="cx"> localizedStrings[&quot;Waiting to be upgraded&quot;] = &quot;Waiting to be upgraded&quot;;
</span><span class="cx"> localizedStrings[&quot;Warning: &quot;] = &quot;Warning: &quot;;
</span><span class="cx"> localizedStrings[&quot;Warnings&quot;] = &quot;Warnings&quot;;
</span><span class="lines">@@ -897,7 +898,7 @@
</span><span class="cx"> localizedStrings[&quot;WebSocket Connection Established&quot;] = &quot;WebSocket Connection Established&quot;;
</span><span class="cx"> localizedStrings[&quot;Weight&quot;] = &quot;Weight&quot;;
</span><span class="cx"> localizedStrings[&quot;Whitespace&quot;] = &quot;Whitespace&quot;;
</span><del>-localizedStrings[&quot;Whitespace Characters:&quot;] = &quot;Whitespace Characters:&quot;;
</del><ins>+localizedStrings[&quot;Whitespace characters&quot;] = &quot;Whitespace characters&quot;;
</ins><span class="cx"> localizedStrings[&quot;Width&quot;] = &quot;Width&quot;;
</span><span class="cx"> localizedStrings[&quot;With Object Properties&quot;] = &quot;With Object Properties&quot;;
</span><span class="cx"> localizedStrings[&quot;Word&quot;] = &quot;Word&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (215255 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2017-04-11 23:24:26 UTC (rev 215255)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -482,6 +482,12 @@
</span><span class="cx">     &lt;script src=&quot;Views/DetailsSectionSimpleRow.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/DetailsSectionTextRow.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> 
</span><ins>+    &lt;script src=&quot;Views/SettingEditor.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Views/SettingsGroup.js&quot;&gt;&lt;/script&gt;
+    &lt;script src=&quot;Views/SettingsView.js&quot;&gt;&lt;/script&gt;
+
+    &lt;script src=&quot;Views/GeneralSettingsView.js&quot;&gt;&lt;/script&gt;
+
</ins><span class="cx">     &lt;script src=&quot;Views/ActivateButtonNavigationItem.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/ActivateButtonToolbarItem.js&quot;&gt;&lt;/script&gt;
</span><span class="cx">     &lt;script src=&quot;Views/ApplicationCacheDetailsSidebarPanel.js&quot;&gt;&lt;/script&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsGeneralSettingsViewjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/GeneralSettingsView.js (0 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/GeneralSettingsView.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/GeneralSettingsView.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.GeneralSettingsView = class GeneralSettingsView extends WebInspector.SettingsView
+{
+    constructor()
+    {
+        super(&quot;general&quot;, WebInspector.UIString(&quot;General&quot;));
+    }
+
+    // Protected
+
+    initialLayout()
+    {
+        const indentValues = [WebInspector.UIString(&quot;Tabs&quot;), WebInspector.UIString(&quot;Spaces&quot;)];
+
+        let indentEditor = this.addCustomSetting(WebInspector.UIString(&quot;Prefer indent using:&quot;), WebInspector.SettingEditor.Type.Select, {values: indentValues});
+        indentEditor.value = indentValues[WebInspector.settings.indentWithTabs.value ? 0 : 1];
+        indentEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () =&gt; {
+            WebInspector.settings.indentWithTabs.value = indentEditor.value === indentValues[0];
+        });
+
+        const widthLabel = WebInspector.UIString(&quot;spaces&quot;);
+        const widthOptions = {min: 1};
+
+        this.addSetting(WebInspector.UIString(&quot;Tab width:&quot;), WebInspector.settings.tabSize, widthLabel, widthOptions);
+        this.addSetting(WebInspector.UIString(&quot;Indent width:&quot;), WebInspector.settings.indentUnit, widthLabel, widthOptions);
+
+        this.addSetting(WebInspector.UIString(&quot;Line wrapping:&quot;), WebInspector.settings.enableLineWrapping, WebInspector.UIString(&quot;Wrap lines to editor width&quot;));
+
+        let showGroup = this.addGroup(WebInspector.UIString(&quot;Show:&quot;));
+        showGroup.addSetting(WebInspector.settings.showWhitespaceCharacters, WebInspector.UIString(&quot;Whitespace characters&quot;));
+        showGroup.addSetting(WebInspector.settings.showInvalidCharacters, WebInspector.UIString(&quot;Invalid characters&quot;));
+
+        this.addSeparator();
+
+        let stylesEditingGroup = this.addGroup(WebInspector.UIString(&quot;Styles Editing:&quot;));
+        stylesEditingGroup.addSetting(WebInspector.settings.stylesShowInlineWarnings, WebInspector.UIString(&quot;Show inline warnings&quot;));
+        stylesEditingGroup.addSetting(WebInspector.settings.stylesInsertNewline, WebInspector.UIString(&quot;Automatically insert newline&quot;));
+        stylesEditingGroup.addSetting(WebInspector.settings.stylesSelectOnFirstClick, WebInspector.UIString(&quot;Select text on first click&quot;));
+
+        this.addSeparator();
+
+        this.addSetting(WebInspector.UIString(&quot;Network:&quot;), WebInspector.settings.clearNetworkOnNavigate, WebInspector.UIString(&quot;Clear when page navigates&quot;));
+
+        this.addSeparator();
+
+        this.addSetting(WebInspector.UIString(&quot;Console:&quot;), WebInspector.settings.clearLogOnNavigate, WebInspector.UIString(&quot;Clear when page navigates&quot;));
+
+        this.addSeparator();
+
+        this.addSetting(WebInspector.UIString(&quot;Debugger:&quot;), WebInspector.settings.showScopeChainOnPause, WebInspector.UIString(&quot;Show Scope Chain on pause&quot;));
+
+        this.addSeparator();
+
+        const zoomLevels = [0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4];
+        const zoomValues = zoomLevels.map((level) =&gt; [level, Number.percentageString(level, 0)]);
+
+        let zoomEditor = this.addCustomSetting(WebInspector.UIString(&quot;Zoom:&quot;), WebInspector.SettingEditor.Type.Select, {values: zoomValues});
+        zoomEditor.value = WebInspector.settings.zoomFactor.value;
+        zoomEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () =&gt; { WebInspector.setZoomFactor(zoomEditor.value); });
+
+        this.addSeparator();
+
+        const layoutDirectionValues = [
+            [WebInspector.LayoutDirection.System, WebInspector.UIString(&quot;System Default&quot;)],
+            [WebInspector.LayoutDirection.LTR, WebInspector.UIString(&quot;Left to Right (LTR)&quot;)],
+            [WebInspector.LayoutDirection.RTL, WebInspector.UIString(&quot;Right to Left (RTL)&quot;)],
+        ];
+
+        let layoutDirectionEditor = this.addCustomSetting(WebInspector.UIString(&quot;Layout Direction:&quot;), WebInspector.SettingEditor.Type.Select, {values: layoutDirectionValues});
+        layoutDirectionEditor.value = WebInspector.settings.layoutDirection.value;
+        layoutDirectionEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () =&gt; { WebInspector.setLayoutDirection(layoutDirectionEditor.value); });
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingEditorjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/SettingEditor.js (0 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingEditor.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingEditor.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SettingEditor = class SettingEditor extends WebInspector.Object
+{
+    constructor(type, label, options)
+    {
+        super();
+
+        this._type = type;
+        this._label = label;
+        this._value = null;
+
+        this._editorElement = this._createEditorElement(options);
+        console.assert(this._editorElement);
+
+        this._element = document.createElement(&quot;div&quot;);
+        this._element.classList.add(&quot;editor&quot;);
+        this._element.append(this._editorElement);
+
+        if (this._label) {
+            this._editorElement.id = &quot;setting-editor-&quot; + WebInspector.SettingEditor._nextEditorIdentifier++;
+            let labelElement = document.createElement(&quot;label&quot;);
+            labelElement.setAttribute(&quot;for&quot;, this._editorElement.id);
+            labelElement.textContent = label;
+
+            this._element.append(labelElement);
+        }
+    }
+
+    static createForSetting(setting, label, options)
+    {
+        let type;
+        if (typeof setting.value === &quot;boolean&quot;)
+            type = WebInspector.SettingEditor.Type.Checkbox;
+        else if (typeof setting.value === &quot;number&quot;)
+            type = WebInspector.SettingEditor.Type.Numeric;
+
+        console.assert(type, &quot;Cannot deduce editor type from setting value type.&quot;, setting);
+        if (!type)
+            return null;
+
+        let editor = new WebInspector.SettingEditor(type, label, options);
+        editor.value = setting.value;
+        editor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () =&gt; { setting.value = editor.value; });
+
+        return editor;
+    }
+
+    // Public
+
+    get element() { return this._element; }
+    get type() { return this._type; }
+    get label() { return this._label; }
+
+    get value()
+    {
+        return this._value;
+    }
+
+    set value(value)
+    {
+        if (this._value === value)
+            return;
+
+        let oldValue = this._value;
+        this._value = value;
+
+        if (this._type == WebInspector.SettingEditor.Type.Checkbox)
+            this._editorElement.checked = !!this._value;
+        else
+            this._editorElement.value = this._value;
+
+        this.dispatchEventToListeners(WebInspector.SettingEditor.Event.ValueDidChange, {oldValue});
+    }
+
+    // Private
+
+    _createEditorElement(options)
+    {
+        let editorElement;
+
+        switch (this._type) {
+        case WebInspector.SettingEditor.Type.Checkbox:
+            editorElement = document.createElement(&quot;input&quot;);
+            editorElement.type = &quot;checkbox&quot;;
+            editorElement.addEventListener(&quot;change&quot;, (event) =&gt; { this.value = event.target.checked; });
+            break;
+
+        case WebInspector.SettingEditor.Type.Numeric:
+            editorElement = document.createElement(&quot;input&quot;);
+            editorElement.type = &quot;number&quot;;
+
+            if (options.min !== undefined)
+                editorElement.min = options.min;
+            if (options.max !== undefined)
+                editorElement.max = options.max;
+
+            editorElement.addEventListener(&quot;change&quot;, (event) =&gt; {
+                let currentValue = this._value;
+                let newValue = parseInt(event.target.value);
+                this.value = isNaN(newValue) ? currentValue : newValue;
+            });
+            break;
+
+        case WebInspector.SettingEditor.Type.Select:
+            editorElement = document.createElement(&quot;select&quot;);
+            var keyValuePairs = [];
+
+            console.assert(Array.isArray(options.values), &quot;Expected values array for select editor.&quot;, options);
+
+            if (Array.isArray(options.values[0]))
+                keyValuePairs = options.values;
+            else
+                keyValuePairs = options.values.map((value) =&gt; [value, value]);
+
+            for (let [key, value] of keyValuePairs) {
+                let optionElement = editorElement.appendChild(document.createElement(&quot;option&quot;));
+                optionElement.value = key;
+                optionElement.textContent = value;
+            }
+
+            editorElement.addEventListener(&quot;change&quot;, (event) =&gt; { this.value = event.target.value; });
+            break;
+
+        default:
+            console.error(&quot;Unknown editor type: &quot; + this._type);
+        }
+
+        return editorElement;
+    }
+};
+
+WebInspector.SettingEditor._nextEditorIdentifier = 1;
+
+WebInspector.SettingEditor.Type = {
+    Checkbox: &quot;setting-editor-type-checkbox&quot;,
+    Numeric: &quot;setting-editor-type-numeric&quot;,
+    Select: &quot;setting-editor-type-select&quot;,
+};
+
+WebInspector.SettingEditor.Event = {
+    ValueDidChange: &quot;value-did-change&quot;,
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingsGroupjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js (0 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SettingsGroup = class SettingsGroup extends WebInspector.Object
+{
+    constructor(title)
+    {
+        super();
+
+        this._element = document.createElement(&quot;div&quot;);
+        this._element.classList.add(&quot;container&quot;);
+
+        let titleElement = this._element.appendChild(document.createElement(&quot;div&quot;));
+        titleElement.classList.add(&quot;title&quot;);
+        titleElement.textContent = title;
+
+        this._editorGroupElement = this._element.appendChild(document.createElement(&quot;div&quot;));
+        this._editorGroupElement.classList.add(&quot;editor-group&quot;);
+    }
+
+    // Public
+
+    get element() { return this._element; }
+
+    addSetting(setting, label, options)
+    {
+        let editor = WebInspector.SettingEditor.createForSetting(setting, label, options);
+        console.assert(editor, &quot;Could not create default editor for setting. Use addCustomSetting instead.&quot;, setting);
+        if (!editor)
+            return null;
+
+        this._editorGroupElement.append(editor.element);
+        return editor;
+    }
+
+    addCustomSetting(editorType, options)
+    {
+        let editor = new WebInspector.SettingEditor(editorType, options.label, options);
+        if (!editor)
+            return null;
+
+        this._editorGroupElement.append(editor.element);
+        return editor;
+    }
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css (215255 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css        2017-04-11 23:24:26 UTC (rev 215255)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -27,32 +27,29 @@
</span><span class="cx"> .content-view.settings {
</span><span class="cx">     padding: 6vh 0;
</span><span class="cx">     overflow-y: auto;
</span><del>-    background-color: hsl(0, 0%, 93%);
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .header {
-    margin: 0 auto 4vh;
-    text-align: center;
-    font-size: 32px;
-    font-weight: lighter;
</del><ins>+.content-view.settings .navigation-bar .item.radio.button.text-only {
+    color: inherit;
+    background-color: inherit;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .separator {
-    height: 2em;
</del><ins>+.content-view.settings .navigation-bar .item.radio.button.text-only.selected {
+    color: var(--selected-background-color)
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .separator {
+    height: 1em;
+}
+
+.content-view.settings &gt; .settings-view &gt; .container {
</ins><span class="cx">     display: flex;
</span><del>-    align-items: center;
</del><span class="cx">     margin-top: 1em;
</span><span class="cx">     font-size: 13px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container.combined {
-    margin-top: 0;
-}
-
-.content-view.settings &gt; .setting-container &gt; .setting-name {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .title {
+    margin-top: 2px;
</ins><span class="cx">     width: 50%;
</span><span class="cx">     text-align: end;
</span><span class="cx"> 
</span><span class="lines">@@ -59,39 +56,39 @@
</span><span class="cx">     --setting-name-margin-end: 6px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-name {
</del><ins>+body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .title {
</ins><span class="cx">     margin-right: var(--setting-name-margin-end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-name {
</del><ins>+body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .title {
</ins><span class="cx">     margin-left: var(--setting-name-margin-end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container &gt; .setting-value-controller {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group {
</ins><span class="cx">     display: flex;
</span><del>-    align-items: center;
-    width: 50%;
</del><ins>+    flex-direction: column;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container &gt; .setting-value-controller input {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input {
</ins><span class="cx">     font-size: inherit;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;] {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;] {
+    /* Vertically align &lt;select&gt; with the group title text. */
</ins><span class="cx">     font-size: 16px;
</span><span class="cx"> 
</span><span class="cx">     --settings-input-checkbox-margin-end: 4px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;] {
</del><ins>+body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;] {
</ins><span class="cx">     margin-right: var(--settings-input-checkbox-margin-end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;checkbox&quot;] {
</del><ins>+body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;checkbox&quot;] {
</ins><span class="cx">     margin-left: var(--settings-input-checkbox-margin-end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container &gt; .setting-value-controller select {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor select {
</ins><span class="cx">     /*
</span><span class="cx">     To set the font-size of &lt;select&gt; to be exactly 13px, it needs to be set to 16px.
</span><span class="cx">     Setting the font-size to 13px actually sets it to 11px.
</span><span class="lines">@@ -98,14 +95,15 @@
</span><span class="cx">     */
</span><span class="cx">     font-size: 16px;
</span><span class="cx"> 
</span><del>-    /* Vertically align &lt;select&gt; with its label text. */
-    position: relative;
-    top: 0.5px;
</del><ins>+    /* Vertically align &lt;select&gt; with the group title text. */
+    margin-top: 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-.content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;] {
</del><ins>+.content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;] {
+    /* Vertically align &lt;input&gt; with the group title text. */
+    margin-top: -1px;
+
</ins><span class="cx">     max-width: 48px;
</span><del>-    margin: 0;
</del><span class="cx">     text-align: end;
</span><span class="cx"> 
</span><span class="cx">     --settings-input-number-margin-start: 2px;
</span><span class="lines">@@ -112,12 +110,12 @@
</span><span class="cx">     --settings-input-number-margin-end: 5px;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=ltr] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;] {
</del><ins>+body[dir=ltr] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;] {
</ins><span class="cx">     margin-left: var(--settings-input-number-margin-start);
</span><span class="cx">     margin-right: var(--settings-input-number-margin-end);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-body[dir=rtl] .content-view.settings &gt; .setting-container &gt; .setting-value-controller input[type=&quot;number&quot;] {
</del><ins>+body[dir=rtl] .content-view.settings &gt; .settings-view &gt; .container &gt; .editor-group &gt; .editor input[type=&quot;number&quot;] {
</ins><span class="cx">     margin-left: var(--settings-input-number-margin-end);
</span><span class="cx">     margin-right: var(--settings-input-number-margin-start);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js (215255 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js        2017-04-11 23:24:26 UTC (rev 215255)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -38,6 +38,20 @@
</span><span class="cx">         let boundNeedsLayout = this.needsLayout.bind(this, WebInspector.View.LayoutReason.Dirty);
</span><span class="cx">         WebInspector.notifications.addEventListener(WebInspector.Notification.DebugUIEnabledDidChange, boundNeedsLayout);
</span><span class="cx">         WebInspector.settings.zoomFactor.addEventListener(WebInspector.Setting.Event.Changed, boundNeedsLayout);
</span><ins>+
+        this._navigationBar = new WebInspector.NavigationBar;
+        this._navigationBar.element.classList.add(&quot;hidden&quot;);
+        this._navigationBar.addEventListener(WebInspector.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);
+
+        this._selectedSettingsView = null;
+        this._settingsViewIdentifierMap = new Map;
+
+        this.addSubview(this._navigationBar);
+
+        let generalSettingsView = new WebInspector.GeneralSettingsView;
+        this.addSettingsView(generalSettingsView);
+
+        this.selectedSettingsView = generalSettingsView;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static tabInfo()
</span><span class="lines">@@ -60,199 +74,58 @@
</span><span class="cx"> 
</span><span class="cx">     // Public
</span><span class="cx"> 
</span><del>-    get type()
</del><ins>+    get type() { return WebInspector.SettingsTabContentView.Type; }
+
+    get selectedSettingsView()
</ins><span class="cx">     {
</span><del>-        return WebInspector.SettingsTabContentView.Type;
</del><ins>+        return this._selectedSettingsView;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    layout()
</del><ins>+    set selectedSettingsView(page)
</ins><span class="cx">     {
</span><del>-        this.element.removeChildren();
</del><ins>+        if (this._selectedSettingsView === page)
+            return;
</ins><span class="cx"> 
</span><del>-        let header = this.element.createChild(&quot;div&quot;, &quot;header&quot;);
-        header.textContent = WebInspector.UIString(&quot;Settings&quot;);
</del><ins>+        if (this._selectedSettingsView)
+            this.replaceSubview(this._selectedSettingsView, page);
+        else
+            this.addSubview(page);
</ins><span class="cx"> 
</span><del>-        let createContainer = (title, createValueController) =&gt; {
-            let container = this.element.createChild(&quot;div&quot;, &quot;setting-container&quot;);
</del><ins>+        this._selectedSettingsView = page;
+        this._selectedSettingsView.updateLayout();
</ins><span class="cx"> 
</span><del>-            let titleContainer = container.createChild(&quot;div&quot;, &quot;setting-name&quot;);
-            if (title)
-                titleContainer.textContent = title;
-            else
-                container.classList.add(&quot;combined&quot;);
</del><ins>+        this._navigationBar.selectedNavigationItem = page.identifier;
+    }
</ins><span class="cx"> 
</span><del>-            let valueControllerContainer = container.createChild(&quot;div&quot;, &quot;setting-value-controller&quot;);
-            let labelElement = valueControllerContainer.createChild(&quot;label&quot;);
-            if (typeof createValueController === &quot;function&quot;)
-                createValueController(labelElement);
-        };
</del><ins>+    addSettingsView(settingsView)
+    {
+        let identifier = settingsView.identifier;
+        console.assert(!this._settingsViewIdentifierMap.has(identifier), &quot;SettingsView already exists.&quot;, settingsView);
+        if (this._settingsViewIdentifierMap.has(identifier))
+            return;
</ins><span class="cx"> 
</span><del>-        let createCheckbox = (setting) =&gt; {
-            let checkbox = document.createElement(&quot;input&quot;);
-            checkbox.type = &quot;checkbox&quot;;
-            checkbox.checked = setting.value;
-            checkbox.addEventListener(&quot;change&quot;, (event) =&gt; {
-                setting.value = checkbox.checked;
-            });
-            return checkbox;
-        };
</del><ins>+        this._settingsViewIdentifierMap.set(identifier, settingsView);
</ins><span class="cx"> 
</span><del>-        let createSeparator = () =&gt; {
-            let separatorElement = this.element.appendChild(document.createElement(&quot;div&quot;));
-            separatorElement.classList.add(&quot;separator&quot;);
-        };
</del><ins>+        this._navigationBar.addNavigationItem(new WebInspector.RadioButtonNavigationItem(identifier, settingsView.displayName));
</ins><span class="cx"> 
</span><del>-        createContainer(WebInspector.UIString(&quot;Prefer indent using:&quot;), (valueControllerContainer) =&gt; {
-            let select = valueControllerContainer.createChild(&quot;select&quot;);
-            select.addEventListener(&quot;change&quot;, (event) =&gt; {
-                WebInspector.settings.indentWithTabs.value = select.value === &quot;tabs&quot;;
-            });
</del><ins>+        if (this._settingsViewIdentifierMap.size &gt; 1)
+            this._navigationBar.element.classList.remove(&quot;hidden&quot;);
+    }
</ins><span class="cx"> 
</span><del>-            let tabsOption = select.createChild(&quot;option&quot;);
-            tabsOption.value = &quot;tabs&quot;;
-            tabsOption.textContent = WebInspector.UIString(&quot;Tabs&quot;);
-            tabsOption.selected = WebInspector.settings.indentWithTabs.value;
</del><ins>+    // Private
</ins><span class="cx"> 
</span><del>-            let spacesOption = select.createChild(&quot;option&quot;);
-            spacesOption.value = &quot;spaces&quot;;
-            spacesOption.textContent = WebInspector.UIString(&quot;Spaces&quot;);
-            spacesOption.selected = !WebInspector.settings.indentWithTabs.value;
-        });
</del><ins>+    _navigationItemSelected(event)
+    {
+        let navigationItem = event.target.selectedNavigationItem;
+        if (!navigationItem)
+            return;
</ins><span class="cx"> 
</span><del>-        createContainer(WebInspector.UIString(&quot;Tab width:&quot;), (valueControllerContainer) =&gt; {
-            let input = valueControllerContainer.createChild(&quot;input&quot;);
-            input.type = &quot;number&quot;;
-            input.min = 1;
-            input.value = WebInspector.settings.tabSize.value;
-            input.addEventListener(&quot;change&quot;, (event) =&gt; {
-                WebInspector.settings.tabSize.value = parseInt(input.value) || 4;
-            });
</del><ins>+        let settingsView = this._settingsViewIdentifierMap.get(navigationItem.identifier);
+        console.assert(settingsView, &quot;Missing SettingsView for identifier &quot; + navigationItem.identifier);
+        if (!settingsView)
+            return;
</ins><span class="cx"> 
</span><del>-            valueControllerContainer.append(WebInspector.UIString(&quot;spaces&quot;));
-        });
-
-        createContainer(WebInspector.UIString(&quot;Indent width:&quot;), (valueControllerContainer) =&gt; {
-            let input = valueControllerContainer.createChild(&quot;input&quot;);
-            input.type = &quot;number&quot;;
-            input.min = 1;
-            input.value = WebInspector.settings.indentUnit.value;
-            input.addEventListener(&quot;change&quot;, (event) =&gt; {
-                WebInspector.settings.indentUnit.value = parseInt(input.value) || 4;
-            });
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;spaces&quot;));
-        });
-
-        createContainer(WebInspector.UIString(&quot;Line wrapping:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.enableLineWrapping);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Wrap lines to editor width&quot;));
-        });
-
-        createContainer(WebInspector.UIString(&quot;Whitespace Characters:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.showWhitespaceCharacters);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Visible&quot;));
-        });
-
-        createContainer(WebInspector.UIString(&quot;Invalid Characters:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.showInvalidCharacters);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Visible&quot;));
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Styles Editing:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.stylesShowInlineWarnings);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Show inline warnings&quot;));
-        });
-
-        createContainer(null, (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.stylesInsertNewline);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Automatically insert newline&quot;));
-        });
-
-        createContainer(null, (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.stylesSelectOnFirstClick);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Select text on first click&quot;));
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Network:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.clearNetworkOnNavigate);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Clear when page navigates&quot;));
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Console:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.clearLogOnNavigate);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Clear when page navigates&quot;));
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Debugger:&quot;), (valueControllerContainer) =&gt; {
-            let checkbox = createCheckbox(WebInspector.settings.showScopeChainOnPause);
-            valueControllerContainer.appendChild(checkbox);
-
-            valueControllerContainer.append(WebInspector.UIString(&quot;Show Scope Chain on pause&quot;));
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Zoom:&quot;), (valueControllerContainer) =&gt; {
-            let select = valueControllerContainer.createChild(&quot;select&quot;);
-            select.addEventListener(&quot;change&quot;, (event) =&gt; {
-                WebInspector.setZoomFactor(select.value);
-            });
-
-            let currentZoom = WebInspector.getZoomFactor().maxDecimals(1);
-            [0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4].forEach((level) =&gt; {
-                let option = select.createChild(&quot;option&quot;);
-                option.value = level;
-                option.textContent = Number.percentageString(level, 0);
-                option.selected = currentZoom === level;
-            });
-        });
-
-        createSeparator();
-
-        createContainer(WebInspector.UIString(&quot;Layout Direction:&quot;), (valueControllerContainer) =&gt; {
-            let selectElement = valueControllerContainer.appendChild(document.createElement(&quot;select&quot;));
-            selectElement.addEventListener(&quot;change&quot;, (event) =&gt; {
-                WebInspector.setLayoutDirection(selectElement.value);
-            });
-
-            let currentLayoutDirection = WebInspector.settings.layoutDirection.value;
-            let options = new Map([
-                [WebInspector.LayoutDirection.System, WebInspector.UIString(&quot;System Default&quot;)],
-                [WebInspector.LayoutDirection.LTR, WebInspector.UIString(&quot;Left to Right (LTR)&quot;)],
-                [WebInspector.LayoutDirection.RTL, WebInspector.UIString(&quot;Right to Left (RTL)&quot;)],
-            ]);
-
-            for (let [key, value] of options) {
-                let optionElement = selectElement.appendChild(document.createElement(&quot;option&quot;));
-                optionElement.value = key;
-                optionElement.textContent = value;
-                optionElement.selected = currentLayoutDirection === key;
-            }
-        });
</del><ins>+        this.selectedSettingsView = settingsView;
</ins><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsSettingsViewjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/SettingsView.js (0 => 215256)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/SettingsView.js                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/SettingsView.js        2017-04-12 03:05:34 UTC (rev 215256)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.SettingsView = class SettingsView extends WebInspector.View
+{
+    constructor(identifier, displayName)
+    {
+        super();
+
+        this._identifier = identifier;
+        this._displayName = displayName;
+
+        this.element.classList.add(&quot;settings-view&quot;, identifier);
+    }
+
+    // Public
+
+    get identifier() { return this._identifier; }
+    get displayName() { return this._displayName; }
+
+    addSetting(title, setting, label, options)
+    {
+        let settingsGroup = this.addGroup(title);
+        return settingsGroup.addSetting(setting, label, options);
+    }
+
+    addCustomSetting(title, editorType, options)
+    {
+        let settingsGroup = this.addGroup(title);
+        return settingsGroup.addCustomSetting(editorType, options);
+    }
+
+    addGroup(title)
+    {
+        let settingsGroup = new WebInspector.SettingsGroup(title);
+        this.element.append(settingsGroup.element);
+
+        return settingsGroup;
+    }
+
+    addSeparator()
+    {
+        if (this.element.lastChild &amp;&amp; this.element.lastChild.classList.contains(&quot;separator&quot;))
+            return;
+
+        let separatorElement = this.element.appendChild(document.createElement(&quot;div&quot;));
+        separatorElement.classList.add(&quot;separator&quot;);
+    }
+};
+
+WebInspector.SettingsView.EditorType = {
+    Checkbox: &quot;settings-view-editor-type-checkbox&quot;,
+    Numeric: &quot;settings-view-editor-type-numeric&quot;,
+    Select: &quot;settings-view-editor-type-select&quot;,
+};
</ins></span></pre>
</div>
</div>

</body>
</html>