diff --git a/src/css/toolbox-palettes-list.css b/src/css/toolbox-palettes-list.css index 7aa0f837..2d8aa477 100644 --- a/src/css/toolbox-palettes-list.css +++ b/src/css/toolbox-palettes-list.css @@ -1,6 +1,3 @@ -.palettes-list-container { -} - .palettes-list-select { float:right; max-width:90px; @@ -14,7 +11,8 @@ } .palettes-list-colors { - overflow:hidden; + overflow: auto; + max-height: 160px; } .palettes-list-color { @@ -35,8 +33,13 @@ height : 32px; } -.palettes-list-color.primary:before, -.palettes-list-color.secondary:before { +.palettes-list-has-scrollbar .palettes-list-color, +.palettes-list-has-scrollbar .palettes-list-color div{ + width: 29px +} + +.palettes-list-primary-color:before, +.palettes-list-secondary-color:before { content: ""; position: absolute; bottom: 1px; @@ -48,13 +51,13 @@ height: 0px; } -.palettes-list-color.primary:before { +.palettes-list-primary-color:before { left: 1px; border-right-color: transparent; } -.palettes-list-color.secondary:before { +.palettes-list-secondary-color:before { right: 1px; border-left-color: transparent; } \ No newline at end of file diff --git a/src/js/Constants.js b/src/js/Constants.js index 405565f7..23d4cca4 100644 --- a/src/js/Constants.js +++ b/src/js/Constants.js @@ -20,6 +20,8 @@ var Constants = { TRANSPARENT_COLOR : 'rgba(0, 0, 0, 0)', NO_PALETTE_ID : '__no-palette', + CURRENT_COLORS_PALETTE_ID : '__current-colors', + MANAGE_PALETTE_ID : '__manage-palettes', // Used for Spectrum input PREFERRED_COLOR_FORMAT : 'rgb', diff --git a/src/js/Events.js b/src/js/Events.js index 97d84028..4c943a70 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -45,5 +45,7 @@ var Events = { SHOW_NOTIFICATION: "SHOW_NOTIFICATION", HIDE_NOTIFICATION: "HIDE_NOTIFICATION", - ZOOM_CHANGED : "ZOOM_CHANGED" + ZOOM_CHANGED : "ZOOM_CHANGED", + + CURRENT_COLORS_UPDATED : "CURRENT_COLORS_UPDATED" }; \ No newline at end of file diff --git a/src/js/app.js b/src/js/app.js index e98101d3..ecca93f5 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -39,7 +39,10 @@ this.paletteController = new pskl.controller.PaletteController(); this.paletteController.init(); - this.palettesListController = new pskl.controller.PalettesListController(); + this.currentColorsService = new pskl.service.CurrentColorsService(this.piskelController); + this.currentColorsService.init(); + + this.palettesListController = new pskl.controller.PalettesListController(this.paletteController, this.currentColorsService); this.palettesListController.init(); this.cursorCoordinatesController = new pskl.controller.CursorCoordinatesController(this.piskelController); diff --git a/src/js/controller/PalettesListController.js b/src/js/controller/PalettesListController.js index 39918c41..31c3f65a 100644 --- a/src/js/controller/PalettesListController.js +++ b/src/js/controller/PalettesListController.js @@ -1,8 +1,18 @@ (function () { var ns = $.namespace('pskl.controller'); - ns.PalettesListController = function () { + var PRIMARY_COLOR_CLASSNAME = 'palettes-list-primary-color'; + var SECONDARY_COLOR_CLASSNAME = 'palettes-list-secondary-color'; + var HAS_SCROLL_CLASSNAME = 'palettes-list-has-scrollbar'; + // well ... I know that if there are more than 20 colors, a scrollbar will be displayed + // It's linked to the max-height: 160px; defined in toolbox-palette-list.css ! + // I apologize to my future self for this one. + var NO_SCROLL_MAX_COLORS = 20; + + ns.PalettesListController = function (paletteController, usedColorService) { + this.usedColorService = usedColorService; + this.paletteController = paletteController; }; ns.PalettesListController.prototype.init = function () { @@ -16,8 +26,9 @@ this.colorListContainer_.addEventListener('contextmenu', this.onColorContainerContextMenu.bind(this)); $.subscribe(Events.PALETTE_LIST_UPDATED, this.onPaletteListUpdated.bind(this)); - $.subscribe(Events.PRIMARY_COLOR_SELECTED, this.onColorUpdated.bind(this, 'primary')); - $.subscribe(Events.SECONDARY_COLOR_SELECTED, this.onColorUpdated.bind(this, 'secondary')); + $.subscribe(Events.CURRENT_COLORS_UPDATED, this.fillColorListContainer.bind(this)); + $.subscribe(Events.PRIMARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this)); + $.subscribe(Events.SECONDARY_COLOR_SELECTED, this.highlightSelectedColors.bind(this)); this.fillPaletteList(); this.selectPaletteFromUserSettings(); @@ -38,23 +49,35 @@ }; ns.PalettesListController.prototype.fillColorListContainer = function () { - var html = ''; - - var palette = this.getSelectedPalette(); - if (palette) { - html = palette.colors.map(function (color) { - return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color}); - }.bind(this)).join(''); - } + var colors = this.getSelectedPaletteColors_(); + var html = colors.map(function (color) { + return pskl.utils.Template.replace(this.paletteColorTemplate_, {color : color}); + }.bind(this)).join(''); this.colorListContainer_.innerHTML = html; + + this.highlightSelectedColors(); + + var hasScrollbar = colors.length > NO_SCROLL_MAX_COLORS; + if (hasScrollbar && !pskl.utils.UserAgent.isChrome) { + this.colorListContainer_.classList.add(HAS_SCROLL_CLASSNAME); + } else { + this.colorListContainer_.classList.remove(HAS_SCROLL_CLASSNAME); + } }; - ns.PalettesListController.prototype.getSelectedPalette = function (evt) { + ns.PalettesListController.prototype.getSelectedPaletteColors_ = function () { + var colors = []; var paletteId = this.colorPaletteSelect_.value; - var palettes = this.retrievePalettes(); - var palette = this.getPaletteById(paletteId, palettes); - return palette; + if (paletteId === Constants.CURRENT_COLORS_PALETTE_ID) { + colors = this.usedColorService.getCurrentColors(); + } else { + var palette = this.getPaletteById(paletteId, this.retrievePalettes()); + if (palette) { + colors = palette.colors; + } + } + return colors; }; ns.PalettesListController.prototype.selectPalette = function (paletteId) { @@ -67,7 +90,7 @@ ns.PalettesListController.prototype.onPaletteSelected_ = function (evt) { var paletteId = this.colorPaletteSelect_.value; - if (paletteId === '__manage-palettes') { + if (paletteId === Constants.MANAGE_PALETTE_ID) { $.publish(Events.DIALOG_DISPLAY, 'manage-palettes'); this.selectPaletteFromUserSettings(); } else { @@ -96,27 +119,29 @@ } }; - ns.PalettesListController.prototype.onColorUpdated = function (type, event, color) { - var colorContainer = this.colorListContainer_.querySelector('.palettes-list-color[data-color="'+color+'"]'); + ns.PalettesListController.prototype.highlightSelectedColors = function () { + this.removeClass_(PRIMARY_COLOR_CLASSNAME); + this.removeClass_(SECONDARY_COLOR_CLASSNAME); - // Color is not in the currently selected palette - if (!colorContainer) { - return; + var colorContainer = this.getColorContainer_(this.paletteController.getSecondaryColor()); + if (colorContainer) { + colorContainer.classList.remove(PRIMARY_COLOR_CLASSNAME); + colorContainer.classList.add(SECONDARY_COLOR_CLASSNAME); } - if (type === 'primary') { - this.removeClass_('primary', '.palettes-list-color'); - colorContainer.classList.add('primary'); - colorContainer.classList.remove('secondary'); - } else if (type === 'secondary') { - this.removeClass_('secondary', '.palettes-list-color'); - colorContainer.classList.add('secondary'); - colorContainer.classList.remove('primary'); + colorContainer = this.getColorContainer_(this.paletteController.getPrimaryColor()); + if (colorContainer) { + colorContainer.classList.remove(SECONDARY_COLOR_CLASSNAME); + colorContainer.classList.add(PRIMARY_COLOR_CLASSNAME); } }; - ns.PalettesListController.prototype.removeClass_ = function (cssClass, selector) { - var element = document.querySelector(selector + '.' + cssClass); + ns.PalettesListController.prototype.getColorContainer_ = function (color) { + return this.colorListContainer_.querySelector('.palettes-list-color[data-color="'+color+'"]'); + }; + + ns.PalettesListController.prototype.removeClass_ = function (cssClass) { + var element = document.querySelector('.' + cssClass); if (element) { element.classList.remove(cssClass); } diff --git a/src/js/service/CurrentColorsService.js b/src/js/service/CurrentColorsService.js new file mode 100644 index 00000000..e8f282cf --- /dev/null +++ b/src/js/service/CurrentColorsService.js @@ -0,0 +1,51 @@ +(function () { + var ns = $.namespace('pskl.service'); + + ns.CurrentColorsService = function (piskelController) { + this.piskelController = piskelController; + this.currentColors = []; + this.framesColorsCache_ = {}; + }; + + ns.CurrentColorsService.prototype.init = function () { + $.subscribe(Events.PISKEL_RESET, this.onPiskelUpdated_.bind(this)); + $.subscribe(Events.TOOL_RELEASED, this.onPiskelUpdated_.bind(this)); + }; + + ns.CurrentColorsService.prototype.getCurrentColors = function () { + return this.currentColors; + }; + + ns.CurrentColorsService.prototype.onPiskelUpdated_ = function (evt) { + var layers = this.piskelController.getLayers(); + var frames = layers.map(function (l) {return l.getFrames();}).reduce(function (p, n) {return p.concat(n);}); + var colors = {}; + frames.forEach(function (f) { + var frameHash = f.getHash(); + if (!this.framesColorsCache_[frameHash]) { + var frameColors = {}; + f.forEachPixel(function (color, x, y) { + frameColors[color] = true; + }); + this.framesColorsCache_[frameHash] = frameColors; + } + Object.keys(this.framesColorsCache_[frameHash]).forEach(function (color) { + colors[color] = true; + }); + }.bind(this)); + delete colors[Constants.TRANSPARENT_COLOR]; + this.currentColors = Object.keys(colors); + this.currentColors = this.currentColors.sort(function (c1, c2) { + if (c1 < c2) { + return -1; + } else if (c1 > c2) { + return 1; + } else { + return 0; + } + }); + + // TODO : only fire if there was a change + $.publish(Events.CURRENT_COLORS_UPDATED, colors); + }; +})(); \ No newline at end of file diff --git a/src/js/utils/UserSettings.js b/src/js/utils/UserSettings.js index 59c6455f..c200a346 100644 --- a/src/js/utils/UserSettings.js +++ b/src/js/utils/UserSettings.js @@ -9,7 +9,7 @@ KEY_TO_DEFAULT_VALUE_MAP_ : { 'GRID_WIDTH' : 0, 'CANVAS_BACKGROUND' : 'lowcont-dark-canvas-background', - 'SELECTED_PALETTE' : Constants.NO_PALETTE_ID + 'SELECTED_PALETTE' : Constants.CURRENT_PALETTE_ID }, /** diff --git a/src/piskel-script-list.js b/src/piskel-script-list.js index 26eb3d22..3bc34634 100644 --- a/src/piskel-script-list.js +++ b/src/piskel-script-list.js @@ -106,6 +106,7 @@ "js/service/keyboard/KeycodeTranslator.js", "js/service/keyboard/CheatsheetService.js", "js/service/ImageUploadService.js", + "js/service/CurrentColorsService.js", // Tools "js/drawingtools/BaseTool.js", diff --git a/src/templates/palettes-list.html b/src/templates/palettes-list.html index d3c1e470..8cc447e5 100644 --- a/src/templates/palettes-list.html +++ b/src/templates/palettes-list.html @@ -2,19 +2,18 @@

Palettes

+ -