up down select and focus
This commit is contained in:
+1
-2
@@ -1,2 +1 @@
|
|||||||
g++ -o bin/release/famt -std=gnu++20 -Ofast -flto -fipa-pta -fallow-store-data-races -fgcse-sm -fgcse-las -s -DNDEBUG *.cpp
|
g++ -o bin/release/famt -std=gnu++20 -Ofast -flto -fipa-pta -fallow-store-data-races -fgcse-sm -fgcse-las -s -DNDEBUG *.cpp -lncursesw
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ int main()
|
|||||||
initscr(); /* Start curses mode */
|
initscr(); /* Start curses mode */
|
||||||
noecho();
|
noecho();
|
||||||
cbreak(); /* get input instantly */
|
cbreak(); /* get input instantly */
|
||||||
|
keypad(stdscr, true);
|
||||||
start_color();
|
start_color();
|
||||||
use_default_colors();
|
use_default_colors();
|
||||||
/* init_pair(5, COLOR_BLACK, COLOR_BLACK); */
|
/* init_pair(5, COLOR_BLACK, COLOR_BLACK); */
|
||||||
/* bkgd(COLOR_PAIR(5)); */
|
/* bkgd(COLOR_PAIR(5)); */
|
||||||
init_pair(COLOR_MALE, COLOR_BLUE, -1); /* -1 means use default */
|
init_pair(COLOR_MALE, COLOR_BLUE, -1); /* -1 means use default */
|
||||||
init_pair(COLOR_FEMALE, COLOR_RED, -1);
|
init_pair(COLOR_FEMALE, COLOR_RED, -1);
|
||||||
|
init_pair(COLOR_SELECTED, COLOR_YELLOW, -1);
|
||||||
wnoutrefresh(stdscr); /* if not present the first real refresh is missed */
|
wnoutrefresh(stdscr); /* if not present the first real refresh is missed */
|
||||||
|
|
||||||
Tree test1("Dechkovi"); //addTree Dechkovi addTree Karamanovi load 0 load 1 (to work with these example trees)
|
Tree test1("Dechkovi"); //addTree Dechkovi addTree Karamanovi load 0 load 1 (to work with these example trees)
|
||||||
@@ -46,13 +48,13 @@ int main()
|
|||||||
test2.addPerson("Rumiana", false, 2, 4);
|
test2.addPerson("Rumiana", false, 2, 4);
|
||||||
/* test2.addRelation(5, Brother, 6); */
|
/* test2.addRelation(5, Brother, 6); */
|
||||||
|
|
||||||
test1.draw();
|
test1.display();
|
||||||
test2.draw();
|
test2.display();
|
||||||
|
|
||||||
/* (test1 + test2).draw(4); */
|
/* (test1 + test2).display(); */
|
||||||
test1 += test2;
|
test1 += test2;
|
||||||
test1.draw(4);
|
test1.display();
|
||||||
test1.draw();
|
test1.display();
|
||||||
|
|
||||||
|
|
||||||
/* test1.saveTree(); */
|
/* test1.saveTree(); */
|
||||||
@@ -82,7 +84,7 @@ int main()
|
|||||||
|
|
||||||
|
|
||||||
/* firstTree.print(); */
|
/* firstTree.print(); */
|
||||||
firstTree.draw();
|
firstTree.display();
|
||||||
/* firstTree.saveTree(); */
|
/* firstTree.saveTree(); */
|
||||||
|
|
||||||
/* firstTree.printRel(3); */
|
/* firstTree.printRel(3); */
|
||||||
|
|||||||
+11
-2
@@ -159,6 +159,12 @@ void Person::print()const
|
|||||||
/* cout << '\n'; */
|
/* cout << '\n'; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Person::isMale() const
|
||||||
|
{
|
||||||
|
return isMale_;
|
||||||
|
}
|
||||||
|
|
||||||
U16 Person::boxWidth() const
|
U16 Person::boxWidth() const
|
||||||
{
|
{
|
||||||
return name_.size() + 4; /* TODO: get actual lenght */
|
return name_.size() + 4; /* TODO: get actual lenght */
|
||||||
@@ -176,12 +182,15 @@ U16 Person::boxWidth() const
|
|||||||
/* return pad; */
|
/* return pad; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
void Person::draw(I16 drawY, I16 drawX, bool hasSpouse, bool isSpouse, bool hasKids) const
|
void Person::draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasKids) const
|
||||||
{
|
{
|
||||||
U16 width = boxWidth();
|
U16 width = boxWidth();
|
||||||
WINDOW* pad = newpad(BOX_HEIGHT, width);
|
WINDOW* pad = newpad(BOX_HEIGHT, width);
|
||||||
|
|
||||||
auto color_pair = COLOR_PAIR(isMale_ ? COLOR_MALE : COLOR_FEMALE);
|
auto color_pair = COLOR_PAIR( selected ? COLOR_SELECTED
|
||||||
|
: (isMale_ ? COLOR_MALE : COLOR_FEMALE) );
|
||||||
|
|
||||||
|
|
||||||
wbkgd(pad, color_pair);
|
wbkgd(pad, color_pair);
|
||||||
/* wattron(pad, color_pair); */
|
/* wattron(pad, color_pair); */
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
|
|
||||||
struct EventTime
|
struct EventTime
|
||||||
{
|
{
|
||||||
//enum { UNKNOWN_DATE=0, UNKNOWN_TIME=1};
|
enum: I16 { UNKNOWN_DATE=0 };
|
||||||
static const I16 UNKNOWN_DATE = 0;
|
enum: I8 { UNKNOWN_TIME=-1 };
|
||||||
static const I8 UNKNOWN_TIME = -1;
|
|
||||||
/*explicit*/ EventTime(I16 Year=UNKNOWN_DATE, U8 Month=UNKNOWN_DATE, U16 Day=UNKNOWN_DATE, I8 Hour=UNKNOWN_TIME, I8 Minute=UNKNOWN_TIME);
|
EventTime(I16 Year=UNKNOWN_DATE, U8 Month=UNKNOWN_DATE, U16 Day=UNKNOWN_DATE, I8 Hour=UNKNOWN_TIME, I8 Minute=UNKNOWN_TIME);
|
||||||
void print() const;
|
void print() const;
|
||||||
|
|
||||||
I16 year; //The year in relation to Chritst's birth - 1 (AD) is the year He was born, -1 (BC) is the previous year. There is no year 0
|
I16 year; //The year in relation to Chritst's birth - 1 (AD) is the year He was born, -1 (BC) is the previous year. There is no year 0
|
||||||
@@ -20,12 +20,13 @@ struct EventTime
|
|||||||
I8 minute; //0-59
|
I8 minute; //0-59
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum: U8 {
|
||||||
COLOR_MALE = 1,
|
COLOR_MALE = 1,
|
||||||
COLOR_FEMALE
|
COLOR_FEMALE,
|
||||||
|
COLOR_SELECTED
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum: U8 {
|
||||||
BOX_HEIGHT = 5,
|
BOX_HEIGHT = 5,
|
||||||
LINK_HEIGHT = 3
|
LINK_HEIGHT = 3
|
||||||
};
|
};
|
||||||
@@ -47,12 +48,13 @@ public:
|
|||||||
|
|
||||||
void print() const;
|
void print() const;
|
||||||
|
|
||||||
|
bool isMale() const;
|
||||||
U16 boxWidth() const;
|
U16 boxWidth() const;
|
||||||
|
|
||||||
/* Draw a Person's box on the terminal
|
/* Draw a Person's box on the terminal
|
||||||
drawY,drawX - the coordinates where to draw
|
drawY,drawX - the coordinates where to draw
|
||||||
returns the width of the box*/
|
returns the width of the box*/
|
||||||
void draw(I16 drawY, I16 drawX, bool hasSpouse, bool isSpouse, bool hasChildren=false) const;
|
void draw(I16 drawY, I16 drawX, bool selected, bool hasSpouse, bool isSpouse, bool hasChildren=false) const;
|
||||||
|
|
||||||
/* WINDOW* createPad()const; */
|
/* WINDOW* createPad()const; */
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
Selecting people
|
||||||
|
Help
|
||||||
|
|
||||||
addPerson add siblings (add relation improve)
|
addPerson add siblings (add relation improve)
|
||||||
|
|
||||||
Draw distinct regions of a tree
|
Draw distinct regions of a tree
|
||||||
|
|||||||
@@ -191,6 +191,17 @@ unsigned Tree::findCommonAncestor(const unsigned firstId, const unsigned secondI
|
|||||||
return oldestId;
|
return oldestId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* person_id Tree::findRelation(person_id first, person_id second) const */
|
||||||
|
/* { */
|
||||||
|
/* const auto& curRels = relations[first]; */
|
||||||
|
/* for(auto i =0; i<curRels.gNum(); ++i) */
|
||||||
|
/* { */
|
||||||
|
/* if(curRels[i].id == second) */
|
||||||
|
/* { */
|
||||||
|
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
void Tree::saveTree() const
|
void Tree::saveTree() const
|
||||||
{
|
{
|
||||||
std::ofstream peopleFile(treeName+ ".people", std::ios::binary);
|
std::ofstream peopleFile(treeName+ ".people", std::ios::binary);
|
||||||
@@ -263,7 +274,7 @@ bool Tree::addRelation(const char* firstName, const RelType type, const char* se
|
|||||||
|
|
||||||
bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigned secondId, bool opposite)//
|
bool Tree::addRelation(const unsigned firstId, const RelType type, const unsigned secondId, bool opposite)//
|
||||||
{
|
{
|
||||||
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == Invalid)
|
if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == None)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
@@ -367,30 +378,45 @@ void Tree::removeRelation(const unsigned firstId, const unsigned secondId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tree::draw(person_id focused) const
|
void Tree::display()
|
||||||
{
|
{
|
||||||
erase(); //Clear the screen
|
draw();
|
||||||
wnoutrefresh(stdscr);
|
|
||||||
|
|
||||||
U16 drawY = 0/* (LINES) / 2 */;
|
I32 c;
|
||||||
U16 drawX = 0/* (COLS) / 2 */;
|
|
||||||
drawLineWithWives(focused, drawY, drawX);
|
|
||||||
|
|
||||||
doupdate();
|
|
||||||
|
|
||||||
char c;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
c = std::tolower(getch());
|
c = std::tolower(getch());
|
||||||
|
|
||||||
switch(c)
|
switch(c)
|
||||||
{
|
{
|
||||||
|
case '\n':
|
||||||
|
focused_ = selected_;
|
||||||
|
draw();
|
||||||
|
break;
|
||||||
|
case KEY_DOWN:
|
||||||
|
selectDown();
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
selectUp();
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(c != 'w');
|
while(c != 'w');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tree::draw() const
|
||||||
|
{
|
||||||
|
erase(); //Clear the screen
|
||||||
|
wnoutrefresh(stdscr);
|
||||||
|
|
||||||
|
U16 drawY = 0/* (LINES) / 2 */;
|
||||||
|
U16 drawX = 0/* (COLS) / 2 */;
|
||||||
|
drawLineWithWives(focused_, drawY, drawX);
|
||||||
|
|
||||||
|
doupdate();
|
||||||
|
}
|
||||||
|
|
||||||
void Tree::print() const
|
void Tree::print() const
|
||||||
{
|
{
|
||||||
//for(const auto& member: people)
|
//for(const auto& member: people)
|
||||||
@@ -465,12 +491,13 @@ void Tree::printOldestAncestors(const unsigned id)const
|
|||||||
|
|
||||||
void Tree::commonAncestorRec(person_id id, const Array<char> &visited)const
|
void Tree::commonAncestorRec(person_id id, const Array<char> &visited)const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < people[id].numRel_; ++i)
|
auto& curRels = relations[id];
|
||||||
|
for (unsigned i = 0; i < curRels.gNum(); ++i)
|
||||||
{
|
{
|
||||||
if (relations[id][i].type == Child)
|
if (curRels[i].type == Child)
|
||||||
{
|
{
|
||||||
++visited[relations[id][i].id];
|
++visited[curRels[i].id];
|
||||||
commonAncestorRec(relations[id][i].id, visited);
|
commonAncestorRec(curRels[i].id, visited);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,10 +570,10 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
|
|||||||
/* return drawX; */
|
/* return drawX; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
/* return drawX + people[id].boxWidth() + dist_between; */
|
/* return drawX + people[id].boxWidth() + dist_between_; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
I16 Tree::drawLineWithWives(person_id id, I16 drawY, const I16 drawX) const
|
I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) const
|
||||||
{
|
{
|
||||||
const Person& person = people[id];
|
const Person& person = people[id];
|
||||||
const auto& rels = relations[id];
|
const auto& rels = relations[id];
|
||||||
@@ -562,13 +589,15 @@ I16 Tree::drawLineWithWives(person_id id, I16 drawY, const I16 drawX) const
|
|||||||
spouse = rels[i].id;
|
spouse = rels[i].id;
|
||||||
}
|
}
|
||||||
const size_t numKids = children.size();
|
const size_t numKids = children.size();
|
||||||
person.draw(drawY, drawX, spouse!=Nobody, false, numKids!=0);
|
person.draw(drawY, drawX,
|
||||||
|
id == selected_, spouse!=Nobody, false, numKids!=0);
|
||||||
|
|
||||||
U16 spouse_width = 0;
|
U16 spouse_width = 0;
|
||||||
if(spouse != Nobody)
|
if(spouse != Nobody)
|
||||||
{
|
{
|
||||||
people[spouse].draw(drawY, drawX + person.boxWidth() + spouse_dist, false, true);
|
people[spouse].draw(drawY, drawX + person.boxWidth() + spouse_dist_,
|
||||||
spouse_width = spouse_dist + people[spouse].boxWidth();
|
spouse == selected_, false, true);
|
||||||
|
spouse_width = spouse_dist_ + people[spouse].boxWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto childX = drawX;
|
auto childX = drawX;
|
||||||
@@ -588,6 +617,51 @@ I16 Tree::drawLineWithWives(person_id id, I16 drawY, const I16 drawX) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max(drawX + person.boxWidth() + dist_between + spouse_width,
|
return max(drawX + person.boxWidth() + dist_between_ + spouse_width,
|
||||||
childX);
|
childX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tree::selectLeft() /* todo */
|
||||||
|
{
|
||||||
|
const auto& curRel = relations[selected_];
|
||||||
|
|
||||||
|
for(U32 i = 0; i < curRel.gNum(); ++i)
|
||||||
|
{
|
||||||
|
if(curRel[i].type == Sibling)
|
||||||
|
{
|
||||||
|
selected_ = curRel[i].id;
|
||||||
|
draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::selectDown()
|
||||||
|
{
|
||||||
|
const auto& curRel = relations[selected_];
|
||||||
|
|
||||||
|
for(U32 i = 0; i < curRel.gNum(); ++i)
|
||||||
|
{
|
||||||
|
if(curRel[i].type == Parent)
|
||||||
|
{
|
||||||
|
selected_ = curRel[i].id;
|
||||||
|
draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tree::selectUp()
|
||||||
|
{
|
||||||
|
const auto& curRel = relations[selected_];
|
||||||
|
|
||||||
|
for(U32 i = 0; i < curRel.gNum(); ++i)
|
||||||
|
{
|
||||||
|
if(curRel[i].type == Child && (people[curRel[i].id].isMale() || curRel[i].id == focused_))
|
||||||
|
{
|
||||||
|
selected_ = curRel[i].id;
|
||||||
|
draw();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "person.h"
|
#include "person.h"
|
||||||
|
|
||||||
using person_id = U32;
|
using person_id = U32;
|
||||||
enum RelType : U8;
|
enum RelType: U8;
|
||||||
|
|
||||||
struct Relation
|
struct Relation
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,9 @@ struct Relation
|
|||||||
RelType type;
|
RelType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr person_id Nobody = UINT_MAX;
|
enum: person_id {
|
||||||
|
Nobody = UINT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
class Tree
|
class Tree
|
||||||
{
|
{
|
||||||
@@ -31,9 +33,10 @@ public:
|
|||||||
|
|
||||||
void rename(const char* newName);
|
void rename(const char* newName);
|
||||||
|
|
||||||
person_id findId(const char*, short year=0, const unsigned char month=0, const unsigned char day=0)const;
|
person_id findId(const char*, short year=0, const unsigned char month=0, const unsigned char day=0) const;
|
||||||
person_id findOldestAncestor(person_id id, bool sex = 0)const;//
|
person_id findOldestAncestor(person_id id, bool sex = 0) const;//
|
||||||
person_id findCommonAncestor(person_id firstId, person_id secondId)const; //oldest common ancestor ID
|
person_id findCommonAncestor(person_id firstId, person_id secondId) const; //oldest common ancestor ID
|
||||||
|
person_id findRelation(person_id first, person_id second) const;
|
||||||
|
|
||||||
void saveTree()const;//
|
void saveTree()const;//
|
||||||
bool loadTree();
|
bool loadTree();
|
||||||
@@ -47,7 +50,7 @@ public:
|
|||||||
void removeRelation(person_id firstId, person_id secondId);
|
void removeRelation(person_id firstId, person_id secondId);
|
||||||
void removeRelation(const char* firstName, const char* secondName);
|
void removeRelation(const char* firstName, const char* secondName);
|
||||||
|
|
||||||
void draw(person_id focused=0) const;
|
void display();
|
||||||
|
|
||||||
void print()const;
|
void print()const;
|
||||||
void printRel(person_id id)const; //Prints out close relatives
|
void printRel(person_id id)const; //Prints out close relatives
|
||||||
@@ -56,29 +59,41 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void commonAncestorRec(person_id id, const Array<char> &visited)const;
|
void commonAncestorRec(person_id id, const Array<char> &visited)const;
|
||||||
|
|
||||||
|
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 drawLine(person_id id, I16 drawY, I16 drawX) const;
|
I16 drawLine(person_id id, I16 drawY, I16 drawX) const;
|
||||||
I16 drawLineWithWives(person_id id, I16 drawY, I16 drawX) const;
|
I16 drawLineWithWives(person_id id, I16 drawY, I16 drawX) const;
|
||||||
|
|
||||||
|
void selectLeft();
|
||||||
|
void selectDown();
|
||||||
|
void selectUp();
|
||||||
|
void selectRight();
|
||||||
|
|
||||||
|
|
||||||
std::string treeName = "Unnamed";
|
std::string treeName = "Unnamed";
|
||||||
unsigned numPeople = 0;
|
unsigned numPeople = 0;
|
||||||
Array<Person> people; //The data for each member
|
Array<Person> people; //The data for each member
|
||||||
Array<Array<Relation>> relations; //The relatives of each member
|
Array<Array<Relation>> relations; //The relatives of each member
|
||||||
|
|
||||||
U16 offset = 0;
|
person_id focused_ = 0; /* the tree was draw based on this person */
|
||||||
U8 dist_between = 1;
|
person_id selected_ = 0;
|
||||||
U8 spouse_dist = 0;
|
U16 offset_ = 0; /* offset of the tree */
|
||||||
|
U8 dist_between_ = 1; /* distance between people */
|
||||||
|
U8 spouse_dist_ = 0; /* distance between spouses */
|
||||||
//Search, ect.
|
//Search, ect.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RelType : U8
|
enum RelType : U8
|
||||||
{
|
{
|
||||||
Invalid = 0,
|
None = 0,
|
||||||
Parent,
|
Parent,
|
||||||
Child,
|
Child,
|
||||||
Sibling,
|
Sibling,
|
||||||
HalfSibling,
|
HalfSibling,
|
||||||
Spouse,
|
Spouse,
|
||||||
ExSpouse
|
ExSpouse,
|
||||||
|
|
||||||
|
Other
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user