GUACAMOLE-630: Switch to Pickr for color picker.

This commit is contained in:
Michael Jumper
2019-08-05 21:52:57 -07:00
parent 6936aef540
commit 02d3732c9c
9 changed files with 279 additions and 35 deletions

View File

@@ -47,6 +47,14 @@ angular.module('form').controller('terminalColorSchemeFieldController', ['$scope
*/
$scope.customColorScheme = new ColorScheme();
/**
* The array of colors to include within the color picker as pre-defined
* options for convenience.
*
* @type String[]
*/
$scope.defaultPalette = new ColorScheme().colors;
/**
* The string value which is assigned to selectedColorScheme if a custom
* color scheme is selected.

View File

@@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* A directive which implements a color input field, leveraging the "Pickr"
* color picker.
*/
angular.module('form').directive('guacInputColor', [function guacInputColor() {
var config = {
restrict: 'E',
replace: true,
templateUrl: 'app/form/templates/guacInputColor.html',
};
config.scope = {
/**
* The current selected color value, in standard 6-digit hexadecimal
* RGB notation. When the user selects a different color using this
* directive, this value will updated accordingly.
*
* @type String
*/
model: '=',
/**
* An optional array of colors to include within the color picker as a
* convenient selection of pre-defined colors. The colors within the
* array must be in standard 6-digit hexadecimal RGB notation.
*
* @type String[]
*/
palette: '='
};
config.controller = ['$scope', '$element', '$injector',
function guacInputColorController($scope, $element, $injector) {
// Required services
var $q = $injector.get('$q');
var $translate = $injector.get('$translate');
// Init color picker after required translation strings are available
$q.all({
'save' : $translate('APP.ACTION_SAVE'),
'cancel' : $translate('APP.ACTION_CANCEL')
}).then(function stringsRetrieved(strings) {
/**
* An instance of the "Pickr" color picker, bound to the underlying
* element of this directive.
*
* @type Pickr
*/
var pickr = Pickr.create({
// Bind color picker to the underlying element of this directive
el : $element[0],
// Wrap color picker dialog in Guacamole-specific class for
// sake of additional styling
appClass : 'guac-input-color-picker',
// Display color details as hex
defaultRepresentation : 'HEX',
// Use "monolith" theme, as a nice balance between "nano" (does
// not work in Internet Explorer) and "classic" (too big)
theme : 'monolith',
// Leverage the container element as the button which shows the
// picker, relying on our own styling for that button
useAsButton : true,
appendToBody : true,
// Do not include opacity controls
lockOpacity : true,
// Include a selection of palette entries for convenience and
// reference
swatches : $scope.palette || [],
components: {
// Include hue and color preview controls
preview : true,
hue : true,
// Display only a text color input field and the save and
// cancel buttons (no clear button)
interaction: {
input : true,
save : true,
cancel : true
}
},
// Use translation strings for buttons
strings : strings
});
// Hide color picker after user clicks "cancel"
pickr.on('cancel', function colorChangeCanceled() {
pickr.hide();
});
// Keep model in sync with changes to the color picker
pickr.on('save', function colorChanged(color) {
$scope.$evalAsync(function updateModel() {
$scope.model = color.toHEXA().toString();
});
});
// Keep color picker in sync with changes to the model
pickr.on('init', function pickrReady(color) {
$scope.$watch('model', function modelChanged(model) {
pickr.setColor(model);
});
});
}, angular.noop);
}];
return config;
}]);

View File

@@ -41,8 +41,6 @@
width: 100%;
margin: 0;
padding: 0;
display: flex;
flex-wrap: wrap;
}
.form-field .terminal-color-scheme-field .custom-color-scheme .palette-group {
@@ -51,8 +49,26 @@
flex: 1;
}
.form-field .terminal-color-scheme-field .custom-color-scheme input[type="color"] {
.form-field .terminal-color-scheme-field .custom-color-scheme .guac-input-color {
display: block;
margin: 2px;
flex: 1;
}
width: 1.5em;
height: 1.5em;
min-width: 1.25em;
border-radius: 0.15em;
}
/* Increase width of color picker to allow two even rows of eight color
* swatches */
.guac-input-color-picker[data-theme="monolith"] {
width: 16.25em;
}
/* Remove Guacamole-specific styles inherited from the generic button rules */
.guac-input-color-picker[data-theme="monolith"] button {
min-width: 0;
padding: 0;
margin: 0;
box-shadow: none;
}

View File

@@ -0,0 +1 @@
<div input class="guac-input-color" ng-style="{ 'background-color' : model }"></div>

View File

@@ -11,13 +11,17 @@
<tr>
<th>{{ getFieldHeader(field.name + '-foreground') | translate }}</th>
<td>
<input type="color" ng-model="customColorScheme.foreground">
<div class="palette-group">
<guac-input-color model="customColorScheme.foreground" palette="defaultPalette"></guac-input-color>
</div>
</td>
</tr>
<tr>
<th>{{ getFieldHeader(field.name + '-background') | translate }}</th>
<td>
<input type="color" ng-model="customColorScheme.background">
<div class="palette-group">
<guac-input-color model="customColorScheme.background" palette="defaultPalette"></guac-input-color>
</div>
</td>
</tr>
</tbody>
@@ -29,45 +33,50 @@
<td class="low-intensity-colors">
<div class="palette-group">
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[0]">
<input type="color" ng-model="customColorScheme.colors[1]">
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[0]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[1]" palette="defaultPalette"></guac-input-color>
</div>
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[2]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[3]" palette="defaultPalette"></guac-input-color>
</div>
</div>
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[2]">
<input type="color" ng-model="customColorScheme.colors[3]">
</div>
</div>
<div class="palette-group">
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[4]">
<input type="color" ng-model="customColorScheme.colors[5]">
</div>
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[6]">
<input type="color" ng-model="customColorScheme.colors[7]">
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[4]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[5]" palette="defaultPalette"></guac-input-color>
</div>
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[6]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[7]" palette="defaultPalette"></guac-input-color>
</div>
</div>
</div>
</td>
</tr>
<tr>
<td class="high-intensity-colors">
<div class="palette-group">
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[8]">
<input type="color" ng-model="customColorScheme.colors[9]">
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[8]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[9]" palette="defaultPalette"></guac-input-color>
</div>
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[10]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[11]" palette="defaultPalette"></guac-input-color>
</div>
</div>
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[10]">
<input type="color" ng-model="customColorScheme.colors[11]">
</div>
</div>
<div class="palette-group">
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[12]">
<input type="color" ng-model="customColorScheme.colors[13]">
</div>
<div class="palette-group">
<input type="color" ng-model="customColorScheme.colors[14]">
<input type="color" ng-model="customColorScheme.colors[15]">
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[12]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[13]" palette="defaultPalette"></guac-input-color>
</div>
<div class="palette-group">
<guac-input-color model="customColorScheme.colors[14]" palette="defaultPalette"></guac-input-color>
<guac-input-color model="customColorScheme.colors[15]" palette="defaultPalette"></guac-input-color>
</div>
</div>
</div>
</td>

View File

@@ -27,6 +27,7 @@
<link rel="icon" type="image/png" href="images/logo-64.png"/>
<link rel="icon" type="image/png" sizes="144x144" href="images/logo-144.png"/>
<link rel="apple-touch-icon" type="image/png" href="images/logo-144.png"/>
<link rel="stylesheet" type="text/css" href="webjars/simonwep__pickr/1.2.6/dist/themes/monolith.min.css"/>
<link rel="stylesheet" type="text/css" href="app.css?v=${project.version}">
<title ng-bind="page.title | translate"></title>
</head>
@@ -87,7 +88,10 @@
<!-- JSTZ -->
<script type="text/javascript" src="webjars/jstz/1.0.10/dist/jstz.min.js"></script>
<!-- Pickr (color picker) -->
<script type="text/javascript" src="webjars/simonwep__pickr/1.2.6/dist/pickr.es5.min.js"></script>
<!-- Polyfills for the "datalist" element, Blob and the FileSaver API -->
<script type="text/javascript" src="webjars/blob-polyfill/1.0.20150320/Blob.js"></script>
<script type="text/javascript" src="webjars/datalist-polyfill/1.14.0/datalist-polyfill.min.js"></script>