- First pass at the interface, structure and algorithm used by the
  new View object that will ultimately obsolete Table, Grid and Cell.
This commit is contained in:
Paul Beckingham 2011-04-26 18:19:57 -04:00
parent 120562a7e9
commit 74d799acea
8 changed files with 549 additions and 49 deletions

View file

@ -20,7 +20,7 @@ set (task_SRCS API.cpp API.h Att.cpp Att.h Cmd.cpp Cmd.h Color.cpp Color.h
diag.cpp edit.cpp export.cpp history.cpp i18n.h import.cpp
interactive.cpp recur.cpp report.cpp rules.cpp rx.cpp rx.h
text.cpp text.h utf8.cpp utf8.h util.cpp util.h Uri.cpp Uri.h
Variant.cpp Variant.h)
Variant.cpp Variant.h View.cpp View.h)
add_library (task STATIC ${task_SRCS})
add_executable (task_executable main.cpp)

184
src/View.cpp Normal file
View file

@ -0,0 +1,184 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <sstream>
#include <View.h>
////////////////////////////////////////////////////////////////////////////////
View::View ()
: _width (0)
, _left_margin (0)
, _odd (0)
, _even (0)
, _intra_padding (0)
, _intra_odd (0)
, _intra_even (0)
, _extra_padding (0)
, _extra_odd (0)
, _extra_even (0)
, _truncate (0)
, _lines (0)
{
}
////////////////////////////////////////////////////////////////////////////////
View::~View ()
{
}
////////////////////////////////////////////////////////////////////////////////
void View::add (Column* column)
{
_columns.push_back (column);
}
////////////////////////////////////////////////////////////////////////////////
void View::width (int width)
{
_width = width;
}
////////////////////////////////////////////////////////////////////////////////
void View::leftMargin (int margin)
{
_left_margin = margin;
}
////////////////////////////////////////////////////////////////////////////////
void View::colorOdd (Color& c)
{
_odd = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::colorEven (Color& c)
{
_even = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::intraPadding (int padding)
{
_intra_padding = padding;
}
////////////////////////////////////////////////////////////////////////////////
void View::intraColorOdd (Color& c)
{
_intra_odd = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::intraColorEven (Color& c)
{
_intra_even = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::extraPadding (int padding)
{
_extra_padding = padding;
}
////////////////////////////////////////////////////////////////////////////////
void View::extraColorOdd (Color& c)
{
_extra_odd = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::extraColorEven (Color& c)
{
_extra_even = c;
}
////////////////////////////////////////////////////////////////////////////////
void View::truncate (int n)
{
_truncate = n;
}
////////////////////////////////////////////////////////////////////////////////
int View::lines ()
{
return _lines;
}
////////////////////////////////////////////////////////////////////////////////
// +-------+ +-------+ +-------+
// |header | |header | |header |
// +--+--+-------+--+-------+--+-------+--+
// |ma|ex|cell |in|cell |in|cell |ex|
// +--+--+-------+--+-------+--+-------+--+
// |ma|ex|cell |in|cell |in|cell |ex|
// +--+--+-------+--+-------+--+-------+--+
//
std::string View::render (std::vector <Task>& data, std::vector <int>& sequence)
{
// Determine minimal, ideal column widths.
std::vector <int> minimal;
std::vector <int> ideal;
std::vector <Column*>::iterator i;
for (i = _columns.begin (); i != _columns.end (); ++i)
{
int global_min = 0;
int global_ideal = 0;
std::vector <Task>::iterator d;
for (d = data.begin (); d != data.end (); ++d)
{
int min;
int ideal;
(*i)->measure (*d, min, ideal);
if (min > global_min) global_min = min;
if (ideal > global_ideal) global_ideal = ideal;
}
minimal.push_back (global_min);
ideal.push_back (global_ideal);
}
// TODO Calculate final column widths.
// TODO Compose column headers.
// TODO Render column headers.
// TODO Compose, render columns, in sequence.
std::stringstream output;
std::vector <int>::iterator s;
for (s = sequence.begin (); s != sequence.end (); ++s)
{
}
return output.str ();
}
////////////////////////////////////////////////////////////////////////////////

78
src/View.h Normal file
View file

@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////////////////////////
// task - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_VIEW
#define INCLUDED_VIEW
#include <string>
#include <vector>
#include <Task.h>
#include <Color.h>
#include <Column.h>
class View
{
public:
View ();
~View ();
// View specifications.
void add (Column*);
void width (int);
void leftMargin (int);
void colorOdd (Color&);
void colorEven (Color&);
void intraPadding (int);
void extraPadding (int);
void intraColorOdd (Color&);
void intraColorEven (Color&);
void extraColorOdd (Color&);
void extraColorEven (Color&);
void truncate (int);
int lines ();
// View rendering.
std::string render (std::vector <Task>&, std::vector <int>&);
private:
std::vector <Column*> _columns;
int _width;
int _left_margin;
Color _odd;
Color _even;
int _intra_padding;
Color _intra_odd;
Color _intra_even;
int _extra_padding;
Color _extra_odd;
Color _extra_even;
int _truncate;
int _lines;
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -28,44 +28,34 @@
#include <iostream>
#include <Context.h>
#include <Column.h>
#include <ID.h>
extern Context context;
////////////////////////////////////////////////////////////////////////////////
Column* Column::factory (const std::string& name)
{
/*
if (name == "description") return new ColumnDescription ();
if (name == "id") return new ColumnID ();
throw std::string ("Unrecognized column type '") + name + "'";
*/
return NULL;
}
////////////////////////////////////////////////////////////////////////////////
Column::Column ()
: _name ("")
/*
: _style ("default")
, _label ("")
, _minimum (0)
, _maximum (0)
, _wrap (false)
, _just (left)
, _sizing (minimal)
*/
{
}
////////////////////////////////////////////////////////////////////////////////
Column::Column (const Column& other)
{
_name = other._name;
/*
_label = other._label;
_minimum = other._minimum;
_maximum = other._maximum;
_wrap = other._wrap;
_just = other._just;
_sizing = other._sizing;
*/
}
////////////////////////////////////////////////////////////////////////////////
@ -73,14 +63,9 @@ Column& Column::operator= (const Column& other)
{
if (this != &other)
{
_name = other._name;
/*
_label = other._label;
_minimum = other._minimum;
_maximum = other._maximum;
_wrap = other._wrap;
_just = other._just;
_sizing = other._sizing;
*/
}
return *this;
@ -89,12 +74,9 @@ Column& Column::operator= (const Column& other)
////////////////////////////////////////////////////////////////////////////////
bool Column::operator== (const Column& other) const
{
return _name == other._name /*&&
return _label == other._label &&
_minimum == other._minimum &&
_maximum == other._maximum &&
_wrap == other._wrap &&
_just == other._just &&
_sizing == other._sizing*/;
_maximum == other._maximum;
}
////////////////////////////////////////////////////////////////////////////////
@ -103,9 +85,15 @@ Column::~Column ()
}
////////////////////////////////////////////////////////////////////////////////
void Column::setName (const std::string& name)
void Column::setStyle (const std::string& style)
{
_name = name;
_style = style;
}
////////////////////////////////////////////////////////////////////////////////
void Column::setLabel (const std::string& label)
{
_label = label;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -33,11 +33,6 @@
class Column
{
public:
/*
enum just {right = 0, left, center};
enum sizing {minimal = 0, fixed, proportional, maximal};
*/
static Column* factory (const std::string&);
Column ();
@ -46,19 +41,18 @@ public:
bool operator== (const Column&) const; // TODO Is this necessary?
~Column ();
virtual void setName (const std::string&);
virtual std::string render (Task*, int, int, const std::string style = "default") = 0;
virtual void setStyle (const std::string&);
virtual void setLabel (const std::string&);
virtual void measure (Task&, int&, int&) = 0;
virtual void renderHeader (std::vector <std::string>&, int) = 0;
virtual void render (std::vector <std::string>&, Task*, int) = 0;
virtual std::string type () const = 0;
protected:
std::string _name;
/*
std::string _style;
std::string _label;
int _minimum;
int _maximum;
bool _wrap;
just _just;
sizing _sizing;
*/
};
#endif

View file

@ -25,6 +25,7 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <Context.h>
#include <ID.h>
@ -33,7 +34,7 @@ extern Context context;
////////////////////////////////////////////////////////////////////////////////
ColumnID::ColumnID ()
{
setName ("id");
setLabel ("id");
}
////////////////////////////////////////////////////////////////////////////////
@ -42,11 +43,28 @@ ColumnID::~ColumnID ()
}
////////////////////////////////////////////////////////////////////////////////
std::string ColumnID::render (
Task* task,
int width,
int height,
const std::string style)
// Set the minimum and maximum widths for the value.
void ColumnID::measure (Task& task, int& minimum, int& maximum)
{
int length;
if (task.id < 10) length = 1; // Fast
else if (task.id < 100) length = 2; // Fast
else if (task.id < 1000) length = 3; // Fast
else if (task.id < 10000) length = 4; // Fast
else length = (int) log10 ((double) task.id); // Slow
minimum = maximum = length;
}
////////////////////////////////////////////////////////////////////////////////
void ColumnID::renderHeader (std::vector <std::string>& lines, int width)
{
lines.push_back ("ID");
}
////////////////////////////////////////////////////////////////////////////////
void ColumnID::render (std::vector <std::string>& lines, Task* task, int width)
{
}

View file

@ -27,6 +27,7 @@
#ifndef INCLUDED_ID
#define INCLUDED_ID
#include <vector>
#include <string>
#include <Column.h>
#include <Task.h>
@ -37,7 +38,9 @@ public:
ColumnID ();
~ColumnID ();
std::string render (Task*, int, int, const std::string style = "default");
void measure (Task&, int&, int&);
void renderHeader (std::vector <std::string>&, int);
void render (std::vector <std::string>&, Task*, int);
std::string type () const;
private:

235
src/sort.cpp Normal file
View file

@ -0,0 +1,235 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <vector>
#include <string>
#include <Task.h>
static std::vector <Task>* data = NULL;
////////////////////////////////////////////////////////////////////////////////
void view_sort (
std::vector <Task>& data)
{
}
////////////////////////////////////////////////////////////////////////////////
// Re-implementation, using direct Task access instead of data copies that
// require re-parsing.
bool sort_compare (int left, int right)
{
}
////////////////////////////////////////////////////////////////////////////////
// Essentially a static implementation of a dynamic operator<.
bool sort_compare (int left, int right)
{
for (size_t c = 0; c < table->mSortColumns.size (); ++c)
{
int column = table->mSortColumns[c];
Table::order sort_type = table->mSortOrder[column];
Grid::Cell* cell_left = table->mData.byRow (left, column);
Grid::Cell* cell_right = table->mData.byRow (right, column);
// Equally NULL - next column.
if (cell_left == NULL && cell_right == NULL)
continue;
// Equal - next column
if (cell_left && cell_right && *cell_left == *cell_right)
continue;
// Note: Table::ascendingDueDate is not represented here because it is not
// possible to have a NULL due date, only a blank "".
// nothing < something.
if (cell_left == NULL && cell_right != NULL)
return (sort_type == Table::ascendingNumeric ||
sort_type == Table::ascendingCharacter ||
sort_type == Table::ascendingPriority ||
sort_type == Table::ascendingDate ||
sort_type == Table::ascendingPeriod) ? true : false;
// something > nothing.
if (cell_left != NULL && cell_right == NULL)
return (sort_type == Table::ascendingNumeric ||
sort_type == Table::ascendingCharacter ||
sort_type == Table::ascendingPriority ||
sort_type == Table::ascendingDate ||
sort_type == Table::ascendingPeriod) ? false : true;
// Differing data - do a proper comparison.
if (cell_left && cell_right)
{
switch (sort_type)
{
case Table::ascendingNumeric:
return (float)*cell_left < (float)*cell_right ? true : false;
break;
case Table::descendingNumeric:
return (float)*cell_left < (float)*cell_right ? false : true;
break;
case Table::ascendingCharacter:
return (std::string)*cell_left < (std::string)*cell_right ? true : false;
break;
case Table::descendingCharacter:
return (std::string)*cell_left < (std::string)*cell_right ? false : true;
break;
case Table::ascendingDate:
{
// something > nothing.
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return false;
// nothing < something.
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return true;
else
{
Date dl ((std::string)*cell_left, table->mDateFormat);
Date dr ((std::string)*cell_right, table->mDateFormat);
return dl < dr ? true : false;
}
}
break;
case Table::descendingDate:
{
// something > nothing.
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return true;
// nothing < something.
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return false;
else
{
Date dl ((std::string)*cell_left, table->mDateFormat);
Date dr ((std::string)*cell_right, table->mDateFormat);
return dl < dr ? false : true;
}
}
break;
case Table::ascendingDueDate:
{
// something > nothing.
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return true;
// nothing < something.
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return false;
else
{
std::string format = context.config.get ("report." + table->mReportName + ".dateformat");
if (format == "")
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
Date dl ((std::string)*cell_left, format);
Date dr ((std::string)*cell_right, format);
return dl < dr ? true : false;
}
}
break;
case Table::descendingDueDate:
{
// something > nothing.
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return true;
// nothing < something.
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return false;
else
{
std::string format = context.config.get ("report." + table->mReportName + ".dateformat");
if (format == "")
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
Date dl ((std::string)*cell_left, format);
Date dr ((std::string)*cell_right, format);
return dl < dr ? false : true;
}
}
break;
case Table::ascendingPriority:
if (((std::string)*cell_left == "" && (std::string)*cell_right != "") ||
((std::string)*cell_left == "L" && ((std::string)*cell_right == "M" || (std::string)*cell_right == "H")) ||
((std::string)*cell_left == "M" && (std::string)*cell_right == "H"))
return true;
else
return false;
break;
case Table::descendingPriority:
if (((std::string)*cell_left != "" && (std::string)*cell_right == "") ||
((std::string)*cell_left == "M" && (std::string)*cell_right == "L") ||
((std::string)*cell_left == "H" && ((std::string)*cell_right == "L" || (std::string)*cell_right == "M")))
return true;
else
return false;
break;
case Table::ascendingPeriod:
if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return true;
else if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return false;
else
return Duration ((std::string)*cell_left) < Duration ((std::string)*cell_right) ? true : false;
break;
case Table::descendingPeriod:
if ((std::string)*cell_left != "" && (std::string)*cell_right == "")
return false;
else if ((std::string)*cell_left == "" && (std::string)*cell_right != "")
return true;
else
return Duration ((std::string)*cell_left) < Duration ((std::string)*cell_right) ? false : true;
break;
}
}
}
return false;
}