ActionScript3 How to increment score when working with classes - class

I would like to increment the value of a TextField by one every time an event listener in another class is activated. This is proving very difficult because the event listener can only be triggered once the Timer in the main class reaches completion.
I have tried using a getter method on a Boolean to ensure that the event listener in a different class has been triggered. This has proven unsucsessful however because of the Timer which is only triggered once on completion.
I am a begginer to AS3 and so any help would be greately appreciated. Thank You
THIS IS THE CODE FOR THE MAIN CLASS
public function t1Finish(e:TimerEvent):void {
ranNum2 = randomNum1(0, 11);
holes[ranNum2].sendUp();
setCounter();
}
public function setCounter():void {
if(holes[ranNum2].returnHasHit() == true) {
counter1++;
txt1instance.text = counter1.toString();
} else {
txt1instance.text = counter1.toString();
}
}
THIS IS THE CODE FOR THE OTHER CLASS
public function click1(e:MouseEvent):void {
this.gotoAndPlay(32);
hasHit = true;
}
public function returnHasHit():Boolean {
return hasHit;
}

You need to properly arrange your app hierarchy. Your case is not exactly problematic: you have main class that wants to capture some events occurring in certain subservient objects.
// That HOLE class.
// I assume it is an inner event handler, not a public
// interface, thus there's no need for it to be public.
private function click1(e:MouseEvent):void
{
// Normally you don't need to explicitly state "this".
gotoAndPlay(32);
// Produce a custom event.
dispatchEvent(new Event(Event.OPEN));
}
Then, you need to catch that event in the main class.
// The MAIN class.
// You need to subscribe for that custom event somewhere.
private function subscribeAll():void
{
for each (var aHole:MovieClip in holes)
{
aHole.addEventListener(Event.OPEN, onOpen);
}
}
// The custom event handler.
private function onOpen(e:Event):void
{
// If you want to know which hole dispatched this event.
var aHole:MovieClip = e.target as MovieClip;
// Here you might want to put any additional criteria
// to check if you want to accept this event.
// This handler is invoked ONLY if that "click1" handler was invoked
// on any of the holes, so there's no need to check "wasHit" interface.
counter1++;
txt1instance.text = counter1.toString();
}

Related

How to add an event trigger listener(callback)

Basically how you would create a public void MethodToDoStuff(), attach a monobehaviour script and link the method on a button, so that when its clicked, said method "MethodToDoStuff" is called.
Now I want to do that via an editor script.
Add an event trigger component
On the event trigger component, add a PointerDown and PointerUp event
On the PointerUp and PointerDown, link a public method on another script to be run (doesHandler.HidePanel()) "see code below"
I could do this manually but having an editor script is super effiecient.
Here is what I have so far:
All help is appreciated, Thanks!
EDITOR SCRIPT:
void OnWizardCreate()
{
doesHandler = GameObject.FindWithTag("WhatItDoes").GetComponent<WhatThisDoes>();
GameObject selection = Selection.activeGameObject;
EventTrigger trig=(EventTrigger)selection.AddComponent(typeof(EventTrigger));
EventTrigger.Entry onPointerDown = new EventTrigger.Entry();
onPointerDown.eventID = EventTriggerType.PointerDown;
EventTrigger.Entry onPointerUp = new EventTrigger.Entry();
onPointerUp.eventID = EventTriggerType.PointerUp;
trig.triggers.Add(onPointerDown);
trig.triggers.Add(onPointerUp);
}
OTHER SCRIPT:
public void HidePanel()
{
whatItDoesPanel.SetActive(false);
}
On runtime you would usually call e.g.
onPointerDown.AddListener(doesHandler.HidePanel);
however this would only add the listener temporarily.
Adding a persistent listener is a bit more complex but luckily there now is a tool for this: UnityEventTools.AddPersistentListener so afaik you would only have to add
UnityEventTools.AddPersistentListener(onPointerDown, doesHandler.HidePanel);
UnityEventTools.AddPersistentListener(onPointerUp, doesHandler.HidePanel);
Additional afaik you should before use Undo.RecordObject in order to mark the changed object and the scene as dirty and add a Undo/Redo entry like
Undo.RecordObject(selection, "Added event triggers");
So probably something like
void OnWizardCreate()
{
doesHandler = Object.FindObjectOfType<WhatThisDoes>();
if(!doesHandler)
{
Debug.LogWarning("No WhatThisDoes found in the scene -> Ignored");
return;
}
var selection = Selection.activeGameObject;
if(!selection)
{
Debug.LogWarning("Nothing selected -> Ignored")
return;
}
if(selection.GetComponent<EventTrigger>())
{
Debug.LogWarning($"The selected object {selection} already has an EventTrigger attached! -> Ignored");
return;
}
// log the undo before making changes
Undo.RecordObject(selection, "Added event triggers");
var onPointerDown = new EventTrigger.Entry();
onPointerDown.eventID = EventTriggerType.PointerDown;
UnityEventTools.AddPersistentListener(onPointerDown, doesHandler.HidePanel);
var onPointerUp = new EventTrigger.Entry();
onPointerUp.eventID = EventTriggerType.PointerUp;
UnityEventTools.AddPersistentListener(onPointerUp, doesHandler.HidePanel);
var trig = selection.AddComponent<EventTrigger>();
trig.triggers.Add(onPointerDown);
trig.triggers.Add(onPointerUp);
}

