Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread David Adams via 4D_Tech
On Sat, Mar 18, 2017 at 12:01 PM, Douglas von Roeder via 4D_Tech <
4d_tech@lists.4d.com> wrote:

> David:
>
> Just read the feature request thread for WebSockets and I'm pretty certain
> I voted for it (clicked 4 stars on the first message in the thread).
>

Thanks! Not my feature request, but, dang, one of my favorites this year.
That and Cannon's request for an implicit C_OBJECT store for forms and so
on. That would also be pretty darn great for different reasons.


> WebSocket fits well into the concepts of Call worker/form in that it's
> providing developers with more granular connections and, hence more
> granular control, over how data is requested and supplied. That would be a
> very welcome addition to the 4D toolset.
>

Yeah, 'game changer' isn't an overstatement. A WebSocket is a reasonably
easy-to-use, dedicated two-way communications pipe between two processes.
And "processes", in this case, can mean a Web browser. So, you get a really
platform agnostic way of hooking 4D up to...well...anything that supports
WebSockets. Very, very nice idea. It doesn't do everything - but it fills
in a big gap. WebSockets also very neatly leverage a lot of existing HTTP
gunk (like for security), they don't require moderation by a dedicated Web
server. That's super flexible...and efficient. Imagine if you could spin up
a worker that's dedicated to a 4D process on a remote stand-alone, or a
remote client connected to a *different* 4D server, or connected to an
entirely different program in some completely unrelated language you've
never heard of, or connected to a Web browser. Persistently connected.
Bi-directional. The mind is blown.

For anyone that's interested in message-oriented architectures and/or
distributed computing setups (read: anyone working on a network),
WebSockets would real make 4D something like 4D^ 16D?
**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread Douglas von Roeder via 4D_Tech
David:

Just read the feature request thread for WebSockets and I'm pretty certain
I voted for it (clicked 4 stars on the first message in the thread).

WebSocket fits well into the concepts of Call worker/form in that it's
providing developers with more granular connections and, hence more
granular control, over how data is requested and supplied. That would be a
very welcome addition to the 4D toolset.


--
Douglas von Roeder
949-336-2902

On Fri, Mar 17, 2017 at 3:02 PM, Douglas von Roeder 
wrote:

