Override mousePressedHandler BasicTableUI (JTable) - java

I want to adjust my JTable such that when I start editing a cell and then select a range of cells, the cell editor doesn't disappear, but instead changes it's value to the "current selection".
I already have a custom ListSelectionListener that listens for changes in the selections and creates an Range object from that which can be converted to a String (eg. A1:C3), but I'm looking for a way to hook in at the moment where the cell editor is being stopped / the selection event starts, so that I can prevent the default behaviour and stay in editing mode while selecting cells. Does any one have an idea?
Edit:
I have come a little bit further. When throwing an error in the removeEditor() method, I get the following stack trace:
at GUI.STable.removeEditor(STable.java:71)
at javax.swing.JTable.editingStopped(JTable.java:4724)
at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141)
at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(DefaultCellEditor.java:368)
at javax.swing.DefaultCellEditor.stopCellEditing(DefaultCellEditor.java:233)
at GUI.STable$CustomTableCellEditor.stopCellEditing(STable.java:119)
at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(BasicTableUI.java:1010)
This leads to the mousePressed event in BasicTableUI, which indeed closes the current editor:
if (table.isEditing() && !table.getCellEditor().stopCellEditing()) {
Component editorComponent = table.getEditorComponent();
if (editorComponent != null && !editorComponent.hasFocus()) {
SwingUtilities2.compositeRequestFocus(editorComponent);
}
return;
}
But how can I override this mousePressed handler in BasicTableUI?

Related

JFace TableViewer - Deselected rows reselect themselves automatically, with bonus asynchronous weirdness

I'm writing an eclipse RCP program that has a single-select JFace TableViewer in the GUI. Single select TableViewers don't have a default way of deselecting the selection, so I figured I'd add one by adding my own listener. The idea is to clear the selection if the user clicks on the already-selected row.
myTableViewer.addPostSelectionChangedListener(new ISelectionChangedListener(){
private boolean inLoop = false;
private StructuredSelection previousSelection = StructuredSelection.EMPTY;
#Override
public void selectionChanged(SelectionChangedEvent event) {
//Needed because setting the selection causes the listener to be called again.
if (inLoop) {
inLoop = false;
return;
}
StructuredSelection newSelection = (StructuredSelection) event.getSelection();
if (newSelection.equals(previousSelection)) {
newSelection = StructuredSelection.EMPTY;
inLoop = true;
myTableViewer.setSelection(StructuredSelection.EMPTY);
}
previousSelection = newSelection;
}
});
This unfortunately doesn't work. The selection is very briefly cleared, but about .2 seconds later the TableViewer automatically reselects the row that I just barely deselected!
It gets better. I debugged the JFace code a little to try and solve the issue. The TableViewer delegates its selection code to a StructuredViewer. If I put a breakpoint in StructuredViewer.setSelection(...), then all of a sudden my code works.
Apparently the PostSelectionChangedListener is poorly named and fires before the selection code is done running. My listener then races the StructuredViewer code, ends up changing the value too early, and then immediately gets overwritten.
Is there any way to avoid this? I'd really like to be able to deselect rows in the table viewer without having to add a clunky deselection button or keybinding. So far I've tried calling myTableViewer.getTable().setSelection(...), as well as packing the setSelection() call into a Display.asyncExec(...), but with no luck as yet. Any tips would be greatly appreciated!

How to check if the tab selected is changed in java

As far as i have seen the event:
(1) private void jTabbedPane1StateChanged(javax.swing.event.ChangeEvent evt) {}
Checks whether a new tab is added or an exiting tab is deleted or not.
On googling , i found this code:
(2) ChangeListener changeListener = new ChangeListener() {
public void stateChanged(ChangeEvent changeEvent) {
// my code
}
};
jTabbedPane1.addChangeListener(changeListener);
I guess since it uses stateChanged event , it should do what the same a my first code.
By t way even after using both the codes i could not get the required resuts(ie An event that could be invoked when user changes the tab).
Can anyone suggest me a good event [i am using netbeans GUI environment] for effective action. (I dont want any mouseEvents)
Edit:
I want the following code to be excecuted if the tab changes:
String send3=( jTabbedPane1.getSelectedComponent().getComponentAt(0,0)).getName();
The above code dynamically gets the name of jTextarea (in the current tab) which is created dynamically in the jTabbedPanel.
I just checked my own source code where addChangeListener() works fine. The event is fired whenever the tab is changed by the user or programatically. In stateChanged() itself, the now selected tab is determined by
JTabbedPane p = (JTabbedPane)e.getSource();
int idx = p.getSelectedIndex();

Java Focus Traversal to newly disabled button

I have a problem with the focus traversal system in Java. When I tab between components in a pane in my application everything works fine Tab moves the focus to the next component.
Some of my components perform validation on loss of focus, if the validation returns errors then the screens save button is disabled.
My problem occurs when the validated component is followed by the save button.
Tab removes focus from the validated component and begins the asynchronous process of assigning focus to the next component that is enabled (The Save Button)
Next my validation kicks in and disables the save button
The asynchronous process then finished and attempts to assign focus to the now disabled Save button.
The Focus now becomes trapped and tabbing no longer shifts focus because no component actually has the focus.
Has anyone else come across this problem, how did you solve the problem of having the validation and disablement carried out before the focus traversal event started?
You could use an InputVerifier to validate the text field. In this case focus will be placed back on the text field in error.
Or you could change your focus listener to handle this situation. Something like:
FocusListener fl = new FocusAdapter()
{
public void focusLost(final FocusEvent e)
{
JTextField tf = (JTextField)e.getSource();
if (tf.getDocument().getLength() < 1)
{
System.out.println("Error");
button.setEnabled( false );
Component c = e.getOppositeComponent();
if (c instanceof JButton
&& c.isEnabled() == false)
{
tf.requestFocusInWindow();
}
}
else
button.setEnabled( true );
}
};

