[Solved] Resizing Form Edit Boxes to their size content

Creating and using forms
Post Reply
intuited
Posts: 25
Joined: Sat Nov 08, 2008 11:51 pm

[Solved] Resizing Form Edit Boxes to their size content

Post by intuited »

Hi,
I'm looking for a way to resize Edit Boxes, or some other control that can be set to display the content of a single database field, to the size of the text they contain. I'm quite comfortable with doing this with a macro but the api that would seem to be useful for this is not particularly well-documented. Does someone out there know how to do this? Thanks!
Last edited by intuited on Fri Dec 05, 2008 5:45 am, edited 1 time in total.
intuited
Posts: 25
Joined: Sat Nov 08, 2008 11:51 pm

Re: Resizing Form Edit Boxes to the size of their contents

Post by intuited »

Well I've made some progress on this. from what I understand the following code, located in a macro called on form load, should set the size of the control to its preferred size to contain its contents:

Code: Select all

	forms = ThisComponent.DrawPage.Forms
	Form = ThisComponent.DrawPage.Forms.GetByName("Form")
	CtlModelEdit = Form.GetByName("txtEdit")

	Doc = StarDesktop.CurrentComponent
   	DocController = Doc.getCurrentController()
  	CtlEdit = DocController.GetControl(CtlModelEdit)
  	CtlEdit.SetOutputSize(CtlEdit.PreferredSize)
but it doesn't. when debugging the code, the size is shown as being set and then it bounces back to its previous value for no obvious reason.
I also tried using SetPosSize instead of SetOutputSize, with similar results.
I'd love to understand why this isn't working. Anyone?
OOo 3.2 on Ubuntu 10.04
User avatar
bobban
Volunteer
Posts: 535
Joined: Sat Nov 01, 2008 3:12 pm
Location: Australia

Re: Resizing Form Edit Boxes to the size of their contents

Post by bobban »

I'm no expert on this stuff, and indeed still quite confused about the object architecture myself, but I believe you need the 'shape' relating to your control. I've not quite got a grasp on when you need the control, the view, the model or the shape but I think a good guide is in order. :?

Also, I have had no luck with PreferredSize either. In just experimenting with it now on a button, I found that it was always suggesting a size far too small, indeed microscopic, but maybe this is not intended to be used with buttons.

So maybe something more like this:

Code: Select all

sub testPosition2()

	oDoc = ThisComponent
	
	oView = oDoc.currentcontroller()
	oCtlr = oView.getcontrol(SaveButton) ' the control view
	
	BasicLibraries.LoadLibrary("Tools")
	oCtlrShape = GetControlShape(oDoc, "SavePDF_Button") ' the control view
	
	'Dim oShapePosition As Object
	'oShapePosition = oCtlrShape.getPosition()
	'oCtlrShape.SetPosition(oShapePosition) 
	
	'oShapeSize = oCtlrShape.getSize()
	'oShapeSize.Width = oShapeSize.Width*0.8
	'oShapeSize.Height = oShapeSize.Height*0.8
	'oCtlrShape.SetSize(oShapeSize)     
	
	oPreferredShapeSize = oCtlr.getPreferredSize()
	oCtlrShape.SetSize(oPreferredShapeSize)
	
end sub
OOo 3.1.1 on Ms Windows XP
intuited
Posts: 25
Joined: Sat Nov 08, 2008 11:51 pm

Re: Resizing Form Edit Boxes to the size of their contents

Post by intuited »

hmm...
that kind of worked. doing

Code: Select all

oPreferredShapeSize = CtlEdit.getPreferredSize()
CtlEdit.SetOutputSize(oPreferredShapeSize)
oCtlrShape.SetSize(oPreferredShapeSize)
results in a rectangle just big enough to hold the text being displayed over top of the original edit box.
hovering the mouse cursor over top of the original edit box causes it to be redisplayed on top.
the newer, smaller, text box does not respond to mouseover events.

Although this might be leading somewhere, it's leading me to believe that there's a better way to do this sort of thing. the fact that the original edit box still responds to mouseover events implies that despite all these efforts the size of the edit box has stayed fundamentally the same. Since the size is defined in the form design, it seems like there's possibly something in the model that's overriding this controller/view[/shape??] stuff.

What I'm interested in doing is resizing text edit controls to fit their contents, ie making them become the same rectangular size as the text that's in them. I'm attempting to do this because it seemed like the most appropriate and quick way to be able to lay out the fields in a form so that they flow like text without having awkward arbitrarily-sized spaces between words. This is a pretty easy thing to do in, for example, MFC. But perhaps there's an easier and more appropriate way to do what I want to do in OpenOffice.org.
I don't actually need the resized fields to be editable, just displayed. But resizing the edit controls seemed likely to be a less difficult thing to figure out how to do than did displaying the text from the corresponding data fields in some other entity that's more amenable to subjection to layout rules. I do need some interactive elements to be present in the form, so using a report doesn't seem like an appropriate solution. And I need to use different font sizes within a block of text, so I can't just combine the various text fields in a query and show them in one control.
OOo 3.2 on Ubuntu 10.04
intuited
Posts: 25
Joined: Sat Nov 08, 2008 11:51 pm

