DUDS
Distributed Update of Data from Something
MenuOutput.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the DUDS project. It is subject to the BSD-style
3  * license terms in the LICENSE file found in the top-level directory of this
4  * distribution and at https://github.com/jjackowski/duds/blob/master/LICENSE.
5  * No part of DUDS, including this file, may be copied, modified, propagated,
6  * or distributed except according to the terms contained in the LICENSE file.
7  *
8  * Copyright (C) 2019 Jeff Jackowski
9  */
13 #include <duds/general/Errors.hpp>
14 
15 namespace duds { namespace ui { namespace menu {
16 
17 MenuOutput::MenuOutput(const std::shared_ptr<MenuView> &view, int vis) :
18 mview(view), range(vis) { }
19 
20 void MenuOutput::attach(const std::shared_ptr<MenuView> &view, int vis) {
21  // only make changes if being attached to something different
22  if (mview != view) {
23  mview = view;
24  if (vis > 0) {
25  range = vis;
26  }
27  items.clear();
28  updateIdx = -1;
29  }
30 }
31 
32 const std::shared_ptr<Menu> &MenuOutput::menu() const {
33  if (!mview) {
35  }
36  return mview->menu();
37 }
38 
39 void MenuOutput::lock(std::size_t newRange) {
40  // mark view as in use; prevents view updates
41  mview->incUser();
42  // get a shared lock on the menu to allow multiple threads to render the
43  // menu simultaneously
44  menu()->block.lock_shared();
45  // different range?
46  if ((newRange != -1) && (newRange != range)) {
47  // change the range
48  range = newRange;
49  // ensure the visble items are updated
50  updateIdx = -1;
51  }
52  // figure out which menu items should be shown to the user
53  updateVisible();
54 }
55 
57  mview->decUser();
58  mview->menu()->block.unlock_shared();
59 }
60 
61 void MenuOutput::maxVisible(std::size_t newRange) {
62  // something different?
63  if (newRange != range) {
64  // change the range
65  range = newRange;
66  // ensure the visble items are updated
67  updateIdx = -1;
68  updateVisible();
69  }
70 }
71 
72 bool MenuOutput::fore(Menu::ItemVec::const_iterator &iter) {
73  if (iter != menu()->cbegin()) {
74  --iter;
75  while ((iter != menu()->cbegin()) && (*iter)->isInvisible()) {
76  --iter;
77  }
78  if (!(*iter)->isInvisible()) {
79  return true;
80  }
81  }
82  return false;
83 }
84 
85 bool MenuOutput::revr(Menu::ItemVec::const_iterator &iter) {
86  if (iter != menu()->cend()) {
87  ++iter;
88  while ((iter != menu()->cend()) && (*iter)->isInvisible()) {
89  ++iter;
90  }
91  if ((iter != menu()->cend()) && !(*iter)->isInvisible()) {
92  return true;
93  }
94  }
95  return false;
96 }
97 
99  if (menu()->empty()) {
100  vchg = !items.empty();
101  items.clear();
102  return;
103  }
104  std::size_t sel = mview->selectedIndex();
105  int uidx = menu()->updateIndex();
106  if ((updateIdx != uidx) || (sel != selected)) {
107  // figure out what menu items will be displayed
108  items.clear();
109  Menu::ItemVec::const_iterator front = menu()->iterator(sel);
110  Menu::ItemVec::const_iterator back = front;
111  // capture the selected item
112  if ((*front)->isVisible()) {
113  // start the selected item at the begining of visible items
114  items.push_front(front->get());
115  // capture iterator to selected item
116  seliter = items.cbegin();
117  // reset the selected item visible index; the selected item is now
118  // at the start of visible items
119  selectedVis = 0;
120  // the selected item is the first and last on the menu for now
121  firstIdx = lastIdx = sel;
122  } else {
123  // must only happen with an empty menu
124  assert(menu()->empty());
125  // ensure valid iterator
126  seliter = items.cend();
127  firstIdx = lastIdx = -1;
128  }
129  // start with an item before if selection moved towards front
130  if ((sel < selected) && fore(front)) {
131  items.push_front(front->get());
132  firstIdx = front - menu()->cbegin();
133  // selected item moved towards end of visible items
134  ++selectedVis;
135  }
136  // continue to add items
137  bool done = false;
138  while (!done && (items.size() < range)) {
139  // item behind
140  if (revr(back)) {
141  items.push_back(back->get());
142  lastIdx = back - menu()->cbegin();
143  } else {
144  done = true;
145  //showLast = true;
146  }
147  // may be at the target size
148  if (items.size() == range) {
149  break;
150  }
151  // item in front
152  if (fore(front)) {
153  items.push_front(front->get());
154  firstIdx = front - menu()->cbegin();
155  // selected item moved towards end of visible items
156  ++selectedVis;
157  done = false;
158  }
159  }
160  // record update status
161  updateIdx = uidx;
162  selected = sel;
163  vchg = true;
164  // discover if first & last visible items of the menu are visible in
165  // this output view
166  showFirst = !fore(front);
167  showLast = !revr(back);
168  } else {
169  vchg = false;
170  }
171 }
172 
173 } } }
bool showFirst
True if the visible list includes the first visible item on the menu.
Definition: MenuOutput.hpp:104
const std::shared_ptr< MenuView > & view() const
Returns the MenuView used by this output view.
Definition: MenuOutput.hpp:215
MenuOutput()=default
Constructs a menu output without a view.
int updateIdx
The menu&#39;s update index value when this subview was last rendered.
Definition: MenuOutput.hpp:95
bool revr(Menu::ItemVec::const_iterator &iter)
A helper function for update() that moves iter towards the back of the menu until it finds a visible ...
Definition: MenuOutput.cpp:85
std::size_t selected
Index of the selected item from the container of all menu items.
Definition: MenuOutput.hpp:91
void updateVisible()
Updates which items should be visible.
Definition: MenuOutput.cpp:98
bool vchg
True when the view has changed since the last access, and false otherwise.
Definition: MenuOutput.hpp:100
Attempted use of a MenuOutput object that hasn&#39;t been attached to a MenuView.
Definition: MenuErrors.hpp:72
std::shared_ptr< MenuView > mview
The menu view handling the selected menu item.
Definition: MenuOutput.hpp:50
MenuVisibleList::const_iterator seliter
Iterator to the currently selected item.
Definition: MenuOutput.hpp:65
std::size_t lastIdx
Index of the last menu item that is visible.
Definition: MenuOutput.hpp:81
MenuVisibleList items
The currently visible menu items.
Definition: MenuOutput.hpp:58
void unlock()
Informs the MenuView that it has one fewer MenuOutput objects acting upon it, and releases the shared...
Definition: MenuOutput.cpp:56
std::size_t firstIdx
Index of the first menu item that is visible.
Definition: MenuOutput.hpp:77
void maxVisible(std::size_t newRange)
Changes the maximum number of visible menu items and causes the visible list to be regenerated...
Definition: MenuOutput.cpp:61
void lock(std::size_t newRange)
Handles several tasks to lock and prepare menu data.
Definition: MenuOutput.cpp:39
bool fore(Menu::ItemVec::const_iterator &iter)
A helper function for update() that moves iter towards the front of the menu until it finds a visible...
Definition: MenuOutput.cpp:72
std::size_t selectedVis
Index of the selected item within the list of currently visible menu items.
Definition: MenuOutput.hpp:73
void attach(const std::shared_ptr< MenuView > &view, int vis=0)
Attaches this object to the given MenuView.
Definition: MenuOutput.cpp:20
bool showLast
True if the visible list includes the last visible item on the menu.
Definition: MenuOutput.hpp:108
std::size_t range
The maximum number of visible items.
Definition: MenuOutput.hpp:85
General errors.
#define DUDS_THROW_EXCEPTION(x)
Works like BOOST_THROW_EXCEPTION, but includes a stack trace if DUDS_ERRORS_VERBOSE is defined...
Definition: Errors.hpp:48
const std::shared_ptr< Menu > & menu() const
Returns the Menu used by this output view.
Definition: MenuOutput.cpp:32