Author | Topic: Popup menu in xbpbrowse() | |
---|---|---|
Itai Ben-Artzi | Popup 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-Artzi | Re: 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-Artzi | Re: 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 |