[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