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:
commit
594506081a
13 changed files with 280 additions and 183 deletions
|
@ -1,61 +1,17 @@
|
|||
import 'package:angular/angular.dart';
|
||||
|
||||
import 'dart:html' as html;
|
||||
import 'package:rules_of_living/src/Engine.dart';
|
||||
import 'package:angular_components/angular_components.dart';
|
||||
import 'package:rules_of_living/components/controls_component.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(
|
||||
selector: 'my-app',
|
||||
templateUrl: "app_component.html",
|
||||
directives: [coreDirectives])
|
||||
class AppComponent implements OnInit {
|
||||
directives: [coreDirectives, MaterialButtonComponent, MaterialIconComponent, MaterialSliderComponent, HeaderComponent, SimulationComponent, ControlsComponent],
|
||||
providers: [materialProviders, ClassProvider(EngineService)],
|
||||
styleUrls: const ['package:angular_components/app_layout/layout.scss.css'],
|
||||
)
|
||||
class AppComponent {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
<h1>Cellular Automata</h1>
|
||||
<app_header></app_header>
|
||||
<div id="rules-input">
|
||||
Ruleset: <input type="text" title="ruleset" content="S23/B3">
|
||||
<i class="fas fa-paint-brush"></i>
|
||||
</div>
|
||||
<div id="output">
|
||||
<canvas #caCanvas width="500" height="500"></canvas>
|
||||
</div>
|
||||
<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 id="viewport">
|
||||
<gol-simulation></gol-simulation>
|
||||
<sim-controls></sim-controls>
|
||||
</div>
|
4
lib/components/controls_component.css
Normal file
4
lib/components/controls_component.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
material-slider {
|
||||
display: inline-block;
|
||||
width: 50px;
|
||||
}
|
44
lib/components/controls_component.dart
Normal file
44
lib/components/controls_component.dart
Normal 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();
|
||||
}
|
||||
}
|
14
lib/components/controls_component.html
Normal file
14
lib/components/controls_component.html
Normal 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>
|
13
lib/components/header_component.dart
Normal file
13
lib/components/header_component.dart
Normal 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 {
|
||||
|
||||
}
|
12
lib/components/header_component.html
Normal file
12
lib/components/header_component.html
Normal 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>
|
41
lib/components/simulation_component.dart
Normal file
41
lib/components/simulation_component.dart
Normal 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);
|
||||
}
|
||||
}
|
1
lib/components/simulation_component.html
Normal file
1
lib/components/simulation_component.html
Normal file
|
@ -0,0 +1 @@
|
|||
<div id="simulation"></div>
|
11
lib/service/engine_service.dart
Normal file
11
lib/service/engine_service.dart
Normal 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);
|
||||
}
|
|
@ -9,6 +9,7 @@ environment:
|
|||
|
||||
dependencies:
|
||||
angular: ^5.0.0-beta
|
||||
angular_components: ^0.9.0-beta
|
||||
|
||||
dev_dependencies:
|
||||
angular_test: ^2.0.0-beta
|
||||
|
|
|
@ -15,11 +15,15 @@
|
|||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<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="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">
|
||||
|
||||
<!-- 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>
|
||||
</head>
|
||||
|
||||
|
|
233
web/styles.css
233
web/styles.css
|
@ -1,117 +1,126 @@
|
|||
@import url(https://fonts.googleapis.com/css?family=Roboto);
|
||||
@import url(https://fonts.googleapis.com/css?family=Material+Icons);
|
||||
|
||||
/* Master Styles */
|
||||
h1 {
|
||||
color: #369;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 250%;
|
||||
}
|
||||
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;
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/*!* Master Styles *!*/
|
||||
/*h1 {*/
|
||||
/*color: #369;*/
|
||||
/*font-family: Arial, Helvetica, sans-serif;*/
|
||||
/*font-size: 250%;*/
|
||||
/*}*/
|
||||
/*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 *!*/
|
||||
/*.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;*/
|
||||
/*}*/
|
||||
|
|
Loading…
Reference in a new issue