[Commits] r2579 - in core/trunk/geoext: examples lib lib/GeoExt/plugins resources/images/default tests tests/lib/GeoExt/plugins
commits at geoext.org
commits at geoext.org
Tue Jan 25 09:24:24 CET 2011
Author: pgiraud
Date: 2011-01-25 09:24:24 +0100 (Tue, 25 Jan 2011)
New Revision: 2579
Added:
core/trunk/geoext/examples/tree-actions.html
core/trunk/geoext/examples/tree-actions.js
core/trunk/geoext/lib/GeoExt/plugins/TreeNodeActions.js
core/trunk/geoext/resources/images/default/bullet_arrow_down.png
core/trunk/geoext/resources/images/default/bullet_arrow_up.png
core/trunk/geoext/resources/images/default/delete.png
core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeActions.html
Modified:
core/trunk/geoext/lib/GeoExt.js
core/trunk/geoext/tests/list-tests.html
Log:
New plugin to be able to render actions within tree nodes, p=elemoine,me, r=elemoine, (Closes #348)
Added: core/trunk/geoext/examples/tree-actions.html
===================================================================
--- core/trunk/geoext/examples/tree-actions.html (rev 0)
+++ core/trunk/geoext/examples/tree-actions.html 2011-01-25 08:24:24 UTC (rev 2579)
@@ -0,0 +1,65 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>GeoExt Actions Tree</title>
+
+ <script type="text/javascript" src="http://extjs.cachefly.net/ext-3.2.1/adapter/ext/ext-base.js"></script>
+ <script type="text/javascript" src="http://extjs.cachefly.net/ext-3.2.1/ext-all-debug.js"></script>
+ <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-3.2.1/resources/css/ext-all.css" />
+ <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-3.2.1/examples/shared/examples.css" />
+ <script src="http://www.openlayers.org/api/2.10/OpenLayers.js"></script>
+ <script type="text/javascript" src="../lib/GeoExt.js"></script>
+
+ <script type="text/javascript" src="tree-actions.js"></script>
+
+ <style type="text/css">
+ .gx-tree-layer-actions {
+ float: right;
+ }
+ .gx-tree-layer-action {
+ background-position: center center;
+ background-repeat: no-repeat;
+ border: 0 none;
+ height: 16px;
+ margin: 0;
+ padding: 0;
+ vertical-align: top;
+ width: 16px;
+ }
+ .gx-tree-layer-actions .delete {
+ background: transparent url(../resources/images/default/delete.png);
+ }
+ .gx-tree-layer-actions .up {
+ background: transparent url(../resources/images/default/bullet_arrow_up.png);
+ }
+ .gx-tree-layer-actions .down {
+ background: transparent url(../resources/images/default/bullet_arrow_down.png);
+ }
+ .gx-tree-layer-actions .disabled {
+ opacity: 0.2;
+ }
+ .x-tree-node-el {
+ border-bottom: 1px solid #ddd;
+ }
+ .x-tree-no-lines .x-tree-elbow,
+ .x-tree-no-lines .x-tree-elbow-end,
+ .x-tree-node-collapsed .x-tree-node-icon,
+ .x-tree-node-expanded .x-tree-node-icon,
+ .x-tree-node-leaf .gx-tree-layer-icon {
+ width: 0px; !important;
+ }
+ </style>
+
+ </head>
+ <body>
+ <div id="desc">
+ <h1>GeoExt Tree Node UI</h1>
+
+ <p>This example shows how to add tools (actions) in
+ tree nodes. The tools added here allow moving the layers up and
+ down and deleting them.</p>
+
+ <p>The js is not minified so it is readable. See
+ <a href="tree-actions.js">tree-actions.js</a>.</p>
+ </div>
+ </body>
+</html>
Added: core/trunk/geoext/examples/tree-actions.js
===================================================================
--- core/trunk/geoext/examples/tree-actions.js (rev 0)
+++ core/trunk/geoext/examples/tree-actions.js 2011-01-25 08:24:24 UTC (rev 2579)
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ *
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+Ext.namespace("GeoExt.examples");
+
+// this function takes action based on the "action"
+// parameter, it is used as a listener to layer
+// nodes' "action" events
+GeoExt.examples.onAction = function(node, action, evt) {
+ var layer = node.layer;
+ switch(action) {
+ case "down":
+ layer.map.raiseLayer(layer, -1);
+ break;
+ case "up":
+ layer.map.raiseLayer(layer, +1);
+ break;
+ case "delete":
+ layer.destroy();
+ break;
+ }
+};
+
+// custom layer node UI class
+GeoExt.examples.LayerNodeUI = Ext.extend(
+ GeoExt.tree.LayerNodeUI,
+ new GeoExt.tree.TreeNodeUIEventMixin()
+);
+
+Ext.onReady(function() {
+ Ext.QuickTips.init();
+
+ // the map panel
+ var mapPanel = new GeoExt.MapPanel({
+ border: true,
+ region: "center",
+ center: [146.1569825, -41.6109735],
+ zoom: 6,
+ layers: [
+ new OpenLayers.Layer.WMS("Tasmania State Boundaries",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_state_boundaries"
+ }, {
+ buffer: 0,
+ // exclude this layer from layer container nodes
+ displayInLayerSwitcher: false
+ }),
+ new OpenLayers.Layer.WMS("Water",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_water_bodies",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ buffer: 0
+ }),
+ new OpenLayers.Layer.WMS("Cities",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_cities",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ buffer: 0
+ }),
+ new OpenLayers.Layer.WMS("Tasmania Roads",
+ "http://demo.opengeo.org/geoserver/wms", {
+ layers: "topp:tasmania_roads",
+ transparent: true,
+ format: "image/gif"
+ }, {
+ buffer: 0
+ })
+ ]
+ });
+
+ // the layer tree panel. In this tree the node actions are set using
+ // the loader's "baseAttrs" property.
+ var tree = new Ext.tree.TreePanel({
+ region: "west",
+ width: 250,
+ title: "Layer Tree",
+ loader: {
+ applyLoader: false,
+ uiProviders: {
+ "ui": GeoExt.examples.LayerNodeUI
+ }
+ },
+ // apply the tree node actions plugin to layer nodes
+ plugins: [{
+ ptype: "gx_treenodeactions",
+ listeners: {
+ action: GeoExt.examples.onAction
+ }
+ }],
+ root: {
+ nodeType: "gx_layercontainer",
+ loader: {
+ baseAttrs: {
+ radioGroup: "radiogroup",
+ uiProvider: "ui",
+ actions: [{
+ action: "delete",
+ qtip: "delete"
+ }, {
+ action: "up",
+ qtip: "move up",
+ update: function(el) {
+ // "this" references the tree node
+ var layer = this.layer, map = layer.map;
+ if (map.getLayerIndex(layer) == map.layers.length - 1) {
+ el.addClass('disabled');
+ } else {
+ el.removeClass('disabled');
+ }
+ }
+ }, {
+ action: "down",
+ qtip: "move down",
+ update: function(el) {
+ // "this" references the tree node
+ var layer = this.layer, map = layer.map;
+ if (map.getLayerIndex(layer) == 1) {
+ el.addClass('disabled');
+ } else {
+ el.removeClass('disabled');
+ }
+ }
+ }]
+ }
+ }
+ },
+ rootVisible: false,
+ lines: false
+ });
+
+ // the viewport
+ new Ext.Viewport({
+ layout: "fit",
+ hideBorders: true,
+ items: {
+ layout: "border",
+ deferredRender: false,
+ items: [
+ mapPanel,
+ tree, {
+ region: "east",
+ contentEl: "desc",
+ width: 250
+ }]
+ }
+ });
+});
Added: core/trunk/geoext/lib/GeoExt/plugins/TreeNodeActions.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/plugins/TreeNodeActions.js (rev 0)
+++ core/trunk/geoext/lib/GeoExt/plugins/TreeNodeActions.js 2011-01-25 08:24:24 UTC (rev 2579)
@@ -0,0 +1,167 @@
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ *
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+Ext.namespace("GeoExt.plugins");
+
+/** api: (define)
+ * module = GeoExt.plugins
+ * class = TreeNodeActions
+ */
+
+/** api: constructor
+ * A plugin to create tree node UIs with actions.
+ *
+ * An action is a clickable image in a tree node, which, when clicked,
+ * leads to an "action" event being triggered by the node.
+ *
+ * To set actions in a node an ``actions`` property must be provided in
+ * the node config options. This property is an array of
+ * action objects, each action object has the following property:
+ *
+ * * "action" ``String`` the name of the action. It is used as
+ * the name of the ``<img>`` class. The ``img`` tag being placed in a
+ * div whose class is "gx-tree-layer-actions" a CSS selector for the
+ * action is ``.gx-tree-layer-actions .action-name``. The name of the
+ * action is also provided in the "action" event for listeners to know
+ * which action got clicked. (required)
+ * * "qtip" ``String`` the tooltip displayed when the action
+ * image is hovered. (required)
+ * * "update" ``Function`` a function executed after the action is
+ * rendered in the node, it receives the ``Ext.Element`` object
+ * representing the image and executes with the node as its
+ * scope. For example, this function can be used to hide the
+ * action based on some condition. (optional)
+ */
+
+/** api: example
+ * Sample code to create a layer node UI with an actions mixin:
+ *
+ * .. code-block:: javascript
+ *
+ * var uiClass = Ext.extend(
+ * GeoExt.tree.LayerNodeUI,
+ * new GeoExt.plugins.TreeNodeActions()
+ * );
+ *
+ */
+
+GeoExt.plugins.TreeNodeActions = Ext.extend(Ext.util.Observable, {
+ /** private: constant[actionsCls]
+ */
+ actionsCls: "gx-tree-layer-actions",
+
+ /** private: constant[actionCls]
+ */
+ actionCls: "gx-tree-layer-action",
+
+ /** private: method[constructor]
+ * :param config: ``Object``
+ */
+ constructor: function(config) {
+ Ext.apply(this.initialConfig, Ext.apply({}, config));
+ Ext.apply(this, config);
+
+ this.addEvents(
+
+ /** api: event[radiochange]
+ * Fires when an action image is clicked.
+ *
+ * Listener arguments:
+ *
+ * * node - ``Ext.TreeNode`` The node of the clicked action image.
+ */
+ "action"
+ );
+
+ GeoExt.plugins.TreeNodeActions.superclass.constructor.apply(this, arguments);
+ },
+
+ /** private: method[init]
+ * :param tree: ``Ext.tree.TreePanel`` The tree.
+ */
+ init: function(tree) {
+ tree.on({
+ "rendernode": this.onRenderNode,
+ "rawclicknode": this.onRawClickNode,
+ "beforedestroy": this.onBeforeDestroy,
+ scope: this
+ });
+ },
+
+ /** private: method[onRenderNode]
+ * :param node: ``Ext.tree.TreeNode``
+ */
+ onRenderNode: function(node) {
+ var rendered = node.rendered;
+ if(!rendered) {
+ var attr = node.attributes;
+ var actions = attr.actions || this.actions;
+ if(actions && actions.length > 0) {
+ var html = ['<div class="', this.actionsCls, '">'];
+ for(var i=0,len=actions.length; i<len; i++) {
+ var a = actions[i];
+ html = html.concat([
+ '<img id="'+node.id+'_'+a.action,
+ '" ext:qtip="'+a.qtip,
+ '" src="'+Ext.BLANK_IMAGE_URL,
+ '" class="'+this.actionCls+' '+a.action+'" />'
+ ]);
+ }
+ html.concat(['</div>']);
+ Ext.DomHelper.insertFirst(node.ui.elNode, html.join(""));
+ }
+ if (node.layer.map) {
+ this.updateActions(node);
+ } else if (node.layerStore) {
+ node.layerStore.on({
+ 'bind': function() {
+ this.updateActions(node);
+ },
+ scope: this
+ });
+ }
+ }
+ },
+
+ /** private: method[updateActions]
+ *
+ * Update all the actions.
+ */
+ updateActions: function(node) {
+ var actions = node.attributes.actions || this.actions || [];
+ Ext.each(actions, function(a, index) {
+ var el = Ext.get(node.id + '_' + a.action);
+ if (el && typeof a.update == "function") {
+ a.update.call(node, el);
+ }
+ });
+ },
+
+ /** private: method[onRawClickNode]
+ * :param node: ``Ext.tree.TreeNode``
+ * :param e: ``Ext.EventObject``
+ */
+ onRawClickNode: function(node, e) {
+ if(e.getTarget('.' + this.actionCls, 1)) {
+ var t = e.getTarget('.' + this.actionCls, 1);
+ var action = t.className.replace(this.actionCls + ' ', '');
+ this.fireEvent("action", node, action, e);
+ return false;
+ }
+ },
+
+ /** private: method[onBeforeDestroy]
+ */
+ onBeforeDestroy: function(tree) {
+ tree.un("rendernode", this.onRenderNode, this);
+ tree.un("rawclicknode", this.onRawClickNode, this);
+ tree.un("beforedestroy", this.onBeforeDestroy, this);
+ }
+});
+
+Ext.preg("gx_treenodeactions", GeoExt.plugins.TreeNodeActions);
Modified: core/trunk/geoext/lib/GeoExt.js
===================================================================
--- core/trunk/geoext/lib/GeoExt.js 2011-01-23 16:11:43 UTC (rev 2578)
+++ core/trunk/geoext/lib/GeoExt.js 2011-01-25 08:24:24 UTC (rev 2579)
@@ -96,6 +96,7 @@
"GeoExt/widgets/tree/TreeNodeUIEventMixin.js",
"GeoExt/plugins/TreeNodeComponent.js",
"GeoExt/plugins/TreeNodeRadioButton.js",
+ "GeoExt/plugins/TreeNodeActions.js",
"GeoExt/widgets/tree/LayerLoader.js",
"GeoExt/widgets/tree/LayerContainer.js",
"GeoExt/widgets/tree/BaseLayerContainer.js",
Added: core/trunk/geoext/resources/images/default/bullet_arrow_down.png
===================================================================
(Binary files differ)
Property changes on: core/trunk/geoext/resources/images/default/bullet_arrow_down.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: core/trunk/geoext/resources/images/default/bullet_arrow_up.png
===================================================================
(Binary files differ)
Property changes on: core/trunk/geoext/resources/images/default/bullet_arrow_up.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: core/trunk/geoext/resources/images/default/delete.png
===================================================================
(Binary files differ)
Property changes on: core/trunk/geoext/resources/images/default/delete.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeActions.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeActions.html (rev 0)
+++ core/trunk/geoext/tests/lib/GeoExt/plugins/TreeNodeActions.html 2011-01-25 08:24:24 UTC (rev 2579)
@@ -0,0 +1,84 @@
+<html>
+ <head>
+ <script src="../../../../../openlayers/lib/OpenLayers.js"></script>
+ <script src="../../../../../ext/adapter/ext/ext-base.js"></script>
+ <script src="../../../../../ext/ext-all-debug.js"></script>
+ <script src="../../../../lib/GeoExt.js"></script>
+
+ <script>
+ function test_ui_node_action(t) {
+ t.plan(6);
+
+ // setup
+
+ var UI, node, tree, ui, elNode;
+
+ UI = Ext.extend(
+ GeoExt.tree.LayerNodeUI,
+ new GeoExt.tree.TreeNodeUIEventMixin()
+ );
+
+ node = new GeoExt.tree.LayerNode({
+ uiProvider: UI,
+ layer: new OpenLayers.Layer(),
+ actions: [{
+ action: "foo-action",
+ qtip: "foo-qtip"
+ }]
+ });
+ tree = new Ext.tree.TreePanel({
+ renderTo: "tree",
+ root: node,
+ plugins: [new GeoExt.plugins.TreeNodeActions({
+ listeners: {
+ action: function(n, a, e) {
+ log.push({n: n, a: a, e: e});
+ }
+ }
+ })]
+ });
+ ui = node.ui;
+ elNode = Ext.fly(ui.elNode);
+
+ // 2 tests
+ t.ok(elNode.first().hasClass("gx-tree-layer-actions"),
+ "the actions div is at correct location and " +
+ "has a correct class");
+ t.ok(elNode.first().first() &&
+ elNode.first().first().hasClass("gx-tree-layer-action") &&
+ elNode.first().first().hasClass("foo-action"),
+ "the action div is at correct location and " +
+ "has correct classes");
+
+ // simulate click
+ var log = [];
+ var e = {
+ getTarget: function(selector) {
+ if (selector == "." + "gx-tree-layer-action") {
+ return {
+ className: "gx-tree-layer-action" + " foo-action"
+ };
+ }
+ }
+ };
+
+ ui.onClick(e);
+ t.eq(log.length, 1,
+ "click on action img triggers \"action\" event");
+ t.ok(log[0].n == node,
+ "\"action\" listener given expected node");
+ t.eq(log[0].a, "foo-action",
+ "\"action\" listener given expected action");
+ t.ok(log[0].e == e,
+ "\"action\" listener given expected event");
+
+ // teardown
+
+ tree.destroy();
+ }
+ </script>
+ </head>
+ <body>
+ <div id="tree" style="width: 100px; height: 100px;"></div>
+ </body>
+</html>
Modified: core/trunk/geoext/tests/list-tests.html
===================================================================
--- core/trunk/geoext/tests/list-tests.html 2011-01-23 16:11:43 UTC (rev 2578)
+++ core/trunk/geoext/tests/list-tests.html 2011-01-25 08:24:24 UTC (rev 2579)
@@ -23,6 +23,7 @@
<li>lib/GeoExt/plugins/AttributeForm.html</li>
<li>lib/GeoExt/plugins/TreeNodeComponent.html</li>
<li>lib/GeoExt/plugins/TreeNodeRadioButton.html</li>
+ <li>lib/GeoExt/plugins/TreeNodeActions.html</li>
<li>lib/GeoExt/widgets/Action.html</li>
<li>lib/GeoExt/widgets/FeatureRenderer.html</li>
<li>lib/GeoExt/widgets/LayerOpacitySlider.html</li>
More information about the Commits
mailing list