[Aptitude-svn-commit] r4116 - in branches/aptitude-0.3/aptitude: . src/vscreen

Daniel Burrows dburrows at costa.debian.org
Mon Sep 19 23:22:11 UTC 2005


Author: dburrows
Date: Mon Sep 19 23:22:07 2005
New Revision: 4116

Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc
   branches/aptitude-0.3/aptitude/src/vscreen/fragment.h
   branches/aptitude-0.3/aptitude/src/vscreen/testvscreen.cc
Log:
Add basic support for formatting fragments in columns.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Mon Sep 19 23:22:07 2005
@@ -1,5 +1,10 @@
 2005-09-19  Daniel Burrows  <dburrows at debian.org>
 
+	* src/vscreen/fragment.cc, src/vscreen/fragment.h, src/vscreen/testvscreen.cc:
+
+	  Add a simple column-generating class.  It has a caveat regarding
+	  indentation, but aside from that it should be safe.
+
 	* src/broken_indicator.cc, src/cmdline/cmdline_resolver.cc, src/cmdline/cmdline_spinner.cc, src/cmdline/cmdline_spinner.h, src/cmdline/Makefile.am, src/generic/resolver_manager.cc, src/generic/resolver_manager.h, src/solution_dialog.cc, src/solution_screen.cc, src/ui.cc:
 
 	  Use the background thread to keep the UI responsive while the

Modified: branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/fragment.cc	Mon Sep 19 23:22:07 2005
@@ -942,6 +942,175 @@
   return new _indentbox(firstindent, restindent, contents);
 }
 