Re: Resizing Form Edit Boxes to the size of their contents

Post by intuited »

Bobbin,
I took some time off from this, and have come back to it with a vengeance.
Although I previously wasn't having the problem that you mentioned with the preferred size being too small, i've switched boxes and the new one is doing that. The reason why, or at least what I've divined, is that the unit of measurement being used by ooo at the shape layer is not pixels, but something else. on this box it seems to be thousandths of a cm.
so although the form is laid out in pixels, in order to interact with the lower-level shape layer, the coordinates and sizes need to be translated into whatever unit of measurement is in use at that level. this, as well as and in light of the fact that it's necessary to set the size of a control at least twice, raises a number of design and technical questions, none of which I've found the answer to in any documentation. However I do have some working code. I created a label and a textbox called "size label" and "size textbox"; this code resizes them so that they are just large enough to contain their contents. to convert the pixel size to a shape-layer-unit size it uses the ratio of the original size of the component to that of the shape:

Code: Select all

Sub TestResizing (Event as Object)
	'this code will work when the sub is mapped to When Loading and When Reloading events (& some others)
	Form = Event.Source
	sizelabelModel = Form.GetByName("size label")
	sizetextboxModel = Form.GetByName("size textbox")

	Controller = ThisComponent.GetCurrentController()
	sizelabelCtl = Controller.GetControl(sizelabelModel)
	sizetextboxCtl = Controller.GetControl(sizetextboxModel)
	
	sizelabelPeer = sizelabelCtl.Peer
	sizetextboxPeer = sizetextboxCtl.Peer
	
	sizelabelShape = GetControlShape(ThisComponent, "size label")
	sizetextboxShape = GetControlShape(ThisComponent, "size textbox")
	
	labelPreferredSize = sizelabelCtl.PreferredSize
	textboxPreferredSize = sizetextboxCtl.PreferredSize
	sizelabelCtl.SetOutputSize(labelPreferredSize)
	sizetextboxCtl.SetOutputSize(textboxPreferredSize)
	sizelabelCtl.SetPosSize(0, 0, labelPreferredSize.Width, labelPreferredSize.Height, 24)
	sizetextboxCtl.SetPosSize(0, 0, textboxPreferredSize.Width, textboxPreferredSize.Height, 24)
	'the shape size is sometimes very different from the control size.
	'  although this is undocumented it seems to be because the shape size is measured physical dimension units and not pixels.
	ShapeHeightRatio = sizelabelShape.Size.Height / sizelabelCtl.Size.Height
	if sizelabelShape.Size.Height mod sizelabelCtl.Size.Height > 0 then
		ShapeHeightRatio = ShapeHeightRatio + 1
	endif
	ShapeWidthRatio = sizelabelShape.Size.Width / sizelabelCtl.Size.Width
	if sizelabelShape.Size.Width mod sizelabelCtl.Size.Width > 0 then
		ShapeWidthRatio = ShapeWidthRatio + 1
	endif
	
	labelPreferredSize.Height = labelPreferredSize.Height * ShapeHeightRatio
	labelPreferredSize.Width = labelPreferredSize.Width * ShapeWidthRatio
	textboxPreferredSize.Height = textboxPreferredSize.Height * ShapeHeightRatio
	textboxPreferredSize.Width = textboxPreferredSize.Width * ShapeWidthRatio

	sizelabelShape.SizeProtect = False
	sizetextboxShape.SizeProtect = False
	sizelabelShape.SetSize(labelPreferredSize)
	sizetextboxShape.SetSize(textboxPreferredSize)
End Sub
information that I didn't put in code comments:
  • - The lines that set SizeProtect to False may not be necessary -- the shapes seem to accept the new size regardless of the value of this property.
    - i calculate the width and height ratios separately in case the aspect ratio used by the shape layer is not 1:1
    - the modula ("mod") condition rounds the division up so that the control will end up 1 pixel bigger than necessary rather than smaller
    - the 24 used in the calls to SetPosSize should actually reference and bitwise-add a couple of constants from i think the awt module. check the documentation for com.sun.star.awt.XWindow.SetPosSize for more information.
