blob: f6152f87ee972745f41da060fc02abbf9211bf8f [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import '../logic/croupier.dart' as logic_croupier;
import '../logic/croupier_settings.dart' show CroupierSettings;
import '../logic/game/game.dart' as logic_game;
import '../sound/sound_assets.dart';
import '../styles/common.dart' as style;
import 'croupier_game_advertisement.dart'
show CroupierGameAdvertisementComponent;
import 'croupier_profile.dart' show CroupierProfileComponent;
import 'game.dart' as component_game;
GlobalObjectKey _gameKey = new GlobalObjectKey("CroupierGameKey");
GlobalObjectKey _gameArrangeKey = new GlobalObjectKey("CroupierGameArrangeKey");
class CroupierComponent extends StatefulWidget {
final logic_croupier.Croupier croupier;
final SoundAssets sounds;
CroupierComponent(this.croupier, this.sounds);
@override
CroupierComponentState createState() => new CroupierComponentState();
}
class CroupierComponentState extends State<CroupierComponent> {
VoidCallback makeSetStateCallback(logic_croupier.CroupierState s,
[var data = null]) {
return () => setState(() {
config.croupier.setState(s, data);
});
}
@override
Widget build(BuildContext context) {
switch (config.croupier.state) {
case logic_croupier.CroupierState.welcome:
// in which we show them a UI to start a new game, join a game, or change some settings.
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: new Column(children: [
new FlatButton(
child: new Text('Create Game', style: style.Text.titleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.chooseGame)),
new FlatButton(
child: new Text('Join Game', style: style.Text.titleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.joinGame)),
new FlatButton(
child: new Text('Resume Game', style: style.Text.titleStyle),
onPressed: config.croupier.settings.hasLastGame
? makeSetStateCallback(
logic_croupier.CroupierState.resumeGame,
config.croupier.settings.lastGameID)
: null),
new CroupierProfileComponent(
settings: config.croupier.settings,
width: style.Size.settingsWidth,
height: style.Size.settingsHeight)
]));
case logic_croupier.CroupierState.chooseGame:
// in which we let them pick a game out of the many possible games... There aren't that many.
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: new Column(children: [
new FlatButton(
child: new Text('Proto', style: style.Text.titleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.arrangePlayers,
logic_game.GameType.proto)),
new FlatButton(
child: new Text('Hearts', style: style.Text.titleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.arrangePlayers,
logic_game.GameType.hearts)),
new FlatButton(
child: new Text('Poker', style: style.Text.titleStyle)),
new FlatButton(
child: new Text('Solitaire', style: style.Text.titleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.arrangePlayers,
logic_game.GameType.solitaire)),
new FlatButton(
child: new Text('Back', style: style.Text.subtitleStyle),
onPressed: makeSetStateCallback(
logic_croupier.CroupierState.welcome))
]));
case logic_croupier.CroupierState.joinGame:
// A stateful view, showing the game ads discovered.
List<Widget> gameAdWidgets = new List<Widget>();
if (config.croupier.gamesFound.length == 0) {
gameAdWidgets.add(
new Text("Looking for Games...", style: style.Text.titleStyle));
} else {
gameAdWidgets
.add(new Text("Available Games", style: style.Text.titleStyle));
}
config.croupier.gamesFound
.forEach((String _, logic_game.GameStartData gsd) {
CroupierSettings cs = config.croupier.settingsEveryone[gsd.ownerID];
gameAdWidgets.add(new CroupierGameAdvertisementComponent(gsd,
onTap: makeSetStateCallback(
logic_croupier.CroupierState.arrangePlayers, gsd),
settings: cs));
});
gameAdWidgets.add(new FlatButton(
child: new Text('Back', style: style.Text.subtitleStyle),
onPressed:
makeSetStateCallback(logic_croupier.CroupierState.welcome)));
// in which players wait for game invitations to arrive.
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: new Column(children: gameAdWidgets));
case logic_croupier.CroupierState.arrangePlayers:
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: _buildArrangePlayers());
case logic_croupier.CroupierState.playGame:
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: component_game.createGameComponent(
config.croupier,
config.sounds,
makeSetStateCallback(logic_croupier.CroupierState.welcome),
width: ui.window.size.width,
height: ui.window.size.height - ui.window.padding.top,
key: _gameKey));
case logic_croupier.CroupierState.resumeGame:
return new Container(
padding: new EdgeInsets.only(top: ui.window.padding.top),
child: new Text("Resuming Game...", style: style.Text.titleStyle),
width: ui.window.size.width,
height: ui.window.size.height - ui.window.padding.top);
default:
assert(false);
return null;
}
}
// Show the player profiles. If needs arrangement, then the profile is only
// shown if the person has not sat down yet.
Widget _buildPlayerProfiles(bool needsArrangement) {
List<Widget> profileWidgets = new List<Widget>();
config.croupier.playersFound.forEach((int userID, int playerNumber) {
// Note: Even if cs is null, a placeholder will be shown instead.
CroupierSettings cs = config.croupier.settingsEveryone[userID];
bool isMe = config.croupier.settings.userID == userID;
Widget cpc = new Container(
decoration: isMe ? style.Box.liveNow : null,
child: new CroupierProfileComponent(
settings: cs,
height: style.Size.settingsHeight,
width: style.Size.settingsWidth));
// If the player profiles can be arranged, they should be draggable too.
if (needsArrangement) {
profileWidgets.add(new Draggable<CroupierSettings>(
child: cpc, feedback: cpc, data: cs));
} else {
profileWidgets.add(cpc);
}
});
if (needsArrangement) {
return new ScrollableViewport(
child: new Row(children: profileWidgets),
scrollDirection: Axis.horizontal);
}
return new MaxTileWidthGrid(
children: profileWidgets,
maxTileWidth: style.Size.settingsWidth,
columnSpacing: 0.0,
rowSpacing: 0.0);
}
Widget _buildArrangePlayers() {
List<Widget> allWidgets = new List<Widget>();
logic_game.GameArrangeData gad = config.croupier.game.gameArrangeData;
Iterable<int> playerNumbers = config.croupier.playersFound.values;
allWidgets.add(new Flexible(
flex: 0,
child: new Row(children: [
new Text("${config.croupier.game.gameTypeName}",
style: style.Text.hugeStyle)
], mainAxisAlignment: MainAxisAlignment.spaceAround)));
// Then show the profile widgets of those who have joined the game.
allWidgets.add(new Flexible(flex: 0, child: new Text("Player List")));
allWidgets.add(new Flexible(
flex: 1, child: _buildPlayerProfiles(gad.needsArrangement)));
if (gad.needsArrangement) {
// Games that need arrangement can show their game arrange component.
allWidgets.add(component_game.createGameArrangeComponent(config.croupier,
width: ui.window.size.width * 0.90,
height: ui.window.size.height * 0.50,
key: _gameArrangeKey));
}
// Allow games that can start with these players to begin.
// Debug Mode should also go through.
VoidCallback startCb;
if (gad.canStart(playerNumbers) || config.croupier.debugMode) {
startCb = () {
config.croupier.settingsManager
.setGameStatus(config.croupier.game.gameID, "RUNNING");
// Since playerNumber starts out as null, we should set it to -1 if
// the person pressed Start Game without sitting.
if (config.croupier.game.playerNumber == null) {
config.croupier.game.playerNumber = -1;
}
};
}
if (config.croupier.game.isCreator) {
allWidgets.add(new Flexible(
flex: 0,
child: new Row(children: [
new FlatButton(
child: new Text("Start Game", style: style.Text.hugeStyle),
onPressed: startCb,
color: style.theme.accentColor)
], mainAxisAlignment: MainAxisAlignment.spaceAround)));
}
allWidgets.add(new Flexible(
flex: 0,
child: new FlatButton(
child: new Text('Back'),
onPressed:
makeSetStateCallback(logic_croupier.CroupierState.welcome))));
return new Column(children: allWidgets);
}
}