123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- Namespace mojo.app
- #rem monkeydoc The View class.
- #end
- Class View
- #rem monkeydoc Invoked when a view becomes visible and active.
- #end
- Field Activated:Void()
- #rem monkeydoc Invoked when a view is no longer visible or active.
- #end
- Field Deactivated:Void()
- Method New()
-
- If Not _themeSeq
- _themeSeq=1
- App.ThemeChanged+=Lambda()
- _themeSeq+=1
- If _themeSeq=$40000000 _themeSeq=1
- End
- Endif
-
- _style=New Style( App.Theme.DefaultStyle )
-
- _styleSeq=_themeSeq
-
- InvalidateStyle()
- End
- #rem monkeydoc View visibility state.
- #end
- Property Visible:Bool()
-
- Return _visible
-
- Setter( visible:Bool )
- If visible=_visible Return
-
- _visible=visible
-
- RequestRender()
-
- UpdateActive()
- End
-
- #rem monkeydoc View enabled state.
- #end
- Property Enabled:Bool()
-
- Return _enabled And (Not _parent Or _parent.Enabled)
-
- Setter( enabled:Bool )
- If enabled=_enabled Return
-
- _enabled=enabled
-
- InvalidateStyle()
-
- UpdateActive()
- End
- #rem monkeydoc View active state.
-
- A view is active it is visible, enabled, attached to a window and all its parents are also active.
-
- Events are only sent to active windows.
-
- #end
- Property Active:Bool()
-
- Return _active
- End
-
- #rem monkeydoc Whether the view accepts key events.
- #end
- Property AcceptsKeyEvents:Bool()
-
- Return _acceptsKeyEvents
-
- Setter( acceptsKeyEvents:Bool )
-
- _acceptsKeyEvents=acceptsKeyEvents
- End
-
- #rem monkeydoc Whether the view accepts mouse events.
- #end
- Property AcceptsMouseEvents:Bool()
-
- Return _acceptsMouseEvents
-
- Setter( acceptsMouseEvents:Bool )
-
- _acceptsMouseEvents=acceptsMouseEvents
- End
-
- #rem monkeydoc View style.
- #end
- Property Style:Style()
-
- Return _style
-
- Setter( style:Style )
- If style=_style Return
-
- _style=style
-
- InvalidateStyle()
- End
-
- #rem monkeydoc View style state.
- #end
- Property StyleState:String()
-
- Return _styleState
-
- Setter( styleState:String )
- If styleState=_styleState Return
- _styleState=styleState
-
- InvalidateStyle()
- End
-
- #rem monkeydoc View render style.
-
- This is the style used to render the view, and is dependant on [[Style]] and [[StyleState]].
-
- #end
- Property RenderStyle:Style()
-
- ValidateStyle()
-
- Return _rstyle
- End
-
- #rem monkeydoc Layout mode.
-
- The following layout modes are supported
-
- | Layout mode | Description
- |:------------------|:-----------
- | "fill" | View is resized to fit its layout frame.
- | "float" | View floats within its layout frame according to the view [[Gravity]].
- | "fill-x" | View is resized on the x axis and floats on the y axis.
- | "fill-y" | View is resized on the y axis and floats on the x axis.
- | "stretch" | View is stretched non-uniformly to fit its layout frame.
- | "letterbox" | View is uniformly stretched on both axii and centered within its layout frame.
- | "letterbox-int" | View is uniformly stretched on both axii and centered within its layout frame. Scale factors are integrized.
- #end
- Property Layout:String()
- Return _layout
- Setter( layout:String )
- If layout=_layout Return
- _layout=layout
- End
- #rem monkeydoc View frame rect.
-
- The 'frame' the view is contained in.
-
- Note that the frame rect is in parent space coordinates, and is usually set by the parent view when layout occurs.
-
- #end
- Property Frame:Recti()
-
- Return _frame
-
- Setter( frame:Recti )
-
- _frame=frame
- End
-
- #rem monkeydoc Gravity for floating views.
-
- #end
- Property Gravity:Vec2f()
- Return _gravity
- Setter( gravity:Vec2f )
- If gravity=_gravity Return
- _gravity=gravity
- End
- #rem monkeydoc @hidden
- #end
- Property Offset:Vec2i()
-
- Return _offset
-
- Setter( offset:Vec2i )
- If offset=_offset Return
-
- _offset=offset
- End
-
- #rem monkeydoc Minimum view size.
- #end
- Property MinSize:Vec2i()
-
- Return _minSize
-
- Setter( minSize:Vec2i )
-
- _minSize=minSize
- End
-
- #rem monkeydoc Maximum view size.
- #end
- Property MaxSize:Vec2i()
-
- Return _maxSize
-
- Setter( maxSize:Vec2i )
-
- _maxSize=maxSize
- End
-
- #rem monkeydoc View content rect.
-
- The content rect represents the rendering area of the view.
-
- The content rect is in view local coordinates and its origin is always (0,0).
-
- #end
- Property Rect:Recti()
-
- Return _rect
- End
-
- #rem monkeydoc Width of the view content rect.
- #end
- Property Width:Int()
- Return _rect.Width
- End
-
- #rem monkeydoc Height of the view content rect.
- #end
- Property Height:Int()
-
- Return _rect.Height
- End
-
- #rem monkeydoc @hidden
- #end
- Property Bounds:Recti()
-
- Return _bounds
- End
-
- #rem monkeydoc Mouse location relative to the view.
- #end
- Property MouseLocation:Vec2i()
- Return TransformPointFromView( App.MouseLocation,Null )
- End
-
- #rem monkeydoc View clip rect.
-
- The clip rect represents the part of the content rect NOT obscured by an parent views.
-
- The clip rect is in view local coordinates.
-
- #end
- Property ClipRect:Recti()
-
- Return _clip
- End
-
- #rem monkeydoc @hidden
- #end
- Property RenderRect:Recti()
-
- Return _rclip
- End
-
- #rem monkeydoc @hidden
- #end
- Property RenderBounds:Recti()
-
- Return _rbounds
- End
-
- #rem monkeydoc @hidden
- #end
- Property LocalMatrix:AffineMat3f()
-
- Return _matrix
- End
-
- #rem monkeydoc @hidden
- #end
- Property RenderMatrix:AffineMat3f()
-
- Return _rmatrix
- End
-
- #rem monkeydoc The parent view of this view.
- #end
- Property Parent:View()
-
- Return _parent
- End
-
- #rem monkeydoc The Window this view is attached to, if any.
- #end
- Property Window:Window()
-
- Return _window
- End
-
- #rem monkeydoc Gets a style.
-
- This is a convenience method equivalent to App.Theme.GetStyle( name ).
-
- #end
- Method GetStyle:Style( name:String )
-
- Return App.Theme.GetStyle( name )
- End
-
- #rem monkeydoc Adds a child view to this view.
-
- AddChildView is normally used internally by 'layout' views. However you can also add a child view to any view directly by calling this method.
-
- If you use this method to add a child view to a view, it is your responsiblity to also manage the child view's frame using the [[Frame]] property.
- #end
- Method AddChildView( view:View )
-
- If Not view Return
-
- Assert( Not view._parent,"View already has a parent" )
- Assert( Not Cast<Window>( view ),"Windows cannot be child views" )
-
- view._parent=Self
- view.SetWindow( _window )
- _children.Add( view )
-
- RequestRender()
-
- view.UpdateActive()
- End
-
- #rem monkeydoc Removes a child view from this view.
- #end
- Method RemoveChildView( view:View )
-
- If Not view Return
-
- Assert( view._parent=Self,"View is not a child view" )
- view._parent=Null
- view.SetWindow( Null )
- _children.Remove( view )
-
- RequestRender()
-
- view.UpdateActive()
- End
-
- #rem monkeydoc @hidden
- #end
- Method FindViewAtWindowPoint:View( point:Vec2i )
-
- If Not _visible Return Null
-
- If Not _rbounds.Contains( point ) Return Null
-
- For Local i:=0 Until _children.Length
-
- Local child:=_children[_children.Length-i-1]
- Local view:=child.FindViewAtWindowPoint( point )
- If view Return view
-
- Next
-
- Return Self
- End
-
- #rem monkeydoc Transforms a point to another view.
-
- Transforms `point` in coordinates local to this view to coordinates local to `view`.
-
- @param point The point to transform.
-
- @param view View to transform point to.
-
- #end
- Method TransformPointToView:Vec2i( point:Vec2i,view:View )
-
- Local t:=_rmatrix * New Vec2f( point.x,point.y )
-
- If view t=-view._rmatrix * t
-
- Return New Vec2i( Round( t.x ),Round( t.y ) )
- End
-
- #rem monkeydoc Transforms a point from another view.
-
- Transforms `point` in coordinates local to 'view' to coordinates local to this view.
-
- @param point The point to transform.
-
- @param view View to transform point from.
-
- #end
- Method TransformPointFromView:Vec2i( point:Vec2i,view:View )
-
- Local t:=New Vec2f( point.x,point.y )
-
- If view t=view._matrix * t
-
- t=-_rmatrix * t
-
- Return New Vec2i( Round( t.x ),Round( t.y ) )
- End
-
- #rem monkeydoc Transforms a rect to another view.
-
- Transforms `rect` from coordinates local to this view to coordinates local to `view`.
-
- @param rect The rect to transform.
- @param view View to transform rect to.
-
- #end
- Method TransformRectToView:Recti( rect:Recti,view:View )
-
- Return New Recti( TransformPointToView( rect.min,view ),TransformPointToView( rect.max,view ) )
- End
-
- #rem monkeydoc Transforms a rect from another view.
-
- Transform `rect` from coordinates local to `view` to coordinates local to this view.
-
- @param rect The rect to transform.
-
- @param view The view to transform rect from.
-
- #end
- Method TransformRectFromView:Recti( rect:Recti,view:View )
-
- Return New Recti( TransformPointFromView( rect.min,view ),TransformPointFromView( rect.max,view ) )
- End
-
- #rem monkeydoc Transforms a point in window coordinates to view coordinates.
- Transforms `point` in window coordinates to coordinates local to this view.
-
- @param point The point to transform.
-
- @return The transformed point.
-
- #end
- Method TransformWindowPointToView:Vec2i( point:Vec2i )
-
- Local t:=-_rmatrix * New Vec2f( point.x,point.y )
-
- Return New Vec2i( Round( t.x ),Round( t.y ) )
- End
-
- #rem monkeydoc Makes this view the key view.
-
- The key view is the view that receives keyboard events.
-
- #end
- Method MakeKeyView()
- Local oldKeyView:=App.KeyView
- If oldKeyView=Self Return
-
- If Not Active Return
-
- App.KeyView=Self
-
- If oldKeyView oldKeyView.OnKeyViewChanged( oldKeyView,Self )
-
- OnKeyViewChanged( oldKeyView,Self )
- End
-
- #rem monkeydoc Sends a key event to the view.
- #end
- Method SendKeyEvent( event:KeyEvent )
-
- If _acceptsKeyEvents
-
- OnKeyEvent( event )
-
- If event.Eaten Return
- Endif
-
- If _parent _parent.SendKeyEvent( event )
- End
-
- #rem monkeydoc Sends a mouse event to the view.
- #end
- Method SendMouseEvent( event:MouseEvent )
-
- If _acceptsMouseEvents
-
- event=event.TransformToView( Self )
-
- OnMouseEvent( event )
-
- If event.Eaten Return
- Endif
-
- If _parent _parent.SendMouseEvent( event )
- End
-
- #rem monkeydoc Checks if the view is a child of another view.
- #end
- Method IsChildOf:Bool( view:View )
-
- If view=Self Return True
-
- If _parent Return _parent.IsChildOf( view )
-
- Return False
- End
-
- #rem monkeydoc @hidden
- #end
- Method RequestRender()
-
- App.RequestRender()
- End
- #rem monkeydoc @hidden
- #end
- Method InvalidateStyle()
-
- _styleSeq|=$40000000
-
- App.RequestRender()
- End
-
- #rem monkeydoc @hidden
- #end
- Method ValidateStyle()
-
- If _styleSeq=_themeSeq Return
-
- Local themeChanged:=(_styleSeq & $3fffffff<>_themeSeq)
-
- _styleSeq=_themeSeq
-
- _rstyle=_style
-
- If Enabled
- _rstyle=_style.GetState( _styleState )
- Else
- _rstyle=_style.GetState( "disabled" )
- Endif
-
- _styleBounds=_rstyle.Bounds
-
- If themeChanged OnThemeChanged()
-
- OnValidateStyle()
- End
-
- Method MeasureLayoutSize:Vec2i()
-
- Measure()
-
- Return _layoutSize
- End
-
- Protected
-
- #rem monkeydoc @hidden
- #end
- Method Measure()
- ' If Not _visible Return
-
- For Local view:=Eachin _children
- view.Measure()
- Next
-
- ValidateStyle()
-
- Local size:=OnMeasure()
-
- Local scale:=App.Theme.Scale
-
- If _minSize.x size.x=Max( size.x,Int( _minSize.x*scale.x ) )
- If _minSize.y size.y=Max( size.y,Int( _minSize.y*scale.y ) )
- If _maxSize.x size.x=Min( size.x,Int( _maxSize.x*scale.x ) )
- If _maxSize.y size.y=Min( size.y,Int( _maxSize.y*scale.y ) )
-
- _measuredSize=size
-
- _layoutSize=size+_styleBounds.Size
- End
-
- #rem monkeydoc @hidden
- #end
- Method UpdateLayout()
-
- _rect=New Recti( 0,0,_measuredSize )
-
- _bounds=_rect+_styleBounds
-
- _matrix=New AffineMat3f
-
- If _parent _matrix=_matrix.Translate( _frame.min.x,_frame.min.y )
-
- _matrix=_matrix.Translate( _offset.x,_offset.y )
-
- Select _layout
- Case "fill","resize"
-
- _rect=New Recti( 0,0,_frame.Size-_styleBounds.Size )
- _bounds=_rect+_styleBounds
-
- Case "fill-x"
-
- _rect.max.x=_frame.Width-_styleBounds.Width
-
- _bounds.min.x=_rect.min.x+_styleBounds.min.x
- _bounds.max.x=_rect.max.x+_styleBounds.max.x
-
- _matrix=_matrix.Translate( 0,(_frame.Height-_bounds.Height)*_gravity.y )
-
- Case "fill-y"
-
- _rect.max.y=_frame.Height-_styleBounds.Height
-
- _bounds.min.y=_rect.min.y+_styleBounds.min.y
- _bounds.max.y=_rect.max.y+_styleBounds.max.y
-
- _matrix=_matrix.Translate( (_frame.Width-_bounds.Width)*_gravity.x,0 )
-
- Case "float"
-
- _matrix=_matrix.Translate( (_frame.Width-_bounds.Width)*_gravity.x,(_frame.Height-_bounds.Height)*_gravity.y )
-
- _matrix.t.x=Round( _matrix.t.x )
- _matrix.t.y=Round( _matrix.t.y )
-
- Case "stretch"
-
- Local sx:=Float(_frame.Width)/_bounds.Width
- Local sy:=Float(_frame.Height)/_bounds.Height
- _matrix=_matrix.Scale( sx,sy )
- Case "stretch-int"
-
- Local sx:=Float(_frame.Width)/_bounds.Width
- Local sy:=Float(_frame.Height)/_bounds.Height
- If sx>1 sx=Floor( sx )
- If sy>1 sy=Floor( sy )
-
- _matrix=_matrix.Scale( sx,sy )
-
- Case "scale","letterbox"
-
- Local sx:=Float(_frame.Width)/_bounds.Width
- Local sy:=Float(_frame.Height)/_bounds.Height
-
- If sx<sy
- _matrix=_matrix.Translate( 0,(_frame.Height-_bounds.Height*sx)*_gravity.y )
- _matrix=_matrix.Scale( sx,sx )
- Else
- _matrix=_matrix.Translate( (_frame.Width-_bounds.Width*sy)*_gravity.x,0 )
- _matrix=_matrix.Scale( sy,sy )
- Endif
-
- Case "scale-int","letterbox-int"
-
- Local sx:=Float(_frame.Width)/_bounds.Width
- Local sy:=Float(_frame.Height)/_bounds.Height
-
- If sx>1 sx=Floor( sx )
- If sy>1 sy=Floor( sy )
-
- Local sc:=Min( sx,sy )
- _matrix=_matrix.Translate( (_frame.Width-_bounds.Width*sc)*_gravity.x,(_frame.Height-_bounds.Height*sc)*_gravity.y )
- _matrix=_matrix.Scale( sc,sc )
-
- End
-
- _matrix=_matrix.Translate( -_bounds.min.x,-_bounds.min.y )
-
- If _parent _rmatrix=_parent._rmatrix * _matrix Else _rmatrix=_matrix
-
- _rclip=TransformRecti( _rect,_rmatrix )
-
- _rbounds=TransformRecti( _bounds-_rstyle.Margin,_rmatrix )
-
- If _parent
- _rclip&=_parent._rclip
- _rbounds&=_parent._rclip
- _clip=TransformRecti( _rclip,-_rmatrix )
- Else
- _clip=_rclip
- End
-
- OnLayout()
-
- For Local view:=Eachin _children
- view.UpdateLayout()
- Next
- End
- #rem monkeydoc @hidden
- #end
- Method Render( canvas:Canvas )
-
- If Not _visible Return
-
- canvas.BeginRender( _bounds,_matrix )
-
- _rstyle.Render( canvas,New Recti( 0,0,_bounds.Size ) )
-
- canvas.Viewport=_rect
-
- OnRender( canvas )
- For Local view:=Eachin _children
- view.Render( canvas )
- Next
-
- canvas.EndRender()
- End
- Protected
-
- #rem monkeydoc Called during layout if theme has changed.
-
- This is called immediately before [[OnValidateStyle]] if the theme has changed.
- #end
- Method OnThemeChanged() Virtual
- End
-
- #rem monkeydoc Called during layout if [[Style]] or [[StyleState]] have changed.
- Views can use this method to cache [[RenderStyle]] properties if necessary.
-
- #end
- Method OnValidateStyle() Virtual
- End
-
- #rem monkeydoc Called during layout to measure the view.
-
- Overriding methods should return their preferred content size.
-
- #end
- Method OnMeasure:Vec2i() Virtual
- Return New Vec2i( 0,0 )
- End
-
- #rem monkeydoc Called during layout when the view needs to update its child views.
-
- Overriding methods should set the [[Frame]] property of any child views they are resposible for.
-
- #end
- Method OnLayout() Virtual
- End
-
- #rem monkeydoc Called when the view needs to render itself.
- #end
- Method OnRender( canvas:Canvas ) Virtual
- End
-
- #rem monkeydoc Called when the key view changes.
-
- This method is invoked on both the old key view and new key view when the key view changes.
-
- #end
- Method OnKeyViewChanged( oldKeyView:View,newKeyView:View ) Virtual
- End
-
- #rem monkeydoc Keyboard event handler.
-
- Called when a keyboard event is sent to this view.
-
- #end
- Method OnKeyEvent( event:KeyEvent ) Virtual
- End
-
- #rem monkeydoc Mouse event handler.
-
- Called when a mouse event is sent to this view.
-
- #end
- Method OnMouseEvent( event:MouseEvent ) Virtual
- End
-
- #rem monkeydoc The last size returned by OnMeasure.
- #end
- Property MeasuredSize:Vec2i()
-
- Return _measuredSize
- End
-
- #rem monkeydoc MeasuredSize plus the current [[RenderStyle]] bounds size.
-
- Use this instead of MeasuredSize when calculating layout size for child views.
-
- #end
- Property LayoutSize:Vec2i()
-
- Return _layoutSize
- End
-
- #rem monkeydoc The current [[RenderStyle]] bounds rect.
- #end
- Property StyleBounds:Recti()
-
- Return _styleBounds
- End
-
- '***** INTERNAL *****
-
- #rem monkeydoc @hidden
-
- For height-dependant-on-width views - clean me up!
-
- #end
- Method OnMeasure2:Vec2i( size:Vec2i ) Virtual
- Return New Vec2i( 0,0 )
- End
-
- #rem monkeydoc @hidden
-
- For height-dependant-on-width views - clean me up!
-
- #end
- Method Measure2:Vec2i( size:Vec2i )
- size=OnMeasure2( size-_styleBounds.Size )
- If size.x And size.y _layoutSize=size+_styleBounds.Size
- Return _layoutSize
- End
- #rem monkeydoc @hidden
- #end
- Method SetWindow( window:Window )
-
- _window=window
-
- For Local view:=Eachin _children
- view.SetWindow( window )
- Next
- End
-
- #rem monkeydoc @hidden
- #end
- Method UpdateActive()
-
- 'Note: views are activated top-down, deactivated bottom-up.
- '
- Local active:=_visible And _enabled And _window And (Not _parent Or _parent._active )
-
- Local changed:=active<>_active
-
- If changed
- _active=active
- If Not _active Deactivated()
- Endif
-
- For Local child:=Eachin _children
- child.UpdateActive()
- Next
-
- If changed And _active Activated()
- End
-
- Private
-
- Global _themeSeq:Int
-
- Field _styleSeq:Int=0
-
- Field _parent:View
- Field _window:Window
- Field _children:=New Stack<View>
-
- Field _visible:Bool=True
- Field _enabled:Bool=True
- Field _active:Bool=False
- Field _acceptsKeyEvents:Bool=True
- Field _acceptsMouseEvents:Bool=True
-
- Field _style:Style
- Field _styleState:String
-
- Field _layout:String="fill"
- Field _gravity:=New Vec2f( .5,.5 )
- Field _offset:=New Vec2i( 0,0 )
- Field _minSize:Vec2i
- Field _maxSize:Vec2i
-
- Field _frame:Recti
-
- 'After measuring...
- Field _rstyle:Style
- Field _styleBounds:Recti
- Field _measuredSize:Vec2i
- Field _layoutSize:Vec2i
-
- 'After layout..
- Field _rect:Recti
- Field _bounds:Recti
- Field _matrix:AffineMat3f
- Field _rmatrix:AffineMat3f
- Field _rbounds:Recti
- Field _rclip:Recti
- Field _clip:Recti
- End
|