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