Jump to content

Creating a Find text function


Recommended Posts

I am trying to create a feature to search a text box for a certain string. I plan to implement this like the Find function you get with most text editors when you press Ctrl-F.

I can use the Search and Replace function to locate the test and I can use the Text.SelectionStart and Text.SelectionEnd properties to highlight the found text, but I cannot figure out how to scroll the text box to the proper line. There is a Text.ScrollPosition property, but how do I figure out what line the text is in?

Has anyone already created this and if so, can you share your code?

thanks,

-John

Link to comment

QUOTE (crelf @ Sep 19 2008, 07:57 PM)

Maybe your svn is beginning to slow down your network after all... :laugh:

(Quoting myself...)

QUOTE (normandinf @ Sep 19 2008, 07:09 PM)

One trick is to use the method "Get Nth Line".

I tested the method a little tonight and I don't think it will be useful with large files as it seems very slow. It took a few seconds to scan a 591 lines string on my QuadCore! For long files, like help documents, it's gonna take a better scanning algorithm.

Link to comment

QUOTE (normandinf @ Sep 19 2008, 07:38 PM)

I tested the method a little tonight and I don't think it will be useful with large files as it seems very slow. It took a few seconds to scan a 591 lines string on my QuadCore! For long files, like help documents, it's gonna take a better scanning algorithm.

Get Nth Line is something I wrote to make various UI problems solvable. The problem is that it has to mimic the rendering of the text in the current font in order to figure out where word wrapping occurs. The font system is structured in the OS such that there's no way to do it except by actually rendering the font off screen (at least no other mechanism that I could puzzle out). As you observed, this means that for very large blocks of text, you'll have a slow down as if the entire file were drawn on a very large screen. Ugly.

So, you'll have to do this: Pick a font. Measure the width of every character in that font in pixels. Then do your own running calculations of where the word wrapping occurs. This should be very fast. It's something that Get Nth Line cannot do because it has to work with all possible fonts. Doing your own running calculation of the word wrapping will allow you to avoid the graphics rendering.

And now you know why word processors are such a pain to write and why so many end up so bloated and slow. And you know why MS Word was such an impressive app when it was released. It was able to track font runs very very quickly -- a seriously non-trivial problem, though it seems simple enough when you start on it.

Link to comment

QUOTE (Aristos Queue @ Sep 21 2008, 08:56 PM)

Yes, that is how I solved this for my first attempt. I have posted the code in the Code Repository in Development section.

Search Text Dialog

It has several areas that could see improvement.

1. Speed (it is slow). I am not up to writting a word wrap detector right now. By using the Get Nth Line function, I can support a text control with any font. I think this could be improved by doing a binary search algorithm, but I would need to know how many lines a text control contains. As noted, this is not easy and requires counting <CR> and word wraps.

2. To make sure it does not get lost, I need to make it floating. But, for some reason, you cannot bring a floating window to the front programatically. So, when it first appears, you must click in the window before you can type anything.

3. In order to make the text in the original control appear highlighted, that window must be front most. So, after it finds something, it has to set the caller's window front most. This means each time you wish to do another search, you must select the dialog window again. Any ideas on this?

4. I am using a combo box to allow it to remember past searches. For some reason, if you type the very first entry into the combo box and then press return to toggle the find button, it will not see this entry when it reads the string from the combo box. So, instead, I had to force the user to click on the Find button.

Please take a look at the code and see if you can help improve it. This could be a really useful feature to share with others if it can be made bullet proof.

-John

Link to comment

QUOTE (Aristos Queue @ Sep 21 2008, 11:56 PM)

Get Nth Line is something I wrote to make various UI problems solvable. The problem is that it has to mimic the rendering of the text in the current font in order to figure out where word wrapping occurs. The font system is structured in the OS such that there's no way to do it except by actually rendering the font off screen (at least no other mechanism that I could puzzle out). As you observed, this means that for very large blocks of text, you'll have a slow down as if the entire file were drawn on a very large screen. Ugly.

So, you'll have to do this: Pick a font. Measure the width of every character in that font in pixels. Then do your own running calculations of where the word wrapping occurs. This should be very fast. It's something that Get Nth Line cannot do because it has to work with all possible fonts. Doing your own running calculation of the word wrapping will allow you to avoid the graphics rendering.

And now you know why word processors are such a pain to write and why so many end up so bloated and slow. And you know why MS Word was such an impressive app when it was released. It was able to track font runs very very quickly -- a seriously non-trivial problem, though it seems simple enough when you start on it.

Thanks for those insights... I had really no idea about that!

QUOTE (jlokanis @ Sep 22 2008, 02:32 AM)

1. Speed (it is slow). I am not up to writting a word wrap detector right now. By using the Get Nth Line function, I can support a text control with any font. I think this could be improved by doing a binary search algorithm, but I would need to know how many lines a text control contains. As noted, this is not easy and requires counting <CR> and word wraps.

Sure would be a nice snippet of code...

Link to comment

The search could be made binary instead, that would cut the number of Nth line calls dramatically...

QUOTE (normandinf @ Sep 20 2008, 02:38 AM)

Maybe your svn is beginning to slow down your network after all... :laugh:

