2013-05-02 22:21:39 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// More traditional UI framework than ui/ui.h.
|
|
|
|
|
|
|
|
// Still very simple to use.
|
|
|
|
|
|
|
|
// Works very similarly to Android, there's a Measure pass and a Layout pass which you don't
|
|
|
|
// really need to care about if you just use the standard containers and widgets.
|
|
|
|
|
2013-05-31 22:50:08 +00:00
|
|
|
#include <string>
|
2013-05-02 22:21:39 +00:00
|
|
|
#include <vector>
|
2013-05-25 14:52:27 +00:00
|
|
|
#include <cmath>
|
2013-06-04 12:50:22 +00:00
|
|
|
#include <cstdio>
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-06-08 23:21:08 +00:00
|
|
|
#include "base/logging.h"
|
2013-06-01 16:59:03 +00:00
|
|
|
#include "base/functional.h"
|
2013-05-02 22:21:39 +00:00
|
|
|
#include "base/mutex.h"
|
|
|
|
#include "base/basictypes.h"
|
|
|
|
#include "base/scoped_ptr.h"
|
2013-08-19 22:34:54 +00:00
|
|
|
#include "gfx/texture_atlas.h"
|
2013-05-02 22:21:39 +00:00
|
|
|
#include "math/lin/matrix4x4.h"
|
2013-05-25 14:52:27 +00:00
|
|
|
#include "math/math_util.h"
|
|
|
|
#include "math/geom2d.h"
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-07-08 10:34:39 +00:00
|
|
|
struct KeyInput;
|
2013-05-02 22:21:39 +00:00
|
|
|
struct TouchInput;
|
2013-08-12 21:07:27 +00:00
|
|
|
struct AxisInput;
|
2013-05-25 10:40:57 +00:00
|
|
|
struct InputState;
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
class DrawBuffer;
|
2013-06-08 20:41:17 +00:00
|
|
|
class Texture;
|
2013-05-27 22:32:00 +00:00
|
|
|
class UIContext;
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
// I don't generally like namespaces but I think we do need one for UI, so many potentially-clashing names.
|
|
|
|
namespace UI {
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
class View;
|
|
|
|
|
|
|
|
// The ONLY global is the currently focused item.
|
|
|
|
// Can be and often is null.
|
|
|
|
void EnableFocusMovement(bool enable);
|
|
|
|
bool IsFocusMovementEnabled();
|
|
|
|
View *GetFocusedView();
|
|
|
|
void SetFocusedView(View *view);
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
enum DrawableType {
|
|
|
|
DRAW_NOTHING,
|
|
|
|
DRAW_SOLID_COLOR,
|
|
|
|
DRAW_4GRID,
|
2013-06-08 20:41:17 +00:00
|
|
|
DRAW_STRETCH_IMAGE,
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
2013-06-02 21:44:28 +00:00
|
|
|
enum Visibility {
|
|
|
|
V_VISIBLE,
|
|
|
|
V_INVISIBLE, // Keeps position, not drawn or interacted with
|
|
|
|
V_GONE, // Does not participate in layout
|
|
|
|
};
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
struct Drawable {
|
2013-06-08 20:41:17 +00:00
|
|
|
Drawable() : type(DRAW_NOTHING), image(-1), color(0xFFFFFFFF) {}
|
|
|
|
explicit Drawable(uint32_t col) : type(DRAW_SOLID_COLOR), image(-1), color(col) {}
|
|
|
|
Drawable(DrawableType t, int img, uint32_t col = 0xFFFFFFFF) : type(t), image(img), color(col) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
DrawableType type;
|
2013-06-08 20:41:17 +00:00
|
|
|
uint32_t image;
|
|
|
|
uint32_t color;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Style {
|
2013-06-08 20:41:17 +00:00
|
|
|
Style() : fgColor(0xFFFFFFFF), background(0xFF303030), image(-1) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
uint32_t fgColor;
|
2013-06-08 20:41:17 +00:00
|
|
|
Drawable background;
|
2013-06-03 23:24:49 +00:00
|
|
|
int image; // where applicable.
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
2013-08-30 12:44:23 +00:00
|
|
|
struct FontStyle {
|
|
|
|
FontStyle() : atlasFont(0), sizePts(0), flags(0) {}
|
|
|
|
FontStyle(const char *name, int size) : atlasFont(0), fontName(name), sizePts(size), flags(0) {}
|
|
|
|
FontStyle(int atlasFnt, const char *name, int size) : atlasFont(atlasFnt), fontName(name), sizePts(size), flags(0) {}
|
|
|
|
|
|
|
|
int atlasFont;
|
|
|
|
// For native fonts:
|
|
|
|
std::string fontName;
|
|
|
|
int sizePts;
|
|
|
|
int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
// To use with an UI atlas.
|
|
|
|
struct Theme {
|
2013-08-30 12:44:23 +00:00
|
|
|
FontStyle uiFont;
|
|
|
|
FontStyle uiFontSmall;
|
|
|
|
FontStyle uiFontSmaller;
|
2013-05-02 22:21:39 +00:00
|
|
|
int checkOn;
|
|
|
|
int checkOff;
|
2013-07-18 08:25:30 +00:00
|
|
|
int sliderKnob;
|
2013-05-25 14:52:27 +00:00
|
|
|
int whiteImage;
|
2013-08-16 14:47:25 +00:00
|
|
|
int dropShadow4Grid;
|
2013-05-25 10:40:57 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
Style buttonStyle;
|
2013-05-25 10:40:57 +00:00
|
|
|
Style buttonFocusedStyle;
|
|
|
|
Style buttonDownStyle;
|
2013-06-02 21:44:28 +00:00
|
|
|
Style buttonDisabledStyle;
|
2013-10-07 16:15:25 +00:00
|
|
|
Style buttonHighlightedStyle;
|
2013-05-25 14:52:27 +00:00
|
|
|
|
2013-06-08 20:41:17 +00:00
|
|
|
Style itemStyle;
|
2013-05-25 14:52:27 +00:00
|
|
|
Style itemDownStyle;
|
|
|
|
Style itemFocusedStyle;
|
2013-08-16 14:47:25 +00:00
|
|
|
Style itemDisabledStyle;
|
2013-10-07 16:15:25 +00:00
|
|
|
Style itemHighlightedStyle;
|
2013-08-16 14:47:25 +00:00
|
|
|
|
|
|
|
Style headerStyle;
|
2013-08-14 21:29:27 +00:00
|
|
|
|
|
|
|
Style popupTitle;
|
2013-05-25 10:40:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// The four cardinal directions should be enough, plus Prev/Next in "element order".
|
|
|
|
enum FocusDirection {
|
|
|
|
FOCUS_UP,
|
|
|
|
FOCUS_DOWN,
|
|
|
|
FOCUS_LEFT,
|
|
|
|
FOCUS_RIGHT,
|
|
|
|
FOCUS_NEXT,
|
|
|
|
FOCUS_PREV,
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
WRAP_CONTENT = -1,
|
|
|
|
FILL_PARENT = -2,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Gravity
|
|
|
|
enum Gravity {
|
|
|
|
G_LEFT = 0,
|
|
|
|
G_RIGHT = 1,
|
|
|
|
G_HCENTER = 2,
|
|
|
|
|
|
|
|
G_HORIZMASK = 3,
|
|
|
|
|
|
|
|
G_TOP = 0,
|
|
|
|
G_BOTTOM = 4,
|
|
|
|
G_VCENTER = 8,
|
|
|
|
|
|
|
|
G_TOPLEFT = G_TOP | G_LEFT,
|
|
|
|
G_TOPRIGHT = G_TOP | G_RIGHT,
|
|
|
|
|
|
|
|
G_BOTTOMLEFT = G_BOTTOM | G_LEFT,
|
|
|
|
G_BOTTOMRIGHT = G_BOTTOM | G_RIGHT,
|
|
|
|
|
|
|
|
G_VERTMASK = 3 << 2,
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef float Size; // can also be WRAP_CONTENT or FILL_PARENT.
|
|
|
|
|
|
|
|
enum Orientation {
|
|
|
|
ORIENT_HORIZONTAL,
|
|
|
|
ORIENT_VERTICAL,
|
|
|
|
};
|
|
|
|
|
2013-06-10 20:05:58 +00:00
|
|
|
inline Orientation Opposite(Orientation o) {
|
|
|
|
if (o == ORIENT_HORIZONTAL) return ORIENT_VERTICAL; else return ORIENT_HORIZONTAL;
|
|
|
|
}
|
|
|
|
|
2013-07-15 17:56:36 +00:00
|
|
|
inline FocusDirection Opposite(FocusDirection d) {
|
|
|
|
switch (d) {
|
|
|
|
case FOCUS_UP: return FOCUS_DOWN;
|
|
|
|
case FOCUS_DOWN: return FOCUS_UP;
|
|
|
|
case FOCUS_LEFT: return FOCUS_RIGHT;
|
|
|
|
case FOCUS_RIGHT: return FOCUS_LEFT;
|
|
|
|
case FOCUS_PREV: return FOCUS_NEXT;
|
|
|
|
case FOCUS_NEXT: return FOCUS_PREV;
|
|
|
|
}
|
2013-07-15 22:25:08 +00:00
|
|
|
return d;
|
2013-07-15 17:56:36 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
enum MeasureSpecType {
|
|
|
|
UNSPECIFIED,
|
|
|
|
EXACTLY,
|
|
|
|
AT_MOST,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum EventReturn {
|
|
|
|
EVENT_DONE,
|
|
|
|
EVENT_SKIPPED,
|
|
|
|
};
|
|
|
|
|
2013-07-15 15:51:12 +00:00
|
|
|
enum FocusFlags {
|
|
|
|
FF_LOSTFOCUS = 1,
|
|
|
|
FF_GOTFOCUS = 2
|
|
|
|
};
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
class ViewGroup;
|
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
void Fill(UIContext &dc, const Bounds &bounds, const Drawable &drawable);
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
struct MeasureSpec {
|
|
|
|
MeasureSpec(MeasureSpecType t, float s = 0.0f) : type(t), size(s) {}
|
|
|
|
MeasureSpec() : type(UNSPECIFIED), size(0) {}
|
|
|
|
|
|
|
|
MeasureSpec operator -(float amount) {
|
|
|
|
// TODO: Check type
|
|
|
|
return MeasureSpec(type, size - amount);
|
|
|
|
}
|
|
|
|
MeasureSpecType type;
|
|
|
|
float size;
|
|
|
|
};
|
|
|
|
|
|
|
|
class View;
|
|
|
|
|
|
|
|
|
|
|
|
// Should cover all bases.
|
|
|
|
struct EventParams {
|
|
|
|
View *v;
|
|
|
|
uint32_t a, b, x, y;
|
2013-06-10 20:05:58 +00:00
|
|
|
std::string s;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct HandlerRegistration {
|
2013-06-02 12:25:57 +00:00
|
|
|
std::function<EventReturn(EventParams&)> func;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Event {
|
|
|
|
public:
|
2013-06-27 14:20:18 +00:00
|
|
|
Event() {}
|
|
|
|
~Event() {
|
|
|
|
handlers_.clear();
|
|
|
|
}
|
2013-05-02 22:21:39 +00:00
|
|
|
// Call this from input thread or whatever, it doesn't matter
|
2013-06-01 16:59:03 +00:00
|
|
|
void Trigger(EventParams &e);
|
2013-05-02 22:21:39 +00:00
|
|
|
// Call this from UI thread
|
2013-07-15 17:56:36 +00:00
|
|
|
EventReturn Dispatch(EventParams &e);
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-06-09 09:18:57 +00:00
|
|
|
// This is suggested for use in most cases. Autobinds, allowing for neat syntax.
|
2013-06-04 21:53:41 +00:00
|
|
|
template<class T>
|
2013-06-09 10:40:53 +00:00
|
|
|
T *Handle(T *thiz, EventReturn (T::* theCallback)(EventParams &e)) {
|
2013-06-04 21:53:41 +00:00
|
|
|
Add(std::bind(theCallback, thiz, placeholder::_1));
|
2013-06-09 10:40:53 +00:00
|
|
|
return thiz;
|
2013-06-04 21:53:41 +00:00
|
|
|
}
|
|
|
|
|
2013-06-09 09:18:57 +00:00
|
|
|
// Sometimes you have an already-bound function<>, just use this then.
|
2013-06-04 21:53:41 +00:00
|
|
|
void Add(std::function<EventReturn(EventParams&)> func);
|
|
|
|
|
2013-06-09 09:18:57 +00:00
|
|
|
private:
|
2013-05-02 22:21:39 +00:00
|
|
|
std::vector<HandlerRegistration> handlers_;
|
2013-06-27 14:20:18 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(Event);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Margins {
|
|
|
|
Margins() : top(0), bottom(0), left(0), right(0) {}
|
2013-08-19 22:34:54 +00:00
|
|
|
explicit Margins(int8_t all) : top(all), bottom(all), left(all), right(all) {}
|
|
|
|
Margins(int8_t horiz, int8_t vert) : top(vert), bottom(vert), left(horiz), right(horiz) {}
|
|
|
|
Margins(int8_t l, int8_t t, int8_t r, int8_t b) : top(t), bottom(b), left(l), right(r) {}
|
2013-06-08 20:41:17 +00:00
|
|
|
|
2013-08-19 22:34:54 +00:00
|
|
|
int8_t top;
|
|
|
|
int8_t bottom;
|
|
|
|
int8_t left;
|
|
|
|
int8_t right;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
2013-06-09 11:01:36 +00:00
|
|
|
enum LayoutParamsType {
|
|
|
|
LP_PLAIN = 0,
|
|
|
|
LP_LINEAR = 1,
|
|
|
|
LP_ANCHOR = 2,
|
|
|
|
};
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
// Need a virtual destructor so vtables are created, otherwise RTTI can't work
|
|
|
|
class LayoutParams {
|
|
|
|
public:
|
2013-06-09 11:01:36 +00:00
|
|
|
LayoutParams(LayoutParamsType type = LP_PLAIN)
|
2013-06-11 18:33:41 +00:00
|
|
|
: width(WRAP_CONTENT), height(WRAP_CONTENT), type_(type) {}
|
2013-06-09 11:01:36 +00:00
|
|
|
LayoutParams(Size w, Size h, LayoutParamsType type = LP_PLAIN)
|
|
|
|
: width(w), height(h), type_(type) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
virtual ~LayoutParams() {}
|
|
|
|
Size width;
|
|
|
|
Size height;
|
2013-06-09 11:01:36 +00:00
|
|
|
|
|
|
|
// Fake RTTI
|
|
|
|
bool Is(LayoutParamsType type) const { return type_ == type; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
LayoutParamsType type_;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
View *GetFocusedView();
|
|
|
|
|
|
|
|
class View {
|
|
|
|
public:
|
2013-06-08 23:21:08 +00:00
|
|
|
View(LayoutParams *layoutParams = 0) : layoutParams_(layoutParams), enabled_(true), visibility_(V_VISIBLE), measuredWidth_(0), measuredHeight_(0) {
|
2013-05-02 22:21:39 +00:00
|
|
|
if (!layoutParams)
|
|
|
|
layoutParams_.reset(new LayoutParams());
|
|
|
|
}
|
|
|
|
|
2013-07-15 17:56:36 +00:00
|
|
|
virtual ~View() { if (HasFocus()) SetFocusedView(0); }
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
// Please note that Touch is called ENTIRELY asynchronously from drawing!
|
|
|
|
// Can even be called on a different thread! This is to really minimize latency, and decouple
|
2013-08-27 17:43:40 +00:00
|
|
|
// touch response from the frame rate. Same with Key and Axis.
|
|
|
|
virtual void Key(const KeyInput &input) {}
|
|
|
|
virtual void Touch(const TouchInput &input) {}
|
2013-08-12 21:07:27 +00:00
|
|
|
virtual void Axis(const AxisInput &input) {}
|
|
|
|
virtual void Update(const InputState &input_state) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-07-15 15:51:12 +00:00
|
|
|
virtual void FocusChanged(int focusFlags) {}
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
void Move(Bounds bounds) {
|
|
|
|
bounds_ = bounds;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Views don't do anything here in Layout, only containers implement this.
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert);
|
2013-05-02 22:21:39 +00:00
|
|
|
virtual void Layout() {}
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
virtual float GetMeasuredWidth() const { return measuredWidth_; }
|
|
|
|
virtual float GetMeasuredHeight() const { return measuredHeight_; }
|
|
|
|
|
|
|
|
// Override this for easy standard behaviour. No need to override Measure.
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
// Called when the layout is done.
|
|
|
|
void SetBounds(Bounds bounds) { bounds_ = bounds; }
|
|
|
|
virtual const LayoutParams *GetLayoutParams() const { return layoutParams_.get(); }
|
2013-06-08 20:41:17 +00:00
|
|
|
virtual void ReplaceLayoutParams(LayoutParams *newLayoutParams) { layoutParams_.reset(newLayoutParams); }
|
2013-05-02 22:21:39 +00:00
|
|
|
const Bounds &GetBounds() const { return bounds_; }
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
virtual bool SetFocus() {
|
|
|
|
if (CanBeFocused()) {
|
|
|
|
SetFocusedView(this);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2013-05-26 22:54:02 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
virtual bool CanBeFocused() const { return true; }
|
2013-05-27 19:39:56 +00:00
|
|
|
virtual bool SubviewFocused(View *view) { return false; }
|
2013-05-25 10:40:57 +00:00
|
|
|
bool HasFocus() const {
|
2013-05-02 22:21:39 +00:00
|
|
|
return GetFocusedView() == this;
|
|
|
|
}
|
|
|
|
|
2013-06-01 16:59:03 +00:00
|
|
|
void SetEnabled(bool enabled) { enabled_ = enabled; }
|
2013-08-18 21:11:26 +00:00
|
|
|
bool IsEnabled() const { return enabled_; }
|
2013-06-02 21:44:28 +00:00
|
|
|
|
|
|
|
void SetVisibility(Visibility visibility) { visibility_ = visibility; }
|
|
|
|
Visibility GetVisibility() const { return visibility_; }
|
2013-06-01 16:59:03 +00:00
|
|
|
|
2013-06-08 20:41:17 +00:00
|
|
|
const std::string &Tag() const { return tag_; }
|
|
|
|
void SetTag(const std::string &str) { tag_ = str; }
|
|
|
|
|
2013-06-09 11:01:36 +00:00
|
|
|
// Fake RTTI
|
|
|
|
virtual bool IsViewGroup() const { return false; }
|
|
|
|
|
2013-07-15 17:56:36 +00:00
|
|
|
Point GetFocusPosition(FocusDirection dir);
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
protected:
|
|
|
|
// Inputs to layout
|
|
|
|
scoped_ptr<LayoutParams> layoutParams_;
|
2013-06-08 20:41:17 +00:00
|
|
|
|
|
|
|
std::string tag_;
|
2013-06-01 16:59:03 +00:00
|
|
|
bool enabled_;
|
2013-06-02 21:44:28 +00:00
|
|
|
Visibility visibility_;
|
2013-06-01 16:59:03 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
// Results of measure pass. Set these in Measure.
|
|
|
|
float measuredWidth_;
|
|
|
|
float measuredHeight_;
|
|
|
|
|
|
|
|
// Outputs of layout. X/Y are absolute screen coordinates, hierarchy is "gone" here.
|
|
|
|
Bounds bounds_;
|
|
|
|
|
|
|
|
scoped_ptr<Matrix4x4> transform_;
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(View);
|
|
|
|
};
|
|
|
|
|
|
|
|
// These don't do anything when touched.
|
|
|
|
class InertView : public View {
|
|
|
|
public:
|
|
|
|
InertView(LayoutParams *layoutParams)
|
|
|
|
: View(layoutParams) {}
|
|
|
|
|
2013-07-08 10:34:39 +00:00
|
|
|
virtual void Key(const KeyInput &input) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
virtual void Touch(const TouchInput &input) {}
|
2013-05-25 10:40:57 +00:00
|
|
|
virtual bool CanBeFocused() const { return false; }
|
|
|
|
virtual void Update(const InputState &input_state) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// All these light up their background when touched, or have focus.
|
|
|
|
class Clickable : public View {
|
|
|
|
public:
|
|
|
|
Clickable(LayoutParams *layoutParams)
|
2013-10-08 12:34:56 +00:00
|
|
|
: View(layoutParams), downCountDown_(0), dragging_(false), down_(false){}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-07-08 10:34:39 +00:00
|
|
|
virtual void Key(const KeyInput &input);
|
2013-05-02 22:21:39 +00:00
|
|
|
virtual void Touch(const TouchInput &input);
|
|
|
|
|
2013-07-15 15:51:12 +00:00
|
|
|
virtual void FocusChanged(int focusFlags);
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
Event OnClick;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
// Internal method that fires on a click. Default behaviour is to trigger
|
|
|
|
// the event.
|
|
|
|
// Use it for checking/unchecking checkboxes, etc.
|
|
|
|
virtual void Click();
|
|
|
|
|
2013-05-25 14:52:27 +00:00
|
|
|
int downCountDown_;
|
|
|
|
bool dragging_;
|
2013-05-02 22:21:39 +00:00
|
|
|
bool down_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Button : public Clickable {
|
|
|
|
public:
|
|
|
|
Button(const std::string &text, LayoutParams *layoutParams = 0)
|
|
|
|
: Clickable(layoutParams), text_(text) {}
|
2013-08-27 17:43:40 +00:00
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-06-27 14:20:18 +00:00
|
|
|
const std::string &GetText() const { return text_; }
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
Style style_;
|
|
|
|
std::string text_;
|
|
|
|
};
|
|
|
|
|
2013-07-18 08:25:30 +00:00
|
|
|
class Slider : public Clickable {
|
|
|
|
public:
|
|
|
|
Slider(int *value, int minValue, int maxValue, LayoutParams *layoutParams = 0)
|
2013-09-11 09:19:41 +00:00
|
|
|
: Clickable(layoutParams), value_(value), showPercent_(false), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {}
|
2013-07-18 08:25:30 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
virtual void Key(const KeyInput &input);
|
|
|
|
virtual void Touch(const TouchInput &input);
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-08-20 10:48:48 +00:00
|
|
|
void SetShowPercent(bool s) { showPercent_ = s; }
|
2013-07-18 08:25:30 +00:00
|
|
|
private:
|
|
|
|
void Clamp();
|
|
|
|
int *value_;
|
2013-08-20 10:48:48 +00:00
|
|
|
bool showPercent_;
|
2013-07-18 08:25:30 +00:00
|
|
|
int minValue_;
|
|
|
|
int maxValue_;
|
2013-08-20 10:48:48 +00:00
|
|
|
float paddingLeft_;
|
|
|
|
float paddingRight_;
|
2013-07-18 08:25:30 +00:00
|
|
|
};
|
|
|
|
|
2013-07-20 11:54:09 +00:00
|
|
|
class SliderFloat : public Clickable {
|
|
|
|
public:
|
|
|
|
SliderFloat(float *value, float minValue, float maxValue, LayoutParams *layoutParams = 0)
|
2013-09-11 09:19:41 +00:00
|
|
|
: Clickable(layoutParams), value_(value), minValue_(minValue), maxValue_(maxValue), paddingLeft_(5), paddingRight_(70) {}
|
2013-07-20 11:54:09 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
virtual void Key(const KeyInput &input);
|
|
|
|
virtual void Touch(const TouchInput &input);
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void Clamp();
|
|
|
|
float *value_;
|
|
|
|
float minValue_;
|
|
|
|
float maxValue_;
|
2013-08-20 10:48:48 +00:00
|
|
|
float paddingLeft_;
|
|
|
|
float paddingRight_;
|
2013-07-20 11:54:09 +00:00
|
|
|
};
|
2013-07-18 08:25:30 +00:00
|
|
|
|
2013-05-27 20:22:35 +00:00
|
|
|
// Basic button that modifies a bitfield based on the pressed status. Supports multitouch.
|
|
|
|
// Suitable for controller simulation (ABXY etc).
|
|
|
|
class TriggerButton : public View {
|
|
|
|
public:
|
|
|
|
TriggerButton(uint32_t *bitField, uint32_t bit, int imageBackground, int imageForeground, LayoutParams *layoutParams)
|
|
|
|
: View(layoutParams), down_(0.0), bitField_(bitField), bit_(bit), imageBackground_(imageBackground), imageForeground_(imageForeground) {}
|
|
|
|
|
|
|
|
virtual void Touch(const TouchInput &input);
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-05-27 20:22:35 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int down_; // bitfield of pressed fingers, translates into bitField
|
|
|
|
|
|
|
|
uint32_t *bitField_;
|
|
|
|
uint32_t bit_;
|
|
|
|
|
|
|
|
int imageBackground_;
|
|
|
|
int imageForeground_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// The following classes are mostly suitable as items in ListView which
|
|
|
|
// really is just a LinearLayout in a ScrollView, possibly with some special optimizations.
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
class Item : public InertView {
|
|
|
|
public:
|
2013-05-27 22:50:19 +00:00
|
|
|
Item(LayoutParams *layoutParams);
|
2013-06-09 09:18:57 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-05-25 10:40:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class ClickableItem : public Clickable {
|
|
|
|
public:
|
2013-05-27 22:50:19 +00:00
|
|
|
ClickableItem(LayoutParams *layoutParams);
|
2013-06-09 09:18:57 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-05-25 10:40:57 +00:00
|
|
|
|
2013-05-25 14:52:27 +00:00
|
|
|
// Draws the item background.
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
2013-05-25 14:52:27 +00:00
|
|
|
};
|
2013-05-25 10:40:57 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
// Use to trigger something or open a submenu screen.
|
2013-05-25 10:40:57 +00:00
|
|
|
class Choice : public ClickableItem {
|
2013-05-02 22:21:39 +00:00
|
|
|
public:
|
2013-08-16 14:47:25 +00:00
|
|
|
Choice(const std::string &text, LayoutParams *layoutParams = 0)
|
2013-10-08 12:34:56 +00:00
|
|
|
: ClickableItem(layoutParams), text_(text), smallText_(), atlasImage_(-1), selected_(false), centered_(false), highlighted_(false) {}
|
2013-08-16 14:47:25 +00:00
|
|
|
Choice(const std::string &text, const std::string &smallText, bool selected = false, LayoutParams *layoutParams = 0)
|
2013-10-08 12:34:56 +00:00
|
|
|
: ClickableItem(layoutParams), text_(text), smallText_(smallText), atlasImage_(-1), selected_(selected), centered_(false), highlighted_(false) {}
|
2013-08-19 22:34:54 +00:00
|
|
|
|
|
|
|
Choice(ImageID image, LayoutParams *layoutParams = 0)
|
2013-10-08 12:34:56 +00:00
|
|
|
: ClickableItem(layoutParams), atlasImage_(image), selected_(false), highlighted_(false) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-10-08 12:34:56 +00:00
|
|
|
virtual void HighlightChanged(bool highlighted);
|
2013-06-10 20:05:58 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
2013-08-30 20:42:02 +00:00
|
|
|
virtual void SetCentered(bool c) {
|
|
|
|
centered_ = c;
|
|
|
|
}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-07-16 23:03:29 +00:00
|
|
|
protected:
|
2013-08-20 11:03:42 +00:00
|
|
|
// hackery
|
|
|
|
virtual bool IsSticky() const { return false; }
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
std::string text_;
|
|
|
|
std::string smallText_;
|
2013-08-19 22:34:54 +00:00
|
|
|
ImageID atlasImage_;
|
2013-08-30 20:42:02 +00:00
|
|
|
bool centered_;
|
2013-10-08 12:34:56 +00:00
|
|
|
bool highlighted_;
|
2013-08-30 12:44:23 +00:00
|
|
|
|
2013-07-16 23:03:29 +00:00
|
|
|
private:
|
2013-07-15 22:25:08 +00:00
|
|
|
bool selected_;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
2013-07-15 17:56:36 +00:00
|
|
|
// Different key handling.
|
|
|
|
class StickyChoice : public Choice {
|
|
|
|
public:
|
|
|
|
StickyChoice(const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0)
|
2013-07-15 22:25:08 +00:00
|
|
|
: Choice(text, smallText, false, layoutParams) {}
|
2013-08-19 22:34:54 +00:00
|
|
|
StickyChoice(ImageID buttonImage, LayoutParams *layoutParams = 0)
|
|
|
|
: Choice(buttonImage, layoutParams) {}
|
2013-07-15 17:56:36 +00:00
|
|
|
|
2013-08-16 14:47:25 +00:00
|
|
|
virtual void Key(const KeyInput &key);
|
|
|
|
virtual void Touch(const TouchInput &touch);
|
2013-07-15 17:56:36 +00:00
|
|
|
virtual void FocusChanged(int focusFlags);
|
2013-10-08 12:34:56 +00:00
|
|
|
|
2013-08-17 10:06:08 +00:00
|
|
|
void Press() { down_ = true; dragging_ = false; }
|
2013-07-15 17:56:36 +00:00
|
|
|
void Release() { down_ = false; dragging_ = false; }
|
|
|
|
bool IsDown() { return down_; }
|
2013-10-08 12:34:56 +00:00
|
|
|
|
2013-08-20 11:03:42 +00:00
|
|
|
protected:
|
|
|
|
// hackery
|
|
|
|
virtual bool IsSticky() const { return true; }
|
2013-07-15 17:56:36 +00:00
|
|
|
};
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
class InfoItem : public Item {
|
|
|
|
public:
|
|
|
|
InfoItem(const std::string &text, const std::string &rightText, LayoutParams *layoutParams = 0)
|
|
|
|
: Item(layoutParams), text_(text), rightText_(rightText) {}
|
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
2013-05-25 10:40:57 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::string text_;
|
|
|
|
std::string rightText_;
|
|
|
|
};
|
|
|
|
|
2013-05-25 14:52:27 +00:00
|
|
|
class ItemHeader : public Item {
|
|
|
|
public:
|
2013-08-19 22:34:54 +00:00
|
|
|
ItemHeader(const std::string &text, LayoutParams *layoutParams = 0);
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
2013-05-25 14:52:27 +00:00
|
|
|
private:
|
|
|
|
std::string text_;
|
|
|
|
};
|
|
|
|
|
2013-08-14 21:29:27 +00:00
|
|
|
class PopupHeader : public Item {
|
|
|
|
public:
|
|
|
|
PopupHeader(const std::string &text, LayoutParams *layoutParams = 0)
|
|
|
|
: Item(layoutParams), text_(text) {
|
|
|
|
layoutParams_->width = FILL_PARENT;
|
|
|
|
layoutParams_->height = 64;
|
|
|
|
}
|
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
private:
|
|
|
|
std::string text_;
|
|
|
|
};
|
|
|
|
|
2013-05-25 13:12:46 +00:00
|
|
|
class CheckBox : public ClickableItem {
|
2013-05-02 22:21:39 +00:00
|
|
|
public:
|
2013-05-25 10:40:57 +00:00
|
|
|
CheckBox(bool *toggle, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = 0)
|
2013-06-08 20:41:17 +00:00
|
|
|
: ClickableItem(layoutParams), toggle_(toggle), text_(text), smallText_(smallText) {
|
2013-06-04 21:53:41 +00:00
|
|
|
OnClick.Handle(this, &CheckBox::OnClicked);
|
2013-05-25 10:40:57 +00:00
|
|
|
}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc);
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-06-01 16:59:03 +00:00
|
|
|
EventReturn OnClicked(EventParams &e) {
|
2013-05-25 10:40:57 +00:00
|
|
|
if (toggle_)
|
|
|
|
*toggle_ = !(*toggle_);
|
|
|
|
return EVENT_DONE;
|
|
|
|
}
|
2013-05-25 13:12:46 +00:00
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
private:
|
2013-05-25 10:40:57 +00:00
|
|
|
bool *toggle_;
|
2013-05-02 22:21:39 +00:00
|
|
|
std::string text_;
|
|
|
|
std::string smallText_;
|
|
|
|
};
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
// These are for generic use.
|
|
|
|
|
|
|
|
class Spacer : public InertView {
|
|
|
|
public:
|
|
|
|
Spacer(LayoutParams *layoutParams = 0)
|
2013-08-20 10:27:42 +00:00
|
|
|
: InertView(layoutParams), size_(0.0f) {}
|
|
|
|
Spacer(float size, LayoutParams *layoutParams = 0)
|
|
|
|
: InertView(layoutParams), size_(size) {}
|
2013-07-27 06:04:53 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const {
|
2013-08-20 10:27:42 +00:00
|
|
|
w = size_; h = size_;
|
2013-05-25 10:40:57 +00:00
|
|
|
}
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void Draw(UIContext &dc) {}
|
2013-08-20 10:27:42 +00:00
|
|
|
private:
|
|
|
|
float size_;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class TextView : public InertView {
|
|
|
|
public:
|
2013-08-16 10:51:57 +00:00
|
|
|
TextView(const std::string &text, LayoutParams *layoutParams = 0)
|
2013-08-30 12:44:23 +00:00
|
|
|
: InertView(layoutParams), text_(text), textAlign_(0), small_(false) {}
|
2013-08-16 10:51:57 +00:00
|
|
|
|
2013-08-30 12:44:23 +00:00
|
|
|
TextView(const std::string &text, int textAlign, bool small, LayoutParams *layoutParams = 0)
|
|
|
|
: InertView(layoutParams), text_(text), textAlign_(textAlign), small_(small) {}
|
2013-05-02 22:21:39 +00:00
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
|
|
|
virtual void Draw(UIContext &dc);
|
2013-06-20 19:51:42 +00:00
|
|
|
void SetText(const std::string &text) { text_ = text; }
|
2013-08-30 12:44:23 +00:00
|
|
|
void SetSmall(bool small) { small_ = small; }
|
2013-05-02 22:21:39 +00:00
|
|
|
private:
|
2013-06-01 16:59:03 +00:00
|
|
|
std::string text_;
|
|
|
|
int textAlign_;
|
2013-08-30 18:18:16 +00:00
|
|
|
bool small_;
|
2013-05-02 22:21:39 +00:00
|
|
|
};
|
|
|
|
|
2013-05-25 10:40:57 +00:00
|
|
|
enum ImageSizeMode {
|
|
|
|
IS_DEFAULT,
|
|
|
|
};
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
class ImageView : public InertView {
|
|
|
|
public:
|
|
|
|
ImageView(int atlasImage, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0)
|
|
|
|
: InertView(layoutParams), atlasImage_(atlasImage), sizeMode_(sizeMode) {}
|
|
|
|
|
2013-05-27 22:32:00 +00:00
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
|
|
|
virtual void Draw(UIContext &dc);
|
2013-05-02 22:21:39 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
int atlasImage_;
|
|
|
|
ImageSizeMode sizeMode_;
|
|
|
|
};
|
|
|
|
|
2013-06-08 20:41:17 +00:00
|
|
|
class TextureView : public InertView {
|
|
|
|
public:
|
|
|
|
TextureView(Texture *texture, ImageSizeMode sizeMode, LayoutParams *layoutParams = 0)
|
|
|
|
: InertView(layoutParams), texture_(texture), sizeMode_(sizeMode) {}
|
|
|
|
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
|
|
|
|
void SetTexture(Texture *texture) { texture_ = texture; }
|
|
|
|
void SetColor(uint32_t color) { color_ = color; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Texture *texture_;
|
|
|
|
uint32_t color_;
|
|
|
|
ImageSizeMode sizeMode_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-06-02 21:44:28 +00:00
|
|
|
class ProgressBar : public InertView {
|
|
|
|
public:
|
|
|
|
ProgressBar(LayoutParams *layoutParams = 0)
|
|
|
|
: InertView(layoutParams), progress_(0.0) {}
|
|
|
|
|
|
|
|
virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const;
|
|
|
|
virtual void Draw(UIContext &dc);
|
|
|
|
|
|
|
|
void SetProgress(float progress) { progress_ = progress; }
|
|
|
|
float GetProgress() const { return progress_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
float progress_;
|
|
|
|
};
|
|
|
|
|
2013-05-27 20:22:35 +00:00
|
|
|
|
|
|
|
|
2013-05-02 22:21:39 +00:00
|
|
|
// This tab strip is a little special.
|
|
|
|
/*
|
|
|
|
class TabStrip : public View {
|
|
|
|
public:
|
|
|
|
TabStrip();
|
|
|
|
|
|
|
|
virtual void Touch(const TouchInput &input);
|
|
|
|
virtual void Draw(DrawContext &dc);
|
|
|
|
|
|
|
|
void AddTab(const std::string &title, uint32_t color) {
|
|
|
|
Tab tab;
|
|
|
|
tab.title = title;
|
|
|
|
tab.color = color;
|
|
|
|
tabs_.push_back(tab);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
int selected_;
|
|
|
|
struct Tab {
|
|
|
|
std::string title;
|
|
|
|
uint32_t color;
|
|
|
|
};
|
|
|
|
std::vector<Tab> tabs_;
|
|
|
|
};*/
|
|
|
|
|
|
|
|
void MeasureBySpec(Size sz, float contentWidth, MeasureSpec spec, float *measured);
|
|
|
|
|
2013-06-27 14:20:18 +00:00
|
|
|
void EventTriggered(Event *e, EventParams params);
|
|
|
|
void DispatchEvents();
|
2013-08-12 21:07:27 +00:00
|
|
|
bool IsAcceptKeyCode(int keyCode);
|
|
|
|
bool IsEscapeKeyCode(int keyCode);
|
2013-06-27 14:20:18 +00:00
|
|
|
|
2013-06-02 03:06:40 +00:00
|
|
|
} // namespace
|