2013-05-03 00:21:39 +02:00
# pragma once
2013-10-23 13:55:11 +02:00
// More traditional UI framework than ui/ui.h.
2013-05-03 00:21:39 +02: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 16:52:27 +02:00
# include <cmath>
2013-06-04 22:50:22 +10:00
# include <cstdio>
2016-10-12 11:32:24 +02:00
# include <functional>
# include <map>
2015-09-19 10:21:42 +02:00
# include <memory>
2016-10-12 11:32:24 +02:00
# include <string>
# include <vector>
2013-05-03 00:21:39 +02:00
2020-10-04 23:24:14 +02:00
# include "Common/Render/TextureAtlas.h"
2020-10-04 00:25:21 +02:00
# include "Common/Math/lin/matrix4x4.h"
# include "Common/Math/math_util.h"
# include "Common/Math/geom2d.h"
2023-05-26 18:40:13 +02:00
# include "Common/Input/KeyCodes.h"
2013-05-03 00:21:39 +02:00
2020-09-29 12:44:47 +02:00
# include "Common/Common.h"
2013-10-19 03:45:05 +10:00
# undef small
2013-07-08 12:34:39 +02:00
struct KeyInput ;
2013-05-03 00:21:39 +02:00
struct TouchInput ;
2013-08-12 23:07:27 +02:00
struct AxisInput ;
2013-05-03 00:21:39 +02:00
2020-02-29 21:51:14 +01:00
struct ImageID ;
2013-05-03 00:21:39 +02:00
class DrawBuffer ;
2013-06-08 22:41:17 +02:00
class Texture ;
2013-05-28 00:32:00 +02:00
class UIContext ;
2013-05-03 00:21:39 +02:00
2016-12-25 18:18:19 +01:00
namespace Draw {
2018-03-27 23:10:33 +02:00
class DrawContext ;
2016-12-25 20:54:37 +01:00
class Texture ;
2016-12-25 18:18:19 +01:00
}
2014-08-17 21:28:34 +02:00
2013-05-03 00:21:39 +02: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 12:40:57 +02:00
class View ;
2013-05-03 00:21:39 +02:00
enum DrawableType {
DRAW_NOTHING ,
DRAW_SOLID_COLOR ,
DRAW_4GRID ,
2013-06-08 22:41:17 +02:00
DRAW_STRETCH_IMAGE ,
2013-05-03 00:21:39 +02:00
} ;
2013-06-02 23:44:28 +02:00
enum Visibility {
V_VISIBLE ,
V_INVISIBLE , // Keeps position, not drawn or interacted with
V_GONE , // Does not participate in layout
} ;
2013-05-03 00:21:39 +02:00
struct Drawable {
2020-02-29 21:51:14 +01:00
Drawable ( ) : type ( DRAW_NOTHING ) , image ( ImageID : : invalid ( ) ) , color ( 0xFFFFFFFF ) { }
explicit Drawable ( uint32_t col ) : type ( DRAW_SOLID_COLOR ) , image ( ImageID : : invalid ( ) ) , color ( col ) { }
Drawable ( DrawableType t , ImageID img , uint32_t col = 0xFFFFFFFF ) : type ( t ) , image ( img ) , color ( col ) { }
2013-05-03 00:21:39 +02:00
DrawableType type ;
2020-02-29 21:51:14 +01:00
ImageID image ;
2013-06-08 22:41:17 +02:00
uint32_t color ;
2013-05-03 00:21:39 +02:00
} ;
struct Style {
2020-02-29 21:51:14 +01:00
Style ( ) : fgColor ( 0xFFFFFFFF ) , background ( 0xFF303030 ) , image ( ImageID : : invalid ( ) ) { }
2013-05-03 00:21:39 +02:00
uint32_t fgColor ;
2013-06-08 22:41:17 +02:00
Drawable background ;
2020-02-29 21:51:14 +01:00
ImageID image ; // where applicable.
2013-05-03 00:21:39 +02:00
} ;
2013-08-30 14:44:23 +02:00
struct FontStyle {
2021-10-16 16:47:24 -07:00
FontStyle ( ) { }
FontStyle ( FontID atlasFnt , const char * name , int size ) : atlasFont ( atlasFnt ) , fontName ( name ) , sizePts ( size ) { }
2013-08-30 14:44:23 +02:00
2021-10-16 16:47:24 -07:00
FontID atlasFont { nullptr } ;
2013-08-30 14:44:23 +02:00
// For native fonts:
std : : string fontName ;
2021-10-16 16:47:24 -07:00
int sizePts = 0 ;
int flags = 0 ;
2013-08-30 14:44:23 +02:00
} ;
2013-05-03 00:21:39 +02:00
// To use with an UI atlas.
struct Theme {
2013-08-30 14:44:23 +02:00
FontStyle uiFont ;
FontStyle uiFontSmall ;
FontStyle uiFontSmaller ;
2020-02-29 21:51:14 +01:00
ImageID checkOn ;
ImageID checkOff ;
ImageID sliderKnob ;
ImageID whiteImage ;
ImageID dropShadow4Grid ;
2013-05-25 12:40:57 +02:00
2013-06-08 22:41:17 +02:00
Style itemStyle ;
2013-05-25 16:52:27 +02:00
Style itemDownStyle ;
Style itemFocusedStyle ;
2013-08-16 16:47:25 +02:00
Style itemDisabledStyle ;
Style headerStyle ;
2017-03-26 08:57:04 -07:00
Style infoStyle ;
2013-08-14 23:29:27 +02:00
2017-03-26 08:57:04 -07:00
Style popupStyle ;
2022-02-18 21:02:07 +01:00
uint32_t backgroundColor ;
2013-05-25 12:40:57 +02: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 ,
2021-08-08 13:38:19 -07:00
FOCUS_FIRST ,
FOCUS_LAST ,
FOCUS_PREV_PAGE ,
FOCUS_NEXT_PAGE ,
2013-05-03 00:21:39 +02:00
} ;
2022-11-12 10:27:19 -08:00
typedef float Size ; // can also be WRAP_CONTENT or FILL_PARENT.
static constexpr Size WRAP_CONTENT = - 1.0f ;
static constexpr Size FILL_PARENT = - 2.0f ;
2013-05-03 00:21:39 +02:00
// 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 15:28:14 +01:00
G_CENTER = G_HCENTER | G_VCENTER ,
2013-05-03 00:21:39 +02:00
G_VERTMASK = 3 < < 2 ,
} ;
2021-09-27 17:42:47 -07:00
enum Borders {
BORDER_NONE = 0 ,
BORDER_TOP = 0x0001 ,
BORDER_LEFT = 0x0002 ,
BORDER_BOTTOM = 0x0004 ,
BORDER_RIGHT = 0x0008 ,
BORDER_HORIZ = BORDER_LEFT | BORDER_RIGHT ,
BORDER_VERT = BORDER_TOP | BORDER_BOTTOM ,
BORDER_ALL = BORDER_TOP | BORDER_LEFT | BORDER_BOTTOM | BORDER_RIGHT ,
} ;
enum class BorderStyle {
HEADER_FG ,
ITEM_DOWN_BG ,
} ;
2013-05-03 00:21:39 +02:00
enum Orientation {
ORIENT_HORIZONTAL ,
ORIENT_VERTICAL ,
} ;
2013-06-10 22:05:58 +02:00
inline Orientation Opposite ( Orientation o ) {
if ( o = = ORIENT_HORIZONTAL ) return ORIENT_VERTICAL ; else return ORIENT_HORIZONTAL ;
}
2013-07-15 19:56:36 +02: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 ;
2021-08-08 13:38:19 -07:00
case FOCUS_FIRST : return FOCUS_LAST ;
case FOCUS_LAST : return FOCUS_FIRST ;
case FOCUS_PREV_PAGE : return FOCUS_NEXT_PAGE ;
case FOCUS_NEXT_PAGE : return FOCUS_PREV_PAGE ;
2013-07-15 19:56:36 +02:00
}
2013-07-16 00:25:08 +02:00
return d ;
2013-07-15 19:56:36 +02:00
}
2013-05-03 00:21:39 +02:00
enum MeasureSpecType {
UNSPECIFIED ,
EXACTLY ,
AT_MOST ,
} ;
2013-10-13 20:33:42 +02:00
// I hope I can find a way to simplify this one day.
2013-05-03 00:21:39 +02:00
enum EventReturn {
2013-10-13 20:33:42 +02: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 20:49:10 +02: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-03 00:21:39 +02:00
} ;
2013-07-15 17:51:12 +02:00
enum FocusFlags {
FF_LOSTFOCUS = 1 ,
FF_GOTFOCUS = 2
} ;
2016-01-22 22:40:16 -08:00
enum PersistStatus {
PERSIST_SAVE ,
PERSIST_RESTORE ,
} ;
2013-05-03 00:21:39 +02:00
2016-01-22 22:40:16 -08:00
typedef std : : vector < int > PersistBuffer ;
typedef std : : map < std : : string , UI : : PersistBuffer > PersistMap ;
class ViewGroup ;
2013-05-03 00:21:39 +02: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 16:50:03 +01:00
float f ;
2013-06-10 22:05:58 +02:00
std : : string s ;
2013-05-03 00:21:39 +02:00
} ;
struct HandlerRegistration {
2013-06-02 22:25:57 +10:00
std : : function < EventReturn ( EventParams & ) > func ;
2013-05-03 00:21:39 +02:00
} ;
class Event {
public :
2013-06-27 16:20:18 +02:00
Event ( ) { }
2019-06-23 11:13:14 -07:00
~ Event ( ) ;
2013-05-03 00:21:39 +02:00
// Call this from input thread or whatever, it doesn't matter
2013-06-01 18:59:03 +02:00
void Trigger ( EventParams & e ) ;
2013-05-03 00:21:39 +02:00
// Call this from UI thread
2013-07-15 19:56:36 +02:00
EventReturn Dispatch ( EventParams & e ) ;
2013-05-03 00:21:39 +02:00
2013-06-09 11:18:57 +02:00
// This is suggested for use in most cases. Autobinds, allowing for neat syntax.
2013-12-06 16:44:39 +01:00
template < class T >
2013-06-09 12:40:53 +02:00
T * Handle ( T * thiz , EventReturn ( T : : * theCallback ) ( EventParams & e ) ) {
2016-10-12 11:32:24 +02:00
Add ( std : : bind ( theCallback , thiz , std : : placeholders : : _1 ) ) ;
2013-06-09 12:40:53 +02:00
return thiz ;
2013-06-04 23:53:41 +02:00
}
2013-06-09 11:18:57 +02:00
// Sometimes you have an already-bound function<>, just use this then.
2013-06-04 23:53:41 +02:00
void Add ( std : : function < EventReturn ( EventParams & ) > func ) ;
2013-06-09 11:18:57 +02:00
private :
2013-05-03 00:21:39 +02:00
std : : vector < HandlerRegistration > handlers_ ;
DISALLOW_COPY_AND_ASSIGN ( Event ) ;
} ;
struct Margins {
Margins ( ) : top ( 0 ) , bottom ( 0 ) , left ( 0 ) , right ( 0 ) { }
2013-08-20 00:34:54 +02: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 22:41:17 +02:00
2016-08-07 17:35:41 -07:00
int horiz ( ) const {
2016-08-07 11:56:08 -07:00
return left + right ;
}
2016-08-07 17:35:41 -07:00
int vert ( ) const {
2016-08-07 11:56:08 -07:00
return top + bottom ;
}
2022-12-08 00:01:46 +01:00
void SetAll ( float f ) {
int8_t i = ( int ) f ;
top = i ;
bottom = i ;
left = i ;
right = i ;
}
2016-08-07 11:56:08 -07:00
2013-08-20 00:34:54 +02:00
int8_t top ;
int8_t bottom ;
int8_t left ;
int8_t right ;
2013-05-03 00:21:39 +02:00
} ;
2016-08-07 11:39:15 -07: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-07 17:35:41 -07:00
float horiz ( ) const {
2016-08-07 11:39:15 -07:00
return left + right ;
}
2016-08-07 17:35:41 -07:00
float vert ( ) const {
2016-08-07 11:39:15 -07:00
return top + bottom ;
}
float top ;
float bottom ;
float left ;
float right ;
} ;
2013-06-09 13:01:36 +02:00
enum LayoutParamsType {
LP_PLAIN = 0 ,
LP_LINEAR = 1 ,
LP_ANCHOR = 2 ,
2021-08-29 14:10:14 -07:00
LP_GRID = 3 ,
2013-06-09 13:01:36 +02:00
} ;
2013-05-03 00:21:39 +02:00
// Need a virtual destructor so vtables are created, otherwise RTTI can't work
class LayoutParams {
public :
2013-06-09 13:01:36 +02:00
LayoutParams ( LayoutParamsType type = LP_PLAIN )
2013-06-11 20:33:41 +02:00
: width ( WRAP_CONTENT ) , height ( WRAP_CONTENT ) , type_ ( type ) { }
2013-06-09 13:01:36 +02:00
LayoutParams ( Size w , Size h , LayoutParamsType type = LP_PLAIN )
: width ( w ) , height ( h ) , type_ ( type ) { }
2013-05-03 00:21:39 +02:00
virtual ~ LayoutParams ( ) { }
Size width ;
Size height ;
2013-06-09 13:01:36 +02:00
// Fake RTTI
bool Is ( LayoutParamsType type ) const { return type_ = = type ; }
2015-12-22 20:07:37 -08: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 13:01:36 +02:00
private :
LayoutParamsType type_ ;
2013-05-03 00:21:39 +02:00
} ;
View * GetFocusedView ( ) ;
2017-12-03 10:40:09 -08:00
class Tween ;
2017-12-10 00:17:35 -08:00
class CallbackColorTween ;
2017-12-03 10:40:09 -08:00
2013-05-03 00:21:39 +02:00
class View {
public :
2022-12-15 09:30:47 +01:00
View ( LayoutParams * layoutParams = 0 ) : layoutParams_ ( layoutParams ) {
2013-05-03 00:21:39 +02:00
if ( ! layoutParams )
layoutParams_ . reset ( new LayoutParams ( ) ) ;
}
2013-10-13 20:33:42 +02:00
virtual ~ View ( ) ;
2013-05-03 00:21:39 +02: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 19:43:40 +02:00
// touch response from the frame rate. Same with Key and Axis.
2015-02-03 00:10:38 +01:00
virtual bool Key ( const KeyInput & input ) { return false ; }
2022-11-27 16:15:16 +01:00
virtual bool Touch ( const TouchInput & input ) { return true ; }
2013-08-12 23:07:27 +02:00
virtual void Axis ( const AxisInput & input ) { }
2017-12-03 10:40:09 -08:00
virtual void Update ( ) ;
2013-05-03 00:21:39 +02:00
2018-03-27 23:10:33 +02:00
virtual void DeviceLost ( ) { }
virtual void DeviceRestored ( Draw : : DrawContext * draw ) { }
2015-10-31 13:43:33 +01: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 ) ;
2021-02-21 12:42:56 -08:00
virtual std : : string DescribeLog ( ) const ;
2021-02-21 16:38:02 -08:00
// Accessible/searchable description.
virtual std : : string DescribeText ( ) const { return " " ; }
2015-10-31 13:43:33 +01:00
2013-07-15 17:51:12 +02:00
virtual void FocusChanged ( int focusFlags ) { }
2016-01-23 01:59:25 -08:00
virtual void PersistData ( PersistStatus status , std : : string anonId , PersistMap & storage ) ;
2013-07-15 17:51:12 +02:00
2013-05-03 00:21:39 +02:00
void Move ( Bounds bounds ) {
bounds_ = bounds ;
}
2013-11-04 13:34:15 +01:00
2013-05-03 00:21:39 +02:00
// Views don't do anything here in Layout, only containers implement this.
2013-05-28 00:32:00 +02:00
virtual void Measure ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert ) ;
2013-05-03 00:21:39 +02:00
virtual void Layout ( ) { }
2013-05-28 00:32:00 +02:00
virtual void Draw ( UIContext & dc ) { }
2013-05-03 00:21:39 +02: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-28 00:32:00 +02:00
virtual void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const ;
2016-08-07 13:34:47 -07:00
virtual void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const ;
2013-05-03 00:21:39 +02:00
// Called when the layout is done.
void SetBounds ( Bounds bounds ) { bounds_ = bounds ; }
virtual const LayoutParams * GetLayoutParams ( ) const { return layoutParams_ . get ( ) ; }
2013-06-08 22:41:17 +02:00
virtual void ReplaceLayoutParams ( LayoutParams * newLayoutParams ) { layoutParams_ . reset ( newLayoutParams ) ; }
2013-05-03 00:21:39 +02:00
const Bounds & GetBounds ( ) const { return bounds_ ; }
2014-03-03 12:33:57 +01:00
virtual bool SetFocus ( ) ;
2013-05-27 00:54:02 +02:00
2013-05-03 00:21:39 +02:00
virtual bool CanBeFocused ( ) const { return true ; }
2013-05-27 21:39:56 +02:00
virtual bool SubviewFocused ( View * view ) { return false ; }
2015-09-17 20:29:37 +02:00
2013-05-25 12:40:57 +02:00
bool HasFocus ( ) const {
2013-05-03 00:21:39 +02:00
return GetFocusedView ( ) = = this ;
}
2020-03-21 18:33:54 -07:00
void SetEnabled ( bool enabled ) {
enabledFunc_ = nullptr ;
enabledPtr_ = nullptr ;
enabled_ = enabled ;
enabledMeansDisabled_ = false ;
}
2013-10-29 10:11:41 +01:00
bool IsEnabled ( ) const {
2020-03-21 18:33:54 -07:00
if ( enabledFunc_ )
return enabledFunc_ ( ) ! = enabledMeansDisabled_ ;
2013-10-29 10:11:41 +01:00
if ( enabledPtr_ )
2014-07-08 23:37:51 -07:00
return * enabledPtr_ ! = enabledMeansDisabled_ ;
2020-03-21 18:33:54 -07:00
return enabled_ ! = enabledMeansDisabled_ ;
}
void SetEnabledFunc ( std : : function < bool ( ) > func ) {
enabledFunc_ = func ;
enabledPtr_ = nullptr ;
enabledMeansDisabled_ = false ;
}
void SetEnabledPtr ( bool * enabled ) {
enabledFunc_ = nullptr ;
enabledPtr_ = enabled ;
enabledMeansDisabled_ = false ;
}
void SetDisabledPtr ( bool * disabled ) {
enabledFunc_ = nullptr ;
enabledPtr_ = disabled ;
enabledMeansDisabled_ = true ;
2013-10-29 10:11:41 +01:00
}
2013-06-02 23:44:28 +02:00
2016-01-23 09:12:56 -08:00
virtual void SetVisibility ( Visibility visibility ) { visibility_ = visibility ; }
2013-06-02 23:44:28 +02:00
Visibility GetVisibility ( ) const { return visibility_ ; }
2013-06-01 18:59:03 +02:00
2013-06-08 22:41:17 +02:00
const std : : string & Tag ( ) const { return tag_ ; }
void SetTag ( const std : : string & str ) { tag_ = str ; }
2013-06-09 13:01:36 +02:00
// Fake RTTI
virtual bool IsViewGroup ( ) const { return false ; }
2021-08-08 14:46:05 -07:00
virtual bool ContainsSubview ( const View * view ) const { return false ; }
2013-06-09 13:01:36 +02:00
2022-12-10 21:02:44 -08:00
Point GetFocusPosition ( FocusDirection dir ) const ;
2013-07-15 19:56:36 +02:00
2017-12-03 10:40:09 -08:00
template < class T >
T * AddTween ( T * t ) {
tweens_ . push_back ( t ) ;
return t ;
}
2013-05-03 00:21:39 +02:00
protected :
// Inputs to layout
2015-09-19 10:21:42 +02:00
std : : unique_ptr < LayoutParams > layoutParams_ ;
2013-06-08 22:41:17 +02:00
std : : string tag_ ;
2022-12-15 09:30:47 +01:00
Visibility visibility_ = V_VISIBLE ;
2013-06-01 18:59:03 +02:00
2013-05-03 00:21:39 +02:00
// Results of measure pass. Set these in Measure.
2022-12-15 09:30:47 +01:00
float measuredWidth_ = 0.0f ;
float measuredHeight_ = 0.0f ;
2013-05-03 00:21:39 +02:00
// Outputs of layout. X/Y are absolute screen coordinates, hierarchy is "gone" here.
2022-12-15 09:30:47 +01:00
Bounds bounds_ { } ;
2013-05-03 00:21:39 +02:00
2017-12-03 10:40:09 -08:00
std : : vector < Tween * > tweens_ ;
2013-05-03 00:21:39 +02:00
private :
2020-03-21 18:33:54 -07:00
std : : function < bool ( ) > enabledFunc_ ;
2022-12-15 09:30:47 +01:00
bool * enabledPtr_ = nullptr ;
bool enabled_ = true ;
bool enabledMeansDisabled_ = false ;
2013-10-29 10:11:41 +01:00
2013-05-03 00:21:39 +02: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-03 00:10:38 +01:00
bool Key ( const KeyInput & input ) override { return false ; }
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & input ) override { return false ; }
2015-02-03 00:10:38 +01:00
bool CanBeFocused ( ) const override { return false ; }
2013-05-03 00:21:39 +02:00
} ;
// All these light up their background when touched, or have focus.
class Clickable : public View {
public :
2017-12-10 00:17:35 -08:00
Clickable ( LayoutParams * layoutParams ) ;
2013-05-03 00:21:39 +02:00
2015-02-03 00:10:38 +01:00
bool Key ( const KeyInput & input ) override ;
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & input ) override ;
2013-05-03 00:21:39 +02:00
2015-02-03 00:10:38 +01:00
void FocusChanged ( int focusFlags ) override ;
2013-07-15 17:51:12 +02:00
2013-05-03 00:21:39 +02: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 ( ) ;
2017-12-10 00:17:35 -08:00
void DrawBG ( UIContext & dc , const Style & style ) ;
2013-05-03 00:21:39 +02:00
2017-12-10 00:17:35 -08:00
CallbackColorTween * bgColor_ = nullptr ;
2017-12-10 12:21:57 -08:00
float bgColorLast_ = 0.0f ;
2017-12-10 00:17:35 -08:00
int downCountDown_ = 0 ;
bool dragging_ = false ;
bool down_ = false ;
2013-05-03 00:21:39 +02:00
} ;
2021-09-19 15:54:01 +02:00
// TODO: Very similar to Choice, should probably merge them.
// Right now more flexible image support though.
2013-05-03 00:21:39 +02:00
class Button : public Clickable {
public :
Button ( const std : : string & text , LayoutParams * layoutParams = 0 )
2020-02-29 21:51:14 +01:00
: Clickable ( layoutParams ) , text_ ( text ) , imageID_ ( ImageID : : invalid ( ) ) { }
2013-12-11 09:32:14 +01:00
Button ( const std : : string & text , ImageID imageID , LayoutParams * layoutParams = 0 )
: Clickable ( layoutParams ) , text_ ( text ) , imageID_ ( imageID ) { }
2013-08-27 19:43:40 +02:00
2020-08-03 11:58:55 +02:00
void Click ( ) override ;
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-06-27 16:20:18 +02:00
const std : : string & GetText ( ) const { return text_ ; }
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2018-06-02 16:32:04 -07:00
void SetPadding ( int w , int h ) {
paddingW_ = w ;
paddingH_ = h ;
}
2021-01-08 20:05:43 +01:00
void SetImageID ( ImageID imageID ) {
imageID_ = imageID ;
}
2021-02-21 18:48:01 -08:00
void SetIgnoreText ( bool ignore ) {
ignoreText_ = ignore ;
}
2020-08-30 17:50:42 +02:00
// Needed an extra small button...
void SetScale ( float f ) {
scale_ = f ;
}
2013-05-03 00:21:39 +02:00
private :
Style style_ ;
std : : string text_ ;
2013-12-11 09:32:14 +01:00
ImageID imageID_ ;
2018-06-02 16:32:04 -07:00
int paddingW_ = 16 ;
int paddingH_ = 8 ;
2020-08-30 17:50:42 +02:00
float scale_ = 1.0f ;
2021-02-21 18:48:01 -08:00
bool ignoreText_ = false ;
2013-05-03 00:21:39 +02:00
} ;
2021-09-19 15:54:01 +02:00
class RadioButton : public Clickable {
public :
RadioButton ( int * value , int thisButtonValue , const std : : string & text , LayoutParams * layoutParams = 0 )
: Clickable ( layoutParams ) , value_ ( value ) , thisButtonValue_ ( thisButtonValue ) , text_ ( text ) { }
void Click ( ) override ;
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
std : : string DescribeText ( ) const override ;
private :
int * value_ ;
int thisButtonValue_ ;
std : : string text_ ;
const float paddingW_ = 8 ;
const float paddingH_ = 4 ;
const float radioRadius_ = 16.0f ;
const float radioInnerRadius_ = 8.0f ;
} ;
2013-07-18 10:25:30 +02:00
class Slider : public Clickable {
public :
Slider ( int * value , int minValue , int maxValue , LayoutParams * layoutParams = 0 )
2016-09-05 16:14:01 -07:00
: Clickable ( layoutParams ) , value_ ( value ) , showPercent_ ( false ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , step_ ( 1 ) , repeat_ ( - 1 ) { }
2014-05-05 23:52:10 -04:00
2014-05-05 23:39:57 -04:00
Slider ( int * value , int minValue , int maxValue , int step = 1 , LayoutParams * layoutParams = 0 )
2016-09-05 16:14:01 -07:00
: Clickable ( layoutParams ) , value_ ( value ) , showPercent_ ( false ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , repeat_ ( - 1 ) {
2014-05-06 00:55:37 -04:00
step_ = step < = 0 ? 1 : step ;
2014-05-05 23:52:10 -04:00
}
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2015-02-03 00:10:38 +01:00
bool Key ( const KeyInput & input ) override ;
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & input ) override ;
2017-03-14 22:01:18 -07:00
void Update ( ) override ;
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-08-20 12:48:48 +02:00
void SetShowPercent ( bool s ) { showPercent_ = s ; }
2013-12-06 15:01:34 +01:00
// OK to call this from the outside after having modified *value_
2013-07-18 10:25:30 +02:00
void Clamp ( ) ;
2015-02-03 00:10:38 +01:00
2015-11-12 19:25:11 +01:00
Event OnChange ;
2013-12-06 15:01:34 +01:00
private :
2023-05-26 18:40:13 +02:00
bool ApplyKey ( InputKeyCode keyCode ) ;
2016-09-05 16:14:01 -07:00
2013-07-18 10:25:30 +02:00
int * value_ ;
2013-08-20 12:48:48 +02:00
bool showPercent_ ;
2013-07-18 10:25:30 +02:00
int minValue_ ;
int maxValue_ ;
2013-08-20 12:48:48 +02:00
float paddingLeft_ ;
float paddingRight_ ;
2014-05-06 00:55:37 -04:00
int step_ ;
2019-06-18 00:18:40 +02:00
int repeat_ = 0 ;
2023-05-26 18:40:13 +02:00
InputKeyCode repeatCode_ = NKCODE_UNKNOWN ;
2013-07-18 10:25:30 +02:00
} ;
2013-07-20 13:54:09 +02:00
class SliderFloat : public Clickable {
public :
SliderFloat ( float * value , float minValue , float maxValue , LayoutParams * layoutParams = 0 )
2016-09-05 16:14:01 -07:00
: Clickable ( layoutParams ) , value_ ( value ) , minValue_ ( minValue ) , maxValue_ ( maxValue ) , paddingLeft_ ( 5 ) , paddingRight_ ( 70 ) , repeat_ ( - 1 ) { }
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2015-02-03 00:10:38 +01:00
bool Key ( const KeyInput & input ) override ;
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & input ) override ;
2017-03-14 22:01:18 -07:00
void Update ( ) override ;
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-07-20 13:54:09 +02:00
2013-12-06 15:01:34 +01:00
// OK to call this from the outside after having modified *value_
2013-07-20 13:54:09 +02:00
void Clamp ( ) ;
2015-11-12 19:25:11 +01:00
Event OnChange ;
2013-12-06 15:01:34 +01:00
private :
2023-05-26 18:40:13 +02:00
bool ApplyKey ( InputKeyCode keyCode ) ;
2016-09-05 16:14:01 -07:00
2013-07-20 13:54:09 +02:00
float * value_ ;
float minValue_ ;
float maxValue_ ;
2013-08-20 12:48:48 +02:00
float paddingLeft_ ;
float paddingRight_ ;
2016-09-05 16:14:01 -07:00
int repeat_ ;
2023-05-26 18:40:13 +02:00
InputKeyCode repeatCode_ = NKCODE_UNKNOWN ;
2013-07-20 13:54:09 +02:00
} ;
2013-07-18 10:25:30 +02:00
2013-05-27 22:22:35 +02: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 :
2020-02-29 21:51:14 +01:00
TriggerButton ( uint32_t * bitField , uint32_t bit , ImageID imageBackground , ImageID imageForeground , LayoutParams * layoutParams )
2013-05-27 22:22:35 +02:00
: View ( layoutParams ) , down_ ( 0.0 ) , bitField_ ( bitField ) , bit_ ( bit ) , imageBackground_ ( imageBackground ) , imageForeground_ ( imageForeground ) { }
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & input ) override ;
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-27 22:22:35 +02:00
private :
int down_ ; // bitfield of pressed fingers, translates into bitField
uint32_t * bitField_ ;
uint32_t bit_ ;
2020-02-29 21:51:14 +01:00
ImageID imageBackground_ ;
ImageID imageForeground_ ;
2013-05-27 22:22:35 +02:00
} ;
// 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 12:40:57 +02:00
class Item : public InertView {
public :
2013-05-28 00:50:19 +02:00
Item ( LayoutParams * layoutParams ) ;
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-25 12:40:57 +02:00
} ;
class ClickableItem : public Clickable {
public :
2013-05-28 00:50:19 +02:00
ClickableItem ( LayoutParams * layoutParams ) ;
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-25 16:52:27 +02:00
// Draws the item background.
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2013-05-25 12:40:57 +02:00
} ;
2013-05-03 00:21:39 +02:00
// Use to trigger something or open a submenu screen.
2013-05-25 12:40:57 +02:00
class Choice : public ClickableItem {
2013-05-03 00:21:39 +02:00
public :
2017-12-10 00:17:35 -08:00
Choice ( const std : : string & text , LayoutParams * layoutParams = nullptr )
: Choice ( text , std : : string ( ) , false , layoutParams ) { }
2021-09-19 18:45:15 +02:00
Choice ( const std : : string & text , ImageID image , LayoutParams * layoutParams = nullptr )
: ClickableItem ( layoutParams ) , text_ ( text ) , image_ ( image ) { }
2017-12-10 00:17:35 -08:00
Choice ( const std : : string & text , const std : : string & smallText , bool selected = false , LayoutParams * layoutParams = nullptr )
2021-09-19 18:45:15 +02:00
: ClickableItem ( layoutParams ) , text_ ( text ) , smallText_ ( smallText ) , image_ ( ImageID : : invalid ( ) ) { }
2017-12-10 00:17:35 -08:00
Choice ( ImageID image , LayoutParams * layoutParams = nullptr )
2021-09-19 18:45:15 +02:00
: ClickableItem ( layoutParams ) , image_ ( image ) , rightIconImage_ ( ImageID : : invalid ( ) ) { }
2021-09-22 23:05:33 +02:00
Choice ( ImageID image , float imgScale , float imgRot , bool imgFlipH = false , LayoutParams * layoutParams = nullptr )
: ClickableItem ( layoutParams ) , image_ ( image ) , rightIconImage_ ( ImageID : : invalid ( ) ) , imgScale_ ( imgScale ) , imgRot_ ( imgRot ) , imgFlipH_ ( imgFlipH ) { }
2013-05-03 00:21:39 +02:00
2020-08-10 02:20:47 +00:00
void Click ( ) override ;
2016-08-07 17:35:41 -07:00
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2023-01-08 23:35:52 +01:00
void SetCentered ( bool c ) {
2013-08-30 22:42:02 +02:00
centered_ = c ;
}
2023-01-08 23:35:52 +01:00
void SetDrawTextFlags ( u32 flags ) {
drawTextFlags_ = flags ;
}
void SetIcon ( ImageID iconImage , float scale = 1.0f , float rot = 0.0f , bool flipH = false , bool keepColor = true ) {
2022-02-14 13:57:22 +01:00
rightIconKeepColor_ = keepColor ;
2021-09-22 23:05:33 +02:00
rightIconScale_ = scale ;
rightIconRot_ = rot ;
rightIconFlipH_ = flipH ;
2021-09-19 18:45:15 +02:00
rightIconImage_ = iconImage ;
2013-10-31 13:33:53 +01:00
}
2013-05-03 00:21:39 +02:00
2013-07-17 01:03:29 +02:00
protected :
2013-08-20 13:03:42 +02:00
// hackery
virtual bool IsSticky ( ) const { return false ; }
2013-05-03 00:21:39 +02:00
std : : string text_ ;
std : : string smallText_ ;
2021-09-19 18:45:15 +02:00
ImageID image_ ; // Centered if no text, on the left if text.
2021-09-22 23:05:33 +02:00
ImageID rightIconImage_ = ImageID : : invalid ( ) ; // Shows in the right.
2023-02-16 19:01:13 +01:00
float rightIconScale_ = 0.0f ;
float rightIconRot_ = 0.0f ;
bool rightIconFlipH_ = false ;
bool rightIconKeepColor_ = false ;
2016-08-07 11:39:15 -07:00
Padding textPadding_ ;
2021-09-19 18:45:15 +02:00
bool centered_ = false ;
2021-09-22 23:05:33 +02:00
float imgScale_ = 1.0f ;
float imgRot_ = 0.0f ;
bool imgFlipH_ = false ;
2023-01-08 23:35:52 +01:00
u32 drawTextFlags_ = 0 ;
2013-08-30 14:44:23 +02:00
2013-07-17 01:03:29 +02:00
private :
2021-09-19 18:45:15 +02:00
bool selected_ = false ;
2013-05-03 00:21:39 +02:00
} ;
2013-07-15 19:56:36 +02:00
// Different key handling.
class StickyChoice : public Choice {
public :
StickyChoice ( const std : : string & text , const std : : string & smallText = " " , LayoutParams * layoutParams = 0 )
2013-07-16 00:25:08 +02:00
: Choice ( text , smallText , false , layoutParams ) { }
2013-08-20 00:34:54 +02:00
StickyChoice ( ImageID buttonImage , LayoutParams * layoutParams = 0 )
: Choice ( buttonImage , layoutParams ) { }
2013-07-15 19:56:36 +02:00
2015-02-03 00:10:38 +01:00
bool Key ( const KeyInput & key ) override ;
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & touch ) override ;
2015-02-03 00:10:38 +01:00
void FocusChanged ( int focusFlags ) override ;
2013-12-06 16:44:39 +01:00
2013-08-17 12:06:08 +02:00
void Press ( ) { down_ = true ; dragging_ = false ; }
2013-07-15 19:56:36 +02:00
void Release ( ) { down_ = false ; dragging_ = false ; }
bool IsDown ( ) { return down_ ; }
2013-10-08 18:04:56 +05:30
2013-08-20 13:03:42 +02:00
protected :
// hackery
2015-09-17 20:29:37 +02:00
bool IsSticky ( ) const override { return true ; }
2013-07-15 19:56:36 +02:00
} ;
2013-05-25 12:40:57 +02:00
class InfoItem : public Item {
public :
2017-12-10 00:17:35 -08:00
InfoItem ( const std : : string & text , const std : : string & rightText , LayoutParams * layoutParams = nullptr ) ;
2013-05-25 12:40:57 +02:00
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2013-05-25 12:40:57 +02:00
2015-06-28 18:48:22 -07:00
// These are focusable so that long lists of them can be keyboard scrolled.
2015-04-03 11:14:21 +02:00
bool CanBeFocused ( ) const override { return true ; }
2015-07-05 18:45:23 +02:00
void SetText ( const std : : string & text ) {
text_ = text ;
}
2015-09-17 22:46:59 +02:00
const std : : string & GetText ( ) const {
return text_ ;
}
2015-07-05 18:45:23 +02:00
void SetRightText ( const std : : string & text ) {
rightText_ = text ;
}
2021-09-19 19:19:15 +02:00
void SetChoiceStyle ( bool choiceStyle ) {
choiceStyle_ = choiceStyle ;
}
2015-07-05 18:45:23 +02:00
2013-05-25 12:40:57 +02:00
private :
2017-12-10 00:17:35 -08:00
CallbackColorTween * bgColor_ = nullptr ;
CallbackColorTween * fgColor_ = nullptr ;
2013-05-25 12:40:57 +02:00
std : : string text_ ;
std : : string rightText_ ;
2021-09-19 19:19:15 +02:00
bool choiceStyle_ = false ;
2013-05-25 12:40:57 +02:00
} ;
2013-05-25 16:52:27 +02:00
class ItemHeader : public Item {
public :
2013-08-20 00:34:54 +02:00
ItemHeader ( const std : : string & text , LayoutParams * layoutParams = 0 ) ;
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2017-12-12 00:16:05 -08:00
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
2015-02-03 00:10:38 +01:00
2013-05-25 16:52:27 +02:00
private :
std : : string text_ ;
} ;
2013-08-14 23:29:27 +02: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-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2013-08-14 23:29:27 +02:00
private :
std : : string text_ ;
} ;
2013-05-25 15:12:46 +02:00
class CheckBox : public ClickableItem {
2013-05-03 00:21:39 +02:00
public :
2022-12-07 11:12:10 +01:00
CheckBox ( bool * toggle , const std : : string & text , const std : : string & smallText = " " , LayoutParams * layoutParams = nullptr )
2013-06-08 22:41:17 +02:00
: ClickableItem ( layoutParams ) , toggle_ ( toggle ) , text_ ( text ) , smallText_ ( smallText ) {
2013-06-04 23:53:41 +02:00
OnClick . Handle ( this , & CheckBox : : OnClicked ) ;
2013-05-25 12:40:57 +02:00
}
2013-05-03 00:21:39 +02:00
2022-12-07 11:12:10 +01:00
// Image-only "checkbox", lights up instead of showing a checkmark.
CheckBox ( bool * toggle , ImageID imageID , LayoutParams * layoutParams = nullptr )
: ClickableItem ( layoutParams ) , toggle_ ( toggle ) , imageID_ ( imageID ) {
OnClick . Handle ( this , & CheckBox : : OnClicked ) ;
}
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2016-08-07 17:35:41 -07:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2013-05-03 00:21:39 +02:00
2013-10-13 19:07:10 +02:00
EventReturn OnClicked ( EventParams & e ) ;
2013-10-27 10:58:16 +05:30
//allow external agents to toggle the checkbox
2019-02-03 14:02:47 -08:00
virtual void Toggle ( ) ;
virtual bool Toggled ( ) const ;
2023-07-16 17:34:56 +02:00
protected :
2013-05-25 12:40:57 +02:00
bool * toggle_ ;
2013-05-03 00:21:39 +02:00
std : : string text_ ;
std : : string smallText_ ;
2022-12-07 11:12:10 +01:00
ImageID imageID_ ;
2013-05-03 00:21:39 +02:00
} ;
2023-07-16 17:34:56 +02:00
class CollapsibleHeader : public CheckBox {
public :
CollapsibleHeader ( bool * toggle , const std : : string & text , LayoutParams * layoutParams = nullptr ) ;
void Draw ( UIContext & dc ) override ;
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
2023-07-23 11:04:42 +02:00
void SetHasSubitems ( bool hasSubItems ) { hasSubItems_ = hasSubItems ; }
private :
bool hasSubItems_ = true ;
2023-07-16 17:34:56 +02:00
} ;
2019-02-03 14:02:47 -08:00
class BitCheckBox : public CheckBox {
public :
BitCheckBox ( uint32_t * bitfield , uint32_t bit , const std : : string & text , const std : : string & smallText = " " , LayoutParams * layoutParams = nullptr )
: CheckBox ( nullptr , text , smallText , layoutParams ) , bitfield_ ( bitfield ) , bit_ ( bit ) {
}
2023-01-27 11:19:29 +03:00
2023-01-29 00:25:00 +01:00
BitCheckBox ( int * bitfield , int bit , const std : : string & text , const std : : string & smallText = " " , LayoutParams * layoutParams = nullptr ) : BitCheckBox ( ( uint32_t * ) bitfield , ( uint32_t ) bit , text , smallText , layoutParams ) { }
2019-02-03 14:02:47 -08:00
void Toggle ( ) override ;
bool Toggled ( ) const override ;
private :
uint32_t * bitfield_ ;
uint32_t bit_ ;
} ;
2013-05-25 12:40:57 +02:00
// These are for generic use.
class Spacer : public InertView {
public :
Spacer ( LayoutParams * layoutParams = 0 )
2013-08-20 12:27:42 +02:00
: InertView ( layoutParams ) , size_ ( 0.0f ) { }
Spacer ( float size , LayoutParams * layoutParams = 0 )
: InertView ( layoutParams ) , size_ ( size ) { }
2015-09-17 20:29:37 +02:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override {
2013-08-20 12:27:42 +02:00
w = size_ ; h = size_ ;
2013-05-25 12:40:57 +02:00
}
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override { }
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override { return " " ; }
2013-08-20 12:27:42 +02:00
private :
2021-09-27 17:42:47 -07:00
float size_ = 0.0f ;
} ;
class BorderView : public InertView {
public :
BorderView ( Borders borderFlags , BorderStyle style , float size = 2.0f , LayoutParams * layoutParams = nullptr )
: InertView ( layoutParams ) , borderFlags_ ( borderFlags ) , style_ ( style ) , size_ ( size ) {
}
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
std : : string DescribeText ( ) const override { return " " ; }
private :
Borders borderFlags_ ;
BorderStyle style_ ;
2013-08-20 12:27:42 +02:00
float size_ ;
2013-05-03 00:21:39 +02:00
} ;
class TextView : public InertView {
public :
2015-09-23 17:34:16 +02: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 12:51:57 +02:00
2013-08-30 14:44:23 +02:00
TextView ( const std : : string & text , int textAlign , bool small , LayoutParams * layoutParams = 0 )
2015-09-23 17:39:52 +02:00
: InertView ( layoutParams ) , text_ ( text ) , textAlign_ ( textAlign ) , textColor_ ( 0xFFFFFFFF ) , small_ ( small ) , shadow_ ( false ) , focusable_ ( false ) , clip_ ( true ) { }
2013-05-03 00:21:39 +02:00
2016-08-07 13:34:47 -07:00
void GetContentDimensionsBySpec ( const UIContext & dc , MeasureSpec horiz , MeasureSpec vert , float & w , float & h ) const override ;
2015-02-03 00:10:38 +01:00
void Draw ( UIContext & dc ) override ;
2013-06-20 21:51:42 +02:00
void SetText ( const std : : string & text ) { text_ = text ; }
2015-09-17 22:46:59 +02:00
const std : : string & GetText ( ) const { return text_ ; }
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override { return GetText ( ) ; }
2013-08-30 14:44:23 +02:00
void SetSmall ( bool small ) { small_ = small ; }
2017-03-26 08:57:04 -07:00
void SetTextColor ( uint32_t color ) { textColor_ = color ; hasTextColor_ = true ; }
2015-02-15 11:20:19 +01:00
void SetShadow ( bool shadow ) { shadow_ = shadow ; }
2015-04-03 11:14:21 +02:00
void SetFocusable ( bool focusable ) { focusable_ = focusable ; }
2015-09-23 17:34:16 +02:00
void SetClip ( bool clip ) { clip_ = clip ; }
2021-08-06 22:32:43 +02:00
void SetBullet ( bool bullet ) { bullet_ = bullet ; }
2023-01-31 21:26:12 +01:00
void SetPadding ( float pad ) { pad_ = pad ; }
2015-04-03 11:14:21 +02:00
bool CanBeFocused ( ) const override { return focusable_ ; }
2013-05-03 00:21:39 +02:00
private :
2013-06-01 18:59:03 +02:00
std : : string text_ ;
int textAlign_ ;
2015-01-05 01:19:49 +01:00
uint32_t textColor_ ;
2017-03-26 08:57:04 -07:00
bool hasTextColor_ = false ;
2013-08-30 20:18:16 +02:00
bool small_ ;
2015-02-15 11:20:19 +01:00
bool shadow_ ;
2015-04-03 11:14:21 +02:00
bool focusable_ ;
2015-09-23 17:34:16 +02:00
bool clip_ ;
2021-08-06 22:32:43 +02:00
bool bullet_ = false ;
2023-01-31 21:26:12 +01:00
float pad_ = 0.0f ;
2013-05-03 00:21:39 +02:00
} ;
2014-07-18 11:03:18 +02:00
class TextEdit : public View {
public :
2021-02-21 16:38:02 -08:00
TextEdit ( const std : : string & text , const std : : string & title , const std : : string & placeholderText , LayoutParams * layoutParams = nullptr ) ;
2017-10-24 23:05:21 +02:00
void SetText ( const std : : string & text ) { text_ = text ; scrollPos_ = 0 ; caret_ = ( int ) text_ . size ( ) ; }
2017-03-26 08:57:04 -07:00
void SetTextColor ( uint32_t color ) { textColor_ = color ; hasTextColor_ = true ; }
2014-07-18 11:03:18 +02:00
const std : : string & GetText ( ) const { return text_ ; }
2014-08-30 02:05:21 -07:00
void SetMaxLen ( size_t maxLen ) { maxLen_ = maxLen ; }
2017-11-22 22:14:06 +01:00
void SetTextAlign ( int align ) { align_ = align ; } // Only really useful for setting FLAG_DYNAMIC_ASCII
2014-07-18 11:03:18 +02:00
2023-08-23 21:01:00 +04:00
void FocusChanged ( int focusFlags ) override ;
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2015-02-03 00:10:38 +01:00
bool Key ( const KeyInput & key ) override ;
2022-11-27 16:15:16 +01:00
bool Touch ( const TouchInput & touch ) override ;
2014-07-18 11:03:18 +02:00
2014-11-16 16:44:07 +01:00
Event OnTextChange ;
2015-01-05 01:19:49 +01:00
Event OnEnter ;
2014-11-16 16:44:07 +01:00
2014-07-18 11:03:18 +02:00
private :
2014-07-21 11:59:05 +02:00
void InsertAtCaret ( const char * text ) ;
2014-07-18 11:03:18 +02:00
std : : string text_ ;
2021-02-21 16:38:02 -08:00
std : : string title_ ;
2014-07-22 22:16:09 +02:00
std : : string undo_ ;
2014-07-18 11:03:18 +02:00
std : : string placeholderText_ ;
2017-03-26 08:57:04 -07:00
uint32_t textColor_ ;
bool hasTextColor_ = false ;
2014-07-18 11:03:18 +02:00
int caret_ ;
2017-10-24 23:05:21 +02:00
int scrollPos_ = 0 ;
2014-08-30 02:05:21 -07:00
size_t maxLen_ ;
2017-03-26 08:57:04 -07:00
bool ctrlDown_ = false ; // TODO: Make some global mechanism for this.
2017-11-22 22:14:06 +01:00
int align_ = 0 ;
2014-07-18 11:03:18 +02:00
// TODO: Selections
} ;
2013-05-25 12:40:57 +02:00
enum ImageSizeMode {
IS_DEFAULT ,
2015-02-01 18:03:31 +01:00
IS_FIXED ,
2018-09-21 23:24:36 -07:00
IS_KEEP_ASPECT ,
2013-05-25 12:40:57 +02:00
} ;
2013-05-03 00:21:39 +02:00
class ImageView : public InertView {
public :
2021-02-21 16:38:02 -08:00
ImageView ( ImageID atlasImage , const std : : string & text , ImageSizeMode sizeMode , LayoutParams * layoutParams = 0 )
: InertView ( layoutParams ) , text_ ( text ) , atlasImage_ ( atlasImage ) , sizeMode_ ( sizeMode ) { }
2013-05-03 00:21:39 +02:00
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override { return text_ ; }
2013-05-03 00:21:39 +02:00
private :
2021-02-21 16:38:02 -08:00
std : : string text_ ;
2020-02-29 21:51:14 +01:00
ImageID atlasImage_ ;
2013-05-03 00:21:39 +02:00
ImageSizeMode sizeMode_ ;
} ;
2013-06-02 23:44:28 +02:00
class ProgressBar : public InertView {
public :
ProgressBar ( LayoutParams * layoutParams = 0 )
: InertView ( layoutParams ) , progress_ ( 0.0 ) { }
2015-02-03 00:10:38 +01:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override ;
2013-06-02 23:44:28 +02:00
2013-12-06 15:28:52 +01: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 23:44:28 +02:00
float GetProgress ( ) const { return progress_ ; }
private :
float progress_ ;
} ;
2018-02-08 12:02:44 +01:00
class Spinner : public InertView {
public :
2020-02-29 21:51:14 +01:00
Spinner ( const ImageID * images , int numImages , LayoutParams * layoutParams = 0 )
2018-02-08 12:02:44 +01:00
: InertView ( layoutParams ) , images_ ( images ) , numImages_ ( numImages ) {
}
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override ;
void Draw ( UIContext & dc ) override ;
2021-02-21 16:38:02 -08:00
std : : string DescribeText ( ) const override { return " " ; }
2018-02-08 12:02:44 +01:00
void SetColor ( uint32_t color ) { color_ = color ; }
private :
2020-02-29 21:51:14 +01:00
const ImageID * images_ ;
2018-02-08 12:02:44 +01:00
int numImages_ ;
uint32_t color_ = 0xFFFFFFFF ;
} ;
2013-05-03 00:21:39 +02:00
void MeasureBySpec ( Size sz , float contentWidth , MeasureSpec spec , float * measured ) ;
2023-07-07 15:23:19 +02:00
void ApplyBoundsBySpec ( Bounds & bounds , MeasureSpec horiz , MeasureSpec vert ) ;
2013-05-03 00:21:39 +02:00
2015-08-28 20:51:33 +02:00
bool IsDPadKey ( const KeyInput & key ) ;
2015-08-28 17:05:11 +02:00
bool IsAcceptKey ( const KeyInput & key ) ;
bool IsEscapeKey ( const KeyInput & key ) ;
bool IsTabLeftKey ( const KeyInput & key ) ;
bool IsTabRightKey ( const KeyInput & key ) ;
2013-06-27 16:20:18 +02:00
2013-06-02 13:06:40 +10:00
} // namespace