I would like to have a document editor where certain document lines are uneditable, unclickable, etc.
I currently am using a JTextPane for my editor and extensions of DefaultStyledDocument and LeafElement, StyledEditorKit, and ParagraphView, to parse the document text into the appropriate elements and assign them to the appropriate extensions of ParagraphView. Everything is peachy up to this point.
So how to take the next step? How to designate and enforce certain extended ParagraphViews are "read-only"?
My current approach is to override getNextVisualPositionFrom in the Leaf and Section ParagraphViews to prevent arrow keys from moving the cursor into a restricted ParagraphView, but preventing the mouse from clicking inside a restricted ParagraphView has to be handled separately.
Is there a simpler, more comprehensive approach to this?
Thanks!
After a bit more research, a different approach that seems to fit more elegantly is to use a ComponentView for the uneditable views, instead of ParagraphView.
I can then use something as simple as a JTextArea in the ComponentView in its createComponent() method and setEditable to false.
It automatically ignores mouse clicks in that view. I still have to include my code for nicely skipping the caret over the view when the user presses up, down, left, right. Otherwise, the caret will invisibly move through underlying model text. I will also have to prevent backspacing through the protected view. Even though the view is uneditable, the model data underneath can still be affected by the user.
Related
In this answer, I've posted my solution for disable default copy, paste, select all and clipboard behaviour for an EditText, including disable handle select cursor:
There are three steps that includes a) a short snippet of code (many times posted in Stackoverflow); b) an empty image and c) a custom and global EditText style
If one does just step a, it keeps on showing the handle select. And if one click the handle select, appears the popup with Clipboard + Select All So one should select an empty image associated with the handle select.
However, there is one feature that I can't handle at all:
The double click Android default behaviour that selects with pink background the clicked word just for a fraction of a second, below showed:
I've tried many solution proposed in StackOverflow, including change onClick (plugged by setOnClickListener) event for disable the TextEdit control for less than 1 second, using timer or post events.
I also tried handle the cursor in onTouch event.
I even try to program a empty double click handling in GestureDetector.SimpleOnGestureListener()
No success. No clue.
Update
For helping clarify, the features of my problem demand:
1) There is no way to display any extra keys to start typing
2) I need to let the user touch any point of the text, indicating their "insert" position, if applicable. Usually he types at the end of the text and there is no cursor. In that case, I disable it.
3) I need to let the user touch in sequence 2 points of the text, to make a selection, with a marked background. It's not exactly a double click, it's two comfortably separate clicks. I don't like double click for mobile.
-/-
In short, I need to work with the cursor, but not in the standard way that Android offers. Therefore I would need to disable the default Android behaviour, but without losing the cursor and the ability to select a piece of text.
-/-
There is an option to make an artificial cursor that blinks, but I imagine it is quite laborious because the cursor don't occupy on character position exactly.
Update 2
When I use in EditText global style
<item name="android:focusableInTouchMode">false</item>
The double click becomes inactive, but I cannot show the cursor anymore neither make a selection by software.
Have you tried this:
1) Have a TextView showing on the screen (non editable with non of the problems you are explaining).
2) Have a button on the screen that says "start typing" or whatever you want as UX to start the interaction. You could even put the click listener straight on the TextView.
3) Have an offscreen / hidden under another view EditText, that when the OnClick in #2 is triggered will focus on this view - thus popping up the keyboard and starting input.
4) Have a text changed listener on the edittext and whenever they type into the edittext it updates the TextView from #1 with this text.
Thus making the whole thing cursor-less.
I've found a way to work around the problem. It is not the most elegant solution that could exist, however it acceptable.
However, I don't go consider a right solution, it is just a trick. It's amazing that apparently has no general solution to turn off word selection by double click.
When I create the EditText dinamically, i set
tEdit.setHighlightColor(Color.TRANSPARENT) // tEdit is my TextEdit view
When I will select an area inside my program, I will use underline to delimit my selected area, so I keep the highlight color always transparent.
I have questions according to my final project in my IT Faculty.. I have to make A simple text editor (like notepad) without using JTextArea (GUI Java), I have to make my own JTextArea..
Idea/Topic= Own Text Editor
Algorithms= doesnt have any idea yet
Data Structure= Rope(Member of Binary Trees)
Requirement= Typing without JTextArea...
Is that possible to make that? Can a panel (or something else like that) has a listener or make a listener to do that?
simply thinking, First step I just want to try for typing on a panel, absolutely algorithms needed but i dont get right algorithms so far.. Is that possible?
My thinking is, for text that im typing is stored to a tree.. Is that Rope(Member of Binary Trees) for my data Structure?
Thanks for helping...
It's possible.
Use as you mentioned JPanel attaching KeyListener and MouseListener.
You need a model (Document). For simplest case it could be e.g StringBuilder where you can add content and show the StringBuilder content.
You need caret position (int field) to indicate where the edit should happen.
You need Font field to keep all the font info to be used in the editor.
Override paintComponent() and use FontMetrics to measure the text and calculate necessary width/height. For the start I would create a text area without line wrap.
Implement viewToModel/modelToView methods. They should calculate position of caret for given x,y and x,y for given caret position.
As a part of a GUI design that I'm implementing in Java swing, I need the user to be able to select parts or subparts of a tree like structure represented as a string.
For example, if I were to display the following expression, ((a|b)|(c|d))
The user would need to be able to select any of the following
(a|b), (c|d) or the entire thing ((a|b)|(c|d)).
Ideally I'd like them to be able to navigate via the keyboard arrows, moving up and down though the nested subexpressions, and hit enter when they come to the subexpression they want. However if its only possible to do this on mouse click, thats also acceptable.
The main issue that I'm having with this is the nesting component. I could easily make the entire expression selectable, but I don't know how to allow subexpressions to be selectable using SWING components. Based on my research Swing doesn't allow nesting of labels of text areas in the manner that I need so I'm looking for any alternatives.
Any help or suggestions would be much appreciated.
You could use a Highlighter and a DocumentListener on the read-only JTextField suggested by Joop in the comment above, following http://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html in the section about JTextFieldDemo. That way you can highlight your (partial) string and listen to what (sub)string is selected, and compare it to the original string to check for matches.
If you have a text component in Java and you do a replace the cursor will not move, if you undo and redo that replace using a standard undo manager the cursor will move to the beginning or end of that insertion or deletion.
How would I prevent this behavior?
I was able to trigger this with the Java TextComponentDemo, where I added a simple replace action that did this:
doc.replace(doc.getText(0, doc.getLength()).indexOf("mouse"), 5, "cat", null);
If I then use the demo's undo's and redo's the cursor will move.
Java Swing isn't the only API that has this behaviour in the standard undo manager. Sometimes XUL (which is the base for Firefox and Thunderbird) does the same thing with text areas in 3rd-party extensions. Essentially, even though the original text and the replacement text are similar in this case, the text area has to treat the document as an entirely new one, just like if you had done a select all and paste to overwrite the old text. In general, restoring the same cursor position to the new document would be useless, and if the document is shorter, it might not even be possible.
I think the easiest way around this would be to create your own custom actions for replacing text. Listen for them and perform the actions instead of performing the default action. Your custom action should be a compound action which scans the document manually, replacing substrings in the existing document - scan and replace all the way to the end by performing a number of document changes. When you override the undo method, just go through the list of modifications you made, undoing each one in reverse order. As long as each action in the compound action sets the text and the cursor position correctly, and its undo method works properly, the whole compound action will also undo properly.
This guide should hopefully explain this concept a little more clearly. The example merges actions into groups while the user types. You just need to do the same, but with procedural edits instead.
Check out the caret update policy in the class DefaultCaret.
The following update policies are
allowed:
NEVER_UPDATE: the caret stays at the same absolute position in the
document regardless of any document
updates, except when document length
becomes less than the current caret
position due to removal. In that case
caret position is adjusted to the end
of the document. The caret doesn't try
to keep itself visible by scrolling
the associated view when using this
policy.
ALWAYS_UPDATE: the caret always tracks document changes. For regular
changes it increases its position if
an insertion occurs before or at its
current position, and decreases
position if a removal occurs before
its current position. For undo/redo
updates it is always moved to the
position where update occurred. The
caret also tries to keep itself
visible by calling adjustVisibility
method.
UPDATE_WHEN_ON_EDT: acts like ALWAYS_UPDATE if the document updates
are performed on the Event Dispatching
Thread and like NEVER_UPDATE if
updates are performed on other thread.
You can set the update policy to NEVER_UPDATE before an undo or redo action, then set it back to what it was after the action.
public void actionPerformed(ActionEvent e) {
int updatePolicy = caret.getUpdatePolicy();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
undoManager.undo();
caret.setUpdatePolicy(updatePolicy);
}
I'm currently making a GWT project where I display some HTML in a RichTextArea, and I want the RichTextArea to be selectable/highlight-able by a mouse but NOT be editable/modifiable by the user. In addition to this question, could you also tell me how to retrieve some highlighted text in string from without me having to add a text-background toolbar, which, after highlighting a text from the RichTextArea, you change the color of the text-background, upon which, you add a separate periodically looping thread which checks to see when the text-background changes substantially from white (or a native color of the webpage) and finally extracting the string whose text-background color differs as the selected text.
I really hate to give any pointers without explanation but i think your requirements are bigger ::: so --->
http://examples.roughian.com/index.htm#Widgets~RichTextArea
http://www.java2s.com/Code/Java/GWT/RichTextArea.htm