1 /*
2    Copyright (C) 2002 Kai Sterker <kai.sterker@gmail.com>
3    Part of the Adonthell Project  <http://adonthell.nongnu.org>
4 
5    Dlgedit is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    Dlgedit is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with Dlgedit.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /**
20  * @file kb_traverse.h
21  *
22  * @author Kai Sterker
23  * @brief Graph traversal via keyboard
24  */
25 
26 #ifndef KB_TRAVERSE_H
27 #define KB_TRAVERSE_H
28 
29 #include "dlg_node.h"
30 
31 /**
32  * This class implements the graph traversal strategy for keyboard users.
33  * As a single node may have both multiple children and multiple parents,
34  * this is not that easy. The current strategy is the following:
35  *
36  * - when a node is selected, LEFT and RIGHT iterate over a list of
37  *   siblings of that node.
38  * - pressing UP will move to the first parent of the selected node. The
39  *   list of siblings will contain all the remainig parents.
40  * - pressing DOWN will move to the first child of the selected node. The
41  *   list of siblings will contain all the remaining children.
42  * - pressing a key with no node selected will select the first node
43  *   without parent. The list of siblings will contain all other nodes
44  *   without parents.
45  *
46  * If you got a better solution, please tell me :).
47  */
48 class KBTraverse
49 {
50 public:
51     /**
52      * Default constructor.
53      */
54     KBTraverse ();
55     /**
56      * Default destructor.
57      */
58     ~KBTraverse ();
59 
60     /**
61      * @name Movement
62      */
63     //@{
64     /**
65      * Select previous node in list and return new selection.
66      * @return pointer to current selection or \b NULL if nothing selected.
67      */
68     DlgNode* left ();
69     /**
70      * Select next node in list and return new selection.
71      * @return pointer to current selection or \b NULL if nothing selected.
72      */
73     DlgNode* right ();
74     /**
75      * Select first parent of current selection. Update list with
76      * this node's siblings.
77      * @return pointer to current selection or \b NULL if nothing selected.
78      */
79     DlgNode* up ();
80     /**
81      * Select first child of current selection. Update list with
82      * its siblings.
83      * @return pointer to current selection or \b NULL if nothing selected.
84      */
85     DlgNode* down ();
86     //@}
87 
88     /**
89      * @name Selection
90      */
91     //@{
92     /**
93      * Get all parents of selected node. Adds them to the list
94      * of siblings and selects the first of them.
95      * @return <b>true</b> if a parent can be selected, <b>false</b> otherwise.
96      */
97     bool selectParents ();
98     /**
99      * Get all children of selected node. Adds them to the list
100      * of siblings and selects the first of them.
101      * @return <b>true</b> if a child can be selected, <b>false</b> otherwise.
102      */
103     bool selectChildren ();
104     /**
105      * Select the given node. Update list with this nodes siblings. Use this
106      * method to keep the keyboard selection up-to-date when selecting  nodes
107      * in a different way.
108      * @param node to be selected
109      * @return <b>true</b> if node has been selected, <b>false</b> otherwise.
110      */
111     bool select (DlgNode *node);
112     /**
113      * Select the first of the module's root nodes.
114      * @param nodes vector with the module's nodes.
115      * @return pointer to current selection or \b NULL if nothing selected.
116      */
117     DlgNode *selectRoot (std::vector<DlgNode*> *nodes);
118     /**
119      * Empty list of nodes and clear selection.
120      */
121     void clear ();
122     //@}
123 
124 private:
125     /**
126      * Add a node to the list of siblings. The nodes are sorted by their
127      * position. The ones with the smallest y value come first; if nodes have
128      * the same y value, then those with the smallest x value come first.
129      * @param node the DlgNode to add.
130      */
131     void addSibling (DlgNode *node);
132 
133     std::list<DlgNode*> Siblings;           // Nodes reachable with left/right
134     std::list<DlgNode*>::iterator Current;  // Selected node
135 };
136 
137 #endif // KB_TRAVERSE_H
138