Merge branch '19-add-material-styling-to-app' into 'master'

Resolve "Add Material Styling to App"

Closes #19

See merge request marty.oehme/cellular-automata!5
This commit is contained in:
Marty 2018-08-23 07:43:18 +00:00
commit 594506081a
13 changed files with 280 additions and 183 deletions

View File

@ -1,61 +1,17 @@
import 'package:angular/angular.dart'; import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'dart:html' as html; import 'package:rules_of_living/components/controls_component.dart';
import 'package:rules_of_living/src/Engine.dart'; import 'package:rules_of_living/components/header_component.dart';
import 'package:rules_of_living/components/simulation_component.dart';
import 'package:rules_of_living/service/engine_service.dart';
@Component( @Component(
selector: 'my-app', selector: 'my-app',
templateUrl: "app_component.html", templateUrl: "app_component.html",
directives: [coreDirectives]) directives: [coreDirectives, MaterialButtonComponent, MaterialIconComponent, MaterialSliderComponent, HeaderComponent, SimulationComponent, ControlsComponent],
class AppComponent implements OnInit { providers: [materialProviders, ClassProvider(EngineService)],
styleUrls: const ['package:angular_components/app_layout/layout.scss.css'],
)
class AppComponent {
var name = "World"; var name = "World";
Engine engine;
@ViewChild("caCanvas")
html.CanvasElement canvas;
@override
void ngOnInit() {
canvas.context2D.setFillColorRgb(200, 0, 0);
canvas.context2D.fillRect(0, 0, canvas.width, canvas.height);
canvas.context2D.setFillColorRgb(0, 255, 0);
canvas.context2D.fillText('''
If you see this
the app is broken :(
''', canvas.width/2, canvas.height/2);
engine = new Engine(canvas);
html.window.animationFrame.then(animFrame);
}
void animFrame(num now) {
engine.process(now);
html.window.animationFrame.then(animFrame);
}
void onStartClicked() {
engine.running = !engine.running;
}
void onStepClicked() {
engine.step();
}
void onResetClicked() {
engine.reset();
}
void onRandomClicked() {
engine.running = false;
engine.addPattern();
}
void onEdgesClicked() {
engine.toggleEdgeRendering();
}
void onClearClicked() {
engine.clear();
}
} }

View File

@ -1,22 +1,9 @@
<h1>Cellular Automata</h1> <app_header></app_header>
<div id="rules-input"> <div id="rules-input">
Ruleset: <input type="text" title="ruleset" content="S23/B3"> Ruleset: <input type="text" title="ruleset" content="S23/B3">
<i class="fas fa-paint-brush"></i> <i class="fas fa-paint-brush"></i>
</div> </div>
<div id="output"> <div id="viewport">
<canvas #caCanvas width="500" height="500"></canvas> <gol-simulation></gol-simulation>
</div> <sim-controls></sim-controls>
<div id="controls">
<button id="run" (click)="onStartClicked()">
<span [ngSwitch]="engine.running">
<i *ngSwitchCase="false" class="fas fa-play"></i>
<i *ngSwitchCase="true" class="fas fa-stop"></i>
</span>
</button>
<button id="step" (click)="onStepClicked()"><i class="fas fa-step-forward"></i></button>
<button id="random" (click)="onRandomClicked()"><i class="fas fa-random"></i></button>
<button id="reset" (click)="onResetClicked()"><i class="fas fa-undo"></i></button>
<button id="clear" (click)="onClearClicked()"><i class="fas fa-trash-alt"></i></button>
<i class="fas fa-clock"> Speed:</i><input type="text" title="speed" value="1">
<button id="edges" (click)="onEdgesClicked()"><i class="fas fa-chess-board"></i> </button>
</div> </div>

View File

@ -0,0 +1,4 @@
material-slider {
display: inline-block;
width: 50px;
}

View File

@ -0,0 +1,44 @@
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
import 'package:rules_of_living/service/engine_service.dart';
import 'package:rules_of_living/src/Engine.dart';
@Component(
selector: 'sim-controls',
templateUrl: "controls_component.html",
directives: [coreDirectives, MaterialButtonComponent, MaterialIconComponent, MaterialSliderComponent],
providers: [],
styleUrls: const ["controls_component.css"],
)
class ControlsComponent {
final EngineService engineService;
int simSpeed = 5;
Engine get engine => engineService.engine;
ControlsComponent(this.engineService);
void onStartClicked() {
engine.running = !engine.running;
}
void onStepClicked() {
engine.step();
}
void onResetClicked() {
engine.reset();
}
void onRandomClicked() {
engine.running = false;
engine.addPattern();
}
void onEdgesClicked() {
engine.toggleEdgeRendering();
}
void onClearClicked() {
engine.clear();
}
}

View File

