width

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

width

pablo digonzelli
Hello all !!!.
I have a View , really StaticText view. I am displaying  a text on it.
I want to set the width of the view in function of the text i'm displaying
in.
i use width: (text size * font pontSize)  method on the view.
but, the view don't  adjust exactly to the text.
it is a little wider .

My question is: How can i adjust more exactly the size of the view.

TIA
Pablo


Reply | Threaded
Open this post in threaded view
|

Re: width

Andy Bower
Pablo,

> I have a View , really StaticText view. I am displaying  a text on it.
> I want to set the width of the view in function of the text i'm displaying
> in.
> i use width: (text size * font pontSize)  method on the view.
> but, the view don't  adjust exactly to the text.
> it is a little wider .
>
> My question is: How can i adjust more exactly the size of the view.

The reason why your original attempt at resizing the view does not work
correctly is becase #pointSize returns the *height* of the characters and
not the width. The difficulty is that most fonts are "proportional", that is
their characters are different widths (e.g. an M is bigger than an i). In
order to find the width of a particular string you will have to ask for the
text size of the whole string, as calculated by a Canvas using #textExtent:.
Here's an example:

"Build a shell with a text field in it"
shell := ShellView new create.
textEdit := shell addSubView: TextEdit new.
shell show.

"Now set the text edit contents"
textEdit value: 'Hello, this is a line of text'.

"Compute the size of the text string (note this is a Point)"
size := textEdit canvas textExtent: textEdit value. "Display it"

"Set the width of the text view to the width of the string"
textEdit width: size x.

Best Regards,

Andy Bower
Dolphin Support
http://www.object-arts.com

---
Visit the Dolphin Smalltalk WikiWeb
http://www.object-arts.com/wiki/html/Dolphin/FrontPage.htm
---


Reply | Threaded
Open this post in threaded view
|

Re: width

pablo digonzelli
Thanks a lot Andy !!!
Pablo
"Andy Bower" <[hidden email]> wrote in message
news:98if7j$20l62$[hidden email]...
> Pablo,
>
> > I have a View , really StaticText view. I am displaying  a text on it.
> > I want to set the width of the view in function of the text i'm
displaying

> > in.
> > i use width: (text size * font pontSize)  method on the view.
> > but, the view don't  adjust exactly to the text.
> > it is a little wider .
> >
> > My question is: How can i adjust more exactly the size of the view.
>
> The reason why your original attempt at resizing the view does not work
> correctly is becase #pointSize returns the *height* of the characters and
> not the width. The difficulty is that most fonts are "proportional", that
is
> their characters are different widths (e.g. an M is bigger than an i). In
> order to find the width of a particular string you will have to ask for
the
> text size of the whole string, as calculated by a Canvas using
#textExtent:.

> Here's an example:
>
> "Build a shell with a text field in it"
> shell := ShellView new create.
> textEdit := shell addSubView: TextEdit new.
> shell show.
>
> "Now set the text edit contents"
> textEdit value: 'Hello, this is a line of text'.
>
> "Compute the size of the text string (note this is a Point)"
> size := textEdit canvas textExtent: textEdit value. "Display it"
>
> "Set the width of the text view to the width of the string"
> textEdit width: size x.
>
> Best Regards,
>
> Andy Bower
> Dolphin Support
> http://www.object-arts.com
>
> ---
> Visit the Dolphin Smalltalk WikiWeb
> http://www.object-arts.com/wiki/html/Dolphin/FrontPage.htm
> ---
>
>


Reply | Threaded
Open this post in threaded view
|

Re: width

Chris Uppal-3
In reply to this post by Andy Bower
Andy,

> shell := ShellView new create.
> textEdit := shell addSubView: TextEdit new.
> shell show.
> textEdit value: 'Hello, this is a line of text'.
> size := textEdit canvas textExtent: textEdit value. "Display it"
> textEdit width: size x.

I've just tried this on my machine here, and it results in the TextEdit
being about 25% wider than it needs to be.

It doesn't actually matter to me (since I don't use this technique) but
it might be indicative of another place where Dolphin/Windows is not
picking up the actual font in use ?

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: width

pablo digonzelli
Andy,
I try and found the same as Chris

"Chris Uppal" <[hidden email]> wrote in message
news:98nvkm$jk5$[hidden email]...

