2013-05-03 00:21:39 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "ui/view.h"
|
|
|
|
#include "input/gesture_detector.h"
|
|
|
|
|
|
|
|
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:
|
|
|
|
ViewGroup(LayoutParams *layoutParams = 0) : View(layoutParams) {}
|
|
|
|
virtual ~ViewGroup();
|
|
|
|
|
|
|
|
// Pass through external events to children.
|
|
|
|
virtual void Touch(const TouchInput &input);
|
|
|
|
|
|
|
|
// By default, a container will layout to its own bounds.
|
2013-05-28 00:32:00 +02:00
|
|
|
virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) = 0;
|
2013-05-03 00:21:39 +02:00
|
|
|
virtual void Layout() = 0;
|
2013-05-25 12:40:57 +02:00
|
|
|
virtual void Update(const InputState &input_state);
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2013-05-28 00:32:00 +02:00
|
|
|
virtual void Draw(UIContext &dc);
|
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!
|
|
|
|
void Add(View *view) { views_.push_back(view); }
|
|
|
|
|
2013-05-25 12:40:57 +02:00
|
|
|
virtual bool SetFocus();
|
2013-05-27 21:39:56 +02:00
|
|
|
virtual bool SubviewFocused(View *view);
|
2013-05-25 12:40:57 +02:00
|
|
|
|
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-05-03 00:21:39 +02:00
|
|
|
|
2013-05-25 12:40:57 +02:00
|
|
|
virtual bool CanBeFocused() const { return false; }
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
protected:
|
|
|
|
std::vector<View *> views_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// A frame layout contains a single child view (normally).
|
|
|
|
class FrameLayout : public ViewGroup {
|
|
|
|
public:
|
2013-05-28 00:32:00 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-03 00:21:39 +02:00
|
|
|
void Layout();
|
|
|
|
};
|
|
|
|
|
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-05-27 22:22:35 +02:00
|
|
|
AnchorLayoutParams(Size w, Size h, float l, float t, float r, float b)
|
|
|
|
: LayoutParams(w, h), left(l), top(t), right(r), bottom(b) {}
|
|
|
|
|
|
|
|
AnchorLayoutParams(float l, float t, float r, float b)
|
|
|
|
: LayoutParams(WRAP_CONTENT, WRAP_CONTENT), left(l), top(t), right(r), bottom(b) {}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
|
|
|
class AnchorLayout : public ViewGroup {
|
|
|
|
public:
|
|
|
|
AnchorLayout(LayoutParams *layoutParams = 0) : ViewGroup(layoutParams) {}
|
2013-05-28 00:32:00 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-03 00:21:39 +02:00
|
|
|
void Layout();
|
|
|
|
};
|
|
|
|
|
2013-05-27 22:22:35 +02:00
|
|
|
class LinearLayoutParams : public LayoutParams {
|
|
|
|
public:
|
|
|
|
LinearLayoutParams()
|
|
|
|
: LayoutParams(), weight(0.0f), gravity(G_TOPLEFT), hasMargins_(false) {}
|
|
|
|
explicit LinearLayoutParams(float wgt)
|
|
|
|
: LayoutParams(), weight(wgt), gravity(G_TOPLEFT), hasMargins_(false) {}
|
|
|
|
LinearLayoutParams(Size w, Size h, float wgt = 0.0f, Gravity grav = G_TOPLEFT)
|
|
|
|
: LayoutParams(w, h), weight(wgt), gravity(grav), hasMargins_(false) {}
|
|
|
|
LinearLayoutParams(Size w, Size h, float wgt, Gravity grav, const Margins &mgn)
|
|
|
|
: LayoutParams(w, h), weight(wgt), gravity(grav), margins(mgn), hasMargins_(true) {}
|
|
|
|
LinearLayoutParams(const Margins &mgn)
|
|
|
|
: LayoutParams(WRAP_CONTENT, WRAP_CONTENT), weight(0.0f), gravity(G_TOPLEFT), margins(mgn), hasMargins_(true) {}
|
|
|
|
|
|
|
|
float weight;
|
|
|
|
Gravity gravity;
|
|
|
|
Margins margins;
|
|
|
|
|
|
|
|
bool HasMargins() const { return hasMargins_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool hasMargins_;
|
|
|
|
};
|
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
class LinearLayout : public ViewGroup {
|
|
|
|
public:
|
|
|
|
LinearLayout(Orientation orientation, LayoutParams *layoutParams = 0)
|
|
|
|
: ViewGroup(layoutParams), spacing_(5), orientation_(orientation), defaultMargins_(0) {}
|
|
|
|
|
2013-05-28 00:32:00 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-03 00:21:39 +02:00
|
|
|
void Layout();
|
|
|
|
|
|
|
|
private:
|
|
|
|
Orientation orientation_;
|
|
|
|
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) {}
|
|
|
|
GridLayoutSettings(int colW, int colH, int spac = 5) : orientation(ORIENT_HORIZONTAL), columnWidth(colW), rowHeight(colH), spacing(spac), fillCells(false) {}
|
|
|
|
|
|
|
|
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)
|
|
|
|
: ViewGroup(layoutParams), settings_(settings) {
|
|
|
|
if (settings.orientation != ORIENT_HORIZONTAL)
|
|
|
|
ELOG("GridLayout: Vertical layouts not yet supported");
|
|
|
|
}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2013-05-28 00:32:00 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-03 00:21:39 +02:00
|
|
|
void Layout();
|
|
|
|
|
|
|
|
private:
|
2013-05-27 00:54:02 +02:00
|
|
|
GridLayoutSettings settings_;
|
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-05-28 00:50:19 +02:00
|
|
|
ViewGroup(layoutParams), orientation_(orientation), scrollPos_(0), scrollTarget_(0), scrollToTarget_(false) {}
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2013-05-28 00:32:00 +02:00
|
|
|
void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-03 00:21:39 +02:00
|
|
|
void Layout();
|
|
|
|
|
|
|
|
void Touch(const TouchInput &input);
|
2013-05-28 00:32:00 +02:00
|
|
|
void Draw(UIContext &dc);
|
2013-05-03 00:21:39 +02:00
|
|
|
|
2013-05-27 21:39:56 +02:00
|
|
|
void ScrollTo(float newScrollPos);
|
2013-05-28 00:50:19 +02:00
|
|
|
void Update(const InputState &input_state);
|
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.
|
2013-05-27 21:39:56 +02:00
|
|
|
virtual bool SubviewFocused(View *view);
|
2013-05-27 00:54:02 +02:00
|
|
|
|
2013-05-03 00:21:39 +02:00
|
|
|
private:
|
|
|
|
GestureDetector gesture_;
|
|
|
|
Orientation orientation_;
|
|
|
|
float scrollPos_;
|
|
|
|
float scrollStart_;
|
2013-05-27 21:39:56 +02:00
|
|
|
float scrollMax_;
|
2013-05-28 00:50:19 +02:00
|
|
|
float scrollTarget_;
|
|
|
|
bool scrollToTarget_;
|
2013-05-03 00:21:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class ViewPager : public ScrollView {
|
|
|
|
public:
|
|
|
|
};
|
|
|
|
|
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-05-03 00:21:39 +02:00
|
|
|
|
|
|
|
} // namespace UI
|