""" DeluxePage.cobra This is a continuation of the framework found in WebPages.cobra. cobra -r=System.Web WebPages.cobra DeluxePage.cobra > deluxe.html """ class DeluxePage inherits Page """ DeluxePage adds these capabilities: * A more sophisticated page structure with header, left sidebar, right sidebar, content well and footer. This more closely reflects the structure of typical web pages. All parts are optional. * Word-wrapped output with a left and right margin and indent/outdent capability. """ test dp = DeluxePage() sw = StringWriter() dp.writeHtml(sw) var _writer as DeluxeWriter? get rightHtmlSourceMargin as int """ The HTML source code that is output is actually wrapped at a right hand margin. This often makes it easier to read the source, but doesn't work well with
content that will cross the
margin (especially if the content has tags in it).
"""
return 100
def indent
_writer.indent
def indent(s as String)
"""
While the name .writeLineAndIndent is explicit, it's also annoyingly
long. This shorter named method does the same thing.
"""
.writeLineAndIndent(s)
def outdent
_writer.outdent
def outdent(s as String)
"""
While the name .outdentAndWriteLine is explicit, it's also annoyingly
long. This shorter named method does the same thing.
"""
.outdentAndWriteLine(s)
def writeLineAndIndent(s as String)
.writeLine(s)
.indent
def outdentAndWriteLine(s as String)
.outdent
.writeLine(s)
def begin(name as String, tag)
.writeLine('')
.indent
.writeLine('[HtmlUtils.toHtml(tag)]\n')
.indent
def end(name as String, tag)
.outdent
didWrite = false
if tag inherits String
if not tag.startsWith('<')
.writeLine('[tag]>')
didWrite = true
if not didWrite
.writeLine('[HtmlUtils.toHtml(tag)]')
.outdent
.writeLine('\n')
def writeHtml(tw as TextWriter)
_writer = writer = DeluxeWriter(tw, .rightHtmlSourceMargin)
try
base.writeHtml(writer) # TODO: axe writer local and use "_writer to !" when it's available
finally
_writer = nil
var _wholePageTableTag = Tag('table', 'class=wholePage border=0 cellpadding=0 cellspacing=0')
var _leftBarTdTag = Tag('td', 'class', 'leftBar', 'valign', 'top', 'width', 0)
get numCols as int
return 1 + if(.hasLeftBar,1,0) + if(.hasRightBar,1,0)
def writeBodyParts is override
numCols = .numCols
.indent
.begin('whole page', _wholePageTableTag)
if .hasPageHeader
.writePageHeader
.begin('page row', '')
if .hasLeftBar
.begin('left bar', _leftBarTdTag)
.writeLine('')
.writeLeftBar
.writeLine('')
.end('left bar', 'td')
.begin('page content', ' ')
.writeContent
.end('page content', ' ')
if .hasRightBar
.begin('right bar', '')
.writeRightBar
.end('right bar', 'td')
if .hasPageFooter
.begin('page footer', ' ')
.indent('\n')
.writePageFooter
.outdent('\n \n')
.end('page footer', 'tr')
.end('page row', 'tr')
.end('whole page', 'table')
.outdent
def writePageHeader
.begin('page header', ' ')
.indent('\n')
.innerWritePageHeader
.outdent('\n \n')
.end('page header', 'tr')
def innerWritePageHeader
.writeLine(.htTitle)
def writeLeftBar
pass
def writeRightBar
pass
def writePageFooter
.writeLine('Copyright © [DateTime.now.year]. All Rights Reserved.')
get hasPageHeader as bool
return true
get hasLeftBar as bool
return true
get hasRightBar as bool
return true
get hasPageFooter as bool
return true
class MyPage inherits DeluxePage
get styleSheetUrls as String* is override
yield 'styles.css'
def writeLeftBar is override
.writeLine('Nav 1')
def writeContent is override
.writeLine('Added unit testing as a language level feature. You can now write test sections for methods, properties and classes. Because these unit tests can be specified next to what they actually test, they are more likely to be kept up to date. Also, because they are a natural part of the source code, they benefit from development environment features such as syntax highlighting and autocompletion. Finally, more programmers may be encouraged to write unit tests when it is this easy.')
class DeluxeWriter inherits TextWriter
"""
Provides:
* indented writing (useful for structured HTML pages)
* right margin (useful for yielding easy-to-read HTML)
Used internally by DeluxePage although you are free to use DeluxeWriter if
you have a need for it.
"""
test
iw = DeluxeWriter(StringWriter())
assert iw.toString == ''
nl = iw.newLine
tab = ' '
iw.writeLine('one')
assert iw.toString == 'one[nl]'
iw.indent
iw.writeLine('two')
assert iw.toString == 'one[nl][tab]two[nl]'
iw.outdent
iw.writeLine('three')
assert iw.toString == 'one[nl][tab]two[nl]three[nl]'
var _innerWriter as TextWriter
var _lastChar = '' # use a string because _innerWriter.newLine is a string
var _indentString = ' '
var _indentLevel = 0
var _totalIndentString = ''
var _isWritingIndent = false
var _column = 1
var _rightMargin = 80
cue init(tw as TextWriter)
base.init
_innerWriter = tw
cue init(tw as TextWriter, rightMargin as int)
require rightMargin == 0 or rightMargin > 10
.init(tw)
_rightMargin = rightMargin
def indent
_indentLevel += 1
_setTotalIndentString()
def outdent
_indentLevel -= 1
_setTotalIndentString()
pro indentString from var
"""
Returns the string used for one level of indentation.
Default value is "\t".
"""
get newLine2 as String
return '\n' # because NewLine is "\r\n" but we don't require the \r
# *** Being a TextWriter ***
def write(value as char) is override
if _isWritingIndent
_innerWriter.write(value)
_column += 1
return
if _lastChar==_innerWriter.newLine or _lastChar==.newLine2
_column = 1
_isWritingIndent = true
try
.write(_totalIndentString)
_column += _totalIndentString.length
finally
_isWritingIndent = false
_innerWriter.write(value)
_column += 1
_lastChar = value.toString
/#
if _rightMargin and _column > _rightMargin and _lastChar==' '
# TODO: need a better word wrapping algorithm that doesn't allow words to poke out of the right hand margin
# but this is good enough for now
.write(_innerWriter.newLine)
#/
def write(value as String?) is override
if _isWritingIndent
_innerWriter.write(value)
else
base.write(value)
get encoding as Encoding? is override
return _innerWriter.encoding
def toString as String is override
return _innerWriter.toString
# *** Private Util ***
def _setTotalIndentString is protected
sb = StringBuilder()
for i in _indentLevel, sb.append(_indentString)
_totalIndentString = sb.toString