> Andy,
>
> > shell := ShellView new create.
> > textEdit := shell addSubView: TextEdit new.
> > shell show.
> > textEdit value: 'Hello, this is a line of text'.
> > size := textEdit canvas textExtent: textEdit value. "Display it"
> > textEdit width: size x.
>
> I've just tried this on my machine here, and it results in the TextEdit
> being about 25% wider than it needs to be.
>
> It doesn't actually matter to me (since I don't use this technique) but
> it might be indicative of another place where Dolphin/Windows is not
> picking up the actual font in use ?
>
>     -- chris
>
>


Reply | Threaded
Open this post in threaded view
|

Re: width

Blair McGlashan
"pablo digonzelli" <[hidden email]> wrote in message
news:98o6ks$2sbfp$[hidden email]...

> Andy,
> I try and found the same as Chris
>
> "Chris Uppal" <[hidden email]> wrote in message
> news:98nvkm$jk5$[hidden email]...
> > Andy,
> >
> > > shell := ShellView new create.
> > > textEdit := shell addSubView: TextEdit new.
> > > shell show.
> > > textEdit value: 'Hello, this is a line of text'.
> > > size := textEdit canvas textExtent: textEdit value. "Display it"
> > > textEdit width: size x.

There are two problems with this:
1) View>>canvas doesn't actually set the Font of the supplied Canvas to the
actualFont of the view, so the calculated extent will be for the default
system font.
2) The width needs to be the window width, not the client width, so width of
the text needs to be adjusted (expanded) to allow for the adornment.

    shell := ShellView new create.

    shell layoutManager: FlowLayout new.

    t := shell addSubView: TextEdit new.

    t value: 'Hello, this is a line of text'.

    size := t canvas font: t actualFont; textExtent: t value.

    t extent: (t calcExtentFromClientExtent: size+2).

    t2 := shell addSubView: TextEdit new.

    t2 value: 'and this another'.

    size := t2 canvas font: t2 actualFont; textExtent: t2 value.

    t2 extent: (t2 calcExtentFromClientExtent: size+2).

    shell show


Why is it necessary to add 2? Not sure, but then I was never very good with
off-by-one errors, so off-by-two errors confuse me totally :-). Actually I
vaguely remember something screwy about the Win32 API AdjustWindowRect
(which underlies View>>calcExtentFromClientExtent:), so maybe its about time
I went back to the API documentation.

Is it a good idea for View>>canvas to answer a canvas that isn't configured
with the font one has specified for the View (or that which it inherits)?
Not sure, its always worked like that but I don't know the reason or whether
it is deliberate or not.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: width

pablo digonzelli
It is working OK

"Blair McGlashan" <[hidden email]> wrote in message
news:98o9ph$2rsb7$[hidden email]...

> "pablo digonzelli" <[hidden email]> wrote in message
> news:98o6ks$2sbfp$[hidden email]...
> > Andy,
> > I try and found the same as Chris
> >
> > "Chris Uppal" <[hidden email]> wrote in message
> > news:98nvkm$jk5$[hidden email]...
> > > Andy,
> > >
> > > > shell := ShellView new create.
> > > > textEdit := shell addSubView: TextEdit new.
> > > > shell show.
> > > > textEdit value: 'Hello, this is a line of text'.
> > > > size := textEdit canvas textExtent: textEdit value. "Display it"
> > > > textEdit width: size x.
>
> There are two problems with this:
> 1) View>>canvas doesn't actually set the Font of the supplied Canvas to
the
> actualFont of the view, so the calculated extent will be for the default
> system font.
> 2) The width needs to be the window width, not the client width, so width
of

> the text needs to be adjusted (expanded) to allow for the adornment.
>
>     shell := ShellView new create.
>
>     shell layoutManager: FlowLayout new.
>
>     t := shell addSubView: TextEdit new.
>
>     t value: 'Hello, this is a line of text'.
>
>     size := t canvas font: t actualFont; textExtent: t value.
>
>     t extent: (t calcExtentFromClientExtent: size+2).
>
>     t2 := shell addSubView: TextEdit new.
>
>     t2 value: 'and this another'.
>
>     size := t2 canvas font: t2 actualFont; textExtent: t2 value.
>
>     t2 extent: (t2 calcExtentFromClientExtent: size+2).
>
>     shell show
>
>
> Why is it necessary to add 2? Not sure, but then I was never very good
with
> off-by-one errors, so off-by-two errors confuse me totally :-). Actually I
> vaguely remember something screwy about the Win32 API AdjustWindowRect
> (which underlies View>>calcExtentFromClientExtent:), so maybe its about
time
> I went back to the API documentation.
>
> Is it a good idea for View>>canvas to answer a canvas that isn't
configured
> with the font one has specified for the View (or that which it inherits)?
> Not sure, its always worked like that but I don't know the reason or
whether
> it is deliberate or not.
>
> Regards
>
> Blair
>
>


