C++-CLI: UI Control as parameter of external function? - winforms

I try to make an interface for the device using WinForms. I have a class which stores all parameters and methods, like below:
// device.h:
class Device {
double parameter_a;
double parameter_b;
double setParameterA(double new_value);
double setParameterB(double new_value);
}
Then, I would create an instance and use it's methods to modify parameters by event handling and return either corrected value for UI Control or just 0 if everything is fine.
However, I found that this solution doesn't really make my code shorter, as I still have to modify UI inside my Form document, where all my controls are reachable (if errors / out of range values encountered).
What would I like to do is to somehow pass a kind of pointer to UI Control (like TextBox) to the function and make it like below:
void setParameterA(double new_value, *ui_ctrl_pointer* ) {
// simple value check
if (new_value > 0) {
// numToMStr() - function I have to convert numbers to managed string
*ui_ctrl_pointer*->Text = numToMStr(new_value);
return;
}
}
and modify the control inside the setParameterA() along with input control and setting my device.
1. Is it possible to make such a thing in C++-cli? (if so, what would ui_ctrl_pointer look like?)
2. Is this a correct approach or should I stick to the basic solution, which would force me to check for function output to determine what to do with value set by user inside my UI?

Related

RxJS proper way of Creating Behavior Subjects from other Behavior Subjects?

So I'm using an observable values in an angular application, and I want to make several behavior subjects derived from other behavior subject. I was transforming my behavior subjects with the .map() operator, but found out that I could not reference .value. I wanted to be able to reference the current value as was emitted last (so passed through the mapping function). A little digging around with the output of foo.map() I found I could get the functionality I wanted with:
let foo = /* some BehaviourSubject */
let bar = foo.map((x) => x / 2)
bar.operator.project(bar.destination.value) // to get the value as last emitted
But thats not very nice looking
Currently I'm doing something that looks like this to get the functionality i want:
foo = /* some observable*/
bar = foo.map((x) => x / 2).toBehaviorSubject()
foobar = bar.map((y) => y > 10).toBehaviorSubject()
toBehaviorSubject() is a function I've defined as the following
rx.Observable.prototype.toBehaviorSubject = function (initialValue) {
initialValue = initialValue || null
let subject$ = new rx.BehaviorSubject(initialValue)
this.subscribe((value) => { subject$.next(value) })
return subject$
}
I had earlier toyed with this as a solution, but opted for what I've shown above:
foo = /* some BehaviourSubject */
bar = new rx.BehaviorSubject( foo.value / 2))
foo.subscribe( (x) => {
bar.next(x / 2)
})
foobar = new rx.BehaviorSubject(bar.value > 10)
bar.subscribe( (y) => {
foobar.next(y > 10)
})
These work and all, but I have to ask, is there a standard convention for something that works like the above two examples?
Edit-------------------
Some added context might be helpful.
so I have a BehaviorSubject auth.User$ that is sourced from a service I wrote for window.localstorage access which hands out BehaviorSubjects on its localStorage.get(key) function. I wrote this wrapper to deal with the fact that the localStorage change event fires on all tabs except the tab that changed the value.
Some parts of my application need to know whether the user has been initialized, or if the user is an anonymous user (some portlets can be accessed without logging in) or authenticated (for those which require the user to be logged in), and when these statuses change. In order to avoid duplicating the logic for producing the boolean values for isInitialized, isAnonymous, and isAuthenticated, I wanted to derive more BehaviorSubjects from auth.User$. I want them to be BehaviorSubjects specifically because some of the parts of the application only need the values on an on-call basis, and so being able to reference auth.isAuthenticated$.value is preferable to subscribing to that observable.
I used the Observable.map() function because I wanted to have observable values that fire when auth.user$ does and which transform the emitted values from it, but would like it to still be a BehavorSubject as mentioned above.
So my question is essentially: is there a standard convention for applying a transformation/mapping function to a BehaviorSubject and still get a BehaviorSubject?
I am not sure I understand your question, but basically a behaviour subject always has a value, so you can query the subject from that value at any point of time. I believe in Rxjs v5, getValue is the relevant method.
When you do let foo = /* some BehaviourSubject */ let bar = foo.map((x) => x / 2), then bar is not a subject anymore, it is an observable, i.e. a producer of a stream of values. You need to subscribe to bar to start that producer and actually get a value. Your API seems to do just that. A shorter way is to do bar.subscribe(anotherBehaviourSubject).
Now, do you really need to start the producer so early? i.e. do you actually need a behaviour subject in the first place? If you do, then of course go ahead.

