import React from "react"; import { action, makeObservable } from "mobx"; import { observer } from "mobx-react"; import classNames from "classnames"; import { IconAction } from "eez-studio-ui/action"; import { ProjectContext } from "project-editor/project/context"; import { Messages } from "project-editor/ui-components/Output"; import { MATCH_CASE_ICON, MATCH_WHOLE_WORD_ICON, REPLACE_ALL_ICON, REPLACE_SELECTED_ICON } from "project-editor/ui-components/icons"; import { Message, Section } from "project-editor/store"; import { findAllOccurrences } from "project-editor/core/search"; import { getKey, getParent, getProperty } from "project-editor/core/object"; export const SearchPanel = observer( class SearchPanel extends React.Component { static contextType = ProjectContext; declare context: React.ContextType; render() { return (
); } } ); const Toolbar = observer( class Toolbar extends React.Component { static contextType = ProjectContext; declare context: React.ContextType; constructor(props: any) { super(props); makeObservable(this, { onSearchPatternChange: action.bound, toggleMatchCase: action.bound, toggleMatchWholeWord: action.bound, nextResult: action.bound, previousResult: action.bound, toggleReplace: action.bound, onReplaceTextChange: action.bound, replaceSelected: action.bound, replaceAll: action.bound }); } get startSearchEnabled() { return this.context.uiStateStore.searchPattern != ""; } startSearch() { this.context.startSearch(); } onSearchPatternChange(event: any) { this.context.uiStateStore.searchPattern = event.target.value; this.startSearch(); } toggleMatchCase() { this.context.uiStateStore.searchMatchCase = !this.context.uiStateStore.searchMatchCase; this.startSearch(); } toggleMatchWholeWord() { this.context.uiStateStore.searchMatchWholeWord = !this.context.uiStateStore.searchMatchWholeWord; this.startSearch(); } get nextResultEnabled() { const searchSection = this.context.outputSectionsStore.getSection( Section.SEARCH ); const selectedMessage = searchSection.selectedMessage; if (!selectedMessage) { return searchSection.messages.searchResults.length > 0; } return ( searchSection.messages.searchResults.indexOf(selectedMessage) < searchSection.messages.searchResults.length - 1 ); } nextResult() { const searchSection = this.context.outputSectionsStore.getSection( Section.SEARCH ); const selectedMessage = searchSection.selectedMessage; if (!selectedMessage) { if (searchSection.messages.searchResults.length > 0) { searchSection.selectMessage( searchSection.messages.searchResults[0] ); } } else { const i = searchSection.messages.searchResults.indexOf( selectedMessage ); if (i < searchSection.messages.searchResults.length - 1) { searchSection.selectMessage( searchSection.messages.searchResults[i + 1] ); } } } get previousResultEnabled() { const searchSection = this.context.outputSectionsStore.getSection( Section.SEARCH ); const selectedMessage = searchSection.selectedMessage; if (!selectedMessage) { return searchSection.messages.searchResults.length > 0; } return ( searchSection.messages.searchResults.indexOf(selectedMessage) > 0 ); } previousResult() { const searchSection = this.context.outputSectionsStore.getSection( Section.SEARCH ); const selectedMessage = searchSection.selectedMessage; if (!selectedMessage) { if (searchSection.messages.searchResults.length > 0) { searchSection.selectMessage( searchSection.messages.searchResults[ searchSection.messages.searchResults.length - 1 ] ); } } else { const i = searchSection.messages.searchResults.indexOf( selectedMessage ); if (i > 0) { searchSection.selectMessage( searchSection.messages.searchResults[i - 1] ); } } } toggleReplace() { this.context.uiStateStore.replaceEnabled = !this.context.uiStateStore.replaceEnabled; this.startSearch(); } onReplaceTextChange(event: any) { this.context.uiStateStore.replaceText = event.target.value; this.startSearch(); } replaceMessage(message: Message) { const uiStateStore = this.context.uiStateStore; const pattern = uiStateStore.searchPattern; const replace = uiStateStore.replaceText; const object = message.object!; const key = getKey(object); const value = getProperty(getParent(object), key); const str = value.toString(); const occurrences = findAllOccurrences( str, pattern, uiStateStore.searchMatchCase, uiStateStore.searchMatchWholeWord ); let newStr = ""; let end = 0; for (const occurrence of occurrences) { if (end < occurrence.start) { newStr += str.substring(end, occurrence.start); } newStr += replace; end = occurrence.end; } if (end < str.length) { newStr += str.substring(end); } const parent = getParent(object); if (typeof value == "string") { this.context.updateObject(parent, { [key]: newStr }); } else if (typeof value == "number") { const newValue = Number.parseFloat(newStr); if (!isNaN(newValue)) { this.context.updateObject(parent, { [key]: newValue }); } } } get replaceSelectedEnabled() { return ( this.context.outputSectionsStore.getSection(Section.SEARCH) .selectedMessage != undefined ); } replaceSelected() { const selectedMessage = this.context.outputSectionsStore.getSection( Section.SEARCH ).selectedMessage; if (selectedMessage) { this.replaceMessage(selectedMessage); } this.startSearch(); } get replaceAllEnabled() { return ( this.context.uiStateStore.replaceEnabled && this.context.outputSectionsStore.getSection(Section.SEARCH) .messages.searchResults.length > 0 ); } replaceAll() { if (!this.replaceAllEnabled) { return; } const section = this.context.outputSectionsStore.getSection( Section.SEARCH ); this.context.undoManager.setCombineCommands(true); for (const message of section.messages.searchResults) { this.replaceMessage(message); } this.context.undoManager.setCombineCommands(false); this.startSearch(); } render() { return (
this.toggleReplace()} style={{ marginTop: 2 }} />
{this.context.uiStateStore.replaceEnabled ? ( ) : ( )}
this.startSearch()} enabled={this.startSearchEnabled} />
this.nextResult()} enabled={this.nextResultEnabled} /> this.previousResult()} enabled={this.previousResultEnabled} />
{this.context.uiStateStore.replaceEnabled && (
this.replaceSelected()} enabled={this.replaceSelectedEnabled} /> this.replaceAll()} enabled={this.replaceAllEnabled} />
)}
); } } );