OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

Programatically move/rezise a control in a sheet/document
Goto page 1, 2  Next
 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API
View previous topic :: View next topic  
Author Message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Fri Apr 30, 2004 4:39 am    Post subject: Programatically move/rezise a control in a sheet/document Reply with quote

Hi, I want to move/rezie a control programatically. I thought I had all the pieces puzzled together, but it seems I don't.

Here is my code:
Code:

Sub Test
  Dim oView As Object
  Dim oSheet As Object
  Dim oDpage As Object
  Dim oForm As Object
  Dim oCtrlModel As Object
  Dim oCtrl As Object

  oSheet = ThisComponent.Sheets.GetByName("Sheet1")
  oDpage = oSheet.DrawPage
  oForm = oDpage.Forms.getByName("Standard")
  oCtrlModel = oForm.getByName("aComboBox")
  oView = ThisComponent.CurrentController
  oCtrl = oView.GetControl(oCtrlModel)   
   
  Dim oPosSize As Object
  oPosSize = oCtrl.GetPosSize()
   
  Dim x, y, w, h As Long
  x = oPosSize.X
  y = oPosSize.Y
  w = oPosSize.Width
  h = oPosSize.Height
   
  Dim oCellAddress As Object
  oCellAddress = ThisComponent.getCurrentSelection().getCellAddress()   
   
  Dim iCol, iRow As Integer
  iRow = oCellAddress.Row   
  iCol = oCellAddress.Column
   
  Dim oCellPosition As Object
  oCellPosition = oSheet.getCellByPosition(iCol, iRow).Position
   
  Dim lX, lY As Long
  lX = oCellPosition.X
  lY = oCellPosition.Y   
   
  oCtrl.setDesignMode(True)
  oCtrl.setPosSize(lX, lY, w, h, 15)
  oCtrl.setDesignMode(False)
  oCtrl.setVisible(True)
End Sub


The last parameter in setPosSize() is a flag that says which of the first four parameters to bother about when size and position is set. Flag = 15 means to adjust according to all the four parameters.

When I step through the code the control is actually set to the new position, but when I click in the sheet, the control pops right back to its original position... And when I assign this code to a button, nothing happens at all when clicking the button.

Anyone?

Henrik
Back to top
View user's profile Send private message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Sun May 02, 2004 11:45 am    Post subject: Reply with quote

Hi, I see my post hasn't attracted much interest. Pity Confused
Well, I've still not been able to solve this problem, and am starting to wonder whether this is a bug. I kind of believe it is not...it's probably just me missing out on some api.

If I step through the code in the IDE, the control (a listbox) actually moves in the sheet like it s supposed to:

Code:

oCtrl.setDesignMode(True)
oCtrl.setPosSize(x, y, w, h, 15)
oCtrl.setDesignMode(False)
oCtrl.setVisible(True)


Without stepping, but just running the code "normally", nothing happens. This is almost true... if I first step through the code so that the listbox is moved away from it's original position, the code actually works 100% when running the code straight the next time. Something is not obviously not right.

