[Omnis-Newsletter] Omnis Technical Newsletter
omnis-news-admin@omnis.net
omnis-news-admin@omnis.net
Wed, 17 Apr 2002 12:17:43 +0100
April 17th, 2002
========================================
UNSUBSCRIBE OPTIONS: You have been sent this email because you have directly
signed up for, or expressed an interest in receiving a technical newsletter
when you downloaded an evaluation of Omnis Studio, or registered the Lite
version of Omnis Studio. If, however you feel you have received this email
in error you can unsubscribe as well as change your subscription options at
www.omnis.net/newsletter.
N.B. If you subscribed by checking a box on one of our forms, you will not
have received a password. You will need to submit your email address at
www.omnis.net/newsletter and select the 'email me my password' option on the
next page in order to receive this.
========================================
WELCOME!
Welcome and thank you for subscribing to the Omnis Technical Newsletter.
Published fortnightly, it is intended for Omnis developers of all levels and
experience, for those people evaluating Omnis Studio, or for developers
moving from a similar tool. We think you'll find the content both
interesting and useful for your Omnis development needs and hopefully it
will help you become more productive in Omnis application design.
Geir Fjaerli is taking a break this issue, mainly due to work pressures,
deadlines etc. So we turn over the newsletter to David Swain who discusses
how you can create wrapping lists in reports using the powerful report list
component and methods in Omnis Studio. You may find it easier to work
through the exercises and examples in this newsletter by printing it out
before you begin.
CONTENTS:
-About the Author
-RescuePet site Launches
-Wrapping List Fields in Reports, by David Swain
-Omnis in the News
-Copyright and Unsubscribe details
========================================
About the Author
David Swain is the founder and president of Polymath Business Systems, for
many years a leading provider of Omnis training. His expertise in Omnis
programming and his ability to make complex concepts understandable are
recognized throughout the worldwide Omnis community. Latterly, David has
appeared at Omnis Developer conferences providing his own Studio 101
introductory course to Omnis programming and application development.
========================================
RescuePet site Launches
Finally the months of hard work and planning are over for Dr Caroline
Wilkins and her team of helpers and advisors. The RescuePet.org web site was
launched on April 15th: the site will become a valuable resource for animal
lovers and the shelters alike, plus the launch should attract a lot of
publicity in the national press and UK media.
Top Omnis developer Dr Caroline Wilkins has created a web site called
RescuePet.org that will link all UK animal shelters and members of the
public wishing to adopt an animal. Following a competition in ".net"
magazine, the UK's best selling Internet magazine, she won £10,000 of
investment from e-business service provider 'Space' to help her develop and
market the site.
The June issue (#97) of .net magazine will have a full write up about the
RescuePet.org web site, Omnis Studio will also be on the cover CD/DVD
(version 3.01, not the most current of course), plus Caroline has written a
5-page masterclass showing readers how to develop a web application in Omnis
using the Web Client (there's also a competition tied to the masterclass).
So look out for it on your local news stand, or maybe you should subscribe
to the mag!
Please take a look at the RescuePet (www.rescuepet.org) web site and if you
are in the UK maybe you can support it by recommending it to your animal
loving friends or telling the local animal shelter about it. And from an
Omnis development point of view, it's a great example of a web application
that uses the HTML and web client user interfaces available in Omnis Studio.
The current issue of the .net magazine is featured at:
http://www.netmag.co.uk/magazine/default.asp?subsectionid=43
and the CD is described here:
http://www.netmag.co.uk/magazine/default.asp?subsectionid=44
========================================
Wrapping List Fields in Reports
By David Swain, Polymath Business Systems Inc
Email: dataguru@polymath-bus-sys.com
Web: www.polymath-bus-sys.com
------------------------------------------------------------------
In the series of articles I wrote late last year about list display fields,
I neglected to include one about the Wrapping List external component for
reports. This is a fascinating and useful component, so we'll catch up on it
here.
The Wrapping List component offers features that are a combination of those
from some other aspects of Omnis Studio, with a few amazing new twists
thrown in for good measure! Perhaps comparing what it does to some other
features of Omnis Studio with which we are already familiar will help...
Comparisons
The content presented by a Wrapping List field is structured in the same way
we structure the contents of a List Box field on a window. There is a
"::calculation" property (yes, the colon characters are required) that lets
us define a character string that the Wrapping List will display for each
record. We can create "columns" within this string by using the "jst"
function, but this requires that we assign a mono-spaced font for the
field's "fontname" property for those "columns" to properly align - and this
could get confusing in the otherwise "multi-column" nature of the component.
Think of this as a List Box that we can "split" and wrap onto multiple
columns. (The demo should clarify this.)
The record images determined by the calculation mentioned above are then
placed into multiple columns much like in a "Label" report. This has less
power than a label report in some respects and more in others. A label
report places an entire record section (which can be multiple lines high and
include many independently-placed fields) into multiple columns (and the
"Repeat factor" property of the report allows for more than one copy of a
record, if needed) while the Wrapping List component only gives us one
printed line per list line. On the other hand, we have much more control
over the "direction" of the wrapping - label reports can only place records
left to right across the page in their default behavior whereas Wrapping
Lists can place lines either across the field or down its columns. So we can
either choose:
Record 1 Record 2 Record 3
Record 4 Record 5 Record 6
Record 7 Record 8 Record 9
or
Record 1 Record 4 Record 7
Record 2 Record 5 Record 8
Record 3 Record 6 Record 9
And all this is done within a single field that extends horizontally and
vertically as needed! As with the Report Data Grid, we can place lists
formatted with this component within the Record Section on a
record-by-record basis (or in any other section as appropriate) or make it
the basis for an entire report by printing a large list in a single-record
report. The Wrapping List component (when placed in a Record or
subtotal-related section) can span multiple pages and will continue printing
until its contents have all been printed. That is, it is automatically an
"Extending" field even though we would use "Left", "Right" or "Center"
justification for formatting the contents it displays.
It also does some clever things at page breaks - but I'm getting ahead of
myself...
Setup
First let's look at how we set up a Wrapping List field. To do so, we need
to place the field on a Report class. We find this field in the "External
Components" section of the Component Store when we are working on a Report
class.
It is possible that you may not see this component when you first look in
the Component Store. This is because the "Report Lists Library" extension is
not loaded by default and you may not have turned it on for your copy of
Omnis Studio.
If you don't already know, we can open the window that lets us load
extensions in a couple of ways: An "External Components..." menu item is
available from the "Library" menu of the Library and Class Browsers and from
the "View" menu (which is also the context menu) of the Component Store
window when it is working with a Window, Report or Remote Form class in
design mode. This menu item opens the External Components Browser that is
used (among other things) to specify which external components will be
automatically loaded and when. In the list in the upper left corner of this
window, open the "External Components" group and scroll down to the "Report
Lists Library" item. When we select this, the components it contains appear
in the list in the upper right corner of the window, showing us their names,
their icons and their scope (window, report, remote form and/or object). Set
the "Pre-Load Status" of this external component library to "Starting
Omnis", since I assume you will want both the Wrapping List and the Report
Data Grid components readily available once you know how to use them.
Now create a new Report class for testing this component and drag the
Wrapping List component to the Record section of the Report class. One of
the first things we notice about this field is that it is automatically a
"floating" field; that is, it does not automatically snap to the top of the
line on which it is placed. This is typical of Report external components,
as they generally do not include a "floating" property. If there were
another field component already on the desired line, we could either copy
the "top" property value from that other field or use the alignment tools in
Omnis Studio to pull the Wrapping List up to the same vertical position. For
now, though, let's just set the "top" property value to "0.000".
To use the Wrapping List component, we need a list variable. Open the Method
Editor and create an Instance variable named "contentList", making sure its
data type is "List". We will also need some variables to serve as the
columns in the definition of our list (at least to make this an easy
exercise), so create two "Character" variables (again of Instance scope)
named "column1" and "column2". Then set the "dataname" property of the
Wrapping List field to "contentList".
Now we can create a simple $construct method to define and populate our list
variable, sort its contents and print the result. (The sorting will be
important for examining the various "wrapping" options a bit later.)
Although we are testing with a "single record print" technique, we can use a
Wrapping List with any list variable in any section of our report - with
size limitations for headers and footers, of course...
We also need a little fictitious data to flesh out our list and give us
something to report. Put this code in the $construct method to define,
populate, sort and print our list - but don't try to execute it yet because
we still have some setup work to do:
Begin reversible block
Set current list contentList
Clear sort fields
End reversible block
Set sort field column2 (Upper case)
Set sort field column1 (Upper case)
Define list {column1,column2}
Add line to list {('David','Swain')}
Add line to list {('Geir','Fjaerli')}
Add line to list {('Dick','Smith')}
Add line to list {('Bob','Mitchell')}
Add line to list {('Mark','Phillips')}
Add line to list {('Thad','Bogert')}
Sort list
Do $cinst.$printrecord()
Do $cinst.$endprint()
OK, so you tried to print the report anyway and found that it was empty.
This is because we haven't supplied a value for the "::calculation" property
yet. This property is used to specify how the content of each list line will
be displayed on the output. While some list display fields for Window
classes don't require such a calculation (i.e., it's optional for them), the
Wrapping List component has the same need in this regard as a List Box
field. It is best to consider the Wrapping List as a single column list for
purposes of the "::calculation" property; that is, it creates a single
string per line with no built-in column breaks. For our demo, set this
property to:
con(column2,', ',column1)
Test-printing our report now (clicking the "Print To Screen" button on the
Report Editor window) will yield a nice one-column list of our fictitious
name data.
N.B.: A subtle nuance, but it might prove important to you: It appears that
the contents of the "calculation" property are stored as a string. Certainly
the value in the Property Manager field is tested for syntactic correctness
as the focus leaves the field, but variable names are not changed within the
expression if they are changed at their definition point. This indicates
that they are not tokenized when stored. (Just a "heads up" on this...)
Column Properties
But what about the "wrapping" feature? This is handled, in part, by the
properties found under the "Columns" tab of the Property Manager. There are
three properties here:
"columncount" (no colons in this one) sets the number of "columns" into
which our list is split. In the demo displayed earlier in this article, the
value of this property was set to "3".
"::columntype" is used to determine whether the columns will be of a "fixed"
size or whether they will adjust their size upward for long text values.
This property can only accept values of "kRLclmnAutoSize" or
"kRLclmnFixedSize" (or their numeric equivalents of "0" or "1"
respectively).
The value of "::columnwidth" is interpreted as either inches or centimeters
depending on the value of the Omnis Studio root property "usecms". It sets
the width of each column of the Wrapping List component. If "::columntype"
equals "kRLclmnFixedSize", this is the "absolute" width of each column. If
there is not enough room for the full string on a specific line when using
"fixed" column widths, an ellipsis (...) is included to indicate there is
more content that is not currently visible. But if "::columntype" equals
"kRLclmnAutoSize", "::columnwidth" is intended to be the "minimum" width of
each column, allowing the columns to expand if they contain text that
requires more display room.
N.B.: I have found autosizing to not be reliable for the Wrapping List
component (at least on the MacOSX platform), so I recommend treating
"::columnwidth" as a fixed width in any case. If "autosizing" is used but is
not working correctly, the string values are simply truncated with no
ellipsis to indicate there is more content.
For our example, set the "::columntype" property value to "kRLclmnFixedSize"
and the "::columnwidth" property value to either "1.0000" inches or "2.5400"
centimeters. (Feel free to test "kRLclmnAutoSize" and smaller
"::columnwidth" values.)
To prevent column contents merging into one another, we can also set a
"columngap" property (found under the "General" tab in the Property
Manager). This separates the columns by a fixed amount of space in inches or
centimeters. Using this feature is highly recommended as it makes a
multi-column list much easier to read if minimum tolerance is given in the
"::columnwidth" value. This property default to "0.0787" inches or "0.2000"
centimeters as shipped. Note that "columngap" and other "custom" properties
of this component allow for four decimal places instead of the usual three.
Width Property
We set the default width of a Wrapping List field with its "width" property.
As with other report fields, though, the field will expand in the direction
determined by its "rowalign" property (found under the "Text" tab in the
Property Manager) to display the full value for the field. So the actual
width of a Wrapping List will be the number of columns times the column
width (::columnwidth*columncount) plus the space required for the column
gaps (columngap*(columncount-1)). There are also an optional border (with
different width settings) and a "bordergap" value (both of which we will
examine later) that are taken into account. So the width we originally set
is only useful as a "layout" tool in case we want to place other fields next
to the Wrapping List component. It is a good idea to set the "width" value
to a reasonable approximation of its runtime size in such cases - otherwise
it is unimportant.
Wrapping Direction Options
Now for the central theme of this component - how it arranges line images ov
er multiple columns! The "direction" property (under the "General" tab)
determines this. There are three possible values for this property:
When set to "kRLdirectHorz" (numeric equivalent is "2"), the "direction"
property arranges the line images like an Omnis Studio label report. That
is, the images are placed "across" the rows (horizontally) as their primary
placement direction:
Record 1 Record 2 Record 3
Record 4 Record 5 Record 6
Record 7 Record 8 Record 9
Record10 Record11 Record12
Page breaks make no difference in this placement, so the line images will
just continue if the component must span a page boundary:
Record 1 Record 2 Record 3
Record 4 Record 5 Record 6
------------page break--------------
Record 7 Record 8 Record 9
Record10 Record11 Record12
When the "direction" property is set to "kRLdirectVert" (numeric equivalent
is "1"), the line images are arranged "down columns" as their primary
placement direction:
Record 1 Record 5 Record 9
Record 2 Record 6 Record10
Record 3 Record 7 Record11
Record 4 Record 8 Record12
This direction option ignores page breaks, so each column continues on its
merry way, even if the component must print its content onto many pages:
Record 1 Record 5 Record 9
Record 2 Record 6 Record10
------------page break--------------
Record 3 Record 7 Record11
Record 4 Record 8 Record12
The "kRLdirectVertPage" (numeric equivalent is "0") value for the
"direction" property, however, senses page breaks and fills the current page
before beginning to consider the next. For multi-page content, this gives a
"page-wise continuity" that can prove useful in the real world that deals
with the printed output. If no page break is encountered,
"kRLdirectVertPage" is equivalent to "kRLdirectVert". But if a page break IS
encountered mid-component, the output for "kRLdirectVertPage" looks like
this:
Record 1 Record 3 Record 5
Record 2 Record 4 Record 6
------------page break--------------
Record 7 Record 9 Record11
Record 8 Record10 Record12
I find this to be the most useful option and am pleased that it is set as
the default!
Try printing our test report using each of these settings for "direction".
(A much larger list - or font size - will be required to see a difference
between the two vertical options.)
Appearance Options
We have been empowered to create some truly ugly reports with all the
Appearance options of the Wrapping List component! Without getting bogged
down in the details of all these wonderful options, here is a brief
description to start you on your exploration:
We can apply a 3D border to a Wrapping List using any of the border types
for Omnis Studio 3D rectangle objects. (Setting the "bordergap" property
appropriately will keep the body of the list from butting up to the border
edge.) Beyond that, we have additional control over the various constituent
parts of certain border types. For shadow borders, we can independently
control the right and bottom offsets (in pixels) of the shadow as well as
its color. For lined borders, we can control the style and color of the
line. For beveled borders, we can independently control the size (in pixels)
of the inner, outer and center parts of the bevel.
While there are no internal grid lines (as we have with the Report Data
Grid) to separate rows and columns, we can use color to make list contents
more readable. We can set an overall "fillcolor" for the field, but beyond
this we can independently set the "forecolor" and "backcolor" (and a
"backpattern" to dither the two) for the even and odd lines within the
field. There is also an option (the "useoddforselected" property) to use the
color combination for the odd numbered lines to highlight the lines that are
"selected" in the list variable. (Non-selected lines take on the default
background in this case.)
Suffice it to say that we have enough creative control for most presentation
situations.
"selectedonly"
We also have to option to only display the content of selected lines from
our list. We do this by setting the "selectedonly" property value to
"kTrue". Of course, if no lines are selected in that list we will end up
with nothing being printed, so caution should be exercised (as always...).
Text Options
Unfortunately, the Wrapping List does not give us a "fieldstyle" property,
so we must deal with the old "Report Fonts Table" of the library instead. If
you have ignored this aspect of Omnis Studio in favor of the more advanced
"fieldstyle" options, it's time to go back and make sure that you have at
least one viable Report Font slot that is consistent across platforms in
order to successfully use the Wrapping List component in real projects. I
have set up one Report Font that is "Helvetica" (in the appropriate names
for all supported platforms) just for this purpose.
There are five "Text" properties for this component. They are the same five
text properties we see in most other fields, but their names are a bit
different. (It is important to be aware of this in case we intend to
manipulate them using notation!) Here are brief descriptions of each:
The value of "rowfont" MUST be selected from the list provided. Simply
typing a name into the entry field provided will not select a font even if
it is in the list. Selecting from the list actually selects a slot in the
Report Font Table, so a selection is actually being made for each supported
platform no matter which platform is used for design work.
The value of the "rowfontsize" property is expressed in points. It can be
freely entered into the field provided or modified with a simple "Calculate"
or "Do xxx.$assign()" command.
The value of the "rowfontstyle" property is set in the same manner as the
typical "fontstyle" property. The combination of style characteristics is
set by checking the desired ones in the Property Manager. If it is necessary
to modify these through notation, the sum of style constants must be used
(for example, "kBold+kItalic").
The value of the "rowalign" property is one of three alignment constants:
"kLeftJst", "kRightJst" or "kCenterJst". This sets the alignment of the list
content within the component. "Extending" justification is not an option
here because the component is automatically an extending one no matter what
alignment is applied to its contents.
The value of the "rowtextcolor" property is either a color constant or an
RGB value selected from the color palette that appears when we click on the
property value field in the Property Manager.
Using Styled Text
If we set the "::styledtext" property (under the "General" tab) to "kTrue",
we can locally override "rowfontstyle" and "rowtextcolor" and can even
include an icon within a line of a Wrapping List. Set that property value
for our test report and let's have some practical fun!
For this next experiment we'll need a couple of additional instance
variables:
isTechNews Boolean
isEmployee Boolean
Then we need to expand our list definition and content, so change these
seven lines of code in our $construct method as follows:
Define list {column1,column2,isTechNews,isEmployee}
Add line to list {('David','Swain',kTrue,kFalse)}
Add line to list {('Geir','Fjaerli',kTrue,kFalse)}
Add line to list {('Dick','Smith',kTrue,kTrue)}
Add line to list {('Bob','Mitchell',kFalse,kTrue)}
Add line to list {('Mark','Phillips',kFalse,kTrue)}
Add line to list {('Thad','Bogert',kFalse,kTrue)}
Now we have two switches within our list that we can use in some interesting
and useful ways. Suppose we want to display a checkbox icon to indicate
whether a person works on Omnis Tech News. We could change the
"::calculation" property like this:
con(style(kEscBmp,pick(isTechNews,10000,10001)),' ',column2,', ',column1)
This assumes we have the empty and selected checkbox icons that we put in
#ICONS in the previous article on the Icon Editor. We will also want to
increase the "rowfontsize" value to at least "12" so that there is enough
text height to avoid clipping of the 16x16 icons. (We didn't set the size in
the expression above because 16x16 is the default size for these.)
We can take this even further. Suppose we want to indicate which people are
employees using text color (Red for employees and Blue for non-employees).
We could expand the "::calculation" property value like this:
con(style(kEscBmp,pick(isTechNews,10000,10001)),'
',style(kEscColor,pick(isEmployee,kBlue,kRed)),column2,', ',column1)
Hopefully this little exercise will jog your mind a bit and open it to some
of the tremendous possibilities the Wrapping List component offers us. But
there is even another aspect to it that has some intriguing potential.
Table of Contents Style
The Wrapping List component also has a specialized feature that may
occasionally come in handy. This is called the "Table of Contents" or "TOC"
style, but it is not strictly limited to that implied use (as we will soon
see!).
Consider the structure of a Table of Contents on a line-by-line basis. Each
line (usually) has a label on the left end and (usually) another label on
the right end. The left label is often the name of a chapter, section or
subject while the right label is often some combination of page number,
section number and/or chapter number (with appropriate punctuation).
Occasionally, one end or the other (or both) may be left blank.
The gap between the two end labels may be filled with some punctuation
(dotted line, underscores, etc.) or it may be left empty (like an empty
"tab" space). Additionally, some lines may be indented to indicate their
position in the hierarchy of outline levels for the document - and some
lines may be given special emphasis using font size or style variations for
easier reading. These are the features provided by the "TOC" style of the
Wrapping List component.
Of course, there are many other things that might be organized in this
manner: price lists, listings of cast and crew for a theatrical production
or movie, ingredient lists for recipes, bills of material, daily appointment
lists (time and meeting description), etc. So perhaps this component will
prove useful for solving some of the problems posed by these types of
database output requirements.
To properly use the "TOC" functionality, the list variable used with the
component must have five columns in its definition. These columns are
nominally the "Title", "Page Number", "TOC Level", "Font Style" and "Font
Size Adjustment" for each line of the list. The first two columns contain
values that will be printed in the Wrapping List field; the other columns
are used for formatting the content (within certain limitations to be
explained below). It is important to note that this formatting is applied on
a line-by-line basis. The names of the columns are not important, nor are
the associated data types of some columns (which may vary depending on our
specific use of this feature). The generic uses of these columns are as
follows:
Title
The "Title" column contains the content to be placed on the left end of the
line. It can be of any simple data type, but will usually be a character
string so we'll use a Character variable for this column in our demo. Be
aware, though, that number and date-time types (even Booleans) may be used
here if appropriate. Using Character allows us to keep it empty if we need
to - or even allows us to include "style" escape strings in the display
value! (Oh, did I give something away?)
Page Number
The "Page Number" column contains the content to be placed on the right end
of the line. The name may imply it should be a number, but it too can be of
any simple data type. It just depends what we want to put on the right end
of a line - if anything. For greatest flexibility, let's use a Character
variable here too.
TOC Level
The "TOC Level" is used to determine what level of indentation to use for
the line. The amount of indentation is determined by the "tocindent "
property (under the "General" tab), which is expressed in inches or
centimeters like most other positioning and measurement properties. The
indentation ALWAYS occurs on the left side of the content, no matter what
the setting of the "rowalign" property. In fact, the "rowalign" property
appears to have no effect on a "TOC" style Wrapping List.
A numeric variable is most appropriate for this column of the source list.
Since only a small number (well under 255) of indentation levels are likely
to be used, it is tempting to use a Short Integer for this column, but Long
Integer may offer some advantages.
The base level number for indentation is "1". For lines with a "1" in this
column, their text is flush with the left side of the text content of their
column of the Wrapping List area. So the amount of indentation is
(TOCLevel-1) times "tocindent". "0" or negative values "out-dent" the left
end label from the edge of the field. There may be times when this comes in
handy.
Font Style
The value of the "Font Style" column determines the font style for the
entire row. This overrides whatever value is in "rowfontstyle" for the
component, so that property is also ignored by a "TOC" style Wrapping List.
Short Integer is probably the most appropriate data type for this column. We
populate it using font style constants by adding constants to generate a
non-negative integer value with a maximum value of "31". It only takes five
bits to store this value, so a one-byte numeric variable is more than
adequate. Here are the font style constants and their numeric equivalent
values:
kPlain (0)
kBold (1)
kItalic (2)
kUnderline (4)
kOutline (8)
kShadow (16)
For example, if we want a specific line to be bold and italic, we would set
the value of this column in our source list as "kBold+kItalic" or as "3".
Font Size Adjustment
The value of the "Font Size Adjustment" column increases or decreases the
font size of its line (in points) from the "rowfontsize" value of the field
set in the "Text" properties. However this does not affect the actual text
height of the line, so large increases tend to clip the bottom of the text
of the line to the row height (determined from "Rowfontsize" including the
leading for that font size). My suggestion is to set the font size of the
field to the largest size required by any TOC level and use negative numbers
to adjust the size of subordinate line downward.
For example, if we want our major lines to be 18 points high, we would set
"rowfontsize" to "18". If some other line should be only 12 points high, we
set the value of the "Font Size Adjustment" column for that line to be "-6".
Since we want negative integer numbers, we need to use the Long Integer data
type.
Some might object to the fact that lines with font size adjustments retain
the full leading of the default line size. But consider the needs of the
component. It is trying to keep lines aligned across multiple columns, so
this behavior is very appropriate!
Turning It On
To turn on the TOC Style, we just set the value of the "tocenabled" property
for the field (found under the "General" tab) to kTrue. When we do this, we
notice that a number of changes take place. First we notice that the field
takes on a slightly new look: Instead of displaying the name of the
associated list variable, the field shows the word "Title" followed by a
dotted line (whose style happens to be determined by the "toclinestyle"
property).
We then notice that the "::calculation" property is disabled (and that the
"tocindent" and "toclinestyle" properties are enabled). No calculation is
required since the display content is entirely determined by the contents of
the first two columns of the list variable associated with the component.
Let's make another example to test this feature. Create a new Report class
(name it "tocReport1") and drag a Wrapping List component to its Record
section. Set "tocenabled" to "kTrue", "rowfontsize" to "18" ("rowfont" to
"Helvetica" or something similar if you've got it) and "::columnwidth" to
"3.0000" inches or "7.6201" centimeters. Leave "columncount" at "1" for now.
Now create six Instance variables:
tocList List
Title Character
PageNo Character
TocLevel Long integer
FontStyle Short integer
FontSizeAdj Long integer
Set the "dataname" property to "tocList". Now add the following code to the
$construct method of the Report class:
Begin reversible block
Set current list tocList
End reversible block
Define list {Title,PageNo,TocLevel,FontStyle,FontSizeAdj}
Add line to list {('Main Title',1,0,kBold,0)}
Add line to list {('Chapter 1',3,1,kBold+kItalic,-4)}
Add line to list {('Subject x',4,2,kPlain,-8)}
Add line to list {('Chapter 2',9,1,kBold+kItalic,-4)}
Add line to list {('Subject y',10,2,kPlain,-8)}
Add line to list {('Index',16,1,kBold+kItalic,-4)}
Do $cinst.$printrecord()
Do $cinst.$endprint()
Print the report to the screen and look at the result. The first line is
bold and uses an18 point font size (the default for the field). The chapter
lines are 14 points (but on the same total leading as the 18 point line),
bold and italic and indented from the title line (which is technically
"out-dented" from the design boundary of the field). The subject lines are
further indented and in plain 10 point text. All label text entries are
connected to their page numbers by a dotted line.
Now let's see how this style looks with multiple columns. Set the
"columncount" property to "2". Also set the "columngap" property (on the
"General" tab) to "0.3333" inches or "0.8467" centimeters. Now print the
report to screen again. Notice the benefit of the column gap in making this
more readable.
Just for kicks, let's put the "Main Title" entry on the right side of its
line and remove the page number. Set the report back to "1" column and then
change the line in the $construct method that sets the content for the "Main
Title" list line to read:
Add line to list {('','Main Title',0,kBold,0)}
When we execute the report again, we see the "Main Title" text where we
wanted it, but with that dotted line still preceding it. Why don't we turn
that off?
We find the "toclinestyle" property in the "Appearance" tab of the Property
Manager for the Wrapping List component. We can set it to any of the 16
Omnis Studio line styles. Set it to number 16 ("None") for this report. When
we have lines with text only on one end, this seems most appropriate.
Styled Text in TOC Wrapping Lists
So if we can't use the "::calculation" property, how do we use styled text?
Perhaps we'd like all our page numbers to be in plain text, even if the rest
of the content on that line is some other style.
The answer is that we include the "style" tags within the content columns of
our list variable if we set the "::styledtext" property to "kTrue". The
calculations are performed directly in the parameters of the "Add line to
list" command! For example, let's suppose we want to set the page number of
Chapter 1 to be in plain text and a red color. We could change the line of
code that adds that line to our list to read:
Add line to list {('Chapter
1',con(style(kEscStyle,kPlain),style(kEscColor,kRed),3),1,kBold+kItalic,-4)}
The "style" function generates "tags" or "escape strings" that are special
strings of characters recognized by the host program (Omnis Studio) as
containing special formatting instructions. Here we must make them part of
the actual content of our list columns rather than putting that information
in the formatting string of the component itself.
Each line and each end of a line is independent of the others, so we don't
have to "turn off" a style setting to keep it from affecting content that
follows it. For example, if we want the "Subject x" entry set to red, but
not its page number, we only have to precede it with the style information:
Add line to list {(con(style(kEscColor,kRed),'Subject x'),4,2,kPlain,-8)}
If we had done this using the "::calculation" property, we would have had to
set the color back to black before the page number part of the calculation
string.
N.B.: It is worth mentioning that the connecting lines (if you still have
them turned on) are somewhat degraded by applying these style tags. For now
I avoid using them if I have a need for these "special" techniques, but
there may be a way I have not yet discovered to control the display of these
lines on a line-by-line basis - which would be VERY nice!
As with a "normal" Wrapping List, we can include icons in our lines as well
using styled text.
Alternate Uses for TOC Style
Let's consider just one "different" use of the Wrapping List technology to
prime the pump of your imagination. Our task is to print a directory of
members in an organization with the name and telephone number of each member
on the first line of their entry followed by their address information on
the subsequent two lines (like a telephone directory listing). We need this
printed in two columns per page with the records going down the columns in
alphabetic order by family name and given name. Sounds like a job for a
label report, doesn't it? Well, let's see what we can do with the Wrapping
List component instead.
First, we don't need to be tied to only one line in our source list per
record in the database. We just have to keep the lines for the same record
together (and in the proper internal order) if we use more than one. Next,
we don't have to use both labels on a line if some elements (like the
address) require only the left or right label. We just have to avoid
unsightly connecting lines on the output.
To begin, create a new Report class and name it "tocDirectory". Create the
following Instance variables:
tocList List
Column1 Character
Column2 Character
TocLevel Long integer
FontStyle Short integer
FontSizeAdj Long integer
Place a Wrapping List component in the Record section and set the following
properties:
tocenabled kTrue
dataname tocList
direction kRLdirectVertPage
columngap 0.5000 (in) or 1.2701 (cm)
tocindent 0.2000 (in) or 0.5081 (cm)
rowfont Helvetica (or your choice)
rowfontsize 10
toclinestyle 16 (None)
columncount 2
::columntype kRLclmnFixedSize
::columnwidth 3.5000 (in) or 8.8901 (cm)
I'm using the native datafile technique for this demo since everyone reading
this article has this. If you object, just avert your eyes and repeat
"...and then a miracle happened, and then there was data..." or create a
"Select and Fetch" technique or a Pick Basic procedure to retrieve records
in a similar manner to the following. In the $construct method of the Report
class, place the following code (or whatever gets you record images):
Begin reversible block
Set current list tocList
Set main file {Member file}
End reversible block
Define list {Column1,Column2,TocLevel,FontStyle,FontSizeAdj}
Find first on Member file.lastName
Repeat
Add line to list {(con(Member file.lastName,', ',Member
file.firstName),con(mid(Member file.telephoneNumber,1,3),'-',mid(Member
file.telephoneNumber,4,3),'-',mid(Member
file.telephoneNumber,7,4)),1,kBold,2)}
Add line to list {(Member file.streetAddress,'',2,'',0)}
Add line to list {(con(Member file.cityName,', ',Member file.stateCode,'
',Member file.zipCode),'',2,'',0)}
Next
Until flag false
Do $cinst.$printrecord()
Do $cinst.$endprint()
Here is what transpired in pseudo-code:
We retrieved records along an index already sorted in lastname/firstname
order (could have done a Select with an "Order by" clause). We then add
three lines to our source list for each record as follows:
The first line concatenates the last (family) and first (given) name values
with a comma and a space character separating them for readability. We also
parse a ten-digit North American telephone number to include punctuation
that I prefer not to store in the database (used a masked entry field to
gather the data). This line is left at the base level of indentation ("1"),
set to bold text and bumped up two points in size (the safe limit for a
field at 10 points to begin with - this just uses up the extra leading while
emphasizing the name and telephone number part of the listing).
The second line contains the street address. It is indented one level, left
at plain text and the default point size for the field.
The third line concatenates the city, state and postal code with appropriate
punctuation and applies the same formatting as the second line.
The result is a very readable two-column directory. A little tweaking needs
to be done to the size of the page header and footer so that the column and
page breaks don't split record groups of list lines, but that isn't
difficult. (The secret is to make sure that the "top" property is set to
"0.000" of the Record section - because it will be on each subsequent
page...) You may find this solution easier than some of the more advanced
(and seemingly more mystical) techniques I detail in my advanced reporting
classes.
I could go on with other examples, but I don't want to spoil any more of the
fun for you. I hope you have found this subject intriguing - but you must
have if you've read this far...
========================================
Omnis in the News
Omnis Studio will be appearing on one or two magazine cover CDs in the near
future: the June issues of ".net" magazine (as already mentioned) plus
"MacFormat", as well as the July issue of PC Plus. Readers of the magazines
can register with Omnis to receive a serial number for their copy of Omnis
Studio 3.01 as supplied on the cover-mounted CD/DVD. All these magazines are
predominantly UK circulation, but they do reach other parts of Europe and
further afield, especially PC Plus, so Omnis should be getting some good
exposure.
Meanwhile, the UK's best-selling Linux magazine LinuxFormat has reviewed
Omnis Studio 3.1 in the April issue, and Omnis gets an 8/10 overall rating
by reviewer Richard Drummond. In the review he says: "The Omnis IDE is
polished and easy-to-use. A comprehensive set of documentation is provided
as PDFs, and plenty of example and tutorial material is supplied." Then "The
range of prebuilt classes in Omnis is rich...Omnis provides a solid platform
for database-driven and web-based applications." The review is not available
online, but you can go to the LinuxFormat web site (www.linuxformat.com) to
subscribe to the magazine.
========================================
I hope you've found this issue of the Omnis Tech Newsletter both interesting
and informative. Please send me your comments and feedback, and include
suggestions for future articles if you like. We would like to hear from
you...
Regards,
--Andrew Smith.
Omnis Technical Newsletter Editor
Email: editor@omnis.net
========================================
No part of this newsletter may be reproduced, transmitted, stored in a
retrieval system or translated into any language in any form by any means
without the written permission of Raining Data.
(c) Copyright Raining Data, Inc., and its licensors 2002. All rights
reserved.
Omnis(r) is a registered trademark and Omnis 7(tm), and Omnis Studio are
trademarks of Raining Data UK Ltd. Other products mentioned are trademarks
or registered trademarks of their corporations.
========================================
To unsubscribe from this newsletter or change your subscription options,
please go to:
www.omnis.net/newsletter