ZK Combobox disable closing - java

I'm struggling with ZK Framework Combobox UI rendering. I have a combobox with 2 logical lists (1 is a short version of 2, with "Show more" option, and 2 is a list with all entries and no "Show more" option). I've done some list swapping logic tracked by onClick event of "Show more" option. And when I click this option combobox closes and than I need to re-open it to see the full list. So my question is do anyone know a way how to keep combobox opened when I click this specific option (and furthermore, dynamically populate model by another list)? Maybe there are any other best practices of how to do the task more efficiently? Thanks everyone for help
I have a thought about combobox that enables multiple choice — it doesn't close when some option is clicked, but I haven't found any related information. Maybe you could make your suggestions about it

The behavior you want "clicking 'show more' and keep the popup open" is not supported by default.
So you have to override its js widget's doClick_(), please read
https://www.zkoss.org/wiki/ZK_Client-side_Reference/General_Control/Widget_Customization
here is an example.
<zscript><![CDATA[
ListModelList fullModel = new ListModelList(Locale.getAvailableLocales());
ListModelList model1 = new ListModelList(fullModel.subList(0, 2));
model1.add("show more");
]]></zscript>
<combobox id="box" model="${model1}" readonly="true" onSelect="loadAll()"/>
<script src="comboitem-doclick.js"/>
<zscript><![CDATA[
public void loadAll(){
if (model1.getSelection().iterator().next().equals("show more")){
box.setModel(fullModel);
box.setValue("");
}
}
]]></zscript>
/**
* Purpose: when a user selects a specific item, keep the popup open.
* Based on version: 9.6.3
*/
zk.afterLoad('zul.inp', function() {
var exWidget = {};
zk.override(zul.inp.Comboitem.prototype, exWidget, {
doClick_: function doClick_(evt) {
if (!this._disabled) {
var cb = this.parent;
cb._select(this, {
sendOnSelect: true,
sendOnChange: true
});
this._updateHoverImage();
if (this.getLabel() != 'show more'){
cb.close({
sendOnOpen: true,
focus: true
}); // Fixed the onFocus event is triggered too late in IE.
}
cb._shallClose = true;
if (zul.inp.InputCtrl.isPreservedFocus(this)) zk(cb.getInputNode()).focus();
evt.stop();
}
},
});
});

Related

Java if two buttons have the same icons increase score and if not display "wrong match"