using the exact same code works for both control types (i didn't try anything with buttons), although the edit box ends up having a margin on the left but not the right side of the text that it contains.
the problem that I was having with the size being reset on mouseover hasn't recurred. It may be something that happens with controls that are bound to database fields -- the controls I used in this test code are not.
OOo 3.2 on Ubuntu 10.04
User avatar
bobban
Volunteer
Posts: 535
Joined: Sat Nov 01, 2008 3:12 pm
Location: Australia

Re: Resizing Form Edit Boxes to the size of their contents

Post by bobban »

intuited (better get yourself a hot drink before tucking into this :lol: ),

Thanks for posting back your findings, they were most interesting to read. Sorry for the slow response, I have little time at the moment but managed to have brief look into this. I had a play around with your code and here is my observations. The code at bottom is your but I have chopped it up a fair bit. I have a spreadsheet document with literally just one text label control named "size label".
so although the form is laid out in pixels, in order to interact with the lower-level shape layer, the coordinates and sizes need to be translated into whatever unit of measurement is in use at that level. this, as well as and in light of the fact that it's necessary to set the size of a control at least twice, raises a number of design and technical questions, none of which I've found the answer to in any documentation.
1) You only need to change the size in one place - the shape. As you can see from my code below, when the shape size is changed, this propagates to the control. In other words, the calls to SetOutputSize(), SetPosSize() are not necessary (I have wrapped the call to Shape.Setsize() in Ctrl.GetOutputSize() and Ctrl.GetPosSize() which you can uncomment to verify this).

2) I was originally testing with a TextBox and TextLabel and found that the sizes from Ctrl.GetOutputSize() and Ctrl.GetPosSize() were slightly different but this was realted to the TextBox control having a '3D look' set. Just thought I'd mention that as an aside.

3) The unit scaling in general is the most perplexing component here, as you discovered. You are correct that the shape size units are in 100ths of mm (or 1000ths of cm as you said). The mystery to me is the units of the control, but I shall get to that soon.

Just briefly, I think you did the right thing in how you scaled between the two units. However that bit you did about trying to add one pixel by using a mod function on the ratio is unnecessary, and indeed created an error. What you are actually doing there is simply adding one to the ratio, because your code effectively says: 'if the ratio is not an integer, add one to it'. It's highly unlikely to be an integer so one is always added. I seem to always get width ratio of 26.536, and a height ratio of 27.879 (which become 27.536 and 28.879 if you add one). That addition of one results in the label I am testing with, which is about 9cm wide, results in about an extra 0.3cm. Hence the following:
although the edit box ends up having a margin on the left but not the right side of the text that it contains.
The fact that is on the left, and not right, is probably related to control's text alignment property. I would just get the rid of that operation, and if necessary (and it's not on the control I am testing on) add one to the height and width of the PreferredSize before multiplying it by the ratio to get the shape's size.

So back to control's units of measurement. Figuring out exactly what is going on here is something I am stuck on and have no more time at the moment although I am very curious. What I did find is that the call to GetView() 'returns the size of the object in device units'. Unfortunately a call to getGraphics() returns NULL, because no device is set.

However it's obvious some object is using a device that is scaling these controls in some way. For example, if I make my control 10cm by 10cm (right click on the control and select 'position and size'), and give it a colored background, I can see visually that it is not a square. It is higher than it is wider, and I get the following results:
Shape.Width = 10000
Shape.Height = 10000
Control.Width = 359 (WidthRatio = 27.855)
Control.Height = 376 (HeightRatio = 26.596))

All I can confirm is that device units are indeed pixels (I cut an image of the control and measured it in GIMP), but why they are being scaled as they are I am not sure.

I was recently mucking around with the graphics exporter, in order to make a whole page of an Impress document export as a jpeg. This is where I first came across shapes using 100ths of mm. And in that process I had the page's shape, and using the size from that I could use a ratio of 0.0378 to convert that to pixels (or 26.455 for pixels to 100ths of a mm as we are doing here), both horizontally and vertically. That was because:
OOo uses, 1440 twips per inch, which equals 56.7 twips per mm,
The functions TwipsPerPixelX() and TwipsPerPixelY() (both of which return 15 on my system),
Shape is in 100ths of a mm,
Therefore,
PixelsWidth = (1/15) * 56.7 * (ShapeSize.Width/100) [ (pixels/twips) * (twips/mm) * ((mm*100)/100) = pixels ]
PixelsWidth = 0.0378 * ShapeSize.Width

So yeh, why Calc (which is what I am using) has slightly odd display ratios I am not sure... :?

Code: Select all

