How can I dynamically change the font colour within a JTextArea? - java

I'm writing a script for a code editor and I want dynamic commands.
So, if the user types "class" it will change the colour of "class".
How do I do this?
// This is the main focus part of the code.
textarea.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
word += evt.getKeyChar();
if(evt.getKeyCode() == KeyEvent.VK_ENTER) {
word = "";
line = "";
lineInMemory = line;
}
if(evt.getKeyCode() == KeyEvent.VK_SPACE) {
word = word.replaceAll("null","");
line += word;
word = "";
String text = textarea.getText();
String[] words = line.split(" ");
if(word.toLowerCase().equals("class")) {
// What the heck do I put here?!
}
}
}
});
I already have key listeners that read the keys, put them into words, and then the words are put into sentences. I would like it so that they type the keyword and it automatically changes the colour of the keyword while they are still typing, a bit like what Sublime Text does.

A JTextArea is only meant to contain plain text and cannot color certain words. If you want to be able to color different words, you need to use a JTextPane or a JEditorPane.
For more information, see this question. This question might also be helpful (especially the second answer).
Here is an example:
JTextPane textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
Style style = textPane.addStyle("Style", null);
StyleConstants.setForeground(style, Color.red);
String word = "Hello";
if (word.equals("Hello")) {
try {
doc.insertString(doc.getLength(), word, style);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
} else {
StyleConstants.setForeground(style, Color.blue);
try {
doc.insertString(doc.getLength(), word, style);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
This makes a String word. If word is "Hello" it will be displayed in red, otherwise it will be displayed in blue.

Related

Type what I have in a String into a program [duplicate]

I already know how to use java.awt.Robot to type a single character using keyPress, as seen below. How can I simply enter a whole pre-defined String value at once into a textbox?
robot.keyPress(KeyEvent.VK_1);
robot.keyPress(KeyEvent.VK_1);
robot.keyPress(KeyEvent.VK_1);
// instead, enter String x = "111"
Common solution is to use the clipboard:
String text = "Hello World";
StringSelection stringSelection = new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, stringSelection);
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_V);
robot.keyRelease(KeyEvent.VK_CONTROL);
Since Java 7 you can also use KeyEvent.getExtendedKeyCodeForChar(c). An example for lower case only could be:
void sendKeys(Robot robot, String keys) {
for (char c : keys.toCharArray()) {
int keyCode = KeyEvent.getExtendedKeyCodeForChar(c);
if (KeyEvent.CHAR_UNDEFINED == keyCode) {
throw new RuntimeException(
"Key code not found for character '" + c + "'");
}
robot.keyPress(keyCode);
robot.delay(100);
robot.keyRelease(keyCode);
robot.delay(100);
}
}
You need to "type" the character, which is a press AND release action...
robot.keyPress(KeyEvent.VK_1);
robot.keyRelease(KeyEvent.VK_1);
Now you could just copy and paste it three times, but I'd just put it in a loop
You can enter value in a string and then you can use that string as explained by Eng.Fouad. But there is no fun in using it, you can give a try to this
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_H);
robot.keyRelease(KeyEvent.VK_H);
robot.keyPress(KeyEvent.VK_E);
robot.keyRelease(KeyEvent.VK_E);
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_L);
robot.keyRelease(KeyEvent.VK_L);
robot.keyPress(KeyEvent.VK_O);
robot.keyRelease(KeyEvent.VK_O);
and you can also use Thread.sleep so that it can enter data bit slowly.
This doesn't type the entire "string" but helps to type whatever you want other than one character at a time.
Runtime.getRuntime().exec("notepad.exe");//or anywhere you want.
Thread.sleep(5000);//not required though gives a good feel.
Robot r=new Robot();
String a="Hi My name is Whatever you want to say.";
char c;
int d=a.length(),e=0,f=0;
while(e<=d)
{
c=a.charAt(e);
f=(int) c; //converts character to Unicode.
r.keyPress(KeyEvent.getExtendedKeyCodeForChar(f));
e++;
Thread.sleep(150);
}
see it works perfectly and it's awesome!
Though it doesn't work for special characters which cannot be traced by unicode like |,!...etc.
I think I've implemented better soultion, maybe someone found it usefull (the main approach is to read all values from enum KeyCode and than to put it into a HashMap and use it later to find a int key code)
public class KeysMapper {
private static HashMap<Character, Integer> charMap = new HashMap<Character, Integer>();
static {
for (KeyCode keyCode : KeyCode.values()) {
if (keyCode.impl_getCode() >= 65 && keyCode.impl_getCode() <= 90){
charMap.put(keyCode.getName().toLowerCase().toCharArray()[0], keyCode.impl_getCode());
}
else{
charMap.put(keyCode.getName().toLowerCase().toCharArray()[0], keyCode.impl_getCode());
}
}
}
public static Key charToKey(char c){
if(c>=65 && c<=90){
return new Key(charMap.get(c), true);
} else {
return new Key(charMap.get(c), false);
}
}
public static List<Key> stringToKeys(String text){
List<Key> keys = new ArrayList<Key>();
for (char c : text.toCharArray()) {
keys.add(charToKey(c));
}
return keys;
}
I created also a key class to know whether to type an uppercase or lowercase char:
public class Key {
int keyCode;
boolean uppercase;
//getters setter constructors}
and finally you can use it like that (for single character) robot.keyPress(charToKey('a').getKeyCode());
If you want to press an uppercase you have to press and release with shift key simultaneously
StringSelection path = new StringSelection("path of your document ");
// create an object to desktop
Toolkit tol = Toolkit.getDefaultToolkit();
// get control of mouse cursor
Clipboard c = tol.getSystemClipboard();
// copy the path into mouse
c.setContents(path, null);
// create a object of robot class
Robot r = new Robot();
r.keyPress(KeyEvent.VK_CONTROL);
r.keyPress(KeyEvent.VK_V);
r.keyRelease(KeyEvent.VK_CONTROL);
r.keyRelease(KeyEvent.VK_V);
r.keyPress(KeyEvent.VK_ENTER);
r.keyRelease(KeyEvent.VK_ENTER);
}

Moving both text and icons from one JTextPane to another

I'm currently making a GUI for a chat room. I've made it so the user enters text and can pick images that end up in a JTextPane. After the user presses enter I want to display it in another JTextPane though. Is there an easy way to move both text and icons from one JTextPane to another at the same time? I've only managed to move one of them at a time.
You can use an ElementIterator to copy over a JTextPane’s StyledDocument element by element, with all styling, including icons:
static void copy(Document source,
Document dest) {
try {
dest.remove(0, dest.getLength());
ElementIterator iterator = new ElementIterator(source);
Element element;
while ((element = iterator.next()) != null) {
if (element.isLeaf()) {
int start = element.getStartOffset();
int end = element.getEndOffset();
String text = source.getText(start, end - start);
dest.insertString(dest.getLength(), text,
element.getAttributes());
}
}
} catch (BadLocationException e) {
throw new RuntimeException(e);
}
}

How to add multiple data in JTextField?

I want to add data from JTextField but if I pressed the process again, the data that I write is missing. Is there any solution for this code?
try{
txttujuan.removeAll();
int xxx=0;
String XNilai,Nilai;
for (xxx=0;xxx <jtable.getRowCount();xxx++){
if (jtable.getValueAt(xxx,4).equals("1")){
Nilai ="0"+ (String) jtable.getValueAt(xxx,2);
XNilai+=Nilai+",";
} else continue;
System.out.print(XNilai.substring(0,XNilai.lastIndexOf(",")));
jtextfield.setText();
jtextfield.setText(XNilai.substring(0,XNilai.lastIndexOf(",")));
XNilai="";
}
} catch (Exception e){
System.out.print(e);
}
my data i've already wrote is missing
That is what the setText() method does. It replaces the existing text with the new text.
Instead of using a JTextField you can try using a JTextArea, then you can use the following to add text to the end:
textArea.append( "some text" );
If you really want to use a JTextField then you can use:
Document doc = textField.getDocument();
doc.insertString("some text", doc.getLength(), null);
to append text to the text field.

Get current line when some previous lines was collapsed in my own eclipse editor

Im trying to get the current line of keyboard cursor.
StyledText styledText = (StyledText) getAdapter(Control.class);
styledText.addCaretListener(event -> {
try {
IDocument document = getDocumentProvider().getDocument(getEditorInput());
// This is the current line
int currentLine = document.getLineOfOffset(event.caretOffset);
} catch (BadLocationException e) {
}
});
But the method getLineOfOffset doesn't work when some previous lines are collapsed. The event.caretOffset change if the document was collapsed.
Im tryed to use this code:
ISelectionProvider selectionProvider = ((ITextEditor)editor).getSelectionProvider();
ISelection selection = selectionProvider.getSelection();
if (selection instanceof ITextSelection) {
ITextSelection textSelection = (ITextSelection)selection;
return textSelection.getStartLine();
}
But this last code return the old line selected. I think the event of addCaretListener executes before the change line (not sure).
How can I get the current line even the document was collapsed in addCaretListener event?
If your editor is using ProjectionViewer as the source viewer you can
use the ITextViewerExtension5 widgetOffset2ModelOffset method:
ISourceViewer sourceViewer = getSourceViewer(); // Get your SourceViewer
StyledText styledText = sourceViewer.getTextWidget();
int docOffset = 0;
if (sourceViewer instanceof ITextViewerExtension5) {
ITextViewerExtension5 extension = (ITextViewerExtension5)sourceViewer;
docOffset = extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
}
else {
int offset = sourceViewer.getVisibleRegion().getOffset();
docOffset = offset + styledText.getCaretOffset();
}
IDocument document = sourceViewer.getDocument();
int currentLine = document.getLineOfOffset(docOffset);
(adapted from the JDT JavaEditor).

Java String- Font style check

I need to do font style check for my selected text area.
I used applescript to copy my highlighted/selected text area to clipboard and retrieve the clipboard value in java. I used string to capture the selected/highlighted value.
Is there any way I can do style check using String in java.
Code retrieve clipboard value:
String result = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//odd: the Object param of getContents is not currently used
Transferable contents = clipboard.getContents(null);
boolean hasTransferableText = (contents != null) &&
contents.isDataFlavorSupported(DataFlavor.stringFlavor);
if ( hasTransferableText ) {
try {
result = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch (UnsupportedFlavorException ex){
}
catch (IOException ex) {
}
}
return result;
}
Font Info:
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
{\fonttbl\f0\fnil\fcharset0 Verdana;\f1\fnil\fcharset0 Tahoma;}
{\colortbl;\red255\green255\blue255;}
\deftab720
\pard\pardeftab720\sa280
\f0\i\fs34 \cf0 testing
\f1\i0 hello\'a0
\b Module
\b0 \ul world}
{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
{\fonttbl\f0\fnil\fcharset0 Verdana;\f1\fnil\fcharset0 Tahoma;}
{\colortbl;\red255\green255\blue255;}
\deftab720
\pard\pardeftab720\sa280
\f0\i\fs34 \cf0 testing
\f1\i0 hello\'a0
\b Module
\b0 \ul world}
Please advice. Any advice/references is highly appreciated.
The values you are getting are the semantical codes for the rich text format. The code for an entire Java based rtf parser would be to long to post here, but for reference there is a RTFEditorKit0 in Swing and the Tika project at Apache has a RTFParser.
RTF uses Control Words - they have opening and closing tags similar to other markup languages like:
EXAMPLE: \someAsciiTag1 ... \someAsciiTag1
In the case of your question:
Font style is right there in the font table or \fnttbl group - groups are encapsulated by braces{}.
Font styles are ordered on an index like structure with \f*index* as the control code.
Next code is \f*font-family* and so on.
While global font styles are set at the top of the file in the \fnttbl certain style modifications can be made in the plain text section like html for instance: \fs20 means font-size = 20 of whatever units are inherited further up the structure like css.
While I could post Java code here to show you how to access a particular tag, and will if you just need to access a few global elements, but I don't know the scope of your whole project, if it is your goal to get ALL the style from your text I would really, very strongly encourage you to use one of the parsers available above as RTF is a very complex format.
In case you doubt me on this here is a link to the Microsoft spec it's about 270 pages, the lightest weight implementation that I know of that is pretty close to spec complete is over 9000 lines of code, which is why you probably don't want to do it yourself.
http://www.microsoft.com/en-us/download/details.aspx?id=10725
EDIT:
I realized i didn't fully answer your second question in the previous answer
\b or \b1 = bold(true or 1) AND \b0 = bold(false or 0)
\i or \i1 = italic(true or 1) AND \i0 = italic(false or 0)
FYI however, these are not the only ways to set style, rtf allows other less common programatic ways of setting these values. Also there are differences between ascii and unicode rtf codes, so once again use a parser.
I have none the less included the font tag structure so if you want global info you can get it.
<fonttbl> '{' \fonttbl (<fontinfo> | ('{' <fontinfo> '}'))+ '}'
<fontinfo> <themefont>? \fN <fontfamily> \fcharsetN? \fprq? <panose>? <nontaggedname>?
<fontemb>? \cpgN? <fontname> <fontaltname>? ';'
<themefont> \flomajor | \fhimajor | \fdbmajor | \fbimajor | \flominor | \fhiminor |
\fdbminor | \fbiminor
<fontfamily> \fnil | \froman | \fswiss | \fmodern | \fscript | \fdecor | \ftech |
\fbidi
<panose> '{\*' \panose <data> '}'
<nontaggedname> '{\*' \fname #PCDATA ';}'
<fontname> #PCDATA
<fontaltname> '{\*' \falt #PCDATA '}'
<fontemb> '{\*' \fontemb <fonttype> <fontfname>? <data>? '}'
<fonttype> \ftnil | \fttruetype
<fontfname> '{\*' \fontfile \cpgN? #PCDATA '}'
That is a list of font data tags and the general structure of the font data in line. Hope that helps.
EDIT: Follow Up
Well from look of it you have a nice chunk of Mac rtfd (the extra tags)
cocoartf1038\cocoasubrtf360 - tells you it's mac encoded
The first part gives the encoding
The second gives two main font styles Verdana at f0, and Tahoma at f1
the third line tells you it's white rgb(255,255,255) and all.
the fourth and fifth define tabs and pagination.
the sixth (non-blank) say f0\i\fs34 = Verdana, Italic, size 34 \cf0 is black foreground color
the seventh is Tahoma italic, bold is around module, while world is underlined and so on then repeats.
There is a Java based rtf parser that recently added support for some of the mac custom tags you can find it on GitHub here it should be fairly simple to wire-up the modules and parse any files you may need.
You have the formatting data included in your data, only if the text in the clipboard is in Rich Formatted Text (RTF). In this case, when you checked and the content of clipboard contained RTF text, you can check its font and other formatting information. You can use this sample code as a starting point.
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
public class ClipboardTest {
public static void main(String[] args) {
System.out.println(getClipboardData());
}
public static String getClipboardData() {
String result = "";
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
// odd: the Object param of getContents is not currently used
Transferable contents = clipboard.getContents(null);
DataFlavor dfRTF = new DataFlavor("text/rtf", "Rich Formatted Text");
DataFlavor dfTxt = DataFlavor.stringFlavor;
boolean hasTransferableRTFText = (contents != null)
&& contents.isDataFlavorSupported(dfRTF);
boolean hasTransferableTxtText = (contents != null)
&& contents.isDataFlavorSupported(dfTxt);
if (hasTransferableRTFText) {
try {
result = streamToString((InputStream)contents
.getTransferData(dfRTF));
} catch (Exception ex) {
ex.printStackTrace();
}
} else if (hasTransferableTxtText) {
try {
result = (String)contents
.getTransferData(dfTxt);
} catch (Exception ex) {
ex.printStackTrace();
}
}
return result;
}
private static String streamToString(InputStream transferData) {
return slurp(transferData, 1024);
}
public static String slurp(final InputStream is, final int bufferSize)
{
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
try {
final Reader in = new InputStreamReader(is, "UTF-8");
try {
for (;;) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
}
finally {
in.close();
}
}
catch (UnsupportedEncodingException ex) {
/* ... */
}
catch (IOException ex) {
/* ... */
}
return out.toString();
}
}

Categories