HoverRace  2.0
BaseContainer.h
Go to the documentation of this file.
1 
2 // BaseContainer.h
3 //
4 // Copyright (c) 2013-2015 Michael Imamura.
5 //
6 // Licensed under GrokkSoft HoverRace SourceCode License v1.0(the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // A copy of the license should have been attached to the package from which
10 // you have taken this file. If you can not find the license you can not use
11 // this file.
12 //
13 //
14 // The author makes no representations about the suitability of
15 // this software for any purpose. It is provided "as is" "AS IS",
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
17 // implied.
18 //
19 // See the License for the specific language governing permissions
20 // and limitations under the License.
21 
22 #pragma once
23 
24 #include "UiViewModel.h"
25 
26 #if defined(_WIN32) && defined(HR_ENGINE_SHARED)
27 # ifdef MR_ENGINE
28 # define MR_DllDeclare __declspec( dllexport )
29 # else
30 # define MR_DllDeclare __declspec( dllimport )
31 # endif
32 #else
33 # define MR_DllDeclare
34 #endif
35 
36 namespace HoverRace {
37  namespace Display {
38  class Display;
39  }
40 }
41 
42 namespace HoverRace {
43 namespace Display {
44 
64 {
65  using SUPER = UiViewModel;
66 
67 public:
68  struct Props
69  {
70  enum
71  {
72  SIZE = SUPER::Props::NEXT_,
78  };
79  };
80 
81 public:
82  BaseContainer(Display &display, uiLayoutFlags_t layoutFlags = 0);
83  BaseContainer(Display &display, const Vec2 &size, bool clip = true,
84  uiLayoutFlags_t layoutFlags = 0);
85  virtual ~BaseContainer() { }
86 
87 public:
88  void AttachView(Display &disp) override { AttachViewDynamic(disp, this); }
89 
90 protected:
91  class Child
92  {
93  public:
94  Child(BaseContainer &bc, std::shared_ptr<UiViewModel> child) :
95  child(std::move(child)), visible(true)
96  {
97  // Route focus request events back to the container.
98  focusRequestedConn.reset(
99  new boost::signals2::scoped_connection(
100  this->child->GetFocusRequestedSignal().connect(
101  std::bind(&BaseContainer::OnChildRequestedFocus, &bc,
102  std::placeholders::_1))));
103  focusRelinquishedConn.reset(
104  new boost::signals2::scoped_connection(
105  this->child->GetFocusRelinquishedSignal().connect(
107  std::placeholders::_1, std::placeholders::_2))));
108  }
109  Child(const Child&) = delete;
110  Child(Child&&) = default;
111 
112  Child &operator=(const Child&) = delete;
113  Child &operator=(Child&&) = default;
114 
115  public:
116  std::shared_ptr<UiViewModel> child;
117  bool visible;
118  private:
119  // scoped_connection is not movable, so we wrap in a unique_ptr.
120  std::unique_ptr<boost::signals2::scoped_connection> focusRequestedConn;
121  std::unique_ptr<boost::signals2::scoped_connection> focusRelinquishedConn;
122  };
123 
124  using children_t = std::vector<std::unique_ptr<Child>>;
125 
126  // These are marked as protected so that subclasses can restrict how and
127  // what types of widgets can be added / removed from the container.
128 
136  template<class T, class... Args>
137  typename std::enable_if<std::is_base_of<UiViewModel, T>::value,
138  std::shared_ptr<T>>::type
139  NewChild(Args&&... args)
140  {
141  auto sharedChild = std::make_shared<T>(std::forward<Args>(args)...);
142  children.emplace_back(new Child(*this, sharedChild));
143  sharedChild->AttachView(display);
144  return sharedChild;
145  }
146 
153  template<typename T>
154  typename std::enable_if<std::is_base_of<UiViewModel, T>::value, std::shared_ptr<T>>::type
155  RemoveChild(const std::shared_ptr<T> &child)
156  {
157  for (auto iter = children.begin(); iter != children.end(); ++iter) {
158  if ((*iter)->child == child) {
159  children.erase(iter);
160  break;
161  }
162  }
163  return child;
164  }
165 
173  template<class T>
174  typename std::enable_if<std::is_base_of<UiViewModel, T>::value,
175  std::shared_ptr<T>
176  >::type
177  ReorderChild(const std::shared_ptr<T> &child, size_t idx)
178  {
179  auto sz = children.size();
180  if (sz == 0) return child;
181 
182  if (idx >= sz) {
183  idx = sz - 1;
184  }
185 
186  for (auto iter = children.begin(); iter != children.end(); ++iter) {
187  if ((*iter)->child == child) {
188  auto dest = children.begin();
189  std::advance(dest, idx);
190  if (dest < iter) {
191  std::rotate(dest, iter, iter + 1);
192  }
193  else if (dest > iter) {
194  std::rotate(iter, iter + 1, dest + 1);
195  }
196  break;
197  }
198  }
199 
200  return child;
201  }
202 
206  virtual void Clear()
207  {
208  children.clear();
209  }
210 
224  virtual void Reserve(size_t capacity)
225  {
226  children.reserve(capacity);
227  }
228 
229 private:
230  template<typename P, bool(UiViewModel::*F)(P)>
231  bool PropagateMouseEvent(P param)
232  {
233  if (!visible || children.empty()) return false;
234 
235  // We iterate over the child widgets in reverse since the widgets
236  // are rendered back to front, so we let the ones in front get
237  // first chance to handle the events.
238 
239  Vec2 oldOrigin(0, 0);
240  for (auto iter = children.rbegin();
241  iter != children.rend(); ++iter)
242  {
243  auto &child = (*iter)->child;
244  if (!(*iter)->visible) continue;
245  oldOrigin = display.AddUiOrigin(child->GetPos());
246  bool retv = (child.get()->*F)(param);
247  display.SetUiOrigin(oldOrigin);
248  if (retv) return true;
249  }
250 
251  return false;
252  }
253 
254 public:
255  bool OnMouseMoved(const Vec2 &pos) override;
256  bool OnMousePressed(const Control::Mouse::Click &click) override;
257  bool OnMouseReleased(const Control::Mouse::Click &click) override;
258  bool OnMouseScrolled(const Control::Mouse::Scroll &scroll) override;
259 
260 protected:
265  virtual void OnChildRequestedFocus(UiViewModel &child) { HR_UNUSED(child); }
266 
273  const Control::Nav &nav) { HR_UNUSED(child); HR_UNUSED(nav); }
274 
275 public:
276  void ShrinkWrap();
277 
283  const Vec2 &GetSize() const { return size; }
284  void SetSize(const Vec2 &size);
286  void SetSize(double w, double h) { SetSize(Vec2(w, h)); }
287 
293  bool IsClip() const { return clip; }
294  void SetClip(bool clip);
295 
300  double GetOpacity() const { return opacity; }
301  void SetOpacity(double opacity);
302 
307  bool IsVisible() const { return visible; }
308  void SetVisible(bool visible);
309 
314  const Vec2 &GetChildOffset() const { return childOffset; }
315 protected:
316  void SetChildOffset(const Vec2 &offset);
317 
318 public:
323  bool IsEmpty() const { return children.empty(); }
324 
329  template<class Fn>
330  void ForEachChild(Fn fn) const
331  {
332  for (auto &child : children) {
333  fn(child->child);
334  }
335  }
336 
341  template<class Fn>
342  void ForEachVisibleChild(Fn fn) const
343  {
344  for (auto &child : children) {
345  if (child->visible) {
346  fn(child->child);
347  }
348  }
349  }
350 
351 protected:
352  children_t &GetChildren() { return children; }
353 
354 public:
355  Vec3 Measure() override { return size.Promote(); }
356 
357 protected:
358  bool TestHit(const Vec2 &pos);
359 
360 protected:
362 private:
364  bool clip;
365  double opacity;
366  bool visible;
369 };
370 
371 } // namespace Display
372 } // namespace HoverRace
373 
374 #undef MR_DllDeclare
First index for subclasses.
Definition: BaseContainer.h:77
bool IsEmpty() const
Check if this container is devoid of child widgets.
Definition: BaseContainer.h:323
std::enable_if< std::is_base_of< UiViewModel, T >::value, std::shared_ptr< T > >::type RemoveChild(const std::shared_ptr< T > &child)
Remove a child element.
Definition: BaseContainer.h:155
constexpr Vec3 Promote(double z=0) const noexcept
Definition: Vec.h:206
virtual void OnChildRequestedFocus(UiViewModel &child)
Called when a child widget requests input focus.
Definition: BaseContainer.h:265
Definition: BaseContainer.h:91
std::enable_if< MPL::HasSetSize< T >::value, void >::type SetSize(T &widget, double w, double h)
Definition: MPL.h:60
Base class for UI (2D) components.
Definition: UiViewModel.h:56
virtual void Reserve(size_t capacity)
Increase the capacity of the of this container.
Definition: BaseContainer.h:224
std::shared_ptr< UiViewModel > child
Definition: BaseContainer.h:116
STL namespace.
Mouse click events.
Definition: Action.h:67
children_t children
Definition: BaseContainer.h:368
Display & display
Definition: BaseContainer.h:361
Base class for widgets that contain other widgets.
Definition: BaseContainer.h:63
Definition: Vec.h:38
Vec2 size
Definition: BaseContainer.h:363
void AttachView(Display &disp) override
Definition: BaseContainer.h:88
Vec3 Measure() override
Calculate the size of the component.
Definition: BaseContainer.h:355
void ForEachVisibleChild(Fn fn) const
Iterate over each visible child widget.
Definition: BaseContainer.h:342
std::unique_ptr< boost::signals2::scoped_connection > focusRelinquishedConn
Definition: BaseContainer.h:121
MR_UInt32 uiLayoutFlags_t
Definition: UiLayoutFlags.h:53
#define MR_DllDeclare
Definition: BaseContainer.h:33
double GetOpacity() const
Retrieve the opacity.
Definition: BaseContainer.h:300
virtual ~BaseContainer()
Definition: BaseContainer.h:85
Base class for display managers.
Definition: Display.h:73
bool visible
Used for filtering in subclasses.
Definition: BaseContainer.h:117
const Vec2 & GetSize() const
Retrieve the size of the container.
Definition: BaseContainer.h:283
void ForEachChild(Fn fn) const
Iterate over each child widget.
Definition: BaseContainer.h:330
const Vec2 & GetChildOffset() const
Retrieve the offset to the position of the child widgets.
Definition: BaseContainer.h:314
std::unique_ptr< boost::signals2::scoped_connection > focusRequestedConn
Definition: BaseContainer.h:120
Mouse scroll events.
Definition: Action.h:77
virtual void OnChildRelinquishedFocus(UiViewModel &child, const Control::Nav &nav)
Called when a child widget passes input focus to another widget.
Definition: BaseContainer.h:272
children_t & GetChildren()
Definition: BaseContainer.h:352
bool IsClip() const
Check if child elements are clipped to the container bounds.
Definition: BaseContainer.h:293
virtual void Clear()
Remove all child elements.
Definition: BaseContainer.h:206
void SetSize(double w, double h)
Convenience function for SetSize(const Vec2&).
Definition: BaseContainer.h:286
bool IsVisible() const
Check if the children of this container are shown.
Definition: BaseContainer.h:307
A navigation direction.
Definition: Nav.h:45
int idx
Definition: SdlDisplay.cpp:254
std::vector< std::unique_ptr< Child >> children_t
Definition: BaseContainer.h:124
Vec2 childOffset
Definition: BaseContainer.h:367
bool visible
Definition: BaseContainer.h:366
static const Vec2 SIZE
Definition: ProfileEditScene.cpp:90
Definition: Announcement.h:24
double opacity
Definition: BaseContainer.h:365
Definition: Vec.h:114
std::enable_if< std::is_base_of< UiViewModel, T >::value, std::shared_ptr< T > >::type NewChild(Args &&...args)
Create and append a new child widget to the end of the list.
Definition: BaseContainer.h:139
bool clip
Definition: BaseContainer.h:364
Child(BaseContainer &bc, std::shared_ptr< UiViewModel > child)
Definition: BaseContainer.h:94
std::enable_if< std::is_base_of< UiViewModel, T >::value, std::shared_ptr< T > >::type ReorderChild(const std::shared_ptr< T > &child, size_t idx)
Move a widget to a different position in the list.
Definition: BaseContainer.h:177
Definition: BaseContainer.h:68
bool PropagateMouseEvent(P param)
Definition: BaseContainer.h:231