Class: MonoclePrint::Table

Inherits:
Object
  • Object
show all
Includes:
Enumerable, MonoclePrint, Presentation
Defined in:
lib/monocle-print/table.rb,
lib/monocle-print/table/column.rb,
lib/monocle-print/table/members.rb,
lib/monocle-print/table/segments.rb

Direct Known Subclasses

ColumnLayout

Defined Under Namespace

Classes: Column, Member, Segments

Constant Summary collapse

Blank =
Member.define( 'blank' ) do
  def render!( * )
  end
end
Row =
Member.define( 'row' ) do
  def initialize!( *content )
    @cells = [ content ].flatten!.map! { | c | Text( c ) }
    @table.expand_columns( @cells.length )
  end

  def []( index )
    @cells[ index ]
  end

  def []=(index, value)
    @cells[ index ] = value
  end

  def cells
    @table.columns.zip( @cells ).
      map! { | col, cell | col.prepare( cell ) }
  end

  def height
    cells.map! { | c | c.height }.max
  end

  def render!( out, style )
    cells =
      @table.columns.zip( @cells ).map! do | col, cell |
        col.prepare( cell )
      end

    height = cells.map { | col, cell | cell ? cell.height : 1 }.max

    joint = style.format( ' <v> ' )
    left  = style.format( '<v> ' )
    right = style.format( ' <v>' )

    result = cells.inject { | result, cell | result.juxtapose( cell, joint ) }
    result.each do | line |
      out.put!( left + line + right )
    end
    return( out )
  end

  def inspect
    super( *cells )
  end

private

  def prepare
    height = cells.map { | c | c.height }.max
    if height > 1
      cell_lines.zip( @table.columns ) do | lines, col |
        if lines.length < height
          blank = col.fill_text( ' ' )
          lines.fill( blank, lines.length, height - lines.length )
        end
      end
    end
    return( cell_lines )
  end

  def pad
    n = @table.columns.length
    m = @cells.length
    @cells.fill( Text(' '), m, n - m ) if n > m
  end
end
TitleRow =
Member.define( 'title_row', Row ) do
  def initialize!( *content )
    super
    divider!( :title )
  end
end
Divider =
Member.define( 'divider' ) do
  attr_accessor :type

  def initialize!( type )
    @type = type.to_sym
  end

  def render( out, style )
    super( out, style ) unless @after.is_a?( Divider )
  end

  def inspect( *args )
    super( @type, *args )
  end

  def render!( out, style )
    fills = @table.columns.map { | c | "<h:#{ c.width + 2 }>" }
    template =
      case @type
      when :row, :title
        '<nse>' << fills.join( '<hv>' ) << '<nsw>'
      when :section_open
        '<nse>' << fills.join( '<hs>' ) << '<nsw>'
      when :section_close
        '<nse>' << fills.join( '<hn>' ) << '<nsw>'
      when :head
        '<se>' << fills.join( '<hs>' ) << '<sw>'
      when :foot
        '<ne>' << fills.join( '<hn>' ) << '<nw>'
      end
    out.puts( style.format( template ) )
  end
end
SectionTitle =
Member.define( 'section' ) do
  attr_accessor :title, :alignment

  def initialize!( title, options = {} )
    @title = Text( title )
    @alignment = options.fetch( :align, :left )
    @before.divider!( :section_close )
    divider!( :section_open )
  end

  def inspect
    super( @title, @alignment )
  end

  def render!( out, style )
    w     = @table.inner_width
    title = @title.width > w ? @title.wrap( w ) : @title
    left  = style.format( '<v> ' )
    right = style.format( ' <v>' )

    for line in title.align( @alignment, w )
      out.puts(  left + line + right )
    end
  end

end

Constants included from Presentation

Presentation::ALIGNMENTS

Constants included from MonoclePrint

COLOR_ESCAPE, FOUR_BYTES, MULTIBYTE_CHARACTER, ONE_BYTE, THREE_BYTES, TWO_BYTES, VERSION

Instance Attribute Summary collapse

Attributes included from Presentation

#max_width, #owner

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Presentation

#alignment, #alignment=, #height, included, #output, #output=, #render, #style, #style=, #to_s

Methods included from MonoclePrint

Line, Output, Rectangle, Style, Text, buffer, included, library_path, stderr, stdout, version

Constructor Details

#initialize(columns, options = {}) ⇒ Table

Returns a new instance of Table.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/monocle-print/table.rb', line 21

