Skip to main content

Supporting Search and Replace

A module can tie into the search and replace system by registering a SearchProvider implementation with the DesignerContext. The SearchProvider will be used to get information about search options, and will be used to generate potential search matches.

How the Search and Replace Process Works

The basic process is simple:

  1. The SearchProvider generates potential search results (SearchObject).
  2. The search and replace system will try to match the text of the SearchObject to the search pattern.
  3. If the object passes, it will be displayed to the user.
  4. The user can then double-click on the object, wch delegates to the SearchObject.locate() function, or can try to replace the value.

The SearchObjects generated by the SearchProvider are returned through an Iterator, with the idea being that they are generated on the fly, so that only matching results need to be kept in memory. The SearchObject implementation will be unique to the provider, as it must know how to locate and replace the resource that it represents.

Refining the Search: Categories and Selected Objects

The SearchProvider can use two mechanisms to refine the objects to be searched. The first, called categories, are a simple way to provide a broad choice. They are displayed as check boxes under the search provider entry on the search window, and the selected objects are passed back to the provider when the search is executed. The second method is through the use of selectable objects. With this mechanism, the search provider will be displayed with a link that will call into the search provider with a SelectedObjectsHandler. The search provider can display a dialog to select which "items" should be searched. The definition of an item is free-form, and can be as simple or complex as the provider wants. Like categories, the selected objects will be passed into the main search function when the search is executed.

Common Design Paradigms and Tools

While the implementation of the search and replace interface is specific to each module, there are certain concerns and patterns that come up frequently.

SearchObject Information

SearchObjects have the ability to provide an Icon, an Owner, and a Name. Some experimentation may be necessary to find the right amount of information to provide in order to make the search results intuitive and easy to identify. For example, returning values of "Button" and "Text" for owner and name respectively, on the Text property of a Button might seem clear at first, but once multiple buttons appear on a screen, it becomes impossible to distinguish them. Including the actual component name in the "owner" string solves this proboem, but can then make it difficult to decipher at a glance what the result is. Using a button image for the icon can provide the final visual clue that the user needs to order to understand quickly.

Iterator Management

While the Iterator mechanism works great for reducing the amount of memory required for searching, it can sometimes be unwieldy to deal with in anything but the simplest modules. It is not uncommon to encounter a situation where you must recursively iterate through multiple levels, potentially returning results at each level. There are several important classes and libraries available that can help:

  • Google Collections - Ignition includes access to the very useful Google Collections package that includes a set of classes that can help when working with iterators. The Iterators class, in particular, has functions for concatenating iterators and more that are very useful.
  • Ignition's SearchObjectAggregator and SearchObjectCursor classes - These incredibly useful classes can be used to overcome the difficulty mentioned above. The SearchObjectCursor is an adaptation of Iterator that can return SearchObjects or other SearchObjectCursors. The SearchObjectAggregator is an implementation of Iterator that knows how to deal with the SearchObjectCursor. In other words, if you implement SearchObjectCursor, you can return either results or new cursors to search, and the aggregator will sort it out for you