move tree drawing to ui
This commit is contained in:
+2
-2
@@ -75,7 +75,7 @@ void Person::displayInfo()const
|
||||
mvwaddstr(info_tab, LINES-1, 0, "Press any key to return.");
|
||||
|
||||
wrefresh(info_tab);
|
||||
getch(); /* waint press */
|
||||
getch(); /* wait press */
|
||||
|
||||
werase(info_tab);
|
||||
wrefresh(info_tab); /* todo: dont update */
|
||||
@@ -163,7 +163,7 @@ U16 Person::draw(I16 drawY, I16 drawX, bool selected, ZoomLevel zoom,
|
||||
|
||||
}
|
||||
|
||||
U16 person_box_width(ZoomLevel z)
|
||||
U16 person_box_height(ZoomLevel z)
|
||||
{
|
||||
switch(z)
|
||||
{
|
||||
|
||||
+3
-1
@@ -57,6 +57,7 @@ public:
|
||||
drawY,drawX - top left coordinates where to draw (negative if outside the screen)
|
||||
partOfMain - is the person a decendant of the current root
|
||||
hasSpouse, hasSpouse, hasChildren - wheather the person has them on display
|
||||
ZoomLevel - how the box will be drawn
|
||||
returns the width of the box*/
|
||||
U16 drawAsFocused(I16 drawY, I16 drawX, bool selected, bool hasSpouse,
|
||||
bool hasChildren, ZoomLevel) const;
|
||||
@@ -64,6 +65,7 @@ public:
|
||||
/* Draw a Person's box on the terminal, as a spouse of someone in the focused tree
|
||||
drawY,drawX - top left coordinates where to draw (negative if outside the screen)
|
||||
hasTree - weather the spouse has a tree that can be displayed
|
||||
ZoomLevel - how the box will be drawn
|
||||
returns the width of the box*/
|
||||
U16 drawAsSpouse(I16 drawY, I16 drawX, bool selected, bool hasTree, ZoomLevel) const;
|
||||
|
||||
@@ -77,4 +79,4 @@ private:
|
||||
U32 topleft, U32 topright, U32 botleft, U32 botright) const;
|
||||
};
|
||||
|
||||
U16 person_box_width(ZoomLevel);
|
||||
U16 person_box_height(ZoomLevel);
|
||||
|
||||
-125
@@ -267,12 +267,6 @@ void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother
|
||||
updateRels(new_person_id);
|
||||
}
|
||||
|
||||
/* bool Tree::addRelation(const char* firstName, const RelType type, const char* secondName) */
|
||||
/* { */
|
||||
|
||||
/* return addRelation(findId(firstName)[0], type, findId(secondName)[0]); */
|
||||
/* } */
|
||||
|
||||
bool Tree::addRelation(const unsigned first, const RelType type, const unsigned second, bool update)
|
||||
{
|
||||
if (first == Nobody || first >= people_.size() || second == Nobody || second >= people_.size() || type == None)
|
||||
@@ -323,11 +317,6 @@ void Tree::addRelOneSide(person_id first, RelType type, person_id second)
|
||||
}
|
||||
}
|
||||
|
||||
/* void Tree::removeRelation(const char* firstName, const char* secondName) */
|
||||
/* { */
|
||||
/* removeRelation(findId(firstName)[0], findId(secondName)[0]); */
|
||||
/* } */
|
||||
|
||||
void Tree::removePerson(const person_id id)
|
||||
{
|
||||
person_id relId;
|
||||
@@ -359,11 +348,6 @@ void Tree::removePerson(const person_id id)
|
||||
remove(people_, id);
|
||||
}
|
||||
|
||||
/* void Tree::removePerson(const char* personName, short year, unsigned char month, unsigned char day) */
|
||||
/* { */
|
||||
/* removePerson(findId(personName, year, month, day)); */
|
||||
/* } */
|
||||
|
||||
void Tree::removeRelation(const unsigned first, const unsigned second)
|
||||
{
|
||||
for (unsigned i = 0; i < relations_[first].size(); ++i)
|
||||
@@ -384,16 +368,6 @@ void Tree::removeRelation(const unsigned first, const unsigned second)
|
||||
}
|
||||
}
|
||||
|
||||
void Tree::focusPerson(person_id id)
|
||||
{
|
||||
focused_ = id;
|
||||
}
|
||||
|
||||
person_id Tree::focused() const
|
||||
{
|
||||
return focused_;
|
||||
}
|
||||
|
||||
void Tree::updateRels(person_id id)
|
||||
{
|
||||
person_id dad = findParent(id, M);
|
||||
@@ -426,25 +400,6 @@ void Tree::updateRels(person_id id)
|
||||
}
|
||||
|
||||
|
||||
void Tree::draw(const person_id selected, const ZoomLevel zoom, const I16 offsetY, const I16 offsetX)
|
||||
{
|
||||
selected_ = selected;
|
||||
zoom_ = zoom;
|
||||
|
||||
erase(); //Clear the screen
|
||||
wnoutrefresh(stdscr);
|
||||
|
||||
drawLineWithSpouses(focused_, offsetY, offsetX);
|
||||
|
||||
doupdate();
|
||||
}
|
||||
|
||||
void Tree::printMember(const unsigned id)const // todo: rename
|
||||
{
|
||||
people_[id].displayInfo();
|
||||
}
|
||||
|
||||
|
||||
void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
|
||||
{
|
||||
++visited[id];
|
||||
@@ -456,83 +411,3 @@ void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
|
||||
commonAncestorRec(rel.id, visited);
|
||||
}
|
||||
}
|
||||
|
||||
// return the height of the space occupied by the link
|
||||
static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings)
|
||||
{
|
||||
if (willBeVisible(startY, startX, 3, 1))
|
||||
{
|
||||
AutoWin pad( newpad(3, 1) );
|
||||
|
||||
waddch(pad, ACS_VLINE);
|
||||
mvwaddch(pad, 1, 0,
|
||||
moreSiblings ? ACS_LTEE : ACS_VLINE);
|
||||
mvwaddch(pad, 2, 0, ACS_VLINE);
|
||||
|
||||
drawpad(pad, startY, startX);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
|
||||
{
|
||||
assert(endX >= startX);
|
||||
const I16 len = endX - startX;
|
||||
if (willBeVisible(startY, startX, 2, len))
|
||||
{
|
||||
AutoWin pad( newpad(2, len) );
|
||||
|
||||
for(U16 i = 0; i < len-1; ++i)
|
||||
waddch(pad, ACS_HLINE);
|
||||
/* whline(pad, '_', len-1); */
|
||||
waddch(pad, moreSiblings ? ACS_TTEE : ACS_URCORNER);
|
||||
|
||||
mvwaddch(pad, 1, len-1, ACS_VLINE);
|
||||
|
||||
drawpad(pad, startY, startX);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
I16 Tree::drawLineWithSpouses(const person_id id, I16 drawY, const I16 drawX) const
|
||||
{
|
||||
const Person& person = people_[id];
|
||||
|
||||
person_id spouse = findSpouse(id);
|
||||
vector<person_id> children = findChildren(id);
|
||||
|
||||
const size_t numKids = children.size();
|
||||
U16 person_w = person.drawAsFocused(drawY, drawX,
|
||||
id == selected_, spouse!=Nobody, numKids!=0, zoom_);
|
||||
|
||||
U16 spouse_w = 0;
|
||||
if (spouse != Nobody)
|
||||
{
|
||||
bool spouse_has_tree = (findParent(spouse, M) != Nobody) || (findParent(spouse, F) != Nobody);
|
||||
U16 spouse_box = people_[spouse].drawAsSpouse(drawY, drawX + person_w + spouse_dist_,
|
||||
spouse == selected_, spouse_has_tree, zoom_);
|
||||
spouse_w = spouse_dist_ + spouse_box;
|
||||
}
|
||||
|
||||
auto childX = drawX;
|
||||
if (numKids!=0)
|
||||
{
|
||||
auto prevX = childX;
|
||||
drawY += person_box_width(zoom_);
|
||||
|
||||
auto lnHt = linkToFirstBorn(drawY, childX, numKids > 1); /* Link height */
|
||||
childX = drawLineWithSpouses(children[0], drawY + lnHt, childX);
|
||||
|
||||
for(size_t j = 1; j < numKids; ++j)
|
||||
{
|
||||
/* +1 because LTC starts lower then LTFB */
|
||||
lnHt = linkToChild(drawY+1, prevX+1, childX+1, j < numKids-1) + 1;
|
||||
|
||||
prevX = childX;
|
||||
childX = drawLineWithSpouses(children[j], drawY + lnHt, childX);
|
||||
}
|
||||
}
|
||||
|
||||
return max(drawX + person_w + dist_between_ + spouse_w,
|
||||
childX);
|
||||
}
|
||||
|
||||
+3
-29
@@ -4,8 +4,6 @@
|
||||
#include <vector>
|
||||
#include "person.hpp"
|
||||
|
||||
enum ZoomLevel: U8;
|
||||
|
||||
using person_id = U32;
|
||||
enum: person_id {
|
||||
Nobody = UINT32_MAX
|
||||
@@ -48,36 +46,25 @@ public:
|
||||
// Get person by id
|
||||
const Person& operator[](person_id) const;
|
||||
|
||||
std::vector<person_id> findId(const std::string& name) const;
|
||||
std::vector<person_id> findId(const std::string& name) const; // todo merge the 2 findId
|
||||
person_id findId(const std::string& name, Sex) const;
|
||||
person_id findRootAncestor(person_id) const;
|
||||
person_id findOldestAncestor(person_id, Sex) const;//
|
||||
|
||||
//oldest common ancestor ID, a person is considerd an ancestor of himself
|
||||
// Oldest common ancestor ID, a person is considerd an ancestor of himself
|
||||
person_id findCommonAncestor(person_id first, person_id second) const; /* needs to be fixed, never return nobody */
|
||||
RelType findRelation(person_id first, person_id second) const;
|
||||
const std::vector<Relation>& findRelations(person_id) const;
|
||||
person_id findParent(person_id child, Sex parentSex) const;
|
||||
person_id findSpouse(person_id person) const;
|
||||
std::vector<person_id> findChildren(person_id person) const;
|
||||
std::vector<person_id> findChildren(person_id person, person_id exclude) const;
|
||||
std::vector<person_id> findChildren(person_id person, person_id exclude) const; // exclude the child with the given ID
|
||||
|
||||
void addPerson(const char* name, Sex sex, person_id father=Nobody, person_id mother=Nobody, EventTime birth={}, EventTime death={});
|
||||
bool addRelation(const char* firstName, RelType, const char* secondName); //Adds a new relation or edits an old one. 0 - failure 1 - success
|
||||
bool addRelation(person_id first, RelType, person_id second, bool update=true); //0 - failure 1 - success
|
||||
|
||||
void removePerson(person_id id); //Removes a member and the last one takes his ID
|
||||
/* void removePerson(const char*, short year = 0, const unsigned char month = 0, const unsigned char day = 0); */
|
||||
void removeRelation(person_id first, person_id second);
|
||||
void removeRelation(const char* firstName, const char* secondName);
|
||||
|
||||
/* draw the tree based on this person */
|
||||
void focusPerson(person_id);
|
||||
person_id focused() const;
|
||||
|
||||
/* void printRel(person_id id)const; //Prints out close relatives */
|
||||
void printMember(person_id)const;
|
||||
void draw(person_id selected, ZoomLevel, I16 offsetY, I16 offsetX);
|
||||
|
||||
private:
|
||||
// recursion to find common ancestor
|
||||
@@ -88,20 +75,7 @@ private:
|
||||
(example adds siblings after parents are added) */
|
||||
void updateRels(person_id);
|
||||
|
||||
/* draw a line of people starting from person with id
|
||||
return the farthest X on the screen where it will be drawn */
|
||||
I16 drawLineWithSpouses(person_id, I16 drawY, I16 drawX) const;
|
||||
|
||||
std::string treeName_;
|
||||
std::vector<Person> people_; //The data for each member
|
||||
std::vector<std::vector<Relation>> relations_; //The relatives of each member
|
||||
|
||||
// 0 is the first person in the tree
|
||||
person_id focused_ = 0; /* the tree was draw based on this person */
|
||||
person_id selected_;
|
||||
ZoomLevel zoom_;
|
||||
|
||||
// todo: figure out what to do with these constants
|
||||
const U8 dist_between_ = 1; /* distance between people */
|
||||
const U8 spouse_dist_ = 0; /* distance between spouses */
|
||||
};
|
||||
|
||||
+144
-25
@@ -2,17 +2,34 @@
|
||||
#include "tree.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "assert.h"
|
||||
#include "../config.h" /* user's configuration */
|
||||
#include "../config.h" // user's configuration
|
||||
|
||||
using std::vector;
|
||||
|
||||
namespace
|
||||
{
|
||||
// State
|
||||
person_id focused_; // the tree was draw based on this person
|
||||
person_id selected_; // the currently selected selected
|
||||
ZoomLevel zoom_; // how much info to show for each selected
|
||||
|
||||
// todo: figure out what to do with these constants
|
||||
const U8 dist_between_ = 1; /* distance between people */
|
||||
const U8 spouse_dist_ = 0; /* distance between spouses */
|
||||
|
||||
void drawTree(const Tree&, const I16 offsetY, const I16 offsetX);
|
||||
/* draw a line of people starting from person with id
|
||||
return the farthest X on the screen where it will be drawn */
|
||||
I16 drawTreeLine(const Tree&, person_id, I16 drawY, I16 drawX);
|
||||
|
||||
|
||||
void displayHelp();
|
||||
person_id selectLeft(const Tree& t, person_id selected);
|
||||
person_id selectDown(const Tree& t, person_id selected);
|
||||
person_id selectUp(const Tree& t, person_id selected);
|
||||
person_id selectRight(const Tree& t, person_id selected);
|
||||
person_id selectLeftSibSpouse(const Tree& t, person_id selected); /* todo: split? */
|
||||
person_id selectRightSib(const Tree& t, person_id selected);
|
||||
person_id selectLeft(const Tree&, person_id selected);
|
||||
person_id selectDown(const Tree&, person_id selected);
|
||||
person_id selectUp(const Tree&, person_id selected);
|
||||
person_id selectRight(const Tree&, person_id selected);
|
||||
person_id selectLeftSibSpouse(const Tree&, person_id selected); /* todo: split? */
|
||||
person_id selectRightSib(const Tree&, person_id selected);
|
||||
}
|
||||
|
||||
ZoomLevel operator++(ZoomLevel& z)
|
||||
@@ -27,10 +44,12 @@ ZoomLevel operator--(ZoomLevel& z)
|
||||
return z;
|
||||
}
|
||||
|
||||
void displayTree(Tree& t)
|
||||
void displayTree(const Tree& t)
|
||||
{
|
||||
person_id selected = 0; // the currently selected selected
|
||||
ZoomLevel zoom = ZoomLevel::FIRST_NAME; // how much info to show for each selected
|
||||
// 0 is the first person in the tree
|
||||
focused_ = 0;
|
||||
selected_ = 0;
|
||||
zoom_ = ZoomLevel::FIRST_NAME;
|
||||
|
||||
// offset of the tree in relation to the top left corner of the screen
|
||||
I16 offsetY = 0, offsetX = 0;
|
||||
@@ -40,7 +59,7 @@ void displayTree(Tree& t)
|
||||
do
|
||||
{
|
||||
if(to_draw)
|
||||
t.draw(selected, zoom, offsetY, offsetX);
|
||||
drawTree(t, offsetY, offsetX);
|
||||
else
|
||||
to_draw = true;
|
||||
|
||||
@@ -52,7 +71,7 @@ void displayTree(Tree& t)
|
||||
break;
|
||||
case SELECT:
|
||||
case '\n':
|
||||
t.focusPerson( t.findRootAncestor(selected) );
|
||||
focused_ = t.findRootAncestor(selected_);
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
break;
|
||||
@@ -70,27 +89,35 @@ void displayTree(Tree& t)
|
||||
break;
|
||||
case '=':
|
||||
case '+':
|
||||
if(zoom < ZoomLevel::MAX_ZOOM)
|
||||
++zoom;
|
||||
if(zoom_ < ZoomLevel::MAX_ZOOM)
|
||||
{
|
||||
++zoom_;
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if(zoom > 0)
|
||||
--zoom;
|
||||
if(zoom_ > 0)
|
||||
{
|
||||
--zoom_;
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
}
|
||||
break;
|
||||
case SELECT_LEFT:
|
||||
selected = selectLeft(t, selected);
|
||||
selected_ = selectLeft(t, selected_);
|
||||
break;
|
||||
case SELECT_DOWN:
|
||||
selected = selectDown(t, selected);
|
||||
selected_ = selectDown(t, selected_);
|
||||
break;
|
||||
case SELECT_UP:
|
||||
selected = selectUp(t, selected);
|
||||
selected_ = selectUp(t, selected_);
|
||||
break;
|
||||
case SELECT_RIGHT:
|
||||
selected = selectRight(t, selected);
|
||||
selected_ = selectRight(t, selected_);
|
||||
break;
|
||||
case DISPLAY_INFO:
|
||||
t.printMember(selected);
|
||||
t[selected_].displayInfo();
|
||||
break;
|
||||
default:
|
||||
to_draw = false; /* invalid key, don't redraw */
|
||||
@@ -103,6 +130,98 @@ void displayTree(Tree& t)
|
||||
|
||||
namespace
|
||||
{
|
||||
void drawTree(const Tree& t, const I16 offsetY, const I16 offsetX)
|
||||
{
|
||||
erase(); //Clear the screen
|
||||
wnoutrefresh(stdscr);
|
||||
|
||||
drawTreeLine(t, focused_, offsetY, offsetX);
|
||||
|
||||
doupdate();
|
||||
}
|
||||
|
||||
// return the height of the space occupied by the link
|
||||
U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings)
|
||||
{
|
||||
if (willBeVisible(startY, startX, 3, 1))
|
||||
{
|
||||
AutoWin pad( newpad(3, 1) );
|
||||
|
||||
waddch(pad, ACS_VLINE);
|
||||
mvwaddch(pad, 1, 0,
|
||||
moreSiblings ? ACS_LTEE : ACS_VLINE);
|
||||
mvwaddch(pad, 2, 0, ACS_VLINE);
|
||||
|
||||
drawpad(pad, startY, startX);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
|
||||
{
|
||||
assert(endX >= startX);
|
||||
const I16 len = endX - startX;
|
||||
if (willBeVisible(startY, startX, 2, len))
|
||||
{
|
||||
AutoWin pad( newpad(2, len) );
|
||||
|
||||
for(U16 i = 0; i < len-1; ++i)
|
||||
waddch(pad, ACS_HLINE);
|
||||
/* whline(pad, '_', len-1); */
|
||||
waddch(pad, moreSiblings ? ACS_TTEE : ACS_URCORNER);
|
||||
|
||||
mvwaddch(pad, 1, len-1, ACS_VLINE);
|
||||
|
||||
drawpad(pad, startY, startX);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
I16 drawTreeLine(const Tree& t, const person_id id, I16 drawY, const I16 drawX)
|
||||
{
|
||||
const Person& person = t[id];
|
||||
|
||||
person_id spouse = t.findSpouse(id);
|
||||
vector<person_id> children = t.findChildren(id);
|
||||
|
||||
const size_t numKids = children.size();
|
||||
U16 person_w = person.drawAsFocused(drawY, drawX,
|
||||
id == selected_, spouse!=Nobody, numKids!=0, zoom_);
|
||||
|
||||
U16 spouse_w = 0;
|
||||
if (spouse != Nobody)
|
||||
{
|
||||
bool spouse_has_tree = (t.findParent(spouse, M) != Nobody) || (t.findParent(spouse, F) != Nobody);
|
||||
U16 spouse_box = t[spouse].drawAsSpouse(drawY, drawX + person_w + spouse_dist_,
|
||||
spouse == selected_, spouse_has_tree, zoom_);
|
||||
spouse_w = spouse_dist_ + spouse_box;
|
||||
}
|
||||
|
||||
auto childX = drawX;
|
||||
if (numKids!=0)
|
||||
{
|
||||
auto prevX = childX;
|
||||
drawY += person_box_height(zoom_);
|
||||
|
||||
auto lnHt = linkToFirstBorn(drawY, childX, numKids > 1); /* Link height */
|
||||
childX = drawTreeLine(t, children[0], drawY + lnHt, childX);
|
||||
|
||||
for(size_t j = 1; j < numKids; ++j)
|
||||
{
|
||||
/* +1 because LTC starts lower then LTFB */
|
||||
lnHt = linkToChild(drawY+1, prevX+1, childX+1, j < numKids-1) + 1;
|
||||
|
||||
prevX = childX;
|
||||
childX = drawTreeLine(t, children[j], drawY + lnHt, childX);
|
||||
}
|
||||
}
|
||||
|
||||
return max(drawX + person_w + dist_between_ + spouse_w,
|
||||
childX);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void displayHelp()
|
||||
{
|
||||
AutoWin help_tab( newwin(LINES, COLS, 0, 0) );
|
||||
@@ -120,7 +239,7 @@ namespace
|
||||
|
||||
person_id selectLeft(const Tree& t, person_id selected)
|
||||
{
|
||||
if (t.findCommonAncestor(t.focused(), selected) != Nobody) //if the selected is part of main tree
|
||||
if (t.findCommonAncestor(focused_, selected) != Nobody) //if the selected is part of main tree
|
||||
{
|
||||
selected = selectLeftSibSpouse(t, selected);
|
||||
}
|
||||
@@ -151,12 +270,12 @@ namespace
|
||||
|
||||
person_id selectUp(const Tree& t, person_id selected)
|
||||
{
|
||||
if (t.findCommonAncestor(t.focused(), selected) != Nobody) //if the selected is part of main tree
|
||||
if (t.findCommonAncestor(focused_, selected) != Nobody) //if the selected is part of main tree
|
||||
{
|
||||
person_id dad = t.findParent(selected, M);
|
||||
person_id mom = t.findParent(selected, F);
|
||||
|
||||
if (t.findCommonAncestor(t.focused(), mom) != Nobody) //if selected's mom is part of main tree
|
||||
if (t.findCommonAncestor(focused_, mom) != Nobody) //if selected's mom is part of main tree
|
||||
selected = mom;
|
||||
else if (dad != Nobody)
|
||||
selected = dad;
|
||||
@@ -166,7 +285,7 @@ namespace
|
||||
|
||||
person_id selectRight(const Tree& t, person_id selected)
|
||||
{
|
||||
if (t.findCommonAncestor(t.focused(), selected) != Nobody) //if the selected is part of main tree
|
||||
if (t.findCommonAncestor(focused_, selected) != Nobody) //if the selected is part of main tree
|
||||
{
|
||||
if (person_id spouse = t.findSpouse(selected); spouse != Nobody)
|
||||
{
|
||||
|
||||
+1
-1
@@ -14,4 +14,4 @@ ZoomLevel operator++(ZoomLevel&);
|
||||
ZoomLevel operator--(ZoomLevel&);
|
||||
|
||||
class Tree;
|
||||
void displayTree(Tree&);
|
||||
void displayTree(const Tree&);
|
||||
|
||||
Reference in New Issue
Block a user