UWP Custom ListView to scroll down

So, I have a listview and I want it whenever an item is created to scroll to that item (bottom). Because I am using MVVM I found really nice explanation on how to make a new control that inherits from listview that scrolls down. The problem is that this answer (the third) is referring to WPF 6 years ago.
I am making a UWP app, so I copied the code and tried to format it to my needs. The following code doesn't give any error or exception but instead it loads the "ChatListView" as I call it perfectly and then does nothing. The comments are only a bit edited compared to the original code.
What can I do ? Thank you in advance!
public class ChatListView : ListView
{
//Define the AutoScroll property. If enabled, causes the ListBox to scroll to
//the last item whenever a new item is added.
public static readonly DependencyProperty AutoScrollProperty =
DependencyProperty.Register(
"AutoScroll",
typeof(Boolean),
typeof(ChatListView),
new PropertyMetadata(
true, //Default value.
new PropertyChangedCallback(AutoScroll_PropertyChanged)));
//Gets or sets whether or not the list should scroll to the last item
//when a new item is added.
public bool AutoScroll
{
get { return (bool)GetValue(AutoScrollProperty); }
set { SetValue(AutoScrollProperty, value); }
}
//Event handler for when the AutoScroll property is changed.
//This delegates the call to SubscribeToAutoScroll_ItemsCollectionChanged().
//d = The DependencyObject whose property was changed.</param>
//e = Change event args.</param>
private static void AutoScroll_PropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
SubscribeToAutoScroll_ItemsCollectionChanged(
(ChatListView)d,
(bool)e.NewValue);
}
//Subscribes to the list items' collection changed event if AutoScroll is enabled.
//Otherwise, it unsubscribes from that event.
//For this to work, the underlying list must implement INotifyCollectionChanged.
//
//(This function was only creative for brevity)
//listBox = The list box containing the items collection.
//subscribe = Subscribe to the collection changed event?
private static void SubscribeToAutoScroll_ItemsCollectionChanged(
ChatListView listView, bool subscribe)
{
INotifyCollectionChanged notifyCollection =
listView as INotifyCollectionChanged;
if (notifyCollection != null)
{
if (subscribe)
{
//AutoScroll is turned on, subscribe to collection changed events.
notifyCollection.CollectionChanged +=
listView.AutoScroll_ItemsCollectionChanged;
}
else
{
//AutoScroll is turned off, unsubscribe from collection changed events.
notifyCollection.CollectionChanged -=
listView.AutoScroll_ItemsCollectionChanged;
}
}
}
//Event handler called only when the ItemCollection changes
//and if AutoScroll is enabled.
//sender = The ItemCollection.
//e = Change event args.
private void AutoScroll_ItemsCollectionChanged(
object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
int count = Items.Count;
ScrollIntoView(Items[count - 1]);
}
}
//Constructor a new ChatListView.
public ChatListView()
{
//Subscribe to the AutoScroll property's items collection
//changed handler by default if AutoScroll is enabled by default.
SubscribeToAutoScroll_ItemsCollectionChanged(
this, (bool)AutoScrollProperty.GetMetadata(typeof(ChatListView)).DefaultValue);
}
}
If you want to create a chat application you can use the ItemsStackPanel's ItemsUpdatingScrollMode particular property to KeepLastItemInView value to scroll to the latest item.
Usage:
<ListView>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel ItemsUpdatingScrollMode="KeepLastItemInView" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
Note: KeepLastItemInView enum member was introduced in the 14393 SDK.
Related link:
https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Controls.ItemsStackPanel#properties_
The accepted answer is pretty nice. However I there is one thing it won't do (at least if I simply copy and paste the above XAML): it won't do its intended scrolling if, say, the user was away from that page while new items were added, and then they navigated to the page.
For that I had to hook into
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (MyListView.Items.Count == 0)
return;
object lastItem = MyListView.Items[MyListView.Items.Count - 1];
MyListView.ScrollIntoView(lastItem);
}