(Quoting myself...)

I tested the method a little tonight and I don't think it will be useful with large files as it seems very slow. It took a few seconds to scan a 591 lines string on my QuadCore! For long files, like help documents, it's gonna take a better scanning algorithm.

Link to comment

QUOTE (Mads @ Sep 22 2008, 10:18 AM)

The search could be made binary instead, that would cut the number of Nth line calls dramatically...

Indeed you're right. :yes: Thanks for the wiki-link.

John has suggested this a few posts above.

QUOTE (jlokanis @ Sep 22 2008, 02:32 AM)

1. Speed (it is slow). I am not up to writting a word wrap detector right now. By using the Get Nth Line function, I can support a text control with any font. I think this could be improved by doing a binary search algorithm, but I would need to know how many lines a text control contains. As noted, this is not easy and requires counting <CR> and word wraps.

Link to comment

QUOTE (Aristos Queue @ Sep 21 2008, 11:56 PM)

So, you'll have to do this: Pick a font. Measure the width of every character in that font in pixels. Then do your own running calculations of where the word wrapping occurs. This should be very fast. It's something that Get Nth Line cannot do because it has to work with all possible fonts. Doing your own running calculation of the word wrapping will allow you to avoid the graphics rendering.

That is definately the fastest and most repeatable method! I had a similar challenge a few years ago when making a VI that would adjust the width of the column in a table to the widest item in each column respectively. It's fast and works great, but it took some out-of-the-box thinking.

Link to comment

QUOTE (crelf @ Sep 22 2008, 09:35 AM)

That is definately the fastest and most repeatable method! I had a similar challenge a few years ago when making a VI that would adjust the width of the column in a table to the widest item in each column respectively. It's fast and works great, but it took some out-of-the-box thinking.

The problem with this approach is that you need to turn off "dialog font" and specify exactly some font. You don't want it to switch to whatever font the user is using on their machine because that font may not be the same size as the one you wrote your word wrap code to support.

Link to comment

QUOTE (jlokanis @ Sep 21 2008, 11:32 PM)

Well, I think I cracked it! Here is the key:

http://lavag.org/old_files/monthly_09_2008/post-2411-1222119801.jpg' target="_blank">post-2411-1222119801.jpg?width=400

With this code, I was able to change the line locator algorithm to do a binary search. So, this is font independant and very fast. Please try it out. I updated it on the code repository.

*New* Search Text Control

-John

Link to comment

QUOTE (Aristos Queue @ Sep 23 2008, 07:54 AM)

Nope. Doesn't quite work...

post-5877-1222181592.png?width=400

The problem is that "Text.Font" comes back as "bold", which is not true of the entire string, just a portion of it.

Here's the problem VI if you want to work on this: Download File:post-5877-1222181619.vi

I think John solution works well for text with no formatting (using only one font). However as you pointed out earlier when you start to consider a string with multiple fonts and multiple formatting (bold, italic...) this is getting quite tricky.

PJM

Link to comment

QUOTE (JFM @ Sep 23 2008, 09:09 AM)

ou should also consider copying the "Enable Wrapping" property

Good point. I will add that.

As far as the multiple font issue goes, I don't use multiple fonts in my text displays, so that won't be an issue for me. But, if you come up with a solution, please post it in the CRID section where I posted the whole solution.

Unfortunatly, I was not able to open the code Aristos posted because I have yet to update to 8.6. I am guessing that the issue is the wrapping changes due to the bold. If I do not copy the font over, is there another way to make an exact copy of the contents, fonts and all? What about using the clipboard and the 'copy to clipboard' method? Does this preserver fonts between string controls?

As PJM pointed out, if you stick to one font, this solution does work. Hopefully we can get to a truely universal solution in the future. Perhaps Aristos can add a 'Get Number of lines' method to the string control in LV8.6.1? That would do the trick!

-John

Link to comment

QUOTE (Aristos Queue @ Sep 23 2008, 03:06 PM)

You'll have to find a new champion for that. Font runs and string controls are an area of LV I don't typically work in these days. :-)

I think this is one area of LV where it fails the 'general purpose' language test badly. We really should have text display controls that allow rich text, html rendering and support cut and paste of data that contains multiple fonts. And don't get me started on the fact that the string control scroll bar does not respond to the mouse wheel! :headbang:

As it currently stands, I can find no way to solve this issue. You simply cannot clone a string controls data EXACTLY to another string control.

Oh well, it works well for my use case (single font with no special formatting). I guess that is the state of the art for now...

On to the other issues:

1. Anyone know how to solve the highlighting issue? Can you have text highlighted in a stirng indicator when it is not in the frontmost VI?

2. How can I have the combo box 'see' the new entry when the user presses <CR> when it is bound to the find button?

thanks,

-John

Link to comment

QUOTE (jlokanis @ Sep 23 2008, 08:12 PM)

2. How can I have the combo box 'see' the new entry when the user presses <CR> when it is bound to the find button?

Set your <CR> button to both toggle and set focus. The combo box value doesn't update until it loses focus, and hitting <CR> isn't causing the combo box to lose focus, so the value doesn't update.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.