Coded UI test playback. Wrong control is being selected and used

I am trying to design a simple Coded UI tests that access the two following functions. Currently they are written with the CUITe framework but I see the same issue when using Coded UI code.
I have a test case which first calls GLJEEnterDescription, then calls GLJEEnterNotes. When the test runs, GLJEEnterDescription is manipulated and BOTH strings passed into the functions are entered into it. Nothing is ever entered into GLJEEnterNotes. I have checked and rechecked and the properties for the controls are correct.
The only difference between the two controls is GLJEEnterDescription is a standard single line text box and GLJEEnterNotes is a custom (derived from standard) multiline text box. Any thoughts on why I would not be able to access and use the GLJEEnterNotes text box but not the GLJEEnterDescription text box? Below is my functions called from the Coded UI tests:
public void GLJEEnterDescription(string JEDescription)
{
akwindow.Find<WinEdit>(By.ControlName("txtJEDescription")).Text = JEDescription;
}
public void GLJEEnterNotes(string JENotes)
{
akwindow.Find<WinEdit>(By.ControlName("txtMultiJENotes")).Text = JENotes;
}
You most likely need to specify more search criteria for those controls.
Ideally, I would recommend trying to use control ID's or even AutomationID's for your controls. These are the HIGHEST priority for the search algorithm
Like in This Post
var textBox = new WinEdit(yourAppWindow);
textBox.SearchProperties.Add(WinEdit.PropertyNames.Name, "txtMultiJENotes");
textBox.SearchProperties.Add(WinEdit.PropertyNames.LineCount, "1");
else you might have to use FindMatchingControls and cycle each control for the right things you want.

Movie Clip through Display Object Not working correctly

