John Lokanis Posted September 20, 2008 Report Share Posted September 20, 2008 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 Quote Link to comment
Francois Normandin Posted September 21, 2008 Report Share Posted September 21, 2008 One trick is to use the method "Get Nth Line". Here's a quick example. (LV 8.6) Download File:post-10515-1221865409.vi Quote Link to comment
Francois Normandin Posted September 21, 2008 Report Share Posted September 21, 2008 One trick is to use the method "Get Nth Line". Here's a quick example. (LV 8.6) Download File:post-10515-1221865409.vi Quote Link to comment
crelf Posted September 21, 2008 Report Share Posted September 21, 2008 QUOTE (jlokanis @ Sep 19 2008, 05:38 PM) I can... locate the test and I can... highlight the found text, but I cannot figure out how to scroll the text box to the proper line. I honestly don't think you can do it directly - try using the "Get Nth Line" property and compare that with the start index of your search text. This might look a little funny as if the text scrolls over multiple lines, but it should work... QUOTE (normandinf @ Sep 19 2008, 07:09 PM) One trick is to use the method "Get Nth Line". Bugger it! I must be typing slow today Quote Link to comment
Francois Normandin Posted September 21, 2008 Report Share Posted September 21, 2008 QUOTE (crelf @ Sep 19 2008, 07:57 PM) Bugger it! I must be typing slow today 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. Quote Link to comment
crelf Posted September 21, 2008 Report Share Posted September 21, 2008 QUOTE (normandinf @ Sep 19 2008, 08:38 PM) Maybe your svn is beginning to slow down your network after all... :laugh: Actually, it was because I'd started the reply a couple of hours earlier and had gotten sidetracked with billable work half way through it Quote Link to comment
Aristos Queue Posted September 23, 2008 Report Share Posted September 23, 2008 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. Quote Link to comment
John Lokanis Posted September 23, 2008 Author Report Share Posted September 23, 2008 QUOTE (Aristos Queue @ Sep 21 2008, 08:56 PM) 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. 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 Quote Link to comment
Francois Normandin Posted September 23, 2008 Report Share Posted September 23, 2008 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... Quote Link to comment
Mads Posted September 23, 2008 Report Share Posted September 23, 2008 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. Quote Link to comment
Francois Normandin Posted September 23, 2008 Report Share Posted September 23, 2008 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. 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. Quote Link to comment
crelf Posted September 23, 2008 Report Share Posted September 23, 2008 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. Quote Link to comment
Aristos Queue Posted September 23, 2008 Report Share Posted September 23, 2008 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. Quote Link to comment
John Lokanis Posted September 23, 2008 Author Report Share Posted September 23, 2008 QUOTE (jlokanis @ Sep 21 2008, 11:32 PM) 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. Well, I think I cracked it! Here is the key: http://lavag.org/old_files/monthly_09_2008/post-2411-1222119801.jpg' target="_blank"> 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 Quote Link to comment
Aristos Queue Posted September 24, 2008 Report Share Posted September 24, 2008 Nope. Doesn't quite work... 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 Quote Link to comment
PJM_labview Posted September 24, 2008 Report Share Posted September 24, 2008 QUOTE (Aristos Queue @ Sep 23 2008, 07:54 AM) Nope. Doesn't quite work... 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 Quote Link to comment
Mellroth Posted September 24, 2008 Report Share Posted September 24, 2008 QUOTE (jlokanis @ Sep 22 2008, 11:50 PM) ...Well, I think I cracked it! Here is the key... Very nice... but I think you should also consider copying the "Enable Wrapping" property (cannot check at the moment). /J Quote Link to comment
John Lokanis Posted September 24, 2008 Author Report Share Posted September 24, 2008 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 Quote Link to comment
Mellroth Posted September 24, 2008 Report Share Posted September 24, 2008 QUOTE (jlokanis @ Sep 23 2008, 07:44 PM) Perhaps Aristos can add a 'Get Number of lines' method to the string control in LV8.6.1? That would do the trick! and/or make "text.scroll position" work with character number as well as line number... /J Quote Link to comment
John Lokanis Posted September 24, 2008 Author Report Share Posted September 24, 2008 QUOTE (JFM @ Sep 23 2008, 10:58 AM) and/or make "text.scroll position" work with character number as well as line number... Now your thinking! What we need is something like the 'ensure visable' method in the tree control! Quote Link to comment
Aristos Queue Posted September 24, 2008 Report Share Posted September 24, 2008 QUOTE (jlokanis @ Sep 23 2008, 12:44 PM) Perhaps Aristos can add a 'Get Number of lines' method to the string control in LV8.6.1? 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. :-) Quote Link to comment
John Lokanis Posted September 25, 2008 Author Report Share Posted September 25, 2008 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 Quote Link to comment
ned Posted September 25, 2008 Report Share Posted September 25, 2008 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. Quote Link to comment
John Lokanis Posted September 25, 2008 Author Report Share Posted September 25, 2008 QUOTE (ned @ Sep 24 2008, 06:35 AM) Set your <CR> button to both toggle and set focus. That fixed it! I posted the update in the CRID. Updated! Search Text Control Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.