Commit 29a93b8c authored by webchick's avatar webchick

#693504 by stBorchert, ksenzee, dixon_ | jarek, joachim, EvanDonovan,...

#693504 by stBorchert, ksenzee, dixon_ | jarek, joachim, EvanDonovan, eigentor, sun, dmitrig01, et al.: Added support to color.module for flexible color schemes and gradients, and removed hard-coded assumptions about Garland.
parent 7817a0a5
......@@ -3,6 +3,7 @@
Drupal.behaviors.color = {
attach: function (context, settings) {
var i, colors, field_name;
// This behavior attaches by ID, so is only valid once on a page.
var form = $('#system-theme-settings .color-form', context).once('color');
if (form.length == 0) {
......@@ -24,11 +25,23 @@ Drupal.behaviors.color = {
}
// Build a preview.
$('#preview').once('color').append('<div id="gradient"></div>');
var gradient = $('#preview #gradient');
var h = parseInt(gradient.css('height'), 10) / 10;
for (i = 0; i < h; ++i) {
gradient.append('<div class="gradient-line"></div>');
var height = [];
var width = [];
// Loop through all defined gradients.
for (i in settings.gradients) {
// Add element to display the gradient.
$('#preview').once('color').append('<div id="gradient-' + i + '"></div>');
var gradient = $('#preview #gradient-' + i);
// Add height of current gradient to the list (divided by 10).
height.push(parseInt(gradient.css('height'), 10) / 10);
// Add width of current gradient to the list (divided by 10).
width.push(parseInt(gradient.css('width'), 10) / 10);
// Add rows (or columns for horizontal gradients).
// Each gradient line should have a height (or width for horizontal
// gradients) of 10px (because we divided the height/width by 10 above).
for (j = 0; j < (settings.gradients[i]['direction'] == 'vertical' ? height[i] : width[i]); ++j) {
gradient.append('<div class="gradient-line"></div>');
}
}
// Fix preview background in IE6.
......@@ -39,13 +52,14 @@ Drupal.behaviors.color = {
e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')";
}
// Set up colorscheme selector.
// Set up colorScheme selector.
$('#edit-scheme', form).change(function () {
var colors = this.options[this.selectedIndex].value;
if (colors != '') {
colors = colors.split(',');
for (i in colors) {
callback(inputs[i], colors[i], false, true);
var schemes = settings.color.schemes, colorScheme = this.options[this.selectedIndex].value;
if (colorScheme != '' && schemes[colorScheme]) {
// Get colors of active scheme.
colors = schemes[colorScheme];
for (field_name in colors) {
callback($('#edit-palette-' + field_name), colors[field_name], false, true);
}
preview();
}
......@@ -56,29 +70,31 @@ Drupal.behaviors.color = {
*/
function preview() {
// Solid background.
$('#preview', form).css('backgroundColor', inputs[0].value);
$('#preview', form).css('backgroundColor', $('#palette input[name="palette[base]"]', form).val());
// Text preview
$('#text', form).css('color', inputs[4].value);
$('#text a, #text h2', form).css('color', inputs[1].value);
// Set up gradient.
var top = farb.unpack(inputs[2].value);
var bottom = farb.unpack(inputs[3].value);
if (top && bottom) {
var delta = [];
for (i in top) {
delta[i] = (bottom[i] - top[i]) / h;
}
var accum = top;
// Render gradient lines.
$('#gradient > div', form).each(function () {
for (i in accum) {
accum[i] += delta[i];
$('#text', form).css('color', $('#palette input[name="palette[text]"]', form).val());
$('#text a, #text h2', form).css('color', $('#palette input[name="palette[link]"]', form).val());
// Set up gradients if there are some.
var color_start, color_end;
for (i in settings.gradients) {
color_start = farb.unpack($('#palette input[name="palette[' + settings.gradients[i]['colors'][0] + ']"]', form).val());
color_end = farb.unpack($('#palette input[name="palette[' + settings.gradients[i]['colors'][1] + ']"]', form).val());
if (color_start && color_end) {
var delta = [];
for (j in color_start) {
delta[j] = (color_end[j] - color_start[j]) / (settings.gradients[i]['vertical'] ? height[i] : width[i]);
}
this.style.backgroundColor = farb.pack(accum);
});
var accum = color_start;
// Render gradient lines.
$('#gradient-' + i + ' > div', form).each(function () {
for (j in accum) {
accum[j] += delta[j];
}
this.style.backgroundColor = farb.pack(accum);
});
}
}
}
......@@ -132,7 +148,8 @@ Drupal.behaviors.color = {
/**
* Callback for Farbtastic when a new color is chosen.
*/
function callback(input, color, propagate, colorscheme) {
function callback(input, color, propagate, colorScheme) {
var i, j, matched;
// Set background/foreground colors.
$(input).css({
backgroundColor: color,
......@@ -140,20 +157,20 @@ Drupal.behaviors.color = {
});
// Change input value.
if (input.value && input.value != color) {
input.value = color;
if ($(input).val() && $(input).val() != color) {
$(input).val(color);
// Update locked values.
if (propagate) {
var i = input.i;
i = input.i;
for (j = i + 1; ; ++j) {
if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break;
var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
callback(inputs[j], matched, false);
}
for (j = i - 1; ; --j) {
if (!locks[j] || $(locks[j]).is('.unlocked')) break;
var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
callback(inputs[j], matched, false);
}
......@@ -161,8 +178,8 @@ Drupal.behaviors.color = {
preview();
}
// Reset colorscheme selector.
if (!colorscheme) {
// Reset colorScheme selector.
if (!colorScheme) {
resetScheme();
}
}
......
......@@ -128,12 +128,8 @@ function color_get_info($theme) {
*/
function color_get_palette($theme, $default = FALSE) {
// Fetch and expand default palette.
$fields = array('base', 'link', 'top', 'bottom', 'text');
$info = color_get_info($theme);
$keys = array_keys($info['schemes']);
foreach (explode(',', array_shift($keys)) as $k => $scheme) {
$palette[$fields[$k]] = $scheme;
}
$palette = $info['schemes']['default']['colors'];
// Load variable.
return $default ? $palette : variable_get('color_' . $theme . '_palette', $palette);
......@@ -146,18 +142,39 @@ function color_scheme_form($complete_form, &$form_state, $theme) {
$base = drupal_get_path('module', 'color');
$info = color_get_info($theme);
$info['schemes'][''] = array('title' => t('Custom'), 'colors' => array());
$color_sets = array();
$schemes = array();
foreach ($info['schemes'] as $key => $scheme) {
$color_sets[$key] = $scheme['title'];
$schemes[$key] = $scheme['colors'];
$schemes[$key] += $info['schemes']['default']['colors'];
}
// See if we're using a predefined scheme.
$current = implode(',', variable_get('color_' . $theme . '_palette', array()));
// Note: we use the original theme when the default scheme is chosen.
$current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : '');
$current_scheme = variable_get('color_' . $theme . '_palette', array());
foreach ($schemes as $key => $scheme) {
if ($current_scheme == $scheme) {
$scheme_name = $key;
break;
}
}
if (empty($scheme_name)) {
if (empty($current_scheme)) {
$scheme_name = 'default';
}
else {
$scheme_name = '';
}
}
// Add scheme selector.
$info['schemes'][''] = t('Custom');
$form['scheme'] = array(
'#type' => 'select',
'#title' => t('Color set'),
'#options' => $info['schemes'],
'#default_value' => $current,
'#options' => $color_sets,
'#default_value' => $scheme_name,
'#attached' => array(
// Add Farbtastic color picker.
'library' => array(
......@@ -172,7 +189,11 @@ function color_scheme_form($complete_form, &$form_state, $theme) {
$base . '/color.js',
array(
'data' => array(
'color' => array('reference' => color_get_palette($theme, TRUE)),
'color' => array(
'reference' => color_get_palette($theme, TRUE),
'schemes' => $schemes,
),
'gradients' => $info['gradients'],
),
'type' => 'setting',
),
......@@ -182,21 +203,17 @@ function color_scheme_form($complete_form, &$form_state, $theme) {
// Add palette fields.
$palette = color_get_palette($theme);
$names = array(
'base' => t('Base color'),
'link' => t('Link color'),
'top' => t('Header top'),
'bottom' => t('Header bottom'),
'text' => t('Text color'),
);
$names = $info['fields'];
$form['palette']['#tree'] = TRUE;
foreach ($palette as $name => $value) {
$form['palette'][$name] = array(
'#type' => 'textfield',
'#title' => $names[$name],
'#default_value' => $value,
'#size' => 8,
);
if (isset($names[$name])) {
$form['palette'][$name] = array(
'#type' => 'textfield',
'#title' => $names[$name],
'#default_value' => $value,
'#size' => 8,
);
}
}
$form['theme'] = array('#type' => 'value', '#value' => $theme);
$form['info'] = array('#type' => 'value', '#value' => $info);
......@@ -251,10 +268,12 @@ function color_scheme_form_submit($form, &$form_state) {
// Resolve palette.
$palette = $form_state['values']['palette'];
if ($form_state['values']['scheme'] != '') {
$scheme = explode(',', $form_state['values']['scheme']);
foreach ($palette as $k => $color) {
$palette[$k] = array_shift($scheme);
foreach ($palette as $key => $color) {
if (isset($info['schemes'][$form_state['values']['scheme']]['colors'][$key])) {
$palette[$key] = $info['schemes'][$form_state['values']['scheme']]['colors'][$key];
}
}
$palette += $info['schemes']['default']['colors'];
}
// Make sure enough memory is available, if PHP's memory limit is compiled in.
......@@ -450,7 +469,6 @@ function _color_save_stylesheet($file, $style, &$paths) {
* Render images that match a given palette.
*/
function _color_render_images($theme, &$info, &$paths, $palette) {
// Prepare template image.
$source = $paths['source'] . '/' . $info['base_image'];
$source = imagecreatefrompng($source);
......@@ -466,10 +484,23 @@ function _color_render_images($theme, &$info, &$paths, $palette) {
imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color]));
}
// Render gradient.
for ($y = 0; $y < $info['gradient'][3]; ++$y) {
$color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1));
imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][0] + $info['gradient'][2], $info['gradient'][1] + $y + 1, $color);
// Render gradients.
foreach ($info['gradients'] as $gradient) {
// Get direction of the gradient.
if (isset($gradient['direction']) && $gradient['direction'] == 'horizontal') {
// Horizontal gradient.
for ($x = 0; $x < $gradient['dimension'][2]; $x++) {
$color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $x / ($gradient['dimension'][2] - 1));
imagefilledrectangle($target, ($gradient['dimension'][0] + $x), $gradient['dimension'][1], ($gradient['dimension'][0] + $x + 1), ($gradient['dimension'][1] + $gradient['dimension'][3]), $color);
}
}
else {
// Vertical gradient.
for ($y = 0; $y < $gradient['dimension'][3]; $y++) {
$color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $y / ($gradient['dimension'][3] - 1));
imagefilledrectangle($target, $gradient['dimension'][0], $gradient['dimension'][1] + $y, $gradient['dimension'][0] + $gradient['dimension'][2], $gradient['dimension'][1] + $y + 1, $color);
}
}
}
// Blend over template.
......
......@@ -45,6 +45,18 @@ class ColorTestCase extends DrupalWebTestCase {
$stylesheet_content = join("\n", file($stylesheets[0]));
$matched = preg_match('/(.*color: #123456.*)/i', $stylesheet_content, $matches);
$this->assertTrue($matched == 1, 'Make sure the color we changed is in the color stylesheet.');
$this->drupalGet('admin/appearance/settings/garland');
$this->assertResponse(200);
$edit['scheme'] = 'greenbeam';
$this->drupalPost('admin/appearance/settings/garland', $edit, t('Save configuration'));
$this->drupalGet('<front>');
$stylesheets = variable_get('color_' . $theme_key . '_stylesheets', array());
$stylesheet_content = join("\n", file($stylesheets[0]));
$matched = preg_match('/(.*color: #0c7a00.*)/i', $stylesheet_content, $matches);
$this->assertTrue($matched == 1, 'Make sure the color we changed is in the color stylesheet.');
}
}
......@@ -3,23 +3,160 @@
$info = array(
// Available colors and color labels used in theme.
'fields' => array(
'base' => t('Base color'),
'link' => t('Link color'),
'top' => t('Header top'),
'bottom' => t('Header bottom'),
'text' => t('Text color'),
),
// Pre-defined color schemes.
'schemes' => array(
'#0072b9,#027ac6,#2385c2,#5ab5ee,#494949' => t('Blue Lagoon (Default)'),
'#464849,#2f416f,#2a2b2d,#5d6779,#494949' => t('Ash'),
'#55c0e2,#000000,#085360,#007e94,#696969' => t('Aquamarine'),
'#d5b048,#6c420e,#331900,#971702,#494949' => t('Belgian Chocolate'),
'#3f3f3f,#336699,#6598cb,#6598cb,#000000' => t('Bluemarine'),
'#d0cb9a,#917803,#efde01,#e6fb2d,#494949' => t('Citrus Blast'),
'#0f005c,#434f8c,#4d91ff,#1a1575,#000000' => t('Cold Day'),
'#c9c497,#0c7a00,#03961e,#7be000,#494949' => t('Greenbeam'),
'#ffe23d,#a9290a,#fc6d1d,#a30f42,#494949' => t('Mediterrano'),
'#788597,#3f728d,#a9adbc,#d4d4d4,#707070' => t('Mercury'),
'#5b5fa9,#5b5faa,#0a2352,#9fa8d5,#494949' => t('Nocturnal'),
'#7db323,#6a9915,#b5d52a,#7db323,#191a19' => t('Olivia'),
'#12020b,#1b1a13,#f391c6,#f41063,#898080' => t('Pink Plastic'),
'#b7a0ba,#c70000,#a1443a,#f21107,#515d52' => t('Shiny Tomato'),
'#18583d,#1b5f42,#34775a,#52bf90,#2d2d2d' => t('Teal Top'),
'default' => array(
'title' => t('Blue Lagoon (Default)'),
'colors' => array(
'base' => '#0072b9',
'link' => '#027ac6',
'top' => '#2385c2',
'bottom' => '#5ab5ee',
'text' => '#494949',
),
),
'ash' => array(
'title' => t('Ash'),
'colors' => array(
'base' => '#464849',
'link' => '#2f416f',
'top' => '#2a2b2d',
'bottom' => '#5d6779',
),
),
'aquamarine' => array(
'title' => t('Aquamarine'),
'colors' => array(
'base' => '#55c0e2',
'link' => '#000000',
'text' => '#696969',
'top' => '#085360',
'bottom' => '#007e94',
),
),
'chocolate' => array(
'title' => t('Belgian Chocolate'),
'colors' => array(
'base' => '#d5b048',
'link' => '#6c420e',
'top' => '#331900',
'bottom' => '#971702',
),
),
'bluemarine' => array(
'title' => t('Bluemarine'),
'colors' => array(
'base' => '#3f3f3f',
'link' => '#336699',
'text' => '#000000',
'top' => '#6598cb',
'bottom' => '#6598cb',
),
),
'citrus' => array(
'title' => t('Citrus Blast'),
'colors' => array(
'base' => '#d0cb9a',
'link' => '#917803',
'top' => '#efde01',
'bottom' => '#e6fb2d',
),
),
'cold' => array(
'title' => t('Cold Day'),
'colors' => array(
'base' => '#0f005c',
'link' => '#434f8c',
'text' => '#000000',
'top' => '#4d91ff',
'bottom' => '#1a1575',
),
),
'greenbeam' => array(
'title' => t('Greenbeam'),
'colors' => array(
'base' => '#c9c497',
'link' => '#0c7a00',
'top' => '#03961e',
'bottom' => '#7be000',
),
),
'mediterrano' => array(
'title' => t('Mediterrano'),
'colors' => array(
'base' => '#ffe23d',
'link' => '#a9290a',
'top' => '#fc6d1d',
'bottom' => '#a30f42',
),
),
'mercury' => array(
'title' => t('Mercury'),
'colors' => array(
'base' => '#788597',
'link' => '#3f728d',
'top' => '#a9adbc',
'bottom' => '#d4d4d4',
'text' => '#707070',
),
),
'nocturnal' => array(
'title' => t('Nocturnal'),
'colors' => array(
'base' => '#5b5fa9',
'link' => '#5b5faa',
'top' => '#0a2352',
'bottom' => '#9fa8d5',
),
),
'olivia' => array(
'title' => t('Olivia'),
'colors' => array(
'base' => '#7db323',
'link' => '#6a9915',
'top' => '#b5d52a',
'bottom' => '#7db323',
'text' => '#191a19',
),
),
'pink_plastic' => array(
'title' => t('Pink Plastic'),
'colors' => array(
'base' => '#12020b',
'link' => '#1b1a13',
'top' => '#f391c6',
'bottom' => '#f41063',
'text' => '#898080',
),
),
'shiny_tomato' => array(
'title' => t('Shiny Tomato'),
'colors' => array(
'base' => '#b7a0ba',
'link' => '#c70000',
'top' => '#a1443a',
'bottom' => '#f21107',
'text' => '#515d52',
),
),
'teal_top' => array(
'title' => t('Teal Top'),
'colors' => array(
'base' => '#18583d',
'link' => '#1b5f42',
'top' => '#34775a',
'bottom' => '#52bf90',
'text' => '#2d2d2d',
),
),
),
// Images to copy over.
......@@ -35,8 +172,17 @@
'style.css',
),
// Coordinates of gradient (x, y, width, height).
'gradient' => array(0, 37, 760, 121),
// Gradient definitions.
'gradients' => array(
array(
// (x, y, width, height).
'dimension' => array(0, 38, 760, 121),
// Direction of gradient ('vertical' or 'horizontal').
'direction' => 'vertical',
// Keys of colors to use for the gradient.
'colors' => array('top', 'bottom'),
),
),
// Color areas to fill (x, y, width, height).
'fill' => array(
......
......@@ -6,10 +6,10 @@
max-width: 100%;
}
#preview, #preview #img {
width: 596px;
width: 600px;
height: 371px;
}
#preview #gradient {
#preview #gradient-0 {
position: absolute;
left: 0;
right: 0;
......@@ -29,7 +29,7 @@
position: relative;
z-index: 3;
}
#preview #gradient .gradient-line {
#preview #gradient-0 .gradient-line {
height: 10px;
overflow: hidden;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment