Bit by Bit: Resizing and Scroll Bars
Stephen Beaulieu <hippo@be.com>

Last week's installment of Rephrase showed you how to open
large files. Now you need an easy way to view the file's
contents. Although BTextView provides keyboard navigation
(PageUp and PageDown), scroll bars and a resizable window
are more useful, so we'll add them this week.

You'll find this version of Rephrase at:

<ftp://ftp.be.com/pub/samples/tutorials/rephrase/rephrase0.1d3.zip>

Rephrase 0.1d3
New Features
Resizable Windows
Scroll Bars
"Intelligent" Window Sizing


Programming Concepts

A frame rectangle is the size and position of a window or
a view in its parent's coordinate space. For a window this
is the screen; for a view it is its window or parent view.
It is the rect where the object is responsible for
displaying itself.

When the frame rectangle of a window or a view changes,
a frame event message is sent. Windows and views that
have the B_FRAME_EVENTS flag receive these messages and
the FrameResized() or FrameMoved() hook functions are
called. The functions themselves are straightforward:
FrameResized() reports the new width and height of the
rectangle; FrameMoved() informs the object of its new
position in its parent's coordinates (the screen for a
window or the view's parent).

Currently Rephrase doesn't care about FrameMoved() calls.
FrameResized() calls are another matter. The phrase display
window responds to FrameResized() calls to adjust the size
of the text view's text rectangle. The BTextView also cares
about FrameResized() messages; it uses them to update any
scroll bars that might be targeting the view.

Scrolling a view changes the portion of its contents
visible in a view's frame. BScrollBars are BViews that
visually represent the section of the display view shown
and provide a means to scroll that view. BViews and
BScrollBars interact to keep in sync: BScrollBars call
BView::ScrollTo() and BView::ScrollBy(), and BViews call
BScrollBar::SetValue().

BTextView takes this interaction a bit further. When the
content in a text view changes, it will update the value,
proportions, and ranges of any BScrollBar targeting it.
All the work is done by the BTextView; just create the
BScrollBars and target the text view.


Implementation details:

1. pDisplay now has a BTextView * member, fEdit. This is
   used throughout the window to access the text view.
   [pDisplay.h:20]

2. pDisplay now creates its BWindow superclass with a
   document window look and removes previous restrictions
   on zooming and resizing.
   [pDisplay.cpp:27-28]

3. BuildMenus() is a new function that encapsulates
   building the main menu bar. It was introduced mainly
   for readability purposes.
   [pDisplay.cpp:209-232]

4. pDisplay::FrameResized() adjusts the size of the text
   rectangle in the text view. It remains a constant 4
   pixels inset from the text view proper. The text
   flickers a bit, as the entire text view may need to be
   redrawn because of differing line wrap.
   [pDisplay.cpp:154-165]

5. Window size is determined dynamically, based on the
   default font and the current printer settings, rather
   than having a fixed rectangle size. The window's text
   rectangle is set to be 40 lines high, based on the font.
   The width of the text rect is either the width of the
   current printer's printable rectangle or 45 ems. An em
   is a typographical unit based on the width of an uppercase
   M. For roman character fonts it's considered a good
   estimate of the widest character in the font.
   [pDisplay.cpp: 31-82]

6. The BPrintJob class is used for interacting with the
   print server. We'll use it again in a future installment
   addressing printing issues. In this issue we use
   BPrintJob::PrintableRect() to return a BRect that
   represents the default printer's rectangle for printing.
   If a printer has been set up, Rephrase uses its printable
   rect's width for the width of the pDisplay text rectangle.
   If no printer has been set up, the rectangle will be
   invalid.
   [pDisplay.cpp:43-53]

7. The BFont class represents a font used to display text for
   a view. You can use the class to acquire information about
   the font. Three global font pointers are defined for the
   system: be_plain_font, be_bold_font, and be_fixed_font.
   You make these systemwide settings in the Font preferences
   panel. be_plain_font is the default font for all text views.

   Rephrase uses BFont::GetHeight() to determine the height
   of a line of text. BFont::StringWidth() determines the
   size of an em (see number 5 above). This value is used to
   set the window's minimum width, and perhaps the default
   width if no printer is available.
   [pDisplay.cpp:35-41]

8. Window size limits are based on font and screen size.
   The minimum size is based on a text rect 12 ems wide and
   10 lines deep. The maximum is the size of the screen.
   [pDisplay.cpp:74-82]

9. To enlarge a BRect by a specific amount on each side,
   pass negative values into BRect::InsetBy(). Be sure
   to remember to offset the rectangle to B_ORIGIN
   (BPoint(0,0)) if you're expecting the rectangle to
   start there.
   [pDisplay.cpp:58-59]

Next week: BFilePanels and saving files.

