eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'ScrollableView':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: ScrollableView


Inheritance:

   Object
   |
   +--GraphicsMedium
      |
      +--DisplaySurface
         |
         +--SimpleView
            |
            +--ScrollableView
               |
               +--DataSetView
               |
               +--HTMLView
               |
               +--HVScrollableView
               |
               +--SequenceView
               |
               +--SubCanvas

Package:
stx:libwidg
Category:
Views-Basic
Version:
rev: 1.186 date: 2024/04/26 11:41:24
user: cg
file: ScrollableView.st directory: libwidg
module: stx stc-classLibrary: libwidg

Description:


a view containing a scrollbar and some other (slave-)view.
This view wraps scrollbar(s) around the view to be scrolled.
The scrollbars are setup to send scrollUp/scrollDown/scrollVerticalTo
and scrollLeft/scrollRight/scrollHorizontalTo- messages whenever moved.
The view itself has to implement these (there is a default implementation
in the common View class for this - so your widgets usually don't have to
care for this).

For the scrollbars to know about the full (maximum) size, the view
MUST implement #heightOfContents and/or #widthOfContents.
The values returned by those methods are used to compute the fraction
which is visible (i.e. the scrollers thumb heights).

There are three ways to setup a scrollableView:
if the type of the view to be scrolled is known in advance,
use:
    v := ScrollableView for:<ViewClass>
or:
    v := ScrollableView for:<ViewClass> in:someSuperView


otherwise, create an empty scrollableView with:

    v := ScrollableView new
or:
    v := ScrollableView in:someSuperView

and define the view later with:

    v scrolledView:aViewToBeScrolled


Finally, if the view to be scrolled has been already created,
use:

    v := ScrollableView forView:aViewToBeScrolled
or:
    v := ScrollableView forView:aViewToBeScrolled in:someSuperView

It is also possible to change the scrolledView later (even multiple times).
This may be useful if different views are needed to display different types
of data (see example2) and at creation time, it is not known what type
of view is required (multidocument format applications).

