From 6cbe64f92753769058080706483b1b981b8408fc Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 2 Jan 2023 17:31:29 +0200 Subject: [PATCH] up down select and focus --- compile.sh | 3 +- main.cpp | 14 ++++--- person.cpp | 13 +++++- person.h | 18 +++++---- todo.txt | 3 ++ tree.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++---------- tree.h | 37 ++++++++++++----- 7 files changed, 154 insertions(+), 50 deletions(-) diff --git a/compile.sh b/compile.sh index 958b69a..3e159b9 100755 --- a/compile.sh +++ b/compile.sh @@ -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 diff --git a/main.cpp b/main.cpp index f58c65e..34f61a0 100644 --- a/main.cpp +++ b/main.cpp @@ -13,12 +13,14 @@ int main() initscr(); /* Start curses mode */ noecho(); cbreak(); /* get input instantly */ + keypad(stdscr, true); start_color(); use_default_colors(); /* init_pair(5, COLOR_BLACK, COLOR_BLACK); */ /* bkgd(COLOR_PAIR(5)); */ init_pair(COLOR_MALE, COLOR_BLUE, -1); /* -1 means use default */ 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 */ 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.addRelation(5, Brother, 6); */ - test1.draw(); - test2.draw(); + test1.display(); + test2.display(); - /* (test1 + test2).draw(4); */ + /* (test1 + test2).display(); */ test1 += test2; - test1.draw(4); - test1.draw(); + test1.display(); + test1.display(); /* test1.saveTree(); */ @@ -82,7 +84,7 @@ int main() /* firstTree.print(); */ - firstTree.draw(); + firstTree.display(); /* firstTree.saveTree(); */ /* firstTree.printRel(3); */ diff --git a/person.cpp b/person.cpp index 0d758d5..fcc53cb 100644 --- a/person.cpp +++ b/person.cpp @@ -159,6 +159,12 @@ void Person::print()const /* cout << '\n'; */ } + +bool Person::isMale() const +{ + return isMale_; +} + U16 Person::boxWidth() const { return name_.size() + 4; /* TODO: get actual lenght */ @@ -176,12 +182,15 @@ U16 Person::boxWidth() const /* 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(); 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); /* wattron(pad, color_pair); */ diff --git a/person.h b/person.h index 7090729..87d087a 100644 --- a/person.h +++ b/person.h @@ -7,10 +7,10 @@ struct EventTime { - //enum { UNKNOWN_DATE=0, UNKNOWN_TIME=1}; - static const I16 UNKNOWN_DATE = 0; - 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); + enum: I16 { UNKNOWN_DATE=0 }; + enum: I8 { UNKNOWN_TIME=-1 }; + + EventTime(I16 Year=UNKNOWN_DATE, U8 Month=UNKNOWN_DATE, U16 Day=UNKNOWN_DATE, I8 Hour=UNKNOWN_TIME, I8 Minute=UNKNOWN_TIME); 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 @@ -20,12 +20,13 @@ struct EventTime I8 minute; //0-59 }; -enum { +enum: U8 { COLOR_MALE = 1, - COLOR_FEMALE + COLOR_FEMALE, + COLOR_SELECTED }; -enum { +enum: U8 { BOX_HEIGHT = 5, LINK_HEIGHT = 3 }; @@ -47,12 +48,13 @@ public: void print() const; + bool isMale() const; U16 boxWidth() const; /* Draw a Person's box on the terminal drawY,drawX - the coordinates where to draw 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; */ diff --git a/todo.txt b/todo.txt index 235b10e..f0446e0 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,6 @@ +Selecting people +Help + addPerson add siblings (add relation improve) Draw distinct regions of a tree diff --git a/tree.cpp b/tree.cpp index b66e174..0bc89eb 100644 --- a/tree.cpp +++ b/tree.cpp @@ -191,6 +191,17 @@ unsigned Tree::findCommonAncestor(const unsigned firstId, const unsigned secondI return oldestId; } +/* person_id Tree::findRelation(person_id first, person_id second) const */ +/* { */ +/* const auto& curRels = relations[first]; */ +/* for(auto i =0; i= numPeople || secondId == Nobody || secondId >= numPeople || type == Invalid) + if (firstId == Nobody || firstId >= numPeople || secondId == Nobody || secondId >= numPeople || type == None) return 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 - wnoutrefresh(stdscr); + draw(); - U16 drawY = 0/* (LINES) / 2 */; - U16 drawX = 0/* (COLS) / 2 */; - drawLineWithWives(focused, drawY, drawX); - - doupdate(); - - char c; + I32 c; do { c = std::tolower(getch()); switch(c) { + case '\n': + focused_ = selected_; + draw(); + break; + case KEY_DOWN: + selectDown(); + break; + case KEY_UP: + selectUp(); + break; default: break; } } 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 { //for(const auto& member: people) @@ -465,12 +491,13 @@ void Tree::printOldestAncestors(const unsigned id)const void Tree::commonAncestorRec(person_id id, const Array &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]; - commonAncestorRec(relations[id][i].id, visited); + ++visited[curRels[i].id]; + commonAncestorRec(curRels[i].id, visited); } } } @@ -543,10 +570,10 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings) /* 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 auto& rels = relations[id]; @@ -562,13 +589,15 @@ I16 Tree::drawLineWithWives(person_id id, I16 drawY, const I16 drawX) const spouse = rels[i].id; } 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; if(spouse != Nobody) { - people[spouse].draw(drawY, drawX + person.boxWidth() + spouse_dist, false, true); - spouse_width = spouse_dist + people[spouse].boxWidth(); + people[spouse].draw(drawY, drawX + person.boxWidth() + spouse_dist_, + spouse == selected_, false, true); + spouse_width = spouse_dist_ + people[spouse].boxWidth(); } 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); } + +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; + } + } +} diff --git a/tree.h b/tree.h index 2b85b4a..009fec0 100644 --- a/tree.h +++ b/tree.h @@ -5,7 +5,7 @@ #include "person.h" using person_id = U32; -enum RelType : U8; +enum RelType: U8; struct Relation { @@ -13,7 +13,9 @@ struct Relation RelType type; }; -static constexpr person_id Nobody = UINT_MAX; +enum: person_id { + Nobody = UINT_MAX +}; class Tree { @@ -31,9 +33,10 @@ public: 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 findOldestAncestor(person_id id, bool sex = 0)const;// - person_id findCommonAncestor(person_id firstId, person_id secondId)const; //oldest common ancestor ID + 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 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;// bool loadTree(); @@ -47,7 +50,7 @@ public: void removeRelation(person_id firstId, person_id secondId); void removeRelation(const char* firstName, const char* secondName); - void draw(person_id focused=0) const; + void display(); void print()const; void printRel(person_id id)const; //Prints out close relatives @@ -56,29 +59,41 @@ public: private: void commonAncestorRec(person_id id, const Array &visited)const; + + void draw() const; /* draw a line of people starting from person with id return the farthest X that will be drawn */ I16 drawLine(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"; unsigned numPeople = 0; Array people; //The data for each member Array> relations; //The relatives of each member - U16 offset = 0; - U8 dist_between = 1; - U8 spouse_dist = 0; + person_id focused_ = 0; /* the tree was draw based on this person */ + person_id selected_ = 0; + U16 offset_ = 0; /* offset of the tree */ + U8 dist_between_ = 1; /* distance between people */ + U8 spouse_dist_ = 0; /* distance between spouses */ //Search, ect. }; enum RelType : U8 { - Invalid = 0, + None = 0, Parent, Child, Sibling, HalfSibling, Spouse, - ExSpouse + ExSpouse, + + Other };