> David:
>
> I'll read up on the web sockets - when I first saw that I misread it for
> "WebObjects". A cold chill ensued.
>
> C_Object is a great addition to the language. Agree that it doesn't do
> everything that OT does but that why we have wrapper routines. I've
> extended Cannon's OBJ_Module with OBJ_SetArray_Text/Long/Real and a few
> other array commands and I can get a lot done with C_Object that I'm doing
> in OT. The biggest benefits - scope/garbage collection and the content of a
> C_Object is visible in the debugger. Those are "bloody mavhelous".
>
> "you're tossing blocks of code at the end of the thread of control over
> there for one-off execution."
> Excellent way to phrase it. And the emphasis is on "over there" because
> the code executes in the context of the destination form.
>
> "execute in form" similar to "execute on client"
>
> "On Outside Call was always documented as being unreliable while CALL
> FORM / CALL WORKER guarantee delivery."
> OOC worked well form me, as far as I know (emphasis on the "AFAIK").
> I did have to tweak my original code to work in a Repeat loop, as you say,
> Call form/Call worker will always get through so there's no need to jump
> through hoops (loops) to make sure the message arrived.
>
>
> "NTK's IPC channels easier" - agreed. I"m using an array-based derivative
> of that approach (taken from ITK about 20 years ago) with a change in
> 2000-01 and that's it. Highly reliable and zero maintenance but it doesn't
> allow me to get to a specific form…which is what's needed to get at the *
> dialog. Very nice to have multiple active windows in a process but
> disappointing that I couldn't get to it with a message.
>
>
> "You mention that you're doing message routine. This can be pretty darn
> impossible to trace or debug if there's nothing in the message about the
> path that it has followed."
> I only had to chase messages "down a rabbit hole" a few times over the
> years. Two ways of reducing the odds of that happening - one of the
> properties of a message will allow the message and its metadata to be
> displayed added to arrays displayed in a grid. I needed that to debug some
> code that had become very involved and the end result is that it helped
> force me to rethink my approach.
>
> The other technique that I've used it a bit dated now but was very helpful
> before V11, back in the dark ages when "Find in design" was dreadfully
> slow. That situation convinced me to use IP vars in the message. From
> *MSGIP_Vars_Init*:
>
> C_TEXT(<>MSG_InsertCarriageReturn)
> <>MSG_InsertCarriageReturn:="<>MSG_InsertCarriageReturn"
>
>  C_TEXT(<>MSG_ProposalIsLocked)
> <>MSG_ProposalIsLocked:="Proposals_is_Locked"
>
>  C_TEXT(<>MSG_BringToFront)
> <>MSG_BringToFront:="<>MSG_BringToFront"
>
> C_TEXT(<>MSG_Close)
> <>MSG_Close:="<>MSG_Close"
>
> C_TEXT(<>PROC_Activated)
> <>PROC_Activated:="<>PROC_Activated"
>
>
> From On Outside call:
> Repeat
>
> C_LONGINT($msgHandle_L)
> $msgHandle_L:=MSGIP_Message_Get (Current process)
>
> C_TEXT($msg_T)
> $msg_T:=MSGIP_TextMessage_Get ($msgHandle_L;False)
>
> Case of
> : ($msg_T=<>MSG_BringToFront)
> PROC_ResumeAndBringToFront (Current process)
>
> : ($msg_T=<>MSG_Close)
> CANCEL
> End case
>
> MSGIP_Message_Clear ($msgHandle_L)
>
> Until (MSGIP_MessageCount_Get (Current process)=0)
>
>
> To your point about the provenance of the message, another significant
> argument for an object without which it would be gruesome to try to add
> that sort of data to…a BLOB?! No interest in the level of mental gymnastics…
>
> Time to have a looksee here - http://forums.4d.fr/Post/EN/
> 19129127/1/19129128
>
>
> --
> Douglas von Roeder
> 949-336-2902 <(949)%20336-2902>
>
> On Fri, Mar 17, 2017 at 2:18 PM, David Adams via 4D_Tech <
> 4d_tech@lists.4d.com> wrote:
>
>> > Interesting approach - thank you for posting that.
>>
>> DvR: You, of all people, will *love* this approach.
>>
>> > Lacking "callers" and C_Object, I've been using On outside call +
>> > ObjectTools + IP messaging based on the ITK message queuing system.
>>
>> Once you have access to V16, you may find:
>>
>> * You like C_OBJECT because it's very fast and native. But it won't do
>> everything that ObjectTools does.
>>
>> * You may still want to use IPC channels from NTK. They're traditional
>> messages, easily support a wider range of messaging patterns, and can be
>> used to-from anywhere.
>>
>> * CALL FORM/CALL WORKER are great! You'll love them. On Outside Call was
>> always documen

RE: Problem accessing 4D via ODBC and Excel Power Query

2017-03-17 Thread Timothy Penner via 4D_Tech
Hi Kirk,

I did a really quick test with Power Query (32 bit) with Excel 2010 (32 bit) 
connecting to 4D Server v15.4 (64 bit) using the 4D ODBC Driver (32 bit).
https://www.microsoft.com/en-us/download/details.aspx?id=39379

For me it worked, but my test database only had 1 table with 3 fields and 1 
record.
I then added a second record and refreshed the data on the excel spreadsheet to 
get two records.

This was the first time I used Power Query so I don't know if I am doing the 
same thing you are doing...

I have no idea what HY02470 is,  it doesn’t seem to be coming up in my online 
searches.

If you open a case on taow.4d.com we can get you more dedicated help on 
troubleshooting this.

