move keyhandling from Tree

This commit is contained in:
vrd
2023-11-11 19:09:01 +02:00
parent bc5e5d1deb
commit 06186f51a2
8 changed files with 287 additions and 310 deletions
-53
View File
@@ -1,53 +0,0 @@
void create_tree()
{
// Declare your tree
Tree t("first_tree");
// Add member Adam with parents Nobody
t.addPerson("Адам", M, // ID 0
Nobody, Nobody,
{0, 1, 6}); // Born: y, m, d
t.addPerson("Ева", F, // ID 1
Nobody, Nobody,
{0, 1, 6});
// Adam (0) is a Spouse of Eve (1)
t.addRelation(0, Spouse, 1);
// Add Cain with parents Adam (0) and Eve
t.addPerson("Кайн", M,
0, 1);
t.addPerson("Авел", M,
0, 1);
t.addPerson("Сит", M,
0, 1,
230);
t.addPerson("Енос", M,
4, Nobody,
435);
t.addPerson("Каинан", M,
5, Nobody,
605);
t.addPerson("Малелеил", M,
6, Nobody,
605);
t.addPerson("Енох", M,
3, Nobody);
t.addPerson("Гаидад", M,
8, Nobody);
t.addPerson("Малелеил", M,
9, Nobody);
/* t.saveToFile(); */
t.display();
}
+2
View File
@@ -1,3 +1,5 @@
#include "tree.hpp" #include "tree.hpp"
// Parses tft files to produce a Tree object
Tree parseTftFile(const char* path); Tree parseTftFile(const char* path);
+2 -1
View File
@@ -1,6 +1,7 @@
#include "tree.hpp" #include "tree.hpp"
#include "utils.hpp" #include "utils.hpp"
#include "parser.hpp" #include "parser.hpp"
#include "ui.hpp"
#include <ncursesw/ncurses.h> #include <ncursesw/ncurses.h>
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
@@ -31,7 +32,7 @@ int main(int argc, char* argv[])
} }
init_ncurses(); init_ncurses();
tree.display(); displayTree(tree);
return 0; return 0;
} }
+17 -231
View File
@@ -4,8 +4,6 @@
#include <fstream> #include <fstream>
#include <assert.h> #include <assert.h>
#include "../config.h" /* user's configuration */
using std::vector; using std::vector;
using std::string; using std::string;
@@ -86,10 +84,9 @@ Tree& Tree::operator-= (const Tree& other)
return *this; return *this;
} }
bool Tree::isEmpty()
void Tree::rename(const char* newName)
{ {
treeName_ = newName; return people_.empty();
} }
person_id Tree::last() person_id Tree::last()
@@ -229,6 +226,11 @@ RelType Tree::findRelation(person_id first, person_id second) const
return None; return None;
} }
const std::vector<Relation>& Tree::findRelations(person_id id) const
{
return relations_[id];
}
void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother, EventTime birth, EventTime death) void Tree::addPerson(const char* name, Sex sex, unsigned father, unsigned mother, EventTime birth, EventTime death)
{ {
people_.emplace_back(name, birth, sex, death); people_.emplace_back(name, birth, sex, death);
@@ -359,87 +361,14 @@ void Tree::removeRelation(const unsigned first, const unsigned second)
} }
} }
static void displayHelp() void Tree::focusPerson(person_id id)
{ {
AutoWin help_tab( newwin(LINES, COLS, 0, 0) ); focused_ = id;
waddstr(help_tab, VISUALIZATION_HELP_STR);
mvwaddstr(help_tab, LINES-1, 0, "Press any key to return.");
wrefresh(help_tab);
getch(); /* wait press */
werase(help_tab);
wnoutrefresh(help_tab);
} }
void Tree::display() person_id Tree::focused() const
{ {
if(people_.size() == 0) return focused_;
return;
bool to_draw = true;
I32 c;
do
{
if(to_draw)
draw();
else
to_draw = true;
c = getch();
switch(c)
{
case KEY_F(1):
displayHelp();
break;
case SELECT:
case '\n':
focused_ = findRootAncestor(selected_);
offsetX_ = 0;
offsetY_ = 0;
break;
case MOVE_LEFT:
++offsetX_;
break;
case MOVE_RIGHT:
--offsetX_;
break;
case MOVE_DOWN:
--offsetY_;
break;
case MOVE_UP:
++offsetY_;
break;
case '=':
case '+':
zoom_ = 1;
break;
case '-':
zoom_ = 0;
break;
case SELECT_LEFT:
selectLeft();
break;
case SELECT_DOWN:
selectDown();
break;
case SELECT_UP:
selectUp();
break;
case SELECT_RIGHT:
selectRight();
break;
case DISPLAY_INFO:
people_[selected_].displayInfo();
break;
default:
to_draw = false; /* invalid key, don't redraw */
break;
}
}
while(c != CLOSE);
} }
void Tree::updateRels(person_id id) void Tree::updateRels(person_id id)
@@ -474,35 +403,24 @@ void Tree::updateRels(person_id id)
} }
void Tree::draw() const void Tree::draw(const person_id selected, const U8 zoom, const I16 offsetY, const I16 offsetX)
{ {
selected_ = selected;
zoom_ = zoom;
erase(); //Clear the screen erase(); //Clear the screen
wnoutrefresh(stdscr); wnoutrefresh(stdscr);
I16 drawY = offsetY_; drawLineWithWives(focused_, offsetY, offsetX);
I16 drawX = offsetX_;
drawLineWithWives(focused_, drawY, drawX);
doupdate(); doupdate();
} }
void Tree::print() const void Tree::printMember(const unsigned id)const // todo: rename
{
for(const Person& member: people_)
member.displayInfo();
}
void Tree::printMember(const unsigned id)const
{ {
people_[id].displayInfo(); people_[id].displayInfo();
} }
void Tree::printOldestAncestors(const unsigned id)const
{
people_[findOldestAncestor(id, M)].displayInfo();
people_[findOldestAncestor(id, F)].displayInfo();
}
void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
{ {
@@ -634,135 +552,3 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
return max(drawX + person_w + dist_between_ + spouse_w, return max(drawX + person_w + dist_between_ + spouse_w,
childX); childX);
} }
void Tree::selectLeft()
{
if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree
{
selectLeftSibSpouse(selected_);
}
else
{
person_id spouse = findSpouse(selected_);
assert(spouse != Nobody);
selected_ = spouse;
}
draw();
}
void Tree::selectDown()
{
const auto& curRels = relations_[selected_];
for(const Relation& rel: curRels)
{
if (rel.type == Parent)
{
selected_ = rel.id;
draw();
return;
}
}
}
void Tree::selectUp()
{
if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree
{
person_id dad = findParent(selected_, M);
person_id mom = findParent(selected_, F);
if (findCommonAncestor(focused_, mom) != Nobody) //if selecteds mom is part of main tree
selected_ = mom;
else if (dad != Nobody)
selected_ = dad;
draw();
}
}
void Tree::selectRight()
{
if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree
{
if (person_id spouse = findSpouse(selected_); spouse != Nobody)
{
selected_ = spouse;
}
else
{
selectRightSib(selected_);
}
}
else //if spouse of someone in main tree
{
person_id spouse = findSpouse(selected_);
assert(spouse != Nobody);
selectRightSib(spouse);
}
draw();
}
void Tree::selectLeftSibSpouse(person_id person) /* todo: return a value and split */
{
person_id leftSib = Nobody;
if(findRelation(person, focused_) == Child)
{
auto siblings = findChildren(focused_);
for(auto it = siblings.begin()+1; it < siblings.end(); ++it)
{
if(*it == person)
{
leftSib = *(it-1);
break;
}
}
}
else if(person_id sel_par = findParent(person, M); sel_par != Nobody)
{
auto siblings = findChildren(sel_par);
for(auto it = siblings.begin()+1; it < siblings.end(); ++it)
{
if(*it == person)
{
leftSib = *(it-1);
break;
}
}
}
if(leftSib != Nobody)
{
person_id leftSibSpouse = findSpouse(leftSib);
selected_ = leftSibSpouse != Nobody ? leftSibSpouse : leftSib;
}
}
void Tree::selectRightSib(person_id person)
{
if(findRelation(person, focused_) == Child)
{
auto siblings = findChildren(focused_);
for(auto it = siblings.begin(); it < siblings.end()-1; ++it)
{
if(*it == person)
{
selected_ = *(it+1);
break;
}
}
}
else if(person_id sel_par = findParent(person, M); sel_par != Nobody)
{
auto siblings = findChildren(sel_par);
for(auto it = siblings.begin(); it < siblings.end()-1; ++it)
{
if(*it == person)
{
selected_ = *(it+1);
break;
}
}
}
}
+13 -23
View File
@@ -34,17 +34,15 @@ public:
Tree() = default; Tree() = default;
template <class Str> template <class Str>
explicit Tree(Str&& Name) : treeName_(std::forward<Str>(Name)) {} explicit Tree(Str&& Name) : treeName_(std::forward<Str>(Name)) {}
/* Tree(const Tree&) = default; */
/* Tree& operator= (const Tree& other); */
Tree operator+ (const Tree& other) const; Tree operator+ (const Tree& other) const;
Tree operator- (const Tree& other) const; /* todo */ Tree operator- (const Tree& other) const; /* todo */
Tree& operator+= (const Tree& other); Tree& operator+= (const Tree& other);
Tree& operator-= (const Tree& other); Tree& operator-= (const Tree& other);
void rename(const char* newName); bool isEmpty();
person_id last(); person_id last();
std::vector<person_id> findId(const std::string& name) const; std::vector<person_id> findId(const std::string& name) const;
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;
@@ -53,6 +51,7 @@ public:
//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;
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;
@@ -67,15 +66,16 @@ public:
void removeRelation(person_id first, person_id second); void removeRelation(person_id first, person_id second);
void removeRelation(const char* firstName, const char* secondName); void removeRelation(const char* firstName, const char* secondName);
/* display the tree and wait process key input */ /* draw the tree based on this person */
void display(); void focusPerson(person_id);
person_id focused() const;
void print()const;
/* void printRel(person_id id)const; //Prints out close relatives */ /* void printRel(person_id id)const; //Prints out close relatives */
void printMember(person_id)const; void printMember(person_id)const;
void printOldestAncestors(person_id)const;// void draw(person_id selected, U8 zoom, I16 offsetY, I16 offsetX);
private: private:
// recursion to find common ancestor
void commonAncestorRec(person_id, std::vector<U8> &visited)const; void commonAncestorRec(person_id, std::vector<U8> &visited)const;
void addRelOneSide(person_id first, RelType, person_id second); void addRelOneSide(person_id first, RelType, person_id second);
@@ -83,30 +83,20 @@ private:
(example adds siblings after parents are added) */ (example adds siblings after parents are added) */
void updateRels(person_id); void updateRels(person_id);
void draw() const;
/* draw a line of people starting from person with id /* draw a line of people starting from person with id
return the farthest X that will be drawn */ return the farthest X that will be drawn */
I16 drawLineWithWives(person_id, I16 drawY, I16 drawX) const; I16 drawLineWithWives(person_id, I16 drawY, I16 drawX) const;
void selectLeft();
void selectDown();
void selectUp();
void selectRight();
void selectLeftSibSpouse(person_id);
void selectRightSib(person_id);
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 focused_ = 0; /* the tree was draw based on this person */
person_id selected_ = 0; person_id selected_ = 0;
I16 offsetX_ = 0; /* offset of the tree in relation to the screen*/
I16 offsetY_ = 0;
U8 zoom_ = 0; U8 zoom_ = 0;
U8 dist_between_ = 1; /* distance between people */
U8 spouse_dist_ = 0; /* distance between spouses */
//Search, ect.
};
// 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 */
};
+240
View File
@@ -0,0 +1,240 @@
#include "tree.hpp"
#include "utils.hpp"
#include "assert.h"
#include "../config.h" /* user's configuration */
namespace
{
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);
}
void displayTree(Tree& t)
{
// checck there are people
person_id selected = 0; // the currently selected selected
U8 zoom = 0; // how much info to show for each selected
// offset of the tree in relation to the top left corner of the screen
I16 offsetY = 0, offsetX = 0;
bool to_draw = true;
I32 input;
do
{
if(to_draw)
t.draw(selected, zoom, offsetY, offsetX);
else
to_draw = true;
input = getch();
switch(input)
{
case KEY_F(1):
displayHelp();
break;
case SELECT:
case '\n':
t.focusPerson( t.findRootAncestor(selected) );
offsetX = 0;
offsetY = 0;
break;
case MOVE_LEFT:
++offsetX;
break;
case MOVE_RIGHT:
--offsetX;
break;
case MOVE_DOWN:
--offsetY;
break;
case MOVE_UP:
++offsetY;
break;
case '=':
case '+':
zoom = 1;
break;
case '-':
zoom = 0;
break;
case SELECT_LEFT:
selected = selectLeft(t, selected);
break;
case SELECT_DOWN:
selected = selectDown(t, selected);
break;
case SELECT_UP:
selected = selectUp(t, selected);
break;
case SELECT_RIGHT:
selected = selectRight(t, selected);
break;
case DISPLAY_INFO:
t.printMember(selected);
break;
default:
to_draw = false; /* invalid key, don't redraw */
break;
}
}
while(input != CLOSE);
}
namespace
{
void displayHelp()
{
AutoWin help_tab( newwin(LINES, COLS, 0, 0) );
waddstr(help_tab, VISUALIZATION_HELP_STR);
mvwaddstr(help_tab, LINES-1, 0, "Press any key to return.");
wrefresh(help_tab);
getch(); /* wait press */
werase(help_tab);
wnoutrefresh(help_tab);
}
person_id selectLeft(const Tree& t, person_id selected)
{
if (t.findCommonAncestor(t.focused(), selected) != Nobody) //if the selected is part of main tree
{
selected = selectLeftSibSpouse(t, selected);
}
else
{
person_id spouse = t.findSpouse(selected);
assert(spouse != Nobody);
selected = spouse;
}
return selected;
}
person_id selectDown(const Tree& t, person_id selected)
{
const auto& curRels = t.findRelations(selected);
for(const Relation& rel: curRels)
{
if (rel.type == Parent)
{
selected = rel.id;
break;
}
}
return 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
{
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
selected = mom;
else if (dad != Nobody)
selected = dad;
}
return 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 (person_id spouse = t.findSpouse(selected); spouse != Nobody)
{
selected = spouse;
}
else
{
selected = selectRightSib(t, selected);
}
}
else //if spouse of someone in main tree
{
person_id spouse = t.findSpouse(selected);
assert(spouse != Nobody);
selected = selectRightSib(t, spouse);
}
return selected;
}
person_id selectLeftSibSpouse(const Tree& t, person_id selected) /* todo: return a value and split */
{
person_id leftSib = Nobody;
if(t.findRelation(selected, t.focused()) == Child) // todo: why not just the else?
{
auto siblings = t.findChildren(t.focused());
for(auto it = siblings.begin()+1; it < siblings.end(); ++it)
{
if(*it == selected)
{
leftSib = *(it-1);
break;
}
}
}
else if(person_id sel_par = t.findParent(selected, M); sel_par != Nobody)
{
auto siblings = t.findChildren(sel_par);
for(auto it = siblings.begin()+1; it < siblings.end(); ++it)
{
if(*it == selected)
{
leftSib = *(it-1);
break;
}
}
}
if(leftSib != Nobody)
{
person_id leftSibSpouse = t.findSpouse(leftSib);
selected = (leftSibSpouse != Nobody) ? leftSibSpouse : leftSib;
}
return selected;
}
person_id selectRightSib(const Tree& t, person_id selected)
{
if(t.findRelation(selected, t.focused()) == Child)
{
auto siblings = t.findChildren(t.focused());
for(auto it = siblings.begin(); it < siblings.end()-1; ++it)
{
if(*it == selected)
{
selected = *(it+1);
break;
}
}
}
else if(person_id sel_par = t.findParent(selected, M); sel_par != Nobody)
{
auto siblings = t.findChildren(sel_par);
for(auto it = siblings.begin(); it < siblings.end()-1; ++it)
{
if(*it == selected)
{
selected = *(it+1);
break;
}
}
}
return selected;
}
}
+6
View File
@@ -0,0 +1,6 @@
#pragma once
// Handles keys and displays the tree
class Tree;
void displayTree(Tree&);
+7 -2
View File
@@ -2,12 +2,12 @@ findRelative
findRelation - extend findRelation - extend
Combine trees on the command line
Person info Person info
man page man page
types - screenCoord...
Visualization: Visualization:
- zooming - zooming
- snap to selection/scroll with selection - snap to selection/scroll with selection
@@ -17,6 +17,8 @@ Visualization:
- empty tree - empty tree
- half children and main tree - half children and main tree
- distinct tree regions - distinct tree regions
- aproximate birth day
- indicator for people with their own tree
Compilation Compilation
- static and dynamic ncurses - static and dynamic ncurses
@@ -31,4 +33,7 @@ Compilation
Refactoring Refactoring
- comment style /* - comment style /*
test
- no Adam
readelf -a /usr/lib/x86_64-linux-gnu/libncursesw.a | grep lto readelf -a /usr/lib/x86_64-linux-gnu/libncursesw.a | grep lto