scala : double "selection changed" event raised for ListView component - scala

here is the part of code:
val lsv_syns = new ListView[String]()
val scp_syns = new ScrollPane() {
listenTo(lsv_syns.mouse.moves,lsv_syns.selection)
reactions += {
case me: MouseExited => {
txf_mot.requestFocus()
}
case SelectionChanged(`lsv_syns`)=> {
println("sélection:"+lsv_syns.selection.items(0))
}
}
}
As you can see, the listView is in a scrollPane; don't pay attention to the mouseExited event, the interesting thing is the selectionChanged, which seems to be called twice when I only click on time on an other line, because the println is called two times.
thanks.

Well i also recently worked with a ListView and now that you mentioned it, it also does my calculation twice.
The answer seems to be related to mouse events. Following the stack trace SelectionChanged is called twice. One coming from the Java event MousePressed and one from MouseReleased.
When you change the selection with KeyEvents it is only called once.
My first (and I guess not nice) idea to avoid the problem would be to ignore one of the events:
reactions += {
case SelectionChanged(`lsv_syns`) if !lsv_syns.selection.adjusting => {
println("sélection:"+lsv_syns.selection.items(0))
}
}
Both ListSelection events share the same data except getValueIsAdjusting. So if you check for it you can avoid doing your stuff twice.
Warning: !lsv_syns.selection.adjusting will result in printing on key release and not on press!
If you put lsv_syns.selection.adjusting it will correspond to key press but it will also filter key events. As I said. Not nice at all...

Related

MAUI Text Entry on Complete not Working - Possible Work around?

