Automatic resize of Math formulas

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
lmari
Posts: 7
Joined: Mon Mar 03, 2008 1:00 pm

Automatic resize of Math formulas

Post by lmari »

Hi.
Currently OOo does not seem to offer any off-the-shelf solution for automatically changing the size of all Math formulas in a document or a selection. This would be a pretty useful tool, in my opinion.
While waiting for a cleaner and brighter solution, a macro could be operated to this goal, according to the following logic:

Code: Select all

1. create the collection of the embedded objects (in the document, or selection)
2. loop on the collection
3. if the current object is a formula,
3.1 apply the new size
3.2 and refresh 
Ok, and I append below my current implementation, that, on the other hand, has two problems:
A. when the collection contains more than 20 (yes, exactly 20 is the threshold) formulas, the debugger is activated, with the error
"BASIC runtime error. - Object variable not set"
set by the line 3 above (the line

Code: Select all

if oTR3.EmbeddedObject.supportsService("com.sun.star.formula.FormulaProperties") then
in the implementation below);
B. the logic for refreshing the resized formulas (line 3.2 above) does not work, so that the size change must be "manually notified " by double clicking one by one all the formulas.

Any suggestions to solve these issues A and B? Thank a lot everybody.

Luca

... and here is the code:

Code: Select all

sub Prova
newSize = InputBox("New formula font size:", "BaseFontHeight", 10)
if isNull(newSize) or newSize = "" then exit sub
oDoc = ThisComponent
oSel = oDoc.CurrentController.Selection
if oSel.supportsService("com.sun.star.text.TextEmbeddedObject") then
  if oSel.EmbeddedObject.supportsService("com.sun.star.formula.FormulaProperties") then
    SetFormulaSize(oSel, newSize)
    oDoc.reformat()
    msgbox "ok..."
    exit sub
  endif
endif
if oSel.supportsService("com.sun.star.text.TextRanges") then
  oTR = oSel.getByIndex(0)
  oEnum = oTR.createEnumeration()
  while oEnum.hasMoreElements()
    oTR1 = oEnum.nextElement()
    oEnum1 = oTR1.createEnumeration()
    while oEnum1.hasMoreElements()
      oTR2 = oEnum1.nextElement()
      if oTR2.TextPortionType = "Frame" then
        oEnum2 = oTR2.createContentEnumeration("com.sun.star.text.TextEmbeddedObject")
        while oEnum2.hasMoreElements()
          oTR3 = oEnum2.nextElement()
          if oTR3.EmbeddedObject.supportsService("com.sun.star.formula.FormulaProperties") then
    		SetFormulaSize(oTR3, newSize) 'msgbox "Formula"
          endif
        wend
      endif
    wend
  wend
  oDoc.reformat()
  msgbox "ok..."
  exit sub
endif
end sub

sub SetFormulaSize(obj, newSize)
oFormula = obj.EmbeddedObject
oFormula.BaseFontHeight = newSize
temp = oFormula.Formula ' some tricks to force OO.o redraw formulas '*** THESE DO NOT WORK!***
oFormula.Formula = ""
oFormula.Formula = temp
end sub
lmari
Posts: 7
Joined: Mon Mar 03, 2008 1:00 pm

Re: Automatic resize of Math formulas

Post by lmari »

A further note on the post (sorry for this missing point...):
I tested the macro on OOo 2.3 and 2.4, on both Linux (OpenSuse 10.3) and WinXp, and the mentioned behavior is exactly the same.

Luca
ms777
Volunteer
Posts: 177
Joined: Mon Oct 08, 2007 1:33 am

Re: Automatic resize of Math formulas

Post by ms777 »

Hi,

try the following. At least it solves your second problem ...

It may also be possible to iterate the code over all objects of a drawpage. Then, you should not run into the max 20 problem

Good luck,

ms777

Code: Select all

Sub Main 

oShape = ThisComponent.Drawpage.getByIndex(0)
if oShape.supportsService("com.sun.star.text.TextEmbeddedObject") then
  oEO = oShape.EmbeddedObject
  if oEO.supportsService("com.sun.star.formula.FormulaProperties") then
    oXEO = oShape.ExtendedControlOverEmbeddedObject
    iCurrentState = oXEO.currentState
    oXEO.changeState(com.sun.star.embed.EmbedStates.UI_ACTIVE)
    if oEO.BaseFontHeight = 100 then
      oEO.BaseFontHeight = 30
    else
      oEO.BaseFontHeight = 100 
    endif

    wait(200)
    dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
    dispatcher.executeDispatch(oEO.CurrentController.Frame, ".uno:Draw", "", 0, Array())
    oXEO.changeState(iCurrentState)
  endif
endif


End Sub
lmari
Posts: 7
Joined: Mon Mar 03, 2008 1:00 pm

Re: Automatic resize of Math formulas

Post by lmari »

Thank you so much.

I tried your solution, so that I discovered that the reason for which the formulas do not refresh after being resized by the macro seems to be related to their "activation": only after the first double click on it, a formula "becomes alive" and it is correctly refreshed by the macro.
If, for example, I close a document and then reopen it, for having its formulas correctly visualized after their automatic resize by the macro, I must double click on each of them.
Hence, I suspect that what is missing in the macro is some code simulating the double click (the "activation"...) of each formula to be resized.
Any idea on this issue?

Thanks again.

Luca
ms777
Volunteer
Posts: 177
Joined: Mon Oct 08, 2007 1:33 am

Re: Automatic resize of Math formulas

Post by ms777 »

Hi Luca,

does the code work or not ? It should do all resizing without the need for any user interaction ...

In my code,

Code: Select all

oXEO.changeState(com.sun.star.embed.EmbedStates.UI_ACTIVE)
is the equivalent of doubleclicking on the formula. Normally, this should be sufficient to also update the view. Here, you have to add the draw dispatch to actually update the view.

Good luck,

ms777
lmari
Posts: 7
Joined: Mon Mar 03, 2008 1:00 pm

Re: Automatic resize of Math formulas

Post by lmari »

Dear ms777,

I suppose that you are right: for the first formula in the document, obtained by:

Code: Select all

oShape = ThisComponent.Drawpage.getByIndex(0)
your code actually works.
But may you show me how to get all formulas in the current selection, or in the current document, so to apply your code to them?
Even in the simple case of a single selected formula, I tried to get it by:

Code: Select all

oShape = ThisComponent.CurrentController.Selection

but I got an exception (com.sun.star.embed.WrongStateException) on the line:

Code: Select all

 oXEO.changeState(com.sun.star.embed.EmbedStates.UI_ACTIVE)
Thank you again

Luca
Post Reply