JavaFX: Select a single line of text in a textarea where .getCaretPosition() - javafx

Platform: Intellij IDEA
Language: JavaFX
I would like to be able to select a line of text where the cursor lies. Similar to SQL Developer, I have a textarea that allows multiples lines of input or queries. It is nice to be able to use the textarea as a query bank while testing queries.
Using the txtOutput.getCaretPosition(), I would like to get the current integer index of the line where the cursor resides and then be able to select all of the text that is within that same line with the same keyboard shortcut as SQL Developer (Ctrl + Enter). Using the .selectForward() or .selectBackward() will not work if there are multiple lines.
Any help or suggestions as to how to limit the selection of text to one line or select text up until a specific character (e.g. ";") would be much appreciated.
public void executeEvent(KeyEvent event) {
//int cursorLine = txtInput.getCaretPosition();
if (event.isControlDown() == true && event.getCode() == KeyCode.ENTER) {
//select line of text where integer equals cursorLine
//txtInput.selectBackward();
//txtInput.selectForward();
}
}

Just search the text for the relevant delimiting character (e.g. a newline character), and select the relevant portion. The only thing you have to be careful of here is if the user selects the last line, in which case there will be subsequent newline character:
int caretPos = txtInput.getCaretPosition();
int previousNewline = txtInput.getText().lastIndexOf('\n', caretPos);
int nextNewline = txtInput.getText().indexOf('\n', caretPos);
if (nextNewline == -1) nextNewline = txtInput.getText().length();
txtInput.selectRange(previousNewLine + 1, nextNewLine);

Related

Selecting non-alpha chars with QTextCursor

I'm trying to add syntax completion to a QTextEdit base editor and I'd like to support non-alpha characters to trigger the QCompleter popup. I'm using QTextCursor::select to get the current word but it is always filtering out non-alpha characters. Is there an option I need to use for this ?
Here's the code I use to get the text:
QTextCursor tc = textCursor();
tc.select(QTextCursor::WordUnderCursor);
QString t = tc.selectedText();
thanks
Words actually do not contain alpha characters. To select the last input character:
QTextCursor tc = textCursor();
tc.movePosition ( QTextCursor::Left, QTextCursor::KeepAnchor);
QChar lastChar = tc.selectedText().at(0);
if (!lastChar.isLetterOrNumber())
{
do something;
}
Replace the isLetterOrNumber() with whatever characters you might check for.

how do i delete characters in a string/text of a textbox?