I'm trying to use text entry on maui to fire an event when completed. I have set the "Completed" event to a handler and it works correctly on windows. But on Android I have no joy, the event just isn't firing.
I realise there is a bug in Maui which is preventing this. But it looks like the problem was discovered in August? It's a fairly basic thing, well at least it appears to be on the face of things.
What is the best work around for this? The only thing I can think is by using the textchanged event instead of completed. This works correctly, but then i have to bodge it by doing this sort of thing:
if (entry1.Text.EndsWith("#"))
{
//Then string is complete, so need to fire correct event
System.Diagnostics.Debug.WriteLine("Complete String Detected");
}
This works and I can use it since I'm awaiting for input from a barcode scanner, so I can set the last terminating character to whatever I want. In this case I set it to a #. I can't figure out a way to detect the return key being pressed.
Thanks
Andrew
There is a similar issue on the github about the Entry.Completed and Entry.ReturnCommand not executed.
This comment shows the cause and the workaround about this problem.
detect the return key being pressed
In addition, I can't understand the problem. I have created a sample to test. The Entry.Completed event will call when I pressed the enter key. I don't kown the return key you mentioned is what. But you can use the IOnKeyListener for the android to detect any key being pressed.
Create a Listener class in the /Platform/Android:
public class MyKeyListener : Java.Lang.Object, IOnKeyListener
{
public bool OnKey(global::Android.Views.View v, [GeneratedEnum] Keycode keyCode, KeyEvent e)
{
var edittext = v as AppCompatEditText;
if (keyCode == Keycode.Enter && e.Action == KeyEventActions.Down )
//I used the Entry key as the example, you can use any other key you want to replace it.
{
edittext.ClearFocus();
edittext.SetBackgroundColor(Color.GreenYellow);
return true;
}
return false;
}
And in the page.xml:
<Entry Completed="Entry_Completed" x:Name="entry"/>
Set the listener to the entry by overriding the OnHandlerChanged() in the page.cs:
protected override void OnHandlerChanged()
      {
            base.OnHandlerChanged();
#if ANDROID
(entry.Handler.PlatformView as AndroidX.AppCompat.Widget.AppCompatEditText).SetOnKeyListener(new MauiAppTest.Platforms.Android.MyKeyListener());
#endif
}
You can also set the listener with the handler. Finally, you can try both the method above and the workaround in the issue on the github.

Scala swing wait for a button press after pressing a button

So What I want to do is to press a button and inside the ButtonClicked Event I want to wait completing the event, until I press a specific button/one of the specified buttons.
I also know that there are some similar questions to this topic but I wasnt able to find a fix out of the answers
So basically this:
reactions += {
case event.ButtonClicked(`rollDice`) =>
some code ...
wait for one of the specified buttons to be pressed and then continue
some code ...
Is there an easy way to solve this problem without the use of threads?
There are certainly some abstractions you could set up around the event layer, but you asked for "easy", so my suggestion is to set a flag/state when the dice are rolled, and then check for that flag in the other buttons' event handler.
private var postDiceRollState: Option[InfoRelatedToRollDice] = None
reactions += {
case event.ButtonClicked(`rollDice`) =>
// capture whatever info you need to pass along to the later button handler
val relevantInfo = /* some code... */
// store that info in the "state"
postDiceRollState = Some(relevantInfo)
case event.ButtonClicked(other) if isPostDiceRollButton(other) =>
// when the other button gets clicked, pull the relevant info from your "state"
postDiceRollState match {
case Some(relevantInfo) =>
postDiceRollState = None // clear state
doInterestingStuff(relevantInfo) // "some code..."
case None =>
// nothing happens if you didn't roll the dice first
}
}
Note: I represented the "flag" as an Option, under the assumption that you might have some information you want to capture about the rollDice event. If you don't actually have anything to put in there, you could represent your state as private var didRollDice: Boolean = false and set/clear would be setting it to true/false respectively.

Trying to get user's latest mouse click in scalafx

I'm trying to get user's latest mouse click in order to display the right table. However, I can't find any way to implement this idea. How do i get user's latest mouse click by using mouseEvent function?
I tried using if else statements but it doesn't work when there is still value in the monstersTable1
def handleEditMonster(action : ActionEvent) = {
val selectedMonster1 = monstersTable1.selectionModel().selectedItem.value
val selectedMonster2 = monstersTable2.selectionModel().selectedItem.value
if (selectedMonster1 != null){
val okClicked = MainApp.showMonsterEditDialog(selectedMonster1)
if (okClicked) showMonstersDetails(Some(selectedMonster1))
} else if (selectedMonster2 != null) {
val okClicked = MainApp.showMonsterEditDialog(selectedMonster2)
if (okClicked) showMonstersDetails(Some(selectedMonster2))
} else {
// Nothing selected.
val alert = new Alert(Alert.AlertType.Warning){
initOwner(MainApp.stage)
title = "No Selection"
headerText = "No monsters Selected"
contentText = "Please select a monsters in the table."
}.showAndWait()
}
}
I want it to be able to access the second table even though selectedMonster1 is still != null
It's not entirely clear from your question what it is you're trying to do, so please bear with me... (For future reference, it's best if you can create a ''minimal, complete and verifiable example'' that illustrates your problem.)
I'm assuming that you have two scalafx.scene.control.TableView instances, referenced via monstersTable1 and monstersTable2. You want to allow the user to select either one of the monsters in the first table, or one of the monsters in the second table, but not to be able to select one monster from each table simultaneously.
I'm unclear when your handleEditMonster function is called, so I'm guessing that it's invoked when the user clicks, say, an Edit Monster button, as that button's clicked event handler.
Do I have that right?
Assuming the above is accurate, you should listen for changes in table selection, and clear the selection in the other table when a new selection is made. The currently selected item in each table is a property that we can add a listener to, so we can achieve this with the following code (in your scene's initialization):
// In the onChange handlers, the first argument references the observable property
// that has been changed (in this case, the property identifying the currently
// selected item in the table), the second is the property's new value and the third
// is its previous value. We can ignore the first and the third arguments in this
// case. If the newValue is non-null (that is, if the user has made a
// selection from this table), then clear the current selection in the other
// table.
monstersTable1.selectionModel.selectedItem.onChange {(_, newValue, _) =>
if(newValue ne null) monstersTable2.selectionModel.clearSelection()
}
monstersTable2.selectionModel.selectedItem.onChange {(_, newValue, _) =>
if(newValue ne null) monstersTable1.selectionModel.clearSelection()
}
This should do the trick for you, and your handleEditMonster function should now work. You might want to add an assertion to guard against both tables having a current selection, which would indicate a bug in the selection handler logic.

MS Word VSTO Addin Find.Execute fires ContentControlOnEnter event

It seems that if Find.Execute finds a result inside a ContentControl, it will cause the ContentControlOnEnter and ContentControlOnExit events to fire. It's particularly annoying because the exit event fires even if the selection is still in the content control, so any code which sets the states of buttons dependent upon a content control being active will appear to be in the incorrect state.
Given a document containing a single content control with the word "test", and the following code:
// In setup
Application.ActiveDocument.ContentControlOnEnter += ActiveDocument_ContentControlOnEnter;
private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
var selRange = _Application.Selection.Range;
_logger.Debug(m => m("Selection: {0}-{1}", selRange.Start, selRange.End));
}
//Later in another method
var finder = _Application.ActiveDocument.Range().Find;
_logger.Debug("Find.Execute start");
finder.Execute("test);
_logger.Debug("Find.Execute end");
The following gets logged:
38137 [VSTA_Main] DEBUG - Find.Execute start
38141 [VSTA_Main] DEBUG - Selection: 1-5
38149 [VSTA_Main] DEBUG - Find.Execute end
We have a lot of code that handles ContentControlOnEnter and ContentControlOnExit events, and having the find operation cause them to be called is really causing problems!
Is there any way to use Find.Execute without having it trigger these events? Failing that, is there a good way to distinguish between the Find-triggered ones and the genuine user ones? I have tried using the time between the enter and exit events, but this is not reliable.
I had similar problems in Word, though it was about the Selection event. I tried many solutions, but only one helped. In your case, make a new field bool _skipEnterAndExitEvents and set it true before calling
finder.Execute("test) and false after calling. And in the enter and exit event handlers check this field, if the field is true then just skip. This solutions is not beautiful, looks like a hack, but other solutions are even uglier and don't really work.
I think I found a decent solution:
private bool _doIgnoreNextExit = false;
private void ActiveDocument_ContentControlOnEnter(Word.ContentControl ContentControl)
{
if (Application.Selection.Find.Found)
{
_logger.Debug("Ignoring CC enter event caused by Find operation");
_doIgnoreNextExit = true;
return;
}
// Do things
}
private void ActiveDocument_ContentControlOnExit(Word.ContentControl ContentControl)
{
if(_doIgnoreNextExit)
{
_logger.Debug("Ignoring fake exit");
_doIgnoreNextExit = false;
return;
}
// Do things
}

DWT togglebutton: does it even work?

I'm not sure if we are just 20 people in the world using dart right now and maybe just 10% of us try to use widgets..anyway, I seem not to understand if I'm doing something wrong with DWT or there is a bug. Here is a very simple example. I don't understand why the event are not even fired.
void main() {
ui.HorizontalPanel panel = new ui.HorizontalPanel();
ui.ToggleButton t1;
t1= new ui.ToggleButton.fromText("click",handler: new event.ClickHandlerAdapter((event.ClickEvent e) {
hans(panel,t1);
} ));
ui.ToggleButton t3;
t3 = new ui.ToggleButton.fromText("click");
t3.addClickHandler(new event.ClickHandlerAdapter((event.ClickEvent event) {
window.alert("Stop poking me!");
}));
panel.add(t1);
panel.add(t3);
ui.RootLayoutPanel.get().add(panel);
}
void hans(ui.Panel panel,ui.ToggleButton button){
var iter = panel.iterator();
while (iter.moveNext()) {
var butt = iter.current;
if (butt is ui.ToggleButton){
if (butt != button) {
butt.setDown(true);
}
}
}
Not really an answer to your question, but something I've noticed:
Not sure if bug or by design, but seems like the first node of a Tree does not handle clicks properly. I've created a tree with two ui.Label(s) in it and the first ui.Label does not respond to clicks. No aparent reason for that.
If I insert these ui.Label(s) in reversed order the situation is still the same: the first ui.Label (the other ui.Label, this time) does not respond to clicks.
So, I've circumvented the trouble by adding a Label in the beginning as "/" which is absolutely useless but does not need to respond to any clicks anyway.