how to catch event in codes after linking events in an array of string inside “events” properties of form object variable in dynamic 4D form? - 4d-database

It's easy to catch events from 4D object's methods of 4D binary form (traditional 4D form) but didn't find any clue to do this in the json dynamic form.
I already gave a try with some 4D commands (CALL FORM, CALL WORKER or POST OUTSIDE CALL) as well to install a project method for a form side by side in a new process inside a loop where I handled events inside that project method. But couldn't get around it. Also I couldn't find any solution/example for this in kb or 4D blog or anywhere.
So any example or database template would be more helpful.

Ravi,
Simply string them in an array named "events".
The docs are your friend for things like this: 4D Manual/Dynamic Forms#Events
The "events" property accepts a JSON array (collection) of strings or
numbers. To call an event, enter the event's name or value (see form
event constant values). For exemple, "events":["onLoad"]) or
"events":[1]
I don't know if you can mix the literal and numeric references. I would expect so but haven't actually tested that.
Edit:
Ravi, if by "catch events in code" you mean have the form you've dynamically created respond to them then you will need to include the name of a project method in the "method" tag. You can't just write some code into an object when you build it dynamically, like you can in regular 4D, but you can call a project method. In that method you can use a Case of statement to test the Form event function to determine which event fired and respond appropriately.
You can't pass parameters to this method. But you can use Object get name or Object get pointer commands to determine the particular object that called it.
For example, let's say I include myMethod as the method. The code for myMethod might look like this:
Case of
:(Form event=On Clicked) // on Clicked is a 4D constant
// do something
:(Form event=on Data Change)
// do something else
End case
Or
Case of
:(Object get name(Object current)="myButton")
Case of
:(Form event=on Clicked)
...
End case
:(Object get name(Object current)="anotherName")
Case of
:(Form event=on Clicked)
...
End case
End case
This illustrates two approaches: 1) you write a separate method for each object or 2) write a single method and determine which object called it. I prefer #2 but that's strictly my opinion.

Related

Is it possible to set an Actions submission criteria that prevents submission if an object has more than a certain number of linked objects?

