2013-05-03 00:21:39 +02:00
|
|
|
#pragma once
|
|
|
|
|
2014-01-22 16:29:59 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2013-06-01 18:59:03 +02:00
|
|
|
#include "base/logging.h"
|
2014-01-22 16:29:59 +01:00
|
|
|
#include "base/mutex.h"
|
2013-06-08 22:41:17 +02:00
|
|
|
#include "math/geom2d.h"
|
2013-05-03 00:21:39 +02:00
|
|
|
#include "input/gesture_detector.h"
|
2014-01-22 16:29:59 +01:00
|
|
|
#include "ui/view.h"
|
2013-05-03 00:21:39 +02:00
|
|
|
|
|
|
|
namespace UI {
|
|
|
|
|
2013-05-27 00:54:02 +02:00
|
|
|
struct NeighborResult {
|
|
|
|
NeighborResult() : view(0), score(0) {}
|
|
|
|
NeighborResult(View *v, float s) : view(v), score(s) {}
|
|
|
|
|
|
|
|
View *view;
|
|
|
|
float score;
|
|
|
|
};
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
class ViewGroup : public View {
|
|
|
|
public:
|
2014-03-03 11:39:06 +01:00
|
|
|
ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams), defaultFocusView_(0), hasDropShadow_(false), clip_(false) {}
|
2013-05-03 00:21:39 +02:00
|
|
|
virtual ~ViewGroup();
|
|
|
|
|
|
|
|
// Pass through external events to children.
|
2015-02-03 00:10:38 +01:00
|
|
|
virtual bool Key(const KeyInput &input) override;
|
|
|
|
virtual void Touch(const TouchInput &input) override;
|
|
|
|
virtual void Axis(const AxisInput &input) override;
|
2013-05-03 00:21:39 +02:00
|
|
|
|
|
|
|
// By default, a container will layout to its own bounds.
|
2015-09-17 20:29:37 +02:00
|
|
|
virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override = 0;
|
|
|
|
virtual void Layout() override = 0;
|
|
|
|
virtual void Update(const InputState &input_state) override;
|
2015-10-31 13:43:33 +01:00
|
|
|
virtual void Query(float x, float y, std::vector<View *> &list) override;
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-02-03 00:10:38 +01:00
|
|
|
virtual void Draw(UIContext &dc) override;
|
2013-05-03 00:21:39 +02:00
|
|
|
|
|
|
|
// These should be unused.
|
|
|
|
virtual float GetContentWidth() const { return 0.0f; }
|
|
|
|
virtual float GetContentHeight() const { return 0.0f; }
|
|
|
|
|
|
|
|
// Takes ownership! DO NOT add a view to multiple parents!
|
2013-06-01 18:59:03 +02:00
|
|
|
template <class T>
|
2014-08-17 12:17:59 +02:00
|
|
|
T *Add(T *view) {
|
|
|
|
lock_guard guard(modifyLock_);
|
|
|
|
views_.push_back(view);
|
|
|
|
return view;
|
|
|
|
}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-02-03 00:10:38 +01:00
|
|
|
virtual bool SetFocus() override;
|
2015-09-17 20:29:37 +02:00
|
|
|
virtual bool SubviewFocused(View *view) override;
|
2013-08-16 12:51:57 +02:00
|
|
|
virtual void RemoveSubview(View *view);
|
2013-05-25 12:40:57 +02:00
|
|
|
|
2014-03-03 11:39:06 +01:00
|
|
|
void SetDefaultFocusView(View *view) { defaultFocusView_ = view; }
|
|
|
|
View *GetDefaultFocusView() { return defaultFocusView_; }
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
// Assumes that layout has taken place.
|
2013-05-27 00:54:02 +02:00
|
|
|
NeighborResult FindNeighbor(View *view, FocusDirection direction, NeighborResult best);
|
2013-12-06 16:44:39 +01:00
|
|
|
|
2015-09-17 20:29:37 +02:00
|
|
|
virtual bool CanBeFocused() const override { return false; }
|
|
|
|
virtual bool IsViewGroup() const override { return true; }
|
2013-05-25 12:40:57 +02:00
|
|
|
|
2013-07-16 00:25:08 +02:00
|
|
|
virtual void SetBG(const Drawable &bg) { bg_ = bg; }
|
|
|
|
|
|
|
|
virtual void Clear();
|
2016-01-22 22:40:16 -08:00
|
|
|
void PersistData(PersistStatus status, PersistMap &storage) override;
|
2013-07-16 00:25:08 +02:00
|
|
|
View *GetViewByIndex(int index) { return views_[index]; }
|
2014-11-16 16:44:07 +01:00
|
|
|
int GetNumSubviews() const { return (int)views_.size(); }
|
2013-07-16 00:25:08 +02:00
|
|
|
void SetHasDropShadow(bool has) { hasDropShadow_ = has; }
|
|
|
|
|
2013-08-18 22:29:50 +02:00
|
|
|
void Lock() { modifyLock_.lock(); }
|
|
|
|
void Unlock() { modifyLock_.unlock(); }
|
2013-08-20 12:27:42 +02:00
|
|
|
|
|
|
|
void SetClip(bool clip) { clip_ = clip; }
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return "ViewGroup: " + View::Describe(); }
|
2013-08-20 12:27:42 +02:00
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
protected:
|
2013-08-16 14:02:28 +02:00
|
|
|
recursive_mutex modifyLock_; // Hold this when changing the subviews.
|
2013-05-03 00:21:39 +02:00
|
|
|
std::vector<View *> views_;
|
2014-03-03 11:39:06 +01:00
|
|
|
View *defaultFocusView_;
|
2013-07-16 00:25:08 +02:00
|
|
|
Drawable bg_;
|
|
|
|
bool hasDropShadow_;
|
2013-08-20 12:27:42 +02:00
|
|
|
bool clip_;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// A frame layout contains a single child view (normally).
|
2013-06-09 11:18:57 +02:00
|
|
|
// It simply centers the child view.
|
2013-05-03 00:21:39 +02:00
|
|
|
class FrameLayout : public ViewGroup {
|
|
|
|
public:
|
2015-09-17 20:29:37 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
|
|
|
void Layout() override;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
2013-05-27 22:22:35 +02:00
|
|
|
enum {
|
|
|
|
NONE = -1,
|
|
|
|
};
|
|
|
|
|
|
|
|
class AnchorLayoutParams : public LayoutParams {
|
2013-05-03 00:21:39 +02:00
|
|
|
public:
|
2013-07-20 12:04:24 +02:00
|
|
|
AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b, bool c = false)
|
|
|
|
: LayoutParams(w, h, LP_ANCHOR), left(l), top(t), right(r), bottom(b), center(c) {
|
2013-06-09 11:18:57 +02:00
|
|
|
|
|
|
|
}
|
2013-08-10 23:03:12 +02:00
|
|
|
AnchorLayoutParams(Size w, Size h, bool c = false)
|
|
|
|
: LayoutParams(w, h, LP_ANCHOR), left(0), top(0), right(NONE), bottom(NONE), center(c) {
|
|
|
|
}
|
2013-07-20 12:04:24 +02:00
|
|
|
AnchorLayoutParams(float l, float t, float r, float b, bool c = false)
|
|
|
|
: LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_ANCHOR), left(l), top(t), right(r), bottom(b), center(c) {}
|
2013-05-27 22:22:35 +02:00
|
|
|
|
|
|
|
// These are not bounds, but distances from the container edges.
|
|
|
|
// Set to NONE to not attach this edge to the container.
|
|
|
|
float left, top, right, bottom;
|
2013-07-20 12:04:24 +02:00
|
|
|
bool center; // If set, only two "sides" can be set, and they refer to the center, not the edge, of the view being layouted.
|
2015-12-22 20:07:37 -08:00
|
|
|
|
|
|
|
static LayoutParamsType StaticType() {
|
|
|
|
return LP_ANCHOR;
|
|
|
|
}
|
2013-05-27 22:22:35 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class AnchorLayout : public ViewGroup {
|
|
|
|
public:
|
2015-12-22 19:52:23 -08:00
|
|
|
AnchorLayout(LayoutParams *layoutParams = 0) : ViewGroup(layoutParams), overflow_(true) {}
|
2015-10-31 13:43:33 +01:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
|
|
|
void Layout() override;
|
2015-12-22 19:52:23 -08:00
|
|
|
void Overflow(bool allow) {
|
|
|
|
overflow_ = allow;
|
|
|
|
}
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return "AnchorLayout: " + View::Describe(); }
|
2015-12-22 19:52:23 -08:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool overflow_;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
2013-05-27 22:22:35 +02:00
|
|
|
class LinearLayoutParams : public LayoutParams {
|
|
|
|
public:
|
|
|
|
LinearLayoutParams()
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {}
|
2013-06-01 18:59:03 +02:00
|
|
|
explicit LinearLayoutParams(float wgt, Gravity grav = G_TOPLEFT)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(LP_LINEAR), weight(wgt), gravity(grav), hasMargins_(false) {}
|
2013-06-01 18:59:03 +02:00
|
|
|
LinearLayoutParams(float wgt, const Margins &mgn)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(LP_LINEAR), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {}
|
2013-05-27 22:22:35 +02:00
|
|
|
LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(grav), hasMargins_(false) {}
|
2013-05-27 22:22:35 +02:00
|
|
|
LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {}
|
2013-06-08 22:41:17 +02:00
|
|
|
LinearLayoutParams(Size w, Size h, const Margins &mgn)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(w, h, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {}
|
2013-10-08 11:06:38 +02:00
|
|
|
LinearLayoutParams(Size w, Size h, float wgt, const Margins &mgn)
|
|
|
|
: LayoutParams(w, h, LP_LINEAR), weight(wgt), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {}
|
2013-05-27 22:22:35 +02:00
|
|
|
LinearLayoutParams(const Margins &mgn)
|
2013-06-09 13:01:36 +02:00
|
|
|
: LayoutParams(WRAP_CONTENT, WRAP_CONTENT, LP_LINEAR), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {}
|
2013-05-27 22:22:35 +02:00
|
|
|
|
|
|
|
float weight;
|
|
|
|
Gravity gravity;
|
|
|
|
Margins margins;
|
|
|
|
|
|
|
|
bool HasMargins() const { return hasMargins_; }
|
|
|
|
|
2015-12-22 20:07:37 -08:00
|
|
|
static LayoutParamsType StaticType() {
|
|
|
|
return LP_LINEAR;
|
|
|
|
}
|
|
|
|
|
2013-05-27 22:22:35 +02:00
|
|
|
private:
|
|
|
|
bool hasMargins_;
|
|
|
|
};
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
class LinearLayout : public ViewGroup {
|
|
|
|
public:
|
|
|
|
LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0)
|
2013-06-04 22:05:17 +02:00
|
|
|
: ViewGroup(layoutParams), orientation_(orientation), defaultMargins_(0), spacing_(10) {}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-10-31 13:43:33 +01:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
|
|
|
void Layout() override;
|
2013-07-17 01:03:29 +02:00
|
|
|
void SetSpacing(float spacing) {
|
|
|
|
spacing_ = spacing;
|
|
|
|
}
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return (orientation_ == ORIENT_HORIZONTAL ? "LinearLayoutHoriz: " : "LinearLayoutVert: ") + View::Describe(); }
|
|
|
|
|
2013-08-20 12:27:42 +02:00
|
|
|
protected:
|
2013-05-03 00:21:39 +02:00
|
|
|
Orientation orientation_;
|
2013-08-20 12:27:42 +02:00
|
|
|
private:
|
2013-05-03 00:21:39 +02:00
|
|
|
Margins defaultMargins_;
|
|
|
|
float spacing_;
|
|
|
|
};
|
|
|
|
|
2013-05-27 00:54:02 +02:00
|
|
|
// GridLayout is a little different from the Android layout. This one has fixed size
|
|
|
|
// rows and columns. Items are not allowed to deviate from the set sizes.
|
|
|
|
// Initially, only horizontal layout is supported.
|
|
|
|
struct GridLayoutSettings {
|
|
|
|
GridLayoutSettings() : orientation(ORIENT_HORIZONTAL), columnWidth(100), rowHeight(50), spacing(5), fillCells(false) {}
|
2013-12-06 16:44:39 +01:00
|
|
|
GridLayoutSettings(int colW, int colH, int spac = 5)
|
|
|
|
: orientation(ORIENT_HORIZONTAL), columnWidth(colW), rowHeight(colH), spacing(spac), fillCells(false) {}
|
2013-05-27 00:54:02 +02:00
|
|
|
|
|
|
|
Orientation orientation;
|
|
|
|
int columnWidth;
|
|
|
|
int rowHeight;
|
|
|
|
int spacing;
|
|
|
|
bool fillCells;
|
|
|
|
};
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
class GridLayout : public ViewGroup {
|
|
|
|
public:
|
2013-05-27 00:54:02 +02:00
|
|
|
GridLayout(GridLayoutSettings settings, LayoutParams *layoutParams = 0)
|
2013-07-18 16:56:47 +02:00
|
|
|
: ViewGroup(layoutParams), settings_(settings), numColumns_(1) {
|
2013-05-27 00:54:02 +02:00
|
|
|
if (settings.orientation != ORIENT_HORIZONTAL)
|
|
|
|
ELOG("GridLayout: Vertical layouts not yet supported");
|
|
|
|
}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-10-31 13:43:33 +01:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
|
|
|
void Layout() override;
|
|
|
|
std::string Describe() const override { return "GridLayout: " + View::Describe(); }
|
2013-05-03 00:21:39 +02:00
|
|
|
|
|
|
|
private:
|
2013-05-27 00:54:02 +02:00
|
|
|
GridLayoutSettings settings_;
|
2013-07-18 16:56:47 +02:00
|
|
|
int numColumns_;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// A scrollview usually contains just a single child - a linear layout or similar.
|
|
|
|
class ScrollView : public ViewGroup {
|
|
|
|
public:
|
2013-05-25 15:12:46 +02:00
|
|
|
ScrollView(Orientation orientation, LayoutParams *layoutParams = 0) :
|
2013-10-16 11:29:58 +02:00
|
|
|
ViewGroup(layoutParams),
|
2013-06-04 22:05:17 +02:00
|
|
|
orientation_(orientation),
|
|
|
|
scrollPos_(0),
|
|
|
|
scrollStart_(0),
|
|
|
|
scrollTarget_(0),
|
2013-08-18 22:29:50 +02:00
|
|
|
scrollToTarget_(false),
|
2013-08-20 11:35:54 +02:00
|
|
|
inertia_(0),
|
2013-08-19 22:05:22 +02:00
|
|
|
lastViewSize_(0.0f),
|
|
|
|
scrollToTopOnSizeChange_(true) {}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-10-31 13:43:33 +01:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
|
|
|
void Layout() override;
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2015-10-31 13:43:33 +01:00
|
|
|
bool Key(const KeyInput &input) override;
|
|
|
|
void Touch(const TouchInput &input) override;
|
|
|
|
void Draw(UIContext &dc) override;
|
|
|
|
std::string Describe() const override { return "ScrollView: " + View::Describe(); }
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2013-05-27 21:39:56 +02:00
|
|
|
void ScrollTo(float newScrollPos);
|
2015-01-05 01:19:49 +01:00
|
|
|
void ScrollToBottom();
|
2013-07-08 12:34:39 +02:00
|
|
|
void ScrollRelative(float distance);
|
2013-08-10 23:03:12 +02:00
|
|
|
bool CanScroll() const;
|
2015-10-31 13:43:33 +01:00
|
|
|
void Update(const InputState &input_state) override;
|
2013-05-27 21:39:56 +02:00
|
|
|
|
2013-05-27 00:54:02 +02:00
|
|
|
// Override so that we can scroll to the active one after moving the focus.
|
2016-01-22 23:02:44 -08:00
|
|
|
bool SubviewFocused(View *view) override;
|
|
|
|
|
|
|
|
void PersistData(PersistStatus status, PersistMap &storage) override;
|
2013-05-27 00:54:02 +02:00
|
|
|
|
2013-08-19 22:05:22 +02:00
|
|
|
// Quick hack to prevent scrolling to top in some lists
|
|
|
|
void SetScrollToTop(bool t) { scrollToTopOnSizeChange_ = t; }
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
private:
|
2013-07-10 21:58:35 +02:00
|
|
|
void ClampScrollPos(float &pos);
|
2013-07-08 12:34:39 +02:00
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
GestureDetector gesture_;
|
|
|
|
Orientation orientation_;
|
|
|
|
float scrollPos_;
|
|
|
|
float scrollStart_;
|
2013-05-28 00:50:19 +02:00
|
|
|
float scrollTarget_;
|
|
|
|
bool scrollToTarget_;
|
2013-08-20 11:35:54 +02:00
|
|
|
float inertia_;
|
2013-08-18 22:29:50 +02:00
|
|
|
float lastViewSize_;
|
2013-08-19 22:05:22 +02:00
|
|
|
bool scrollToTopOnSizeChange_;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class ViewPager : public ScrollView {
|
|
|
|
public:
|
|
|
|
};
|
|
|
|
|
2013-07-15 19:56:36 +02:00
|
|
|
|
|
|
|
class ChoiceStrip : public LinearLayout {
|
|
|
|
public:
|
2013-12-06 16:44:39 +01:00
|
|
|
ChoiceStrip(Orientation orientation, LayoutParams *layoutParams = 0);
|
2013-07-15 19:56:36 +02:00
|
|
|
|
|
|
|
void AddChoice(const std::string &title);
|
2013-08-20 00:34:54 +02:00
|
|
|
void AddChoice(ImageID buttonImage);
|
2013-10-07 21:45:25 +05:30
|
|
|
|
2013-07-15 19:56:36 +02:00
|
|
|
int GetSelection() const { return selected_; }
|
|
|
|
void SetSelection(int sel);
|
2013-10-07 21:45:25 +05:30
|
|
|
|
2013-10-08 18:04:56 +05:30
|
|
|
void HighlightChoice(unsigned int choice);
|
2013-10-07 21:45:25 +05:30
|
|
|
|
2015-02-03 00:10:38 +01:00
|
|
|
bool Key(const KeyInput &input) override;
|
2013-10-07 21:45:25 +05:30
|
|
|
|
2013-08-17 12:06:08 +02:00
|
|
|
void SetTopTabs(bool tabs) { topTabs_ = tabs; }
|
2015-02-03 00:10:38 +01:00
|
|
|
void Draw(UIContext &dc) override;
|
2013-10-07 21:45:25 +05:30
|
|
|
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return "ChoiceStrip: " + View::Describe(); }
|
|
|
|
|
2013-07-15 19:56:36 +02:00
|
|
|
Event OnChoice;
|
|
|
|
|
|
|
|
private:
|
|
|
|
EventReturn OnChoiceClick(EventParams &e);
|
|
|
|
|
|
|
|
int selected_;
|
2013-08-17 12:06:08 +02:00
|
|
|
bool topTabs_; // Can be controlled with L/R.
|
2013-07-15 19:56:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-06-08 22:41:17 +02:00
|
|
|
class TabHolder : public LinearLayout {
|
|
|
|
public:
|
2015-02-24 00:22:21 +01:00
|
|
|
TabHolder(Orientation orientation, float stripSize, LayoutParams *layoutParams = 0);
|
2013-06-08 22:41:17 +02:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T *AddTab(const std::string &title, T *tabContents) {
|
|
|
|
tabContents->ReplaceLayoutParams(new LinearLayoutParams(1.0f));
|
|
|
|
tabs_.push_back(tabContents);
|
2013-07-15 19:56:36 +02:00
|
|
|
tabStrip_->AddChoice(title);
|
2013-06-08 22:41:17 +02:00
|
|
|
Add(tabContents);
|
|
|
|
if (tabs_.size() > 1)
|
|
|
|
tabContents->SetVisibility(V_GONE);
|
|
|
|
return tabContents;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetCurrentTab(int tab) {
|
|
|
|
tabs_[currentTab_]->SetVisibility(V_GONE);
|
|
|
|
currentTab_ = tab;
|
|
|
|
tabs_[currentTab_]->SetVisibility(V_VISIBLE);
|
2013-10-20 19:39:54 +02:00
|
|
|
tabStrip_->SetSelection(tab);
|
2013-06-08 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
2013-08-27 19:43:40 +02:00
|
|
|
int GetCurrentTab() const { return currentTab_; }
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return "TabHolder: " + View::Describe(); }
|
2013-08-27 19:43:40 +02:00
|
|
|
|
2016-01-22 22:40:36 -08:00
|
|
|
void PersistData(PersistStatus status, PersistMap &storage) override;
|
|
|
|
|
2013-06-08 22:41:17 +02:00
|
|
|
private:
|
|
|
|
EventReturn OnTabClick(EventParams &e);
|
|
|
|
|
2013-07-15 19:56:36 +02:00
|
|
|
ChoiceStrip *tabStrip_;
|
2015-02-24 00:22:21 +01:00
|
|
|
ScrollView *tabScroll_;
|
2013-06-08 22:41:17 +02:00
|
|
|
|
|
|
|
float stripSize_;
|
2013-06-11 20:33:41 +02:00
|
|
|
int currentTab_;
|
2013-06-08 22:41:17 +02:00
|
|
|
std::vector<View *> tabs_;
|
|
|
|
};
|
|
|
|
|
2013-06-09 11:18:57 +02:00
|
|
|
// Yes, this feels a bit Java-ish...
|
|
|
|
class ListAdaptor {
|
|
|
|
public:
|
|
|
|
virtual ~ListAdaptor() {}
|
|
|
|
virtual View *CreateItemView(int index) = 0;
|
|
|
|
virtual int GetNumItems() = 0;
|
|
|
|
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback) { return false; }
|
2014-05-19 23:28:11 +02:00
|
|
|
virtual std::string GetTitle(int index) const { return ""; }
|
2013-07-16 00:25:08 +02:00
|
|
|
virtual void SetSelected(int sel) { }
|
|
|
|
virtual int GetSelected() { return -1; }
|
2013-06-09 11:18:57 +02:00
|
|
|
};
|
|
|
|
|
2013-07-16 00:25:08 +02:00
|
|
|
class ChoiceListAdaptor : public ListAdaptor {
|
2013-06-09 11:18:57 +02:00
|
|
|
public:
|
|
|
|
ChoiceListAdaptor(const char *items[], int numItems) : items_(items), numItems_(numItems) {}
|
|
|
|
virtual View *CreateItemView(int index);
|
|
|
|
virtual int GetNumItems() { return numItems_; }
|
|
|
|
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback);
|
|
|
|
|
|
|
|
private:
|
|
|
|
const char **items_;
|
|
|
|
int numItems_;
|
|
|
|
};
|
|
|
|
|
2013-07-16 00:25:08 +02:00
|
|
|
|
|
|
|
// The "selected" item is what was previously selected (optional). This items will be drawn differently.
|
|
|
|
class StringVectorListAdaptor : public ListAdaptor {
|
|
|
|
public:
|
|
|
|
StringVectorListAdaptor() : selected_(-1) {}
|
|
|
|
StringVectorListAdaptor(const std::vector<std::string> &items, int selected = -1) : items_(items), selected_(selected) {}
|
2014-05-19 23:28:11 +02:00
|
|
|
virtual View *CreateItemView(int index) override;
|
|
|
|
virtual int GetNumItems() override { return (int)items_.size(); }
|
|
|
|
virtual bool AddEventCallback(View *view, std::function<EventReturn(EventParams&)> callback) override;
|
2015-09-17 20:29:37 +02:00
|
|
|
void SetSelected(int sel) override { selected_ = sel; }
|
2014-05-19 23:28:11 +02:00
|
|
|
virtual std::string GetTitle(int index) const override { return items_[index]; }
|
|
|
|
virtual int GetSelected() override { return selected_; }
|
2013-07-16 00:25:08 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<std::string> items_;
|
|
|
|
int selected_;
|
|
|
|
};
|
|
|
|
|
2013-06-09 11:18:57 +02:00
|
|
|
// A list view is a scroll view with autogenerated items.
|
|
|
|
// In the future, it might be smart and load/unload items as they go, but currently not.
|
|
|
|
class ListView : public ScrollView {
|
|
|
|
public:
|
2013-07-16 00:25:08 +02:00
|
|
|
ListView(ListAdaptor *a, LayoutParams *layoutParams = 0);
|
2013-10-23 13:55:11 +02:00
|
|
|
|
2013-07-16 00:25:08 +02:00
|
|
|
int GetSelected() { return adaptor_->GetSelected(); }
|
2015-11-04 12:46:38 +01:00
|
|
|
virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override;
|
2013-12-11 09:32:14 +01:00
|
|
|
virtual void SetMaxHeight(float mh) { maxHeight_ = mh; }
|
2013-06-09 11:18:57 +02:00
|
|
|
Event OnChoice;
|
2015-10-31 13:43:33 +01:00
|
|
|
std::string Describe() const override { return "ListView: " + View::Describe(); }
|
2013-06-09 11:18:57 +02:00
|
|
|
|
|
|
|
private:
|
2013-07-16 00:25:08 +02:00
|
|
|
void CreateAllItems();
|
2013-06-09 11:18:57 +02:00
|
|
|
EventReturn OnItemCallback(int num, EventParams &e);
|
|
|
|
ListAdaptor *adaptor_;
|
2013-07-16 00:25:08 +02:00
|
|
|
LinearLayout *linLayout_;
|
2013-12-11 09:32:14 +01:00
|
|
|
float maxHeight_;
|
2013-06-09 11:18:57 +02:00
|
|
|
};
|
|
|
|
|
2013-05-28 00:32:00 +02:00
|
|
|
void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root);
|
2013-05-25 12:40:57 +02:00
|
|
|
void UpdateViewHierarchy(const InputState &input_state, ViewGroup *root);
|
2013-08-12 23:07:27 +02:00
|
|
|
// Hooks arrow keys for navigation
|
2014-06-15 13:04:10 +02:00
|
|
|
bool KeyEvent(const KeyInput &key, ViewGroup *root);
|
|
|
|
bool TouchEvent(const TouchInput &touch, ViewGroup *root);
|
|
|
|
bool AxisEvent(const AxisInput &axis, ViewGroup *root);
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2014-01-31 14:31:19 +01:00
|
|
|
void CaptureDrag(int id);
|
|
|
|
void ReleaseDrag(int id);
|
|
|
|
bool IsDragCaptured(int id);
|
|
|
|
|
2013-07-14 13:51:30 +02:00
|
|
|
} // namespace UI
|