Page 1 of 1

[Solved] Calc Listener: MouseClickHandler, Position Cell X Y

Posted: Thu Jan 01, 2015 8:42 pm
by Kiel
[Calc] Listener: MouseClickHandler, Position Cell X and Y relactive a Rectangle, and PopupMenu

I will like to achieve in the end:
Click the cell “B6” and display the “PopupMenu” below.

Problem found:
The first image file attached in "Plan1.png" the “PopupMenu” appears just below the button. However, moving the active cell further down or rolling down the spreadsheet by clicking on the cell “B6” does not follow that, as seen in the second image.

Question:
How do I make pop-up menu and follow the button always appears below it?

Re: [Calc] Listener: MouseClickHandler, Position Cell X and

Posted: Thu Jan 01, 2015 11:43 pm
by Zizi64

Code: Select all

Function ShowPopup
      
    oPopup = CreateUnoService("com.sun.star.awt.PopupMenu")
    oPopup.insertItem(1, "Option 1                             ", 0, 0)
    oPopup.insertItem(2, "Option 2                             ", 0, 1)
    oPopup.insertItem(3, "Option 3                             ", 0, 2)
  
    Dim aRect As New com.sun.star.awt.Rectangle 
    With aRect 
      .X      = 130 ' ------------------------> ?
      .Y      = 199 ' ------------------------> ?
      .Width  = 0   ' ------------------------> ?
      .Height = 0   ' ------------------------> ?
    End With 
The X, and Y coordinates have relative values to the "origo" of the aplication window, but not relative to the associated Cell.

Maybe this thread will help you:

viewtopic.php?f=9&t=34544

(You can try anchor the "option rectangle" to a cell... I do not know if it is possible.)

Re: [Calc] Listener: MouseClickHandler, Position Cell X and

Posted: Thu Jan 01, 2015 11:47 pm
by RoryOF
There is some code in this issue listing which might be of help
https://issues.apache.org/ooo/show_bug. ... e&id=76767

Re: [Calc] Listener: MouseClickHandler, Position Cell X and

Posted: Fri Jan 02, 2015 5:02 am
by hanya
I need to change the following functions:

Code: Select all

Sub Selection_Changed(event)
   
   Dim oCtrlWindow
   oCtrlWindow = ThisComponent.CurrentController.Frame.ContainerWindow
   oCtrlWindow.Enable=False
   If event.supportsservice("com.sun.star.sheet.SheetCell") Then
        aAddr = event.getCellAddress()
        sCell = event.AbsoluteName
        If sCell = "$Plan1.$B$6" Then
            async(Array("Plan1", aAddr.Row, aAddr.Column))
        EndIf
    EndIf
   oCtrlWindow.Enable=True
End Sub

Function ShowPopup(aData)
    
    oPopup = CreateUnoService("com.sun.star.awt.PopupMenu")
    oPopup.insertItem(1, "Option 1                             ", 0, 0)
    oPopup.insertItem(2, "Option 2                             ", 0, 1)
    oPopup.insertItem(3, "Option 3                             ", 0, 2)
    
    aBounds = GetCellBounds(aData(0), aData(1), aData(2))
    If IsNull(aBounds) Then Exit Function
    
    nFormulaBarHeight = GetFormulaBarHeight(ThisComponent)
    oColumnRowHeaderSize = GetColumnRowHeaderSize(ThisComponent)
    Dim aRect As New com.sun.star.awt.Rectangle 
    With aRect 
      .X      = aBounds.X + oColumnRowHeaderSize.Width + 1
      .Y      = aBounds.Y + aBounds.Height + nFormulaBarHeight + oColumnRowHeaderSize.Height + 1
      .Width  = 0   ' ------------------------> ?
      .Height = 0   ' ------------------------> ?
    End With 
    
    oCompWin = ThisComponent.getCurrentController().getFrame().getComponentWindow()     
    n = oPopup.execute(oCompWin, aRect, 0)
    
    If n > 0 Then
       Ctrl = ThisComponent.CurrentController
       oSheet = ThisComponent.Sheets.getByIndex(n-1)
       Ctrl.setActiveSheet(oSheet)
    Else ' clicou fora do menu
       ThisComponent.CurrentController.Select(oSelect):
       oEmpty = ThisComponent.CreateInstance("com.sun.star.sheet.SheetCellRanges"):
       ThisComponent.CurrentController.Select(oEmpty):
    End If