Creating a really basic Memory game using Java Swing. I created my GUI with a list of blank buttons where I set the icon property to none.
My code for some of the buttons is:
private void tbtnCard3ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
if(tbtnCard5.isSelected()){
score++;
lblScore.setText(""+score);
}
}
private void tbtnCard4ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card7EWaste.png")));
if(tbtnCard7.isSelected()){
score++;
lblScore.setText(""+score);
}
}
private void tbtnCard5ActionPerformed(java.awt.event.ActionEvent evt) {
tbtnCard5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/Card3Logo.png")));
if(tbtnCard3.isSelected()){
score++;
lblScore.setText(""+score);
}
}
I have about 20 toggle buttons and for example the code above works and the scores go up by 1 when a match is found. So for tbtnCard3, if tbtnCard5 is selected the score goes up by 1. Now my question is how would I make it so that if tbtnCard3 is selected but tbtnCard 5 is not selected, display "Wrong Match". Since im using if Selected I'm not too sure how to display "wrong match" when the case is false. It doesn't make sense to say else ifSelected as no parameters can be put either....
In my opinion, the OPs suggestion is not a good approach. You do not want the listener of one button to be "aware" of some other component unnecessarily. Suppose you have an 8-by-8 grid with toggle buttons. You don't want each toggle button listener to be aware of the other 63 toggle buttons.
I believe there is a much simpler (and cleaner) approach. What you want is for the toggle button listener to register and deregister the toggle when the state of the button changes. Let say, you add the toggle button to or remove from a list (most likely a custom class) where you can trigger some logic when the list size reaches two. Then, depending on the outcome of the comparison, it will count a match (and disable these two toggle buttons in the current state), or will display some message like "Try again" and then toggle the buttons to hide the image.
In pseudocode, this will look something like this:
public class ToggleListener implements ItemListener {
public void actionPerformed (ItemEvent event) {
JToggleButton button = (JToggleButton) event.getSource();
if (event.getStateChange()==ItemEvent.SELECTED) {
// TODO Add the button to your list..
} else {
// remove button
}
}
}
In your Swing application, you can create a single instance of the above listener and add it to every single toggle button. And, as you can see, this listener is only responsible to register and unregister the component associated with the triggered event.
The "List Listener" on the other hand, is responsible to trigger the comparison logic when the size of the list reaches two. So, if you click on the same toggle button over and over again, the only thing the button listener will do is add or remove the button from the list depending on the button's current state. However, once a second button is toggled to reveal its image, the list listener will trigger the comparison logic. I am not 100% sure, but I think you could use JavaFX ObservableList interface or one of its implementing classes to do this. If the ListChangeListener.Change class is not suitable to figure out the size of the list to trigger the logic, you will have to implement this on your own. Regardless, in pseudocode, you need to do something like this:
public void onListChange(Event event) {
if (list.size() == 2 && btn1.getIconName().equals(btn2.getIconName())) {
displayMatchMessage();
btn1.setEnabled(false);
btn2.setEnabled(false);
list.clear(); // you should remove matched items from list manually
} else {
displayMismatchMessage();
btn1.setSelected(false); // flip the card
btn2.setSelected(false); // flip the card
// list.clear(); // you should not need this because the setSelected should trigger the Item Listener which should remove item from list.
}
}
Doing something like this is a much cleaner implementation where the button listener have a single job to do and the "list listener" has another job to do. Neither one encroaches on the other's job.

Change TextField Display with RadioButton

I'm having a problem with Label and TextField placement in a gridpane in response to toggled RadioButtons.
The window will display the same options except for two different labels and text fields which depend on which RadioButton the user has selected.(See images attached).
InHouse RB Selected
Outsourced RB Selected
I added the RadioButton objects to a Toggle Group, then coded the "on actions" to add the "Machine ID" or "Company Name" fields to the GridPane as needed when one of the options is selected.
My problem is that I can only select each option once, and the display of the second option only overlaps the first instance instead of replacing it. If I try to switch back again, I get a runtime error(in Netbeans) about adding the same object twice to the grid.
Any code that I have tried that could remove the node from the display had no affect on the menu's behavior.
ArrayList<Label> typeSpecLabels = new ArrayList<Label>();
ArrayList<TextField>typeSpecFields = new ArrayList<TextField>();
typeSpecLabels.add(machineIDLabel);
typeSpecLabels.add(companyLabel);
typeSpecFields.add(machineIDField);
typeSpecFields.add(companyNameField);
inHouseBtn.setOnAction(inHouseSpecificEvent ->
{
typeSpecLabels.add(machineIDLabel);
grid1.add(typeSpecLabels.get(0),0,8,1,1);
grid1.add(typeSpecFields.get(0), 1,8,1,1);
if(outSourceBtn.isArmed() == true){
grid1.getChildren().remove(companyLabel);
grid1.getChildren().remove(companyNameField);
}
});
outSourceBtn.setOnAction(outSourceSpecificEvent ->
{
typeSpecLabels.add(companyLabel);
grid1.add(companyLabel,0,8,1,1);
grid1.add(companyNameField,1,8,1,1);
if(outSourceBtn.isArmed() == true){
grid1.getChildren().remove(machineIDLabel);
grid1.getChildren().remove(machineIDField);
}
});
I have heard that I could try using 2 or 3 different scenes(one for each state of the RadioButtons), so I may try that. But if it can be done the way I have coded it so far, I would prefer to do it that way.
I would suggest to remove all type specific labels and fields from your grid and then add ones that you need. So the code will look like following:
inHouseBtn.setOnAction(inHouseSpecificEvent ->
{
grid1.getChildren().removeAll(machineIDLabel, companyLabel, machineIDField, companyNameField);
grid1.add(machineIDLabel,0,8,1,1);
grid1.add(machineIDField, 1,8,1,1);
});
outSourceBtn.setOnAction(outSourceSpecificEvent ->
{
grid1.getChildren().removeAll(machineIDLabel, companyLabel, machineIDField, companyNameField);
grid1.add(companyLabel,0,8,1,1);
grid1.add(companyNameField,1,8,1,1);
});
This code ended up working, as Pavlo suggested.
Although I just removed the objects specific to the opposing event.
The code works with no errors or overlapping.
inHouseBtn.setOnAction(inHouseSpecificEvent ->
{
grid1.add(machineIDLabel,0,8,1,1);
grid1.add(machineIDField,1,8,1,1);
grid1.getChildren().remove(companyLabel);
grid1.getChildren().remove(companyNameField);
});
outSourceBtn.setOnAction(outSourceSpecificEvent ->
{
grid1.add(companyLabel,0,8,1,1);
grid1.add(companyNameField,1,8,1,1);
grid1.getChildren().remove(machineIDLabel);
grid1.getChildren().remove(machineIDField);
});