def initialize( columns, options = {} )
  initialize_view( options )
  
  @titles = nil
  @item = @head = Divider.new( self, :head )
  @foot = Divider.new( self, :foot )
  @columns = []
  @body = []
  
  case columns
  when Fixnum
    expand_columns( columns )
  when Array
    title_row( *columns )
  end
  
  block_given? and yield( self )
end

Instance Attribute Details

#columnsObject (readonly)

Returns the value of attribute columns.



55
56
57
# File 'lib/monocle-print/table.rb', line 55

def columns
  @columns
end

#titlesObject (readonly)

Returns the value of attribute titles.



55
56
57
# File 'lib/monocle-print/table.rb', line 55

def titles
  @titles
end

Class Method Details

.build(*args) ⇒ Object



13
14
15
16
17
18
# File 'lib/monocle-print/table.rb', line 13

def self.build( *args )
  table = new( *args ) do | table |
    block_given? and yield( table )
  end
  return( table.render )
end

Instance Method Details

#column(name_or_index) ⇒ Object



106
107
108
109
110
111
112
113
114
# File 'lib/monocle-print/table.rb', line 106

def column( name_or_index )
  case name_or_index
  when Integer, Range then @columns[ name_or_index ]
  else
    @columns.find do | col |
      name_or_index === col.title
    end
  end
end

#divider(type = :row_divider) ⇒ Object



82
83
84
# File 'lib/monocle-print/table.rb', line 82

def divider( type = :row_divider )
  @item = @item.divider!( type )
end

#eachObject



48
49
50
51
52
53
# File 'lib/monocle-print/table.rb', line 48

def each
  block_given? or return( enum_for( :each ) )
  for item in @head
    yield( item )
  end
end

#expand_columns(new_size) ⇒ Object



141
142
143
144
145
146
147
# File 'lib/monocle-print/table.rb', line 141

def expand_columns(new_size)
  new_size.zero? and return
  
  until @columns.length >= new_size
    @columns << Column.new( self, @columns.length )
  end
end

#fixed_columns(*column_indicies) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/monocle-print/table.rb', line 86

def fixed_columns( *column_indicies )
  for column_index in column_indicies
    if c = column( column_indicies )
      if Array === c then c.each { | i | i.fixed = true }
      else c.fixed = true
      end
    end
  end
end

#inner_widthObject



133
134
135
# File 'lib/monocle-print/table.rb', line 133

def inner_width
  @inner_width or calculate_inner_width
end

#malleable_columns(*column_indicies) ⇒ Object



96
97
98
99
100
101
102
103
104
# File 'lib/monocle-print/table.rb', line 96

def malleable_columns( *column_indicies )
  for column_index in column_indicies
    if c = column( column_index )
      if Array === c then c.each { | i | i.malleable = true }
      else c.malleable = true
      end
    end
  end
end

#render_content(out) ⇒ Object



40
41
42
43
44
45
46
# File 'lib/monocle-print/table.rb', line 40

def render_content( out )
  style = @style || out.style
  lock do
    width > out.width and resize( out.width )
    each { | member | member.render( out, style ) }
  end
end

#resize(new_size) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/monocle-print/table.rb', line 116

def resize( new_size )
  resizable = @columns.select { | c | c.malleable? }
  if resizable.empty?
    warn( "cannot resize #{ self.inspect } as all columns are fixed" )
    return( self )
  end
  
  lock do
    difference = new_size - @width
    resize_columns( difference, resizable )
  end
  
  return( self )
end

#row(*members) ⇒ Object



57
58
59
# File 'lib/monocle-print/table.rb', line 57

def row( *members )
  @item = @item.row!( *members )
end

#rows(*list_of_rows) ⇒ Object



73
74
75
76
# File 'lib/monocle-print/table.rb', line 73

def rows( *list_of_rows )
  for row in list_of_rows do row( *row ) end
  self
end

#section(title, options = {}) ⇒ Object



78
79
80
# File 'lib/monocle-print/table.rb', line 78

def section( title, options = {} )
  @item = @item.section!( title, options )
end

#title_row(*members) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/monocle-print/table.rb', line 61

def title_row( *members )
  @titles = @item = @item.title_row!( *members )
  while @titles
    if TitleRow === @titles
      @titles = @titles.cells.map { | c | c.to_s }
      break
    end
    @titles = @titles.before
  end
  self
end

#widthObject



137
138
139
# File 'lib/monocle-print/table.rb', line 137

def width
  @width or calculate_width
end