Eclipse Scout callback for entering value in fields - infinite-loop

I would like to know if there is a function that fires up when user set value in field but not if program set value in field.
so function :
user click on field 'myField and change value -> method fires up
in program : myField.setValue = SomeValue; -> method doesn't fires up.
problem is with loop detection. If your logic is that you have 4 field and try to detect if any of those fields are changed and then fire method for change some values inside those fields :
#Override
protected void execChangedValue() throws ProcessingException {
super.execChangedValue();
valueFieldsChange(this);
}
protected void valueInPriceBoxFieldsChange(AbstractValueField field) {
... calculate some values in those fields....
}
and I get :
!MESSAGE org.eclipse.scout.rt.client.ui.form.fields.AbstractValueField.setValue(AbstractValueField.java:338) Loop detection in...
So I know the method execChangedValue() are not what I am looking for. Is there similar method with explained behavior ?
Marko

Let start to say that loop detection is useful in 90% of the cases.
The warning is displayed when you are inside an execChangedValue() and you try to update the value of the same field.
If I understand your example correctly you have inside your field:
public class FirstField extends AbstractStringField {
#Override
protected void execChangedValue() throws ProcessingException {
calculateNewValues();
}
}
And the method:
public void calculateNewValues() {
//some logic to compute the new values: value1, value2, value3
getFirstField().setValue(value1);
getSecondField().setValue(value2);
getThirdField().setValue(value3);
}
At this point, you really need to be sure that when the user sets the value in the FirstField to something, you might want to change it pragmatically to something else. This might be really confusing for the user.
If you are sure that you need to update the value, there is a way to set a value without triggering execChangedValue() on the field. I have proposed a new method: setValueWithoutChangedValueTrigger(T value) on the Eclipse Scout Form: Controlling if execChangedValue() is called or not.
On the forum you will find a snippet that you can add to your field (or in a common template: AbstractMyAppStringField).
public class FirstField extends AbstractStringField {
#Override
protected void execChangedValue() throws ProcessingException {
calculateNewValues();
}
public void setValueWithoutValueChangeTrigger(String value) {
try {
setValueChangeTriggerEnabled(false);
setValue(value);
}
finally {
setValueChangeTriggerEnabled(true);
}
}
}
And you will be able to use it:
public void calculateNewValues() {
//some logic to compute the new values: value1, value2, value3
getFirstField().setValueWithoutChangedValueTrigger(value1);
getSecondField().setValueWithoutChangedValueTrigger(value2);
getThirdField().setValueWithoutChangedValueTrigger(value3);
}
I hope this helps.

Related

JavaFX Implementing 2 different MapChangeListeners [duplicate]

