2013-05-02 22:21:39 +00:00
# pragma once
2013-10-23 11:55:11 +00:00
// More traditional UI framework than ui/ui.h.
2013-05-02 22:21:39 +00:00
// 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-25 14:52:27 +00:00
# include <cmath>
2013-06-04 12:50:22 +00:00
# include <cstdio>
2016-10-12 09:32:24 +00:00
# include <functional>
# include <map>
2015-09-19 08:21:42 +00:00
# include <memory>
2016-10-12 09:32:24 +00:00
# include <string>
# include <vector>
2013-05-02 22:21:39 +00:00
2013-06-08 23:21:08 +00:00
# include "base/logging.h"
2013-05-02 22:21:39 +00:00
# include "base/basictypes.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-10-18 17:45:05 +00:00
# undef small
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-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
2016-12-25 17:18:19 +00:00
namespace Draw {
2016-12-25 19:54:37 +00:00
class Texture ;
2016-12-25 17:18:19 +00:00
}
2014-08-17 19:28:34 +00:00
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 ( ) ;
2014-07-23 19:39:44 +00:00
void SetFocusedView ( View * view , bool force = false ) ;
2013-05-25 10:40:57 +00:00
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 ;
2017-03-26 15:57:04 +00:00
Style infoStyle ;
2013-08-14 21:29:27 +00:00
Style popupTitle ;
2017-03-26 15:57:04 +00:00
Style popupStyle ;
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 ,
2014-12-31 14:28:14 +00:00
G_CENTER = G_HCENTER | G_VCENTER ,
2013-05-02 22:21:39 +00:00
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 ,
} ;
2013-10-13 18:33:42 +00:00
// I hope I can find a way to simplify this one day.
2013-05-02 22:21:39 +00:00
enum EventReturn {
2013-10-13 18:33:42 +00:00
EVENT_DONE , // Return this when no other view may process this event, for example if you changed the view hierarchy
EVENT_SKIPPED , // Return this if you ignored an event
2013-10-13 18:49:10 +00:00
EVENT_CONTINUE , // Return this if it's safe to send this event to further listeners. This should normally be the default choice but often EVENT_DONE is necessary.
2013-05-02 22:21:39 +00:00
} ;
2013-07-15 15:51:12 +00:00
enum FocusFlags {
FF_LOSTFOCUS = 1 ,
FF_GOTFOCUS = 2
} ;
2016-01-23 06:40:16 +00:00
enum PersistStatus {
PERSIST_SAVE ,
PERSIST_RESTORE ,
} ;
2013-05-02 22:21:39 +00:00
2016-01-23 06:40:16 +00:00
typedef std : : vector < int > PersistBuffer ;
typedef std : : map < std : : string , UI : : PersistBuffer > PersistMap ;
class ViewGroup ;
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 ;
} ;
// Should cover all bases.
struct EventParams {
View * v ;
uint32_t a , b , x , y ;
2013-12-02 15:50:03 +00:00
float f ;
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-12-06 15:44:39 +00:00
template < class T >
2013-06-09 10:40:53 +00:00
T * Handle ( T * thiz , EventReturn ( T : : * theCallback ) ( EventParams & e ) ) {
2016-10-12 09:32:24 +00:00
Add ( std : : bind ( theCallback , thiz , std : : placeholders : : _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_ ;
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
2016-08-08 00:35:41 +00:00
int horiz ( ) const {
2016-08-07 18:56:08 +00:00
return left + right ;
}
2016-08-08 00:35:41 +00:00
int vert ( ) const {
2016-08-07 18:56:08 +00:00
return top + bottom ;
}
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
} ;
2016-08-07 18:39:15 +00:00
struct Padding {
Padding ( ) : top ( 0 ) , bottom ( 0 ) , left ( 0 ) , right ( 0 ) { }
explicit Padding ( float all ) : top ( all ) , bottom ( all ) , left ( all ) , right ( all ) { }
Padding ( float horiz , float vert ) : top ( vert ) , bottom ( vert ) , left ( horiz ) , right ( horiz ) { }
Padding ( float l , float t , float r , float b ) : top ( t ) , bottom ( b ) , left ( l ) , right ( r ) { }
2016-08-08 00:35:41 +00:00
float horiz ( ) const {
2016-08-07 18:39:15 +00:00
return left + right ;
}
2016-08-08 00:35:41 +00:00
float vert ( ) const {
2016-08-07 18:39:15 +00:00
return top + bottom ;
}
float top ;
float bottom ;
float left ;
float right ;
} ;
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 ; }
2015-12-23 04:07:37 +00:00
template < typename T >
T * As ( ) {
if ( Is ( T : : StaticType ( ) ) ) {
return static_cast < T * > ( this ) ;
}
return nullptr ;
}
template < typename T >
const T * As ( ) const {
if ( Is ( T : : StaticType ( ) ) ) {
return static_cast < const T * > ( this ) ;
}
return nullptr ;
}
static LayoutParamsType StaticType ( ) {
return LP_PLAIN ;
}
2013-06-09 11:01:36 +00:00
private :
LayoutParamsType type_ ;
2013-05-02 22:21:39 +00:00
} ;
View * GetFocusedView ( ) ;
2017-12-03 18:40:09 +00:00
class Tween ;
2013-05-02 22:21:39 +00:00
class View {
public :
2014-07-09 06:37:51 +00:00
View ( LayoutParams * layoutParams = 0 ) : layoutParams_ ( layoutParams ) , visibility_ ( V_VISIBLE ) , measuredWidth_ ( 0 ) , measuredHeight_ ( 0 ) , enabledPtr_ ( 0 ) , enabled_ ( true ) , enabledMeansDisabled_ ( false ) {
2013-05-02 22:21:39 +00:00
if ( ! layoutParams )
layoutParams_ . reset ( new LayoutParams ( ) ) ;
}
2013-10-13 18:33:42 +00:00
virtual ~ View ( ) ;
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.
2015-02-02 23:10:38 +00:00
virtual bool Key ( const KeyInput & input ) { return false ; }
2013-08-27 17:43:40 +00:00
virtual void Touch ( const TouchInput & input ) { }
2013-08-12 21:07:27 +00:00
virtual void Axis ( const AxisInput & input ) { }
2017-12-03 18:40:09 +00:00
virtual void Update ( ) ;
2013-05-02 22:21:39 +00:00
2015-10-31 12:43:33 +00:00
// If this view covers these coordinates, it should add itself and its children to the list.
virtual void Query ( float x , float y , std : : vector < View * > & list ) ;
virtual std : : string Describe ( ) const ;
2013-07-15 15:51:12 +00:00
virtual void FocusChanged ( int focusFlags ) { }
2016-01-23 09:59:25 +00:00
virtual void PersistData ( PersistStatus status , std : : string anonId , PersistMap & storage ) ;
2013-07-15 15:51:12 +00:00
2013-05-02 22:21:39 +00:00
void Move ( Bounds bounds ) {
bounds_ = bounds ;
}
2013-11-04 12:34:15 +00:00
2013-05-02 22:21:39 +00:00
// 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 ;
2016-08-07 20:34:47 +00:00
virtual void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , 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_ ; }
2014-03-03 11:33:57 +00:00
virtual bool SetFocus ( ) ;
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 ; }
2015-09-17 18:29:37 +00:00
2013-05-25 10:40:57 +00:00
bool HasFocus ( ) const {
2013-05-02 22:21:39 +00:00
return GetFocusedView ( ) = = this ;
}
2014-07-09 06:37:51 +00:00
void SetEnabled ( bool enabled ) { enabled_ = enabled ; enabledMeansDisabled_ = false ; }
2013-10-29 09:11:41 +00:00
bool IsEnabled ( ) const {
if ( enabledPtr_ )
2014-07-09 06:37:51 +00:00
return * enabledPtr_ ! = enabledMeansDisabled_ ;
2013-10-29 09:11:41 +00:00
else
2014-07-09 06:37:51 +00:00
return enabled_ ! = enabledMeansDisabled_ ;
2013-10-29 09:11:41 +00:00
}
2014-07-09 06:37:51 +00:00
void SetEnabledPtr ( bool * enabled ) { enabledPtr_ = enabled ; enabledMeansDisabled_ = false ; }
void SetDisabledPtr ( bool * disabled ) { enabledPtr_ = disabled ; enabledMeansDisabled_ = true ; }
2013-06-02 21:44:28 +00:00
2016-01-23 17:12:56 +00:00
virtual void SetVisibility ( Visibility visibility ) { visibility_ = visibility ; }
2013-06-02 21:44:28 +00:00
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 ) ;
2017-12-03 18:40:09 +00:00
template < class T >
T * AddTween ( T * t ) {
tweens_ . push_back ( t ) ;
return t ;
}
2013-05-02 22:21:39 +00:00
protected :
// Inputs to layout
2015-09-19 08:21:42 +00:00
std : : unique_ptr < LayoutParams > layoutParams_ ;
2013-06-08 20:41:17 +00:00
std : : string tag_ ;
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_ ;
2017-12-03 18:40:09 +00:00
std : : vector < Tween * > tweens_ ;
2013-05-02 22:21:39 +00:00
private :
2013-10-29 09:11:41 +00:00
bool * enabledPtr_ ;
bool enabled_ ;
2014-07-09 06:37:51 +00:00
bool enabledMeansDisabled_ ;
2013-10-29 09:11:41 +00:00
2013-05-02 22:21:39 +00:00
DISALLOW_COPY_AND_ASSIGN ( View ) ;
} ;
// These don't do anything when touched.
class InertView : public View {
public :
InertView ( LayoutParams * layoutParams )
: View ( layoutParams ) { }
2015-02-02 23:10:38 +00:00
bool Key ( const KeyInput & input ) override { return false ; }
void Touch ( const TouchInput & input ) override { }
bool CanBeFocused ( ) const override { return false ; }
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
2015-02-02 23:10:38 +00:00
bool Key ( const KeyInput & input ) override ;
void Touch ( const TouchInput & input ) override ;
2013-05-02 22:21:39 +00:00
2015-02-02 23:10:38 +00:00
void FocusChanged ( int focusFlags ) override ;
2013-07-15 15:51:12 +00:00
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 )
2013-12-11 08:32:14 +00:00
: Clickable ( layoutParams ) , text_ ( text ) , imageID_ ( - 1 ) { }
Button ( ImageID imageID , LayoutParams * layoutParams = 0 )
: Clickable ( layoutParams ) , imageID_ ( imageID ) { }
Button ( const std : : string & text , ImageID imageID , LayoutParams * layoutParams = 0 )
: Clickable ( layoutParams ) , text_ ( text ) , imageID_ ( imageID ) { }
2013-08-27 17:43:40 +00:00
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
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-12-11 08:32:14 +00:00
ImageID imageID_ ;
2013-05-02 22:21:39 +00:00
} ;
2013-07-18 08:25:30 +00:00
class Slider : public Clickable {
public :
Slider ( int * value , int minValue , int maxValue , LayoutParams * layoutParams = 0 )
2016-09-05 23:14:01 +00:00
: Clickable ( layoutParams ) , value_ ( value ) , showPercent_ ( false ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , step_ ( 1 ) , repeat_ ( - 1 ) { }
2014-05-06 03:52:10 +00:00
2014-05-06 03:39:57 +00:00
Slider ( int * value , int minValue , int maxValue , int step = 1 , LayoutParams * layoutParams = 0 )
2016-09-05 23:14:01 +00:00
: Clickable ( layoutParams ) , value_ ( value ) , showPercent_ ( false ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , repeat_ ( - 1 ) {
2014-05-06 04:55:37 +00:00
step_ = step < = 0 ? 1 : step ;
2014-05-06 03:52:10 +00:00
}
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
bool Key ( const KeyInput & input ) override ;
void Touch ( const TouchInput & input ) override ;
2017-03-15 05:01:18 +00:00
void Update ( ) override ;
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-08-20 10:48:48 +00:00
void SetShowPercent ( bool s ) { showPercent_ = s ; }
2013-12-06 14:01:34 +00:00
// OK to call this from the outside after having modified *value_
2013-07-18 08:25:30 +00:00
void Clamp ( ) ;
2015-02-02 23:10:38 +00:00
2015-11-12 18:25:11 +00:00
Event OnChange ;
2013-12-06 14:01:34 +00:00
private :
2016-09-05 23:14:01 +00:00
bool ApplyKey ( int keyCode ) ;
2013-07-18 08:25:30 +00:00
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_ ;
2014-05-06 04:55:37 +00:00
int step_ ;
2016-09-05 23:14:01 +00:00
int repeat_ ;
int repeatCode_ ;
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 )
2016-09-05 23:14:01 +00:00
: Clickable ( layoutParams ) , value_ ( value ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , repeat_ ( - 1 ) { }
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
bool Key ( const KeyInput & input ) override ;
void Touch ( const TouchInput & input ) override ;
2017-03-15 05:01:18 +00:00
void Update ( ) override ;
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-07-20 11:54:09 +00:00
2013-12-06 14:01:34 +00:00
// OK to call this from the outside after having modified *value_
2013-07-20 11:54:09 +00:00
void Clamp ( ) ;
2015-11-12 18:25:11 +00:00
Event OnChange ;
2013-12-06 14:01:34 +00:00
private :
2016-09-05 23:14:01 +00:00
bool ApplyKey ( int keyCode ) ;
2013-07-20 11:54:09 +00:00
float * value_ ;
float minValue_ ;
float maxValue_ ;
2013-08-20 10:48:48 +00:00
float paddingLeft_ ;
float paddingRight_ ;
2016-09-05 23:14:01 +00:00
int repeat_ ;
int repeatCode_ ;
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 ) { }
2015-02-02 23:10:38 +00:00
void Touch ( const TouchInput & input ) override ;
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
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 ) ;
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-25 10:40:57 +00:00
} ;
class ClickableItem : public Clickable {
public :
2013-05-27 22:50:19 +00:00
ClickableItem ( LayoutParams * layoutParams ) ;
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-25 10:40:57 +00:00
2013-05-25 14:52:27 +00:00
// Draws the item background.
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
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-31 12:33:53 +00:00
: ClickableItem ( layoutParams ) , text_ ( text ) , smallText_ ( ) , atlasImage_ ( - 1 ) , iconImage_ ( - 1 ) , centered_ ( false ) , highlighted_ ( false ) , selected_ ( 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-31 12:33:53 +00:00
: ClickableItem ( layoutParams ) , text_ ( text ) , smallText_ ( smallText ) , atlasImage_ ( - 1 ) , iconImage_ ( - 1 ) , centered_ ( false ) , highlighted_ ( false ) , selected_ ( selected ) { }
2013-08-19 22:34:54 +00:00
Choice ( ImageID image , LayoutParams * layoutParams = 0 )
2013-10-31 12:33:53 +00:00
: ClickableItem ( layoutParams ) , atlasImage_ ( image ) , iconImage_ ( - 1 ) , centered_ ( false ) , highlighted_ ( false ) , selected_ ( false ) { }
2013-05-02 22:21:39 +00:00
2013-10-08 12:34:56 +00:00
virtual void HighlightChanged ( bool highlighted ) ;
2016-08-08 00:35:41 +00:00
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
2013-08-30 20:42:02 +00:00
virtual void SetCentered ( bool c ) {
centered_ = c ;
}
2013-10-31 12:33:53 +00:00
virtual void SetIcon ( ImageID iconImage ) {
iconImage_ = iconImage ;
}
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 ; }
2016-08-08 00:35:41 +00:00
virtual float CalculateTextScale ( const UIContext & dc , float availWidth ) const ;
2013-08-20 11:03:42 +00:00
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-10-31 12:33:53 +00:00
ImageID iconImage_ ; // Only applies for text, non-centered
2016-08-07 18:39:15 +00:00
Padding textPadding_ ;
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
2015-02-02 23:10:38 +00:00
bool Key ( const KeyInput & key ) override ;
void Touch ( const TouchInput & touch ) override ;
void FocusChanged ( int focusFlags ) override ;
2013-12-06 15:44:39 +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
2015-09-17 18:29:37 +00:00
bool IsSticky ( ) const override { 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 ) { }
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
2013-05-25 10:40:57 +00:00
2015-06-29 01:48:22 +00:00
// These are focusable so that long lists of them can be keyboard scrolled.
2015-04-03 09:14:21 +00:00
bool CanBeFocused ( ) const override { return true ; }
2015-07-05 16:45:23 +00:00
void SetText ( const std : : string & text ) {
text_ = text ;
}
2015-09-17 20:46:59 +00:00
const std : : string & GetText ( ) const {
return text_ ;
}
2015-07-05 16:45:23 +00:00
void SetRightText ( const std : : string & text ) {
rightText_ = text ;
}
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 ) ;
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
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 ;
}
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
2013-08-14 21:29:27 +00:00
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
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
2016-08-08 00:35:41 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-02 22:21:39 +00:00
2013-10-13 17:07:10 +00:00
EventReturn OnClicked ( EventParams & e ) ;
2013-10-27 05:28:16 +00:00
//allow external agents to toggle the checkbox
void Toggle ( ) ;
2013-05-02 22:21:39 +00:00
private :
2016-08-08 00:35:41 +00:00
float CalculateTextScale ( const UIContext & dc , float availWidth ) const ;
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 ) { }
2015-09-17 18:29:37 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override {
2013-08-20 10:27:42 +00:00
w = size_ ; h = size_ ;
2013-05-25 10:40:57 +00:00
}
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override { }
2013-08-20 10:27:42 +00:00
private :
float size_ ;
2013-05-02 22:21:39 +00:00
} ;
class TextView : public InertView {
public :
2015-09-23 15:34:16 +00:00
TextView ( const std : : string & text , LayoutParams * layoutParams = 0 )
: InertView ( layoutParams ) , text_ ( text ) , textAlign_ ( 0 ) , textColor_ ( 0xFFFFFFFF ) , small_ ( false ) , shadow_ ( false ) , focusable_ ( false ) , clip_ ( true ) { }
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 )
2015-09-23 15:39:52 +00:00
: InertView ( layoutParams ) , text_ ( text ) , textAlign_ ( textAlign ) , textColor_ ( 0xFFFFFFFF ) , small_ ( small ) , shadow_ ( false ) , focusable_ ( false ) , clip_ ( true ) { }
2013-05-02 22:21:39 +00:00
2016-08-07 20:34:47 +00:00
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
2015-02-02 23:10:38 +00:00
void Draw ( UIContext & dc ) override ;
2013-06-20 19:51:42 +00:00
void SetText ( const std : : string & text ) { text_ = text ; }
2015-09-17 20:46:59 +00:00
const std : : string & GetText ( ) const { return text_ ; }
2013-08-30 12:44:23 +00:00
void SetSmall ( bool small ) { small_ = small ; }
2017-03-26 15:57:04 +00:00
void SetTextColor ( uint32_t color ) { textColor_ = color ; hasTextColor_ = true ; }
2015-02-15 10:20:19 +00:00
void SetShadow ( bool shadow ) { shadow_ = shadow ; }
2015-04-03 09:14:21 +00:00
void SetFocusable ( bool focusable ) { focusable_ = focusable ; }
2015-09-23 15:34:16 +00:00
void SetClip ( bool clip ) { clip_ = clip ; }
2015-04-03 09:14:21 +00:00
bool CanBeFocused ( ) const override { return focusable_ ; }
2013-05-02 22:21:39 +00:00
private :
2013-06-01 16:59:03 +00:00
std : : string text_ ;
int textAlign_ ;
2015-01-05 00:19:49 +00:00
uint32_t textColor_ ;
2017-03-26 15:57:04 +00:00
bool hasTextColor_ = false ;
2013-08-30 18:18:16 +00:00
bool small_ ;
2015-02-15 10:20:19 +00:00
bool shadow_ ;
2015-04-03 09:14:21 +00:00
bool focusable_ ;
2015-09-23 15:34:16 +00:00
bool clip_ ;
2013-05-02 22:21:39 +00:00
} ;
2014-07-18 09:03:18 +00:00
class TextEdit : public View {
public :
TextEdit ( const std : : string & text , const std : : string & placeholderText , LayoutParams * layoutParams = 0 ) ;
2017-10-24 21:05:21 +00:00
void SetText ( const std : : string & text ) { text_ = text ; scrollPos_ = 0 ; caret_ = ( int ) text_ . size ( ) ; }
2017-03-26 15:57:04 +00:00
void SetTextColor ( uint32_t color ) { textColor_ = color ; hasTextColor_ = true ; }
2014-07-18 09:03:18 +00:00
const std : : string & GetText ( ) const { return text_ ; }
2014-08-30 09:05:21 +00:00
void SetMaxLen ( size_t maxLen ) { maxLen_ = maxLen ; }
2017-11-22 21:14:06 +00:00
void SetTextAlign ( int align ) { align_ = align ; } // Only really useful for setting FLAG_DYNAMIC_ASCII
2014-07-18 09:03:18 +00:00
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
bool Key ( const KeyInput & key ) override ;
void Touch ( const TouchInput & touch ) override ;
2014-07-18 09:03:18 +00:00
2014-11-16 15:44:07 +00:00
Event OnTextChange ;
2015-01-05 00:19:49 +00:00
Event OnEnter ;
2014-11-16 15:44:07 +00:00
2014-07-18 09:03:18 +00:00
private :
2014-07-21 09:59:05 +00:00
void InsertAtCaret ( const char * text ) ;
2014-07-18 09:03:18 +00:00
std : : string text_ ;
2014-07-22 20:16:09 +00:00
std : : string undo_ ;
2014-07-18 09:03:18 +00:00
std : : string placeholderText_ ;
2017-03-26 15:57:04 +00:00
uint32_t textColor_ ;
bool hasTextColor_ = false ;
2014-07-18 09:03:18 +00:00
int caret_ ;
2017-10-24 21:05:21 +00:00
int scrollPos_ = 0 ;
2014-08-30 09:05:21 +00:00
size_t maxLen_ ;
2017-03-26 15:57:04 +00:00
bool ctrlDown_ = false ; // TODO: Make some global mechanism for this.
2017-11-22 21:14:06 +00:00
int align_ = 0 ;
2014-07-18 09:03:18 +00:00
// TODO: Selections
} ;
2013-05-25 10:40:57 +00:00
enum ImageSizeMode {
IS_DEFAULT ,
2015-02-01 17:03:31 +00:00
IS_FIXED ,
2013-05-25 10:40:57 +00:00
} ;
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 ) { }
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2013-05-02 22:21:39 +00:00
private :
int atlasImage_ ;
ImageSizeMode sizeMode_ ;
} ;
2014-08-17 19:28:34 +00:00
// TextureView takes a texture that is assumed to be alive during the lifetime
// of the view.
2017-01-30 13:33:38 +00:00
class TextureView : public InertView {
2014-08-17 19:28:34 +00:00
public :
2017-01-30 13:33:38 +00:00
TextureView ( Draw : : Texture * texture , ImageSizeMode sizeMode , LayoutParams * layoutParams = 0 )
2015-06-12 10:38:48 +00:00
: InertView ( layoutParams ) , texture_ ( texture ) , color_ ( 0xFFFFFFFF ) , sizeMode_ ( sizeMode ) { }
2014-08-17 19:28:34 +00:00
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2014-08-17 19:28:34 +00:00
2016-12-25 19:54:37 +00:00
void SetTexture ( Draw : : Texture * texture ) { texture_ = texture ; }
2014-08-17 19:28:34 +00:00
void SetColor ( uint32_t color ) { color_ = color ; }
private :
2016-12-25 19:54:37 +00:00
Draw : : Texture * texture_ ;
2014-08-17 19:28:34 +00:00
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 ) { }
2015-02-02 23:10:38 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2013-06-02 21:44:28 +00:00
2013-12-06 14:28:52 +00:00
void SetProgress ( float progress ) {
if ( progress > 1.0f ) {
progress_ = 1.0f ;
} else if ( progress < 0.0f ) {
progress_ = 0.0f ;
} else {
progress_ = progress ;
}
}
2013-06-02 21:44:28 +00:00
float GetProgress ( ) const { return progress_ ; }
private :
float progress_ ;
} ;
2013-05-02 22:21:39 +00:00
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 ( ) ;
2015-08-28 18:51:33 +00:00
bool IsDPadKey ( const KeyInput & key ) ;
2015-08-28 15:05:11 +00:00
bool IsAcceptKey ( const KeyInput & key ) ;
bool IsEscapeKey ( const KeyInput & key ) ;
bool IsTabLeftKey ( const KeyInput & key ) ;
bool IsTabRightKey ( const KeyInput & key ) ;
2013-06-27 14:20:18 +00:00
2013-06-02 03:06:40 +00:00
} // namespace