class ScreenView extends Lanes.Data.BasicModel session: screen: 'object' session: active: ['boolean', true, false] ui: 'state' derived: view: deps: ['screen'], fn: -> new @screen.viewModel( screen: this.screen, ui: @ui ) initialize: (options)-> super @screen=options.screen Lanes.Data.Screens.displaying.add( this ) this.active=true renderScreen: -> this.view.render() remove: -> Lanes.Data.Screens.displaying.remove( this ) class Screen extends Lanes.Data.BasicModel session: id: 'string' title: 'string' description: 'string' view: 'string' icon: 'string' group_id: 'string' files: 'array' loading: 'boolean' model: 'string' derived: model_type: deps: ['model'], fn: -> Lanes.Data[this.model] initialize: -> @views = [] _setDisplaying: (ui)-> @views.push( new ScreenView( screen: this, ui: ui ) ) display: (ui)-> @viewModel ||= Lanes.Screens[this.view] if @viewModel? this._setDisplaying(ui) else this.loading=true Lanes.lib.Loader(this.files) .then => @viewModel = Lanes.Screens[this.view] @_setDisplaying(ui) @loading=false .catch (failures)=> @loading=false Lanes.warn(failures) class ScreenViewSet extends Lanes.Data.BasicCollection model: ScreenView active: -> @findWhere( active: true ) initialize: (models, options={})-> this.on( 'change:active', this.onActiveChange ) remove: (model)-> index = this.indexOf(model) super if model.active && this.length this.at(_.min([index,this.length-1])).active = true model.active = false this onActiveChange: (changed,active)-> return unless active this.each (screen)-> screen.set( active: false ) unless screen == changed activateNext: -> this._moveActive(+1) activatePrev: -> this._moveActive(-1) _moveActive: (inc)-> return if this.length == 1 current = this.findIndexWhere( active: true ) return if current == -1 if inc>0 && current == this.length-1 current = -1 if inc<0 && current == 0 current = this.length this.at(current+inc).active = true class ScreenSet extends Lanes.Data.BasicCollection model: Screen register: (spec)-> addScreen: (screen)-> screen = this.add( screen ) screen.set(active:true) class MenuGroup extends Lanes.Data.BasicModel session: id: 'string' title: 'string' description: 'string' icon: 'string' active: ['boolean', true, false] screens: -> @avail ||= new Lanes.Data.SubCollection( Lanes.Data.Screens.all, { filter: (screen)=> screen.group_id == @id && Lanes.current_user.canRead(screen.model_type) watched: ['group_id'] }) class MenuGroupSet extends Lanes.Data.BasicCollection constructor: -> super model: MenuGroup available: -> @avail ||= new Lanes.Data.SubCollection(this, { filter: (mgs)=> mgs.screens().filter() mgs.screens().length > 0 }) Lanes.Data.Screens = { all: new ScreenSet displaying: new ScreenViewSet([],{ single_active_only: true }) groups: new MenuGroupSet available_groups: -> MenuGroupSet.where({ id: available.groupBy (screen)-> screen.group_id.keys }) register: (spec)-> this.all.add( spec ) }