+class _fragment_columns : public fragment_container
+{
+  vector<fragment_column_entry> columns;
+
+  void update_widths(vector<size_t> &widths,
+		     size_t w) const
+  {
+    size_t total = 0, denominator = 0;
+
+    for(size_t i = 0; i < columns.size(); ++i)
+      {
+	if(columns[i].proportional)
+	  {
+	    widths[i]    = 0;
+	    denominator += columns[i].width;
+	  }
+	else
+	  {
+	    widths[i] = columns[i].width;
+	    total    += widths[i];
+	  }
+      }
+
+    if(total < w && denominator > 0)
+      {
+	size_t remainder = w - total;
+
+	for(size_t i = 0; i < columns.size(); ++i)
+	  if(columns[i].proportional)
+	    {
+	      widths[i]   += (remainder * columns[i].width) / denominator;
+	      denominator -= columns[i].width;
+	      remainder   -= widths[i];
+	    }
+      }
+
+    // Clip.
+    for(size_t i = 0; i < columns.size(); ++i)
+      {
+	widths[i] = min<int>(w, widths[i]);
+	w        -= widths[i];
+      }
+  }
+public:
+  _fragment_columns(const vector<fragment_column_entry> &_columns)
+    :columns(_columns)
+  {
+  }
+
+  ~_fragment_columns()
+  {
+    for(vector<fragment_column_entry>::const_iterator
+	  i = columns.begin(); i != columns.end(); ++i)
+      delete i->f;
+  }
+
+  fragment_contents layout(size_t firstw, size_t restw, const style &st)
+  {
+    assert(firstw == restw);
+
+    vector<size_t> widths(columns.size());
+    update_widths(widths, restw);
+
+    vector<fragment_contents> child_layouts(columns.size());
+
+    for(size_t i = 0; i < columns.size(); ++i)
+      if(columns[i].f != NULL)
+	child_layouts[i]    = columns[i].f->layout(widths[i], widths[i], st);
+
+    size_t height = 0;
+    for(size_t i = 0; i < columns.size(); ++i)
+      if(child_layouts[i].size() > height)
+	height = child_layouts[i].size();
+
+    vector<size_t> starting_lines(columns.size());
+
+    for(size_t i = 0; i < columns.size(); ++i)
+      {
+	switch(columns[i].vert_align)
+	  {
+	  case fragment_column_entry::top:
+	    starting_lines[i] = 0;
+	    break;
+
+	  case fragment_column_entry::center:
+	    starting_lines[i] = (height - child_layouts[i].size()) / 2;
+	    break;
+
+	  case fragment_column_entry::bottom:
+	    starting_lines[i] = height - child_layouts[i].size();
+	    break;
+	  }
+      }
+
+    fragment_contents rval;
+    for(size_t y = 0; y < height; ++y)
+      {
+	fragment_line tmp(L"");
+
+	for(size_t i = 0; i < columns.size(); ++i)
+	  if(columns[i].f != NULL &&
+	     y >= starting_lines[i] &&
+	     y < starting_lines[i] + child_layouts[i].size())
+	    {
+	      fragment_line &s = child_layouts[i][y - starting_lines[i]];
+	      tmp += s;
+
+	      if(widths[i] > s.size())
+		tmp += fragment_line(widths[i] - s.size(), L' ',
+				     st.get_attrs());
+	    }
+	  else
+	    tmp += fragment_line(widths[i], L' ', st.get_attrs());
+
+	rval.push_back(tmp);
+      }
+
+    return rval;
+  }
+
+  size_t calc_max_width(size_t first_indent, size_t rest_indent) const
+  {
+    assert(first_indent == rest_indent);
+
+    size_t rval = 0;
+
+    for(vector<fragment_column_entry>::const_iterator
+	  i = columns.begin(); i != columns.end(); ++i)
+      {
+	size_t thisw =
+	  i->f == NULL ? 0 : i->f->max_width(first_indent, rest_indent);
+
+	if(!i->proportional && thisw < i->width)
+	  thisw = i->width;
+
+	rval += thisw;
+
+	if(first_indent < thisw)
+	  first_indent = 0;
+	else
+	  first_indent -= thisw;
+
+	if(rest_indent < thisw)
+	  rest_indent = 0;
+	else
+	  rest_indent -= thisw;
+      }
+
+    return rval;
+  }
+
+  size_t calc_trailing_width(size_t first_indent, size_t rest_indent) const
+  {
+    assert(first_indent == rest_indent);
+
+    return rest_indent;
+  }
+
+  bool calc_final_newline() const
+  {
+    return true;
+  }
+};
+
+fragment *fragment_columns(const vector<fragment_column_entry> &columns)
+{
+  return new _fragment_columns(columns);
+}
+
 struct argument
 {
   argument():format(0) {}

Modified: branches/aptitude-0.3/aptitude/src/vscreen/fragment.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/fragment.h	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/fragment.h	Mon Sep 19 23:22:07 2005
@@ -249,6 +249,61 @@
  */
 fragment *indentbox(size_t firstindent, size_t restindent, fragment *contents);
 
+/** Stores information on a single column of fragments. */
+struct fragment_column_entry
+{
+  /** If \b true, this column is allocated space proportionally;
+   *  otherwise, its width is exactly what is specified.
+   */
+  bool proportional;
+
+  /** If proportional is \b true, this is a number giving the relative
+   *  size of this column compared to other proportional columns;
+   *  otherwise, this is the width of the column in character cells.
+   */
+  size_t width;
+
+  enum align {top, center, bottom};
+
+  /** The vertical alignment of the column.  If top, the top of this
+   *  column is placed at the top of the fragment.  If center, the
+   *  center of this column is aligned with the center of the
+   *  fragment.  And if bottom, the bottom of this column is aligned
+   *  with the bottom of the fragment.
+   */
+  align vert_align;
+
+  /** The fragment to display, or \b NULL for blank space. */
+  fragment *f;
+
+  fragment_column_entry(bool _proportional, size_t _width, align _vert_align,
+			fragment *_f)
+    :proportional(_proportional),
+     width(_width),
+     vert_align(_vert_align),
+     f(_f)
+  {
+  }
+
+  fragment_column_entry()
+    :proportional(false), width(0), vert_align(top)
+  {
+  }
+};
+
+/** A fragment that formats its contents into columns.  If the
+ *  fixed-width columns overflow the available space, they will be
+ *  clipped hard.
+ *
+ *  This fragment may NOT be placed inside an indent box or any other
+ *  box that alters the shape of its contents.  Doing so will cause
+ *  the program to abort.
+ *
+ *  \param columns a list of column entry information ordered from
+ *  left to right.
+ */
+fragment *fragment_columns(const std::vector<fragment_column_entry> &columns);
+
 /** A printf-alike for fragments.
  *
  *  Formatting codes:

Modified: branches/aptitude-0.3/aptitude/src/vscreen/testvscreen.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/vscreen/testvscreen.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/vscreen/testvscreen.cc	Mon Sep 19 23:22:07 2005
@@ -355,6 +355,16 @@
 
   v.push_back(hardwrapbox(fragf("The mention of Marley's funeral brings me back to the point I started from.  There is no doubt that Marley was dead.  This must be distinctly understood, or nothing wonderful can come of the story I am going to relate.  If we were not perfectly convinced that Hamlet's Father died before the play began, there would be nothing more remarkable in his taking a stroll at night, in an easterly wind, upon his own ramparts, than there would be in any other middle-aged gentleman rashly turning out after dark in a breezy spot -- say Saint Paul's Churchyard for instance -- literally to astonish his son's weak mind.")));
 
+  v.push_back(newline_fragment());
+
+  vector<fragment_column_entry> column_entries;
+
+  column_entries.push_back(fragment_column_entry(true, 5, fragment_column_entry::top, flowbox(fragf("Scrooge never painted out Old Marley's name. There it stood, years afterwards, above the warehouse door: Scrooge and Marley.  The firm was known as Scrooge and Marley.  Sometimes people new to the business called Scrooge Scrooge, and sometimes Marley, but he answered to both names: it was all the same to him.%n%nOh!  But he was a tight-fisted hand at the grind-stone, Scrooge! a squeezing, wrenching, grasping, scraping, clutching, covetous, old sinner!  Hard and sharp as flint, from which no steel had ever struck out generous fire; secret, and self-contained, and solitary as an oyster.  The cold within him froze his old features, nipped his pointed nose, shriveled his cheek, stiffened his gait; made his eyes red, his thin lips blue and spoke out shrewdly in his grating voice.  A frosty rime was on his head, and on his eyebrows, and his wiry chin.  He carried his own low temperature always about with him; he iced his office in the dogdays; and didn't thaw it one degree at Christmas."))));
+  column_entries.push_back(fragment_column_entry(false, 1, fragment_column_entry::top, NULL));
+  column_entries.push_back(fragment_column_entry(true, 1, fragment_column_entry::bottom, flowbox(fragf("Here we see further evidence of Scrooge's miserly behavior: to save himself a bit of money on paint and labour, he leaves an inaccurate (and somewhat spooky) sign above the door of his business."))));
+
+  v.push_back(fragment_columns(column_entries));
+
   return sequence_fragment(v);
 }
 



More information about the Aptitude-svn-commit mailing list