This question already has answers here:
How to make a Java class that implements one interface with two generic types?
(9 answers)
Closed 8 years ago.
I have the following interface, which I want to implement multiple times in my classes:
public interface EventListener<T extends Event>
{
public void onEvent(T event);
}
Now, I want to be able to implement this interface in the following way:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
{
#Override
public void onEvent(LoginEvent event)
{
}
#Override
public void onEvent(LogoutEvent event)
{
}
}
However, this gives me the error: Duplicate class com.foo.EventListener on the line:
class Foo implements EventListener<LoginEvent>, EventListener<LogoutEvent>
Is it possible to implement the interface twice with different generics? If not, what's the next closest thing I can do to achieve what I'm trying to do here?
Is it possible to implement the interface twice with different generics
Unfortunately no. The reason you can't implement the same interface twice is because of type erasure. The compiler will handle type parameters, and a runtime EventListener<X> is just a EventListener
If not, what's the next closest thing I can do to achieve what I'm trying to do here?
Type erasure can work in our favor. Once you know that EventListener<X> and EventListener<Y> are just raw EventListener at run-time, it is easier than you think to write an EventListener that can deal with different kinds of Events. Bellow is a solution that passes the IS-A test for EventListener and correctly handles both Login and Logout events by means of simple delegation:
#SuppressWarnings("rawtypes")
public class Foo implements EventListener {
// Map delegation, but could be anything really
private final Map<Class<? extends Event>, EventListener> listeners;
// Concrete Listener for Login - could be anonymous
private class LoginListener implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
System.out.println("Login");
}
}
// Concrete Listener for Logout - could be anonymous
private class LogoutListener implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
System.out.println("Logout");
}
}
public Foo() {
#SuppressWarnings("rawtypes")
Map<Class<? extends Event>, EventListener> temp = new HashMap<>();
// LoginEvents will be routed to LoginListener
temp.put(LoginEvent.class, new LoginListener());
// LogoutEvents will be routed to LoginListener
temp.put(LogoutEvent.class, new LogoutListener());
listeners = Collections.unmodifiableMap(temp);
}
#SuppressWarnings("unchecked")
#Override
public void onEvent(Event event) {
// Maps make it easy to delegate, but again, this could be anything
if (listeners.containsKey(event.getClass())) {
listeners.get(event.getClass()).onEvent(event);
} else {
/* Screams if a unsupported event gets passed
* Comment this line if you want to ignore
* unsupported events
*/
throw new IllegalArgumentException("Event not supported");
}
}
public static void main(String[] args) {
Foo foo = new Foo();
System.out.println(foo instanceof EventListener); // true
foo.onEvent(new LoginEvent()); // Login
foo.onEvent(new LogoutEvent()); // Logout
}
}
The suppress warnings are there because we are "abusing" type erasure and delegating to two different event listeners based on the event concrete type. I have chosen to do it using a HashMap and the run-time Event class, but there are a lot of other possible implementations. You could use anonymous inner classes like #user949300 suggested, you could include a getEventType discriminator on the Event class to know what do to with each event and so on.
By using this code for all effects you are creating a single EventListener able to handle two kinds of events. The workaround is 100% self-contained (no need to expose the internal EventListeners).
Finally, there is one last issue that may bother you. At compile time Foo type is actually EventListener. Now, API methods out of your control may be expecting parametrized EventListeners:
public void addLoginListener(EventListener<LoginEvent> event) { // ...
// OR
public void addLogoutListener(EventListener<LogoutEvent> event) { // ...
Again, at run-time both of those methods deal with raw EventListeners. So by having Foo implement a raw interface the compiler will be happy to let you get away with just a type safety warning (which you can disregard with #SuppressWarnings("unchecked")):
eventSource.addLoginListener(foo); // works
While all of this may seem daunting, just repeat to yourself "The compiler is trying to trick me (or save me); there is no spoon <T>. Once you scratch your head for a couple of months trying to make legacy code written before Java 1.5 work with modern code full of type parameters, type erasure becomes second nature to you.
You need to use inner or anonymous classes. For instance:
class Foo {
public EventListener<X> asXListener() {
return new EventListener<X>() {
// code here can refer to Foo
};
}
public EventListener<Y> asYListener() {
return new EventListener<Y>() {
// code here can refer to Foo
};
}
}
This is not possible.
But for that you could create two different classes that implement EventListener interface with two different arguments.
public class Login implements EventListener<LoginEvent> {
public void onEvent(LoginEvent event) {
// TODO Auto-generated method stub
}
}
public class Logout implements EventListener<LogoutEvent> {
public void onEvent(LogoutEvent event) {
// TODO Auto-generated method stub
}
}

C# property not working

Dont understand why its not working.. im using the property to set the Activelogin to true then getting the value in another page to certify that the user is has access.
namespace Ibrax_1
{
public partial class loginPage : System.Web.UI.Page
{
public bool activelogin;
public bool Activelogin
{
get
{
return activelogin;
}
set
{
activelogin = value;
}
}
.
.
.
Activelogin = true; // here in a method im setting the value to true.
and im getting value here:
namespace Ibrax_1
{
public partial class Program : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
CheckAvailablePrograms();
}
private void CheckAvailablePrograms()
{
loginPage lp = new loginPage();
if (lp.Activelogin) //here im getting the value but its false
{
am i doing anything wrong?
You're creating a new instance:
loginPage lp = new loginPage();
That new instance will have every property set to its default value. For boolean, that's false.
If you're setting it to true somewhere else, then it won't matter since you're not looking at that instance.
It's like drawing on a piece of paper and then taking another paper and wondering why there's no drawing on it. You can't expect there to be a drawing unless you're looking at the same piece of paper.
So you need to save the instance of object somewhere so you can use it again in the CheckAvailablePrograms method. As Alex Kudryashev mentioned, you could save it as a Session variable, although it's not the only way. You can read more about the Session object here if you wish: https://msdn.microsoft.com/en-us/library/ms178581.aspx

Is there any way to pass Output of one workflow to another without using outarguments?

I have recently started working with Workflows.I am able to pass output of one activity as input to another through making use of OutArgument .Is it possible without using OutArgument.
If Possible please suggest me how?
Thanks all
You can use a workflow extension to act as a repository of variables in the scope of the whole workflow.
Create a workflow extension that contains properties.
Add the extension to the workflow application.
Set or Get the value of the properties from within Activities.
See https://msdn.microsoft.com/en-us/library/ff460215(v=vs.110).aspx
In response to your comment below.
You are wrong in your assumption. The extension "holds" the output from activity 1 which is then available to activity 2.
For example:
Create a class to hold properties:
public class PropertyStoreExtension
{
int _myProperty
public int MyProperty
{
get
{
return this._myProperty;
}
set
{
this._myProperty = value;
}
}
}
Add this as an extension to your workflow:
PropertyStoreExtension propertyStoreExtension = new PropertyStoreExtension
WorkflowInvoker myWorkflowInstence = new
WorkflowInvoker(myWorkflowDefinition());
myWorkflowInstence.Extensions.Add(propertyStoreExtension);
myWorkflowInstence.Invoke()
Your workflow contains 2 activities:
The first takes its "output" and stores it in the extension.
public class Activity1_SetProperty: CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
PropertyStoreExtension pse =context.GetExtension<PropertyStoreExtension>();
if (pse != null)
{
pse.MyProperty=outputValue;
}
}
}
The second gets the value out of the extension.
public class Activity2_GetProperty: CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
PropertyStoreExtension pse =context.GetExtension<PropertyStoreExtension>();
if (pse != null)
{
int intputValue; = pse.MyProperty
}
}
}

C# ASP.NET - Controlling/updating a textbox.text value through a class

Newbie here, I need help with a website I'm creating.
I have a class that does some analysis on some text that is input by the user, the class then finds an appropriate answer and sends it back to the textbox. (in theory)
Problem is I don't know how I can control and access the textbox on the default.aspx page from a class, all I get is "object reference is required non static field".
I made the textbox public in the designer file yet still no joy. :(
I've also read this: How can I access the controls on my ASP.NET page from a class within the solution? , which I think is along the lines of what I'm trying to achieve but I need clarification/step by step on how to achieve this.
Hope someone can point me in the right direction.
Many thanks,
Kal
This is the code I have added to the designer.cs file:
public global::System.Web.UI.WebControls.TextBox TextBox3;
public string MyTextBoxText
{
get
{
return TextBox3.Text;
}
set
{
TextBox3.Text = value;
}
}
This is the class method i have created:
public static cleanseMe(string input)
{
string utterance = input;
string cleansedUtt = Regex.Replace(utterance, #"[!]|[.]|[?]|[,]|[']", "");
WebApplication1._Default.TextBox3.text = cleansedUtt;
}
I could just return the cleansedUtt string i know, but is it possible for me to just append this string to the said textbox from this method, within this class?
I also tried it this way, i wrote a class that takes in the name of the textbox and string to append to that textbox. it works BUT only on the default.aspx page and does not recognise the textbox names within the difference classes. The code is as follows:
public class formControl
{
public static void ModifyText(TextBox textBox, string appendthis)
{
textBox.Text += appendthis + "\r\n";
}
I would suggest you that do not access the Page Controls like TextBox in your class. It will be more useful and a good practice that whatever functionality your class does, convert them into function which accept the parameters and returns some value and then on the basis of that value you can set the controls value.
So now you have reusable function that you can use from any of the page you want. You do not need to write it for every textbox.
Here I am giving you a simple example
public class Test
{
public bool IsValid(string value)
{
// Your logic
return true;
}
}
Now you can use it simple on your page like this
Test objTest = new Test();
bool result=objTest.IsValid(TextBox1.Text);
if(result)
{
TextBox1.Text="Everything is correct";
}
else
{
TextBox1.Text="Something went wrong";
}
If you have your class in the same project (Web Project) the following will work:
public class Test
{
public Test()
{
//
// TODO: Add constructor logic here
//
}
public static void ValidateTextBox(System.Web.UI.WebControls.TextBox txt)
{
//validation logic here
if (txt != null)
txt.Text = "Modified from class";
}
}
You can use this from your webform like this:
protected void Page_Load(object sender, EventArgs e)
{
Test.ValidateTextBox(this.txt);
}
If your class is in a different (class project), you would need to add a reference to System.Web to your project.

WF4 - Composite custom activity throw an strange exception when using OutArgument

I'm trying to use a composite custom activity that apply a regular expression and return a boolean if it match.
The pattern is something encoded in design time.
The source text is coming from an activity. This activity is also specified in design time (I've made a activity designer that allow to drop an activity as source)
But I also need to return what sub string match the expression, so I added an OutArgument to retrieve the string that match, and the string captured.
Here is the code:
public class RegularExpression : NativeActivity<bool>
{
[RequiredArgument]
public string Pattern { get; set; }
public OutArgument<string> Captured { get; set; }
[RequiredArgument]
public Activity<string> RetrieveTextActivity { get; set; }
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddChild(this.RetrieveTextActivity);
}
protected override void Execute(NativeActivityContext context)
{
if (this.RetrieveTextActivity != null)
context.ScheduleActivity<string>(this.RetrieveTextActivity, this.onRetrieveComplete);
}
private void onRetrieveComplete(NativeActivityContext context, ActivityInstance completedInstance, string result)
{
var regexp = new Regex(this.Pattern);
var match = regexp.Match(result);
this.Result.Set(context, match.Success);
if (this.Captured != null)
this.Captured.Set(context, match.Value);
}
}
If I execute this activity without binding a variable to the Captured argument, it works as expected (the Result is correctly set).
But if I use the designer to add a variable, then I bind the variable to the Captured argument this error popup:
The argument of type 'System.String' cannot be used. Make sure that
it is declared on an activity.
The exception is thrown when executing this line:
this.Captured.Set(context, match.Value);
Does someone have an idea why I can't set the argument ?
I also read that I shouldn't test that Captured is null, the runtime should automatically set a default value. But If I don't test, I've a NullReference when I don't bind a variable to the argument...
EDIT:
I want to add more information about the workflow itself. I've read in another topic that it may be VS. Here I just want to specify that I'm using a rehosted designer to create the workflow (and not VS). The workflow is then saved as XML in a database.
When I need to start a new workflow, I read the database, use XamlService.Load and Run the created workflow.
Does the error go away if you declare the argument in CacheMetadata?
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddChild(this.RetrieveTextActivity);
RuntimeArgument argument = new RuntimeArgument("Captured", typeof(string), ArgumentDirection.Out);
metadata.Bind(this.Captured, argument);
metadata.AddArgument(argument);
}
EDIT: I was too quick. The above code should now compile and hopefully fix your problem.
My problem went away when I just called the base.CachMetadata(metadata) after my adds. Try:
protected override void CacheMetadata(NativeActivityMetadata metadata)
{
metadata.AddChild(this.RetrieveTextActivity);
base.CacheMetadata(metadata);
}
You want to do it after your adds, because you want the base class to know what you've added when you call it. I think the base class uses reflection to do Damir Arh's answer for you automatically. This way you don't have to add or modify all that code every time you add or modify your properties. If you had a lot of properties it would become a pain real fast.

Resources