diff --git a/src/css/dialogs/dialogs.css b/src/css/dialogs/dialogs.css index c42dd126..8b4317fb 100644 --- a/src/css/dialogs/dialogs.css +++ b/src/css/dialogs/dialogs.css @@ -1,18 +1,19 @@ #dialog-container-wrapper { position: absolute; - z-index: 10000; + z-index: 20000; top: 0; right: 0; bottom: 0; left: 0; - padding: 50px; + padding: 50px 150px; box-sizing: border-box; -moz-box-sizing : border-box; color: white; + background: rgba(0,0,0,0.5); display : none; } @@ -23,7 +24,6 @@ box-sizing: border-box; -moz-box-sizing : border-box; - padding: 20px 3%; border-radius: 3px; background: rgba(0,0,0,0.9); overflow: auto; diff --git a/src/css/dialogs/manage-palettes.css b/src/css/dialogs/manage-palettes.css new file mode 100644 index 00000000..d037bb73 --- /dev/null +++ b/src/css/dialogs/manage-palettes.css @@ -0,0 +1,203 @@ +.palette-manager-wrapper { + height: 100%; + position: relative; +} + +.palette-manager-body { + position: absolute; + top: 45px; + bottom: 0; + right: 0; + left: 0; +} + +.palette-manager-head { + position: absolute; + width: 100%; + background: gold; + margin: 0; + padding: 10px; + color: black; + font-size: 1.8em; + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.palette-manager-drawer { + width: 200px; + position: absolute; + top: 0; + bottom: 0; +} + +.palette-manager-list { + position: absolute; + top:40px; + right: 0; + bottom: 0; + left: 0; + overflow: auto; +} + +.palette-manager-actions { + position: absolute; + height:40px; + line-height:40px; + width: 100%; + text-align: center; +} + +.palette-manager-actions-button { + width: 80px; + margin: 5px; +} + +.palette-manager-list li { + padding-left:10px; + font-size: 1.4em; + height: 48px; + line-height: 48px; + box-sizing: border-box; + -moz-box-sizing: border-box; + border-bottom: 1px solid #666; + cursor:pointer; +} + +.palette-manager-list li:hover { + background : #222; +} + +.palette-manager-list li.selected { + color : gold; + font-weight: bold; +} + + +.palette-manager-list li:nth-child(1) { + border-top: 1px solid #666; +} + +.palette-manager-details { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 200px; + + box-sizing: border-box; + -moz-box-sizing: border-box; + + border-left:1px solid #666; +} + +.palette-manager-details-head { + position: absolute; + height:40px; + line-height:40px; + width: 100%; + + box-sizing: border-box; + -moz-box-sizing: border-box; +} + +.palette-manager-details-head-name { + padding: 0 10px 0 20px; + font-size: 1.5em; + font-weight: bold; +} + +.palette-manager-details-head-edit-icon { + cursor: pointer; + width: 24px; + height: 100%; + background: url('../../img/tools/pen.png'); + display: inline-block; + background-size: 20px; + background-repeat: no-repeat; + background-position-y: 50%; +} + +.palette-manager-details-head-actions { + float: right; + line-height: 40px; + padding-right: 10px; +} + +.palette-manager-details-body { + position: absolute; + top:40px; + right: 0; + bottom: 0; + left: 0; + overflow: auto; + + box-sizing: border-box; + -moz-box-sizing: border-box; +} + + + +.palette-manager-color-card { + width: 120px; + height: 180px; + display: inline-block; + position: relative; + margin: 20px 0 20px 20px; +} + +.palette-manager-delete-card { + position: absolute; + top: 0; + right: 0; + width: 20px; + + text-align: center; + font-size: 1.6em; + font-weight: bold; + color: rgb(255,255,255); + text-shadow : 0 0 2px rgb(0,0,0); + cursor: pointer; + + opacity : 0.2; + transition : opacity 0.3s, color 0.1s; +} + +.palette-manager-color-card:hover .palette-manager-delete-card { + opacity : 0.6; +} + +.palette-manager-color-card .palette-manager-delete-card:hover { + opacity : 1; + color: rgb(240,80,80); +} + +.palette-manager-new-color .palette-manager-color-square { + border: 3px dotted #888; + border-bottom-width: 0; + box-sizing: border-box; + -moz-box-sizing: border-box; + border-radius: 3px 3px 0 0; + cursor: pointer; + text-align: center; + font-size: 24px; + color: #888; + line-height: 120px; +} + +.palette-manager-color-square { + width: 120px; + height: 120px; + cursor: pointer; + /*background-image:url(../../img/tools/eyedropper.png);*/ +} + +.palette-manager-color-details { + color : #888; + background: #eee; + height: 60px; + padding-left: 5px; +} + +.palette-manager-color-details li{ + line-height: 20px; +} \ No newline at end of file diff --git a/src/css/forms.css b/src/css/forms.css index cb912f01..dcf706c1 100644 --- a/src/css/forms.css +++ b/src/css/forms.css @@ -64,8 +64,8 @@ color: #333; } -.button[disabled=disabled], -.button[disabled=disabled]:hover { +.button[disabled], +.button[disabled]:hover { cursor:default; background-color: #aaa; color: #777; diff --git a/src/css/spectrum/spectrum-overrides.css b/src/css/spectrum/spectrum-overrides.css index 7f8d167b..f9bd072b 100644 --- a/src/css/spectrum/spectrum-overrides.css +++ b/src/css/spectrum/spectrum-overrides.css @@ -7,7 +7,7 @@ border-radius: 4px; background-color: #2B2B2B; border: solid 4px #888; - padding: 5px; + padding: 5px 5px 0 5px; box-shadow : 0 0 5px 0 black; } @@ -71,6 +71,12 @@ border-right-width: 0; } +.sp-picker-container { + padding: 5px; + padding-bottom: 300px; + margin-bottom: -295px; +} + .sp-slider { height: 5px; left: -2px; @@ -96,4 +102,17 @@ .sp-palette .sp-thumb-el.sp-thumb-active { border-color: gold; box-shadow: 0 0 0px 1px gold; +} + +.sp-input { + border: 1px solid #666; + margin: 0; + background: #111; + border-radius: 2px; + color: #D3D3D3; + font-family: Courier!important; +} + +.sp-input.sp-validation-error { + background: #330000; } \ No newline at end of file diff --git a/src/css/style.css b/src/css/style.css index d7d9e7c7..4c85147f 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -11,6 +11,15 @@ body { display: none; } +.allow-user-select { + -webkit-touch-callout: initial; + -webkit-user-select: initial; + -khtml-user-select: initial; + -moz-user-select: initial; + -ms-user-select: initial; + user-select: initial; +} + /** * Application layout */ diff --git a/src/js/Constants.js b/src/js/Constants.js index d3af0d98..851c9405 100644 --- a/src/js/Constants.js +++ b/src/js/Constants.js @@ -18,6 +18,9 @@ var Constants = { DEFAULT_PEN_COLOR : '#000000', TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)', + // Used for Spectrum input + PREFERRED_COLOR_FORMAT : 'rgb', + /* * Fake semi-transparent color used to highlight transparent * strokes and rectangles: diff --git a/src/js/controller/PaletteController.js b/src/js/controller/PaletteController.js index 786ced1e..2180d485 100644 --- a/src/js/controller/PaletteController.js +++ b/src/js/controller/PaletteController.js @@ -22,6 +22,7 @@ var spectrumCfg = { showPalette: true, showButtons: false, + showInput: true, palette: [ ['rgba(0,0,0,0)'] ], diff --git a/src/js/controller/dialogs/DialogsController.js b/src/js/controller/dialogs/DialogsController.js index bc471956..9e4fcbf7 100644 --- a/src/js/controller/dialogs/DialogsController.js +++ b/src/js/controller/dialogs/DialogsController.js @@ -4,12 +4,13 @@ var dialogs = { 'manage-palettes' : { template : 'templates/dialogs/manage-palettes.html', - controller : ns.ManagePalettesController + controller : ns.PaletteManagerController } }; ns.DialogsController = function (piskelController) { this.piskelController = piskelController; + this.currentDialog_ = null; }; ns.DialogsController.prototype.init = function () { @@ -17,17 +18,20 @@ this.dialogWrapper_ = document.getElementById('dialog-container-wrapper'); $.subscribe(Events.DIALOG_DISPLAY, this.onDialogDisplayEvent_.bind(this)); $.subscribe(Events.DIALOG_HIDE, this.onDialogHideEvent_.bind(this)); + pskl.app.shortcutService.addShortcut('M', this.onDialogDisplayEvent_.bind(this, null, 'manage-palettes')); }; ns.DialogsController.prototype.onDialogDisplayEvent_ = function (evt, dialogId) { - var config = dialogs[dialogId]; - - if (config) { - this.dialogContainer_.innerHTML = pskl.utils.Template.get(config.template); - (new config.controller(this.piskelController)).init(); - this.showDialogWrapper_(); - } else { - console.error('Could not find dialog configuration for dialogId : ' + dialogId); + if (!this.isDisplayed()) { + var config = dialogs[dialogId]; + if (config) { + this.dialogContainer_.innerHTML = pskl.utils.Template.get(config.template); + (new config.controller(this.piskelController)).init(); + this.showDialogWrapper_(); + this.currentDialog_ = dialogId; + } else { + console.error('Could not find dialog configuration for dialogId : ' + dialogId); + } } }; @@ -36,13 +40,22 @@ }; ns.DialogsController.prototype.showDialogWrapper_ = function () { - pskl.app.shortcutService.addShortcut('ESC', this.hideDialogWrapper_.bind(this)); + pskl.app.shortcutService.addShortcut('ESC', this.hideDialog.bind(this)); this.dialogWrapper_.style.display = 'block'; }; + ns.DialogsController.prototype.hideDialog = function () { + this.hideDialogWrapper_(); + this.currentDialog_ = null; + }; + ns.DialogsController.prototype.hideDialogWrapper_ = function () { pskl.app.shortcutService.removeShortcut('ESC'); this.dialogWrapper_.style.display = 'none'; }; + ns.DialogsController.prototype.isDisplayed = function () { + return this.currentDialog_ !== null; + }; + })(); \ No newline at end of file diff --git a/src/js/controller/dialogs/ManagePalettesController.js b/src/js/controller/dialogs/ManagePalettesController.js deleted file mode 100644 index 284aa973..00000000 --- a/src/js/controller/dialogs/ManagePalettesController.js +++ /dev/null @@ -1,9 +0,0 @@ -(function () { - var ns = $.namespace('pskl.controller.dialogs'); - - ns.ManagePalettesController = function (piskelController) { - this.piskelController = piskelController; - }; - - ns.ManagePalettesController.prototype.init = function () {}; -})(); \ No newline at end of file diff --git a/src/js/controller/dialogs/PaletteManagerController.js b/src/js/controller/dialogs/PaletteManagerController.js new file mode 100644 index 00000000..a4ed490f --- /dev/null +++ b/src/js/controller/dialogs/PaletteManagerController.js @@ -0,0 +1,326 @@ +(function () { + var ns = $.namespace('pskl.controller.dialogs'); + + var tinycolor = window.tinycolor; + + var SELECTED_CLASSNAME = 'selected'; + var NEW_COLOR_CLASS = 'palette-manager-new-color'; + var CLOSE_ICON_CLASS = 'palette-manager-delete-card'; + var EDIT_NAME_CLASS = 'palette-manager-details-head-edit-icon'; + + ns.PaletteManagerController = function (piskelController) { + this.piskelController = piskelController; + this.palettes = this.retrieveUserPalettes(); + this.originalPalettes = this.retrieveUserPalettes(); + this.selectedPaletteId = null; + }; + + ns.PaletteManagerController.prototype.init = function () { + this.palettesList = document.querySelector('.palette-manager-list'); + this.paletteBody = document.querySelector('.palette-manager-details-body'); + this.paletteHead = document.querySelector('.palette-manager-details-head'); + this.createButton = document.querySelector('.palette-manager-actions-button[data-action="create"]'); + + this.colorCardTemplate = pskl.utils.Template.get('palette-color-card-template'); + this.newColorTemplate = pskl.utils.Template.get('palette-new-color-template'); + this.paletteHeadTemplate = pskl.utils.Template.get('palette-details-head-template'); + + // Events + this.palettesList.addEventListener('click', this.onPaletteListClick.bind(this)); + // Delegated event listener for events repeated on all cards + this.paletteBody.addEventListener('click', this.delegatedPaletteBodyClick.bind(this)); + this.paletteHead.addEventListener('click', this.delegatedPaletteHeadClick.bind(this)); + this.createButton.addEventListener('click', this.createPalette.bind(this)); + + // Init markup + this.createPaletteListMarkup(); + if (this.palettes.length > 0) { + this.selectPalette(this.palettes[0].id); + } else { + console.error('[PaletteManagerController] >>> Implement fallback screen when no palette can be retrieved'); + } + }; + + ns.PaletteManagerController.prototype.createPalette = function () { + var name = window.prompt('Please enter a name for your palette', 'New palette'); + if (name) { + var palette = this.createPaletteObject(name); + this.palettes.push(palette); + this.createPaletteListMarkup(); + this.selectPalette(palette.id); + } + }; + + ns.PaletteManagerController.prototype.createPaletteObject = function (name) { + return { + id : 'palette-' + Date.now() + '-' + Math.floor(Math.random()*1000), + name : name, + colors : [] + }; + }; + + ns.PaletteManagerController.prototype.selectPalette = function (paletteId) { + this.deselectCurrentPalette(); + var paletteListItem = this.palettesList.querySelector('[data-palette-id='+paletteId+']'); + if (paletteListItem) { + this.selectedPaletteId = paletteId; + paletteListItem.classList.add(SELECTED_CLASSNAME); + this.refreshPaletteDetails(); + } + }; + + ns.PaletteManagerController.prototype.refreshPaletteDetails = function () { + this.createPaletteHeadMarkup(); + this.createPaletteBodyMarkup(); + this.initPaletteDetailsEvents(); + this.initPaletteCardsSpectrum(); + }; + + ns.PaletteManagerController.prototype.createPaletteListMarkup = function () { + var html = this.palettes.map(function (palette) { + var paletteCopy = { + id : palette.id, + name : this.isPaletteModified(palette) ? palette.name + " *" : palette.name + }; + return pskl.utils.Template.replace('