Alaska Software Inc. - Re: Popup menu in xbpbrowse()
Username: Password:
AuthorTopic: Re: Popup menu in xbpbrowse()
Itai Ben-ArtziPopup menu in xbpbrowse()
on Wed, 31 Jan 2024 10:17:06 -0800
I've set a right-click popup menu in XbpBrowse() which is working well
via the following codeblock:
oBrowse:itemRbDown := {| aMousePos, aRowCol, self | oMenu1:PopUp
(self, aMousePos, , XBPMENU_PU_DEFAULT+XBPMENU_PU_MOUSE_RBDOWN ) }

I'd like to invoke this menu programmatically via: PostAppEvent(
xbeBRW_ItemRbDown, { nRow, 1 }, nil, @oBrowse ).
But that line causes the software to crash.  What am I doing wrong? Is
there a way to programmatically popup a menu just like the
right-click?

Many thanks,
-Itai
Andreas Gehrs-Pahl
Re: Popup menu in xbpbrowse()
on Wed, 31 Jan 2024 22:52:14 -0500
Itai,

>Is there a way to programmatically popup a menu just like the right-click?

Why not call it directly?

   oMenu1:PopUp(oBrowse, aMousePos)

If you want to use PostAppEvent(), try this:

   PostAppEvent(xbeBRW_ItemRbDown, aMousePos, aRowCol, oBrowse)

Where aMousePos is the current mouse position with respect to the lower 
left corner of the oBrowse object, and aRowCol is a two-element array 
{oBrowse:RowPos, oBrowse:ColPos}, which indicates the row and column 
position of the cell that was clicked.

If aRowCol is NIL, as in your example, you will get a runtime error.

How you calculate aMousePos, where the Menu is actually displayed, is 
another issue, though.

Hope that helps.

Andreas

Andreas Gehrs-Pahl
Absolute Software, LLC

phone: (989) 723-9927
email: Andreas@AbsoluteSoftwareLLC.com
web:   http://www.AbsoluteSoftwareLLC.com
[L]:   https://www.LinkedIn.com/in/AndreasGehrsPahl
[F]:   https://www.FaceBook.com/AbsoluteSoftwareLLC
Itai Ben-ArtziRe: Popup menu in xbpbrowse()
on Fri, 09 Feb 2024 00:26:57 -0800
Thank you, Andreas.
I'd like to activate a customize popup menu with a left click (to
replace the current right-click that works well).
Here is the click callback from the XbpBrowse:
oBrowse:GetColumn(1):dataArea:lbDown := {|aPos, uNIL, self |
ShowItemMenu(@oBrowse, @aArray, @oMenu, @aMenu, aPos, self) }   
Single click column 1 

**************************************************
Static Procedure ShowItemMenu(oBrowse, aArray, oMenu, aMenu,
aPosition, oCell)
Local nRow := oCell:cellFromPos(aPosition)   get the clicked row
PostAppEvent( xbeBRW_ItemMarked, { nRow, 1 }, nil, @oBrowse )  Move
the highlight to the selected row and col
oBrowse:forceStable()
SetMyRegisterMenu( @oMenu, @aMenu, @aArray[oBrowse:cargo], @oBrowse)
 set a context menu for the selected line

 oMenu:PopUp(oBrowse, aPosition)   this line crashes the app

PostAppEvent(xbeBRW_ItemRbDown, aPosition, {nRow,1}, oBrowse)   This
line also crashes the app at ADJUSTPOS(4741).
Return
**********

Can you help?
Thanks,
Itai
Andreas Gehrs-Pahl
Re: Popup menu in xbpbrowse()
on Fri, 09 Feb 2024 20:03:00 -0500
Itai,

Thanks for the additional details.

I'm not sure why you use the reference operator "@" in so many places of 
your code. Are you replacing the values of the oBrowse, aArray, oMenu, and 
aMenu variables in the ShowItemMenu() and SetMyRegisterMenu() routines? If 
you don't, do not use the reference operator "@" for those variables. 
Otherwise, this could have unforeseen side effects, if you are assigning 
anything to those variables in your sub-routines.

In the PostAppEvent() calls, oBrowse should definitely not be @oBrowse!

Based on example code that you posted earlier, it seems like you create and 
destroy the menu in the SetMyRegisterMenu() routine, which might be the 
reason why you use reference operators "@", even though that wouldn't be 
necessary even in that case. But it is much better to just remove any 
existing menu items, before adding the required ones, instead of destroying 
the menu and then creating it again!

You write: 
>Here is the click callback from the XbpBrowse
>oBrowse:GetColumn(1):dataArea:lbDown := {|aPos, uNIL, self |
> ShowItemMenu(@oBrowse, @aArray, @oMenu, @aMenu, aPos, self)}

This code creates a callback for the DataArea of the 1st XbpColumn of the 
XbpBrowse, which is actually a XbpCellGroup() object. That's why the last 
parameter in the ShowItemMenu() function, self, is also named oCell in your 
code further down.