End Function

Type Size
  Width As Long
  Height As Long
End Type

Function GetColumnRowHeaderSize(oDoc As Variant) As Variant
  oRet = CreateObject("Size")
  If oDoc.getCurrentController().HasColumnRowHeaders Then
    oAccCtx = oDoc.getCurrentController().getFrame().getComponentWindow().getAccessibleContext()
    oScrollPaneAcc = FindChildByRole(oAccCtx, com.sun.star.accessibility.AccessibleRole.SCROLL_PANE)
    If not IsNull(oScrollPaneAcc) then
      aPanels = FindSimplePanels(oScrollPaneAcc.getAccessibleContext())
      CalculateSize(aPanels, oRet)
    End If
  End If
  GetColumnRowHeaderSize = oRet
End Function


Function CalculateSize(aChildren As Variant, oRet As Variant) As Variant
  aWidth = Array(0, 0, 0)
  aHeight = Array(0, 0, 0)
  For i = 0 to 2 step 1
    aSize = aChildren(i).getPosSize()
    aWidth(i) = aSize.Width
    aHeight(i) = aSize.Height
  Next
 
  For i = 0 to 2 step 1
    bWidthMatch = False
    bHeightMatch = False
    nWidth = aWidth(i)
    nHeight = aHeight(i)
    For j = 0 to 2 step 1
      If i <> j then
        If aWidth(j) = nWidth then bWidthMatch = True
        If aHeight(j) = nHeight then bHeightMatch = True
      end if
    next
    If bWidthMatch AND bHeightMatch then
      oRet.Width = nWidth
      oRet.Height = nHeight
      Exit For
    End If
  next
  CalculateSize = oRet
End Function


Function FindSimplePanels(oCtx As Variant) As Variant
  aRet = Array(NULL, NULL, NULL)
  nRole = com.sun.star.accessibility.AccessibleRole.PANEL
  n = 0
  m = oCtx.getAccessibleChildCount()
  for i = 0 to oCtx.getAccessibleChildCount() -1 step 1
    oChild = oCtx.getAccessibleChild(i)
    If NOT HasUnoInterfaces(oChild, "com.sun.star.accessibility.XAccessibleComponent") Then
      oChildCtx = oChild.getAccessibleContext()
      If oChildCtx.getAccessibleRole() = nRole then
        aRet(n) = oChild
        n = n + 1
        if n > 2 then Exit For
      End If
    End If
  next
  FindSimplePanels = aRet
End Function


Function GetFormulaBarHeight(oDoc As Variant) As Long
  nHeight = 0
  oAccCtx = oDoc.getCurrentController().getFrame().getComponentWindow().getAccessibleContext()
  oFormulaBarAcc = FindChildByRole(oAccCtx, com.sun.star.accessibility.AccessibleRole.TOOL_BAR)
  If not IsNull(oFormulaBarAcc) Then
    If oFormulaBarAcc.isVisible() = True then nHeight = oFormulaBarAcc.getSize().Height
  End If
  GetFormulaBarHeight = nHeight
End Function


