Start on the newest megapull

This one swaps out dojo entirely. I wish that there was a way to divide
tasks between dojo and nojo, but the module loader system makes this
more or less impossible, or at least incredibly annoying.
This commit is contained in:
Tom MacWright
2012-10-23 16:41:16 -04:00
parent 6cade83979
commit 6d07b7f45d
18 changed files with 1206 additions and 1327 deletions

View File

@@ -25,12 +25,6 @@ input[type=text]:focus {
border-color:#222;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
text {
-webkit-user-select: none;
-moz-user-select: none;
@@ -44,16 +38,6 @@ table th {
text-align:left;
}
#map {
height: 600px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.help-pane {
position:absolute;
left:0;
@@ -146,10 +130,6 @@ table th {
width:135px;
}
polyline {
cursor: pointer;
}
.edit-pane {
position:absolute;
display:none;

View File

@@ -2,37 +2,95 @@
<html>
<head>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.8/dojo/dojo.js" data-dojo-config="async: true, parseOnLoad: true, baseUrl: 'js/iD/'"></script>
<title>iD</title>
<!-- load Dojo -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.8/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body class="claro">
<div id="appLayout" class="demoLayout">
<script type="text/javascript" src="js/lib/underscore-min.js"></script>
<script type="text/javascript" src="js/lib/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="js/lib/d3.v2.min.js"></script>
<script type="text/javascript" src="js/iD/actions/UndoStack.js"></script>
<script type="text/javascript" src="js/iD/Util.js"></script>
<script type="text/javascript" src="js/iD/Taginfo.js"></script>
<script type="text/javascript" src="js/iD/styleparser/styleparser.js"></script>
<script type="text/javascript" src="js/iD/styleparser/Condition.js"></script>
<script type="text/javascript" src="js/iD/styleparser/Rule.js"></script>
<script type="text/javascript" src="js/iD/styleparser/Style.js"></script>
<script type="text/javascript" src="js/iD/styleparser/StyleChooser.js"></script>
<script type="text/javascript" src="js/iD/styleparser/StyleList.js"></script>
<script type="text/javascript" src="js/iD/styleparser/RuleSet.js"></script>
<script type="text/javascript" src="js/iD/renderer/renderer.js"></script>
<script type="text/javascript" src="js/iD/renderer/EntityUI.js"></script>
<script type="text/javascript" src="js/iD/renderer/WayUI.js"></script>
<script type="text/javascript" src="js/iD/renderer/NodeUI.js"></script>
<script type="text/javascript" src="js/iD/renderer/Map.js"></script>
<script type="text/javascript" src="js/iD/Node.js"></script>
<script type="text/javascript" src="js/iD/Relation.js"></script>
<script type="text/javascript" src="js/iD/Entity.js"></script>
<script type="text/javascript" src="js/iD/Way.js"></script>
<script type="text/javascript" src="js/iD/Connection.js"></script>
<script type="text/javascript" src="js/iD/Controller.js"></script>
<script>
require(["dojo/on", "dojo/dom", "dojo/Evented",
"iD/actions/UndoStack",
"iD/actions/CreatePOIAction",
"iD/actions/AddNodeToWayAction",
"iD/actions/CreateEntityAction",
"iD/controller/edit/NoSelection",
"iD/controller/shape/NoSelection",
"iD/renderer/Map","iD/styleparser/RuleSet",
"iD/ui/DragAndDrop","iD/ui/StepPane",
"dojo/domReady!"], function(on, dom, Evented){
<div id='modebuttons'>
<button id='add-place'>
+ Place</button><button id="add-road">
+ Road</button><button id="add-area">
+ Area</button><button id="undo">
&larr;</button><button id="redo">
&rarr;</button>
<div id='addPOI'>
<table id='dndgrid'>
</table>
</div>
</div>
<div id="zoombuttons">
<button id="zoomIn">+</button><button id="zoomOut">&ndash;</button>
</div>
<!-- Floating help window -->
<div class='help-pane' id='road-help'>
<div>Click on the map to start a road</div>
<div>Draw the road by clicking on points along its path</div>
<div>Choose a road type</div>
</div>
<!-- Floating edit pane -->
<div class='edit-pane'>
<h2>&nbsp;</h2>
<a class='close' href='#close'>&times;</a>
<div class='hud tags'>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class='hud presets'></div>
</div>
</div>
<!-- Map div -->
<div id="map"></div>
<p>Work in progress: <a href='http://www.geowiki.com/'>introduction</a>, <a href='http://github.com/systemed/iD'>code</a>, <a href='http://www.geowiki.com/docs'>docs</a>. Imagery <a href="http://opengeodata.org/microsoft-imagery-details">&copy; 2012</a> Bing, GeoEye, Getmapping, Intermap, Microsoft.</p>
</div>
<script>
var ruleset = new iD.styleparser.RuleSet();
var connection = new iD.Connection("http://www.overpass-api.de/api/xapi?");
@@ -45,7 +103,7 @@ require(["dojo/on", "dojo/dom", "dojo/Evented",
lat: 51.87,
lon: -1.49,
zoom: 17,
div: "map",
selector: "#map",
connection: connection,
width: $('#map').width(),
height: $('#map').height()
@@ -118,61 +176,6 @@ require(["dojo/on", "dojo/dom", "dojo/Evented",
scroll = 0;
}
});
});
</script>
<div id='modebuttons'>
<button id='add-place'>
+ Place</button><button id="add-road">
+ Road</button><button id="add-area">
+ Area</button><button id="undo">
&larr;</button><button id="redo">
&rarr;</button>
<div id='addPOI'>
<table id='dndgrid'>
</table>
</div>
</div>
<div id="zoombuttons">
<button id="zoomIn">+</button><button id="zoomOut">&ndash;</button>
</div>
<!-- Floating help window -->
<div class='help-pane' id='road-help'>
<div>Click on the map to start a road</div>
<div>Draw the road by clicking on points along its path</div>
<div>Choose a road type</div>
</div>
<!-- Floating edit pane -->
<div class='edit-pane'>
<h2>&nbsp;</h2>
<a class='close' href='#close'>&times;</a>
<div class='hud tags'>
<table>
<thead>
<tr>
<th>Key</th>
<th>Value</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<div class='hud presets'></div>
</div>
</div>
<!-- Map div -->
<div id='progress'></div>
<div id="map"></div>
<p>Work in progress: <a href='http://www.geowiki.com/'>introduction</a>, <a href='http://github.com/systemed/iD'>code</a>, <a href='http://www.geowiki.com/docs'>docs</a>. Imagery <a href="http://opengeodata.org/microsoft-imagery-details">&copy; 2012</a> Bing, GeoEye, Getmapping, Intermap, Microsoft.</p>
</div><!-- applayout -->
</body>
</html>

View File

@@ -1,7 +1,3 @@
// define(["dojo/_base/xhr","dojo/_base/lang","dojox/xml/DomParser","dojo/_base/array",'dojo/_base/declare',
// "iD/Entity","iD/Node","iD/Way","iD/Relation","iD/actions/CreateEntityAction"],
// function(xhr,lang,DomParser,array,declare,Entity){
// ----------------------------------------------------------------------
// Connection base class

View File

@@ -7,7 +7,7 @@ iD.Controller = function(map) {
controller.editorCache = {};
controller.undoStack = new iD.UndoStack();
controller.stepper = new iD.ui.StepPane();
// controller.stepper = new iD.ui.StepPane();
controller.setState = function(newState) {
// summary: Enter a new ControllerState, firing exitState on the old one, and enterState on the new one.

View File

@@ -7,128 +7,120 @@
// fill images
// opacity
define(['dojo/_base/declare','iD/Entity','iD/renderer/Map'],
function(declare) {
// ----------------------------------------------------------------------
// EntityUI base class
// ----------------------------------------------------------------------
// EntityUI base class
iD.renderer.EntityUI = function() {
this.entity=entity;
this.map=map;
this.stateClasses=stateClasses ? stateClasses.slice() : [];
this.sprites=[];
};
iD.renderer.EntityUI.prototype = {
declare("iD.renderer.EntityUI", null, {
entity:null, // Entity this represents
map:null, // the Map object containing this
layer:0, // OSM layer
sprites:null, // array of sprites created for this EntityUI
styleList:null, // current StyleList
stateClasses:null, // list of stateClass tags to apply
entity:null, // Entity this represents
map:null, // the Map object containing this
layer:0, // OSM layer
sprites:null, // array of sprites created for this EntityUI
styleList:null, // current StyleList
stateClasses:null, // list of stateClass tags to apply
constructor: function(entity,map,stateClasses) {
// summary: Base class for a UI representing an entity.
this.entity=entity;
this.map=map;
this.stateClasses=stateClasses ? stateClasses.slice() : [];
this.sprites=[];
},
getConnection: function() {
// summary: Get the Connection from where the map draws its data.
return this.map.connection; // iD.Connection
},
targetGroup: function(groupType,sublayer) {
// summary: Find a gfx.Group to render on.
return this.map.sublayer(this.layer,groupType,sublayer); // dojox.gfx.Group
},
recordSprite: function(sprite) {
// summary: Record that an individual sprite (one stroke, icon or text item) has been added.
if (!_.include(this.sprites, sprite)) {
this.sprites.push(sprite);
}
return sprite;
},
removeSprites: function() {
// summary: Clear all sprites currently used.
for (var i=0; i<this.sprites.length; i++) {
this.sprites[i].removeShape();
}
this.sprites=[];
},
refreshStyleList: function(tags) {
// summary: Calculate the list of styles that apply to this UI at this zoom level.
if (!this.styleList || !this.styleList.isValidAt(this.map.zoom)) {
this.styleList=this.map.ruleset.getStyles(this.entity,tags, this.map.zoom);
}
this.layer=this.styleList.layerOverride();
if (isNaN(this.layer)) {
this.layer=0;
if (tags.layer) { this.layer = +tags.layer; }
}
// Iterate through each subpart, drawing any styles on that layer
var drawn=false;
for (i=0; i<this.styleList.subparts.length; i++) {
var subpart=this.styleList.subparts[i];
}
},
getEnhancedTags: function() {
// summary: Return tags for this entity augmented by the EntityUI's state classes.
var tags = _.clone(this.entity.tags);
// Apply stateClasses (hover, selected, hoverway, selectedway)
for (var i in this.stateClasses) {
tags[':'+this.stateClasses[i]] = 'yes';
}
// todo - Add any common 'special-case' tags, e.g. :hasTags
return tags; // Object
},
// --------------------
// State class handling
setStateClasses:function(stateClasses) {
// summary: Set all state classes at once, and prompt a redraw if they're different to previously,
if (stateClasses && this.stateClasses.join(',')!=stateClasses.join(',')) {
this.stateClasses=stateClasses.slice();
this.invalidateStyleList();
}
return this;
},
setStateClass:function(sc) {
// summary: Set a single state class, and prompt a redraw if it wasn't set previously.
if (this.stateClasses.indexOf(sc)==-1) {
this.stateClasses.push(sc);
this.invalidateStyleList();
}
return this;
},
resetStateClass:function(sc) {
// summary: Reset a single state class, and prompt a redraw if it was set previously.
if (this.stateClasses.indexOf(sc)>-1) {
this.stateClasses.splice(this.stateClasses.indexOf(sc),1);
this.invalidateStyleList();
}
return this;
},
hasStateClass:function(sc) {
// summary: Is a particular state class set for this UI?
return this.stateClasses.indexOf(sc) > -1;
},
invalidateStyleList:function() {
// summary: Invalidate the StyleList so it's recalculated on next redraw.
this.styleList = null;
},
// --------------------
// Mouse event handling
entityMouseEvent:function(event) {
// summary: Receive a mouse event (e.g. clicking on the UI), and forward it to the Controller.
this.map.controller.entityMouseEvent(event, event.gfxTarget.source);
event.stopPropagation();
getConnection: function() {
// summary: Get the Connection from where the map draws its data.
return this.map.connection; // iD.Connection
},
targetGroup: function(groupType,sublayer) {
// summary: Find a gfx.Group to render on.
return this.map.sublayer(this.layer,groupType,sublayer); // dojox.gfx.Group
},
recordSprite: function(sprite) {
// summary: Record that an individual sprite (one stroke, icon or text item) has been added.
if (!_.include(this.sprites, sprite)) {
this.sprites.push(sprite);
}
return sprite;
},
removeSprites: function() {
// summary: Clear all sprites currently used.
for (var i=0; i<this.sprites.length; i++) {
this.sprites[i].removeShape();
}
this.sprites=[];
},
refreshStyleList: function(tags) {
// summary: Calculate the list of styles that apply to this UI at this zoom level.
if (!this.styleList || !this.styleList.isValidAt(this.map.zoom)) {
this.styleList=this.map.ruleset.getStyles(this.entity,tags, this.map.zoom);
}
this.layer=this.styleList.layerOverride();
if (isNaN(this.layer)) {
this.layer=0;
if (tags.layer) { this.layer = +tags.layer; }
}
});
// ----------------------------------------------------------------------
// End of module
});
// Iterate through each subpart, drawing any styles on that layer
var drawn=false;
for (i=0; i<this.styleList.subparts.length; i++) {
var subpart=this.styleList.subparts[i];
}
},
getEnhancedTags: function() {
// summary: Return tags for this entity augmented by the EntityUI's state classes.
var tags = _.clone(this.entity.tags);
// Apply stateClasses (hover, selected, hoverway, selectedway)
for (var i in this.stateClasses) {
tags[':'+this.stateClasses[i]] = 'yes';
}
// todo - Add any common 'special-case' tags, e.g. :hasTags
return tags; // Object
},
// --------------------
// State class handling
setStateClasses:function(stateClasses) {
// summary: Set all state classes at once, and prompt a redraw if they're different to previously,
if (stateClasses && this.stateClasses.join(',')!=stateClasses.join(',')) {
this.stateClasses=stateClasses.slice();
this.invalidateStyleList();
}
return this;
},
setStateClass:function(sc) {
// summary: Set a single state class, and prompt a redraw if it wasn't set previously.
if (this.stateClasses.indexOf(sc)==-1) {
this.stateClasses.push(sc);
this.invalidateStyleList();
}
return this;
},
resetStateClass:function(sc) {
// summary: Reset a single state class, and prompt a redraw if it was set previously.
if (this.stateClasses.indexOf(sc)>-1) {
this.stateClasses.splice(this.stateClasses.indexOf(sc),1);
this.invalidateStyleList();
}
return this;
},
hasStateClass:function(sc) {
// summary: Is a particular state class set for this UI?
return this.stateClasses.indexOf(sc) > -1;
},
invalidateStyleList:function() {
// summary: Invalidate the StyleList so it's recalculated on next redraw.
this.styleList = null;
},
// --------------------
// Mouse event handling
entityMouseEvent:function(event) {
// summary: Receive a mouse event (e.g. clicking on the UI), and forward it to the Controller.
this.map.controller.entityMouseEvent(event, event.gfxTarget.source);
event.stopPropagation();
}
};

View File

@@ -1,513 +1,496 @@
// iD/renderer/Map.js
// at present this combines P2's Map and MapPaint functionality
define(['dojo/_base/declare','dojo/_base/event',
'dojo/dom-geometry',
'dojox/gfx','dojox/gfx/matrix',
'iD/Connection','iD/Entity','iD/renderer/EntityUI','iD/renderer/WayUI','iD/renderer/NodeUI'],
function(declare, Event, domGeom, Gfx, Matrix){
// ----------------------------------------------------------------------
// Connection base class
// ----------------------------------------------------------------------
// Connection base class
iD.renderer.Map = function(obj) {
// summary: The main map display, containing the individual sprites (UIs) for each entity.
// obj: Object An object containing .lat, .lon, .scale, .div (the name of the <div> to be used),
// .connection, .width (px) and .height (px) properties.
this.mapwidth = obj.width ? obj.width : 800;
this.mapheight = obj.height ? obj.height : 400;
declare("iD.renderer.Map", null, {
// Initialise variables
this.uis = {};
MASTERSCALE: 5825.4222222222,
MINSCALE: 14,
MAXSCALE: 23,
zoom: NaN,
zoomfactor: NaN,
baselon: NaN, // original longitude at top left of viewport
baselat: NaN, // original latitude at top left of viewport
baselatp: NaN, // original projected latitude at top left of viewport
this.surface = d3.selectAll(obj.selector)
.append('svg')
.attr('width', this.mapwidth)
.attr('height', this.mapwidth);
div: '', // <div> of this map
surface: null, // <div>.surface containing the rendering
container: null, // root-level group within the surface
backdrop: null, // coloured backdrop (MapCSS canvas element)
connection: null, // data store
controller: null, // UI controller
uis: {},
this.tilegroup = this.surface.append('g');
this.container = this.surface.append('g');
this.connection = obj.connection;
this.zoom = obj.zoom ? obj.zoom : 17;
this.baselon = obj.lon;
this.baselat = obj.lat;
this.baselatp = this.lat2latp(obj.lat);
this._setScaleFactor();
this.updateCoordsFromViewportPosition();
tilegroup: null, // group within container for adding bitmap tiles
tiles: {}, // index of tile objects
tilebaseURL: 'http://ecn.t0.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z', // Bing imagery URL
// Cache the margin box, since this is expensive.
// this.marginBox = domGeom.getMarginBox(this.div);
dragging: false, // current drag state
dragged: false, // was most recent click a drag?
dragx: NaN, // click co-ordinates at previously recorded drag event
dragy: NaN, // |
startdragx: NaN, // click co-ordinates at start of drag
startdragy: NaN, // |
dragtime: NaN, // timestamp of mouseup (compared to stop resulting click from firing)
dragconnect: null, // event listener for endDrag
// Initialise layers
this.layers={};
for (var l=this.minlayer; l<=this.maxlayer; l++) {
var r = this.container.append('g');
this.layers[l]={
root: r,
fill: r.append('g'),
casing: r.append('g'),
stroke: r.append('g'),
text: r.append('g'),
hit: r.append('g')
};
}
containerx: 0, // screen co-ordinates of container
containery: 0, // |
centrelat: NaN, // lat/long and bounding box of map
centrelon: NaN, // |
extent: {}, // |
mapheight: NaN, // size of map object in pixels
mapwidth: NaN, // |
// Create group for elastic band
this.elastic = this.container.append('g');
layers: null, // array-like object of Groups, one for each OSM layer
minlayer: -5, // minimum OSM layer supported
maxlayer: 5, // maximum OSM layer supported
// Make draggable
this.tilegroup.on('onmousedown', _.bind(this.startDrag, this));
this.surface.on('onclick', _.bind(this.clickSurface, this));
this.surface.on('onmousemove', _.bind(this.processMove, this));
this.surface.on('onmousedown', _.bind(this._mouseEvent, this));
this.surface.on('onmouseup', _.bind(this._mouseEvent, this));
};
iD.renderer.Map.prototype = {
elastic: null, // Group for drawing elastic band
MASTERSCALE: 5825.4222222222,
MINSCALE: 14,
MAXSCALE: 23,
zoom: NaN,
zoomfactor: NaN,
baselon: NaN, // original longitude at top left of viewport
baselat: NaN, // original latitude at top left of viewport
baselatp: NaN, // original projected latitude at top left of viewport
ruleset: null, // map style
div: '', // <div> of this map
surface: null, // <div>.surface containing the rendering
container: null, // root-level group within the surface
backdrop: null, // coloured backdrop (MapCSS canvas element)
connection: null, // data store
controller: null, // UI controller
uis: {},
constructor: function(obj) {
// summary: The main map display, containing the individual sprites (UIs) for each entity.
// obj: Object An object containing .lat, .lon, .scale, .div (the name of the <div> to be used),
// .connection, .width (px) and .height (px) properties.
tilegroup: null, // group within container for adding bitmap tiles
tiles: {}, // index of tile objects
tilebaseURL: 'http://ecn.t0.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z', // Bing imagery URL
this.mapwidth = obj.width ? obj.width : 800;
this.mapheight = obj.height ? obj.height : 400;
dragging: false, // current drag state
dragged: false, // was most recent click a drag?
dragx: NaN, // click co-ordinates at previously recorded drag event
dragy: NaN, // |
startdragx: NaN, // click co-ordinates at start of drag
startdragy: NaN, // |
dragtime: NaN, // timestamp of mouseup (compared to stop resulting click from firing)
dragconnect: null, // event listener for endDrag
// Initialise variables
this.uis = {};
this.div=document.getElementById(obj.div);
this.surface=Gfx.createSurface(obj.div, this.mapwidth, this.mapheight);
this.backdrop=this.surface.createRect({
x: 0,
y: 0,
width: this.mapwidth,
height: this.mapheight
}).setFill(new dojo.Color([255,255,245,1]));
this.tilegroup = this.surface.createGroup();
this.container = this.surface.createGroup();
this.connection = obj.connection;
this.zoom = obj.zoom ? obj.zoom : 17;
this.baselon = obj.lon;
this.baselat = obj.lat;
this.baselatp = this.lat2latp(obj.lat);
this._setScaleFactor();
this.updateCoordsFromViewportPosition();
containerx: 0, // screen co-ordinates of container
containery: 0, // |
centrelat: NaN, // lat/long and bounding box of map
centrelon: NaN, // |
extent: {}, // |
mapheight: NaN, // size of map object in pixels
mapwidth: NaN, // |
// Cache the margin box, since this is expensive.
this.marginBox = domGeom.getMarginBox(this.div);
layers: null, // array-like object of Groups, one for each OSM layer
minlayer: -5, // minimum OSM layer supported
maxlayer: 5, // maximum OSM layer supported
// Initialise layers
this.layers={};
for (var l=this.minlayer; l<=this.maxlayer; l++) {
var r=this.container.createGroup();
this.layers[l]={
root: r,
fill: r.createGroup(),
casing: r.createGroup(),
stroke: r.createGroup(),
text: r.createGroup(),
hit: r.createGroup()
};
elastic: null, // Group for drawing elastic band
ruleset: null, // map style
setController:function(controller) {
// summary: Set the controller that will handle events on the map (e.g. mouse clicks).
this.controller = controller;
},
_moveToPosition:function(group, position) {
// summary: Supplementary method for dojox.gfx.
// This should ideally be core Dojo stuff: see http://bugs.dojotoolkit.org/ticket/15296
var parent=group.getParent();
if (!parent) { return; }
this._moveChildToPosition(parent,group,position);
if (position === group.rawNode.parentNode.childNodes.length) {
group.rawNode.parentNode.appendChild(group.rawNode);
} else {
group.rawNode.parentNode.insertBefore(group.rawNode, group.rawNode.parentNode.childNodes[position]);
}
},
_moveChildToPosition: function(parent, child, position) {
for (var i = 0; i < parent.children.length; ++i){
if (parent.children[i] === child){
parent.children.splice(i, 1);
parent.children.splice(position, 0, child);
break;
}
}
},
// Create group for elastic band
this.elastic = this.container.createGroup();
// ----------------------------
// Sprite and EntityUI handling
// Make draggable
this.backdrop.connect("onmousedown", _.bind(this.startDrag, this));
this.tilegroup.connect("onmousedown", _.bind(this.startDrag, this));
this.surface.connect("onclick", _.bind(this.clickSurface, this));
this.surface.connect("onmousemove", _.bind(this.processMove, this));
this.surface.connect("onmousedown", _.bind(this._mouseEvent, this));
this.surface.connect("onmouseup", _.bind(this._mouseEvent, this));
},
setController:function(controller) {
// summary: Set the controller that will handle events on the map (e.g. mouse clicks).
this.controller = controller;
},
_moveToPosition:function(group, position) {
// summary: Supplementary method for dojox.gfx.
// This should ideally be core Dojo stuff: see http://bugs.dojotoolkit.org/ticket/15296
var parent=group.getParent();
if (!parent) { return; }
this._moveChildToPosition(parent,group,position);
if (position === group.rawNode.parentNode.childNodes.length) {
group.rawNode.parentNode.appendChild(group.rawNode);
} else {
group.rawNode.parentNode.insertBefore(group.rawNode, group.rawNode.parentNode.childNodes[position]);
sublayer:function(layer,groupType,sublayer) {
// summary: Find the gfx.Group for a given OSM layer and rendering sublayer, creating it
// if necessary. Note that sublayers are only implemented for stroke and fill.
// groupType: String 'casing','text','hit','stroke', or 'fill'
var collection = this.layers[layer][groupType], sub;
switch (groupType) {
case 'casing':
case 'text':
case 'hit':
return collection;
}
// Find correct sublayer, inserting if necessary
var insertAt=collection.children.length;
for (var i = 0; i < collection.children.length; i++) {
sub=collection.children[i];
if (sub.sublayer==sublayer) { return sub; }
else if (sub.sublayer>sublayer) {
sub = collection.createGroup();
this._moveToPosition(sub,i);
sub.sublayer=sublayer;
return sub;
}
},
}
sub = collection.createGroup().moveToFront();
sub.sublayer=sublayer;
return sub; // dojox.gfx.Group
},
_moveChildToPosition: function(parent, child, position) {
for (var i = 0; i < parent.children.length; ++i){
if (parent.children[i] === child){
parent.children.splice(i, 1);
parent.children.splice(position, 0, child);
break;
}
createUI: function(e, stateClasses) {
// summary: Create a UI (sprite) for an entity, assigning any specified state classes
// (temporary attributes such as ':hover' or ':selected')
if (!this.uis[e.id]) {
if (e.entityType === 'node') {
this.uis[e.id] = new iD.renderer.NodeUI(e, this, stateClasses);
} else if (e.entityType === 'way') {
this.uis[e.id] = new iD.renderer.WayUI(e, this, stateClasses);
}
},
} else {
this.uis[e.id].setStateClasses(stateClasses).redraw();
}
},
// ----------------------------
// Sprite and EntityUI handling
getUI: function(e) {
// summary: Return the UI for an entity, if it exists.
return this.uis[e.id]; // iD.renderer.EntityUI
},
sublayer:function(layer,groupType,sublayer) {
// summary: Find the gfx.Group for a given OSM layer and rendering sublayer, creating it
// if necessary. Note that sublayers are only implemented for stroke and fill.
// groupType: String 'casing','text','hit','stroke', or 'fill'
var collection = this.layers[layer][groupType], sub;
switch (groupType) {
case 'casing':
case 'text':
case 'hit':
return collection;
}
// Find correct sublayer, inserting if necessary
var insertAt=collection.children.length;
for (var i = 0; i < collection.children.length; i++) {
sub=collection.children[i];
if (sub.sublayer==sublayer) { return sub; }
else if (sub.sublayer>sublayer) {
sub = collection.createGroup();
this._moveToPosition(sub,i);
sub.sublayer=sublayer;
return sub;
}
}
sub = collection.createGroup().moveToFront();
sub.sublayer=sublayer;
return sub; // dojox.gfx.Group
},
refreshUI: function(e) {
// summary: Redraw the UI for an entity.
if (this.uis[e.id]) { this.uis[e.id].redraw(); }
},
createUI: function(e, stateClasses) {
// summary: Create a UI (sprite) for an entity, assigning any specified state classes
// (temporary attributes such as ':hover' or ':selected')
deleteUI: function(e) {
// summary: Delete the UI for an entity.
if (this.uis[e.id]) {
this.uis[e.id].removeSprites();
delete this.uis[e.id];
}
},
download: function() {
// summary: Ask the connection to download data for the current viewport.
this.connection.loadFromAPI(this.extent, _.bind(this.updateUIs, this));
},
updateUIs: function() {
// summary: Draw/refresh all EntityUIs within the bbox, and remove any others.
// redraw: Boolean Should we redraw any UIs that are already present?
// remove: Boolean Should we delete any UIs that are no longer in the bbox?
var o = this.connection.getObjectsByBbox(this.extent);
var touch = _(o.inside).chain()
.filter(function(w) { return w.loaded; })
.map(_.bind(function(e) {
if (!this.uis[e.id]) {
if (e.entityType === 'node') {
this.uis[e.id] = new iD.renderer.NodeUI(e, this, stateClasses);
} else if (e.entityType === 'way') {
this.uis[e.id] = new iD.renderer.WayUI(e, this, stateClasses);
}
this.createUI(e);
} else {
this.uis[e.id].setStateClasses(stateClasses).redraw();
this.uis[e.id].redraw();
}
},
return '' + e.id;
}, this)).value();
_.each(_.difference(_.keys(this.uis), touch), _.bind(function(k) {
this.deleteUI(k);
}, this));
},
getUI: function(e) {
// summary: Return the UI for an entity, if it exists.
return this.uis[e.id]; // iD.renderer.EntityUI
},
// -------------
// Zoom handling
refreshUI: function(e) {
// summary: Redraw the UI for an entity.
if (this.uis[e.id]) { this.uis[e.id].redraw(); }
},
zoomIn: function() {
// summary: Zoom in by one level (unless maximum reached).
return this.setZoom(this.zoom + 1);
},
deleteUI: function(e) {
// summary: Delete the UI for an entity.
if (this.uis[e.id]) {
this.uis[e.id].removeSprites();
delete this.uis[e.id];
}
},
zoomOut: function() {
// summary: Zoom out by one level (unless minimum reached).
this.setZoom(this.zoom - 1);
this.download();
return this;
},
download: function() {
// summary: Ask the connection to download data for the current viewport.
$('#progress').show().addClass('spinner');
this.connection.loadFromAPI(this.extent, _.bind(this.updateUIs, this));
},
setZoom: function(zoom) {
if (zoom < this.MINSCALE || zoom > this.MAXSCALE) return this;
// summary: Redraw the map at a new zoom level.
this.zoom = zoom;
this._setScaleFactor();
this._blankTiles();
this.setCentre({
lat: this.centrelat,
lon: this.centrelon
});
this.updateUIs(true, true);
return this;
},
updateUIs: function() {
// summary: Draw/refresh all EntityUIs within the bbox, and remove any others.
// redraw: Boolean Should we redraw any UIs that are already present?
// remove: Boolean Should we delete any UIs that are no longer in the bbox?
$('#progress').hide().removeClass('spinner');
var o = this.connection.getObjectsByBbox(this.extent);
var touch = _(o.inside).chain()
.filter(function(w) { return w.loaded; })
.map(_.bind(function(e) {
if (!this.uis[e.id]) {
this.createUI(e);
} else {
this.uis[e.id].redraw();
}
return '' + e.id;
}, this)).value();
_.each(_.difference(_.keys(this.uis), touch), _.bind(function(k) {
this.deleteUI(k);
}, this));
},
_setScaleFactor: function() {
// summary: Calculate the scaling factor for this zoom level.
this.zoomfactor = this.MASTERSCALE/Math.pow(2, 13 - this.zoom);
},
// -------------
// Zoom handling
// ----------------------
// Elastic band redrawing
zoomIn: function() {
// summary: Zoom in by one level (unless maximum reached).
return this.setZoom(this.zoom + 1);
},
clearElastic: function() {
// summary: Remove the elastic band used to draw new ways.
this.elastic.clear();
},
zoomOut: function() {
// summary: Zoom out by one level (unless minimum reached).
this.setZoom(this.zoom - 1);
this.download();
return this;
},
drawElastic: function(x1,y1,x2,y2) {
// summary: Draw the elastic band (for new ways) between two points.
this.elastic.clear();
// **** Next line is SVG-specific
this.elastic.rawNode.setAttribute("pointer-events","none");
this.elastic.createPolyline( [{ x:x1, y:y1 }, { x:x2, y:y2 }] ).setStroke( {
color: [0, 0, 0, 1],
style: 'Solid',
width: 1
});
},
setZoom: function(zoom) {
if (zoom < this.MINSCALE || zoom > this.MAXSCALE) return this;
// summary: Redraw the map at a new zoom level.
this.zoom = zoom;
this._setScaleFactor();
this._blankTiles();
this.setCentre({
lat: this.centrelat,
lon: this.centrelon
});
this.updateUIs(true, true);
return this;
},
// -------------
// Tile handling
// ** FIXME: see docs
loadTiles: function() {
// summary: Load all tiles for the current viewport. This is a bare-bones function
// at present: it needs configurable URLs (not just Bing), attribution/logo
// support, and to be 'nudgable' (i.e. adjust the offset).
var tl = this.locationCoord({
lat: this.extent.north,
lon: this.extent.west
}, this.zoom),
br = this.locationCoord({
lat: this.extent.south,
lon: this.extent.east
}, this.zoom),
tileKeys = _.keys(this.tiles),
seen = [],
coord = { z: this.zoom };
_setScaleFactor: function() {
// summary: Calculate the scaling factor for this zoom level.
this.zoomfactor = this.MASTERSCALE/Math.pow(2, 13 - this.zoom);
},
// ----------------------
// Elastic band redrawing
clearElastic: function() {
// summary: Remove the elastic band used to draw new ways.
this.elastic.clear();
},
drawElastic: function(x1,y1,x2,y2) {
// summary: Draw the elastic band (for new ways) between two points.
this.elastic.clear();
// **** Next line is SVG-specific
this.elastic.rawNode.setAttribute("pointer-events","none");
this.elastic.createPolyline( [{ x:x1, y:y1 }, { x:x2, y:y2 }] ).setStroke( {
color: [0, 0, 0, 1],
style: 'Solid',
width: 1
});
},
// -------------
// Tile handling
// ** FIXME: see docs
loadTiles: function() {
// summary: Load all tiles for the current viewport. This is a bare-bones function
// at present: it needs configurable URLs (not just Bing), attribution/logo
// support, and to be 'nudgable' (i.e. adjust the offset).
var tl = this.locationCoord({
lat: this.extent.north,
lon: this.extent.west
}, this.zoom),
br = this.locationCoord({
lat: this.extent.south,
lon: this.extent.east
}, this.zoom),
tileKeys = _.keys(this.tiles),
seen = [],
coord = { z: this.zoom };
for (coord.x = tl.x; coord.x <= br.x; coord.x++) {
for (coord.y = tl.y; coord.y <= br.y; coord.y++) {
if (!this._getTile(coord)) {
this._fetchTile(coord);
}
seen.push(iD.Util.tileKey(coord));
for (coord.x = tl.x; coord.x <= br.x; coord.x++) {
for (coord.y = tl.y; coord.y <= br.y; coord.y++) {
if (!this._getTile(coord)) {
this._fetchTile(coord);
}
seen.push(iD.Util.tileKey(coord));
}
}
_.each(_.without(tileKeys, seen), _.bind(function(key) {
delete this.tiles[key];
}, this));
},
_.each(_.without(tileKeys, seen), _.bind(function(key) {
delete this.tiles[key];
}, this));
},
_fetchTile: function(coord) {
// summary: Load a tile image at the given tile co-ordinates.
var t = this.tilegroup.createImage({
x: Math.floor(this.lon2coord(this.tile2lon(coord.x))),
y: Math.floor(this.lat2coord(this.tile2lat(coord.y))),
_fetchTile: function(coord) {
// summary: Load a tile image at the given tile co-ordinates.
var t = this.tilegroup.append('image')
.attr({
width: 256,
height: 256,
src: this._tileURL(coord)
x: Math.floor(this.lon2coord(this.tile2lon(coord.x))),
y: Math.floor(this.lat2coord(this.tile2lat(coord.y))),
'xlink:href': this._tileURL(coord)
});
this._assignTile(coord, t);
},
this._assignTile(coord, t);
},
_getTile: function(coord) {
// summary: See if this tile is already loaded.
return this.tiles[iD.Util.tileKey(coord)];
},
_getTile: function(coord) {
// summary: See if this tile is already loaded.
return this.tiles[iD.Util.tileKey(coord)];
},
_assignTile: function(coord, t) {
// summary: Store a reference to the tile so we know it's loaded.
this.tiles[iD.Util.tileKey(coord)] = t;
},
_assignTile: function(coord, t) {
// summary: Store a reference to the tile so we know it's loaded.
this.tiles[iD.Util.tileKey(coord)] = t;
},
_tileURL: function(coord) {
// summary: Calculate the URL for a tile at the given co-ordinates.
var u = '';
for (var zoom = coord.z; zoom > 0; zoom--) {
var byte = 0;
var mask = 1 << (zoom - 1);
if ((coord.x & mask) !== 0) byte++;
if ((coord.y & mask) !== 0) byte += 2;
u += byte.toString();
_tileURL: function(coord) {
// summary: Calculate the URL for a tile at the given co-ordinates.
var u = '';
for (var zoom = coord.z; zoom > 0; zoom--) {
var byte = 0;
var mask = 1 << (zoom - 1);
if ((coord.x & mask) !== 0) byte++;
if ((coord.y & mask) !== 0) byte += 2;
u += byte.toString();
}
return this.tilebaseURL
.replace('$z', coord.z)
.replace('$x', coord.x)
.replace('$y', coord.y)
.replace('$quadkey', u);
},
_blankTiles: function() {
// summary: Unload all tiles and remove from the display.
this.tilegroup.clear();
this.tiles = {};
},
// -------------------------------------------
// Co-ordinate management, dragging and redraw
startDrag: function(e) {
// summary: Start dragging the map in response to a mouse-down.
// e: MouseEvent The mouse-down event that triggered it.
var srcElement = (e.gfxTarget === this.backdrop) ?
e.gfxTarget : e.gfxTarget.parent;
Event.stop(e);
this.dragging = true;
this.dragged = false;
this.dragx = this.dragy=NaN;
this.startdragx = e.clientX;
this.startdragy = e.clientY;
this.dragconnect = srcElement.connect("onmouseup", _.bind(this.endDrag, this));
},
endDrag: function(e) {
// summary: Stop dragging the map in response to a mouse-up.
// e: MouseEvent The mouse-up event that triggered it.
Event.stop(e);
dojo.disconnect(this.dragconnect);
this.dragging=false;
this.dragtime=e.timeStamp;
this.updateCoordsFromViewportPosition();
if (Math.abs(e.clientX - this.startdragx) < 3 &&
Math.abs(e.clientY - this.startdragy) < 3) {
return;
}
this.download();
},
processMove: function(e) {
// summary: Drag the map to a new origin.
// e: MouseEvent The mouse-move event that triggered it.
var x = e.clientX;
var y = e.clientY;
if (this.dragging) {
if (this.dragx) {
this.containerx += (x - this.dragx);
this.containery += (y - this.dragy);
this.updateOrigin();
this.dragged=true;
}
return this.tilebaseURL
.replace('$z', coord.z)
.replace('$x', coord.x)
.replace('$y', coord.y)
.replace('$quadkey', u);
},
_blankTiles: function() {
// summary: Unload all tiles and remove from the display.
this.tilegroup.clear();
this.tiles = {};
},
// -------------------------------------------
// Co-ordinate management, dragging and redraw
startDrag: function(e) {
// summary: Start dragging the map in response to a mouse-down.
// e: MouseEvent The mouse-down event that triggered it.
var srcElement = (e.gfxTarget === this.backdrop) ?
e.gfxTarget : e.gfxTarget.parent;
Event.stop(e);
this.dragging = true;
this.dragged = false;
this.dragx = this.dragy=NaN;
this.startdragx = e.clientX;
this.startdragy = e.clientY;
this.dragconnect = srcElement.connect("onmouseup", _.bind(this.endDrag, this));
},
endDrag: function(e) {
// summary: Stop dragging the map in response to a mouse-up.
// e: MouseEvent The mouse-up event that triggered it.
Event.stop(e);
dojo.disconnect(this.dragconnect);
this.dragging=false;
this.dragtime=e.timeStamp;
this.updateCoordsFromViewportPosition();
if (Math.abs(e.clientX - this.startdragx) < 3 &&
Math.abs(e.clientY - this.startdragy) < 3) {
return;
}
this.download();
},
processMove: function(e) {
// summary: Drag the map to a new origin.
// e: MouseEvent The mouse-move event that triggered it.
var x = e.clientX;
var y = e.clientY;
if (this.dragging) {
if (this.dragx) {
this.containerx += (x - this.dragx);
this.containery += (y - this.dragy);
this.updateOrigin();
this.dragged=true;
}
this.dragx = x;
this.dragy = y;
} else {
this.controller.entityMouseEvent(e,null);
}
},
updateOrigin: function() {
// summary: Tell Dojo to update the viewport origin.
this.container.setTransform([Matrix.translate(this.containerx, this.containery)]);
this.tilegroup.setTransform([Matrix.translate(this.containerx, this.containery)]);
},
_mouseEvent: function(e) {
// summary: Catch mouse events on the surface but not the tiles - in other words,
// on drawn items that don't have their own hitzones, like the fill of a shape.
if (e.type=='mousedown') { this.startDrag(e); }
// ** FIXME: we may want to reinstate this at some point...
// this.controller.entityMouseEvent(e,null);
},
updateCoordsFromViewportPosition: function(e) {
// summary: Update centre and bbox from the current viewport origin.
this._updateCoords(this.containerx, this.containery);
},
setCentre: function(loc) {
// summary: Update centre and bbox to a specified lat/lon.
var coord = this.locationCoord(loc, this.zoom);
this._updateCoords(
-coord.x - this.mapwidth / 2,
-coord.y - this.mapheight / 2);
return this;
},
setCenter: function(loc) { this.setCentre(loc); },
_updateCoords:function(x, y) {
// summary: Set centre and bbox.
this.containerx = x;
this.containery = y;
this.updateOrigin();
this.centrelon = this.coord2lon(-x + this.mapwidth/2);
this.centrelat = this.coord2lat(-y + this.mapheight/2);
this.extent = {
north: this.coord2lat(-y),
south: this.coord2lat(-y + this.mapheight),
west: this.coord2lon(-x),
east: this.coord2lon(-x + this.mapwidth)
};
this.loadTiles();
},
clickSurface:function(e) {
// summary: Handle a click on an empty area of the map.
if (this.dragged && e.timeStamp==this.dragtime) { return; }
this.dragx = x;
this.dragy = y;
} else {
this.controller.entityMouseEvent(e,null);
},
}
},
// -----------------------
// Co-ordinate conversions
updateOrigin: function() {
// summary: Tell Dojo to update the viewport origin.
// this.container.setTransform([Matrix.translate(this.containerx, this.containery)]);
// this.tilegroup.setTransform([Matrix.translate(this.containerx, this.containery)]);
},
latp2coord:function(a) { return -(a-this.baselatp)*this.zoomfactor; },
coord2latp:function(a) { return a/-this.zoomfactor+this.baselatp; },
lon2coord:function(a) { return (a-this.baselon)*this.zoomfactor; },
coord2lon:function(a) { return a/this.zoomfactor+this.baselon; },
lon2screen:function(a) { return this.lon2coord(a) + this.marginBox.l + this.containerx; },
_mouseEvent: function(e) {
// summary: Catch mouse events on the surface but not the tiles - in other words,
// on drawn items that don't have their own hitzones, like the fill of a shape.
if (e.type=='mousedown') { this.startDrag(e); }
// ** FIXME: we may want to reinstate this at some point...
// this.controller.entityMouseEvent(e,null);
},
lat2latp:function(a) { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); },
latp2lat:function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); },
lat2coord:function(a) { return -(this.lat2latp(a)-this.baselatp)*this.zoomfactor; },
coord2lat:function(a) { return this.latp2lat(a/-this.zoomfactor+this.baselatp); },
lat2screen:function(a) { return this.lat2coord(a) + this.marginBox.t + this.containery; },
updateCoordsFromViewportPosition: function(e) {
// summary: Update centre and bbox from the current viewport origin.
this._updateCoords(this.containerx, this.containery);
},
locationCoord: function(ll, z) {
var z2 = Math.pow(2, z), d2r = Math.PI / 180;
return {
z: z,
x: Math.floor((ll.lon + 180) / 360 * z2),
y: Math.floor((1 - Math.log(Math.tan(ll.lat * d2r) +
1 / Math.cos(ll.lat * d2r)) / Math.PI) / 2 * z2)
};
},
lon2tile:function(a) { return (Math.floor((a+180)/360*Math.pow(2,this.zoom))); },
lat2tile:function(a) { return (Math.floor((1-Math.log(Math.tan(a*Math.PI/180) + 1/Math.cos(a*Math.PI/180))/Math.PI)/2 *Math.pow(2,this.zoom))); },
tile2lon:function(a) { return (a/Math.pow(2,this.zoom)*360-180); },
tile2lat:function(a) {
var n=Math.PI-2*Math.PI*a/Math.pow(2,this.zoom);
return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
},
setCentre: function(loc) {
// summary: Update centre and bbox to a specified lat/lon.
var coord = this.locationCoord(loc, this.zoom);
this._updateCoords(
-coord.x - this.mapwidth / 2,
-coord.y - this.mapheight / 2);
return this;
},
// Turn event co-ordinates into map co-ordinates
setCenter: function(loc) { this.setCentre(loc); },
mouseX: function(e) { return e.clientX - this.marginBox.l - this.containerx; },
mouseY: function(e) { return e.clientY - this.marginBox.t - this.containery; }
});
_updateCoords:function(x, y) {
// summary: Set centre and bbox.
this.containerx = x;
this.containery = y;
this.updateOrigin();
this.centrelon = this.coord2lon(-x + this.mapwidth/2);
this.centrelat = this.coord2lat(-y + this.mapheight/2);
// ----------------------------------------------------------------------
// End of module
});
this.extent = {
north: this.coord2lat(-y),
south: this.coord2lat(-y + this.mapheight),
west: this.coord2lon(-x),
east: this.coord2lon(-x + this.mapwidth)
};
this.loadTiles();
},
clickSurface:function(e) {
// summary: Handle a click on an empty area of the map.
if (this.dragged && e.timeStamp==this.dragtime) { return; }
this.controller.entityMouseEvent(e,null);
},
// -----------------------
// Co-ordinate conversions
latp2coord:function(a) { return -(a-this.baselatp)*this.zoomfactor; },
coord2latp:function(a) { return a/-this.zoomfactor+this.baselatp; },
lon2coord:function(a) { return (a-this.baselon)*this.zoomfactor; },
coord2lon:function(a) { return a/this.zoomfactor+this.baselon; },
lon2screen:function(a) { return this.lon2coord(a) + this.marginBox.l + this.containerx; },
lat2latp:function(a) { return 180/Math.PI * Math.log(Math.tan(Math.PI/4+a*(Math.PI/180)/2)); },
latp2lat:function(a) { return 180/Math.PI * (2 * Math.atan(Math.exp(a*Math.PI/180)) - Math.PI/2); },
lat2coord:function(a) { return -(this.lat2latp(a)-this.baselatp)*this.zoomfactor; },
coord2lat:function(a) { return this.latp2lat(a/-this.zoomfactor+this.baselatp); },
lat2screen:function(a) { return this.lat2coord(a) + this.marginBox.t + this.containery; },
locationCoord: function(ll, z) {
var z2 = Math.pow(2, z), d2r = Math.PI / 180;
return {
z: z,
x: Math.floor((ll.lon + 180) / 360 * z2),
y: Math.floor((1 - Math.log(Math.tan(ll.lat * d2r) +
1 / Math.cos(ll.lat * d2r)) / Math.PI) / 2 * z2)
};
},
lon2tile:function(a) { return (Math.floor((a+180)/360*Math.pow(2,this.zoom))); },
lat2tile:function(a) { return (Math.floor((1-Math.log(Math.tan(a*Math.PI/180) + 1/Math.cos(a*Math.PI/180))/Math.PI)/2 *Math.pow(2,this.zoom))); },
tile2lon:function(a) { return (a/Math.pow(2,this.zoom)*360-180); },
tile2lat:function(a) {
var n=Math.PI-2*Math.PI*a/Math.pow(2,this.zoom);
return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
},
// Turn event co-ordinates into map co-ordinates
mouseX: function(e) { return e.clientX - this.marginBox.l - this.containerx; },
mouseY: function(e) { return e.clientY - this.marginBox.t - this.containery; }
};

View File

@@ -1,107 +1,94 @@
// iD/renderer/NodeUI.js
// NodeUI classes for iD
iD.renderer.NodeUI = function() {};
iD.renderer.NodeUI.prototype = {
getEnhancedTags:function() {
var tags=this.inherited(arguments);
if (!this.entity.entity.hasParentWays()) { tags[':poi']='yes'; }
// add junction and dupe
return tags;
},
redraw:function() {
// summary: Draw the object (mostly icons) and add hitzone sprites.
var node = this.entity;
this.removeSprites();
define(['dojo/_base/declare','dojox/gfx/_base','iD/renderer/EntityUI'],
function(declare, g) {
// Tags, position and styleList
var x = Math.floor(this.map.lon2coord(this.entity.lon));
var y = Math.floor(this.map.latp2coord(this.entity.latp));
var tags = this.getEnhancedTags();
this.refreshStyleList(tags);
// ----------------------------------------------------------------------
// NodeUI class
declare("iD.renderer.NodeUI", [iD.renderer.EntityUI], {
constructor:function() {
// summary: A UI (rendering) representing a node.
this.redraw();
},
getEnhancedTags:function() {
var tags=this.inherited(arguments);
if (!this.entity.entity.hasParentWays()) { tags[':poi']='yes'; }
// add junction and dupe
return tags;
},
redraw:function() {
// summary: Draw the object (mostly icons) and add hitzone sprites.
var node = this.entity;
this.removeSprites();
// Tags, position and styleList
var x = Math.floor(this.map.lon2coord(this.entity.lon));
var y = Math.floor(this.map.latp2coord(this.entity.latp));
var tags = this.getEnhancedTags();
this.refreshStyleList(tags);
// Iterate through each subpart, drawing any styles on that layer
var drawn = false;
var s, p, t, w, h;
for (i = 0; i < this.styleList.subparts.length; i++) {
var subpart=this.styleList.subparts[i];
p = this.styleList.pointStyles[subpart];
if (!p || !p.drawn()) { continue; }
s = this.styleList.shapeStyles[subpart];
t = this.styleList.textStyles[subpart];
w = p.icon_width ? p.icon_width : 16;
h = p.icon_height ? p.icon_height: w;
// Iterate through each subpart, drawing any styles on that layer
var drawn = false;
var s, p, t, w, h;
for (i = 0; i < this.styleList.subparts.length; i++) {
var subpart=this.styleList.subparts[i];
p = this.styleList.pointStyles[subpart];
if (!p || !p.drawn()) { continue; }
s = this.styleList.shapeStyles[subpart];
t = this.styleList.textStyles[subpart];
w = p.icon_width ? p.icon_width : 16;
h = p.icon_height ? p.icon_height: w;
// Draw icon
var shape;
if (p.icon_image === 'square') shape = this.targetGroup('stroke', p.sublayer)
if (p.icon_image === 'square') {
shape = this.targetGroup('stroke', p.sublayer)
.createRect({
x: x-w/2,
y: y-h/2,
width: w,
height: h
});
else if (p.icon_image === 'circle') shape = this.targetGroup('stroke', p.sublayer)
.createCircle({
cx: x,
cy: y,
r: w
});
else shape = this.targetGroup('stroke',p.sublayer)
.createImage({
width: w,
height: h,
x: x-w/2,
y: y-h/2,
src: p.icon_image
});
if (p.icon_image === 'square' || p.icon_image === 'circle') {
shape.setStroke(s.shapeStrokeStyler()).setFill(s.shapeFillStyler());
}
this.recordSprite(shape);
// Add text label
// Add hit-zone
var hit;
if (p.icon_image === 'circle') {
hit = this.targetGroup('hit').createCircle({
cx: x,
cy: y,
r: w
});
} else if (p.icon_image === 'circle') {
shape = this.targetGroup('stroke', p.sublayer)
.createCircle({
cx: x,
cy: y,
r: w
});
} else {
hit = this.targetGroup('hit').createRect({
x: x-w/2,
y: y-h/2,
width: w,
height: h
});
shape = this.targetGroup('stroke',p.sublayer)
.createImage({
width: w,
height: h,
x: x-w/2,
y: y-h/2,
src: p.icon_image
});
if (p.icon_image === 'square' || p.icon_image === 'circle') {
shape.setStroke(s.shapeStrokeStyler()).setFill(s.shapeFillStyler());
}
this.recordSprite(shape);
// Add text label
// Add hit-zone
var hit;
if (p.icon_image === 'circle') {
hit = this.targetGroup('hit').createCircle({
cx: x,
cy: y,
r: w
});
} else {
hit = this.targetGroup('hit').createRect({
x: x-w/2,
y: y-h/2,
width: w,
height: h
});
}
hit.setFill([0,1,0,0]).setStroke({
width:2,
color:[0,0,0,0]
});
this.recordSprite(hit);
hit.source = this;
hit.connect("onclick", _.bind(this.entityMouseEvent, this));
hit.connect("onmousedown", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseup", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseenter", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseleave", _.bind(this.entityMouseEvent, this));
}
hit.setFill([0,1,0,0]).setStroke({
width:2,
color:[0,0,0,0]
});
this.recordSprite(hit);
hit.source = this;
hit.connect("onclick", _.bind(this.entityMouseEvent, this));
hit.connect("onmousedown", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseup", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseenter", _.bind(this.entityMouseEvent, this));
hit.connect("onmouseleave", _.bind(this.entityMouseEvent, this));
}
}
});
// ----------------------------------------------------------------------
// End of module
});
}
}
};

View File

@@ -1,4 +1,3 @@
// iD/renderer/WayUI.js
// WayUI classes for iD
// **** TODO:
// multipolygon support - http://mail.dojotoolkit.org/pipermail/dojo-interest/2011-January/052042.html
@@ -7,16 +6,11 @@
// fill images
// opacity
define(['dojo/_base/declare','iD/renderer/EntityUI'], function(declare) {
// ----------------------------------------------------------------------
// WayUI class
iD.renderer.WayUI = function() {};
declare("iD.renderer.WayUI", [iD.renderer.EntityUI], {
constructor: function() {
// summary: A UI (rendering) representing a way.
this.redraw();
},
iD.renderer.WayUI.prototype = {
getEnhancedTags: function() {
var tags = this.inherited(arguments);
if (this.entity.isClosed()) { tags[':area']='yes'; }
@@ -139,8 +133,4 @@ declare("iD.renderer.WayUI", [iD.renderer.EntityUI], {
entityMouseEvent:function(event) {
this.inherited(arguments);
}
});
// ----------------------------------------------------------------------
// End of module
});
};

View File

@@ -0,0 +1 @@
iD.renderer = {};

View File

@@ -1,11 +1,8 @@
// iD/styleparser/Condition.js
define(['dojo/_base/declare'], function(declare){
// ----------------------------------------------------------------------
// Condition base class
declare("iD.styleparser.Condition", null, {
iD.styleparser.Condition = function() {};
iD.styleparser.Condition.prototype = {
type: '', // eq/ne/regex etc.
params: [], // what to test against
@@ -38,8 +35,4 @@ declare("iD.styleparser.Condition", null, {
toString:function() {
return "["+this.type+": "+this.params+"]";
}
});
// ----------------------------------------------------------------------
// End of module
});
};

View File

@@ -1,55 +1,47 @@
// iD/styleparser/Rule.js
define(['dojo/_base/declare','dojo/_base/array'], function(declare,array){
// ----------------------------------------------------------------------
// Rule class
iD.styleparser.Rule = function() {};
iD.styleparser.Rule.prototype = {
declare("iD.styleparser.Rule", null, {
conditions: [], // the Conditions to be evaluated for the Rule to be fulfilled
isAnd: true, // do all Conditions need to be true for the Rule to be fulfilled? (Always =true for MapCSS)
minZoom: 0, // minimum zoom level at which the Rule is fulfilled
maxZoom: 255, // maximum zoom level at which the Rule is fulfilled
subject: '', // entity type to which the Rule applies: 'way', 'node', 'relation', 'area' (closed way) or 'line' (unclosed way)
conditions: [], // the Conditions to be evaluated for the Rule to be fulfilled
isAnd: true, // do all Conditions need to be true for the Rule to be fulfilled? (Always =true for MapCSS)
minZoom: 0, // minimum zoom level at which the Rule is fulfilled
maxZoom: 255, // maximum zoom level at which the Rule is fulfilled
subject: '', // entity type to which the Rule applies: 'way', 'node', 'relation', 'area' (closed way) or 'line' (unclosed way)
constructor: function(_subject) {
// summary: A MapCSS selector. Contains a list of Conditions; the entity type to which the selector applies;
// and the zoom levels at which it is true. way[waterway=river][boat=yes] would be parsed into one Rule.
// The selectors and declaration together form a StyleChooser.
this.subject=_subject;
this.conditions=[];
},
addCondition: function(_condition) {
// summary: Add a condition to this rule.
this.conditions.push(_condition);
},
constructor: function(_subject) {
// summary: A MapCSS selector. Contains a list of Conditions; the entity type to which the selector applies;
// and the zoom levels at which it is true. way[waterway=river][boat=yes] would be parsed into one Rule.
// The selectors and declaration together form a StyleChooser.
this.subject=_subject;
this.conditions=[];
},
test: function(entity,tags,zoom) {
// summary: Evaluate the Rule on the given entity, tags and zoom level.
// returns: true if the Rule passes, false if the conditions aren't fulfilled.
if ((this.subject !== '') && (entity.entityType !== this.subject)) {
addCondition: function(_condition) {
// summary: Add a condition to this rule.
this.conditions.push(_condition);
},
test: function(entity,tags,zoom) {
// summary: Evaluate the Rule on the given entity, tags and zoom level.
// returns: true if the Rule passes, false if the conditions aren't fulfilled.
if ((this.subject !== '') && (entity.entityType !== this.subject)) {
return false;
}
if (zoom<this.minZoom || zoom>this.maxZoom) { return false; }
if (zoom<this.minZoom || zoom>this.maxZoom) { return false; }
var v=true; var i=0; var isAnd=this.isAnd;
array.forEach(this.conditions, function(condition) {
var r=condition.test(tags);
if (i === 0) { v=r; }
else if (isAnd) { v=v && r; }
else { v = v || r; }
i++;
});
return v;
},
var v=true; var i=0; var isAnd=this.isAnd;
array.forEach(this.conditions, function(condition) {
var r=condition.test(tags);
if (i === 0) { v=r; }
else if (isAnd) { v=v && r; }
else { v = v || r; }
i++;
});
return v;
},
toString:function() {
return this.subject+" z"+this.minZoom+"-"+this.maxZoom+": "+this.conditions;
}
});
// ----------------------------------------------------------------------
// End of module
});
toString:function() {
return this.subject+" z"+this.minZoom+"-"+this.maxZoom+": "+this.conditions;
}
};

View File

@@ -1,81 +1,72 @@
// iD/styleparser/RuleChain.js
define(['dojo/_base/declare','iD/styleparser/Rule'], function(declare){
// ----------------------------------------------------------------------
// RuleChain base class
// In contrast to Halcyon, note that length() is a function, not a getter property
/** A descendant list of MapCSS selectors (Rules).
For example,
relation[type=route] way[highway=primary]
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
first Rule second Rule
|------------|---------|
|
one RuleChain
For example,
relation[type=route] way[highway=primary]
^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
first Rule second Rule
|------------|---------|
|
one RuleChain
*/
declare("iD.styleparser.RuleChain", null, {
iD.styleparser.RuleChain = function() { };
iD.styleparser.RuleChain.prototype = {
rules:[], // list of Rules
subpart: 'default', // subpart name, as in way[highway=primary]::centreline
constructor:function() {
// summary: A descendant list of MapCSS selectors (Rules).
this.rules=[];
},
rules:[], // list of Rules
subpart: 'default', // subpart name, as in way[highway=primary]::centreline
// Functions to define the RuleChain
// Functions to define the RuleChain
addRule:function(_subject) {
this.rules.push(new iD.styleparser.Rule(_subject));
},
addRule:function(_subject) {
this.rules.push(new iD.styleparser.Rule(_subject));
},
addConditionToLast:function(_condition) {
this.rules[this.rules.length-1].addCondition(_condition);
},
addConditionToLast:function(_condition) {
this.rules[this.rules.length-1].addCondition(_condition);
},
addZoomToLast:function(z1,z2) {
this.rules[this.rules.length-1].minZoom=z1;
this.rules[this.rules.length-1].maxZoom=z2;
},
addZoomToLast:function(z1,z2) {
this.rules[this.rules.length-1].minZoom=z1;
this.rules[this.rules.length-1].maxZoom=z2;
},
length:function() {
return this.rules.length;
},
setSubpart:function(subpart) {
this.subpart = subpart || 'default';
},
length:function() {
return this.rules.length;
},
// Test a ruleChain
// - run a set of tests in the chain
// works backwards from at position "pos" in array, or -1 for the last
// separate tags object is required in case they've been dynamically retagged
// - if they fail, return false
// - if they succeed, and it's the last in the chain, return happily
// - if they succeed, and there's more in the chain, rerun this for each parent until success
setSubpart:function(subpart) {
this.subpart = subpart || 'default';
},
test: function(pos, entity, tags, zoom) {
// summary: Test a rule chain by running all the tests in reverse order.
if (this.rules.length === 0) { return false; }
if (pos==-1) { pos=this.rules.length-1; }
// Test a ruleChain
// - run a set of tests in the chain
// works backwards from at position "pos" in array, or -1 for the last
// separate tags object is required in case they've been dynamically retagged
// - if they fail, return false
// - if they succeed, and it's the last in the chain, return happily
// - if they succeed, and there's more in the chain, rerun this for each parent until success
var r = this.rules[pos];
if (!r.test(entity, tags, zoom)) { return false; }
if (pos === 0) { return true; }
test: function(pos, entity, tags, zoom) {
// summary: Test a rule chain by running all the tests in reverse order.
if (this.rules.length === 0) { return false; }
if (pos==-1) { pos=this.rules.length-1; }
var o = entity.entity.parentObjects();
for (var i = 0; i < o.length; i++) {
var p=o[i];
if (this.test(pos-1, p, p.tags, zoom)) { return true; }
}
return false;
}
var r = this.rules[pos];
if (!r.test(entity, tags, zoom)) { return false; }
if (pos === 0) { return true; }
var o = entity.entity.parentObjects();
for (var i = 0; i < o.length; i++) {
var p=o[i];
if (this.test(pos-1, p, p.tags, zoom)) { return true; }
}
return false;
}
});
// ----------------------------------------------------------------------

View File

@@ -1,173 +1,168 @@
// iD/styleparser/RuleSet.js
define(['dojo/_base/xhr','dojo/_base/lang','dojo/_base/declare','dojo/_base/array','iD/styleparser/Style','iD/styleparser/StyleChooser','iD/styleparser/Condition','iD/styleparser/StyleList'], function(xhr,lang,declare,array){
// ----------------------------------------------------------------------
// RuleSet base class
// needs to cope with nested CSS files
// doesn't do untagged nodes optimisation
declare("iD.styleparser.RuleSet", null, {
iD.styleparser.RuleSet = function() {};
choosers: [], // list of StyleChoosers
callback: null,
iD.styleparser.RuleSet.prototype = {
constructor: function() {
// summary: An entire stylesheet in parsed form.
this.choosers = [];
},
choosers: [], // list of StyleChoosers
callback: null,
registerCallback: function(callback) {
// summary: Set a callback function to be called when the CSS is loaded and parsed.
this.callback = callback;
},
registerCallback: function(callback) {
// summary: Set a callback function to be called when the CSS is loaded and parsed.
this.callback = callback;
},
getStyles: function(entity, tags, zoom) {
// summary: Find the styles for a given entity.
var sl=new iD.styleparser.StyleList();
for (var i in this.choosers) {
this.choosers[i].updateStyles(entity, tags, sl, zoom);
}
return sl; // iD.styleparser.StyleList
},
getStyles: function(entity, tags, zoom) {
// summary: Find the styles for a given entity.
var sl=new iD.styleparser.StyleList();
for (var i in this.choosers) {
this.choosers[i].updateStyles(entity, tags, sl, zoom);
}
return sl; // iD.styleparser.StyleList
},
loadFromCSS:function(url) {
// summary: Load a MapCSS file from a URL, then throw it at the parser when it's loaded.
xhr.get({ url: url, load: lang.hitch(this, "parseCSS") });
},
loadFromCSS:function(url) {
// summary: Load a MapCSS file from a URL, then throw it at the parser when it's loaded.
$.ajax({
url: url,
load: _.bind(this.parseCSS, this)
});
},
parseCSS:function(css) {
// summary: Parse a CSS document into a set of StyleChoosers.
var previous=0; // what was the previous CSS word?
var sc = new iD.styleparser.StyleChooser(); // currently being assembled
this.choosers = [];
css = css.replace(/[\r\n]/g,""); // strip linebreaks because JavaScript doesn't have the /s modifier
parseCSS:function(css) {
// summary: Parse a CSS document into a set of StyleChoosers.
var previous=0; // what was the previous CSS word?
var sc = new iD.styleparser.StyleChooser(); // currently being assembled
this.choosers = [];
css = css.replace(/[\r\n]/g,""); // strip linebreaks because JavaScript doesn't have the /s modifier
var o = {};
while (css.length>0) {
var o = {};
while (css.length>0) {
// CSS comment
if ((o=this.COMMENT.exec(css))) {
css=css.replace(this.COMMENT,'');
// CSS comment
if ((o=this.COMMENT.exec(css))) {
css=css.replace(this.COMMENT,'');
// Whitespace (probably only at beginning of file)
} else if ((o=this.WHITESPACE.exec(css))) {
css=css.replace(this.WHITESPACE,'');
// Whitespace (probably only at beginning of file)
} else if ((o=this.WHITESPACE.exec(css))) {
css=css.replace(this.WHITESPACE,'');
// Class - .motorway, .builtup, :hover
} else if ((o=this.CLASS.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
// Class - .motorway, .builtup, :hover
} else if ((o=this.CLASS.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
css=css.replace(this.CLASS,'');
sc.currentChain().addConditionToLast(new iD.styleparser.Condition('set',o[1]));
previous=this.oCONDITION;
css=css.replace(this.CLASS,'');
sc.currentChain().addConditionToLast(new iD.styleparser.Condition('set',o[1]));
previous=this.oCONDITION;
// Not class - !.motorway, !.builtup, !:hover
} else if ((o=this.NOT_CLASS.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
// Not class - !.motorway, !.builtup, !:hover
} else if ((o=this.NOT_CLASS.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
css=css.replace(this.NOT_CLASS,'');
sc.currentChain().addConditionToLast(new iD.styleparser.Condition('unset',o[1]));
previous=this.oCONDITION;
css=css.replace(this.NOT_CLASS,'');
sc.currentChain().addConditionToLast(new iD.styleparser.Condition('unset',o[1]));
previous=this.oCONDITION;
// Zoom
} else if ((o=this.ZOOM.exec(css))) {
if (previous!=this.oOBJECT && previous!=this.oCONDITION) { sc.currentChain().addRule(); }
// Zoom
} else if ((o=this.ZOOM.exec(css))) {
if (previous!=this.oOBJECT && previous!=this.oCONDITION) { sc.currentChain().addRule(); }
css=css.replace(this.ZOOM,'');
var z=parseZoom(o[1]);
sc.currentChain().addZoomToLast(z[0],z[1]);
sc.zoomSpecific=true;
previous=this.oZOOM;
css=css.replace(this.ZOOM,'');
var z=parseZoom(o[1]);
sc.currentChain().addZoomToLast(z[0],z[1]);
sc.zoomSpecific=true;
previous=this.oZOOM;
// Grouping - just a comma
} else if ((o=this.GROUP.exec(css))) {
css=css.replace(this.GROUP,'');
sc.newRuleChain();
previous=this.oGROUP;
// Grouping - just a comma
} else if ((o=this.GROUP.exec(css))) {
css=css.replace(this.GROUP,'');
sc.newRuleChain();
previous=this.oGROUP;
// Condition - [highway=primary]
} else if ((o=this.CONDITION.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
if (previous!=this.oOBJECT && previous!=this.oZOOM && previous!=this.oCONDITION) { sc.currentChain().addRule(); }
css=css.replace(this.CONDITION,'');
sc.currentChain().addConditionToLast(this.parseCondition(o[1]));
previous=this.oCONDITION;
// Condition - [highway=primary]
} else if ((o=this.CONDITION.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
if (previous!=this.oOBJECT && previous!=this.oZOOM && previous!=this.oCONDITION) { sc.currentChain().addRule(); }
css=css.replace(this.CONDITION,'');
sc.currentChain().addConditionToLast(this.parseCondition(o[1]));
previous=this.oCONDITION;
// Object - way, node, relation
} else if ((o=this.OBJECT.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
// Object - way, node, relation
} else if ((o=this.OBJECT.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
css=css.replace(this.OBJECT,'');
sc.currentChain().addRule(o[1]);
previous=this.oOBJECT;
css=css.replace(this.OBJECT,'');
sc.currentChain().addRule(o[1]);
previous=this.oOBJECT;
// Subpart - ::centreline
} else if ((o=this.SUBPART.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
css=css.replace(this.SUBPART,'');
sc.currentChain().setSubpart(o[1]);
previous=this.oSUBPART;
// Subpart - ::centreline
} else if ((o=this.SUBPART.exec(css))) {
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
css=css.replace(this.SUBPART,'');
sc.currentChain().setSubpart(o[1]);
previous=this.oSUBPART;
// Declaration - {...}
} else if ((o=this.DECLARATION.exec(css))) {
css=css.replace(this.DECLARATION,'');
sc.addStyles(this.parseDeclaration(o[1]));
previous=this.oDECLARATION;
// Unknown pattern
} else if ((o=this.UNKNOWN.exec(css))) {
css=css.replace(this.UNKNOWN,'');
// console.log("unknown: "+o[1]);
// Declaration - {...}
} else if ((o=this.DECLARATION.exec(css))) {
css=css.replace(this.DECLARATION,'');
sc.addStyles(this.parseDeclaration(o[1]));
previous=this.oDECLARATION;
} else {
// console.log("choked on "+css);
return;
}
}
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
if (this.callback) { this.callback(); }
},
// Unknown pattern
} else if ((o=this.UNKNOWN.exec(css))) {
css=css.replace(this.UNKNOWN,'');
// console.log("unknown: "+o[1]);
saveChooser:function(sc) {
this.choosers.push(sc);
},
parseDeclaration:function(s) {
var styles=[];
var t={};
var o={};
var k, v;
} else {
// console.log("choked on "+css);
return;
}
}
if (previous==this.oDECLARATION) { this.saveChooser(sc); sc=new iD.styleparser.StyleChooser(); }
if (this.callback) { this.callback(); }
},
// Create styles
var ss = new iD.styleparser.ShapeStyle();
var ps = new iD.styleparser.PointStyle();
var ts = new iD.styleparser.TextStyle();
var hs = new iD.styleparser.ShieldStyle();
var xs = new iD.styleparser.InstructionStyle();
saveChooser:function(sc) {
this.choosers.push(sc);
},
var r=s.split(';');
var isEval={};
for (var i in r) {
var a=r[i];
if ((o=this.ASSIGNMENT_EVAL.exec(a))) { k=o[1].replace(this.DASH,'_'); t[k]=o[2]; isEval[k]=true; }
else if ((o=this.ASSIGNMENT.exec(a))) { k=o[1].replace(this.DASH,'_'); t[k]=o[2]; }
else if ((o=this.SET_TAG_EVAL.exec(a))) { } // xs.addSetTag(o[1],this.saveEval(o[2]));
else if ((o=this.SET_TAG.exec(a))) { xs.addSetTag(o[1],o[2]); }
else if ((o=this.SET_TAG_TRUE.exec(a))) { xs.addSetTag(o[1],true); }
else if ((o=this.EXIT.exec(a))) { xs.setPropertyFromString('breaker',true); }
}
parseDeclaration:function(s) {
var styles=[];
var t={};
var o={};
var k, v;
// Find sublayer
var sub=5;
if (t['z_index']) { sub=Number(t['z_index']); delete t['z_index']; }
ss.sublayer=ps.sublayer=ts.sublayer=hs.sublayer=sub;
xs.sublayer=10;
// Create styles
var ss = new iD.styleparser.ShapeStyle();
var ps = new iD.styleparser.PointStyle();
var ts = new iD.styleparser.TextStyle();
var hs = new iD.styleparser.ShieldStyle();
var xs = new iD.styleparser.InstructionStyle();
// Find "interactive" property - it's true unless explicitly set false
var inter=true;
if (t['interactive']) { inter=t['interactive'].match(this.FALSE) ? false : true; delete t['interactive']; }
ss.interactive=ps.interactive=ts.interactive=hs.interactive=xs.interactive=inter;
var r=s.split(';');
var isEval={};
for (var i in r) {
var a=r[i];
if ((o=this.ASSIGNMENT_EVAL.exec(a))) { k=o[1].replace(this.DASH,'_'); t[k]=o[2]; isEval[k]=true; }
else if ((o=this.ASSIGNMENT.exec(a))) { k=o[1].replace(this.DASH,'_'); t[k]=o[2]; }
else if ((o=this.SET_TAG_EVAL.exec(a))) { } // xs.addSetTag(o[1],this.saveEval(o[2]));
else if ((o=this.SET_TAG.exec(a))) { xs.addSetTag(o[1],o[2]); }
else if ((o=this.SET_TAG_TRUE.exec(a))) { xs.addSetTag(o[1],true); }
else if ((o=this.EXIT.exec(a))) { xs.setPropertyFromString('breaker',true); }
}
// Find sublayer
var sub=5;
if (t['z_index']) { sub=Number(t['z_index']); delete t['z_index']; }
ss.sublayer=ps.sublayer=ts.sublayer=hs.sublayer=sub;
xs.sublayer=10;
// Find "interactive" property - it's true unless explicitly set false
var inter=true;
if (t['interactive']) { inter=t['interactive'].match(this.FALSE) ? false : true; delete t['interactive']; }
ss.interactive=ps.interactive=ts.interactive=hs.interactive=xs.interactive=inter;
// Munge special values
// (we should stop doing this and do it in the style instead)
@@ -198,261 +193,257 @@ declare("iD.styleparser.RuleSet", null, {
}
// Add each style to list
if (ss.edited) { styles.push(ss); }
if (ps.edited) { styles.push(ps); }
if (ts.edited) { styles.push(ts); }
if (hs.edited) { styles.push(hs); }
if (xs.edited) { styles.push(xs); }
return styles;
},
if (ss.edited) { styles.push(ss); }
if (ps.edited) { styles.push(ps); }
if (ts.edited) { styles.push(ts); }
if (hs.edited) { styles.push(hs); }
if (xs.edited) { styles.push(xs); }
return styles;
},
parseZoom:function(s) {
var o={};
if ((o=this.ZOOM_MINMAX.exec(s))) { return [o[1],o[2]]; }
else if ((o=this.ZOOM_MIN.exec(s) )) { return [o[1], maxscale]; }
else if ((o=this.ZOOM_MAX.exec(s) )) { return [minscale, o[1]]; }
else if ((o=this.ZOOM_SINGLE.exec(s))) { return [o[1],o[1]]; }
return null;
},
parseZoom:function(s) {
var o={};
if ((o=this.ZOOM_MINMAX.exec(s))) { return [o[1],o[2]]; }
else if ((o=this.ZOOM_MIN.exec(s) )) { return [o[1], maxscale]; }
else if ((o=this.ZOOM_MAX.exec(s) )) { return [minscale, o[1]]; }
else if ((o=this.ZOOM_SINGLE.exec(s))) { return [o[1],o[1]]; }
return null;
},
parseCondition:function(s) {
var o={};
if ((o=this.CONDITION_TRUE.exec(s))) { return new iD.styleparser.Condition('true' ,o[1]); }
else if ((o=this.CONDITION_FALSE.exec(s))) { return new iD.styleparser.Condition('false',o[1]); }
else if ((o=this.CONDITION_SET.exec(s))) { return new iD.styleparser.Condition('set' ,o[1]); }
else if ((o=this.CONDITION_UNSET.exec(s))) { return new iD.styleparser.Condition('unset',o[1]); }
else if ((o=this.CONDITION_NE.exec(s))) { return new iD.styleparser.Condition('ne' ,o[1],o[2]); }
else if ((o=this.CONDITION_GT.exec(s))) { return new iD.styleparser.Condition('>' ,o[1],o[2]); }
else if ((o=this.CONDITION_GE.exec(s))) { return new iD.styleparser.Condition('>=' ,o[1],o[2]); }
else if ((o=this.CONDITION_LT.exec(s))) { return new iD.styleparser.Condition('<' ,o[1],o[2]); }
else if ((o=this.CONDITION_LE.exec(s))) { return new iD.styleparser.Condition('<=' ,o[1],o[2]); }
else if ((o=this.CONDITION_REGEX.exec(s))) { return new iD.styleparser.Condition('regex',o[1],o[2]); }
else if ((o=this.CONDITION_EQ.exec(s))) { return new iD.styleparser.Condition('eq' ,o[1],o[2]); }
return null;
},
parseCondition:function(s) {
var o={};
if ((o=this.CONDITION_TRUE.exec(s))) { return new iD.styleparser.Condition('true' ,o[1]); }
else if ((o=this.CONDITION_FALSE.exec(s))) { return new iD.styleparser.Condition('false',o[1]); }
else if ((o=this.CONDITION_SET.exec(s))) { return new iD.styleparser.Condition('set' ,o[1]); }
else if ((o=this.CONDITION_UNSET.exec(s))) { return new iD.styleparser.Condition('unset',o[1]); }
else if ((o=this.CONDITION_NE.exec(s))) { return new iD.styleparser.Condition('ne' ,o[1],o[2]); }
else if ((o=this.CONDITION_GT.exec(s))) { return new iD.styleparser.Condition('>' ,o[1],o[2]); }
else if ((o=this.CONDITION_GE.exec(s))) { return new iD.styleparser.Condition('>=' ,o[1],o[2]); }
else if ((o=this.CONDITION_LT.exec(s))) { return new iD.styleparser.Condition('<' ,o[1],o[2]); }
else if ((o=this.CONDITION_LE.exec(s))) { return new iD.styleparser.Condition('<=' ,o[1],o[2]); }
else if ((o=this.CONDITION_REGEX.exec(s))) { return new iD.styleparser.Condition('regex',o[1],o[2]); }
else if ((o=this.CONDITION_EQ.exec(s))) { return new iD.styleparser.Condition('eq' ,o[1],o[2]); }
return null;
},
parseCSSColor:function(colorStr) {
colorStr = colorStr.toLowerCase();
if (this.CSSCOLORS[colorStr]) {
return this.CSSCOLORS[colorStr];
} else {
var match = this.HEX.exec(colorStr);
if ( match ) {
parseCSSColor:function(colorStr) {
colorStr = colorStr.toLowerCase();
if (this.CSSCOLORS[colorStr]) {
return this.CSSCOLORS[colorStr];
} else {
var match = this.HEX.exec(colorStr);
if ( match ) {
if ( match[1].length == 3) {
// repeat digits. #abc => 0xaabbcc
return Number("0x"+match[1].charAt(0)+match[1].charAt(0)+
match[1].charAt(1)+match[1].charAt(1)+
match[1].charAt(2)+match[1].charAt(2));
} else if ( match[1].length == 6) {
return Number("0x"+match[1]);
} else {
return Number("0x000000"); //as good as any
}
}
}
return 0;
},
return Number("0x"+match[1]);
} else {
return Number("0x000000"); //as good as any
}
}
}
return 0;
},
// Regular expression tests and other constants
// Regular expression tests and other constants
WHITESPACE :/^\s+/,
COMMENT :/^\/\*.+?\*\/\s*/,
CLASS :/^([\.:]\w+)\s*/,
NOT_CLASS :/^!([\.:]\w+)\s*/,
ZOOM :/^\|\s*z([\d\-]+)\s*/i,
GROUP :/^,\s*/i,
CONDITION :/^\[(.+?)\]\s*/,
OBJECT :/^(\w+)\s*/,
DECLARATION :/^\{(.+?)\}\s*/,
SUBPART :/^::(\w+)\s*/,
UNKNOWN :/^(\S+)\s*/,
WHITESPACE :/^\s+/,
COMMENT :/^\/\*.+?\*\/\s*/,
CLASS :/^([\.:]\w+)\s*/,
NOT_CLASS :/^!([\.:]\w+)\s*/,
ZOOM :/^\|\s*z([\d\-]+)\s*/i,
GROUP :/^,\s*/i,
CONDITION :/^\[(.+?)\]\s*/,
OBJECT :/^(\w+)\s*/,
DECLARATION :/^\{(.+?)\}\s*/,
SUBPART :/^::(\w+)\s*/,
UNKNOWN :/^(\S+)\s*/,
ZOOM_MINMAX :/^(\d+)\-(\d+)$/,
ZOOM_MIN :/^(\d+)\-$/,
ZOOM_MAX :/^\-(\d+)$/,
ZOOM_SINGLE :/^(\d+)$/,
ZOOM_MINMAX :/^(\d+)\-(\d+)$/,
ZOOM_MIN :/^(\d+)\-$/,
ZOOM_MAX :/^\-(\d+)$/,
ZOOM_SINGLE :/^(\d+)$/,
CONDITION_TRUE :/^\s*([:\w]+)\s*=\s*yes\s*$/i,
CONDITION_FALSE :/^\s*([:\w]+)\s*=\s*no\s*$/i,
CONDITION_SET :/^\s*([:\w]+)\s*$/,
CONDITION_UNSET :/^\s*!([:\w]+)\s*$/,
CONDITION_EQ :/^\s*([:\w]+)\s*=\s*(.+)\s*$/,
CONDITION_NE :/^\s*([:\w]+)\s*!=\s*(.+)\s*$/,
CONDITION_GT :/^\s*([:\w]+)\s*>\s*(.+)\s*$/,
CONDITION_GE :/^\s*([:\w]+)\s*>=\s*(.+)\s*$/,
CONDITION_LT :/^\s*([:\w]+)\s*<\s*(.+)\s*$/,
CONDITION_LE :/^\s*([:\w]+)\s*<=\s*(.+)\s*$/,
CONDITION_REGEX :/^\s*([:\w]+)\s*=~\/\s*(.+)\/\s*$/,
CONDITION_TRUE :/^\s*([:\w]+)\s*=\s*yes\s*$/i,
CONDITION_FALSE :/^\s*([:\w]+)\s*=\s*no\s*$/i,
CONDITION_SET :/^\s*([:\w]+)\s*$/,
CONDITION_UNSET :/^\s*!([:\w]+)\s*$/,
CONDITION_EQ :/^\s*([:\w]+)\s*=\s*(.+)\s*$/,
CONDITION_NE :/^\s*([:\w]+)\s*!=\s*(.+)\s*$/,
CONDITION_GT :/^\s*([:\w]+)\s*>\s*(.+)\s*$/,
CONDITION_GE :/^\s*([:\w]+)\s*>=\s*(.+)\s*$/,
CONDITION_LT :/^\s*([:\w]+)\s*<\s*(.+)\s*$/,
CONDITION_LE :/^\s*([:\w]+)\s*<=\s*(.+)\s*$/,
CONDITION_REGEX :/^\s*([:\w]+)\s*=~\/\s*(.+)\/\s*$/,
ASSIGNMENT_EVAL :/^\s*(\S+)\s*\:\s*eval\s*\(\s*'(.+?)'\s*\)\s*$/i,
ASSIGNMENT :/^\s*(\S+)\s*\:\s*(.+?)\s*$/,
SET_TAG_EVAL :/^\s*set\s+(\S+)\s*=\s*eval\s*\(\s*'(.+?)'\s*\)\s*$/i,
SET_TAG :/^\s*set\s+(\S+)\s*=\s*(.+?)\s*$/i,
SET_TAG_TRUE :/^\s*set\s+(\S+)\s*$/i,
EXIT :/^\s*exit\s*$/i,
ASSIGNMENT_EVAL :/^\s*(\S+)\s*\:\s*eval\s*\(\s*'(.+?)'\s*\)\s*$/i,
ASSIGNMENT :/^\s*(\S+)\s*\:\s*(.+?)\s*$/,
SET_TAG_EVAL :/^\s*set\s+(\S+)\s*=\s*eval\s*\(\s*'(.+?)'\s*\)\s*$/i,
SET_TAG :/^\s*set\s+(\S+)\s*=\s*(.+?)\s*$/i,
SET_TAG_TRUE :/^\s*set\s+(\S+)\s*$/i,
EXIT :/^\s*exit\s*$/i,
oZOOM: 2,
oGROUP: 3,
oCONDITION: 4,
oOBJECT: 5,
oDECLARATION: 6,
oSUBPART: 7,
oZOOM: 2,
oGROUP: 3,
oCONDITION: 4,
oOBJECT: 5,
oDECLARATION: 6,
oSUBPART: 7,
DASH: /\-/g,
COLOR: /color$/,
BOLD: /^bold$/i,
ITALIC: /^italic|oblique$/i,
UNDERLINE: /^underline$/i,
CAPS: /^uppercase$/i,
CENTER: /^center$/i,
FALSE: /^(no|false|0)$/i,
DASH: /\-/g,
COLOR: /color$/,
BOLD: /^bold$/i,
ITALIC: /^italic|oblique$/i,
UNDERLINE: /^underline$/i,
CAPS: /^uppercase$/i,
CENTER: /^center$/i,
FALSE: /^(no|false|0)$/i,
HEX: /^#([0-9a-f]+)$/i,
HEX: /^#([0-9a-f]+)$/i,
CSSCOLORS: {
aliceblue:0xf0f8ff,
antiquewhite:0xfaebd7,
aqua:0x00ffff,
aquamarine:0x7fffd4,
azure:0xf0ffff,
beige:0xf5f5dc,
bisque:0xffe4c4,
black:0x000000,
blanchedalmond:0xffebcd,
blue:0x0000ff,
blueviolet:0x8a2be2,
brown:0xa52a2a,
burlywood:0xdeb887,
cadetblue:0x5f9ea0,
chartreuse:0x7fff00,
chocolate:0xd2691e,
coral:0xff7f50,
cornflowerblue:0x6495ed,
cornsilk:0xfff8dc,
crimson:0xdc143c,
cyan:0x00ffff,
darkblue:0x00008b,
darkcyan:0x008b8b,
darkgoldenrod:0xb8860b,
darkgray:0xa9a9a9,
darkgreen:0x006400,
darkkhaki:0xbdb76b,
darkmagenta:0x8b008b,
darkolivegreen:0x556b2f,
darkorange:0xff8c00,
darkorchid:0x9932cc,
darkred:0x8b0000,
darksalmon:0xe9967a,
darkseagreen:0x8fbc8f,
darkslateblue:0x483d8b,
darkslategray:0x2f4f4f,
darkturquoise:0x00ced1,
darkviolet:0x9400d3,
deeppink:0xff1493,
deepskyblue:0x00bfff,
dimgray:0x696969,
dodgerblue:0x1e90ff,
firebrick:0xb22222,
floralwhite:0xfffaf0,
forestgreen:0x228b22,
fuchsia:0xff00ff,
gainsboro:0xdcdcdc,
ghostwhite:0xf8f8ff,
gold:0xffd700,
goldenrod:0xdaa520,
gray:0x808080,
green:0x008000,
greenyellow:0xadff2f,
honeydew:0xf0fff0,
hotpink:0xff69b4,
indianred:0xcd5c5c,
indigo:0x4b0082,
ivory:0xfffff0,
khaki:0xf0e68c,
lavender:0xe6e6fa,
lavenderblush:0xfff0f5,
lawngreen:0x7cfc00,
lemonchiffon:0xfffacd,
lightblue:0xadd8e6,
lightcoral:0xf08080,
lightcyan:0xe0ffff,
lightgoldenrodyellow:0xfafad2,
lightgrey:0xd3d3d3,
lightgreen:0x90ee90,
lightpink:0xffb6c1,
lightsalmon:0xffa07a,
lightseagreen:0x20b2aa,
lightskyblue:0x87cefa,
lightslategray:0x778899,
lightsteelblue:0xb0c4de,
lightyellow:0xffffe0,
lime:0x00ff00,
limegreen:0x32cd32,
linen:0xfaf0e6,
magenta:0xff00ff,
maroon:0x800000,
mediumaquamarine:0x66cdaa,
mediumblue:0x0000cd,
mediumorchid:0xba55d3,
mediumpurple:0x9370d8,
mediumseagreen:0x3cb371,
mediumslateblue:0x7b68ee,
mediumspringgreen:0x00fa9a,
mediumturquoise:0x48d1cc,
mediumvioletred:0xc71585,
midnightblue:0x191970,
mintcream:0xf5fffa,
mistyrose:0xffe4e1,
moccasin:0xffe4b5,
navajowhite:0xffdead,
navy:0x000080,
oldlace:0xfdf5e6,
olive:0x808000,
olivedrab:0x6b8e23,
orange:0xffa500,
orangered:0xff4500,
orchid:0xda70d6,
palegoldenrod:0xeee8aa,
palegreen:0x98fb98,
paleturquoise:0xafeeee,
palevioletred:0xd87093,
papayawhip:0xffefd5,
peachpuff:0xffdab9,
peru:0xcd853f,
pink:0xffc0cb,
plum:0xdda0dd,
powderblue:0xb0e0e6,
purple:0x800080,
red:0xff0000,
rosybrown:0xbc8f8f,
royalblue:0x4169e1,
saddlebrown:0x8b4513,
salmon:0xfa8072,
sandybrown:0xf4a460,
seagreen:0x2e8b57,
seashell:0xfff5ee,
sienna:0xa0522d,
silver:0xc0c0c0,
skyblue:0x87ceeb,
slateblue:0x6a5acd,
slategray:0x708090,
snow:0xfffafa,
springgreen:0x00ff7f,
steelblue:0x4682b4,
tan:0xd2b48c,
teal:0x008080,
thistle:0xd8bfd8,
tomato:0xff6347,
turquoise:0x40e0d0,
violet:0xee82ee,
wheat:0xf5deb3,
white:0xffffff,
whitesmoke:0xf5f5f5,
yellow:0xffff00,
yellowgreen:0x9acd32 },
CSSCOLORS: {
aliceblue:0xf0f8ff,
antiquewhite:0xfaebd7,
aqua:0x00ffff,
aquamarine:0x7fffd4,
azure:0xf0ffff,
beige:0xf5f5dc,
bisque:0xffe4c4,
black:0x000000,
blanchedalmond:0xffebcd,
blue:0x0000ff,
blueviolet:0x8a2be2,
brown:0xa52a2a,
burlywood:0xdeb887,
cadetblue:0x5f9ea0,
chartreuse:0x7fff00,
chocolate:0xd2691e,
coral:0xff7f50,
cornflowerblue:0x6495ed,
cornsilk:0xfff8dc,
crimson:0xdc143c,
cyan:0x00ffff,
darkblue:0x00008b,
darkcyan:0x008b8b,
darkgoldenrod:0xb8860b,
darkgray:0xa9a9a9,
darkgreen:0x006400,
darkkhaki:0xbdb76b,
darkmagenta:0x8b008b,
darkolivegreen:0x556b2f,
darkorange:0xff8c00,
darkorchid:0x9932cc,
darkred:0x8b0000,
darksalmon:0xe9967a,
darkseagreen:0x8fbc8f,
darkslateblue:0x483d8b,
darkslategray:0x2f4f4f,
darkturquoise:0x00ced1,
darkviolet:0x9400d3,
deeppink:0xff1493,
deepskyblue:0x00bfff,
dimgray:0x696969,
dodgerblue:0x1e90ff,
firebrick:0xb22222,
floralwhite:0xfffaf0,
forestgreen:0x228b22,
fuchsia:0xff00ff,
gainsboro:0xdcdcdc,
ghostwhite:0xf8f8ff,
gold:0xffd700,
goldenrod:0xdaa520,
gray:0x808080,
green:0x008000,
greenyellow:0xadff2f,
honeydew:0xf0fff0,
hotpink:0xff69b4,
indianred:0xcd5c5c,
indigo:0x4b0082,
ivory:0xfffff0,
khaki:0xf0e68c,
lavender:0xe6e6fa,
lavenderblush:0xfff0f5,
lawngreen:0x7cfc00,
lemonchiffon:0xfffacd,
lightblue:0xadd8e6,
lightcoral:0xf08080,
lightcyan:0xe0ffff,
lightgoldenrodyellow:0xfafad2,
lightgrey:0xd3d3d3,
lightgreen:0x90ee90,
lightpink:0xffb6c1,
lightsalmon:0xffa07a,
lightseagreen:0x20b2aa,
lightskyblue:0x87cefa,
lightslategray:0x778899,
lightsteelblue:0xb0c4de,
lightyellow:0xffffe0,
lime:0x00ff00,
limegreen:0x32cd32,
linen:0xfaf0e6,
magenta:0xff00ff,
maroon:0x800000,
mediumaquamarine:0x66cdaa,
mediumblue:0x0000cd,
mediumorchid:0xba55d3,
mediumpurple:0x9370d8,
mediumseagreen:0x3cb371,
mediumslateblue:0x7b68ee,
mediumspringgreen:0x00fa9a,
mediumturquoise:0x48d1cc,
mediumvioletred:0xc71585,
midnightblue:0x191970,
mintcream:0xf5fffa,
mistyrose:0xffe4e1,
moccasin:0xffe4b5,
navajowhite:0xffdead,
navy:0x000080,
oldlace:0xfdf5e6,
olive:0x808000,
olivedrab:0x6b8e23,
orange:0xffa500,
orangered:0xff4500,
orchid:0xda70d6,
palegoldenrod:0xeee8aa,
palegreen:0x98fb98,
paleturquoise:0xafeeee,
palevioletred:0xd87093,
papayawhip:0xffefd5,
peachpuff:0xffdab9,
peru:0xcd853f,
pink:0xffc0cb,
plum:0xdda0dd,
powderblue:0xb0e0e6,
purple:0x800080,
red:0xff0000,
rosybrown:0xbc8f8f,
royalblue:0x4169e1,
saddlebrown:0x8b4513,
salmon:0xfa8072,
sandybrown:0xf4a460,
seagreen:0x2e8b57,
seashell:0xfff5ee,
sienna:0xa0522d,
silver:0xc0c0c0,
skyblue:0x87ceeb,
slateblue:0x6a5acd,
slategray:0x708090,
snow:0xfffafa,
springgreen:0x00ff7f,
steelblue:0x4682b4,
tan:0xd2b48c,
teal:0x008080,
thistle:0xd8bfd8,
tomato:0xff6347,
turquoise:0x40e0d0,
violet:0xee82ee,
wheat:0xf5deb3,
white:0xffffff,
whitesmoke:0xf5f5f5,
yellow:0xffff00,
yellowgreen:0x9acd32 },
});
// ----------------------------------------------------------------------
// End of module
});
};

View File

@@ -1,12 +1,6 @@
// iD/styleparser/Style.js
iD.styleparser.Style = function() {};
define(['dojo/_base/declare','dojo/_base/array'], function(declare,array){
// ----------------------------------------------------------------------
// Style base class
// fillStyler not done for text yet
declare("iD.styleparser.Style", null, {
iD.styleparser.Style.prototype = {
merged: false,
edited: false,
sublayer: 5,
@@ -54,7 +48,8 @@ declare("iD.styleparser.Style", null, {
runEvals: function(tags) {
for (var k in this.evals) {
this.setPropertyFromString(k,eval("with (tags) {"+this.evals[k]+"}"),false);
// TODO: kill
this.setPropertyFromString(k, eval("with (tags) {"+this.evals[k]+"}"),false);
}
},
@@ -72,13 +67,14 @@ declare("iD.styleparser.Style", null, {
}
return str;
}
});
};
// ----------------------------------------------------------------------
// InstructionStyle class
declare("iD.styleparser.InstructionStyle", [iD.styleparser.Style], {
iD.styleparser.InstructionStyle = function() {};
iD.styleparser.InstructionStyle.prototype = {
set_tags: null,
breaker: false,
styleType: 'InstructionStyle',
@@ -87,12 +83,13 @@ declare("iD.styleparser.InstructionStyle", [iD.styleparser.Style], {
if (!this.set_tags) this.set_tags={};
this.set_tags[k]=v;
}
});
};
// ----------------------------------------------------------------------
// PointStyle class
declare("iD.styleparser.PointStyle", [iD.styleparser.Style], {
iD.styleparser.PointStyle = function() {};
iD.styleparser.PointStyle.prototype = {
properties: ['icon_image','icon_width','icon_height','rotation'],
icon_image: null,
icon_width: 0,
@@ -105,12 +102,14 @@ declare("iD.styleparser.PointStyle", [iD.styleparser.Style], {
maxwidth:function() {
return this.evals.icon_width ? 0 : this.icon_width;
}
});
};
// ----------------------------------------------------------------------
// ShapeStyle class
declare("iD.styleparser.ShapeStyle", [iD.styleparser.Style], {
iD.styleparser.ShapeStyle = function() {};
iD.styleparser.ShapeStyle.prototype = {
properties: ['width','color','opacity','dashes','linecap','linejoin','line_style',
'fill_image','fill_color','fill_opacity','casing_width','casing_color','casing_opacity','casing_dashes','layer'],
@@ -168,13 +167,13 @@ declare("iD.styleparser.ShapeStyle", [iD.styleparser.Style], {
join: join
};
}
});
};
// ----------------------------------------------------------------------
// TextStyle class
declare("iD.styleparser.TextStyle", [iD.styleparser.Style], {
iD.styleparser.TextStyle = function() {};
iD.styleparser.TextStyle.prototype = {
properties: ['font_family','font_bold','font_italic','font_caps','font_underline','font_size',
'text_color','text_offset','max_width',
'text','text_halo_color','text_halo_radius','text_center',
@@ -219,13 +218,15 @@ declare("iD.styleparser.TextStyle", [iD.styleparser.Style], {
return this.dojoColor(0,1);
}
// getTextFormat, getHaloFilter, writeNameLabel
});
};
// ----------------------------------------------------------------------
// ShieldStyle class
declare("iD.styleparser.ShieldStyle", [iD.styleparser.Style], {
properties: ['shield_image','shield_width','shield_height'],
iD.styleparser.ShieldStyle = function() {};
iD.styleparser.ShieldStyle.prototype = {
properties: ['shield_image','shield_width','shield_height'],
shield_image: null,
shield_width: NaN,
shield_height: NaN,
@@ -233,8 +234,7 @@ declare("iD.styleparser.ShieldStyle", [iD.styleparser.Style], {
drawn:function() {
return (shield_image !== null);
}
});
};
// ----------------------------------------------------------------------
// End of module
});

View File

@@ -1,14 +1,15 @@
// iD/styleparser/StyleChooser.js
define(['dojo/_base/declare','dojo/_base/lang','iD/styleparser/RuleChain'], function(declare,lang){
declare("iD.styleparser.StyleChooser", null, {
iD.styleparser.StyleChooser = function() {
this.ruleChains = [new iD.styleparser.RuleChain()];
this.styles = [];
};
iD.styleparser.StyleChooser.prototype = {
// UpdateStyles doesn't support image-widths yet
// or setting maxwidth/_width
ruleChains:[], // array of RuleChains (each one an array of Rules)
styles:[], // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle
ruleChains: [], // array of RuleChains (each one an array of Rules)
styles: [], // array of ShapeStyle/ShieldStyle/TextStyle/PointStyle
zoomSpecific:false, // are any of the rules zoom-specific?
rcpos:0,
@@ -17,8 +18,6 @@ declare("iD.styleparser.StyleChooser", null, {
constructor:function() {
// summary: A combination of the selectors (ruleChains) and declaration (styles).
// For example, way[highway=footway] node[barrier=gate] { icon: gate.png; } is one StyleChooser.
this.ruleChains=[new iD.styleparser.RuleChain()];
this.styles=[];
},
currentChain:function() {
@@ -80,8 +79,4 @@ declare("iD.styleparser.StyleChooser", null, {
}
}
}
});
// ----------------------------------------------------------------------
// End of module
});
};

View File

@@ -1,12 +1,7 @@
// iD/styleparser/StyleList.js
define(['dojo/_base/declare'], function(declare){
// ----------------------------------------------------------------------
// StyleList class
declare("iD.styleparser.StyleList", null, {
iD.styleparser.StyleList = function() {};
iD.styleparser.StyleList.prototype = {
shapeStyles: {},
textStyles: {},
@@ -16,17 +11,6 @@ declare("iD.styleparser.StyleList", null, {
subparts: [], // List of subparts used in this StyleList
validAt: -1, // Zoom level this is valid at (or -1 at all levels - saves recomputing)
constructor:function() {
// summary: A StyleList object is the full list of all styles applied to
// a drawn entity (i.e. node/way). Each array element applies to that
// sublayer (z-index). If there is no element, nothing is drawn on that sublayer.
// StyleLists are created by StyleChooser.getStyles.
this.shapeStyles={};
this.textStyles={};
this.pointStyles={};
this.shieldStyles={};
this.subparts=[];
},
hasStyles:function() {
// summary: Does this StyleList contain any styles?
@@ -74,8 +58,4 @@ declare("iD.styleparser.StyleList", null, {
hasTextStyles:function() { for (var a in textStyles ) { return true; } return false; },
hasPointStyles:function() { for (var a in pointStyles ) { return true; } return false; },
hasShieldStyles:function() { for (var a in shieldStyles) { return true; } return false; }
});
// ----------------------------------------------------------------------
// End of module
});
};

View File

@@ -0,0 +1 @@
iD.styleparser = {};

4
js/lib/d3.v2.min.js vendored Normal file

File diff suppressed because one or more lines are too long