how to stop firing unrelated event of event bus

My problem is with how to stop firing unrelated event of event bus. as I got this solution for Dialog box.
but it does not work in case of where one instance already initialize and try to create new instance of same class.
Just example: A below scroll panel has handler initialized. it used for document preview.
class TestScroll extends ScrollPanel
{
public TestScroll(){
}
implemented onload()
{
// eventBus.addHandler code here.
//here some preview related code
}
unload() method
{
//eventBus remove handler code
}
}
This preview has some data which contains some links that open different preview but with same class and different data structure,
Now The problem is like onUnload ( which contains code of remove handler) event does not load , because other panel opened. that does not mean previous panel unload.
So in that case, twice event handler registered. when one event fired then other event also fired.
Due to that, Preview 1 data shows properly, but after that Preview2 opened and when I close it, I find Preview1=Preview2.
so how can I handle such situation?
As per no of instance created each event fired. but I have to check some unique document id with if condition in event itself.
is there any other ways to stop unrelated event firing?
Edit:
public class Gwteventbus implements EntryPoint {
int i=0;
#Override
public void onModuleLoad() {
TestApp panel=new TestApp();
Button button=new Button("Test Event");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
TestApp panel=new TestApp();
int j=i;
new AppUtils().EVENT_BUS.fireEventFromSource(new AuthenticationEvent(),""+(j));
i++;
}
});
panel.add(button);
RootPanel.get().add(panel);
}
}
public class AppUtils {
public static EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
}
public class TestApp extends VerticalPanel{
String testString="";
public TestApp( ) {
AppUtils.EVENT_BUS.addHandler(AuthenticationEvent.TYPE, new AuthenticationEventHandler() {
#Override
public void onAuthenticationChanged(AuthenticationEvent authenticationEvent) {
System.out.println("helloworld"+authenticationEvent.getSource());
}
});
}
}
These are wild guesses as it's difficult to really answer it without code and a clear description.
I'm guessing you have one eventbus for all the panels. So when you register a handler it is registered with that one eventbus. In case you fire an event from one of the panels to the eventbus all panels will receive the event.
To fix this you can either create a new eventbus per panel or check who fired the event with event.getSource().
If this doesn't make sense you probably are reusing a variable or use a static variable which actually should be a new instance or none static variable.
You can use the GwtEventService-Library to fire specific events over a unique domain and every receiver that is registered at this domain receives that events then. You can handle as many different events/domains as you want.
In order to remove a handler attached to the EventBus, you must first store a reference to the HandlerRegistration returned by the addHandler method:
HandlerRegistration hr = eventBus.addHandler(new ClickHandler(){...});
Then you can remove the handler with the removeHandler method:
hr.removeHandler();
A final note worth mentioning is that when using singleton views, like is typical with MVP and GWT Activities and Places, it is best practice to make use of a ResettableEventBus. The eventBus passed to an activity's start() is just such a bus. When the ActivityManager stops the activity, it automatically removes all handlers attached to the ResettableEventBus.
I would strongly recommend reading the GWT Project's documentation on:
Activities and Places
Large scale application development and MVP

