Add super-basic sky widgets.

Eventually we'll want to replace these with something
fancier like polymer, but this exercise helped us
find several bugs in the engine as well as
removed one more blocker from using Sky to
replace mojo/views usage in mojo/examples.

R=esprehn@chromium.org
BUG=443439

Review URL: https://codereview.chromium.org/809233002
This commit is contained in:
Eric Seidel 2014-12-18 13:01:43 -08:00
parent 4e176ff90e
commit bdaf418370
5 changed files with 290 additions and 0 deletions

View File

@ -0,0 +1,56 @@
<!--
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-->
<sky>
<import src="/sky/framework/sky-element/sky-element.sky"/>
<import src="/sky/framework/sky-button/sky-button.sky"/>
<import src="/sky/framework/sky-box/sky-box.sky"/>
<import src="/sky/framework/sky-checkbox/sky-checkbox.sky"/>
<import src="/sky/framework/sky-radio/sky-radio.sky"/>
<sky-element name="widget-root">
<template>
<style>
div { display: paragraph; }
</style>
<sky-box title='Buttons'>
<sky-button id='button'>Button</sky-button>
<div>highlight: {{ myButton.highlight }}</div>
</sky-box>
<sky-box title='Checkboxes'>
<div><sky-checkbox id='checkbox' />Checkbox</div>
<div>highlight: {{ myCheckbox.highlight }}</div>
<div>checked: {{ myCheckbox.checked }}</div>
<div><sky-checkbox id='checkbox' checked='true'/>Checkbox, default checked.</div>
</sky-box>
<sky-box title='Radios'>
<sky-box title='Group One'>
<div><sky-radio group='foo'/>one</div>
<div><sky-radio group='foo' selected='true' />two</div>
<div><sky-radio group='foo'/>three</div>
</sky-box>
<sky-box title='Group Two'>
<div><sky-radio group='bar'/>A</div>
<div><sky-radio group='bar'/>B</div>
<div><sky-radio group='bar' selected='true' />C</div>
</sky-box>
</sky-box>
</template>
<script>
module.exports = class extends SkyElement {
attached() {
this.myButton = this.shadowRoot.getElementById('button');
this.myCheckbox = this.shadowRoot.getElementById('checkbox');
}
}.register();
</script>
</sky-element>
<widget-root />
</sky>

View File

@ -0,0 +1,33 @@
<!--
// Copyright 2014 The Chromium 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 src="/sky/framework/sky-element/sky-element.sky" as="SkyElement" />
<sky-element name="sky-box">
<template>
<style>
:host {
display: flex;
flex-direction: column;
border-radius: 4px;
border: 1px solid gray;
margin: 10px;
}
#title {
text-align: center;
font-size: 10px;
}
div {
flex: 1 100%;
}
</style>
<div id='title'>{{ title }}</div>
<div><content></content></div>
</template>
<script>
module.exports = class extends SkyElement {
}.register();
</script>
</sky-element>

View File

@ -0,0 +1,49 @@
<!--
// Copyright 2014 The Chromium 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 src="/sky/framework/sky-element/sky-element.sky" as="SkyElement" />
<sky-element name="sky-button">
<template>
<style>
:host {
display: inline-flex;
border-radius: 4px;
justify-content: center;
align-items: center;
border: 1px solid blue;
-webkit-user-select: none;
margin: 5px;
}
:host([highlight=true]) {
background-color: orange;
}
</style>
<content></content>
</template>
<script>
module.exports = class extends SkyElement {
created() {
this.tabIndex = 0; // Make focusable.
this.setHighlight(false);
this.addEventListener("mousedown", function() {
this.setHighlight(true);
});
this.addEventListener("mouseup", function() {
this.setHighlight(false);
});
this.addEventListener("mouseout", function() {
this.setHighlight(false);
});
}
setHighlight(newValue) {
// Set both a property and an attribute to keep both parents happy.
this.setAttribute('highlight', newValue);
this.highlight = newValue;
}
}.register();
</script>
</sky-element>

View File

@ -0,0 +1,49 @@
<!--
// Copyright 2014 The Chromium 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 src="/sky/framework/sky-button/sky-button.sky" as="SkyButton" />
<sky-element name="sky-checkbox">
<template>
<style>
:host {
display: inline-flex;
justify-content: center;
align-items: center;
-webkit-user-select: none;
width: 20px;
height: 20px;
border-radius: 4px;
border: 1px solid blue;
margin: 5px;
}
:host([highlight=true]) {
background-color: orange;
}
</style>
<template if="{{ checked }}">
<check>&check;</check>
</template>
</template>
<script>
module.exports = class extends SkyButton {
created() {
super.created();
this.setChecked(this.getAttribute('checked') == 'true');
this.addEventListener("mouseup", function() {
this.toggleChecked();
});
}
toggleChecked() {
this.setChecked(!this.checked);
}
setChecked(checked) {
this.checked = checked;
this.setAttribute('checked', checked);
}
}.register();
</script>
</sky-element>

View File

@ -0,0 +1,103 @@
<!--
// Copyright 2014 The Chromium 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 src="/sky/framework/sky-button/sky-button.sky" as="SkyButton" />
<sky-element name="sky-radio">
<template>
<style>
:host {
display: inline-block;
-webkit-user-select: none;
width: 14px;
height: 14px;
border-radius: 7px;
border: 1px solid blue;
margin: 0 5px;
}
:host([highlight=true]) box {
background-color: orange;
}
dot {
-webkit-user-select: none;
width: 10px;
height: 10px;
border-radius: 5px;
background-color: black;
margin: 2px;
}
</style>
<template if="{{ selected }}">
<dot />
</template>
</template>
<script>
const kControllerMap = new WeakMap();
class RadioGroupController {
static forRadio(radio) {
var scope = radio.ownerScope;
var controller = kControllerMap.get(scope);
if (!controller)
kControllerMap.set(scope, new RadioGroupController());
return kControllerMap.get(scope);
}
constructor() {
this.radios = new Set();
}
addRadio(radio) {
this.radios.add(radio);
// If this new radio is default-selected, take selection from the group.
if (radio.selected)
this.takeSelectionFromGroup(radio);
}
removeRadio(radio) {
this.radios.remove(radio);
}
takeSelectionFromGroup(selectedRadio) {
// Emtpy/null/undefined group means and isolated radio.
if (!selectedRadio.group)
return;
this.radios.forEach(function(radio) {
if (selectedRadio === radio)
return;
if (radio.group != selectedRadio.group)
return;
radio.setSelected(false);
})
}
};
module.exports = class extends SkyButton {
created() {
super.created();
this.setSelected(this.getAttribute('selected'));
this.group = this.getAttribute('group');
this.addEventListener("mouseup", function() {
this.setSelected(true);
});
this.cachedController = null;
}
attached() {
super.attached();
this.cachedController = RadioGroupController.forRadio(this);
this.cachedController.addRadio(this);
}
detached() {
super.detached();
this.cachedController.removeRadio(this);
}
setSelected(selected) {
if (selected == this.selected)
return;
this.setAttribute('selected', selected);
this.selected = selected;
if (selected && this.cachedController)
this.cachedController.takeSelectionFromGroup(this);
}
}.register();
</script>
</sky-element>