APPLY in a PERISTENT RUN trigger?

jkuhns

New Member
10.1C Windows. I've created a dynamic browse thus:

Code:
    CREATE BROWSE hBrowse 
        ASSIGN
        FRAME = hFrame
        FONT = 8
        ROW-MARKERS = FALSE
        MULTIPLE = TRUE
        QUERY = hQuery
        NAME = ttName
        TITLE = IF cTitle = "" OR cTitle = ? THEN ? ELSE cTitle
        X = 0
        Y = 0
        WIDTH-PIXELS = hFrame:WIDTH-PIXELS - hFrame:BORDER-LEFT-PIXELS - hFrame:BORDER-RIGHT-PIXELS 
        HEIGHT-PIXELS = hFrame:HEIGHT-PIXELS - hFrame:BORDER-TOP-PIXELS - hFrame:BORDER-BOTTOM-PIXELS 
        VISIBLE = TRUE
        READ-ONLY = ro
        SENSITIVE = YES
        SEPARATORS = TRUE
        ALLOW-COLUMN-SEARCHING = TRUE
        COLUMN-RESIZABLE = TRUE
 
        TRIGGERS:
        ON 'MOUSE-SELECT-DBLCLICK' 
            PERSISTENT RUN rowDblClick IN THIS-PROCEDURE.
        END.
       .

I then created the rowDblClick procedure:

Code:
    PROCEDURE rowDblClick :
        DEF VAR hFrame AS HANDLE NO-UNDO.
        hFrame = SELF:FRAME.
        m_hBrws = SELF.
        APPLY "MOUSE-SELECT-DBLCLICK" TO hFrame.
    END PROCEDURE.

The browse works just fine, the rowDblClick proc gets called and a message of hFrame:name gives expected results. However, the event doesn't get fired. Is this a bug or is there an explanation for this? I've tried many permutations, no luck. Is there some work around, possible involving a CREATE CALL?
 

RealHeavyDude

Well-Known Member
If I were you I would input the necessary handles to the persistent trigger procedure:

TRIGGERS:
ON 'MOUSE-SELECT-DBLCLICK'
PERSISTENT RUN rowDblClick IN THIS-PROCEDURE ( INPUT hBrowse, INPUT hFrame ).
END.

And probably you should apply the double-click event to the browse instead of the frame.

HTH, RealHeavyDude.
 

Cringer

ProgressTalk.com Moderator
Staff member
And probably you should apply the double-click event to the browse instead of the frame.

I though that, but the procedure is called from the double click event of the browse. So that would result in a cyclic call. For me the question is, what is the OP trying to achieve?
 

RealHeavyDude

Well-Known Member
Cringer you are right!
  1. The message box with the frame name appearing is proof that the trigger on the browse fires.
  2. What should be achieved by applying the MOUSE-SELECT-DBLCLICK event to the frame?
  3. Is there a MOUSE-SELECT-DBLCLICK event trigger defined for the frame?
Regards, RealHeavyDude.
 

jkuhns

New Member
The idea was to make some reusable code in an include. Throw a frame on a form and call a proc to create the browse dynamically. All works just fine, but I'd like to establish an easy mechanism to get notified of most or all events from the browse back to the window, preferably through applying corresponding events to the frame itself.

I can write separate procs in the window and have them called dynamically from the include and fail gracefully if they're not coded, but this is a little kludgy/awkward. Yes, I did have a MOUSE-SELECT-DBLCLICK event trigger defined for the frame, and no, firing the event on the frame should not cause a cyclic call, unless somehow a dynamic widget is lower in the event notification chain than its parent, which I would grudgingly accept as an answer for what is in my opinion unexpected behavior.
 

Cringer

ProgressTalk.com Moderator
Staff member
The reference to the cyclic call was to RHD not to you - I wouldn't expect your code to get stuck!

So if I understand you correctly, you're trying to code a generic piece of code that will allow you to handle the same event differently in different pieces of code?

If that's the case then why not just define the dynamic trigger:

Code:
TRIGGERS:
ON 'MOUSE-SELECT-DBLCLICK' 
  RUN rowDblClick IN THIS-PROCEDURE (INPUT SELF:HANDLE) NO-ERROR.
END.
and then the individual screen can define those procedures if they're required and handle the event?

I've not tested that this works at all - it's just a thought.
 

RealHeavyDude

Well-Known Member
Another idea:
  • On the widgets (the dynamic browse for example) your could define dynamic triggers that do their stuff - including publishing a generic event to which the window is subscribed. Part of the published event would be the type of event and a handle to the origin object.
  • In the parent procedure you could subscribe to that generic event and have a response procedure. Still this response procedure would need to branch on the type of event and probably the type of widget it came from.
Just an idea utilizing publish/subscribe.

HTH, RealHeavyDude.
 

jkuhns

New Member
Thank you both for your suggestions. I just discovered that the developer events (U1-U10) can be applied in my code, so I'll be using them for what I need. Another interesting note, and this is a little weirder. Since I was digging/playing with this, I tried defining a trigger for ROW-DISPLAY for my frame by typing that trigger name, it doesn't complain. Further, I can use that bogus trigger in my code. It seems that I can fire any valid Progress event on the frame widget except for named events explicitly defined for the frame widget.
 

jkuhns

New Member
I really appreciate the insights so far, I hope I'm not pushing it with this post.


I'm on to working with the developer events. I've got one browse that I want to toggle a field in all the rows if:
  • the chosen column is a logical
  • the chosen column is editable
  • the click is on the column header
I chose to do this on a double click, since I also allow sorting. In my Frame's U3 event, I am using the following code. The only mysterious var is m_hBrws, which is set to SELF (the browse handle) in my rowDblClick procedure in the .i file prior to calling APPLY U3 TO SELF:FRAME.
Code:
DO:
 
    DEF VAR hCol AS HANDLE NO-UNDO.
    DEF VAR hQry AS HANDLE NO-UNDO.
    DEF VAR hFld AS HANDLE NO-UNDO.
    DEF VAR bVal AS LOGICAL NO-UNDO.
    IF NOT VALID-HANDLE(m_hBrws) THEN
        RETURN NO-APPLY.
    hCol = m_hBrws:CURRENT-COLUMN.
    IF LAST-EVENT:Y < m_hBrws:ROW-HEIGHT-PIXELS AND 
      hCol:DATA-TYPE = "LOGICAL" AND NOT hCol:COLUMN-READ-ONLY THEN DO:
        hQry = m_hBrws:QUERY.
        hQry:GET-FIRST.
        IF NOT hQry:QUERY-OFF-END THEN DO:
            ASSIGN hFld = hCol:BUFFER-FIELD
                bVal = NOT hFld:BUFFER-VALUE.
            REPEAT:
                IF hQry:QUERY-OFF-END THEN
                    LEAVE.
                hFld:BUFFER-VALUE = bVal.
                hQry:GET-NEXT.
            END.
        END.
        m_hBrws:REFRESH().
    END.
 
END.

Is this best-practice or even close to being efficient/correct? It works just fine, but I'm a newbie to working with the browse and want to make sure I understand it well and that I'm not violating any coding practices. The documentation is kind of light on dynamic browses and queries.

Thanks in advance!
 
Top