I currently have an action that creates a new link between an object of type A, named OA, and an object of type B, named OB.
Our workflow has a constraint such that any object of type B can at most, be linked to 4 objects of type A. As such, I would like to define a submission criterion in the action such that submission is blocked if OB is already linked to 4 objects of type A.
I couldn't find a straightforward way to do this using the Action configuration UI. How could I accomplish this?
The easiest way to accomplish this would be to turn your action into a function backed action. This would allow you to take the following steps to accomplish the desired functionality:
You can search around to all objects of type A that are linked to OB by writing something like:
// Search around to all objects of type A that are linked to OB
const linkedObjects = OB.objectTypeA.all();
// Now get the number of linked objects
const numLinkedObjects = linkedObjects.length;
Prevent the function from running by throwing a UserFacingError if there are more than 4 linked objects
if (numLinkedObjects >= 4) {
throw new UserFacingError("Objects of type B cannot be linked to more than 4
objects of type A");
}
For reference, here are some relevant pages in Foundry’s documentation:
Creating Function Backed Actions (https://www.palantir.com/docs/foundry/action-types/function-actions-getting-started/#getting-started)
Accessing link types in Functions (https://www.palantir.com/docs/foundry/functions/api-objects-links/#link-types)
Throwing UserFacingErrors from Functions (https://www.palantir.com/docs/foundry/functions/user-facing-error/)
While you can certainly do this in a Function-backed action, the tradeoff is that you won't get up front validation of the criteria, but rather the user will submit the action and then will received a toast showing the UserFacingError text. So while this technically achieves the validation, it is a sub-par user experience compared to disabling the button with a message or otherwise catching the condition upstream of the action itself in the workflow.
An alternative, iff you're using the action exclusively through Workshop, (this won't work if you want the action to "stand alone" in object explorer), you can create an object set variable that holds the result of the search around and pass that in as a hidden parameter to the Action. You can then set up the Action submission criteria as normal to check the length of that parameter and provide a message back to the user. You can also use that information in the app itself to, for example, conditionally show or hide some other workflow for the condition.
If you take this approach, make sure to add the hubble-oe:hide-action typeclass to one of the object parameters in the Action Form configuration so that the Action doesn't show up where users could use it through Object Explorer.

How to pass a function AND its parameters into another function

My use case is this: a function called 'time' that will return how long it takes to run any function you give it.
So the time function needs to know all the parameters to pass into the function when it calls it.
I know how to pass a function into another function, but how can I pass all its parameters, without knowing in advance how many and what type they are, so they can be used when calling the function?
For example, if I pass in an array of all the parameters I need to send, is there some Dart way to call a function by expanding an array into a list of parameters? Or perhaps there's another way to capture and pass a function call, including all parameters, as one executable object?
I'm also interested in knowing if there's a more Dartful way to accomplish what I'm trying to do re: timing function calls.
I believe using a List of parameters with the apply method is the most common way and practical of doing this and I have seen something similar used to pass parameters for JS interop. As far as I know, there isn't a way to expand an array into a list of parameters like you can for javascript. You could of course create your own object to pass arguments, but I think it would add unnecessary complexity and end up being more difficult.
Example of passing parameters to function in dart:js here.

How do I keep a variable consistant even after seperate play sessions?

I have a variable area which stores a number.
When the app is restarted, it is reset back to it's original value. How can I keep area persistent after being closed?
I'm using Flash CS6 for Android
You'll have to save the variable. There's multiple ways to do this but using a SharedObject is the easiest IMO.
First thing is you don't actually create a new instance of the SharedObject class, you instead call the static function getLocal and this sets your variable. So somewhere near the start of your program you'll want something like this:
var gameSave:SharedObject = SharedObject.getLocal("gameSave");
This either creates a new locally persistent shared object if one does not exist or it grabs the one with the same initialized name ("gameSave") on your computer. This way you can access the saved variables across multiple playthroughs.
Now to save a variable you simply use the dataObject on the shared object and write values to it, then you call the function flush when you're done writing values to immediately save the shared object to your computer.
So saving your area value would look something like this:
gameSave.data.area = Main.area;
gameSave.flush();
After that you'll want to set the area value to whatever the saved value is when your game launches:
if (gameSave.data.area !== undefined) Main.area = gameSave.data.area;
We check if the value is undefined because it might not exist yet if you're playing the game for the first time and the area hasn't been saved yet.
Last thing in case you want to expand the scope of this and save more values: you can only write specific values to the shared object. The way I understand it is you can only write certain class types and primitives. If you try to write anything that's not a primitive or the exception classes, it'll automatically convert that item to an Object and it more or less becomes useless. The classes that it can accept that you'll probably use the most are: int, uint, Number, String, Boolean, Object, and Array. It has a few others like ByteArray and XML, but you'll either not use those at all or not use them very frequently. If you want to save any other class type you'll have to add that functionality yourself.

What does a period with a name before a function mean when calling it in Arduino code (C/C++)?

What does a period with a name before a function mean when calling it in Arduino code (C/C++)?
For example, I am using an OLED display library and one function is called like this:
display.setTextSize(1);
I know what this function does, but what does the syntax mean where there is some variable "display" or something before it?
In other words, why is a function called this way versus a normal call with just the function name and input?
"display" is an instance of an object, or a reference to some global/system variable. The "setTextSize" method is a member of that object. The end result means that you are setting the text size of, or on, "display".
This lets you do things more concisely by being able to say display.setTextSize(1), foo.setTextSize(1) and bar.setTextSize(1) without having to specify unique functions for each different item on which you are setting the text size.
Within setTextSize you will probably see "this". "this" in only this one instance means "display". If you used bar.setTextSize(1), "this" would mean "bar" and so on.
I could be incredibly wrong, but I think its got to do with structures. In the arduino environment there's a few different functions that revolve around using serial communication. They have it set up as a library that gets called on whenever you use Serial.something();
The something could be any of the functions that is part of serial, like Serial.read();
EDIT forgot to put a source in. http://arduino.cc/en/Reference/Serial
Apologies if I'm way off, still new at this, and also can't figure out how to just make a comment.

Pascal passing a listview from mainform to a nonmodal form

I have a listview in my mainform that I want another nonmodal form to be able to add things to.
How would I pass the listview to the nonmodal form?
The form I want to be able to modify it is shown by the MainForm on a button click, just with Form.Show.
I should also clarify that I want the form to not use the mainform to avoid circular reference.
The simplest and best way would be to add a method to the receiving form - that is, the form with the ListView on it -- that says "AddThingsToListView", and have it accept the things you want to add (Probably a TListItem?)
That way, you can then call
MyMainForm.AddThingsToListView(ANewListItem);
from anywhere.
In other words, don't pass the list view to the non-modal form; instead, have the main form be able to accept additions to its list view.
Note: The question was originally tagged Delphi. I don't know FPC/Lazarus so some of the details may not be accurate below but the concepts are still valid.
I'm guessing that you have a global variable representing the main form, named MainForm for the sake of argument. The quickest and simplest approach is simply to use MainForm.ListView to let your other form refer to the main form's list view.
I'm not terribly keen on this approach since it means that the other form takes a dependency on the implementation of the main form.
As an alternative, you can pass a reference to the list view to the other form. For example you could add a SetListView procedure to your other form:
type
TMyOtherForm = class(TForm)
private
FListView: TListView;
public
procedure SetListView(Value: TListView);
end;
.....
procedure TMyOtherForm.SetListView(Value: TListView);
begin
FListView := Value;
end;
Then in the main form, probably in the OnCreate event handler for the main form, you can call this method:
procedure TMainForm.FormCreate(Sender: TObject);
begin
MyOtherForm.SetListView(ListView);
end;
This isn't really all that much better than the first suggestion. The other form still takes a dependency on the implementation of the main form, albeit an arguably less significant dependency.
If you want to keep the two forms even less coupled then the main form could expose a method that accepts additions to the list:
procedure TMainForm.AddToList(const Name: sting; const Time: TDateTime);
var
Item: TListItem;
begin
Item := ListView.Items.Add;
Item.Caption := Name;
Item.SubItems.Add(DateTimeToStr(Time));
end;
The in your other forms unit you add the main form unit to the uses clause in the implementation section. That allows you access to the MainForm global variable and you can call
MainForm.AddToList(Name, Time);
This approach is the best in my view because it allows the main form to keep its list implementation private to itself.
You state in a comment that you want to avoid any circular references due to uses clauses. That's easy to arrange since none of the above require modifications to the uses clause from the interface section from the two units in question.
What I do: for this kind of situation:
I usually declare a data module, and put most of the code that doesn't fit neatly into non-GUI library units into the Data module. The data module can refer to the forms and vice versa, but none of the forms refer to each other.
In this example, your Form2 can use the DataModule, and you can do either:
Have a global reference to the MainForm's ListView in the datamodule, and use that from your form.
Have a function/class in the datamodule that lets you update the list, and call that from your form.
Either way, your form only has to know about the data module, and the data module does the rest. You can add/delete/change forms, and usually you only have to update the DM.