You are here

openlayers_ui.styles.inc in Openlayers 6.2

This file holds the functions handling styles in the Openlayers UI.

File

modules/openlayers_ui/includes/openlayers_ui.styles.inc
View source
<?php

/**
 * @file
 * This file holds the functions handling styles in the
 * Openlayers UI.
 *
 * @ingroup openlayers
 */

/**
 * Styles add/edit form.
 */
function openlayers_ui_styles_get_properties() {

  // Available styling properies.  Defaults and descriptions are taken
  // from OpenLayers.
  // @see http://docs.openlayers.org/library/feature_styling.html
  $properties = array(
    'externalGraphic' => array(
      'default' => '',
      'desc' => t('The URL of an icon for points in a layer.'),
    ),
    'pointRadius' => array(
      'default' => 6,
      'desc' => t('The radius of a vector point or the size of
        an icon. Note that, when using icons, this value should be half the
        width of the icon image.'),
      'type' => 'integer',
    ),
    'fillColor' => array(
      'default' => '#EE9900',
      'desc' => t('This is the color used for
        filling in Polygons. It is also used in the center of marks for
        points: the interior color of circles or other shapes. It is
        not used if an externalGraphic is applied to a point.  This should be
        a hexadecimal value like #FFFFFF.'),
    ),
    'strokeColor' => array(
      'default' => '#EE9900',
      'desc' => t('This is color of the line on features. On
        polygons and point marks, it is used as an outline to the feature.
        On lines, this is the representation of the feature.  This should be
        a hexadecimal value like #FFFFFF.'),
    ),
    'strokeWidth' => array(
      'default' => 1,
      'desc' => t('This is width of the line on features. On
        polygons and point marks, it is used as an outline to
        the feature. On lines, this is the representation of the
        feature.  This is a value in pixels.'),
      'type' => 'integer',
    ),
    'fillOpacity' => array(
      'default' => 1,
      'desc' => t('This is the opacity used for filling in Polygons.
        It is also used in the center of marks for points: the interior
        color of circles or other shapes. It is not used if an
        externalGraphic is applied to a point.  This should be a value
        between 0 and 1.'),
      'type' => 'float',
    ),
    'strokeOpacity' => array(
      'default' => 1,
      'desc' => t('This is opacity of the line on features.
        On polygons and point marks, it is used as an outline to the
        feature. On lines, this is the representation of the feature.
        This should be a value between 0 and 1.'),
      'type' => 'float',
    ),
    'strokeLinecap' => array(
      'default' => 'round',
      'desc' => t('Options are butt, round, square. This property
        is similar to the SVG stroke-linecap property. It determines
        what the end of lines should look like. See the SVG link for
        image examples.'),
      'options' => array(
        'butt' => t('Butt'),
        'round' => t('Round'),
        'square' => t('Square'),
      ),
    ),
    'strokeDashstyle' => array(
      'default' => 'solid',
      'desc' => t('Options are dot, dash, dashdot, longdash, longdashdot, solid.'),
      'options' => array(
        'dot' => t('Dot'),
        'dash' => t('Dash'),
        'dashdot' => t('Dash-dot'),
        'longdash' => t('Long-dash'),
        'longdashdot' => t('Long-dash-dot'),
        'solid' => t('Solid'),
      ),
    ),
    'cursor' => array(
      'default' => '',
      'desc' => t('Cursor used when mouse is over the feature. Default
        is an empty string, which inherits from parent elements.  See
        <a href="!url">CSS cursor styles</a>.', array(
        '!url' => 'http://www.w3schools.com/css/pr_class_cursor.asp',
      )),
    ),
    'graphicWidth' => array(
      'default' => '',
      'desc' => t('This properties define the width of an externalGraphic.
        This is an alternative to the pointRadius symbolizer property
        to be used when your graphic has different sizes in the X and
        Y direction.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'graphicHeight' => array(
      'default' => '',
      'desc' => t('This properties define the height of an externalGraphic.
        This is an alternative to the pointRadius symbolizer property
        to be used when your graphic has different sizes in the X and
        Y direction.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'graphicOpacity' => array(
      'default' => '1',
      'desc' => t('Opacity of an external graphic.  This should be a
        value between 0 and 1. Grahics that are already semitransparent,
        like alpha PNGs, should have this set to 1, or rendering problems in
        Internet Explorer will ensue.'),
      'type' => 'float',
    ),
    'graphicXOffset' => array(
      'default' => '',
      'desc' => t('Where the X value of the "center" of an
      externalGraphic should be.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'graphicYOffset' => array(
      'default' => '',
      'desc' => t('Where the Y value of the "center" of an
      externalGraphic should be.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'graphicName' => array(
      'default' => '',
      'desc' => t('Name of a type of symbol to be used  for a point mark.
      You can use the names "star", "cross", "x", "square", "triangle",
      and "circle". See <a href="!url">Graphic Name Examples</a>.', array(
        '!url' => 'http://openlayers.org/dev/examples/graphic-name.html',
      )),
    ),
    'graphicZIndex' => array(
      'default' => '',
      'desc' => t('Z index of the feature. This determines drawing order:
         elements with higher Z indexes are drawn on top of those with
         lower Z indexes.'),
      'type' => 'integer',
    ),
    'backgroundGraphic' => array(
      'default' => '',
      'desc' => t('The URL of an icon to display in addition to the main
        feature. Use backgroundGraphicZIndex and graphicZIndex to set its
        drawing order relative to main feature.'),
    ),
    'backgroundWidth' => array(
      'default' => '',
      'desc' => t('Width of a backgroundGraphic, in pixels.'),
      'type' => 'integer',
    ),
    'backgroundHeight' => array(
      'default' => '',
      'desc' => t('Height of a backgroundGraphic, in pixels.'),
      'type' => 'integer',
    ),
    'backgroundXOffset' => array(
      'default' => '',
      'desc' => t('Where the X value of the "center" of a
        backgroundGraphic should be.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'backgroundYOffset' => array(
      'default' => '',
      'desc' => t('Where the Y value of the "center" of a
        backgroundGraphic should be.  This should be in pixels.'),
      'type' => 'integer',
    ),
    'backgroundGraphicZIndex' => array(
      'default' => '',
      'desc' => t('Z index of backgroundGraphic. This determines drawing
         order: elements with higher Z indexes are drawn on top of those
         with lower Z indexes.'),
      'type' => 'integer',
    ),
    'rotation' => array(
      'default' => '',
      'desc' => t('The rotation angle in degrees clockwise for
        a point symbolizer.'),
    ),
    'display' => array(
      'default' => '',
      'desc' => t('Can be set to "none" to hide features
        from rendering.'),
      'options' => array(
        '' => t('On'),
        'none' => t('None (off)'),
      ),
    ),
    'label' => array(
      'default' => '',
      'desc' => t('A label to show for features. ' . 'Typically used with ${attribute} syntax.'),
    ),
    'labelAlign' => array(
      'default' => 'cm',
      'desc' => t('Label alignment.'),
      'options' => array(
        'cm' => t('Center, middle'),
        'ct' => t('Center, top'),
        'cb' => t('Center, bottom'),
        'lm' => t('Left, middle'),
        'lt' => t('Left, top'),
        'lb' => t('Left, bottom'),
        'rm' => t('Right, middle'),
        'rt' => t('Right, top'),
        'rb' => t('Right, bottom'),
      ),
    ),
    'labelXOffset' => array(
      'default' => '',
      'desc' => t('Label X offset. Positive numbers move label right.'),
    ),
    'labelYOffset' => array(
      'default' => '',
      'desc' => t('Label Y offset. Positive numbers move label up.'),
    ),
    'fontColor' => array(
      'default' => '',
      'desc' => t('Label font color.'),
    ),
    'fontSize' => array(
      'default' => '',
      'desc' => t('Label font size.'),
    ),
    'fontFamily' => array(
      'default' => '',
      'desc' => t('Label font family.'),
    ),
    'fontWeight' => array(
      'default' => '',
      'desc' => 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' => 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'),
    '#type' => 'textfield',
    '#required' => TRUE,
    '#default_value' => !empty($style->name) ? $style->name : '',
  );
  $form['info']['title'] = array(
    '#title' => t('Title'),
    '#type' => 'textfield',
    '#required' => TRUE,
    '#default_value' => !empty($style->title) ? $style->title : '',
  );
  $form['info']['description'] = array(
    '#title' => t('Description'),
    '#type' => 'textfield',
    '#default_value' => !empty($style->description) ? $style->description : '',
  );

  // OpenLayers style properties
  $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' => 'fieldset',
      '#tree' => TRUE,
      '#title' => $key,
      '#description' => $prop['desc'],
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $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',
        ),
      );
    }

    // Hackish... but is that new for HTML ? ...
    $form['data'][$key]['plugin_conf_start'] = array(
      '#value' => '<div id="' . $key . '-style-plugin">',
    );
    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' => '</div>',
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  return $form;
}

/**
 * Submit handler for layers.
 */
function openlayers_ui_styles_form_submit(&$form, &$form_state) {
  $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 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 (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] = (double) $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 = $data;
  $success = openlayers_style_save($style);

  // Redirect to edit page
  if ($success) {
    drupal_set_message(t('Style saved.'));
    $form_state['redirect'] = 'admin/build/openlayers/styles/' . $style->name . '/edit';
  }
  else {
    form_set_error('openlayers', t('Error trying to save style.'));
  }
}

/**
 * Get a list of style plugins providing handling of a given property
 *
 * @param $property_name Name of the property we're interested in
 */
function openlayers_ui_get_style_plugins_for_property($property_name) {
  $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($property_name)) {
      $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,
    '#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
    $property = $style_data['definitions'][$propname];
    $def_value = $property['default'];
    if (isset($defaults[$propname]) && !is_array($defaults[$propname])) {
      $def_value = $defaults[$propname];
    }
    $form = array(
      '#type' => !isset($property['options']) ? 'textfield' : 'select',
      '#default_value' => $def_value,
    );

    // Add options if needed
    if (isset($property['options']) && is_array($property['options'])) {
      $form['value']['#options'] = $property['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 ?
  $plugin_form_built = form_builder('style_plugin_form', $form, $form_state);
  $output = drupal_render($plugin_form_built);

  // Final rendering callback.
  drupal_json(array(
    'status' => TRUE,
    'data' => $output,
  ));
}

Related topics

Functions

Namesort descending Description
openlayers_ui_get_style_plugins_for_property Get a list of style plugins providing handling of a given property
openlayers_ui_get_style_plugin_form Get options of a style plugin by plugin name
openlayers_ui_styles_form Styles add/edit form.
openlayers_ui_styles_form_submit Submit handler for layers.
openlayers_ui_styles_get_properties Styles add/edit form.
openlayers_ui_style_plugin_ahah