Are EventHandlers and SinkEvents doing the same functional job?

I am using GWT. I started adding events to my widgets by adding EventHandlers.
Event handler sample code:
widget.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// do something
}
});
I then found there is another way to handle events using sinkEvents().
Sink events sample code (from this website):
{
...
sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONMOUSEOVER |Event.ONMOUSEOUT)
...
}
public void onBrowserEvent(Event event) {
Element td = getEventTargetCell(event);
if (td == null) return;
Element tr = DOM.getParent(td);
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN: {
// do something
break;
}
case Event.ONMOUSEUP: {
// do something
break;
}
case Event.ONMOUSEOVER: {
// do something
break;
}
case Event.ONMOUSEOUT: {
// do something
break;
}
}
}
Are EventHandlers and SinkEvents doing the same functional job?
If yes, what are the tradeoffs? (where would you use one over the other)
If no, how are they different?
I'm not GWT expert, but this is what I gather from looking at the GWT source:
All EventHandlers (eventually) call addDomHandler(..) which calls sinkEvents(). sinkEvents() is lower-level and is a browser-abstraction wrapper around native javascript event handling.
EventHandlers are build on top of sinkEvents so they provide all functionality that sinkEvents does.
But usage-wise they are different: with EventHandlers you can register for different event types with different event handlers that can reside in different classes. Events will be automatically routed to appropriate handlers. With sinkEvents you can register for different event types (via an int, not type-safe), but always this widget's onBrowserEvent(event) will be called.
EventHandlers add certain overhead. It's debatable if this matters at all.
EventHandlers are a type-safe way to add and remove event handlers and an automatic way for events to be routed to the registered handlers of your choice. If you use GWT Widgets than you should use EventHandlers.

GWT/MVP: detecting change events in a table with proper MVP pattern

We're using gwt-presenter, but not really a question specific to that...
I've got a table with users in it. As I build the table in the view (from the data provided by the presenter), I need to add two action buttons ("Edit", and "Delete") at the end of the row.
What's the best way to assign click handlers to these buttons so the presenter knows which was clicked? Previous to this, we could pass a private field from the view to the presenter and attach a discrete click handler to that button. However, this method is rather rigid and doesn't work in this scenario very well.
Thanks in advance.
How about having the view allowing the subscription for edit/delete click events, registering internally the individual row click events, and then delegating the event handling to the ones registered by the view?
I mean something like the following pesudo code:
View:
addRowEditClickHandler(ClickHandler handler) {
this.rowEditClickHandler = handler;
}
addRowDeleteClickHandler(ClickHandler handler) {
this.rowDeleteClickHandler = handler;
}
//... somewhere when setting up of the grid...
rowEditButton.addClickHandler = new ClickHandler() {
onClick(args) {
this.rowEditClickHandler.onClick(args)
}
rowDeleteButton.addClickHandler = new ClickHandler() {
onClick(args) {
this.rowDeleteClickHandler.onClick(args)
}
Presenter:
View view = new View();
view.addRowEditClickHandler( new ClickHandler() {
onClick(args) {
doSomething();
}
});
view.addRowDeleteClickHandler( new ClickHandler() {
onClick(args) {
doSomething();
}
});