Reply | Threaded
Open this post in threaded view
|

Re: width

Blair McGlashan
Pablo

You wrote in message news:98oeld$2rmu6$[hidden email]...
> It is working OK
>

Certainly that is true for small fonts, but I looked into it a bit more (to
see why that extra 2 pixels width was necessary) and this time I first
engaged my brain and thought about what the extent needed to take account
of:

1) EDIT controls seem to implicitly have space for a border. There is an
reference to this in the MFC source code, which has a specialised
implementation of their window rect. calculation method which passes
WS_BORDER to AdjustWindowRectEx. We therefore need to override
TextEdit>>calcRectangleFromClientRectangle:
2) EDIT controls have left and right margins (see MSDN help for
EM_GETMARGINS). The control calculates these from the text metrics of the
font specified for the control, although the precise algorithm is not
specified.
3) The EDIT control allows for the 'external leading' font metric when
calculating the base line.

I looked more closely at the TextEdit class and found the #calculateExtent
method, which appears to be intended to calculate the window extent required
for the current text/font combination. However it doesn't correctly take
account of the Font due to a bug in the way it accesses the font, and it
also ignores the margins and external leading. I've attached a "fixed"
version. If anyone can think of any further subtleties the calculation needs
to account for, please let me know.

If you file in the code below then the #calculateExtent method of TextEdit
will answer what I think is the correct extent for the text currently in the
control, regardless of the Font used.

Note that #calculateExtent is a private method, but if you set the
#usePreferredExtent: aspect of the control to true, then the public method
#layoutExtent will answer the calculated extent. So revising my example
code, and with the patch applied:

shell := ShellView new create.
shell layoutManager: FlowLayout new; height: 200.
2 timesRepeat: [ | t f |
    t := shell addSubView: TextEdit new.
    f := Font choose.
    t usePreferredExtent: true; font: f; value: f displayString.
    t extent: t layoutExtent].
shell show

Its a shame that Microsoft don't document more clearly the calculation that
an EDIT control uses to decide the formatting rectangle for text as if they
did then trial and error wouldn't be necessary to discover it. On the other
hand Smalltalk is ideal for trial and error experimentation, and it was fun!

Regards

Blair

------------------------
!TextEdit methodsFor!

calcRectangleFromClientRectangle: aClientRectangle
 "Private - Given a client <Rectangle>, answer the required window rectangle
 that would be required to achieve this taking into account the current
window
 styles etc.
 Implementation Note: We must override because of EDIT controls implicit
 border."

 | rect |
 rect := RECT fromRectangle: aClientRectangle.
 UserLibrary default
  adjustWindowRectEx: rect
  dwStyle: self baseStyle | WS_BORDER "implicit border"
  bMenu: false
  dwExStyle: self extendedStyle.
 ^rect asRectangle! !
!TextEdit categoriesFor:
#calcRectangleFromClientRectangle:!geometry!private! !

!TextEdit methodsFor!

calculateExtent
 "Private - Answer a calculated preferred extent for the receiver."

 | canvas extent leading margins |

 canvas := self canvas.
 canvas font: self actualFont.
 extent := canvas textExtent: self plainText.
 leading := canvas textMetrics tmExternalLeading.
 canvas free.

 margins := self margins.
 extent := extent + ((self margins first + self margins last)@leading).

 "Now adjust required client extent to window extent"
 ^self calcExtentFromClientExtent: extent
! !
!TextEdit categoriesFor: #calculateExtent!geometry!private! !

Win32Constants at: #EM_GETMARGINS put: 16rD4!

!TextEdit methodsFor!

margins
 "Private - Answer the left and right margins."

 | dword |
 dword := self sendMessage: EM_GETMARGINS.
 ^Array
  with: dword highWord
  with: dword lowWord! !
!TextEdit categoriesFor: #margins!constants!private! !