Powerpoint like GoText

Hi,

i would like to have texts (GoText) in my app, which behave like textboxes (multline, wrapping) in MS Powerpoint & co:

  • When entering text the height automatically increases when a line break (by wrapping or manually) is inserted.
  • They should have a min size limited to the text bounds (dependent of wrapping or not). So text will never have to be clipped at the bounding box.
  • The user should be able to enlarge the width and the height.

Because i was not able to do this by setting the values of some GoText properties, i tried to override some methods but found most of them declared as private :( And even internal properties of a view are used. Can you please tell me how i can implement this behaviour.

Many thanks in advance.

Best regards,
Joern

Try these settings:

Multiline = true
Wrapping = true
WrappingWidth = 150 (or whatever you want here)
Editable = true
EditableWhenSelected = true (optional, but I like this one. only goes into edit mode if already selected)
That should give you requirements 1 and 2.
Requirement 3 isn't clear to me. Do you want resizing the bounding box to grow/shrink the text inside? You probably want
AutoRescales = true
AutoResizes = true
Resizable = true
Reshapable = true
and probably
ResizesRealtime = true
Open up Demo1, and play with the GoText objects in the upper left using the F4 properties dialog.

Hi Jake,

thank you for your fast reply but it is the thing i have already.

Multiline = true;
Wrapping = true;
Editable = true;
AutoRescales = false;
Resizable = true;
Reshapable = true;

AutoResizes has to be false i guess. If it is true user anyway can change the size of the textbox with mouse (i dont know why) – and after deserialization the bounds of the textbox are set to the minimal bounding box of the text.

Requirement 3 in other (more) words:
User places a textbox on a view. Textbox has a height of one text line and a width of at least the default text. The user should be able to change the width and height of the text box but it must not become smaller than the text (text should not needed to be clipped).
If user starts to edit the text the width of the textbox will not change (because wrapping is true) and the height will automatically increase if more lines of text are displayed than fit to the box. If text cursor is at the end of the text and user presses enter, the box’s height will increase to display the additional line of text.
If user terminates edit mode, he will be able to change the width and height of the textbox. Both values can be increased. If width will be decreased, the height of the textbox will be increased if necessary. As long as the text height fits in the bounding box, it can be decreased.

In short: The size of the text box can be changed, but under no circumstances it should be possible to make the box smaller than the text portion (that it will be clipped).

I tried to start to reimplement your GoText methods:
computeHeight
computeWidth
FindFirstLineBreak
fitsInBox
getLineHeight
getStringFormat
getStringWidth
measureString
recalcBoundingRect

I had to abort because recalcBoundingRect uses document.WorldScale – which is declared as internal!

Why are all of them declared private or internal? If some of them had been protected i would have had a good starting point.

And why is a methode like UpdateSizeOrScale declared as private allthough it is use in nearly every property-set-routine?

And because UpdateSize is only executed when AutoResizes is true and UpdateScale is only executed when AutoRescales is true, the property LineCount allways returns 1 if AutoResizes and AutoRescales are false. Is that intended behaviour or eventually a bug?

It would be great if you have any idea how i can start to fullfill the ‘in short’ requirement.

Best regards,
Joern

No, you want AutoResizes to be true.

Grabbing resize handle doesn't change the WrappingWidth, so you might want to override the resizing behavior to set that parameter to get closer to PP behavior.
While editing, the editing control won't get taller if you add a new line... the text scrolls off the top. But when editting is completed, you see the right thing.
In PP, you can't change the height of a text box with resize from what I can see... only the "wrapping width".
I really don't understand why you're down the weeds rewriting GoText... except for resize not setting wrapping width, I don't see what you're missing.
oh... I see one thing. If you resize a GoText smaller than the text, it will clip the contents. Well, PP lets you do that too, but on the mouse-up, it sets the WrappingWidth and reformats the text to be as long as it needs to be to fit. If you add the "set WrappingWidth to resize behavior" to your GoText (as I mentioned ealier), you'll get the same behavior.

Perhaps the main thing that Joern wants is a custom System.Windows.Forms.TextBox control that has the behavior he describes.

Talking about features of GoText or about reimplementing GoText would be unrelated to such a TextBox control.

For the one (?) issue about the user’s manual resizing feature of GoText, you can probably implement that easily enough in an override of GoObject.DoResize. Assuming that such manual resizing is trying to resize the GoText, not the TextBox control.

No, the size of the .net textbox while editing text is not important for me. It can be initialized with wrappingwidth and height of current bounding box – like it is already. I don not need a real inplace text editing. It is kind of eye candy ;)
Only my GoText.Bounds need to fullfill my requirements.

I still think that my GoText needs to be AutoResized=false. If i set it to true the bounds can not be changed by user. They allways snap back to minimal bounding box – at least when deserializing a document. I did not find a sequence of setting the properties which maintains original bounding box.

So i have to override DoResize to handle manul resize of the GoText bounds. This is a thing i know i have to do, and i have done it several times so far with different implementations.
This time i need to implement a custom resizing which needs the height of the text in pixel. All methods i would like to use are implemented in GoText but not accessable because they are private or internal:

  • LineCount for calculating min height to show all text. GoText implementation of LineCount can not be used because it is always 1 (because AutoResizes and AutoRescales are both false).
  • computeHeight (private)
  • FindFirstLineBreak (private)
  • maybe fitsInBox (private)
  • getLineHeight (private)
  • getStringFormat (private)
  • measureString (private)