@ -0,0 +1,14 @@
<div id="controls">
<material-button id="run" (click)="onStartClicked()">
<span [ngSwitch]="engine.running">
<i *ngSwitchCase="false" class="fas fa-play"></i>
<i *ngSwitchCase="true" class="fas fa-stop"></i>
</span>
</material-button>
<material-button id="step" (click)="onStepClicked()"><i class="fas fa-step-forward"></i></material-button>
<material-button id="random" (click)="onRandomClicked()"><i class="fas fa-random"></i></material-button>
<material-button id="reset" (click)="onResetClicked()"><i class="fas fa-undo"></i></material-button>
<material-button id="clear" (click)="onClearClicked()"><i class="fas fa-trash-alt"></i></material-button>
<i class="fas fa-clock">{{simSpeed}}</i> <material-slider [max]="10" [min]="1" [(value)]="simSpeed" ></material-slider>
<material-button id="edges" (click)="onEdgesClicked()"><i class="fas fa-chess-board"></i> </material-button>
</div>

View File

@ -0,0 +1,13 @@
import 'package:angular/angular.dart';
import 'package:angular_components/angular_components.dart';
@Component(
selector: 'app_header',
templateUrl: "header_component.html",
directives: [coreDirectives, MaterialButtonComponent, MaterialIconComponent, MaterialSliderComponent],
providers: [],
styleUrls: const ['package:angular_components/app_layout/layout.scss.css'],
)
class HeaderComponent {
}

View File

@ -0,0 +1,12 @@
<header class="material-header">
<div class="material-header-row">
<material-button icon class="material-drawer-button">
<material-icon icon="menu"></material-icon>
</material-button>
<span class="material-header-title">Cellular Automata</span>
<div class="material-spacer"></div>
<nav class="material-navigation">
<a>Link 1</a>
</nav>
</div>
</header>

View File

@ -0,0 +1,41 @@
import 'dart:html' as html;
import 'package:angular/angular.dart';
import 'package:rules_of_living/service/engine_service.dart';
@Component(
selector: 'gol-simulation',
templateUrl: "simulation_component.html",
directives: [coreDirectives],
providers: [],
// styleUrls: const ['package:angular_components/app_layout/layout.scss.css'],
)
class SimulationComponent implements OnInit {
final EngineService engineService;
SimulationComponent(this.engineService);
@override
void ngOnInit() {
html.CanvasElement canvas = html.CanvasElement()..id = "simulation";
html.querySelector("#simulation")..append(canvas);
canvas.width = 500;
canvas.height= 500;
canvas.context2D.setFillColorRgb(200, 0, 0);
canvas.context2D.fillRect(0, 0, canvas.width, canvas.height);
canvas.context2D.setFillColorRgb(0, 255, 0);
canvas.context2D.fillText('''
If you see this\n
the app is broken :(
''', canvas.width/2-50, canvas.height/2);
engineService.create(canvas);
html.window.animationFrame.then(animFrame);
}
void animFrame(num now) {
engineService.engine.process(now);
html.window.animationFrame.then(animFrame);
}
}

View File

@ -0,0 +1 @@
<div id="simulation"></div>

View File

@ -0,0 +1,11 @@
import 'dart:html' as html;
import 'package:rules_of_living/src/Engine.dart';
class EngineService {
Engine _engine;
Engine get engine => _engine;
void create(html.CanvasElement canvas) => _engine = Engine(canvas);
}

View File

@ -9,6 +9,7 @@ environment:
dependencies: dependencies:
angular: ^5.0.0-beta angular: ^5.0.0-beta
angular_components: ^0.9.0-beta
dev_dependencies: dev_dependencies:
angular_test: ^2.0.0-beta angular_test: ^2.0.0-beta

View File

@ -15,11 +15,15 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/solid.css" integrity="sha384-TbilV5Lbhlwdyc4RuIV/JhD8NR+BfMrvz4BL5QFa2we1hQu6wvREr3v6XSRfCTRp" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/solid.css" integrity="sha384-TbilV5Lbhlwdyc4RuIV/JhD8NR+BfMrvz4BL5QFa2we1hQu6wvREr3v6XSRfCTRp" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/fontawesome.css" integrity="sha384-ozJwkrqb90Oa3ZNb+yKFW2lToAWYdTiF1vt8JiH5ptTGHTGcN7qdoR1F95e0kYyG" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/fontawesome.css" integrity="sha384-ozJwkrqb90Oa3ZNb+yKFW2lToAWYdTiF1vt8JiH5ptTGHTGcN7qdoR1F95e0kYyG" crossorigin="anonymous">
<!-- As per https://pub.dartlang.org/packages/angular_components/versions/0.9.0-beta#-readme-tab-#Required-Icon-Font -->
<script defer src="main.dart.js"></script> <script defer src="main.dart.js"></script>
</head> </head>

View File

