1
|
/*
|
2
|
License: LGPL as per: http://www.gnu.org/copyleft/lesser.html
|
3
|
$Id: ButtonBase.js 3879 2008-02-27 14:20:29Z gjvoosten $
|
4
|
*/
|
5
|
|
6
|
// Ensure this object's dependancies are loaded.
|
7
|
mapbuilder.loadScript(baseDir+"/util/Util.js");
|
8
|
mapbuilder.loadScript(baseDir+"/widget/WidgetBase.js");
|
9
|
|
10
|
/**
|
11
|
* Abstract base button object that all Buttons extend.
|
12
|
* A Button is a widget which renders an image and an optional second image
|
13
|
* for the enabled state.
|
14
|
* @constructor
|
15
|
* @base WidgetBase
|
16
|
* @author Mike Adair mike.adairATccrs.nrcan.gc.ca
|
17
|
* @param widgetNode The tool node from the Config XML file.
|
18
|
* @param model The parent model object (optional).
|
19
|
*/
|
20
|
function ButtonBase(widgetNode, model) {
|
21
|
WidgetBase.apply(this, new Array(widgetNode, model));
|
22
|
|
23
|
this.htmlTagId = this.getProperty("mb:buttonBar");
|
24
|
if (!this.htmlTagId) {
|
25
|
this.htmlTagId = this.getProperty("mb:htmlTagId");
|
26
|
}
|
27
|
if (!this.htmlTagId) {
|
28
|
alert(mbGetMessage("buttonBarRequired", widgetNode.nodeName));
|
29
|
}
|
30
|
// Set button text values as parameters
|
31
|
if (config.widgetText) {
|
32
|
var textNodeXpath = "/mb:WidgetText/mb:widgets/mb:" + widgetNode.nodeName;
|
33
|
var textParams = config.widgetText.selectNodes(textNodeXpath+"/*");
|
34
|
for (var j=0;j<textParams.length;j++) {
|
35
|
this[textParams[j].nodeName]=getNodeValue(textParams[j]);
|
36
|
}
|
37
|
}
|
38
|
// html tag id of the div where OL places its panel code
|
39
|
this.panelHtmlTagId = this.htmlTagId+'_panel';
|
40
|
|
41
|
// load controlPanel.css for button base styles
|
42
|
loadCss('controlPanel.css');
|
43
|
|
44
|
//set the button type
|
45
|
this.buttonType = this.getProperty("mb:class")
|
46
|
this.buttonType = this.buttonType ? this.buttonType.toUpperCase() : null;
|
47
|
if (this.buttonType == "RADIOBUTTON") this.enabled = false;
|
48
|
|
49
|
// map between MB and OL button types
|
50
|
this.olButtonType = {
|
51
|
"RADIOBUTTON" : OpenLayers.Control.TYPE_TOOL,
|
52
|
"TOOL" : OpenLayers.Control.TYPE_TOOL,
|
53
|
"BUTTON" : OpenLayers.Control.TYPE_BUTTON,
|
54
|
"TOGGLE" : OpenLayers.Control.TYPE_TOGGLE
|
55
|
}
|
56
|
|
57
|
//set the button action
|
58
|
this.action = this.getProperty("mb:action");
|
59
|
|
60
|
// set the button tooltip
|
61
|
var tooltip = this.getProperty("mb:tooltip");
|
62
|
if (tooltip) {
|
63
|
this.tooltip = tooltip;
|
64
|
}
|
65
|
|
66
|
//pre-load the button bar images; add them to the config
|
67
|
var disabledImage = this.getProperty("mb:disabledSrc");
|
68
|
if (disabledImage) {
|
69
|
this.disabledImage = config.skinDir + disabledImage;
|
70
|
}
|
71
|
|
72
|
//optional second image to be displayed in the enabled state
|
73
|
var enabledImage = this.getProperty("mb:enabledSrc");
|
74
|
if (enabledImage) {
|
75
|
this.enabledImage = config.skinDir + enabledImage;
|
76
|
}
|
77
|
|
78
|
this.cursor = 'default';
|
79
|
|
80
|
// Check for cursor override
|
81
|
this.cursor = this.getProperty("mb:cursor");
|
82
|
|
83
|
//a button may be set as selected in the config file
|
84
|
this.selected = Mapbuilder.parseBoolean(this.getProperty("mb:selected", false));
|
85
|
|
86
|
/**
|
87
|
* Gets the css classname for this button. We use this
|
88
|
* to define the button styles.
|
89
|
* @param objRef Reference to this object.
|
90
|
* @param state 'Active' or 'Inactive' (case sensitive!)
|
91
|
*/
|
92
|
this.getButtonClass = function(objRef, state) {
|
93
|
var cssName;
|
94
|
if (objRef.control.displayClass) {
|
95
|
cssName = objRef.control.displayClass;
|
96
|
} else {
|
97
|
cssName = objRef.control.CLASS_NAME;
|
98
|
cssName = cssName.replace(/OpenLayers/, 'ol').replace(/\./g, '');
|
99
|
}
|
100
|
cssName += 'Item';
|
101
|
return '.' + cssName + state;
|
102
|
}
|
103
|
|
104
|
/**
|
105
|
* OpenLayers control for this button.
|
106
|
* This will be filled with the instance of the control
|
107
|
* by the attachToOL method.
|
108
|
*/
|
109
|
this.control = null;
|
110
|
|
111
|
//TBD This is never called, but I think we can drop it
|
112
|
// if we get rid of MB mouse handlers
|
113
|
/**
|
114
|
* Override this in buttons which inherit from this object to carry out the action.
|
115
|
* This is the function that will be called either when the button is selected
|
116
|
* via the select() method or on a mouseup event if there is an associated
|
117
|
* mouseHandler property in config.
|
118
|
*/
|
119
|
this.doAction = function() {}
|
120
|
|
121
|
/**
|
122
|
* Select this button. Enables and disables associated tools,
|
123
|
* then the control.trigger()/activate() methods make OL call
|
124
|
* the doSelect method defined in derived classes.
|
125
|
*/
|
126
|
this.select = function() {
|
127
|
if (this.control.type == OpenLayers.Control.TYPE_BUTTON) {
|
128
|
this.control.trigger();
|
129
|
} else {
|
130
|
this.panel.activateControl(this.control);
|
131
|
}
|
132
|
}
|
133
|
|
134
|
/**
|
135
|
* Method overriden by subclasses
|
136
|
* @param objRef Reference to this object.
|
137
|
* @param selected True when selected, false when deselected.
|
138
|
*/
|
139
|
this.doSelect = function(objRef, selected) {
|
140
|
}
|
141
|
|
142
|
/**
|
143
|
* Attaches the control for this button to OpenLayers
|
144
|
* and add it to the buttonBar. When this method is called,
|
145
|
* everything of the OL map is available.
|
146
|
* @param {OpenLayers.Control} control to add.
|
147
|
* @param objRef Reference to this object.
|
148
|
*/
|
149
|
this.attachToOL = function(objRef,refreshId) {
|
150
|
if (objRef.control) {
|
151
|
return;
|
152
|
}
|
153
|
|
154
|
//pass in a widget ID to refresh only that widget
|
155
|
if (refreshId && (refreshId!=objRef.id)) return;
|
156
|
|
157
|
// nothing to do here if subclass does not have a
|
158
|
// createControl method
|
159
|
if (!objRef.createControl) return;
|
160
|
|
161
|
// override the control from the subclass to add
|
162
|
// MB-stuff to the activate and deactivate methods
|
163
|
var SubclassControl = objRef.createControl(objRef);
|
164
|
var type = objRef.olButtonType[objRef.buttonType] ||
|
165
|
SubclassControl.prototype.type;
|
166
|
|
167
|
var Control = OpenLayers.Class( SubclassControl, {
|
168
|
objRef: objRef,
|
169
|
type: type,
|
170
|
superclass: SubclassControl.prototype,
|
171
|
// call objRef.doSelect after OL activate from this control
|
172
|
trigger: function() {
|
173
|
if(this.superclass.trigger) {
|
174
|
this.superclass.trigger.call(this);
|
175
|
}
|
176
|
objRef.doSelect(objRef, true);
|
177
|
},
|
178
|
activate: function() {
|
179
|
if (this.superclass.activate.call(this)) {
|
180
|
this.panel_div.style.backgroundImage = "url(\""+objRef.enabledImage+"\")";
|
181
|
this.map.div.style.cursor = objRef.cursor;
|
182
|
// store the cursor with the map object; this will be applied
|
183
|
// to the map div again when setting the aoi on the
|
184
|
// OpenLayers moveend event
|
185
|
this.map.mbCursor = objRef.cursor;
|
186
|
objRef.enabled = true;
|
187
|
this.active = true;
|
188
|
objRef.doSelect(objRef, true);
|
189
|
}
|
190
|
},
|
191
|
// call objRef.doSelect after OL deactivate from this control
|
192
|
deactivate: function() {
|
193
|
if (this.superclass.deactivate.call(this)) {
|
194
|
this.panel_div.style.backgroundImage = "url(\""+objRef.disabledImage+"\")";
|
195
|
objRef.enabled = false;
|
196
|
this.active = false;
|
197
|
if (map.getControlsBy("active", true).length == 0) {
|
198
|
this.map.div.style.cursor = "";
|
199
|
this.map.mbCursor = "";
|
200
|
}
|
201
|
objRef.doSelect(objRef, false)
|
202
|
}
|
203
|
},
|
204
|
destroy: function() {
|
205
|
try {
|
206
|
this.superclass.destroy.apply(this, arguments);
|
207
|
} catch(e) {
|
208
|
OpenLayers.Control.prototype.destroy.apply(this, arguments);
|
209
|
}
|
210
|
this.superclass = null;
|
211
|
OpenLayers.Event.stopObservingElement(this.panel_div);
|
212
|
this.objRef.panel.div.removeChild(this.panel_div);
|
213
|
this.objRef.control = null;
|
214
|
this.objRef = null;
|
215
|
this.panel_div = null;
|
216
|
this.div = null;
|
217
|
}
|
218
|
});
|
219
|
|
220
|
// if the subclass provides an instantiateControl() method,
|
221
|
// use it for instantiation. If not, instantiate directly
|
222
|
if (!objRef.control) {
|
223
|
objRef.control = objRef.instantiateControl ? objRef.instantiateControl(objRef, Control) : new Control();
|
224
|
}
|
225
|
|
226
|
// get the control from the createControl method of the subclass
|
227
|
//objRef.control = objRef.createControl(objRef);
|
228
|
var map = objRef.targetContext.map;
|
229
|
objRef.panel = objRef.targetContext.buttonBars[objRef.htmlTagId];
|
230
|
// create a panel, if we do not have one yet for this buttonBar
|
231
|
// or if the old map.panel was destroyed
|
232
|
if (!objRef.panel || objRef.panel.map == null) {
|
233
|
// create a dom node for OL to use as panel
|
234
|
if (!document.getElementById(objRef.panelHtmlTagId)) {
|
235
|
var olPanelNode = document.createElement('div');
|
236
|
olPanelNode.setAttribute('id', objRef.panelHtmlTagId);
|
237
|
olPanelNode.setAttribute('class', 'olControlPanel');
|
238
|
var parentNode = objRef.getNode();
|
239
|
parentNode.appendChild(olPanelNode);
|
240
|
parentNode.innerHTML += " ";
|
241
|
}
|
242
|
var Panel = OpenLayers.Class( OpenLayers.Control.Panel, {
|
243
|
div: document.getElementById(objRef.panelHtmlTagId),
|
244
|
defaultControl: null,
|
245
|
destroy: function() {
|
246
|
parentNode.removeChild(this.div);
|
247
|
OpenLayers.Control.prototype.destroy.apply(this, arguments);
|
248
|
this.div = null;
|
249
|
objRef.panel = null;
|
250
|
}
|
251
|
});
|
252
|
objRef.panel = new Panel();
|
253
|
objRef.targetContext.buttonBars[objRef.htmlTagId] = objRef.panel;
|
254
|
map.addControl(objRef.panel);
|
255
|
}
|
256
|
|
257
|
// add the control to the panel
|
258
|
if (OpenLayers.Util.indexOf(objRef.control, objRef.panel.controls) == -1) {
|
259
|
// we do not want to stop event propagation. So we save the original
|
260
|
// Event.stop function...
|
261
|
var originalStop = OpenLayers.Event.stop;
|
262
|
// and overwrite it with a new one...
|
263
|
OpenLayers.Event.stop = function(){};
|
264
|
// now, thanks to boxing, this one will be assigned in addControls...
|
265
|
objRef.panel.addControls(objRef.control);
|
266
|
// and we can switch back to the original one.
|
267
|
OpenLayers.Event.stop = originalStop;
|
268
|
}
|
269
|
|
270
|
// set tooltip for the button
|
271
|
if (objRef.tooltip) {
|
272
|
objRef.control.panel_div.title=objRef.tooltip;
|
273
|
}
|
274
|
|
275
|
//set default css style properties
|
276
|
objRef.control.panel_div.style.backgroundImage = "url(\""+objRef.disabledImage+"\")";
|
277
|
|
278
|
// activate the control if it is defined as selected in config
|
279
|
if(objRef.selected == true) {
|
280
|
objRef.control.activate();
|
281
|
}
|
282
|
}
|
283
|
|
284
|
/**
|
285
|
* Set the target context for the button, initialise the
|
286
|
* buttonBars array in the context document and add a
|
287
|
* listener to the target model for adding controls
|
288
|
* to the OL map as soon as the map is initialized.
|
289
|
* @param objRef Reference to this object.
|
290
|
*/
|
291
|
this.buttonInit = function(objRef) {
|
292
|
//set the target context
|
293
|
var targetContext = objRef.widgetNode.selectSingleNode("mb:targetContext");
|
294
|
if (targetContext) {
|
295
|
objRef.targetContext = window.config.objects[getNodeValue(targetContext)];
|
296
|
if ( !objRef.targetModel ) {
|
297
|
alert(mbGetMessage("noTargetContext", getNodeValue(targetContext), objRef.id));
|
298
|
}
|
299
|
} else {
|
300
|
objRef.targetContext = objRef.targetModel;
|
301
|
}
|
302
|
|
303
|
// initialize button bars for the context
|
304
|
if (!objRef.targetContext.buttonBars) {
|
305
|
// this array in the context will hold all
|
306
|
// buttonBars used by button widgets
|
307
|
objRef.targetContext.buttonBars = new Array();
|
308
|
}
|
309
|
|
310
|
// add another event listener for the loaded context,
|
311
|
// because we need the map to add panel and buttons,
|
312
|
// and we do not have tha map yet
|
313
|
objRef.targetContext.addListener("refresh", objRef.attachToOL, objRef);
|
314
|
}
|
315
|
|
316
|
this.model.addListener("init",this.buttonInit,this);
|
317
|
this.model.removeListener("newNodel", this.clearWidget, this);
|
318
|
}
|