Selaa lähdekoodia

[add] JSonContainer first child's getter
[add] expand / collapse mode

isundil 9 vuotta sitten
vanhempi
commit
11e536e011
7 muutettua tiedostoa jossa 125 lisäystä ja 27 poistoa
  1. 6 2
      include/curseOutput.hh
  2. 3 0
      include/jsonArray.hh
  3. 2 0
      include/jsonContainer.hh
  4. 3 0
      include/jsonObject.hh
  5. 83 25
      src/curseOutput.cpp
  6. 14 0
      src/jsonArray.cpp
  7. 14 0
      src/jsonObject.cpp

+ 6 - 2
include/curseOutput.hh

@@ -2,9 +2,11 @@
 
 #include <fstream>
 #include <ios>
+#include <set>
 #include <ncurses.h>
 
 class JSonElement;
+class JSonContainer;
 template<class T> class Optional;
 
 class CurseOutput
@@ -27,7 +29,7 @@ class CurseOutput
         /**
          * return false if bottom of screen is touched
         **/
-        bool redraw(std::pair<int, int> &, const std::pair<int, int>&, const JSonElement *);
+        bool redraw(std::pair<int, int> &, const std::pair<int, int>&, const JSonElement *, const JSonContainer *);
         bool readInput();
         void getScreenSize(std::pair<int, int> &, std::pair<int, int> &);
         static CurseOutput::t_nextKey findNext(const JSonElement *);
@@ -35,6 +37,8 @@ class CurseOutput
         void write(const int &x, const int &y, const std::string &item, bool selected =false);
         void writeKey(const std::string &key, std::pair<int, int> &cursor, bool selected);
 
+        std::set<const JSonContainer *> collapsed;
+
         const JSonElement *data, *selection;
         SCREEN *screen;
         FILE *screen_fd;
@@ -43,7 +47,7 @@ class CurseOutput
         const unsigned int indentLevel;
 
         //FIXME optimize
-        const JSonElement *select_up, *select_down;
+        const JSonElement *select_up, *select_down, *select_parent;
         bool selectFound;
 };
 

+ 3 - 0
include/jsonArray.hh

@@ -9,5 +9,8 @@ class JSonArray: public JSonContainer, public std::list<JSonElement *>
         JSonArray(JSonContainer *parent);
         virtual ~JSonArray();
         virtual unsigned int size() const;
+
+        virtual JSonElement *firstChild();
+        virtual const JSonElement *firstChild() const;
 };
 

+ 2 - 0
include/jsonContainer.hh

@@ -8,6 +8,8 @@ class JSonContainer: public JSonElement
         JSonContainer(JSonContainer *parent);
         virtual ~JSonContainer();
         virtual unsigned int size() const =0;
+        virtual JSonElement *firstChild() =0;
+        virtual const JSonElement *firstChild() const =0;
 
         virtual std::string stringify() const;
 };

+ 3 - 0
include/jsonObject.hh

@@ -15,6 +15,9 @@ class JSonObject: public JSonContainer, public std::map<std::string, JSonElement
         virtual unsigned int size() const;
         bool contains(const std::string &) const;
 
+        virtual JSonElement *firstChild();
+        virtual const JSonElement *firstChild() const;
+
         const JSonElement* get(const std::string &) const;
 };
 

+ 83 - 25
src/curseOutput.cpp

@@ -75,16 +75,19 @@ void CurseOutput::redraw()
     std::pair<int, int> screenSize;
     std::pair<int, int> cursor;
 
-    select_up = select_down = nullptr;
+    select_up = select_down = select_parent = nullptr;
     selectFound = false;
     getScreenSize(screenSize, cursor);
     cursor.first += topleft.second->getLevel() * indentLevel;
-    redraw(cursor, screenSize, topleft.second);
+    clear();
+    redraw(cursor, screenSize, topleft.second, dynamic_cast<const JSonContainer *> (topleft.second));
     move(screenSize.second, screenSize.first);
     if (!select_down)
         select_down = selection;
     if (!select_up)
         select_up = selection;
+    if (!select_parent)
+        select_parent = selection;
     refresh();
 }
 
@@ -136,57 +139,76 @@ CurseOutput::t_nextKey CurseOutput::findNext(const JSonElement *item)
     return t_nextKey::empty(); // Primitive, can't have child (impossible)
 }
 