@ -1,117 +1,126 @@
@import url(https://fonts.googleapis.com/css?family=Roboto); @import url(https://fonts.googleapis.com/css?family=Roboto);
@import url(https://fonts.googleapis.com/css?family=Material+Icons); @import url(https://fonts.googleapis.com/css?family=Material+Icons);
/* Master Styles */ html, body {
h1 { height: 100%;
color: #369; margin: 0;
font-family: Arial, Helvetica, sans-serif; padding: 0;
font-size: 250%; width: 100%;
} font-family: 'Roboto', sans-serif;
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
label {
padding-right: 0.5em;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.active {
color: #039be5;
} }
/* items class */ /*!* Master Styles *!*/
.items { /*h1 {*/
margin: 0 0 2em 0; /*color: #369;*/
list-style-type: none; /*font-family: Arial, Helvetica, sans-serif;*/
padding: 0; /*font-size: 250%;*/
width: 24em; /*}*/
} /*h2, h3 {*/
.items li { /*color: #444;*/
cursor: pointer; /*font-family: Arial, Helvetica, sans-serif;*/
position: relative; /*font-weight: lighter;*/
left: 0; /*}*/
background-color: #EEE; /*body {*/
margin: .5em; /*margin: 2em;*/
padding: .3em 0; /*}*/
height: 1.6em; /*body, input[text], button {*/
border-radius: 4px; /*color: #888;*/
} /*font-family: Cambria, Georgia;*/
.items li:hover { /*}*/
color: #607D8B; /*a {*/
background-color: #DDD; /*cursor: pointer;*/
left: .1em; /*cursor: hand;*/
} /*}*/
.items li.selected { /*button {*/
background-color: #CFD8DC; /*font-family: Arial;*/
color: white; /*background-color: #eee;*/
} /*border: none;*/
.items li.selected:hover { /*padding: 5px 10px;*/
background-color: #BBD8DC; /*border-radius: 4px;*/
} /*cursor: pointer;*/
.items .text { /*cursor: hand;*/
position: relative; /*}*/
top: -3px; /*button:hover {*/
} /*background-color: #cfd8dc;*/
.items .badge { /*}*/
display: inline-block; /*button:disabled {*/
font-size: small; /*background-color: #eee;*/
color: white; /*color: #aaa;*/
padding: 0.8em 0.7em 0 0.7em; /*cursor: auto;*/
background-color: #607D8B; /*}*/
line-height: 1em; /*label {*/
position: relative; /*padding-right: 0.5em;*/
left: -1px; /*}*/
top: -4px; /*!* Navigation link styles *!*/
height: 1.8em; /*nav a {*/
margin-right: .8em; /*padding: 5px 10px;*/
border-radius: 4px 0 0 4px; /*text-decoration: none;*/
} /*margin-right: 10px;*/
/* everywhere else */ /*margin-top: 10px;*/
* { /*display: inline-block;*/
font-family: Arial, Helvetica, sans-serif; /*background-color: #eee;*/
} /*border-radius: 4px;*/
/*}*/
/*nav a:visited, a:link {*/
/*color: #607D8B;*/
/*}*/
/*nav a:hover {*/
/*color: #039be5;*/
/*background-color: #CFD8DC;*/
/*}*/
/*nav a.active {*/
/*color: #039be5;*/
/*}*/
/*!* items class *!*/
/*.items {*/
/*margin: 0 0 2em 0;*/
/*list-style-type: none;*/
/*padding: 0;*/
/*width: 24em;*/
/*}*/
/*.items li {*/
/*cursor: pointer;*/
/*position: relative;*/
/*left: 0;*/
/*background-color: #EEE;*/
/*margin: .5em;*/
/*padding: .3em 0;*/
/*height: 1.6em;*/
/*border-radius: 4px;*/
/*}*/
/*.items li:hover {*/
/*color: #607D8B;*/
/*background-color: #DDD;*/
/*left: .1em;*/
/*}*/
/*.items li.selected {*/
/*background-color: #CFD8DC;*/
/*color: white;*/
/*}*/
/*.items li.selected:hover {*/
/*background-color: #BBD8DC;*/
/*}*/
/*.items .text {*/
/*position: relative;*/
/*top: -3px;*/
/*}*/
/*.items .badge {*/
/*display: inline-block;*/
/*font-size: small;*/
/*color: white;*/
/*padding: 0.8em 0.7em 0 0.7em;*/
/*background-color: #607D8B;*/
/*line-height: 1em;*/
/*position: relative;*/
/*left: -1px;*/
/*top: -4px;*/
/*height: 1.8em;*/
/*margin-right: .8em;*/
/*border-radius: 4px 0 0 4px;*/
/*}*/
/*!* everywhere else *!*/
/** {*/
/*font-family: Arial, Helvetica, sans-serif;*/
/*}*/