Sub TestResizing (Event as Object)

	oDoc = ThisComponent
	Controller = ThisComponent.GetCurrentController()
		
	If NOT GlobalScope.BasicLibraries.isLibraryLoaded( "Tools" ) Then GlobalScope.BasicLibraries.loadLibrary( "Tools" )

	labelModel = getControlModel( oDoc.Sheets(0), "size label")
	labelCtl = Controller.GetControl( labelModel )
	labelShape = GetControlShape( oDoc.Sheets(0), "size label" )

	labelPreferredSize = labelCtl.PreferredSize
	
	'the shape size is sometimes very different from the control size.
	'  although this is undocumented it seems to be because the shape size is measured physical dimension units and not pixels.
	ShapeHeightRatio = labelShape.Size.Height / labelCtl.Size.Height
	ShapeWidthRatio = labelShape.Size.Width / labelCtl.Size.Width
	

	labelPreferredSize.Height = labelPreferredSize.Height * ShapeHeightRatio
	labelPreferredSize.Width = labelPreferredSize.Width * ShapeWidthRatio


	'-----------------------------------------------------------
	'labelSize = labelCtl.getPosSize()
	'labelOutputSize = labelCtl.getOutputSize()
	'-----------------------------------------------------------

	labelShape.SizeProtect = False
	labelShape.SetSize(labelPreferredSize)

	'-----------------------------------------------------------
	'labelSize = labelCtl.getPosSize()
	'labelOutputSize = labelCtl.getOutputSize()
	'-----------------------------------------------------------
	
End Sub
OOo 3.1.1 on Ms Windows XP
User avatar
bobban
Volunteer
Posts: 535
Joined: Sat Nov 01, 2008 3:12 pm
Location: Australia

Re: Resizing Form Edit Boxes to the size of their contents

Post by bobban »

Just a small update. I created a 10cm by 10cm text label control in Writer and found:
  • it visually looked like a square
  • it's Width and Height ratios between control and shape sizes were both 26.45 (as I found in Impress)
So again, something is doing some scaling in Calc, but for the purposes of resizing it's irrelevant as long as you take separate width and height ratios as you have done originally.
OOo 3.1.1 on Ms Windows XP
intuited
Posts: 25
Joined: Sat Nov 08, 2008 11:51 pm

Re: Resizing Form Edit Boxes to the size of their contents

Post by intuited »

a quick update here too:
ThisComponent.CurrentController.Frame.ComponentWindow.Info.PixelPerMeterX
and
ThisComponent.CurrentController.Frame.ComponentWindow.Info.PixelPerMeterY
will give you the screen aspect ratio. being somewhat skeptical I've chosen not to use these as a conversion ratio between control-units, ie pixels, and shape-units, mostly because 1000ths of a cm seems like an arbitrary unit that might change in the future. But they do work, at least for my form document -- the ratio they gave, converted to pixels per 1000ths of a cm, is just about equal to what you get by dividing control size by shape size for any given control.

Thanks for the tips on setting the shape size. I've succeeded in doing the resizing that was the original point of this thread. I ended up ditching entirely the bound edit boxes that are built by the form wizard and instead copying everything into labels in a macro. This was in order to have the text background be transparent so I could cut down on empty space. no new revelations on the resizing code so I won't post it. basically I'm just taking the preferred size of each label's control, multiplying it by the ratio, and setting the shape's size to that result.

there is yet another layer of presentation: the Canvas layer. I haven't looked into it much but its services & interfaces are what you'll find in com.sun.star.rendering. I'm guessing its main purpose is to provide platform independence and doesn't do much higher-level stuff.

Thanks again for your help, I'm going to call this one done.
OOo 3.2 on Ubuntu 10.04
longi
Posts: 110
Joined: Mon Jul 15, 2013 5:04 pm

Re: [Solved] Resizing Form Edit Boxes to their size content

Post by longi »

Hi!
I'm really sorry, because my language and my knowledge about programming.
I'm a foreing person and I hardly can speak (write) in English.
I'm writing because I'm really interested in this topic, but I can't understand anything.
Could you put an example ?, especially with a Report?

Thank you in advance.

Bye!
OpenOffice 4.1.5 on Windows 10
LibreOffice 5.1 on Windows 7
LibreOffice 6.0.1 on Windows10
arfgh
Posts: 566
Joined: Tue Mar 05, 2013 6:44 pm

Re: [Solved] Resizing Form Edit Boxes to their size content

Post by arfgh »

hey there friends.

Is there a way to obtain the shape reference from event, whitout to have to call the function 'GetControlShape', that is in fact a loop ?
Just imagine that we have several controls that we want to dynamically change its size. In that case, the given example on this thread is so slow on its execution, and eventually create visual anomalies like form blinkings if all is contained into a group. So i have thought to short that shape finding for our controls to execute that macro fast.

what you guys think about ?
OpenOffice last version | Mageia Linux x64 | Ubuntu Linux | Windows 8.1 Enterprise x64 | Java last version
Post Reply