Stop JSF Event Chain - java

I'm working on modifying a jsf-1.2 application for use on a tablet pc.
For that purpose I have made the rows of a table clickable to open the detail view of the rows contents, rather than have the user click on a link in that table (which is the case in the Desktop Version).
It works fine so far.
Each row can, however, contain two rich-buttons that open a different link.
The contents of that link is opened in a new tab, like it's supposed to.
My problem is, that the action event of the rowclick is activated in the original tab as well, which is not the intended behaviour.
What I want to do now is stop the event if one of the buttons in the row is clicked.
I know already, that the event of the butons is fired before the rowclick event.
Is there a way to just cut the event chain at this point?

This happens due to Event Bubbling. Try using Event.stop(event); in your commandButton as below.
<a4j:commandButton onclick="Event.stop(event);" action="#{myBean.myMethod())}" value="Show" />

I don't know if you can break the chain - but even if it is possible (probably by throwing an exception) - I would recommend against it.
The proper (sadly) way to do it in an event-driven environment is to set some boolean indicator to be true when a handler for a button fires, and set it back to false when the handler finishes its job.
In the handler for the row-clicked event, you need to check to see if the boolean is true - and only if it is false - continue with handling the row-clicked event.
A suggested name for the boolean: isRowButtownClicked
Disclaimer: I'm basing this answer on my knowledge in C# - I do not have any experience in GUI development in Java and specifically not in JSF.

Related

Java swing requestFocusInWindow()

I know there are many questions on how to focus on a certain text field and so on, but it seems that the issue I am facing is a bit different. So, I have a JTextField which has functionality to autocomplete the text if something that is currently in it has been typed before by the user. I also have a set of buttons that perform insertion of some predefined portion of text into the text field when pressed. The problem is that every time any new text appears in the text field, the autocomplete can trigger and append the text that was used by the user previously. In order to it more friendly, I decided to select the part appended by the autocomplete. All the code is executed in the ED thread. Consider the case when the text field was not in focus :
Both code samples are in the actionPerformed method of the button.
// does not work
if (textField.requestFocusInWindow()) {
textField.getDocument().insertString(...);
}
The insertString() is overriden and has all the logic to select appended string by the autocomplete. So, the only thing I need is that the text field is selected before the string is inserted.
I tried :
// does work
textField.requestFocusInWindow();
SwingUtilities.invokeLater(() -> {
textField.getDocument().insertString(...);
});
The official doc says :
The call to the requestFocusInWindow method initiates the focus transfer, but it does not immediately move the focus ...
This sort of makes sense, since to acquire the focus, a call must be made to the window manager of the clients operating system (that's how I understand that, correct me if I am wrong).
Is the second example working mainly because both events (getting focus and inserting the string) are added to the event queue and the insertion appears after the focus request (actually at the end of the queue) or am I missing something? Is it a valid solution? Can it be done better?
Note: simply adding a listener to the text field ( to react when it is in focus) is not a solution, since the logic I described here is only a part of the whole functionality used.

Java Swing: How to distinguish events triggered by user?

I'd like to update GUI elements (JComboBox, JLabel, etc.) from code which shouldn't trigger change event. Is it possible to find out from java.awt.event.ActionEvent or java.awt.event.ItemEvent if the change was caused by an user or by running code like this?
combo.setSelectedItem("my item")
The answer is: no.
But in some cases you can try to analyze the current InputEvent. To get it, use EventQueue.getCurrentEvent(). For example if user has triggered the change on clicking of another component, you can compare the component of the input event and the component of the action event (OK I know: it's unsafe. But in some cases it can help to avoid incrementing of application complexity).
For a button you can get the event modifiers:
int buttonModifiers = evt.getModifiers();
If the button event was generated with a call to doClick() the modifier is 0, otherwise not.
By the way, you can find out such differences relatively easy by logging / printing using evt.toString()
.

Is it possible to programatically set an Eclipse RCP button as 'checked'?

I want to programatically set an Eclipse plugin action (button) such as this here:
For example, if the user presses it, I do not want it to toggle off under certain conditions.
This code here creates the action (button):
class MyAction extends Action {
public MyAction() {
super(NAME, IAction.AS_CHECK_BOX);
}
...
Thread.sleep(100); wait a little bit incase there is a thread update issue
if (condition)
setChecked(true); // does not work, it does not force the button to appear as depressed. It just keeps toggling.
...
}
For some reason setChecked(true) does not work.
The problem here I believe is the fact you're calling setChecked inside of Action.run(). Since one of the effects of clicking a checkbox is to check it, you're sneakily trying to cancel the action while it's going on. In fact, I bet the framework code sets checked to true after Action.run() returns, so it's stomping on your change.
Action has a way of letting you control this in a more defined way. Rather than implementing .run(), implement .runWithEvent(Event). This function passes in an Event object that you can use to have finer grained control.
In this case, I think you want to set Event.doit to false. From the docs:
Setting this field to false will cancel the operation.
Another option
Depending on how your condition is calculated, you may want to preemptively enable/disable your checkbox when it changes. This way you can also prevent a tooltip or similar to explain why it's disabled.

JTable: double-click should keep prior selection

I have a JTable where I can select one or more cells. I also want to react on double-click for doing some extra action for the selected cells. But the problem is, when the user double-clicks, the selection changes to the clicked cell. But I want to keep the prior selection on double-click, so I can handle the double-click for all selected cells.
EDIT:
Related to this question:
Java : ignore single click on double click?
But I hope, there is a better/easier solution for my case.
The problem is, that on the first click the first event goes out. A bit later the second click might come or not. So the first click event does know nothing. As in the proposed solution a timer might do.
What also might do is on the first click to select nothing, but invoke a special selection event a bit later.
SwingUtilities.invokeLater(myRunnable);
and on handling the double click/myRunnable the true selection. Timing might be unavoidable though.
you can use setClickCountToStart() for XxxCellEditor, I don't know something about your JTable

Passing accelerator keystrokes to the main menu in Java

I have added some accelerators to the main menu, using MenuItem.setAccelerator(). Just basic stuff like ctrl-c for copy, etc.
This works ok. But the app is a bit like an IDE, it has several panels containing JTables. If a table cell has focus, it absorbs the accelerator key, which means the main menu never sees it.
Clearly, if an editable table cell is active I would like the cut and paste keys to function normally, but in every other case I would like the main menu to respond.
Any ideas?
KeyStrokes go to the component that has focus first. Since JTable binds Ctrl+C to an Action, that action is invoked.
If you don't like the default Action of the table, then you would need to remove the binding from the table.
Read the section from the Swing tutorial on How to Use Key Bindings. It shows you how to remove a binding.
Thanks, that got me on the right track.
Removing the bindings didn't quite work, it just stopped the table doing its default action so the keypress was ignored altogether.
However, adding this to the table itself worked ok:
component.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK), "copy");
component.getActionMap().put("copy", actions.copyAction);
(Repeated for each desired key of course). Needs to be kept in synch with any changes to the main menu itself, but I can't see a way to avoid that with any method.

Categories