Tomato Cans - Word-Wrapping Strings, and You

by Jeff Slarve

Published 1997-11-01    Printer-friendly version

Download the code here

I hate limitations. I really do. No matter what I am trying to do, there is always something – that one little simple thing that turns a simple 2-minute job into a chaotic jumbling of decisions about which alternative would be the best. Sometimes it takes longer to just think about which course to take then it does to actually take the course. I guess that is what they call experience. Personally, I would rather do away with some of that experience and turn it into free time. Or perhaps money.

Experience

A while back, I needed to place some text on a window. This text was to be display only., and it needed to take up several lines. Of course, my first thought was TEXT control. (Actually, it was really "It has been 5 whole minutes since I logged onto Compuserve. I wonder if I have any e-mail waiting."). Anyway, I went through the motions, and populated a TEXT control on the window because it handles word wrapping and can handle a lot of characters. The trouble is, no matter what you do with a text control, it just doesn’t look good for display-only text. To me, text controls always look like something that you can/should type something into (mostly because they are, I suppose). I tried setting the control to transparent (yech), toggling the VSCROLL attribute, different colors, skip, readonly, but it just didn’t look good. Geez. All I wanted was to put some text on the window, not build a rocket.

Okay, what are my other alternatives? PROMPT controls are display-only and word wrap. Sounds like just what I want. The trouble is, is prompts are, well, prompts. They can’t USE() a variable, they treat the ampersand (&) character funny, they are limited to 255 characters, and I know a prompt that owes me money. I just found the prompt to be too limiting. What else is there? There is the STRING control. Ugh. The string doesn’t word-wrap, and is limited to 255 characters. I suppose I could place 50 strings on my window and place them "just so" on the window and try not to accidentally drag one the wrong way in the window formatter. It was looking like there was no Clarion control currently available to handle what I wanted.

Why is such a simple thing turning into a "check the e-mail every 5 minutes" ordeal? Gosh, I hate experience sometimes.

Take a deep breath

Since I had already wasted a good amount of time messing with existing controls, it was looking like a great time to go out to the work shed and pull out my pal the tomato can (see the "Looks like a slider" article from issue #1). It was time to re-think this simple objective and develop a plan.

  • First, I had to determine exactly what I wanted to do, which was to put readonly, wordwrapping, neat looking, non-selectable, and plentiful text on the window.
  • Next, I had to determine what I didn't want to do, which was to use a TEXT control, PROMPT, or STRING on the window. I had enough of that.

Basically, between the TEXT and STRING controls, there were properties from each that I wanted:

  • Automatic word-wrap: TEXT
  • Able to handle more than 255 characters: TEXT
  • Readonly: STRING
  • Non-selectable: STRING
  • Non-corrupted transparent attribute: STRING

Now how am I going to gain the benefits from each of these without having to put up with the undesirable stuff? Luckily, Clarion has ability to create controls and set their properties at run-time. Perhaps if I could use the TEXT control to handle the word-wrapping magic, I could read each line of text in the control and transfer it over to multiple STRING controls. That still sounds like a lot of work, but if I write a PROCEDURE to handle all of this for me, then at least it won’t be me doing the work. That I like.

Finally, a solution.

Making it work

As with many of my "Tomato Can, slap it together and make it work" projects, things get written and re-written many, many times. Balancing functionality with speed and efficiency is especially difficult in situations like this. Balancing whether or not it is worth the extra time to make it happen – you don’t want to ask me that…

When a TEXT control displays text and handles it’s word-wrapping magic, it is all done automatically. Once it is loaded, the Clarion programmer has access to the properties of the text control. What I did, was write a Clarion procedure to read all of the pertinent properties from the TEXT control, and transfer them to the STRING controls. With this procedure, all a Clarion programmer needs to do is pass the field number of the TEXT control, and it will sort of "convert" the text control into multiple string controls, inheriting the FONT, POSITION, and TEXT properties. Since Clarion is so fast, this is all done with very little noticeable "flicker".

The Class

Each "Wrapping String" instance has its own instance of the JSStringWrapClass. This is a simple OOP class that manages the creation and refresh of the string controls. Since this is "new" code, you may need to salt it to taste.

The code for the class is in the JSSTWRAP.CLW file. It, along with the header file (JSSTWRAP.INC), should be located in your \libsrc directory. Here is the source from JSSTWRAP.INC.

JSStringWrapClass     CLASS,TYPE,MODULE('jsstwrap.clw')
FirstCtl                SHORT !The first string control
LastCtl                 SHORT !The last string control
FEQ                     SHORT !The Text box
LineCnt                 BYTE !Number of lines
Init                    PROCEDURE( Short FEQ )
Refresh                 PROCEDURE
Hide                    PROCEDURE
UnHide                  PROCEDURE
                      END

As you can see, there is very little to this. The INIT() method handles all of the creation of the string controls. It examines the TEXT control to see how many lines, what font, how high, how wide, how cool, etc... It then uses this information to create the string controls. This is only done one time. After the INIT() method has done it’s thing, the REFRESH method updates the text of each string control according to what is contained in it’s respective line from the TEXT control. Just saying it makes it sound a lot more complicated than it really is.

The Hide() and UnHide() methods each do stuff that I can’t remember. Oh yeah: they Hide() and UnHide() the string controls. That way, you (the programmer) don’t have to know the field numbers for each control if you happen to want to hide/unhide the string controls.

The template

The template for this class is extremely simple. Just add the GLOBAL extension to your application, and then you can place the CONTROL template on your window where you want the word-wrapping string. The control that gets populated by the template is a TEXT box. This text box will not be visible when the program is running. All you have to do is size the textbox where you want the word-wrapping text to be, then fill in the prompts in the control template. That is it! Just compile and go.

Wiping off the sweat

Every now and then, when what you want isn’t quite there, sometimes you have to just take a deep breath, step back, and re-assess the situation. Maybe you are going at it the hard way. Take that moment to assess the goal, available tools, and the time. Usually the answer is there. It might take a couple of tomato cans and some bailing wire, but the answer is there somewhere, be it a workaround for a bug, an unconventional requirement, getting around a limitation, or whatever. Maybe you will end up with some neat tools that you will be able to use for a long time to come. Maybe not. Most likely, you will have fun.

Printer-friendly version

 
 

Search

 

Advanced Search
Topical Index

Related Articles

Subscribe to
ClarionMag

One year: $184

(includes all back issues since '99)

Renewals from $134

Two years: $274

Renewals from $224

More Info

Subscribe Now!

ClarionMag Blog

RSS Feeds

Updates via Email

Enter your Email


Powered by FeedBlitz

Quick Links