Pass information from popup to main window on Oracle ADF

I have a popup that show a table with data, I am able to select a row, and by pressing a OK button I can retrieve the idNo of the selected row in the table.
What I want to do is to pass this idNo to the window that is calling the popup and update a outputText that is on this window.
Can some one help me?
Code for the button:
newBean Class for the button:
public String b1_action() {
// Add event code here...
System.out.println("Select One Button has been Clicked");
// Get bindings associated with the current scope, then access the one that we have assigned to our table - e.g. OpenSupportItemsIterator
DCBindingContainer bindings =
(DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding dcItteratorBindings =
bindings.findIteratorBinding("NameView1_1Iterator");
// Get an object representing the table and what may be selected within it
ViewObject voTableData = dcItteratorBindings.getViewObject();
// Get selected row
Row rowSelected = voTableData.getCurrentRow();
// Display attriebute of row in console output - would generally be bound to a UI component like a Label and or used to call another proces
System.out.println(rowSelected.getAttribute("IdNo"));
setOutputText("" + rowSelected.getAttribute("IdNo") + "");
closePopup("p1");
return null;
}
I want that my function: setOutputText() which is not implemented yet to be able to update my outputText on the main Window.
Thanks
Best Regards
Put the "IdNo" in view or page flow scope depending on how you want to keep the value.
//view scope
AdfFacesContext.getCurrentInstance().getViewScope().put("IdNo", value);
//or page flow scope
AdfFacesContext.getCurrentInstance().getPageFlowScope.put("IdNo", value);
In the window bean, write a listener for the popup dialog:
public void dialogCloseListener(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
String idNo = AdfFacesContext.getCurrentInstance().getViewScope().get("IdNo");
//now you have the idNo, do whatever you want
}
}
You can also use the returnListener inside the button or link that is invoking the popup like in this article

Multiple submit buttons, javascript