Function GetCellBounds(sSheetName As String, nRow As Long, nColumn As Long) As Variant
  oResult = Null
  oAccCtx = ThisComponent.getCurrentController().getFrame().getComponentWindow().getAccessibleContext()
  oDocumentPanelAcc = FindChildByRole(oAccCtx, com.sun.star.accessibility.AccessibleRole.SCROLL_PANE)
  If not IsNull(oDocumentPanelAcc) Then
    oDocumentAcc = FindChildByRole(oDocumentPanelAcc.getAccessibleContext(), com.sun.star.accessibility.AccessibleRole.DOCUMENT)
    oFound = Null
    For i = 0 to oDocumentAcc.getAccessibleChildCount() -1 step 1
      oAccChild = oDocumentAcc.getAccessibleChild(i)
      If oAccChild.getAccessibleRole() = com.sun.star.accessibility.AccessibleRole.TABLE Then
        If Right(oAccChild.getAccessibleName(), Len(sSheetName)) = sSheetName Then
          oFound = oAccChild
          Exit For
        End If
      End If
    next
    If NOT IsNull(oFound) Then
      oCellAcc = oAccChild.getAccessibleCellAt(nRow, nColumn)
      oResult = oCellAcc.getBounds()
    End If
  End If
  GetCellBounds = oResult
End Function


Function FindChildByRole(oCtx As Variant, nRole As Integer) As Variant
  oFound = NULL
  For i = 0 to oCtx.getAccessibleChildCount() - 1 step 1
    oChild = oCtx.getAccessibleChild(i)
    oChildCtx = oChild.getAccessibleContext()
    If oChildCtx.getAccessibleRole() = nRole then
      oFound = oChild
      exit for
    End If
  next
  FindChildByRole = oFound
End Function


Sub Callback_notify( aData )
   If oActiveMenu = Empyt or oActiveMenu = True Then 
      ShowPopup(aData)
      oActiveMenu = False
   EndIf
End Sub

Re: [Calc] Listener: MouseClickHandler, Position Cell X and

Posted: Sun Jan 04, 2015 2:42 am
by Kiel
Zizi64, thank you for the answer, and I liked the idea of using the anchor cell, which intend to study a little more this option. I do not think I will use to address this topic, but can be useful in a future routine.

RoryOf, the material that has passed is interesting, will help me, because I'm looking for a lot of material on mouse events at that time.

Hanya, like much of the material to send, it is very good. Tested with OOo 3.4 and it worked perfectly. Also tested with the loo 4.3.2.2 and generated the error in the image that is attached. But that's just a detail, considering the distance that I was the solution before this code.

I thank you all,

Kiel

Re: [Calc] Listener: MouseClickHandler, Position Cell X and

Posted: Sun Jan 04, 2015 7:10 am
by hanya
Use this function on LibreOffice:

Code: Select all

Function GetCellBounds(sSheetName As String, nRow As Long, nColumn As Long) As Variant
  oResult = Null
  oAccCtx = ThisComponent.getCurrentController().getFrame().getComponentWindow().getAccessibleContext()
  oDocumentPanelAcc = FindChildByRole(oAccCtx, com.sun.star.accessibility.AccessibleRole.SCROLL_PANE)
  If not IsNull(oDocumentPanelAcc) Then
    oDocumentAcc = FindChildByRole(oDocumentPanelAcc.getAccessibleContext(), com.sun.star.accessibility.AccessibleRole.DOCUMENT)
    If IsNull(oDocumentAcc) Then oDocumentAcc = FindChildByRole(oDocumentPanelAcc.getAccessibleContext(), com.sun.star.accessibility.AccessibleRole.DOCUMENT_SPREADSHEET)
    oFound = Null
    For i = 0 to oDocumentAcc.getAccessibleChildCount() -1 step 1
      oAccChild = oDocumentAcc.getAccessibleChild(i)
      If oAccChild.getAccessibleRole() = com.sun.star.accessibility.AccessibleRole.TABLE Then
        If Right(oAccChild.getAccessibleName(), Len(sSheetName)) = sSheetName Then
          oFound = oAccChild
          Exit For
        End If
      End If
    next
    If NOT IsNull(oFound) Then
      oCellAcc = oAccChild.getAccessibleCellAt(nRow, nColumn)
      oResult = oCellAcc.getBounds()
    End If
  End If
  GetCellBounds = oResult
End Function

[Calc] Listener: MouseClickHandler, Position Cell X and Y re

Posted: Sun Jan 04, 2015 1:32 pm
by Kiel
Thank Hanya the code works now both in OOo as in LibreOffice.

Grateful,

Kiel