source: sipes/modules_contrib/ctools/includes/stylizer.inc @ a8b1f3f

stableversion-3.0
Last change on this file since a8b1f3f was 2efe680, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se actualizo el modulo

  • Propiedad mode establecida a 100755
File size: 51.4 KB
Línea 
1<?php
2/**
3 * @file
4 * Create customized CSS and images from palettes created by user input.
5 */
6
7/**
8 * Fetch metadata on a specific style_base plugin.
9 *
10 * @param $content type
11 *   Name of a panel content type.
12 *
13 * @return
14 *   An array with information about the requested stylizer style base.
15 */
16function ctools_get_style_base($style_base) {
17  ctools_include('plugins');
18  return ctools_get_plugins('ctools', 'style_bases', $style_base);
19}
20
21/**
22 * Fetch metadata for all style_base plugins.
23 *
24 * @return
25 *   An array of arrays with information about all available styleizer style bases.
26 */
27function ctools_get_style_bases() {
28  ctools_include('plugins');
29  return ctools_get_plugins('ctools', 'style_bases');
30}
31
32/**
33 * Fetch metadata about all of the style base types that are available.
34 */
35function ctools_get_style_base_types() {
36  $types = array();
37  foreach (module_implements('ctools_style_base_types') as $module) {
38    $types[$module] = module_invoke($module, 'ctools_style_base_types');
39  }
40
41  return $types;
42}
43
44/**
45 * Render the icon for a style base.
46 */
47function ctools_stylizer_print_style_icon($plugin, $print_title = TRUE) {
48  $file = $plugin['path'] . '/' . $plugin['icon'];
49  $title = $print_title ? $plugin['title'] : '';
50  return theme('ctools_style_icon', theme('image', $file), $title);
51}
52
53/**
54 * Theme the style icon image
55 */
56function theme_ctools_style_icon($image, $title = NULL) {
57  ctools_add_css('stylizer');
58  ctools_add_js('stylizer');
59  $output = '<div class="ctools-style-icon">';
60  $output .= $image;
61  if ($title) {
62    $output .= '<div class="caption">' . $title . '</div>';
63  }
64  $output .= '</div>';
65  return $output;
66}
67
68/**
69 * Add the necessary CSS for a stylizer plugin to the page.
70 *
71 * This will check to see if the images directory and the cached CSS
72 * exists and, if not, will regenerate everything needed.
73 */
74function ctools_stylizer_add_css($plugin, $settings) {
75  if (!file_exists(ctools_stylizer_get_image_path($plugin, $settings, FALSE))) {
76    ctools_stylizer_build_style($plugin, $settings, TRUE);
77    return;
78  }
79
80  ctools_include('css');
81  $filename = ctools_css_retrieve(ctools_stylizer_get_css_id($plugin, $settings));
82  if (!$filename) {
83    ctools_stylizer_build_style($plugin, $settings, TRUE);
84  }
85  else {
86    ctools_css_add_css($filename);
87  }
88}
89
90/**
91 * Build the files for a stylizer given the proper settings.
92 */
93function ctools_stylizer_build_style($plugin, $settings, $add_css = FALSE) {
94  $path = ctools_stylizer_get_image_path($plugin, $settings);
95  if (!$path) {
96    return;
97  }
98
99  $replacements = array();
100
101  // Set up palette conversions
102  foreach ($settings['palette'] as $key => $color) {
103    $replacements['%' . $key ] = $color;
104  }
105
106  // Process image actions:
107  if (!empty($plugin['actions'])) {
108    $processor = new ctools_stylizer_image_processor;
109    $processor->execute($path, $plugin, $settings);
110
111// @todo -- there needs to be an easier way to get at this.
112//  dsm($processor->message_log);
113    // Add filenames to our conversions.
114  }
115
116  // Convert and write the CSS file.
117  $css = file_get_contents($plugin['path'] . '/' . $plugin['css']);
118
119  // Replace %style keyword with our generated class name.
120  // @todo We need one more unique identifier I think.
121  $class = ctools_stylizer_get_css_class($plugin, $settings);
122  $replacements['%style'] = '.' . $class;
123
124  if (!empty($processor) && !empty($processor->paths)) {
125    foreach ($processor->paths as $file => $image) {
126      $replacements[$file] = file_create_url($image);
127    }
128  }
129
130  if (!empty($plugin['build']) && function_exists($plugin['build'])) {
131    $plugin['build']($plugin, $settings, $css, $replacements);
132  }
133
134  $css = strtr($css, $replacements);
135  ctools_include('css');
136  $filename = ctools_css_store(ctools_stylizer_get_css_id($plugin, $settings), $css, FALSE);
137
138  if ($add_css) {
139    ctools_css_add_css($filename);
140  }
141}
142
143/**
144 * Clean up no longer used files.
145 *
146 * To prevent excess clutter in the files directory, this should be called
147 * whenever a style is going out of use. When being deleted, but also when
148 * the palette is being changed.
149 */
150function ctools_stylizer_cleanup_style($plugin, $settings) {
151  ctools_include('css');
152  $path = ctools_stylizer_get_image_path($plugin, $settings, FALSE);
153  if ($path) {
154    ctools_stylizer_recursive_delete($path);
155  }
156
157  ctools_css_clear(ctools_stylizer_get_css_id($plugin, $settings));
158}
159
160/**
161 * Recursively delete all files and folders in the specified filepath, then
162 * delete the containing folder.
163 *
164 * Note that this only deletes visible files with write permission.
165 *
166 * @param string $path
167 *   A filepath relative to file_directory_path.
168 */
169function ctools_stylizer_recursive_delete($path) {
170  if (empty($path)) {
171    return;
172  }
173
174  $listing = $path . '/*';
175
176  foreach (glob($listing) as $file) {
177    if (is_file($file) === TRUE) {
178      @unlink($file);
179    }
180    elseif (is_dir($file) === TRUE) {
181      ctools_stylizer_recursive_delete($file);
182    }
183  }
184
185  @rmdir($path);
186}
187
188/**
189 * Get a safe name for the settings.
190 *
191 * This uses an md5 of the palette if the name is temporary so
192 * that multiple temporary styles on the same page can coexist
193 * safely.
194 */
195function ctools_stylizer_get_settings_name($settings) {
196  if ($settings['name'] != '_temporary') {
197    return $settings['name'];
198  }
199
200  return $settings['name'] . '-' . md5(serialize($settings['palette']));
201}
202
203/**
204 * Get the path where images will be stored for a given style plugin and settings.
205 *
206 * This function will make sure the path exists.
207 */
208function ctools_stylizer_get_image_path($plugin, $settings, $check = TRUE) {
209  $file = 'ctools/style/' . $settings['name'] . '/' . md5(serialize($settings['palette']));
210  $path = file_create_path($file);
211
212  if ($check && !ctools_file_check_directory($path)) {
213    $base = '';
214    foreach (explode('/', $file) as $bit) {
215      $base .= '/' . $bit;
216      $path = file_directory_path() . $base;
217      if (!ctools_file_check_directory($path, FILE_CREATE_DIRECTORY)) {
218        drupal_set_message(t('Unable to create CTools styles cache directory @path. Check the permissions on your files directory.', array('@path' => $path)), 'error');
219        return;
220      }
221    }
222  }
223
224  return $path;
225}
226
227/**
228 * Get the id used to cache CSS for a given style plugin and settings.
229 */
230function ctools_stylizer_get_css_id($plugin, $settings) {
231  return 'ctools-stylizer:' . $settings['name'] . ':' . md5(serialize($settings['palette']));
232}
233
234/**
235 * Get the class to use for a stylizer plugin.
236 */
237function ctools_stylizer_get_css_class($plugin, $settings) {
238  ctools_include('cleanstring');
239  return ctools_cleanstring($plugin['name'] . '-' . ctools_stylizer_get_settings_name($settings));
240}
241
242class ctools_stylizer_image_processor {
243  var $workspace = NULL;
244  var $name = NULL;
245
246  var $workspaces = array();
247
248  var $message_log = array();
249  var $error_log = array();
250
251  function execute($path, $plugin, $settings) {
252    $this->path = $path;
253    $this->plugin = $plugin;
254    $this->settings = $settings;
255    $this->palette = $settings['palette'];
256
257    if (is_string($plugin['actions']) && function_exists($plugin['actions'])) {
258      $actions = $plugin['actions']($plugin, $settings);
259    }
260    else if (is_array($plugin['actions'])) {
261      $actions = $plugin['actions'];
262    }
263
264    if (!empty($actions) && is_array($actions)) {
265      foreach ($plugin['actions'] as $action) {
266        $command = 'command_' . array_shift($action);
267        if (method_exists($this, $command)) {
268          call_user_func_array(array($this, $command), $action);
269        }
270      }
271    }
272
273    // Clean up buffers.
274    foreach ($this->workspaces as $name => $workspace) {
275      imagedestroy($this->workspaces[$name]);
276    }
277  }
278
279  function log($message, $type = 'normal') {
280    $this->message_log[] = $message;
281    if ($type == 'error') {
282      $this->error_log[] = $message;
283    }
284  }
285
286  function set_current_workspace($workspace) {
287    $this->log("Set current workspace: $workspace");
288    $this->workspace = &$this->workspaces[$workspace];
289    $this->name = $workspace;
290  }
291
292  /**
293   * Create a new workspace.
294   */
295  function command_new($name, $width, $height) {
296    $this->log("New workspace: $name ($width x $height)");
297    // Clean up if there was already a workspace there.
298    if (isset($this->workspaces[$name])) {
299      imagedestroy($this->workspaces[$name]);
300    }
301
302    $this->workspaces[$name] = imagecreatetruecolor($width, $height);
303    $this->set_current_workspace($name);
304
305    // Make sure the new workspace has a transparent color.
306
307    // Turn off transparency blending (temporarily)
308    imagealphablending($this->workspace, FALSE);
309
310    // Create a new transparent color for image
311    $color = imagecolorallocatealpha($this->workspace, 0, 0, 0, 127);
312
313    // Completely fill the background of the new image with allocated color.
314    imagefill($this->workspace, 0, 0, $color);
315
316    // Restore transparency blending
317    imagesavealpha($this->workspace, TRUE);
318
319  }
320
321  /**
322   * Create a new workspace a file.
323   *
324   * This will make the new workspace the current workspace.
325   */
326  function command_load($name, $file) {
327    $this->log("New workspace: $name (from $file)");
328    if (!file_exists($file)) {
329      // Try it relative to the plugin
330      $file = $this->plugin['path'] . '/' . $file;
331      if (!file_exists($file)) {
332        $this->log("Unable to open $file");
333        return;
334      }
335    }
336
337    // Clean up if there was already a workspace there.
338    if (isset($this->workspaces[$name])) {
339      imagedestroy($this->workspaces[$name]);
340    }
341
342    $this->workspaces[$name] = imagecreatefrompng($file);
343    $this->set_current_workspace($name);
344  }
345
346  /**
347   * Create a new workspace using the properties of an existing workspace
348   */
349  function command_new_from($name, $workspace) {
350    $this->log("New workspace: $name from existing $workspace");
351    if (empty($this->workspaces[$workspace])) {
352      $this->log("Workspace $name does not exist.", 'error');
353      return;
354    }
355
356    // Clean up if there was already a workspace there.
357    if (isset($this->workspaces[$name])) {
358      imagedestroy($this->workspaces[$name]);
359    }
360
361    $this->workspaces[$name] = $this->new_image($this->workspace[$workspace]);
362    $this->set_current_workspace($name);
363  }
364
365  /**
366   * Set the current workspace.
367   */
368  function command_workspace($name) {
369    $this->log("Set workspace: $name");
370    if (empty($this->workspaces[$name])) {
371      $this->log("Workspace $name does not exist.", 'error');
372      return;
373    }
374    $this->set_current_workspace($name);
375  }
376
377  /**
378   * Copy the contents of one workspace into the current workspace.
379   */
380  function command_merge_from($workspace, $x = 0, $y = 0) {
381    $this->log("Merge from: $workspace ($x, $y)");
382    if (empty($this->workspaces[$workspace])) {
383      $this->log("Workspace $name does not exist.", 'error');
384      return;
385    }
386
387    $this->merge($this->workspaces[$workspace], $this->workspace, $x, $y);
388  }
389
390  function command_merge_to($workspace, $x = 0, $y = 0) {
391    $this->log("Merge to: $workspace ($x, $y)");
392    if (empty($this->workspaces[$workspace])) {
393      $this->log("Workspace $name does not exist.", 'error');
394      return;
395    }
396
397    $this->merge($this->workspace, $this->workspaces[$workspace], $x, $y);
398    $this->set_current_workspace($workspace);
399  }
400
401  /**
402   * Blend an image into the current workspace.
403   */
404  function command_merge_from_file($file, $x = 0, $y = 0) {
405    $this->log("Merge from file: $file ($x, $y)");
406    if (!file_exists($file)) {
407      // Try it relative to the plugin
408      $file = $this->plugin['path'] . '/' . $file;
409      if (!file_exists($file)) {
410        $this->log("Unable to open $file");
411        return;
412      }
413    }
414
415    $source = imagecreatefrompng($file);
416
417    $this->merge($source, $this->workspace, $x, $y);
418
419    imagedestroy($source);
420  }
421
422  function command_fill($color, $x, $y, $width, $height) {
423    $this->log("Fill: $color ($x, $y, $width, $height)");
424    imagefilledrectangle($this->workspace, $x, $y, $x + $width, $y + $height, ctools_color_gd($this->workspace, $this->palette[$color]));
425  }
426
427  function command_gradient($from, $to, $x, $y, $width, $height, $direction = 'down') {
428    $this->log("Gradient: $from to $to ($x, $y, $width, $height) $direction");
429
430    if ($direction == 'down') {
431      for ($i = 0; $i < $height; ++$i) {
432        $color = ctools_color_blend($this->workspace, $this->palette[$from], $this->palette[$to], $i / ($height - 1));
433        imagefilledrectangle($this->workspace, $x, $y + $i, $x + $width, $y + $i + 1, $color);
434      }
435    }
436    else {
437      for ($i = 0; $i < $width; ++$i) {
438        $color = ctools_color_blend($this->workspace, $this->palette[$from], $this->palette[$to], $i / ($width - 1));
439        imagefilledrectangle($this->workspace, $x + $i, $y, $x + $i + 1, $y + $height, $color);
440      }
441    }
442  }
443
444  /**
445   * Colorize the current workspace with the given location.
446   *
447   * This uses simple color blending to colorize the image.
448   *
449   * @todo it is possible that this colorize could allow different methods for
450   * determining how to blend colors?
451   */
452  function command_colorize($color, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
453    if (!isset($x)) {
454      $whole_image = TRUE;
455      $x = $y = 0;
456      $width = imagesx($this->workspace);
457      $height = imagesy($this->workspace);
458    }
459    $this->log("Colorize: $color ($x, $y, $width, $height)");
460
461    $c = ctools_color_unpack($this->palette[$color]);
462
463    imagealphablending($this->workspace, FALSE);
464    imagesavealpha($this->workspace, TRUE);
465
466    // If PHP 5 use the nice imagefilter which is faster.
467    if (!empty($whole_image) && version_compare(phpversion(), '5.2.5', '>=') && function_exists('imagefilter')) {
468      imagefilter($this->workspace, IMG_FILTER_COLORIZE, $c[0], $c[1], $c[2]);
469    }
470    else {
471      // Otherwise we can do it the brute force way.
472      for ($j = 0; $j < $height; $j++) {
473        for ($i = 0; $i < $width; $i++) {
474          $current = imagecolorsforindex($this->workspace, imagecolorat($this->workspace, $i, $j));
475          $new_index = imagecolorallocatealpha($this->workspace, $c[0], $c[1], $c[2], $current['alpha']);
476          imagesetpixel($this->workspace, $i, $j, $new_index);
477        }
478      }
479    }
480  }
481
482  /**
483   * Colorize the current workspace with the given location.
484   *
485   * This uses a color replacement algorithm that retains luminosity but
486   * turns replaces all color with the specified color.
487   */
488  function command_hue($color, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
489    if (!isset($x)) {
490      $whole_image = TRUE;
491      $x = $y = 0;
492      $width = imagesx($this->workspace);
493      $height = imagesy($this->workspace);
494    }
495    $this->log("Hue: $color ($x, $y, $width, $height)");
496
497    list($red, $green, $blue) = ctools_color_unpack($this->palette[$color]);
498
499    // We will create a monochromatic palette based on the input color
500    // which will go from black to white.
501
502    // Input color luminosity: this is equivalent to the position of the
503    // input color in the monochromatic palette
504    $luminosity_input = round(255 * ($red + $green + $blue) / 765); // 765 = 255 * 3
505
506    // We fill the palette entry with the input color at itscorresponding position
507    $palette[$luminosity_input]['red'] = $red;
508    $palette[$luminosity_input]['green'] = $green;
509    $palette[$luminosity_input]['blue'] = $blue;
510
511    // Now we complete the palette, first we'll do it tothe black, and then to
512    // the white.
513
514    // From input to black
515    $steps_to_black = $luminosity_input;
516
517    // The step size for each component
518    if ($steps_to_black) {
519      $step_size_red = $red / $steps_to_black;
520      $step_size_green = $green / $steps_to_black;
521      $step_size_blue = $blue / $steps_to_black;
522
523      for ($i = $steps_to_black; $i >= 0; $i--) {
524        $palette[$steps_to_black-$i]['red'] = $red - round($step_size_red * $i);
525        $palette[$steps_to_black-$i]['green'] = $green - round($step_size_green * $i);
526        $palette[$steps_to_black-$i]['blue'] = $blue - round($step_size_blue * $i);
527      }
528    }
529
530    // From input to white
531    $steps_to_white = 255 - $luminosity_input;
532
533    if ($steps_to_white) {
534      $step_size_red = (255 - $red) / $steps_to_white;
535      $step_size_green = (255 - $green) / $steps_to_white;
536      $step_size_blue = (255 - $blue) / $steps_to_white;
537    }
538    else {
539      $step_size_red=$step_size_green=$step_size_blue=0;
540    }
541
542    // The step size for each component
543    for($i = ($luminosity_input + 1); $i <= 255; $i++) {
544      $palette[$i]['red'] = $red + round($step_size_red * ($i - $luminosity_input));
545      $palette[$i]['green'] = $green + round($step_size_green * ($i - $luminosity_input));
546      $palette[$i]['blue']= $blue + round($step_size_blue * ($i - $luminosity_input));
547    }
548
549    // Go over the specified area of the image and update the colors.
550    for ($j = $x; $j < $height; $j++) {
551      for ($i = $y; $i < $width; $i++) {
552        $color = imagecolorsforindex($this->workspace, imagecolorat($this->workspace, $i, $j));
553        $luminosity = round(255 * ($color['red'] + $color['green'] + $color['blue']) / 765);
554        $new_color = imagecolorallocatealpha($this->workspace, $palette[$luminosity]['red'], $palette[$luminosity]['green'], $palette[$luminosity]['blue'], $color['alpha']);
555        imagesetpixel($this->workspace, $i, $j, $new_color);
556      }
557    }
558  }
559
560  /**
561   * Take a slice out of the current workspace and save it as an image.
562   */
563  function command_slice($file, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
564    if (!isset($x)) {
565      $x = $y = 0;
566      $width = imagesx($this->workspace);
567      $height = imagesy($this->workspace);
568    }
569
570    $this->log("Slice: $file ($x, $y, $width, $height)");
571
572    $base = basename($file);
573    $image = $this->path . '/' . $base;
574
575    $slice = $this->new_image($this->workspace, $width, $height);
576    imagecopy($slice, $this->workspace, 0, 0, $x, $y, $width, $height);
577
578    // Make sure alphas are saved:
579    imagealphablending($slice, FALSE);
580    imagesavealpha($slice, TRUE);
581
582    // Save image.
583    imagepng($slice, $image);
584    imagedestroy($slice);
585
586    // Set standard file permissions for webserver-generated files
587    @chmod(realpath($image), 0664);
588
589    $this->paths[$file] = $image;
590  }
591
592  /**
593   * Prepare a new image for being copied or worked on, preserving transparency.
594   */
595  function &new_image(&$source, $width = NULL, $height = NULL) {
596    if (!isset($width)) {
597      $width = imagesx($source);
598    }
599
600    if (!isset($height)) {
601      $height = imagesy($source);
602    }
603
604    $target = imagecreatetruecolor($width, $height);
605    imagealphablending($target, FALSE);
606      imagesavealpha($target, TRUE);
607
608    $transparency_index = imagecolortransparent($source);
609
610    // If we have a specific transparent color
611    if ($transparency_index >= 0) {
612      // Get the original image's transparent color's RGB values
613      $transparent_color = imagecolorsforindex($source, $transparency_index);
614
615      // Allocate the same color in the new image resource
616      $transparency_index = imagecolorallocate($target, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
617
618      // Completely fill the background of the new image with allocated color.
619      imagefill($target, 0, 0, $transparency_index);
620
621      // Set the background color for new image to transparent
622      imagecolortransparent($target, $transparency_index);
623    }
624    // Always make a transparent background color for PNGs that don't have one allocated already
625    else {
626      // Create a new transparent color for image
627      $color = imagecolorallocatealpha($target, 0, 0, 0, 127);
628
629      // Completely fill the background of the new image with allocated color.
630      imagefill($target, 0, 0, $color);
631    }
632
633    return $target;
634  }
635
636  /**
637   * Merge two images together, preserving alpha transparency.
638   */
639  function merge(&$from, &$to, $x, $y) {
640    // Blend over template.
641    $width = imagesx($from);
642    $height = imagesy($from);
643
644    // Re-enable alpha blending to make sure transparency merges.
645    imagealphablending($to, TRUE);
646    imagecopy($to, $from, $x, $y, 0, 0, $width, $height);
647    imagealphablending($to, FALSE);
648  }
649}
650
651/**
652 * Get the cached changes to a given task handler.
653 */
654function ctools_stylizer_get_settings_cache($name) {
655  ctools_include('object-cache');
656  return ctools_object_cache_get('ctools_stylizer_settings', $name);
657}
658
659/**
660 * Store changes to a task handler in the object cache.
661 */
662function ctools_stylizer_set_settings_cache($name, $settings) {
663  ctools_include('object-cache');
664  ctools_object_cache_set('ctools_stylizer_settings', $name, $settings);
665}
666
667/**
668 * Remove an item from the object cache.
669 */
670function ctools_stylizer_clear_settings_cache($name) {
671  ctools_include('object-cache');
672  ctools_object_cache_clear('ctools_stylizer_settings', $name);
673}
674
675/**
676 * Add a new style of the specified type.
677 */
678function ctools_stylizer_edit_style(&$info, $js, $step = NULL) {
679  $name = '::new';
680  $form_info = array(
681    'id' => 'ctools_stylizer_edit_style',
682    'path' => $info['path'],
683    'show trail' => TRUE,
684    'show back' => TRUE,
685    'show return' => FALSE,
686    'next callback' => 'ctools_stylizer_edit_style_next',
687    'finish callback' => 'ctools_stylizer_edit_style_finish',
688    'return callback' => 'ctools_stylizer_edit_style_finish',
689    'cancel callback' => 'ctools_stylizer_edit_style_cancel',
690    'forms' => array(
691      'choose' => array(
692        'form id' => 'ctools_stylizer_edit_style_form_choose',
693      ),
694    ),
695  );
696
697  if (empty($info['settings'])) {
698    $form_info['order'] = array(
699      'choose' => t('Select base style'),
700    );
701    if (empty($step)) {
702      $step = 'choose';
703    }
704
705    if ($step != 'choose') {
706      $cache = ctools_stylizer_get_settings_cache($name);
707      if (!$cache) {
708        $output = t('Missing settings cache.');
709        if ($js) {
710          return ctools_modal_form_render($form_state, $output);
711        }
712        else {
713          return $output;
714        }
715      }
716
717      if (!empty($cache['owner settings'])) {
718        $info['owner settings'] = $cache['owner settings'];
719      }
720      $settings = $cache['settings'];
721    }
722    else {
723      $settings = array(
724        'name' => '_temporary',
725        'style_base' => NULL,
726        'palette' => array(),
727      );
728      ctools_stylizer_clear_settings_cache($name);
729    }
730    $op = 'add';
731  }
732  else {
733    $cache = ctools_stylizer_get_settings_cache($info['settings']['name']);
734
735    if (!empty($cache)) {
736      if (!empty($cache['owner settings'])) {
737        $info['owner settings'] = $cache['owner settings'];
738      }
739      $settings = $cache['settings'];
740    }
741    else {
742      $settings = $info['settings'];
743    }
744    $op = 'edit';
745  }
746
747  if (!empty($info['op'])) {
748    // Allow this to override. Necessary to allow cloning properly.
749    $op = $info['op'];
750  }
751
752  $plugin = NULL;
753  if (!empty($settings['style_base'])) {
754    $plugin = ctools_get_style_base($settings['style_base']);
755    $info['type'] = $plugin['type'];
756    ctools_stylizer_add_plugin_forms($form_info, $plugin, $op);
757  }
758  else {
759    // This is here so the 'finish' button does not show up, and because
760    // we don't have the selected style we don't know what the next form(s)
761    // will be.
762    $form_info['order']['next'] = t('Configure style');
763  }
764
765  if (count($form_info['order']) < 2 || $step == 'choose') {
766    $form_info['show trail'] = FALSE;
767  }
768
769  $form_state = array(
770    'module' => $info['module'],
771    'type' => $info['type'],
772    'owner info' => &$info,
773    'plugin' => $plugin,
774    'name' => $name,
775    'step' => $step,
776    'settings' => $settings,
777    'ajax' => $js,
778    'op' => $op,
779  );
780
781  if (!empty($info['modal'])) {
782    $form_state['modal'] = TRUE;
783    $form_state['title'] = $info['modal'];
784    $form_state['modal return'] = TRUE;
785  }
786
787  ctools_include('wizard');
788  $output = ctools_wizard_multistep_form($form_info, $step, $form_state);
789
790  if (!empty($form_state['complete'])) {
791    $info['complete'] = TRUE;
792    $info['settings'] = $form_state['settings'];
793  }
794
795  if ($js && !$output && !empty($form_state['clicked_button']['#next'])) {
796    // We have to do a separate redirect here because the formula that adds
797    // stuff to the wizard after being chosen hasn't happened. The wizard
798    // tried to go to the next step which did not exist.
799    return ctools_stylizer_edit_style($info, $js, $form_state['clicked_button']['#next']);
800  }
801
802  if ($js) {
803    return ctools_modal_form_render($form_state, $output);
804  }
805  else {
806    return $output;
807  }
808}
809
810/**
811 * Add wizard forms specific to a style base plugin.
812 *
813 * The plugin can store forms either as a simple 'edit form'
814 * => 'form callback' or if it needs the more complicated wizard
815 * functionality, it can set 'forms' and 'order' with values suitable
816 * for the wizard $form_info array.
817 *
818 * @param &$form_info
819 *   The form info to modify.
820 * @param $plugin
821 *   The plugin to use.
822 * @param $op
823 *   Either 'add' or 'edit' so we can get the right forms.
824 */
825function ctools_stylizer_add_plugin_forms(&$form_info, $plugin, $op) {
826  if (empty($plugin['forms'])) {
827    if ($op == 'add' && isset($plugin['add form'])) {
828      $id = $plugin['add form'];
829    }
830    else if (isset($plugin['edit form'])) {
831      $id = $plugin['edit form'];
832    }
833    else {
834      $id = 'ctools_stylizer_edit_style_form_default';
835    }
836
837    $form_info['forms']['settings'] = array(
838      'form id' => $id,
839    );
840    $form_info['order']['settings'] = t('Settings');
841  }
842  else {
843    $form_info['forms'] += $plugin['forms'];
844    $form_info['order'] += $plugin['order'];
845  }
846}
847
848/**
849 * Callback generated when the add style process is finished.
850 */
851function ctools_stylizer_edit_style_finish(&$form_state) {
852  $form_state['complete'] = TRUE;
853  ctools_stylizer_clear_settings_cache($form_state['name']);
854
855  if (isset($form_state['settings']['old_settings'])) {
856    unset($form_state['settings']['old_settings']);
857  }
858}
859
860/**
861 * Callback generated when the 'next' button is clicked.
862 */
863function ctools_stylizer_edit_style_next(&$form_state) {
864  $form_state['form_info']['path'] = str_replace('%name', $form_state['name'], $form_state['form_info']['path']);
865  $form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']);
866
867  // Update the cache with changes.
868  $cache = array('settings' => $form_state['settings']);
869  if (!empty($form_state['owner info']['owner settings'])) {
870    $cache['owner settings'] = $form_state['owner info']['owner settings'];
871  }
872  ctools_stylizer_set_settings_cache($form_state['name'], $cache);
873}
874
875/**
876 * Callback generated when the 'cancel' button is clicked.
877 *
878 * We might have some temporary data lying around. We must remove it.
879 */
880function ctools_stylizer_edit_style_cancel(&$form_state) {
881  if (!empty($form_state['name'])) {
882    ctools_stylizer_clear_settings_cache($form_state['name']);
883  }
884}
885
886/**
887 * Choose which plugin to use to create a new style.
888 */
889function ctools_stylizer_edit_style_form_choose(&$form, &$form_state) {
890  $plugins = ctools_get_style_bases();
891  $options = array();
892
893  $categories = array();
894  foreach ($plugins as $name => $plugin) {
895    if ($form_state['module'] == $plugin['module'] && $form_state['type'] == $plugin['type']) {
896      $categories[$plugin['category']] = $plugin['category'];
897      $unsorted_options[$plugin['category']][$name] = ctools_stylizer_print_style_icon($plugin, TRUE);
898    }
899  }
900
901  asort($categories);
902
903  foreach ($categories as $category) {
904    $options[$category] = $unsorted_options[$category];
905  }
906
907  $form['style_base'] = array(
908    '#prefix' => '<div class="ctools-style-icons clear-block">',
909    '#suffix' => '</div>',
910  );
911
912  ctools_include('cleanstring');
913  foreach ($options as $category => $radios) {
914    $cat = ctools_cleanstring($category);
915    $form['style_base'][$cat] = array(
916      '#prefix' => '<div class="ctools-style-category clear-block"><label>' . $category . '</label>',
917      '#suffix' => '</div>',
918    );
919
920    foreach ($radios as $key => $choice) {
921      // Generate the parents as the autogenerator does, so we will have a
922      // unique id for each radio button.
923      $form['style_base'][$cat][$key] = array(
924        '#type' => 'radio',
925        '#title' => $choice,
926        '#parents' => array('style_base'),
927        '#id' => form_clean_id('edit-style-base-' . $key),
928        '#return_value' => check_plain($key),
929      );
930    }
931  }
932}
933
934function ctools_stylizer_edit_style_form_choose_submit(&$form, &$form_state) {
935  $form_state['settings']['style_base'] = $form_state['values']['style_base'];
936
937  // The 'next' form will show up as 'next' but that's not accurate now that
938  // we have a style. Figure out what next really is and update.
939  $plugin = ctools_get_style_base($form_state['settings']['style_base']);
940  if (empty($plugin['forms'])) {
941    $form_state['clicked_button']['#next'] = 'settings';
942  }
943  else {
944    $forms = array_keys($form_info['forms']);
945    $form_state['clicked_button']['#next'] = array_shift($forms);
946  }
947
948  // Fill in the defaults for the settings.
949  if (!empty($plugin['defaults'])) {
950    // @todo allow a callback
951    $form_state['settings'] += $plugin['defaults'];
952  }
953}
954
955/**
956 * The default stylizer style editing form.
957 *
958 * Even when not using this, styles should call through to this form in
959 * their own edit forms.
960 */
961function ctools_stylizer_edit_style_form_default(&$form, &$form_state) {
962  ctools_add_js('stylizer');
963  ctools_add_css('stylizer');
964  drupal_add_js('misc/farbtastic/farbtastic.js');
965  drupal_add_css('misc/farbtastic/farbtastic.css');
966
967  $plugin = &$form_state['plugin'];
968  $settings = &$form_state['settings'];
969
970  $form['top box'] = array(
971    '#prefix' => '<div id="ctools-stylizer-top-box" class="clear-block">',
972    '#suffix' => '</div>',
973  );
974  $form['top box']['left'] = array(
975    '#prefix' => '<div id="ctools-stylizer-left-box">',
976    '#suffix' => '</div>',
977  );
978  $form['top box']['preview'] = array(
979    // We have a copy of the $form_state on $form because form theme functions
980    // do not get $form_state.
981    '#theme' => 'ctools_stylizer_preview_form',
982    '#form_state' => &$form_state,
983  );
984
985  $form['top box']['preview']['submit'] = array(
986    '#type' => 'submit',
987    '#value' => t('Preview'),
988  );
989
990  if (!empty($plugin['palette'])) {
991    $form['top box']['color'] = array(
992      '#type' => 'fieldset',
993      '#title' => t('Color scheme'),
994      '#attributes' => array('id' => 'ctools_stylizer_color_scheme_form', 'class' => 'ctools-stylizer-color-edit'),
995      '#theme' => 'ctools_stylizer_color_scheme_form',
996    );
997
998    $form['top box']['color']['palette']['#tree'] = true;
999
1000    foreach ($plugin['palette'] as $key => $color) {
1001      if (empty($settings['palette'][$key])) {
1002        $settings['palette'][$key] = $color['default_value'];
1003      }
1004
1005      $form['top box']['color']['palette'][$key] = array(
1006        '#type' => 'textfield',
1007        '#title' => $color['label'],
1008        '#default_value' => $settings['palette'][$key],
1009        '#size' => 8,
1010      );
1011    }
1012  }
1013
1014  if (!empty($plugin['settings form']) && function_exists($plugin['settings form'])) {
1015    $plugin['settings form']($form, $form_state);
1016  }
1017
1018  if (!empty($form_state['owner info']['owner form']) && function_exists($form_state['owner info']['owner form'])) {
1019    $form_state['owner info']['owner form']($form, $form_state);
1020  }
1021}
1022
1023/**
1024 * Theme the stylizer color scheme form.
1025 */
1026function theme_ctools_stylizer_color_scheme_form($form) {
1027  $output = '';
1028
1029  // Wrapper
1030  $output .= '<div class="color-form clear-block">';
1031
1032  // Color schemes
1033//  $output .= drupal_render($form['scheme']);
1034
1035  // Palette
1036  $output .= '<div id="palette" class="clear-block">';
1037  foreach (element_children($form['palette']) as $name) {
1038    $output .= drupal_render($form['palette'][$name]);
1039  }
1040  $output .= '</div>'; // palette
1041
1042  $output .= '</div>'; // color form
1043
1044  return $output;
1045}
1046
1047/**
1048 * Theme the stylizer preview form.
1049 */
1050function theme_ctools_stylizer_preview_form($form) {
1051  $plugin = $form['#form_state']['plugin'];
1052  $settings = $form['#form_state']['settings'];
1053
1054  if (!empty($form['#form_state']['settings']['old_settings'])) {
1055    ctools_stylizer_cleanup_style($plugin, $form['#form_state']['settings']['old_settings']);
1056  }
1057  $preview = '';
1058  if (!empty($plugin['preview'])) {
1059    $preview = $plugin['preview'];
1060  }
1061  else {
1062    $base_types = ctools_get_style_base_types();
1063    if (!empty($base_types[$plugin['module']][$plugin['type']]['preview'])) {
1064      $preview = $base_types[$plugin['module']][$plugin['type']]['preview'];
1065    }
1066  }
1067
1068  if (!empty($preview) && function_exists($preview)) {
1069    $output = '<fieldset id="preview"><legend>' . t('Preview') . '</legend>';
1070    $output .= $preview($plugin, $settings);
1071    $output .= drupal_render($form);
1072    $output .= '</fieldset>';
1073
1074    return $output;
1075  }
1076}
1077
1078function ctools_stylizer_edit_style_form_default_validate($form, &$form_state) {
1079  if (!empty($form_state['owner info']['owner form validate']) && function_exists($form_state['owner info']['owner form validate'])) {
1080    $form_state['owner info']['owner form validate']($form, $form_state);
1081  }
1082
1083  if (!empty($form_state['plugin']['settings form validate']) && function_exists($form_state['plugin']['settings form validate'])) {
1084    $form_state['plugin']['settings form validate']($form, $form_state);
1085  }
1086}
1087
1088function ctools_stylizer_edit_style_form_default_submit($form, &$form_state) {
1089  // Store old settings for the purposes of cleaning up.
1090  $form_state['settings']['old_settings'] = $form_state['settings'];
1091  $form_state['settings']['palette'] = $form_state['values']['palette'];
1092
1093  if (!empty($form_state['owner info']['owner form submit']) && function_exists($form_state['owner info']['owner form submit'])) {
1094    $form_state['owner info']['owner form submit']($form, $form_state);
1095  }
1096
1097  if (!empty($form_state['plugin']['settings form submit']) && function_exists($form_state['plugin']['settings form submit'])) {
1098    $form_state['plugin']['settings form submit']($form, $form_state);
1099  }
1100
1101  if ($form_state['clicked_button']['#value'] == t('Preview')) {
1102    $form_state['rerender'] = TRUE;
1103    // Update the cache with changes.
1104    if (!empty($form_state['name'])) {
1105      $cache = array('settings' => $form_state['settings']);
1106      if (!empty($form_state['owner info']['owner settings'])) {
1107        $cache['owner settings'] = $form_state['owner info']['owner settings'];
1108      }
1109      ctools_stylizer_set_settings_cache($form_state['name'], $cache);
1110    }
1111  }
1112}
1113
1114// --------------------------------------------------------------------------
1115// CSS forms and tools that plugins can use.
1116
1117/**
1118 * Font selector form
1119 */
1120function ctools_stylizer_font_selector_form(&$form, &$form_state, $label, $settings) {
1121  // Family
1122  $form['#prefix'] = '<div class="ctools-stylizer-spacing-form clear-block">';
1123  $form['#type'] = 'fieldset';
1124  $form['#title'] = $label;
1125  $form['#suffix'] = '</div>';
1126  $form['#tree'] = TRUE;
1127
1128  $form['font'] = array(
1129    '#title' => t('Font family'),
1130    '#type' => 'select',
1131    '#default_value' => isset($settings['font']) ? $settings['font'] : '',
1132    '#options' => array(
1133      '' => '',
1134      'Arial, Helvetica, sans-serif' => t('Arial, Helvetica, sans-serif'),
1135      'Times New Roman, Times, serif' => t('Times New Roman, Times, serif'),
1136      'Courier New, Courier, monospace' => t('Courier New, Courier, monospace'),
1137      'Georgia, Times New Roman, Times, serif' => t('Georgia, Times New Roman, Times, serif'),
1138      'Verdana, Arial, Helvetica, sans-serif' => t('Verdana, Arial, Helvetica, sans-serif'),
1139      'Geneva, Arial, Helvetica, sans-serif' => t('Geneva, Arial, Helvetica, sans-serif'),
1140      'Trebuchet MS, Trebuchet, Verdana, sans-serif' => t('Trebuchet MS, Trebuchet, Verdana, sans-serif'),
1141    ),
1142  );
1143
1144  // size
1145  $form['size'] = array(
1146    '#title' => t('Size'),
1147    '#type' => 'select',
1148    '#default_value' => isset($settings['size']) ? $settings['size'] : '',
1149    '#options' => array(
1150      '' => '',
1151      'xx-small' => t('XX-Small'),
1152      'x-small' => t('X-Small'),
1153      'small' => t('Small'),
1154      'medium' => t('Medium'),
1155      'large' => t('Large'),
1156      'x-large' => t('X-Large'),
1157      'xx-large' => t('XX-Large'),
1158    ),
1159  );
1160
1161  // letter spacing
1162  $form['letter_spacing'] = array(
1163    '#title' => t('Letter spacing'),
1164    '#type' => 'select',
1165    '#default_value' => isset($settings['letter_spacing']) ? $settings['letter_spacing'] : '',
1166    '#options' => array(
1167      '' => '',
1168      "-10px" => '10px',
1169      "-9px" => '9px',
1170      "-8px" => '8px',
1171      "-7px" => '7px',
1172      "-6px" => '6px',
1173      "-5px" => '5px',
1174      "-4px" => '4px',
1175      "-3px" => '3px',
1176      "-2px" => '2px',
1177      "-1px" => '1px',
1178      "0" => '0',
1179      "1px" => '1px',
1180      "2px" => '2px',
1181      "3px" => '3px',
1182      "4px" => '4px',
1183      "5px" => '5px',
1184      "6px" => '6px',
1185      "7px" => '7px',
1186      "8px" => '8px',
1187      "9px" => '9px',
1188      "10px" => '10px',
1189      "11px" => '11px',
1190      "12px" => '12px',
1191      "13px" => '13px',
1192      "14px" => '14px',
1193      "15px" => '15px',
1194      "16px" => '16px',
1195      "17px" => '17px',
1196      "18px" => '18px',
1197      "19px" => '19px',
1198      "20px" => '20px',
1199      "21px" => '21px',
1200      "22px" => '22px',
1201      "23px" => '23px',
1202      "24px" => '24px',
1203      "25px" => '25px',
1204      "26px" => '26px',
1205      "27px" => '27px',
1206      "28px" => '28px',
1207      "29px" => '29px',
1208      "30px" => '30px',
1209      "31px" => '31px',
1210      "32px" => '32px',
1211      "33px" => '33px',
1212      "34px" => '34px',
1213      "35px" => '35px',
1214      "36px" => '36px',
1215      "37px" => '37px',
1216      "38px" => '38px',
1217      "39px" => '39px',
1218      "40px" => '40px',
1219      "41px" => '41px',
1220      "42px" => '42px',
1221      "43px" => '43px',
1222      "44px" => '44px',
1223      "45px" => '45px',
1224      "46px" => '46px',
1225      "47px" => '47px',
1226      "48px" => '48px',
1227      "49px" => '49px',
1228      "50px" => '50px',
1229    ),
1230  );
1231
1232  // word space
1233  $form['word_spacing'] = array(
1234    '#title' => t('Word spacing'),
1235    '#type' => 'select',
1236    '#default_value' => isset($settings['word_spacing']) ? $settings['word_spacing'] : '',
1237    '#options' => array(
1238      '' => '',
1239      "-1em" => '-1em',
1240      "-0.95em" => '-0.95em',
1241      "-0.9em" => '-0.9em',
1242      "-0.85em" => '-0.85em',
1243      "-0.8em" => '-0.8em',
1244      "-0.75em" => '-0.75em',
1245      "-0.7em" => '-0.7em',
1246      "-0.65em" => '-0.65em',
1247      "-0.6em" => '-0.6em',
1248      "-0.55em" => '-0.55em',
1249      "-0.5em" => '-0.5em',
1250      "-0.45em" => '-0.45em',
1251      "-0.4em" => '-0.4em',
1252      "-0.35em" => '-0.35em',
1253      "-0.3em" => '-0.3em',
1254      "-0.25em" => '-0.25em',
1255      "-0.2em" => '-0.2em',
1256      "-0.15em" => '-0.15em',
1257      "-0.1em" => '-0.1em',
1258      "-0.05em" => '-0.05em',
1259      "normal" => 'normal',
1260      "0.05em" => '0.05em',
1261      "0.1em" => '0.1em',
1262      "0.15em" => '0.15em',
1263      "0.2em" => '0.2em',
1264      "0.25em" => '0.25em',
1265      "0.3em" => '0.3em',
1266      "0.35em" => '0.35em',
1267      "0.4em" => '0.4em',
1268      "0.45em" => '0.45em',
1269      "0.5em" => '0.5em',
1270      "0.55em" => '0.55em',
1271      "0.6em" => '0.6em',
1272      "0.65em" => '0.65em',
1273      "0.7em" => '0.7em',
1274      "0.75em" => '0.75em',
1275      "0.8em" => '0.8em',
1276      "0.85em" => '0.85em',
1277      "0.9em" => '0.9em',
1278      "0.95em" => '0.95em',
1279      "1em" => '1em',
1280    ),
1281  );
1282
1283  // decoration
1284  $form['decoration'] = array(
1285    '#title' => t('Decoration'),
1286    '#type' => 'select',
1287    '#default_value' => isset($settings['decoration']) ? $settings['decoration'] : '',
1288    '#options' => array(
1289      '' => '',
1290      'none' => t('None'),
1291      'underline' => t('Underline'),
1292      'overline' => t('Overline'),
1293      'line-through' => t('Line-through'),
1294    ),
1295  );
1296
1297  // weight
1298  $form['weight'] = array(
1299    '#title' => t('Weight'),
1300    '#type' => 'select',
1301    '#default_value' => isset($settings['weight']) ? $settings['weight'] : '',
1302    '#options' => array(
1303      '' => '',
1304      'normal' => t('Normal'),
1305      'bold' => t('Bold'),
1306      'bolder' => t('Bolder'),
1307      'lighter' => t('Lighter'),
1308    ),
1309  );
1310
1311  // style
1312  $form['style'] = array(
1313    '#title' => t('Style'),
1314    '#type' => 'select',
1315    '#default_value' => isset($settings['style']) ? $settings['style'] : '',
1316    '#options' => array(
1317      '' => '',
1318      'normal' => t('Normal'),
1319      'italic' => t('Italic'),
1320      'oblique' => t('Oblique'),
1321    ),
1322  );
1323
1324  // variant
1325  $form['variant'] = array(
1326    '#title' => t('Variant'),
1327    '#type' => 'select',
1328    '#default_value' => isset($settings['variant']) ? $settings['variant'] : '',
1329    '#options' => array(
1330      '' => '',
1331      'normal' => t('Normal'),
1332      'small-caps' => t('Small-caps'),
1333    ),
1334  );
1335
1336  // case
1337  $form['case'] = array(
1338    '#title' => t('Case'),
1339    '#type' => 'select',
1340    '#default_value' => isset($settings['case']) ? $settings['case'] : '',
1341    '#options' => array(
1342      '' => '',
1343      'capitalize' => t('Capitalize'),
1344      'uppercase' => t('Uppercase'),
1345      'lowercase' => t('Lowercase'),
1346      'none' => t('None'),
1347    ),
1348  );
1349
1350  // alignment
1351  $form['alignment'] = array(
1352    '#title' => t('Align'),
1353    '#type' => 'select',
1354    '#default_value' => isset($settings['alignment']) ? $settings['alignment'] : '',
1355    '#options' => array(
1356      '' => '',
1357      'justify' => t('Justify'),
1358      'left' => t('Left'),
1359      'right' => t('Right'),
1360      'center' => t('Center'),
1361    ),
1362  );
1363}
1364
1365/**
1366 * Copy font selector information into the settings
1367 */
1368function ctools_stylizer_font_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
1369  $settings = $values;
1370}
1371
1372function ctools_stylizer_font_apply_style(&$stylesheet, $selector, $settings) {
1373  $css = '';
1374  if (isset($settings['font']) && $settings['font'] !== '') {
1375    $css .= '  font-family: ' . $settings['font'] . ";\n";
1376  }
1377
1378  if (isset($settings['size']) && $settings['size'] !== '') {
1379    $css .= '  font-size: ' . $settings['size'] . ";\n";
1380  }
1381
1382  if (isset($settings['weight']) && $settings['weight'] !== '') {
1383    $css .= '  font-weight: ' . $settings['weight'] . ";\n";
1384  }
1385
1386  if (isset($settings['style']) && $settings['style'] !== '') {
1387    $css .= '  font-style: ' . $settings['style'] . ";\n";
1388  }
1389
1390  if (isset($settings['variant']) && $settings['variant'] !== '') {
1391    $css .= '  font-variant: ' . $settings['variant'] . ";\n";
1392  }
1393
1394  if (isset($settings['case']) && $settings['case'] !== '') {
1395    $css .= '  text-transform: ' . $settings['case'] . ";\n";
1396  }
1397
1398  if (isset($settings['decoration']) && $settings['decoration'] !== '') {
1399    $css .= '  text-decoration: ' . $settings['decoration'] . ";\n";
1400  }
1401
1402  if (isset($settings['alignment']) && $settings['alignment'] !== '') {
1403    $css .= '  text-align: ' . $settings['alignment'] . ";\n";
1404  }
1405
1406  if (isset($settings['letter_spacing']) && $settings['letter_spacing'] !== '') {
1407    $css .= '  letter-spacing: ' . $settings['letter_spacing'] . ";\n";
1408  }
1409
1410  if (isset($settings['word_spacing']) && $settings['word_spacing'] !== '') {
1411    $css .= '  word-spacing: ' . $settings['word_spacing'] . ";\n";
1412  }
1413
1414  if ($css) {
1415    $stylesheet .= $selector . " {\n" . $css . "}\n";
1416  }
1417}
1418
1419/**
1420 * Border selector form
1421 */
1422function ctools_stylizer_border_selector_form(&$form, &$form_state, $label, $settings) {
1423  // Family
1424  $form['#prefix'] = '<div class="ctools-stylizer-spacing-form clear-block">';
1425  $form['#type'] = 'fieldset';
1426  $form['#title'] = $label;
1427  $form['#suffix'] = '</div>';
1428  $form['#tree'] = TRUE;
1429
1430  $form['thickness'] = array(
1431    '#title' => t('Thickness'),
1432    '#type' => 'select',
1433    '#default_value' => isset($settings['thickness']) ? $settings['thickness'] : '',
1434    '#options' => array(
1435      '' => '',
1436      "none" => t('None'),
1437      "1px" => '1px',
1438      "2px" => '2px',
1439      "3px" => '3px',
1440      "4px" => '4px',
1441      "5px" => '5px',
1442    ),
1443  );
1444
1445  $form['style'] = array(
1446    '#title' => t('style'),
1447    '#type' => 'select',
1448    '#default_value' => isset($settings['style']) ? $settings['style'] : '',
1449    '#options' => array(
1450      '' => '',
1451      'solid' => t('Solid'),
1452      'dotted' => t('Dotted'),
1453      'dashed' => t('Dashed'),
1454      'double' => t('Double'),
1455      'groove' => t('Groove'),
1456      'ridge' => t('Ridge'),
1457      'inset' => t('Inset'),
1458      'outset' => t('Outset'),
1459    ),
1460  );
1461}
1462
1463/**
1464 * Copy border selector information into the settings
1465 */
1466function ctools_stylizer_border_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
1467  $settings = $values;
1468}
1469
1470function ctools_stylizer_border_apply_style(&$stylesheet, $selector, $settings, $color, $which = NULL) {
1471  $border = 'border';
1472  if ($which) {
1473    $border .= '-' . $which;
1474  }
1475
1476  $css = '';
1477  if (isset($settings['thickness']) && $settings['thickness'] !== '') {
1478    if ($settings['thickness'] == 'none') {
1479      $css .= '  ' . $border . ': none';
1480    }
1481    else {
1482      $css .= '  ' . $border . '-width: ' . $settings['thickness'] . ";\n";
1483
1484      if (isset($settings['style']) && $settings['style'] !== '') {
1485        $css .= '  ' . $border . '-style: ' . $settings['style'] . ";\n";
1486      }
1487
1488      $css .= '  ' . $border . '-color: ' . $color . ";\n";
1489    }
1490  }
1491
1492  if ($css) {
1493    $stylesheet .= $selector . " {\n" . $css . "}\n";
1494  }
1495
1496}
1497
1498/**
1499 * padding selector form
1500 */
1501function ctools_stylizer_padding_selector_form(&$form, &$form_state, $label, $settings) {
1502  // Family
1503  $form['#prefix'] = '<div class="ctools-stylizer-spacing-form clear-block">';
1504  $form['#type'] = 'fieldset';
1505  $form['#title'] = $label;
1506  $form['#suffix'] = '</div>';
1507  $form['#tree'] = TRUE;
1508
1509  $options = array(
1510    '' => '',
1511    "0.05em" => '0.05em',
1512    "0.1em" => '0.1em',
1513    "0.15em" => '0.15em',
1514    "0.2em" => '0.2em',
1515    "0.25em" => '0.25em',
1516    "0.3em" => '0.3em',
1517    "0.35em" => '0.35em',
1518    "0.4em" => '0.4em',
1519    "0.45em" => '0.45em',
1520    "0.5em" => '0.5em',
1521    "0.55em" => '0.55em',
1522    "0.6em" => '0.6em',
1523    "0.65em" => '0.65em',
1524    "0.7em" => '0.7em',
1525    "0.75em" => '0.75em',
1526    "0.8em" => '0.8em',
1527    "0.85em" => '0.85em',
1528    "0.9em" => '0.9em',
1529    "0.95em" => '0.95em',
1530    "1.0em" => '1.0em',
1531    "1.05em" => '1.05em',
1532    "1.1em" => '1.1em',
1533    "1.15em" => '1.15em',
1534    "1.2em" => '1.2em',
1535    "1.25em" => '1.25em',
1536    "1.3em" => '1.3em',
1537    "1.35em" => '1.35em',
1538    "1.4em" => '1.4em',
1539    "1.45em" => '1.45em',
1540    "1.5em" => '1.5em',
1541    "1.55em" => '1.55em',
1542    "1.6em" => '1.6em',
1543    "1.65em" => '1.65em',
1544    "1.7em" => '1.7em',
1545    "1.75em" => '1.75em',
1546    "1.8em" => '1.8em',
1547    "1.85em" => '1.85em',
1548    "1.9em" => '1.9em',
1549    "1.95em" => '1.95em',
1550    "2.0em" => '2.0em',
1551    "2.05em" => '2.05em',
1552    "2.1em" => '2.1em',
1553    "2.15em" => '2.15em',
1554    "2.2em" => '2.2em',
1555    "2.25em" => '2.25em',
1556    "2.3em" => '2.3em',
1557    "2.35em" => '2.35em',
1558    "2.4em" => '2.4em',
1559    "2.45em" => '2.45em',
1560    "2.5em" => '2.5em',
1561    "2.55em" => '2.55em',
1562    "2.6em" => '2.6em',
1563    "2.65em" => '2.65em',
1564    "2.7em" => '2.7em',
1565    "2.75em" => '2.75em',
1566    "2.8em" => '2.8em',
1567    "2.85em" => '2.85em',
1568    "2.9em" => '2.9em',
1569    "2.95em" => '2.95em',
1570    "3.0em" => '3.0em',
1571    "3.05em" => '3.05em',
1572    "3.1em" => '3.1em',
1573    "3.15em" => '3.15em',
1574    "3.2em" => '3.2em',
1575    "3.25em" => '3.25em',
1576    "3.3em" => '3.3em',
1577    "3.35em" => '3.35em',
1578    "3.4em" => '3.4em',
1579    "3.45em" => '3.45em',
1580    "3.5em" => '3.5em',
1581    "3.55em" => '3.55em',
1582    "3.6em" => '3.6em',
1583    "3.65em" => '3.65em',
1584    "3.7em" => '3.7em',
1585    "3.75em" => '3.75em',
1586    "3.8em" => '3.8em',
1587    "3.85em" => '3.85em',
1588    "3.9em" => '3.9em',
1589    "3.95em" => '3.95em',
1590  );
1591
1592  $form['top'] = array(
1593    '#title' => t('Top'),
1594    '#type' => 'select',
1595    '#default_value' => isset($settings['top']) ? $settings['top'] : '',
1596    '#options' => $options,
1597  );
1598
1599  $form['right'] = array(
1600    '#title' => t('Right'),
1601    '#type' => 'select',
1602    '#default_value' => isset($settings['right']) ? $settings['right'] : '',
1603    '#options' => $options,
1604  );
1605
1606  $form['bottom'] = array(
1607    '#title' => t('Bottom'),
1608    '#type' => 'select',
1609    '#default_value' => isset($settings['bottom']) ? $settings['bottom'] : '',
1610    '#options' => $options,
1611  );
1612
1613  $form['left'] = array(
1614    '#title' => t('Left'),
1615    '#type' => 'select',
1616    '#default_value' => isset($settings['left']) ? $settings['left'] : '',
1617    '#options' => $options,
1618  );
1619}
1620
1621/**
1622 * Copy padding selector information into the settings
1623 */
1624function ctools_stylizer_padding_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
1625  $settings = $values;
1626}
1627
1628function ctools_stylizer_padding_apply_style(&$stylesheet, $selector, $settings) {
1629  $css = '';
1630
1631  if (isset($settings['top']) && $settings['top'] !== '') {
1632    $css .= '  padding-top: ' . $settings['top'] . ";\n";
1633  }
1634
1635  if (isset($settings['right']) && $settings['right'] !== '') {
1636    $css .= '  padding-right: ' . $settings['right'] . ";\n";
1637  }
1638
1639  if (isset($settings['bottom']) && $settings['bottom'] !== '') {
1640    $css .= '  padding-bottom: ' . $settings['bottom'] . ";\n";
1641  }
1642
1643  if (isset($settings['left']) && $settings['left'] !== '') {
1644    $css .= '  padding-left: ' . $settings['left'] . ";\n";
1645  }
1646
1647  if ($css) {
1648    $stylesheet .= $selector . " {\n" . $css . "}\n";
1649  }
1650
1651}
1652
1653/**
1654 * Check to see that a directory exists.
1655 *
1656 * This is an exact copy of core's, but without the stupid drupal_set_message
1657 * because we need this to be silent.
1658 *
1659 * @todo this should probably be in another file.
1660 */
1661function ctools_file_check_directory(&$directory, $mode = 0, $form_item = NULL) {
1662  $directory = rtrim($directory, '/\\');
1663
1664  // Check if directory exists.
1665  if (!is_dir($directory)) {
1666    if (($mode & FILE_CREATE_DIRECTORY) && @mkdir($directory)) {
1667      @chmod($directory, 0775); // Necessary for non-webserver users.
1668    }
1669    else {
1670      if ($form_item) {
1671        form_set_error($form_item, t('The directory %directory does not exist.', array('%directory' => $directory)));
1672      }
1673      return FALSE;
1674    }
1675  }
1676
1677  // Check to see if the directory is writable.
1678  if (!is_writable($directory)) {
1679    if (($mode & FILE_MODIFY_PERMISSIONS) && @chmod($directory, 0775)) {
1680      drupal_set_message(t('The permissions of directory %directory have been changed to make it writable.', array('%directory' => $directory)));
1681    }
1682    else {
1683      form_set_error($form_item, t('The directory %directory is not writable', array('%directory' => $directory)));
1684      watchdog('file system', 'The directory %directory is not writable, because it does not have the correct permissions set.', array('%directory' => $directory), WATCHDOG_ERROR);
1685      return FALSE;
1686    }
1687  }
1688
1689  if ((file_directory_path() == $directory || file_directory_temp() == $directory) && !is_file("$directory/.htaccess")) {
1690    $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks";
1691    if (($fp = fopen("$directory/.htaccess", 'w')) && fputs($fp, $htaccess_lines)) {
1692      fclose($fp);
1693      chmod($directory .'/.htaccess', 0664);
1694    }
1695    else {
1696      $variables = array('%directory' => $directory, '!htaccess' => '<br />'. nl2br(check_plain($htaccess_lines)));
1697      form_set_error($form_item, t("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>!htaccess</code>", $variables));
1698      watchdog('security', "Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>!htaccess</code>", $variables, WATCHDOG_ERROR);
1699    }
1700  }
1701
1702  return TRUE;
1703}
1704
1705/**
1706 * Blend two hex colors and return the GD color.
1707 */
1708function ctools_color_blend($img, $hex1, $hex2, $alpha) {
1709  $in1 = ctools_color_unpack($hex1);
1710  $in2 = ctools_color_unpack($hex2);
1711  $out = array($img);
1712  for ($i = 0; $i < 3; ++$i) {
1713    $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha;
1714  }
1715  return call_user_func_array('imagecolorallocate', $out);
1716}
1717
1718/**
1719 * Convert a hex color into an RGB triplet.
1720 */
1721function ctools_color_unpack($hex, $normalize = false) {
1722  if (strlen($hex) == 4) {
1723    $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
1724  }
1725  $c = hexdec($hex);
1726  for ($i = 16; $i >= 0; $i -= 8) {
1727    $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
1728  }
1729  return $out;
1730}
1731
1732/**
1733 * Convert a hex triplet into a GD color.
1734 */
1735function ctools_color_gd($img, $hex) {
1736  $c = array_merge(array($img), ctools_color_unpack($hex));
1737  return call_user_func_array('imagecolorallocate', $c);
1738}
1739
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.