I have an asp.net 4 textbox control that has it's text being dynamically populated by some java script. A Google Maps call to be exact. It's giving me mileage from 1 point to another. When the text displays, it shows " 234 mi" I need to get rid of the "mi" part of this text because the text is being converted to an Int32 Updating a table in my DB.
Basically I can only have an INT. Nothing else in the text box. How do I get rid of the "mi" at the end of the text?
Thanks
C#
EB
On the postback, before you save it you could:
var saveValue = Int32.Parse(tbTarget.Text.Replace("mi", string.Empty).Trim());
If your working with a variable length of chars (say someone enters miles instead) then your must do a foreach against the string (an array of char) and check isnumeric on each char.
A simple String.Substring works also:
String leftPart = TxtMileAge.Text.Substring(0, txt.IndexOf(' '));
int mileAge = int.Parse(leftPart);
This retrieves the part of the String in the range of 0 - indexOfWhiteSpace and converts it to an int
Edit: Since the value can have decimal places (as you've commented), you need to parse it to double, round it and then cast it to int:
var txtEstDistance = new TextBox() { Text = "40.2 mi" };
String leftPart = txtEstDistance.Text.Substring(0, txtEstDistance.Text.IndexOf(' '));
double distanceMiles = double.Parse(leftPart, System.Globalization.CultureInfo.InvariantCulture);
int oDdstanceMiles = (int)Math.Round(distanceMiles, MidpointRounding.AwayFromZero);

How to get multiple value from one textbox?

I have created web application and textbox as a textarea. I am using javascript for validation. When I enter value in text box so it should be number not alphabet I have use textmode is multiple line.
My problem is that how I get multiple value from textbox and store in array in javascript and check each value is number or not. I am using the web form. Please help me.
You can get the value from a textarea like
var txtvalue = document.getElementById("txtareaid").value
and if are using a separator then something like
var txtvaluearray = document.getElementById("txtareaid").value.split(';')
will get you all the values in an array if the seperator is ;
Edit
As per your update you can use \n as the separator and as pointed by #Sohnee you can do the validation.
As addition to rahul:
If you want the values in the textarea seperated by line, you can use \r\n as the splitter.
This is a starter for ten.
var textValues = document.getElementById("mytextarea").value.split("\n");
for (var i = 0; i < textValues.length; i++) {
if (isNaN(textValues[i])) {
alert(textValues[i] + " is not a number.";
}
}

Flex Rich Text Editor - Limiting the number of characters

Is there a way to restrict the number
of characters in the Flex Rich Text Editor?
I guess there should be, since it's possible
in a textarea. So, if I could get hold
of the textarea contained in the rich
text editor, I would be able to do it
I think this would be fairly easy in actionscript, although I'm not exactly sure how one would do it in mxml. It appears that there are two children that are contained in the RichTextEditor, one of them being TextArea. According to the documentation (http://livedocs.adobe.com/flex/3/langref/mx/controls/RichTextEditor.html#propertySummary), you can access the subcontrols like so:
myRTE.toolBar2.setStyle("backgroundColor", 0xCC6633);
With myRTE being the instance of your text editor. So my guess would be something like this would work:
myRTE.textArea.maxChars = 125;
With 125 being the number a characters you would want restricted to.
i just ran into this.
setting your maxChars on the textArea will provide a limit to the text area, but that won't be representative of the number of characters the user can type.
as the user is typing, markup is added behind the scenes, and that greatly increases the char count.
for example, if i type the letter 'a' into a RichTextEditor, i get a char count of 142 and this htmlText:
<TEXTFORMAT LEADING="2"><P ALIGN="LEFT"><FONT FACE="Verdana" SIZE="10" COLOR="#0B333C" LETTERSPACING="0" KERNING="0">a</FONT></P></TEXTFORMAT>
i could not see a straightforward way to get a proper maxChar to work out of the box, so i extended RichTextEditor and gave it a maxChar. if maxChar > 0, i added a listener to "change" and did something like this in the event handler:
protected function handleTextChange(event:Event) : void
{
var htmlCount:int = htmlText.length;
// if we're within limits, ensure we reset
if (htmlCount < maxChars)
{
textArea.maxChars = 0;
this.errorString = null;
}
// otherwise, produce an error string and set the component so the user
// can't keep typing.
else
{
var textCount:int = textArea.text.length;
textArea.maxChars = textCount;
var msg:String = "Maximum character count exceeded. " +
"You are using " + htmlCount + " of " + maxChars + " characters.";
this.errorString = msg;
}
}
the idea is to apply a maxChars to the text area only when in the error state, so the user cannot type anything additional and will be prompted to erase some chars. once we leave the error state, we need to set the textArea.maxChars to zero so they can continue.

Full text search on a mobile device?

We'll soon be embarking on the development of a new mobile application. This particular app will be used for heavy searching of text based fields. Any suggestions from the group at large for what sort of database engine is best suited to allowing these types of searches on a mobile platform?
Specifics include Windows Mobile 6 and we'll be using the .Net CF. Also some of the text based fields will be anywhere between 35 and 500 characters. The device will operate in two different methods, batch and WiFi. Of course for WiFi we can just submit requests to a full blown DB engine and just fetch results back. This question centres around the "batch" version which will house a database loaded with information on the devices flash/removable storage card.
At any rate, I know SQLCE has some basic indexing but you don't get into the real fancy "full text" style indexes until you've got the full blown version which of course isn't available on a mobile platform.
An example of what the data would look like:
"apron carpenter adjustable leather container pocket waist hardware belt" etc. etc.
I haven't gotten into the evaluation of any other specific options yet as I figure I'd leverage the experience of this group in order to first point me down some specific avenues.
Any suggestions/tips?
Just recently I had the same issue. Here is what I did:
I created a class to hold just an id and the text for each object (in my case I called it a sku (item number) and a description). This creates a smaller object that uses less memory since it is only used for searching. I'll still grab the full-blown objects from the database after I find matches.
public class SmallItem
{
private int _sku;
public int Sku
{
get { return _sku; }
set { _sku = value; }
}
// Size of max description size + 1 for null terminator.
private char[] _description = new char[36];
public char[] Description
{
get { return _description; }
set { _description = value; }
}
public SmallItem()
{
}
}
After this class is created, you can then create an array (I actually used a List in my case) of these objects and use it for searching throughout your application. The initialization of this list takes a bit of time, but you only need to worry about this at start up. Basically just run a query on your database and grab the data you need to create this list.
Once you have a list, you can quickly go through it searching for any words you want. Since it's a contains, it must also find words within words (e.g. drill would return drill, drillbit, drills etc.). To do this, we wrote a home-grown, unmanaged c# contains function. It takes in a string array of words (so you can search for more than one word... we use it for "AND" searches... the description must contain all words passed in... "OR" is not currently supported in this example). As it searches through the list of words it builds a list of IDs, which are then passed back to the calling function. Once you have a list of IDs, you can easily run a fast query in your database to return the full-blown objects based on a fast indexed ID number. I should mention that we also limit the maximum number of results returned. This could be taken out. It's just handy if someone types in something like "e" as their search term. That's going to return a lot of results.
Here's the example of custom Contains function:
public static int[] Contains(string[] descriptionTerms, int maxResults, List<SmallItem> itemList)
{
// Don't allow more than the maximum allowable results constant.
int[] matchingSkus = new int[maxResults];
// Indexes and counters.
int matchNumber = 0;
int currentWord = 0;
int totalWords = descriptionTerms.Count() - 1; // - 1 because it will be used with 0 based array indexes
bool matchedWord;
try
{
/* Character array of character arrays. Each array is a word we want to match.
* We need the + 1 because totalWords had - 1 (We are setting a size/length here,
* so it is not 0 based... we used - 1 on totalWords because it is used for 0
* based index referencing.)
* */
char[][] allWordsToMatch = new char[totalWords + 1][];
// Character array to hold the current word to match.
char[] wordToMatch = new char[36]; // Max allowable word size + null terminator... I just picked 36 to be consistent with max description size.
// Loop through the original string array or words to match and create the character arrays.
for (currentWord = 0; currentWord <= totalWords; currentWord++)
{
char[] desc = new char[descriptionTerms[currentWord].Length + 1];
Array.Copy(descriptionTerms[currentWord].ToUpper().ToCharArray(), desc, descriptionTerms[currentWord].Length);
allWordsToMatch[currentWord] = desc;
}
// Offsets for description and filter(word to match) pointers.
int descriptionOffset = 0, filterOffset = 0;
// Loop through the list of items trying to find matching words.
foreach (SmallItem i in itemList)
{
// If we have reached our maximum allowable matches, we should stop searching and just return the results.
if (matchNumber == maxResults)
break;
// Loop through the "words to match" filter list.
for (currentWord = 0; currentWord <= totalWords; currentWord++)
{
// Reset our match flag and current word to match.
matchedWord = false;
wordToMatch = allWordsToMatch[currentWord];
// Delving into unmanaged code for SCREAMING performance ;)
unsafe
{
// Pointer to the description of the current item on the list (starting at first char).
fixed (char* pdesc = &i.Description[0])
{
// Pointer to the current word we are trying to match (starting at first char).
fixed (char* pfilter = &wordToMatch[0])
{
// Reset the description offset.
descriptionOffset = 0;
// Continue our search on the current word until we hit a null terminator for the char array.
while (*(pdesc + descriptionOffset) != '\0')
{
// We've matched the first character of the word we're trying to match.
if (*(pdesc + descriptionOffset) == *pfilter)
{
// Reset the filter offset.
filterOffset = 0;
/* Keep moving the offsets together while we have consecutive character matches. Once we hit a non-match
* or a null terminator, we need to jump out of this loop.
* */
while (*(pfilter + filterOffset) != '\0' && *(pfilter + filterOffset) == *(pdesc + descriptionOffset))
{
// Increase the offsets together to the next character.
++filterOffset;
++descriptionOffset;
}
// We hit matches all the way to the null terminator. The entire word was a match.
if (*(pfilter + filterOffset) == '\0')
{
// If our current word matched is the last word on the match list, we have matched all words.
if (currentWord == totalWords)
{
// Add the sku as a match.
matchingSkus[matchNumber] = i.Sku.ToString();
matchNumber++;
/* Break out of this item description. We have matched all needed words and can move to
* the next item.
* */
break;
}
/* We've matched a word, but still have more words left in our list of words to match.
* Set our match flag to true, which will mean we continue continue to search for the
* next word on the list.
* */
matchedWord = true;
}
}
// No match on the current character. Move to next one.
descriptionOffset++;
}
/* The current word had no match, so no sense in looking for the rest of the words. Break to the
* next item description.
* */
if (!matchedWord)
break;
}
}
}
}
};
// We have our list of matching skus. We'll resize the array and pass it back.
Array.Resize(ref matchingSkus, matchNumber);
return matchingSkus;
}
catch (Exception ex)
{
// Handle the exception
}
}
Once you have the list of matching skus, you can iterate through the array and build a query command that only returns the matching skus.
For an idea of performance, here's what we have found (doing the following steps):
Search ~171,000 items
Create list of all matching items
Query the database, returning only the matching items
Build full-blown items (similar to SmallItem class, but a lot more fields)
Populate a datagrid with the full-blow item objects.
On our mobile units, the entire process takes 2-4 seconds (takes 2 if we hit our match limit before we have searched all items... takes 4 seconds if we have to scan every item).
I've also tried doing this without unmanaged code and using String.IndexOf (and tried String.Contains... had same performance as IndexOf as it should). That way was much slower... about 25 seconds.
I've also tried using a StreamReader and a file containing lines of [Sku Number]|[Description]. The code was similar to the unmanaged code example. This way took about 15 seconds for an entire scan. Not too bad for speed, but not great. The file and StreamReader method has one advantage over the way I showed you though. The file can be created ahead of time. The way I showed you requires the memory and the initial time to load the List when the application starts up. For our 171,000 items, this takes about 2 minutes. If you can afford to wait for that initial load each time the app starts up (which can be done on a separate thread of course), then searching this way is the fastest way (that I've found at least).
Hope that helps.
PS - Thanks to Dolch for helping with some of the unmanaged code.
You could try Lucene.Net. I'm not sure how well it's suited to mobile devices, but it is billed as a "high-performance, full-featured text search engine library".
http://incubator.apache.org/lucene.net/
http://lucene.apache.org/java/docs/

Resources