I tried to reimplement these methods, but at some point your implementation uses Document.WorldScale which is inaccessable too. I dont exactly know what it is for but the annoying fact is, i can not use this function. I could try to leave it out, but what functionallity will get lost?

So, i dont know how to start, writing a correct computation of needed
minimal height of the GoText. That is the thing i was trying to say the
two posts before.

And i need to compute and eventually change the height of the GoText when the needed height (pixel) of the text changes. It is the case for the properties Text, Font, Wrapping… UpdateSizeOrScale is executed after all such changes. So i had the idea
i just need to override UpdateSizeOrScale – but it is private.
So i think i need to override all these properties to insert my UpdateHeight methode.

Best regards,
Joern

This is a long holiday weekend, so Jake will answer next week.

In any case, thanks for the clarification as to what you want. Offhand I don’t see any serious problem, nor any need to override lots of methods. But Jake will investigate.

You need autoresizes=true to get the box to resize around the text after editing. Without that, you go down the path of trying to tweak this and that in a class that wasn't designed for that kind of tweaking.
Try the code below. I think the "feel" is pretty close to PP.
[code]
[Serializable]
public class PowerPointText : GoText {
public PowerPointText() {
Resizable = true;
Multiline = true;
Editable = true;
EditableWhenSelected = true;
Wrapping = true;
AutoResizes = true;
//ResizesRealtime = true; // powerpoint doesn't do this.
}
public override void DoResize(GoView view, System.Drawing.RectangleF origRect, System.Drawing.PointF newPoint,
int whichHandle, GoInputState evttype, System.Drawing.SizeF min, System.Drawing.SizeF max) {
base.DoResize(view, origRect, newPoint, whichHandle, evttype, min, max);
if (evttype == GoInputState.Finish) {
InvalidBounds = true;
float width = this.Width;
if (width <= 30) width = 30;
WrappingWidth = width + 1; // +1 ensures it isn't a no-op
}
}
public override void SetSizeKeepingLocation(SizeF s) {
if (s.Width < this.WrappingWidth) s.Width = this.WrappingWidth;
base.SetSizeKeepingLocation(s);
}
}

[/code]

Hi Jake,

thanks for the code. The GoText behaves similar to my requirements. Propably i will use it for a start. Only two thinks are missing in this implementation:

  1. Height of bounding box is fix to the calculated min value and can not be increased.
  2. The ‘+1’ hack increases width continuesly. I implemented text rotation and if text rotates (via button click) width gets larger with every click. So i think i have to try a ‘+1 -1’ hack :(

And i see that GoText perhaps is not made for my kind of customization – i would not call it tweaking. But obviously i can not implement my own PowerpointLikeText (derived from GoObject) because document.WorldScale is missing. What is it for? What can i use instead?

Best regards,
Joern

actually, the +1 hack was in there for handling realtime resizing, I think you can pull that if that isn’t enabled.

No, it is not the same. I set ResizesRealtime = false of your implementation (i added to your demo1 example). After adding a JakeText Wink to the document everything was ok until i enlarged the width of the JakeText. After that i was able to enlarge height with dragging bottom middle handle. It resets to text height when i change the width again. So, it does not work. And again: If i had been able to execute UpdateSizeOrScale, there would not have been the need to simulate a WrappingWidth change by adding 1.

What about the WorldScale-Questions in my last two posts?

You can assume that that value is 1.

However, re-implementing GoText as you suggest will mean that you won’t automatically get improvements and bug fixes as they come out in future versions.

Does the following do something like what you want?

[code] [Serializable]
public class PowerPointText : GoText {
public PowerPointText() {
this.Alignment = MiddleTop;
this.Resizable = true;
this.Multiline = true;
this.Editable = true;
this.EditableWhenSelected = true;
this.Wrapping = true;
this.AutoResizes = true;
// in case user forces height to be too short:
this.StringTrimming = StringTrimming.EllipsisCharacter;
this.Clipping = true;
}

public override void DoResize(GoView view, System.Drawing.RectangleF origRect, System.Drawing.PointF newPoint,
                  int whichHandle, GoInputState evttype, System.Drawing.SizeF min, System.Drawing.SizeF max) {
  base.DoResize(view, origRect, newPoint, whichHandle, evttype, new SizeF(30, 15), max);
  if (evttype == GoInputState.Finish) {
    SizeF size = this.Size;
    this.WrappingWidth = size.Width;  // may resize
    this.Size = new SizeF(size.Width, Math.Max(this.Height, size.Height));
  }
}

}[/code]

Hi Walter,

if i do not need to re-implement a GoText-like text element, i will be happy to take advantage of improvements oder bug fixes Smile

Your implementation of PowerPointText tries to allow user to increase height of the GoText. I changed two things and i am very close to to required behaviour:

  1. Removed StringTrimming and Clipping from constructor. I do not need trimming. And clipping results in a bottom cut off of the ‘long’ letters q, p, g and y.

  2. I had to change your simple assignment of WrappingWidth to

this.WrappingWidth = size.Width + 1; // may resize this.WrappingWidth = size.Width; // may resize
If this is not done decreasing height of PowerPointText behaves different on moving bottom-right handle and bottom-middle handle.

The ‘+1 -1’ hack is not the best code and unfortunatly after deserializing the height of the PowerPointText will be set to minimal height (to fit the text). I guess that it is based on the implementation of UpdateSize, because all relevant properties will be set while deserialization. So i had to remove the changable height.

In summary: i had another expectation what AutoResizes does or what it can be used for. I did not expect that it is a legal way to manipulate bounds of an AutoResizing object. But now it is clear Smile

Best regards,
Joern