/************************************************************************** * * @@@BUILDINFO@@@ 85findReplaceDialog-2.jsx 2.0.1.61 14-March-2007 * Copyright 2006-2007 Adobe Systems Incorporated * All Rights Reserved. * * NOTICE: All information contained herein is, and remains the property of * Adobe Systems Incorporated and its suppliers, if any. The intellectual * and technical concepts contained herein are proprietary to Adobe Systems * Incorporated and its suppliers and may be covered by U.S. and Foreign * Patents,patents in process,and are protected by trade secret or copyright * law. Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained from * Adobe Systems Incorporated. **************************************************************************/ app.createFR = function( where ) { findReplaceObj = new DocFindReplace( where ); findReplaceObj.initialShow = true; findReplaceObj.show(); findReplaceObj.initialShow = false; globalBroadcaster.registerClient( findReplaceObj ); } /////////////////////////////////////////////////////////////////////////////// // // F&R object // DocFindReplace.WHERE_CURRDOC = 0; DocFindReplace.WHERE_CURRSEL = 1; DocFindReplace.WHERE_ALLDOCS = 2; // multiple find DocFindReplace.WHERE_FAVORITES = 3; // multiple find DocFindReplace.WHERE_CURRENGINE = 4; // multiple find function DocFindReplace( where ) { this.strFind = "$$$/ESToolkit/FindReplaceDlg/Find=&Find"; this.strFindNext = "$$$/ESToolkit/FindReplaceDlg/FindNext=&Find Next"; this.strFindAll = "$$$/ESToolkit/FindReplaceDlg/FindAll=&Find All"; this.strSearchFailed = "$$$/ESToolkit/FindReplaceDlg/Alerts/SearchFailed=No matches found"; this.strSearchFailedRetry = "$$$/ESToolkit/FindReplaceDlg/Alerts/SearchFailedRetry=The end of the document has been reached.^nContinue checking from the beginning?"; this.strReplacementDone = "$$$/ESToolkit/FindReplaceDlg/Alerts/ReplacementDone=Search complete. %1 changes were made."; this.strOneReplacementDone = "$$$/ESToolkit/FindReplaceDlg/Alerts/OneReplacementDone=Search complete. One change was made."; // // The Find/Replace floating palette resource // var dlgResSpec = "dockpalette { \ properties : \ { \ defaultVisibility : false, \ closeOnKey : 'Escape', \ minimumSize : [335,160], \ maximumSize : [5000,1000], \ name : 'findAndReplace', \ icon : '#PFindReplace_N', \ rollover : '#PFindReplace_R'," + where + " \ }, \ text : '$$$/ESToolkit/FindReplaceDlg/Title=Find and Replace', \ alignment : ['fill','top'], \ orientation : 'column', \ alignChildren: 'top', \ margins : 5, \ spacing : 5, \ topGroup : Group \ { \ alignment : ['fill','top'], \ orientation : 'row', \ findGrp : Group \ { \ alignment : ['fill','top'], \ orientation : 'column', \ alignChildren : 'left', \ margins : 0, \ search : Group \ { \ alignment : ['fill','top'], \ orientation : 'row', \ lbl : StaticText \ { \ text : '$$$/ESToolkit/FindReplaceDlg/FindLbl=Find:' \ }, \ string : EditText \ { \ alignment : ['fill','top'], \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htFind=A text string to search for', \ properties : { enterKeySignalsOnChange : false } \ } \ }, \ replace: Group \ { \ alignment : ['fill','top'], \ orientation : 'row', \ lbl : StaticText { text : '$$$/ESToolkit/FindReplaceDlg/ReplaceWith=Replace With:' }, \ string : EditText \ { \ alignment : ['fill','top'], \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htReplaceWith=A text string to replace the search text',\ properties : { enterKeySignalsOnChange : false } \ } \ }, \ where: Group \ { \ alignment : ['fill','center'], \ orientation : 'row', \ lbl : StaticText \ { \ alignment : ['left','center'],\ text : '$$$/ESToolkit/FindReplaceDlg/Where=&Search Where:' \ }, \ list : DropDownList \ { \ preferredSize : [180,21], \ alignment : ['fill','center'],\ helpTip : '$$$/ESToolkit/FindReplaceDlg/htWhere=Choose where to search' \ }, \ } \ }, \ btnsGrp: Group \ { \ alignment : ['right','fill'], \ orientation : 'column', \ alignChildren : 'fill', \ margins : 0, \ spacing : 5, \ find : Button \ { \ enabled : true, \ text : '$$$/ESToolkit/FindReplaceDlg/Find=&Find',\ helpTip : '$$$/ESToolkit/FindReplaceDlg/Btn/htFind=Find the specified text string' \ }, \ replace : Button \ { \ enabled : true, \ text : '$$$/ESToolkit/FindReplaceDlg/Btn/Replace=&Replace', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplace=Replace the selected text with the specified text' \ }, \ replaceFind : Button \ { \ enabled : true, \ helpTip : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplaceFind=Replace the selected text with the specified text, and find the next occurence', \ text : '$$$/ESToolkit/FindReplaceDlg/Btn/ReplaceFind=Replace && Fi&nd' \ }, \ replaceAll : Button \ { \ enabled : true, \ text : '$$$/ESToolkit/FindReplaceDlg/Btn/ReplaceAll=Replace &All', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/Btn/htReplaceAll=Replace all occurences of the selected text with the specified text' \ } \ } \ }, \ bottomGroup: Group \ { \ orientation : 'row', \ alignChildren : ['left','top'], \ margins : 0, \ left: Group \ { \ orientation : 'column', \ alignChildren : ['left','top'], \ matchCase : Checkbox \ { \ text : '$$$/ESToolkit/FindReplaceDlg/MatchCase=Match &Case', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htMatchCase=Only matches with the same capitalization will be found' \ }, \ wholeWord : Checkbox \ { \ text : '$$$/ESToolkit/FindReplaceDlg/FindWholeWord=Match &Whole Word', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htFindWholeWord=Only matches that are an entire word will be found' \ }, \ }, \ right: Group \ { \ orientation : 'column', \ alignChildren : ['left','top'], \ matchRegExp : Checkbox \ { \ text : '$$$/ESToolkit/FindReplaceDlg/MatchRegExp=Match Regular E&xpression', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htMatchRegExp=Only strings which match the given regular expression will be found' \ }, \ clearResults: Checkbox \ { \ text : '$$$/ESToolkit/FindReplaceDlg/ClearResults=&Clear Old Results', \ helpTip : '$$$/ESToolkit/FindReplaceDlg/htClearResults=Clear old results.' \ } \ } \ } \ }"; // Create the floating palette, link it to the FindReplace object this.palette = new Window (dlgResSpec); this.palette.findReplaceObj = this; this.baseFolder = ""; // the base folder for Favorites search this.where = DocFindReplace.WHERE_CURRDOC; this.searchEdit = this.palette.topGroup.findGrp.search.string; this.replaceEdit = this.palette.topGroup.findGrp.replace.string; this.whereList = this.palette.topGroup.findGrp.where.list; this.findBtn = this.palette.topGroup.btnsGrp.find; this.replaceBtn = this.palette.topGroup.btnsGrp.replace; this.replaceFindBtn = this.palette.topGroup.btnsGrp.replaceFind; this.replaceAllBtn = this.palette.topGroup.btnsGrp.replaceAll; this.matchCase = this.palette.bottomGroup.left.matchCase; this.wholeWord = this.palette.bottomGroup.left.wholeWord; this.matchRegExp = this.palette.bottomGroup.right.matchRegExp; this.clearResults = this.palette.bottomGroup.right.clearResults; // Set update event handlers for Find and Replace strings this.searchEdit.onChanging = this.searchEdit.onChange = this.replaceEdit.onChanging = this.replaceEdit.onChange = function () { this.window.findReplaceObj.resetFindReplace (true); } this.searchEdit.onEnterKey = function() { this.window.findReplaceObj.findBtn.notify(); } this.replaceEdit.onEnterKey = function () { this.window.findReplaceObj.replaceBtn.notify(); } // Set update event handlers for 'match options' checkboxes this.matchCase.onClick = this.wholeWord.onClick = this.matchRegExp.onClick = function () { // A match option is changing: reset FindReplace controls state this.window.findReplaceObj.resetFindReplace (true); } // Set onClick event handlers for the buttons pane this.findBtn.onClick = function () { var frObj = this.window.findReplaceObj; frObj.find (false); /* We want the search string to retain the focus after a Find/Find Next, so it is easy to change the string. Because Find/Find Next is the default button, it will get Enter keystrokes even if the search string has the focus, unlike in the Replace and Replace & Find cases below. */ if (frObj.where < DocFindReplace.WHERE_ALLDOCS) frObj.resetFocus (frObj.searchEdit); } this.replaceBtn.onClick = function () { var frObj = this.window.findReplaceObj; var replaced = frObj.replace (false, false); /* After a successful Replace, we want the focus to stay on the Replace button, so the user can easily do another Replace by typing Enter. If the Replace was unsuccessful, return the focus to the search string, so it can be easily changed. */ if (replaced) frObj.resetFocus (frObj.replaceEdit); else frObj.resetFocus (frObj.searchEdit); } this.replaceFindBtn.onClick = function () { var frObj = this.window.findReplaceObj; var replacedAndFound = false; if (frObj.replace (false, false)) // Only do the 'follow on' find if the replace() matched replacedAndFound = frObj.find (false); /* After a successful Replace & Find, we want the focus to stay on the 'Replace & Find' button, so the user can easily do another 'Replace & Find' by typing Enter. If the Replace was unsuccessful, return the focus to the search string, so it can be easily changed. */ if (replacedAndFound) frObj.resetFocus (frObj.replaceFindBtn); else frObj.resetFocus (frObj.searchEdit); }; this.replaceAllBtn.onClick = function () { var frObj = this.window.findReplaceObj; frObj.replace (true, false); /* After a 'Replace All', always return the focus to the search string, so it can be easily changed. */ frObj.resetFocus (frObj.searchEdit); }; // initialize "where" popup this.updateTargetList(); this.clearResults.enabled = false; this.whereList.onChange = function() { var frObj = this.window.findReplaceObj; if( frObj ) { if (this.selection) { frObj.where = this.selection.where; frObj.wherePath = this.selection.path; frObj.filter = this.selection.filter; frObj.recursive = this.selection.recursive; } else { frObj.where = DocFindReplace.WHERE_CURRDOC; frObj.wherePath = ''; frObj.filter = "*.jsx"; frObj.recursive = false; } frObj.resetFindReplace( true ); } } // Define an onActivate event handler that will execute each time the dialog is activated this.palette.onShow = function () { var frObj = this.findReplaceObj; // On each 'show', reset the find & replace strings and the states of the buttons /* Replace current 'Find' string if a selection is active in current document. For multi-line selections, use only the first line */ var selection = document ? document.textselection : ''; var nlIndex = selection.indexOf ('\n'); if (nlIndex >= 0) selection = selection.substring (0, nlIndex); if (selection.length == 0) // Use last known search string frObj.searchEdit.text = frObj.searchEdit.activeSearchString; else // Use the selection (up to first newline) frObj.searchEdit.text = selection; frObj.replaceEdit.text = frObj.replaceEdit.activeReplaceString; // Adjust widths of some text labels for alignment with (this.topGroup.findGrp) { var maxWidth = replace.lbl.size.width; var findWidth = search.lbl.size.width; if (findWidth > maxWidth) maxWidth = findWidth; var whereWidth = where.lbl.size.width; if (whereWidth > maxWidth) maxWidth = whereWidth; search.lbl.size.width = maxWidth; replace.lbl.size.width = maxWidth; where.lbl.size.width = maxWidth; this.layout.layout(true); } frObj.resetFindReplace (true); // After the window is visible, give the 'search' edit field the focus if( !frObj.initialShow ) addDelayedTask( frObj.resetFocus, frObj.searchEdit, frObj.palette ); }; this.palette.onResize = this.palette.onResizing = function () { this.layout.resize(); } this.initFromPrefs(); } DocFindReplace.prototype.updateTargetList = function() { var sel = ( this.whereList.selection ? this.whereList.selection.text : '' ); // force Current Doc if documents.length > 0 for the first time if (documents.length > 0 && this.whereList.items[0].where != DocFindReplace.WHERE_CURRDOC) sel = ""; this.whereList.removeAll(); var item = null; var mustHaveDocs = (documents.length != 0); if ((this.docInfoInTargetList == undefined || mustHaveDocs != this.docInfoInTargetList) && mustHaveDocs) { item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrDoc=Current document' ) ); item.where = DocFindReplace.WHERE_CURRDOC; item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrSel=Current selection' ) ); item.where = DocFindReplace.WHERE_CURRSEL; item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/AllDocs=All open documents' ) ); item.where = DocFindReplace.WHERE_ALLDOCS; item = this.whereList.add( 'item', localize( '$$$/ESToolkit/FindReplaceDlg/Where/CurrEng=Current target/engine' ) ); item.where = DocFindReplace.WHERE_CURRENGINE; } this.docInfoInTargetList = mustHaveDocs; if( favorites && favorites.length > 0 ) { if (this.whereList.items.length == 0 && this.where != DocFindReplace.WHERE_FAVORITES) this.where = DocFindReplace.WHERE_FAVORITES; if (this.whereList.items.length) this.whereList.add ('separator', ''); for( var i=0; i 0 ) { for( var i=0; i 0 ) { var title = decodeURIComponent (files[i].getRelativeURI (this.baseFolder)); if (!this.findInText( hiddenSearchDoc, text, title, f.absoluteURI )) return false; } } } if (recursive) { files = folder.getFiles (); for (var i = 0; i < files.length; i++) { folder = files [i]; var resolved = folder.resolve(); if (resolved) folder = resolved; if (folder instanceof Folder) { if (!this.searchInFolder (hiddenSearchDoc, folder, filter, recursive)) return false; } } } return true; } DocFindReplace.prototype.findInFiles = function() { var searchString = this.searchEdit.text; var options = this.getMatchOptions(true); var found = false; if( !this.hiddenSearchWin ) { this.hiddenSearchWin = new Window( 'palette', 'hidden' ); this.hiddenSearchWin.hiddenSearchDoc = this.hiddenSearchWin.add( 'document' ); this.hiddenSearchWin.show(); this.hiddenSearchWin.hide(); } switch( this.where ) { case DocFindReplace.WHERE_ALLDOCS: { app.findResult.startSearch( searchString, documents.length, this.clearResults.value, "" ); for( var i=0; i 0 && engine.length > 0 && scripts.getScriptListFor( target, engine, this ) ) { if( wait( DocFindReplace.checkScriptList ) ) { var havescripts = this.awaitedScriptList; if( havescripts ) { app.findResult.startSearch( searchStringt, havescripts.length, this.clearResults.value ); for( var i=0; i 0 ) { if (!this.findInText( this.hiddenSearchWin.hiddenSearchDoc, source, havescripts[i].displayName, havescripts[i].scriptID, target, engine )) break; } } found = app.findResult.endSearch(); } } } } break; } return found; } /* replace(replaceAll, searchWholeDoc) Replace the currently selected text with the contents of findGrp.replaceEdit.text. * If 'replaceAll' is true, replace all instances of the selected text in the document. * If 'searchWholeDoc' is true, search the entire document, otherwise search from the insertion point to the end of the document. Return: * true if a match was found Called from the Replace, Replace & Find, and Replace All button event handlers, or from a keyboard shortcut handler. */ DocFindReplace.prototype.replace = function(replaceAll, searchWholeDoc) { var options = this.getMatchOptions (searchWholeDoc); if (replaceAll) options += Document.FIND_REPLACEALL; var searchString = this.searchEdit.text; var replaceString = this.replaceEdit.text; // Remember that we searched for this text, for preferences this.searchEdit.activeSearchString = searchString; // Remember that we used this text for replacements, for preferences this.replaceEdit.activeReplaceString = replaceString; var replacements = document.replace (searchString, replaceString, options); if (replacements > 0) { // Match(es) found: reset search state this.resetFindReplace (false); if (replaceAll) { // Tell user how many replacements were made if (replacements == 1) messageBox (this.strOneReplacementDone); else messageBox (this.strReplacementDone, replacements); } return true; } else { /* Match not found: if already in 'search the whole doc' mode, note the search failure, else, ask if user wants to search from the beginning */ if (searchWholeDoc) { // Already searched whole doc: we're done messageBox (this.strSearchFailed); this.resetFindReplace (true); return false; } else if (queryBox (this.strSearchFailedRetry)) { // Search again, from the top, but don't allow a global search again this.resetFindReplace (false); return this.replace (replaceAll, true); } else { this.resetFindReplace (true); return false; } } } // DFR_replace /* show() show the Find/Replace palette. If this is the first call to show() in this invocation of the IDE, load (or create) the find/replace preferences. Called from the Find/Replace menu item onSelect handler */ DocFindReplace.prototype.show = function() { if( this.palette.visible ) addDelayedTask( this.resetFocus, this.searchEdit, this.palette ); else this.palette.show(); } // DFR_show /////////////////////////////////////////////////////////////////////////////// // // // /* initFromPrefs() Initialize values of various controls from the saved 'preference' values. Called from first 'show' of the F/R palette. */ DocFindReplace.prototype.initFromPrefs = function() { if (prefs.findReplacePrefs.paletteLocation != null) this.palette.frameLocation = prefs.findReplacePrefs.paletteLocation; else this.palette.center(window); this.searchEdit.activeSearchString = PrefUtils.getValue( 'prefs.findReplacePrefs.searchString', 'String' ); this.replaceEdit.activeReplaceString = PrefUtils.getValue( 'prefs.findReplacePrefs.replaceString', 'String' ); this.matchCase.value = PrefUtils.getValue( 'prefs.findReplacePrefs.matchCase', 'Boolean' ); this.wholeWord.value = PrefUtils.getValue( 'prefs.findReplacePrefs.wholeWord', 'Boolean' ); this.matchRegExp.value = PrefUtils.getValue( 'prefs.findReplacePrefs.matchRegExp', 'Boolean' ); this.clearResults.value = PrefUtils.getValue( 'prefs.findReplacePrefs.clearresults', 'Boolean' ); if( this.searchEdit.activeSearchString.length > 0 ) // Initially, if there's a search string, make the // Find button respond to Enter key this.palette.defaultElement = this.findBtn; this.resetFindReplace (true); } // DFR_initFromPrefs /* updatePrefs() Update the find/replace 'preferences' object with current values from the controls. */ DocFindReplace.prototype.updatePrefs = function() { prefs.findReplacePrefs.paletteLocation = this.palette.frameLocation; prefs.findReplacePrefs.searchString = this.searchEdit.activeSearchString; prefs.findReplacePrefs.replaceString = this.replaceEdit.activeReplaceString; prefs.findReplacePrefs.matchCase = this.matchCase.value; prefs.findReplacePrefs.wholeWord = this.wholeWord.value; prefs.findReplacePrefs.matchRegExp = this.matchRegExp.value; prefs.findReplacePrefs.clearresults = this.clearResults.value; } // DFR_updatePrefs /* resetFindReplace() Reset states of the 'find' and 'replace' controls after a state change. 'newSearch' indicates a new search string: false means searching again for same string. */ DocFindReplace.prototype.resetFindReplace = function(newSearch) { var palette = this.palette; var haveSearchString = this.currentSearchString().length > 0; var docIsWriteable = true; // replace with "! document.readOnly" if we need to disable F/R for RO docs var multiFind = (this.where >= DocFindReplace.WHERE_ALLDOCS); var btnText; if (multiFind) btnText = this.strFindAll; else btnText = ( newSearch || documents.length == 0 ) ? this.strFind : this.strFindNext; this.findBtn.text = localize ( btnText ); this.findBtn.enabled = haveSearchString; this.replaceBtn.enabled = this.replaceFindBtn.enabled = this.replaceAllBtn.enabled = ( haveSearchString && documents.length > 0 && docIsWriteable && ( this.where == DocFindReplace.WHERE_CURRDOC || this.where == DocFindReplace.WHERE_CURRSEL ) ); this.clearResults.enabled = multiFind; } // DFR_resetFindReplace /* resetFocus(control) Set keyboard focus to the given 'control', or to the palette if control == null. */ DocFindReplace.prototype.resetFocus = function( control, palette ) { var palette = palette; if( !palette ) palette = this.palette; if( palette && !palette.active ) palette.active = true; if (control) { if( control.active ) control.active = false; control.active = true; } } // DFR_resetFocus /* getMatchOptions() Return the 'match options' flags to pass to Document.find() or Document.replace(), based on the current dialog match options checkboxes and the 'searchWholeDoc' parameter. */ DocFindReplace.prototype.getMatchOptions = function(searchWholeDoc) { var options = 0; if (searchWholeDoc) options += Document.FIND_WRAPAROUND; if (this.matchCase.value == 0) options += Document.FIND_IGNORECASE; if (this.wholeWord.value != 0) options += Document.FIND_WORDS; if (this.matchRegExp.value != 0) options += Document.FIND_REGEXP; if( this.where == DocFindReplace.WHERE_CURRSEL ) options += Document.FIND_SELECTION; return options; } // DFR_getMatchOptions /* currentSearchString() Return the current string to search for: may be empty. */ DocFindReplace.prototype.currentSearchString = function() { return this.searchEdit.text; } // currentSearchString