Just so that we are clear, your code implements this callback (for a left 
mouse button click) only for the data area of the first column of your 
browse, not the browse itself or any other column or any of the header or 
footer areas of any of the columns.

I'm also not sure why the following line would crash:

>oMenu:PopUp(oBrowse, aPosition)   this line crashes the app

The actual error message you are getting might help to clarify the issue!

Also, you use PostAppEvent() to move the highlight in the browse (which is 
done asynchronosly, so in fact much later), then you do the :ForceStable(), 
which is done right away, and then you create or update the Menu, and 
finally you use PostAppEvent() to (later) pop up the menu.

After your routine ends, the events (xbeBRW_ItemMarked & xbeBRW_ItemRbDown) 
are finally evaluated in the oBrowse:HandleEvent() routine (asynchronosly).

I would suggest that you do the :ForceStable() asynchronosly, too, using:

   PostAppEvent(xbeBRW_ForceStable, NIL, NIL, oBrowse)

And finally, this error makes some sense now:

>PostAppEvent(xbeBRW_ItemRbDown, aPosition, {nRow,1}, oBrowse)   This
>line also crashes the app at ADJUSTPOS(4741).

The reason for the crash is that the documentation doesn't completely 
reflect the way that this event is processed by the XbpBrowse class.

The actual parameters mp1 and mp2 that the XbpBrowse:ItemRbDown(), as well 
as the :HeaderRbDown() and :FooterRbDown() methods require are not the same 
that will be given to the Code blocks in the corresponding callback slots.

Those three methods expect mp1 to be aPos (the Mouse Position array), but 
mp2 is supposed to be an array of two different values: {oCol, nRow}. This 
array is used by those three methods to calculate and update the Mouse 
position in aPos, before evaluating the corresponding callback. Normally, 
those events are created by the corresponding XbpColumn routines, which 
correctly post those two parameters.

But the point is, you don't need to do any of these, as the call back is on 
the Left Mouse Button Down event (oBrowse:GetColumn(1):DataArea:LbDown), so 
the Item Marked event and the navigation is done automatically.

So, something like this should work:

oBrowse:GetColumn(1):DataArea:LbDown := {|aPos, uNIL, Self |
   ShowItemMenu(oBrowse, aArray, oMenu, aMenu, aPos, Self)}

And either calling oMenu:Popup directly:

Static Procedure ShowItemMenu(oBrowse, aArray, oMenu, aMenu, aPos, oCell)
   SetMyRegisterMenu(oMenu, aMenu, aArray[oBrowse:Cargo], oBrowse)

   oMenu:PopUp(oBrowse, aPos)
return

Or calling it indirectly (assuming that there is a callback slot for right 
clicking on the browser data area exists):

Static Procedure ShowItemMenu(oBrowse, aArray, oMenu, aMenu, aPos, oCell)
LOCAL nRow := oCell:CellFromPos(aPos)
LOCAL oCol := oBrowse:GetColumn(1)
   SetMyRegisterMenu(oMenu, aMenu, aArray[oBrowse:Cargo], oBrowse)

   PostAppEvent(xbeBRW_ItemMarked, {nRow, 1}, NIL, oBrowse)
   PostAppEvent(xbeBRW_ForceStable, NIL, NIL, oBrowse)
   PostAppEvent(xbeBRW_ItemRbDown, aPos, {oCol, nRow}, oBrowse)
return

If it still doesn't work, check what your SetMyRegisterMenu() procedure 
does.

None of this code has been tested, but I hope that this explains some of the 
problems in your code. For complex issues like this, it always helps to post 
an actual working program, though.

Andreas

Andreas Gehrs-Pahl
Absolute Software, LLC

phone: (989) 723-9927
email: Andreas@AbsoluteSoftwareLLC.com
web:   http://www.AbsoluteSoftwareLLC.com
[L]:   https://www.LinkedIn.com/in/AndreasGehrsPahl
[F]:   https://www.FaceBook.com/AbsoluteSoftwareLLC
Itai Ben-ArtziRe: Popup menu in xbpbrowse()
on Mon, 12 Feb 2024 12:24:05 -0800
Many many thanks, Andreas!
Seems I've overworked the browser because I've forgot that the
left-click already moves the cursor to the clicked line.  The simple
two lines you suggested fixed the problem and simplify the code. Thank
you!

For clarity:
I set the context sensitive menu by deleting all menu items and adding
the ones pertaining to the selected line (I do not destroy and
create).

Because users complained that the right-click is hidden and they do
not know it exist, I've added a menu-symbol (three dots) to the first
column so a user can access the pop-up menu with a simple (left)
click.
Also, the concept of right-click is somewhat foreign to users only
familiar with cell-phone, but they are familiar with the menu-symbol
at the right column.
Therefor, I am now adding the menu-symbol to all browsers that include
the right-click pop-up menu.

Again, many thanks for explaining this issue so well.

-Itai