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.");
|
mvwaddstr(info_tab, LINES-1, 0, "Press any key to return.");
|
||||||
|
|
||||||
wrefresh(info_tab);
|
wrefresh(info_tab);
|
||||||
getch(); /* waint press */
|
getch(); /* wait press */
|
||||||
|
|
||||||
werase(info_tab);
|
werase(info_tab);
|
||||||
wrefresh(info_tab); /* todo: dont update */
|
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)
|
switch(z)
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-1
@@ -57,6 +57,7 @@ public:
|
|||||||
drawY,drawX - top left coordinates where to draw (negative if outside the screen)
|
drawY,drawX - top left coordinates where to draw (negative if outside the screen)
|
||||||
partOfMain - is the person a decendant of the current root
|
partOfMain - is the person a decendant of the current root
|
||||||
hasSpouse, hasSpouse, hasChildren - wheather the person has them on display
|
hasSpouse, hasSpouse, hasChildren - wheather the person has them on display
|
||||||
|
ZoomLevel - how the box will be drawn
|
||||||
returns the width of the box*/
|
returns the width of the box*/
|
||||||
U16 drawAsFocused(I16 drawY, I16 drawX, bool selected, bool hasSpouse,
|
U16 drawAsFocused(I16 drawY, I16 drawX, bool selected, bool hasSpouse,
|
||||||
bool hasChildren, ZoomLevel) const;
|
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
|
/* 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)
|
drawY,drawX - top left coordinates where to draw (negative if outside the screen)
|
||||||
hasTree - weather the spouse has a tree that can be displayed
|
hasTree - weather the spouse has a tree that can be displayed
|
||||||
|
ZoomLevel - how the box will be drawn
|
||||||
returns the width of the box*/
|
returns the width of the box*/
|
||||||
U16 drawAsSpouse(I16 drawY, I16 drawX, bool selected, bool hasTree, ZoomLevel) const;
|
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;
|
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);
|
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)
|
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)
|
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)
|
void Tree::removePerson(const person_id id)
|
||||||
{
|
{
|
||||||
person_id relId;
|
person_id relId;
|
||||||
@@ -359,11 +348,6 @@ void Tree::removePerson(const person_id id)
|
|||||||
remove(people_, 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)
|
void Tree::removeRelation(const unsigned first, const unsigned second)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < relations_[first].size(); ++i)
|
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)
|
void Tree::updateRels(person_id id)
|
||||||
{
|
{
|
||||||
person_id dad = findParent(id, M);
|
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
|
void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
|
||||||
{
|
{
|
||||||
++visited[id];
|
++visited[id];
|
||||||
@@ -456,83 +411,3 @@ void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
|
|||||||
commonAncestorRec(rel.id, visited);
|
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 <vector>
|
||||||
#include "person.hpp"
|
#include "person.hpp"
|
||||||
|
|
||||||
enum ZoomLevel: U8;
|
|
||||||
|
|
||||||
using person_id = U32;
|
using person_id = U32;
|
||||||
enum: person_id {
|
enum: person_id {
|
||||||
Nobody = UINT32_MAX
|
Nobody = UINT32_MAX
|
||||||
@@ -48,36 +46,25 @@ public:
|
|||||||
// Get person by id
|
// Get person by id
|
||||||
const Person& operator[](person_id) const;
|
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 findId(const std::string& name, Sex) const;
|
||||||
person_id findRootAncestor(person_id) const;
|
person_id findRootAncestor(person_id) const;
|
||||||
person_id findOldestAncestor(person_id, Sex) 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 */
|
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;
|
RelType findRelation(person_id first, person_id second) const;
|
||||||
const std::vector<Relation>& findRelations(person_id) const;
|
const std::vector<Relation>& findRelations(person_id) const;
|
||||||
person_id findParent(person_id child, Sex parentSex) const;
|
person_id findParent(person_id child, Sex parentSex) const;
|
||||||
person_id findSpouse(person_id person) 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) 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={});
|
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
|
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(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(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:
|
private:
|
||||||
// recursion to find common ancestor
|
// recursion to find common ancestor
|
||||||
@@ -88,20 +75,7 @@ private:
|
|||||||
(example adds siblings after parents are added) */
|
(example adds siblings after parents are added) */
|
||||||
void updateRels(person_id);
|
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::string treeName_;
|
||||||
std::vector<Person> people_; //The data for each member
|
std::vector<Person> people_; //The data for each member
|
||||||
std::vector<std::vector<Relation>> relations_; //The relatives of 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 "tree.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "../config.h" /* user's configuration */
|
#include "../config.h" // user's configuration
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
namespace
|
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();
|
void displayHelp();
|
||||||
person_id selectLeft(const Tree& t, person_id selected);
|
person_id selectLeft(const Tree&, person_id selected);
|
||||||
person_id selectDown(const Tree& t, person_id selected);
|
person_id selectDown(const Tree&, person_id selected);
|
||||||
person_id selectUp(const Tree& t, person_id selected);
|
person_id selectUp(const Tree&, person_id selected);
|
||||||
person_id selectRight(const Tree& t, person_id selected);
|
person_id selectRight(const Tree&, person_id selected);
|
||||||
person_id selectLeftSibSpouse(const Tree& t, person_id selected); /* todo: split? */
|
person_id selectLeftSibSpouse(const Tree&, person_id selected); /* todo: split? */
|
||||||
person_id selectRightSib(const Tree& t, person_id selected);
|
person_id selectRightSib(const Tree&, person_id selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomLevel operator++(ZoomLevel& z)
|
ZoomLevel operator++(ZoomLevel& z)
|
||||||
@@ -27,10 +44,12 @@ ZoomLevel operator--(ZoomLevel& z)
|
|||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayTree(Tree& t)
|
void displayTree(const Tree& t)
|
||||||
{
|
{
|
||||||
person_id selected = 0; // the currently selected selected
|
// 0 is the first person in the tree
|
||||||
ZoomLevel zoom = ZoomLevel::FIRST_NAME; // how much info to show for each selected
|
focused_ = 0;
|
||||||
|
selected_ = 0;
|
||||||
|
zoom_ = ZoomLevel::FIRST_NAME;
|
||||||
|
|
||||||
// offset of the tree in relation to the top left corner of the screen
|
// offset of the tree in relation to the top left corner of the screen
|
||||||
I16 offsetY = 0, offsetX = 0;
|
I16 offsetY = 0, offsetX = 0;
|
||||||
@@ -40,7 +59,7 @@ void displayTree(Tree& t)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
if(to_draw)
|
if(to_draw)
|
||||||
t.draw(selected, zoom, offsetY, offsetX);
|
drawTree(t, offsetY, offsetX);
|
||||||
else
|
else
|
||||||
to_draw = true;
|
to_draw = true;
|
||||||
|
|
||||||
@@ -52,7 +71,7 @@ void displayTree(Tree& t)
|
|||||||
break;
|
break;
|
||||||
case SELECT:
|
case SELECT:
|
||||||
case '\n':
|
case '\n':
|
||||||
t.focusPerson( t.findRootAncestor(selected) );
|
focused_ = t.findRootAncestor(selected_);
|
||||||
offsetX = 0;
|
offsetX = 0;
|
||||||
offsetY = 0;
|
offsetY = 0;
|
||||||
break;
|
break;
|
||||||
@@ -70,27 +89,35 @@ void displayTree(Tree& t)
|
|||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
case '+':
|
case '+':
|
||||||
if(zoom < ZoomLevel::MAX_ZOOM)
|
if(zoom_ < ZoomLevel::MAX_ZOOM)
|
||||||
++zoom;
|
{
|
||||||
|
++zoom_;
|
||||||
|
offsetX = 0;
|
||||||
|
offsetY = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
if(zoom > 0)
|
if(zoom_ > 0)
|
||||||
--zoom;
|
{
|
||||||
|
--zoom_;
|
||||||
|
offsetX = 0;
|
||||||
|
offsetY = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SELECT_LEFT:
|
case SELECT_LEFT:
|
||||||
selected = selectLeft(t, selected);
|
selected_ = selectLeft(t, selected_);
|
||||||
break;
|
break;
|
||||||
case SELECT_DOWN:
|
case SELECT_DOWN:
|
||||||
selected = selectDown(t, selected);
|
selected_ = selectDown(t, selected_);
|
||||||
break;
|
break;
|
||||||
case SELECT_UP:
|
case SELECT_UP:
|
||||||
selected = selectUp(t, selected);
|
selected_ = selectUp(t, selected_);
|
||||||
break;
|
break;
|
||||||
case SELECT_RIGHT:
|
case SELECT_RIGHT:
|
||||||
selected = selectRight(t, selected);
|
selected_ = selectRight(t, selected_);
|
||||||
break;
|
break;
|
||||||
case DISPLAY_INFO:
|
case DISPLAY_INFO:
|
||||||
t.printMember(selected);
|
t[selected_].displayInfo();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
to_draw = false; /* invalid key, don't redraw */
|
to_draw = false; /* invalid key, don't redraw */
|
||||||
@@ -103,6 +130,98 @@ void displayTree(Tree& t)
|
|||||||
|
|
||||||
namespace
|
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()
|
void displayHelp()
|
||||||
{
|
{
|
||||||
AutoWin help_tab( newwin(LINES, COLS, 0, 0) );
|
AutoWin help_tab( newwin(LINES, COLS, 0, 0) );
|
||||||
@@ -120,7 +239,7 @@ namespace
|
|||||||
|
|
||||||
person_id selectLeft(const Tree& t, person_id selected)
|
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);
|
selected = selectLeftSibSpouse(t, selected);
|
||||||
}
|
}
|
||||||
@@ -151,12 +270,12 @@ namespace
|
|||||||
|
|
||||||
person_id selectUp(const Tree& t, person_id selected)
|
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 dad = t.findParent(selected, M);
|
||||||
person_id mom = t.findParent(selected, F);
|
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;
|
selected = mom;
|
||||||
else if (dad != Nobody)
|
else if (dad != Nobody)
|
||||||
selected = dad;
|
selected = dad;
|
||||||
@@ -166,7 +285,7 @@ namespace
|
|||||||
|
|
||||||
person_id selectRight(const Tree& t, person_id selected)
|
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)
|
if (person_id spouse = t.findSpouse(selected); spouse != Nobody)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -14,4 +14,4 @@ ZoomLevel operator++(ZoomLevel&);
|
|||||||
ZoomLevel operator--(ZoomLevel&);
|
ZoomLevel operator--(ZoomLevel&);
|
||||||
|
|
||||||
class Tree;
|
class Tree;
|
||||||
void displayTree(Tree&);
|
void displayTree(const Tree&);
|
||||||
|
|||||||
Reference in New Issue
Block a user