JTabbedPane.getTabComponentAt(int) returning null

I have the following code :
JTabbedPane container;
...
AWindow page = WinUtils.buildWindow();
boolean existing = checkIfExists(page); // in this code, this will always be false
if(!existing)
{
String tabName = page.getLoadedFileLocation().getName();
container.addTab(page.getLoadedFileLocation().getName(), page);
}
Component comp = container.getTabComponentAt(0);
int sel = container.getSelectedIndex();
container.setSelectedComponent(page);
the thing is :
container.getTabComponentAt(0)
returns null. The other weird thing is :
container.getSelectedIndex()
returns 0. The logical thing that I think should happen, is to have a reference to the created window. Why am I receiving null? What am I doing wrong?
getTabComponentAt() returns the custom component you might add as the tab title. You might be looking for the getComponentAt() method to return the contents of a tab. The getSelectedIndex() just returns that the first tab is currently selected (it would return -1 for no tabs selected)
You're confusing the two sets of methods in JTabbedPane: the tab component methods and the component methods.
getTabComponentAt(0) is returning null because you haven't set the tab component. You've set the component that is displayed at index 0, but the tab component is the component that renders the tab--not the component that displays in the pane.
(Notice the example in the Javadocs:
// In this case the look and feel renders the title for the tab.
tabbedPane.addTab("Tab", myComponent);
// In this case the custom component is responsible for rendering the
// title of the tab.
tabbedPane.addTab(null, myComponent);
tabbedPane.setTabComponentAt(0, new JLabel("Tab"));
The latter is typically used when you want a more complex user interaction that requires custom components on the tab. For example, you could provide a custom component that animates or one that has widgets for closing the tab.
Normally, you won't need to mess with tab components.)
Anyway, try getComponentAt(0) instead.

Hide certain actions from Swing's undo manager

I am trying to write a JTextPane which supports some sort of coloring: as the user is typing the text, I am running some code that colors the text according to a certain algorithm. This works well.
The problem is that the coloring operations is registered with the undo manager (a DefaultDocumentEvent with EventType.CHANGE). So when the user clicks undo the coloring disappears. Only at the second undo request the text itself is rolled back.
(Note that the coloring algorithm is somewhat slow so I cannot color the text as it is being inserted).
If I try to prevent the CHANGE events from reaching the undo manager I get an exception after several undo requests: this is because the document contents are not conforming to what the undoable-edit object expects.
Any ideas?
You could intercept the CHANGE edits and wrap each one in another UndoableEdit whose isSignificant() method returns false, before adding it to the UndoManager. Then each Undo command will undo the most recent INSERT or REMOVE edit, plus every CHANGE edit that occurred since then.
Ultimately, I think you'll find that the styling mechanism provided by JTextPane/StyledDocument/etc. is too limited for this kind of thing. It's slow, it uses too much memory, and it's based on the same Element tree that's used to keep track of the lexical structure of the document. It's okay (I guess) for applications in which the styles are applied by the user, like word processors, but not for a syntax highlighter that has to update the styles constantly as the user types.
There are several examples out there of syntax-highlighting editors based on custom implementations of the Swing JTextComponent, View and Document classes. Some, like JEdit, re-implement practically the whole javax.swing.text package, but I don't think you need to go that far.
How are you trying to prevent the CHANGE events from reaching the undo manager?
Can you not send the UndoManager a lastEdit().die() call immediately after the CHANGE is queued?
I can only assume how you are doing the text colouring. If you are doing it in the StyledDocuments change character attribute method you can get the undo listener and temporarily deregister it from the document for that operation and then once the colour change has finshed then you can reregister the listener.
Should be fine for what you are trying to do there.
hope that helps
I have just been through this problem. Here is my solution:
private class UndoManagerFix extends UndoManager {
private static final long serialVersionUID = 5335352180435980549L;
#Override
public synchronized void undo() throws CannotUndoException {
do {
UndoableEdit edit = editToBeUndone();
if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
if (event.getType() == EventType.CHANGE) {
super.undo();
continue;
}
}
break;
} while (true);
super.undo();
}
#Override
public synchronized void redo() throws CannotRedoException {
super.redo();
int caretPosition = getCaretPosition();
do {
UndoableEdit edit = editToBeRedone();
if (edit instanceof AbstractDocument.DefaultDocumentEvent) {
AbstractDocument.DefaultDocumentEvent event = (AbstractDocument.DefaultDocumentEvent) edit;
if (event.getType() == EventType.CHANGE) {
super.redo();
continue;
}
}
break;
} while (true);
setCaretPosition(caretPosition);
}
}
It is an inner class in my custom JTextPane, so I can fix the caret position on redo.

Categories