diff --git a/src/person.cpp b/src/person.cpp index f9079f8..5fe1987 100644 --- a/src/person.cpp +++ b/src/person.cpp @@ -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) { diff --git a/src/person.hpp b/src/person.hpp index f950bea..3112197 100644 --- a/src/person.hpp +++ b/src/person.hpp @@ -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); diff --git a/src/tree.cpp b/src/tree.cpp index 7d42409..aa70252 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -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 &visited) const { ++visited[id]; @@ -456,83 +411,3 @@ void Tree::commonAncestorRec(person_id id, vector &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 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); -} diff --git a/src/tree.hpp b/src/tree.hpp index 203664c..322adf1 100644 --- a/src/tree.hpp +++ b/src/tree.hpp @@ -4,8 +4,6 @@ #include #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 findId(const std::string& name) const; + std::vector 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& findRelations(person_id) const; person_id findParent(person_id child, Sex parentSex) const; person_id findSpouse(person_id person) const; std::vector findChildren(person_id person) const; - std::vector findChildren(person_id person, person_id exclude) const; + std::vector 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 people_; //The data for each member std::vector> 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 */ }; diff --git a/src/ui.cpp b/src/ui.cpp index b05115c..9ef9c46 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -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 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) { diff --git a/src/ui.hpp b/src/ui.hpp index fab3e4b..632d8e3 100644 --- a/src/ui.hpp +++ b/src/ui.hpp @@ -14,4 +14,4 @@ ZoomLevel operator++(ZoomLevel&); ZoomLevel operator--(ZoomLevel&); class Tree; -void displayTree(Tree&); +void displayTree(const Tree&); diff --git a/todo.txt b/todo.txt index 1e33724..9cab631 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,5 @@ +Give error when wrongly indexed person declaration + findRelative findRelation - extend