DannyB if you read this, I saw a post by you where you said you were able to move controls around using setPosSize() ( http://www.oooforum.org/forum/viewtopic.php?t=8095&highlight=setpossize ). Did you experience the same problems?

Well, it's annoying not figuring this one out. I think it'll be cool to be able to move controls around, and if I manage to get this to work, I'll be using it in a front end database solution I'm developing.

Hope I have more luck this time... If noone knows how to do this, is there a mailinglist or something where the openoffice developers lurk around? They should be able to do this in 2 minutes (not 2 days like me...).

Thx,
Henrik
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Sun May 02, 2004 12:36 pm    Post subject: Reply with quote

I moved controls, using setPosSize exactly as you did, but it was not in a spreadsheet.

Maybe the issue is that in a spreadsheet, the control model is anchored to a cell. In addition to moving the position of the control you need to change the cell that the control is anchored to?

Your code looks like it moves the physical position of the control to another cell, but is there some other aspect of the control or its model that is tied to the original cell?

I know in Writer that controls have an "anchor". Is this true in Calc as well?

In Draw or Impress you can just move the control, there is no "anchor".

When I first discovered how to use setPosSize, as mentioned in the post you linked to, I was doing it in an AWT window. (That is OOo's AWT, not Java's AWT.) Since we're talking about it, here is some code over in Code Snippets that shows what I'm talking about.

http://www.oooforum.org/forum/viewtopic.php?t=8481
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
dfrench
Moderator
Moderator


Joined: 03 Mar 2003
Posts: 1605
Location: Wellington, New Zealand

PostPosted: Sun May 02, 2004 1:52 pm    Post subject: Reply with quote

Try the mailing list for the api project api.openoffice.org.
I do not know why, but the co-ordinates of the cell and control seem to be on a different scale looking at the values I get for x y and IX IY but that does not help .Reducing the code to the basic
Code:
  oSheet = ThisComponent.Sheets.GetByName("Sheet1")
  oDpage = oSheet.DrawPage
  oForm = oDpage.Forms.getByName("Standard")
  oCtrlModel = oForm.getByName("aComboBox")
  oView = ThisComponent.CurrentController
  oCtrl = oView.GetControl(oCtrlModel)   
  oCtrl.setPosSize(100, 100, 0, 0, 3)
results only in an elastic move (you can see the move but it snaps back immediately) and it makes no difference whether the cell or page is the anchor point.
Back to top
View user's profile Send private message
pitonyak
Administrator
Administrator


Joined: 09 Mar 2004
Posts: 3655
Location: Columbus, Ohio, USA

PostPosted: Sun May 02, 2004 4:00 pm    Post subject: Reply with quote

So if I understand correctly, you are able to run the macro and WHILE the script is running the control moves, but as soon as the macro finished, the control is back at its original position.

Well, I designed a dialog. When I load and run the dialog, I tied a scroll bar to a button so that I can use the scroll bar to move the button around on the dialog. When I close the dialog and open it again, it is back where I had originally designed it to be. The reason is that although I modified the "runtime" position of the control, the actual position as displayed when I opened the dialog is defined by the dialog definition.

I suspect that something similar is happening in your case. Off hand, I do not know how this information is stored for a document, but I suspect that even though you are modifying the model of the control, this informationo is NOT persisted into the document. This, of course, is only a guess.
_________________
--
Andrew Pitonyak
http://www.pitonyak.org/oo.php
Back to top
View user's profile Send private message Send e-mail Visit poster's website AIM Address
dfrench
Moderator
Moderator


Joined: 03 Mar 2003
Posts: 1605
Location: Wellington, New Zealand

PostPosted: Sun May 02, 2004 8:03 pm    Post subject: Reply with quote

Quote:
WHILE the script is running the control moves, but as soon as the macro finished, the control is back at its original position.
Not quite, both the move & spring back takes place with the execution of the setposition ... (I put a wait after it to verify this)
It is not peculiar to CALC ... the same effect occurs on writer forms.
The 'set' does change the properties , you can verify that with a get afterwards , but the properties have been reset if you check them in a further execution of the macro.
Back to top
View user's profile Send private message
dfrench
Moderator
Moderator


Joined: 03 Mar 2003
Posts: 1605
Location: Wellington, New Zealand

PostPosted: Sun May 02, 2004 9:10 pm    Post subject: Reply with quote

Cracked it. Paolo Mantovani had pointed out that the control is actually in a shape which is what controls the position and size, so...
Code:
Sub Main
odoc=thiscomponent
osheet=odoc.getsheets().getbyname("Sheet1")  ' calc document form on sheet 1
oShape = GetControlShape(osheet, "ComboBox")  ' Combobox control SHAPE
Position= oShape.getPosition()
Position.X= Position.X+4000    'Point object - move it 40mm across and down
Position.Y= Position.Y+4000
oShape.setPosition(Position)
End Sub

This code moves the control Right and Down using get and set position. I will leave the size to you ...

GetControlShape is a Function in ModuleControls of the Tools basic library
Back to top
View user's profile Send private message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Mon May 03, 2004 12:15 am    Post subject: Reply with quote

Thx, a lot guys! dfrench's solution does the trick Smile

As for adjusting the size (not only the position) XRay gave the solution, so to test the size feature one might do something like this:
Code:

oSize = oShape.getSize()
oSize.Width = CLng(oSize.Width*1.1)
oSize.Height = CLng(oSize.Height*1.1)
oShape.setSize(oSize)



The GetControlShape function in ModuleControls of the Tools basic library that dfrench is referencing to looks like this:
Quote:

Function GetControlShape(oContainer as Object,CName as String)
Dim i as integer
Dim aShape as Object

for i = 0 to oContainer.DrawPage.Count-1
aShape = oContainer.DrawPage(i)
if HasUnoInterfaces(aShape, "com.sun.star.drawing.XControlShape") then
if ashape.Control.Name = CName then
GetControlShape = aShape
exit Function
endif
endif
next
End Function


There's actually several useful macros in that library.

Henrik
Back to top
View user's profile Send private message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Mon May 03, 2004 3:32 am    Post subject: Reply with quote

Hi, here is the code to move and resize a control (combobox) according to which cell in the sheet that is active. So if anyone cares...

Code:

Sub setComboBoxPosSize
  On Error GoTo ErrorHandler
   
  Dim oSheet As Object
  oSheet = ThisComponent.Sheets.GetByName("Sheet1")
   
  Dim oShape As Object
  oShape = GetControlShape(oSheet, "ComboBox")
   
  Dim oCellAddress As Object
  oCellAddress = ThisComponent.getCurrentSelection().getCellAddress()
   
  Dim iCol, iRow As Integer
  iRow = oCellAddress.Row   
  iCol = oCellAddress.Column
   
  Dim oCellPosition As Object
  oCellPosition = oSheet.getCellByPosition(iCol, iRow).Position
   
  Dim oShapePosition As Object
  oShapePosition   = oShape.getPosition()
 
  oShapePosition.X = oCellPosition.X
  oShapePosition.Y = oCellPosition.Y
  oShape.SetPosition(oShapePosition)
   
  Dim oCellSize As Object
  oCellSize = oSheet.getCellByPosition(iCol, iRow).Size

  Dim oShapeSize As Object
  oShapeSize        = oShape.getSize()

  oShapeSize.Width  = oCellSize.Width
  oShapeSize.Height = oCellSize.Height
  oShape.setSize(oShapeSize)
   
  exit Sub

ErrorHandler:
  MsgBox error$
End Sub


So far this code has not produced any errors. See one of the earlier posts for the function GetControlShape()
Henrik
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Sat May 08, 2004 12:15 pm    Post subject: Reply with quote

Henrik wrote:
The GetControlShape function in ModuleControls of the Tools basic library that dfrench is referencing to looks like this:
Code:

Function GetControlShape(oContainer as Object,CName as String)
  Dim i as integer
  Dim aShape as Object
   
  for i = 0 to oContainer.DrawPage.Count-1
    aShape = oContainer.DrawPage(i)
    if HasUnoInterfaces(aShape, "com.sun.star.drawing.XControlShape") then
      if ashape.Control.Name = CName then
        GetControlShape = aShape
        exit Function
      endif
    endif
  next
End Function



Alas, that function assumes that the oContainer has a getDrawPage() i.e. an XDrawPageSupplier rather than the plural XDrawPagesSupplier which has method getDrawPages().

So this function, as written, is useless for Draw and Impress. It is a pity because a slightly different function would be useful for all document types.

It is also unfortunate that you cannot access the control shape without having to search for it. But I've had to deal with this same delema with shapes in draw pages or other XShapes containers. Each shape can have a name, but you cannot access a shape by name -- you have to search for it.

I'm building a library that manipulates forms and controls. I can see I'm going to have to build a mechanism to find the control shape of a control.

What I have so far, actually working....

GetDrawPage
Function to get a drawpage. You must supply....
+ Document (either model, one of the controllers, or one of the frames)
+ optional: page number (for Draw, Impress or Calc -- ignored for Writer)

GetForms
Similar function to get the Forms collection. Same params as above.

CreateControl
Function to create a new control. You must supply...
+ Control service name (i.e. "com.sun.star.form.component.CommandButton" for a button)
+ control name (i.e. "btnMeowMix")
+ form name (i.e. "MyForm")
+ Document (either model, one of the controllers, or one of the frames)
+ optional: page number (for Draw, Impress or Calc -- ignored for Writer)
If the form (i.e. MyForm) doesn't exist already, the form is created prior to the control being created.
The control model is returned. You can trivially change the control's model like this....
oControlModel = CreateControl( ....params as above.... )
oControlModel.Label = "Meow Mix"

GetControlModel
Function to find and return the control model of a form. You must supply...
+ control name (i.e. "btnMeowMix")
+ form name (i.e. "MyForm")
+ Document (either model, one of the controllers, or one of the frames)
+ optional: page number (for Draw, Impress or Calc -- ignored for Writer)
The control model is returned.

GetControl
Similar to GetControlModel, but the control is returned rather than the model.


GetControlValue
SetControlValue
GetControlText
SetControlText
GetControlState
SetControlState
GetControlEnabled
SetControlEnabled


So for instance, to disable a checkbox control named "chkCornflakes" on page 2, form "CerealTypes", you would write...
Code:
SetControlEnabled( "chkCornflakes", False, "CerealTypes", 2, oDoc )

Note that the oDoc parameter can be omitted if it is ThisComponent.
Note that the page number can be omitted, or is ignored if the document is a Writer document, otherwise the page number "2" refers to the Calc sheet number, or the draw page number for Draw or Impress.
The False causes the control to be disabled instead of enabled.


Still need to do....

* Routines to move the controls around.
* Routines to hide/show controls

Otherwise, I soon will have a library (for Code Snippets) that makes it easy to construct completely new forms and populate them with controls. Even for an existing form with controls that you designed manually, this library makes it trivially easy to manipulate the value (numeric fields) or text (text fields), or the enable/disable state of controls, or the checked/unchecked state of option buttons and checkboxes.


Probably also need functions to....
* anchor a control to a particular paragraph.
* anchor a control to a particular calc cell
* size a control to a particular calc cell(s)
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Sat May 08, 2004 4:06 pm    Post subject: Reply with quote

Hi, DannyB Smile

Your work sounds interesting. Maybe you could release the code you already have? I have a good deal of code myself that manipulates controls, but most if it is taylored to calc. I'm sure several others here also have code "lying around".

If you show us what you've already got, then we can help filling in the missing pieces if you want.

Just a thought...
Henrik
Back to top
View user's profile Send private message
az
Newbie
Newbie


Joined: 08 May 2004
Posts: 2
Location: Canberra (Australia)

PostPosted: Sat May 08, 2004 5:21 pm    Post subject: Reply with quote

Hi DannyB,

I am very interested in your code, too. In particular the CreateControl sounds like the ideal solution to my problem in http://www.oooforum.org/forum/viewtopic.php?t=8678 . Hope you can convince yourself to post it soon Wink
Cheers, Andreas
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Sun May 09, 2004 12:02 pm    Post subject: Reply with quote

Henrik wrote:
Your work sounds interesting. Maybe you could release the code you already have? I have a good deal of code myself that manipulates controls, but most if it is taylored to calc. I'm sure several others here also have code "lying around".


also...

az wrote:
I am very interested in your code, too. ..... Hope you can convince yourself to post it soon


Since this is not really ready for the full glory of a posting to Code Snippets, with a detailed write up, here is what I've got so far.


Here is a simple example of how my library is used. Notice the first three lines. You can do this on either a Draw (which implies Impress) or Writer or Calc document. Alas, Draw on Linux does not work because Draw's Controller does not implement the getControl() method. I'm going to file an enhancement request for this.

Anyway, this program creates a new document, then creates a form form with two buttons, and attaches listeners to the two buttons. The buttons are NOT put onto the current document, but a NEW document is created and button controls with listeners are put into a new document.

Code:
Sub Main
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/sdraw", "_blank", 0, Array() )
'   oDoc = StarDesktop.loadComponentFromURL( "private:factory/scalc", "_blank", 0, Array() )
   oDoc = StarDesktop.loadComponentFromURL( "private:factory/swriter", "_blank", 0, Array() )

   oDocCtrl = GetDocumentController( oDoc )
   Xray.Xray oDocCtrl

   oControlModel = FormCreateControl_Button( 2000, 4000, 6000, 2000, "Apples", "btnApples", "MyForm", 0, oDoc )
   oControl = oDocCtrl.getControl( oControlModel )
   oListener = CreateUnoListener( "btnApples_", "com.sun.star.awt.XActionListener" )
   oControl.addActionListener( oListener )

   oControlModel = FormCreateControl_Button( 2000, 8000, 6000, 2000, "Oranges", "btnOranges", "MyForm", 0, oDoc )
   oControl = oDocCtrl.getControl( oControlModel )
   oListener = CreateUnoListener( "btnOranges_", "com.sun.star.awt.XActionListener" )
   oControl.addActionListener( oListener )

   ' Since form design mode is on, toggle it off.
   DocumentDispatch( oDoc, ".uno:SwitchControlDesignMode" )
End Sub



'---------- com.sun.star.awt.ActionListener ----------

Sub btnApples_actionPerformed( tActionEvent As com.sun.star.awt.ActionEvent )
   Print "You clicked Apples"
End Sub

Sub btnOranges_actionPerformed( tActionEvent As com.sun.star.awt.ActionEvent )
   Print "You clicked Oranges"
End Sub



Of course, the really cold routine here is
FormCreateControl_Button()
This function creates a button control, with a specified label, control name, coordinates, and onto a particular named form (even creating the form if it doesn't already exist)

Similarly, I plan to create new routines such as....
FormCreateControl_Checkbox()
FormCreateControl_OptionButton()
etc., etc..
I think you can trivially see how this would be done by looking at how FormCreateControl_Button() works. Just change the service name within.

This routine is from my incomplete library. I'm posting this here under LGPL for your reference. But no detailed writeup on how it works.

I have also got working some of the things I mentioned above as "Still to do".
* Routines to move the controls around.
* Routines to hide/show controls
These now work.

In hopes that it might be useful, here it is, incomplete, such as it is.


Code:
'**********************************************************************
'   UtilForm module
'
'   Utility functions for working with document Forms.
'
'**********************************************************************
'   Copyright (c) 2003-2004 Danny Brewer
'   d29583@groovegarden.com
'
'   This library is free software; you can redistribute it and/or
'   modify it under the terms of the GNU Lesser General Public
'   License as published by the Free Software Foundation; either
'   version 2.1 of the License, or (at your option) any later version.
'
'   This library is distributed in the hope that it will be useful,
'   but WITHOUT ANY WARRANTY; without even the implied warranty of
'   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
'   Lesser General Public License for more details.
'
'   You should have received a copy of the GNU Lesser General Public
'   License along with this library; if not, write to the Free Software
'   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'
'   See:  http://www.gnu.org/licenses/lgpl.html
'
'**********************************************************************
'   If you make changes, please append to the change log below.
'
'   Change Log
'      Danny Brewer         Revised 2004-05-08-02
'
'**********************************************************************




'----------
'   Get the Forms collection from a certian page of a document.
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
'   Once you have the collection of Forms, you can do the following things...
'      from XNameContainer....
'         oForms.insertByName( "FormName", oForm )
'         oForms.removeByName( "FormName" )
'         oForms.replaceByName( "FormName", oForm )
'         aNames = oForms.getElementNames()
'         oForm = oForms.getByName( "FormName )
'         If oForms.hasByName( "FormName" ) Then...
'      from XIndexAccess...
'         oForms.insertByIndex( 0, oForm )
'         oForms.removeByIndex( 0 )
'         oForms.replaceByIndex( 0, oForm )
'         nNumForms = oForms.getCount()
'         oForm = oForms.getByIndex( 0 )
'      from XEnumerationAccess...
'         oEnumeration = oForms.createEnumeration()
'         ...then use hasMoreElements() and nextElement()
'
'   Examples....
'      Create new form, and give it the name MyForm...
'         oForm = createUnoService( "com.sun.star.form.component.Form" )
'         oForms.insertByName( "MyForm", oForm )
'      Get the form named MyForm
'         oForm = oForms.getByName( "MyForm" )
'
Function FormGetForms( Optional nPage, Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oDrawPage = GetDrawPage( nPage, oDoc )
   oForms = oDrawPage.getForms()
   FormGetForms = oForms
End Function



'----------
'   Get the DrawPage of a document.
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function GetDrawPage( Optional nPage, Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
      oDocModel = oDoc
   Else
      oDocModel = GetDocumentModel( oDoc )
   EndIf
   
   ' If the document is a spreadsheet...
   If oDocModel.supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) Then
      oSheet = oDocModel.getSheets().getByIndex( nPage )
      oDrawPage = oSheet.getDrawPage()
      
   ElseIf oDocModel.supportsService( "com.sun.star.text.TextDocument" ) Then
      ' Ignore the nPage parameter for Writer documents.
      oDrawPage = oDocModel.getDrawPage()

   ' If no draw page number specified, then assume
   '  there is only one draw page, via. an XDrawPageSupplier interface,
   '  instead of multiple pages via. an XDrawPagesSupplier interface.
   ElseIf IsMissing( nPage )  Or  (nPage = -1) Then
      oDrawPage = oDocModel.getDrawPage()
   Else
      oDrawPage = oDocModel.getDrawPages().getByIndex( nPage )
   EndIf
   
   GetDrawPage = oDrawPage
End Function



'----------
'   Create a new Form, or return the existing form of the same name.
'   This returns the form.
'   Parameters:
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormCreateForm( ByVal cFormName As String, Optional nPage, Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oForms = FormGetForms( nPage, oDoc )
   
   If oForms.hasByName( cFormName ) Then
      ' Get existing form.
      oForm = oForms.getByname( cFormName )
   Else
      ' Create new form.
      oForm = createUnoService( "com.sun.star.form.component.Form" )
      oForms.insertByName( cFormName, oForm )
   EndIf
   
   FormCreateForm = oForm
End Function



'----------
'   Create a Button control.
'   This returns the control model.  (Not the control.)
'   Parameters:
'      x, y, width, height   - the control's location and size.
'      cControlCaption   -   The name that is displayed to the user.
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormCreateControl_Button( _
            ByVal x As Long, ByVal y As Long,_
            ByVal width As Long, ByVal height As Long,_
            ByVal cControlCaption As String,_
            ByVal cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlShape = FormCreateControlShape( "com.sun.star.form.component.CommandButton",_
            cControlName, cFormName, nPage, oDoc )
   oControlModel = oControlShape.getControl()
   
   oControlShape.Position = MakePoint( x, y )
   oControlShape.Size = MakeSize( width, height )
   
   oControlModel.Label = cControlCaption
   
   FormCreateControl_Button = oControlModel
End Function



'----------
'   Create a new control.
'   This returns the control model.  (Not the control.)
'   Parameters:
'      cControlServiceName
'                  -   something like...  "com.sun.star.form.component.CommandButton"
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormCreateControl( ByVal cControlServiceName As String,_
            ByVal cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlShape = FormCreateControlShape( cControlServiceName,_
            cControlName, cFormName, nPage, oDoc )
   oControlModel = oControlShape.getControl()
   
   FormCreateControl = oControlModel
End Function



'----------
'   Create a new control -- return its shape.
'   This is very similar to CreateControl(), but returns the control shape.
'   This returns the control shape.
'   Parameters:
'      cControlServiceName
'                  -   something like...  "com.sun.star.form.component.CommandButton"
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormCreateControlShape( ByVal cControlServiceName As String,_
            ByVal cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oDrawPage = GetDrawPage( nPage, oDoc )
   oForms = oDrawPage.getForms()
      
   If oForms.hasByName( cFormName ) Then
      ' Get existing form.
      oForm = oForms.getByname( cFormName )
   Else
      ' Create new form.
      oForm = createUnoService( "com.sun.star.form.component.Form" )
      oForms.insertByName( cFormName, oForm )
   EndIf
   
   ' Create the control shape for the draw page.
   oControlShape = MakeControlShape( oDoc, MakePoint( 1000, 2000 ), MakeSize( 4000, 1000 ) )
   ' Create the control model.
   oControlModel = createUnoService( cControlServiceName )
   
   ' Introduce the control model to the control shape.
   oControlShape.setControl( oControlModel )
   ' Note that both the control model and control shape are still disembodied.
   ' That is, they are not contained in any hierarchy.
   
   ' Now insert the control model into the form.
   oForm.insertByName( cControlName, oControlModel )
   ' Insert the control shape into the draw page.
   oDrawPage.add( oControlShape )
   
   ' Special behavior for Writer.
   ' Anchor the control to a paragraph.  (Default is draw page.)
   oDocModel = GetDocumentModel( oDoc )
   If oDocModel.supportsService( "com.sun.star.text.TextDocument" ) Then
      oControlShape.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PARAGRAPH
'      oCtrlShape.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PAGE
   EndIf
   
   FormCreateControlShape = oControlShape
End Function



'----------
'   Get a control model from a form of a document.
'   This returns the control model.  (Not the control.)
'   Parameters:
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormGetControlModel( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oForms = FormGetForms( nPage, oDoc )   
   oForm = oForms.getByName( cFormName )
   oControlModel = oForm.getByName( cControlName )

   FormGetControlModel = oControlModel
End Function


'----------
'   Get a control from a form of a document.
'   This returns the control.  (Not the model.)
'   Parameters:
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormGetControl( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   
   oDocCtrl = GetDocumentController( oDoc )
   oControl = oDocCtrl.getControl( oControlModel )
   
   FormGetControl = oControl
End Function



'----------
'   Search the draw page for a particular control shape.
'   This returns the control shape.
'   Parameters:
'      cControlName   -   The control's name.
'      cFormName      -   The form's name.  (Usually: "Standard")
'   Optional Parameters:
'      nPage         -   The page number of a document that has multiple
'                      draw pages, such as Draw, Impress or Calc.
'                     Passing -1 is the same as omitting this argument.
'      oDoc         -   The document model.  If not supplied, then ThisComponent is used.
'                     It is okay to pass one of the document's controllers or frame instead.
'
Function FormFindControlShape( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oDrawPage = GetDrawPage( nPage, oDoc )
   oForms = oDrawPage.getForms()
   oForm = oForms.getByName( cFormName )
   
   nNumShapes = oDrawPage.getCount()
   For i = 0 To nNumShapes - 1
      oShape = oDrawPage.getByIndex( i )
      If HasUnoInterfaces( oShape, "com.sun.star.drawing.XControlShape" ) Then
         oControlModel = oShape.getControl()
         If oControlModel.getName() = cControlName Then
            FormFindControlShape = oShape
            Exit Function
         EndIf
      EndIf
   Next
End Function



Function FormGetControlValue( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Double
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   nValue = oControlModel.Value
   FormGetControlValue = nValue
End Function


Sub FormSetControlValue( cControlName As String,_
            ByVal nValue As Double,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc )
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   oControlModel.Value = nValue
End Sub


Function FormGetControlText( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As String
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   cText = oControlModel.Text
   FormGetControlText = cText
End Function


Sub FormSetControlText( cControlName As String,_
            ByVal cText As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc )
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   oControlModel.Text = cText
End Sub


Function FormGetControlState( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Boolean
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   bState = oControlModel.State
   FormGetControlState = bState
End Function


Sub FormSetControlState( cControlName As String,_
            ByVal bState As Boolean,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc )
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   oControlModel.State = bState
End Sub


Function FormGetControlEnabled( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Boolean
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   bEnabled = oControlModel.Enabled
   FormGetControlEnabled = bEnabled
End Function


Sub FormSetControlEnabled( cControlName As String,_
            ByVal bEnabled As Boolean,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc )
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControlModel = FormGetControlModel( cControlName, cFormName, nPage, oDoc )
   oControlModel.Enabled = bEnabled
End Sub



' Note that the control is visible in Form Design Mode.
' To toggle design mode do this....
'      DocumentDispatch( oDoc, ".uno:SwitchControlDesignMode" )
'
Sub FormSetControlVisible( cControlName As String,_
            ByVal bVisible As Boolean,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc )
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf

   oControl = FormGetControl( cControlName, cFormName, nPage, oDoc )
   oControl.setVisible( bVisible )
End Sub




Sub FormGetControlPosition( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oShape = FormFindControlShape( cControlName, cFormName, nPage, oDoc )
   oPosition = oShape.Position
   FormGetControlPosition = oPosition
End Sub


Sub FormSetControlPosition( cControlName As String,_
            oPosition As com.sun.star.awt.Point,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oShape = FormFindControlShape( cControlName, cFormName, nPage, oDoc )
   oShape.Position = oPosition
End Sub


Sub FormGetControlSize( cControlName As String,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oShape = FormFindControlShape( cControlName, cFormName, nPage, oDoc )
   oSize = oShape.Size
   FormGetControlSize = oSize
End Sub


Sub FormSetControlSize( cControlName As String,_
            oSize As com.sun.star.awt.Size,_
            ByVal cFormName As String,_
            Optional nPage,_
            Optional oDoc ) As Object
   ' If no document specified, then use this document.
   If IsMissing( oDoc ) Then
      oDoc = ThisComponent
   EndIf
   ' If no page number specified, then pass -1.   
   If IsMissing( nPage ) Then
      nPage = -1
   EndIf
   
   oShape = FormFindControlShape( cControlName, cFormName, nPage, oDoc )
   oShape.Size = oSize
End Sub


In order to make this work, you will no doubt need other routines from my library.

In particular, see articles in Code Snippets titled....

Document model, controller and frame
http://www.oooforum.org/forum/viewtopic.php?t=5057

Making the Dispatcher easier to use
http://www.oooforum.org/forum/viewtopic.php?t=5058

for some of the routines that this library depends upon. I think those two articles have all of the missing routines. If you find that the above code references routines not present in the above two articles, please reply, and I'll supply them. (Or look at the outdated version of Danny's Library on OOoMacros.org)

So there it is, such as it is. Don't blame me. You asked for it. Smile

With the above code, it should be possible to build upon it and construct things such as auto-pilots which create new data entry forms for existing database tables, for example.

I have a similar incomplete library for creating dialog boxes (not using the visual dialog designer in Basic's IDE, but creating them on the fly from code). This library is in both Python or Basic. It can create dialog boxes, and populate it with controls, and attach listeners. This does not quite work the same way as forms.

Good luck.



Danny, later added....
To make the code in this example work, you also need....
Code:


'----------
'   Create and return a ControlShape object,
'    optionally with its position and size initialized.
'
Function MakeControlShape( oDoc As Object,_
               Optional position As com.sun.star.awt.Point,_
               Optional size As com.sun.star.awt.Size ) As com.sun.star.drawing.ControlShape
   oShape = oDoc.createInstance( "com.sun.star.drawing.ControlShape" )
   If Not IsMissing( position ) Then
      oShape.Position = position
   EndIf
   If Not IsMissing( size ) Then
      oShape.Size = size
   EndIf
   MakeControlShape = oShape
End Function


'----------
'   Easy sugar coated way to create and initialize a new Point object.
'
Function MakePoint( ByVal x As Long, ByVal y As Long ) As com.sun.star.awt.Point
   oPoint = createUnoStruct( "com.sun.star.awt.Point" )
   oPoint.X = x
   oPoint.Y = y
   MakePoint = oPoint
End Function


'----------
'   Easy sugar coated way to create and initialize a new Size object.
'
Function MakeSize( ByVal width As Long, ByVal height As Long ) As com.sun.star.awt.Size
   oSize = createUnoStruct( "com.sun.star.awt.Size" )
   oSize.Width = width
   oSize.Height = height
   MakeSize = oSize
End Function

_________________
Want to make OOo Drawings like the colored flower design to the left?


Last edited by DannyB on Mon Jun 28, 2004 10:39 am; edited 3 times in total
Back to top
View user's profile Send private message
Henrik
OOo Enthusiast
OOo Enthusiast


Joined: 15 Jan 2004
Posts: 118

PostPosted: Sun May 09, 2004 1:20 pm    Post subject: Reply with quote

Hi again DannyB!

I think this is great. I've read through your code and it's very clear and consice I think. Much of the code actually is quite similar to my own code, execpt that I more or less have focused exclusively on Calc. I'm actually happy to see that some few modifications here and there will allow my existing code to also work with Writer and Draw.

Some of the concepts in your code I have not worked with before, like how to create controls on the fly. I'm always learning something reading your posts. Great!

I my last post I said I (the rest of us) could help you with filling in the missing pieces, but to me the code looks more or less complete... I have some code that gets/sets/populates values in comboboxes/listboxes, and possibly a couple of other things that might be useful, but other than that you more or less have covered it all.

I think this library will be of great value to both beginners and "advanced". In addition to doing a lot of the common manipulations that one often wish to accomplish, it's also a great way to learn the api. Also if one is coding in java, python or c++ (or whatever) one could use this libary as a template, and it should make life easier.

I hope this libary can be a work in progress. When you or anyone else comes up with something that seems like a good idea to add to the library, we would add it. That way we should hopefully be able to save a lot of time not having to re-invent the wheel all the time.

Thx,
Henrik Smile
Back to top
View user's profile Send private message
DannyB
Moderator
Moderator


Joined: 02 Apr 2003
Posts: 3991
Location: Lawrence, Kansas, USA

PostPosted: Sun May 09, 2004 3:02 pm    Post subject: Reply with quote

Henrik wrote:
I think this is great. I've read through your code and it's very clear and consice I think.

Thanks.


Henrik wrote:
I'm actually happy to see that some few modifications here and there will allow my existing code to also work with Writer and Draw.

I always try to make things as general purpose as possible.



Henrik wrote:
Some of the concepts in your code I have not worked with before, like how to create controls on the fly. I'm always learning something reading your posts. Great!

I am a lifelong learner. I always try to read, study and learn new things.




Henrik wrote:
I my last post I said I (the rest of us) could help you with filling in the missing pieces, but to me the code looks more or less complete... I have some code that gets/sets/populates values in comboboxes/listboxes, and possibly a couple of other things that might be useful, but other than that you more or less have covered it all.

It would be interesting to study your code. I may learn techniques more quickly, with which I can expand my code library. Otherwise, I will still learn these techniques, just more slowly.




Henrik wrote:
I hope this libary can be a work in progress. When you or anyone else comes up with something that seems like a good idea to add to the library, we would add it. That way we should hopefully be able to save a lot of time not having to re-invent the wheel all the time.

I have a library of code, I think you can find it at OOoMacros.org, but it is never up to date. (I can't expect it to be, because I keep updating it.) This library is programmed in my own style. I use it for things like Danny's Draw Power Tools (also at OOoMacros.org). Anyone is free to use my library routines under LGPL, or study techniques from it to build their own. I am always happy of course to learn techniques here from OOoForum and then construct my own implementation of those techniques.
_________________
Want to make OOo Drawings like the colored flower design to the left?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API All times are GMT - 8 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group