From 84b96ace5eddc0cf557f667e90041f00ce2caef4 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sat, 6 Apr 2024 23:50:50 -0500 Subject: [PATCH] Wiring Search/Replace UI --- .../search_replace/styling_mixin.py | 2 +- .../usr/share/newton/context_path/index.html | 55 +++-- .../resources/css/newton/main.css | 20 ++ .../resources/css/newton/overrides.css | 10 + .../resources/js/newton/components.js | 225 +++++++++++++++++- .../resources/js/newton/events.js | 16 +- .../resources/js/newton/globals.js | 6 + .../resources/js/newton/keybinding-newton.js | 5 +- .../resources/js/newton/ui-logic.js | 37 +-- 9 files changed, 311 insertions(+), 65 deletions(-) diff --git a/plugins/gtksourceview/search_replace/styling_mixin.py b/plugins/gtksourceview/search_replace/styling_mixin.py index 1baf8a5..3336bec 100644 --- a/plugins/gtksourceview/search_replace/styling_mixin.py +++ b/plugins/gtksourceview/search_replace/styling_mixin.py @@ -63,4 +63,4 @@ class StylingMixin: plural = "s" if total_count > 1 else "" if total_count == 0: self.update_style(2) - self._find_status_lbl.set_label(f"{count} results{plural} found for '{query}'") + self._find_status_lbl.set_label(f"{count} result{plural} found for '{query}'") diff --git a/user_config/usr/share/newton/context_path/index.html b/user_config/usr/share/newton/context_path/index.html index 63f8ffb..430591d 100644 --- a/user_config/usr/share/newton/context_path/index.html +++ b/user_config/usr/share/newton/context_path/index.html @@ -123,17 +123,15 @@
- - + - - - - - + +
@@ -141,34 +139,43 @@
-
- +
+ +
- - + +
-
-
- -
-
- - +
+
+
+ +
+
+
+ + +
+
diff --git a/user_config/usr/share/newton/context_path/resources/css/newton/main.css b/user_config/usr/share/newton/context_path/resources/css/newton/main.css index e0caaa3..f3a34af 100644 --- a/user_config/usr/share/newton/context_path/resources/css/newton/main.css +++ b/user_config/usr/share/newton/context_path/resources/css/newton/main.css @@ -172,6 +172,26 @@ font-size: initial; } + +.searching, +.search-success, +.search-fail { + border-style: solid; + color: rgba(125, 125, 125, 1) !important; +} + +.searching { + border-color: rgba(0, 225, 225, 0.64) !important; +} +.search-success { + background: rgba(136, 204, 39, 0.12) !important; + border-color: rgba(136, 204, 39, 1) !important; +} +.search-fail { + background: rgba(170, 18, 18, 0.12) !important; + border-color: rgba(200, 18, 18, 1) !important; +} + /* Other message text colors */ .error { color: rgb(170, 18, 18); } .warning { color: rgb(255, 168, 0); } diff --git a/user_config/usr/share/newton/context_path/resources/css/newton/overrides.css b/user_config/usr/share/newton/context_path/resources/css/newton/overrides.css index ad1b63f..81e53b5 100644 --- a/user_config/usr/share/newton/context_path/resources/css/newton/overrides.css +++ b/user_config/usr/share/newton/context_path/resources/css/newton/overrides.css @@ -13,6 +13,16 @@ ul, li { list-style: none; } +input.form-control, +input.form-control:focus, +input.form-control::after, +input.form-control::placeholder { + background-color: rgba(0, 0, 0, 0.0) !important; + color: rgba(255, 255, 255, 1.0) !important; + /*text-shadow: 0px 0px 0px black !important;*/ + box-shadow: none !important; +} + .modal-header, .modal-footer { background-color: rgba(0, 0, 0, 0.64); diff --git a/user_config/usr/share/newton/context_path/resources/js/newton/components.js b/user_config/usr/share/newton/context_path/resources/js/newton/components.js index 61f85e5..bc4173f 100644 --- a/user_config/usr/share/newton/context_path/resources/js/newton/components.js +++ b/user_config/usr/share/newton/context_path/resources/js/newton/components.js @@ -175,6 +175,13 @@ class InputCheckboxContainer extends HTMLElement { } } +const QueryState = { + Searching: 0, + SearchSuccess: 1, + SearchFail: 2 +} + + class SearchReplaceContainer extends HTMLElement { constructor() { super(); @@ -186,16 +193,232 @@ class SearchReplaceContainer extends HTMLElement { const shadowRoot = this.attachShadow({ mode: "open" }); shadowRoot.appendChild( templateContent.cloneNode(true) ); + this.showing = false; } loadSignals() { + this.bindToggleSignal( this.shadowRoot.getElementById("whole-word-btn") ); + this.bindToggleSignal( this.shadowRoot.getElementById("only-in-selection-btn") ); + this.bindToggleSignal( this.shadowRoot.getElementById("match-case-btn") ); + this.bindToggleSignal( this.shadowRoot.getElementById("use-regex-btn") ); + let elm = this.shadowRoot.getElementById("find-entry"); elm.addEventListener("keyup", (eve) => { - findEntry(eve.value); + if (eve.key === "Enter") { + let elm = this.shadowRoot.getElementById("find-btn"); + elm.click(); + return + } + + let elm = this.shadowRoot.getElementById("find-all-btn"); + elm.click(); + }); + + + elm = this.shadowRoot.getElementById("find-btn"); + elm.addEventListener("click", (eve) => { + this.findEntry( this.getQuery() ); + }); + + elm = this.shadowRoot.getElementById("find-all-btn"); + elm.addEventListener("click", (eve) => { + this.findAllEntries( this.getQuery() ); + }); + + elm = this.shadowRoot.getElementById("replace-btn"); + elm.addEventListener("click", (eve) => { + this.findEntry( this.getQuery() ); + this.replaceEntry( this.getreplacer() ); + }); + + elm = this.shadowRoot.getElementById("replace-all-btn"); + elm.addEventListener("click", (eve) => { + this.findEntry( this.getQuery() ); + this.replaceAll( this.getreplacer() ); }); } + bindToggleSignal(elm) { + elm.addEventListener("click", (eve) => { + let elm = eve.target.nodeName === "IMG" ? eve.target.parentElement : eve.target; + let isActive = elm.classList.contains("btn-info"); + + if (isActive) { + elm.classList.remove("btn-info"); + elm.classList.add("btn-dark"); + } else { + elm.classList.add("btn-info"); + elm.classList.remove("btn-dark") + } + + this.setFindOptionsLbl(); + }); + } + + toggleShow() { + if (this.showing) { + this.showing = false; + $('#bottom-gutter').popover('hide'); + } else { + this.showing = true; + $('#bottom-gutter').popover('show'); + } + + setTimeout(() => { + if (this.showing) { + let elm = this.shadowRoot.getElementById("find-entry"); + elm.focus(); + } else { + editor.focus(); + } + }, 0.5); + } + + findPreviousEntry(query) { + editor.findPrevious(); + } + + replaceEntry(toStr) { + editor.replace(toStr); + } + + replaceAll(toStr) { + editor.replaceAll(toStr); + } + + findNextEntry(query) { + editor.findNext(); + } + + findAllEntries(query = null, isBackwwards = true, isWrap = true, range = null) { + this.updateStyle(QueryState.SearchSuccess); + if (query === "") { + this.shadowRoot.getElementById("find-status-lbl").innerText = "Find in current buffer"; + this.updateStyle(QueryState.Searching); + this.clearSearchMarkers(); + + return; + } + + let totalCount = editor.findAll(query, { + backwards: isBackwwards === "True" ? true : false, + wrap: isWrap === "True" ? true : false, + caseSensitive: this.isMatchCase(), + wholeWord: this.isUseWholeWord(), + regExp: this.isUseRegex(), + range: range === "True" ? true : false + }); + + if (totalCount === 0) { + console.log('Empty search result...'); + this.clearSearchMarkers(); + } + + this.updateStatusLbl(totalCount, query); + + return totalCount; + } + + clearSearchMarkers() { + let markers = session.getMarkers(false); + for (var id in markers) { + if ( + markers[id].clazz.indexOf("ace_selection") === 0 || + markers[id].clazz.indexOf("ace_selected-word") === 0 + ) { + session.removeMarker(id); + } + } + } + + findEntry(query = null, isBackwwards = true, isWrap = true, range = null) { + let result = editor.find(query, { + backwards: isBackwwards === "True" ? true : false, + wrap: isWrap === "True" ? true : false, + caseSensitive: this.isMatchCase(), + wholeWord: this.isUseWholeWord(), + regExp: this.isUseRegex(), + range: range === "True" ? true : false + }); + + return result; + } + + updateStatusLbl(totalCount = 0, query = "") { + if ( !query ) return; + + let count = (totalCount > 0) ? totalCount : "No"; + let plural = (totalCount > 1) ? "s" : ""; + + if (totalCount === 0) + this.updateStyle(QueryState.SearchFail); + + const statusLbl = `${count} result${plural} found for '${query}'`; + this.shadowRoot.getElementById("find-status-lbl").innerText = statusLbl; + } + + setFindOptionsLbl() { + let findOptions = "Finding with Options: "; + + if ( this.isUseRegex() ) + findOptions += "Regex"; + + findOptions += ( this.isUseRegex() ) ? ", " : ""; + findOptions += ( this.isMatchCase() ) ? "Case Sensitive" : "Case Inensitive"; + + if ( this.isSelectionSearchOnly() ) + findOptions += ", Within Current Selection"; + + if ( this.isUseWholeWord() ) + findOptions += ", Whole Word"; + + this.shadowRoot.getElementById("find-options-lbl").innerText = findOptions; + } + + updateStyle(state) { + let elm = this.shadowRoot.getElementById("find-entry"); + + elm.classList.remove("searching") + elm.classList.remove("search-success") + elm.classList.remove("search-fail") + + if (state === 0) + elm.classList.add("searching"); + else if (state === 1) + elm.classList.add("search-success"); + else if (state === 2) + elm.classList.add("search-fail"); + } + + + getQuery() { + return this.shadowRoot.getElementById("find-entry").value; + } + + getreplacer() { + return this.shadowRoot.getElementById("replace-entry").value; + } + + isUseWholeWord() { + let elm = this.shadowRoot.getElementById("whole-word-btn"); + return elm.classList.contains("btn-info"); + } + + isSelectionSearchOnly() { + let elm = this.shadowRoot.getElementById("only-in-selection-btn"); + return elm.classList.contains("btn-info"); + } + + isMatchCase() { + let elm = this.shadowRoot.getElementById("match-case-btn"); + return elm.classList.contains("btn-info"); + } + + isUseRegex() { + let elm = this.shadowRoot.getElementById("use-regex-btn"); + return elm.classList.contains("btn-info"); + } } diff --git a/user_config/usr/share/newton/context_path/resources/js/newton/events.js b/user_config/usr/share/newton/context_path/resources/js/newton/events.js index 4cae356..c13cbf3 100644 --- a/user_config/usr/share/newton/context_path/resources/js/newton/events.js +++ b/user_config/usr/share/newton/context_path/resources/js/newton/events.js @@ -37,8 +37,8 @@ const loadLSPClientJSFiles = () => { } const loadSearchFind = () => { - let elm = document.createElement("search-replace"); - let options = {container: "html", content: elm, html: true}; + searchReplace = document.createElement("search-replace"); + let options = {container: "html", content: searchReplace, html: true}; $('#bottom-gutter').popover(options); } @@ -57,6 +57,11 @@ window.onerror = function(msg, url, line, col, error) { document.addEventListener("keyup", (eve) => { + if (blockHigherNewtonEvePropigation) { + blockHigherNewtonEvePropigation = false; + return; + } + switch (eve.key) { case "ArrowUp": setLabels(); @@ -96,6 +101,11 @@ document.addEventListener("keyup", (eve) => { } } break; + case "f": + if (searchReplace.showing) { + searchReplace.toggleShow(); + } + break default: setLabels(); break @@ -104,6 +114,8 @@ document.addEventListener("keyup", (eve) => { document.addEventListener("keydown", (eve) => { + if (blockHigherNewtonEvePropigation) return; + switch (eve.key) { case "ArrowUp": if ( isNotNullOrUndefined(previewSel) ) { diff --git a/user_config/usr/share/newton/context_path/resources/js/newton/globals.js b/user_config/usr/share/newton/context_path/resources/js/newton/globals.js index e109bde..049c6dc 100644 --- a/user_config/usr/share/newton/context_path/resources/js/newton/globals.js +++ b/user_config/usr/share/newton/context_path/resources/js/newton/globals.js @@ -2,6 +2,7 @@ const messenger = (window.webkit) ? window.webkit.messageHandlers : (message) = console.log("Message: " + message); }; + const EDITOR_OPTS = { printMarginColumn: 80, enableBasicAutocompletion: true, @@ -17,6 +18,7 @@ const EDITOR_OPTS = { mergeUndoDeltas: false } + const BASE_LINK = `${window.location.href}resources/js/libs/ace_editor/lsp`; const LSP_SERVER_CONFG = `${window.location.href}../lsp-servers-config.json`; const BASE_LSP_LINK = "http://0.0.0.0:4880"; @@ -27,6 +29,7 @@ let lspServersConfig = null; let lspSettingsUI = document.getElementById('lsp-settings'); +let searchReplace = null; let editor = null; let previewEditor = null; let aceSessions = {}; @@ -36,3 +39,6 @@ let fontSize = 12; let highlightLine = true; let isControlDown = false; let queryMarkers = []; + + +let blockHigherNewtonEvePropigation = false; \ No newline at end of file diff --git a/user_config/usr/share/newton/context_path/resources/js/newton/keybinding-newton.js b/user_config/usr/share/newton/context_path/resources/js/newton/keybinding-newton.js index d4b92e9..e712fe2 100644 --- a/user_config/usr/share/newton/context_path/resources/js/newton/keybinding-newton.js +++ b/user_config/usr/share/newton/context_path/resources/js/newton/keybinding-newton.js @@ -29,9 +29,8 @@ const editorCommands = [ name: "search", bindKey: {win: "ctrl-f", mac: "ctrl-f"}, exec: function(editor) { - // let selectedStr = session.doc.getTextRange(editor.getSelectionRange()); - $('#bottom-gutter').popover('toggle') - // sendMessage("tggl_search_replace", "", "", "", selectedStr); + blockHigherNewtonEvePropigation = true; + searchReplace.toggleShow(); }, readOnly: true }, { diff --git a/user_config/usr/share/newton/context_path/resources/js/newton/ui-logic.js b/user_config/usr/share/newton/context_path/resources/js/newton/ui-logic.js index 526a7d5..89f4406 100644 --- a/user_config/usr/share/newton/context_path/resources/js/newton/ui-logic.js +++ b/user_config/usr/share/newton/context_path/resources/js/newton/ui-logic.js @@ -221,40 +221,6 @@ const setLabels = () => { } -const findEntry = (query = null, isBackwwards = true, isWrap = true, - isCaseSensitive = false, - useWholeWord = false, - useRegExp = false, - range = null) => { - // if ( isNotNullOrUndefined(queryMarkers) ) { - // for (let i = 0; i < queryMarkers.length; i++) { - // delete queryMarkers[i]; - // } - // } - - // let result = editor.find(query, { - // backwards: isBackwwards === "True" ? true : false, - // wrap: isWrap === "True" ? true : false, - // caseSensitive: isCaseSensitive === "True" ? true : false, - // wholeWord: useWholeWord === "True" ? true : false, - // regExp: useRegExp === "True" ? true : false, - // range: range === "True" ? true : false - // }); - - let result = editor.findAll(query, { - caseSensitive: isCaseSensitive === "True" ? true : false, - wholeWord: useWholeWord === "True" ? true : false, - regExp: useRegExp === "True" ? true : false, - }); - - console.log(result) - // if ( isNotNullOrUndefined(result) ) { - // for (let i = 0; i < result.length; i++) { - // loadMarker( result[i] ); - // } - // } -} - const loadMarker = (r) => { var range = new Range(rowStart, columnStart, rowEnd, columnEnd); @@ -264,6 +230,9 @@ const loadMarker = (r) => { } +const findAllEntries = (query) => { + editor.findAll(); +} const findNextEntry = (query) => { editor.findNext();