-bool CurseOutput::redraw(std::pair<int, int> &cursor, const std::pair<int, int> &maxSize, const JSonElement *item)
+bool CurseOutput::redraw(std::pair<int, int> &cursor, const std::pair<int, int> &maxSize, const JSonElement *item, const JSonContainer *parent)
 {
     do
     {
         if (dynamic_cast<const JSonObject*>(item) != nullptr)
         {
-            cursor.first += indentLevel /2;
             if (selection == item)
+            {
+                select_parent = parent;
                 selectFound = true;
+            }
             else if (!selectFound)
                 select_up = item;
             else if (!select_down)
                 select_down = item;
-            write(cursor.first, cursor.second, "{", selection == item);
-            if (++cursor.second > maxSize.second)
-                return false;
-            for (JSonObject::const_iterator i = ((JSonObject *)item)->cbegin(); i != ((JSonObject *)item)->cend(); ++i)
+            
+            cursor.first += indentLevel /2;
+            if (collapsed.find((const JSonContainer *)item) != collapsed.end())
+                write(cursor.first, cursor.second, "{ ... }", selection == item);
+            else
             {
-                const std::pair<std::string, JSonElement *> ipair = *i;
-                cursor.first += indentLevel /2;
-                writeKey(ipair.first, cursor, selection == ipair.second);
-                // TODO write primitive<> values inline
-                cursor.first -= indentLevel /2;
-                if (!redraw(cursor, maxSize, ipair.second))
+                write(cursor.first, cursor.second, "{", selection == item);
+                if (++cursor.second > maxSize.second)
                     return false;
-                cursor.first -= indentLevel;
+                for (JSonObject::const_iterator i = ((JSonObject *)item)->cbegin(); i != ((JSonObject *)item)->cend(); ++i)
+                {
+                    const std::pair<std::string, JSonElement *> ipair = *i;
+                    cursor.first += indentLevel /2;
+                    writeKey(ipair.first, cursor, selection == ipair.second);
+                    // TODO write primitive<> values / collapsed inline
+                    cursor.first -= indentLevel /2;
+                    if (!redraw(cursor, maxSize, ipair.second, (JSonContainer *) item))
+                        return false;
+                    cursor.first -= indentLevel;
+                }
+                write(cursor.first, cursor.second, "}", selection == item);
             }
-            write(cursor.first, cursor.second, "}", selection == item);
             cursor.first -= indentLevel /2;
-            cursor.second++;
             if (++cursor.second > maxSize.second)
                 return false;
         }
         else if (dynamic_cast<const JSonArray*>(item) != nullptr)
         {
-            cursor.first += indentLevel /2;
             if (selection == item)
+            {
+                select_parent = parent;
                 selectFound = true;
+            }
             else if (!selectFound)
                 select_up = item;
             else if (!select_down)
                 select_down = item;
-            write(cursor.first, cursor.second, "[", selection == item);
+
             cursor.first += indentLevel /2;
-            if (++cursor.second > maxSize.second)
-                return false;
-            for (JSonArray::const_iterator i = ((JSonArray *)item)->cbegin(); i != ((JSonArray *)item)->cend(); ++i)
-                if (!redraw(cursor, maxSize, *i))
+            if (collapsed.find((const JSonContainer *)item) != collapsed.end())
+                write(cursor.first, cursor.second, "[ ... ]", selection == item);
+            else
+            {
+                write(cursor.first, cursor.second, "[", selection == item);
+                cursor.first += indentLevel /2;
+                if (++cursor.second > maxSize.second)
                     return false;
-            cursor.first -= indentLevel /2;
-            write(cursor.first, cursor.second, "]", selection == item);
+                for (JSonArray::const_iterator i = ((JSonArray *)item)->cbegin(); i != ((JSonArray *)item)->cend(); ++i)
+                {
+                    if (!redraw(cursor, maxSize, *i, (JSonContainer *)item))
+                        return false;
+                }
+                cursor.first -= indentLevel /2;
+                write(cursor.first, cursor.second, "]", selection == item);
+            }
             cursor.first -= indentLevel /2;
             if (++cursor.second > maxSize.second)
                 return false;
@@ -194,7 +216,10 @@ bool CurseOutput::redraw(std::pair<int, int> &cursor, const std::pair<int, int>
         else
         {
             if (item == selection)
+            {
+                select_parent = parent;
                 selectFound = true;
+            }
             else if (!selectFound)
                 select_up = item;
             else if (!select_down)
@@ -269,6 +294,38 @@ bool CurseOutput::readInput()
             case 'J':
                 selection = select_down;
                 return true;
+
+            case 'l':
+            case 'L':
+            case KEY_RIGHT:
+            {
+                const JSonContainer *_selection = dynamic_cast<const JSonContainer *>(selection);
+                if (!_selection)
+                    break;
+
+                if (collapsed.erase((const JSonContainer *) selection))
+                    return true;
+                if (!_selection->size())
+                    break;
+                selection = _selection->firstChild();
+                return true;
+            }
+
+            case 'h':
+            case 'H':
+            case KEY_LEFT:
+            {
+                const JSonContainer *_selection = dynamic_cast<const JSonContainer *>(selection);
+                if (!_selection
+                        || collapsed.find((const JSonContainer *) selection) != collapsed.end()
+                        || (_selection && _selection->size() == 0))
+                    selection = select_parent;
+                else if (_selection)
+                    collapsed.insert((const JSonContainer *)selection);
+                else
+                    break;
+                return true;
+            }
         }
     }
     return false;
@@ -287,6 +344,7 @@ void CurseOutput::init()
     wtimeout(stdscr, 150);
     cbreak();
     clear();
+    noecho();
     curs_set(false);
     keypad(stdscr, true);
 

+ 14 - 0
src/jsonArray.cpp

@@ -16,3 +16,17 @@ unsigned int JSonArray::size() const
     return std::list<JSonElement *>::size();
 }
 
+JSonElement *JSonArray::firstChild()
+{
+    if (begin() == end())
+        return nullptr;
+    return *begin();
+}
+
+const JSonElement *JSonArray::firstChild() const
+{
+    if (cbegin() == cend())
+        return nullptr;
+    return *cbegin();
+}
+

+ 14 - 0
src/jsonObject.cpp

@@ -33,3 +33,17 @@ unsigned int JSonObject::size() const
     return std::map<std::string, JSonElement *>::size();
 }
 
+JSonElement *JSonObject::firstChild()
+{
+    if (begin() == end())
+        return nullptr;
+    return (*begin()).second;
+}
+
+const JSonElement *JSonObject::firstChild() const
+{
+    if (cbegin() == cend())
+        return nullptr;
+    return (*cbegin()).second;
+}
+