ColUDA: Split ColUDA into ColUDA{String,Numeric,Date,Duration} to make use of ColType*::modify

This commit is contained in:
Paul Beckingham 2016-02-01 01:10:11 -05:00
parent 73d789c593
commit 6f4f468d0d
3 changed files with 401 additions and 88 deletions

View file

@ -36,19 +36,18 @@
extern Context context; extern Context context;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
ColumnUDA::ColumnUDA () ColumnUDAString::ColumnUDAString ()
{ {
_name = "<uda>"; _name = "<uda>";
_type = "string";
_style = "default"; _style = "default";
_label = ""; _label = "";
_uda = true; _uda = true;
_hyphenate = (_type == "string") ? true : false; _hyphenate = true;
_styles = {_style, "indicator"}; _styles = {_style, "indicator"};
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool ColumnUDA::validate (std::string& value) bool ColumnUDAString::validate (std::string& value)
{ {
// No restrictions. // No restrictions.
if (_values.size () == 0) if (_values.size () == 0)
@ -66,7 +65,7 @@ bool ColumnUDA::validate (std::string& value)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Set the minimum and maximum widths for the value. // Set the minimum and maximum widths for the value.
// //
void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximum) void ColumnUDAString::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
{ {
minimum = maximum = 0; minimum = maximum = 0;
@ -77,35 +76,9 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
std::string value = task.get (_name); std::string value = task.get (_name);
if (value != "") if (value != "")
{ {
if (_type == "date") std::string stripped = Color::strip (value);
{ maximum = longestLine (stripped);
// Determine the output date format, which uses a hierarchy of definitions. minimum = longestWord (stripped);
// rc.report.<report>.dateformat
// rc.dateformat.report
// rc.dateformat
ISO8601d date ((time_t) strtol (value.c_str (), NULL, 10));
std::string format = context.config.get ("report." + _report + ".dateformat");
if (format == "")
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
minimum = maximum = ISO8601d::length (format);
}
else if (_type == "duration")
{
minimum = maximum = ISO8601p (value).format ().length ();
}
else if (_type == "string")
{
std::string stripped = Color::strip (value);
maximum = longestLine (stripped);
minimum = longestWord (stripped);
}
else if (_type == "numeric")
{
minimum = maximum = value.length ();
}
} }
} }
else if (_style == "indicator") else if (_style == "indicator")
@ -127,7 +100,7 @@ void ColumnUDA::measure (Task& task, unsigned int& minimum, unsigned int& maximu
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void ColumnUDA::render ( void ColumnUDAString::render (
std::vector <std::string>& lines, std::vector <std::string>& lines,
Task& task, Task& task,
int width, int width,
@ -138,36 +111,304 @@ void ColumnUDA::render (
if (_style == "default") if (_style == "default")
{ {
std::string value = task.get (_name); std::string value = task.get (_name);
if (_type == "date") std::vector <std::string> raw;
{ wrapText (raw, value, width, _hyphenate);
// Determine the output date format, which uses a hierarchy of definitions.
// rc.report.<report>.dateformat
// rc.dateformat.report
// rc.dateformat.
std::string format = context.config.get ("report." + _report + ".dateformat");
if (format == "")
{
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
}
renderStringLeft (lines, width, color, ISO8601d ((time_t) strtol (value.c_str (), NULL, 10)).toString (format)); for (auto& i : raw)
} renderStringLeft (lines, width, color, i);
else if (_type == "duration") }
renderStringRight (lines, width, color, ISO8601p (value).format ()); else if (_style == "indicator")
{
else if (_type == "string") if (task.has (_name))
{ {
std::vector <std::string> raw; auto indicator = context.config.get ("uda." + _name + ".indicator");
wrapText (raw, value, width, _hyphenate); if (indicator == "")
indicator = "U";
for (auto& i : raw)
renderStringLeft (lines, width, color, i); renderStringRight (lines, width, color, indicator);
} }
}
else if (_type == "numeric") }
renderStringRight (lines, width, color, value); }
////////////////////////////////////////////////////////////////////////////////
ColumnUDANumeric::ColumnUDANumeric ()
{
_name = "<uda>";
_type = "numeric";
_style = "default";
_label = "";
_uda = true;
_hyphenate = false;
_styles = {_style, "indicator"};
}
////////////////////////////////////////////////////////////////////////////////
bool ColumnUDANumeric::validate (std::string& value)
{
// No restrictions.
if (_values.size () == 0)
return true;
// Look for exact match value.
for (auto& i : _values)
if (i == value)
return true;
// Fail if not found.
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Set the minimum and maximum widths for the value.
//
void ColumnUDANumeric::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
{
minimum = maximum = 0;
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
if (value != "")
minimum = maximum = value.length ();
}
else if (_style == "indicator")
{
if (task.has (_name))
{
auto indicator = context.config.get ("uda." + _name + ".indicator");
if (indicator == "")
indicator = "U";
minimum = maximum = utf8_width (indicator);
}
else
minimum = maximum = 0;
}
else
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
}
}
////////////////////////////////////////////////////////////////////////////////
void ColumnUDANumeric::render (
std::vector <std::string>& lines,
Task& task,
int width,
Color& color)
{
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
renderStringRight (lines, width, color, value);
}
else if (_style == "indicator")
{
if (task.has (_name))
{
auto indicator = context.config.get ("uda." + _name + ".indicator");
if (indicator == "")
indicator = "U";
renderStringRight (lines, width, color, indicator);
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
ColumnUDADate::ColumnUDADate ()
{
_name = "<uda>";
_type = "date";
_style = "default";
_label = "";
_uda = true;
_hyphenate = false;
_styles = {_style, "indicator"};
}
////////////////////////////////////////////////////////////////////////////////
bool ColumnUDADate::validate (std::string& value)
{
// No restrictions.
if (_values.size () == 0)
return true;
// Look for exact match value.
for (auto& i : _values)
if (i == value)
return true;
// Fail if not found.
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Set the minimum and maximum widths for the value.
//
void ColumnUDADate::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
{
minimum = maximum = 0;
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
if (value != "")
{
// Determine the output date format, which uses a hierarchy of definitions.
// rc.report.<report>.dateformat
// rc.dateformat.report
// rc.dateformat
ISO8601d date ((time_t) strtol (value.c_str (), NULL, 10));
std::string format = context.config.get ("report." + _report + ".dateformat");
if (format == "")
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
minimum = maximum = ISO8601d::length (format);
}
}
else if (_style == "indicator")
{
if (task.has (_name))
{
auto indicator = context.config.get ("uda." + _name + ".indicator");
if (indicator == "")
indicator = "U";
minimum = maximum = utf8_width (indicator);
}
else
minimum = maximum = 0;
}
else
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
}
}
////////////////////////////////////////////////////////////////////////////////
void ColumnUDADate::render (
std::vector <std::string>& lines,
Task& task,
int width,
Color& color)
{
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
// Determine the output date format, which uses a hierarchy of definitions.
// rc.report.<report>.dateformat
// rc.dateformat.report
// rc.dateformat.
std::string format = context.config.get ("report." + _report + ".dateformat");
if (format == "")
{
format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
}
renderStringLeft (lines, width, color, ISO8601d ((time_t) strtol (value.c_str (), NULL, 10)).toString (format));
}
else if (_style == "indicator")
{
if (task.has (_name))
{
auto indicator = context.config.get ("uda." + _name + ".indicator");
if (indicator == "")
indicator = "U";
renderStringRight (lines, width, color, indicator);
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
ColumnUDADuration::ColumnUDADuration ()
{
_name = "<uda>";
_type = "duration";
_style = "default";
_label = "";
_uda = true;
_hyphenate = false;
_styles = {_style, "indicator"};
}
////////////////////////////////////////////////////////////////////////////////
bool ColumnUDADuration::validate (std::string& value)
{
// No restrictions.
if (_values.size () == 0)
return true;
// Look for exact match value.
for (auto& i : _values)
if (i == value)
return true;
// Fail if not found.
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Set the minimum and maximum widths for the value.
//
void ColumnUDADuration::measure (Task& task, unsigned int& minimum, unsigned int& maximum)
{
minimum = maximum = 0;
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
if (value != "")
minimum = maximum = ISO8601p (value).format ().length ();
}
else if (_style == "indicator")
{
if (task.has (_name))
{
auto indicator = context.config.get ("uda." + _name + ".indicator");
if (indicator == "")
indicator = "U";
minimum = maximum = utf8_width (indicator);
}
else
minimum = maximum = 0;
}
else
throw format (STRING_COLUMN_BAD_FORMAT, _name, _style);
}
}
////////////////////////////////////////////////////////////////////////////////
void ColumnUDADuration::render (
std::vector <std::string>& lines,
Task& task,
int width,
Color& color)
{
if (task.has (_name))
{
if (_style == "default")
{
std::string value = task.get (_name);
renderStringRight (lines, width, color, ISO8601p (value).format ());
} }
else if (_style == "indicator") else if (_style == "indicator")
{ {

View file

@ -27,12 +27,64 @@
#ifndef INCLUDED_COLUDA #ifndef INCLUDED_COLUDA
#define INCLUDED_COLUDA #define INCLUDED_COLUDA
#include <Column.h> #include <ColTypeString.h>
#include <ColTypeNumeric.h>
#include <ColTypeDate.h>
#include <ColTypeDuration.h>
class ColumnUDA : public Column ////////////////////////////////////////////////////////////////////////////////
class ColumnUDAString : public ColumnTypeString
{ {
public: public:
ColumnUDA (); ColumnUDAString ();
bool validate (std::string&);
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
public:
std::vector <std::string> _values;
private:
bool _hyphenate;
};
////////////////////////////////////////////////////////////////////////////////
class ColumnUDANumeric : public ColumnTypeNumeric
{
public:
ColumnUDANumeric ();
bool validate (std::string&);
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
public:
std::vector <std::string> _values;
private:
bool _hyphenate;
};
////////////////////////////////////////////////////////////////////////////////
class ColumnUDADate : public ColumnTypeDate
{
public:
ColumnUDADate ();
bool validate (std::string&);
void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&);
public:
std::vector <std::string> _values;
private:
bool _hyphenate;
};
////////////////////////////////////////////////////////////////////////////////
class ColumnUDADuration : public ColumnTypeDuration
{
public:
ColumnUDADuration ();
bool validate (std::string&); bool validate (std::string&);
void measure (Task&, unsigned int&, unsigned int&); void measure (Task&, unsigned int&, unsigned int&);
void render (std::vector <std::string>&, Task&, int, Color&); void render (std::vector <std::string>&, Task&, int, Color&);

View file

@ -175,29 +175,49 @@ void Column::uda (std::map <std::string, Column*>& all)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
Column* Column::uda (const std::string& name) Column* Column::uda (const std::string& name)
{ {
ColumnUDA* c = new ColumnUDA (); auto type = context.config.get ("uda." + name + ".type");
c->_name = name; auto label = context.config.get ("uda." + name + ".label");
auto values = context.config.get ("uda." + name + ".values");
std::string key = "uda." + name + ".type"; if (type == "string")
c->_type = context.config.get (key); {
if (c->_type == "") auto c = new ColumnUDAString ();
context.error (format (STRING_UDA_TYPE_MISSING, name)); c->_name = name;
c->_label = label;
if (values != "")
split (c->_values, values, ',');
return c;
}
else if (type == "numeric")
{
auto c = new ColumnUDANumeric ();
c->_name = name;
c->_label = label;
if (values != "")
split (c->_values, values, ',');
return c;
}
else if (type == "date")
{
auto c = new ColumnUDADate ();
c->_name = name;
c->_label = label;
if (values != "")
split (c->_values, values, ',');
return c;
}
else if (type == "duration")
{
auto c = new ColumnUDADuration ();
c->_name = name;
c->_label = label;
if (values != "")
split (c->_values, values, ',');
return c;
}
if (c->_type != "string" && throw std::string (STRING_UDA_TYPE);
c->_type != "date" && return NULL;
c->_type != "duration" &&
c->_type != "numeric")
context.error (STRING_UDA_TYPE);
key = "uda." + name + ".label";
if (context.config.get (key) != "")
c->_label = context.config.get (key);
key = "uda." + name + ".values";
if (context.config.get (key) != "")
split (c->_values, context.config.get (key), ',');
return c;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////