If you want to scroll a bunch of other views (instead of a view's contents),
you need a companion class (ViewScroller). See the documentation there.

By default, scrollbars are full size scrollbars - for horizontal scrolling
(which is less often used), scrollableViews can optionally be created with
miniscrollers which take up less screen space.

Recent changes:
    Originally, there were two classes, for vertical-only and
    horizontal+vertical scrollability.
    These have now been merged into the common ScrollableView class,
    and each scrollability can be controlled individually.

copyright

COPYRIGHT (c) 1989 by Claus Gittinger All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

Class protocol:

defaults
o  defaultHorizontalScrollable

o  defaultScrollBarPosition
return the default position of the scrollBar.
(max be of interest to panels, to make the handlePosition alike)

Usage example(s):

     self defaultScrollBarPosition

o  defaultVerticalScrollable

o  updateStyleCache
extract values from the styleSheet and cache them in class variables

Usage example(s):

     self updateStyleCache

instance creation
o  for: aViewClass
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars.

o  for: aViewClass hasHorizontalScrollBar: hasH hasVerticalScrollBar: hasV miniScrollerH: miniH miniScrollerV: miniV
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  for: aViewClass hasHorizontalScrollBar: hasH hasVerticalScrollBar: hasV miniScrollerH: miniH miniScrollerV: miniV origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

Usage example(s):

     |top scr|

     top := StandardSystemView extent:200@200.
     scr := ScrollableView for:nil
                 hasHorizontalScrollBar:true
                 hasVerticalScrollBar:true
                 miniScrollerH:false
                 miniScrollerV:false
                 origin:0.0@0.0
                 corner:1.0@1.0
                 in:top.
     top open

o  for: aViewClass in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars.

o  for: aViewClass miniScroller: mini
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if mini is false, miniscrollers
if true.

o  for: aViewClass miniScroller: mini in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if mini is false, miniscrollers
if true.

o  for: aViewClass miniScroller: mini origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if mini is false, miniscrollers
if true.

o  for: aViewClass miniScrollerH: miniH
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if miniH is false,
and a horizontal miniscroller if true.

o  for: aViewClass miniScrollerH: miniH in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  for: aViewClass miniScrollerH: miniH miniScrollerV: miniV
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  for: aViewClass miniScrollerH: miniH miniScrollerV: miniV in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  for: aViewClass miniScrollerH: miniH miniScrollerV: miniV origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  for: aViewClass miniScrollerH: miniH origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have a full horizontal scrollbar if miniH is false,
a miniscroller if true.

o  for: aViewClass miniScrollerV: miniV origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have a full vertical scrollbar if miniV is false,
a miniscroller if true.

o  for: aViewClass origin: org corner: corner in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars.

o  forView: aView
return a new scrolling view scrolling aView.
The view will have full scrollbars.

o  forView: aView hasHorizontalScrollBar: hasH hasVerticalScrollBar: hasV miniScrollerH: miniH miniScrollerV: miniV
return a new scrolling view scrolling a aView.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  forView: aScrolledView hasHorizontalScrollBar: hasH hasVerticalScrollBar: hasV miniScrollerH: miniH miniScrollerV: miniV origin: org corner: corn in: aView
return a new scrolling view scrolling an instance of aViewClass.
The subview is created here.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

Usage example(s):

     |top scr|

     top := StandardSystemView extent:200@200.
     scr := ScrollableView 
                 forView:(TextView new)
                 hasHorizontalScrollBar:true
                 hasVerticalScrollBar:true
                 miniScrollerH:false
                 miniScrollerV:false
                 origin:0.0@0.0
                 corner:1.0@1.0
                 in:top.
     top open

Usage example(s):

     |top scr|

     top := StandardSystemView extent:200@200.
     scr := ScrollableView 
                 forView:(TextView new)
                 hasHorizontalScrollBar:false
                 hasVerticalScrollBar:true
                 miniScrollerH:false
                 miniScrollerV:false
                 origin:0.0@0.0
                 corner:1.0@1.0
                 in:top.
     top open

o  forView: aView in: aSuperView
return a new scrolling view scrolling aView.
The view will have full scrollbars.

o  forView: aView miniScroller: mini
return a new scrolling view scrolling aView.
The view will have a miniScrollera, if mini is true.

o  forView: aView miniScrollerH: mini
return a new scrolling view scrolling aView.
The view will have a full vertical scrollbar and a horizontal
miniScroller if mini is true.

o  forView: scrolledView miniScrollerH: miniH miniScrollerV: miniV
return a new scrolling view, scrolling aView.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  forView: scrolledView miniScrollerH: miniH miniScrollerV: miniV in: aView
return a new scrolling view, scrolling aView.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  in: aView
return a new scrolling view to be contained in aView.
There is no slave view now - this has to be set later via
the scrolledView: method.
The view will have full scrollbars.

o  miniScroller: mini
return a new scrolling view. The subview will be created later.
The view will have full scrollbars if mini is false,
miniscrollers if true.

o  miniScrollerH: miniH
return a new scrolling view. The subview will be created later.
The view will have full scrollbars if miniH is false,
and a horizontal miniscroller if true.

o  miniScrollerH: miniH miniScrollerV: miniV
return a new scrolling view. The subview will be created later.
The view will have full scrollbars if the corresponding miniH/miniV
is false, miniscrollers if true.

o  new
return a new scrolling view.
There is no slave view now - this has to be set later via
the scrolledView: method.
The view will have full scrollbars.


Instance protocol:

accessing-behavior
o  autoHideHorizontalScrollBar: aBoolean
set/clear the flag which controls if the horizontal scrollBar should
be made invisible dynamically, if there is nothing to scroll
(and shown if there is).
This flags setting is normally controlled by the styleSheet.

o  autoHideHorizontalScrollBar: hideHBoolean autoHideVerticalScrollBar: hideVBoolean
set/clear the flag which controls if the scrollBars should
be made invisible dynamically, if there is nothing to scroll
(and shown if there is).
This flags setting is normally controlled by the styleSheet.

o  autoHideScrollBars: aBoolean
set/clear the flag which controls if scrollBars should
be made invisible dynamically, if there is nothing to scroll
(and shown if there is).
This flags setting is normally controlled by the styleSheet.

o  autoHideVerticalScrollBar: aBoolean
set/clear the flag which controls if the vertical scrollBar should
be made invisible dynamically, if there is nothing to scroll
(and shown if there is).
This flags setting is normally controlled by the styleSheet.

o  readOnly: aBoolean
(comment from inherited method)
ignored here; present for compatibility with some textView subclasses,
so that UIPainter can handle it in its TextView spec (which contains a
readOnly field)

accessing-components
o  horizontalScrollBar
return the horizontal scrollbar (or nil, if there is none)

o  removeSubView: aView
(comment from inherited method)
remove a view from the collection of subviews

o  scrollBar
return the vertical scrollbar (or nil, if there is none)

o  scrolledView
return the scrolled view (or nil, if there is none)

o  scrolledView: aView
set the view to scroll

o  verticalScrollBar
return the vertical scrollbar (or nil, if there is none)

o  widget
for ST80 compatibility (where a wrapper returns its wrapped
widget), return the scrolledView here

accessing-look
o  horizontalMini: aBoolean
control the horizontal scrollBar to be either a miniScroller,
or a full scrollBar.

o  horizontalMini: horizontalMiniBoolean verticalMini: verticalMiniBoolean
control the scrollBars to be either a miniScroller, or a full scrollBar.

o  horizontalScrollable: aBoolean
enable/disable horizontal scrollability.
If disabled, the horizontal scrollBar is made invisible.

o  horizontalScrollable: scrollableBoolean miniScroller: miniScrollerBoolean
enable/disable horizontal scrollability.
If disabled, the horizontal scrollBar is made invisible.

o  horizontalScrollable: scrollableHBoolean miniScroller: miniScrollerHBoolean verticalScrollable: scrollableVBoolean miniScroller: miniScrollerVBoolean
enable/disable scrollability.
If disabled, the scrollBar(s) are made invisible.

o  horizontalScrollable: horizontalScrollableBoolean verticalScrollable: verticalScrollableBoolean
enable/disable scrollability.
If disabled, the scrollBar(s) are made invisible.

o  setupForChangedScrollbars

o  verticalMini: aBoolean
control the vertical scrollBar to be either a miniScroller,
or a full scrollBar.

o  verticalScrollable: aBoolean
enable/disable vertical scrollability.
If disabled, the vertical scrollBar is made invisible.

o  verticalScrollable: scrollableBoolean miniScroller: miniScrollerBoolean
enable/disable vertical scrollability.
If disabled, the vertical scrollBar is made invisible.

change & update
o  pointerInView
Transcript showCR:pv.

o  update: something with: argument from: changedObject
whenever the scrolledView changes its contents, the scroller(s) must
be updated as well

o  updateHScrollBarVisibility
hScrollBarHidden

o  updateScrollBarVisibility
check if any scrollbar needs to be hidden or shown

o  updateVScrollBarVisibility
vScrollBarHidden

drag & drop
o  dropTarget
returns the dropTarget (a DropTarget instance) or nil.
Can be either set staticallz (at init time), or created dynamically,
(bz redefining this method to return a DropTarget instance)
The dropTarget object provides infor about enter/leave/over/drop selectors,
to be sent to the view for a drag&drop operation.
If nil is returned, a default dropTarget instance is created bz the DnD manager.

o  dropTarget: aDropTarget
set the dropTarget (a DropTarget instance) or nil.
The dropTarget object provides info about enter/leave/over/drop selectors,
to be sent to the view for a drag&drop operation.
If nil is returned, a default dropTarget instance is created by the DnD manager.

event handling
o  keyPress: key x: x y: y
a key was pressed - handle page-keys here

o  pointerEnter: state x: x y: y
(comment from inherited method)
mouse pointer entered - request the keyboard focus (sometimes)

o  pointerLeave: state
(comment from inherited method)
mouse pointer left

o  repairDamage
(comment from inherited method)
force the receiver to repair all of its
damaged areas right now.

o  requestAutoAccept
request to accept: this is invoked when a dialog closes via accept or cancel.
This forces my value to be accepted into my model.
Any widget may suppress the ok/cancel, by returning false.

o  sizeChanged: how from: oldExtentOrNil
my view has changed the size (not the contents);
handle size changes - this may change any scrollBars visibility

o  win32NativeScroll: scrollCode position: newPosition
this is generated by a native scrollBar widget

forced scroll
o  pageDown
page down - but only if there is a vertical scrollbar

o  pageLeft
page left - but only if there is a horizontal scrollbar

o  pageRight
page right - but only if there is a horizontal scrollbar

o  pageUp
page up - but only if there is a vertical scrollbar

initialization
o  initStyle
initialize style specifics

o  initialize
setup some default

o  realize
realize (i.e. make me visible).
Since scrolledView may have done something to its contents
during init-time we had no chance yet to catch contents-
changes; do it now

o  releaseHorizontalScrollBar
destroy any horizontal scrollBar

o  releaseVerticalScrollBar
destroy any vertical scrollBar

o  setScrollActions
lock prevents repositioning the scroller to the
actual (often rounded) position while scrolling,
and keeps it instead at the pointer position.

(this avoids run-away scroller when scrolling
textviews, when the text is aligned line-wise).
Consider this as a kludge.

o  setVertical: isVertical mini: miniV horizontal: isHorizontal mini: miniH
set scrollbar-flags as specified in the arguments

o  setupVertical: isVertical mini: miniV horizontal: isHorizontal mini: miniH
setup scrollbars as specified in the arguments

o  setupViews
setup scrollbars as specified in the arguments

layout
o  horizontalScrollBarLayout: aLayout

o  scrolledViewLayout: aLayout

o  setupDimensionsConfigureScrolledView: configureScrolledView
set the components dimensions (i.e. layouts) according to
the scrollability and hidden settings.
This may heavily move around the parts ...
This method is overly complex and we should think about alternatives;
the reason is that it tries to shift views so that borders overlap
(to avoid thick borders in-between components).
This is very questionable, since borders are only used with 2D styles,
and those 2D styles are more-or-less obsolete anyway.

o  usedScrollBarHSpacingWhenHasV: hasV andHasH: hasH
return the horizontal spacing between scrollBar and scrolledView.
Made a separate method to allow subclasses to overwrite this (subCanvas)

o  usedScrollBarVSpacingWhenHasV: hasV andHasH: hasH
return the vertical spacing between scrollBar and scrolledView.
Made a separate method to allow subclasses to overwrite this (subCanvas)

o  usedScrolledViewHMarginWhenHasV: hasV andHasH: hasH
return the horizontal margin around (outer margin).
Made a separate method to allow subclasses to overwrite this (subCanvas)

o  usedScrolledViewVMarginWhenHasV: hasV andHasH: hasH
return the vertical margin around (outer margin).
Made a separate method to allow subclasses to overwrite this (subCanvas)

o  verticalScrollBarLayout: aLayout

queries
o  computePreferredExtent
return my preferredExtent from the scrolledViews prefExtent
plus the size of the scrollBar

o  isHorizontalScrollable
return true if I am horizontally scrollable

o  isScrollWrapper
answer true if this view wraps a possibly larger view and has scroll bars

o  isScrolling
true, if scrollbars thumb is being moved (by user)

o  isVerticalScrollable
return true if I am vertically scrollable

o  preferredExtentForLines: numLines cols: numCols
return my preferredExtent from the scrolledViews prefExtent
plus the size of the scrollBar

o  respondsTo: aSelector
return true, if the receiver responds to a message.
Possibly delegated to my scrolled view

Usage example(s):

        self new respondsTo:#isScrolling

o  specClass
returns my spec class (for UI editor)

slave-view messages
o  accept
pass on to scrolledView

o  acceptIsUserAction: isUserAction
pass on to scrolledView

o  clear
convenient method: forward this to the scrolledView

o  clearView
convenient method: forward this to the scrolledView

o  doesNotUnderstand: aMessage
this is funny: all message we do not understand, are passed
on to the scrolledView - so we do not have to care for all
possible messages ...(thanks to the Message class)

o  flash
convenient method: forward this to the scrolledView

o  flash: messageOrNil withColor: flashColor
convenient method: forward this to the scrolledView

o  font: aFont
(comment from inherited method)
set the font for drawing if it has changed.
This should be redefined in some widget to perform an automatic
redraw/invalidate. See also: #basicFont:

o  leftButtonMenu
return scrolledViews leftbuttonmenu

o  leftButtonMenu: aMenu
pass on leftbuttonmenu to scrolledView

o  middleButtonMenu
return scrolledViews middlebuttonmenu

o  middleButtonMenu: aMenu
pass on middlebuttonmenu to scrolledView

o  model
return my scrolledViews model

o  model: aModel
forward model change to my scrolledViews

o  requestFocus
(comment from inherited method)
request focus from my windowGroup;
typically, this is invoked when the mouse pointer enters a
widget. The request may or may not be ignored by the wGroup
(it will be ignored, if an explicit focus-change is currently
active - i.e. if the user tabbed into a widget)

o  rightButtonMenu
return scrolledViews rightbuttonmenu

o  rightButtonMenu: aMenu
pass on rightbuttonmenu to scrolledView


Examples:


simple scrolled text:
      |top scr txt|

      top := StandardSystemView label:'scroll example1'.
      top extent:200@100.

      scr := ScrollableView for:EditTextView in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      txt := scr scrolledView.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
changing the scrolledView later:
      |top scr txtView1 txtView2 browserView|

      top := StandardSystemView label:'scroll example2'.
      top extent:300@100.

      scr := ScrollableView in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.

      top open.

      (Delay forSeconds:5) wait.

      txtView1 := EditTextView new.
      txtView1 list:#(
                      'wait 5 seconds to see the other text'
                      'line2'
                      'line3'
                      'line4'
                      'line5'
                      'line7'
                      'line8'
                      'line9'
                      'line10'
                ).
      scr scrolledView:txtView1.

      (Delay forSeconds:5) wait.

      txtView2 := EditTextView new.
      txtView2 list:#('this is the other views text'
                      'alternative line2'
                      'alternative line3'
                      'alternative line4'
                      'alternative line5'
                      'alternative line6').
      scr scrolledView:txtView2.
