Split plugin editor into separate element.

Also fixed card flip effect.
This commit is contained in:
Oliver Hamlet
2014-11-14 09:58:32 +00:00
parent 0155d57861
commit 8dc14d8dd1
4 changed files with 514 additions and 452 deletions
+2 -1
View File
@@ -45,7 +45,8 @@ div[drawer] {
z-index: 1;
}
#main {
overflow: auto;
overflow-y: auto;
overflow-x: hidden;
position: relative;
z-index: 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,492 @@
<!-- Fires the following events:
loot-editor-close
detail: boolean
True if the editor was closed using the Apply button.
--->
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/core-toolbar/core-toolbar.html">
<link rel="import" href="../bower_components/core-tooltip/core-tooltip.html">
<link rel="import" href="../bower_components/core-icon/core-icon.html">
<link rel="import" href="../bower_components/core-icons/core-icons.html">
<link rel="import" href="../bower_components/paper-checkbox/paper-checkbox.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
<link rel="import" href="../bower_components/paper-input/paper-input-decorator.html">
<link rel="import" href="../bower_components/paper-tabs/paper-tabs.html">
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/core-animated-pages/core-animated-pages.html">
<link rel="import" href="../bower_components/core-animated-pages/transitions/slide-from-right.html">
<link rel="import" href="editable-table.html">
<polymer-element name="loot-plugin-editor">
<template>
<style>
/* Icon styling. */
:host-context(loot-plugin-card[data-active=false]) #activeTick {
visibility: hidden;
}
:host-context(loot-plugin-card[data-bsa=false]) #loadsBSA {
display: none;
}
:host-context(loot-plugin-card[data-dummy=false]) #dummyPlugin {
display: none;
}
#activeTick {
color: green;
}
/* Content styling. */
::content .version, .version {
display: inline-block;
margin-left: 1em;
color:#6394F8;
}
::content .crc, .crc {
display: inline-block;
margin-left: 1em;
color:#BC8923;
}
::content .hidden, .hidden {
display: none;
}
/* Editor input styling. */
#editor > div > paper-checkbox, #editor > div > core-tooltip {
display: table;
}
#enableEdits {
margin-bottom: 1em;
}
#priorityValue {
margin-left: 0.5em;
}
input[readonly] {
border: none;
-webkit-user-select: none;
}
input:invalid {
background-color: pink;
color: white;
}
/* Table styling. */
table {
margin: 0;
border-collapse: collapse;
width: 100%;
}
td input {
width: 100%;
text-overflow: ellipsis;
}
td:last-child {
cursor: pointer;
}
td:last-child:hover {
color: red;
}
td, th {
vertical-align: top;
text-align: left;
padding: 0.5em;
}
th {
border-bottom: 1px black solid;
}
tbody tr:last-child {
cursor: pointer;
color: grey;
}
tbody tr:last-child:hover {
color: black;
}
/* Misc Styling. */
core-toolbar {
background: white;
}
#buttons {
text-align: right;
}
main {
padding: 1em;
}
</style>
<core-toolbar>
<core-tooltip id="activeTick" label="Active Plugin">
<core-icon icon="check"></core-icon>
</core-tooltip>
<content select="h1"></content>
<content select=".version"></content>
<span flex><content select=".crc"></content></span>
<core-tooltip id="dummyPlugin" label="Dummy Plugin">
<core-icon icon="visibility-off"></core-icon>
</core-tooltip>
<core-tooltip id="loadsBSA" label="Loads BSA">
<core-icon icon="attachment"></core-icon>
</core-tooltip>
</core-toolbar>
<main>
<paper-checkbox id="enableEdits" label="Enable Edits"></paper-checkbox>
<core-tooltip label="Global priorities are compared against all other plugins. Normal priorities are compared against only conflicting plugins." position="right">
<paper-checkbox id="globalPriority" label="Global Priority"></paper-checkbox>
</core-tooltip>
<div horizontal layout center>
<div>Priority Value</div>
<paper-input-decorator>
<input id="priorityValue" is="core-input" type="number" max="999999" min="-999999" step="1" value="0" preventInvalidInput>
</paper-input-decorator>
</div>
<div id="tableTabs">
<paper-tabs selected="loadAfter" valueattr="data-for" scrollable>
<paper-tab data-for="loadAfter">Load After</paper-tab>
<paper-tab data-for="req">Requirements</paper-tab>
<paper-tab data-for="inc">Incompatibilities</paper-tab>
<paper-tab data-for="message">Messages</paper-tab>
<paper-tab data-for="tags">Bash Tags</paper-tab>
<paper-tab data-for="dirty">Dirty Info</paper-tab>
<paper-tab data-for="locations">Locations</paper-tab>
</paper-tabs>
<core-animated-pages selected="loadAfter" valueattr="id" transitions="slide-from-right">
<table is="editable-table" id="loadAfter" data-template="fileRow">
<thead>
<tr><th>Filename</th><th>Display Name</th><th>Condition</th><th></th></tr>
</thead>
<tbody>
<!-- File rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="req" data-template="fileRow">
<thead>
<tr><th>Filename</th><th>Display Name</th><th>Condition</th><th></th></tr>
</thead>
<tbody>
<!-- File rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="inc" data-template="fileRow">
<thead>
<tr><th>Filename</th><th>Display Name</th><th>Condition</th><th></th></tr>
</thead>
<tbody>
<!-- File rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="message" data-template="messageRow">
<thead>
<tr><th>Type</th><th>Content</th><th>Condition</th><th>Language</th><th></th></tr>
</thead>
<tbody>
<!-- Message rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="tags" data-template="tagRow">
<thead>
<tr><th>Add/Remove</th><th>Bash Tag</th><th>Condition</th><th></th></tr>
</thead>
<tbody>
<!-- Bash Tag rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="dirty" data-template="dirtyInfoRow">
<thead>
<tr><th>CRC</th><th>ITM Count</th><th>Deleted References</th><th>Deleted Navmeshes</th><th>Cleaning Utility</th><th></th></tr>
</thead>
<tbody>
<!-- Dirty info rows go here. -->
<tr><td colspan="4">Add new row...</td><td></td></tr>
</tbody>
</table>
<table is="editable-table" id="locations" data-template="locationRow">
<thead>
<tr><th>URL</th><th>Version</th><th></th></tr>
</thead>
<tbody>
<!-- Location rows go here. -->
<tr><td colspan="3">Add new row...</td><td></td></tr>
</tbody>
</table>
</core-animated-pages>
</div>
<div id="buttons">
<paper-button id="accept">Apply</paper-button>
<paper-button id="cancel">Cancel</paper-button>
</div>
</main>
</template>
<script>
Polymer({
attached: function() {
this.shadowRoot.getElementById('tableTabs').firstElementChild.addEventListener('core-select', this.onShowEditorTable, false);
this.shadowRoot.getElementById('accept').addEventListener('click', this.onHideEditor, false);
this.shadowRoot.getElementById('cancel').addEventListener('click', this.onHideEditor, false);
},
detached: function() {
this.shadowRoot.getElementById('tableTabs').firstElementChild.removeEventListener('core-select', this.onShowEditorTable, false);
this.shadowRoot.getElementById('accept').removeEventListener('click', this.onHideEditor, false);
this.shadowRoot.getElementById('cancel').removeEventListener('click', this.onHideEditor, false);
},
onShowEditorTable: function(evt) {
evt.target.nextElementSibling.selected = evt.target.selected;
},
readFromEditor: function(oldData) {
/* Need to turn all the editor controls' values into data to
process. The control values can be compared with the existing
values to determine what's been changed, and masterlist rows in
the tables can be ignored because they're immutable. */
var plugin = {
name: this.getElementsByTagName('h1')[0].textContent,
userlist: {},
};
if (oldData.id == this.id) {
/* If either of the priority values have been changed, the
base priority value they're derived from will have
changed, so record both. */
if (this.shadowRoot.getElementById('globalPriority').checked != oldData.isGlobalPriority
|| this.shadowRoot.getElementById('priorityValue').value != oldData.modPriority) {
plugin.isGlobalPriority = this.shadowRoot.getElementById('globalPriority').checked;
plugin.modPriority = this.shadowRoot.getElementById('priorityValue').value;
}
plugin.userlist.enabled = this.shadowRoot.getElementById('enableEdits').checked;
var tables = this.shadowRoot.getElementsByTagName('table');
for (var j = 0; j < tables.length; ++j) {
var rowsData = tables[j].getRowsData(true);
if (rowsData.length > 0) {
if (tables[j].id == 'loadAfter') {
plugin.userlist.after = rowsData;
} else if (tables[j].id == 'req') {
plugin.userlist.req = rowsData;
} else if (tables[j].id == 'inc') {
plugin.userlist.inc = rowsData;
} else if (tables[j].id == 'message') {
rowsData.forEach(function(data){
data.content = [{
str: data.content,
lang: data.language
}]
delete data.language;
});
plugin.userlist.msg = rowsData;
} else if (tables[j].id == 'tags') {
rowsData.forEach(function(data){
data = oldData.convTagObj(data);
});
plugin.userlist.tag = rowsData;
} else if (tables[j].id == 'dirty') {
rowsData.forEach(function(data){
data.crc = parseInt(data.crc, 16);
});
plugin.userlist.dirty = rowsData;
} else if (tables[j].id == 'locations') {
rowsData.forEach(function(data){
/* User metadata can only specify one version, but it should be a list. */
if (data.ver.length > 0) {
data.ver = [
data.ver
];
} else {
delete data.ver;
}
});
plugin.userlist.url = rowsData;
}
}
}
}
return plugin;
},
onHideEditor: function(evt) {
/* First validate table inputs. */
var isValid = true;
var inputs = evt.target.parentElement.parentElement.getElementsByTagName('input');
for (var i = 0; i < inputs.length; ++i) {
if (!inputs[i].checkValidity()) {
isValid = false;
console.log(inputs[i]);
}
}
if (isValid || evt.target.id != 'accept') {
/* Fire the close event, saying whether or not to save data. */
evt.target.dispatchEvent(new CustomEvent('loot-editor-close', {
bubbles: true,
detail: (evt.target.id == 'accept'),
}));
}
},
setEditorData: function(data) {
this.shadowRoot.getElementById('editor').getElementsByTagName('h1')[0].textContent = data.name;
this.shadowRoot.getElementById('editor').getElementsByClassName('version')[0].textContent = data.version;
if (data.crc != '0') {
this.shadowRoot.getElementById('editor').getElementsByClassName('crc')[0].textContent = data.crc.toString(16).toUpperCase();
}
/* Fill in the editor input values. */
if (data.userlist && !data.userlist.enabled) {
this.shadowRoot.getElementById('enableEdits').checked = false;
} else {
this.shadowRoot.getElementById('enableEdits').checked = true;
}
this.shadowRoot.getElementById('globalPriority').checked = data.isGlobalPriority;
this.shadowRoot.getElementById('priorityValue').value = data.modPriority;
/* Clear any existing editor table data. Don't remove the last row though,
that's the "add new row" one. */
var tables = this.shadowRoot.getElementsByTagName('table');
for (var j = 0; j < tables.length; ++j) {
tables[j].clear();
}
/* Fill in editor table data. Masterlist-originated rows should have
their contents made read-only, and be unremovable. */
var tables = this.shadowRoot.getElementsByTagName('table');
for (var j = 0; j < tables.length; ++j) {
if (tables[j].id == 'loadAfter') {
if (data.masterlist && data.masterlist.after) {
data.masterlist.after.forEach(function(file) {
var row = tables[j].addRow(file);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.after) {
data.userlist.after.forEach(function(file) {
tables[j].addRow(file);
});
}
} else if (tables[j].id == 'req') {
if (data.masterlist && data.masterlist.req) {
data.masterlist.req.forEach(function(file) {
var row = tables[j].addRow(file);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.req) {
data.userlist.req.forEach(function(file) {
tables[j].addRow(file);
});
}
} else if (tables[j].id == 'inc') {
if (data.masterlist && data.masterlist.inc) {
data.masterlist.inc.forEach(function(file) {
var row = tables[j].addRow(file);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.inc) {
data.userlist.inc.forEach(function(file) {
tables[j].addRow(file);
});
}
} else if (tables[j].id == 'message') {
if (data.masterlist && data.masterlist.msg) {
data.masterlist.msg.forEach(function(message) {
var data = {
type: message.type,
content: message.content[0].str,
condition: message.condition,
language: message.content[0].lang
};
var row = tables[j].addRow(data);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.msg) {
data.userlist.msg.forEach(function(message) {
var data = {
type: message.type,
content: message.content[0].str,
condition: message.condition,
language: message.content[0].lang
};
tables[j].addRow(data);
});
}
} else if (tables[j].id == 'tags') {
if (data.masterlist && data.masterlist.tag) {
data.masterlist.tag.forEach(function(tag) {
var data = data.convTagObj(tag);
var row = tables[j].addRow(data);
tables[j].setReadOnly(row);
}, data);
}
if (data.userlist && data.userlist.tag) {
data.userlist.tag.forEach(function(tag) {
var data = data.convTagObj(tag);
tables[j].addRow(data);
}, data);
}
} else if (tables[j].id == 'dirty') {
if (data.masterlist && data.masterlist.dirty) {
data.masterlist.dirty.forEach(function(info) {
info.crc = info.crc.toString(16).toUpperCase();
var row = tables[j].addRow(info);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.dirty) {
data.userlist.dirty.forEach(function(info) {
info.crc = info.crc.toString(16).toUpperCase();
tables[j].addRow(info);
});
}
} else if (tables[j].id == 'locations') {
if (data.masterlist && data.masterlist.url) {
data.masterlist.url.forEach(function(location) {
var temp = location;
if (temp.ver) {
temp.ver = temp.ver[0];
}
var row = tables[j].addRow(temp);
tables[j].setReadOnly(row);
});
}
if (data.userlist && data.userlist.url) {
data.userlist.url.forEach(function(location) {
var temp = location;
if (temp.ver) {
temp.ver = temp.ver[0];
}
tables[j].addRow(temp);
});
}
}
}
},
});
</script>
</polymer-element>
+6
View File
@@ -1037,6 +1037,9 @@ function handleEditorOpen(evt) {
elements[i].addEventListener('dragstart', elements[i].handleDragStart, false);
}
/* Now show editor. */
evt.target.classList.toggle('flip');
/* Enable priority hover in plugins list and enable header
buttons if this is the only editor instance. */
var numEditors = 0;
@@ -1083,6 +1086,9 @@ function handleEditorClose(evt) {
}).catch(processCefError);
}
/* Now hide editor. */
evt.target.classList.toggle('flip');
/* Remove drag 'n' drop event handlers. */
var elements = document.getElementById('cardsNav').getElementsByTagName('loot-plugin-item');
for (var i = 0; i < elements.length; ++i) {