diff --git docs/STYLE_PLUGINS.txt docs/STYLE_PLUGINS.txt new file mode 100644 index 0000000..f9704f5 --- /dev/null +++ docs/STYLE_PLUGINS.txt @@ -0,0 +1,181 @@ +$Id$ + +Current for 6.x-2.x + +Style plugins are code snippets providing style context +callbacks to OpenLayers styles. + +Such callbacks (written in JavaScript) are needed to provide +styling which is dependent on characteristics which are not +known at time of PHP rendering. + +A common example is changing pointRadius style property based +on the number of features taking place in a cluster, whereas +clustering is performed by JavaScript and so cluster composition +changes w/out PHP being invoked. + +# Creating a new OpenLayers Style Plugin from Scratch + +First, you'll need to create a module. Of course, skip through this step if +there's already a module that exists to which this style plugin will be added. +But if not, create a file called `modulename.info` with the contents + + core = "6.x" + dependencies[] = "openlayers" + name = "modulename" + package = "OpenLayers" + project = "modulename" + +Then you'll want to register your style plugins. + +## Registering plugins directory + +This is done implementing `hook_ctools_plugin_directory' +and `hook_ctools_plugin_api'. + +Since your module is called `modulename', their implementation would be: + + function modulename_ctools_plugin_api($module, $api) { + // Define plugins for OpenLayers plugins api + if ($module == "openlayers") { + switch ($api) { + case 'openlayers_styles': + return array('version' => 1); + } + } + } + + function modulename_ctools_plugin_directory($module, $plugin) { + if ($module == 'openlayers' && $plugin == 'style_plugin') { + return 'plugins/style_plugin'; + } + } + +At that point you can put actual plugins, one file per plugin, +in the `plugins/style_plugin' directory, or whatever you returned +from the `hook_ctools_plugin_directory' implementation. + +## Writing the minimal PHP side of plugin + +A plugin file starts with a plugin definition, like the +following: + + // Define plugin for CTools + $plugin = array( + 'title' => t('My style plugin title'), + 'description' => t('What this plugin does'), + 'style_plugin' => array( + 'class' => 'modulename_pluginname', // <-- NOTE! + 'parent' => 'openlayers_style_plugin', + ), + ); + +The above definition says that the plugin is implemented by +the `modulename_pluginname' class (see NOTE above), which is +a subclass of `openlayers_style_plugin`. We implement that next: + + + class modulename_pluginname extends openlayers_style_plugin { + + // Advertise which style properties we expose support for, + // and which callback to use for each one + function get_context_properties() { + return array( + 'label' => 'getLabel' // <-- NOTE ! + ); + } + + // Send the JS file containing the JavaScript side + // implementation of the plugin. + function render() { + drupal_add_js(drupal_get_path('module', 'modulename') . + '/plugins/style_plugin/modulename_pluginname.js'); + } + + } + +The above definition provides NO parameters to the actual context +callback function. We'll see how to add configurability later. +For now let's move on to the JavaScript side. + +## Writing the JavaScript side of plugin + +The OpenLayers module renderer will expect to find a +Drupal.openlayers.style_plugins. +Javascript class, as specified by the 'class' attribute of +the 'style_plugin' array in the PHP plugin definition. + +The JavaScript side of style plugin will be put in the file +referenced by the render() function of the PHP part, and will need +to provide this class. As with the following example: + + // Define the class constructor + Drupal.openlayers.style_plugin.modulename_pluginname = function (params) { + this.params = params; + }; + +Note that the constructor can take parameters, which the PHP side +of the style plugin can export to let user configure the style plugin. +We'll see this later. + +In addition to the constructor, the Drupal OpenLayers module (`DOL', +from now on) will also expect to find the callbacks advertised +by the `get_context_properties` function of the PHP side of the style +plugin. We'll need to provide those as well. They can be defined +in the class prototype: + + // Style plugin class prototype + Drupal.openlayers.style_plugin.modulename_pluginname.prototype = { + + // Style context function + 'getLabel' = function(feature) { + return feature.attributes.length; + } + + } + +## Providing configurability of style plugin + +The PHP side of code can provide a configuration form for the plugin. +As you saw above, the JavaScript class constructor will be passed +configuration parameters. These parameters you can define from +the PHP side, defining an options_form() and optionally an +options_init() method. Example: + + function options_init() { + return array( + 'feature_weight' => 2, + 'point_radius_min' => 6, + 'point_radius_max' => 12, + ); + } + + function options_form($defaults = array()) { + $form = array(); + + $form['point_radius_min'] = array( + '#type' => 'textfield', + '#title' => t('Min radius'), + '#description' => t('Minimum value for the point radius.'), + '#default_value' => isset($defaults['point_radius_min']) ? + $defaults['point_radius_min'] : 6, + ); + $form['point_radius_max'] = array( + '#type' => 'textfield', + '#title' => t('Max radius'), + '#description' => t('Maximum value for the point radius.'), + '#default_value' => isset($defaults['point_radius_max']) ? + $defaults['point_radius_max'] : 12, + ); + $form['feature_weight'] = array( + '#type' => 'textfield', + '#title' => t('Feature weight'), + '#description' => t('Weight of each additional feature for the final point + radius.'), + '#default_value' => isset($defaults['feature_weight']) ? + $defaults['feature_weight'] : 2, + ); + + return $form; + } + diff --git docs/openlayers.api.php docs/openlayers.api.php index 7951b81..dcb75f3 100644 --- docs/openlayers.api.php +++ docs/openlayers.api.php @@ -282,3 +282,33 @@ function hook_openlayers_presets() { ); return array('default' => $default); } + +/** + * CTools Registration Hook (Style Plugins) + * + * IMPORTANT: + * + * In order to support style plugins, the first step is to + * tell CTools where to find the plugin. + * + * This function is just an example implementation of + * hook_ctools_plugin_directory() and should be alter according to + * your module's name. + * + * For an example, please see the openlayers_test.module + * + * @param $module + * Name of a module that supports CTools exportables. + * @param $plugin + * Name of the kind of plugin supported. + * @return + * If $module is 'openlayers', and $api is a type of exportable that + * your module provides, and you are using Openlayers 2.x, then + * return the directory relative to a module to look for this + * particular plugin. + */ +function openlayers_ctools_plugin_directory($module, $plugin) { + if ($module == 'openlayers' && $plugin == 'style_plugin') { + return 'plugins/style_plugin'; + } +} \ No newline at end of file diff --git includes/openlayers.render.inc includes/openlayers.render.inc index 11187e3..2c35d4e 100644 --- includes/openlayers.render.inc +++ includes/openlayers.render.inc @@ -73,10 +73,67 @@ function _openlayers_behaviors_render($behaviors = array(), &$map = array()) { */ function _openlayers_styles_process($styles = array(), $layer_styles = array(), &$map = array()) { + ctools_include('plugins'); // Get styles info array $styles_info = openlayers_styles(); + // Process style property plugins, if any + $used_plugins = array(); + foreach ($styles_info as $i => $style) { + // Check for property plugins. + foreach ($style->data as $prop => $propval) { + if ( is_array($propval) ) { + + $plugname = $propval['plugin']; + + // This should never happen, except + // for cases in which the old style plugin + // system was used (for prop == 'plugins') + if ( empty($plugname) ) continue; + + if ( ! isset($used_plugins[$plugname]) ) { + // Lazily fetch list of style plugins + if ( ! isset($style_plugins) ) { + $style_plugins = openlayers_style_plugins(); + } + // Instanciate plugin class + $ctplug = $style_plugins[$plugname]; + $plugin_class = ctools_plugin_get_class($ctplug, 'style_plugin'); + if ( isset($plugin_class)) { + $plugin = new $plugin_class; + $used_plugins[$plugname] = array( + 'plugin' => $plugin, + 'methods' => $plugin->get_context_properties() + ); + } + } + + if ( isset($used_plugins[$plugname]) ) { + $method_name = $used_plugins[$plugname]['methods'][$prop]; + $style->data[$prop]['method'] = $method_name; + } + else { + watchdog('openlayers', + 'Could not find plugin "!plugname", '. + 'referenced by property "!prop" of style "!style"', + array('!plugname' => $plugname, '!prop' => $prop, '!style' => $i), + WATCHDOG_WARNING); + unset($style->data[$prop]); + } + + } + } + } + + if ( ! empty($used_plugins) ) { + foreach ($used_plugins as $plugname => $plugin_info) { + $plugin = $plugin_info['plugin']; + $plugin->render(); + } + } + + // Go through styles $processed = array(); foreach ($styles as $k => $style) { diff --git js/openlayers.js js/openlayers.js index 7e34a4c..637f400 100644 --- js/openlayers.js +++ js/openlayers.js @@ -281,15 +281,66 @@ Drupal.openlayers = { layer.addFeatures(newFeatures); } }, + /** + * Build an OpenLayers style from a drupal style object + * + * @param map Drupal settings object for the map (const) + * @param style_in Drupal settings object for the style (const) + */ + 'buildStyle': function(map, style_in) { + // Build context object and callback values (if needed) + var style_out = {}; + var newContext = {}; + for (var propname in style_in) { + if (typeof style_in[propname] == 'object') { + var plugin_spec = style_in[propname]; + var plugin_name = plugin_spec['plugin']; + var plugin_class = Drupal.openlayers.style_plugin[plugin_name]; + if ( typeof plugin_class !== 'function' ) { + throw "Style plugin " + plugin_name + " did not install a constructor in Drupal.openlayers.style_plugin['" + plugin_name + "']"; + } + + var plugin_options = plugin_spec['conf']; + var plugin_method_name = plugin_spec['method']; + if ( typeof plugin_method_name === 'undefined' ) { + throw "Name of method handler for property '" + propname + + "' of style plugin '" + plugin_name + "' is undefined"; + } + + var plugin_context = new plugin_class(plugin_options); + + var plugin_method = plugin_context[plugin_method_name]; + if ( typeof plugin_method !== 'function' ) { + throw "Style plugin '" + plugin_name + "' advertised method '" + plugin_method_name + "' as an handler for property " + propname + " but that method is not found in instance of plugin class"; + } + + var new_method_name = plugin_name + '_' + + propname + '_' + + plugin_method_name; + newContext[new_method_name] = + OpenLayers.Function.bind(plugin_method, plugin_context); + + style_out[propname] = '${' + new_method_name + '}'; + } else { + style_out[propname] = style_in[propname]; + } + } + + // Instantiate an OL style object. + var olStyle = new OpenLayers.Style(style_out, { context: newContext } ); + return olStyle; + }, 'getStyleMap': function(map, layername) { if (map.styles) { + var stylesAdded = {}; var roles = ['default', 'delete', 'select', 'temporary']; // Grab and map base styles. for (var i=0; i t('Label font weight.'), ), ); + + return $properties; +} + +/** + * Styles add/edit form. + */ +function openlayers_ui_styles_form(&$form_state, $style = NULL, $edit = FALSE) { + $form = array(); + + $properties = openlayers_ui_styles_get_properties(); + $style_data = !empty($style->data) ? $style->data : array(); + // Pass style data along $form['style_data'] = array( '#type' => 'value', - '#value' => $properties, + '#value' => array( + 'definitions' => $properties, + 'defaults' => $style_data + ) ); // Style object basics $form['info'] = array( '#type' => 'fieldset', '#tree' => FALSE, + '#title' => t('Basic Information'), + '#description' => t('The basic information for the style, used to refer to and describe the style.'), + '#collapsible' => TRUE, ); $form['info']['name'] = array( '#title' => t('Name'), @@ -236,21 +253,91 @@ function openlayers_ui_styles_form(&$form_state, $style = NULL, $edit = FALSE) { ); // OpenLayers style properties - $form['data'] = array('#type' => 'fieldset', '#tree' => TRUE); - + $form['data'] = array( + '#type' => 'fieldset', + '#tree' => TRUE, + '#title' => t('Style Properties and Plugins'), + '#description' => t('Style properties are properties as + defined by the OpenLayers library. Plugins are dynamically + process the layer at render time; plugins may override the + values that you have set for style properies.'), + '#collapsible' => TRUE, + ); foreach ($properties as $key => $prop) { + $form['data'][$key] = array( - '#type' => !isset($prop['options']) ? 'textfield' : 'select', + '#type' => 'fieldset', + '#tree' => TRUE, '#title' => $key, '#description' => $prop['desc'], - '#default_value' => isset($style->data[$key]) ? - $style->data[$key] : $prop['default'], + '#collapsible' => TRUE, + '#collapsed' => TRUE, ); - - // Add options if needed - if (isset($prop['options']) && is_array($prop['options'])) { - $form['data'][$key]['#options'] = $prop['options']; + + $def_value = $prop['default']; + $def_use_plugin = ''; + + if ( isset($style_data[$key]) ) { + if ( is_array($style_data[$key]) ) { + $def_use_plugin = $style_data[$key]['plugin']; + } + else { + $def_value = $style_data[$key]; + } + } + + // Add plugin options, if any + $handling_plugins = openlayers_ui_get_style_plugins_for_property($key); + + if ( ! empty($handling_plugins) ) { + $plugin_options = array('' => t('none')); + foreach ($handling_plugins as $plugname => $plug) { + $plugin_options[$plugname] = $plug['title']; + } + + $form['data'][$key]['uses_plugin'] = array( + '#title' => t('Use plugin'), + '#type' => 'select', + '#options' => $plugin_options, + '#default_value' => $def_use_plugin, + '#ahah' => array( + 'path' => 'openlayers/ahah/style_plugin/' . $key, + 'wrapper' => $key . '-style-plugin', + 'method' => 'replace', + 'effect' => 'fade', // 'fade', 'none', 'slide' + ) + ); + } + + // Hackish... but is that new for HTML ? ... + $form['data'][$key]['plugin_conf_start'] = array( + '#value' => '
' + ); + + if ( isset($style_data[$key]) && is_array($style_data[$key]) ) { + $defaults = $style_data[$key]['conf']; + $plugname = $style_data[$key]['plugin']; + $form['data'][$key]['plugin'] = + openlayers_ui_get_style_plugin_form($def_use_plugin, $defaults); } + else { + $form['data'][$key]['value'] = array( + '#type' => !isset($prop['options']) ? 'textfield' : 'select', + '#default_value' => $def_value + ); + + // Add options if needed + if (isset($prop['options']) && is_array($prop['options'])) { + $form['data'][$key]['value']['#options'] = $prop['options']; + } + } + + + // Hackish... but is that new for HTML ? ... + $form['data'][$key]['plugin_conf_end'] = array( + '#value' => '
' + ); + } $form['submit'] = array( @@ -264,32 +351,49 @@ function openlayers_ui_styles_form(&$form_state, $style = NULL, $edit = FALSE) { * Submit handler for layers. */ function openlayers_ui_styles_form_submit(&$form, &$form_state) { - $style_data = $form_state['values']['style_data']; + + $prop_defn = $form_state['values']['style_data']['definitions']; + //$data = $form_state['values']['data']; + $data = $form_state['clicked_button']['#post']['data']; + // Cast and unset values so JS can handle them better, - // Unless vluase is in form ${attribute} - foreach ($form_state['values']['data'] as $key => $value) { - if ($form_state['values']['data'][$key] === '') { - unset($form_state['values']['data'][$key]); - } - elseif (isset($style_data[$key]['type']) && - strpos($form_state['values']['data'][$key], '${') !== 0) { - if ($style_data[$key]['type'] == 'integer') { - $form_state['values']['data'][$key] = - (int) $form_state['values']['data'][$key]; + // Unless value is in form ${attribute} + foreach ($data as $key => $value) { + if ( empty($data[$key]['uses_plugin']) ) { + $data[$key] = $data[$key]['value']; + if ($data[$key] === '') { + unset($data[$key]); } - elseif ($style_data[$key]['type'] == 'float') { - $form_state['values']['data'][$key] = - (float) $form_state['values']['data'][$key]; + elseif (isset($prop_defn[$key]['type']) && + strpos($data[$key], '${') !== 0) { + if ($prop_defn[$key]['type'] == 'integer') { + $data[$key] = (int) $data[$key]; + } + elseif ($prop_defn[$key]['type'] == 'float') { + $data[$key] = (float) $data[$key]; + } } } + else { + $spec = array( + 'plugin' => $data[$key]['uses_plugin'], + ); + if ( isset($data[$key]['plugin']['conf']) ) { + $spec['conf'] = $data[$key]['plugin']['conf']; + } + $data[$key] = $spec; + } } - + + $form_state['values']['data'] = $data; + $form_state['clicked_button']['#post']['data'] = $data; + $style = new stdClass(); $style->name = $form_state['values']['name']; $style->title = $form_state['values']['title']; $style->description = $form_state['values']['description']; - $style->data = $form_state['values']['data']; + $style->data = $data; $success = openlayers_style_save($style); @@ -303,3 +407,123 @@ function openlayers_ui_styles_form_submit(&$form, &$form_state) { form_set_error('openlayers', t('Error trying to save style.')); } } + +/** + * Get a list of style plugins providing handling of a given property + * + * @param $propname Name of the property we're interested in + * + */ +function openlayers_ui_get_style_plugins_for_property($propname) { + $handling = array(); + $available = openlayers_style_plugins(); + foreach ($available as $plugname => $plugin) { + $plugin_class = ctools_plugin_get_class($plugin, 'style_plugin'); + if (empty($plugin_class)) continue; // should we watchdog here ? + $plugin_instance = new $plugin_class; + if ( $plugin_instance->can_handle_property($propname) ) { + $handling[$plugname] = $plugin; + } + } + return $handling; +} + +/** + * Get options of a style plugin by plugin name + */ +function openlayers_ui_get_style_plugin_form($plugname, $defaults) { + + $form = array(); + + $available = openlayers_style_plugins(); + if ( ! $available[$plugname] ) { + watchdog('openlayers_ui', 'Style plugin !name unknown', + array('!name' => $plugname), WATCHDOG_ERROR); + return $form; + } + + $plugin = $available[$plugname]; + $plugin_class = ctools_plugin_get_class($plugin, 'style_plugin'); + if (empty($plugin_class)) { + watchdog('openlayers_ui', 'Style plugin !name does not have a class?!', + array('!name' => $plugname), WATCHDOG_ERROR); + return $form; + } + + // Create object and ask it for options + $style_plugin = new $plugin_class; + + $form = array( + '#type' => 'fieldset', + '#tree' => TRUE, + //'#title' => $plugin['title'], + '#description' => $plugin['description'], + 'conf' => $style_plugin->options_form($defaults) + ); + + return $form; +} + +function openlayers_ui_style_plugin_ahah($propname) { + + $posted = $_POST["data"][$propname]; + $plugname = $posted['uses_plugin']; + + // Get cached form + $form_state = array('storage' => NULL, 'submitted' => FALSE); + $form_build_id = $_POST['form_build_id']; + $form_cached = form_get_cache($form_build_id, $form_state); + + // Get style_data from cached form, and defaults + $style_data = $form_cached['style_data']['#value']; + $defaults = $style_data['defaults']; + + + + if ( ! $plugname ) { + + // Find default value + $properties = $style_data['definitions']; + $prop = $properties[$propname]; + $def_value = $prop['default']; + if ( isset($defaults[$propname]) && ! is_array($defaults[$propname]) ) { + $def_value = $defaults[$propname]; + } + + $form = array( + '#type' => !isset($prop['options']) ? 'textfield' : 'select', + '#default_value' => $def_value + ); + + // Add options if needed + if (isset($prop['options']) && is_array($prop['options'])) { + $form['value']['#options'] = $prop['options']; + } + + $form['#parents'] = array('data', $propname, 'value'); + + } + else { + + // Find default value + $defs = array(); + if ( isset($defaults[$propname]) && is_array($defaults[$propname]) + && $defaults[$propname]['plugin'] == $plugname ) { + $defs = $defaults[$propname]['conf']; + } + + $form = openlayers_ui_get_style_plugin_form($plugname, $defs); + $form['#parents'] = array('data', $propname, 'plugin'); + + } + + + $form_state = array(); // TODO: what to do with this ? + $plugform_built = form_builder('style_plugin_form', $form, $form_state); + + $output = drupal_render($plugform_built); + + // Final rendering callback. + drupal_json(array('status' => TRUE, 'data' => $output)); + +} diff --git modules/openlayers_ui/openlayers_ui.module modules/openlayers_ui/openlayers_ui.module index 85b1e56..0a4f275 100644 --- modules/openlayers_ui/openlayers_ui.module +++ modules/openlayers_ui/openlayers_ui.module @@ -323,6 +323,14 @@ function openlayers_ui_menu() { 'file' => 'includes/openlayers_ui.presets.inc', 'type' => MENU_CALLBACK, ); + $items['openlayers/ahah/style_plugin/%'] = array( + 'title' => 'OpenLayers Style Plugin AHAH', + 'page callback' => 'openlayers_ui_style_plugin_ahah', + 'page arguments' => array(3), // 3rd url item (the '%') is first arg + 'access callback' => TRUE, + 'file' => 'includes/openlayers_ui.styles.inc', + 'type' => MENU_CALLBACK, + ); return $items; } diff --git openlayers.module openlayers.module index 51884bd..8021c93 100644 --- openlayers.module +++ openlayers.module @@ -465,6 +465,21 @@ function openlayers_behaviors($reset = FALSE) { } /** + * Get all style plugins. + * + * @ingroup openlayers_api + * + * @param $reset + * Boolean whether to reset cache or not. + * @return + * Array of style handler info. + */ +function openlayers_style_plugins($reset = FALSE) { + ctools_include('plugins'); + return ctools_get_plugins('openlayers', 'style_plugin'); +} + +/** * Get all openlayers styles. * * @ingroup openlayers_api @@ -922,6 +937,88 @@ class openlayers_layer_type { } /** + * Base class for style plugins + * + * We define base classes in the core module. + * All other parent classes can be autoloaded through ctools. + */ +class openlayers_style_plugin { + + /** + * Return true if this plugin can handle + * the given property + */ + function can_handle_property($propname) { + return array_key_exists($propname, $this->get_context_properties()); + } + + /** + * Get an array of style property callbacks + * + * @return + * Array of => + */ + function get_context_properties() { + return array(); + } + + /** + * Initial default options. + * + * @return + * Array of default options. + */ + function options_init() { + return array(); + } + + /** + * Options form. + * + * @param $defaults + * Array of default values for the form. + * @return + * Array of Drupal form elements. + */ + function options_form($defaults = array()) { + return array(); + } + + /** + * Render the style. + */ + function render() { + // Render style. + } +} + +/** + * Implementation of hook_ctools_plugin_directory + */ +function openlayers_ctools_plugin_directory($module, $plugin) { + // The format of plugin includes should be the + // following: + // modulename_plugin_name.inc + // + // For example: + // openlayers_style_plugin_name.inc + + // If this module needed to supply style plugins. + /* + if ($module == 'openlayers' && $plugin == 'style_plugin') { + return 'plugins/style_plugin'; + } + */ + + // This should change to the following when converted: + /* + if ($module == 'openlayers') { + return 'plugins/' . $plugin; + } + */ +} + +/** * Implementation of hook_ctools_plugin */ function openlayers_ctools_plugin_behaviors() { diff --git tests/openlayers_test.module tests/openlayers_test.module index 9e0d826..67362cf 100644 --- tests/openlayers_test.module +++ tests/openlayers_test.module @@ -30,6 +30,16 @@ function openlayers_test_menu() { } /** + * Implementation of hook_ctools_plugin_directory + */ +function openlayers_test_ctools_plugin_directory($module, $plugin) { + if ($module == 'openlayers' && $plugin == 'style_plugin') { + return 'plugins/style_plugin'; + } +} + + +/** * Implementation of hook_ctools_plugin_api(). */ function openlayers_test_ctools_plugin_api($module, $api) { @@ -38,6 +48,9 @@ function openlayers_test_ctools_plugin_api($module, $api) { switch ($api) { case 'openlayers_presets': return array('version' => 1); + + case 'openlayers_styles': + return array('version' => 1); } } @@ -455,4 +468,4 @@ function openlayers_test_openlayers_map_alter(&$map) { drupal_set_message(t('OpenLayers map alter hook fired.')); $performed = TRUE; } -} \ No newline at end of file +} diff --git tests/plugins/style_plugin/openlayers_test_rnd_factor.inc tests/plugins/style_plugin/openlayers_test_rnd_factor.inc new file mode 100644 index 0000000..9112f72 --- /dev/null +++ tests/plugins/style_plugin/openlayers_test_rnd_factor.inc @@ -0,0 +1,61 @@ + t('TEST: random factor'), + 'description' => t('Example style plugin for context styling. ' + . 'Provides a random 0..1 factors.'), + 'style_plugin' => array( + 'class' => 'openlayers_test_rnd_factor', + 'parent' => 'openlayers_style_plugin', + ), +); + +/** + * Style Plugin for testing purposes. + */ +class openlayers_test_rnd_factor extends + openlayers_style_plugin { + /** + * Provide initial values for options. + */ + function options_init() { + return array( + ); + } + + /** + * Options form. + */ + function options_form($defaults = array()) { + $form = array(); + return $form; + } + + /** + * Get an array of style property callbacks + */ + function get_context_properties() { + return array( + 'fillOpacity' => 'getFactor', + 'strokeOpacity' => 'getFactor', + 'graphicOpacity' => 'getFactor', + ); + } + + + /** + * Render function + */ + function render() { + // Add JS + drupal_add_js(drupal_get_path('module', 'openlayers_test') . + '/plugins/style_plugin/openlayers_test_rnd_factor.js'); + } +} diff --git tests/plugins/style_plugin/openlayers_test_rnd_factor.js tests/plugins/style_plugin/openlayers_test_rnd_factor.js new file mode 100644 index 0000000..823de59 --- /dev/null +++ tests/plugins/style_plugin/openlayers_test_rnd_factor.js @@ -0,0 +1,26 @@ +// $Id$ + +/** + * @file + * File to hold custom context styling + */ + +/** + * Style plugin context class + */ +Drupal.openlayers.style_plugin.openlayers_test_rnd_factor = function (params) { + this.params = params; +}; + +/** + * Style plugin context class methods + */ +Drupal.openlayers.style_plugin.openlayers_test_rnd_factor.prototype = { + + // Fill opacity context. Sets random fill opacity. + 'getFactor' : function(feature) { + // Random factor + return Math.random(); + } + +}; diff --git tests/plugins/style_plugin/openlayers_test_rnd_int.inc tests/plugins/style_plugin/openlayers_test_rnd_int.inc new file mode 100644 index 0000000..c72fd90 --- /dev/null +++ tests/plugins/style_plugin/openlayers_test_rnd_int.inc @@ -0,0 +1,88 @@ + t('TEST: random integer'), + 'description' => t('Example style plugin for context styling. ' + . 'Provides random integers.'), + 'style_plugin' => array( + 'class' => 'openlayers_test_rnd_int', + 'parent' => 'openlayers_style_plugin', + ), +); + +/** + * Style Plugin for testing purposes. + */ +class openlayers_test_rnd_int extends + openlayers_style_plugin { + /** + * Provide initial values for options. + */ + function options_init() { + return array( + 'low' => 1, + 'high' => 10, + ); + } + + /** + * Options form. + */ + function options_form($defaults = array()) { + $form = array(); + + // Allow use to pick the highest and lowest for random + // point radius + $form['low'] = array( + '#type' => 'textfield', + '#title' => t('Lowest value'), + '#description' => t('Lowest value for the random integer.'), + '#default_value' => isset($defaults['low']) ? + $defaults['low'] : 2, + ); + $form['high'] = array( + '#type' => 'textfield', + '#title' => t('Highest value'), + '#description' => t('Highest value for the random integer.'), + '#default_value' => isset($defaults['high']) ? + $defaults['high'] : 10, + ); + + return $form; + } + + /** + * Get an array of style property callbacks + */ + function get_context_properties() { + return array( + 'pointRadius' => 'getInt', + 'strokeWidth' => 'getInt', + 'graphicWidth' => 'getInt', + 'graphicHeight' => 'getInt', + 'graphicXOffset' => 'getInt', + 'graphicYOffset' => 'getInt', + 'rotation' => 'getInt', + 'labelXOffset' => 'getInt', + 'labelYOffset' => 'getInt', + 'fontSize' => 'getInt', + ); + } + + + /** + * Render function + */ + function render() { + // Add JS + drupal_add_js(drupal_get_path('module', 'openlayers_test') . + '/plugins/style_plugin/openlayers_test_rnd_int.js'); + } +} diff --git tests/plugins/style_plugin/openlayers_test_rnd_int.js tests/plugins/style_plugin/openlayers_test_rnd_int.js new file mode 100644 index 0000000..b575d70 --- /dev/null +++ tests/plugins/style_plugin/openlayers_test_rnd_int.js @@ -0,0 +1,37 @@ +// $Id$ + +/** + * @file + * File to hold custom context styling + */ + +/** + * Style plugin context class + */ +Drupal.openlayers.style_plugin.openlayers_test_rnd_int = function (params) { + this.params = params; + this.params.high = parseInt(this.params.high); + this.params.low = parseInt(this.params.low); +}; + +/** + * Style plugin context class methods + */ +Drupal.openlayers.style_plugin.openlayers_test_rnd_int.prototype = { + + // Private methods (not copied to final style context object) + 'prv' : { + 'random' : function(low, high) { + return Math.floor(Math.random() * (high-low+1)) + low; + } + }, + + // Point radius context. Given paramters, gets a random + // pointRadius. + 'getInt' : function(feature) { + var high = this.params.high; + var low = this.params.low; + var ret = this.prv.random(low, high); + return ret; + } +};