using a miniscroller:
      |top scr txt|

      top := StandardSystemView label:'scroll example3'.
      top extent:200@100.

      scr := ScrollableView for:EditTextView miniScroller:true in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      txt := scr scrolledView.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
scrolling in both directions: Notice: HVScrollableView remains existent for backward compatibility; scrollability can now be controlled in both directions at any time (see examples below).
      |top scr txt|

      top := StandardSystemView label:'scroll example4'.
      top extent:200@100.

      scr := HVScrollableView for:EditTextView in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      txt := scr scrolledView.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
using a full scroller vertically, miniscroller horizontally: Notice: HVScrollableView remains existent for backward compatibility; scrollability can now be controlled in both directions at any time (see examples below).
      |top scr txt|

      top := StandardSystemView label:'scroll example5'.
      top extent:200@100.

      scr := HVScrollableView for:EditTextView miniScrollerH:true in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      txt := scr scrolledView.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
using miniscrollers for both directions: Notice: HVScrollableView remains existent for backward compatibility; scrollability can now be controlled in both directions at any time (see examples below).
      |top scr txt|

      top := StandardSystemView label:'scroll example6'.
      top extent:200@100.

      scr := HVScrollableView for:EditTextView miniScroller:true in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      txt := scr scrolledView.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
controlling scrollability:
      |top scr txt|

      top := StandardSystemView label:'scroll example6'.
      top extent:200@100.

      txt := EditTextView new.

      scr := ScrollableView forView:txt in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      scr horizontalScrollable:true.
      scr verticalScrollable:false.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
controlling scrollability and miniScroller:
      |top scr txt|

      top := StandardSystemView label:'scroll example6'.
      top extent:200@100.

      txt := EditTextView new.

      scr := ScrollableView forView:txt in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      scr horizontalScrollable:true; horizontalMini:false.
      scr verticalScrollable:true; verticalMini:true.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open
autohiding scrollbars (edit the text to make scrollbars visible/invisible) (NOTICE: this is controlled by the styleSheet and should normally NOT be done by the program):
      |top scr txt|

      top := StandardSystemView label:'scroll example6'.
      top extent:200@100.

      txt := EditTextView new.

      scr := ScrollableView forView:txt in:top.
      scr origin:0.0@0.0 corner:1.0@1.0.
      scr horizontalScrollable:true; horizontalMini:false.
      scr verticalScrollable:true; verticalMini:true.
      scr autoHideScrollBars:true.

      txt list:#('line1'
                 'line2'
                 'line3'
                 'line4'
                 'line5'
                 'line7'
                 'line8'
                 'line9'
                 'line10'
                ).
      top open


ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Mon, 18 Nov 2024 04:43:44 GMT