-Tim



**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

RE: v13 MSC Maintenance Mode Activation—Mac.

2017-03-17 Thread Timothy Penner via 4D_Tech
Is it a merged/built application using OEM Desktop or is it a regular 4D 
application running your 4DC/4DB?

If it is a merged/built application I think you need to use the Alt/option key: 
http://kb.4d.com/assetid=76457

If it is a regular 4D application then you could just open 4D (without opening 
your database) and then from the help menu choose the MSC option.
Or use the MSC option from the Open dialog (see screenshots here: 
http://kb.4d.com/assetid=76900 - 
http://kb.4d.com/kbase/assets/images/76900-3.jpg)

-Tim



**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread Douglas von Roeder via 4D_Tech
David:

I'll read up on the web sockets - when I first saw that I misread it for
"WebObjects". A cold chill ensued.

C_Object is a great addition to the language. Agree that it doesn't do
everything that OT does but that why we have wrapper routines. I've
extended Cannon's OBJ_Module with OBJ_SetArray_Text/Long/Real and a few
other array commands and I can get a lot done with C_Object that I'm doing
in OT. The biggest benefits - scope/garbage collection and the content of a
C_Object is visible in the debugger. Those are "bloody mavhelous".

"you're tossing blocks of code at the end of the thread of control over
there for one-off execution."
Excellent way to phrase it. And the emphasis is on "over there" because the
code executes in the context of the destination form.

"execute in form" similar to "execute on client"

"On Outside Call was always documented as being unreliable while CALL FORM
/ CALL WORKER guarantee delivery."
OOC worked well form me, as far as I know (emphasis on the "AFAIK").
I did have to tweak my original code to work in a Repeat loop, as you say,
Call form/Call worker will always get through so there's no need to jump
through hoops (loops) to make sure the message arrived.


"NTK's IPC channels easier" - agreed. I"m using an array-based derivative
of that approach (taken from ITK about 20 years ago) with a change in
2000-01 and that's it. Highly reliable and zero maintenance but it doesn't
allow me to get to a specific form…which is what's needed to get at the *
dialog. Very nice to have multiple active windows in a process but
disappointing that I couldn't get to it with a message.


"You mention that you're doing message routine. This can be pretty darn
impossible to trace or debug if there's nothing in the message about the
path that it has followed."
I only had to chase messages "down a rabbit hole" a few times over the
years. Two ways of reducing the odds of that happening - one of the
properties of a message will allow the message and its metadata to be
displayed added to arrays displayed in a grid. I needed that to debug some
code that had become very involved and the end result is that it helped
force me to rethink my approach.

The other technique that I've used it a bit dated now but was very helpful
before V11, back in the dark ages when "Find in design" was dreadfully
slow. That situation convinced me to use IP vars in the message. From
*MSGIP_Vars_Init*:

C_TEXT(<>MSG_InsertCarriageReturn)
<>MSG_InsertCarriageReturn:="<>MSG_InsertCarriageReturn"

 C_TEXT(<>MSG_ProposalIsLocked)
<>MSG_ProposalIsLocked:="Proposals_is_Locked"

 C_TEXT(<>MSG_BringToFront)
<>MSG_BringToFront:="<>MSG_BringToFront"

C_TEXT(<>MSG_Close)
<>MSG_Close:="<>MSG_Close"

C_TEXT(<>PROC_Activated)
<>PROC_Activated:="<>PROC_Activated"


From On Outside call:
Repeat

C_LONGINT($msgHandle_L)
$msgHandle_L:=MSGIP_Message_Get (Current process)

C_TEXT($msg_T)
$msg_T:=MSGIP_TextMessage_Get ($msgHandle_L;False)

Case of
: ($msg_T=<>MSG_BringToFront)
PROC_ResumeAndBringToFront (Current process)

: ($msg_T=<>MSG_Close)
CANCEL
End case

MSGIP_Message_Clear ($msgHandle_L)

Until (MSGIP_MessageCount_Get (Current process)=0)


To your point about the provenance of the message, another significant
argument for an object without which it would be gruesome to try to add
that sort of data to…a BLOB?! No interest in the level of mental gymnastics…

Time to have a looksee here - http://forums.4d.fr/Post/EN/
19129127/1/19129128


--
Douglas von Roeder
949-336-2902

On Fri, Mar 17, 2017 at 2:18 PM, David Adams via 4D_Tech <
4d_tech@lists.4d.com> wrote:

> > Interesting approach - thank you for posting that.
>
> DvR: You, of all people, will *love* this approach.
>
> > Lacking "callers" and C_Object, I've been using On outside call +
> > ObjectTools + IP messaging based on the ITK message queuing system.
>
> Once you have access to V16, you may find:
>
> * You like C_OBJECT because it's very fast and native. But it won't do
> everything that ObjectTools does.
>
> * You may still want to use IPC channels from NTK. They're traditional
> messages, easily support a wider range of messaging patterns, and can be
> used to-from anywhere.
>
> * CALL FORM/CALL WORKER are great! You'll love them. On Outside Call was
> always documented as being unreliable while CALL FORM / CALL WORKER
> guarantee delivery. (Unless you kill a worker, kill a process, kill 4D, or
> crash. But, hey, that's pretty reasonable for a lot of situations.)
>
> > I'm not sure if this is germane to Call form/worker but I include a
> "reply to ID"
> > in the message that's sent.
>
> Yes, that can be entirely relevant. These 'calls' aren't a channel, you're
> tossing blocks of code at the end of the thread of control over there for
> one-off execution. There is no return message. You can send along callback
> details if, for example, you need a result. There are times when you'll
> find NTK's IPC channels easier. And, yes, message discipline is _super_
> beneficial. You

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread David Adams via 4D_Tech
> Interesting approach - thank you for posting that.

DvR: You, of all people, will *love* this approach.

> Lacking "callers" and C_Object, I've been using On outside call +
> ObjectTools + IP messaging based on the ITK message queuing system.

Once you have access to V16, you may find:

* You like C_OBJECT because it's very fast and native. But it won't do
everything that ObjectTools does.

* You may still want to use IPC channels from NTK. They're traditional
messages, easily support a wider range of messaging patterns, and can be
used to-from anywhere.

* CALL FORM/CALL WORKER are great! You'll love them. On Outside Call was
always documented as being unreliable while CALL FORM / CALL WORKER
guarantee delivery. (Unless you kill a worker, kill a process, kill 4D, or
crash. But, hey, that's pretty reasonable for a lot of situations.)

> I'm not sure if this is germane to Call form/worker but I include a
"reply to ID"
> in the message that's sent.

Yes, that can be entirely relevant. These 'calls' aren't a channel, you're
tossing blocks of code at the end of the thread of control over there for
one-off execution. There is no return message. You can send along callback
details if, for example, you need a result. There are times when you'll
find NTK's IPC channels easier. And, yes, message discipline is _super_
beneficial. You mention that you're doing message routine. This can be
pretty darn impossible to trace or debug if there's nothing in the message
about the path that it has followed.

Tip: I've found it helpful to define a 'recipient' object as a specific
type. This can be the recipient of a CALL FORM/CALL WORKER message or the
callback details when you want a result, error, or confirmation message
returned. By treating this as a custom data type, it's easy to have a
single method for creating recipients and for validating them. "Validating"
matters if you, for example, want to be sure that method names exist and
that window refs are valid.

> My projects are just moving to 15.x now so Call worker/call form are still
> a bit out of reach for me but I'm glad to see that these have been added
to
> the language. They're a natural outgrowth of OOC, Call subform container,
> etc., and we *finally* have a way to communicate with those windows opened
> in the asterisk.

Yeah, you'll love it. Given our existing framework, you'll feel like some
things are missing - so keep NTK around. Also, vote for a native WebSockets
implementation. This would be an *amazingly* great addition to 4D. You
could have a persistent, bi-directional, point-to-point pipe between
processes on one machine or different machines. Game changer.

WebSocket protocol on 4D webserver
http://forums.4d.fr/Post/EN/19129127/1/19129128
**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread David Adams via 4D_Tech
> On Fri, Mar 17, 2017 at 6:22 PM, Justin Carr via 4D_Tech wrote:

> OK, so it's Friday afternoon and I've got a few moments while I sup on a
cold
> bevvy.

Hey J, thanks for chiming in!

> David & I kind of got the fervour about CALL FORM/WORKER at the same
> time and this is one of the things about them that really captured our
> imagination.

I have Justin to thank for getting me to jump to V16. And the idea he
outlines in his post is *very* cool. As Justin points out, it's actually
simpler in the code than it is to explain! If you grasp this idea, you'll
have a pretty high level mastery of how the CALL FORM and CALL WORKER
commands work.

> We are using CALL FORM and CALL WORKER to automate unit testing of our
forms.
> This has been something we've been wanting to do for a very long time but
has
> been impossible or at the very least impractical prior to the
introduction of
> these two commands.

A side note for those following along at home. Eggplant is the name that
comes up at this point amongst people that know about automated testing.
And Justin and his group have looked at Eggplant. For those of you that
don't know already, Eggplant is a long-established GUI testing suite that
works in a novel way. Rather than tap into the APIs for UI widgets on a
specific platform, it compares screenshots. That's a pretty crude summary
as Eggplant is vastly more sophisticated than that - but the basic
technology is to compare screen components (text, images, etc.) with
current screen contents. It's scriptable, flexible and pretty impressive.
It's virtue is that it works like a sort of automated user - one that can
spot when something has changed (an icon is different, the expected text
did not appear, a weird window showed up, a button click does nothing,
etc.) It's virtue is also it's weakness. Namely, that it doesn't get under
the skin. Sometimes what you want to test is not the UI itself, it's the
behaviors that the UI drives. Say you've got a drop-down, an entry area, a
button, and a display variable. You want to test what happens when you
select different items from the dropdown - say a discount rate or a post
code, whatever - and different values in the entry area. The button click
runs a calculation and the result appears in the display area. Perhaps you
could do that with Eggplant, but there are times when it's more involved
and you can't. So, with Justin's approach, you get to pass in instructions
for setting values (the popup and the entry area), clicking things (the
button)...and you are inside of 4D code. Meaning, you can test the outcome.
The outcome might be how a variable is set, what selection of records is
found, etc.

Now, if all of your code were structured as perfect little headless APIs
that you could write headless test code for then, well, then you probably
wouldn't be on this list. Who has massive code bases going back to the
1980s and 1990s? I'm seeing a lot of people raising their hands;-) Between
Justin's solution and Eggplant, there's not a lot of GUI-driven testing
that you can't do. I know that formal testing is (understandably) not of
great interest to many one-person development organizations, but it is a
very big deal to larger organizations, particularly ones that face
regulatory scrutiny of any kind.

Note: Someone from Pelican Engineering did an automated testing some years
back at a 4D Summit that included discussion of Eggplant. It was a very
well-received event. Sorry, I don't remember the year or other details.

> There is very little cost to setting it up if you implement your form and
> object methods as separate project methods, and if you use meaningful
names
> for the objects on the form.

Both really good points. To take advantage of CALL FORM, you're much better
off having form methods and objects that call a global method or methods. I
started 1+ thread(s) on this subject in the past couple of months for this
very reason. Meaningful object names are a good call for this sort of
system. Instead of passing pointers, you pass object names and derive
pointers on the recipient side.

> The beauty of this system is that the forms and their associated methods
are
> driven completely externally, so they need to have absolutely no extra
logic
> built in to handle the messaging. Furthermore, the control methods for
driving
> it are completely generic. The only thing that needs any knowledge of the
form
> interactions is the method that's describing the unit tests.

It's a real thing of beauty to behold. There's no special test mode that
you have to add to your code. Your code stays the same! You just now have
the scriptable tool to provoke the items on the form. So nice. It's a bit
hard to grasp exactly how easy and cool this is until you see it. But it
really is easy and cool. Well, "easy" once Justin figures it all out in
about an hour ;-)

> We have a small number of message types that can be sent to the form
> It sounds complicated, trying to write it all out, but th

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread Douglas von Roeder via 4D_Tech
Justin:

Interesting approach - thank you for posting that.

Lacking "callers" and C_Object, I've been using On outside call +
ObjectTools + IP messaging based on the ITK message queuing system. I'm not
sure if this is germane to Call form/worker but I include a "reply to ID"
in the message that's sent. Most of the time, if the called code needs to
reply, the reply is directed to the calling process but there are times
when I've wanted the called code to pass the result to another process.


My projects are just moving to 15.x now so Call worker/call form are still
a bit out of reach for me but I'm glad to see that these have been added to
the language. They're a natural outgrowth of OOC, Call subform container,
etc., and we *finally* have a way to communicate with those windows opened
in the asterisk.



--
Douglas von Roeder
949-336-2902

On Fri, Mar 17, 2017 at 12:22 AM, Justin Carr via 4D_Tech <
4d_tech@lists.4d.com> wrote:

> OK, so it's Friday afternoon and I've got a few moments while I sup on a
> cold bevvy. David & I kind of got the fervour about CALL FORM/WORKER at the
> same time and this is one of the things about them that really captured our
> imagination.
>
> We are using CALL FORM and CALL WORKER to automate unit testing of our
> forms. This has been something we've been wanting to do for a very long
> time but has been impossible or at the very least impractical prior to the
> introduction of these two commands.
>
> There is very little cost to setting it up if you implement your form and
> object methods as separate project methods, and if you use meaningful names
> for the objects on the form.
>
> The beauty of this system is that the forms and their associated methods
> are driven completely externally, so they need to have absolutely no extra
> logic built in to handle the messaging. Furthermore, the control methods
> for driving it are completely generic. The only thing that needs any
> knowledge of the form interactions is the method that's describing the unit
> tests.
>
> We have a small number of message types that can be sent to the form.
> These are things like:
>  - set a value (could apply to any object on the form, e.g. field, button,
> checkbox, listbox, etc.)
>  - delay for a number of ticks
>  - trigger a form or object event
>
> These messages are created as C_OBJECTs, e.g. we have a method
> UT_UIMessageSetTextValue. This takes an object name and a text value as
> parameters and returns a C_OBJECT representing that message. We have
> methods to set different data types, trigger a form or object event, delay,
> etc. We can then create a queue of these messages and send them to a worker
> process for delivery to the form (window). We have a generic method to do
> all of this, which takes one or more of the C_OBJECT messages, creates
> another C_OBJECT containing the current process number and an OBJECT ARRAY
> of the supplied messages, and then passes that object (using CALL WORKER)
> to a worker process.
>
> So a simple example of driving a wrapper for the Request dialog might look
> like this:
>
>
> $vT_ExpectedResult:="Some Value"
> UT_UIMessageQueue(\
> UT_UIMessageSetTextValue ("Response_Fld";$vT_ExpectedResult);\
> UT_UIMessageDelay (30);\
> UT_UIMessageSetLongintValue ("OK_Btn";1);\
> UT_UIMessageTriggerEvent ("DLG_RequestFM";On Clicked))
>
> $vT_ActualResult:=WRAP_Request ("Enter a value")
>
> ASSERT($vT_ActualResult=$vT_ExpectedResult;"Unexpected response")
>
>
> The worker process determines the correct window reference (the frontmost
> window for the process contained in the C_OBJECT it receives), waits for
> that window to load, and iterates through the queue of C_OBJECTS. If it's a
> delay message, the delay is actually performed in the worker. If it's an
> event, the form or object's project method is called using CALL FORM,
> passing the event to be triggered. Otherwise the message is sent to a
> "broker" method using CALL FORM which sets the requested object value.
>
> It sounds complicated, trying to write it all out, but the framework is
> actually beautifully simple. It just consists of a handful generic methods,
> none of which extends to more than about 40 lines of code:
>
> - UT_UIMessageSetValue
> - UT_UIMessageDelay
> - UT_UIMessageTriggerEvent
> - UT_UIMessageQueue
> - UT_UIWorker
> - UT_UIBroker
>
> And strictly speaking the delay capability is probably not necessary, but
> it's kinda cool watching the form objects update as if by magic in front of
> your eyes.
>
> Oh and +1 for the proposed command name changes - definitely clarifies the
> functions of these two commands.
>
> Regards
> Justin Carr
> Genie Solutions
> **
> 4D Internet Users Group (4D iNUG)
> FAQ:  http://lists.4d.com/faqnug.html
> Archive:  http://lists.4d.com/archives.html
> Options: http://lists.4d.com/mailman/options/4d_tech
> Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
> 

Re: 4D Server - Not letting go of users

2017-03-17 Thread Dave Nasralla via 4D_Tech
I'm on version 15.4 and am seeing what I call "ghost sessions". It's a
logon where you see in the users section of the server admin where the
4D username is blank. It's the kind of thing you see where someone has
called up the logon screen, but has not logged in.

I'll see other entries where the same machine name and ip address
where the user actually is logged on. These ghost users can not be
dropped and do take up a license. This is also the network layer.

Anyone else see this on occasion?

dave

On Thu, Mar 16, 2017 at 1:32 PM, Randy Engle via 4D_Tech
<4d_tech@lists.4d.com> wrote:
> Hi Lahav,
>
> Thanks for the note.
> I'm pretty sure we are using the legacy network layer
> But I'll check.
>
> Thanks
>
> Randy Engle
> XC2 Software LLC
>
>
> -Original Message-
> From: 4D_Tech [mailto:4d_tech-boun...@lists.4d.com] On Behalf Of lists via 
> 4D_Tech
> Sent: Thursday, March 16, 2017 12:30 PM
> To: Randy Engle via 4D_Tech <4d_tech@lists.4d.com>
> Cc: lists 
> Subject: RE: 4D Server - Not letting go of users
>
> Hi Randy,
>
> I see this quite a bit, and it has something to do with the new network 
> layer.  I have reported it to tech support, but never really saw the issues 
> resolved.
>
> The problem goes away if I use the legacy network layer.
>
> Cheers,
>
> Lahav
>
>
>
> **
> 4D Internet Users Group (4D iNUG)
> FAQ:  http://lists.4d.com/faqnug.html
> Archive:  http://lists.4d.com/archives.html
> Options: http://lists.4d.com/mailman/options/4d_tech
> Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
> **



-- 
David Nasralla
Clean Air Engineering
**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread Jeremy French via 4D_Tech
Hi David,

Yes, you need to log in.

Notes are only available at livedoc.4d.com . (There is 
NO note feature at doc.4d.com .) 

The login link is at the top right of the web page.

https://s8.postimg.org/oylrfbtsl/p01_comment_log_in.png

Scroll down to the “Previous Page” and “Next Page” buttons, and click “Add 
Comment”.

https://s15.postimg.org/e0nqetxt7/p2_add_comment_button.png 


A “window” opens in which to write the comment.

https://s21.postimg.org/k4j2wzss7/p03_add_a_comment.png


Jeremy French


> On Mar 16, 2017, at 10:28 PM, David Adams via 4D_Tech <4d_tech@lists.4d.com> 
> wrote:
> 
> I was going to add some comments to the docs, but I just looked and don't see 
> how you do it.
> Presumably there's something you need to log into first (?) Instructions 
> appreciated.

**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**

Re: CALL FORM: Some notes on a command that's easy to misunderstand

2017-03-17 Thread Justin Carr via 4D_Tech
OK, so it's Friday afternoon and I've got a few moments while I sup on a cold 
bevvy. David & I kind of got the fervour about CALL FORM/WORKER at the same 
time and this is one of the things about them that really captured our 
imagination.

We are using CALL FORM and CALL WORKER to automate unit testing of our forms. 
This has been something we've been wanting to do for a very long time but has 
been impossible or at the very least impractical prior to the introduction of 
these two commands.

There is very little cost to setting it up if you implement your form and 
object methods as separate project methods, and if you use meaningful names for 
the objects on the form.

The beauty of this system is that the forms and their associated methods are 
driven completely externally, so they need to have absolutely no extra logic 
built in to handle the messaging. Furthermore, the control methods for driving 
it are completely generic. The only thing that needs any knowledge of the form 
interactions is the method that's describing the unit tests.

We have a small number of message types that can be sent to the form. These are 
things like:
 - set a value (could apply to any object on the form, e.g. field, button, 
checkbox, listbox, etc.)
 - delay for a number of ticks
 - trigger a form or object event

These messages are created as C_OBJECTs, e.g. we have a method 
UT_UIMessageSetTextValue. This takes an object name and a text value as 
parameters and returns a C_OBJECT representing that message. We have methods to 
set different data types, trigger a form or object event, delay, etc. We can 
then create a queue of these messages and send them to a worker process for 
delivery to the form (window). We have a generic method to do all of this, 
which takes one or more of the C_OBJECT messages, creates another C_OBJECT 
containing the current process number and an OBJECT ARRAY of the supplied 
messages, and then passes that object (using CALL WORKER) to a worker process.

So a simple example of driving a wrapper for the Request dialog might look like 
this:


$vT_ExpectedResult:="Some Value"
UT_UIMessageQueue(\
UT_UIMessageSetTextValue ("Response_Fld";$vT_ExpectedResult);\
UT_UIMessageDelay (30);\
UT_UIMessageSetLongintValue ("OK_Btn";1);\
UT_UIMessageTriggerEvent ("DLG_RequestFM";On Clicked))
  
$vT_ActualResult:=WRAP_Request ("Enter a value")

ASSERT($vT_ActualResult=$vT_ExpectedResult;"Unexpected response")


The worker process determines the correct window reference (the frontmost 
window for the process contained in the C_OBJECT it receives), waits for that 
window to load, and iterates through the queue of C_OBJECTS. If it's a delay 
message, the delay is actually performed in the worker. If it's an event, the 
form or object's project method is called using CALL FORM, passing the event to 
be triggered. Otherwise the message is sent to a "broker" method using CALL 
FORM which sets the requested object value.

It sounds complicated, trying to write it all out, but the framework is 
actually beautifully simple. It just consists of a handful generic methods, 
none of which extends to more than about 40 lines of code:

- UT_UIMessageSetValue
- UT_UIMessageDelay
- UT_UIMessageTriggerEvent
- UT_UIMessageQueue
- UT_UIWorker
- UT_UIBroker

And strictly speaking the delay capability is probably not necessary, but it's 
kinda cool watching the form objects update as if by magic in front of your 
eyes.

Oh and +1 for the proposed command name changes - definitely clarifies the 
functions of these two commands.

Regards
Justin Carr
Genie Solutions
**
4D Internet Users Group (4D iNUG)
FAQ:  http://lists.4d.com/faqnug.html
Archive:  http://lists.4d.com/archives.html
Options: http://lists.4d.com/mailman/options/4d_tech
Unsub:  mailto:4d_tech-unsubscr...@lists.4d.com
**