Source/WebInspectorUI/ChangeLog

 12017-04-06 Matt Baker <mattbaker@apple.com>
 2
 3 Web Inspector: checkboxes in Settings screen use inappropriate layout
 4 https://bugs.webkit.org/show_bug.cgi?id=166993
 5 <rdar://problem/30002272>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * Localizations/en.lproj/localizedStrings.js:
 10 New checkbox setting strings.
 11
 12 * UserInterface/Main.html:
 13 New settings view classes.
 14
 15 * UserInterface/Views/GeneralSettingsView.js: Added.
 16 (WebInspector.GeneralSettingsView):
 17 (WebInspector.GeneralSettingsView.prototype.initialLayout):
 18 Move settings UI creation from SettingsTabContentView.
 19
 20 * UserInterface/Views/SettingEditor.js: Added.
 21 Basic setting editor UI for the following input types: checkbox,
 22 number, and select. In the future it may be useful to include
 23 additional types, such as radio buttons.
 24
 25 (WebInspector.SettingEditor):
 26 (WebInspector.SettingEditor.createForSetting):
 27 (WebInspector.SettingEditor.prototype.get element):
 28 (WebInspector.SettingEditor.prototype.get type):
 29 (WebInspector.SettingEditor.prototype.get label):
 30 (WebInspector.SettingEditor.prototype.get value):
 31 (WebInspector.SettingEditor.prototype.set value):
 32 (WebInspector.SettingEditor.prototype._createEditorElement):
 33
 34 * UserInterface/Views/SettingsGroup.js: Added.
 35 A container holding editors for one or more WebInspector.Settings.
 36 Every editor belongs to a group. SettingsView provides convenience
 37 methods for adding settings and groups, so create instances directly
 38 shouldn't normally be necessary.
 39
 40 (WebInspector.SettingsGroup):
 41 (WebInspector.SettingsGroup.prototype.get element):
 42 (WebInspector.SettingsGroup.prototype.addSetting):
 43 (WebInspector.SettingsGroup.prototype.addCustomSetting):
 44
 45 * UserInterface/Views/SettingsTabContentView.css:
 46 Refactored styles to more closely match Xcode settings UI.
 47 Eliminated redundant use of "setting" from CSS class names.
 48
 49 (.content-view.settings):
 50 (.content-view.settings .navigation-bar .item.radio.button.text-only):
 51 (.content-view.settings .navigation-bar .item.radio.button.text-only.selected):
 52 (.content-view.settings > .settings-view > .separator):
 53 (.content-view.settings > .settings-view > .container):
 54 (.content-view.settings > .settings-view > .container > .title):
 55 (body[dir=ltr] .content-view.settings > .settings-view > .container > .title):
 56 (body[dir=rtl] .content-view.settings > .settings-view > .container > .title):
 57 (.content-view.settings > .settings-view > .container > .editor-group):
 58 (.content-view.settings > .settings-view > .container > .editor-group > .editor input):
 59 (.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"]):
 60 (body[dir=ltr] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"]):
 61 (body[dir=rtl] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"]):
 62 (.content-view.settings > .settings-view > .container > .editor-group > .editor select):
 63 (.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"]):
 64 (body[dir=ltr] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"]):
 65 (body[dir=rtl] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"]):
 66 (.content-view.settings > .header): Deleted.
 67 (.content-view.settings > .separator): Deleted.
 68 (.content-view.settings > .setting-container): Deleted.
 69 (.content-view.settings > .setting-container.combined): Deleted.
 70 (.content-view.settings > .setting-container > .setting-name): Deleted.
 71 (body[dir=ltr] .content-view.settings > .setting-container > .setting-name): Deleted.
 72 (body[dir=rtl] .content-view.settings > .setting-container > .setting-name): Deleted.
 73 (.content-view.settings > .setting-container > .setting-value-controller): Deleted.
 74 (.content-view.settings > .setting-container > .setting-value-controller input): Deleted.
 75 (.content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"]): Deleted.
 76 (body[dir=ltr] .content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"]): Deleted.
 77 (body[dir=rtl] .content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"]): Deleted.
 78 (.content-view.settings > .setting-container > .setting-value-controller select): Deleted.
 79 (.content-view.settings > .setting-container > .setting-value-controller input[type="number"]): Deleted.
 80 (body[dir=ltr] .content-view.settings > .setting-container > .setting-value-controller input[type="number"]): Deleted.
 81 (body[dir=rtl] .content-view.settings > .setting-container > .setting-value-controller input[type="number"]): Deleted.
 82
 83 * UserInterface/Views/SettingsTabContentView.js:
 84 To better organize the growing number of settings, multiple settings views
 85 are now supported, with a navigation bar for switching between them. For
 86 now there is a single "General" setting view, and and the navigation bar
 87 is hidden. Adding a second view will cause the bar to be shown.
 88
 89 (WebInspector.SettingsTabContentView):
 90 (WebInspector.SettingsTabContentView.prototype.get type):
 91 (WebInspector.SettingsTabContentView.prototype.get selectedSettingsView):
 92 (WebInspector.SettingsTabContentView.prototype.set selectedSettingsView):
 93 (WebInspector.SettingsTabContentView.prototype.addSettingsView):
 94 (WebInspector.SettingsTabContentView.prototype._navigationItemSelected):
 95 (WebInspector.SettingsTabContentView.prototype.layout): Deleted.
 96 No longer needed.
 97
 98 * UserInterface/Views/SettingsView.js: Added.
 99 Base class for displaying editing UI for a collection of related
 100 WebInspector.Setting objects.
 101
 102 (WebInspector.SettingsView):
 103 (WebInspector.SettingsView.prototype.get identifier):
 104 (WebInspector.SettingsView.prototype.get displayName):
 105 A string suitable for display in a NavigationBar showing a list of
 106 SettingsViews (e.g. "General", "Text Editing", "Fonts & Colors", etc).
 107
 108 (WebInspector.SettingsView.prototype.addSetting):
 109 Add UI for a setting, consisting of a title, an editor appropriate for
 110 the setting's value type, and optional label and formatting options.
 111 For example:
 112
 113 addSetting("Setting 1:", new WebInspector.Setting(…, true), "Item one")
 114 addSetting("Setting 2:", new WebInspector.Setting(…, 1), "units")
 115
 116 will create a checkbox and number input field:
 117
 118 Setting 1: [x] Item one
 119 Setting 2: [ 1] units
 120
 121 (WebInspector.SettingsView.prototype.addCustomSetting):
 122 Add UI for a specific editor type, with optional formatting options.
 123 A setting can be updated in response to changes in the editor's value.
 124
 125 (WebInspector.SettingsView.prototype.addGroup):
 126 Add a group, for listing multiple settings under one title. For example:
 127
 128 group = addGroup("Title:")
 129 group.addSetting(new WebInspector.Setting(…, true), "Item one")
 130 group.addSetting(new WebInspector.Setting(…, false), "Item two")
 131
 132 will create two checkboxes under the same title:
 133
 134 Title: [x] Item one
 135 [ ] Item two
 136
 137 (WebInspector.SettingsView.prototype.addSeparator):
 138 Add vertical space between two settings or groups.
 139
11402017-04-05 Matt Baker <mattbaker@apple.com>
2141
3142 Web Inspector: XHR breakpoints should be global

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["Full URL"] = "Full URL";
408408localizedStrings["Function"] = "Function";
409409localizedStrings["Function Name Variable"] = "Function Name Variable";
410410localizedStrings["Garbage Collection"] = "Garbage Collection";
 411localizedStrings["General"] = "General";
411412localizedStrings["Getter"] = "Getter";
412413localizedStrings["Global Code"] = "Global Code";
413414localizedStrings["Global Lexical Environment"] = "Global Lexical Environment";

@@localizedStrings["Input: "] = "Input: ";
461462localizedStrings["Inset"] = "Inset";
462463localizedStrings["Instances"] = "Instances";
463464localizedStrings["Invalid"] = "Invalid";
464 localizedStrings["Invalid Characters:"] = "Invalid Characters:";
 465localizedStrings["Invalid characters"] = "Invalid characters";
465466localizedStrings["Inverted"] = "Inverted";
466467localizedStrings["Invoke getter"] = "Invoke getter";
467468localizedStrings["Iterations"] = "Iterations";

@@localizedStrings["Show the details sidebar (%s)"] = "Show the details sidebar (%
757758localizedStrings["Show the navigation sidebar (%s)"] = "Show the navigation sidebar (%s)";
758759localizedStrings["Show type information"] = "Show type information";
759760localizedStrings["Show warnings logged to the Console"] = "Show warnings logged to the Console";
 761localizedStrings["Show:"] = "Show:";
760762localizedStrings["Shrink"] = "Shrink";
761763localizedStrings["Size"] = "Size";
762764localizedStrings["Size of current object plus all objects it keeps alive"] = "Size of current object plus all objects it keeps alive";

@@localizedStrings["Version"] = "Version";
888890localizedStrings["Vertical"] = "Vertical";
889891localizedStrings["View variable value"] = "View variable value";
890892localizedStrings["Visibility"] = "Visibility";
891 localizedStrings["Visible"] = "Visible";
892893localizedStrings["Waiting to be upgraded"] = "Waiting to be upgraded";
893894localizedStrings["Warning: "] = "Warning: ";
894895localizedStrings["Warnings"] = "Warnings";

@@localizedStrings["Web Inspector"] = "Web Inspector";
897898localizedStrings["WebSocket Connection Established"] = "WebSocket Connection Established";
898899localizedStrings["Weight"] = "Weight";
899900localizedStrings["Whitespace"] = "Whitespace";
900 localizedStrings["Whitespace Characters:"] = "Whitespace Characters:";
 901localizedStrings["Whitespace characters"] = "Whitespace characters";
901902localizedStrings["Width"] = "Width";
902903localizedStrings["With Object Properties"] = "With Object Properties";
903904localizedStrings["Word"] = "Word";

Source/WebInspectorUI/UserInterface/Main.html

481481 <script src="Views/DetailsSectionSimpleRow.js"></script>
482482 <script src="Views/DetailsSectionTextRow.js"></script>
483483
 484 <script src="Views/SettingEditor.js"></script>
 485 <script src="Views/SettingsGroup.js"></script>
 486 <script src="Views/SettingsView.js"></script>
 487
 488 <script src="Views/GeneralSettingsView.js"></script>
 489
484490 <script src="Views/ActivateButtonNavigationItem.js"></script>
485491 <script src="Views/ActivateButtonToolbarItem.js"></script>
486492 <script src="Views/ApplicationCacheDetailsSidebarPanel.js"></script>

Source/WebInspectorUI/UserInterface/Views/GeneralSettingsView.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.GeneralSettingsView = class GeneralSettingsView extends WebInspector.SettingsView
 27{
 28 constructor()
 29 {
 30 super("general", WebInspector.UIString("General"));
 31 }
 32
 33 // Protected
 34
 35 initialLayout()
 36 {
 37 const indentValues = [WebInspector.UIString("Tabs"), WebInspector.UIString("Spaces")];
 38
 39 let indentEditor = this.addCustomSetting(WebInspector.UIString("Prefer indent using:"), WebInspector.SettingEditor.Type.Select, {values: indentValues});
 40 indentEditor.value = indentValues[WebInspector.settings.indentWithTabs.value ? 0 : 1];
 41 indentEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () => {
 42 WebInspector.settings.indentWithTabs.value = indentEditor.value === indentValues[0];
 43 });
 44
 45 const widthLabel = WebInspector.UIString("spaces");
 46 const widthOptions = {min: 1};
 47
 48 this.addSetting(WebInspector.UIString("Tab width:"), WebInspector.settings.tabSize, widthLabel, widthOptions);
 49 this.addSetting(WebInspector.UIString("Indent width:"), WebInspector.settings.indentUnit, widthLabel, widthOptions);
 50
 51 this.addSetting(WebInspector.UIString("Line wrapping:"), WebInspector.settings.enableLineWrapping, WebInspector.UIString("Wrap lines to editor width"));
 52
 53 let showGroup = this.addGroup(WebInspector.UIString("Show:"));
 54 showGroup.addSetting(WebInspector.settings.showWhitespaceCharacters, WebInspector.UIString("Whitespace characters"));
 55 showGroup.addSetting(WebInspector.settings.showInvalidCharacters, WebInspector.UIString("Invalid characters"));
 56
 57 this.addSeparator();
 58
 59 let stylesEditingGroup = this.addGroup(WebInspector.UIString("Styles Editing:"));
 60 stylesEditingGroup.addSetting(WebInspector.settings.stylesShowInlineWarnings, WebInspector.UIString("Show inline warnings"));
 61 stylesEditingGroup.addSetting(WebInspector.settings.stylesInsertNewline, WebInspector.UIString("Automatically insert newline"));
 62 stylesEditingGroup.addSetting(WebInspector.settings.stylesSelectOnFirstClick, WebInspector.UIString("Select text on first click"));
 63
 64 this.addSeparator();
 65
 66 this.addSetting(WebInspector.UIString("Network:"), WebInspector.settings.clearNetworkOnNavigate, WebInspector.UIString("Clear when page navigates"));
 67
 68 this.addSeparator();
 69
 70 this.addSetting(WebInspector.UIString("Console:"), WebInspector.settings.clearLogOnNavigate, WebInspector.UIString("Clear when page navigates"));
 71
 72 this.addSeparator();
 73
 74 this.addSetting(WebInspector.UIString("Debugger:"), WebInspector.settings.showScopeChainOnPause, WebInspector.UIString("Show Scope Chain on pause"));
 75
 76 this.addSeparator();
 77
 78 const zoomLevels = [0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4];
 79 const zoomValues = zoomLevels.map((level) => [level, Number.percentageString(level, 0)]);
 80
 81 let zoomEditor = this.addCustomSetting(WebInspector.UIString("Zoom:"), WebInspector.SettingEditor.Type.Select, {values: zoomValues});
 82 zoomEditor.value = WebInspector.settings.zoomFactor.value;
 83 zoomEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () => { WebInspector.setZoomFactor(zoomEditor.value); });
 84
 85 this.addSeparator();
 86
 87 const layoutDirectionValues = [
 88 [WebInspector.LayoutDirection.System, WebInspector.UIString("System Default")],
 89 [WebInspector.LayoutDirection.LTR, WebInspector.UIString("Left to Right (LTR)")],
 90 [WebInspector.LayoutDirection.RTL, WebInspector.UIString("Right to Left (RTL)")],
 91 ];
 92
 93 let layoutDirectionEditor = this.addCustomSetting(WebInspector.UIString("Layout Direction:"), WebInspector.SettingEditor.Type.Select, {values: layoutDirectionValues});
 94 layoutDirectionEditor.value = WebInspector.settings.layoutDirection.value;
 95 layoutDirectionEditor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () => { WebInspector.setLayoutDirection(layoutDirectionEditor.value); });
 96 }
 97};

Source/WebInspectorUI/UserInterface/Views/SettingEditor.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.SettingEditor = class SettingEditor extends WebInspector.Object
 27{
 28 constructor(type, label, options)
 29 {
 30 super();
 31
 32 this._type = type;
 33 this._label = label;
 34 this._value = null;
 35
 36 this._editorElement = this._createEditorElement(options);
 37 console.assert(this._editorElement);
 38
 39 this._element = document.createElement("div");
 40 this._element.classList.add("editor");
 41 this._element.append(this._editorElement);
 42
 43 if (this._label) {
 44 this._editorElement.id = "setting-editor-" + WebInspector.SettingEditor._nextEditorIdentifier++;
 45 let labelElement = document.createElement("label");
 46 labelElement.setAttribute("for", this._editorElement.id);
 47 labelElement.textContent = label;
 48
 49 this._element.append(labelElement);
 50 }
 51 }
 52
 53 static createForSetting(setting, label, options)
 54 {
 55 let type;
 56 if (typeof setting.value === "boolean")
 57 type = WebInspector.SettingEditor.Type.Checkbox;
 58 else if (typeof setting.value === "number")
 59 type = WebInspector.SettingEditor.Type.Numeric;
 60
 61 console.assert(type, "Cannot deduce editor type from setting value type.", setting);
 62 if (!type)
 63 return null;
 64
 65 let editor = new WebInspector.SettingEditor(type, label, options);
 66 editor.value = setting.value;
 67 editor.addEventListener(WebInspector.SettingEditor.Event.ValueDidChange, () => { setting.value = editor.value; });
 68
 69 return editor;
 70 }
 71
 72 // Public
 73
 74 get element() { return this._element; }
 75 get type() { return this._type; }
 76 get label() { return this._label; }
 77
 78 get value()
 79 {
 80 return this._value;
 81 }
 82
 83 set value(value)
 84 {
 85 if (this._value === value)
 86 return;
 87
 88 let oldValue = this._value;
 89 this._value = value;
 90
 91 if (this._type == WebInspector.SettingEditor.Type.Checkbox)
 92 this._editorElement.checked = !!this._value;
 93 else
 94 this._editorElement.value = this._value;
 95
 96 this.dispatchEventToListeners(WebInspector.SettingEditor.Event.ValueDidChange, {oldValue});
 97 }
 98
 99 // Private
 100
 101 _createEditorElement(options)
 102 {
 103 let editorElement;
 104
 105 switch (this._type) {
 106 case WebInspector.SettingEditor.Type.Checkbox:
 107 editorElement = document.createElement("input");
 108 editorElement.type = "checkbox";
 109 editorElement.addEventListener("change", (event) => { this.value = event.target.checked; });
 110 break;
 111
 112 case WebInspector.SettingEditor.Type.Numeric:
 113 editorElement = document.createElement("input");
 114 editorElement.type = "number";
 115
 116 if (options.min !== undefined)
 117 editorElement.min = options.min;
 118 if (options.max !== undefined)
 119 editorElement.max = options.max;
 120
 121 editorElement.addEventListener("change", (event) => {
 122 let currentValue = this._value;
 123 let newValue = parseInt(event.target.value);
 124 this.value = isNaN(newValue) ? currentValue : newValue;
 125 });
 126 break;
 127
 128 case WebInspector.SettingEditor.Type.Select:
 129 editorElement = document.createElement("select");
 130 let keyValuePairs = [];
 131
 132 console.assert(Array.isArray(options.values), "Expected values array for select editor.", options);
 133
 134 if (Array.isArray(options.values[0]))
 135 keyValuePairs = options.values;
 136 else
 137 keyValuePairs = options.values.map((value) => [value, value]);
 138
 139 for (let [key, value] of keyValuePairs) {
 140 let optionElement = editorElement.appendChild(document.createElement("option"));
 141 optionElement.value = key;
 142 optionElement.textContent = value;
 143 }
 144
 145 editorElement.addEventListener("change", (event) => { this.value = event.target.value; });
 146 break;
 147
 148 default:
 149 console.error("Unknown editor type: " + this._type);
 150 }
 151
 152 return editorElement;
 153 }
 154};
 155
 156WebInspector.SettingEditor._nextEditorIdentifier = 1;
 157
 158WebInspector.SettingEditor.Type = {
 159 Checkbox: "setting-editor-type-checkbox",
 160 Numeric: "setting-editor-type-numeric",
 161 Select: "setting-editor-type-select",
 162};
 163
 164WebInspector.SettingEditor.Event = {
 165 ValueDidChange: "value-did-change",
 166};

Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.SettingsGroup = class SettingsGroup extends WebInspector.Object
 27{
 28 constructor(title)
 29 {
 30 super();
 31
 32 this._element = document.createElement("div");
 33 this._element.classList.add("container");
 34
 35 let titleElement = this._element.appendChild(document.createElement("div"));
 36 titleElement.classList.add("title");
 37 titleElement.textContent = title;
 38
 39 this._editorGroupElement = this._element.appendChild(document.createElement("div"));
 40 this._editorGroupElement.classList.add("editor-group");
 41 }
 42
 43 // Public
 44
 45 get element() { return this._element; }
 46
 47 addSetting(setting, label, options)
 48 {
 49 let editor = WebInspector.SettingEditor.createForSetting(setting, label, options);
 50 console.assert(editor, "Could not create default editor for setting. Use addCustomSetting instead.", setting);
 51 if (!editor)
 52 return null;
 53
 54 this._editorGroupElement.append(editor.element);
 55 return editor;
 56 }
 57
 58 addCustomSetting(editorType, options)
 59 {
 60 let editor = new WebInspector.SettingEditor(editorType, options.label, options);
 61 if (!editor)
 62 return null;
 63
 64 this._editorGroupElement.append(editor.element);
 65 return editor;
 66 }
 67};

Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css

2727.content-view.settings {
2828 padding: 6vh 0;
2929 overflow-y: auto;
30  background-color: hsl(0, 0%, 93%);
3130}
3231
33 .content-view.settings > .header {
34  margin: 0 auto 4vh;
35  text-align: center;
36  font-size: 32px;
37  font-weight: lighter;
 32.content-view.settings .navigation-bar .item.radio.button.text-only {
 33 color: inherit;
 34 background-color: inherit;
3835}
3936
40 .content-view.settings > .separator {
41  height: 2em;
 37.content-view.settings .navigation-bar .item.radio.button.text-only.selected {
 38 color: var(--selected-background-color)
4239}
4340
44 .content-view.settings > .setting-container {
 41.content-view.settings > .settings-view > .separator {
 42 height: 1em;
 43}
 44
 45.content-view.settings > .settings-view > .container {
4546 display: flex;
46  align-items: center;
4747 margin-top: 1em;
4848 font-size: 13px;
4949}
5050
51 .content-view.settings > .setting-container.combined {
52  margin-top: 0;
53 }
54 
55 .content-view.settings > .setting-container > .setting-name {
 51.content-view.settings > .settings-view > .container > .title {
 52 margin-top: 2px;
5653 width: 50%;
5754 text-align: end;
5855
5956 --setting-name-margin-end: 6px;
6057}
6158
62 body[dir=ltr] .content-view.settings > .setting-container > .setting-name {
 59body[dir=ltr] .content-view.settings > .settings-view > .container > .title {
6360 margin-right: var(--setting-name-margin-end);
6461}
6562
66 body[dir=rtl] .content-view.settings > .setting-container > .setting-name {
 63body[dir=rtl] .content-view.settings > .settings-view > .container > .title {
6764 margin-left: var(--setting-name-margin-end);
6865}
6966
70 .content-view.settings > .setting-container > .setting-value-controller {
 67.content-view.settings > .settings-view > .container > .editor-group {
7168 display: flex;
72  align-items: center;
73  width: 50%;
 69 flex-direction: column;
7470}
7571
76 .content-view.settings > .setting-container > .setting-value-controller input {
 72.content-view.settings > .settings-view > .container > .editor-group > .editor input {
7773 font-size: inherit;
7874}
7975
80 .content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"] {
 76.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"] {
 77 /* Vertically align <select> with the group title text. */
8178 font-size: 16px;
8279
8380 --settings-input-checkbox-margin-end: 4px;
8481}
8582
86 body[dir=ltr] .content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"] {
 83body[dir=ltr] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"] {
8784 margin-right: var(--settings-input-checkbox-margin-end);
8885}
8986
90 body[dir=rtl] .content-view.settings > .setting-container > .setting-value-controller input[type="checkbox"] {
 87body[dir=rtl] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="checkbox"] {
9188 margin-left: var(--settings-input-checkbox-margin-end);
9289}
9390
94 .content-view.settings > .setting-container > .setting-value-controller select {
 91.content-view.settings > .settings-view > .container > .editor-group > .editor select {
9592 /*
9693 To set the font-size of <select> to be exactly 13px, it needs to be set to 16px.
9794 Setting the font-size to 13px actually sets it to 11px.
9895 */
9996 font-size: 16px;
10097
101  /* Vertically align <select> with its label text. */
102  position: relative;
103  top: 0.5px;
 98 /* Vertically align <select> with the group title text. */
 99 margin-top: 0;
104100}
105101
106 .content-view.settings > .setting-container > .setting-value-controller input[type="number"] {
 102.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"] {
 103 /* Vertically align <input> with the group title text. */
 104 margin-top: -1px;
 105
107106 max-width: 48px;
108  margin: 0;
109107 text-align: end;
110108
111109 --settings-input-number-margin-start: 2px;
112110 --settings-input-number-margin-end: 5px;
113111}
114112
115 body[dir=ltr] .content-view.settings > .setting-container > .setting-value-controller input[type="number"] {
 113body[dir=ltr] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"] {
116114 margin-left: var(--settings-input-number-margin-start);
117115 margin-right: var(--settings-input-number-margin-end);
118116}
119117
120 body[dir=rtl] .content-view.settings > .setting-container > .setting-value-controller input[type="number"] {
 118body[dir=rtl] .content-view.settings > .settings-view > .container > .editor-group > .editor input[type="number"] {
121119 margin-left: var(--settings-input-number-margin-end);
122120 margin-right: var(--settings-input-number-margin-start);
123121}

Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js

@@WebInspector.SettingsTabContentView = class SettingsTabContentView extends WebIn
3838 let boundNeedsLayout = this.needsLayout.bind(this, WebInspector.View.LayoutReason.Dirty);
3939 WebInspector.notifications.addEventListener(WebInspector.Notification.DebugUIEnabledDidChange, boundNeedsLayout);
4040 WebInspector.settings.zoomFactor.addEventListener(WebInspector.Setting.Event.Changed, boundNeedsLayout);
 41
 42 this._navigationBar = new WebInspector.NavigationBar;
 43 this._navigationBar.element.classList.add("hidden");
 44 this._navigationBar.addEventListener(WebInspector.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);
 45
 46 this._selectedSettingsView = null;
 47 this._settingsViewIdentifierMap = new Map;
 48
 49 this.addSubview(this._navigationBar);
 50
 51 let generalSettingsView = new WebInspector.GeneralSettingsView;
 52 this.addSettingsView(generalSettingsView);
 53
 54 this.selectedSettingsView = generalSettingsView;
4155 }
4256
4357 static tabInfo()

@@WebInspector.SettingsTabContentView = class SettingsTabContentView extends WebIn
6074
6175 // Public
6276
63  get type()
 77 get type() { return WebInspector.SettingsTabContentView.Type; }
 78
 79 get selectedSettingsView()
6480 {
65  return WebInspector.SettingsTabContentView.Type;
 81 return this._selectedSettingsView;
6682 }
6783
68  layout()
 84 set selectedSettingsView(page)
6985 {
70  this.element.removeChildren();
71 
72  let header = this.element.createChild("div", "header");
73  header.textContent = WebInspector.UIString("Settings");
74 
75  let createContainer = (title, createValueController) => {
76  let container = this.element.createChild("div", "setting-container");
77 
78  let titleContainer = container.createChild("div", "setting-name");
79  if (title)
80  titleContainer.textContent = title;
81  else
82  container.classList.add("combined");
83 
84  let valueControllerContainer = container.createChild("div", "setting-value-controller");
85  let labelElement = valueControllerContainer.createChild("label");
86  if (typeof createValueController === "function")
87  createValueController(labelElement);
88  };
89 
90  let createCheckbox = (setting) => {
91  let checkbox = document.createElement("input");
92  checkbox.type = "checkbox";
93  checkbox.checked = setting.value;
94  checkbox.addEventListener("change", (event) => {
95  setting.value = checkbox.checked;
96  });
97  return checkbox;
98  };
99 
100  let createSeparator = () => {
101  let separatorElement = this.element.appendChild(document.createElement("div"));
102  separatorElement.classList.add("separator");
103  };
104 
105  createContainer(WebInspector.UIString("Prefer indent using:"), (valueControllerContainer) => {
106  let select = valueControllerContainer.createChild("select");
107  select.addEventListener("change", (event) => {
108  WebInspector.settings.indentWithTabs.value = select.value === "tabs";
109  });
110 
111  let tabsOption = select.createChild("option");
112  tabsOption.value = "tabs";
113  tabsOption.textContent = WebInspector.UIString("Tabs");
114  tabsOption.selected = WebInspector.settings.indentWithTabs.value;
115 
116  let spacesOption = select.createChild("option");
117  spacesOption.value = "spaces";
118  spacesOption.textContent = WebInspector.UIString("Spaces");
119  spacesOption.selected = !WebInspector.settings.indentWithTabs.value;
120  });
121 
122  createContainer(WebInspector.UIString("Tab width:"), (valueControllerContainer) => {
123  let input = valueControllerContainer.createChild("input");
124  input.type = "number";
125  input.min = 1;
126  input.value = WebInspector.settings.tabSize.value;
127  input.addEventListener("change", (event) => {
128  WebInspector.settings.tabSize.value = parseInt(input.value) || 4;
129  });
130 
131  valueControllerContainer.append(WebInspector.UIString("spaces"));
132  });
133 
134  createContainer(WebInspector.UIString("Indent width:"), (valueControllerContainer) => {
135  let input = valueControllerContainer.createChild("input");
136  input.type = "number";
137  input.min = 1;
138  input.value = WebInspector.settings.indentUnit.value;
139  input.addEventListener("change", (event) => {
140  WebInspector.settings.indentUnit.value = parseInt(input.value) || 4;
141  });
142 
143  valueControllerContainer.append(WebInspector.UIString("spaces"));
144  });
 86 if (this._selectedSettingsView === page)
 87 return;
14588
146  createContainer(WebInspector.UIString("Line wrapping:"), (valueControllerContainer) => {
147  let checkbox = createCheckbox(WebInspector.settings.enableLineWrapping);
148  valueControllerContainer.appendChild(checkbox);
 89 if (this._selectedSettingsView)
 90 this.replaceSubview(this._selectedSettingsView, page);
 91 else
 92 this.addSubview(page);
14993
150  valueControllerContainer.append(WebInspector.UIString("Wrap lines to editor width"));
151  });
 94 this._selectedSettingsView = page;
 95 this._selectedSettingsView.updateLayout();
15296
153  createContainer(WebInspector.UIString("Whitespace Characters:"), (valueControllerContainer) => {
154  let checkbox = createCheckbox(WebInspector.settings.showWhitespaceCharacters);
155  valueControllerContainer.appendChild(checkbox);
156 
157  valueControllerContainer.append(WebInspector.UIString("Visible"));
158  });
159 
160  createContainer(WebInspector.UIString("Invalid Characters:"), (valueControllerContainer) => {
161  let checkbox = createCheckbox(WebInspector.settings.showInvalidCharacters);
162  valueControllerContainer.appendChild(checkbox);
163 
164  valueControllerContainer.append(WebInspector.UIString("Visible"));
165  });
166 
167  createSeparator();
168 
169  createContainer(WebInspector.UIString("Styles Editing:"), (valueControllerContainer) => {
170  let checkbox = createCheckbox(WebInspector.settings.stylesShowInlineWarnings);
171  valueControllerContainer.appendChild(checkbox);
172 
173  valueControllerContainer.append(WebInspector.UIString("Show inline warnings"));
174  });
175 
176  createContainer(null, (valueControllerContainer) => {
177  let checkbox = createCheckbox(WebInspector.settings.stylesInsertNewline);
178  valueControllerContainer.appendChild(checkbox);
179 
180  valueControllerContainer.append(WebInspector.UIString("Automatically insert newline"));
181  });
182 
183  createContainer(null, (valueControllerContainer) => {
184  let checkbox = createCheckbox(WebInspector.settings.stylesSelectOnFirstClick);
185  valueControllerContainer.appendChild(checkbox);
186 
187  valueControllerContainer.append(WebInspector.UIString("Select text on first click"));
188  });
189 
190  createSeparator();
191 
192  createContainer(WebInspector.UIString("Network:"), (valueControllerContainer) => {
193  let checkbox = createCheckbox(WebInspector.settings.clearNetworkOnNavigate);
194  valueControllerContainer.appendChild(checkbox);
195 
196  valueControllerContainer.append(WebInspector.UIString("Clear when page navigates"));
197  });
198 
199  createSeparator();
200 
201  createContainer(WebInspector.UIString("Console:"), (valueControllerContainer) => {
202  let checkbox = createCheckbox(WebInspector.settings.clearLogOnNavigate);
203  valueControllerContainer.appendChild(checkbox);
204 
205  valueControllerContainer.append(WebInspector.UIString("Clear when page navigates"));
206  });
207 
208  createSeparator();
209 
210  createContainer(WebInspector.UIString("Debugger:"), (valueControllerContainer) => {
211  let checkbox = createCheckbox(WebInspector.settings.showScopeChainOnPause);
212  valueControllerContainer.appendChild(checkbox);
 97 this._navigationBar.selectedNavigationItem = page.identifier;
 98 }
21399
214  valueControllerContainer.append(WebInspector.UIString("Show Scope Chain on pause"));
215  });
 100 addSettingsView(settingsView)
 101 {
 102 let identifier = settingsView.identifier;
 103 console.assert(!this._settingsViewIdentifierMap.has(identifier), "SettingsView already exists.", settingsView);
 104 if (this._settingsViewIdentifierMap.has(identifier))
 105 return;
216106
217  createSeparator();
 107 this._settingsViewIdentifierMap.set(identifier, settingsView);
218108
219  createContainer(WebInspector.UIString("Zoom:"), (valueControllerContainer) => {
220  let select = valueControllerContainer.createChild("select");
221  select.addEventListener("change", (event) => {
222  WebInspector.setZoomFactor(select.value);
223  });
 109 this._navigationBar.addNavigationItem(new WebInspector.RadioButtonNavigationItem(identifier, settingsView.displayName));
224110
225  let currentZoom = WebInspector.getZoomFactor().maxDecimals(1);
226  [0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.2, 2.4].forEach((level) => {
227  let option = select.createChild("option");
228  option.value = level;
229  option.textContent = Number.percentageString(level, 0);
230  option.selected = currentZoom === level;
231  });
232  });
 111 if (this._settingsViewIdentifierMap.size > 1)
 112 this._navigationBar.element.classList.remove("hidden");
 113 }
233114
234  createSeparator();
 115 // Private
235116
236  createContainer(WebInspector.UIString("Layout Direction:"), (valueControllerContainer) => {
237  let selectElement = valueControllerContainer.appendChild(document.createElement("select"));
238  selectElement.addEventListener("change", (event) => {
239  WebInspector.setLayoutDirection(selectElement.value);
240  });
 117 _navigationItemSelected(event)
 118 {
 119 let navigationItem = event.target.selectedNavigationItem;
 120 if (!navigationItem)
 121 return;
241122
242  let currentLayoutDirection = WebInspector.settings.layoutDirection.value;
243  let options = new Map([
244  [WebInspector.LayoutDirection.System, WebInspector.UIString("System Default")],
245  [WebInspector.LayoutDirection.LTR, WebInspector.UIString("Left to Right (LTR)")],
246  [WebInspector.LayoutDirection.RTL, WebInspector.UIString("Right to Left (RTL)")],
247  ]);
 123 let settingsView = this._settingsViewIdentifierMap.get(navigationItem.identifier);
 124 console.assert(settingsView, "Missing SettingsView for identifier " + navigationItem.identifier);
 125 if (!settingsView)
 126 return;
248127
249  for (let [key, value] of options) {
250  let optionElement = selectElement.appendChild(document.createElement("option"));
251  optionElement.value = key;
252  optionElement.textContent = value;
253  optionElement.selected = currentLayoutDirection === key;
254  }
255  });
 128 this.selectedSettingsView = settingsView;
256129 }
257130};
258131

Source/WebInspectorUI/UserInterface/Views/SettingsView.js

 1/*
 2 * Copyright (C) 2017 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WebInspector.SettingsView = class SettingsView extends WebInspector.View
 27{
 28 constructor(identifier, displayName)
 29 {
 30 super();
 31
 32 this._identifier = identifier;
 33 this._displayName = displayName;
 34
 35 this.element.classList.add("settings-view", identifier);
 36 }
 37
 38 // Public
 39
 40 get identifier() { return this._identifier; }
 41 get displayName() { return this._displayName; }
 42
 43 addSetting(title, setting, label, options)
 44 {
 45 let settingsGroup = this.addGroup(title);
 46 return settingsGroup.addSetting(setting, label, options);
 47 }
 48
 49 addCustomSetting(title, editorType, options)
 50 {
 51 let settingsGroup = this.addGroup(title);
 52 return settingsGroup.addCustomSetting(editorType, options);
 53 }
 54
 55 addGroup(title)
 56 {
 57 let settingsGroup = new WebInspector.SettingsGroup(title);
 58 this.element.append(settingsGroup.element);
 59
 60 return settingsGroup;
 61 }
 62
 63 addSeparator()
 64 {
 65 if (this.element.lastChild && this.element.lastChild.classList.contains("separator"))
 66 return;
 67
 68 let separatorElement = this.element.appendChild(document.createElement("div"));
 69 separatorElement.classList.add("separator");
 70 }
 71};
 72
 73WebInspector.SettingsView.EditorType = {
 74 Checkbox: "settings-view-editor-type-checkbox",
 75 Numeric: "settings-view-editor-type-numeric",
 76 Select: "settings-view-editor-type-select",
 77};