I have a servlet with a form and two buttons. One is a Submit button, the other is a Delete button. The default action is Updater.do, but when I click the Delete button, I have a function to change the action to Deleter.do. This works fine. The problem I have now is that when I put in a confirm dialog, if the user clicks "OK", then it does go on to Deleter.do, as I wanted. However, when they click "Cancel", instead of just staying on the page, it appears to go to "Updater.do". How would I remedy this? I tried deleting the default action and having both Submit and Delete call changeAction, but that didn't work. Here is the javascript chgAction.
function chgAction(action_name) {
if (action_name=="Delete") {
var answer = confirm("Are you sure you want to delete this Person? This action cannot be undone.")
if (answer) { document.forms[0].action = \"Deleter.do\"; }
}
}
Try adding a return false to the "cancel" part:
function chgAction(action_name) {
if (action_name=="Delete") {
var answer = confirm("Are you sure you want to delete this Person? This action cannot be undone.")
if (answer) {
document.forms[0].action = \"Deleter.do\";
}
else {
return false; //ADDED
}
}
}
If both submit and delete are submit buttons, just give them different names. The name of whichever button is clicked will be sent with the request so the server can sort it out.
When calling the confirm dialog, you must return false from the listener or the form will still submit:
<form onsubmit="return chgAction(...);"
and chgAction must return false as suggested by Nivas.

Validate JList Before Selection Occur

Currently, I have a JList listen to list selection listener.
private void jList1ValueChanged(javax.swing.event.ListSelectionEvent evt) {
// When the user release the mouse button and completes the selection,
// getValueIsAdjusting() becomes false
if (evt.getValueIsAdjusting()) {
/*
In certain situation, I may want to prevent user from selecting other
than current selection. How can I do so?
*/
}
}
In certain situation, I may want to prevent user from selecting other than current selection. How can I do so?
It seems too late when I receive ListSelectionEvent. But, if I want to do it before ListSelectionEvent happen, I do not know that user is trying to select other.
Here is one of the senario.
The JList is contains list of project name.
So, whenever user select new list item, we need to turn the View, from current project, and display new project.
However, current project may be unsaved yet.
Hence, if current project unsaved yet, we will ask for user confirmation, "Save Project?" (Yes, No, Cancel)
When user select cancel, this means he want to cancel his "select to another project" action. He want to stick with current JList selection.
We will pop up the confirmation dialog box in jList1ValueChanged event handle.
But when we try to stick with current JList selection, it is already too late.
I've implemented this as follows for the same workflow use-case. While it works sufficiently for me, I do wish there was a simpler and more elegant approach where the selection event could be vetoed before proceeding. If I have time to investigate and figure that out I'll repost, but it might rank as a case where the return on investment isn't worth it (i.e. customizing Swing classes, handling lower level mouse/keyboard events directly, etc). Anyway what I'm doing currently is saving the last good 'validated' selection, and reverting back to it if the user cancels a future selection. It's admittedly not the prettiest solution, but it works:
// save the last good (i.e. validated) selection:
private ProjectClass lastSelectedProj;
// listing of available projects:
private JList list;
// true if current selected project has been modified without saving:
private boolean dirty;
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
if (evt.getValueIsAdjusting()) return;
// first validate this selection, and give the user a chance to cancel.
// e.g. if selected project is dirty show save: yes/no/cancel dialog.
if (dirty) {
int choice = JOptionPane.showConfirmDialog(this,
"Save changes?",
"Unsaved changes",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
// if the user cancels the selection event revert to previous selection:
if (choice == JOptionPane.CANCEL_OPTION) {
dirty = false; // don't cause yet another prompt when reverting selection
list.setSelectedValue(lastSelectedProj, true);
dirty = true; // restore dirty state. not elegant, but it works.
return;
} else {
// handle YES and NO options
dirty = false;
}
}
// on a validated selection event:
lastSelectedProj = list.getSelectedValue();
// proceed to update views for the newly selected project...
}
}
I think you would need to override the setSelectionInterval(...) method of JList to do nothing under your special situations.
Handling it at the event level is too late as the event has already occured.
I would suggest that you implement a custom ListSelectionModel.
table.setSelectionModel(new DefaultListSelectionModel(){
#Override
public void setSelectionInterval(int index0, int index1) {
if (dragState==0 && index0==index1 && isSelectedIndex(index0)) {
// Deny all clicks that are one row & already selected
return;
} else {
super.setSelectionInterval(index0, index1);
}
}
});

Categories

Resources