Hey everyone so I have a movie Clip called popEffect that i want to show on the current bubbles that are being clicked by the mouse. Now Whenever I click on a Bubble everything works correctly they get removed from the stage, but the problem I am having is that the popEffect is not positioned to the current bubbles that are being clicked. Instead they are positioned at a different bubble that shows on the screen in the display object array.
Here is how I have it all set up:
private function addBubbles(e:TimerEvent):void
{
bubbles = new mcBubbles();
stage.addChild(bubbles);
aBubbleArray.push(bubbles);
bubbles.addEventListener(MouseEvent.CLICK, bubblesBeingClicked);
}
Then the BubblesBeingClicked function:
private function bubblesBeingClicked(e:MouseEvent):void
{
var BubblePop:DisplayObject = e.target as DisplayObject; // HERE is your clicked square
var i:int = aBubbleArray.indexOf(BubblePop); // and HERE is your index in the array
if (i < 0)
{
// the MC is out of the array
//trace("Pop Clicked");
onBubbleIsClicked(BubblePop);
aBubbleArray.splice(i, 1);
BubblePop.parent.removeChild(BubblePop);
//Remove Listeners!!!
BubblePop.removeEventListener(MouseEvent.MOUSE_DOWN, onBubbleIsClicked);
// Null
BubblePop = null;
}
}
Finally my onBubbleIsClicked function where i have the popEffect located:
private function onBubbleIsClicked(bubblePop:DisplayObject):void
{
nScore++;
updateHighScore();
//Pop Effect
popEffect = new mcBubblePop();
stage.addChild(popEffect);
popEffect.x = bubbles.x;
popEffect.y = bubbles.y;
}
Can anyone see why the popEffect wont position on the current bubble that is being popped? Its acting really weird.
The reason is this:
popEffect.x = bubbles.x;
popEffect.y = bubbles.y;
As far as I can understand, bubbles is a member variable in the class (you are using it in the addBubbles function. Inside onBubbleIsClicked, you provide bubblePop, but do not use it. You are using bubbles instead, which is actually the last instance you've created inside the tick function!
So every time you create popEffect, you actually assign the x and y to the latest created bubblePop.
Some advises:
Do not use member variables that often. They are used WHEN you need to use a variable between functions. In your case, bubbles is a variable that is used only inside the creational function. You even put them into an array! And because you override it with a new one every time you create an instance, your member variables just saves the last one. Is this really needed? Same with popEffect, does anyone else uses it, as it's again just the last one? Such things create mistakes, as you see..
I truly don't understand what this means: if (i < 0). You search if the object you've clicked is not in the array? Well if it is not (how come?!), then what's the meaning of aBubbleArray.splice(i, 1);? Since i < 0, you actually splice with negative value, so you splice some other element! Plan what you want to do, thing logically and then do the actual code. If the object is not in the array, then why do you remove anything from the array?
Start formatting your code better. Read about camel case and variables scope.
Try to manage your logic better. For example this is pretty awkward: BubblePop.parent.removeChild(BubblePop);, as long as you've added it by using stage.addChild(bubbles);. So isn't it more simple to use stage.removeChild(child);? There are some rules in programming (especially in Flash), like 'what added it should remove it'. This will keep you safe in future.
Good luck!

Define component list dynamically for Sidekick and Insert dialog in CQ5

I am trying to modify the list of components displayed in the sidekick based on the user's privileges.
I am trying it as explained here.
What i would like to know is how to send back the modified allowed array that is received as the argument, because what ever modifications i make to the array appears to be in the local scope. For e.g. if i want the allowed components to consist only of the default list component, i do something like this.
function MyHandler(cell, allowed, componentList) {
allowed = [];
allowed.push("/libs/foundation/components/list");
}
But once the control goes back to the function that triggered this event, these changes are not visible. Should i be returning the array or something ? Could you please explain if i am missing something here?
Ok. Finally figured the issue. I wanted to clear the existing list of components that were passed on to my handler, for which I used allowed = [];.
This removed all the existing references to the allowed array. (More about this explained here).
Thus changing it to allowed.length = 0; works absolutely fine.
function MyHandler(cell, allowed, componentList) {
allowed.length = 0;
allowed.push("/libs/foundation/components/list");
}

Make variable name using loop and string in PowerBuilder

I am interested if it is possible to make variable name in PowerBuilder using a loop and a string. For example:
long ll_go
string lst_new
for ll_go = 1 to 8
lst_new = "text" + ll_go
lst_new.tag = 5500
next
So, it should give me variables text1, text2..,.,text8 and I would be able to assign values for them. Let me know if anybody succeeded, thanks in advance
Your description is lacking some term precision.
If you actually want to dynamically create new variables as "variable in a powerscript subroutine or function" this is simply not possible.
If instead you want to create dynamically some new controls statictext or textedit objects in a window or visual userobject this is possible:
use a local variable of the type of the new object you need to create, e.g. static text
make it a live object (instantiate) with create
set the object properties to whatever you need
"attach" the new object to its parent (either a window or a visual userobject - though any graphicobject is possible with using the win32api SetParent function) with the OpenUserObject() method. Note that you cannot simply add it directly to the parent's Control[] array.
you can also keep the object in your own array for later convenience access to the created objects instead of looping on the Control[] array
once the object is attached it its parent, you can reuse the local variable to create another one
Here is an example:
//put this in a button clicked() event on a window
//i_myedits is declared in instances variables as
//SingleLineEdit i_myedits[]
SingleLineEdit sle
int i
for i = 1 to 8
sle = create singlelineedit
sle.text = string(i)
sle.tag = "text_" + string(i)
sle.height = pixelstounits(20, ypixelstounits!)
sle.width = pixelstounits(100, xpixelstounits!)
parent.openuserobject(sle, pixelstounits(10, xpixelstounits!), pixelstounits(22 * i, ypixelstounits!))
i_myedits[i] = sle //keep our own reference
next
An exemple of values access:
//put that in another button clicked() event
SingleLineEdit sle
int i
string s_msg
for i = 1 to upperbound(i_myedits[])
sle = i_myedits[i]
if i > 1 then s_msg += "~r~n"
s_msg += "edit #" + string(i) + " (" + sle.tag + ") says '" + sle.text + "'"
next
messagebox("Edits values", s_msg)
As you can see, one practicality problem is that you cannot refer to these controls by constructing the control's name like "text"+2, instead you must access the my edits[] array or loop through the controls and test their .tag property if you set it to something specific.
I do not think that it is possible. Workaround could be an array maybe.
Br. Gábor
I'd see two ways to do this, but they aren't as easy as it seems that you were hoping:
1. Control Array
First method would be to go through the control arrays (on windows, tabs and user objects). I'd create a function that took the control name as a string, then another that overloaded the same function and took control name and an array of windowobject. The string-only method would just call the string/array method, passing the string through and adding the window.Control as the second parameter. The string/array method would go through the array, and for each element, get the ClassDefinition. Pull the name off of it, and parse it apart the way you want it to match the string parameter (e.g. for w_test`tab_first`tabpage_first`cb_here, do you want cb_here to match, or tab_first`tabpage_first`cb_here?). Deal with matches as appropriate. When you find a control of type tab or user object, call the string/array function again with the Control array from that object; deal with success/fail returns as appropriate.
2. DataWindow
What you're describing works extremely well with DataWindows, and their Describe() and Modify() functions. Since you pass these functions only a string, you can build not only the control names, but the values they're set to as you would build any string. In fact, you can build multiple Modify() strings together (delimited by a space) and make a single call to Modify(); this is not only faster, but reduces window flicker and visible activity.
Don't fall into the trap of thinking that, since your data isn't from a database, you can't use a DataWindow. Create an external DataWindow, and simply use it with one row inserted during the Constructor event.
As you might guess, I'd strongly favour the DataWindow approach. Not only is it going to perform better, but it's going to provide a lot more flexibility when you want to move on and tag more control types than just static text. (You'll have to do some type casting even with one control type, but if you want to get into multiples, you'll need to start a CHOOSE CASE to handle all your types.)
Good luck,
Terry
You can't create a variable name in a script because the variables have to be declared before you can use them. With PBNI it's possible to generate a name the way you describe and then get a reference to a variable of that name that already exists but I don't think that's what you want. If you want to keep track of additional properties for your controls, just inherit a new user object from whatever it is (sle, mle, etc.) and add the properties you want. Then you can place your user object on a window and use the properties. Another approach is to use the control's Tag property. It holds a string that you can put whatever you want in. PFC uses this technique. Terry's DataWindow solution is a good approach for storing arbitrary data.
Yes, and there are more than one way to skin a cat.
Sounds like you have several properties so I'd use an array of custom non visual user objects, or an array of structures. Otherwise you could probably use something from the .NET framework like a dictionary object or something like that, or a datawidnow using an external datasource, where you can refer to column names as col + ll_index.ToString().
SIMPLE Example:
Make custom NVO with following instance variables, plus getter/setter functions for each, name it n_single_field
// add the properties and recommend getter and setter functions
public string myTag
public string myText
public int myTabOrder
...
// To USE the NVO define an unbounded array
n_single_field fields[]
// to process the populated fields
integer li_x, li_max_fields
// loop through field 1 through max using array index for field number
li_max_fields = upperbound(fields)
for li_x = 1 to li_max_fields
fields[li_x].myTag = 'abc'
fields[li_x].myText = 'text for field number ' + li_x.ToString()
fields[li_x].myTabOrder = li_x * 10
next
Maybe I'm oversimplifying if so let me know, if there is a will there is always a way. ;)

Resources